#include "Server.hpp"
#include "../app/init.hpp"
+#include "../model/CompositeModel.hpp"
#include "../world/World.hpp"
#include <cstring>
Client::Client(const Config &conf)
: conn(client_resolve(conf.host.c_str(), conf.port))
, client_sock(client_bind(0))
-, client_pack{ -1, nullptr, 0 } {
+, client_pack{ -1, nullptr, 0 }
+, update_timer(16) {
client_pack.data = new Uint8[sizeof(Packet)];
client_pack.maxlen = sizeof(Packet);
// establish connection
SendPing();
+ update_timer.Start();
}
Client::~Client() {
}
void Client::Update(int dt) {
+ update_timer.Update(dt);
conn.Update(dt);
if (conn.ShouldPing()) {
SendPing();
return conn.Send(client_pack, client_sock);
}
-uint16_t Client::SendPlayerUpdate(const Entity &player) {
+int Client::SendPlayerUpdate(const Entity &player) {
+ // don't send all too many updates
+ if (!update_timer.Hit()) return -1;
auto pack = Packet::Make<Packet::PlayerUpdate>(client_pack);
pack.WritePlayer(player);
return conn.Send(client_pack, client_sock);
, conn(addr)
, player(nullptr)
, spawns()
-, confirm_wait(0) {
+, confirm_wait(0)
+, player_update_pack(0)
+, player_update_timer(1500) {
conn.SetHandler(this);
}
string name;
pack.ReadPlayerName(name);
- Entity *new_player = server.GetWorld().AddPlayer(name);
+ Entity *new_player = server.GetWorld().AddPlayer(name).entity;
if (new_player) {
// success!
response.WritePlayer(*new_player);
response.WriteWorldName(server.GetWorld().Name());
conn.Send(server.GetPacket(), server.GetSocket());
+ // set up update tracking
+ player_update_pack = pack.Seq();
+ player_update_timer.Reset();
+ player_update_timer.Start();
} else {
// aw no :(
cout << "rejected login from player \"" << name << '"' << endl;
void ClientConnection::On(const Packet::PlayerUpdate &pack) {
if (!HasPlayer()) return;
- pack.ReadPlayer(Player());
+ int pack_diff = int16_t(pack.Seq()) - int16_t(player_update_pack);
+ bool overdue = player_update_timer.HitOnce();
+ player_update_timer.Reset();
+ if (pack_diff > 0 || overdue) {
+ player_update_pack = pack.Seq();
+ pack.ReadPlayer(Player());
+ }
}
void Packet::SpawnEntity::WriteEntity(const Entity &e) noexcept {
Write(e.ID(), 0);
- Write(e.ChunkCoords(), 4);
- Write(e.Position(), 16);
- Write(e.Velocity(), 28);
- Write(e.Orientation(), 40);
- Write(e.AngularVelocity(), 56);
- Write(e.Bounds(), 68);
+ if (e.GetModel()) {
+ Write(e.GetModel().GetModel().ID(), 4);
+ } else {
+ Write(uint32_t(0), 4);
+ }
+ Write(e.ChunkCoords(), 8);
+ Write(e.Position(), 20);
+ Write(e.Velocity(), 32);
+ Write(e.Orientation(), 44);
+ Write(e.AngularVelocity(), 60);
+ Write(e.Bounds(), 72);
uint32_t flags = 0;
if (e.WorldCollidable()) {
flags |= 1;
}
- Write(flags, 92);
- WriteString(e.Name(), 96, 32);
+ Write(flags, 96);
+ WriteString(e.Name(), 100, 32);
}
void Packet::SpawnEntity::ReadEntityID(uint32_t &id) const noexcept {
Read(id, 0);
}
+void Packet::SpawnEntity::ReadSkeletonID(uint32_t &id) const noexcept {
+ Read(id, 4);
+}
+
void Packet::SpawnEntity::ReadEntity(Entity &e) const noexcept {
glm::ivec3 chunk_coords(0);
glm::vec3 pos;
uint32_t flags = 0;
string name;
- Read(chunk_coords, 4);
- Read(pos, 16);
- Read(vel, 28);
- Read(rot, 40);
- Read(ang, 56);
- Read(bounds, 68);
- Read(flags, 92);
- ReadString(name, 96, 32);
+ Read(chunk_coords, 8);
+ Read(pos, 20);
+ Read(vel, 32);
+ Read(rot, 44);
+ Read(ang, 60);
+ Read(bounds, 72);
+ Read(flags, 96);
+ ReadString(name, 100, 32);
e.Position(chunk_coords, pos);
e.Velocity(vel);