move write_object to NetworkMessage, fix player sync, and implement projectile sync
#include "Engine.hh"
#include "SinglePlayer.hh"
#include "Config.hh"
// XXX: how does this work if we don't have NETWORK_ENABLED?
#include "Network/Reactor.hh"
// include the real component definitions
#if NETWORK_ENABLED
#include "Network/Client.hh"
#include "Network/Server.hh"
#endif
#if GRAPHICS_ENABLED
#include "Graphics/Graphics.hh"
#include "Graphics/GameView.hh"
#endif
#include <iostream>
#include <cassert>
/*
* Initialize static Engine global state
*/
LogLevel Engine::log_level = DEBUG;
Engine::Engine (const EngineConfig &config) :
terrain(NULL), game_state(NULL), graphics(NULL), net_server(NULL), net_client_connect(NULL),
game_view(NULL),
is_running(true), resources(config.resource_path)
{
// update global log_level
Engine::log_level = config.log_level;
}
void Engine::setupGame (Terrain *terrain) {
// ensure this isn't called in inappropriate ways
assert(!net_server);
// remember the terrain
this->terrain = terrain;
// create the GameState
game_state = new GameState(*terrain);
}
void Engine::setupGame (const TerrainConfig &config) {
// proxy off to setupGame(Terrain *)
setupGame(new Terrain(config));
}
void Engine::setupGraphics (const DisplayConfig &config) {
#if GRAPHICS_ENABLED
assert(!graphics);
// create the graphics
graphics = new graphics::Graphics(*this, resources, config);
#else
(void) config;
throw Error("No Graphics support available");
#endif
}
void Engine::startGameView (LocalPlayer *player) {
#if GRAPHICS_ENABLED
assert(graphics && !game_view);
game_view = graphics->displayGameView(*game_state, player);
#else
(void) player;
throw Error("No Graphics support available");
#endif
}
void Engine::setupNetworkServer (const std::string &listen_port) {
#if NETWORK_ENABLED
NetworkEndpoint listen_addr(listen_port);
assert(terrain && game_state);
// create the server
net_server = new NetworkServer(*game_state, listen_addr);
// put graphics into GameView mode
if (graphics)
startGameView(NULL);
#else
(void) listen_port;
throw Error("No Network support available");
#endif
}
void Engine::setupNetworkClient (const std::string &connect_host, const std::string &connect_port) {
#if NETWORK_ENABLED
// client operation requires graphics
if (!GRAPHICS_ENABLED)
throw Error("Network client mode requires graphics support");
// connect_to
NetworkEndpoint connect_addr(connect_host, connect_port);
// begin connecting, the client will callback us with setupGame once it's connected
net_client_connect = new NetworkClientConnect(*this, connect_addr);
#else
(void) connect_host;
(void) connect_port;
throw Error("No Network support available");
#endif
}
void Engine::setupSinglePlayer (void) {
assert(terrain && game_state);
// create player directly
LocalPlayer* lp = new SinglePlayer(*game_state);
// add to gamestate
game_state->setLocalPlayer(lp);
// put graphics into GameView mode
if (graphics)
startGameView(lp);
}
GameState& Engine::onNetworkClientConnected (Terrain *terrain) {
// sanity-check
assert(!this->terrain && !game_state && graphics);
// setup the game
setupGame(terrain);
// start the GameView, but no LocalPlayer yet
startGameView(NULL);
// return GameState
return *game_state;
}
void Engine::onNetworkClientPlayer (LocalPlayer *player) {
#if GRAPHICS_ENABLED
assert(game_view);
// set the GameView's player
game_view->setPlayer(player);
#else
(void) player;
assert(graphics);
#endif
}
void Engine::stop (void) {
is_running = false;
}
void Engine::run (void) {
#if NETWORK_ENABLED
// timeout for NetworkReactor
timeval timeout;
#endif
while (is_running) {
/*
* Run internal ClanLib stuff (also includes our timers) until our timeout has elapsed
*/
CL_System::keep_alive(ENGINE_TIMEOUT_MS);
#if NETWORK_ENABLED
// setup timeout to zero
timeout.tv_sec = 0;
timeout.tv_usec = 0;
/*
* Thursday came and went, I re-wrote clan-event.
*
* (actually, we only use it for zero-timeout polling now... not sure if this is better than using the above
* CL_System::keep_alive)
*/
NetworkReactor::current->poll(&timeout);
#endif
}
}