forked from OctaForge/OctaCore
generally drop game/server.cc
parent
376f3f7693
commit
c935752a6b
|
@ -22,17 +22,6 @@ ICOMMAND(disconnect, "", (), trydisconnect());
|
||||||
ICOMMAND(localconnect, "", (), { if(!isconnected()) localconnect(); });
|
ICOMMAND(localconnect, "", (), { if(!isconnected()) localconnect(); });
|
||||||
ICOMMAND(localdisconnect, "", (), { if(haslocalclients()) localdisconnect(); });
|
ICOMMAND(localdisconnect, "", (), { if(haslocalclients()) localdisconnect(); });
|
||||||
|
|
||||||
void localservertoclient(int chan, ENetPacket *packet) // processes any updates from the server
|
|
||||||
{
|
|
||||||
packetbuf p(packet);
|
|
||||||
game::parsepacketclient(chan, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendclientpacket(ENetPacket *packet, int chan)
|
|
||||||
{
|
|
||||||
localclienttoserver(chan, packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clientkeepalive() {}
|
void clientkeepalive() {}
|
||||||
|
|
||||||
void gets2c() {}
|
void gets2c() {}
|
||||||
|
|
|
@ -1183,7 +1183,6 @@ int main(int argc, char **argv)
|
||||||
checksleep(lastmillis);
|
checksleep(lastmillis);
|
||||||
|
|
||||||
server::serverupdate();
|
server::serverupdate();
|
||||||
server::sendpackets();
|
|
||||||
|
|
||||||
if(frames) updatefpshistory(elapsedtime);
|
if(frames) updatefpshistory(elapsedtime);
|
||||||
frames++;
|
frames++;
|
||||||
|
|
|
@ -100,7 +100,6 @@ client &addclient(int type)
|
||||||
c->num = clients.length();
|
c->num = clients.length();
|
||||||
clients.add(c);
|
clients.add(c);
|
||||||
}
|
}
|
||||||
c->info = server::newclientinfo();
|
|
||||||
c->type = type;
|
c->type = type;
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
|
@ -118,84 +117,12 @@ void delclient(client *c)
|
||||||
case ST_EMPTY: return;
|
case ST_EMPTY: return;
|
||||||
}
|
}
|
||||||
c->type = ST_EMPTY;
|
c->type = ST_EMPTY;
|
||||||
if(c->info)
|
|
||||||
{
|
|
||||||
server::deleteclientinfo(c->info);
|
|
||||||
c->info = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanupserver()
|
void cleanupserver()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void process(ENetPacket *packet, int sender, int chan);
|
|
||||||
|
|
||||||
void *getclientinfo(int i) { return !clients.inrange(i) || clients[i]->type==ST_EMPTY ? NULL : clients[i]->info; }
|
|
||||||
|
|
||||||
void sendpacket(int n, int chan, ENetPacket *packet, int exclude)
|
|
||||||
{
|
|
||||||
if(n<0)
|
|
||||||
{
|
|
||||||
loopv(clients) if(i!=exclude && server::allowbroadcast(i)) sendpacket(i, chan, packet);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch(clients[n]->type)
|
|
||||||
{
|
|
||||||
case ST_LOCAL:
|
|
||||||
localservertoclient(chan, packet);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ENetPacket *sendf(int cn, int chan, const char *format, ...)
|
|
||||||
{
|
|
||||||
int exclude = -1;
|
|
||||||
bool reliable = false;
|
|
||||||
if(*format=='r') { reliable = true; ++format; }
|
|
||||||
packetbuf p(MAXTRANS, reliable ? ENET_PACKET_FLAG_RELIABLE : 0);
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
while(*format) switch(*format++)
|
|
||||||
{
|
|
||||||
case 'x':
|
|
||||||
exclude = va_arg(args, int);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'v':
|
|
||||||
{
|
|
||||||
int n = va_arg(args, int);
|
|
||||||
int *v = va_arg(args, int *);
|
|
||||||
loopi(n) putint(p, v[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'i':
|
|
||||||
{
|
|
||||||
int n = isdigit(*format) ? *format++-'0' : 1;
|
|
||||||
loopi(n) putint(p, va_arg(args, int));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'f':
|
|
||||||
{
|
|
||||||
int n = isdigit(*format) ? *format++-'0' : 1;
|
|
||||||
loopi(n) putfloat(p, (float)va_arg(args, double));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 's': sendstring(va_arg(args, const char *), p); break;
|
|
||||||
case 'm':
|
|
||||||
{
|
|
||||||
int n = va_arg(args, int);
|
|
||||||
p.put(va_arg(args, uchar *), n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
va_end(args);
|
|
||||||
ENetPacket *packet = p.finalize();
|
|
||||||
sendpacket(cn, chan, packet, exclude);
|
|
||||||
return packet->referenceCount > 0 ? packet : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *disconnectreason(int reason)
|
const char *disconnectreason(int reason)
|
||||||
{
|
{
|
||||||
switch(reason)
|
switch(reason)
|
||||||
|
@ -222,20 +149,6 @@ void kicknonlocalclients(int reason)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void process(ENetPacket *packet, int sender, int chan) // sender may be -1
|
|
||||||
{
|
|
||||||
packetbuf p(packet);
|
|
||||||
server::parsepacket(sender, chan, p);
|
|
||||||
if(p.overread()) { disconnect_client(sender, DISC_EOP); return; }
|
|
||||||
}
|
|
||||||
|
|
||||||
void localclienttoserver(int chan, ENetPacket *packet)
|
|
||||||
{
|
|
||||||
client *c = NULL;
|
|
||||||
loopv(clients) if(clients[i]->type==ST_LOCAL) { c = clients[i]; break; }
|
|
||||||
if(c) process(packet, c->num, chan);
|
|
||||||
}
|
|
||||||
|
|
||||||
void updatetime()
|
void updatetime()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -260,7 +173,6 @@ void localconnect()
|
||||||
client &c = addclient(ST_LOCAL);
|
client &c = addclient(ST_LOCAL);
|
||||||
copystring(c.hostname, "local");
|
copystring(c.hostname, "local");
|
||||||
game::gameconnect(false);
|
game::gameconnect(false);
|
||||||
server::localconnect(c.num);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void logoutfv(const char *fmt, va_list args)
|
void logoutfv(const char *fmt, va_list args)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "game.hh"
|
#include "game.hh"
|
||||||
|
|
||||||
|
extern void clearmainmenu();
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
VARP(minradarscale, 0, 384, 10000);
|
VARP(minradarscale, 0, 384, 10000);
|
||||||
|
@ -75,8 +77,10 @@ namespace game
|
||||||
|
|
||||||
void changemap(const char *name, int mode) // request map change, server may ignore
|
void changemap(const char *name, int mode) // request map change, server may ignore
|
||||||
{
|
{
|
||||||
server::forcemap(name, mode);
|
changemapserv(name, 0);
|
||||||
if(!isconnected()) localconnect();
|
localconnect();
|
||||||
|
clearmainmenu(); /* XXX hack */
|
||||||
|
connected = true;
|
||||||
}
|
}
|
||||||
void changemap(const char *name)
|
void changemap(const char *name)
|
||||||
{
|
{
|
||||||
|
@ -91,7 +95,10 @@ namespace game
|
||||||
|
|
||||||
void newmap(int size)
|
void newmap(int size)
|
||||||
{
|
{
|
||||||
addmsg(N_NEWMAP, "ri", size);
|
if(size>=0) emptymap(size, true, NULL);
|
||||||
|
else enlargemap(true);
|
||||||
|
localconnect();
|
||||||
|
connected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void edittrigger(const selinfo &sel, int op, int arg1, int arg2, int arg3, const VSlot *vs)
|
void edittrigger(const selinfo &sel, int op, int arg1, int arg2, int arg3, const VSlot *vs)
|
||||||
|
@ -107,63 +114,6 @@ namespace game
|
||||||
|
|
||||||
int scaletime(int t) { return t*100; }
|
int scaletime(int t) { return t*100; }
|
||||||
|
|
||||||
// collect c2s messages conveniently
|
|
||||||
vector<uchar> messages;
|
|
||||||
int messagecn = -1, messagereliable = false;
|
|
||||||
|
|
||||||
bool addmsg(int type, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
if(!connected) return false;
|
|
||||||
static uchar buf[MAXTRANS];
|
|
||||||
ucharbuf p(buf, sizeof(buf));
|
|
||||||
putint(p, type);
|
|
||||||
int numi = 1, numf = 0, nums = 0;
|
|
||||||
bool reliable = false;
|
|
||||||
if(fmt)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
while(*fmt) switch(*fmt++)
|
|
||||||
{
|
|
||||||
case 'r': reliable = true; break;
|
|
||||||
case 'c':
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'v':
|
|
||||||
{
|
|
||||||
int n = va_arg(args, int);
|
|
||||||
int *v = va_arg(args, int *);
|
|
||||||
loopi(n) putint(p, v[i]);
|
|
||||||
numi += n;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'i':
|
|
||||||
{
|
|
||||||
int n = isdigit(*fmt) ? *fmt++-'0' : 1;
|
|
||||||
loopi(n) putint(p, va_arg(args, int));
|
|
||||||
numi += n;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'f':
|
|
||||||
{
|
|
||||||
int n = isdigit(*fmt) ? *fmt++-'0' : 1;
|
|
||||||
loopi(n) putfloat(p, (float)va_arg(args, double));
|
|
||||||
numf += n;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 's': sendstring(va_arg(args, const char *), p); nums++; break;
|
|
||||||
}
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
int num = nums || numf ? 0 : numi, msgsize = server::msgsizelookup(type);
|
|
||||||
if(msgsize && num!=msgsize) { fatal("inconsistent msg size for %d (%d != %d)", type, num, msgsize); }
|
|
||||||
if(reliable) messagereliable = true;
|
|
||||||
messages.put(buf, p.length());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void connectfail()
|
void connectfail()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -179,11 +129,7 @@ namespace game
|
||||||
player1->clientnum = -1;
|
player1->clientnum = -1;
|
||||||
if(editmode) toggleedit();
|
if(editmode) toggleedit();
|
||||||
sessionid = 0;
|
sessionid = 0;
|
||||||
messages.setsize(0);
|
|
||||||
messagereliable = false;
|
|
||||||
messagecn = -1;
|
|
||||||
player1->respawn();
|
player1->respawn();
|
||||||
player1->lifesequence = 0;
|
|
||||||
player1->state = CS_ALIVE;
|
player1->state = CS_ALIVE;
|
||||||
if(cleanup)
|
if(cleanup)
|
||||||
{
|
{
|
||||||
|
@ -192,112 +138,5 @@ namespace game
|
||||||
}
|
}
|
||||||
|
|
||||||
void toserver(char *text) { conoutf(CON_CHAT, "%s", text); }
|
void toserver(char *text) { conoutf(CON_CHAT, "%s", text); }
|
||||||
|
|
||||||
void sendmessages()
|
|
||||||
{
|
|
||||||
packetbuf p(MAXTRANS);
|
|
||||||
if(messages.length())
|
|
||||||
{
|
|
||||||
p.put(messages.getbuf(), messages.length());
|
|
||||||
messages.setsize(0);
|
|
||||||
if(messagereliable) p.reliable();
|
|
||||||
messagereliable = false;
|
|
||||||
messagecn = -1;
|
|
||||||
}
|
|
||||||
sendclientpacket(p.finalize(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void c2sinfo(bool force) // send update to the server
|
|
||||||
{
|
|
||||||
static int lastupdate = -1000;
|
|
||||||
if(totalmillis - lastupdate < 40 && !force) return; // don't update faster than 30fps
|
|
||||||
lastupdate = totalmillis;
|
|
||||||
sendmessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendintro()
|
|
||||||
{
|
|
||||||
packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE);
|
|
||||||
putint(p, N_CONNECT);
|
|
||||||
sendstring(player1->name, p);
|
|
||||||
sendclientpacket(p.finalize(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void parsestate(gameent *d, ucharbuf &p, bool resume = false)
|
|
||||||
{
|
|
||||||
if(!d) { static gameent dummy; d = &dummy; }
|
|
||||||
if(resume)
|
|
||||||
{
|
|
||||||
if(d==player1) getint(p);
|
|
||||||
else d->state = getint(p);
|
|
||||||
}
|
|
||||||
d->lifesequence = getint(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void parsemessages(int cn, gameent *d, ucharbuf &p)
|
|
||||||
{
|
|
||||||
static char text[MAXTRANS];
|
|
||||||
int type;
|
|
||||||
|
|
||||||
while(p.remaining()) switch((type = getint(p)))
|
|
||||||
{
|
|
||||||
case N_SERVINFO: // welcome messsage from the server
|
|
||||||
{
|
|
||||||
int mycn = getint(p);
|
|
||||||
sessionid = getint(p);
|
|
||||||
player1->clientnum = mycn; // we are now connected
|
|
||||||
sendintro();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case N_WELCOME:
|
|
||||||
{
|
|
||||||
connected = true;
|
|
||||||
notifywelcome();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case N_MAPCHANGE:
|
|
||||||
getstring(text, p);
|
|
||||||
changemapserv(text, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case N_SPAWN:
|
|
||||||
{
|
|
||||||
printf("spawn\n");
|
|
||||||
if(d)
|
|
||||||
{
|
|
||||||
d->respawn();
|
|
||||||
}
|
|
||||||
parsestate(d, p);
|
|
||||||
if(!d) break;
|
|
||||||
d->state = CS_SPAWNING;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case N_NEWMAP:
|
|
||||||
{
|
|
||||||
int size = getint(p);
|
|
||||||
if(size>=0) emptymap(size, true, NULL);
|
|
||||||
else enlargemap(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
neterr("type", cn < 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void parsepacketclient(int chan, packetbuf &p) // processes any updates from the server
|
|
||||||
{
|
|
||||||
if(p.packet->flags&ENET_PACKET_FLAG_UNSEQUENCED) return;
|
|
||||||
switch(chan)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
parsemessages(-1, NULL, p);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,18 +57,16 @@ namespace game
|
||||||
void updateworld() // main game update loop
|
void updateworld() // main game update loop
|
||||||
{
|
{
|
||||||
if(!maptime) { maptime = lastmillis; maprealtime = totalmillis; return; }
|
if(!maptime) { maptime = lastmillis; maprealtime = totalmillis; return; }
|
||||||
if(!curtime) { gets2c(); if(player1->clientnum>=0) c2sinfo(); return; }
|
if(!curtime) { return; }
|
||||||
|
|
||||||
physicsframe();
|
physicsframe();
|
||||||
moveragdolls();
|
moveragdolls();
|
||||||
gets2c();
|
|
||||||
if(connected)
|
if(connected)
|
||||||
{
|
{
|
||||||
crouchplayer(player1, 10, true);
|
crouchplayer(player1, 10, true);
|
||||||
moveplayer(player1, 10, true);
|
moveplayer(player1, 10, true);
|
||||||
entities::checkitems(player1);
|
entities::checkitems(player1);
|
||||||
}
|
}
|
||||||
if(player1->clientnum>=0) c2sinfo(); // do this last, to reduce the effective frame lag
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spawnplayer(gameent *d) // place at random spawn
|
void spawnplayer(gameent *d) // place at random spawn
|
||||||
|
|
|
@ -77,31 +77,6 @@ struct gameentity : extentity
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
M_EDIT = 1<<0
|
|
||||||
};
|
|
||||||
|
|
||||||
// network messages codes, c2s, c2c, s2c
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
N_CONNECT = 0, N_SERVINFO, N_WELCOME,
|
|
||||||
N_SPAWN,
|
|
||||||
N_MAPCHANGE,
|
|
||||||
N_NEWMAP,
|
|
||||||
NUMMSG
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int msgsizes[] = // size inclusive message token, 0 for variable or not-checked sizes
|
|
||||||
{
|
|
||||||
N_CONNECT, 0, N_SERVINFO, 0, N_WELCOME, 1,
|
|
||||||
N_SPAWN, 2,
|
|
||||||
N_MAPCHANGE, 0,
|
|
||||||
N_NEWMAP, 2,
|
|
||||||
-1
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TESSERACT_SERVER_PORT 42000
|
#define TESSERACT_SERVER_PORT 42000
|
||||||
#define TESSERACT_LANINFO_PORT 41998
|
#define TESSERACT_LANINFO_PORT 41998
|
||||||
|
|
||||||
|
@ -136,7 +111,6 @@ struct gameent : dynent, gamestate
|
||||||
{
|
{
|
||||||
int weight; // affects the effectiveness of hitpush
|
int weight; // affects the effectiveness of hitpush
|
||||||
int clientnum, lastupdate, plag, ping;
|
int clientnum, lastupdate, plag, ping;
|
||||||
int lifesequence; // sequence id for each respawn, used in damage test
|
|
||||||
int respawned;
|
int respawned;
|
||||||
int lastaction;
|
int lastaction;
|
||||||
editinfo *edit;
|
editinfo *edit;
|
||||||
|
@ -149,7 +123,7 @@ struct gameent : dynent, gamestate
|
||||||
|
|
||||||
vec muzzle;
|
vec muzzle;
|
||||||
|
|
||||||
gameent() : weight(100), clientnum(-1), lastupdate(0), plag(0), ping(0), lifesequence(0), respawned(-1), edit(NULL), smoothmillis(-1), team(0), playermodel(-1), playercolor(0), ownernum(-1), muzzle(-1, -1, -1)
|
gameent() : weight(100), clientnum(-1), lastupdate(0), plag(0), ping(0), respawned(-1), edit(NULL), smoothmillis(-1), team(0), playermodel(-1), playercolor(0), ownernum(-1), muzzle(-1, -1, -1)
|
||||||
{
|
{
|
||||||
name[0] = info[0] = 0;
|
name[0] = info[0] = 0;
|
||||||
respawn();
|
respawn();
|
||||||
|
@ -175,7 +149,6 @@ struct gameent : dynent, gamestate
|
||||||
|
|
||||||
void startgame()
|
void startgame()
|
||||||
{
|
{
|
||||||
lifesequence = -1;
|
|
||||||
respawned = -2;
|
respawned = -2;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -224,14 +197,10 @@ namespace game
|
||||||
// client
|
// client
|
||||||
extern bool connected, remote, demoplayback;
|
extern bool connected, remote, demoplayback;
|
||||||
extern string servdesc;
|
extern string servdesc;
|
||||||
extern vector<uchar> messages;
|
|
||||||
|
|
||||||
extern int parseplayer(const char *arg);
|
extern int parseplayer(const char *arg);
|
||||||
extern bool addmsg(int type, const char *fmt = NULL, ...);
|
|
||||||
extern void sendmapinfo();
|
extern void sendmapinfo();
|
||||||
extern void changemap(const char *name, int mode);
|
extern void changemap(const char *name, int mode);
|
||||||
extern void c2sinfo(bool force = false);
|
|
||||||
extern void sendposition(gameent *d, bool reliable = false);
|
|
||||||
|
|
||||||
// render
|
// render
|
||||||
|
|
||||||
|
|
|
@ -7,104 +7,9 @@ namespace game
|
||||||
|
|
||||||
namespace server
|
namespace server
|
||||||
{
|
{
|
||||||
struct clientinfo;
|
|
||||||
|
|
||||||
struct servstate : gamestate
|
|
||||||
{
|
|
||||||
vec o;
|
|
||||||
int state, editstate;
|
|
||||||
int lastspawn, lifesequence;
|
|
||||||
|
|
||||||
servstate() : state(CS_DEAD), editstate(CS_DEAD), lifesequence(0) {}
|
|
||||||
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
state = editstate = CS_DEAD;
|
|
||||||
|
|
||||||
respawn();
|
|
||||||
}
|
|
||||||
|
|
||||||
void respawn()
|
|
||||||
{
|
|
||||||
gamestate::respawn();
|
|
||||||
o = vec(-1e10f, -1e10f, -1e10f);
|
|
||||||
lastspawn = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reassign()
|
|
||||||
{
|
|
||||||
respawn();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int gamemillis;
|
|
||||||
|
|
||||||
struct clientinfo
|
|
||||||
{
|
|
||||||
int clientnum, ownernum, connectmillis, sessionid, overflow;
|
|
||||||
string name;
|
|
||||||
bool connected, local, timesync;
|
|
||||||
servstate state;
|
|
||||||
vector<uchar> messages;
|
|
||||||
uchar *wsdata;
|
|
||||||
int wslen;
|
|
||||||
string clientmap;
|
|
||||||
bool warned;
|
|
||||||
|
|
||||||
clientinfo() { reset(); }
|
|
||||||
|
|
||||||
void mapchange()
|
|
||||||
{
|
|
||||||
state.reset();
|
|
||||||
overflow = 0;
|
|
||||||
timesync = false;
|
|
||||||
clientmap[0] = '\0';
|
|
||||||
warned = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reassign()
|
|
||||||
{
|
|
||||||
state.reassign();
|
|
||||||
timesync = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
name[0] = 0;
|
|
||||||
connected = local = false;
|
|
||||||
messages.setsize(0);
|
|
||||||
mapchange();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int gamemillis = 0;
|
|
||||||
bool shouldstep = true;
|
|
||||||
|
|
||||||
string smapname = "";
|
string smapname = "";
|
||||||
|
|
||||||
vector<clientinfo *> connects, clients;
|
|
||||||
|
|
||||||
void *newclientinfo() { return new clientinfo; }
|
|
||||||
void deleteclientinfo(void *ci) { delete (clientinfo *)ci; }
|
|
||||||
|
|
||||||
clientinfo *getinfo(int n)
|
|
||||||
{
|
|
||||||
return (clientinfo *)getclientinfo(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
int msgsizelookup(int msg)
|
|
||||||
{
|
|
||||||
static int sizetable[NUMMSG] = { -1 };
|
|
||||||
if(sizetable[0] < 0)
|
|
||||||
{
|
|
||||||
memset(sizetable, -1, sizeof(sizetable));
|
|
||||||
for(const int *p = msgsizes; *p >= 0; p += 2) sizetable[p[0]] = p[1];
|
|
||||||
}
|
|
||||||
return msg >= 0 && msg < NUMMSG ? sizetable[msg] : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendservmsg(const char *) {}
|
|
||||||
|
|
||||||
void serverinit()
|
void serverinit()
|
||||||
{
|
{
|
||||||
smapname[0] = '\0';
|
smapname[0] = '\0';
|
||||||
|
@ -112,130 +17,25 @@ namespace server
|
||||||
|
|
||||||
int numclients(int exclude = -1, bool nospec = true, bool noai = true, bool priv = false)
|
int numclients(int exclude = -1, bool nospec = true, bool noai = true, bool priv = false)
|
||||||
{
|
{
|
||||||
int n = 0;
|
return 0;
|
||||||
loopv(clients)
|
|
||||||
{
|
|
||||||
clientinfo *ci = clients[i];
|
|
||||||
if(ci->clientnum!=exclude && (!nospec || ci->state.state!=CS_SPECTATOR || (priv && ci->local))) n++;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool duplicatename(clientinfo *ci, const char *name)
|
|
||||||
{
|
|
||||||
if(!name) name = ci->name;
|
|
||||||
loopv(clients) if(clients[i]!=ci && !strcmp(name, clients[i]->name)) return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int spawntime(int type)
|
int spawntime(int type)
|
||||||
{
|
{
|
||||||
int np = numclients(-1, true, false);
|
return 0;
|
||||||
np = np<3 ? 4 : (np>4 ? 2 : 3); // spawn times are dependent on number of players
|
|
||||||
int sec = 0;
|
|
||||||
switch(type)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
return sec*1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool delayspawn(int type)
|
bool delayspawn(int type)
|
||||||
{
|
{
|
||||||
switch(type)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int welcomepacket(packetbuf &p, clientinfo *ci);
|
|
||||||
void sendwelcome(clientinfo *ci);
|
|
||||||
|
|
||||||
bool ispaused() { return false; }
|
bool ispaused() { return false; }
|
||||||
|
|
||||||
int scaletime(int t) { return t*100; }
|
int scaletime(int t) { return t*100; }
|
||||||
|
|
||||||
int checktype(int type, clientinfo *ci)
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sendpackets(bool force)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void sendstate(servstate &gs, T &p)
|
|
||||||
{
|
|
||||||
putint(p, gs.lifesequence);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendwelcome(clientinfo *ci)
|
|
||||||
{
|
|
||||||
packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE);
|
|
||||||
int chan = welcomepacket(p, ci);
|
|
||||||
sendpacket(ci->clientnum, chan, p.finalize());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasmap(clientinfo *ci)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int welcomepacket(packetbuf &p, clientinfo *ci)
|
|
||||||
{
|
|
||||||
putint(p, N_WELCOME);
|
|
||||||
putint(p, N_MAPCHANGE);
|
|
||||||
sendstring(smapname, p);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void changemap(const char *s, int mode)
|
|
||||||
{
|
|
||||||
gamemillis = 0;
|
|
||||||
copystring(smapname, s);
|
|
||||||
|
|
||||||
kicknonlocalclients(DISC_LOCAL);
|
|
||||||
|
|
||||||
sendf(-1, 1, "ris", N_MAPCHANGE, smapname);
|
|
||||||
|
|
||||||
loopv(clients)
|
|
||||||
{
|
|
||||||
clientinfo *ci = clients[i];
|
|
||||||
ci->mapchange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void forcemap(const char *map, int mode)
|
|
||||||
{
|
|
||||||
changemap(map, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void serverupdate()
|
void serverupdate()
|
||||||
{
|
{
|
||||||
if(shouldstep)
|
|
||||||
{
|
|
||||||
gamemillis += curtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
loopv(connects) if(totalmillis-connects[i]->connectmillis>15000) disconnect_client(connects[i]->clientnum, DISC_TIMEOUT);
|
|
||||||
|
|
||||||
shouldstep = clients.length() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool shouldspectate(clientinfo *ci)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unspectate(clientinfo *ci)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendservinfo(clientinfo *ci)
|
|
||||||
{
|
|
||||||
sendf(ci->clientnum, 1, "ri3", N_SERVINFO, ci->clientnum, ci->sessionid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void noclients()
|
void noclients()
|
||||||
|
@ -244,158 +44,26 @@ namespace server
|
||||||
|
|
||||||
void localconnect(int n)
|
void localconnect(int n)
|
||||||
{
|
{
|
||||||
clientinfo *ci = getinfo(n);
|
|
||||||
ci->clientnum = ci->ownernum = n;
|
|
||||||
ci->connectmillis = totalmillis;
|
|
||||||
ci->sessionid = (rnd(0x1000000)*((totalmillis%10000)+1))&0xFFFFFF;
|
|
||||||
ci->local = true;
|
|
||||||
|
|
||||||
connects.add(ci);
|
|
||||||
sendservinfo(ci);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void localdisconnect(int n)
|
void localdisconnect(int n)
|
||||||
{
|
{
|
||||||
clientdisconnect(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int clientconnect(int n, uint ip)
|
int clientconnect(int n, uint ip)
|
||||||
{
|
{
|
||||||
clientinfo *ci = getinfo(n);
|
|
||||||
ci->clientnum = ci->ownernum = n;
|
|
||||||
ci->connectmillis = totalmillis;
|
|
||||||
ci->sessionid = (rnd(0x1000000)*((totalmillis%10000)+1))&0xFFFFFF;
|
|
||||||
|
|
||||||
connects.add(ci);
|
|
||||||
return DISC_LOCAL;
|
return DISC_LOCAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clientdisconnect(int n)
|
void clientdisconnect(int n)
|
||||||
{
|
{
|
||||||
clientinfo *ci = getinfo(n);
|
|
||||||
if(ci->connected)
|
|
||||||
{
|
|
||||||
clients.removeobj(ci);
|
|
||||||
if(!numclients(-1, false, true)) noclients(); // bans clear when server empties
|
|
||||||
}
|
|
||||||
else connects.removeobj(ci);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int reserveclients() { return 3; }
|
int reserveclients() { return 3; }
|
||||||
|
|
||||||
bool allowbroadcast(int n)
|
bool allowbroadcast(int n)
|
||||||
{
|
{
|
||||||
clientinfo *ci = getinfo(n);
|
return true;
|
||||||
return ci && ci->connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
void receivefile(int sender, uchar *data, int len)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void connected(clientinfo *ci)
|
|
||||||
{
|
|
||||||
shouldstep = true;
|
|
||||||
|
|
||||||
connects.removeobj(ci);
|
|
||||||
clients.add(ci);
|
|
||||||
|
|
||||||
ci->connected = true;
|
|
||||||
|
|
||||||
sendwelcome(ci);
|
|
||||||
}
|
|
||||||
|
|
||||||
void parsepacket(int sender, int chan, packetbuf &p) // has to parse exactly each byte of the packet
|
|
||||||
{
|
|
||||||
if(sender<0 || p.packet->flags&ENET_PACKET_FLAG_UNSEQUENCED || chan > 2) return;
|
|
||||||
char text[MAXTRANS];
|
|
||||||
int type;
|
|
||||||
clientinfo *ci = sender>=0 ? getinfo(sender) : NULL, *cq = ci, *cm = ci;
|
|
||||||
if(ci && !ci->connected)
|
|
||||||
{
|
|
||||||
if(chan==0) return;
|
|
||||||
else if(chan!=1) { disconnect_client(sender, DISC_MSGERR); return; }
|
|
||||||
else while(p.length() < p.maxlen) switch(checktype(getint(p), ci))
|
|
||||||
{
|
|
||||||
case N_CONNECT:
|
|
||||||
{
|
|
||||||
getstring(text, p);
|
|
||||||
filtertext(text, text, false, false, MAXNAMELEN);
|
|
||||||
if(!text[0]) copystring(text, "unnamed");
|
|
||||||
copystring(ci->name, text, MAXNAMELEN+1);
|
|
||||||
connected(ci);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
disconnect_client(sender, DISC_MSGERR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if(chan==2)
|
|
||||||
{
|
|
||||||
receivefile(sender, p.buf, p.maxlen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define QUEUE_AI clientinfo *cm = cq;
|
|
||||||
#define QUEUE_MSG { if(cm && (!cm->local || hasnonlocalclients())) while(curmsg<p.length()) cm->messages.add(p.buf[curmsg++]); }
|
|
||||||
#define QUEUE_BUF(body) { \
|
|
||||||
if(cm && (!cm->local || hasnonlocalclients())) \
|
|
||||||
{ \
|
|
||||||
curmsg = p.length(); \
|
|
||||||
{ body; } \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#define QUEUE_INT(n) QUEUE_BUF(putint(cm->messages, n))
|
|
||||||
#define QUEUE_UINT(n) QUEUE_BUF(putuint(cm->messages, n))
|
|
||||||
#define QUEUE_STR(text) QUEUE_BUF(sendstring(text, cm->messages))
|
|
||||||
int curmsg;
|
|
||||||
while((curmsg = p.length()) < p.maxlen) switch(type = checktype(getint(p), ci))
|
|
||||||
{
|
|
||||||
case N_SPAWN:
|
|
||||||
{
|
|
||||||
int ls = getint(p);
|
|
||||||
if(!cq || (cq->state.state!=CS_ALIVE && cq->state.state!=CS_DEAD && cq->state.state!=CS_EDITING) || ls!=cq->state.lifesequence || cq->state.lastspawn<0) break;
|
|
||||||
cq->state.lastspawn = -1;
|
|
||||||
cq->state.state = CS_ALIVE;
|
|
||||||
QUEUE_AI;
|
|
||||||
QUEUE_BUF({
|
|
||||||
putint(cm->messages, N_SPAWN);
|
|
||||||
sendstate(cq->state, cm->messages);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case N_NEWMAP:
|
|
||||||
{
|
|
||||||
int size = getint(p);
|
|
||||||
if(!ci->local && ci->state.state==CS_SPECTATOR) break;
|
|
||||||
if(size>=0)
|
|
||||||
{
|
|
||||||
smapname[0] = '\0';
|
|
||||||
}
|
|
||||||
QUEUE_MSG;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case -1:
|
|
||||||
disconnect_client(sender, DISC_MSGERR);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case -2:
|
|
||||||
disconnect_client(sender, DISC_OVERFLOW);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
int size = server::msgsizelookup(type);
|
|
||||||
if(size<=0) { disconnect_client(sender, DISC_MSGERR); return; }
|
|
||||||
loopi(size-1) getint(p);
|
|
||||||
if(cq && (ci != cq || ci->state.state!=CS_SPECTATOR)) { QUEUE_AI; QUEUE_MSG; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int laninfoport() { return TESSERACT_LANINFO_PORT; }
|
int laninfoport() { return TESSERACT_LANINFO_PORT; }
|
||||||
|
|
Loading…
Reference in New Issue