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