Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2008-08-04 18:24:36 +0000
committerStijn Buys <ingar@osirion.org>2008-08-04 18:24:36 +0000
commit50a1e2b2fe3c207c7227df4941f2f66990db0c2c (patch)
tree5c4293babed4434d81cf9284f522dd0e74482cf0 /src/core/netserver.cc
parentebd5cd9daabb2d2eb6f5e06f9433cc8e6a4e0f7a (diff)
network protocol version 5, netserver per-client updates, zone change protocol
Diffstat (limited to 'src/core/netserver.cc')
-rw-r--r--src/core/netserver.cc209
1 files changed, 122 insertions, 87 deletions
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)
{