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-08-04 18:24:36 +0000
committerStijn Buys <ingar@osirion.org>2008-08-04 18:24:36 +0000
commit50a1e2b2fe3c207c7227df4941f2f66990db0c2c (patch)
tree5c4293babed4434d81cf9284f522dd0e74482cf0 /src
parentebd5cd9daabb2d2eb6f5e06f9433cc8e6a4e0f7a (diff)
network protocol version 5, netserver per-client updates, zone change protocol
Diffstat (limited to 'src')
-rw-r--r--src/client/client.cc24
-rw-r--r--src/client/client.h2
-rw-r--r--src/core/application.cc6
-rw-r--r--src/core/application.h3
-rw-r--r--src/core/entity.cc179
-rw-r--r--src/core/entity.h27
-rw-r--r--src/core/gameconnection.cc2
-rw-r--r--src/core/gameserver.cc73
-rw-r--r--src/core/net.h2
-rw-r--r--src/core/netconnection.cc109
-rw-r--r--src/core/netserver.cc209
-rw-r--r--src/core/netserver.h45
-rw-r--r--src/core/player.cc41
-rw-r--r--src/core/player.h7
-rw-r--r--src/core/zone.cc1
15 files changed, 412 insertions, 318 deletions
diff --git a/src/client/client.cc b/src/client/client.cc
index 93d254e..5d060aa 100644
--- a/src/client/client.cc
+++ b/src/client/client.cc
@@ -222,5 +222,29 @@ void Client::notify_message(std::string const & message)
console()->notify(message);
}
+void Client::notify_zoneclear(core::Zone *zone)
+{
+ // FIXME unload zone textures
+ /*
+ if (!zone)
+ return;
+
+ for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content.end(); i++) {
+ core:: Entity *entity = (*it);
+
+ if (entity->type() == core::Entity::Globe) {
+ core::EntityGlobe *globe = static_cast<core::EntityGlobe *>(entity);
+ if (globe->render_texture)
+ render::Textures::unload(render_texture);
+
+ }
+
+ if (zone->sky_texture()) {
+ render::Textures::unload(zone->sky_texture());
+ zone->set_sky_texture(0);
+ }
+ */
+}
+
} // namespace client
diff --git a/src/client/client.h b/src/client/client.h
index 9b60671..664bbb4 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -37,6 +37,8 @@ public:
/// remove sound source notification
virtual void notify_remove_sound(size_t source);
+ /// clear zone notification
+ virtual void notify_zoneclear(core::Zone *zone);
};
diff --git a/src/core/application.cc b/src/core/application.cc
index 5cf4d66..49c61d7 100644
--- a/src/core/application.cc
+++ b/src/core/application.cc
@@ -461,4 +461,10 @@ void Application::notify_message(std::string const & message)
con_print << message << std::endl;
}
+void Application::notify_zoneclear(Zone *zone)
+{
+ // the default implementation does nothing.
+ // The client uses this to clear old zones
+}
+
}
diff --git a/src/core/application.h b/src/core/application.h
index 0e5c9c0..ef89e70 100644
--- a/src/core/application.h
+++ b/src/core/application.h
@@ -67,6 +67,9 @@ public:
/// remove sound source notification
virtual void notify_remove_sound(size_t source);
+ /// zone clear notification
+ virtual void notify_zoneclear(Zone *zone);
+
/*----- static --------------------------------------------------- */
/// a pointer to the current application instance
diff --git a/src/core/entity.cc b/src/core/entity.cc
index 20e1b05..060ceab 100644
--- a/src/core/entity.cc
+++ b/src/core/entity.cc
@@ -77,7 +77,7 @@ void Entity::list()
con_print << entity_registry.size() << " registered entities" << std::endl;
}
-/*----- Entity ----------------------------------------------------- */
+/*----- class Entity ----------------------------------------------- */
Entity::Entity(unsigned int flags) :
entity_location(0.0f, 0.0f, 0.0f),
@@ -109,65 +109,13 @@ Entity::Entity(unsigned int flags) :
Entity::Entity(std::istream & is)
{
+ entity_id = 0;
entity_zone = 0;
-
- // type is already determined
- unsigned int s;
- std::string n;
-
- is >> entity_id;
- is >> entity_moduletypeid;
- is >> entity_flags;
- is >> s;
-
- set_zone(Zone::find(s));
- if (entity_zone && !s) {
- con_warn << "Received entity " << entity_id << " for unknown zone " << s << "!" << std::endl;
- }
-
- is >> entity_location;
- is >> entity_color;
- is >> entity_color_second;
-
- is >> s; // shape
- entity_shape = (Shape) s;
-
- is >> entity_radius;
-
- is >> entity_axis[0];
- is >> entity_axis[1];
- entity_axis[2] = math::crossproduct(entity_axis.forward(), entity_axis.left());
-
- char c;
- // read label
- while ( (is.get(c)) && (c != '"'));
- while ( (is.get(c)) && (c != '"'))
- n += c;
- entity_label = n;
- n.clear();
-
- // read name
- while ( (is.get(c)) && (c != '"'));
- while ( (is.get(c)) && (c != '"'))
- n += c;
- entity_name = n;
- n.clear();
-
- // read model name
- while ( (is.get(c)) && (c != '"'));
- while ( (is.get(c)) && (c != '"'))
- n += c;
- entity_modelname = n;
- entity_model = 0; // this will be resolved later
+ entity_model = 0;
+ entity_clientstate = 0;
entity_created = true;
entity_destroyed = false;
- entity_dirty = false;
-
- // this entity is created clientside
- entity_clientstate = 0;
-
- add(this, entity_id);
}
Entity::~Entity()
@@ -201,11 +149,9 @@ void Entity::set_zone(Zone *zone)
entity_zone->add(this);
}
-void Entity::serialize(std::ostream & os) const
+void Entity::serialize_server_create(std::ostream & os) const
{
- os << type() << " "
- << entity_id << " "
- << entity_moduletypeid << " "
+ os << entity_moduletypeid << " "
<< entity_flags << " "
<< (entity_zone ? entity_zone->id() : 0) << " "
<< entity_location << " "
@@ -220,6 +166,58 @@ void Entity::serialize(std::ostream & os) const
<< "\"" << entity_modelname << "\"";
}
+void Entity::receive_server_create(std::istream &is)
+{
+ unsigned int s;
+ unsigned int zo;
+ std::string n;
+
+ is >> entity_moduletypeid;
+ is >> entity_flags;
+ is >> zo;
+
+ set_zone(Zone::find(zo));
+ if (entity_zone && !zo) {
+ con_warn << "Received entity " << entity_id << " for unknown zone " << zo << "!" << std::endl;
+ }
+
+ is >> entity_location;
+ is >> entity_color;
+ is >> entity_color_second;
+
+ is >> s; // shape
+ entity_shape = (Shape) s;
+
+ is >> entity_radius;
+
+ is >> entity_axis[0];
+ is >> entity_axis[1];
+ entity_axis[2] = math::crossproduct(entity_axis.forward(), entity_axis.left());
+
+ char c;
+ // read label
+ while ( (is.get(c)) && (c != '"'));
+ while ( (is.get(c)) && (c != '"'))
+ n += c;
+ entity_label = n;
+ n.clear();
+
+ // read name
+ while ( (is.get(c)) && (c != '"'));
+ while ( (is.get(c)) && (c != '"'))
+ n += c;
+ entity_name = n;
+ n.clear();
+
+ // read model name
+ while ( (is.get(c)) && (c != '"'));
+ while ( (is.get(c)) && (c != '"'))
+ n += c;
+ entity_modelname = n;
+
+ entity_dirty = false;
+}
+
void Entity::serialize_client_update(std::ostream & os) const
{
}
@@ -241,7 +239,7 @@ void Entity::frame(float seconds)
{
}
-/* ---- EntityDynamic ---------------------------------------------- */
+/* ---- class EntityDynamic ---------------------------------------- */
EntityDynamic::EntityDynamic(unsigned int flags) :
Entity(flags)
@@ -252,7 +250,7 @@ EntityDynamic::EntityDynamic(unsigned int flags) :
EntityDynamic::EntityDynamic(std::istream & is) :
Entity(is)
{
- is >> entity_speed;
+ entity_speed = 0.0f;
}
EntityDynamic::~EntityDynamic()
@@ -272,12 +270,18 @@ void EntityDynamic::frame(float seconds)
entity_dirty = true;
}
-void EntityDynamic::serialize(std::ostream & os) const
+void EntityDynamic::serialize_server_create(std::ostream & os) const
{
- Entity::serialize(os);
+ Entity::serialize_server_create(os);
os << " " << entity_speed;
}
+void EntityDynamic::receive_server_create(std::istream &is)
+{
+ Entity::receive_server_create(is);
+ is >> entity_speed;
+}
+
void EntityDynamic::serialize_client_update(std::ostream & os) const
{
}
@@ -340,8 +344,6 @@ EntityControlable::EntityControlable(Player *owner, unsigned int flags) :
EntityControlable::EntityControlable(std::istream & is) :
EntityDynamic(is)
{
- unsigned int o;
-
entity_thrust = 0;
entity_autolevel = false;
@@ -350,10 +352,6 @@ EntityControlable::EntityControlable(std::istream & is) :
target_pitch = 0.0f;
target_roll = 0.0f;
- is >> entity_thrust;
- is >> o;
-
- // FIXME resolve owner
entity_owner = 0;
}
@@ -364,13 +362,25 @@ EntityControlable::~EntityControlable()
entity_owner->remove_asset(this);
}
-void EntityControlable::serialize(std::ostream & os) const
+void EntityControlable::serialize_server_create(std::ostream & os) const
{
- EntityDynamic::serialize(os);
+ EntityDynamic::serialize_server_create(os);
os << " " << entity_thrust;
os << " " << ( entity_owner ? entity_owner->id() : 0);
}
+void EntityControlable::receive_server_create(std::istream &is)
+{
+ unsigned int o;
+
+ EntityDynamic::receive_server_create(is);
+ is >> entity_thrust;
+ is >> o;
+
+ // FIXME resolve owner
+ entity_owner = 0;
+}
+
void EntityControlable::serialize_client_update(std::ostream & os) const
{
EntityDynamic::serialize_client_update(os);
@@ -483,6 +493,21 @@ EntityGlobe::EntityGlobe(std::istream & is) :
{
render_texture = 0;
entity_shape = Sphere;
+}
+
+EntityGlobe::~EntityGlobe()
+{
+}
+
+void EntityGlobe::serialize_server_create(std::ostream & os) const
+{
+ Entity::serialize_server_create(os);
+ os << " \"" << entity_texture << "\"";
+}
+
+void EntityGlobe::receive_server_create(std::istream &is)
+{
+ Entity::receive_server_create(is);
std::string n;
char c;
@@ -494,15 +519,5 @@ EntityGlobe::EntityGlobe(std::istream & is) :
}
-EntityGlobe::~EntityGlobe()
-{
-}
-
-void EntityGlobe::serialize(std::ostream & os) const
-{
- Entity::serialize(os);
- os << " \"" << entity_texture << "\"";
-}
-
}
diff --git a/src/core/entity.h b/src/core/entity.h
index 2515796..feb99f7 100644
--- a/src/core/entity.h
+++ b/src/core/entity.h
@@ -109,7 +109,7 @@ public:
inline float radius() const { return entity_radius; }
/// serialize the entity to a stream
- virtual void serialize(std::ostream & os) const;
+ virtual void serialize_server_create(std::ostream & os) const;
/// serialize a client-to-server update on a stream
virtual void serialize_client_update(std::ostream & os) const;
@@ -123,6 +123,9 @@ public:
/// receive a client-to-server update from a stream
virtual void receive_client_update(std::istream &is);
+ /// receive a server-to-client create from a stream
+ virtual void receive_server_create(std::istream &is);
+
/// receive a server-to-client update from a stream
virtual void receive_server_update(std::istream &is);
@@ -150,6 +153,9 @@ public:
/// find an entity in the registry
static Entity *find(unsigned int id);
+ /// add an entity to the registry
+ static void add(Entity *ent, unsigned int it);
+
/// erase an entity from the registry and delete it
static void erase(unsigned int entity_id);
@@ -191,9 +197,6 @@ private:
// add an entity to the registry
static void add(Entity *ent);
- // add an entity to the registry
- static void add(Entity *ent, unsigned int it);
-
// the id is set by add()
unsigned int entity_id;
@@ -224,7 +227,7 @@ public:
inline float speed() const { return entity_speed; }
/// serialize the entity to a stream
- virtual void serialize(std::ostream & os) const;
+ virtual void serialize_server_create(std::ostream & os) const;
/// serialize a client-to-server update on a stream
virtual void serialize_client_update(std::ostream & os) const ;
@@ -237,6 +240,9 @@ public:
/// receive a client-to-server update from a stream
virtual void receive_client_update(std::istream &is);
+ /// receive a server-to-client create from a stream
+ virtual void receive_server_create(std::istream &is);
+
/// receive a server-to-client update from a stream
virtual void receive_server_update(std::istream &is);
@@ -278,7 +284,7 @@ public:
inline float thrust() const { return entity_thrust; }
/// serialize the entity to a stream
- virtual void serialize(std::ostream & os) const;
+ virtual void serialize_server_create(std::ostream & os) const;
/// serialize a client-to-server update on a stream
virtual void serialize_client_update(std::ostream & os) const;
@@ -295,6 +301,9 @@ public:
/// receive a client-to-server update from a stream
virtual void receive_client_update(std::istream &is);
+ /// receive a server-to-client create from a stream
+ virtual void receive_server_create(std::istream &is);
+
/// receive a server-to-client update from a stream
virtual void receive_server_update(std::istream &is);
@@ -354,7 +363,11 @@ public:
~EntityGlobe();
- virtual void serialize(std::ostream & os) const;
+ /// serialize the entity to a stream
+ virtual void serialize_server_create(std::ostream & os) const;
+
+ /// receive a server-to-client create from a stream
+ virtual void receive_server_create(std::istream &is);
inline const std::string &texture() const { return entity_texture; }
diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc
index 2085adb..ef998e6 100644
--- a/src/core/gameconnection.cc
+++ b/src/core/gameconnection.cc
@@ -23,7 +23,7 @@ GameConnection::GameConnection(std::string const &connectionstr)
connection_network = 0;
connection_running = false;
connection_frametime = 0;
-
+
unsigned int port = DEFAULTPORT;
std::string host(connectionstr);
size_t found = host.find(':');
diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc
index 53698c2..717ce87 100644
--- a/src/core/gameserver.cc
+++ b/src/core/gameserver.cc
@@ -553,71 +553,28 @@ void GameServer::frame(float seconds)
}
}
- // send updates
- if (server_network) {
- // FIXME prevent connecting clients from receiving update frames
-
- // transmit buffered sends
- server_network->transmit();
-
- // start server frame
- server_network->broadcast_frame(server_time, server_previoustime);
-
- // send changes in the world
- for (Entity::Registry::iterator it=Entity::registry().begin(); it != Entity::registry().end(); ) {
-
- Entity *entity = (*it).second;
-
- if (entity->entity_destroyed) {
-
- if (!entity->entity_created) {
- server_network->broadcast_entity_delete(entity);
- }
-
- delete entity;
- (*it).second = entity = 0;
- Entity::registry().erase(it++);
-
- } else {
- if (entity->entity_created) {
-
- server_network->broadcast_entity_create(entity);
- entity->entity_created = false;
- entity->entity_dirty = false;
- } else if (entity->dirty()) {
-
- server_network->broadcast_entity_update(entity);
- entity->entity_dirty = false;
- }
- ++it;
- }
- }
+ if (server_network) {
- // update player info
- server_network->broadcast_player_update();
+ // send network updates
+ server_network->frame(server_time, server_previoustime);
- // transmit buffered sends
- server_network->transmit();
+ }
- } else {
+ for (Entity::Registry::iterator it=Entity::registry().begin(); it != Entity::registry().end(); ) {
+ Entity *entity = (*it).second;
- // local update stub
- for (Entity::Registry::iterator it=Entity::registry().begin(); it != Entity::registry().end(); ) {
- Entity *entity = (*it).second;
-
- if (entity->entity_destroyed) {
- delete entity;
- (*it).second = entity = 0;
- Entity::registry().erase(it++);
- } else {
- entity->entity_created = false;
- entity->entity_dirty = false;
- ++it;
- }
+ if (entity->entity_destroyed) {
+ delete entity;
+ (*it).second = entity = 0;
+ Entity::registry().erase(it++);
+ } else {
+ entity->entity_created = false;
+ entity->entity_dirty = false;
+ ++it;
}
}
-
+
if (!Cvar::sv_dedicated->value()) {
update_clientstate(0);
}
diff --git a/src/core/net.h b/src/core/net.h
index 04c77a5..6f4a280 100644
--- a/src/core/net.h
+++ b/src/core/net.h
@@ -11,7 +11,7 @@ namespace core
{
/// network protocol version
-const unsigned int PROTOCOLVERSION = 4;
+const unsigned int PROTOCOLVERSION = 5;
/// maximum lenght of a (compressed) network message block
const unsigned int FRAMESIZE = 1152;
diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc
index db8e3a2..3b302dd 100644
--- a/src/core/netconnection.cc
+++ b/src/core/netconnection.cc
@@ -451,7 +451,7 @@ void NetConnection::parse_incoming_message(const std::string & message)
} else if (command == "die") {
unsigned int id;
if (msgstream >> id) {
- //con_debug << "Received die entity id " << id << std::endl;
+ con_debug << "Received die entity id " << id << std::endl;
Entity *e = Entity::find(id);
if (localcontrol() == e)
localplayer()->set_control(0);
@@ -460,47 +460,96 @@ void NetConnection::parse_incoming_message(const std::string & message)
}
} else if (command == "ent") {
- unsigned int type;
- if (msgstream >> type) {
- //con_debug << "Received create entity type " << type << std::endl;
- switch (type)
- {
- case Entity::Default:
- game()->update_entity_clientstate(new Entity(msgstream));
- break;
- case Entity::Dynamic:
- game()->update_entity_clientstate(new EntityDynamic(msgstream));
- break;
- case Entity::Controlable:
- game()->update_entity_clientstate(new EntityControlable(msgstream));
- break;
- case Entity::Globe:
- game()->update_entity_clientstate(new EntityGlobe(msgstream));
- break;
- default:
- con_warn << "Create for unknown entity type " << type << std::endl;
- break;
+
+ unsigned int type = 0;
+ unsigned int id = 0;
+
+ if ((msgstream >> id) && (msgstream >> type)) {
+
+ if (!id) {
+ con_warn << "Received create for NULL entity!" << std::endl;
+ return;
+ }
+ con_debug << "Received create entity id " << id << " type " << type << std::endl;
+
+ Entity *entity = Entity::find(id);
+
+ if (!entity) {
+ switch (type)
+ {
+ case Entity::Default:
+ entity = new Entity(msgstream);
+ break;
+ case Entity::Dynamic:
+ entity = new EntityDynamic(msgstream);
+ break;
+ case Entity::Controlable:
+ entity = new EntityControlable(msgstream);
+ break;
+ case Entity::Globe:
+ entity = new EntityGlobe(msgstream);
+ break;
+ default:
+ con_warn << "Received create for unknown entity type " << type << std::endl;
+ return;
+ break;
+ }
+
+ Entity::add(entity, id);
}
+
+ entity->receive_server_create(msgstream);
+ game()->update_entity_clientstate(entity);
}
+
} else if (command.compare("zone") == 0) {
+
unsigned int id;
std::string label;
if (msgstream >> id) {
- con_debug << "Received create zone " << id << std::endl;
- Zone * zone = Zone::find(id);
+ if (id) {
+ con_debug << "Received zone " << id << std::endl;
+ Zone * zone = Zone::find(id);
- // create the zone if necessary
- if (!zone) {
- zone = new Zone(msgstream);
- Zone::add(zone, id);
- } else {
- zone->receive_server_update(msgstream);
+ // create the zone if necessary
+ if (!zone) {
+ zone = new Zone(msgstream);
+ Zone::add(zone, id);
+ } else {
+ zone->receive_server_update(msgstream);
+ }
}
+
+ // control is set to 0 on zone change and is put back by pif
+ connection()->localplayer()->set_control(0);
}
} else if (command == "pif") {
- //con_debug << "Received update player info" << std::endl;
+ con_debug << "Received update player info" << std::endl;
+
+ Zone *oldzone = connection()->localplayer()->zone();
connection()->localplayer()->receive_server_update(msgstream);
+
+ con_debug << "zone " << ( connection()->localplayer()->zone() ? connection()->localplayer()->zone()->id() : 0) << std::endl;
+
+ if (connection()->localplayer()->zonechange() && oldzone && (oldzone != connection()->localplayer()->zone())) {
+
+ // notify the applciation to clear none-core zone assets (textures etc)
+ application()->notify_zoneclear(oldzone);
+
+ // delete all entities in the old zone
+ for (Entity::Registry::iterator it=Entity::registry().begin(); it != Entity::registry().end(); ) {
+ Entity *entity = (*it).second;
+
+ if ((entity->zone() == oldzone)) {
+ delete entity;
+ Entity::registry().erase(it++);
+ } else {
+ ++it;
+ }
+ }
+ oldzone->content().clear();
+ }
} else if (command == "sup") {
if (connection_state == Connected)
diff --git a/src/core/netserver.cc b/src/core/netserver.cc
index dd5dc38..b674dbd 100644
--- a/src/core/netserver.cc
+++ b/src/core/netserver.cc
@@ -122,6 +122,17 @@ void NetServer::abort() {
netserver_error = true;
}
+// find the client corresponding to a player
+NetClient *NetServer::find_client(Player const *player)
+{
+ for (Clients::iterator it = clients.begin(); it != clients.end(); it++) {
+ if ((*it)->player() == player) {
+ return (*it);
+ }
+ }
+ return 0;
+}
+
// remove disconnected clients
void NetServer::reap()
{
@@ -160,14 +171,6 @@ void NetServer::reap()
}
}
-
-void NetServer::transmit()
-{
- for (Clients::iterator it = clients.begin(); it != clients.end(); it++) {
- (*it)->transmit(fd());
- }
-}
-
void NetServer::receive()
{
if (error())
@@ -286,11 +289,6 @@ void NetServer::client_initialize(NetClient *client) {
send_zone_update(client, (*it).second);
}
- // send entities
- for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) {
- send_entity_create(client, (*it).second);
- }
-
// send connect completed
std::string connect("connect\n");
client->send_raw(connect);
@@ -300,21 +298,96 @@ void NetServer::client_initialize(NetClient *client) {
client->client_state = NetClient::Pending;
}
-// find the client corresponding to a player
-NetClient *NetServer::find_client(Player const *player)
+// send updates to one client
+void NetServer::client_frame(NetClient *client, float timestamp, float previoustimestamp)
{
+ if (client->state() != NetClient::Connected)
+ return;
+
+ Zone *zone = client->player()->zone();
+
+ if (zone) {
+ if (client->player()->zonechange()) {
+
+ // send zone info
+ send_zone_update(client, zone);
+
+ // send entities in zone
+ if (client->player()->zone()) {
+ for (Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) {
+ Entity *entity = (*it);
+
+ if (!entity->entity_destroyed) {
+ send_entity_create(client, entity);
+ }
+ }
+ }
+
+ // the actual zone change is send by the "pif" message
+
+ } else {
+ // send a server frame marker
+ send_frame_marker(client, timestamp, previoustimestamp);
+
+ // send updates for entities in the zone
+ for (Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) {
+ Entity *entity = (*it);
+
+ if (entity->entity_destroyed) {
+ if (!entity->entity_created) {
+ send_entity_delete(client, entity);
+ }
+ } else if (entity->entity_created) {
+ send_entity_create(client, entity);
+ } else if (entity->dirty() && !(entity->flags() & Entity::Static) ) {
+
+ // FIXME only within visual range
+ send_entity_update(client, entity);
+ }
+ }
+ }
+ }
+}
+
+// run a network server frame, send updates to clients
+void NetServer::frame(float timestamp, float previoustimestamp)
+{
+ /* FIXME
+ This code has to be rewritten to send per-player updates.
+ Players should only receive updates from their current zone
+ Fix zonechange events
+
+ Only entities within visual range should send updates (1024 game units?)
+ Fix reliable messages
+ It would be nice if players with the highest ping got their updates first
+ */
+
+ // send updates to each client
for (Clients::iterator it = clients.begin(); it != clients.end(); it++) {
- if ((*it)->player() == player) {
- return (*it);
+ NetClient *client = *it;
+
+ client->transmit(fd());
+
+ if (client->state() == NetClient::Connected)
+ client_frame(client, timestamp, previoustimestamp);
+
+ // update player info always gets through
+ if (client->player()->dirty() || client->player()->zonechange()) {
+
+ send_player_update(client);
+
+ client->player()->player_dirty = false;
+ client->player()->player_zonechange = false;
}
+
+ client->transmit(fd());
}
- return 0;
}
// send outgoing messages to clients
/**
- * The followig messages can be send to a client
+ * The following messages can be send to a client
*
* frame <timestamp> <previous timestamp>
* ent <id> <entity create data>
@@ -361,7 +434,6 @@ void NetServer::send_message(NetClient *client, const char *channel, std::string
client->send_raw(msg);
}
-
// disconnect a client
void NetServer::send_disconnect(NetClient *client)
{
@@ -370,101 +442,64 @@ void NetServer::send_disconnect(NetClient *client)
client->abort();
}
-// broadcast a "frame" message to all clients
-void NetServer::broadcast_frame(float timestamp, float previoustimestamp)
+// send a "frame" message to a client
+void NetServer::send_frame_marker(NetClient *client, float timestamp, float previoustimestamp)
{
std::ostringstream msg("");
msg << "frame " << timestamp << " " << previoustimestamp << "\n";
- for (Clients::iterator it = clients.begin(); it != clients.end(); it++) {
- if ((*it)->state() == NetClient::Connected) {
- (*it)->send_raw(msg.str());
- }
+ if (client->state() == NetClient::Connected) {
+ client->send_raw(msg.str());
}
+
}
-// broadcast a "die" delete entity message to all clients
-void NetServer::broadcast_entity_delete(Entity *entity)
+// send a "ent" create entity message to all clients
+void NetServer::send_entity_create(NetClient *client, Entity *entity)
{
- std::ostringstream msg("");
- msg << "die " << entity->id() << '\n';
-
- for (Clients::iterator it = clients.begin(); it != clients.end(); it++) {
- if ((*it)->state() == NetClient::Connected) {
- (*it)->send_raw(msg.str());
- }
+ if (client->state() == NetClient::Connected) {
+ std::ostringstream msg;
+ msg << "ent " << entity->id() << " " << entity->type() << " ";
+ entity->serialize_server_create(msg);
+ msg << '\n';
+ client->send_raw(msg.str());
}
}
-// broadcast a "ent" create entity message to all clients
-void NetServer::broadcast_entity_create(Entity *entity)
+// send a "die" delete entity message to a client
+void NetServer::send_entity_delete(NetClient *client, Entity *entity)
{
- std::ostringstream msg;
- msg << "ent ";
- entity->serialize(msg);
- msg << '\n';
+ std::ostringstream msg("");
+ msg << "die " << entity->id() << '\n';
- for (Clients::iterator it = clients.begin(); it != clients.end(); it++) {
- if ((*it)->state() == NetClient::Connected) {
- (*it)->send_raw(msg.str());
- }
+ if (client->state() == NetClient::Connected) {
+ client->send_raw(msg.str());
}
}
-// send a "ent" create entity message to all clients
-void NetServer::send_entity_create(NetClient *client, Entity *entity)
+// broadcast a "sup" server update entity message to all clients
+void NetServer::send_entity_update(NetClient *client, Entity *entity)
{
- std::ostringstream msg;
- msg << "ent ";
- entity->serialize(msg);
- msg << '\n';
- client->send_raw(msg.str());
+ if (client->state() == NetClient::Connected) {
+ std::ostringstream msg;
+ msg << "sup " << entity->id() << " ";
+ entity->serialize_server_update(msg);
+ msg << '\n';
+
+ client->send_raw(msg.str());
+ }
}
// send a "zone" update zone message to a client
void NetServer::send_zone_update(NetClient *client, Zone *zone)
{
std::ostringstream msg;
- msg << "zone ";
+ msg << "zone " << zone->id() << " ";
zone->serialize_server_update(msg);
msg << '\n';
client->send_raw(msg.str());
}
-// broadcast a "sup" server update entity message to all clients
-void NetServer::broadcast_entity_update(Entity *entity)
-{
- std::ostringstream msg;
- msg << "sup " << entity->id() << " ";
- entity->serialize_server_update(msg);
- msg << '\n';
-
- for (Clients::iterator it = clients.begin(); it != clients.end(); it++) {
- if ((*it)->state() == NetClient::Connected) {
- (*it)->send_raw(msg.str());
- }
- }
-}
-
-// broadcast a "pif" update player information if necessary
-void NetServer::broadcast_player_update()
-{
- for (Clients::iterator it = clients.begin(); it != clients.end(); it++) {
- NetClient *client = *it;
-
- if (client->player()->dirty()) {
- // send player data
- std::ostringstream msg;
- msg << "pif ";
- client->player()->serialize_server_update(msg);
- msg << '\n';
- client->send_raw(msg.str());
-
- client->player()->player_dirty = false;
- }
- }
-}
-
// send a "pif" update player information to a single player
void NetServer::send_player_update(NetClient *client)
{
diff --git a/src/core/netserver.h b/src/core/netserver.h
index 2340a5d..4dcae69 100644
--- a/src/core/netserver.h
+++ b/src/core/netserver.h
@@ -48,49 +48,43 @@ public:
/*----- mutators -------------------------------------------------- */
+ /// run a network server frame
+ void frame(float timestamp, float previoustimestamp);
+
/// receive data from clients
void receive();
- /// transmit data to clients
- void transmit();
-
/// broadcast a message
void broadcast_message(const char *channel, std::string const & message, Player *ignore_player=0);
- /// send a message to a single client
+ /// send a message to a client
void send_message(NetClient *client, const char *channel, std::string const & message);
- /// disconnect a single client
+ /// disconnect a client
void send_disconnect(NetClient *client);
- /// broadcast a server frame message
- void broadcast_frame(float timestamp, float previoustimestamp);
-
- /// broadcast a delete entity event
- void broadcast_entity_delete(Entity *entity);
+ /// find the client corresponding to a player
+ NetClient *find_client(Player const *player);
- /// broadcast a create entity event
- void broadcast_entity_create(Entity *entity);
+protected:
+ /// send a server frame marker
+ void send_frame_marker(NetClient *client, float timestamp, float previoustimestamp);
- /// send a create entity event to a single player
+ /// send a create entity event
void send_entity_create(NetClient *client, Entity *entity);
-
- /// send a zone update event to a single player
- void send_zone_update(NetClient *client, Zone *zone);
+
+ /// broadcast a delete entity event
+ void send_entity_delete(NetClient *client, Entity *entity);
/// broadcast a update entity event
- void broadcast_entity_update(Entity *entity);
+ void send_entity_update(NetClient *client, Entity *entity);
- /// broadcast updated player information, if necessary
- void broadcast_player_update();
+ /// send a zone update event
+ void send_zone_update(NetClient *client, Zone *zone);
- /// send an update player information message to a single client
+ /// send an update player information message
void send_player_update(NetClient *client);
- /// find the client corresponding to a player
- NetClient *find_client(Player const *player);
-
-protected:
/// set the error state
void abort();
@@ -106,6 +100,9 @@ protected:
/// parse incoming client messages
void parse_incoming_message(NetClient *client, const std::string & message);
+ /// send a server frame to a single client
+ void client_frame(NetClient *client, float timestamp, float previoustimestamp);
+
private:
bool netserver_error;
int netserver_fd;
diff --git a/src/core/player.cc b/src/core/player.cc
index ba5ffbe..fafb052 100644
--- a/src/core/player.cc
+++ b/src/core/player.cc
@@ -29,6 +29,7 @@ void Player::clear()
player_zone = 0;
player_name.clear();
player_dirty = false;
+ player_zonechange = false;
player_rcon = false;
player_mute = false;
@@ -40,16 +41,17 @@ void Player::set_control(EntityControlable *entitycontrolable)
player_control = entitycontrolable;
if (entitycontrolable) {
- player_zone = entitycontrolable->zone();
+ set_zone(entitycontrolable->zone());
}
-
player_dirty = true;
}
void Player::set_zone(Zone *zone)
{
- player_zone = zone;
- player_dirty = true;
+ if (zone != player_zone) {
+ player_zone = zone;
+ player_zonechange = true;
+ }
}
void Player::update_info()
@@ -99,41 +101,26 @@ void Player::receive_client_update(std::istream &is)
void Player::serialize_server_update(std::ostream & os) const
{
- unsigned int zone;
- if (player_zone)
- zone = player_zone->id();
- else
- zone = 0;
-
- unsigned int co;
- if (player_control)
- co = player_control->id();
- else
- co = 0;
-
-
- os << player_id << " " << zone << " " << co << " " << player_color << " \"" << player_name << "\"";
+ unsigned int zo = (zone() ? zone()->id() : 0);
+ unsigned int co = (player_control ? player_control->id() : 0);
+
+ os << player_id << " " << zo << " " << co << " " << player_color << " \"" << player_name << "\"";
}
void Player::receive_server_update(std::istream &is)
{
is >> player_id;
- unsigned int zone = 0;
- is >> zone;
- if (zone) {
- player_zone = Zone::find(zone);
- } else {
- player_zone = 0;
- }
+ unsigned int zo = 0;
+ is >> zo;
+ set_zone(Zone::find(zo));
unsigned int co = 0;
is >> co;
if (co) {
Entity *e = Entity::find(co);
if (e && e->type() == Entity::Controlable) {
- player_control = (EntityControlable *) e;
- player_zone = player_control->zone();
+ player_control = static_cast<EntityControlable *>(e);
} else {
player_control = 0;
con_warn << "control set to unknown entity " << co << "\n";
diff --git a/src/core/player.h b/src/core/player.h
index cdcdbd1..7bf533c 100644
--- a/src/core/player.h
+++ b/src/core/player.h
@@ -56,6 +56,8 @@ public:
/// set the zone the player is currently in
void set_zone(Zone *zone);
+ inline bool zonechange() const { return player_zonechange; }
+
/// player primary color
inline math::Color const & color() const { return player_color; }
@@ -102,6 +104,9 @@ public:
/// dirty state
bool player_dirty;
+ /// player has changed zone
+ bool player_zonechange;
+
/// indicates rcon access
bool player_rcon;
@@ -128,6 +133,8 @@ private:
// the zone the player is currently in
Zone *player_zone;
+
+
};
}
diff --git a/src/core/zone.cc b/src/core/zone.cc
index 584f75d..a81736d 100644
--- a/src/core/zone.cc
+++ b/src/core/zone.cc
@@ -182,7 +182,6 @@ Entity *Zone::find_entity(unsigned int id)
void Zone::serialize_server_update(std::ostream & os) const
{
- os << zone_id << " ";
os << zone_label << " ";
os << "\"" << zone_name << "\" ";
os << "\"" << zone_sky << "\" ";