Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2008-02-16 12:22:33 +0000
committerStijn Buys <ingar@osirion.org>2008-02-16 12:22:33 +0000
commitd6ee7ec642cc6b3097c8d321a1a00630e24027d1 (patch)
tree35f56e5168cc3e12724898b9efb81b4b2938f575 /src
parent715d0c3952a3a1d59b64074e472d0a9a3b414351 (diff)
initial client-to-server connection
Diffstat (limited to 'src')
-rw-r--r--src/client/camera.cc12
-rw-r--r--src/client/client.cc2
-rw-r--r--src/client/console.cc2
-rw-r--r--src/client/input.cc12
-rw-r--r--src/client/video.cc2
-rw-r--r--src/client/view.cc8
-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
-rw-r--r--src/game/game.cc43
-rw-r--r--src/net/tcpconnection.cc16
-rw-r--r--src/net/tcpconnection.h2
-rw-r--r--src/server/server.cc4
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()