void Entity::applyUpdate(BufferPointer buffer) { for (unsigned int i = 0; i < properties.size(); i++) { int changed = buffer->readUnsignedInt(1); if (changed && (properties[i].getFlags() & EPF_Unlocked)) { properties[i].read(buffer); } } }
void Entity::setState(BufferPointer buffer) { if (buffer.isNull()) return; for (unsigned int i = 0; i < properties.size(); i++) { int changed = buffer->readUnsignedInt(1); if (changed) { properties[i].read(buffer); } } }
void ClientWorldComponent::onPreUpdate() { client->update(); // Receive data while (connection->hasData()) { BufferPointer data = connection->receive(); PacketType type = (PacketType)data->read8(); switch (type) { case EPT_EntityCreated: { unsigned int id = data->read16() + 1; std::string type = data->readString(); bool local = data->readUnsignedInt(1); // Create entity Game *game = getWorld()->getEngine()->getGame(); EntityFactory *factory = game->getEntityFactory(type); if (!factory) { std::cout << "Could not get entity factory " << type << std::endl; continue; } Entity *entity = factory->createEntity(getWorld()); ClientEntityComponent *component = (ClientEntityComponent*)entity->getComponent(EECT_Client); component->setID(id); component->setState(data.get()); addEntity(entity); getWorld()->addEntity(entity); break; } case EPT_EntityDeleted: { unsigned int id = data->read16() + 1; Entity *entity = getEntity(id); removeEntity(entity); delete entity; break; } case EPT_Update: { bool updatevalid = true; unsigned int updatetime = data->read32(); unsigned int updateclienttime = data->read32(); lastacked = data->read32(); // Adjust time if the latency has decreased // TODO: This might affect client prediction if (updatetime > getWorld()->getTime()) getWorld()->setTime(updatetime); // Apply the updates while (data->getPosition() + 16 <= data->getSize() * 8) { unsigned int id = data->read16() + 1; ClientEntityComponent *entity = getComponent(id); // Ignore invalid updates if (!entity) { updatevalid = false; break; } // Apply backup to remove any user changes if (entity->hasBackup()) entity->applyBackup(); // Apply update entity->applyUpdate(data.get(), updatetime); entity->onUpdate().trigger(updateclienttime); } // Only send the server that we have received this // update if it was valid if (updatevalid) lastupdate = updatetime; break; } case EPT_EntityMessage: { unsigned int id = data->read16() + 1; ClientEntityComponent *entity = getComponent(id); entity->onMessage().trigger(data.get()); break; } default: // TODO: Warn break; } } }