buildworldstate cleanups
parent
86de965bbd
commit
3646a2ca5e
|
@ -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(); }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
|
Loading…
Reference in New Issue