diff options
Diffstat (limited to 'src/fpsgame/server.cpp')
| -rw-r--r-- | src/fpsgame/server.cpp | 1779 |
1 files changed, 473 insertions, 1306 deletions
diff --git a/src/fpsgame/server.cpp b/src/fpsgame/server.cpp index ec781c6..2095dd1 100644 --- a/src/fpsgame/server.cpp +++ b/src/fpsgame/server.cpp @@ -1,9 +1,7 @@ #include "game.h" -namespace game -{ - void parseoptions(vector<const char *> &args) - { +namespace game { + void parseoptions(vector<const char *> &args) { loopv(args) #ifndef STANDALONE if(!game::clientoption(args[i])) @@ -11,7 +9,6 @@ namespace game if(!server::serveroption(args[i])) conoutf(CON_ERROR, "unknown command-line option: %s", args[i]); } - const char *gameident() { return "fps"; } } @@ -19,105 +16,69 @@ VAR(regenbluearmour, 0, 1, 1); extern ENetAddress masteraddress; -namespace server -{ - struct server_entity // server side version of "entity" type - { +namespace server { + struct server_entity { // server side version of "entity" type { int type; int spawntime; bool spawned; }; - static const int DEATHMILLIS = 300; - struct clientinfo; - - struct gameevent - { + struct gameevent { virtual ~gameevent() {} - virtual bool flush(clientinfo *ci, int fmillis); - virtual void process(clientinfo *ci) {} - + virtual void process(clientinfo *) {} virtual bool keepable() const { return false; } }; - - struct timedevent : gameevent - { + struct timedevent : gameevent { int millis; - bool flush(clientinfo *ci, int fmillis); }; - - struct hitinfo - { + struct hitinfo { int target; int lifesequence; int rays; float dist; vec dir; }; - - struct shotevent : timedevent - { + struct shotevent : timedevent { int id, gun; vec from, to; vector<hitinfo> hits; - void process(clientinfo *ci); }; - - struct explodeevent : timedevent - { + struct explodeevent : timedevent { int id, gun; vector<hitinfo> hits; - bool keepable() const { return true; } - void process(clientinfo *ci); }; - - struct suicideevent : gameevent - { + struct suicideevent : gameevent { void process(clientinfo *ci); }; - - struct pickupevent : gameevent - { + struct pickupevent : gameevent { int ent; - void process(clientinfo *ci); }; - template <int N> - struct projectilestate - { + struct projectilestate { int projs[N]; int numprojs; - projectilestate() : numprojs(0) {} - void reset() { numprojs = 0; } - - void add(int val) - { + void add(int val) { if(numprojs>=N) numprojs = 0; projs[numprojs++] = val; } - - bool remove(int val) - { - loopi(numprojs) if(projs[i]==val) - { + bool remove(int val) { + loopi(numprojs) if(projs[i]==val) { projs[i] = projs[--numprojs]; return true; } return false; } }; - - struct gamestate : fpsstate - { + struct gamestate : fpsstate { vec o; int state, editstate; int lastdeath, deadflush, lastspawn, lifesequence; @@ -126,38 +87,26 @@ namespace server int frags, flags, deaths, teamkills, shotdamage, damage, tokens; int lasttimeplayed, timeplayed; float effectiveness; - gamestate() : state(CS_DEAD), editstate(CS_DEAD), lifesequence(0) {} - - bool isalive(int gamemillis) - { + bool isalive(int gamemillis) { return state==CS_ALIVE || (state==CS_DEAD && gamemillis - lastdeath <= DEATHMILLIS); } - - bool waitexpired(int gamemillis) - { + bool waitexpired(int gamemillis) { return gamemillis - lastshot >= gunwait; } - - void reset() - { + void reset() { if(state!=CS_SPECTATOR) state = editstate = CS_DEAD; maxhealth = 100; maxarmour = 50; rockets.reset(); grenades.reset(); - timeplayed = 0; effectiveness = 0; frags = flags = deaths = teamkills = shotdamage = damage = tokens = 0; - lastdeath = 0; - respawn(); } - - void respawn() - { + void respawn() { fpsstate::respawn(); o = vec(-1e10f, -1e10f, -1e10f); deadflush = 0; @@ -165,25 +114,19 @@ namespace server lastshot = 0; tokens = 0; } - - void reassign() - { + void reassign() { respawn(); rockets.reset(); grenades.reset(); } }; - - struct savedscore - { + struct savedscore { uint ip; string name; int frags, flags, deaths, teamkills, shotdamage, damage; int timeplayed; float effectiveness; - - void save(gamestate &gs) - { + void save(gamestate &gs) { frags = gs.frags; flags = gs.flags; deaths = gs.deaths; @@ -193,9 +136,7 @@ namespace server timeplayed = gs.timeplayed; effectiveness = gs.effectiveness; } - - void restore(gamestate &gs) - { + void restore(gamestate &gs) { gs.frags = frags; gs.flags = flags; gs.deaths = deaths; @@ -206,11 +147,8 @@ namespace server gs.effectiveness = effectiveness; } }; - extern int gamemillis, nextexceeded; - - struct clientinfo - { + struct clientinfo { int clientnum, ownernum, connectmillis, sessionid, overflow; string name, team, mapvote; int playermodel; @@ -236,58 +174,39 @@ namespace server void *authchallenge; int authkickvictim; char *authkickreason; - clientinfo() : getdemo(NULL), getmap(NULL), clipboard(NULL), authchallenge(NULL), authkickreason(NULL) { reset(); } ~clientinfo() { events.deletecontents(); cleanclipboard(); cleanauth(); } - - void addevent(gameevent *e) - { + void addevent(gameevent *e) { if(state.state==CS_SPECTATOR || events.length()>100) delete e; else events.add(e); } - - enum - { + enum { PUSHMILLIS = 3000 }; - - int calcpushrange() - { + int calcpushrange() { ENetPeer *peer = getclientpeer(ownernum); return PUSHMILLIS + ((peer) ? (int) (peer->roundTripTime + peer->roundTripTimeVariance) : (int) ENET_PEER_DEFAULT_ROUND_TRIP_TIME); } - - bool checkpushed(int millis, int range) - { + bool checkpushed(int millis, int range) { return millis >= pushed - range && millis <= pushed + range; } - - void scheduleexceeded() - { + void scheduleexceeded() { if(state.state!=CS_ALIVE || !exceeded) return; int range = calcpushrange(); if(!nextexceeded || exceeded + range < nextexceeded) nextexceeded = exceeded + range; } - - void setexceeded() - { + void setexceeded() { if(state.state==CS_ALIVE && !exceeded && !checkpushed(gamemillis, calcpushrange())) exceeded = gamemillis; scheduleexceeded(); } - - void setpushed() - { + void setpushed() { pushed = max(pushed, gamemillis); if(exceeded && checkpushed(exceeded, calcpushrange())) exceeded = 0; } - - bool checkexceeded() - { + bool checkexceeded() { return state.state==CS_ALIVE && exceeded && gamemillis > exceeded + calcpushrange(); } - - void mapchange() - { + void mapchange() { mapvote[0] = 0; modevote = INT_MAX; state.reset(); @@ -302,36 +221,26 @@ namespace server warned = false; gameclip = false; } - - void reassign() - { + void reassign() { state.reassign(); events.deletecontents(); timesync = false; lastevent = 0; } - - void cleanclipboard(bool fullclean = true) - { + void cleanclipboard(bool fullclean = true) { if(clipboard) { if(--clipboard->referenceCount <= 0) enet_packet_destroy(clipboard); clipboard = NULL; } if(fullclean) lastclipboard = 0; } - - void cleanauthkick() - { + void cleanauthkick() { authkickvictim = -1; DELETEA(authkickreason); } - - void cleanauth(bool full = true) - { + void cleanauth(bool full = true) { authreq = 0; if(authchallenge) { freechallenge(authchallenge); authchallenge = NULL; } if(full) cleanauthkick(); } - - void reset() - { + void reset() { name[0] = team[0] = 0; playermodel = -1; privilege = PRIV_NONE; @@ -346,11 +255,8 @@ namespace server cleanauth(); mapchange(); } - - int geteventmillis(int servmillis, int clientmillis) - { - if(!timesync || (events.empty() && state.waitexpired(servmillis))) - { + int geteventmillis(int servmillis, int clientmillis) { + if(!timesync || (events.empty() && state.waitexpired(servmillis))) { timesync = true; gameoffset = servmillis - clientmillis; return servmillis; @@ -358,15 +264,11 @@ namespace server else return gameoffset + clientmillis; } }; - - struct ban - { + struct ban { int time, expire; uint ip; }; - - namespace aiman - { + namespace aiman { extern void removeai(clientinfo *ci); extern void clearai(); extern void checkai(); @@ -378,29 +280,23 @@ namespace server extern void addclient(clientinfo *ci); extern void changeteam(clientinfo *ci); } - #define MM_MODE 0xF #define MM_AUTOAPPROVE 0x1000 #define MM_PRIVSERV (MM_MODE | MM_AUTOAPPROVE) #define MM_PUBSERV ((1<<MM_OPEN) | (1<<MM_VETO)) #define MM_COOPSERV (MM_AUTOAPPROVE | MM_PUBSERV | (1<<MM_LOCKED)) - bool notgotitems = true; // true when map has changed and waiting for clients to send item int gamemode = 0; int gamemillis = 0, gamelimit = 0, nextexceeded = 0, gamespeed = 100; bool gamepaused = false, shouldstep = true; - string smapname = ""; int interm = 0; enet_uint32 lastsend = 0; int mastermode = MM_OPEN, mastermask = MM_PRIVSERV; stream *mapdata = NULL; - vector<uint> allowedips; vector<ban> bannedips; - - void addban(uint ip, int expire) - { + void addban(uint ip, int expire) { allowedips.removeobj(ip); ban b; b.time = totalmillis; @@ -409,71 +305,49 @@ namespace server loopv(bannedips) if(bannedips[i].expire - b.expire > 0) { bannedips.insert(i, b); return; } bannedips.add(b); } - vector<clientinfo *> connects, clients, bots; - - void kickclients(uint ip, clientinfo *actor = NULL, int priv = PRIV_NONE) - { - loopvrev(clients) - { + void kickclients(clientinfo *actor = NULL, int priv = PRIV_NONE) { + loopvrev(clients) { clientinfo &c = *clients[i]; if(c.state.aitype != AI_NONE || c.privilege >= PRIV_ADMIN || c.local) continue; if(actor && ((c.privilege > priv && !actor->local) || c.clientnum == actor->clientnum)) continue; - //~if(getclientip(c.clientnum) == ip) disconnect_client(c.clientnum, DISC_KICK); } } - - struct maprotation - { + struct maprotation { static int exclude; int modes; string map; - int calcmodemask() const { return modes&(1<<NUMGAMEMODES) ? modes & ~exclude : modes; } bool hasmode(int mode, int offset = STARTGAMEMODE) const { return (calcmodemask() & (1 << (mode-offset))) != 0; } - - int findmode(int mode) const - { + int findmode(int mode) const { if(!hasmode(mode)) loopi(NUMGAMEMODES) if(hasmode(i, 0)) return i+STARTGAMEMODE; return mode; } - - bool match(int reqmode, const char *reqmap) const - { + bool match(int reqmode, const char *reqmap) const { return hasmode(reqmode) && (!map[0] || !reqmap[0] || !strcmp(map, reqmap)); } - - bool includes(const maprotation &rot) const - { + bool includes(const maprotation &rot) const { return rot.modes == modes ? rot.map[0] && !map[0] : (rot.modes & modes) == rot.modes; } }; int maprotation::exclude = 0; vector<maprotation> maprotations; int curmaprotation = 0; - VAR(lockmaprotation, 0, 0, 2); - - void maprotationreset() - { + void maprotationreset() { maprotations.setsize(0); curmaprotation = 0; maprotation::exclude = 0; } - - void nextmaprotation() - { + void nextmaprotation() { curmaprotation++; if(maprotations.inrange(curmaprotation) && maprotations[curmaprotation].modes) return; do curmaprotation--; while(maprotations.inrange(curmaprotation) && maprotations[curmaprotation].modes); curmaprotation++; } - - int findmaprotation(int mode, const char *map) - { - for(int i = max(curmaprotation, 0); i < maprotations.length(); i++) - { + int findmaprotation(int mode, const char *map) { + for(int i = max(curmaprotation, 0); i < maprotations.length(); i++) { maprotation &rot = maprotations[i]; if(!rot.modes) break; if(rot.match(mode, map)) return i; @@ -481,35 +355,28 @@ namespace server int start; for(start = max(curmaprotation, 0) - 1; start >= 0; start--) if(!maprotations[start].modes) break; start++; - for(int i = start; i < curmaprotation; i++) - { + for(int i = start; i < curmaprotation; i++) { maprotation &rot = maprotations[i]; if(!rot.modes) break; if(rot.match(mode, map)) return i; } int best = -1; - loopv(maprotations) - { + loopv(maprotations) { maprotation &rot = maprotations[i]; if(rot.match(mode, map) && (best < 0 || maprotations[best].includes(rot))) best = i; } return best; } - - bool searchmodename(const char *haystack, const char *needle) - { + bool searchmodename(const char *haystack, const char *needle) { if(!needle[0]) return true; - do - { - if(needle[0] != '.') - { + do { + if(needle[0] != '.') { haystack = strchr(haystack, needle[0]); if(!haystack) break; haystack++; } const char *h = haystack, *n = needle+1; - for(; *h && *n; h++) - { + for(; *h && *n; h++) { if(*h == *n) n++; else if(*h != ' ') break; } @@ -518,16 +385,12 @@ namespace server } while(needle[0] != '.'); return false; } - - int genmodemask(vector<char *> &modes) - { + int genmodemask(vector<char *> &modes) { int modemask = 0; - loopv(modes) - { + loopv(modes) { const char *mode = modes[i]; int op = mode[0]; - switch(mode[0]) - { + switch(mode[0]) { case '*': modemask |= 1<<NUMGAMEMODES; loopk(NUMGAMEMODES) if(m_checknot(k+STARTGAMEMODE, M_DEMO|M_EDIT|M_LOCAL)) modemask |= 1<<k; @@ -538,8 +401,7 @@ namespace server [[fallthrough]]; case '?': mode++; - loopk(NUMGAMEMODES) if(searchmodename(gamemodes[k].name, mode)) - { + loopk(NUMGAMEMODES) if(searchmodename(gamemodes[k].name, mode)) { if(op == '!') modemask &= ~(1<<k); else modemask |= 1<<k; } @@ -549,17 +411,14 @@ namespace server if(isdigit(mode[0])) modenum = atoi(mode); else loopk(NUMGAMEMODES) if(searchmodename(gamemodes[k].name, mode)) { modenum = k+STARTGAMEMODE; break; } if(!m_valid(modenum)) continue; - switch(op) - { + switch(op) { case '!': modemask &= ~(1 << (modenum - STARTGAMEMODE)); break; default: modemask |= 1 << (modenum - STARTGAMEMODE); break; } } return modemask; } - - bool addmaprotation(int modemask, const char *map) - { + bool addmaprotation(int modemask, const char *map) { if(!map[0]) loopk(NUMGAMEMODES) if(modemask&(1<<k) && !m_check(k+STARTGAMEMODE, M_EDIT)) modemask &= ~(1<<k); if(!modemask) return false; if(!(modemask&(1<<NUMGAMEMODES))) maprotation::exclude |= modemask; @@ -568,12 +427,9 @@ namespace server copystring(rot.map, map); return true; } - - void addmaprotations(tagval *args, int numargs) - { + void addmaprotations(tagval *args, int numargs) { vector<char *> modes, maps; - for(int i = 0; i + 1 < numargs; i += 2) - { + for(int i = 0; i + 1 < numargs; i += 2) { explodelist(args[i].getstr(), modes); explodelist(args[i+1].getstr(), maps); int modemask = genmodemask(modes); @@ -582,74 +438,54 @@ namespace server modes.deletearrays(); maps.deletearrays(); } - if(maprotations.length() && maprotations.last().modes) - { + if(maprotations.length() && maprotations.last().modes) { maprotation &rot = maprotations.add(); rot.modes = 0; rot.map[0] = '\0'; } } - COMMAND(maprotationreset, ""); COMMANDN(maprotation, addmaprotations, "ss2V"); - - struct demofile - { + struct demofile { string info; uchar *data; int len; }; - vector<demofile> demos; - bool demonextmatch = false; stream *demotmp = NULL, *demorecord = NULL, *demoplayback = NULL; int nextplayback = 0; - VAR(maxdemos, 0, 5, 25); VAR(maxdemosize, 0, 16, 31); VAR(restrictdemos, 0, 1, 1); VARF(autorecorddemo, 0, 0, 1, demonextmatch = autorecorddemo!=0); - VAR(restrictpausegame, 0, 1, 1); VAR(restrictgamespeed, 0, 1, 1); - SVAR(serverdesc, ""); SVAR(serverpass, ""); SVAR(adminpass, ""); VARF(publicserver, 0, 0, 2, { - switch(publicserver) - { + switch(publicserver) { case 0: default: mastermask = MM_PRIVSERV; break; case 1: mastermask = MM_PUBSERV; break; case 2: mastermask = MM_COOPSERV; break; } }); SVAR(servermotd, ""); - - struct teamkillkick - { + struct teamkillkick { int modes, limit, ban; - - bool match(int mode) const - { + bool match(int mode) const { return (modes&(1<<(mode-STARTGAMEMODE)))!=0; } - - bool includes(const teamkillkick &tk) const - { + bool includes(const teamkillkick &tk) const { return tk.modes != modes && (tk.modes & modes) == tk.modes; } }; vector<teamkillkick> teamkillkicks; - - void teamkillkickreset() - { + void teamkillkickreset() { teamkillkicks.setsize(0); } - - void addteamkillkick(char *modestr, int *limit, int *ban) - { + void addteamkillkick(char *modestr, int *limit, int *ban) { vector<char *> modes; explodelist(modestr, modes); teamkillkick &kick = teamkillkicks.add(); @@ -658,25 +494,19 @@ namespace server kick.ban = *ban > 0 ? *ban*60000 : (*ban < 0 ? 0 : 30*60000); modes.deletearrays(); } - COMMAND(teamkillkickreset, ""); COMMANDN(teamkillkick, addteamkillkick, "sii"); - - struct teamkillinfo - { + struct teamkillinfo { uint ip; int teamkills; }; vector<teamkillinfo> teamkills; bool shouldcheckteamkills = false; - - void addteamkill(clientinfo *actor, clientinfo *victim, int n) - { + void addteamkill(clientinfo *actor, clientinfo *victim, int n) { if(!m_timed || actor->state.aitype != AI_NONE || actor->local || actor->privilege || (victim && victim->state.aitype != AI_NONE)) return; shouldcheckteamkills = true; uint ip = getclientip(actor->clientnum); - loopv(teamkills) if(teamkills[i].ip == ip) - { + loopv(teamkills) if(teamkills[i].ip == ip) { teamkills[i].teamkills += n; return; } @@ -684,92 +514,67 @@ namespace server tk.ip = ip; tk.teamkills = n; } - - void checkteamkills() - { + void checkteamkills() { teamkillkick *kick = NULL; if(m_timed) loopv(teamkillkicks) if(teamkillkicks[i].match(gamemode) && (!kick || kick->includes(teamkillkicks[i]))) kick = &teamkillkicks[i]; - if(kick) loopvrev(teamkills) - { + if(kick) loopvrev(teamkills) { teamkillinfo &tk = teamkills[i]; - if(tk.teamkills >= kick->limit) - { + if(tk.teamkills >= kick->limit) { if(kick->ban > 0) addban(tk.ip, kick->ban); - kickclients(tk.ip); + kickclients(); teamkills.removeunordered(i); } } shouldcheckteamkills = false; } - void *newclientinfo() { return new clientinfo; } void deleteclientinfo(void *ci) { delete (clientinfo *)ci; } - - clientinfo *getinfo(int n) - { + clientinfo *getinfo(int n) { if(n < MAXCLIENTS) return (clientinfo *)getclientinfo(n); n -= MAXCLIENTS; return bots.inrange(n) ? bots[n] : NULL; } - uint mcrc = 0; vector<entity> ments; vector<server_entity> sents; vector<savedscore> scores; - - int msgsizelookup(int msg) - { + int msgsizelookup(int msg) { static int sizetable[NUMMSG] = { -1 }; - if(sizetable[0] < 0) - { + 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; } - - const char *modename(int n, const char *unknown) - { + const char *modename(int n, const char *unknown) { if(m_valid(n)) return gamemodes[n - STARTGAMEMODE].name; return unknown; } - - const char *mastermodename(int n, const char *unknown) - { + const char *mastermodename(int n, const char *unknown) { return (n>=MM_START && size_t(n-MM_START)<sizeof(mastermodenames)/sizeof(mastermodenames[0])) ? mastermodenames[n-MM_START] : unknown; } - - const char *privname(int type) - { - switch(type) - { + const char *privname(int type) { + switch(type) { case PRIV_ADMIN: return "admin"; case PRIV_AUTH: return "auth"; case PRIV_MASTER: return "master"; default: return "unknown"; } } - void sendservmsg(const char *s) { sendf(-1, 1, "ris", N_SERVMSG, s); } - void sendservmsgf(const char *fmt, ...) - { + void sendservmsgf(const char *fmt, ...) { defvformatstring(s, fmt, fmt); sendf(-1, 1, "ris", N_SERVMSG, s); } - - void resetitems() - { + void resetitems() { mcrc = 0; ments.setsize(0); sents.setsize(0); //cps.reset(); } - - bool serveroption(const char *arg) - { - if(arg[0]=='-') switch(arg[1]) - { + bool serveroption(const char *arg) { + if(arg[0]=='-') switch(arg[1]) { case 'n': setsvar("serverdesc", &arg[2]); return true; case 'y': setsvar("serverpass", &arg[2]); return true; case 'p': setsvar("adminpass", &arg[2]); return true; @@ -777,33 +582,24 @@ namespace server } return false; } - - void serverinit() - { + void serverinit() { smapname[0] = '\0'; resetitems(); } - - 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; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->clientnum!=exclude && (!nospec || ci->state.state!=CS_SPECTATOR || (priv && (ci->privilege || ci->local))) && (!noai || ci->state.aitype == AI_NONE)) n++; } return n; } - - bool duplicatename(clientinfo *ci, const char *name) - { + 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; } - - const char *colorname(clientinfo *ci, const char *name = NULL) - { + const char *colorname(clientinfo *ci, const char *name = NULL) { if(!name) name = ci->name; if(name[0] && !duplicatename(ci, name) && ci->state.aitype == AI_NONE) return name; static string cname[3]; @@ -812,16 +608,12 @@ namespace server formatstring(cname[cidx], ci->state.aitype == AI_NONE ? "%s \fs\f5(%d)\fr" : "%s \fs\f5[%d]\fr", name, ci->clientnum); return cname[cidx]; } - bool canspawnitem(int type) { return !m_noitems && (type>=I_SHELLS && type<=I_QUAD && (!m_noammo || type<I_SHELLS || type>I_CARTRIDGES)); } - - int spawntime(int type) - { + int spawntime(int type) { int np = numclients(-1, true, false); np = np<3 ? 4 : (np>4 ? 2 : 3); // spawn times are dependent on number of players int sec = 0; - switch(type) - { + switch(type) { case I_SHELLS: case I_BULLETS: case I_ROCKETS: @@ -838,11 +630,8 @@ namespace server } return sec*1000; } - - bool delayspawn(int type) - { - switch(type) - { + bool delayspawn(int type) { + switch(type) { case I_GREENARMOUR: case I_YELLOWARMOUR: case I_BOOST: @@ -852,14 +641,11 @@ namespace server return false; } } - - bool pickup(int i, int sender) // server side item pickup, acknowledge first client that gets it - { + bool pickup(int i, int sender) { // server side item pickup, acknowledge first client that gets it { if((m_timed && gamemillis>=gamelimit) || !sents.inrange(i) || !sents[i].spawned) return false; clientinfo *ci = getinfo(sender); if(!ci) return false; - if(!ci->local && !ci->state.canpickup(sents[i].type)) - { + if(!ci->local && !ci->state.canpickup(sents[i].type)) { sendf(sender, 1, "ri3", N_ITEMACC, i, -1); return false; } @@ -869,30 +655,21 @@ namespace server ci->state.pickup(sents[i].type); return true; } - static hashset<teaminfo> teaminfos; - - void clearteaminfo() - { + void clearteaminfo() { teaminfos.clear(); } - bool teamhasplayers(const char *team) { loopv(clients) if(!strcmp(clients[i]->team, team)) return true; return false; } - - bool pruneteaminfo() - { + bool pruneteaminfo() { int oldteams = teaminfos.numelems; enumerate(teaminfos, teaminfo, old, if(!old.frags && !teamhasplayers(old.team)) teaminfos.remove(old.team); ); return teaminfos.numelems < oldteams; } - - teaminfo *addteaminfo(const char *team) - { + teaminfo *addteaminfo(const char *team) { teaminfo *t = teaminfos.access(team); - if(!t) - { + if(!t) { if(teaminfos.numelems >= MAXTEAMS && !pruneteaminfo()) return NULL; t = &teaminfos[team]; copystring(t->team, team, sizeof(t->team)); @@ -900,13 +677,10 @@ namespace server } return t; } - - clientinfo *choosebestclient(float &bestrank) - { + clientinfo *choosebestclient(float &bestrank) { clientinfo *best = NULL; bestrank = -1; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.timeplayed<0) continue; float rank = ci->state.state!=CS_SPECTATOR ? ci->state.effectiveness/max(ci->state.timeplayed, 1) : -1; @@ -914,19 +688,14 @@ namespace server } return best; } - VAR(persistteams, 0, 0, 1); - - void autoteam() - { + void autoteam() { static const char * const teamnames[2] = {"good", "evil"}; vector<clientinfo *> team[2]; float teamrank[2] = {0, 0}; - for(int round = 0, remaining = clients.length(); remaining>=0; round++) - { + for(int round = 0, remaining = clients.length(); remaining>=0; round++) { int first = round&1, second = (round+1)&1, selected = 0; - while(teamrank[first] <= teamrank[second]) - { + while(teamrank[first] <= teamrank[second]) { float rank; clientinfo *ci = choosebestclient(rank); if(!ci) break; @@ -940,15 +709,12 @@ namespace server if(!selected) break; remaining -= selected; } - loopi(sizeof(team)/sizeof(team[0])) - { + loopi(sizeof(team)/sizeof(team[0])) { addteaminfo(teamnames[i]); - loopvj(team[i]) - { + loopvj(team[i]) { clientinfo *ci = team[i][j]; if(!strcmp(ci->team, teamnames[i])) continue; - if(persistteams && ci->team[0]) - { + if(persistteams && ci->team[0]) { addteaminfo(ci->team); continue; } @@ -957,29 +723,21 @@ namespace server } } } - - struct teamrank - { + struct teamrank { const char *name; float rank; int clients; - teamrank(const char *name) : name(name), rank(0), clients(0) {} }; - - const char *chooseworstteam(const char *suggest = NULL, clientinfo *exclude = NULL) - { + const char *chooseworstteam(clientinfo *exclude = NULL) { teamrank teamranks[2] = { teamrank("good"), teamrank("evil") }; const int numteams = sizeof(teamranks)/sizeof(teamranks[0]); - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci==exclude || ci->state.aitype!=AI_NONE || ci->state.state==CS_SPECTATOR || !ci->team[0]) continue; ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed; ci->state.lasttimeplayed = lastmillis; - - loopj(numteams) if(!strcmp(ci->team, teamranks[j].name)) - { + loopj(numteams) if(!strcmp(ci->team, teamranks[j].name)) { teamrank &ts = teamranks[j]; ts.rank += ci->state.effectiveness/max(ci->state.timeplayed, 1); ts.clients++; @@ -987,24 +745,19 @@ namespace server } } teamrank *worst = &teamranks[numteams-1]; - loopi(numteams-1) - { + loopi(numteams-1) { teamrank &ts = teamranks[i]; if(ts.rank < worst->rank || (ts.rank == worst->rank && ts.clients < worst->clients)) worst = &ts; } return worst->name; } - - void prunedemos(int extra = 0) - { + void prunedemos(int extra = 0) { int n = clamp(demos.length() + extra - maxdemos, 0, demos.length()); if(n <= 0) return; loopi(n) delete[] demos[i].data; demos.remove(0, n); } - - void adddemo() - { + void adddemo() { if(!demotmp) return; int len = (int)min(demotmp->size(), stream::offset((maxdemosize<<20) + 0x10000)); demofile &d = demos.add(); @@ -1019,22 +772,15 @@ namespace server demotmp->read(d.data, len); DELETEP(demotmp); } - - void enddemorecord() - { + void enddemorecord() { if(!demorecord) return; - DELETEP(demorecord); - if(!demotmp) return; if(!maxdemos || !maxdemosize) { DELETEP(demotmp); return; } - prunedemos(1); adddemo(); } - - void writedemo(int chan, void *data, int len) - { + void writedemo(int chan, void *data, int len) { if(!demorecord) return; int stamp[3] = { gamemillis, chan, len }; lilswap(stamp, 3); @@ -1042,86 +788,61 @@ namespace server demorecord->write(data, len); if(demorecord->rawtell() >= (maxdemosize<<20)) enddemorecord(); } - - void recordpacket(int chan, void *data, int len) - { + void recordpacket(int chan, void *data, int len) { writedemo(chan, data, len); } - int welcomepacket(packetbuf &p, clientinfo *ci); void sendwelcome(clientinfo *ci); - - void setupdemorecord() - { + void setupdemorecord() { if(!m_mp(gamemode) || m_edit) return; - demotmp = opentempfile("demorecord", "w+b"); if(!demotmp) return; - stream *f = opengzfile(NULL, "wb", demotmp); if(!f) { DELETEP(demotmp); return; } - sendservmsg("recording demo"); - demorecord = f; - demoheader hdr; memcpy(hdr.magic, DEMO_MAGIC, sizeof(hdr.magic)); hdr.version = DEMO_VERSION; hdr.protocol = PROTOCOL_VERSION; lilswap(&hdr.version, 2); demorecord->write(&hdr, sizeof(demoheader)); - packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); welcomepacket(p, NULL); writedemo(1, p.buf, p.len); } - - void listdemos(int cn) - { + void listdemos(int cn) { packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); putint(p, N_SENDDEMOLIST); putint(p, demos.length()); loopv(demos) sendstring(demos[i].info, p); sendpacket(cn, 1, p.finalize()); } - - void cleardemos(int n) - { - if(!n) - { + void cleardemos(int n) { + if(!n) { loopv(demos) delete[] demos[i].data; demos.shrink(0); sendservmsg("cleared all demos"); } - else if(demos.inrange(n-1)) - { + else if(demos.inrange(n-1)) { delete[] demos[n-1].data; demos.remove(n-1); sendservmsgf("cleared demo %d", n); } } - - static void freegetmap(ENetPacket *packet) - { - loopv(clients) - { + static void freegetmap(ENetPacket *packet) { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->getmap == packet) ci->getmap = NULL; } } - - static void freegetdemo(ENetPacket *packet) - { - loopv(clients) - { + static void freegetdemo(ENetPacket *packet) { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->getdemo == packet) ci->getdemo = NULL; } } - - void senddemo(clientinfo *ci, int num, int tag) - { + void senddemo(clientinfo *ci, int num, int tag) { if(ci->getdemo) return; if(!num) num = demos.length(); if(!demos.inrange(num-1)) return; @@ -1129,39 +850,28 @@ namespace server if((ci->getdemo = sendf(ci->clientnum, 2, "riim", N_SENDDEMO, tag, d.len, d.data))) ci->getdemo->freeCallback = freegetdemo; } - - void enddemoplayback() - { + void enddemoplayback() { if(!demoplayback) return; DELETEP(demoplayback); - loopv(clients) sendf(clients[i]->clientnum, 1, "ri3", N_DEMOPLAYBACK, 0, clients[i]->clientnum); - sendservmsg("demo playback finished"); - loopv(clients) sendwelcome(clients[i]); } - SVARP(demodir, "demo"); - - const char *getdemofile(const char *file, bool init) - { + const char *getdemofile(const char *file, bool init) { if(!demodir[0]) return NULL; static string buf; copystring(buf, demodir); int dirlen = strlen(buf); if(buf[dirlen] != '/' && buf[dirlen] != '\\' && dirlen+1 < (int)sizeof(buf)) { buf[dirlen++] = '/'; buf[dirlen] = '\0'; } - if(init) - { + if(init) { const char *dir = findfile(buf, "w"); if(!fileexists(dir, "w")) createdir(dir); } concatstring(buf, file); return buf; } - - void setupdemoplayback() - { + void setupdemoplayback() { if(demoplayback) return; demoheader hdr; string msg; @@ -1175,48 +885,37 @@ namespace server if(!demoplayback) formatstring(msg, "could not read demo \"%s\"", file); else if(demoplayback->read(&hdr, sizeof(demoheader))!=sizeof(demoheader) || memcmp(hdr.magic, DEMO_MAGIC, sizeof(hdr.magic))) formatstring(msg, "\"%s\" is not a demo file", file); - else - { + else { lilswap(&hdr.version, 2); if(hdr.version!=DEMO_VERSION) formatstring(msg, "demo \"%s\" requires an %s version of Cube 2: Sauerbraten", file, hdr.version<DEMO_VERSION ? "older" : "newer"); else if(hdr.protocol!=PROTOCOL_VERSION) formatstring(msg, "demo \"%s\" requires an %s version of Cube 2: Sauerbraten", file, hdr.protocol<PROTOCOL_VERSION ? "older" : "newer"); } - if(msg[0]) - { + if(msg[0]) { DELETEP(demoplayback); sendservmsg(msg); return; } - sendservmsgf("playing demo \"%s\"", file); - sendf(-1, 1, "ri3", N_DEMOPLAYBACK, 1, -1); - - if(demoplayback->read(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) - { + if(demoplayback->read(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) { enddemoplayback(); return; } lilswap(&nextplayback, 1); } - - void readdemo() - { + void readdemo() { if(!demoplayback) return; - while(gamemillis>=nextplayback) - { + while(gamemillis>=nextplayback) { int chan, len; if(demoplayback->read(&chan, sizeof(chan))!=sizeof(chan) || - demoplayback->read(&len, sizeof(len))!=sizeof(len)) - { + demoplayback->read(&len, sizeof(len))!=sizeof(len)) { enddemoplayback(); return; } lilswap(&chan, 1); lilswap(&len, 1); ENetPacket *packet = enet_packet_create(NULL, len+1, 0); - if(!packet || demoplayback->read(packet->data+1, len)!=size_t(len)) - { + if(!packet || demoplayback->read(packet->data+1, len)!=size_t(len)) { if(packet) enet_packet_destroy(packet); enddemoplayback(); return; @@ -1225,24 +924,19 @@ namespace server sendpacket(-1, chan, packet); if(!packet->referenceCount) enet_packet_destroy(packet); if(!demoplayback) break; - if(demoplayback->read(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) - { + if(demoplayback->read(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) { enddemoplayback(); return; } lilswap(&nextplayback, 1); } } - - void timeupdate(int secs) - { + void timeupdate(int secs) { if(!demoplayback) return; if(secs <= 0) interm = -1; else gamelimit = max(gamelimit, nextplayback + secs*1000); } - - void seekdemo(char *t) - { + void seekdemo(char *t) { if(!demoplayback) return; bool rev = *t == '-'; if(rev) t++; @@ -1251,170 +945,123 @@ namespace server else { secs = mins; mins = 0; } if(*t == '.') millis = strtoul(t+1, &t, 10); int offset = max(millis + (mins*60 + secs)*1000, 0), prevmillis = gamemillis; - if(rev) while(gamelimit - offset > gamemillis) - { + if(rev) while(gamelimit - offset > gamemillis) { gamemillis = gamelimit - offset; readdemo(); } - else if(offset > gamemillis) - { + else if(offset > gamemillis) { gamemillis = offset; readdemo(); } - if(gamemillis > prevmillis) - { + if(gamemillis > prevmillis) { if(!interm) sendf(-1, 1, "ri2", N_TIMEUP, max((gamelimit - gamemillis)/1000, 1)); } } - - ICOMMAND(seekdemo, "sN$", (char *t, int *numargs, ident *id), - { + ICOMMAND(seekdemo, "sN$", (char *t, int *numargs, ident *id), { if(*numargs > 0) seekdemo(t); - else - { + else { int secs = gamemillis/1000; defformatstring(str, "%d:%02d.%03d", secs/60, secs%60, gamemillis%1000); if(*numargs < 0) result(str); else printsvar(id, str); } }); - - void stopdemo() - { + void stopdemo() { if(m_demo) enddemoplayback(); else enddemorecord(); } - - void pausegame(bool val, clientinfo *ci = NULL) - { + void pausegame(bool val, clientinfo *ci = NULL) { if(gamepaused==val) return; gamepaused = val; sendf(-1, 1, "riii", N_PAUSEGAME, gamepaused ? 1 : 0, ci ? ci->clientnum : -1); } - - void checkpausegame() - { + void checkpausegame() { if(!gamepaused) return; int admins = 0; loopv(clients) if(clients[i]->privilege >= (restrictpausegame ? PRIV_ADMIN : PRIV_MASTER) || clients[i]->local) admins++; if(!admins) pausegame(false); } - - void forcepaused(bool paused) - { + void forcepaused(bool paused) { pausegame(paused); } - bool ispaused() { return gamepaused; } - - void changegamespeed(int val, clientinfo *ci = NULL) - { + void changegamespeed(int val, clientinfo *ci = NULL) { val = clamp(val, 10, 1000); if(gamespeed==val) return; gamespeed = val; sendf(-1, 1, "riii", N_GAMESPEED, gamespeed, ci ? ci->clientnum : -1); } - - void forcegamespeed(int speed) - { + void forcegamespeed(int speed) { changegamespeed(speed); } - int scaletime(int t) { return t*gamespeed; } - SVAR(serverauth, ""); - - struct userkey - { + struct userkey { char *name; char *desc; - userkey() : name(NULL), desc(NULL) {} userkey(char *name, char *desc) : name(name), desc(desc) {} }; - static inline uint hthash(const userkey &k) { return ::hthash(k.name); } static inline bool htcmp(const userkey &x, const userkey &y) { return !strcmp(x.name, y.name) && !strcmp(x.desc, y.desc); } - - struct userinfo : userkey - { + struct userinfo : userkey { void *pubkey; int privilege; - userinfo() : pubkey(NULL), privilege(PRIV_NONE) {} ~userinfo() { delete[] name; delete[] desc; if(pubkey) freepubkey(pubkey); } }; hashset<userinfo> users; - - void adduser(char *name, char *desc, char *pubkey, char *priv) - { + void adduser(char *name, char *desc, char *pubkey, char *priv) { userkey key(name, desc); userinfo &u = users[key]; if(u.pubkey) { freepubkey(u.pubkey); u.pubkey = NULL; } if(!u.name) u.name = newstring(name); if(!u.desc) u.desc = newstring(desc); u.pubkey = parsepubkey(pubkey); - switch(priv[0]) - { + switch(priv[0]) { case 'a': case 'A': u.privilege = PRIV_ADMIN; break; case 'm': case 'M': default: u.privilege = PRIV_AUTH; break; case 'n': case 'N': u.privilege = PRIV_NONE; break; } } COMMAND(adduser, "ssss"); - - void clearusers() - { + void clearusers() { users.clear(); } COMMAND(clearusers, ""); - - void hashpassword(int cn, int sessionid, const char *pwd, char *result, int maxlen) - { + void hashpassword(int cn, int sessionid, const char *pwd, char *result, int maxlen) { char buf[2*sizeof(string)]; formatstring(buf, "%d %d ", cn, sessionid); concatstring(buf, pwd, sizeof(buf)); if(!hashstring(buf, result, maxlen)) *result = '\0'; } - - bool checkpassword(clientinfo *ci, const char *wanted, const char *given) - { + bool checkpassword(clientinfo *ci, const char *wanted, const char *given) { string hash; hashpassword(ci->clientnum, ci->sessionid, wanted, hash, sizeof(hash)); return !strcmp(hash, given); } - - void revokemaster(clientinfo *ci) - { + void revokemaster(clientinfo *ci) { ci->privilege = PRIV_NONE; if(ci->state.state==CS_SPECTATOR && !ci->local) aiman::removeai(ci); } - extern void connected(clientinfo *ci); - - bool setmaster(clientinfo *ci, bool val, const char *pass = "", const char *authname = NULL, const char *authdesc = NULL, int authpriv = PRIV_MASTER, bool force = false, bool trial = false) - { + bool setmaster(clientinfo *ci, bool val, const char *pass = "", const char *authname = NULL, const char *authdesc = NULL, int authpriv = PRIV_MASTER, bool force = false, bool trial = false) { if(authname && !val) return false; const char *name = ""; - if(val) - { + if(val) { bool haspass = adminpass[0] && checkpassword(ci, adminpass, pass); int wantpriv = ci->local || haspass ? PRIV_ADMIN : authpriv; if(wantpriv <= ci->privilege) return true; - else if(wantpriv <= PRIV_MASTER && !force) - { - if(ci->state.state==CS_SPECTATOR) - { + else if(wantpriv <= PRIV_MASTER && !force) { + if(ci->state.state==CS_SPECTATOR) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "Spectators may not claim master."); return false; } - loopv(clients) if(ci!=clients[i] && clients[i]->privilege) - { + loopv(clients) if(ci!=clients[i] && clients[i]->privilege) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "Master is already claimed."); return false; } - if(!authname && !(mastermask&MM_AUTOAPPROVE) && !ci->privilege && !ci->local) - { + if(!authname && !(mastermask&MM_AUTOAPPROVE) && !ci->privilege && !ci->local) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "This server requires you to use the \"/auth\" command to claim master."); return false; } @@ -1423,8 +1070,7 @@ namespace server ci->privilege = wantpriv; name = privname(ci->privilege); } - else - { + else { if(!ci->privilege) return false; if(trial) return true; name = privname(ci->privilege); @@ -1432,14 +1078,12 @@ namespace server } bool hasmaster = false; loopv(clients) if(clients[i]->local || clients[i]->privilege >= PRIV_MASTER) hasmaster = true; - if(!hasmaster) - { + if(!hasmaster) { mastermode = MM_OPEN; allowedips.shrink(0); } string msg; - if(val && authname) - { + if(val && authname) { if(authdesc && authdesc[0]) formatstring(msg, "%s claimed %s as '\fs\f5%s\fr' [\fs\f0%s\fr]", colorname(ci), name, authname, authdesc); else formatstring(msg, "%s claimed %s as '\fs\f5%s\fr'", colorname(ci), name, authname); } @@ -1449,8 +1093,7 @@ namespace server sendstring(msg, p); putint(p, N_CURRENTMASTER); putint(p, mastermode); - loopv(clients) if(clients[i]->privilege >= PRIV_MASTER) - { + loopv(clients) if(clients[i]->privilege >= PRIV_MASTER) { putint(p, clients[i]->clientnum); putint(p, clients[i]->privilege); } @@ -1459,24 +1102,18 @@ namespace server checkpausegame(); return true; } - - bool trykick(clientinfo *ci, int victim, const char *reason = NULL, const char *authname = NULL, const char *authdesc = NULL, int authpriv = PRIV_NONE, bool trial = false) - { + bool trykick(clientinfo *ci, int victim, const char *reason = NULL, const char *authname = NULL, const char *authdesc = NULL, int authpriv = PRIV_NONE, bool trial = false) { int priv = ci->privilege; - if(authname) - { + if(authname) { if(priv >= authpriv || ci->local) authname = authdesc = NULL; else priv = authpriv; } - if((priv || ci->local) && ci->clientnum!=victim) - { + if((priv || ci->local) && ci->clientnum!=victim) { clientinfo *vinfo = (clientinfo *)getclientinfo(victim); - if(vinfo && vinfo->connected && (priv >= vinfo->privilege || ci->local) && vinfo->privilege < PRIV_ADMIN && !vinfo->local) - { + if(vinfo && vinfo->connected && (priv >= vinfo->privilege || ci->local) && vinfo->privilege < PRIV_ADMIN && !vinfo->local) { if(trial) return true; string kicker; - if(authname) - { + if(authname) { if(authdesc && authdesc[0]) formatstring(kicker, "%s as '\fs\f5%s\fr' [\fs\f0%s\fr]", colorname(ci), authname, authdesc); else formatstring(kicker, "%s as '\fs\f5%s\fr'", colorname(ci), authname); } @@ -1485,23 +1122,18 @@ namespace server else sendservmsgf("%s kicked %s", kicker, colorname(vinfo)); uint ip = getclientip(victim); addban(ip, 4*60*60000); - kickclients(ip, ci, priv); + kickclients(ci, priv); } } return false; } - - savedscore *findscore(clientinfo *ci, bool insert) - { + savedscore *findscore(clientinfo *ci, bool insert) { uint ip = getclientip(ci->clientnum); if(!ip && !ci->local) return 0; - if(!insert) - { - loopv(clients) - { + if(!insert) { + loopv(clients) { clientinfo *oi = clients[i]; - if(oi->clientnum != ci->clientnum && getclientip(oi->clientnum) == ip && !strcmp(oi->name, ci->name)) - { + if(oi->clientnum != ci->clientnum && getclientip(oi->clientnum) == ip && !strcmp(oi->name, ci->name)) { oi->state.timeplayed += lastmillis - oi->state.lasttimeplayed; oi->state.lasttimeplayed = lastmillis; static savedscore curscore; @@ -1510,8 +1142,7 @@ namespace server } } } - loopv(scores) - { + loopv(scores) { savedscore &sc = scores[i]; if(sc.ip == ip && !strcmp(sc.name, ci->name)) return ≻ } @@ -1521,30 +1152,22 @@ namespace server copystring(sc.name, ci->name); return ≻ } - - void savescore(clientinfo *ci) - { + void savescore(clientinfo *ci) { savedscore *sc = findscore(ci, true); if(sc) sc->save(ci->state); } - - static struct msgfilter - { + static struct msgfilter { uchar msgmask[NUMMSG]; - - msgfilter(int msg, ...) - { + msgfilter(int msg, ...) { memset(msgmask, 0, sizeof(msgmask)); va_list msgs; va_start(msgs, msg); - for(uchar val = 1; msg < NUMMSG; msg = va_arg(msgs, int)) - { + for(uchar val = 1; msg < NUMMSG; msg = va_arg(msgs, int)) { if(msg < 0) val = uchar(-msg); else msgmask[msg] = val; } va_end(msgs); } - uchar operator[](int msg) const { return msg >= 0 && msg < NUMMSG ? msgmask[msg] : 0; } } msgfilter(-1, N_CONNECT, N_SERVINFO, N_INITCLIENT, N_WELCOME, N_MAPCHANGE, N_SERVMSG, N_DAMAGE, N_HITPUSH, N_SHOTFX, N_EXPLODEFX, N_DIED, N_SPAWNSTATE, N_FORCEDEATH, N_TEAMINFO, N_ITEMACC, N_ITEMSPAWN, N_TIMEUP, N_CDIS, N_CURRENTMASTER, N_PONG, N_RESUME, @@ -1553,13 +1176,9 @@ namespace server N_NEWMAP, N_GETMAP, N_SENDMAP, N_CLIPBOARD, -3, N_EDITENT, N_EDITF, N_EDITT, N_EDITM, N_FLIP, N_COPY, N_PASTE, N_ROTATE, N_REPLACE, N_DELCUBE, N_EDITVAR, N_EDITVSLOT, N_UNDO, N_REDO, -4, N_POS, NUMMSG), connectfilter(-1, N_CONNECT, -2, N_AUTHANS, -3, N_PING, NUMMSG); - - int checktype(int type, clientinfo *ci) - { - if(ci) - { - if(!ci->connected) switch(connectfilter[type]) - { + int checktype(int type, clientinfo *ci) { + if(ci) { + if(!ci->connected) switch(connectfilter[type]) { // allow only before authconnect case 1: return !ci->connectauth ? type : -1; // allow only during authconnect @@ -1571,8 +1190,7 @@ namespace server } if(ci->local) return type; } - switch(msgfilter[type]) - { + switch(msgfilter[type]) { // server-only messages case 1: return ci ? -1 : type; // only allowed in coop-edit @@ -1585,54 +1203,41 @@ namespace server if(ci && ++ci->overflow >= 200) return -2; return type; } - - struct worldstate - { + 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) - { + void cleanworldstate(ENetPacket *packet) { + loopv(worldstates) { worldstate &ws = worldstates[i]; if(!ws.contains(packet->data)) continue; ws.uses--; - if(ws.uses <= 0) - { + if(ws.uses <= 0) { ws.cleanup(); worldstates.removeunordered(i); } break; } } - - void flushclientposition(clientinfo &ci) - { + void flushclientposition(clientinfo &ci) { if(ci.position.empty() || (!hasnonlocalclients() && !demorecord)) return; packetbuf p(ci.position.length(), 0); p.put(ci.position.getbuf(), ci.position.length()); ci.position.setsize(0); sendpacket(-1, 0, p.finalize(), ci.ownernum); } - - static void sendpositions(worldstate &ws, ucharbuf &wsbuf) - { + static void sendpositions(worldstate &ws, ucharbuf &wsbuf) { if(wsbuf.empty()) return; int wslen = wsbuf.length(); recordpacket(0, wsbuf.buf, wslen); wsbuf.put(wsbuf.buf, wslen); - loopv(clients) - { + loopv(clients) { clientinfo &ci = *clients[i]; if(ci.state.aitype != AI_NONE) continue; uchar *data = wsbuf.buf; @@ -1646,9 +1251,7 @@ namespace server } wsbuf.offset(wsbuf.length()); } - - static inline void addposition(worldstate &ws, ucharbuf &wsbuf, int mtu, clientinfo &bi, clientinfo &ci) - { + 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(); @@ -1658,15 +1261,12 @@ namespace server if(ci.wsdata < wsbuf.buf) { ci.wsdata = &wsbuf.buf[offset]; ci.wslen = len; } else ci.wslen += len; } - - static void sendmessages(worldstate &ws, ucharbuf &wsbuf) - { + 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) - { + loopv(clients) { clientinfo &ci = *clients[i]; if(ci.state.aitype != AI_NONE) continue; uchar *data = wsbuf.buf; @@ -1680,9 +1280,7 @@ namespace server } wsbuf.offset(wsbuf.length()); } - - static inline void addmessages(worldstate &ws, ucharbuf &wsbuf, int mtu, clientinfo &bi, clientinfo &ci) - { + 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(); @@ -1695,20 +1293,16 @@ namespace server if(ci.wsdata < wsbuf.buf) { ci.wsdata = &wsbuf.buf[offset]; ci.wslen = len; } else ci.wslen += len; } - - bool buildworldstate() - { + bool buildworldstate() { int wsmax = 0; - loopv(clients) - { + 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) - { + if(wsmax <= 0) { reliablemessages = false; return false; } @@ -1717,16 +1311,14 @@ namespace server int mtu = getservermtu() - 100; if(mtu <= 0) mtu = ws.len; ucharbuf wsbuf(ws.data, ws.len); - loopv(clients) - { + loopv(clients) { 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); } sendpositions(ws, wsbuf); - loopv(clients) - { + loopv(clients) { clientinfo &ci = *clients[i]; if(ci.state.aitype != AI_NONE) continue; addmessages(ws, wsbuf, mtu, ci, ci); @@ -1739,9 +1331,7 @@ namespace server worldstates.drop(); return false; } - - bool sendpackets(bool force) - { + bool sendpackets(bool force) { if(clients.empty() || (!hasnonlocalclients() && !demorecord)) return false; enet_uint32 curtime = enet_time_get()-lastsend; if(curtime<33 && !force) return false; @@ -1749,10 +1339,8 @@ namespace server lastsend += curtime - (curtime%33); return flush; } - template<class T> - void sendstate(gamestate &gs, T &p) - { + void sendstate(gamestate &gs, T &p) { putint(p, gs.lifesequence); putint(p, gs.health); putint(p, gs.maxhealth); @@ -1762,16 +1350,12 @@ namespace server putint(p, gs.gunselect); loopi(GUN_PISTOL-GUN_SG+1) putint(p, gs.ammo[GUN_SG+i]); } - - void spawnstate(clientinfo *ci) - { + void spawnstate(clientinfo *ci) { gamestate &gs = ci->state; gs.spawnstate(gamemode); gs.lifesequence = (gs.lifesequence + 1)&0x7F; } - - void sendspawn(clientinfo *ci) - { + void sendspawn(clientinfo *ci) { gamestate &gs = ci->state; spawnstate(ci); sendf(ci->ownernum, 1, "rii8v", N_SPAWNSTATE, ci->clientnum, gs.lifesequence, @@ -1780,18 +1364,13 @@ namespace server gs.gunselect, GUN_PISTOL-GUN_SG+1, &gs.ammo[GUN_SG]); gs.lastspawn = gamemillis; } - - void sendwelcome(clientinfo *ci) - { + void sendwelcome(clientinfo *ci) { packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); int chan = welcomepacket(p, ci); sendpacket(ci->clientnum, chan, p.finalize()); } - - void putinitclient(clientinfo *ci, packetbuf &p) - { - if(ci->state.aitype != AI_NONE) - { + void putinitclient(clientinfo *ci, packetbuf &p) { + if(ci->state.aitype != AI_NONE) { putint(p, N_INITAI); putint(p, ci->clientnum); putint(p, ci->ownernum); @@ -1801,8 +1380,7 @@ namespace server sendstring(ci->name, p); sendstring(ci->team, p); } - else - { + else { putint(p, N_INITCLIENT); putint(p, ci->clientnum); sendstring(ci->name, p); @@ -1810,57 +1388,43 @@ namespace server putint(p, ci->playermodel); } } - - void welcomeinitclient(packetbuf &p, int exclude = -1) - { - loopv(clients) - { + void welcomeinitclient(packetbuf &p, int exclude = -1) { + loopv(clients) { clientinfo *ci = clients[i]; if(!ci->connected || ci->clientnum == exclude) continue; - putinitclient(ci, p); } } - - bool hasmap(clientinfo *ci) - { + bool hasmap(clientinfo *ci) { return (m_edit && (clients.length() > 0 || ci->local)) || (smapname[0] && (!m_timed || gamemillis < gamelimit || (ci->state.state==CS_SPECTATOR && !ci->privilege && !ci->local) || numclients(ci->clientnum, true, true, true))); } - - int welcomepacket(packetbuf &p, clientinfo *ci) - { + int welcomepacket(packetbuf &p, clientinfo *ci) { putint(p, N_WELCOME); putint(p, N_MAPCHANGE); sendstring(smapname, p); putint(p, gamemode); putint(p, notgotitems ? 1 : 0); - if(!ci || (m_timed && smapname[0])) - { + if(!ci || (m_timed && smapname[0])) { putint(p, N_TIMEUP); putint(p, gamemillis < gamelimit && !interm ? max((gamelimit - gamemillis)/1000, 1) : 0); } - if(!notgotitems) - { + if(!notgotitems) { putint(p, N_ITEMLIST); - loopv(sents) if(sents[i].spawned) - { + loopv(sents) if(sents[i].spawned) { putint(p, i); putint(p, sents[i].type); } putint(p, -1); } bool hasmaster = false; - if(mastermode != MM_OPEN) - { + if(mastermode != MM_OPEN) { putint(p, N_CURRENTMASTER); putint(p, mastermode); hasmaster = true; } - loopv(clients) if(clients[i]->privilege >= PRIV_MASTER) - { - if(!hasmaster) - { + loopv(clients) if(clients[i]->privilege >= PRIV_MASTER) { + if(!hasmaster) { putint(p, N_CURRENTMASTER); putint(p, mastermode); hasmaster = true; @@ -1869,35 +1433,30 @@ namespace server putint(p, clients[i]->privilege); } if(hasmaster) putint(p, -1); - if(gamepaused) - { + if(gamepaused) { putint(p, N_PAUSEGAME); putint(p, 1); putint(p, -1); } - if(gamespeed != 100) - { + if(gamespeed != 100) { putint(p, N_GAMESPEED); putint(p, gamespeed); putint(p, -1); } - if(m_teammode) - { + if(m_teammode) { putint(p, N_TEAMINFO); enumerate(teaminfos, teaminfo, t, if(t.frags) { sendstring(t.team, p); putint(p, t.frags); } ); sendstring("", p); } - if(ci) - { + if(ci) { putint(p, N_SETTEAM); putint(p, ci->clientnum); sendstring(ci->team, p); putint(p, -1); } - if(ci && (m_demo || m_mp(gamemode)) && ci->state.state!=CS_SPECTATOR) - { + if(ci && (m_demo || m_mp(gamemode)) && ci->state.state!=CS_SPECTATOR) { gamestate &gs = ci->state; spawnstate(ci); putint(p, N_SPAWNSTATE); @@ -1905,18 +1464,15 @@ namespace server sendstate(gs, p); gs.lastspawn = gamemillis; } - if(ci && ci->state.state==CS_SPECTATOR) - { + if(ci && ci->state.state==CS_SPECTATOR) { putint(p, N_SPECTATOR); putint(p, ci->clientnum); putint(p, 1); sendf(-1, 1, "ri3x", N_SPECTATOR, ci->clientnum, 1, ci->clientnum); } - if(!ci || clients.length()>1) - { + if(!ci || clients.length()>1) { putint(p, N_RESUME); - loopv(clients) - { + loopv(clients) { clientinfo *oi = clients[i]; if(ci && oi->clientnum==ci->clientnum) continue; putint(p, oi->clientnum); @@ -1932,21 +1488,16 @@ namespace server } return 1; } - - bool restorescore(clientinfo *ci) - { + bool restorescore(clientinfo *ci) { //if(ci->local) return false; savedscore *sc = findscore(ci, false); - if(sc) - { + if(sc) { sc->restore(ci->state); return true; } return false; } - - void sendresume(clientinfo *ci) - { + void sendresume(clientinfo *ci) { gamestate &gs = ci->state; sendf(-1, 1, "ri3i5i6vi", N_RESUME, ci->clientnum, gs.state, gs.frags, gs.flags, gs.deaths, gs.quadmillis, @@ -1955,22 +1506,17 @@ namespace server gs.armour, gs.maxarmour, gs.armourtype, gs.gunselect, GUN_PISTOL-GUN_SG+1, &gs.ammo[GUN_SG], -1); } - - void sendinitclient(clientinfo *ci) - { + void sendinitclient(clientinfo *ci) { packetbuf p(MAXTRANS, ENET_PACKET_FLAG_RELIABLE); putinitclient(ci, p); sendpacket(-1, 1, p.finalize(), ci->clientnum); } - - void loaditems() - { + void loaditems() { resetitems(); notgotitems = true; if(m_edit || !loadents(smapname, ments, &mcrc)) return; - loopv(ments) if(canspawnitem(ments[i].type)) - { + loopv(ments) if(canspawnitem(ments[i].type)) { server_entity se = { NOTUSED, 0, false }; while(sents.length()<=i) sents.add(se); sents[i].type = ments[i].type; @@ -1979,14 +1525,11 @@ namespace server } notgotitems = false; } - - void changemap(const char *s, int mode) - { + void changemap(const char *s, int mode) { stopdemo(); pausegame(false); changegamespeed(100); aiman::clearai(); - gamemode = mode; gamemillis = 0; gamelimit = 10*60000; @@ -1997,50 +1540,36 @@ namespace server scores.shrink(0); shouldcheckteamkills = false; teamkills.shrink(0); - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed; } - if(!m_mp(gamemode)) kicknonlocalclients(DISC_LOCAL); - sendf(-1, 1, "risii", N_MAPCHANGE, smapname, gamemode, 1); - clearteaminfo(); if(m_teammode) autoteam(); - if(m_timed && smapname[0]) sendf(-1, 1, "ri2", N_TIMEUP, gamemillis < gamelimit && !interm ? max((gamelimit - gamemillis)/1000, 1) : 0); - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; ci->mapchange(); ci->state.lasttimeplayed = lastmillis; if(m_mp(gamemode) && ci->state.state!=CS_SPECTATOR) sendspawn(ci); } - aiman::changemap(); - - if(m_demo) - { + if(m_demo) { if(clients.length()) setupdemoplayback(); } - else - { + else { if(demonextmatch) setupdemorecord(); demonextmatch = autorecorddemo!=0; } } - - void rotatemap(bool next) - { - if(!maprotations.inrange(curmaprotation)) - { + void rotatemap(bool next) { + if(!maprotations.inrange(curmaprotation)) { changemap("", 1); return; } - if(next) - { + if(next) { curmaprotation = findmaprotation(gamemode, smapname); if(curmaprotation >= 0) nextmaprotation(); else curmaprotation = smapname[0] ? max(findmaprotation(gamemode, ""), 0) : 0; @@ -2048,29 +1577,23 @@ namespace server maprotation &rot = maprotations[curmaprotation]; changemap(rot.map, rot.findmode(gamemode)); } - - struct votecount - { + struct votecount { char *map; int mode, count; votecount() {} votecount(char *s, int n) : map(s), mode(n), count(0) {} }; - - void checkvotes(bool force = false) - { + void checkvotes(bool force = false) { vector<votecount> votes; int maxvotes = 0; - loopv(clients) - { + loopv(clients) { clientinfo *oi = clients[i]; if(oi->state.state==CS_SPECTATOR && !oi->privilege && !oi->local) continue; if(oi->state.aitype!=AI_NONE) continue; maxvotes++; if(!m_valid(oi->modevote)) continue; votecount *vc = NULL; - loopvj(votes) if(!strcmp(oi->mapvote, votes[j].map) && oi->modevote==votes[j].mode) - { + loopvj(votes) if(!strcmp(oi->mapvote, votes[j].map) && oi->modevote==votes[j].mode) { vc = &votes[j]; break; } @@ -2079,24 +1602,19 @@ namespace server } votecount *best = NULL; loopv(votes) if(!best || votes[i].count > best->count || (votes[i].count == best->count && rnd(2))) best = &votes[i]; - if(force || (best && best->count > maxvotes/2)) - { + if(force || (best && best->count > maxvotes/2)) { sendpackets(true); if(demorecord) enddemorecord(); - if(best && (best->count > (force ? 1 : maxvotes/2))) - { + if(best && (best->count > (force ? 1 : maxvotes/2))) { sendservmsg(force ? "vote passed by default" : "vote passed by majority"); changemap(best->map, best->mode); } else rotatemap(true); } } - - void forcemap(const char *map, int mode) - { + void forcemap(const char *map, int mode) { stopdemo(); - if(!map[0] && !m_check(mode, M_EDIT)) - { + if(!map[0] && !m_check(mode, M_EDIT)) { int idx = findmaprotation(mode, smapname); if(idx < 0 && smapname[0]) idx = findmaprotation(mode, ""); if(idx < 0) return; @@ -2105,54 +1623,43 @@ namespace server if(hasnonlocalclients()) sendservmsgf("local player forced %s on map %s", modename(mode), map[0] ? map : "[new map]"); changemap(map, mode); } - - void vote(const char *map, int reqmode, int sender) - { + void vote(const char *map, int reqmode, int sender) { clientinfo *ci = getinfo(sender); if(!ci || (ci->state.state==CS_SPECTATOR && !ci->privilege && !ci->local) || (!ci->local && !m_mp(reqmode))) return; if(!m_valid(reqmode)) return; - if(!map[0] && !m_check(reqmode, M_EDIT)) - { + if(!map[0] && !m_check(reqmode, M_EDIT)) { int idx = findmaprotation(reqmode, smapname); if(idx < 0 && smapname[0]) idx = findmaprotation(reqmode, ""); if(idx < 0) return; map = maprotations[idx].map; } - if(lockmaprotation && !ci->local && ci->privilege < (lockmaprotation > 1 ? PRIV_ADMIN : PRIV_MASTER) && findmaprotation(reqmode, map) < 0) - { + if(lockmaprotation && !ci->local && ci->privilege < (lockmaprotation > 1 ? PRIV_ADMIN : PRIV_MASTER) && findmaprotation(reqmode, map) < 0) { sendf(sender, 1, "ris", N_SERVMSG, "This server has locked the map rotation."); return; } copystring(ci->mapvote, map); ci->modevote = reqmode; - if(ci->local || (ci->privilege && mastermode>=MM_VETO)) - { + if(ci->local || (ci->privilege && mastermode>=MM_VETO)) { sendpackets(true); if(demorecord) enddemorecord(); if(!ci->local || hasnonlocalclients()) sendservmsgf("%s forced %s on map %s", colorname(ci), modename(ci->modevote), ci->mapvote[0] ? ci->mapvote : "[new map]"); changemap(ci->mapvote, ci->modevote); } - else - { + else { sendservmsgf("%s suggests %s on map %s (select map to vote)", colorname(ci), modename(reqmode), map[0] ? map : "[new map]"); checkvotes(); } } - VAR(overtime, 0, 0, 1); - - bool checkovertime() - { + bool checkovertime() { if(!m_timed || !overtime) return false; const char* topteam = NULL; int topscore = INT_MIN; bool tied = false; - if(m_teammode) - { + if(m_teammode) { vector<teamscore> scores; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.state==CS_SPECTATOR || !ci->team[0]) continue; int score = 0; @@ -2161,10 +1668,8 @@ namespace server else if(score == topscore && strcmp(ci->team, topteam)) tied = true; } } - else - { - loopv(clients) - { + else { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.state==CS_SPECTATOR) continue; int score = ci->state.frags; @@ -2178,39 +1683,30 @@ namespace server sendf(-1, 1, "ri2", N_TIMEUP, max((gamelimit - gamemillis)/1000, 1)); return true; } - - void checkintermission(bool force = false) - { - if(gamemillis >= gamelimit && !interm && (force || !checkovertime())) - { + void checkintermission(bool force = false) { + if(gamemillis >= gamelimit && !interm && (force || !checkovertime())) { sendf(-1, 1, "ri2", N_TIMEUP, 0); changegamespeed(100); interm = gamemillis + 10000; } } - void startintermission() { gamelimit = min(gamelimit, gamemillis); checkintermission(true); } - - void dodamage(clientinfo *target, clientinfo *actor, int damage, int gun, const vec &hitpush = vec(0, 0, 0)) - { + void dodamage(clientinfo *target, clientinfo *actor, int damage, int gun, const vec &hitpush = vec(0, 0, 0)) { gamestate &ts = target->state; ts.dodamage(damage); if(target!=actor && !isteam(target->team, actor->team)) actor->state.damage += damage; sendf(-1, 1, "ri6", N_DAMAGE, target->clientnum, actor->clientnum, damage, ts.armour, ts.health); if(target==actor) target->setpushed(); - else if(!hitpush.iszero()) - { + else if(!hitpush.iszero()) { ivec v(vec(hitpush).rescale(DNF)); sendf(ts.health<=0 ? -1 : target->ownernum, 1, "ri7", N_HITPUSH, target->clientnum, gun, damage, v.x, v.y, v.z); target->setpushed(); } - if(ts.health<=0) - { + if(ts.health<=0) { target->state.deaths++; int fragvalue = (target==actor || isteam(target->team, actor->team) ? -1 : 1); actor->state.frags += fragvalue; - if(fragvalue>0) - { + if(fragvalue>0) { int friends = 0, enemies = 0; // note: friends also includes the fragger if(m_teammode) loopv(clients) if(strcmp(clients[i]->team, actor->team)) enemies++; else friends++; else { friends = 1; enemies = clients.length()-1; } @@ -2222,8 +1718,7 @@ namespace server target->position.setsize(0); ts.state = CS_DEAD; ts.lastdeath = gamemillis; - if(actor!=target && isteam(actor->team, target->team)) - { + if(actor!=target && isteam(actor->team, target->team)) { actor->state.teamkills++; addteamkill(actor, target, 1); } @@ -2232,9 +1727,7 @@ namespace server // ts.respawn(); } } - - void suicide(clientinfo *ci) - { + void suicide(clientinfo *ci) { gamestate &gs = ci->state; if(gs.state!=CS_ALIVE) return; int fragvalue = -1; @@ -2248,39 +1741,29 @@ namespace server gs.lastdeath = gamemillis; gs.respawn(); } - - void suicideevent::process(clientinfo *ci) - { + void suicideevent::process(clientinfo *ci) { suicide(ci); } - - void explodeevent::process(clientinfo *ci) - { + void explodeevent::process(clientinfo *ci) { gamestate &gs = ci->state; - switch(gun) - { + switch(gun) { case GUN_RL: if(!gs.rockets.remove(id)) return; break; - case GUN_GL: if(!gs.grenades.remove(id)) return; break; - default: return; } sendf(-1, 1, "ri4x", N_EXPLODEFX, ci->clientnum, gun, id, ci->ownernum); - loopv(hits) - { + loopv(hits) { hitinfo &h = hits[i]; clientinfo *target = getinfo(h.target); if(!target || target->state.state!=CS_ALIVE || h.lifesequence!=target->state.lifesequence || h.dist<0 || h.dist>guns[gun].exprad) continue; - bool dup = false; loopj(i) if(hits[j].target==h.target) { dup = true; break; } if(dup) continue; - int damage = guns[gun].damage; if(gs.quadmillis) damage *= 4; damage = int(damage*(1-h.dist/EXP_DISTSCALE/guns[gun].exprad)); @@ -2288,9 +1771,7 @@ namespace server dodamage(target, ci, damage, gun, h.dir); } } - - void shotevent::process(clientinfo *ci) - { + void shotevent::process(clientinfo *ci) { gamestate &gs = ci->state; int wait = millis - gs.lastshot; if(!gs.isalive(gamemillis) || @@ -2306,19 +1787,15 @@ namespace server int(to.x*DMF), int(to.y*DMF), int(to.z*DMF), ci->ownernum); gs.shotdamage += guns[gun].damage*(gs.quadmillis ? 4 : 1)*guns[gun].rays; - switch(gun) - { + switch(gun) { case GUN_RL: gs.rockets.add(id); break; case GUN_GL: gs.grenades.add(id); break; - default: - { + default: { int totalrays = 0, maxrays = guns[gun].rays; - loopv(hits) - { + loopv(hits) { hitinfo &h = hits[i]; clientinfo *target = getinfo(h.target); if(!target || target->state.state!=CS_ALIVE || h.lifesequence!=target->state.lifesequence || h.rays<1 || h.dist > guns[gun].range + 1) continue; - totalrays += h.rays; if(totalrays>maxrays) continue; int damage = h.rays*guns[gun].damage; @@ -2329,65 +1806,46 @@ namespace server } } } - - void pickupevent::process(clientinfo *ci) - { + void pickupevent::process(clientinfo *ci) { gamestate &gs = ci->state; if(m_mp(gamemode) && !gs.isalive(gamemillis)) return; pickup(ent, ci->clientnum); } - - bool gameevent::flush(clientinfo *ci, int fmillis) - { + bool gameevent::flush(clientinfo *ci, int fmillis) { + (void) fmillis; process(ci); return true; } - - bool timedevent::flush(clientinfo *ci, int fmillis) - { + bool timedevent::flush(clientinfo *ci, int fmillis) { if(millis > fmillis) return false; - else if(millis >= ci->lastevent) - { + else if(millis >= ci->lastevent) { ci->lastevent = millis; process(ci); } return true; } - - void clearevent(clientinfo *ci) - { + void clearevent(clientinfo *ci) { delete ci->events.remove(0); } - - void flushevents(clientinfo *ci, int millis) - { - while(ci->events.length()) - { + void flushevents(clientinfo *ci, int millis) { + while(ci->events.length()) { gameevent *ev = ci->events[0]; if(ev->flush(ci, millis)) clearevent(ci); else break; } } - - void processevents() - { - loopv(clients) - { + void processevents() { + loopv(clients) { clientinfo *ci = clients[i]; if(curtime>0 && ci->state.quadmillis) ci->state.quadmillis = max(ci->state.quadmillis-curtime, 0); flushevents(ci, gamemillis); } } - - void cleartimedevents(clientinfo *ci) - { + void cleartimedevents(clientinfo *ci) { int keep = 0; - loopv(ci->events) - { - if(ci->events[i]->keepable()) - { - if(keep < i) - { + loopv(ci->events) { + if(ci->events[i]->keepable()) { + if(keep < i) { for(int j = keep; j < i; j++) delete ci->events[j]; ci->events.remove(keep, i - keep); i = keep; @@ -2399,31 +1857,22 @@ namespace server while(ci->events.length() > keep) delete ci->events.pop(); ci->timesync = false; } - - void serverupdate() - { - if(shouldstep && !gamepaused) - { + void serverupdate() { + if(shouldstep && !gamepaused) { gamemillis += curtime; - if(m_demo) readdemo(); - else if(!m_timed || gamemillis < gamelimit) - { + else if(!m_timed || gamemillis < gamelimit) { processevents(); - if(curtime) - { - loopv(sents) if(sents[i].spawntime) // spawn entities when timer reached - { + if(curtime) { + loopv(sents) if(sents[i].spawntime) { // spawn entities when timer reached { int oldtime = sents[i].spawntime; sents[i].spawntime -= curtime; - if(sents[i].spawntime<=0) - { + if(sents[i].spawntime<=0) { sents[i].spawntime = 0; sents[i].spawned = true; sendf(-1, 1, "ri2", N_ITEMSPAWN, i); } - else if(sents[i].spawntime<=10000 && oldtime>10000 && (sents[i].type==I_QUAD || sents[i].type==I_BOOST)) - { + else if(sents[i].spawntime<=10000 && oldtime>10000 && (sents[i].type==I_QUAD || sents[i].type==I_BOOST)) { sendf(-1, 1, "ri2", N_ANNOUNCE, sents[i].type); } } @@ -2431,77 +1880,56 @@ namespace server aiman::checkai(); } } - while(bannedips.length() && bannedips[0].expire-totalmillis <= 0) bannedips.remove(0); //~loopv(connects) if(totalmillis-connects[i]->connectmillis>15000) disconnect_client(connects[i]->clientnum, DISC_TIMEOUT); - - if(nextexceeded && gamemillis > nextexceeded && (!m_timed || gamemillis < gamelimit)) - { + if(nextexceeded && gamemillis > nextexceeded && (!m_timed || gamemillis < gamelimit)) { nextexceeded = 0; - loopvrev(clients) - { + loopvrev(clients) { clientinfo &c = *clients[i]; if(c.state.aitype != AI_NONE) continue; //~if(c.checkexceeded()) disconnect_client(c.clientnum, DISC_MSGERR); else c.scheduleexceeded(); } } - if(shouldcheckteamkills) checkteamkills(); - - if(shouldstep && !gamepaused) - { + if(shouldstep && !gamepaused) { if(m_timed && smapname[0] && gamemillis-curtime>0) checkintermission(); - if(interm > 0 && gamemillis>interm) - { + if(interm > 0 && gamemillis>interm) { if(demorecord) enddemorecord(); interm = -1; checkvotes(true); } } - shouldstep = clients.length() > 0; } - - void forcespectator(clientinfo *ci) - { + void forcespectator(clientinfo *ci) { if(ci->state.state==CS_ALIVE) suicide(ci); ci->state.state = CS_SPECTATOR; ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed; if(!ci->local && (!ci->privilege || ci->warned)) aiman::removeai(ci); sendf(-1, 1, "ri3", N_SPECTATOR, ci->clientnum, 1); } - - struct crcinfo - { + struct crcinfo { int crc, matches; - crcinfo() {} crcinfo(int crc, int matches) : crc(crc), matches(matches) {} - static bool compare(const crcinfo &x, const crcinfo &y) { return x.matches > y.matches; } }; - VAR(modifiedmapspectator, 0, 1, 2); - - void checkmaps(int req = -1) - { + void checkmaps(int req = -1) { if(m_edit || !smapname[0]) return; vector<crcinfo> crcs; int total = 0, unsent = 0, invalid = 0; if(mcrc) crcs.add(crcinfo(mcrc, clients.length() + 1)); - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.state==CS_SPECTATOR || ci->state.aitype != AI_NONE) continue; total++; - if(!ci->clientmap[0]) - { + if(!ci->clientmap[0]) { if(ci->mapcrc < 0) invalid++; else if(!ci->mapcrc) unsent++; } - else - { + else { crcinfo *match = NULL; loopvj(crcs) if(crcs[j].crc == ci->mapcrc) { match = &crcs[j]; break; } if(!match) crcs.add(crcinfo(ci->mapcrc, 1)); @@ -2511,19 +1939,16 @@ namespace server if(!mcrc && total - unsent < min(total, 4)) return; crcs.sort(crcinfo::compare); string msg; - loopv(clients) - { + loopv(clients) { clientinfo *ci = clients[i]; if(ci->state.state==CS_SPECTATOR || ci->state.aitype != AI_NONE || ci->clientmap[0] || ci->mapcrc >= 0 || (req < 0 && ci->warned)) continue; formatstring(msg, "%s has modified map \"%s\"", colorname(ci), smapname); sendf(req, 1, "ris", N_SERVMSG, msg); if(req < 0) ci->warned = true; } - if(crcs.length() >= 2) loopv(crcs) - { + if(crcs.length() >= 2) loopv(crcs) { crcinfo &info = crcs[i]; - if(i || info.matches <= crcs[i+1].matches) loopvj(clients) - { + if(i || info.matches <= crcs[i+1].matches) loopvj(clients) { clientinfo *ci = clients[j]; if(ci->state.state==CS_SPECTATOR || ci->state.aitype != AI_NONE || !ci->clientmap[0] || ci->mapcrc != info.crc || (req < 0 && ci->warned)) continue; formatstring(msg, "%s has modified map \"%s\"", colorname(ci), smapname); @@ -2531,20 +1956,15 @@ namespace server if(req < 0) ci->warned = true; } } - if(req < 0 && modifiedmapspectator && (mcrc || modifiedmapspectator > 1)) loopv(clients) - { + if(req < 0 && modifiedmapspectator && (mcrc || modifiedmapspectator > 1)) loopv(clients) { clientinfo *ci = clients[i]; if(!ci->local && ci->warned && ci->state.state != CS_SPECTATOR) forcespectator(ci); } } - - bool shouldspectate(clientinfo *ci) - { + bool shouldspectate(clientinfo *ci) { return !ci->local && ci->warned && modifiedmapspectator && (mcrc || modifiedmapspectator > 1); } - - void unspectate(clientinfo *ci) - { + void unspectate(clientinfo *ci) { if(shouldspectate(ci)) return; ci->state.state = CS_DEAD; ci->state.respawn(); @@ -2554,55 +1974,40 @@ namespace server if(ci->clientmap[0] || ci->mapcrc) checkmaps(); if(!hasmap(ci)) rotatemap(true); } - - void sendservinfo(clientinfo *ci) - { + void sendservinfo(clientinfo *ci) { sendf(ci->clientnum, 1, "ri5ss", N_SERVINFO, ci->clientnum, PROTOCOL_VERSION, ci->sessionid, serverpass[0] ? 1 : 0, serverdesc, serverauth); } - - void noclients() - { + void noclients() { bannedips.shrink(0); aiman::clearai(); } - - 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) { if(m_demo) enddemoplayback(); clientdisconnect(n); } - - int clientconnect(int n) - { + int clientconnect(int n) { clientinfo *ci = getinfo(n); ci->clientnum = ci->ownernum = n; ci->connectmillis = totalmillis; ci->sessionid = (rnd(0x1000000)*((totalmillis%10000)+1))&0xFFFFFF; - connects.add(ci); if(!m_mp(gamemode)) return DISC_LOCAL; sendservinfo(ci); return DISC_NONE; } - - void clientdisconnect(int n) - { + void clientdisconnect(int n) { clientinfo *ci = getinfo(n); loopv(clients) if(clients[i]->authkickvictim == ci->clientnum) clients[i]->cleanauth(); - if(ci->connected) - { + if(ci->connected) { if(ci->privilege) setmaster(ci, false); ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed; savescore(ci); @@ -2614,58 +2019,39 @@ namespace server } else connects.removeobj(ci); } - int reserveclients() { return 3; } - extern void verifybans(); - - struct banlist - { + struct banlist { vector<ipmask> bans; - void clear() { bans.shrink(0); } - - bool check(uint ip) - { + bool check(uint ip) { loopv(bans) if(bans[i].check(ip)) return true; return false; } - - void add(const char *ipname) - { + void add(const char *ipname) { ipmask ban; ban.parse(ipname); bans.add(ban); - verifybans(); } } ipbans, gbans; - - bool checkbans(uint ip) - { + bool checkbans(uint ip) { loopv(bannedips) if(bannedips[i].ip==ip) return true; return ipbans.check(ip) || gbans.check(ip); } - - void verifybans() - { - loopvrev(clients) - { + void verifybans() { + loopvrev(clients) { clientinfo *ci = clients[i]; if(ci->state.aitype != AI_NONE || ci->local || ci->privilege >= PRIV_ADMIN) continue; //~if(checkbans(getclientip(ci->clientnum))) disconnect_client(ci->clientnum, DISC_IPBAN); } } - ICOMMAND(clearipbans, "", (), ipbans.clear()); ICOMMAND(ipban, "s", (const char *ipname), ipbans.add(ipname)); - - int allowconnect(clientinfo *ci, const char *pwd = "") - { + int allowconnect(clientinfo *ci, const char *pwd = "") { if(ci->local) return DISC_NONE; if(!m_mp(gamemode)) return DISC_LOCAL; - if(serverpass[0]) - { + if(serverpass[0]) { if(!checkpassword(ci, serverpass, pwd)) return DISC_PASSWORD; return DISC_NONE; } @@ -2676,68 +2062,50 @@ namespace server if(mastermode>=MM_PRIVATE && allowedips.find(ip)<0) return DISC_PRIVATE; return DISC_NONE; } - - bool allowbroadcast(int n) - { + bool allowbroadcast(int n) { clientinfo *ci = getinfo(n); return ci && ci->connected; } - - clientinfo *findauth(uint id) - { + clientinfo *findauth(uint id) { loopv(clients) if(clients[i]->authreq == id) return clients[i]; return NULL; } - - void authfailed(clientinfo *ci) - { + void authfailed(clientinfo *ci) { if(!ci) return; ci->cleanauth(); //~if(ci->connectauth) disconnect_client(ci->clientnum, ci->connectauth); } - - void authfailed(uint id) - { + void authfailed(uint id) { authfailed(findauth(id)); } - - void authsucceeded(uint id) - { + void authsucceeded(uint id) { clientinfo *ci = findauth(id); if(!ci) return; ci->cleanauth(ci->connectauth!=0); if(ci->connectauth) connected(ci); - if(ci->authkickvictim >= 0) - { + if(ci->authkickvictim >= 0) { if(setmaster(ci, true, "", ci->authname, NULL, PRIV_AUTH, false, true)) trykick(ci, ci->authkickvictim, ci->authkickreason, ci->authname, NULL, PRIV_AUTH); ci->cleanauthkick(); } else setmaster(ci, true, "", ci->authname, NULL, PRIV_AUTH); } - - void authchallenged(uint id, const char *val, const char *desc = "") - { + void authchallenged(uint id, const char *val, const char *desc = "") { clientinfo *ci = findauth(id); if(!ci) return; sendf(ci->clientnum, 1, "risis", N_AUTHCHAL, desc, id, val); } - uint nextauthreq = 0; - - bool tryauth(clientinfo *ci, const char *user, const char *desc) - { + bool tryauth(clientinfo *ci, const char *user, const char *desc) { ci->cleanauth(); if(!nextauthreq) nextauthreq = 1; ci->authreq = nextauthreq++; filtertext(ci->authname, user, false, false, 100); copystring(ci->authdesc, desc); - if(ci->authdesc[0]) - { + if(ci->authdesc[0]) { userinfo *u = users.access(userkey(ci->authname, ci->authdesc)); - if(u) - { + if(u) { uint seed[3] = { ::hthash(serverauth) + detrnd(size_t(ci) + size_t(user) + size_t(desc), 0x10000), uint(totalmillis), randomMT() }; vector<char> buf; ci->authchallenge = genchallenge(u->pubkey, seed, sizeof(seed), buf); @@ -2745,8 +2113,7 @@ namespace server } else ci->cleanauth(); } - else if(!requestmasterf("reqauth %u %s\n", ci->authreq, ci->authname)) - { + else if(!requestmasterf("reqauth %u %s\n", ci->authreq, ci->authname)) { ci->cleanauth(); sendf(ci->clientnum, 1, "ris", N_SERVMSG, "not connected to authentication server"); } @@ -2754,28 +2121,20 @@ namespace server //~if(ci->connectauth) disconnect_client(ci->clientnum, ci->connectauth); return false; } - - bool answerchallenge(clientinfo *ci, uint id, char *val, const char *desc) - { - if(ci->authreq != id || strcmp(ci->authdesc, desc)) - { + bool answerchallenge(clientinfo *ci, uint id, char *val, const char *desc) { + if(ci->authreq != id || strcmp(ci->authdesc, desc)) { ci->cleanauth(); return !ci->connectauth; } - for(char *s = val; *s; s++) - { + for(char *s = val; *s; s++) { if(!isxdigit(*s)) { *s = '\0'; break; } } - if(desc[0]) - { - if(ci->authchallenge && checkchallenge(val, ci->authchallenge)) - { + if(desc[0]) { + if(ci->authchallenge && checkchallenge(val, ci->authchallenge)) { userinfo *u = users.access(userkey(ci->authname, ci->authdesc)); - if(u) - { + if(u) { if(ci->connectauth) connected(ci); - if(ci->authkickvictim >= 0) - { + if(ci->authkickvictim >= 0) { if(setmaster(ci, true, "", ci->authname, ci->authdesc, u->privilege, false, true)) trykick(ci, ci->authkickvictim, ci->authkickreason, ci->authname, ci->authdesc, u->privilege); } @@ -2784,29 +2143,21 @@ namespace server } ci->cleanauth(); } - else if(!requestmasterf("confauth %u %s\n", id, val)) - { + else if(!requestmasterf("confauth %u %s\n", id, val)) { ci->cleanauth(); sendf(ci->clientnum, 1, "ris", N_SERVMSG, "not connected to authentication server"); } return ci->authreq || !ci->connectauth; } - - void masterconnected() - { + void masterconnected() { } - - void masterdisconnected() - { - loopvrev(clients) - { + void masterdisconnected() { + loopvrev(clients) { clientinfo *ci = clients[i]; if(ci->authreq) authfailed(ci); } } - - void processmasterinput(const char *cmd, int cmdlen, const char *args) - { + void processmasterinput(const char *cmd, int cmdlen) { uint id; string val; if(sscanf(cmd, "failauth %u", &id) == 1) @@ -2820,9 +2171,7 @@ namespace server else if(sscanf(cmd, "addgban %100s", val) == 1) gbans.add(val); } - - void receivefile(int sender, uchar *data, int len) - { + void receivefile(int sender, uchar *data, int len) { if(!m_edit || len <= 0 || len > 4*1024*1024) return; clientinfo *ci = getinfo(sender); if(ci->state.state==CS_SPECTATOR && !ci->privilege && !ci->local) return; @@ -2832,82 +2181,59 @@ namespace server mapdata->write(data, len); sendservmsgf("[%s sent a map to server, \"/getmap\" to receive it]", colorname(ci)); } - - void sendclipboard(clientinfo *ci) - { + void sendclipboard(clientinfo *ci) { if(!ci->lastclipboard || !ci->clipboard) return; bool flushed = false; - loopv(clients) - { + loopv(clients) { clientinfo &e = *clients[i]; - if(e.clientnum != ci->clientnum && e.needclipboard - ci->lastclipboard >= 0) - { + if(e.clientnum != ci->clientnum && e.needclipboard - ci->lastclipboard >= 0) { if(!flushed) { flushserver(true); flushed = true; } sendpacket(e.clientnum, 1, ci->clipboard); } } } - - void connected(clientinfo *ci) - { + void connected(clientinfo *ci) { if(m_demo) enddemoplayback(); - if(!hasmap(ci)) rotatemap(false); - shouldstep = true; - connects.removeobj(ci); clients.add(ci); - ci->connectauth = 0; ci->connected = true; ci->needclipboard = totalmillis ? totalmillis : 1; if(mastermode>=MM_LOCKED) ci->state.state = CS_SPECTATOR; ci->state.lasttimeplayed = lastmillis; - - const char *worst = m_teammode ? chooseworstteam(NULL, ci) : NULL; + const char *worst = m_teammode ? chooseworstteam(ci) : NULL; copystring(ci->team, worst ? worst : "good", MAXTEAMLEN+1); - sendwelcome(ci); if(restorescore(ci)) sendresume(ci); sendinitclient(ci); - aiman::addclient(ci); - if(m_demo) setupdemoplayback(); - if(servermotd[0]) sendf(ci->clientnum, 1, "ris", N_SERVMSG, servermotd); } - - void parsepacket(int sender, int chan, packetbuf &p) // has to parse exactly each byte of the packet - { + 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(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: - { + 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, "Anonymous"); copystring(ci->name, text, MAXNAMELEN+1); ci->playermodel = 0; - string password, authdesc, authname; getstring(password, p, sizeof(password)); getstring(authdesc, p, sizeof(authdesc)); getstring(authname, p, sizeof(authname)); int disc = allowconnect(ci, password); - if(disc) - { - if(disc == DISC_LOCAL || !serverauth[0] || strcmp(serverauth, authdesc) || !tryauth(ci, authname, authdesc)) - { + if(disc) { + if(disc == DISC_LOCAL || !serverauth[0] || strcmp(serverauth, authdesc) || !tryauth(ci, authname, authdesc)) { //~disconnect_client(sender, disc); return; } @@ -2916,63 +2242,53 @@ namespace server else connected(ci); break; } - - case N_AUTHANS: - { + case N_AUTHANS: { string desc, ans; getstring(desc, p, sizeof(desc)); uint id = (uint)getint(p); getstring(ans, p, sizeof(ans)); - if(!answerchallenge(ci, id, ans, desc)) - { + if(!answerchallenge(ci, id, ans, desc)) { //~disconnect_client(sender, ci->connectauth); return; } break; } - case N_PING: getint(p); break; - default: //~disconnect_client(sender, DISC_MSGERR); return; } return; } - else if(chan==2) - { + else if(chan==2) { receivefile(sender, p.buf, p.maxlen); return; } - if(p.packet->flags&ENET_PACKET_FLAG_RELIABLE) reliablemessages = true; #define QUEUE_AI clientinfo *cm = cq; #define QUEUE_MSG { if(cm && (!cm->local || demorecord || hasnonlocalclients())) while(curmsg<p.length()) cm->messages.add(p.buf[curmsg++]); } #define QUEUE_BUF(body) { \ - if(cm && (!cm->local || demorecord || hasnonlocalclients())) \ - { \ - curmsg = p.length(); \ - { body; } \ + if(cm && (!cm->local || demorecord || 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_POS: - { + while((curmsg = p.length()) < p.maxlen) switch(type = checktype(getint(p), ci)) { + case N_POS: { int pcn = getuint(p); p.get(); uint flags = getuint(p); clientinfo *cp = getinfo(pcn); if(cp && pcn != sender && cp->ownernum != sender) cp = NULL; vec pos; - loopk(3) - { + loopk(3) { int n = p.get(); n |= p.get()<<8; if(flags&(1<<k)) { n |= p.get()<<16; if(n&0x800000) n |= ~0U<<24; } pos[k] = n/DMF; } @@ -2980,15 +2296,12 @@ namespace server int mag = p.get(); if(flags&(1<<3)) mag |= p.get()<<8; int dir = p.get(); dir |= p.get()<<8; vec vel = vec((dir%360)*RAD, (clamp(dir/360, 0, 180)-90)*RAD).mul(mag/DVELF); - if(flags&(1<<4)) - { + if(flags&(1<<4)) { p.get(); if(flags&(1<<5)) p.get(); if(flags&(1<<6)) loopk(2) p.get(); } - if(cp) - { - if((!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) - { + if(cp) { + if((!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) { if(!ci->local && !m_edit && max(vel.magnitude2(), (float)fabs(vel.z)) >= 180) cp->setexceeded(); cp->position.setsize(0); @@ -2999,53 +2312,41 @@ namespace server } break; } - - case N_TELEPORT: - { + case N_TELEPORT: { int pcn = getint(p), teleport = getint(p), teledest = getint(p); clientinfo *cp = getinfo(pcn); if(cp && pcn != sender && cp->ownernum != sender) cp = NULL; - if(cp && (!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) - { + if(cp && (!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) { flushclientposition(*cp); sendf(-1, 0, "ri4x", N_TELEPORT, pcn, teleport, teledest, cp->ownernum); } break; } - - case N_JUMPPAD: - { + case N_JUMPPAD: { int pcn = getint(p), jumppad = getint(p); clientinfo *cp = getinfo(pcn); if(cp && pcn != sender && cp->ownernum != sender) cp = NULL; - if(cp && (!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) - { + if(cp && (!ci->local || demorecord || hasnonlocalclients()) && (cp->state.state==CS_ALIVE || cp->state.state==CS_EDITING)) { cp->setpushed(); flushclientposition(*cp); sendf(-1, 0, "ri3x", N_JUMPPAD, pcn, jumppad, cp->ownernum); } break; } - - case N_FROMAI: - { + case N_FROMAI: { int qcn = getint(p); if(qcn < 0) cq = ci; - else - { + else { cq = getinfo(qcn); if(cq && qcn != sender && cq->ownernum != sender) cq = NULL; } break; } - - case N_EDITMODE: - { + case N_EDITMODE: { int val = getint(p); if(!ci->local && !m_edit) break; if(val ? ci->state.state!=CS_ALIVE && ci->state.state!=CS_DEAD : ci->state.state!=CS_EDITING) break; - if(val) - { + if(val) { ci->state.editstate = ci->state.state; ci->state.state = CS_EDITING; ci->events.setsize(0); @@ -3056,16 +2357,12 @@ namespace server QUEUE_MSG; break; } - - case N_MAPCRC: - { + case N_MAPCRC: { getstring(text, p); int crc = getint(p); if(!ci) break; - if(strcmp(text, smapname)) - { - if(ci->clientmap[0]) - { + if(strcmp(text, smapname)) { + if(ci->clientmap[0]) { ci->clientmap[0] = '\0'; ci->mapcrc = 0; } @@ -3078,31 +2375,25 @@ namespace server if(cq && cq != ci && cq->ownernum != ci->clientnum) cq = NULL; break; } - case N_CHECKMAPS: checkmaps(sender); break; - case N_TRYSPAWN: if(!ci || !cq || cq->state.state!=CS_DEAD || cq->state.lastspawn>=0) break; - if(!ci->clientmap[0] && !ci->mapcrc) - { + if(!ci->clientmap[0] && !ci->mapcrc) { ci->mapcrc = -1; checkmaps(); if(ci == cq) { if(ci->state.state != CS_DEAD) break; } else if(cq->ownernum != ci->clientnum) { cq = NULL; break; } } - if(cq->state.deadflush) - { + if(cq->state.deadflush) { flushevents(cq, cq->state.deadflush); cq->state.respawn(); } cleartimedevents(cq); sendspawn(cq); break; - - case N_GUNSELECT: - { + case N_GUNSELECT: { int gunselect = getint(p); if(!cq || cq->state.state!=CS_ALIVE) break; cq->state.gunselect = gunselect >= GUN_FIST && gunselect <= GUN_PISTOL ? gunselect : GUN_FIST; @@ -3110,9 +2401,7 @@ namespace server QUEUE_MSG; break; } - - case N_SPAWN: - { + case N_SPAWN: { int ls = getint(p), gunselect = 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; @@ -3126,15 +2415,11 @@ namespace server }); break; } - - case N_SUICIDE: - { + case N_SUICIDE: { if(cq) cq->addevent(new suicideevent); break; } - - case N_SHOOT: - { + case N_SHOOT: { shotevent *shot = new shotevent; shot->id = getint(p); shot->millis = cq ? cq->geteventmillis(gamemillis, shot->id) : 0; @@ -3142,8 +2427,7 @@ namespace server loopk(3) shot->from[k] = getint(p)/DMF; loopk(3) shot->to[k] = getint(p)/DMF; int hits = getint(p); - loopk(hits) - { + loopk(hits) { if(p.overread()) break; hitinfo &hit = shot->hits.add(); hit.target = getint(p); @@ -3152,25 +2436,21 @@ namespace server hit.rays = getint(p); loopk(3) hit.dir[k] = getint(p)/DNF; } - if(cq) - { + if(cq) { cq->addevent(shot); cq->setpushed(); } else delete shot; break; } - - case N_EXPLODE: - { + case N_EXPLODE: { explodeevent *exp = new explodeevent; int cmillis = getint(p); exp->millis = cq ? cq->geteventmillis(gamemillis, cmillis) : 0; exp->gun = getint(p); exp->id = getint(p); int hits = getint(p); - loopk(hits) - { + loopk(hits) { if(p.overread()) break; hitinfo &hit = exp->hits.add(); hit.target = getint(p); @@ -3183,9 +2463,7 @@ namespace server else delete exp; break; } - - case N_ITEMPICKUP: - { + case N_ITEMPICKUP: { int n = getint(p); if(!cq) break; pickupevent *pickup = new pickupevent; @@ -3193,9 +2471,7 @@ namespace server cq->addevent(pickup); break; } - - case N_TEXT: - { + case N_TEXT: { QUEUE_AI; QUEUE_MSG; getstring(text, p); @@ -3204,14 +2480,11 @@ namespace server if(isdedicatedserver() && cq) logoutf("%s: %s", colorname(cq), text); break; } - - case N_SAYTEAM: - { + case N_SAYTEAM: { getstring(text, p); if(!ci || !cq || (ci->state.state==CS_SPECTATOR && !ci->local && !ci->privilege) || !m_teammode || !cq->team[0]) break; filtertext(text, text, true, true); - loopv(clients) - { + loopv(clients) { clientinfo *t = clients[i]; if(t==cq || t->state.state==CS_SPECTATOR || t->state.aitype != AI_NONE || strcmp(cq->team, t->team)) continue; sendf(t->clientnum, 1, "riis", N_SAYTEAM, cq->clientnum, text); @@ -3219,9 +2492,7 @@ namespace server if(isdedicatedserver() && cq) logoutf("%s <%s>: %s", colorname(cq), cq->team, text); break; } - - case N_SWITCHNAME: - { + case N_SWITCHNAME: { QUEUE_MSG; getstring(text, p); filtertext(ci->name, text, false, false, MAXNAMELEN); @@ -3229,20 +2500,15 @@ namespace server QUEUE_STR(ci->name); break; } - - case N_SWITCHMODEL: - { + case N_SWITCHMODEL: { ci->playermodel = 0; QUEUE_MSG; break; } - - case N_SWITCHTEAM: - { + case N_SWITCHTEAM: { getstring(text, p); filtertext(text, text, false, false, MAXTEAMLEN); - if(m_teammode && text[0] && strcmp(ci->team, text) && addteaminfo(text)) - { + if(m_teammode && text[0] && strcmp(ci->team, text) && addteaminfo(text)) { if(ci->state.state==CS_ALIVE) suicide(ci); copystring(ci->team, text); aiman::changeteam(ci); @@ -3250,9 +2516,7 @@ namespace server } break; } - - case N_MAPVOTE: - { + case N_MAPVOTE: { getstring(text, p); filtertext(text, text, false); fixmapname(text); @@ -3260,18 +2524,14 @@ namespace server vote(text, reqmode, sender); break; } - - case N_ITEMLIST: - { + case N_ITEMLIST: { if((ci->state.state==CS_SPECTATOR && !ci->privilege && !ci->local) || !notgotitems || strcmp(ci->clientmap, smapname)) { while(getint(p)>=0 && !p.overread()) getint(p); break; } int n; - while((n = getint(p))>=0 && n<MAXENTS && !p.overread()) - { + while((n = getint(p))>=0 && n<MAXENTS && !p.overread()) { server_entity se = { NOTUSED, 0, false }; while(sents.length()<=n) sents.add(se); sents[n].type = getint(p); - if(canspawnitem(sents[n].type)) - { + if(canspawnitem(sents[n].type)) { if(m_mp(gamemode) && delayspawn(sents[n].type)) sents[n].spawntime = spawntime(sents[n].type); else sents[n].spawned = true; } @@ -3279,9 +2539,7 @@ namespace server notgotitems = false; break; } - - case N_EDITENT: - { + case N_EDITENT: { int i = getint(p); loopk(3) getint(p); int type = getint(p); @@ -3289,26 +2547,21 @@ namespace server if(!ci || ci->state.state==CS_SPECTATOR) break; QUEUE_MSG; bool canspawn = canspawnitem(type); - if(i<MAXENTS && (sents.inrange(i) || canspawnitem(type))) - { + if(i<MAXENTS && (sents.inrange(i) || canspawnitem(type))) { server_entity se = { NOTUSED, 0, false }; while(sents.length()<=i) sents.add(se); sents[i].type = type; - if(canspawn ? !sents[i].spawned : (sents[i].spawned || sents[i].spawntime)) - { + if(canspawn ? !sents[i].spawned : (sents[i].spawned || sents[i].spawntime)) { sents[i].spawntime = canspawn ? 1 : 0; sents[i].spawned = false; } } break; } - - case N_EDITVAR: - { + case N_EDITVAR: { int type = getint(p); getstring(text, p); - switch(type) - { + switch(type) { case ID_VAR: getint(p); break; case ID_FVAR: getfloat(p); break; case ID_SVAR: getstring(text, p); @@ -3316,91 +2569,69 @@ namespace server if(ci && ci->state.state!=CS_SPECTATOR) QUEUE_MSG; break; } - case N_PING: sendf(sender, 1, "i2", N_PONG, getint(p)); break; - - case N_CLIENTPING: - { + case N_CLIENTPING: { int ping = getint(p); - if(ci) - { + if(ci) { ci->ping = ping; loopv(ci->bots) ci->bots[i]->ping = ping; } QUEUE_MSG; break; } - - case N_MASTERMODE: - { + case N_MASTERMODE: { int mm = getint(p); - if((ci->privilege || ci->local) && mm>=MM_OPEN && mm<=MM_PRIVATE) - { - if((ci->privilege>=PRIV_ADMIN || ci->local) || (mastermask&(1<<mm))) - { + if((ci->privilege || ci->local) && mm>=MM_OPEN && mm<=MM_PRIVATE) { + if((ci->privilege>=PRIV_ADMIN || ci->local) || (mastermask&(1<<mm))) { mastermode = mm; allowedips.shrink(0); - if(mm>=MM_PRIVATE) - { + if(mm>=MM_PRIVATE) { loopv(clients) allowedips.add(getclientip(clients[i]->clientnum)); } sendf(-1, 1, "rii", N_MASTERMODE, mastermode); //sendservmsgf("mastermode is now %s (%d)", mastermodename(mastermode), mastermode); } - else - { + else { defformatstring(s, "mastermode %d is disabled on this server", mm); sendf(sender, 1, "ris", N_SERVMSG, s); } } break; } - - case N_CLEARBANS: - { - if(ci->privilege || ci->local) - { + case N_CLEARBANS: { + if(ci->privilege || ci->local) { bannedips.shrink(0); sendservmsg("cleared all bans"); } break; } - - case N_KICK: - { + case N_KICK: { int victim = getint(p); getstring(text, p); filtertext(text, text); trykick(ci, victim, text); break; } - - case N_SPECTATOR: - { + case N_SPECTATOR: { int spectator = getint(p), val = getint(p); if(!ci->privilege && !ci->local && (spectator!=sender || (ci->state.state==CS_SPECTATOR && mastermode>=MM_LOCKED))) break; clientinfo *spinfo = (clientinfo *)getclientinfo(spectator); // no bots if(!spinfo || !spinfo->connected || (spinfo->state.state==CS_SPECTATOR ? val : !val)) break; - if(spinfo->state.state!=CS_SPECTATOR && val) forcespectator(spinfo); else if(spinfo->state.state==CS_SPECTATOR && !val) unspectate(spinfo); - if(cq && cq != ci && cq->ownernum != ci->clientnum) cq = NULL; break; } - - case N_SETTEAM: - { + case N_SETTEAM: { int who = getint(p); getstring(text, p); filtertext(text, text, false, false, MAXTEAMLEN); if(!ci->privilege && !ci->local) break; clientinfo *wi = getinfo(who); if(!m_teammode || !text[0] || !wi || !wi->connected || !strcmp(wi->team, text)) break; - if(addteaminfo(text)) - { + if(addteaminfo(text)) { if(wi->state.state==CS_ALIVE) suicide(wi); copystring(wi->team, text, MAXTEAMLEN+1); } @@ -3408,17 +2639,13 @@ namespace server sendf(-1, 1, "riisi", N_SETTEAM, who, wi->team, 1); break; } - case N_FORCEINTERMISSION: if(ci->local && !hasnonlocalclients()) startintermission(); break; - - case N_RECORDDEMO: - { + case N_RECORDDEMO: { int val = getint(p); if(ci->privilege < (restrictdemos ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; - if(!maxdemos || !maxdemosize) - { + if(!maxdemos || !maxdemosize) { sendf(ci->clientnum, 1, "ris", N_SERVMSG, "the server has disabled demo recording"); break; } @@ -3426,53 +2653,41 @@ namespace server sendservmsgf("demo recording is %s for next match", demonextmatch ? "enabled" : "disabled"); break; } - - case N_STOPDEMO: - { + case N_STOPDEMO: { if(ci->privilege < (restrictdemos ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; stopdemo(); break; } - - case N_CLEARDEMOS: - { + case N_CLEARDEMOS: { int demo = getint(p); if(ci->privilege < (restrictdemos ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; cleardemos(demo); break; } - case N_LISTDEMOS: if(!ci->privilege && !ci->local && ci->state.state==CS_SPECTATOR) break; listdemos(sender); break; - - case N_GETDEMO: - { + case N_GETDEMO: { int n = getint(p), tag = getint(p); if(!ci->privilege && !ci->local && ci->state.state==CS_SPECTATOR) break; senddemo(ci, n, tag); break; } - case N_GETMAP: if(!mapdata) sendf(sender, 1, "ris", N_SERVMSG, "no map to send"); else if(ci->getmap) sendf(sender, 1, "ris", N_SERVMSG, "already sending map"); - else - { + else { sendservmsgf("[%s is getting the map]", colorname(ci)); if((ci->getmap = sendfile(sender, 2, mapdata, "ri", N_SENDMAP))) ci->getmap->freeCallback = freegetmap; ci->needclipboard = totalmillis ? totalmillis : 1; } break; - - case N_NEWMAP: - { + case N_NEWMAP: { int size = getint(p); if(!ci->privilege && !ci->local && ci->state.state==CS_SPECTATOR) break; - if(size>=0) - { + if(size>=0) { smapname[0] = '\0'; resetitems(); notgotitems = false; @@ -3480,13 +2695,10 @@ namespace server QUEUE_MSG; break; } - - case N_SETMASTER: - { + case N_SETMASTER: { int mn = getint(p), val = getint(p); getstring(text, p); - if(mn != ci->clientnum) - { + if(mn != ci->clientnum) { if(!ci->privilege && !ci->local) break; clientinfo *minfo = (clientinfo *)getclientinfo(mn); if(!minfo || !minfo->connected || (!ci->local && minfo->privilege >= ci->privilege) || (val && minfo->privilege)) break; @@ -3496,44 +2708,32 @@ namespace server // don't broadcast the master password break; } - - case N_ADDBOT: - { + case N_ADDBOT: { aiman::reqadd(ci, getint(p)); break; } - - case N_DELBOT: - { + case N_DELBOT: { aiman::reqdel(ci); break; } - - case N_BOTLIMIT: - { + case N_BOTLIMIT: { int limit = getint(p); if(ci) aiman::setbotlimit(ci, limit); break; } - - case N_BOTBALANCE: - { + case N_BOTBALANCE: { int balance = getint(p); if(ci) aiman::setbotbalance(ci, balance!=0); break; } - - case N_AUTHTRY: - { + case N_AUTHTRY: { string desc, name; getstring(desc, p, sizeof(desc)); getstring(name, p, sizeof(name)); tryauth(ci, name, desc); break; } - - case N_AUTHKICK: - { + case N_AUTHKICK: { string desc, name; getstring(desc, p, sizeof(desc)); getstring(name, p, sizeof(name)); @@ -3541,22 +2741,18 @@ namespace server getstring(text, p); filtertext(text, text); int authpriv = PRIV_AUTH; - if(desc[0]) - { + if(desc[0]) { userinfo *u = users.access(userkey(name, desc)); if(u) authpriv = u->privilege; else break; } if(ci->local || ci->privilege >= authpriv) trykick(ci, victim, text); - else if(trykick(ci, victim, text, name, desc, authpriv, true) && tryauth(ci, name, desc)) - { + else if(trykick(ci, victim, text, name, desc, authpriv, true) && tryauth(ci, name, desc)) { ci->authkickvictim = victim; ci->authkickreason = newstring(text); } break; } - - case N_AUTHANS: - { + case N_AUTHANS: { string desc, ans; getstring(desc, p, sizeof(desc)); uint id = (uint)getint(p); @@ -3564,43 +2760,33 @@ namespace server answerchallenge(ci, id, ans, desc); break; } - - case N_PAUSEGAME: - { + case N_PAUSEGAME: { int val = getint(p); if(ci->privilege < (restrictpausegame ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; pausegame(val > 0, ci); break; } - - case N_GAMESPEED: - { + case N_GAMESPEED: { int val = getint(p); if(ci->privilege < (restrictgamespeed ? PRIV_ADMIN : PRIV_MASTER) && !ci->local) break; changegamespeed(val, ci); break; } - case N_COPY: ci->cleanclipboard(); ci->lastclipboard = totalmillis ? totalmillis : 1; goto genericmsg; - case N_PASTE: if(ci->state.state!=CS_SPECTATOR) sendclipboard(ci); goto genericmsg; - - case N_CLIPBOARD: - { + case N_CLIPBOARD: { int unpacklen = getint(p), packlen = getint(p); ci->cleanclipboard(false); - if(ci->state.state==CS_SPECTATOR) - { + if(ci->state.state==CS_SPECTATOR) { if(packlen > 0) p.subbuf(packlen); break; } - if(packlen <= 0 || packlen > (1<<16) || unpacklen <= 0) - { + if(packlen <= 0 || packlen > (1<<16) || unpacklen <= 0) { if(packlen > 0) p.subbuf(packlen); packlen = unpacklen = 0; } @@ -3614,11 +2800,9 @@ namespace server ci->clipboard->referenceCount++; break; } - case N_EDITT: case N_REPLACE: - case N_EDITVSLOT: - { + case N_EDITVSLOT: { int size = server::msgsizelookup(type); //~if(size<=0) { disconnect_client(sender, DISC_MSGERR); return; } loopi(size-1) getint(p); @@ -3629,13 +2813,10 @@ namespace server if(ci && ci->state.state!=CS_SPECTATOR) QUEUE_MSG; break; } - case N_UNDO: - case N_REDO: - { + case N_REDO: { int unpacklen = getint(p), packlen = getint(p); - if(!ci || ci->state.state==CS_SPECTATOR || packlen <= 0 || packlen > (1<<16) || unpacklen <= 0) - { + if(!ci || ci->state.state==CS_SPECTATOR || packlen <= 0 || packlen > (1<<16) || unpacklen <= 0) { if(packlen > 0) p.subbuf(packlen); break; } @@ -3649,27 +2830,21 @@ namespace server sendpacket(-1, 1, q.finalize(), ci->clientnum); break; } - case N_SERVCMD: getstring(text, p); break; - case -1: //~disconnect_client(sender, DISC_MSGERR); return; - case -2: //~disconnect_client(sender, DISC_OVERFLOW); return; - - default: genericmsg: - { + default: genericmsg: { int size = server::msgsizelookup(type); //~if(size<=0) { disconnect_client(sender, DISC_MSGERR); return; } loopi(size-1) getint(p); - if(ci) switch(msgfilter[type]) - { + if(ci) switch(msgfilter[type]) { case 2: case 3: if(ci->state.state != CS_SPECTATOR) QUEUE_MSG; break; default: if(cq && (ci != cq || ci->state.state!=CS_SPECTATOR)) { QUEUE_AI; QUEUE_MSG; } break; } @@ -3677,24 +2852,18 @@ namespace server } } } - int laninfoport() { return SAUERBRATEN_LANINFO_PORT; } int serverinfoport(int servport) { return servport < 0 ? SAUERBRATEN_SERVINFO_PORT : servport+1; } int serverport(int infoport) { return infoport < 0 ? SAUERBRATEN_SERVER_PORT : infoport-1; } const char *defaultmaster() { return "master.sauerbraten.org"; } int masterport() { return SAUERBRATEN_MASTER_PORT; } int numchannels() { return 3; } - #include "extinfo.h" - - void serverinforeply(ucharbuf &req, ucharbuf &p) - { - if(req.remaining() && !getint(req)) - { + void serverinforeply(ucharbuf &req, ucharbuf &p) { + if(req.remaining() && !getint(req)) { extserverinforeply(req, p); return; } - putint(p, numclients(-1, false, true)); putint(p, gamepaused || gamespeed != 100 ? 7 : 5); // number of attrs following putint(p, PROTOCOL_VERSION); // generic attributes, passed back below @@ -3702,8 +2871,7 @@ namespace server putint(p, m_timed ? max((gamelimit - gamemillis)/1000, 0) : 0); putint(p, maxclients); putint(p, serverpass[0] ? MM_PASSWORD : (!m_mp(gamemode) ? MM_PRIVATE : (mastermode || mastermask&MM_AUTOAPPROVE ? mastermode : MM_AUTH))); - if(gamepaused || gamespeed != 100) - { + if(gamepaused || gamespeed != 100) { putint(p, gamepaused ? 1 : 0); putint(p, gamespeed); } @@ -3711,7 +2879,6 @@ namespace server sendstring(serverdesc, p); sendserverinforeply(p); } - #include "aiman.h" } |
