Ejemplo n.º 1
0
void acceptmove(void)
{
    int ta;
    int ma;
    char af;
    int moved = 0;
    int vma, dir;
    char prompt[60];
    char buf[60], last = '\0';
    char *p;

    if (!mc->crew3 || snagged(ms) || !windspeed) {
	Msg("Unable to move");
	return;
    }

    ta = maxturns(ms, &af);
    ma = maxmove(ms, mf->dir, 0);
    sprintf(prompt, "move (%d,%c%d): ", ma, af ? '\'' : ' ', ta);
    sgetstr(prompt, buf, sizeof buf);
    dir = mf->dir;
    vma = ma;
    for (p = buf; *p; p++)
	switch (*p) {
	    case 'l':
		dir -= 2;
	    case 'r':
		if (++dir == 0)
		    dir = 8;
		else if (dir == 9)
		    dir = 1;
		if (last == 't') {
		    Msg("Ship can't turn that fast.");
		    *p-- = '\0';
		}
		last = 't';
		ma--;
		ta--;
		vma = min(ma, maxmove(ms, dir, 0));
		if ((ta < 0 && moved) || (vma < 0 && moved))
		    *p-- = '\0';
		break;
	    case 'b':
		ma--;
		vma--;
		last = 'b';
		if ((ta < 0 && moved) || (vma < 0 && moved))
		    *p-- = '\0';
		break;
	    case '0':
	    case 'd':
		*p-- = '\0';
		break;
	    case '\n':
		*p-- = '\0';
		break;
	    case '1':
	    case '2':
	    case '3':
	    case '4':
	    case '5':
	    case '6':
	    case '7':
		if (last == '0') {
		    Msg("Can't move that fast.");
		    *p-- = '\0';
		}
		last = '0';
		moved = 1;
		ma -= *p - '0';
		vma -= *p - '0';
		if ((ta < 0 && moved) || (vma < 0 && moved))
		    *p-- = '\0';
		break;
	    default:
		if (!isspace((unsigned char) *p)) {
		    Msg("Input error.");
		    *p-- = '\0';
		}
	}
    if ((ta < 0 && moved) || (vma < 0 && moved)
	|| (af && turnfirst(buf) && moved)) {
	Msg("Movement error.");
	if (ta < 0 && moved) {
	    if (mf->FS == 1) {
		Write(W_FS, ms, 0, 0, 0, 0);
		Msg("No hands to set full sails.");
	    }
	} else if (ma >= 0)
	    buf[1] = '\0';
    }
    if (af && !moved) {
	if (mf->FS == 1) {
	    Write(W_FS, ms, 0, 0, 0, 0);
	    Msg("No hands to set full sails.");
	}
    }
    if (*buf)
	strcpy(movebuf, buf);
    else
	strcpy(movebuf, "d");
    Writestr(W_MOVE, ms, movebuf);
    Msg("Helm: %s.", movebuf);
}
Ejemplo n.º 2
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;
	};
};
Ejemplo n.º 3
0
// server side processing of updates: does very little and most state is tracked
// client only could be extended to move more gameplay to server (at expense of
// lag)
void process(ENetPacket * packet, int sender) { // sender may be -1
  const u16 len = *(u16*) packet->data;
  if (ENET_NET_TO_HOST_16(len)!=packet->dataLength) {
    disconnect_client(sender, "packet length");
    return;
  }

  u8 *end = packet->data+packet->dataLength;
  u8 *p = packet->data+2;
  char text[MAXTRANS];
  int cn = -1, type;

  while (p<end) switch (type = getint(p)) {
    case SV_TEXT:
      sgetstr();
    break;
    case SV_INITC2S:
      sgetstr();
      strcpy_s(clients[cn].name, text);
      sgetstr();
      getint(p);
    break;
    case SV_MAPCHANGE: {
      sgetstr();
      int reqmode = getint(p);
      if (reqmode<0) reqmode = 0;
      if (smapname[0] && !mapreload && !vote(text, reqmode, sender)) return;
      mapreload = false;
      mode = reqmode;
      minremain = mode&1 ? 15 : 10;
      mapend = lastsec+minremain*60;
      interm = 0;
      strcpy_s(smapname, text);
      resetitems();
      sender = -1;
    }
    break;
    case SV_ITEMLIST: {
      int n;
      while ((n = getint(p))!=-1) if (notgotitems) {
        server_entity se = { false, 0 };
        while (sents.size()<=n) sents.push_back(se);
        sents[n].spawned = true;
      }
      notgotitems = false;
    }
    break;
    case SV_ITEMPICKUP: {
      const int n = getint(p);
      pickup(n, getint(p), sender);
    }
    break;
    case SV_PING:
      send2(false, cn, SV_PONG, getint(p));
    break;
    case SV_POS: {
      cn = getint(p);
      if (cn<0 || cn>=clients.size() || clients[cn].type==ST_EMPTY) {
        disconnect_client(sender, "client num");
        return;
      }
      int size = msgsizelookup(type);
      assert(size!=-1);
      loopi(size-2) getint(p);
    }
    break;
    case SV_SENDMAP: {
      sgetstr();
      const auto mapsize = getint(p);
      sendmaps(sender, text, mapsize, p);
    }
    return;
    case SV_RECVMAP:
      send(sender, recvmap(sender));
    return;
    case SV_EXT:   // allows for new features that require no server updates 
      for (int n = getint(p); n; n--) getint(p);
    break;
    default: {
      const int size = msgsizelookup(type);
      if (size==-1) { disconnect_client(sender, "tag type"); return; };
      loopi(size-1) getint(p);
    }
  }

  if (p>end) { disconnect_client(sender, "end of packet"); return; };
  multicast(packet, sender);
}
Ejemplo n.º 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;
	Sprite *spr = 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 = "";
			clientnum = cn;                 // we are now fully connected
			if (!getint(p)) {
				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);
			spr = getclient(cn);
			if (!spr)
				return;
			spr->o.x = getint(p) / DMF;
			spr->o.y = getint(p) / DMF;
			spr->o.z = getint(p) / DMF;
			spr->yaw = getint(p) / DAF;
			spr->pitch = getint(p) / DAF;
			spr->roll = getint(p) / DAF;
			spr->vel.x = getint(p) / DVF;
			spr->vel.y = getint(p) / DVF;
			spr->vel.z = getint(p) / DVF;
			int f = getint(p);
			spr->strafe = (f & 3) == 3 ? -1 : f & 3;
			f >>= 2;
			spr->move = (f & 3) == 3 ? -1 : f & 3;
			spr->onfloor = (f >> 2) & 1;
			int state = f >> 3;
			if (state == CS_DEAD && spr->state != CS_DEAD)
				spr->lastaction = lastmillis;
			spr->state = state;
			if (!demoplayback)
				updatepos(spr);
			break;
		}
		case SV_SOUND:
			playsound(getint(p), &spr->o);
			break;
		case SV_TEXT:
			sgetstr();
			conoutf("%s:\f %s", spr->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);
			std::string nextmapalias = std::string("nextmap_") + getclientmap();
			std::string map = getalias(nextmapalias);     // look up map in the cycle
			changemap(map.empty() ? getclientmap() : map);
			break;
		}

		case SV_INITC2S: // another client either connected or changed name/team
		{
			sgetstr();

			if (spr->name[0]) {         // already connected
				if (strcmp(spr->name, text))
					conoutf("%s is now known as %s", spr->name, text);
			} else {                   // new client
				c2sinit = false;    // send new players my info again 
				conoutf("connected: %s", text);
			};
			strcpy_s(spr->name, text);
			sgetstr();

			strcpy_s(spr->team, text);
			spr->lifesequence = getint(p);
			break;
		}

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

		case SV_SHOT: {
			int gun = getint(p);
			Vec3 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, spr);
			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, spr);
			} else
				playsound(S_PAIN1 + rnd(5), &getclient(target)->o);
			break;
		}

		case SV_DIED: {
			int actor = getint(p);
			if (actor == cn) {
				conoutf("%s suicided", spr->name);
			} else if (actor == clientnum) {
				int frags;
				if (isteam(player1->team, spr->team)) {
					frags = -1;
					conoutf("you fragged a teammate (%s)", spr->name);
				} else {
					frags = 1;
					conoutf("you fragged %s", spr->name);
				};
				addmsg(1, 2, SV_FRAGS, player1->frags += frags);
			} else {
				Sprite *a = getclient(actor);
				if (a) {
					if (isteam(a->team, spr->name)) {
						conoutf("%s fragged his teammate (%s)", a->name, spr->name);
					} else {
						conoutf("%s fragged %s", a->name, spr->name);
					};
				};
			};
			playsound(S_DIE1 + rnd(2), &spr->o);
			spr->lifesequence++;
			break;
		}
		case SV_FRAGS:
			players[cn]->frags = getint(p);
			break;
		case SV_ITEMPICKUP:
			setspawn(getint(p), false);
			getint(p);
			break;
		case SV_ITEMSPAWN: {
			int i = getint(p);
			setspawn(i, true);
			if (i >= entityList.size())
				break;
			Vec3 v = { entityList[i].x, entityList[i].y, entityList[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_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);
			Rect 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
		{
			int i = getint(p);
			while (entityList.size() <= i) {
				entityList.emplace_back(Entity());
				entityList.back().type = NOTUSED;
			}
			int to = entityList[i].type;
			entityList[i].type = getint(p);
			entityList[i].x = getint(p);
			entityList[i].y = getint(p);
			entityList[i].z = getint(p);
			entityList[i].attr1 = getint(p);
			entityList[i].attr2 = getint(p);
			entityList[i].attr3 = getint(p);
			entityList[i].attr4 = getint(p);
			entityList[i].spawned = false;
			if (entityList[i].type == LIGHT || to == LIGHT)
				calclight();
			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;
		}
}