Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2008-02-14 18:04:25 +0000
committerStijn Buys <ingar@osirion.org>2008-02-14 18:04:25 +0000
commit715d0c3952a3a1d59b64074e472d0a9a3b414351 (patch)
treea5d0ddd0613caaf4f9fe01f9a3bd34e823651ad5
parent83e8023c5e46635753a609329cf9805a3520001e (diff)
dedicated server accepts incoming connections
-rw-r--r--configure.in5
-rw-r--r--osirion.kdevelop2
-rw-r--r--osirion.kdevelop.pcsbin323648 -> 378872 bytes
-rw-r--r--osirion.kdevses26
-rw-r--r--src/Makefile.am2
-rw-r--r--src/core/Makefile.am4
-rw-r--r--src/core/application.cc37
-rw-r--r--src/core/application.h4
-rw-r--r--src/core/commandbuffer.cc12
-rw-r--r--src/core/entity.h62
-rw-r--r--src/core/gameinterface.h27
-rw-r--r--src/core/netclient.cc90
-rw-r--r--src/core/netclient.h57
-rw-r--r--src/core/netserver.cc268
-rw-r--r--src/core/netserver.h60
-rw-r--r--src/core/player.h2
-rw-r--r--src/game/Makefile.am2
-rw-r--r--src/game/game.cc11
-rw-r--r--src/game/game.h6
-rw-r--r--src/game/player.h27
-rw-r--r--src/net/tcpclient.cc2
-rw-r--r--src/net/tcpconnection.cc2
-rw-r--r--src/net/tcpserver.cc13
-rw-r--r--src/net/tcpserver.h5
-rw-r--r--src/server/Makefile.am3
25 files changed, 599 insertions, 130 deletions
diff --git a/configure.in b/configure.in
index 83aa028..673249a 100644
--- a/configure.in
+++ b/configure.in
@@ -166,9 +166,8 @@ dnl ---------------------------------------------------------------
dnl Write makefiles and config.h
AC_OUTPUT(Makefile src/Makefile src/client/Makefile src/core/Makefile \
- src/filesystem/Makefile src/game/Makefile src/math/Makefile \
- src/render/Makefile src/server/Makefile \
- src/sys/Makefile)
+ src/filesystem/Makefile src/game/Makefile src/math/Makefile src/net/Makefile src/render/Makefile \
+ src/server/Makefile src/sys/Makefile)
dnl ---------------------------------------------------------------
dnl Configuration summary
diff --git a/osirion.kdevelop b/osirion.kdevelop
index d40c050..dc50872 100644
--- a/osirion.kdevelop
+++ b/osirion.kdevelop
@@ -21,7 +21,7 @@
</general>
<kdevautoproject>
<general>
- <activetarget>src/core/libcore.la</activetarget>
+ <activetarget>src/net/libnet.la</activetarget>
<useconfiguration>debug</useconfiguration>
</general>
<run>
diff --git a/osirion.kdevelop.pcs b/osirion.kdevelop.pcs
index 5ce4adb..95d402b 100644
--- a/osirion.kdevelop.pcs
+++ b/osirion.kdevelop.pcs
Binary files differ
diff --git a/osirion.kdevses b/osirion.kdevses
index 01b9244..0db4634 100644
--- a/osirion.kdevses
+++ b/osirion.kdevses
@@ -1,34 +1,22 @@
<?xml version = '1.0' encoding = 'UTF-8'?>
<!DOCTYPE KDevPrjSession>
<KDevPrjSession>
- <DocsAndViews NumberOfDocuments="9" >
- <Doc0 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/client/draw.cc" >
+ <DocsAndViews NumberOfDocuments="5" >
+ <Doc0 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/core/netserver.cc" >
<View0 Encoding="" Type="Source" />
</Doc0>
- <Doc1 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/core/entity.cc" >
+ <Doc1 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/core/netserver.h" >
<View0 Encoding="" Type="Source" />
</Doc1>
- <Doc2 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/client/camera.cc" >
+ <Doc2 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/net/tcpserver.cc" >
<View0 Encoding="" Type="Source" />
</Doc2>
- <Doc3 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/client/view.cc" >
+ <Doc3 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/core/netclient.cc" >
<View0 Encoding="" Type="Source" />
</Doc3>
- <Doc4 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/core/gameinterface.h" >
- <View0 Encoding="" Type="Source" />
+ <Doc4 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/core/application.cc" >
+ <View0 Encoding="" line="185" Type="Source" />
</Doc4>
- <Doc5 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/game/game.cc" >
- <View0 Encoding="" Type="Source" />
- </Doc5>
- <Doc6 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/game/game.h" >
- <View0 Encoding="" Type="Source" />
- </Doc6>
- <Doc7 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/game/ship.cc" >
- <View0 Encoding="" Type="Source" />
- </Doc7>
- <Doc8 NumberOfViews="1" URL="file:///home/ingar/projects/osirion/osirion-work/src/core/entity.h" >
- <View0 Encoding="" line="84" Type="Source" />
- </Doc8>
</DocsAndViews>
<pluginList>
<kdevdebugger>
diff --git a/src/Makefile.am b/src/Makefile.am
index 4fc1732..4815954 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
# set the include path found by configure
AM_CPPFLAGS = $(DEBUG_CFLAGS) $(WARN_CFLAGS) $(all_includes)
INCLUDES = -I$(top_srcdir)/src
-SUBDIRS = math sys filesystem core server render game client
+SUBDIRS = math sys filesystem net core server render client game
noinst_HEADERS = config.h
bin_PROGRAMS = osiriond osirion
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index bf98501..c5fb791 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -2,10 +2,10 @@ METASOURCES = AUTO
INCLUDES = -I$(top_srcdir)/src
libcore_la_SOURCES = application.cc commandbuffer.cc core.cc cvar.cc entity.cc \
- func.cc gameinterface.cc player.cc
+ func.cc gameinterface.cc netclient.cc netserver.cc player.cc
libcore_la_LDFLAGS = -avoid-version -no-undefined
libcore_la_LIBADD = $(top_builddir)/src/math/libmath.la \
- $(top_builddir)/src/sys/libsys.la $(top_builddir)/src/filesystem/libfilesystem.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 \
diff --git a/src/core/application.cc b/src/core/application.cc
index 9fea8ee..2d29fad 100644
--- a/src/core/application.cc
+++ b/src/core/application.cc
@@ -19,12 +19,16 @@
#include "core/entity.h"
#include "core/func.h"
#include "core/cvar.h"
+#include "core/netserver.h"
namespace core
{
Cvar sv_dedicated;
+Cvar net_host;
+Cvar net_port;
+
// --------------- engine functions ------------------------------
void func_print(std::stringstream &args)
{
@@ -107,6 +111,8 @@ Application *Application::application_instance = 0;
Application::Application()
{
+ netserver = 0;
+
if (application_instance) {
std::cerr << "multiple core::Application instances!" << std::endl;
sys::quit(2);
@@ -137,13 +143,16 @@ void Application::init()
// initialize core subsystems
filesystem::init();
- // dedicated or not
+ // dedicated or not, client should have set this to 0
core::sv_dedicated = core::cvar::get("sv_dedicated", "1", core::cvar::ReadOnly);
if (sv_dedicated->value())
localplayer.name = "Console";
else
- localplayer.name = "Client";
+ localplayer.name = "Player";
+ // network settings
+ core::net_host = core::cvar::get("net_host", "0.0.0.0");
+ core::net_port = core::cvar::get("net_port", "8042");
// register our functions
func::add("print", func_print);
@@ -168,9 +177,12 @@ void Application::shutdown()
if (game() && game()->connected)
disconnect();
-
- //if (game()) unload();
-
+
+ if (netserver) {
+ delete netserver;
+ netserver = 0;
+ }
+
filesystem::shutdown();
}
@@ -197,6 +209,10 @@ void Application::connect()
con_print << "Connected." << 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());
}
}
@@ -211,12 +227,13 @@ void Application::disconnect()
con_warn << "Not connected." << std::endl;
return;
}
-
+
game()->shutdown();
game()->connected = false;
game()->current_time = 0;
+ // remove all entities
entity::clear();
// TODO remove all game functions
@@ -230,12 +247,18 @@ void Application::frame(float seconds)
{
current_time += seconds;
+ 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);
}
+
// execute commands in the buffer
commandbuffer::execute();
diff --git a/src/core/application.h b/src/core/application.h
index d5c83d6..9a531de 100644
--- a/src/core/application.h
+++ b/src/core/application.h
@@ -8,6 +8,7 @@
#define __INCLUDED_CORE_APPLICATION_H__
#include "core/cvar.h"
+#include "core/netserver.h"
namespace core
{
@@ -51,6 +52,9 @@ public:
/// global application object
static Application *application_instance;
+
+ /// network server instance
+ NetServer *netserver;
};
diff --git a/src/core/commandbuffer.cc b/src/core/commandbuffer.cc
index 7f1cda0..04fc406 100644
--- a/src/core/commandbuffer.cc
+++ b/src/core/commandbuffer.cc
@@ -23,13 +23,13 @@ namespace commandbuffer
void exec(const char *text)
{
std::stringstream cmdstream(text);
- std::string cmdname;
+ std::string command;
- if (!(cmdstream >> cmdname))
+ if (!(cmdstream >> command))
return;
// is it a function
- Func f = func::find(cmdname);
+ Func f = func::find(command);
if (f) {
// function exists, execute it
if (f->flags && func::Game) {
@@ -47,7 +47,7 @@ void exec(const char *text)
}
// is it a cvar
- Cvar cv = cvar::find(cmdname);
+ Cvar cv = cvar::find(command);
if (cv) {
// cvar exists
std::string args;
@@ -59,11 +59,11 @@ void exec(const char *text)
(*cv) = args;
}
- con_print << cmdname << " " << cv->text() << std::endl;
+ con_print << command << " " << cv->text() << std::endl;
return;
}
- con_print << "Unknown command '" << cmdname << "'" << std::endl;
+ con_print << "Unknown command '" << command << "'" << std::endl;
}
void execute()
diff --git a/src/core/entity.h b/src/core/entity.h
index 6ff3be1..b3dd7ef 100644
--- a/src/core/entity.h
+++ b/src/core/entity.h
@@ -12,7 +12,6 @@ namespace core
class EntityControlable;
}
-#include "core/core.h"
#include "core/player.h"
#include "math/mathlib.h"
@@ -43,9 +42,7 @@ public:
Entity(unsigned int entity_flags = 0);
virtual ~Entity();
- /**
- * @brief core type id
- */
+ /// core type id
virtual inline unsigned int core_type() { return entity::Default; }
/// unique instance identifier, automaticly set
@@ -54,19 +51,20 @@ public:
/// core shape id
entity::Shape core_shape;
- /// core color id
+ /// core color
math::Color core_color;
/// core radius, in game units
float core_radius;
- /// label
+ /// the entities label
std::string label;
/// custom game type id of this entity
unsigned int type;
/// flags
+ /// @see core::entity::Flags
unsigned int flags;
/* updateable by game */
@@ -74,72 +72,54 @@ public:
/// location of the entity
math::Vector3f location;
- /**
- * @brief direction the entity is facing, in degrees
- * A direction of 0 degrees means the entity is 'looking'
- * along the positive X-axis.
- */
+ /// direction the entity is facing, in degrees
+ /// A direction of 0 degrees means the entity is looking
+ /// along the positive X-axis.
float direction;
};
-/**
- * @brief an entity that can move around in the game world
- */
+/// an entity that can move around in the game world
class EntityDynamic : public Entity
{
public:
EntityDynamic(unsigned int entity_flags = 0);
virtual ~EntityDynamic();
- /**
- * @brief core type id
- */
+ /// core type id
virtual inline unsigned int core_type() { return entity::Dynamic; }
/* updateable by game */
- /**
- * @brief current speed of the entity in game units per second
- */
+ /// current speed of the entity in game units per second
float speed;
};
-/**
- * @brief an entity that can be controlled by a player
- */
+/// an entity that can be controlled by a player
class EntityControlable : public EntityDynamic
{
public:
EntityControlable(unsigned int entity_flags = 0);
virtual ~EntityControlable();
- /**
- * @brief core type id
- */
+ /// core type id
virtual inline unsigned int core_type() { return entity::Controlable; }
- /**
- * @brief owner of this controllable entity
- */
+ /// runs one game frame for the entity, to be implemented by game
+ virtual void frame(float seconds) = 0;
+
+ /* updateable by game */
+
+ /// owner of this controllable entity
Player *owner;
/* updatable by client */
- /**
- * @brief the direction the client wants to travel the entity to
- * @see direction
- */
+ /// the direction the client wants to travel the entity to
+ /// @see direction
float target_direction;
- /**
- * @brief engine thrust as set by the client, 0.0f - 1.0f
- */
+ /// engine thrust as set by the client, 0.0f - 1.0f
float target_thrust;
-
- /**
- * @brief runs one game frame for the entity, to be implemented by game
- */
- virtual void frame(float seconds) = 0;
};
diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h
index 6e53575..1fbae03 100644
--- a/src/core/gameinterface.h
+++ b/src/core/gameinterface.h
@@ -23,17 +23,6 @@ public:
/// destroy the game singleton
virtual ~GameInterface();
- /// initialize the game
- virtual bool init() = 0;
-
- /// shutdown the game
- virtual void shutdown() = 0;
-
- /// run one frame of the game
- /** @param sec time since the previous frame, in seconds
- */
- virtual void frame(float seconds) = 0;
-
/// a pointer to the current game instance
static GameInterface * instance();
@@ -42,6 +31,22 @@ public:
/// time the game has been running, in seconds
float current_time;
+
+ /// 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;
+
+ /// shutdown the game
+ virtual void shutdown() = 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;
private:
static GameInterface *gameinterface_instance;
diff --git a/src/core/netclient.cc b/src/core/netclient.cc
new file mode 100644
index 0000000..2df024b
--- /dev/null
+++ b/src/core/netclient.cc
@@ -0,0 +1,90 @@
+/*
+ net/netclient.h
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#include <iostream>
+#include <sstream>
+
+#include "sys/sys.h"
+#include "net/net.h"
+#include "core/netclient.h"
+
+namespace core
+{
+
+NetClient::NetClient(int clientfd, std::string host, int port) :
+ net::TCPClient(clientfd),
+ client_host(host)
+{
+ std::ostringstream osstream;
+ osstream << host << ":" << port;
+ client_player.name = osstream.str();
+ client_player.id = (unsigned int) clientfd;
+
+ client_host = host;
+ client_port = port;
+ //con_debug << "NetClient " << fd() << ": starting." << std::endl;
+}
+
+NetClient::~NetClient()
+{
+}
+
+std::string NetClient::host() const
+{
+ return client_host;
+}
+
+int NetClient::port() const
+{
+ return client_port;
+}
+
+Player &NetClient::player()
+{
+ return client_player;
+}
+
+bool NetClient::has_messages() const {
+ return (recvq.size() > 0 );
+}
+
+void NetClient::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 NetClient::receive()
+{
+ std::string datablock;
+ net::TCPClient::receive(datablock);
+
+ while(datablock.size() > 0 ) {
+ // scan the datablock for enters
+ if (datablock[0] == '\n' || datablock[0] == '\r') {
+ // TODO detect "begin binary block" message for zlib compression
+ 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 << "NetClient " << fd() << ": message block overflow" << std::endl;
+ messageblock.clear();
+ }
+ }
+ datablock.erase(0,1);
+ }
+ datablock.clear();
+}
+
+}
diff --git a/src/core/netclient.h b/src/core/netclient.h
new file mode 100644
index 0000000..dcffb3c
--- /dev/null
+++ b/src/core/netclient.h
@@ -0,0 +1,57 @@
+/*
+ core/netclient.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_NETCLIENT_H__
+#define __INCLUDED_CORE_NETCLIENT_H__
+
+#include <string>
+#include <deque>
+#include <map>
+
+#include "net/tcpclient.h"
+#include "core/player.h"
+
+namespace core
+{
+
+/// queues incoming client messages
+class NetClient : public net::TCPClient
+{
+public:
+ NetClient(int clientfd, std::string host, int port);
+ ~NetClient();
+
+ /// the remote hostname the client is connected to
+ std::string host() const;
+
+ /// the remote port the client is connected to
+ int port() const;
+
+ /// the player info associated with this client
+ Player & player();
+
+ /// return true if there are incoming messages
+ bool has_messages() const;
+
+ /// receive an incoming message
+ void retreive(std::string & message);
+
+ /// receive incoming data and store messages
+ void receive();
+
+private:
+ std::string client_host;
+ int client_port;
+ Player client_player;
+
+ std::string messageblock;
+ std::deque<std::string> recvq;
+};
+
+}
+
+#endif // __INCLUDED_CORE_NETCLIENT_H__
+
diff --git a/src/core/netserver.cc b/src/core/netserver.cc
new file mode 100644
index 0000000..c37b71d
--- /dev/null
+++ b/src/core/netserver.cc
@@ -0,0 +1,268 @@
+/*
+ net/netserver.h
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#include <iostream>
+#include <sstream>
+
+#include "sys/sys.h"
+#include "core/netclient.h"
+#include "core/netserver.h"
+#include "core/cvar.h"
+#include "core/func.h"
+#include "core/core.h"
+
+namespace core
+{
+
+NetServer::NetServer(std::string const host, unsigned int const port) :
+ net::TCPServer(host, port)
+{
+ FD_ZERO(&serverset);
+ // add the listening socket to the file descriptor set
+ FD_SET(fd(), &serverset);
+
+ fdmax=fd();
+}
+
+NetServer::~NetServer()
+{
+ con_print << "Shutting down network..." << std::endl;
+
+ // delete all clients
+ std::list<NetClient *>:: iterator it;
+ for (it = clients.begin(); it != clients.end(); it++) {
+ // notify the game
+ if (core::connected()) {
+ core::game()->player_disconnect((*it)->player());
+ con_print << (*it)->player().name << " disconnected."<< std::endl;
+ }
+ delete (*it);
+ }
+ clients.clear();
+}
+
+void NetServer::client_connect(int const clientfd, std::string const host, int const port)
+{
+ NetClient *client = new NetClient(clientfd, host, port);
+ if (client->error()) {
+ con_warn << "Client " << client->fd() << " " <<
+ client->host() << ":" << client->port() << " connection failed!" << std::endl;
+ delete(client);
+ return;
+ }
+
+ clients.push_back(client);
+ FD_SET(client->fd(), &serverset);
+
+ // TODO send infos
+
+ con_print << client->player().name << " connected."<< std::endl;
+
+ // notify the game
+ if (core::game())
+ core::game()->player_connect(client->player());
+
+ // BROADCAST connect message
+ std::ostringstream osstream;
+ osstream << "msg info " << client->player().name << " connected."<< std::endl;
+ broadcast(osstream);
+}
+
+// remove disconnected clients
+void NetServer::reap()
+{
+ std::list<NetClient *>:: iterator it;
+ for (it = clients.begin(); it != clients.end(); it++) {
+ NetClient *client = *it;
+ 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);
+
+ // notify the game
+ if (core::game())
+ core::game()->player_disconnect(client->player());
+
+ con_print << client->player().name << " disconnected."<< std::endl;
+
+ // remove the client
+ clients.erase(it);
+ delete client;
+ it=clients.begin();
+
+ }
+ }
+}
+
+
+void NetServer::frame(float seconds) {
+ if (error())
+ return;
+
+ timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ fd_set readset = serverset;
+
+ int nb = select(fdmax+1, &readset, NULL, NULL, &timeout);
+ if (nb == 0)
+ return;
+
+ if (nb == -1) {
+ con_error << "Network error on select()" << std::endl;
+ perror("select");
+ abort();
+ }
+
+ // accept incoming connections
+ if(FD_ISSET(this->fd(), &readset)) {
+ accept();
+ }
+
+ // get messages from clients
+ for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end(); it++) {
+ NetClient *client = *it;
+ if (client->fd() > fdmax)
+ fdmax = client->fd();
+ if (FD_ISSET(client->fd(), &readset) && !client->error()) {
+ client->receive();
+ while (client->has_messages()) {
+ std::string message;
+ client->retreive(message);
+ parse_incoming_message(client, message);
+ }
+ }
+ }
+
+ // remove dead connections
+ reap();
+}
+
+// send a message to one client
+void NetServer::send(NetClient * client, std::ostringstream &osstream) {
+ // FIXME large messages
+ //std::cout << "NetServer: " << osstream.str();
+ client->send(osstream.str());
+ osstream.str("");
+}
+
+void NetServer::send(NetClient * client, std::string message) {
+ //std::cout << "NetServer: " << message;
+ client->send(message);
+}
+
+// send a message to all clients
+void NetServer::broadcast(std::ostringstream &osstream, int ignorefd)
+{
+ //std::cout << "NetServer: " << osstream.str();
+ for (std::list<NetClient *>::iterator it = clients.begin(); it != clients.end(); it++) {
+ NetClient *client = *it;
+ if (!client->error() && client->fd() != ignorefd)
+ client->send(osstream.str());
+ }
+ osstream.str("");
+}
+
+void NetServer::parse_incoming_message(NetClient *client, const std::string & message)
+{
+ std::stringstream msgstream(message);
+
+ std::string command;
+ msgstream >> command;
+
+ // disconnect
+ if (command == "disconnect") {
+ client->abort();
+ return;
+ }
+
+ // say
+ 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;
+ broadcast(osstream);
+ con_print << client->player().name << " " << message.substr(command.size()+1) << std::endl;
+ }
+ return;
+ }
+
+ // name is an alias for set name
+ if (command == "name") {
+ std::string name;
+ if (msgstream >> name) {
+ if (name.size() > 16)
+ 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);
+ client->player().name = name;
+ con_print << client->player().name << " renamed to " << name << std::endl;
+ }
+ }
+ return;
+ }
+
+ 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 client " << clients.size() << " players" << std::endl;
+ send(client, osstream);
+ }
+
+ if (command == "help") {
+ send(client, "msg info Available commands:\n");
+ send(client, "msg info help - shows this help message\n");
+ send(client, "msg info name nickname - changes your nickname\n");
+ send(client, "msg info say text - say something on the public channel\n");
+ send(client, "msg info list_players - shows a list of connected players\n");
+ send(client, "msg info disconnect - disconnect\n");
+ }
+
+ // execute game functions
+ if (game() && game()->connected) {
+ Func f = func::find(command);
+ if (f) {
+ if (f->flags && func::Game) {
+ GameFuncPtr function = (GameFuncPtr) f->ptr;
+ function(client->player(), msgstream);
+ } else {
+ // FIXME 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)
+{
+ 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 << std::endl;
+ broadcast(osstream);
+ client->player().name = name;
+ }
+ }
+ return;
+ }
+}
+
+}
diff --git a/src/core/netserver.h b/src/core/netserver.h
new file mode 100644
index 0000000..4d1eb73
--- /dev/null
+++ b/src/core/netserver.h
@@ -0,0 +1,60 @@
+/*
+ core/netserver.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_NETSERVER_H__
+#define __INCLUDED_CORE_NETSERVER_H__
+
+#include <sys/select.h>
+
+#include <list>
+#include <string>
+
+#include "net/tcpserver.h"
+#include "core/netclient.h"
+
+namespace core
+{
+
+/// Network server
+class NetServer : public net::TCPServer
+{
+public:
+ NetServer(std::string const host, unsigned int const port);
+ virtual ~NetServer();
+
+ /// run one server frame
+ void frame(float seconds);
+
+ /// broadcast a message to all clients
+ void broadcast(std::ostringstream &osstream, int ignorefd=-1);
+
+ /// send a message to a client
+ void send(NetClient * client, std::ostringstream &osstream);
+
+ /// send a message to a client
+ void send(NetClient * client, std::string message);
+
+protected:
+ /// called by accept() when a new client connects
+ virtual void client_connect(int const clientfd, std::string const host, int const port);
+
+ /// remove terminated clients
+ void reap();
+
+ /// parse incoming client messages
+ void parse_incoming_message(NetClient *client, const std::string & message);
+
+ /// parse client variable
+ void parse_client_variable(NetClient * client, const std::string varname, std::istringstream &istringstream);
+
+ std::list<NetClient *> clients;
+ fd_set serverset;
+ int fdmax;
+};
+
+}
+
+#endif // __INCLUDED_CORE_NETSERVER_H__
diff --git a/src/core/player.h b/src/core/player.h
index 1f63d63..859eddc 100644
--- a/src/core/player.h
+++ b/src/core/player.h
@@ -19,6 +19,7 @@ class Player;
namespace core
{
+/// a player in the game
class Player
{
public:
@@ -38,6 +39,7 @@ public:
EntityControlable *controled;
};
+/// the local player, always has id 0
extern Player localplayer;
}
diff --git a/src/game/Makefile.am b/src/game/Makefile.am
index f86c814..d327706 100644
--- a/src/game/Makefile.am
+++ b/src/game/Makefile.am
@@ -5,4 +5,4 @@ libgame_la_LDFLAGS = -avoid-version
libgame_la_SOURCES = game.cc sector.cc ship.cc shipspecs.cc star.cc
noinst_LTLIBRARIES = libgame.la
-noinst_HEADERS = game.h player.h sector.h ship.h shipspecs.h star.h world.h
+noinst_HEADERS = game.h sector.h ship.h shipspecs.h star.h world.h
diff --git a/src/game/game.cc b/src/game/game.cc
index f88c753..f8452f7 100644
--- a/src/game/game.cc
+++ b/src/game/game.cc
@@ -186,10 +186,19 @@ void Game::shutdown()
void Game::frame(float seconds)
{
-
}
+void Game::player_connect(core::Player &player)
+{
+ std::stringstream args;
+ game::func_spectate(player, args);
+}
+void Game::player_disconnect(core::Player &player)
+{
+ std::stringstream args;
+ game::func_spectate(player, args);
+}
} // namespace game
diff --git a/src/game/game.h b/src/game/game.h
index d8a6185..3811a06 100644
--- a/src/game/game.h
+++ b/src/game/game.h
@@ -36,6 +36,12 @@ public:
/// execute one game grame
void frame(float seconds);
+ /// is called when a player connects
+ void player_connect(core::Player &player);
+
+ /// is called when a player disconnects
+ void player_disconnect(core::Player &player);
+
/// sectors in space
std::vector<Sector*> sectors;
diff --git a/src/game/player.h b/src/game/player.h
deleted file mode 100644
index 0fdec76..0000000
--- a/src/game/player.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- game/player.h
- This file is part of the Osirion project and is distributed under
- the terms and conditions of the GNU General Public License version 2
-*/
-
-#ifndef __INCLUDED_GAME_PLAYER_H__
-#define __INCLUDED_GAME_PLAYER_H__
-
-#include <string>
-
-namespace game {
-
-/// a player in the game
-class Player {
-public:
- Player();
- ~Player();
-
- /// name of the player
- std::string name;
-};
-
-} // namespace game
-
-#endif // __INCLUDED_GAME_PLAYER_H__
-
diff --git a/src/net/tcpclient.cc b/src/net/tcpclient.cc
index da5ff27..b8aa9dd 100644
--- a/src/net/tcpclient.cc
+++ b/src/net/tcpclient.cc
@@ -27,7 +27,7 @@ TCPClient::~TCPClient()
{
if (tcpclient_fd != -1)
close(tcpclient_fd);
-
+ //con_debug << "TCPClient: terminated." << std::endl;
}
bool TCPClient::error() const
diff --git a/src/net/tcpconnection.cc b/src/net/tcpconnection.cc
index 9eaba1f..92bc3d2 100644
--- a/src/net/tcpconnection.cc
+++ b/src/net/tcpconnection.cc
@@ -142,7 +142,7 @@ void TCPConnection::receive(std::string &msg)
memset(recvbuf, '\0', sizeof(recvbuf));
bytes_received = ::recv(tcpconnection_fd, recvbuf, msglen, 0);
if (bytes_received == 0) {
- con_print << "Server disconnected.";
+ con_print << "Disconnected.";
abort();
return;
} else if (bytes_received < 0) {
diff --git a/src/net/tcpserver.cc b/src/net/tcpserver.cc
index f194a63..3276f87 100644
--- a/src/net/tcpserver.cc
+++ b/src/net/tcpserver.cc
@@ -27,9 +27,9 @@ TCPServer::TCPServer(std::string const host, unsigned int const port)
{
tcpserver_fd = -1;
tcpserver_error = true;
-
- con_debug << "TCPServer: starting." << std::endl;
-
+
+ con_print << "Initializing network..." << std::endl;
+
// initialize socket
tcpserver_fd = ::socket(PF_INET, SOCK_STREAM, 0);
if (tcpserver_fd == -1) {
@@ -73,7 +73,7 @@ TCPServer::TCPServer(std::string const host, unsigned int const port)
}
tcpserver_error = false;
- con_print << "Listening on " << inet_ntoa(listen_addr.sin_addr) <<
+ con_print << " listening on " << inet_ntoa(listen_addr.sin_addr) <<
":" << ntohs(listen_addr.sin_port) << std::endl;
}
@@ -81,7 +81,7 @@ TCPServer::~TCPServer()
{
if (tcpserver_fd != -1)
::close(tcpserver_fd);
- con_debug << "TCPServer: terminated." << std::endl;
+ //con_debug << "TCPServer: terminated." << std::endl;
}
bool TCPServer::valid() const
@@ -111,7 +111,7 @@ void TCPServer::abort()
void TCPServer::accept()
{
- con_debug << "TCPServer: accept()" << std::endl;
+ //con_debug << "TCPServer: accept()" << std::endl;
struct sockaddr_in client_addr;
socklen_t addrlen = sizeof(struct sockaddr_in);
@@ -129,3 +129,4 @@ void TCPServer::accept()
}
}
+
diff --git a/src/net/tcpserver.h b/src/net/tcpserver.h
index dd87689..99639eb 100644
--- a/src/net/tcpserver.h
+++ b/src/net/tcpserver.h
@@ -32,12 +32,15 @@ public:
bool error() const;
protected:
- /// Accept incoming connections
+ /// accept an incoming connection
void accept();
+
/// Set the error state
void abort();
+
/// Returns the file descriptor the TCP server is listening on
int fd() const;
+
/// Called by accept() whenever a new client connects
virtual void client_connect(int const clientfd, std::string const host, int const port) = 0;
diff --git a/src/server/Makefile.am b/src/server/Makefile.am
index 0e7bde1..f9b2ada 100644
--- a/src/server/Makefile.am
+++ b/src/server/Makefile.am
@@ -5,4 +5,5 @@ noinst_LTLIBRARIES = libserver.la
INCLUDES = -I$(top_srcdir)/src
libserver_la_LDFLAGS = -avoid-version -no-undefined
libserver_la_LIBADD = $(top_builddir)/src/sys/libsys.la \
- $(top_builddir)/src/filesystem/libfilesystem.la $(top_builddir)/src/math/libmath.la $(top_builddir)/src/core/libcore.la
+ $(top_builddir)/src/filesystem/libfilesystem.la $(top_builddir)/src/math/libmath.la \
+ $(top_builddir)/src/net/libnet.la $(top_builddir)/src/core/libcore.la