src/Engine.cc
author Tero Marttila <terom@fixme.fi>
Tue, 27 Jan 2009 00:25:58 +0200
changeset 439 9823e6cd1086
parent 431 c6d7272a164b
permissions -rw-r--r--
some README text

#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        
    }
}