- Partly implemented client side prediction (still unstable).
[peakengine.git] / engine / src / core / Game.cpp
blob1f8bd5c2e192161a196c254f3fd0acb62ade1347
1 /*
2 Copyright (C) 2009 Mathias Gottschlag
4 Permission is hereby granted, free of charge, to any person obtaining a copy of
5 this software and associated documentation files (the "Software"), to deal in the
6 Software without restriction, including without limitation the rights to use,
7 copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
8 Software, and to permit persons to whom the Software is furnished to do so,
9 subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in all
12 copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 #include "core/Game.h"
23 #include "core/Logger.h"
24 #include "core/Entity.h"
25 #include "network/NetworkHost.h"
26 #include "network/NetworkClient.h"
27 #include "network/BroadcastHost.h"
28 #include "network/Connection.h"
30 namespace peak
32 Game *Game::get(void)
34 static Game game;
35 return &game;
37 Game::~Game()
41 bool Game::init(bool client)
43 // Create network host
44 nethost = new NetworkHost;
45 if (!nethost->init(GAME_PORT))
47 LERROR("Could not create server.\n");
48 delete nethost;
49 nethost = 0;
50 return false;
53 stopgame = false;
54 timesinceupdate = 0;
55 server = true;
56 client = false;
58 time = 0;
60 return true;
62 bool Game::init(Address addr)
64 // Fill in standard port
65 if (addr.getPort() == 0) addr.setPort(GAME_PORT);
66 // Connect over network
67 netclient = new NetworkClient;
68 clientconn = netclient->init(addr);
69 if (!clientconn)
71 LERROR("Could not connect.\n");
72 delete netclient;
73 netclient = 0;
74 return false;
76 // Receive initial time
77 Buffer *timemsg = 0;
78 while (!timemsg)
80 netclient->doWork();
81 timemsg = clientconn->readData();
83 time = timemsg->readInt();
84 delete timemsg;
85 printf("Initial time: %d\n", time);
87 // Receive initial entities
88 Buffer *entitydata = 0;
89 while (!entitydata)
91 netclient->doWork();
92 entitydata = clientconn->readData();
94 printf("Got %d bytes of entity data.\n", entitydata->getDataSize());
95 while (entitydata->getPosition() != entitydata->getDataSize())
97 int id = entitydata->readInt();
98 std::string type = entitydata->readString();
99 createClientEntity(type, id, 0);
101 delete entitydata;
103 stopgame = false;
104 server = false;
105 client = true;
107 return true;
110 bool Game::shutdown(void)
112 if (!server && !client) return true;
114 if (bchost)
116 bchost->shutdown();
117 delete bchost;
118 bchost = 0;
121 // Destroy network client/server
122 if (server)
124 nethost->shutdown();
125 delete nethost;
126 //serverconns.clear();
127 nethost = 0;
128 server = false;
129 client = false;
131 else if (client)
133 /*// Disconnect
134 Buffer msg;
135 msg.writeByte(ENM_Disconnect);
136 //clientconn->sendData(&msg, true);
137 clientconn->disconnect();
138 for (int i = 0; i < 1000; i++)
140 netclient->doWork();
141 if (!netclient->isConnected())
143 break;
146 // Destroy client
147 netclient->shutdown();
148 delete netclient;
149 netclient = 0;
150 client = false;
153 return true;
156 void Game::stopGame(void)
158 stopgame = true;
161 bool Game::isServer(void)
163 return server;
165 bool Game::isClient(void)
167 return client;
170 void Game::setVisible(bool visible)
172 if (server)
174 if (visible && !bchost)
176 bchost = new BroadcastHost;
177 bchost->init(27273);
179 else if (!visible && bchost)
181 bchost->shutdown();
182 delete bchost;
183 bchost = 0;
187 bool Game::isVisible(void)
189 return (bchost != 0);
192 int Game::getClientCount(void)
194 return 0;
197 Connection *Game::getClientConnection(int client)
199 return 0;
202 Connection *Game::getServerConnection(void)
204 return 0;
207 Entity *Game::createEntity(std::string type, int owner)
209 if (!isServer())
211 printf("No server.\n");
212 return 0;
214 // Get create function
215 std::map<std::string, Entity *(*)(void)>::iterator it = entitytypes.find(type);
216 if (it == entitytypes.end())
218 printf("Entity type not found.\n");
219 return 0;
221 Entity *(*create)(void) = it->second;
222 // Create entity
223 int id = getNewEntityID();
224 Entity *entity = create();
225 entity->setID(id);
226 if (!entity->init(type))
228 printf("Could not initialize entity.\n");
229 delete entity;
230 return 0;
232 entities[id - 1] = entity;
233 printf("Created %d.\n", id - 1);
235 // TODO: Send entity to clients
237 return entity;
239 Entity *Game::createClientEntity(std::string type, int id, int owner)
241 // Get create function
242 std::map<std::string, Entity *(*)(void)>::iterator it = entitytypes.find(type);
243 if (it == entitytypes.end())
245 printf("Entity type not found.\n");
246 return 0;
248 Entity *(*create)(void) = it->second;
249 // Create entity
250 Entity *entity = create();
251 entity->setID(id);
252 if (!entity->init(type))
254 printf("Could not initialize entity.\n");
255 delete entity;
256 return 0;
258 entities[id - 1] = entity;
259 printf("Created %d.\n", id - 1);
261 return entity;
263 Entity *Game::getEntity(int id)
265 if ((id == 0) || (id > 65535))
266 return 0;
267 return entities[id];
269 bool Game::deleteEntity(Entity *entity, bool now)
271 return false;
274 int Game::getEntityCount(std::string type)
276 return 0;
278 Entity *Game::getEntity(std::string name, int index)
280 return 0;
283 void Game::doWork(float msecs)
285 if (!server && !client) return;
286 // Shutdown game?
287 if (stopgame)
289 shutdown();
290 return;
293 // Answer broadcast messages
294 if (bchost)
296 bchost->doWork();
299 if (isServer())
301 time++;
303 nethost->doWork();
305 // Look for disconnected clients
306 for (unsigned int i = 0; i < clients.size(); i++)
308 if (!clients[i]->conn->isConnected())
310 // Delete connection
311 //int id = clients[i]->owner;
312 nethost->closeConnection(clients[i]->conn);
313 delete clients[i];
314 clients.erase(clients.begin() + i);
315 // TODO: Delete entities
316 //destroyEntities(id);
317 i--;
320 // Look for new clients
321 Connection *newconn;
322 while ((newconn = nethost->getNewConnection()) != 0)
324 LINFO("New connection!\n");
325 // Send initial time
326 Buffer msg;
327 msg.writeInt(time);
328 newconn->sendData(&msg, true);
329 // Add client to list
330 int id = ++lastclientid;
331 clients.push_back(new ClientInfo(newconn, id));
332 // Send existing objects
333 msg.clear();
334 for (int i = 0; i < 65535; i++)
336 if (entities[i])
338 printf("Sending entity %d\n", i + 1);
339 msg.writeInt(i + 1);
340 msg.writeString(entities[i]->getType());
341 if (!entities[i]->sendFullUpdate(&msg))
342 break;
345 printf("Initial update: %d bytes.\n", msg.getDataSize());
346 newconn->sendData(&msg, true);
348 // Read incoming data from clients
349 for (unsigned int i = 0; i < clients.size(); i++)
351 Buffer *msg;
352 while ((msg = clients[i]->conn->readData()) != 0)
354 int type = msg->readByte();
355 if (type == 1)
357 if (msg->getDataSize() < 5) return;
358 // Client command
359 printf("Client command: %d bytes.\n", msg->getDataSize());
360 int entity = msg->readWord();
361 int id = msg->readWord();
362 if (entity == 0)
363 break;
364 if (!entities[entity - 1])
365 break;
366 // Insert command into system
367 // TODO: Validation
368 EntityCommand *command = new EntityCommand;
369 command->data = Buffer(msg->getData() + 5, msg->getDataSize() - 5);
370 command->id = id;
371 command->timestamp = getTime();
372 entities[entity - 1]->sendCommand(command);
374 delete msg;
377 // Physics engine
378 // Game logic
379 for (int i = 0; i < 65535; i++)
381 if (entities[i])
383 entities[i]->applyNextCommand();
384 entities[i]->update(msecs);
385 entities[i]->save();
388 // Write updates to clients
389 int currententity = nextentity;
390 Buffer updatebuffer;
391 updatebuffer.writeByte(1);
392 updatebuffer.writeInt(getTime());
393 for (int i = 0; i < 65535; i++)
395 int currententity = (nextentity + i) % 65535;
396 if (entities[currententity])
398 // Add update to buffer
399 updatebuffer.writeWord(currententity + 1);
400 updatebuffer.writeWord(entities[currententity]->getLastCommandID());
401 updatebuffer.writeWord(getTime() - entities[currententity]->getLastCommandTime());
402 if (!entities[currententity]->update(&updatebuffer))
404 updatebuffer.setSize(updatebuffer.getDataSize() - 2);
406 if (updatebuffer.getDataSize() >= 500)
407 break;
410 nextentity = currententity;
411 printf("Incremental update: %d bytes.\n", updatebuffer.getDataSize());
412 if (updatebuffer.getDataSize() > 1)
413 sendDataToClients(&updatebuffer, false);
415 else
417 netclient->doWork();
419 // Read incoming data from server
420 unsigned int newesttime = time;
421 Buffer *msg;
422 while ((msg = clientconn->readData()) != 0)
424 printf("Server data: %d bytes.\n", msg->getDataSize());
425 int type = msg->readByte();
426 if (type == 1)
428 unsigned int time = msg->readInt();
429 if (time < newesttime)
431 for (int i = 0; i < 65535; i++)
433 if (entities[i])
435 entities[i]->reset(time);
438 newesttime = time;
439 this->time = time;
441 else
443 while (this->time != time)
445 this->time++;
446 for (int i = 0; i < 65535; i++)
448 if (entities[i])
450 entities[i]->update(20);
451 entities[i]->save();
456 // Delta updates
457 while (msg->getPosition() < msg->getDataSize())
459 // Get entity
460 int entity = msg->readWord();
461 if (entity == 0)
462 break;
463 if (!entities[entity - 1])
464 break;
465 int cmdid = msg->readWord();
466 EntityCommand *cmd = 0;
467 if (cmdid != 0)
469 printf("Command: %d\n", cmdid);
470 cmd = entities[entity - 1]->getCommand(cmdid);
472 int cmdtime = msg->readWord();
473 if (cmd)
475 cmdtime += cmd->timestamp;
476 printf("Command data %d ticks in the past.\n", time - cmdtime);
477 EntityState *state = entities[entity - 1]->getState(cmdtime);
478 if (!state || (time - cmdtime <= 0))
480 if (state == 0)
482 printf("State %d not there (now: %d).\n", cmdtime, time);
484 // Force update
485 cmd = 0;
487 else if (!entities[entity - 1]->checkState(state, msg))
489 entities[entity - 1]->applyDeltaUpdate(msg, 0, state);
490 // Reset to step to which the update refers to
491 for (int i = 0; i < 65535; i++)
493 if (entities[i])
495 if (i != entity - 1)
497 entities[i]->reset(cmdtime);
499 else
501 entities[i]->reset(cmdtime, true);
505 int timedifference = time - cmdtime;
506 this->time = cmdtime;
507 // Replay last frames
508 for (int i = 0; i < timedifference; i++)
510 printf(".");
511 this->time++;
512 for (int i = 0; i < 65535; i++)
514 if (entities[i])
516 entities[i]->update(20);
517 if (i == entity - 1)
519 entities[i]->applyCommand(this->time);
520 entities[i]->save();
522 else
524 entities[i]->reset(this->time);
529 printf("\n");
532 if (cmd || entities[entity - 1]->getLastCommandID())
534 break;
536 // Inject delta update
537 if (!entities[entity - 1]->injectUpdate(time, msg, time == this->time))
538 break;
540 //if (time > newesttime)
541 // newesttime = time;
543 delete msg;
545 // FIXME: We really need proper error handling here
546 /*if (newesttime != time)
548 // Update from the future
549 printf("Warning: Update from the future.\n");
550 while (newesttime != time)
552 time++;
553 for (int i = 0; i < 65535; i++)
555 if (entities[i])
557 entities[i]->update(msecs);
558 entities[i]->save();
563 else
565 //printf("Update: %d\n", newesttime - time);
567 // Game logic
568 time++;
569 for (int i = 0; i < 65535; i++)
571 if (entities[i])
573 entities[i]->update(msecs);
574 entities[i]->save();
577 // Write commands to the server
581 void Game::addEntityType(std::string name, Entity *(*create)(void))
583 entitytypes.insert(std::pair<std::string, Entity *(*)(void)>(name, create));
585 void Game::removeEntityType(std::string name)
587 std::map<std::string, Entity *(*)(void)>::iterator it = entitytypes.find(name);
588 if (it != entitytypes.end())
590 entitytypes.erase(it);
594 void Game::sendDataToClients(Buffer *data, bool reliable)
596 for (unsigned int i = 0; i < clients.size(); i++)
598 clients[i]->conn->sendData(data, reliable);
601 void Game::sendServerData(Buffer *data, bool reliable)
603 clientconn->sendData(data, reliable);
606 Game::Game()
608 for (int i = 0; i < 65535; i++)
610 entities[i] = 0;
612 nextentity = 0;
615 int Game::getNewEntityID(void)
617 for (int i = 0; i < 65535; i++)
619 if (entities[i] == 0)
620 return i + 1;
622 return 0;
625 int Game::lastclientid = 0;