Beispiel #1
0
void stopreset()
{
    conoutf("demo stopped (%d msec elapsed)", lastmillis-starttime);
    stop();
    loopv(players) zapdynent(players[i]);
    disconnect(0, 0);
};
Beispiel #2
0
void stop()
{
    if(f)
    {
        if(demorecording) gzputi(-1);
        gzclose(f);
    };
    f = NULL;
    demorecording = false;
    demoplayback = false;
    demoloading = false;
    loopv(playerhistory) zapdynent(playerhistory[i]);
    playerhistory.setsize(0);
};
Beispiel #3
0
void demoplaybackstep()
{
    while(demoplayback && lastmillis>=playbacktime)
    {
        int len = gzgeti();
        if(len<1 || len>MAXTRANS)
        {
            conoutf("error: huge packet during demo play (%d)", len);
            stopreset();
            return;
        };
        uchar buf[MAXTRANS];
        gzread(f, buf, len);
        localservertoclient(buf, len);  // update game state
        
        dynent *target = players[democlientnum];
        assert(target); 
        
		int extras;
        if(extras = gzget())     // read additional client side state not present in normal network stream
        {
            target->gunselect = gzget();
            target->lastattackgun = gzget();
            target->lastaction = scaletime(gzgeti());
            target->gunwait = gzgeti();
            target->health = gzgeti();
            target->armour = gzgeti();
            target->armourtype = gzget();
            loopi(NUMGUNS) target->ammo[i] = gzget();
            target->state = gzget();
            target->lastmove = playbacktime;
			if(bdamage = gzgeti()) damageblend(bdamage);
			if(ddamage = gzgeti()) { gzgetv(dorig); particle_splash(3, ddamage, 1000, dorig); };
            // FIXME: set more client state here
        };
        
        // insert latest copy of player into history
        if(extras && (playerhistory.empty() || playerhistory.last()->lastupdate!=playbacktime))
        {
            dynent *d = newdynent();
            *d = *target;
            d->lastupdate = playbacktime;
            playerhistory.add(d);
            if(playerhistory.length()>20)
            {
                zapdynent(playerhistory[0]);
                playerhistory.remove(0);
            };
        };
        
        readdemotime();
    };
    
    if(demoplayback)
    {
        int itime = lastmillis-demodelaymsec;
        loopvrev(playerhistory) if(playerhistory[i]->lastupdate<itime)      // find 2 positions in history that surround interpolation time point
        {
            dynent *a = playerhistory[i];
            dynent *b = a;
            if(i+1<playerhistory.length()) b = playerhistory[i+1];
            *player1 = *b;
            if(a!=b)                                // interpolate pos & angles
            {
				dynent *c = b;
				if(i+2<playerhistory.length()) c = playerhistory[i+2];
				dynent *z = a;
				if(i-1>=0) z = playerhistory[i-1];
				//if(a==z || b==c) printf("* %d\n", lastmillis);
				float bf = (itime-a->lastupdate)/(float)(b->lastupdate-a->lastupdate);
				fixwrap(a, player1);
				fixwrap(c, player1);
				fixwrap(z, player1);
				vdist(dist, v, z->o, c->o);
				if(dist<16)		// if teleport or spawn, dont't interpolate
				{
					catmulrom(z->o, a->o, b->o, c->o, bf, player1->o);
					catmulrom(*(vec *)&z->yaw, *(vec *)&a->yaw, *(vec *)&b->yaw, *(vec *)&c->yaw, bf, *(vec *)&player1->yaw);
				};
				fixplayer1range();
			};
            break;
        };
        //if(player1->state!=CS_DEAD) showscores(false);
    };
};
Beispiel #4
0
void localservertoclient(uchar *buf, int len)   // processes any updates from the server
{
	if(ENET_NET_TO_HOST_16(*(ushort *)buf)!=len) neterr("packet length");
	incomingdemodata(buf, len);

	uchar *end = buf+len;
	uchar *p = buf+2;
	char text[MAXTRANS];
	int cn = -1, type;
	dynent *d = NULL;
	bool mapchanged = false;

	while(p<end) switch(type = getint(p))
	{
		case SV_INITS2C:                    // welcome messsage from the server
			{
				cn = getint(p);
				int prot = getint(p);
				if(prot!=PROTOCOL_VERSION)
				{
					conoutf("you are using a different game protocol (you: %d, server: %d)", PROTOCOL_VERSION, prot);
					disconnect();
					return;
				};
				toservermap[0] = 0;
				clientnum = cn;                 // we are now fully connected
				if(!getint(p)) strcpy_s(toservermap, getclientmap());   // we are the first client on this server, set map
				sgetstr();
				if(text[0] && strcmp(text, clientpassword))
				{
					conoutf("you need to set the correct password to join this server!");
					disconnect();
					return;
				};
				if(getint(p)==1)
				{
					conoutf("server is FULL, disconnecting..");
				};
				break;
			};

		case SV_POS:                        // position of another client
			{
				cn = getint(p);
				d = getclient(cn);
				if(!d) return;
				d->o.x   = getint(p)/DMF;
				d->o.y   = getint(p)/DMF;
				d->o.z   = getint(p)/DMF;
				d->yaw   = getint(p)/DAF;
				d->pitch = getint(p)/DAF;
				d->roll  = getint(p)/DAF;
				d->vel.x = getint(p)/DVF;
				d->vel.y = getint(p)/DVF;
				d->vel.z = getint(p)/DVF;
				int f = getint(p);
				d->strafe = (f&3)==3 ? -1 : f&3;
				f >>= 2;
				d->move = (f&3)==3 ? -1 : f&3;
				d->onfloor = (f>>2)&1;
				int state = f>>3;
				if(state==CS_DEAD && d->state!=CS_DEAD) d->lastaction = lastmillis;
				d->state = state;
				if(!demoplayback) updatepos(d);
				break;
			};

		case SV_SOUND:
			playsound(getint(p), &d->o);
			break;

		case SV_TEXT:
			sgetstr();
			conoutf("%s:\f %s", d->name, text);
			break;

		case SV_MAPCHANGE:
			sgetstr();
			changemapserv(text, getint(p));
			mapchanged = true;
			break;

		case SV_ITEMLIST:
			{
				int n;
				if(mapchanged) { senditemstoserver = false; resetspawns(); };
				while((n = getint(p))!=-1) if(mapchanged) setspawn(n, true);
				break;
			};

		case SV_MAPRELOAD:          // server requests next map
			{
				getint(p);
				sprintf_sd(nextmapalias)("nextmap_%s", getclientmap());
				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
			{
				sgetstr();
				if(d->name[0])          // already connected
				{
					if(strcmp(d->name, text))
						conoutf("%s is now known as %s", d->name, text);
				}
				else                    // new client
				{
					c2sinit = false;    // send new players my info again
					conoutf("connected: %s", text);
				};
				strcpy_s(d->name, text);
				sgetstr();
				strcpy_s(d->team, text);
				d->lifesequence = getint(p);
				break;
			};

		case SV_CDIS:
			cn = getint(p);
			if(!(d = getclient(cn))) break;
			conoutf("player %s disconnected", d->name[0] ? d->name : "[incompatible client]");
			zapdynent(players[cn]);
			break;

		case SV_SHOT:
			{
				int gun = getint(p);
				vec s, e;
				s.x = getint(p)/DMF;
				s.y = getint(p)/DMF;
				s.z = getint(p)/DMF;
				e.x = getint(p)/DMF;
				e.y = getint(p)/DMF;
				e.z = getint(p)/DMF;
				if(gun==GUN_SG) createrays(s, e);
				shootv(gun, s, e, d);
				break;
			};

		case SV_DAMAGE:
			{
				int target = getint(p);
				int damage = getint(p);
				int ls = getint(p);
				if(target==clientnum) { if(ls==player1->lifesequence) selfdamage(damage, cn, d); }
				else playsound(S_PAIN1+rnd(5), &getclient(target)->o);
				break;
			};

		case SV_DIED:
			{
				int actor = getint(p);
				if(actor==cn)
				{
					conoutf("%s suicided", d->name);
				}
				else if(actor==clientnum)
				{
					int frags;
					if(isteam(player1->team, d->team))
					{
						frags = -1;
						conoutf("you fragged a teammate (%s)", d->name);
					}
					else
					{
						frags = 1;
						conoutf("you fragged %s", d->name);
					};
					addmsg(1, 2, SV_FRAGS, player1->frags += frags);
				}
				else
				{
					dynent *a = getclient(actor);
					if(a)
					{
						if(isteam(a->team, d->name))
						{
							conoutf("%s fragged his teammate (%s)", a->name, d->name);
						}
						else
						{
							conoutf("%s fragged %s", a->name, d->name);
						};
					};
				};
				playsound(S_DIE1+rnd(2), &d->o);
				d->lifesequence++;
				break;
			};

		case SV_FRAGS:
			players[cn]->frags = getint(p);
			break;

		case SV_ITEMPICKUP:
			setspawn(getint(p), false);
			getint(p);
			break;

		case SV_ITEMSPAWN:
			{
				uint i = getint(p);
				setspawn(i, true);
				if(i>=(uint)ents.length()) break;
				vec v = { ents[i].x, ents[i].y, ents[i].z };
				playsound(S_ITEMSPAWN, &v);
				break;
			};

		case SV_ITEMACC:            // server acknowledges that I picked up this item
			realpickup(getint(p), player1);
			break;

		case SV_PING:
			getint(p);
			break;

		case SV_PONG:
			addmsg(0, 2, SV_CLIENTPING, player1->ping = (player1->ping*5+lastmillis-getint(p))/6);
			break;

		case SV_CLIENTPING:
			players[cn]->ping = getint(p);
			break;

		case SV_GAMEMODE:
			nextmode = getint(p);
			break;

		case SV_TIMEUP:
			timeupdate(getint(p));
			break;

		case SV_RECVMAP:
			{
				sgetstr();
				conoutf("received map \"%s\" from server, reloading..", text);
				int mapsize = getint(p);
				writemap(text, mapsize, p);
				p += mapsize;
				changemapserv(text, gamemode);
				break;
			};

		case SV_SERVMSG:
			sgetstr();
			conoutf("%s", text);
			break;

		case SV_EXT:        // so we can messages without breaking previous clients/servers, if necessary
			{
				for(int n = getint(p); n; n--) getint(p);
				break;
			};

		default:
			neterr("type");
			return;
	};
};