From 0b8582a9aa825024edbd0a21c6287bfcccec28de Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Mon, 18 Feb 2008 17:52:15 +0000 Subject: core redesign, part II --- README | 41 ++++++--- osirion.kdevelop.pcs | Bin 403551 -> 420253 bytes osirion.kdevses | 9 +- src/core/Makefile.am | 6 +- src/core/application.cc | 202 ++++++++++----------------------------------- src/core/application.h | 65 ++++++++------- src/core/commandbuffer.cc | 4 +- src/core/core.h | 12 +-- src/core/cvar.cc | 2 +- src/core/entity.h | 2 - src/core/func.cc | 2 +- src/core/gameinterface.cc | 80 +++++++----------- src/core/gameinterface.h | 52 +++++------- src/core/gameserver.cc | 206 ++++++++++++++++++++++++++++++++++++++++++++++ src/core/gameserver.h | 75 +++++++++++++++++ src/core/module.cc | 41 +++++++++ src/core/module.h | 74 +++++++++++++++++ src/core/netclient.cc | 1 - src/core/netgame.cc | 0 src/core/netgame.h | 12 --- src/core/netserver.cc | 90 +++++++------------- src/core/player.h | 4 +- src/game/game.cc | 48 ++++++----- src/game/game.h | 7 +- src/net/tcpserver.cc | 12 +-- src/osirion.cc | 7 +- src/osiriond.cc | 7 +- src/render/tga.cc | 1 + 28 files changed, 642 insertions(+), 420 deletions(-) create mode 100644 src/core/gameserver.cc create mode 100644 src/core/gameserver.h create mode 100644 src/core/module.cc create mode 100644 src/core/module.h delete mode 100644 src/core/netgame.cc delete mode 100644 src/core/netgame.h diff --git a/README b/README index 1ce6035..4d3b555 100644 --- a/README +++ b/README @@ -9,8 +9,8 @@ The Osirion Project Dedicated server - The dedicated server can be started, but it does not yet - support network connections or local input. + The dedicated server can be started and accepts incoming connections. + The default port is 8042. You can connect to it with telnet. Client @@ -20,9 +20,13 @@ Client to join the game. Type 'spectate' to spectate again. Type 'disconnect' to return to the loader screen. + The client is capable of acting as a networked server. You can enable + the private server by setting 'sv_private 1' before you 'connect'. If + you telnet to the private server and type 'join' new ship will appear. + Controls - ~: toggle client console visibility + ~: toggle console space bar: switch camera mode left/right/up/down arrow keys: rotate camera in free mode keypad left/right: turn the ship left/right @@ -34,9 +38,9 @@ Console functions connect connect the client to the game module disconnect disconnect the client from the game module - list_ent lists registered entities - list_func lists registered functions - list_var lists registered variables + list_ent list registered entities + list_func list registered functions + list_var list registered variables quit exit the application r_restart restart the video subsystem @@ -48,10 +52,10 @@ Console functions r_height 768 r_restart - To switch to windowed mode, set the r_fullscreen - variable to 0: + To switch to fullscreen mode, set the r_fullscreen + variable to 1: - r_fullscreen 0 + r_fullscreen 1 r_restart Organization of the distribution @@ -73,11 +77,28 @@ Organization of the distribution The game data can be obtained as a seperate distribution. Refer to the file INSTALLATION for more information. +Acknowledgements + + This project could not have been possible without the work of others: + + Id Software, for releasing the quake source code, which obviously + acted as a example. + + Id Software and the GtkRadiant project contributers + + The Quake2World community + + The Satgnu crew + + Thanks to bobke, blaze-x and Thorn[mDc] + + A special thanks to all =KCT= members + License The program is distributed under the terms and conditions of the GNU General Public License version 2. Copyright 2007-2008 - Ingar + Ingar=KCT= diff --git a/osirion.kdevelop.pcs b/osirion.kdevelop.pcs index 5818147..bce43cb 100644 Binary files a/osirion.kdevelop.pcs and b/osirion.kdevelop.pcs differ diff --git a/osirion.kdevses b/osirion.kdevses index b9db452..e8415d1 100644 --- a/osirion.kdevses +++ b/osirion.kdevses @@ -1,14 +1,7 @@ - - - - - - - - + diff --git a/src/core/Makefile.am b/src/core/Makefile.am index cbe1efd..6c42468 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -2,13 +2,13 @@ METASOURCES = AUTO INCLUDES = -I$(top_srcdir)/src libcore_la_SOURCES = application.cc commandbuffer.cc core.cc cvar.cc entity.cc \ - func.cc gameinterface.cc netclient.cc netconnection.cc netgame.cc netserver.cc \ - player.cc + func.cc gameinterface.cc gameserver.cc module.cc netclient.cc netconnection.cc \ + netserver.cc player.cc libcore_la_LDFLAGS = -avoid-version -no-undefined libcore_la_LIBADD = $(top_builddir)/src/math/libmath.la \ $(top_builddir)/src/filesystem/libfilesystem.la $(top_builddir)/src/sys/libsys.la $(top_builddir)/src/net/libnet.la noinst_LTLIBRARIES = libcore.la noinst_HEADERS = application.h commandbuffer.h core.h cvar.h entity.h func.h \ - gameinterface.h netconnection.h netgame.h player.h + gameinterface.h gameserver.h module.h netconnection.h player.h diff --git a/src/core/application.cc b/src/core/application.cc index 5d313ad..9c7620a 100644 --- a/src/core/application.cc +++ b/src/core/application.cc @@ -18,17 +18,11 @@ #include "core/cvar.h" #include "core/entity.h" #include "core/func.h" -#include "core/netserver.h" +#include "core/gameserver.h" namespace core { -// return the global application object -Application *application() -{ - return Application::instance(); -} - // --------------- engine functions ------------------------------ void func_print(std::string const &args) { @@ -61,24 +55,7 @@ void func_disconnect(std::string const &args) application()->disconnect(); } -// FIXME this is a game function -void func_say(std::string const &args) -{ - if (application()->netserver) { - std::ostringstream osstream; - osstream << "msg public " << Player::local.name() << " " << args << "\n"; - application()->netserver->broadcast(osstream.str()); - con_print << Player::local.name() << ": " << args << "\n"; - } else if (application()->netconnection.connected()) { - std::ostringstream osstream; - osstream << args << "\n"; - application()->netconnection.send(args); - } else if (game() && game()->connected) { - con_print << args << "\n"; - } else - con_print << "Not connected."; -} - +/* void func_name(std::string const &args) { std::istringstream argstream(args); std::string name; @@ -113,6 +90,7 @@ void func_name(std::string const &args) { Player::local.player_name = name; } +*/ // --------------- signal_handler ----------------------------------- @@ -151,8 +129,8 @@ Application::Application() } application_instance = this; - netserver = 0; - gameinterface_preload = 0; + application_time = 0; + application_game = 0; sys::signal(SIGHUP, signal_handler); sys::signal(SIGINT, signal_handler); @@ -163,22 +141,6 @@ Application::Application() Application::~Application() { application_instance = 0; - } - -Application *Application::instance() -{ - return application_instance; -} - -float Application::time() const -{ - return game_time; -} - -bool Application::connected() const -{ - return (Application::instance()->netconnection.connected() || - (GameInterface::instance() && GameInterface::instance()->connected)); } void Application::init() @@ -190,24 +152,11 @@ void Application::init() CommandBuffer::init(); - gameinterface_preload = core::GameInterface::gameinterface_instance; - core::GameInterface::gameinterface_instance = 0; - if (gameinterface_preload) { - con_print << " preloaded game found: " << gameinterface_preload->name() << "\n"; - } - game_time = 0; - - // dedicated server should set this to 1 + // dedicated server has set this to 1 Cvar::sv_dedicated = Cvar::get("sv_dedicated", "0", Cvar::ReadOnly); - // client can set this to 1 Cvar::sv_private = Cvar::get("sv_private", "0"); - if (Cvar::sv_dedicated->value()) - Player::local.player_name = "Console"; - else - Player::local.player_name = "Player0"; - // network settings Cvar::net_host = Cvar::get("net_host", "0.0.0.0"); Cvar::net_port = Cvar::get("net_port", "8042"); @@ -220,8 +169,7 @@ void Application::init() Func::add("connect", func_connect); Func::add("disconnect", func_disconnect); - Func::add("say", func_say); - Func::add("name", func_name); + //Func::add("name", func_name); } void Application::shutdown() @@ -231,6 +179,11 @@ void Application::shutdown() if (connected()) disconnect(); + if (application_game) { + delete application_game; + application_game = 0; + } + // remove our engine functions Func::remove("print"); Func::remove("help"); @@ -238,9 +191,7 @@ void Application::shutdown() Func::remove("connect"); Func::remove("disconnect"); - - Func::remove("say"); - Func::remove("name"); + //Func::remove("name"); CommandBuffer::shutdown(); @@ -252,48 +203,22 @@ void Application::quit(int status) sys::quit(status); } -// clear all game realted objects -void Application::clear() -{ - // remove all entities - for (std::map::iterator it = Entity::registry.begin(); it != Entity::registry.end(); it++) { - delete (*it).second; - } - Entity::registry.clear(); - - // remove all game functions - for (std::map::iterator it = Func::registry.begin(); it != Func::registry.end(); it++) { - if ( ((*it).second->flags() & Func::Game) == Func::Game) { - delete (*it).second; - Func::registry.erase(it); - } - } - - // remove all game cvars - for (std::map::iterator it = Cvar::registry.begin(); it != Cvar::registry.end(); it++) { - if ( ((*it).second->flags() & Cvar::Game) == Cvar::Game) { - delete (*it).second; - Cvar::registry.erase(it); - } - } -} void Application::connect(std::string const &host) { - if (game() && game()->connected || netconnection.connected()) { + if (connected()) { con_warn << "Connected. Disconnect first.\n"; return; } + - if (game()) { - // unload previous game - if (game() != gameinterface_preload) - delete core::GameInterface::gameinterface_instance; + if (application_game) { + delete application_game; + application_game = 0; } - - clear(); - + if (host.size()) { + /* // connect to remote core core::GameInterface::gameinterface_instance = 0; std::string remotehost(host); @@ -316,97 +241,58 @@ void Application::connect(std::string const &host) netconnection.disconnect(); con_warn << "Could not connect to '" << host << "'\n"; } + */ + con_warn << "Can not connect to remote core.... yet!\n"; } else { - // use preloaded game - core::GameInterface::gameinterface_instance = gameinterface_preload; + application_game = new GameServer(); - // reset everything - game_time = 0; - - if (game()->connected = game()->init()) { + if (application_game->running()) { con_print << "Connected.\n"; } else { + delete application_game; + application_game = 0; con_warn << "Could not connect.\n"; - return; - } - - if (!netserver && (Cvar::sv_dedicated->value() || Cvar::sv_private->value())) { - netserver = new NetServer(Cvar::net_host->str(), (unsigned int)Cvar::net_port->value()); - if (!netserver->valid()) { - delete netserver; - if (Cvar::sv_dedicated->value()) - shutdown(); - } } } } void Application::disconnect() { - if (netserver) { - delete netserver; - netserver = 0; + + if(application_game) { + delete application_game; + application_game = 0; + con_print << "Disconnected.\n"; } + /* if (netconnection.connected()) { netconnection.disconnect(); con_print << "Disconnected.\n"; return; } - - if (game()) { - if (!game()->connected) { - con_warn << "Not connected.\n"; - return; - } - - game()->shutdown(); - game()->connected = false; - game_time = 0; - - clear(); - - con_print << "Disconnected.\n"; - } + */ } void Application::frame(float seconds) { - if (seconds == 0.0f) - return; - // execute commands in the buffer CommandBuffer::exec(); - // update entities - if (connected()) { - std::map::iterator it; - for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { - Entity *entity = (*it).second; - if ((entity->type() == Entity::Controlable) || (entity->type() == Entity::Dynamic)) { - entity->frame(seconds); - } - } - } + // don't run zero lenght time frames + if (seconds == 0.0f) + return; - // netstuff - if (netconnection.connected()) { - netconnection.frame(seconds); - // TODO this should come from server - game_time += seconds; - } else { - if (netserver) { - // TODO limit netserver frames in local mode - netserver->frame(seconds); - } + application_time += seconds; - if (game() && game()->connected) { - game_time += seconds; + if (!connected()) + return; + + // run a game interface frame + application_game->frame(seconds); - game()->frame(seconds); - } - } + if (!application_game->running()) + disconnect(); } } - diff --git a/src/core/application.h b/src/core/application.h index 0f4c5fa..de0ab35 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -25,35 +25,18 @@ public: /// default destructor virtual ~Application(); - /// initialize the application - virtual void init(); - - /// shutdown the application - virtual void shutdown(); - - /// a pointer to the current application instance - static Application *instance(); - - /// time the has been connected, in seconds - float time() const; - - /// preloaded game object - GameInterface *gameinterface_preload; - - /// true if the core is connected to a game module or a remote server - bool connected() const; +/*----- inspectors ----------------------------------------------- */ - /// network server instance - NetServer *netserver; - - /// network client to server connection - NetConnection netconnection; + /// time the application has been running + inline float time() const { return application_time; } - /// global application object - static Application *application_instance; + /// true if the core is connected to a running game interface + inline bool connected() const { return (application_game && application_game->running()); } - /// quit the application without proper shutdown - virtual void quit(int status); + /// return the game interface, returns 0 if the pplication is not connected to a game + inline GameInterface *game() { return application_game; } + +/*----- mutators ------------------------------------------------- */ /// start the server or connect to remote host void connect(std::string const &host); @@ -61,20 +44,38 @@ public: /// disconnect from the game module void disconnect(); -protected: - /// clear all game related objects - void clear(); +/*----- virtual mutators ------------------------------------------ */ + /// initialize the application + virtual void init(); + + /// shutdown the application + virtual void shutdown(); + + /// quit the application without proper shutdown + virtual void quit(int status); + +/*----- static --------------------------------------------------- */ + + /// a pointer to the current application instance + static inline Application *instance() { return application_instance; } + +protected: /// run a core frame virtual void frame(float seconds); private: /// time the core has been running - float game_time; + float application_time; + GameInterface *application_game; + static Application *application_instance; }; -/// pointer to the current ApplicationInterface -Application *application(); +/// pointer to the current Application +inline Application *application() { return Application::instance(); } + +/// pointer to the current GameInterface +inline GameInterface *game() { return Application::instance()->game(); } } // namespace core diff --git a/src/core/commandbuffer.cc b/src/core/commandbuffer.cc index 8f02f71..5ab40e5 100644 --- a/src/core/commandbuffer.cc +++ b/src/core/commandbuffer.cc @@ -9,10 +9,10 @@ #include #include "sys/sys.h" +#include "core/application.h" #include "core/commandbuffer.h" #include "core/func.h" #include "core/cvar.h" -#include "core/gameinterface.h" namespace core { @@ -75,7 +75,7 @@ void CommandBuffer::exec(std::string const &cmdline) args += c; } if ((f->flags() & Func::Game)) { - if (game() && game()->connected) { + if (application()->connected()) { f->exec(&Player::local, args); } } else { diff --git a/src/core/core.h b/src/core/core.h index 4e2af22..2a23d84 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -7,22 +7,22 @@ #ifndef __INCLUDED_CORE_H__ #define __INCLUDED_CORE_H__ +/// core contains the basic functionality of the engine +namespace core +{ +} + #include "core/application.h" #include "core/commandbuffer.h" #include "core/cvar.h" #include "core/entity.h" #include "core/func.h" #include "core/gameinterface.h" +#include "core/module.h" #include "core/netserver.h" #include "core/netclient.h" #include "core/netconnection.h" #include "core/player.h" -/// core contains the basic functionality of the engine -namespace core -{ - -} - #endif // __INCLUDED_CORE_H__ diff --git a/src/core/cvar.cc b/src/core/cvar.cc index dbe1d30..9419db3 100644 --- a/src/core/cvar.cc +++ b/src/core/cvar.cc @@ -159,7 +159,7 @@ void Cvar::list() else typeindicator += ' '; - con_print << std::setw(4) << (*it).second->flags() << " " << typeindicator << + con_print << " " << typeindicator << " " << (*it).first << " " << (*it).second->str() << std::endl; } con_print << registry.size() << " registered variables" << std::endl; diff --git a/src/core/entity.h b/src/core/entity.h index 7b3f200..df16075 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -178,14 +178,12 @@ public: virtual void frame(float seconds); /* entity_ variables can be set by the module */ - /// owner of the entity Player *entity_owner; /// current thrust float entity_thrust; /* target_ variables can be set by the client */ - /// target thrust as set by the client float target_thrust; /// target direction as set by the client diff --git a/src/core/func.cc b/src/core/func.cc index 0215ddf..ab3a404 100644 --- a/src/core/func.cc +++ b/src/core/func.cc @@ -78,7 +78,7 @@ void Func::list() typeindicator += 'G'; else typeindicator += ' '; - con_print << std::setw(4) << (*it).second->flags() << " " << typeindicator << + con_print << " " << typeindicator << " " << (*it).second->name() << std::endl; } diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index 38ea6fe..908ffca 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -7,81 +7,57 @@ #include #include -class GameInterface; - +#include "sys/sys.h" #include "core/application.h" +#include "core/cvar.h" +#include "core/func.h" #include "core/gameinterface.h" #include "core/player.h" -#include "sys/sys.h" namespace core { -GameInterface *game() -{ - return GameInterface::instance(); -} - -GameInterface *GameInterface::gameinterface_instance = 0; - -GameInterface::GameInterface(const char *gamename) +GameInterface::GameInterface() { - gameinterface_instance = this; - connected = false; - if (gamename) - game_name.assign(gamename); + if (Cvar::sv_dedicated->value()) + local_player.player_name.assign("Console"); else - game_name.clear(); + local_player.player_name.assign("Player0"); + clear(); } GameInterface::~GameInterface() { - gameinterface_instance = 0; -} - -GameInterface *GameInterface::instance() -{ - return gameinterface_instance; + clear(); } -std::string const &GameInterface::name() +// clear all game related objects +void GameInterface::clear() { - return game_name; -} + con_debug << "Clearing game data\n"; -void message_broadcast(std::string const & message, int ignoreplayer) -{ - // send to console - con_print << message << std::endl; - - // broadcast to remote clients - if (application()->netserver) { - std::string netmessage("msg info "); - netmessage.append(message); - netmessage += '\n'; - - application()->netserver->broadcast(netmessage, ignoreplayer); + // remove all entities + for (std::map::iterator it = Entity::registry.begin(); it != Entity::registry.end(); it++) { + delete (*it).second; } -} + Entity::registry.clear(); -void message_send(Player const *player, const char *protohdr, std::string message) -{ - // send to console - if (player == &Player::local) { - con_print << message << std::endl; + // remove all game functions + for (std::map::iterator it = Func::registry.begin(); it != Func::registry.end(); it++) { + if ( ((*it).second->flags() & Func::Game) == Func::Game) { + delete (*it).second; + Func::registry.erase(it); + } } - // send to remote clients - if (application()->netserver) { - NetClient *client = application()->netserver->find_client(player); - if (client) { - std::string netmessage("msg info "); - netmessage.append(message); - netmessage += '\n'; - - application()->netserver->send(client, message); + // remove all game cvars + for (std::map::iterator it = Cvar::registry.begin(); it != Cvar::registry.end(); it++) { + if ( ((*it).second->flags() & Cvar::Game) == Cvar::Game) { + delete (*it).second; + Cvar::registry.erase(it); } } } + } // namespace core diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h index 9eb6880..5e1f9be 100644 --- a/src/core/gameinterface.h +++ b/src/core/gameinterface.h @@ -12,55 +12,41 @@ namespace core { -/// broadcast a network message to all players -void message_broadcast(std::string const & message, int ignoreplayer=-1); - -/// send a message to a player -void message_send(Player &player, std::string const & message); - /// abstract interface from the core to the game-specific code class GameInterface { public: /// create a new game - GameInterface(const char *gamename = 0); + GameInterface(); + /// destroy the game virtual ~GameInterface(); - - /// a pointer to the current game instance - static GameInterface * instance(); - - /// true if the game is ready and running - bool connected; - - /// run one frame of the game - /// @param sec time since the previous frame, in seconds - virtual void frame(float seconds) = 0; - /// initialize the game - virtual bool init() = 0; +/*----- inspectors ---------------------------------------------- */ - /// shutdown the game - virtual void shutdown() = 0; + /// return the local player + inline Player *localplayer() { return &local_player; } + +/*----- virtual inspectors --------------------------------------- */ - /// is called when a player connects - virtual void player_connect(Player *player) = 0; + /// returns true if the game server can run a time frime + virtual bool running() = 0; - /// is called when a player disconnects - virtual void player_disconnect(Player *player) = 0; +/*----- mutators ------------------------------------------------- */ - static GameInterface *gameinterface_instance; + /// clear all game variables, game functions and entities + void clear(); - /// the name of the game - std::string const & name(); +/*----- virtual mutators ------------------------------------------ */ + + /// run one game time frame + /// @param sec time since the previous frame, in seconds + virtual void frame(float seconds) = 0; -private: - std::string game_name; +protected: + Player local_player; }; -/// pointer to the current GameInterface -GameInterface *game(); - } #endif // __INCLUDED_CORE_GAMEINTERFACE_H__ diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc new file mode 100644 index 0000000..6c84d3e --- /dev/null +++ b/src/core/gameserver.cc @@ -0,0 +1,206 @@ +/* + core/gameserver.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "sys/sys.h" +#include "core/cvar.h" +#include "core/func.h" +#include "core/gameserver.h" +#include "core/netserver.h" + +namespace core +{ + +void func_say(Player *player, std::string const &args) +{ + server()->say(player, args); +} + +GameServer *GameServer::server_instance = 0; + +GameServer::GameServer() : GameInterface() +{ + con_print << "Initializing game server...\n"; + server_instance = this; + server_network = 0; + + server_module = Module::preload(); + if (!server_module) { + con_error << "No module loaded.\n"; + abort(); + return; + } + + server_module->init(); + if (!server_module->running()) { + con_error << "Could not initialize module '" << server_module->name() << "'\n"; + abort(); + return; + } + + con_print << " module '" << server_module->name() << "'\n"; + + if ((Cvar::sv_dedicated->value() || Cvar::sv_private->value())) { + server_network = new NetServer(Cvar::net_host->str(), (unsigned int) Cvar::net_port->value()); + if (!server_network->valid()) { + delete server_network; + server_network = 0; + con_error << "Could not initialize network server\n"; + abort(); + return; + } + } else { + con_debug << "Network server disabled.\n"; + server_network = 0; + } + + Func::add("say", (GameFuncPtr) func_say); + + if (!Cvar::sv_dedicated->value()) + player_connect(localplayer()); + + server_running = true; +} + +GameServer::~GameServer() +{ + server_running = false; + + con_print << "Shutting down game server...\n"; + + if (server_network) { + delete server_network; + server_network = 0; + } + + if (!Cvar::sv_dedicated->value()) + player_disconnect(localplayer()); + + if (server_module) { + server_module->shutdown(); + + if (server_module != Module::preload()) + delete server_module; + } + + Func::remove("say"); + server_instance = 0; +} + +bool GameServer::running() +{ + return server_running; +} + +void GameServer::abort() +{ + server_running = false; +} + +void GameServer::say(Player *player, std::string const &message) +{ + // send to console + con_print <name() << " " << message << "\n"; + + // broadcast to remote clients + if (server_network != 0 ) { + std::string netmessage("msg public "); + netmessage.append(player->name()); + netmessage += ' '; + netmessage.append(message); + netmessage += '\n'; + server_network->broadcast(netmessage); + } +} + +void GameServer::broadcast(std::string const & message, int ignoreplayer) +{ + // send to console + con_print << message << "\n"; + + // broadcast to remote clients + if (server_network) { + std::string netmessage("msg info "); + netmessage.append(message); + netmessage += '\n'; + server_network->broadcast(netmessage, ignoreplayer); + } +} + +void GameServer::send(Player const *player, std::string message) +{ + // send to console + if (player->id() == localplayer()->id()) { + con_print << message << "\n"; + } + + // send to remote clients + if (server_network) { + NetClient *client = server_network->find_client(player); + if (client) { + std::string netmessage("msg info "); + netmessage.append(message); + netmessage += '\n'; + server_network->send(client, netmessage); + } + } +} + +void GameServer::player_connect(Player *player) +{ + std::string message(player->name()); + message.append(" connects."); + broadcast(message, player->id()); + + // TODO transferplayer info, transfer entities + + // notify the game module + server_module->player_connect(player); +} + +void GameServer::player_disconnect(Player *player) +{ + std::string message(player->name()); + message.append(" disconnects."); + broadcast(message, player->id()); + + // notify the game module + server_module->player_disconnect(player); +} + +void GameServer::frame(float seconds) +{ + if (error()) + return; + + // process incoming network messages + if (server_network != 0 ) { + server_network->frame(seconds); + if (server_network->error()) { + abort(); + return; + } + } + + // update entities + std::map::iterator it; + for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { + Entity *entity = (*it).second; + if ((entity->type() == Entity::Controlable) || (entity->type() == Entity::Dynamic)) { + entity->frame(seconds); + } + } + + if (server_module) { + server_module->frame(seconds); + if (server_module->error()) { + abort(); + return; + } + } +} + + +} diff --git a/src/core/gameserver.h b/src/core/gameserver.h new file mode 100644 index 0000000..ba64f2e --- /dev/null +++ b/src/core/gameserver.h @@ -0,0 +1,75 @@ +/* + core/gameserver.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_CORE_GAMESERVER_H__ +#define __INCLUDED_CORE_GAMESERVER_H__ + +#include "core/gameinterface.h" +#include "core/module.h" +#include "core/netserver.h" + +namespace core +{ + +/// the core game server +/** the core game server runs the game module. Network access is enabled + * for the dedicated server or the client with private server enabled. + */ +class GameServer : public GameInterface +{ +public: + GameServer(); + ~GameServer(); + +/*----- inspectors ------------------------------------------------ */ + + /// returns true if the game server can run a time frime + bool running(); + + /// returns true if the game server can not run a time frime + inline bool error() { return !server_running; } + +/*----- mutators -------------------------------------------------- */ + + /// is called when a player connects to the game server + void player_connect(Player *player); + + /// a caleld when a player disconnects from the game server + void player_disconnect(Player *player); + + /// run a game server time frame + void frame(float seconds); + + /// a player sends a chat message on the public channel + void say(Player *player, std::string const &args); + + /// broadcast a message to all players + void broadcast(std::string const & message, int ignoreplayer = -1); + + /// send a message to a single player + void send(Player const *player, std::string message); + +/*----- static ---------------------------------------------------- */ + + /// retuen the current game server + static inline GameServer *instance() { return server_instance; } + +protected: + /// abort runing + void abort(); +private: + bool server_running; + Module *server_module; + static GameServer *server_instance; + NetServer *server_network; + +}; + +inline GameServer *server() { return GameServer::instance(); } + +} + +#endif // __INCLUDED_CORE_GAMESERVER_H__ diff --git a/src/core/module.cc b/src/core/module.cc new file mode 100644 index 0000000..45559f2 --- /dev/null +++ b/src/core/module.cc @@ -0,0 +1,41 @@ +/* + core/module.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "core/module.h" + +namespace core +{ + +Module *Module::module_preload; + +Module::Module(const char *name) +{ + module_running = false; + module_name.assign(name); + module_preload = 0; +} + +Module::~Module() +{ + module_running = false; + module_name.clear(); +} + + +void Module::load(Module *module) +{ + module_preload = module; +} + +void Module::unload() +{ + if (module_preload) { + delete module_preload; + module_preload = 0; + } +} + +} diff --git a/src/core/module.h b/src/core/module.h new file mode 100644 index 0000000..053c9e5 --- /dev/null +++ b/src/core/module.h @@ -0,0 +1,74 @@ +/* + core/module.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_CORE_MODULE_H__ +#define __INCLUDED_CORE_MODULE_H__ + +#include +#include "core/player.h" + +namespace core +{ + +// a loadable game module +class Module +{ +public: + Module(const char *name); + virtual ~Module(); + +/*----- inspectors ------------------------------------------------ */ + /// return true if the game module can run a timeframe + inline bool running() const { return module_running; } + + /// return true if the game module can not run a timeframe + inline bool error() const { return !module_running; } + + /// return the name of the module + inline std::string const & name() const { return module_name; } + +/*----- mutators -------------------------------------------------- */ + + /// initialize the game module + virtual void init() = 0; + + /// shutdown the game module + virtual void shutdown() = 0; + + /// run one timeframe + virtual void frame(float seconds) = 0; + + /// is called when a player connects + virtual void player_connect(Player *player) = 0; + + /// is called when a player disconnects + virtual void player_disconnect(Player *player) = 0; + +/*----- static ---------------------------------------------------- */ + + /// load a game module + static void load(Module *module); + + /// unload the preloaded module + static void unload(); + + /// the preloaded module + inline static Module *preload() { return module_preload; }; + +protected: + /// set the disconnected state + void abort(); + bool module_running; + +private: + static Module *module_preload; + std::string module_name; + +}; + +} + +#endif // __INCLUDED_CORE_MODULE_H__ diff --git a/src/core/netclient.cc b/src/core/netclient.cc index 61a3e64..7b5d554 100644 --- a/src/core/netclient.cc +++ b/src/core/netclient.cc @@ -26,7 +26,6 @@ NetClient::NetClient(int clientfd, std::string host, int port) : client_host = host; client_port = port; - //con_debug << "NetClient " << fd() << ": starting." << std::endl; } NetClient::~NetClient() diff --git a/src/core/netgame.cc b/src/core/netgame.cc deleted file mode 100644 index e69de29..0000000 diff --git a/src/core/netgame.h b/src/core/netgame.h deleted file mode 100644 index e55e8c6..0000000 --- a/src/core/netgame.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - core/netgame.h - This file is part of the Osirion project and is distributed under - the terms of the GNU General Public License version 2 -*/ - -#ifndef __INCLUDED_CORE_GAMEINTERFACE_H__ -#define __INCLUDED_CORE_GAMEINTERFACE_H__ - -#include "core/player.h" - -#endif \ No newline at end of file diff --git a/src/core/netserver.cc b/src/core/netserver.cc index 39548dd..ba8510d 100644 --- a/src/core/netserver.cc +++ b/src/core/netserver.cc @@ -8,6 +8,7 @@ #include #include "sys/sys.h" +#include "core/gameserver.h" #include "core/netclient.h" #include "core/netserver.h" #include "core/cvar.h" @@ -20,6 +21,7 @@ namespace core NetServer::NetServer(std::string const host, unsigned int const port) : net::TCPServer(host, port) { + //con_print << "Initializing network server..." << std::endl; FD_ZERO(&serverset); // add the listening socket to the file descriptor set FD_SET(fd(), &serverset); @@ -29,16 +31,16 @@ NetServer::NetServer(std::string const host, unsigned int const port) : NetServer::~NetServer() { - con_print << "Shutting down network..." << std::endl; + con_print << "Shutting down network server..." << std::endl; // delete all clients std::list:: iterator it; for (it = clients.begin(); it != clients.end(); it++) { - // notify the game - if (game() && game()->connected) { - core::game()->player_disconnect((*it)->player()); - con_print << (*it)->player()->name() << " disconnected."<< std::endl; - } + // notify the game server + server()->player_disconnect((*it)->player()); + + con_print << " " << (*it)->host() << ":" << (*it)->port() << " disconnected.\n"; + delete (*it); } clients.clear(); @@ -48,8 +50,7 @@ void NetServer::client_connect(int const clientfd, std::string const host, int c { NetClient *client = new NetClient(clientfd, host, port); if (client->error()) { - con_warn << "Client " << client->fd() << " " << - client->host() << ":" << client->port() << " connection failed!" << std::endl; + con_warn << client->host() << ":" << client->port() << " connection failed!\n"; delete(client); return; } @@ -57,20 +58,11 @@ void NetServer::client_connect(int const clientfd, std::string const host, int c clients.push_back(client); FD_SET(client->fd(), &serverset); - // TODO send infos - con_print << client->host() << ":" << client->port() << " " << client->player()->name() << " connected."<< std::endl; + con_print << client->host() << ":" << client->port() << " connected.\n"; - // BROADCAST connect message - std::ostringstream osstream; - osstream << "msg info " << client->player()->name() << " connected."<< std::endl; - broadcast(osstream.str(), clientfd); + // notify the game server + server()->player_connect(client->player()); - // notify the game - if (game() && game()->connected) { - core::game()->player_connect(client->player()); - } else { - // TODO send disconnect message and remove client - } } // remove disconnected clients @@ -82,16 +74,9 @@ void NetServer::reap() if (client->error()) { FD_CLR(client->fd(), &serverset); - // BROADCAST disconnect message - std::ostringstream osstream; - osstream << "msg info " << client->player()->name() << " disconnected."<< std::endl; - broadcast(osstream.str()); - - // notify the game - if (core::game()) - core::game()->player_disconnect(client->player()); - - con_print << client->player()->name() << " disconnected."<< std::endl; + // notify the game server + server()->player_disconnect((*it)->player()); + con_print << client->host() << ":" << client->port() << " disconnected.\n"; // remove the client clients.erase(it); @@ -118,7 +103,7 @@ void NetServer::frame(float seconds) { if (nb == -1) { con_error << "Network error on select()" << std::endl; - perror("select"); + //perror("select"); abort(); } @@ -244,40 +229,21 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me } // execute game functions - if (game() && game()->connected) { - Func *function = Func::find(command); - if (function ) { - std::string args; - char c; - if (msgstream >> args) - while (msgstream >> c) - args += c; - if (function ->flags() && Func::Game) { - function->exec(client->player(), args); - } else { - // instant rcon - //function->exec(args); - } + Func *function = Func::find(command); + if (function ) { + std::string args; + char c; + if (msgstream >> args) + while (msgstream >> c) + args += c; + if (function ->flags() && Func::Game) { + function->exec(client->player(), args); + } else { + // FIXME instant rcon + function->exec(args); } } -} -void NetServer::parse_client_variable(NetClient * client, const std::string varname, std::istringstream &istringstream) -{ - if (varname=="name") { - std::string name; - if (istringstream >> name) { - std::ostringstream osstream; - if (name.size() > 16) - name = name.substr(0,16); - if (name != client->player()->name()) { - osstream << "msg info " << client->player()->name() << " renamed to " << name << "\n"; - broadcast(osstream.str()); - client->player()->player_name = name; - } - } - return; - } } } diff --git a/src/core/player.h b/src/core/player.h index e19b8ae..490515d 100644 --- a/src/core/player.h +++ b/src/core/player.h @@ -30,10 +30,10 @@ public: inline std::string const &name() const { return player_name; } /// id of the player - inline unsigned int id() const { return player_id; } + inline int id() const { return player_id; } /// id of the player - unsigned int player_id; + int player_id; /// name of the player std::string player_name; diff --git a/src/game/game.cc b/src/game/game.cc index fb0d917..311a696 100644 --- a/src/game/game.cc +++ b/src/game/game.cc @@ -9,7 +9,7 @@ #include "game/game.h" #include "game/ship.h" #include "game/star.h" -#include "core/entity.h" +#include "core/gameserver.h" #include "sys/sys.h" #include "math/mathlib.h" #include "filesystem/filesystem.h" @@ -17,6 +17,8 @@ namespace game { +/*----- engine game functions ------------------------------------- */ + /// a player joins the game void func_join(core::Player *player, std::string const &args) { @@ -25,9 +27,9 @@ void func_join(core::Player *player, std::string const &args) player->control = new Ship(player); - std::ostringstream osstream; - osstream << player->name() << " joins the game"; - core::message_broadcast(osstream.str(), player->id()); + std::string message(player->name()); + message.append(" joins the game."); + core::server()->broadcast(message); } /// a player joins the spectators @@ -36,9 +38,9 @@ void func_spectate(core::Player *player, std::string const &args) if (!player->control) return; - std::ostringstream osstream; - osstream << player->name() << " spectates"; - core::message_broadcast(osstream.str(), player->id()); + std::string message(player->name()); + message.append(" spectates."); + core::server()->broadcast(message); if (player->control) { // player has only ship for now @@ -47,7 +49,9 @@ void func_spectate(core::Player *player, std::string const &args) } } -Game::Game() : core::GameInterface("Project::OSiRiON") +/*----- Game ------------------------------------------------------ */ + +Game::Game() : core::Module("Project::OSiRiON") { } @@ -55,19 +59,21 @@ Game::~Game() { } -bool Game::init() +void Game::init() { using math::Vector3f; using math::Color; - con_print << "Initializing game..." << std::endl; - con_print << " " << name() << std::endl; + module_running = false; - // set up some stuff in the game world + // setup the game world + + // the star Star *star = new Star(); star->entity_location = Vector3f(256.0f, 0.0f, 256.0f); star->entity_name = "star: Sabishi Hoshi"; + // the green cube core::Entity *cube = new core::Entity(core::Entity::Solid & core::Entity::Static); cube->entity_shape = core::Entity::Cube; cube->entity_color = Color(0.0f, 0.8f, 0.0f); @@ -75,6 +81,7 @@ bool Game::init() cube->entity_name ="cube: Borg cube green"; cube->entity_moduletypeid = cube_enttype; + // the red cube cube = new core::Entity(core::Entity::Solid & core::Entity::Static); cube->entity_shape = core::Entity::Cube; cube->entity_color = Color(1.0f, 0.0f, 0.0f); @@ -82,38 +89,41 @@ bool Game::init() cube->entity_name ="cube: Borg cube red"; cube->entity_moduletypeid = cube_enttype; + // the yellow sphere core::Entity *sphere = new core::Entity(core::Entity::Solid & core::Entity::Static); sphere->entity_shape = core::Entity::Sphere; sphere->entity_color = Color(0.8f, 0.8f, 0.0f); sphere->entity_location = Vector3f(0.0f, 0.0f, -32.0f); sphere->entity_name ="sphere: The Sphere"; + // the galactic origin core::Entity *axis = new core::Entity(core::Entity::Static); axis->entity_shape = core::Entity::Diamond; axis->entity_color = Color(1.0f, 1.0f, 0.0f); axis->entity_location = Vector3f(0, 0, 0); axis->entity_name = "axis: Origin"; - // add game functions + // add engine game functions core::Func::add("join", (core::GameFuncPtr) func_join); core::Func::add("spectate", (core::GameFuncPtr) func_spectate); - // add game variables + // add engine game variables core::Cvar::set("g_borgcubes", "2", core::Cvar::Game); core::Cvar::set("g_name", name().c_str(), core::Cvar::Game | core::Cvar::ReadOnly); - return true; + + // indicate the module is ready to run frames + module_running = true; } void Game::shutdown() { - con_print << "Shutting down game..." << std::endl; - - //core::Func::remove("join"); - //core::Func::remove("spectate"); + module_running = false; } void Game::frame(float seconds) { + if (!running()) + return; } void Game::player_connect(core::Player *player) diff --git a/src/game/game.h b/src/game/game.h index f5f0bc0..811de84 100644 --- a/src/game/game.h +++ b/src/game/game.h @@ -30,18 +30,18 @@ const unsigned int cube_enttype = 258; const unsigned int sphere_enttype = 259; const unsigned int axis_enttype = 260; -class Game : public core::GameInterface { +class Game : public core::Module { public: Game(); ~Game(); /// initialize the game - bool init(); + void init(); /// shutdown the game void shutdown(); - /// execute one game grame + /// run one time frame void frame(float seconds); /// is called when a player connects @@ -49,7 +49,6 @@ public: /// is called when a player disconnects void player_disconnect(core::Player *player); - }; } diff --git a/src/net/tcpserver.cc b/src/net/tcpserver.cc index 3276f87..5b68a65 100644 --- a/src/net/tcpserver.cc +++ b/src/net/tcpserver.cc @@ -28,14 +28,14 @@ TCPServer::TCPServer(std::string const host, unsigned int const port) tcpserver_fd = -1; tcpserver_error = true; - con_print << "Initializing network..." << std::endl; + con_print << "Initializing network server..." << std::endl; // initialize socket tcpserver_fd = ::socket(PF_INET, SOCK_STREAM, 0); if (tcpserver_fd == -1) { // FIXME error handling con_error << "Network can't create socket!" << std::endl; - perror("socket"); + //perror("socket"); return; } @@ -44,7 +44,7 @@ TCPServer::TCPServer(std::string const host, unsigned int const port) if (::setsockopt(tcpserver_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(socklen_t)) == -1) { // FIXME error handling std::cerr << "Network can't set socket options!" << std::endl; - perror("setsockopt"); + //perror("setsockopt"); return; } @@ -60,7 +60,7 @@ TCPServer::TCPServer(std::string const host, unsigned int const port) if (::bind(tcpserver_fd, (struct sockaddr *) &listen_addr, sizeof(struct sockaddr)) == -1) { // FIXME error handling con_error << "Network can't bind to local address!" << std::endl; - perror("bind"); + //perror("bind"); return; } @@ -68,7 +68,7 @@ TCPServer::TCPServer(std::string const host, unsigned int const port) if (::listen(tcpserver_fd, MAXPENDINGCONNECTIONS) == -1) { // FIXME error handling con_error << "Network failed to listen on socket!" << std::endl; - perror("listen"); + //perror("listen"); return; } @@ -119,7 +119,7 @@ void TCPServer::accept() if (clientfd == -1) { // FIXME error handling con_error << "Network accept() error!" << std::endl; - perror("accept"); + //perror("accept"); return; } else { std::string host(inet_ntoa(client_addr.sin_addr)); diff --git a/src/osirion.cc b/src/osirion.cc index 696104f..6fa2eb3 100644 --- a/src/osirion.cc +++ b/src/osirion.cc @@ -9,12 +9,13 @@ int main(int count, char **arguments) { - // preload the game object - game::Game *game = new game::Game(); + // preload the game module + core::Module::load(new game::Game()); client::main(count, arguments); - game = 0; // prevents variable not used warning + // unload the game module + core::Module::unload(); return 0; } diff --git a/src/osiriond.cc b/src/osiriond.cc index 55bbbf5..0e8f6f7 100644 --- a/src/osiriond.cc +++ b/src/osiriond.cc @@ -9,12 +9,13 @@ int main(int count, char **arguments) { - // preload the game object - game::Game *game = new game::Game(); + // preload the game module + core::Module::load(new game::Game()); server::main(count, arguments); - game = 0; // prevents variable not used warning + // unload the game module + core::Module::unload(); return 0; } diff --git a/src/render/tga.cc b/src/render/tga.cc index 5802edf..18b8870 100644 --- a/src/render/tga.cc +++ b/src/render/tga.cc @@ -64,6 +64,7 @@ TGA::image *TGA::load(const char *filename) return 0; pImgData = (image*)malloc(sizeof(image)); + pImgData->data = 0; f->read((void *)&length, sizeof(GLubyte)); f->skip(1); -- cgit v1.2.3