diff options
-rw-r--r-- | src/client/console.cc | 5 | ||||
-rw-r--r-- | src/client/draw.cc | 1 | ||||
-rw-r--r-- | src/client/input.cc | 40 | ||||
-rw-r--r-- | src/client/view.cc | 2 | ||||
-rw-r--r-- | src/core/application.cc | 1 | ||||
-rw-r--r-- | src/core/cvar.cc | 1 | ||||
-rw-r--r-- | src/core/cvar.h | 1 | ||||
-rw-r--r-- | src/core/entity.cc | 166 | ||||
-rw-r--r-- | src/core/entity.h | 88 | ||||
-rw-r--r-- | src/core/gameconnection.cc | 29 | ||||
-rw-r--r-- | src/core/gameconnection.h | 1 | ||||
-rw-r--r-- | src/core/gameserver.cc | 53 | ||||
-rw-r--r-- | src/core/gameserver.h | 2 | ||||
-rw-r--r-- | src/core/netconnection.cc | 50 | ||||
-rw-r--r-- | src/core/netserver.cc | 46 | ||||
-rw-r--r-- | src/core/netserver.h | 2 | ||||
-rw-r--r-- | src/core/player.cc | 40 | ||||
-rw-r--r-- | src/core/player.h | 15 | ||||
-rw-r--r-- | src/game/game.cc | 8 | ||||
-rw-r--r-- | src/game/ship.cc | 4 | ||||
-rw-r--r-- | src/game/ship.h | 2 | ||||
-rw-r--r-- | src/math/color.cc | 11 | ||||
-rw-r--r-- | src/math/color.h | 2 | ||||
-rw-r--r-- | src/math/vector3f.cc | 31 | ||||
-rw-r--r-- | src/math/vector3f.h | 27 | ||||
-rw-r--r-- | src/server/server.cc | 18 | ||||
-rw-r--r-- | src/server/timer.cc | 11 | ||||
-rw-r--r-- | src/sys/sys.cc | 2 |
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 } |