From 5ffaabaf8bf3bb7807e508fa6eaf941411702ec8 Mon Sep 17 00:00:00 2001 From: driAn Date: Sun, 12 Oct 2008 12:07:20 +0000 Subject: [PATCH] debug com on the client as well git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@2980 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/src/clients2c.cpp | 1172 +++++++++++++++++++------------------- 1 file changed, 597 insertions(+), 575 deletions(-) diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index 656c09b8..276ac5f4 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -4,6 +4,8 @@ #include "cube.h" #include "bot/bot.h" +#define DEBUGCOND (true) + extern bool c2sinit, senditemstoserver, watchingdemo; extern string clientpassword; @@ -138,610 +140,626 @@ void parsemessages(int cn, playerent *d, ucharbuf &p) int type, joining = 0; bool mapchanged = false, demoplayback = false; - while(p.remaining()) switch(type = getint(p)) + while(p.remaining()) { - case SV_INITS2C: // welcome messsage from the server + type = getint(p); + + #ifdef _DEBUG + if(type!=SV_POS && type!=SV_CLIENTPING && type!=SV_PING && type!=SV_PONG) { - int mycn = getint(p), prot = getint(p); - if(prot!=PROTOCOL_VERSION) + DEBUGVAR(d); + ASSERT(type>=0 && typeclientnum = mycn; // we are now fully connected + joining = getint(p); + if(getint(p) > 0) conoutf("INFO: this server is password protected"); + break; } - player1->clientnum = mycn; // we are now fully connected - joining = getint(p); - if(getint(p) > 0) conoutf("INFO: this server is password protected"); - break; - } - case SV_CLIENT: - { - int cn = getint(p), len = getuint(p); - ucharbuf q = p.subbuf(len); - parsemessages(cn, getclient(cn), q); - break; - } - - case SV_SOUND: - playsound(getint(p), d); - break; - - case SV_VOICECOMTEAM: - { - playerent *d = getclient(getint(p)); - if(d) d->lastvoicecom = lastmillis; - playsound(getint(p), SP_HIGH); - break; - } - case SV_VOICECOM: - { - playsound(getint(p), SP_HIGH); - if(d) d->lastvoicecom = lastmillis; - break; - } - - case SV_TEAMTEXT: - { - int cn = getint(p); - getstring(text, p); - filtertext(text, text); - playerent *d = getclient(cn); - if(!d) break; - if(m_teammode) conoutf("%s:\f1 %s", colorname(d), text); - else conoutf("%s:\f0 %s", colorname(d), text); - break; - } - - case SV_TEXT: - if(cn == -1) + case SV_CLIENT: { - getstring(text, p); - conoutf("MOTD:"); - conoutf("\f4%s", text); + int cn = getint(p), len = getuint(p); + ucharbuf q = p.subbuf(len); + parsemessages(cn, getclient(cn), q); + break; } - else if(d) + + case SV_SOUND: + playsound(getint(p), d); + break; + + case SV_VOICECOMTEAM: { - getstring(text, p); - filtertext(text, text); - conoutf("%s:\f0 %s", colorname(d), text); + playerent *d = getclient(getint(p)); + if(d) d->lastvoicecom = lastmillis; + playsound(getint(p), SP_HIGH); + break; } - else return; - break; - - case SV_MAPCHANGE: - { - getstring(text, p); - int mode = getint(p); - bool downloadable = getint(p) > 0; - changemapserv(text, mode, downloadable); - if(m_arena && joining>2) deathstate(player1); - mapchanged = true; - break; - } - - case SV_ITEMLIST: - { - int n; - if(mapchanged||watchingdemo) { senditemstoserver = false; resetspawns(); } - while((n = getint(p))!=-1) if(mapchanged||watchingdemo) setspawn(n, true); - break; - } - - case SV_SPAWNLIST: - { - if(getint(p) > 0) loopi(5) getint(p); - break; - } - - case SV_MAPRELOAD: // server requests next map - { - getint(p); - s_sprintfd(nextmapalias)("nextmap_%s", getclientmap()); - const char *map = getalias(nextmapalias); // look up map in the cycle - changemap(map ? map : getclientmap()); - break; - } - - case SV_INITC2S: // another client either connected or changed name/team - { - d = newclient(cn); - getstring(text, p); - filtertext(text, text, 0, MAXNAMELEN); - if(!text[0]) s_strcpy(text, "unarmed"); - if(d->name[0]) // already connected + case SV_VOICECOM: { - if(strcmp(d->name, text)) - conoutf("%s is now known as %s", colorname(d, 0), colorname(d, 1, text)); + playsound(getint(p), SP_HIGH); + if(d) d->lastvoicecom = lastmillis; + break; } - else // new client - { - c2sinit = false; // send new players my info again - conoutf("connected: %s", colorname(d, 0, text)); - } - s_strncpy(d->name, text, MAXNAMELEN+1); - getstring(text, p); - filtertext(d->team, text, 0, MAXTEAMLEN); - setskin(d, getint(p)); - if(m_flags) loopi(2) - { - flaginfo &f = flaginfos[i]; - if(!f.actor) f.actor = getclient(f.actor_cn); - } - break; - } - case SV_CDIS: - { - int cn = getint(p); - playerent *d = getclient(cn); - if(!d) break; - if(d->name[0]) conoutf("player %s disconnected", colorname(d)); - zapplayer(players[cn]); - break; - } - - case SV_EDITMODE: - { - int val = getint(p); - if(!d) break; - if(val) d->state = CS_EDITING; - else d->state = CS_ALIVE; - break; - } - - case SV_SPAWN: - { - playerent *s = d; - if(!s) { static playerent dummy; s = &dummy; } - s->respawn(); - s->lifesequence = getint(p); - s->health = getint(p); - s->armour = getint(p); - s->selectweapon(getint(p)); - loopi(NUMGUNS) s->ammo[i] = getint(p); - loopi(NUMGUNS) s->mag[i] = getint(p); - s->state = CS_SPAWNING; - break; - } - - case SV_SPAWNSTATE: - { - if(editmode) toggleedit(); - showscores(false); - setscope(false); - player1->respawn(); - player1->lifesequence = getint(p); - player1->health = getint(p); - player1->armour = getint(p); - player1->setprimary(getint(p)); - player1->selectweapon(getint(p)); - int arenaspawn = getint(p); - loopi(NUMGUNS) player1->ammo[i] = getint(p); - loopi(NUMGUNS) player1->mag[i] = getint(p); - player1->state = CS_ALIVE; - findplayerstart(player1, false, arenaspawn); - if(player1->skin!=player1->nextskin) setskin(player1, player1->nextskin); - arenaintermission = 0; - if(m_arena) - { - conoutf("new round starting... fight!"); - hudeditf(HUDMSG_TIMER, "fight!"); - if(m_botmode) BotManager.RespawnBots(); - } - addmsg(SV_SPAWN, "rii", player1->lifesequence, player1->weaponsel->type); - break; - } - - case SV_SHOTFX: - { - int scn = getint(p), gun = getint(p); - vec from, to; - loopk(3) from[k] = getint(p)/DMF; - loopk(3) to[k] = getint(p)/DMF; - playerent *s = getclient(scn); - if(!s || !weapon::valid(gun)) break; - if(gun==GUN_SHOTGUN) createrays(from, to); - s->lastaction = lastmillis; - s->mag[gun]--; - if(s->weapons[gun]) - { - s->lastattackweapon = s->weapons[gun]; - s->weapons[gun]->attackfx(from, to, -1); - } - break; - } - - case SV_THROWNADE: - { - vec from, to; - loopk(3) from[k] = getint(p)/DMF; - loopk(3) to[k] = getint(p)/DMF; - int nademillis = getint(p); - if(!d) break; - d->lastaction = lastmillis; - d->lastattackweapon = d->weapons[GUN_GRENADE]; - if(d->weapons[GUN_GRENADE]) d->weapons[GUN_GRENADE]->attackfx(from, to, nademillis); - break; - } - - case SV_RELOAD: - { - int cn = getint(p), gun = getint(p); - playerent *p = cn==getclientnum() ? player1 : getclient(cn); - if(!p || p==player1) break; - int bullets = magsize(gun)-p->mag[gun]; - p->ammo[gun] -= bullets; - p->mag[gun] += bullets; - break; - } - - case SV_GIBDAMAGE: - case SV_DAMAGE: - { - int tcn = getint(p), - acn = getint(p), - damage = getint(p), - armour = getint(p), - health = getint(p); - playerent *target = tcn==getclientnum() ? player1 : getclient(tcn), - *actor = acn==getclientnum() ? player1 : getclient(acn); - if(!target || !actor) break; - target->armour = armour; - target->health = health; - dodamage(damage, target, actor, type==SV_GIBDAMAGE, false); - break; - } - - case SV_HITPUSH: - { - int gun = getint(p), damage = getint(p); - vec dir; - loopk(3) dir[k] = getint(p)/DNF; - player1->hitpush(damage, dir, NULL, gun); - break; - } - - case SV_GIBDIED: - case SV_DIED: - { - int vcn = getint(p), acn = getint(p), frags = getint(p); - playerent *victim = vcn==getclientnum() ? player1 : getclient(vcn), - *actor = acn==getclientnum() ? player1 : getclient(acn); - if(!actor) break; - actor->frags = frags; - if(!victim) break; - dokill(victim, actor, type==SV_GIBDIED); - break; - } - - case SV_RESUME: - { - loopi(MAXCLIENTS) + case SV_TEAMTEXT: { int cn = getint(p); - if(p.overread() || cn<0) break; - int state = getint(p), lifesequence = getint(p), gunselect = getint(p), flagscore = getint(p), frags = getint(p), deaths = getint(p), health = getint(p), armour = getint(p); - int ammo[NUMGUNS], mag[NUMGUNS]; - loopi(NUMGUNS) ammo[i] = getint(p); - loopi(NUMGUNS) mag[i] = getint(p); - playerent *d = (cn == getclientnum() ? player1 : newclient(cn)); - if(!d) continue; - if(d!=player1) d->state = state; - d->lifesequence = lifesequence; - d->flagscore = flagscore; - d->frags = frags; - d->deaths = deaths; - if(d!=player1) + getstring(text, p); + filtertext(text, text); + playerent *d = getclient(cn); + if(!d) break; + if(m_teammode) conoutf("%s:\f1 %s", colorname(d), text); + else conoutf("%s:\f0 %s", colorname(d), text); + break; + } + + case SV_TEXT: + if(cn == -1) { - d->selectweapon(gunselect); - d->health = health; - d->armour = armour; - memcpy(d->ammo, ammo, sizeof(ammo)); - memcpy(d->mag, mag, sizeof(mag)); + getstring(text, p); + conoutf("MOTD:"); + conoutf("\f4%s", text); } - } - break; - } - - case SV_ITEMSPAWN: - { - int i = getint(p); - setspawn(i, true); - break; - } - - case SV_ITEMACC: - { - int i = getint(p), cn = getint(p); - playerent *d = cn==getclientnum() ? player1 : getclient(cn); - pickupeffects(i, d); - break; - } - - case SV_EDITH: // coop editing messages, should be extended to include all possible editing ops - case SV_EDITT: - case SV_EDITS: - case SV_EDITD: - case SV_EDITE: - { - int x = getint(p); - int y = getint(p); - int xs = getint(p); - int ys = getint(p); - int v = getint(p); - block b = { x, y, xs, ys }; - switch(type) - { - case SV_EDITH: editheightxy(v!=0, getint(p), b); break; - case SV_EDITT: edittexxy(v, getint(p), b); break; - case SV_EDITS: edittypexy(v, b); break; - case SV_EDITD: setvdeltaxy(v, b); break; - case SV_EDITE: editequalisexy(v!=0, b); break; - } - break; - } - - case SV_EDITENT: // coop edit of ent - { - uint i = getint(p); - while((uint)ents.length()<=i) ents.add().type = NOTUSED; - int to = ents[i].type; - ents[i].type = getint(p); - ents[i].x = getint(p); - ents[i].y = getint(p); - ents[i].z = getint(p); - ents[i].attr1 = getint(p); - ents[i].attr2 = getint(p); - ents[i].attr3 = getint(p); - ents[i].attr4 = getint(p); - ents[i].spawned = false; - if(ents[i].type==LIGHT || to==LIGHT) calclight(); - break; - } - - case SV_PONG: - { - int millis = getint(p); - addmsg(SV_CLIENTPING, "i", player1->ping = max(0, (player1->ping*5+totalmillis-millis)/6)); - break; - } - - case SV_CLIENTPING: - if(!d) return; - d->ping = getint(p); - break; - - case SV_GAMEMODE: - nextmode = getint(p); - break; - - case SV_TIMEUP: - timeupdate(getint(p)); - break; - - case SV_WEAPCHANGE: - { - if(!d) return; - d->selectweapon(getint(p)); - break; - } - - case SV_SERVMSG: - getstring(text, p); - conoutf("%s", text); - break; - - case SV_FLAGINFO: - { - int flag = getint(p); - if(flag<0 || flag>1) return; - flaginfo &f = flaginfos[flag]; - f.state = getint(p); - switch(f.state) - { - case CTFF_STOLEN: - flagstolen(flag, getint(p)); - break; - case CTFF_DROPPED: + else if(d) { - short x = (ushort) (getint(p)/DMF); - short y = (ushort) (getint(p)/DMF); - short z = ((ushort) (getint(p)/DMF))-((short)player1->eyeheight); // correct z offset, assumes all players do have the same eyeheight - flagdropped(flag, x, y, z); - break; + getstring(text, p); + filtertext(text, text); + conoutf("%s:\f0 %s", colorname(d), text); } - case CTFF_INBASE: - flaginbase(flag); - break; - case CTFF_IDLE: - flagidle(flag); - break; - } - break; - } + else return; + break; - case SV_FLAGMSG: - { - int flag = getint(p); - int message = getint(p); - int actor = getint(p); - int flagtime = message == FM_KTFSCORE ? getint(p) : -1; - flagmsg(flag, message, actor, flagtime); - break; - } - - case SV_FLAGCNT: - { - int fcn = getint(p); - int flags = getint(p); - playerent *p = (fcn == getclientnum() ? player1 : getclient(fcn)); - if(p) p->flagscore = flags; - break; - } - - case SV_ARENAWIN: - { - int acn = getint(p); - playerent *alive = acn<0 ? NULL : (acn==getclientnum() ? player1 : getclient(acn)); - conoutf("arena round is over! next round in 5 seconds..."); - if(m_botmode && acn==-2) hudoutf("the bots have won the round!"); - else if(!alive) hudoutf("everyone died!"); - else if(m_teammode) hudoutf("team %s has won the round!", alive->team); - else if(alive==player1) hudoutf("you are the survivor!"); - else hudoutf("%s is the survivor!", colorname(alive)); - arenaintermission = lastmillis; - break; - } - - case SV_FORCEDEATH: - { - int cn = getint(p); - playerent *d = cn==getclientnum() ? player1 : newclient(cn); - if(!d) break; - deathstate(d); - break; - } - - case SV_SERVOPINFO: - { - loopv(players) { if(players[i]) players[i]->clientrole = CR_DEFAULT; } - player1->clientrole = CR_DEFAULT; - - int cl = getint(p), r = getint(p); - if(cl >= 0 && r >= 0) - { - playerent *pl = (cl == getclientnum() ? player1 : newclient(cl)); - if(pl) - { - pl->clientrole = r; - if(pl->name[0]) conoutf("%s claimed %s status", pl == player1 ? "you" : colorname(pl), r == CR_ADMIN ? "admin" : "master"); - } - } - break; - } - - case SV_FORCETEAM: - { - int team = getint(p), oldteam = team_int(player1->team); - int attr = getint(p); - bool respawn = (attr & 1) == 1; - changeteam(team, respawn); - if(attr & 2) hudoutf("you %s team %s", team == oldteam ? "stay in" : "got forced to", team_string(team)); - break; - } - - case SV_FORCENOTIFY: - { - int fpl = getint(p); - int fnt = getint(p); - playerent *d = getclient(fpl); - bool you = fpl == player1->clientnum; // sound? - bool et = team_int(player1->team) != fnt; - hudoutf("the server forced %s to%s team%s", you ? "you" : d ? colorname(d) : "", you ? "" : et ? " the enemy" : " your", you ? fnt ? " RVSF": " CLA" : ""); - break; - } - - case SV_AUTOTEAM: - { - int na = getint(p); - switch(na) - { - case AT_ENABLED: - case AT_DISABLED: - autoteambalance = na == AT_ENABLED; - break; - case AT_SHUFFLE: // sound? - break; - } - break; - } - case SV_CALLVOTE: - { - int type = getint(p); - if(type < 0 || type >= SA_NUM || !d) return; - votedisplayinfo *v = NULL; - string a; - switch(type) - { - case SA_MAP: - getstring(text, p); - itoa(a, getint(p)); - v = newvotedisplayinfo(d, type, text, a); - break; - case SA_SERVERDESC: - getstring(text, p); - v = newvotedisplayinfo(d, type, text, NULL); - break; - default: - itoa(a, getint(p)); - v = newvotedisplayinfo(d, type, a, NULL); - break; - } - displayvote(v); - break; - } - - case SV_CALLVOTESUC: - callvotesuc(); - break; - - case SV_CALLVOTEERR: - callvoteerr(getint(p)); - break; - - case SV_VOTE: - votecount(getint(p)); - break; - - case SV_VOTERESULT: - voteresult(getint(p)); - break; - - case SV_WHOISINFO: - { - int cn = getint(p); - playerent *pl = cn == getclientnum() ? player1 : getclient(cn); - int ip = getint(p); - if((ip>>16&0xFF) > 0 && (ip>>24&0xFF) > 0) conoutf("WHOIS client %d:\n\f5name\t%s\n\f5IP\t%d.%d.%d.%d", cn, pl ? colorname(pl) : "", ip&0xFF, ip>>8&0xFF, ip>>16&0xFF, ip>>24&0xFF); // full IP - else conoutf("WHOIS client %d:\n\f5name\t%s\n\f5IP\t%d.%d.x.x", cn, pl ? colorname(pl) : "", ip&0xFF, ip>>8&0xFF); // censored IP - break; - } - - case SV_SENDDEMOLIST: - { - int demos = getint(p); - if(!demos) conoutf("no demos available"); - else loopi(demos) + case SV_MAPCHANGE: { getstring(text, p); - conoutf("%d. %s", i+1, text); + int mode = getint(p); + bool downloadable = getint(p) > 0; + changemapserv(text, mode, downloadable); + if(m_arena && joining>2) deathstate(player1); + mapchanged = true; + break; } - break; - } - case SV_DEMOPLAYBACK: - { - watchingdemo = demoplayback = getint(p)!=0; - if(demoplayback) + case SV_ITEMLIST: { - player1->state = CS_SPECTATE; - player1->spectatemode = SM_NONE; + int n; + if(mapchanged||watchingdemo) { senditemstoserver = false; resetspawns(); } + while((n = getint(p))!=-1) if(mapchanged||watchingdemo) setspawn(n, true); + break; } - else + + case SV_SPAWNLIST: { - // cleanups - loopv(players) zapplayer(players[i]); - clearvote(); + if(getint(p) > 0) loopi(5) getint(p); + break; + } + + case SV_MAPRELOAD: // server requests next map + { + getint(p); + s_sprintfd(nextmapalias)("nextmap_%s", getclientmap()); + const char *map = getalias(nextmapalias); // look up map in the cycle + changemap(map ? map : getclientmap()); + break; + } + + case SV_INITC2S: // another client either connected or changed name/team + { + d = newclient(cn); + getstring(text, p); + filtertext(text, text, 0, MAXNAMELEN); + if(!text[0]) s_strcpy(text, "unarmed"); + if(d->name[0]) // already connected + { + if(strcmp(d->name, text)) + conoutf("%s is now known as %s", colorname(d, 0), colorname(d, 1, text)); + } + else // new client + { + c2sinit = false; // send new players my info again + conoutf("connected: %s", colorname(d, 0, text)); + } + s_strncpy(d->name, text, MAXNAMELEN+1); + getstring(text, p); + filtertext(d->team, text, 0, MAXTEAMLEN); + setskin(d, getint(p)); + if(m_flags) loopi(2) + { + flaginfo &f = flaginfos[i]; + if(!f.actor) f.actor = getclient(f.actor_cn); + } + break; + } + + case SV_CDIS: + { + int cn = getint(p); + playerent *d = getclient(cn); + if(!d) break; + if(d->name[0]) conoutf("player %s disconnected", colorname(d)); + zapplayer(players[cn]); + break; + } + + case SV_EDITMODE: + { + int val = getint(p); + if(!d) break; + if(val) d->state = CS_EDITING; + else d->state = CS_ALIVE; + break; + } + + case SV_SPAWN: + { + playerent *s = d; + if(!s) { static playerent dummy; s = &dummy; } + s->respawn(); + s->lifesequence = getint(p); + s->health = getint(p); + s->armour = getint(p); + s->selectweapon(getint(p)); + loopi(NUMGUNS) s->ammo[i] = getint(p); + loopi(NUMGUNS) s->mag[i] = getint(p); + s->state = CS_SPAWNING; + break; + } + + case SV_SPAWNSTATE: + { + if(editmode) toggleedit(); + showscores(false); + setscope(false); + player1->respawn(); + player1->lifesequence = getint(p); + player1->health = getint(p); + player1->armour = getint(p); + player1->setprimary(getint(p)); + player1->selectweapon(getint(p)); + int arenaspawn = getint(p); + loopi(NUMGUNS) player1->ammo[i] = getint(p); + loopi(NUMGUNS) player1->mag[i] = getint(p); player1->state = CS_ALIVE; - player1->spectatemode = SM_NONE; + findplayerstart(player1, false, arenaspawn); + if(player1->skin!=player1->nextskin) setskin(player1, player1->nextskin); + arenaintermission = 0; + if(m_arena) + { + conoutf("new round starting... fight!"); + hudeditf(HUDMSG_TIMER, "fight!"); + if(m_botmode) BotManager.RespawnBots(); + } + addmsg(SV_SPAWN, "rii", player1->lifesequence, player1->weaponsel->type); + break; } - break; - } - default: - neterr("type"); - return; + case SV_SHOTFX: + { + int scn = getint(p), gun = getint(p); + vec from, to; + loopk(3) from[k] = getint(p)/DMF; + loopk(3) to[k] = getint(p)/DMF; + playerent *s = getclient(scn); + if(!s || !weapon::valid(gun)) break; + if(gun==GUN_SHOTGUN) createrays(from, to); + s->lastaction = lastmillis; + s->mag[gun]--; + if(s->weapons[gun]) + { + s->lastattackweapon = s->weapons[gun]; + s->weapons[gun]->attackfx(from, to, -1); + } + break; + } + + case SV_THROWNADE: + { + vec from, to; + loopk(3) from[k] = getint(p)/DMF; + loopk(3) to[k] = getint(p)/DMF; + int nademillis = getint(p); + if(!d) break; + d->lastaction = lastmillis; + d->lastattackweapon = d->weapons[GUN_GRENADE]; + if(d->weapons[GUN_GRENADE]) d->weapons[GUN_GRENADE]->attackfx(from, to, nademillis); + break; + } + + case SV_RELOAD: + { + int cn = getint(p), gun = getint(p); + playerent *p = cn==getclientnum() ? player1 : getclient(cn); + if(!p || p==player1) break; + int bullets = magsize(gun)-p->mag[gun]; + p->ammo[gun] -= bullets; + p->mag[gun] += bullets; + break; + } + + case SV_GIBDAMAGE: + case SV_DAMAGE: + { + int tcn = getint(p), + acn = getint(p), + damage = getint(p), + armour = getint(p), + health = getint(p); + playerent *target = tcn==getclientnum() ? player1 : getclient(tcn), + *actor = acn==getclientnum() ? player1 : getclient(acn); + if(!target || !actor) break; + target->armour = armour; + target->health = health; + dodamage(damage, target, actor, type==SV_GIBDAMAGE, false); + break; + } + + case SV_HITPUSH: + { + int gun = getint(p), damage = getint(p); + vec dir; + loopk(3) dir[k] = getint(p)/DNF; + player1->hitpush(damage, dir, NULL, gun); + break; + } + + case SV_GIBDIED: + case SV_DIED: + { + int vcn = getint(p), acn = getint(p), frags = getint(p); + playerent *victim = vcn==getclientnum() ? player1 : getclient(vcn), + *actor = acn==getclientnum() ? player1 : getclient(acn); + if(!actor) break; + actor->frags = frags; + if(!victim) break; + dokill(victim, actor, type==SV_GIBDIED); + break; + } + + case SV_RESUME: + { + loopi(MAXCLIENTS) + { + int cn = getint(p); + if(p.overread() || cn<0) break; + int state = getint(p), lifesequence = getint(p), gunselect = getint(p), flagscore = getint(p), frags = getint(p), deaths = getint(p), health = getint(p), armour = getint(p); + int ammo[NUMGUNS], mag[NUMGUNS]; + loopi(NUMGUNS) ammo[i] = getint(p); + loopi(NUMGUNS) mag[i] = getint(p); + playerent *d = (cn == getclientnum() ? player1 : newclient(cn)); + if(!d) continue; + if(d!=player1) d->state = state; + d->lifesequence = lifesequence; + d->flagscore = flagscore; + d->frags = frags; + d->deaths = deaths; + if(d!=player1) + { + d->selectweapon(gunselect); + d->health = health; + d->armour = armour; + memcpy(d->ammo, ammo, sizeof(ammo)); + memcpy(d->mag, mag, sizeof(mag)); + } + } + break; + } + + case SV_ITEMSPAWN: + { + int i = getint(p); + setspawn(i, true); + break; + } + + case SV_ITEMACC: + { + int i = getint(p), cn = getint(p); + playerent *d = cn==getclientnum() ? player1 : getclient(cn); + pickupeffects(i, d); + break; + } + + case SV_EDITH: // coop editing messages, should be extended to include all possible editing ops + case SV_EDITT: + case SV_EDITS: + case SV_EDITD: + case SV_EDITE: + { + int x = getint(p); + int y = getint(p); + int xs = getint(p); + int ys = getint(p); + int v = getint(p); + block b = { x, y, xs, ys }; + switch(type) + { + case SV_EDITH: editheightxy(v!=0, getint(p), b); break; + case SV_EDITT: edittexxy(v, getint(p), b); break; + case SV_EDITS: edittypexy(v, b); break; + case SV_EDITD: setvdeltaxy(v, b); break; + case SV_EDITE: editequalisexy(v!=0, b); break; + } + break; + } + + case SV_EDITENT: // coop edit of ent + { + uint i = getint(p); + while((uint)ents.length()<=i) ents.add().type = NOTUSED; + int to = ents[i].type; + ents[i].type = getint(p); + ents[i].x = getint(p); + ents[i].y = getint(p); + ents[i].z = getint(p); + ents[i].attr1 = getint(p); + ents[i].attr2 = getint(p); + ents[i].attr3 = getint(p); + ents[i].attr4 = getint(p); + ents[i].spawned = false; + if(ents[i].type==LIGHT || to==LIGHT) calclight(); + break; + } + + case SV_PONG: + { + int millis = getint(p); + addmsg(SV_CLIENTPING, "i", player1->ping = max(0, (player1->ping*5+totalmillis-millis)/6)); + break; + } + + case SV_CLIENTPING: + if(!d) return; + d->ping = getint(p); + break; + + case SV_GAMEMODE: + nextmode = getint(p); + break; + + case SV_TIMEUP: + timeupdate(getint(p)); + break; + + case SV_WEAPCHANGE: + { + if(!d) return; + d->selectweapon(getint(p)); + break; + } + + case SV_SERVMSG: + getstring(text, p); + conoutf("%s", text); + break; + + case SV_FLAGINFO: + { + int flag = getint(p); + if(flag<0 || flag>1) return; + flaginfo &f = flaginfos[flag]; + f.state = getint(p); + switch(f.state) + { + case CTFF_STOLEN: + flagstolen(flag, getint(p)); + break; + case CTFF_DROPPED: + { + short x = (ushort) (getint(p)/DMF); + short y = (ushort) (getint(p)/DMF); + short z = ((ushort) (getint(p)/DMF))-((short)player1->eyeheight); // correct z offset, assumes all players do have the same eyeheight + flagdropped(flag, x, y, z); + break; + } + case CTFF_INBASE: + flaginbase(flag); + break; + case CTFF_IDLE: + flagidle(flag); + break; + } + break; + } + + case SV_FLAGMSG: + { + int flag = getint(p); + int message = getint(p); + int actor = getint(p); + int flagtime = message == FM_KTFSCORE ? getint(p) : -1; + flagmsg(flag, message, actor, flagtime); + break; + } + + case SV_FLAGCNT: + { + int fcn = getint(p); + int flags = getint(p); + playerent *p = (fcn == getclientnum() ? player1 : getclient(fcn)); + if(p) p->flagscore = flags; + break; + } + + case SV_ARENAWIN: + { + int acn = getint(p); + playerent *alive = acn<0 ? NULL : (acn==getclientnum() ? player1 : getclient(acn)); + conoutf("arena round is over! next round in 5 seconds..."); + if(m_botmode && acn==-2) hudoutf("the bots have won the round!"); + else if(!alive) hudoutf("everyone died!"); + else if(m_teammode) hudoutf("team %s has won the round!", alive->team); + else if(alive==player1) hudoutf("you are the survivor!"); + else hudoutf("%s is the survivor!", colorname(alive)); + arenaintermission = lastmillis; + break; + } + + case SV_FORCEDEATH: + { + int cn = getint(p); + playerent *d = cn==getclientnum() ? player1 : newclient(cn); + if(!d) break; + deathstate(d); + break; + } + + case SV_SERVOPINFO: + { + loopv(players) { if(players[i]) players[i]->clientrole = CR_DEFAULT; } + player1->clientrole = CR_DEFAULT; + + int cl = getint(p), r = getint(p); + if(cl >= 0 && r >= 0) + { + playerent *pl = (cl == getclientnum() ? player1 : newclient(cl)); + if(pl) + { + pl->clientrole = r; + if(pl->name[0]) conoutf("%s claimed %s status", pl == player1 ? "you" : colorname(pl), r == CR_ADMIN ? "admin" : "master"); + } + } + break; + } + + case SV_FORCETEAM: + { + int team = getint(p), oldteam = team_int(player1->team); + int attr = getint(p); + bool respawn = (attr & 1) == 1; + changeteam(team, respawn); + if(attr & 2) hudoutf("you %s team %s", team == oldteam ? "stay in" : "got forced to", team_string(team)); + break; + } + + case SV_FORCENOTIFY: + { + int fpl = getint(p); + int fnt = getint(p); + playerent *d = getclient(fpl); + bool you = fpl == player1->clientnum; // sound? + bool et = team_int(player1->team) != fnt; + hudoutf("the server forced %s to%s team%s", you ? "you" : d ? colorname(d) : "", you ? "" : et ? " the enemy" : " your", you ? fnt ? " RVSF": " CLA" : ""); + break; + } + + case SV_AUTOTEAM: + { + int na = getint(p); + switch(na) + { + case AT_ENABLED: + case AT_DISABLED: + autoteambalance = na == AT_ENABLED; + break; + case AT_SHUFFLE: // sound? + break; + } + break; + } + case SV_CALLVOTE: + { + int type = getint(p); + if(type < 0 || type >= SA_NUM || !d) return; + votedisplayinfo *v = NULL; + string a; + switch(type) + { + case SA_MAP: + getstring(text, p); + itoa(a, getint(p)); + v = newvotedisplayinfo(d, type, text, a); + break; + case SA_SERVERDESC: + getstring(text, p); + v = newvotedisplayinfo(d, type, text, NULL); + break; + default: + itoa(a, getint(p)); + v = newvotedisplayinfo(d, type, a, NULL); + break; + } + displayvote(v); + break; + } + + case SV_CALLVOTESUC: + callvotesuc(); + break; + + case SV_CALLVOTEERR: + callvoteerr(getint(p)); + break; + + case SV_VOTE: + votecount(getint(p)); + break; + + case SV_VOTERESULT: + voteresult(getint(p)); + break; + + case SV_WHOISINFO: + { + int cn = getint(p); + playerent *pl = cn == getclientnum() ? player1 : getclient(cn); + int ip = getint(p); + if((ip>>16&0xFF) > 0 && (ip>>24&0xFF) > 0) conoutf("WHOIS client %d:\n\f5name\t%s\n\f5IP\t%d.%d.%d.%d", cn, pl ? colorname(pl) : "", ip&0xFF, ip>>8&0xFF, ip>>16&0xFF, ip>>24&0xFF); // full IP + else conoutf("WHOIS client %d:\n\f5name\t%s\n\f5IP\t%d.%d.x.x", cn, pl ? colorname(pl) : "", ip&0xFF, ip>>8&0xFF); // censored IP + break; + } + + case SV_SENDDEMOLIST: + { + int demos = getint(p); + if(!demos) conoutf("no demos available"); + else loopi(demos) + { + getstring(text, p); + conoutf("%d. %s", i+1, text); + } + break; + } + + case SV_DEMOPLAYBACK: + { + watchingdemo = demoplayback = getint(p)!=0; + if(demoplayback) + { + player1->state = CS_SPECTATE; + player1->spectatemode = SM_NONE; + } + else + { + // cleanups + loopv(players) zapplayer(players[i]); + clearvote(); + player1->state = CS_ALIVE; + player1->spectatemode = SM_NONE; + } + break; + } + + default: + neterr("type"); + return; + } } // check if joining here so as not to interrupt welcomepacket @@ -750,6 +768,10 @@ void parsemessages(int cn, playerent *d, ucharbuf &p) nextmode = gamemode; changemap(getclientmap()); } + + #ifdef _DEBUG + protocoldebug(false); + #endif } void receivefile(uchar *data, int len)