#include "../geometry/distance.hpp"
#include "../io/WorldSave.hpp"
#include "../model/Model.hpp"
+#include "../shared/CommandService.hpp"
#include "../world/ChunkIndex.hpp"
#include "../world/Entity.hpp"
#include "../world/World.hpp"
void ClientConnection::CheckPlayerFix() {
// player_update_state's position holds the client's most recent prediction
glm::vec3 diff = player_update_state.Diff(PlayerEntity().GetState());
- float dist_squared = dot(diff, diff);
+ float dist_squared = glm::length2(diff);
// if client's prediction is off by more than 1cm, send
// our (authoritative) state back so it can fix it
input.reset(new DirectInput(server.GetWorld(), player, server));
PlayerEntity().Ref();
+ cli_ctx.reset(new NetworkCLIFeedback(player, *this));
+
old_base = PlayerChunks().Base();
ExactLocation::Coarse begin = PlayerChunks().CoordsBegin();
ExactLocation::Coarse end = PlayerChunks().CoordsEnd();
server.GetWorldSave().Write(input->GetPlayer());
PlayerEntity().Kill();
PlayerEntity().UnRef();
+ cli_ctx.reset();
input.reset();
transmitter.Abort();
chunk_queue.clear();
pack.ReadReferral(ref);
pack.ReadMessage(msg);
- if (type == 1 && HasPlayer()) {
- server.DispatchMessage(input->GetPlayer(), msg);
+ if (type == 1 && cli_ctx) {
+ server.DispatchMessage(*cli_ctx, msg);
}
}
+uint16_t ClientConnection::SendMessage(uint8_t type, uint32_t from, const string &msg) {
+ auto pack = Prepare<Packet::Message>();
+ pack.WriteType(type);
+ pack.WriteReferral(from);
+ pack.WriteMessage(msg);
+ return Send(Packet::Message::GetSize(msg));
+}
+
+
+NetworkCLIFeedback::NetworkCLIFeedback(Player &p, ClientConnection &c)
+: CLIContext(&p)
+, conn(c) {
+}
+
+void NetworkCLIFeedback::Error(const string &msg) {
+ conn.SendMessage(0, 0, msg);
+}
+
+void NetworkCLIFeedback::Message(const string &msg) {
+ conn.SendMessage(0, 0, msg);
+}
+
+void NetworkCLIFeedback::Broadcast(const string &msg) {
+ conn.GetServer().DistributeMessage(0, GetPlayer().GetEntity().ID(), msg);
+}
+
+
+// relying on {} zero intitialization for UDPpacket, because
+// the type and number of fields is not well defined
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Server::Server(
const Config::Network &conf,
World &world,
, spawn_index(world.Chunks().MakeIndex(wc.spawn, 3))
, save(save)
, player_model(nullptr)
-, cli(world) {
+, cli(world)
+, cmd_srv() {
+#pragma GCC diagnostic pop
if (!serv_set) {
throw NetError("SDLNet_AllocSocketSet");
}
serv_pack.data = new Uint8[sizeof(Packet)];
serv_pack.maxlen = sizeof(Packet);
+
+ if (conf.cmd_port) {
+ cmd_srv.reset(new CommandService(cli, conf.cmd_port));
+ }
}
Server::~Server() {
void Server::Wait(int dt) noexcept {
SDLNet_CheckSockets(serv_set, dt);
+ if (cmd_srv) {
+ cmd_srv->Wait(0);
+ }
}
bool Server::Ready() noexcept {
- return SDLNet_CheckSockets(serv_set, 0) > 0;
+ if (SDLNet_CheckSockets(serv_set, 0) > 0) {
+ return true;
+ }
+ return cmd_srv && cmd_srv->Ready();
}
void Server::Handle() {
// a boo boo happened
throw NetError("SDLNet_UDP_Recv");
}
+ if (cmd_srv) {
+ cmd_srv->Handle();
+ }
}
void Server::HandlePacket(const UDPpacket &udp_pack) {
++client;
}
}
+ if (cmd_srv) {
+ cmd_srv->Send();
+ }
}
void Server::SetPlayerModel(const Model &m) noexcept {
}
}
-void Server::DispatchMessage(Player &player, const string &msg) {
+void Server::DispatchMessage(CLIContext &ctx, const string &msg) {
if (msg.empty()) {
return;
}
if (msg[0] == '/' && msg.size() > 1 && msg[1] != '/') {
- cli.Execute(player, msg.substr(1));
+ cli.Execute(ctx, msg.substr(1));
} else {
- DistributeMessage(1, player.GetEntity().ID(), msg);
+ DistributeMessage(1, ctx.GetPlayer().GetEntity().ID(), msg);
}
}