Permalink
Browse files

buildworldstate cleanups

  • Loading branch information...
1 parent 86de965 commit 3646a2ca5e26d3573ebeda1b1cbf2e687ac13b87 @lsalzman committed Oct 2, 2012
Showing with 124 additions and 94 deletions.
  1. +1 −0 src/engine/server.cpp
  2. +3 −2 src/fpsgame/aiman.h
  3. +110 −92 src/fpsgame/server.cpp
  4. +1 −0 src/shared/iengine.h
  5. +9 −0 src/shared/tools.h
View
@@ -296,6 +296,7 @@ void cleanupserver()
void process(ENetPacket *packet, int sender, int chan);
//void disconnect_client(int n, int reason);
+int getservermtu() { return serverhost ? serverhost->mtu : -1; }
void *getclientinfo(int i) { return !clients.inrange(i) || clients[i]->type==ST_EMPTY ? NULL : clients[i]->info; }
ENetPeer *getclientpeer(int i) { return clients.inrange(i) && clients[i]->type==ST_TCPIP ? clients[i]->peer : NULL; }
int getnumclients() { return clients.length(); }
View
@@ -103,6 +103,7 @@ namespace aiman
clientinfo *owner = findaiclient();
ci->ownernum = owner ? owner->clientnum : -1;
+ if(owner) owner->bots.add(ci);
ci->aireinit = 2;
dorefresh = true;
return true;
@@ -169,12 +170,12 @@ namespace aiman
}
}
- void shiftai(clientinfo *ci, clientinfo *owner)
+ void shiftai(clientinfo *ci, clientinfo *owner = NULL)
{
clientinfo *prevowner = (clientinfo *)getclientinfo(ci->ownernum);
if(prevowner) prevowner->bots.removeobj(ci);
if(!owner) { ci->aireinit = 0; ci->ownernum = -1; }
- else { ci->aireinit = 2; ci->ownernum = owner->clientnum; owner->bots.add(ci); }
+ else if(ci->clientnum != owner->clientnum) { ci->aireinit = 2; ci->ownernum = owner->clientnum; owner->bots.add(ci); }
dorefresh = true;
}
View
@@ -219,7 +219,8 @@ namespace server
gamestate state;
vector<gameevent *> events;
vector<uchar> position, messages;
- int posoff, poslen, msgoff, msglen;
+ uchar *wsdata;
+ int wslen;
vector<clientinfo *> bots;
int ping, aireinit;
string clientmap;
@@ -347,12 +348,6 @@ namespace server
}
};
- struct worldstate
- {
- int uses;
- vector<uchar> positions, messages;
- };
-
struct ban
{
int time, expire;
@@ -405,8 +400,6 @@ namespace server
}
vector<clientinfo *> connects, clients, bots;
- vector<worldstate *> worldstates;
- bool reliablemessages = false;
void kickclients(uint ip)
{
@@ -1351,17 +1344,31 @@ namespace server
return type;
}
+ struct worldstate
+ {
+ int uses, len;
+ uchar *data;
+
+ worldstate() : uses(0), len(0), data(NULL) {}
+
+ void setup(int n) { len = n; data = new uchar[n]; }
+ void cleanup() { DELETEA(data); len = 0; }
+ bool contains(const uchar *p) const { return p >= data && p < &data[len]; }
+ };
+ vector<worldstate> worldstates;
+ bool reliablemessages = false;
+
void cleanworldstate(ENetPacket *packet)
{
loopv(worldstates)
{
- worldstate *ws = worldstates[i];
- if(ws->positions.inbuf(packet->data) || ws->messages.inbuf(packet->data)) ws->uses--;
- else continue;
- if(!ws->uses)
+ worldstate &ws = worldstates[i];
+ if(!ws.contains(packet->data)) continue;
+ ws.uses--;
+ if(ws.uses <= 0)
{
- delete ws;
- worldstates.remove(i);
+ ws.cleanup();
+ worldstates.removeunordered(i);
}
break;
}
@@ -1376,106 +1383,117 @@ namespace server
sendpacket(-1, 0, p.finalize(), ci.ownernum);
}
- void addclientstate(worldstate &ws, clientinfo &ci)
+ static void sendpositions(worldstate &ws, ucharbuf &wsbuf)
{
- if(ci.position.empty()) ci.posoff = -1;
- else
+ if(wsbuf.empty()) return;
+ int wslen = wsbuf.length();
+ recordpacket(0, wsbuf.buf, wslen);
+ wsbuf.put(wsbuf.buf, wslen);
+ loopv(clients)
{
- ci.posoff = ws.positions.length();
- ws.positions.put(ci.position.getbuf(), ci.position.length());
- ci.poslen = ws.positions.length() - ci.posoff;
- ci.position.setsize(0);
+ clientinfo &ci = *clients[i];
+ uchar *data = wsbuf.buf;
+ int size = wslen;
+ if(ci.wsdata >= wsbuf.buf) { data = ci.wsdata + ci.wslen; size -= ci.wslen; }
+ if(size <= 0) continue;
+ ENetPacket *packet = enet_packet_create(data, size, ENET_PACKET_FLAG_NO_ALLOCATE);
+ sendpacket(ci.clientnum, 0, packet);
+ if(packet->referenceCount) { ws.uses++; packet->freeCallback = cleanworldstate; }
+ else enet_packet_destroy(packet);
}
- if(ci.messages.empty()) ci.msgoff = -1;
- else
+ wsbuf.offset(wsbuf.length());
+ }
+
+ static inline void addposition(worldstate &ws, ucharbuf &wsbuf, int mtu, clientinfo &bi, clientinfo &ci)
+ {
+ if(bi.position.empty()) return;
+ if(wsbuf.length() + bi.position.length() > mtu) sendpositions(ws, wsbuf);
+ int offset = wsbuf.length();
+ wsbuf.put(bi.position.getbuf(), bi.position.length());
+ bi.position.setsize(0);
+ int len = wsbuf.length() - offset;
+ if(ci.wsdata < wsbuf.buf) { ci.wsdata = &wsbuf.buf[offset]; ci.wslen = len; }
+ else ci.wslen += len;
+ }
+
+ static void sendmessages(worldstate &ws, ucharbuf &wsbuf)
+ {
+ if(wsbuf.empty()) return;
+ int wslen = wsbuf.length();
+ recordpacket(1, wsbuf.buf, wslen);
+ wsbuf.put(wsbuf.buf, wslen);
+ loopv(clients)
{
- ci.msgoff = ws.messages.length();
- putint(ws.messages, N_CLIENT);
- putint(ws.messages, ci.clientnum);
- putuint(ws.messages, ci.messages.length());
- ws.messages.put(ci.messages.getbuf(), ci.messages.length());
- ci.msglen = ws.messages.length() - ci.msgoff;
- ci.messages.setsize(0);
+ clientinfo &ci = *clients[i];
+ uchar *data = wsbuf.buf;
+ int size = wslen;
+ if(ci.wsdata >= wsbuf.buf) { data = ci.wsdata + ci.wslen; size -= ci.wslen; }
+ if(size <= 0) continue;
+ ENetPacket *packet = enet_packet_create(data, size, (reliablemessages ? ENET_PACKET_FLAG_RELIABLE : 0) | ENET_PACKET_FLAG_NO_ALLOCATE);
+ sendpacket(ci.clientnum, 1, packet);
+ if(packet->referenceCount) { ws.uses++; packet->freeCallback = cleanworldstate; }
+ else enet_packet_destroy(packet);
}
+ wsbuf.offset(wsbuf.length());
+ }
+
+ static inline void addmessages(worldstate &ws, ucharbuf &wsbuf, int mtu, clientinfo &bi, clientinfo &ci)
+ {
+ if(bi.messages.empty()) return;
+ if(wsbuf.length() + 10 + bi.messages.length() > mtu) sendmessages(ws, wsbuf);
+ int offset = wsbuf.length();
+ putint(wsbuf, N_CLIENT);
+ putint(wsbuf, bi.clientnum);
+ putuint(wsbuf, bi.messages.length());
+ wsbuf.put(bi.messages.getbuf(), bi.messages.length());
+ bi.messages.setsize(0);
+ int len = wsbuf.length() - offset;
+ if(ci.wsdata < wsbuf.buf) { ci.wsdata = &wsbuf.buf[offset]; ci.wslen = len; }
+ else ci.wslen += len;
}
bool buildworldstate()
{
- worldstate &ws = *new worldstate;
+ int wsmax = 0;
loopv(clients)
{
clientinfo &ci = *clients[i];
- if(ci.state.aitype != AI_NONE) continue;
ci.overflow = 0;
- addclientstate(ws, ci);
- loopv(ci.bots)
- {
- clientinfo &bi = *ci.bots[i];
- addclientstate(ws, bi);
- if(bi.posoff >= 0)
- {
- if(ci.posoff < 0) { ci.posoff = bi.posoff; ci.poslen = bi.poslen; }
- else ci.poslen += bi.poslen;
- }
- if(bi.msgoff >= 0)
- {
- if(ci.msgoff < 0) { ci.msgoff = bi.msgoff; ci.msglen = bi.msglen; }
- else ci.msglen += bi.msglen;
- }
- }
+ ci.wsdata = NULL;
+ wsmax += ci.position.length();
+ if(ci.messages.length()) wsmax += 10 + ci.messages.length();
}
- int psize = ws.positions.length(), msize = ws.messages.length();
- if(psize)
+ if(wsmax <= 0)
{
- recordpacket(0, ws.positions.getbuf(), psize);
- ucharbuf p = ws.positions.reserve(psize);
- p.put(ws.positions.getbuf(), psize);
- ws.positions.addbuf(p);
+ reliablemessages = false;
+ return false;
}
- if(msize)
+ worldstate &ws = worldstates.add();
+ ws.setup(2*wsmax);
+ int mtu = getservermtu() - 100;
+ if(mtu <= 0) mtu = ws.len;
+ ucharbuf wsbuf(ws.data, ws.len);
+ loopv(clients)
{
- recordpacket(1, ws.messages.getbuf(), msize);
- ucharbuf p = ws.messages.reserve(msize);
- p.put(ws.messages.getbuf(), msize);
- ws.messages.addbuf(p);
+ clientinfo &ci = *clients[i];
+ if(ci.state.aitype != AI_NONE) continue;
+ addposition(ws, wsbuf, mtu, ci, ci);
+ loopvj(ci.bots) addposition(ws, wsbuf, mtu, *ci.bots[j], ci);
}
- ws.uses = 0;
- if(psize || msize) loopv(clients)
+ sendpositions(ws, wsbuf);
+ loopv(clients)
{
clientinfo &ci = *clients[i];
if(ci.state.aitype != AI_NONE) continue;
- ENetPacket *packet;
- if(psize && (ci.posoff<0 || psize-ci.poslen>0))
- {
- packet = enet_packet_create(&ws.positions[ci.posoff<0 ? 0 : ci.posoff+ci.poslen],
- ci.posoff<0 ? psize : psize-ci.poslen,
- ENET_PACKET_FLAG_NO_ALLOCATE);
- sendpacket(ci.clientnum, 0, packet);
- if(!packet->referenceCount) enet_packet_destroy(packet);
- else { ++ws.uses; packet->freeCallback = cleanworldstate; }
- }
-
- if(msize && (ci.msgoff<0 || msize-ci.msglen>0))
- {
- packet = enet_packet_create(&ws.messages[ci.msgoff<0 ? 0 : ci.msgoff+ci.msglen],
- ci.msgoff<0 ? msize : msize-ci.msglen,
- (reliablemessages ? ENET_PACKET_FLAG_RELIABLE : 0) | ENET_PACKET_FLAG_NO_ALLOCATE);
- sendpacket(ci.clientnum, 1, packet);
- if(!packet->referenceCount) enet_packet_destroy(packet);
- else { ++ws.uses; packet->freeCallback = cleanworldstate; }
- }
+ addmessages(ws, wsbuf, mtu, ci, ci);
+ loopvj(ci.bots) addmessages(ws, wsbuf, mtu, *ci.bots[j], ci);
}
+ sendmessages(ws, wsbuf);
reliablemessages = false;
- if(!ws.uses)
- {
- delete &ws;
- return false;
- }
- else
- {
- worldstates.add(&ws);
- return true;
- }
+ if(ws.uses) return true;
+ ws.cleanup();
+ worldstates.drop();
+ return false;
}
bool sendpackets(bool force)
View
@@ -394,6 +394,7 @@ extern ENetPacket *sendf(int cn, int chan, const char *format, ...);
extern ENetPacket *sendfile(int cn, int chan, stream *file, const char *format = "", ...);
extern void sendpacket(int cn, int chan, ENetPacket *packet, int exclude = -1);
extern void flushserver(bool force);
+extern int getservermtu();
extern int getnumclients();
extern uint getclientip(int n);
extern void putint(ucharbuf &p, int n);
View
@@ -218,6 +218,15 @@ struct databuf
return read;
}
+ void offset(int n)
+ {
+ n = min(n, maxlen);
+ buf += n;
+ maxlen -= n;
+ len = max(len-n, 0);
+ }
+
+ bool empty() const { return len==0; }
int length() const { return len; }
int remaining() const { return maxlen-len; }
bool overread() const { return (flags&OVERREAD)!=0; }

0 comments on commit 3646a2c

Please sign in to comment.