bool ClientWorldComponent::init(std::string address, unsigned int port, unsigned int timeout) { // Create connection client = new NetworkClient(); if(!client->init()) { delete client; client = 0; return false; } connection = client->connect(address, port, timeout); if(!connection) { delete client; client = 0; return false; } // Receive server data // FIXME: Infinite loop if the server does not respond. BufferPointer initialdata; while (!initialdata) { client->update(); if (connection->hasData()) { initialdata = connection->receive(); PacketType type = (PacketType)initialdata->read8(); if (type != EPT_InitialData) { initialdata = 0; } } } serverdata = initialdata; return true; }
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; } } }