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"
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");
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
);
71 LERROR("Could not connect.\n");
76 // Receive initial time
81 timemsg
= clientconn
->readData();
83 time
= timemsg
->readInt();
85 printf("Initial time: %d\n", time
);
87 // Receive initial entities
88 Buffer
*entitydata
= 0;
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);
110 bool Game::shutdown(void)
112 if (!server
&& !client
) return true;
121 // Destroy network client/server
126 //serverconns.clear();
135 msg.writeByte(ENM_Disconnect);
136 //clientconn->sendData(&msg, true);
137 clientconn->disconnect();
138 for (int i = 0; i < 1000; i++)
141 if (!netclient->isConnected())
147 netclient
->shutdown();
156 void Game::stopGame(void)
161 bool Game::isServer(void)
165 bool Game::isClient(void)
170 void Game::setVisible(bool visible
)
174 if (visible
&& !bchost
)
176 bchost
= new BroadcastHost
;
179 else if (!visible
&& bchost
)
187 bool Game::isVisible(void)
189 return (bchost
!= 0);
192 int Game::getClientCount(void)
197 Connection
*Game::getClientConnection(int client
)
202 Connection
*Game::getServerConnection(void)
207 Entity
*Game::createEntity(std::string type
, int owner
)
211 printf("No server.\n");
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");
221 Entity
*(*create
)(void) = it
->second
;
223 int id
= getNewEntityID();
224 Entity
*entity
= create();
226 if (!entity
->init(type
))
228 printf("Could not initialize entity.\n");
232 entities
[id
- 1] = entity
;
233 printf("Created %d.\n", id
- 1);
235 // TODO: Send entity to clients
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");
248 Entity
*(*create
)(void) = it
->second
;
250 Entity
*entity
= create();
252 if (!entity
->init(type
))
254 printf("Could not initialize entity.\n");
258 entities
[id
- 1] = entity
;
259 printf("Created %d.\n", id
- 1);
263 Entity
*Game::getEntity(int id
)
265 if ((id
== 0) || (id
> 65535))
269 bool Game::deleteEntity(Entity
*entity
, bool now
)
274 int Game::getEntityCount(std::string type
)
278 Entity
*Game::getEntity(std::string name
, int index
)
283 void Game::doWork(float msecs
)
285 if (!server
&& !client
) return;
293 // Answer broadcast messages
305 // Look for disconnected clients
306 for (unsigned int i
= 0; i
< clients
.size(); i
++)
308 if (!clients
[i
]->conn
->isConnected())
311 //int id = clients[i]->owner;
312 nethost
->closeConnection(clients
[i
]->conn
);
314 clients
.erase(clients
.begin() + i
);
315 // TODO: Delete entities
316 //destroyEntities(id);
320 // Look for new clients
322 while ((newconn
= nethost
->getNewConnection()) != 0)
324 LINFO("New connection!\n");
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
334 for (int i
= 0; i
< 65535; i
++)
338 printf("Sending entity %d\n", i
+ 1);
340 msg
.writeString(entities
[i
]->getType());
341 if (!entities
[i
]->sendFullUpdate(&msg
))
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
++)
352 while ((msg
= clients
[i
]->conn
->readData()) != 0)
354 int type
= msg
->readByte();
357 if (msg
->getDataSize() < 5) return;
359 printf("Client command: %d bytes.\n", msg
->getDataSize());
360 int entity
= msg
->readWord();
361 int id
= msg
->readWord();
364 if (!entities
[entity
- 1])
366 // Insert command into system
368 EntityCommand
*command
= new EntityCommand
;
369 command
->data
= Buffer(msg
->getData() + 5, msg
->getDataSize() - 5);
371 command
->timestamp
= getTime();
372 entities
[entity
- 1]->sendCommand(command
);
379 for (int i
= 0; i
< 65535; i
++)
383 entities
[i
]->applyNextCommand();
384 entities
[i
]->update(msecs
);
388 // Write updates to clients
389 int currententity
= nextentity
;
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)
410 nextentity
= currententity
;
411 printf("Incremental update: %d bytes.\n", updatebuffer
.getDataSize());
412 if (updatebuffer
.getDataSize() > 1)
413 sendDataToClients(&updatebuffer
, false);
419 // Read incoming data from server
420 unsigned int newesttime
= time
;
422 while ((msg
= clientconn
->readData()) != 0)
424 printf("Server data: %d bytes.\n", msg
->getDataSize());
425 int type
= msg
->readByte();
428 unsigned int time
= msg
->readInt();
429 if (time
< newesttime
)
431 for (int i
= 0; i
< 65535; i
++)
435 entities
[i
]->reset(time
);
443 while (this->time
!= time
)
446 for (int i
= 0; i
< 65535; i
++)
450 entities
[i
]->update(20);
457 while (msg
->getPosition() < msg
->getDataSize())
460 int entity
= msg
->readWord();
463 if (!entities
[entity
- 1])
465 int cmdid
= msg
->readWord();
466 EntityCommand
*cmd
= 0;
469 printf("Command: %d\n", cmdid
);
470 cmd
= entities
[entity
- 1]->getCommand(cmdid
);
472 int cmdtime
= msg
->readWord();
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))
482 printf("State %d not there (now: %d).\n", cmdtime
, time
);
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
++)
497 entities
[i
]->reset(cmdtime
);
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
++)
512 for (int i
= 0; i
< 65535; i
++)
516 entities
[i
]->update(20);
519 entities
[i
]->applyCommand(this->time
);
524 entities
[i
]->reset(this->time
);
532 if (cmd
|| entities
[entity
- 1]->getLastCommandID())
536 // Inject delta update
537 if (!entities
[entity
- 1]->injectUpdate(time
, msg
, time
== this->time
))
540 //if (time > newesttime)
541 // newesttime = time;
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)
553 for (int i = 0; i < 65535; i++)
557 entities[i]->update(msecs);
565 //printf("Update: %d\n", newesttime - time);
569 for (int i
= 0; i
< 65535; i
++)
573 entities
[i
]->update(msecs
);
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
);
608 for (int i
= 0; i
< 65535; i
++)
615 int Game::getNewEntityID(void)
617 for (int i
= 0; i
< 65535; i
++)
619 if (entities
[i
] == 0)
625 int Game::lastclientid
= 0;