cerr << "missing argument to --world-name" << endl;
error = true;
} else {
- config.world_name = argv[i];
+ config.world.name = argv[i];
}
} else {
cerr << "unknown option " << arg << endl;
Environment env(init.window, config.asset_path);
env.viewport.VSync(config.vsync);
- WorldSave save(config.save_path + config.world_name + '/');
+ WorldSave save(config.save_path + config.world.name + '/');
if (save.Exists()) {
save.Read(config.world);
} else {
void Runtime::RunServer() {
HeadlessEnvironment env(config.asset_path);
- WorldSave save(config.save_path + config.world_name + '/');
+ WorldSave save(config.save_path + config.world.name + '/');
if (save.Exists()) {
save.Read(config.world);
} else {
Environment env(init.window, config.asset_path);
env.viewport.VSync(config.vsync);
- WorldSave save(config.save_path + config.world_name + '/');
+ WorldSave save(config.save_path + config.world.name + '/');
if (save.Exists()) {
save.Read(config.world);
} else {
}
conn.Received(udp_pack);
- cout << "I got something!" << endl;
}
void Client::Update(int dt) {
void Client::SendLogin(const string &name) {
Packet &pack = *reinterpret_cast<Packet *>(client_pack.data);
- client_pack.len = pack.Login(name);
+ client_pack.len = pack.MakeLogin(name);
conn.Send(client_pack, client_sock);
}
Connection::Connection(const IPaddress &addr)
: addr(addr)
-, send_timer(5000)
+, send_timer(3000)
, recv_timer(10000)
-, ctrl{ 0, 0xFFFF, 0xFFFF } {
+, ctrl{ 0, 0xFFFF, 0xFFFF }
+, closed(false) {
send_timer.Start();
recv_timer.Start();
}
Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
pack.header.ctrl = ctrl;
+ cout << "sending " << pack.GetType() << " to " << Address() << endl;
+
udp_pack.address = addr;
if (SDLNet_UDP_Send(sock, -1, &udp_pack) == 0) {
throw NetError("SDLNet_UDP_Send");
void Connection::Received(const UDPpacket &udp_pack) {
Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
+ cout << "received " << pack.GetType() << " from " << Address() << endl;
+
int diff = std::int16_t(pack.header.ctrl.seq) - std::int16_t(ctrl.ack);
if (diff > 0) {
void Connection::SendPing(UDPpacket &udp_pack, UDPsocket sock) {
Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
- udp_pack.len = pack.Ping();
+ udp_pack.len = pack.MakePing();
Send(udp_pack, sock);
}
}
+const char *Packet::Type2String(Type t) noexcept {
+ switch (t) {
+ case PING:
+ return "PING";
+ case LOGIN:
+ return "LOGIN";
+ case JOIN:
+ return "JOIN";
+ case PART:
+ return "PART";
+ default:
+ return "UNKNOWN";
+ }
+}
+
void Packet::Tag() noexcept {
header.tag = TAG;
}
-size_t Packet::Ping() noexcept {
+size_t Packet::MakePing() noexcept {
Tag();
header.type = PING;
return sizeof(Header);
}
-size_t Packet::Login(const string &name) noexcept {
+size_t Packet::MakeLogin(const string &name) noexcept {
constexpr size_t maxname = 32;
Tag();
return sizeof(Header) + maxname;
}
+size_t Packet::MakeJoin(const Entity &player, const string &world_name) noexcept {
+ constexpr size_t maxname = 32;
+
+ Tag();
+ header.type = JOIN;
+
+ uint8_t *cursor = &payload[0];
+
+ // TODO: generate entity IDs
+ *reinterpret_cast<uint32_t *>(cursor) = 1;
+ cursor += 4;
+
+ *reinterpret_cast<glm::ivec3 *>(cursor) = player.ChunkCoords();
+ cursor += 12;
+
+ *reinterpret_cast<glm::vec3 *>(cursor) = player.Position();
+ cursor += 12;
+ *reinterpret_cast<glm::vec3 *>(cursor) = player.Velocity();
+ cursor += 12;
+
+ *reinterpret_cast<glm::quat *>(cursor) = player.Orientation();
+ cursor += 16;
+ *reinterpret_cast<glm::vec3 *>(cursor) = player.AngularVelocity();
+ cursor += 12;
+
+ if (world_name.size() < maxname) {
+ memset(cursor, '\0', maxname);
+ memcpy(cursor, world_name.c_str(), world_name.size());
+ } else {
+ memcpy(cursor, world_name.c_str(), maxname);
+ }
+ cursor += maxname;
+
+ return sizeof(Header) + (cursor - &payload[0]);
+}
+
+size_t Packet::MakePart() noexcept {
+ Tag();
+ header.type = PART;
+ return sizeof(Header);
+}
+
Server::Server(const Config &conf, World &world)
: serv_sock(nullptr)
client.Received(udp_pack);
switch (pack.header.type) {
- case Packet::PING:
- // already done all that's supposed to do
- break;
case Packet::LOGIN:
HandleLogin(client, udp_pack);
break;
+ case Packet::PART:
+ HandlePart(client, udp_pack);
+ break;
default:
- // just drop packets of unknown type
+ // just drop packets of unknown or unhandled type
break;
}
}
void Server::Update(int dt) {
for (list<Connection>::iterator client(clients.begin()), end(clients.end()); client != end;) {
client->Update(dt);
- if (client->TimedOut()) {
+ if (client->Closed()) {
OnDisconnect(*client);
client = clients.erase(client);
} else {
for (size_t i = 0; i < maxlen && pack.payload[i] != '\0'; ++i) {
name.push_back(pack.payload[i]);
}
- cout << "got login request from player \"" << name << '"' << endl;
Entity *player = world.AddPlayer(name);
+ Packet &response = *reinterpret_cast<Packet *>(serv_pack.data);
+
if (player) {
// success!
- cout << "\taccepted" << endl;
+ cout << "accepted login from player \"" << name << '"' << endl;
+ response.MakeJoin(*player, world.Name());
+ client.Send(serv_pack, serv_sock);
} else {
// aw no :(
- cout << "\trejected" << endl;
+ cout << "rejected login from player \"" << name << '"' << endl;
+ response.MakePart();
+ client.Send(serv_pack, serv_sock);
+ client.Close();
}
}
+void Server::HandlePart(Connection &client, const UDPpacket &udp_pack) {
+ client.Close();
+}
+
}