Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/Makefile.am5
-rw-r--r--src/core/application.cc255
-rw-r--r--src/core/application.h36
-rw-r--r--src/core/commandbuffer.cc6
-rw-r--r--src/core/core.cc33
-rw-r--r--src/core/core.h11
-rw-r--r--src/core/cvar.cc25
-rw-r--r--src/core/cvar.h1
-rw-r--r--src/core/func.cc43
-rw-r--r--src/core/func.h15
-rw-r--r--src/core/gameinterface.cc10
-rw-r--r--src/core/gameinterface.h10
-rw-r--r--src/core/netclient.cc5
-rw-r--r--src/core/netconnection.cc148
-rw-r--r--src/core/netconnection.h58
-rw-r--r--src/core/netgame.cc0
-rw-r--r--src/core/netgame.h12
-rw-r--r--src/core/netserver.cc56
-rw-r--r--src/core/netserver.h3
-rw-r--r--src/core/player.cc2
-rw-r--r--src/core/player.h2
21 files changed, 591 insertions, 145 deletions
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