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-21 19:06:15 +0000
committerStijn Buys <ingar@osirion.org>2008-02-21 19:06:15 +0000
commit8aa04fc836116a58f8ffd1e0c3539b9ea8a94ddf (patch)
treebb933edb3919ed67d05b098a6b97a73f01746762 /src
parent41ad1e4c9e2a70d0a8811f4b035f0d3018045e61 (diff)
dedicated server, entity transfer
Diffstat (limited to 'src')
-rw-r--r--src/client/console.cc5
-rw-r--r--src/client/draw.cc1
-rw-r--r--src/client/input.cc40
-rw-r--r--src/client/view.cc2
-rw-r--r--src/core/application.cc1
-rw-r--r--src/core/cvar.cc1
-rw-r--r--src/core/cvar.h1
-rw-r--r--src/core/entity.cc166
-rw-r--r--src/core/entity.h88
-rw-r--r--src/core/gameconnection.cc29
-rw-r--r--src/core/gameconnection.h1
-rw-r--r--src/core/gameserver.cc53
-rw-r--r--src/core/gameserver.h2
-rw-r--r--src/core/netconnection.cc50
-rw-r--r--src/core/netserver.cc46
-rw-r--r--src/core/netserver.h2
-rw-r--r--src/core/player.cc40
-rw-r--r--src/core/player.h15
-rw-r--r--src/game/game.cc8
-rw-r--r--src/game/ship.cc4
-rw-r--r--src/game/ship.h2
-rw-r--r--src/math/color.cc11
-rw-r--r--src/math/color.h2
-rw-r--r--src/math/vector3f.cc31
-rw-r--r--src/math/vector3f.h27
-rw-r--r--src/server/server.cc18
-rw-r--r--src/server/timer.cc11
-rw-r--r--src/sys/sys.cc2
28 files changed, 587 insertions, 72 deletions
diff --git a/src/client/console.cc b/src/client/console.cc
index 492d909..9c7c6ca 100644
--- a/src/client/console.cc
+++ b/src/client/console.cc
@@ -120,8 +120,9 @@ void draw()
// draw version below the bottom of the console
gl::enable(GL_TEXTURE_2D);
gl::color(0.0f, 1.0f, 0.0f, 0.5f);
- std:: string version = std::string("The Osirion Project ");
- version.append(VERSION);
+ std::string version(core::name());
+ version += ' ';
+ version.append(core::version());
draw_text(video::width-CHARWIDTH*(version.size()+1), video::height*con_height-CHARHEIGHT-4, version);
gl::disable(GL_TEXTURE_2D);
diff --git a/src/client/draw.cc b/src/client/draw.cc
index 72a67c2..60726b0 100644
--- a/src/client/draw.cc
+++ b/src/client/draw.cc
@@ -215,6 +215,7 @@ void draw_world(float seconds)
break;
case core::Entity::Controlable:
draw_ship(static_cast<core::EntityControlable *> ((*it).second));
+ break;
default:
break;
}
diff --git a/src/client/input.cc b/src/client/input.cc
index e8dacd6..7193c0e 100644
--- a/src/client/input.cc
+++ b/src/client/input.cc
@@ -20,10 +20,21 @@ namespace input
{
// local offset to make turns
-float local_turn_offset;
+float local_turn;
// local thrust setting
float local_thrust;
+core::Player *localplayer() {
+ return core::game()->localplayer();
+}
+
+core::EntityControlable *localcontrol() {
+ if (core::game()->localplayer())
+ return core::game()->localplayer()->control;
+ else
+ return 0;
+}
+
void init()
{
con_print << "Initializing input..." << std::endl;
@@ -77,15 +88,20 @@ void keypressed(const SDL_keysym &keysym)
break;
case SDLK_KP4:
// TODO set core entity params
- local_turn_offset += 5;
- if (local_turn_offset > 90)
- local_turn_offset = 90;
+ local_turn += 5;
+ if (math::degrees180f(local_turn - localcontrol()->direction()) > 90)
+ local_turn = localcontrol()->direction() + 90;
+ if (local_turn > 360)
+ local_turn -= 360;
+
break;
case SDLK_KP6:
// TODO set core entity params
- local_turn_offset -= 5;
- if (local_turn_offset < -90)
- local_turn_offset = -90;
+ local_turn -= 5;
+ if (math::degrees180f(local_turn - localcontrol()->direction()) < -90)
+ local_turn = localcontrol()->direction() - 90;
+ if (local_turn < 0)
+ local_turn += 360;
break;
default:
break;
@@ -101,7 +117,7 @@ void frame(float seconds)
switch (event.type) {
case SDL_KEYUP:
- if (!console::visible() && core::application()->connected() && core::game()->localplayer()->control)
+ if (!console::visible() && core::application()->connected() && localcontrol())
// send key events to the game world
keyreleased(event.key.keysym);
break;
@@ -111,7 +127,7 @@ void frame(float seconds)
} else if (console::visible()) {
// send key events to the console
console::keypressed(event.key.keysym);
- } else if (core::application()->connected() && core::game()->localplayer()->control) {
+ } else if (core::application()->connected() && localcontrol()) {
// send key events to the game world
keypressed(event.key.keysym);
}
@@ -123,9 +139,9 @@ void frame(float seconds)
}
- if (!console::visible() && core::application()->connected() && core::game()->localplayer()->control) {
- core::game()->localplayer()->control->set_thrust(local_thrust);
- core::game()->localplayer()->control->set_direction(math::degrees360f(core::game()->localplayer()->control->direction() + local_turn_offset));
+ if (!console::visible() && core::application()->connected() && localcontrol()) {
+ localcontrol()->set_thrust(local_thrust);
+ localcontrol()->set_direction(local_turn);
}
}
diff --git a/src/client/view.cc b/src/client/view.cc
index 0c8e26b..1a40c4a 100644
--- a/src/client/view.cc
+++ b/src/client/view.cc
@@ -118,7 +118,7 @@ void draw_status()
// print the version number in the upper right corner
gl::color(0.0f, 1.0f, 0.0f, 1.0f);
std::string version("ver. ");
- version.append(VERSION);
+ version.append(core::version());
draw_text(video::width-(version.size()+1)*CHARWIDTH, 4, version);
gl::disable(GL_TEXTURE_2D);
diff --git a/src/core/application.cc b/src/core/application.cc
index a95bd22..b55df34 100644
--- a/src/core/application.cc
+++ b/src/core/application.cc
@@ -157,6 +157,7 @@ void Application::init()
Cvar::sv_dedicated = Cvar::get("sv_dedicated", "0", Cvar::ReadOnly);
// client can set this to 1
Cvar::sv_private = Cvar::get("sv_private", "0");
+ Cvar::sv_framerate = Cvar::get("sv_framerate", "25");
// network settings
Cvar::net_host = Cvar::get("net_host", "0.0.0.0");
diff --git a/src/core/cvar.cc b/src/core/cvar.cc
index 9419db3..9ce1fe6 100644
--- a/src/core/cvar.cc
+++ b/src/core/cvar.cc
@@ -19,6 +19,7 @@ namespace core
Cvar *Cvar::sv_dedicated = 0;
Cvar *Cvar::sv_private = 0;
+Cvar *Cvar::sv_framerate = 0;
Cvar *Cvar::net_host = 0;
Cvar *Cvar::net_port = 0;
diff --git a/src/core/cvar.h b/src/core/cvar.h
index 7350eee..3847a78 100644
--- a/src/core/cvar.h
+++ b/src/core/cvar.h
@@ -101,6 +101,7 @@ public:
static Cvar *sv_dedicated; // dedicated server
static Cvar *sv_private; // client with private server
+ static Cvar *sv_framerate; // server framerate
static Cvar *net_host; // network server ip (default binds to all interfaces)
static Cvar *net_port; // network port
diff --git a/src/core/entity.cc b/src/core/entity.cc
index 229fb52..7e9c788 100644
--- a/src/core/entity.cc
+++ b/src/core/entity.cc
@@ -7,6 +7,11 @@
#include <vector>
#include <iomanip>
+namespace core
+{
+ class Entity;
+}
+
#include "sys/sys.h"
#include "core/entity.h"
@@ -31,6 +36,16 @@ void Entity::add(Entity *ent)
registry[id] = ent;
}
+void Entity::add(Entity *ent, unsigned int id)
+{
+ if (find(id)) {
+ con_warn << "Duplicate entity " << id << "!\n";
+ return;
+ }
+ ent->entity_id = id;
+ registry[id] = ent;
+}
+
Entity *Entity::find(unsigned int id)
{
std::map<unsigned int, Entity *>::iterator it = registry.find(id);
@@ -77,13 +92,78 @@ Entity::Entity(unsigned int flags) :
entity_direction = 0;
entity_shape = Diamond;
+ entity_created = true;
+ entity_destroyed = false;
+ entity_dirty = false;
+
add(this);
}
+Entity::Entity(std::istream & is)
+{
+ // type is already determined
+ unsigned int s;
+ std::string n;
+
+ is >> entity_id;
+ is >> entity_moduletypeid;
+ is >> entity_flags;
+ is >> entity_location;
+ is >> entity_color;
+ is >> s; // shape
+ is >> entity_radius;
+ is >> entity_direction;
+
+ char c;
+ while ( (is.get(c)) && (c != '"'));
+ while ( (is.get(c)) && (c != '"'))
+ n += c;
+
+ entity_shape = (Shape) s ;
+ entity_name = n;
+
+ entity_created = true;
+ entity_destroyed = false;
+ entity_dirty = false;
+
+ add(this, entity_id);
+}
+
Entity::~Entity()
{
}
+void Entity::serialize(std::ostream & os) const
+{
+ os << type() << " "
+ << entity_id << " "
+ << entity_moduletypeid << " "
+ << entity_flags << " "
+ << entity_location << " "
+ << entity_color << " "
+ << entity_shape << " "
+ << entity_radius << " "
+ << entity_direction << " "
+ << "\"" << entity_name << "\"";
+}
+
+void Entity::serialize_client_update(std::ostream & os) const
+{
+}
+
+void Entity::recieve_client_update(std::istream &is)
+{
+}
+
+void Entity::serialize_server_update(std::ostream & os) const
+{
+}
+
+void Entity::recieve_server_update(std::istream &is)
+{
+}
+
+
void Entity::frame(float seconds)
{
}
@@ -96,15 +176,51 @@ EntityDynamic::EntityDynamic(unsigned int flags) :
entity_speed = 0.0f;
}
+EntityDynamic::EntityDynamic(std::istream & is) :
+ Entity(is)
+{
+ is >> entity_speed;
+}
+
EntityDynamic::~EntityDynamic()
{
}
void EntityDynamic::frame(float seconds)
{
+ if (entity_speed == 0)
+ return;
+
// location avoid sin/cos calculations
entity_location.x += cosf(entity_direction * M_PI / 180) * entity_speed * seconds;
entity_location.z -= sinf(entity_direction * M_PI / 180) * entity_speed * seconds;
+ entity_dirty = true;
+}
+
+void EntityDynamic::serialize(std::ostream & os) const
+{
+ Entity::serialize(os);
+ os << " " << entity_speed;
+}
+
+void EntityDynamic::serialize_client_update(std::ostream & os) const
+{
+}
+
+void EntityDynamic::recieve_client_update(std::istream &is)
+{
+}
+
+void EntityDynamic::serialize_server_update(std::ostream & os) const
+{
+ os << entity_location << " " << entity_direction << " " << entity_speed;
+}
+
+void EntityDynamic::recieve_server_update(std::istream &is)
+{
+ is >> entity_location;
+ is >> entity_direction;
+ is >> entity_speed;
}
/*----- EntityControlable ------------------------------------------ */
@@ -119,26 +235,74 @@ EntityControlable::EntityControlable(Player *player, unsigned int flags) :
target_thrust = 0.0f;
}
+EntityControlable::EntityControlable(std::istream & is) :
+ EntityDynamic(is)
+{
+ unsigned int o;
+
+ is >> entity_thrust;
+ is >> o;
+
+ // FIXME resolve owner
+ entity_owner = 0;
+}
+
+
EntityControlable::~EntityControlable()
{
}
+void EntityControlable::serialize(std::ostream & os) const
+{
+ EntityDynamic::serialize(os);
+ os << " " << entity_thrust;
+ os << " " << entity_owner->id();
+}
+
+void EntityControlable::serialize_client_update(std::ostream & os) const
+{
+ EntityDynamic::serialize_client_update(os);
+ os << " " << target_direction;
+ os << " " << target_thrust;
+}
+
+void EntityControlable::recieve_client_update(std::istream &is)
+{
+ EntityDynamic::recieve_client_update(is);
+ is >> target_direction;
+ is >> target_thrust;
+}
+
+void EntityControlable::serialize_server_update(std::ostream & os) const
+{
+ EntityDynamic::serialize_server_update(os);
+ os << " " << entity_thrust;
+}
+
+void EntityControlable::recieve_server_update(std::istream &is)
+{
+ EntityDynamic::recieve_server_update(is);
+ is >> entity_thrust;
+}
+
void EntityControlable::frame(float seconds)
{
entity_direction = target_direction;
entity_thrust = target_thrust;
-
+ entity_dirty = true;
EntityDynamic::frame(seconds);
}
void EntityControlable::set_thrust(float thrust)
{
target_thrust = thrust;
+ entity_dirty = true;
}
void EntityControlable::set_direction(float direction)
{
target_direction = direction;
+ entity_dirty = true;
}
}
diff --git a/src/core/entity.h b/src/core/entity.h
index df16075..9c90ef9 100644
--- a/src/core/entity.h
+++ b/src/core/entity.h
@@ -15,6 +15,7 @@ class EntityControlable;
#include "core/player.h"
#include "math/mathlib.h"
+#include <iostream>
#include <string>
#include <map>
@@ -29,7 +30,7 @@ public:
enum Flags {Static=1, Solid=2};
/// Entity type constants
- enum Type {Default = 0, Dynamic = 1, Controlable = 2};
+ enum Type {Default=0, Dynamic=1, Controlable=2};
/// Entity shape constants
enum Shape {Diamond=0, Sphere=1, Cube=2};
@@ -37,6 +38,9 @@ public:
/// create a new entity and add it to the registry
Entity(unsigned int flags = 0);
+ /// create an entity froms stream data
+ Entity(std::istream & is);
+
/// destroy an entity
virtual ~Entity();
@@ -49,14 +53,17 @@ public:
inline unsigned int moduletype() const { return entity_moduletypeid; }
/// core type id
- virtual inline unsigned int type() { return Default; }
+ virtual inline unsigned int type() const { return Default; }
/// entity flags
inline unsigned int flags() const { return entity_flags; }
- /// entity name
+ /// entity name (can not contain double qoutes ")
inline std::string const & name() { return entity_name; }
+ /// dirty flag
+ inline bool dirty() const { return entity_dirty; }
+
/// entity location
inline math::Vector3f const & location() const { return entity_location; }
@@ -72,8 +79,27 @@ public:
/// base radius of the entity
inline float radius() const { return entity_radius; }
+ /// serialize the entity to a stream
+ virtual void serialize(std::ostream & os) const;
+
+ /// serialize a client-to-server update on a stream
+ virtual void serialize_client_update(std::ostream & os) const;
+
+ /// serialize a server-to-client update on a stream
+ virtual void serialize_server_update(std::ostream & os) const;
+
+
/*----- mutators -------------------------------------------------- */
+ /// receive a client-to-server update from a stream
+ virtual void recieve_client_update(std::istream &is);
+
+ /// receive a server-to-client update from a stream
+ virtual void recieve_server_update(std::istream &is);
+
+ /// mark the entity as destroyed
+ inline void die() { entity_destroyed = true; }
+
/// runs one game frame for the entity
/**
* The default implementation does nothing
@@ -108,30 +134,59 @@ public:
unsigned int entity_moduletypeid;
unsigned int entity_flags;
+ bool entity_dirty;
+ bool entity_created;
+ bool entity_destroyed;
+
private:
/// add an entity to the registry
static void add(Entity *ent);
+ /// add an entity with id to the registry
+ void add(Entity *ent, unsigned int id);
+
/// the id is set by add()
unsigned int entity_id;
};
+
/// an entity that can move around in the game world
class EntityDynamic : public Entity
{
public:
+ /// create a dynamic entity
EntityDynamic(unsigned int flags = 0);
+
+ /// create a dynamic entity from stream data
+ EntityDynamic(std::istream & is);
+
virtual ~EntityDynamic();
+
/*----- inspectors ------------------------------------------------ */
/// core type id
- virtual inline unsigned int type() { return Entity::Dynamic; }
+ virtual inline unsigned int type() const { return Entity::Dynamic; }
/// current speed of the entity in game units per second
inline float speed() const { return entity_speed; }
+ /// serialize the entity to a stream
+ virtual void serialize(std::ostream & os) const;
+
+ /// serialize a client-to-server update on a stream
+ virtual void serialize_client_update(std::ostream & os) const ;
+
+ /// serialize a server-to-client update on a stream
+ virtual void serialize_server_update(std::ostream & os) const;
+
/*----- mutators -------------------------------------------------- */
+ /// receive a client-to-server update from a stream
+ virtual void recieve_client_update(std::istream &is);
+
+ /// receive a server-to-client update from a stream
+ virtual void recieve_server_update(std::istream &is);
+
/// runs one game frame for the entity
/**
* The default implementation will update the position() of the entity,
@@ -147,14 +202,19 @@ public:
class EntityControlable : public EntityDynamic
{
public:
- /// create
+ /// create a controlable entity
EntityControlable(Player *player, unsigned int flags = 0);
+
+ /// create a controlable entity from stream data
+ EntityControlable(std::istream & is);
+
virtual ~EntityControlable();
+
/*----- inspectors ------------------------------------------------ */
/// core type id
- virtual inline unsigned int type() { return Entity::Controlable; }
+ virtual inline unsigned int type() const { return Entity::Controlable; }
/// owner of this entity
inline Player *owner() const { return entity_owner; }
@@ -162,8 +222,24 @@ public:
/// thrust
inline float thrust() const { return entity_thrust; }
+ /// serialize the entity to a stream
+ virtual void serialize(std::ostream & os) const;
+
+ /// serialize a client-to-server update on a stream
+ virtual void serialize_client_update(std::ostream & os) const;
+
+ /// serialize a server-to-client update on a stream
+ virtual void serialize_server_update(std::ostream & os) const;
+
+
/*----- mutators -------------------------------------------------- */
+ /// receive a client-to-server update from a stream
+ virtual void recieve_client_update(std::istream &is);
+
+ /// receive a server-to-client update from a stream
+ virtual void recieve_server_update(std::istream &is);
+
/// set the target thrust
void set_thrust(float t);
diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc
index 43df1be..eeb4692 100644
--- a/src/core/gameconnection.cc
+++ b/src/core/gameconnection.cc
@@ -9,6 +9,7 @@
#include "sys/sys.h"
#include "net/net.h"
+#include "core/cvar.h"
#include "core/gameconnection.h"
namespace core
@@ -46,6 +47,7 @@ GameConnection::GameConnection(std::string const &connectionstr)
return;
}
+ connection_frametime = 0;
connection_running = true;
}
@@ -86,7 +88,32 @@ void GameConnection::frame(float seconds)
return;
}
- connection_network->frame(seconds);
+
+ float f = 0;
+ if (core::Cvar::sv_framerate->value()) {
+ connection_frametime += seconds;
+ f = 1.0f / core::Cvar::sv_framerate->value();
+ if (connection_frametime < f)
+ return;
+ } else {
+ connection_frametime = seconds;
+ }
+
+ connection_network->frame(connection_frametime);
+
+ if (localplayer()->control && localplayer()->control->dirty()) {
+ std::ostringstream netmsg;
+ netmsg << "cup " << localplayer()->control->id() << " ";
+ localplayer()->control->serialize_client_update(netmsg);
+ netmsg << "\n";
+
+ connection_network->send(netmsg.str());
+ localplayer()->control->entity_dirty = false;
+ //con_debug << netmsg.str();
+ }
+
+ connection_frametime += f;
+
}
}
diff --git a/src/core/gameconnection.h b/src/core/gameconnection.h
index c91ef22..65fd495 100644
--- a/src/core/gameconnection.h
+++ b/src/core/gameconnection.h
@@ -49,6 +49,7 @@ private:
bool connection_running;
static GameConnection *connection_instance;
NetConnection *connection_network;
+ float connection_frametime;
};
diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc
index e5795ad..8ddd824 100644
--- a/src/core/gameserver.cc
+++ b/src/core/gameserver.cc
@@ -168,7 +168,7 @@ void GameServer::exec(Player *player, std::string const & cmdline)
std::string message("Unknown command '");
message.append(command);
- message.append("'\n");
+ message.append("'");
send(player, message);
}
@@ -178,8 +178,6 @@ void GameServer::player_connect(Player *player)
message.append(" connects.");
broadcast(message, player->id());
- // TODO transferplayer info, transfer entities
-
// notify the game module
server_module->player_connect(player);
}
@@ -208,15 +206,17 @@ void GameServer::frame(float seconds)
}
}
- // update entities
+ // run a time frame on each entity
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);
}
}
+ // run a frame on the module
if (server_module) {
server_module->frame(seconds);
if (server_module->error()) {
@@ -224,6 +224,51 @@ void GameServer::frame(float seconds)
return;
}
}
+
+ // send updates
+ if (server_network) {
+ std::map<unsigned int, Entity *>::iterator it;
+ for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) {
+ Entity *entity = (*it).second;
+ if (entity->entity_destroyed) {
+ if (!entity->entity_created) {
+ std::ostringstream netmsg;
+ netmsg << "die " << entity->id() << "\n";
+ server_network->broadcast(netmsg.str());
+ }
+ core::Entity::remove(entity->id());
+ } else if (entity->entity_created) {
+ std::ostringstream netmsg;
+ netmsg << "ent ";
+ entity->serialize(netmsg);
+ netmsg << "\n";
+ server_network->broadcast(netmsg.str());
+ entity->entity_created = false;
+
+ } else if (entity->dirty()) {
+ std::ostringstream netmsg;
+ netmsg << "sup " << entity->id() << " ";
+ entity->serialize_server_update(netmsg);
+ netmsg << "\n";
+ server_network->broadcast(netmsg.str());
+ }
+ entity->entity_dirty = false;
+ }
+
+ for (std::list<NetClient *>::iterator it = server_network->clients.begin(); it != server_network->clients.end(); it++) {
+ NetClient *client = *it;
+ if (client->player()->dirty()) {
+ // send player data
+ std::ostringstream netmsg;
+ netmsg.str("");
+ netmsg << "pif ";
+ client->player()->serialize_server_update(netmsg);
+ netmsg << "\n";
+ client->send(netmsg.str());
+ client->player()->player_dirty = false;
+ }
+ }
+ }
}
diff --git a/src/core/gameserver.h b/src/core/gameserver.h
index d4bd0eb..17d581c 100644
--- a/src/core/gameserver.h
+++ b/src/core/gameserver.h
@@ -37,7 +37,7 @@ public:
/// 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
+ /// is called when a player disconnects from the game server
void player_disconnect(Player *player);
/// run a game server time frame
diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc
index 63c906a..4770528 100644
--- a/src/core/netconnection.cc
+++ b/src/core/netconnection.cc
@@ -9,6 +9,7 @@
#include "sys/sys.h"
#include "net/net.h"
#include "core/application.h"
+#include "core/gameconnection.h"
#include "core/netconnection.h"
#include "core/player.h"
@@ -119,6 +120,10 @@ void NetConnection::frame(float seconds)
*
* msg info <text>
* msg public <name> <text>
+ * die
+ * ent
+ * sup
+ * pif
*/
void NetConnection::parse_incoming_message(const std::string & message)
{
@@ -142,6 +147,51 @@ void NetConnection::parse_incoming_message(const std::string & message)
}
}
+ } else if (command == "die") {
+ unsigned int id;
+ msgstream >> id;
+
+ Entity *e = Entity::find(id);
+ con_debug << "Received die entity id " << id << "\n";
+
+ if (game()->localplayer()->control == e)
+ game()->localplayer()-> control = 0;
+ if (e)
+ Entity::remove(id);
+
+ } else if (command == "ent") {
+ unsigned int type;
+ msgstream >> type;
+
+ con_debug << "Received create entity type " << type << "\n";
+ switch (type)
+ {
+ case Entity::Default:
+ new Entity(msgstream);
+ break;
+ case Entity::Dynamic:
+ new EntityDynamic(msgstream);
+ break;
+ case Entity::Controlable:
+ new EntityControlable(msgstream);
+ break;
+ default:
+ break;
+ }
+
+ } else if (command == "sup") {
+ unsigned int id;
+ if (msgstream >> id) {
+ Entity *entity = Entity::find(id);
+ if (!entity) {
+ con_warn << "Update for unknown entity " << id << "\n";
+ } else
+ entity->recieve_server_update(msgstream);
+ }
+ return;
+
+ } else if (command == "pif") {
+ connection()->localplayer()->recieve_server_update(msgstream);
}
}
diff --git a/src/core/netserver.cc b/src/core/netserver.cc
index 3473e6a..43067d7 100644
--- a/src/core/netserver.cc
+++ b/src/core/netserver.cc
@@ -58,6 +58,29 @@ void NetServer::client_connect(int const clientfd, std::string const host, int c
con_print << client->host() << ":" << client->port() << " connected.\n";
+ std::ostringstream netmsg;
+
+ // send entities
+ std::map<unsigned int, Entity *>::iterator it;
+ for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) {
+ netmsg.str("");
+ switch ((*it).second->type()) {
+ case Entity::Default:
+ case Entity::Dynamic:
+ case Entity::Controlable:
+ netmsg << "ent ";
+ (*it).second->serialize(netmsg);
+ netmsg << "\n";
+ client->send(netmsg.str());
+ break;
+ default:
+ break;
+ }
+ }
+
+ // mark player as dirty
+ client->player()->player_dirty = true;
+
// notify the game server
server()->player_connect(client->player());
@@ -169,6 +192,9 @@ NetClient *NetServer::find_client(Player const *player)
*/
void NetServer::parse_incoming_message(NetClient *client, const std::string & message)
{
+ if (!message.size())
+ return;
+
std::stringstream msgstream(message);
std::string command;
@@ -189,6 +215,24 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me
return;
}
+ // cup - client update entity
+ if (command == "cup") {
+ //con_debug << message << "\n";
+ unsigned int id;
+ if (msgstream >> id) {
+ Entity *entity = Entity::find(id);
+ if (!entity) {
+ con_warn << client->host() << ":" << client->port() << " update for unknown entity " << id << "\n";
+
+ } else {
+ entity->entity_dirty = true;
+ entity->recieve_client_update(msgstream);
+ }
+
+ }
+ return;
+ }
+
// say
if (command == "say") {
if (message.size() > command.size()+1) {
@@ -200,7 +244,7 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me
return;
}
- // name is an alias for set name
+ // name
if (command == "name") {
std::string name;
if (msgstream >> name) {
diff --git a/src/core/netserver.h b/src/core/netserver.h
index dd44285..4de87be 100644
--- a/src/core/netserver.h
+++ b/src/core/netserver.h
@@ -37,6 +37,7 @@ public:
/// find the client corresponding to a player
NetClient *find_client(Player const *player);
+ std::list<NetClient *> clients;
protected:
/// called by accept() when a new client connects
virtual void client_connect(int const clientfd, std::string const host, int const port);
@@ -47,7 +48,6 @@ protected:
/// parse incoming client messages
void parse_incoming_message(NetClient *client, const std::string & message);
- std::list<NetClient *> clients;
fd_set serverset;
int fdmax;
};
diff --git a/src/core/player.cc b/src/core/player.cc
index 8fc4ebf..f4ee6ea 100644
--- a/src/core/player.cc
+++ b/src/core/player.cc
@@ -4,6 +4,7 @@
the terms of the GNU General Public License version 2.
*/
+#include "sys/sys.h"
#include "core/player.h"
namespace core
@@ -23,9 +24,46 @@ void Player::clear()
{
player_id = 0;
player_name.clear();
- dirty = false;
+ player_dirty = false;
control = 0;
}
+void Player::serialize_server_update(std::ostream & os) const
+{
+ unsigned int co;
+ if (control)
+ co = control->id();
+ else
+ co = 0;
+
+ os << player_id << " " << co << " \"" << player_name << "\"";
+}
+
+void Player::recieve_server_update(std::istream &is)
+{
+ is >> player_id;
+ unsigned int co = 0;
+ is >> co;
+ if (co) {
+ Entity *e = Entity::find(co);
+ if (e && e->type() == Entity::Controlable) {
+ control = (EntityControlable *) e;
+ } else {
+ control = 0;
+ con_warn << "control set to unknown entity " << co << "\n";
+ }
+ } else {
+ control = 0;
+ }
+
+ std::string n;
+ char c;
+ while ( (is.get(c)) && (c != '"'));
+ while ( (is.get(c)) && (c != '"'))
+ n += c;
+
+ player_name = n;
+}
+
}
diff --git a/src/core/player.h b/src/core/player.h
index 11711b5..fd4053c 100644
--- a/src/core/player.h
+++ b/src/core/player.h
@@ -35,17 +35,26 @@ public:
/// id of the player
inline int id() const { return player_id; }
+ /// dirty flag
+ inline bool dirty() const { return player_dirty; }
+
/// id of the player
int player_id;
/// name of the player
std::string player_name;
- /// dirty state
- bool dirty;
-
/// the entity the Player is currently controling
EntityControlable *control;
+
+ /// serialize player info to a stream
+ void serialize_server_update(std::ostream & os) const;
+
+ /// receive player info from a stream
+ void recieve_server_update(std::istream &is);
+
+ /// dirty state
+ bool player_dirty;
};
}
diff --git a/src/game/game.cc b/src/game/game.cc
index 311a696..a76d5e7 100644
--- a/src/game/game.cc
+++ b/src/game/game.cc
@@ -30,6 +30,8 @@ void func_join(core::Player *player, std::string const &args)
std::string message(player->name());
message.append(" joins the game.");
core::server()->broadcast(message);
+
+ player->player_dirty = true;
}
/// a player joins the spectators
@@ -44,9 +46,11 @@ void func_spectate(core::Player *player, std::string const &args)
if (player->control) {
// player has only ship for now
- core::Entity::remove(player->control->id());
+ player->control->die();
player->control = 0;
}
+
+ player->player_dirty = true;
}
/*----- Game ------------------------------------------------------ */
@@ -136,7 +140,7 @@ void Game::player_disconnect(core::Player *player)
{
if (player->control) {
// player has only one ship for now
- core::Entity::remove(player->control->id());
+ player->control->die();
player->control = 0;
}
}
diff --git a/src/game/ship.cc b/src/game/ship.cc
index e6fcaeb..1bcdfbf 100644
--- a/src/game/ship.cc
+++ b/src/game/ship.cc
@@ -20,7 +20,7 @@ namespace game {
Ship::Ship(core::Player *owner) :
core::EntityControlable(owner, ship_enttype)
{
- // etnity properties
+ // entity properties
entity_name = "ship: <" + owner->name() + "> Micron Vector";
entity_owner = owner;
@@ -62,6 +62,8 @@ void Ship::frame(float seconds)
// location TODO avoid sin/cos calculations
entity_location.x += cosf(entity_direction * M_PI / 180) * entity_speed * seconds;
entity_location.z -= sinf(entity_direction * M_PI / 180) * entity_speed * seconds;
+
+ entity_dirty = true;
}
} // namespace game
diff --git a/src/game/ship.h b/src/game/ship.h
index 2897d6c..1d0fdd4 100644
--- a/src/game/ship.h
+++ b/src/game/ship.h
@@ -21,7 +21,7 @@ public:
~Ship();
/// update the ship state
- void frame(float seconds);
+ virtual void frame(float seconds);
/* -- Ship SPECS --*/
/// acceleration
diff --git a/src/math/color.cc b/src/math/color.cc
index b0c3f65..9a07b7c 100644
--- a/src/math/color.cc
+++ b/src/math/color.cc
@@ -95,4 +95,15 @@ std::ostream &operator<<(std::ostream &os, const Color &c)
return os;
}
+std::istream &operator>>(std::istream & is, Color & color)
+{
+ float r, g, b, a;
+ is >> r;
+ is >> g;
+ is >> b;
+ is >> a;
+ color = Color(r,g,b,a);
+ return (is);
+}
+
} // namespace math
diff --git a/src/math/color.h b/src/math/color.h
index 33efcfc..078faaa 100644
--- a/src/math/color.h
+++ b/src/math/color.h
@@ -45,6 +45,8 @@ private:
std::ostream &operator<<(std::ostream &os, const Color &c);
+std::istream &operator>>(std::istream & is, Color & color);
+
Color operator*(const float scalar, const Color& color);
} // namespace math
diff --git a/src/math/vector3f.cc b/src/math/vector3f.cc
index 277795b..ddf46af 100644
--- a/src/math/vector3f.cc
+++ b/src/math/vector3f.cc
@@ -106,14 +106,6 @@ Vector3f Vector3f::operator+(const Vector3f& other) const
return (r);
}
-float Vector3f::operator*(const Vector3f& other) const
-{
- float r = 0;
- for (int i=0; i < 3; i++)
- r += coord[i] * other.coord[i];
- return (r);
-}
-
bool Vector3f::operator==(const Vector3f& other) const
{
for (int i=0; i < 3; i++)
@@ -144,7 +136,21 @@ void Vector3f::normalize()
(*this) /= this->length();
}
-std::ostream &operator<<(std::ostream & os, const Vector3f & vector)
+Vector3f operator*(float scalar, const Vector3f& vector)
+{
+ return vector * scalar;
+}
+
+Vector3f crossproduct(const Vector3f& first, const Vector3f& second)
+{
+ float x = first[1]*second[2] - first[2]*second[1];
+ float y = first[2]*second[0] - first[0]*second[2];
+ float z = first[0]*second[1] - first[1]*second[0];
+
+ return(Vector3f(x,y,z));
+}
+
+std::ostream &operator<<(std::ostream & os, Vector3f const & vector)
{
os << vector[0] << " " << vector[1] << " " << vector[2];
return os;
@@ -157,9 +163,12 @@ std::istream &operator>>(std::istream & is, Vector3f & vector)
return is;
}
-Vector3f operator*(float scalar, const Vector3f& vector)
+float dotproduct(const Vector3f& first, const Vector3f& second)
{
- return vector * scalar;
+ float r = 0;
+ for (int i=0; i < 3; i++)
+ r += first[i] * second[i];
+ return (r);
}
} // namespace math
diff --git a/src/math/vector3f.h b/src/math/vector3f.h
index cc318b0..d338f50 100644
--- a/src/math/vector3f.h
+++ b/src/math/vector3f.h
@@ -60,7 +60,7 @@ public:
/// perform an element-wise subtraction
Vector3f& operator-=(const Vector3f &other);
- /// perform ann element-wise addition
+ /// perform an element-wise addition
Vector3f& operator+=(const Vector3f &other);
/* -- Mathematical operators -- */
@@ -74,12 +74,9 @@ public:
/// return the element-wise difference between two vectors
Vector3f operator-(const Vector3f &other) const;
- /// return the element-wise sumn of two vectors
+ /// return the element-wise sum of two vectors
Vector3f operator+(const Vector3f &other) const;
- /// return the vector cross-product
- float operator*(const Vector3f &other) const;
-
/// comparison operator
bool operator==(const Vector3f &other) const;
@@ -99,10 +96,6 @@ public:
return coord[index];
}
- float &x;
- float &y;
- float &z;
-
/// Return the cartesian length of this vector
float length() const;
@@ -133,18 +126,28 @@ public:
/// WARNING: vector must not be (0, 0, 0)
static inline Vector3f normalized(const Vector3f& vector) { return (vector / vector.length()); }
+ float &x;
+ float &y;
+ float &z;
+
float coord[3];
};
/// Write a Vector3f to a std::ostream
-std::ostream &operator<<(std::ostream & os, const Vector3f & vector);
+std::ostream &operator<<(std::ostream & os, Vector3f const & vector);
/// Read a Vector3d from a std::istream
-std::istream &operator>>(std::istream & is, Vector3f& vector);
+std::istream &operator>>(std::istream & is, Vector3f & vector);
-/// scalar*Vector3f operators
+/// scalar * Vector3f operators
Vector3f operator*(float scalar, const Vector3f& vector);
+/// vector cross product
+const Vector3f crossproduct(Vector3f const& first, Vector3f const second);
+
+/// vetor dot product
+float dotproduct(const Vector3f& first, const Vector3f& second);
+
} // namespace Math
#endif // __INCLUDED_MATH_VECTOR3F_H__
diff --git a/src/server/server.cc b/src/server/server.cc
index 4c087b8..c07be52 100644
--- a/src/server/server.cc
+++ b/src/server/server.cc
@@ -64,18 +64,24 @@ void Server::init()
void Server::run()
{
- const float server_framerate = 1.0f / 20.0f;
- server::Timer timer;
+ float server_framerate = 1.0f / 20.0f;
+ if (core::Cvar::sv_framerate->value())
+ server_framerate = 1.0f / core::Cvar::sv_framerate->value();
- timer.mark();
+ server::Timer timer;
while(true) {
+ timer.mark();
+ frame(server_framerate);
float elapsed = timer.elapsed();
- frame(elapsed);
+ float sleeptime = server_framerate - elapsed;
+ if (sleeptime <0)
+ sleeptime = 0;
- sys::sleep(server_framerate - elapsed);
- timer.mark();
+ sys::sleep(sleeptime);
+
+
}
}
diff --git a/src/server/timer.cc b/src/server/timer.cc
index 946da2c..56075c7 100644
--- a/src/server/timer.cc
+++ b/src/server/timer.cc
@@ -5,7 +5,9 @@
*/
#include "timer.h"
+
#include <unistd.h>
+#include <iostream>
namespace server {
@@ -26,13 +28,14 @@ void Timer::mark()
float Timer::elapsed()
{
- timeval tick;
+ struct timeval tick;
+ struct timezone tick_tz;
- gettimeofday(&tick, &timer_tz);
+ gettimeofday(&tick, &tick_tz);
// calculate elapsed time in 10^-6 seconds
- long delta = (tick.tv_sec - timer_tick.tv_sec) * 1000000 + (tick.tv_usec - timer_tick.tv_usec);
- return( (float) delta / 1000000);
+ long delta = (tick.tv_sec - timer_tick.tv_sec) * 1000000 + (tick.tv_usec - timer_tick.tv_usec);
+ return( (float) delta / 1000000.0f);
}
}
diff --git a/src/sys/sys.cc b/src/sys/sys.cc
index 508756d..a9958f4 100644
--- a/src/sys/sys.cc
+++ b/src/sys/sys.cc
@@ -67,7 +67,7 @@ unsigned long time()
void sleep(float seconds)
{
#ifndef _WIN32
- ::usleep((useconds_t) seconds * (useconds_t) 1000000.0 );
+ ::usleep((useconds_t) (seconds * 1000000.0) );
#endif
}