diff options
Diffstat (limited to 'src')
31 files changed, 654 insertions, 185 deletions
diff --git a/src/client/camera.cc b/src/client/camera.cc index f274e12..d0f25f3 100644 --- a/src/client/camera.cc +++ b/src/client/camera.cc @@ -82,7 +82,7 @@ void set_mode(Mode newmode) { case Track: // switch camera to Track mode mode = Track; - yaw_target = core::localplayer.controled->direction; + yaw_target = core::localplayer.control->direction; yaw_current = yaw_target; pitch_target = pitch_track; pitch_current = pitch_target; @@ -91,7 +91,7 @@ void set_mode(Mode newmode) { case Free: // switch camera to Free mode mode = Free; - yaw_target = core::localplayer.controled->direction; + yaw_target = core::localplayer.control->direction; yaw_current = yaw_target; pitch_target = pitch_track; pitch_current = pitch_target; @@ -112,7 +112,7 @@ void set_mode(Mode newmode) { void next_mode() { - if (!core::localplayer.controled) { + if (!core::localplayer.control) { set_mode(Overview); return; } @@ -133,7 +133,7 @@ void next_mode() void draw(float elapsed) { - if (!core::localplayer.controled) { + if (!core::localplayer.control) { // switch the camera to Overview of the player is not controling anything if (mode != Overview) { set_mode(Overview); @@ -142,11 +142,11 @@ void draw(float elapsed) if (mode == Overview) set_mode(Track); - camera::target = core::localplayer.controled->location; + camera::target = core::localplayer.control->location; } if (mode == Track) { - yaw_target = core::localplayer.controled->direction; + yaw_target = core::localplayer.control->direction; } if ((mode == Free) || (mode == Track)) { diff --git a/src/client/client.cc b/src/client/client.cc index 214ba2f..407fb5a 100644 --- a/src/client/client.cc +++ b/src/client/client.cc @@ -83,7 +83,7 @@ void Client::init() con_print << "Initializing client..." << std::endl; // initialize core - core::sv_dedicated = core::cvar::get("sv_dedicated", "0", core::cvar::ReadOnly); + core::sv_dedicated = core::cvar::set("sv_dedicated", "0", core::cvar::ReadOnly); core::Application::init(); // initialize SDL, but do not initialize any subsystems diff --git a/src/client/console.cc b/src/client/console.cc index c59f477..c352969 100644 --- a/src/client/console.cc +++ b/src/client/console.cc @@ -168,7 +168,7 @@ void draw() draw_text(CHARWIDTH, video::height*con_height - CHARHEIGHT - 4, (*history_pos)); // draw cursor - if ((core::time() - ::floorf(core::time())) < 0.5f) { + if ((core::application()->time() - ::floorf(core::application()->time())) < 0.5f) { std::string cursor("_"); draw_text(CHARWIDTH*(input_pos+1), video::height*con_height - CHARHEIGHT - 4 , cursor); } diff --git a/src/client/input.cc b/src/client/input.cc index 17c52bb..ee16038 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -63,11 +63,11 @@ void keypressed(const SDL_keysym &keysym) break; case SDLK_KP_PLUS: // TODO set core entity params - core::localplayer.controled->target_thrust += 0.08f; + core::localplayer.control->target_thrust += 0.08f; break; case SDLK_KP_MINUS: // TODO set core entity params - core::localplayer.controled->target_thrust -= 0.1f; + core::localplayer.control->target_thrust -= 0.1f; break; case SDLK_KP4: // TODO set core entity params @@ -95,7 +95,7 @@ void frame(float seconds) switch (event.type) { case SDL_KEYUP: - if (!console::visible() && core::connected() && core::localplayer.controled) + if (!console::visible() && core::application()->connected() && core::localplayer.control) // send key events to the game world keyreleased(event.key.keysym); break; @@ -105,7 +105,7 @@ void frame(float seconds) } else if (console::visible()) { // send key events to the console console::keypressed(event.key.keysym); - } else if (core::connected() && core::localplayer.controled) { + } else if (core::application()->connected() && core::localplayer.control) { // send key events to the game world keypressed(event.key.keysym); } @@ -117,8 +117,8 @@ void frame(float seconds) } - if (!console::visible() && core::connected() && core::localplayer.controled) { - core::localplayer.controled->target_direction = math::degrees360f(core::localplayer.controled->direction+turn_offset); + if (!console::visible() && core::application()->connected() && core::localplayer.control) { + core::localplayer.control->target_direction = math::degrees360f(core::localplayer.control->direction+turn_offset); } } diff --git a/src/client/video.cc b/src/client/video.cc index 1a1f5e2..b441e67 100644 --- a/src/client/video.cc +++ b/src/client/video.cc @@ -54,7 +54,7 @@ bool init() // initialize cvars r_width = core::cvar::get("r_width", width_default); r_height = core::cvar::get("r_height", height_default); - r_fullscreen = core::cvar::get("r_fullscreen", 1); + r_fullscreen = core::cvar::get("r_fullscreen", "0"); int bpp = 0; int flags = 0; diff --git a/src/client/view.cc b/src/client/view.cc index 5c54587..0c8e26b 100644 --- a/src/client/view.cc +++ b/src/client/view.cc @@ -108,8 +108,8 @@ void draw_status() << std::setfill('0') << std::setw(2) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; - minutes = (int) floorf(core::time() / 60.0f); - seconds = (int) floorf(core::time() - (float) minutes* 60.0f); + minutes = (int) floorf(core::application()->time() / 60.0f); + seconds = (int) floorf(core::application()->time() - (float) minutes* 60.0f); status << " time " << std::setfill('0') << std::setw(2) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; status << " fps " << std::setw(4) << fps; @@ -137,7 +137,7 @@ void frame(float seconds) // Clear the color and depth buffers. gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - if (core::connected()) { + if (core::application()->connected()) { // draw the game world // Change to the projection matrix and set our viewing volume. @@ -171,7 +171,7 @@ void frame(float seconds) gl::matrixmode(GL_MODELVIEW); gl::loadidentity(); - if (!core::connected()) { + if (!core::application()->connected()) { // draw the loader bitmap draw_loader(); gl::enable(GL_BLEND); // enable alpha blending diff --git a/src/core/Makefile.am b/src/core/Makefile.am index c5fb791..cbe1efd 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -2,12 +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 netserver.cc player.cc + func.cc gameinterface.cc netclient.cc netconnection.cc netgame.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 player.h + gameinterface.h netconnection.h netgame.h player.h diff --git a/src/core/application.cc b/src/core/application.cc index 2d29fad..55f8fc2 100644 --- a/src/core/application.cc +++ b/src/core/application.cc @@ -25,6 +25,7 @@ namespace core { Cvar sv_dedicated; +Cvar sv_private; Cvar net_host; Cvar net_port; @@ -56,13 +57,18 @@ void func_quit(std::stringstream &args) void func_connect(std::stringstream &args) { - if (Application::instance()) - Application::instance()->connect(); + std::string host; + if (!(args >> host)) + host.clear(); + + if (Application::instance()) { + Application::instance()->connect(host); + } } void func_disconnect(std::stringstream &args) { - if (Application::instance()) + if (Application::instance()) Application::instance()->disconnect(); } @@ -80,6 +86,54 @@ void func_list_ent(std::stringstream &args) { entity::list(); } + +void func_say(std::stringstream &args) +{ + if (application()->netserver) { + std::ostringstream osstream; + osstream << "msg public " << localplayer.name << " " << args.str() << "\n"; + application()->netserver->broadcast(osstream); + con_print << localplayer.name << ": " << args.str() << std::endl; + } else if (application()->netconnection.connected()) { + std::ostringstream osstream; + osstream << args.str() << std::endl; + application()->netconnection.send(osstream.str()); + } else if (game() && game()->connected) { + con_print << args.str() << std::endl; + } else + con_print << "Not connected."; +} + +void func_name(std::stringstream &args) { + std::string name; + if (args >> name) { + if (name.size() > 16) + name = name.substr(0,16); + } else { + con_print << "name " << localplayer.name << std::endl; + return; + } + + if (name == localplayer.name) { + con_print << "name " << name << std::endl; + return; + } + + if (application()->netserver) { + std::ostringstream osstream; + osstream << "msg info " << localplayer.name << " renamed to " << name << "\n"; + application()->netserver->broadcast(osstream); + con_print << "name " << name << std::endl; + } else if (application()->netconnection.connected()) { + std::ostringstream osstream; + osstream << args.str() << std::endl; + application()->netconnection.send(osstream.str()); + } else { + con_print << "name " << name << std::endl; + } + localplayer.name = name; +} + // --------------- signal_handler ----------------------------------- extern "C" void signal_handler(int signum) @@ -111,14 +165,15 @@ Application *Application::application_instance = 0; Application::Application() { - netserver = 0; - if (application_instance) { std::cerr << "multiple core::Application instances!" << std::endl; sys::quit(2); } + application_instance = this; - + netserver = 0; + gameinterface_preload = 0; + sys::signal(SIGHUP, signal_handler); sys::signal(SIGINT, signal_handler); sys::signal(SIGQUIT, signal_handler); @@ -128,27 +183,48 @@ 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() { - con_print << "Initializing core..." << std::endl; con_debug << "Debug messages enabled" << std::endl; + con_print << "Initializing core..." << std::endl; - // initialize core subsystems filesystem::init(); - // dedicated or not, client should have set this to 0 + gameinterface_preload = core::GameInterface::gameinterface_instance; + core::GameInterface::gameinterface_instance = 0; + if (gameinterface_preload) { + con_print << " preloaded game found: " << gameinterface_preload->name << std::endl; + } + game_time = 0; + + // dedicated server, client should have set this to 0 core::sv_dedicated = core::cvar::get("sv_dedicated", "1", core::cvar::ReadOnly); + + // private server for the client, server should have set this to 0 + core::sv_private = core::cvar::get("sv_private", "0"); + if (sv_dedicated->value()) localplayer.name = "Console"; else - localplayer.name = "Player"; + localplayer.name = "Player0"; // network settings core::net_host = core::cvar::get("net_host", "0.0.0.0"); @@ -166,9 +242,8 @@ void Application::init() func::add("list_func", func_list_func); func::add("list_ent", func_list_ent); - if (game()) - game()->connected = false; - current_time = 0; + func::add("say", func_say); + func::add("name", func_name); } void Application::shutdown() @@ -191,74 +266,136 @@ void Application::quit(int status) sys::quit(status); } -void Application::connect() +void Application::connect(std::string const &host) { - if (!game()) { - con_warn << "No game module loaded!" << std::endl; + if (game() && game()->connected || netconnection.connected()) { + con_warn << "Connected. Disconnect first." << std::endl; return; } - if (game()->connected) { - con_warn << "Connected. Disconnect first." << std::endl; + if (game()) { + // unload previous game + if (game() != gameinterface_preload) + delete core::GameInterface::gameinterface_instance; } - - entity::clear(); - game()->current_time = 0; - - if (game()->connected = game()->init()) { - con_print << "Connected." << std::endl; + + if (host.size()) { + // connect to remote core + core::GameInterface::gameinterface_instance = 0; + std::string remotehost(host); + size_t found = remotehost.find(':'); + unsigned int port = 8042; + if (found != std::string::npos) { + std::istringstream str(remotehost.substr(found+1)); + if (str >> port) { + remotehost.erase(found, std::string::npos); + } else { + con_print << "Invalid hostname '" << remotehost << "'" << std::endl; + return; + } + } + netconnection.connect(remotehost, port); + + if (netconnection.connected()) { + con_print << "Connected." << std::endl; + } else { + netconnection.disconnect(); + con_warn << "Could not connect to '" << host << "'" << std::endl; + } } else { - con_warn << "Connect failed." << std::endl; - return; - } - if (core::sv_dedicated->value() && !netserver) { - netserver = new NetServer(net_host->text(), (unsigned int)net_port->value()); + // use preloaded game + core::GameInterface::gameinterface_instance = gameinterface_preload; + + // reset everything + entity::clear(); + game_time = 0; + + if (game()->connected = game()->init()) { + con_print << "Connected." << std::endl; + } else { + con_warn << "Could not connect." << std::endl; + return; + } + + if (!netserver && (core::sv_dedicated->value() || core::sv_private->value())) { + netserver = new NetServer(net_host->text(), (unsigned int)net_port->value()); + if (!netserver->valid()) { + delete netserver; + if (core::sv_dedicated->value()) + shutdown(); + } + } } } void Application::disconnect() { - if (!game()) { - con_warn << "No game module loaded!" << std::endl; - return; + if (netserver) { + delete netserver; + netserver = 0; } - - if (!game()->connected) { - con_warn << "Not connected." << std::endl; + + if (netconnection.connected()) { + netconnection.disconnect(); + con_print << "Disconnected." << std::endl; return; } - game()->shutdown(); - - game()->connected = false; - game()->current_time = 0; + if (game()) { + if (!game()->connected) { + con_warn << "Not connected." << std::endl; + return; + } + + game()->shutdown(); + game()->connected = false; + game_time = 0; - // remove all entities - entity::clear(); - - // TODO remove all game functions - - // TODO remove all game cvars + // remove all entities + entity::clear(); + + // remove all game functions + for (std::map<std::string, Func>::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); + } + } - con_print << "Disconnected." << std::endl; + // remove all game cvars + for (std::map<std::string, Cvar>::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); + } + } + + con_print << "Disconnected." << std::endl; + } } void Application::frame(float seconds) { - current_time += seconds; + if (seconds == 0.0f) + return; - if (netserver) { - // TODO limit netserver frames in local mode - netserver->frame(seconds); - } + 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); + } - if (game() && game()->connected) { - entity::frame(seconds); - - game()->current_time += seconds; - game()->frame(seconds); - } - + if (game() && game()->connected) { + entity::frame(seconds); + game_time += seconds; + + game()->frame(seconds); + } + } // execute commands in the buffer commandbuffer::execute(); diff --git a/src/core/application.h b/src/core/application.h index 9a531de..5bdc6ef 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -9,6 +9,8 @@ #include "core/cvar.h" #include "core/netserver.h" +#include "core/netconnection.h" +#include "core/gameinterface.h" namespace core { @@ -16,6 +18,12 @@ namespace core /// cvar to indicate dedicated server status extern Cvar sv_dedicated; +/// cvar to indicate private server status +/** + * A private server is a client with server cababilities. + */ +extern Cvar sv_private; + /// core interface for the client and server Application classes class Application { @@ -35,26 +43,40 @@ public: /// run a core frame virtual void frame(float seconds); - /// a pointer to the current console instance + /// a pointer to the current application instance static Application *instance(); /// quit the application virtual void quit(int status); - /// load the game module - void connect(); + /// start the server or connect to remote host + void connect(std::string const &host); /// disconnect from the game module void disconnect(); - /// time the core has been running, in seconds - float current_time; + /// time the has been connected, in seconds + float time() const; - /// global application object - static Application *application_instance; + /// preloaded game object + GameInterface *gameinterface_preload; + + /// true if the core is connected to a game module or a remote server + bool connected() const; /// network server instance NetServer *netserver; + + /// network client to server connection + NetConnection netconnection; + + /// global application object + static Application *application_instance; + +private: + /// time the core has been running + float game_time; + }; diff --git a/src/core/commandbuffer.cc b/src/core/commandbuffer.cc index 04fc406..a15708c 100644 --- a/src/core/commandbuffer.cc +++ b/src/core/commandbuffer.cc @@ -32,9 +32,9 @@ void exec(const char *text) Func f = func::find(command); if (f) { // function exists, execute it - if (f->flags && func::Game) { + if (f->flags() && func::Game) { // it's a game function - if (connected()) { + if (game() && game()->connected) { GameFuncPtr function = (GameFuncPtr) f->ptr; function(localplayer, cmdstream); } @@ -51,7 +51,7 @@ void exec(const char *text) if (cv) { // cvar exists std::string args; - if (cmdstream >> args) { + if (((cv->flags() & cvar::ReadOnly) == 0) && (cmdstream >> args)) { // we're setting a new value char c; while (cmdstream >> c) diff --git a/src/core/core.cc b/src/core/core.cc index e7aecaf..b1083a8 100644 --- a/src/core/core.cc +++ b/src/core/core.cc @@ -4,7 +4,12 @@ the terms of the GNU General Public License version 2. */ +#include <iostream> +#include <sstream> + #include "core/core.h" +#include "core/netclient.h" + namespace core { @@ -19,15 +24,35 @@ Application *application() return Application::instance(); } -bool connected() + +void net_broadcast(std::ostringstream &osstream, int ignoreplayer) { - return (GameInterface::instance() && GameInterface::instance()->connected); + if (!application()->netserver) + return; + + application()->netserver->broadcast(osstream, ignoreplayer); } -float time() +void net_send(Player &player, std::ostringstream &osstream) { - return Application::instance()->current_time; + if (!application()->netserver) + return; + + NetClient *client = application()->netserver->find_client(player); + if (client) + application()->netserver->send(client, osstream); } + +void net_send(Player &player, std::string message) +{ + if (!application()->netserver) + return; + + NetClient *client = application()->netserver->find_client(player); + if (client) + application()->netserver->send(client, message); } + +} diff --git a/src/core/core.h b/src/core/core.h index a3c5f0d..0fc7e8d 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -25,11 +25,14 @@ GameInterface *game(); /// pointer to the current ApplicationInterface Application *application(); -/// true if the core is connected to a game module -bool connected(); +/// broadcast a network message to all connected clients +void net_broadcast(std::ostringstream &osstream, int ignoreplayer=-1); -/// return the time the core has been running, in seconds -float time(); +/// send a network message to a player +void net_send(Player &player, std::ostringstream &osstream); + +/// send a network message to a player +void net_send(Player &player, std::string message); } diff --git a/src/core/cvar.cc b/src/core/cvar.cc index 2350b56..531e0ad 100644 --- a/src/core/cvar.cc +++ b/src/core/cvar.cc @@ -36,15 +36,6 @@ Cvar_t & Cvar_t::operator=(const char *other) return ((*this) = std::string(other)); } -Cvar_t & Cvar_t::operator=(int other) -{ - std::stringstream s; - s << other; - s >> cvar_text; - cvar_value = (float) other; - return (*this); -} - Cvar_t & Cvar_t::operator=(float other) { std::stringstream s; @@ -159,7 +150,21 @@ void list() { std::map<std::string, Cvar>::iterator it; for (it = registry.begin(); it != registry.end(); it++) { - con_print << " "<< (*it).first << " " << (*it).second->text() << std::endl; + std::string typeindicator; + if ((*it).second->flags() & cvar::Archive) + typeindicator += 'A'; + else + typeindicator += ' '; + if ((*it).second->flags() & cvar::ReadOnly) + typeindicator += 'R'; + else + typeindicator += ' '; + if ((*it).second->flags() & cvar::Game) + typeindicator += 'G'; + else + typeindicator += ' '; + + con_print << typeindicator << " " << (*it).first << " " << (*it).second->text() << std::endl; } con_print << registry.size() << " registered variables" << std::endl; } diff --git a/src/core/cvar.h b/src/core/cvar.h index 16ceb46..bca3d8a 100644 --- a/src/core/cvar.h +++ b/src/core/cvar.h @@ -22,7 +22,6 @@ public: Cvar_t &operator=(const char *other); Cvar_t &operator=(const std::string &other); - Cvar_t &operator=(int other); Cvar_t &operator=(float other); unsigned int flags() const; diff --git a/src/core/func.cc b/src/core/func.cc index af811cd..06aa5b6 100644 --- a/src/core/func.cc +++ b/src/core/func.cc @@ -11,6 +11,16 @@ namespace core { +Func_t::Func_t(unsigned int funcflags) +{ + func_flags = funcflags; +} + +unsigned int Func_t::flags() +{ + return func_flags; +} + namespace func { @@ -19,35 +29,29 @@ std::map<std::string, Func> registry; void add(const char * functionname, FuncPtr functionptr, unsigned int flags) { std::map<std::string, Func>::iterator it = registry.find(functionname); - Func f; if (it == registry.end()) { // function does not yet exist in the registry - f = new Func_t(); + Func f = new Func_t(flags); + //f->name = functionname; + f->ptr = (void *)functionptr; registry[std::string(functionname)] = f; } else { - f = (*it).second; + con_warn << "Function '" << functionname << "' already registered!" << std::endl; } - - f->name = functionname; - f->ptr = (void *)functionptr; - f->flags = flags; } void add(const char * functionname, GameFuncPtr gamefunctionptr, unsigned int flags) { std::map<std::string, Func>::iterator it = registry.find(functionname); - Func f; if (it == registry.end()) { // function does not yet exist in the registry - f = new Func_t(); + Func f = new Func_t(flags & func::Game); + //f->name = functionname; + f->ptr = (void *)gamefunctionptr; registry[std::string(functionname)] = f; } else { - f = (*it).second; + con_warn << "Function '" << functionname << "' already registered!" << std::endl; } - - f->name = functionname; - f->ptr = (void *)gamefunctionptr; - f->flags = flags & func::Game; } void remove(const char *functionname) @@ -80,15 +84,14 @@ Func find(const std::string &functionname) void list() { - char typeindicator; - std::map<std::string, Func>::iterator it; for (it = registry.begin(); it != registry.end(); it++) { - if ((*it).second->flags & func::Game) - typeindicator = 'G'; + std::string typeindicator; + if ((*it).second->flags() & func::Game) + typeindicator += 'G'; else - typeindicator = ' '; - con_print << " " << typeindicator << " " << (*it).first << std::endl; + typeindicator += ' '; + con_print << " " << typeindicator << " " << (*it).first << std::endl; } con_print << registry.size() << " registered functions" << std::endl; diff --git a/src/core/func.h b/src/core/func.h index d98e954..3d91ab1 100644 --- a/src/core/func.h +++ b/src/core/func.h @@ -20,12 +20,17 @@ namespace core class Func_t { public: - /// pointer to the function - void *ptr; - /// name of the function - std::string name; + Func_t(unsigned int fflags = 0); + /// flags - unsigned int flags; + unsigned int flags(); + + + /// pointer to the function + void *ptr; + +private: + unsigned int func_flags; }; /// function type diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index ebca24b..a4a402d 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -17,14 +17,14 @@ namespace core GameInterface *GameInterface::gameinterface_instance = 0; -GameInterface::GameInterface() +GameInterface::GameInterface(const char *game_name) { - if (gameinterface_instance) { - std::cerr << "multiple singleton instances: core::GameInterface" << std::endl; - exit(2); - } gameinterface_instance = this; connected = false; + if (game_name) + name.assign(game_name); + else + name.clear(); } GameInterface::~GameInterface() diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h index 1fbae03..4b18a9e 100644 --- a/src/core/gameinterface.h +++ b/src/core/gameinterface.h @@ -18,9 +18,9 @@ namespace core class GameInterface { public: - /// create a new game singleton - GameInterface(); - /// destroy the game singleton + /// create a new game + GameInterface(const char *game_name = 0); + /// destroy the game virtual ~GameInterface(); /// a pointer to the current game instance @@ -48,8 +48,10 @@ public: /// is called when a player disconnects virtual void player_disconnect(Player &player) = 0; -private: static GameInterface *gameinterface_instance; + + /// the name of the game + std::string name; }; } diff --git a/src/core/netclient.cc b/src/core/netclient.cc index 2df024b..e2a9b7e 100644 --- a/src/core/netclient.cc +++ b/src/core/netclient.cc @@ -1,5 +1,5 @@ /* - net/netclient.h + net/netclient.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ @@ -19,7 +19,8 @@ NetClient::NetClient(int clientfd, std::string host, int port) : client_host(host) { std::ostringstream osstream; - osstream << host << ":" << port; + //osstream << "host << ":" << port; + osstream << "Player" << clientfd; client_player.name = osstream.str(); client_player.id = (unsigned int) clientfd; diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc new file mode 100644 index 0000000..85c0534 --- /dev/null +++ b/src/core/netconnection.cc @@ -0,0 +1,148 @@ +/* + net/netconnection.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include <sstream> + +#include "sys/sys.h" +#include "net/net.h" +#include "core/netconnection.h" +#include "core/player.h" + +namespace core +{ + +NetConnection::NetConnection() +{ +} + +NetConnection::~NetConnection() +{ +} + +void NetConnection::connect(std::string const &to_host, int to_port) +{ + TCPConnection::connect(to_host, to_port); + if(connected()) { + FD_ZERO(&clientset); + FD_SET(fd(), &clientset); + } + + std::ostringstream osstream; + osstream << "name " << localplayer.name << std::endl; + send(osstream.str()); +} + +void NetConnection::disconnect() +{ + TCPConnection::disconnect(); + FD_ZERO(&clientset); +} + +bool NetConnection::has_messages() const +{ + return (recvq.size() > 0); +} + +void NetConnection::retreive(std::string & message) +{ + if (recvq.size() > 0) { + message.assign(recvq.front()); + recvq.pop_front(); + } else { + message.clear(); + } +} + +// receive data and decode it into lines +void NetConnection::receive() +{ + // TODO: binary mode data transfer + std::string datablock; + TCPConnection::receive(datablock); + + if (error()) + return; + while (datablock.size() > 0) { + // scan the datablock for enters + if (datablock[0] == '\n' || datablock[0] == '\r') { + if (messageblock.size() > 0) { + recvq.push_back(messageblock); + messageblock.clear(); + } + } else { + if (messageblock.size() < net::FRAMESIZE) { + messageblock.append(datablock.substr(0,1)); + } else { + con_warn << "Network message exceeds " << net::FRAMESIZE << " bytes!" << std::endl; + messageblock.clear(); + } + } + datablock.erase(0,1); + } + datablock.clear(); +} + +void NetConnection::frame(float seconds) +{ + timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + fd_set readset = clientset; + + int nb = select(fd()+1, &readset, NULL, NULL, &timeout); + if (nb == 0) + return; + + if (nb == -1) { + con_error << "Network error on select()" << std::endl; + //perror("select"); + abort(); + } + + if (FD_ISSET(this->fd(), &readset) && !error()) { + receive(); + while (has_messages()) { + std::string message; + retreive(message); + parse_incoming_message(message); + } + } +} + +// parse incoming client messages +/** + * The following incoming messages are parsed; + * + * msg info <text> + * msg public <name> <text> + */ +void NetConnection::parse_incoming_message(const std::string & message) +{ + std::istringstream msgstream(message); + + std::string command; + msgstream >> command; + + if (command == "msg") { + std::string level; + if (msgstream >> level) { + if (level =="info") { + if (message.size() > 9) { + con_print << message.substr(9) << std::endl; + } + } else if (level == "public") { + // FIXME - separate sender nickname + if (message.size() > 11) { + con_print << message.substr(11) << std::endl; + } + + } + } + } + +} + +} diff --git a/src/core/netconnection.h b/src/core/netconnection.h new file mode 100644 index 0000000..9a801ec --- /dev/null +++ b/src/core/netconnection.h @@ -0,0 +1,58 @@ +/* + net/netconnection.cc + 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_NETCONNECTION_H__ +#define __INCLUDED_CORE_NETCONNECTION_H__ + +#include <sys/select.h> + +#include <string> +#include <deque> +#include <map> + +#include "net/tcpconnection.h" + +namespace core +{ + +/// a client to server connection +class NetConnection : public net::TCPConnection +{ +public: + NetConnection(); + virtual ~NetConnection(); + + /// connect to a remote host + virtual void connect(std::string const &to_host, int to_port); + + /// disconnect from a remote host + virtual void disconnect(); + + /// process pending incoming messages + void frame(float seconds); + +protected: + /// receive incoming data and store messages + void receive(); + + /// return true if there are incoming messages + bool has_messages() const; + + /// retreive an incoming message + void retreive(std::string & message); + + /// parse an incoming message + void parse_incoming_message(const std::string & message); + +private: + std::string messageblock; + std::deque<std::string> recvq; + fd_set clientset; +}; + +} + +#endif // __INCLUDED_CORE_NETCONNECTION_H__ diff --git a/src/core/netgame.cc b/src/core/netgame.cc new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/core/netgame.cc diff --git a/src/core/netgame.h b/src/core/netgame.h new file mode 100644 index 0000000..e55e8c6 --- /dev/null +++ b/src/core/netgame.h @@ -0,0 +1,12 @@ +/* + 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 c37b71d..072e790 100644 --- a/src/core/netserver.cc +++ b/src/core/netserver.cc @@ -35,7 +35,7 @@ NetServer::~NetServer() std::list<NetClient *>:: iterator it; for (it = clients.begin(); it != clients.end(); it++) { // notify the game - if (core::connected()) { + if (game() && game()->connected) { core::game()->player_disconnect((*it)->player()); con_print << (*it)->player().name << " disconnected."<< std::endl; } @@ -59,11 +59,14 @@ void NetServer::client_connect(int const clientfd, std::string const host, int c // TODO send infos - con_print << client->player().name << " connected."<< std::endl; + con_print << client->host() << ":" << client->port() << " connected."<< std::endl; // notify the game - if (core::game()) + if (game() && game()->connected) { core::game()->player_connect(client->player()); + } else { + // TODO send disconnect message and remove client + } // BROADCAST connect message std::ostringstream osstream; @@ -169,6 +172,28 @@ void NetServer::broadcast(std::ostringstream &osstream, int ignorefd) osstream.str(""); } +// find the client corresponding to a player id +NetClient *NetServer::find_client(Player const &player) +{ + for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end(); it++) { + if ((*it)->fd() == (int) player.id) { + return (*it); + } + } + return 0; +} + +// parse server messages +/** + * The following incoming messages are parsed; + * + * disconnect + * help + * list_players + * name + * say <text> + * + */ void NetServer::parse_incoming_message(NetClient *client, const std::string & message) { std::stringstream msgstream(message); @@ -186,7 +211,7 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me if (command == "say") { if (message.size() > command.size()+1) { std::ostringstream osstream; - osstream << "msg public " << client->player().name << " " << message.substr(command.size()+1) << std::endl; + osstream << "msg public " << client->player().name << " " << message.substr(command.size()+1) << "\n"; broadcast(osstream); con_print << client->player().name << " " << message.substr(command.size()+1) << std::endl; } @@ -201,10 +226,10 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me name = name.substr(0,16); if (name != client->player().name) { std::ostringstream osstream; - osstream << "msg info " << client->player().name << " renamed to " << name << std::endl; - broadcast(osstream); + osstream << "msg info " << client->player().name << " renamed to " << name << "\n"; + broadcast(osstream); + con_print << "name " << name << std::endl; client->player().name = name; - con_print << client->player().name << " renamed to " << name << std::endl; } } return; @@ -213,9 +238,9 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me if (command == "list_players") { std::ostringstream osstream; for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end(); it++) { - osstream << "msg info client " << (*it)->player().name << " " << (*it)->host() << ":" << (*it)->port() << std::endl; + osstream << "msg info " << (*it)->player().name << " " << (*it)->host() << ":" << (*it)->port() << "\n"; } - osstream << "msg info client " << clients.size() << " players" << std::endl; + osstream << "msg info " << clients.size() << " connected players\n" << std::endl; send(client, osstream); } @@ -232,19 +257,16 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me if (game() && game()->connected) { Func f = func::find(command); if (f) { - if (f->flags && func::Game) { + if (f->flags() && func::Game) { GameFuncPtr function = (GameFuncPtr) f->ptr; function(client->player(), msgstream); } else { - // FIXME rcon - // FuncPtr function = (FuncPtr) f->ptr; - // function(msgstream); + // instant rcon + //FuncPtr function = (FuncPtr) f->ptr; + //function(msgstream); } - return; } } - - // TODO rcon } void NetServer::parse_client_variable(NetClient * client, const std::string varname, std::istringstream &istringstream) @@ -256,7 +278,7 @@ void NetServer::parse_client_variable(NetClient * client, const std::string varn if (name.size() > 16) name = name.substr(0,16); if (name != client->player().name) { - osstream << "msg info " << client->player().name << " renamed to " << name << std::endl; + osstream << "msg info " << client->player().name << " renamed to " << name << "\n"; broadcast(osstream); client->player().name = name; } diff --git a/src/core/netserver.h b/src/core/netserver.h index 4d1eb73..ab4976d 100644 --- a/src/core/netserver.h +++ b/src/core/netserver.h @@ -37,6 +37,9 @@ public: /// send a message to a client void send(NetClient * client, std::string message); + /// find the client corresponding to a player + NetClient *find_client(Player const &player); + protected: /// called by accept() when a new client connects virtual void client_connect(int const clientfd, std::string const host, int const port); diff --git a/src/core/player.cc b/src/core/player.cc index 1734d9b..6bd79ec 100644 --- a/src/core/player.cc +++ b/src/core/player.cc @@ -17,7 +17,7 @@ Player::Player() name.clear(); dirty = false; - controled=0; + control = 0; } Player::~Player() diff --git a/src/core/player.h b/src/core/player.h index 859eddc..aa20d20 100644 --- a/src/core/player.h +++ b/src/core/player.h @@ -36,7 +36,7 @@ public: bool dirty; /// the entity the Player is currently controling - EntityControlable *controled; + EntityControlable *control; }; /// the local player, always has id 0 diff --git a/src/game/game.cc b/src/game/game.cc index f8452f7..7dff676 100644 --- a/src/game/game.cc +++ b/src/game/game.cc @@ -21,30 +21,46 @@ namespace game /// a player joins the game void func_join(core::Player &player, std::stringstream &args) { + if (player.control) + return; + Ship *ship = new Ship(); ship->location = math::Vector3f(0,0,0); ship->label = "ship: <" + player.name + "> Micron Vector"; ship->owner = &player; - player.controled = ship; + player.control = ship; + + // net message + std::ostringstream osstream; + osstream << "msg info " << player.name << " joins the game\n"; + core::net_broadcast(osstream, player.id); + // console message con_print << player.name << " joins the game" << std::endl; - /// TODO net broadcast } /// a player joins the spectators void func_spectate(core::Player &player, std::stringstream &args) { - con_print << player.name << " joins the spectators" << std::endl; - /// TODO net broadcast + if (!player.control) + return; + + // net message + std::ostringstream osstream; + osstream << "msg info " << player.name << " spectates\n"; + core::net_broadcast(osstream, player.id); + + // console message + con_print << player.name << " spectates" << std::endl; - if (player.controled) { - // player only has one ship for now - core::entity::remove(player.controled->id); - player.controled = 0; + if (player.control) { + // player has only ship for now + core::entity::remove(player.control->id); + player.control = 0; } } -Game::Game() +Game::Game() : core::GameInterface("Project::OSiRiON") { } @@ -132,6 +148,7 @@ bool Game::init() con_print << " " << sectors[n]->label << " " << sectors[n]->name << std::endl; */ + // set up some stuff in the game world Star *star = new Star(); star->location = Vector3f(256.0f, 0.0f, 256.0f); star->label = "star: Sabishi Hoshi"; @@ -162,6 +179,7 @@ bool Game::init() axis->location = Vector3f(0, 0, 0); axis->label = "axis: Origin"; + // add game functions core::func::add("join", func_join, core::func::Game); core::func::add("spectate", func_spectate, core::func::Game); @@ -196,8 +214,11 @@ void Game::player_connect(core::Player &player) void Game::player_disconnect(core::Player &player) { - std::stringstream args; - game::func_spectate(player, args); + if (player.control) { + // player has only one ship for now + core::entity::remove(player.control->id); + player.control = 0; + } } } // namespace game diff --git a/src/net/tcpconnection.cc b/src/net/tcpconnection.cc index 92bc3d2..e4ff009 100644 --- a/src/net/tcpconnection.cc +++ b/src/net/tcpconnection.cc @@ -83,10 +83,10 @@ void TCPConnection::disconnect() tcpconnection_error = false; tcpconnection_host.clear(); tcpconnection_port = 0; - con_debug << "Network disconnected from server" << std::endl; + //con_debug << "Network disconnected from server" << std::endl; } -void TCPConnection::connect(std::string to_host, int to_port) +void TCPConnection::connect(std::string const &to_host, int to_port) { if (valid()) return; @@ -95,7 +95,7 @@ void TCPConnection::connect(std::string to_host, int to_port) struct hostent *serverhostent; serverhostent = gethostbyname(to_host.c_str()); if (!serverhostent) { - con_warn << "Network can't resolve " << to_host.c_str() << "!" << std::endl; + con_warn << "Could not resolve '" << to_host.c_str() << "'" << std::endl; abort(); return; } @@ -105,7 +105,7 @@ void TCPConnection::connect(std::string to_host, int to_port) // Get a socket file descriptor tcpconnection_fd = socket(PF_INET, SOCK_STREAM, 0); if (tcpconnection_fd == -1) { - con_error << "Network socket() failed!" << std::endl; + //con_error << "Network socket() failed!" << std::endl; abort(); return; } @@ -118,7 +118,7 @@ void TCPConnection::connect(std::string to_host, int to_port) memset(server_addr.sin_zero, '\0', sizeof server_addr.sin_zero); if (::connect(tcpconnection_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) != 0) { - con_error << "Network connect() failed!" << std::endl; + //con_error << "Network connect() failed!" << std::endl; abort(); return; } @@ -126,7 +126,7 @@ void TCPConnection::connect(std::string to_host, int to_port) tcpconnection_host = to_host; tcpconnection_port = to_port; tcpconnection_error = false; - con_print << "Connected to server." << std::endl; + //con_print << "Connected to server." << std::endl; } @@ -147,7 +147,7 @@ void TCPConnection::receive(std::string &msg) return; } else if (bytes_received < 0) { con_error << "Network receive() error!" << std::endl; - perror("recv"); + //perror("recv"); abort(); return; } @@ -172,7 +172,7 @@ void TCPConnection::send(std::string const &msg) bytes_sent = ::send(tcpconnection_fd, sendbuf.c_str(), sendbuf.size(), 0); if (bytes_sent < 0) { con_error << "Network send() error!" << std::endl; - perror("send"); + //perror("send"); abort(); return; } diff --git a/src/net/tcpconnection.h b/src/net/tcpconnection.h index 7e71ed0..6076215 100644 --- a/src/net/tcpconnection.h +++ b/src/net/tcpconnection.h @@ -46,7 +46,7 @@ public: int fd() const; /// connect to a remote host - virtual void connect(std::string to_host, int to_port); + virtual void connect(std::string const &to_host, int to_port); /// disconnect from a remote host virtual void disconnect(); diff --git a/src/server/server.cc b/src/server/server.cc index 4f7d1e9..dde1346 100644 --- a/src/server/server.cc +++ b/src/server/server.cc @@ -54,11 +54,13 @@ void Server::init() { con_print << "Initializing server..." << std::endl; + core::sv_private = core::cvar::set("sv_private", "0", core::cvar::ReadOnly); core::Application::init(); console::init(); - core::Application::connect(); + std::string empty; + core::Application::connect(empty); } void Server::run() |