buildworldstate cleanups

master
Lee Salzman 2012-10-02 18:23:33 +03:00
parent 86de965bbd
commit 3646a2ca5e
5 changed files with 128 additions and 98 deletions

View File

@ -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 File

@ -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 File

@ -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];
ci.overflow = 0;
ci.wsdata = NULL;
wsmax += ci.position.length();
if(ci.messages.length()) wsmax += 10 + ci.messages.length();
}
if(wsmax <= 0)
{
reliablemessages = false;
return false;
}
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)
{
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;
}
}
addposition(ws, wsbuf, mtu, ci, ci);
loopvj(ci.bots) addposition(ws, wsbuf, mtu, *ci.bots[j], ci);
}
int psize = ws.positions.length(), msize = ws.messages.length();
if(psize)
{
recordpacket(0, ws.positions.getbuf(), psize);
ucharbuf p = ws.positions.reserve(psize);
p.put(ws.positions.getbuf(), psize);
ws.positions.addbuf(p);
}
if(msize)
{
recordpacket(1, ws.messages.getbuf(), msize);
ucharbuf p = ws.messages.reserve(msize);
p.put(ws.messages.getbuf(), msize);
ws.messages.addbuf(p);
}
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 File

@ -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 File

@ -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; }