Beispiel #1
0
// recv
BOOL recvDroidSecondary(NETQUEUE queue)
{
	DROID*          psDroid;
	SECONDARY_ORDER sec = DSO_ATTACK_RANGE;
	SECONDARY_STATE state = DSS_NONE;

	NETbeginDecode(queue, GAME_SECONDARY);
	{
		uint8_t player;
		uint32_t droid;

		NETuint8_t(&player);
		NETuint32_t(&droid);
		NETenum(&sec);
		NETenum(&state);

		// If we can not find the droid should we not ask for it?
		if (!IdToDroid(droid, player, &psDroid))
		{
			NETend();
			return false;
		}
	}
	NETend();

	// Set the droids secondary order
	turnOffMultiMsg(true);
	secondarySetState(psDroid, sec, state);
	turnOffMultiMsg(false);

	return true;
}
Beispiel #2
0
/// Does not read/write info->droidId!
static void NETQueuedDroidInfo(QueuedDroidInfo *info)
{
	NETuint8_t(&info->player);
	NETenum(&info->order);
	NETbool(&info->subType);
	if (info->subType)
	{
		NETuint32_t(&info->destId);
		NETenum(&info->destType);
	}
	else
	{
		NETuint32_t(&info->x);
		NETuint32_t(&info->y);
	}
	if (info->order == DORDER_BUILD || info->order == DORDER_LINEBUILD)
	{
		NETuint32_t(&info->structRef);
		NETuint16_t(&info->direction);
	}
	if (info->order == DORDER_LINEBUILD)
	{
		NETuint32_t(&info->x2);
		NETuint32_t(&info->y2);
	}
}
Beispiel #3
0
void recvMultiPlayerFeature(NETQUEUE queue)
{
	FEATURE_TYPE subType = FEAT_TREE;  // Dummy initialisation.
	uint32_t     x, y, id;
	unsigned int i;

	NETbeginDecode(queue, GAME_FEATURES);
	{
		NETenum(&subType);
		NETuint32_t(&x);
		NETuint32_t(&y);
		NETuint32_t(&id);
	}
	NETend();

	// Find the feature stats list that contains the feature type we want to build
	for (i = 0; i < numFeatureStats; ++i)
	{
		// If we found the correct feature type
		if (asFeatureStats[i].subType == subType)
		{
			// Create a feature of the specified type at the given location
			FEATURE *result = buildFeature(&asFeatureStats[i], x, y, false);
			result->id = id;
			break;
		}
	}
}
Beispiel #4
0
static void NETcoder(PACKETDIR dir)
{
	static const char original[] = "THIS IS A TEST STRING";
	char str[sizeof(original)];
	BOOL b = true;
	uint32_t u32 = 32;
	uint16_t u16 = 16;
	uint8_t u8 = 8;
	int32_t i32 = -32;
	int16_t i16 = -16;
	int8_t i8 = -8;
	test_enum te = test_b;

	sstrcpy(str, original);

	if (dir == PACKET_ENCODE)
		NETbeginEncode(0, 0);
	else
		NETbeginDecode(0);
	NETbool(&b);			assert(b == true);
	NETuint32_t(&u32);  assert(u32 == 32);
	NETuint16_t(&u16);  assert(u16 == 16);
	NETuint8_t(&u8);    assert(u8 == 8);
	NETint32_t(&i32);   assert(i32 == -32);
	NETint16_t(&i16);   assert(i16 == -16);
	NETint8_t(&i8);     assert(i8 == -8);
	NETstring(str, sizeof(str)); assert(strncmp(str, original, sizeof(str) - 1) == 0);
	NETenum(&te);       assert(te == test_b);
}
Beispiel #5
0
void recvMultiPlayerFeature(NETQUEUE queue)
{
	FEATURE_TYPE subType = FEAT_TREE;  // Dummy initialisation.
	uint32_t     x, y, id;
	unsigned int i;

	NETbeginDecode(queue, GAME_DEBUG_ADD_FEATURE);
	{
		NETenum(&subType);
		NETuint32_t(&x);
		NETuint32_t(&y);
		NETuint32_t(&id);
	}
	NETend();

	if (!getDebugMappingStatus() && bMultiPlayer)
	{
		debug(LOG_WARNING, "Failed to add feature for player %u.", NetPlay.players[queue.index].position);
		return;
	}

	// Find the feature stats list that contains the feature type we want to build
	for (i = 0; i < numFeatureStats; ++i)
	{
		// If we found the correct feature type
		if (asFeatureStats[i].subType == subType)
		{
			// Create a feature of the specified type at the given location
			FEATURE *result = buildFeature(&asFeatureStats[i], x, y, false);
			result->id = id;
			break;
		}
	}
}
Beispiel #6
0
// Send
BOOL sendDroidSecondary(const DROID* psDroid, SECONDARY_ORDER sec, SECONDARY_STATE state)
{
	if (!bMultiMessages)
		return true;

	NETbeginEncode(NETgameQueue(selectedPlayer), GAME_SECONDARY);
	{
		uint8_t player = psDroid->player;
		uint32_t droid = psDroid->id;

		NETuint8_t(&player);
		NETuint32_t(&droid);
		NETenum(&sec);
		NETenum(&state);
	}
	return NETend();
}
Beispiel #7
0
// ///////////////////////////////////////////////////////////////
// receive splattered artifacts
void recvMultiPlayerRandomArtifacts(NETQUEUE queue)
{
	int				count, i;
	uint8_t			quantity, player;
	uint32_t		tx,ty;
	uint32_t		ref;
	FEATURE_TYPE            type = FEAT_TREE;  // Dummy initialisation.
	FEATURE 		*pF;

	NETbeginDecode(queue, GAME_ARTIFACTS);
		NETuint8_t(&quantity);
		NETenum(&type);

	debug(LOG_FEATURE, "receiving %u artifact(s) type: (%s)", quantity, feature_names[type]);
	for (i = 0; i < numFeatureStats && asFeatureStats[i].subType != type; i++) {}

	for (count = 0; count < quantity; count++)
	{
		MAPTILE *psTile;

		NETuint32_t(&tx);
		NETuint32_t(&ty);
		NETuint32_t(&ref);
		NETuint8_t(&player);

		if (tx == INVALID_XY)
		{
			continue;
		}
		else if (!tileOnMap(tx, ty))
		{
			debug(LOG_ERROR, "Bad tile coordinates (%u,%u)", tx, ty);
			continue;
		}
		psTile = mapTile(tx, ty);
		if (!psTile || psTile->psObject != NULL)
		{
			debug(LOG_ERROR, "Already something at (%u,%u)!", tx, ty);
			continue;
		}

		pF = buildFeature((asFeatureStats + i), world_coord(tx), world_coord(ty), false);
		if (pF)
		{
			pF->id		= ref;
			pF->player	= player;
			syncDebugFeature(pF, '+');
		}
		else
		{
			debug(LOG_ERROR, "Couldn't build feature %u for player %u ?", ref, player);
		}
	}
	NETend();
}
/** Sends a build order for the given feature type to all players
 *  \param subType the type of feature to build
 *  \param x,y the coordinates to place the feature at
 */
void sendMultiPlayerFeature(FEATURE_TYPE subType, uint32_t x, uint32_t y, uint32_t id)
{
	NETbeginEncode(NET_FEATURES, NET_ALL_PLAYERS);
	{
		NETenum(&subType);
		NETuint32_t(&x);
		NETuint32_t(&y);
		NETuint32_t(&id);
	}
	NETend();
}
Beispiel #9
0
/** Sends a build order for the given feature type to all players
 *  \param subType the type of feature to build
 *  \param x,y the coordinates to place the feature at
 */
void sendMultiPlayerFeature(FEATURE_TYPE subType, uint32_t x, uint32_t y, uint32_t id)
{
	NETbeginEncode(NETgameQueue(selectedPlayer), GAME_FEATURES);
	{
		NETenum(&subType);
		NETuint32_t(&x);
		NETuint32_t(&y);
		NETuint32_t(&id);
	}
	NETend();
}
Beispiel #10
0
/// Does not read/write info->droidId!
static void NETQueuedDroidInfo(QueuedDroidInfo *info)
{
	NETuint8_t(&info->player);
	NETenum(&info->subType);
	switch (info->subType)
	{
		case ObjOrder:
		case LocOrder:
			NETenum(&info->order);
			if (info->subType == ObjOrder)
			{
				NETuint32_t(&info->destId);
				NETenum(&info->destType);
			}
			else
			{
				NETauto(&info->pos);
			}
			if (info->order == DORDER_BUILD || info->order == DORDER_LINEBUILD)
			{
				NETuint32_t(&info->structRef);
				NETuint16_t(&info->direction);
			}
			if (info->order == DORDER_LINEBUILD)
			{
				NETauto(&info->pos2);
			}
			if (info->order == DORDER_BUILDMODULE)
			{
				NETauto(&info->index);
			}
			NETbool(&info->add);
			break;
		case SecondaryOrder:
			NETenum(&info->secOrder);
			NETenum(&info->secState);
			break;
	}
}
Beispiel #11
0
// ////////////////////////////////////////////////////////////////////////////
// add an artifact on destruction if required.
void  technologyGiveAway(const STRUCTURE *pS)
{
	int				i;
	uint8_t			count = 1;
	uint32_t		x, y;
	FEATURE			*pF = NULL;
	FEATURE_TYPE	type = FEAT_GEN_ARTE;

	// If a fully built factory (or with modules under construction) which is our responsibility got destroyed
	if (pS->pStructureType->type == REF_FACTORY && (pS->status == SS_BUILT || pS->currentBuildPts >= pS->body)
	 && myResponsibility(pS->player))
	{
		x = map_coord(pS->pos.x);
		y = map_coord(pS->pos.y);

		// Pick a tile to place the artifact
		if (!pickATileGen(&x, &y, LOOK_FOR_EMPTY_TILE, zonedPAT))
		{
			ASSERT(false, "technologyGiveAway: Unable to find a free location");
		}

		// Get the feature offset
		for(i = 0; i < numFeatureStats && asFeatureStats[i].subType != FEAT_GEN_ARTE; i++);

		// 'Build' the artifact
		pF = buildFeature((asFeatureStats + i), world_coord(x), world_coord(y), false);
		if (pF)
		{
			pF->player = pS->player;
		}

		NETbeginEncode(NET_ARTIFACTS, NET_ALL_PLAYERS);
		{
			/* Make sure that we don't have to violate the constness of pS.
			 * Since the nettype functions aren't const correct when sending
			 */
			uint8_t player = pS->player;

			NETuint8_t(&count);
			NETenum(&type);
			NETuint32_t(&x);
			NETuint32_t(&y);
			NETuint32_t(&pF->id);
			NETuint8_t(&player);
		}
		NETend();
	}

	return;
}
Beispiel #12
0
///////////////////////////////////////////////////////////////////////////////
// splatter artifact gifts randomly about.
void  addMultiPlayerRandomArtifacts(uint8_t quantity, FEATURE_TYPE type)
{
	int             i, count;
	uint32_t	x, y;
	uint8_t		player = ANYPLAYER;

	debug(LOG_FEATURE, "Sending %u artifact(s) type: (%s)", quantity, feature_names[type]);
	NETbeginEncode(NETgameQueue(selectedPlayer), GAME_ARTIFACTS);
		NETuint8_t(&quantity);
		NETenum(&type);

		ASSERT(mapWidth > 20, "map not big enough");
		ASSERT(mapHeight > 20, "map not big enough");

		for (count = 0; count < quantity; count++)
		{
			uint32_t id = generateNewObjectId();

			for (i = 0; i < 3; i++) // try three times
			{
				// Between 10 and mapwidth - 10
				x = (rand()%(mapWidth - 20)) + 10;
				y = (rand()%(mapHeight - 20)) + 10;

				if (pickATileGen(&x, &y, LOOK_FOR_EMPTY_TILE, zonedPAT))
				{
					break;
				}
				else if (i == 2)
				{
					debug(LOG_FEATURE, "Unable to find a free location after 3 tries; giving up.");
					x = INVALID_XY;
				}
			}

			NETuint32_t(&x);
			NETuint32_t(&y);
			NETuint32_t(&id);
			NETuint8_t(&player);
		}

	NETend();
}
Beispiel #13
0
// ////////////////////////////////////////////////////////////////////////////
// add an artifact on destruction if required.
void  technologyGiveAway(const STRUCTURE *pS)
{
	uint8_t			count = 1;
	FEATURE_TYPE	type = FEAT_GEN_ARTE;

	// If a fully built factory (or with modules under construction) which is our responsibility got destroyed
	if (pS->pStructureType->type == REF_FACTORY && (pS->status == SS_BUILT || pS->currentBuildPts >= pS->body)
	 && myResponsibility(pS->player))
	{
		uint32_t x = map_coord(pS->pos.x);
		uint32_t y = map_coord(pS->pos.y);
		uint32_t id = generateNewObjectId();

		// Pick a tile to place the artifact
		if (!pickATileGen(&x, &y, LOOK_FOR_EMPTY_TILE, zonedPAT))
		{
			ASSERT(false, "technologyGiveAway: Unable to find a free location");
		}

		NETbeginEncode(NETgameQueue(selectedPlayer), GAME_ARTIFACTS);
		{
			/* Make sure that we don't have to violate the constness of pS.
			 * Since the nettype functions aren't const correct when sending
			 */
			uint8_t player = pS->player;

			NETuint8_t(&count);
			NETenum(&type);
			NETuint32_t(&x);
			NETuint32_t(&y);
			NETuint32_t(&id);
			NETuint8_t(&player);
		}
		NETend();
	}

	return;
}
static void NETtemplate(DROID_TEMPLATE *pTempl)
{
	NETstring(pTempl->aName, sizeof(pTempl->aName));

	for (unsigned i = 0; i < ARRAY_SIZE(pTempl->asParts); ++i)
	{
		// signed, but sent as a bunch of bits...
		NETint32_t(&pTempl->asParts[i]);
	}

	NETuint32_t(&pTempl->buildPoints);
	NETuint32_t(&pTempl->powerPoints);
	NETuint32_t(&pTempl->storeCount);
	NETuint32_t(&pTempl->numWeaps);
	NETbool(&pTempl->stored);	// other players don't need to know, but we need to keep the knowledge in the loop somehow...

	for (int i = 0; i < DROID_MAXWEAPS; ++i)
	{
		NETuint32_t(&pTempl->asWeaps[i]);
	}

	NETenum(&pTempl->droidType);
	NETuint32_t(&pTempl->multiPlayerID);
}
Beispiel #15
0
///////////////////////////////////////////////////////////////////////////////
// splatter artifact gifts randomly about.
void  addMultiPlayerRandomArtifacts(uint8_t quantity, FEATURE_TYPE type)
{
	FEATURE		*pF = NULL;
	int			i, featureStat, count;
	uint32_t	x, y;
	uint8_t		player = ANYPLAYER;

	debug(LOG_FEATURE, "Sending %u artifact(s) type: (%s)", quantity, feature_names[type]);
	NETbeginEncode(NET_ARTIFACTS, NET_ALL_PLAYERS);
		NETuint8_t(&quantity);
		NETenum(&type);

		for(featureStat = 0; featureStat < numFeatureStats && asFeatureStats[featureStat].subType != type; featureStat++);

		ASSERT(mapWidth > 20, "map not big enough");
		ASSERT(mapHeight > 20, "map not big enough");

		for (count = 0; count < quantity; count++)
		{
			for (i = 0; i < 3; i++) // try three times
			{
				// Between 10 and mapwidth - 10
				x = (gameRand(mapWidth - 20)) + 10;
				y = (gameRand(mapHeight - 20)) + 10;

				if (pickATileGen(&x, &y, LOOK_FOR_EMPTY_TILE, zonedPAT))
				{
					break;
				}
				else if (i == 2)
				{
					debug(LOG_FEATURE, "Unable to find a free location after 3 tries; giving up.");
					x = INVALID_XY;
				}
			}
			if (x != INVALID_XY) // at least one of the tries succeeded
			{
				pF = buildFeature(asFeatureStats + featureStat, world_coord(x), world_coord(y), false);
				if (pF)
				{
					pF->player = player;
				}
				else
				{
					x = INVALID_XY;
				}
			}

			NETuint32_t(&x);
			NETuint32_t(&y);
			if (pF)
			{
				NETuint32_t(&pF->id);
			}
			else
			{
				NETuint32_t(&x); // just give them a dummy value; it'll never be used
			}
			NETuint8_t(&player);
		}

	NETend();
}
Beispiel #16
0
// ////////////////////////////////////////////////////////////////////////
// Send structure information.
static bool sendStructureCheck(void)
{
	uint8_t         player;

	if (structureCheckLastSent > gameTime)
	{
		structureCheckLastSent = 0;
	}
	// Only send a struct send if not done recently
	if (gameTime - structureCheckLastSent < STRUCT_PERIOD)
	{
		return true;
	}

	structureCheckLastSent = gameTime;

	for (player = 0; player < MAX_PLAYERS; ++player)
	{
		STRUCTURE       *pS = pickAStructure(player);
		bool            hasCapacity = true;
		uint8_t         capacity;

		// Only send info about complete buildings
		if (pS == NULL || pS->status != SS_BUILT)
		{
			structureCheckLastId[player] = 0;
			continue;
		}

		switch (pS->pStructureType->type)
		{
			case REF_RESEARCH:
				capacity = pS->pFunctionality->researchFacility.capacity;
				break;
			case REF_FACTORY:
			case REF_VTOL_FACTORY:
				capacity = pS->pFunctionality->factory.capacity;
				break;
			case REF_POWER_GEN:
				capacity = pS->pFunctionality->powerGenerator.capacity;
			default:
				hasCapacity = false;
				break;
		}
		structureCheckLastId[player] = pS->id;
		structureCheckLastBody[player] = pS->body;
		structureCheckLastDirection[player] = pS->rot;
		structureCheckLastType[player] = pS->pStructureType->type;

		if (myResponsibility(player))
		{
			if (!isInSync())  // Don't really send anything, unless out of synch.
			{
				NETbeginEncode(NETgameQueue(selectedPlayer), GAME_CHECK_STRUCT);
					NETuint8_t(&player);
					NETuint32_t(&gameTime);
					NETuint32_t(&pS->id);
					NETuint32_t(&pS->body);
					NETenum(&pS->pStructureType->type);
					NETRotation(&pS->rot);
					if (hasCapacity)
					{
						NETuint8_t(&capacity);
					}
				NETend();
			}
		}
	}

	return true;
}
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// Recv Messages. Get a message and dispatch to relevant function.
bool recvMessage(void)
{
	NETQUEUE queue;
	uint8_t type;

	while (NETrecvNet(&queue, &type) || NETrecvGame(&queue, &type))          // for all incoming messages.
	{
		bool processedMessage1 = false;
		bool processedMessage2 = false;

		if (queue.queueType == QUEUE_GAME)
		{
			syncDebug("Processing player %d, message %s", queue.index, messageTypeToString(type));
		}

		// messages only in game.
		if(!ingame.localJoiningInProgress)
		{
			processedMessage1 = true;
			switch(type)
			{
			case GAME_DROIDINFO:					//droid update info
				recvDroidInfo(queue);
				break;
			case NET_TEXTMSG:					// simple text message
				recvTextMessage(queue);
				break;
			case NET_DATA_CHECK:
				recvDataCheck(queue);
				break;
			case NET_AITEXTMSG:					//multiplayer AI text message
				recvTextMessageAI(queue);
				break;
			case NET_BEACONMSG:					//beacon (blip) message
				recvBeacon(queue);
				break;
			case GAME_DROIDDISEMBARK:
				recvDroidDisEmbark(queue);           //droid has disembarked from a Transporter
				break;
			case GAME_GIFT:						// an alliance gift from one player to another.
				recvGift(queue);
				break;
			case GAME_LASSAT:
				recvLasSat(queue);
				break;
			case GAME_DEBUG_MODE:
				recvProcessDebugMappings(queue);
				break;
			case GAME_DEBUG_ADD_DROID:
				recvDroid(queue);
				break;
			case GAME_DEBUG_ADD_STRUCTURE:
				recvBuildFinished(queue);
				break;
			case GAME_DEBUG_ADD_FEATURE:
				recvMultiPlayerFeature(queue);
				break;
			case GAME_DEBUG_REMOVE_DROID:
				recvDestroyDroid(queue);
				break;
			case GAME_DEBUG_REMOVE_STRUCTURE:
				recvDestroyStructure(queue);
				break;
			case GAME_DEBUG_REMOVE_FEATURE:
				recvDestroyFeature(queue);
				break;
			case GAME_DEBUG_FINISH_RESEARCH:
				recvResearch(queue);
				break;
			default:
				processedMessage1 = false;
				break;
			}
		}

		// messages usable all the time
		processedMessage2 = true;
		switch(type)
		{
		case GAME_TEMPLATE:					// new template
			recvTemplate(queue);
			break;
		case GAME_TEMPLATEDEST:				// template destroy
			recvDestroyTemplate(queue);
			break;
		case NET_PING:						// diagnostic ping msg.
			recvPing(queue);
			break;
		case NET_OPTIONS:
			recvOptions(queue);
			break;
		case NET_PLAYER_DROPPED:				// remote player got disconnected
		{
			uint32_t player_id;

			NETbeginDecode(queue, NET_PLAYER_DROPPED);
			{
				NETuint32_t(&player_id);
			}
			NETend();

			if (whosResponsible(player_id) != queue.index && queue.index != NET_HOST_ONLY)
			{
				HandleBadParam("NET_PLAYER_DROPPED given incorrect params.", player_id, queue.index);
				break;
			}

			debug(LOG_INFO,"** player %u has dropped!", player_id);

			if (NetPlay.players[player_id].allocated)
			{
				MultiPlayerLeave(player_id);		// get rid of their stuff
				NET_InitPlayer(player_id, false);
			}
			NETsetPlayerConnectionStatus(CONNECTIONSTATUS_PLAYER_DROPPED, player_id);
			break;
		}
		case NET_PLAYERRESPONDING:			// remote player is now playing
		{
			uint32_t player_id;

			resetReadyStatus(false);

			NETbeginDecode(queue, NET_PLAYERRESPONDING);
				// the player that has just responded
				NETuint32_t(&player_id);
			NETend();
			if (player_id >= MAX_PLAYERS)
			{
				debug(LOG_ERROR, "Bad NET_PLAYERRESPONDING received, ID is %d", (int)player_id);
				break;
			}
			// This player is now with us!
			ingame.JoiningInProgress[player_id] = false;
			break;
		}
		// FIXME: the next 4 cases might not belong here --check (we got two loops for this)
		case NET_COLOURREQUEST:
			recvColourRequest(queue);
			break;
		case NET_POSITIONREQUEST:
			recvPositionRequest(queue);
			break;
		case NET_TEAMREQUEST:
			recvTeamRequest(queue);
			break;
		case NET_READY_REQUEST:
			recvReadyRequest(queue);

			// if hosting try to start the game if everyone is ready
			if(NetPlay.isHost && multiplayPlayersReady(false))
			{
				startMultiplayerGame();
			}
			break;
		case GAME_ALLIANCE:
			recvAlliance(queue, true);
			break;
		case NET_KICK:	// in-game kick message
		{
			uint32_t player_id;
			char reason[MAX_KICK_REASON];
			LOBBY_ERROR_TYPES KICK_TYPE = ERROR_NOERROR;

			NETbeginDecode(queue, NET_KICK);
				NETuint32_t(&player_id);
				NETstring(reason, MAX_KICK_REASON);
				NETenum(&KICK_TYPE);
			NETend();

			if (player_id == NET_HOST_ONLY)
			{
				char buf[250]= {'\0'};

				ssprintf(buf, "Player %d (%s : %s) tried to kick %u", (int) queue.index, NetPlay.players[queue.index].name, NetPlay.players[queue.index].IPtextAddress, player_id);
				NETlogEntry(buf, SYNC_FLAG, 0);
				debug(LOG_ERROR, "%s", buf);
				if (NetPlay.isHost)
				{
					NETplayerKicked((unsigned int) queue.index);
				}
				break;
			}
			else if (selectedPlayer == player_id)  // we've been told to leave.
			{
				debug(LOG_ERROR, "You were kicked because %s", reason);
				setPlayerHasLost(true);
			}
			else
			{
				debug(LOG_NET, "Player %d was kicked: %s", player_id, reason);
				NETplayerKicked(player_id);
			}
			break;
		}
		case GAME_RESEARCHSTATUS:
			recvResearchStatus(queue);
			break;
		case GAME_STRUCTUREINFO:
			recvStructureInfo(queue);
			break;
		case NET_PLAYER_STATS:
			recvMultiStats(queue);
			break;
		case GAME_PLAYER_LEFT:
			recvPlayerLeft(queue);
			break;
		default:
			processedMessage2 = false;
			break;
		}

		if (processedMessage1 && processedMessage2)
		{
			debug(LOG_ERROR, "Processed %s message twice!", messageTypeToString(type));
		}
		if (!processedMessage1 && !processedMessage2)
		{
			debug(LOG_ERROR, "Didn't handle %s message!", messageTypeToString(type));
		}

		NETpop(queue);
	}

	return true;
}
Beispiel #18
0
// receive checking info about a structure and update local world state
bool recvStructureCheck(NETQUEUE queue)
{
	uint32_t                synchTime;
	STRUCTURE		*pS;
	bool			hasCapacity = true;
	int                     j;
	Rotation                rot;
	uint8_t			player, ourCapacity;
	uint32_t		body;
	uint32_t                ref;
	STRUCTURE_TYPE          type = REF_HQ;  // Dummy initialisation.

	NETbeginDecode(queue, GAME_CHECK_STRUCT);
		NETuint8_t(&player);
		NETuint32_t(&synchTime);
		NETuint32_t(&ref);
		NETuint32_t(&body);
		NETenum(&type);
		NETRotation(&rot);

		if (player >= MAX_PLAYERS)
		{
			debug(LOG_ERROR, "Bad GAME_CHECK_STRUCT received!");
			NETend();
			return false;
		}

		if (structureCheckLastSent != synchTime)
		{
			debug(LOG_ERROR, "We got a structure synch at the wrong time.");
		}

		if (ref != structureCheckLastId[player])
		{
			debug(LOG_ERROR, "We got a structure %u synch, but had chosen %u instead.", ref, structureCheckLastId[player]);
			NETend();
			return false;
		}

		// If the structure exists our job is easy
		pS = IdToStruct(ref, player);
		if (pS)
		{
			syncDebugStructure(pS, '<');
			if (pS->pStructureType->type != structureCheckLastType[player] || type != structureCheckLastType[player])
			{
				debug(LOG_ERROR, "GAME_CHECK_STRUCT received, wrong structure type!");
				NETend();
				return false;
			}

			// Check its finished
			if (pS->status != SS_BUILT)
			{
				pS->rot = rot;
				pS->id = ref;
				pS->status = SS_BUILT;
				buildingComplete(pS);
			}

			// If the structure has a capacity
			switch (pS->pStructureType->type)
			{
				case REF_RESEARCH:
					ourCapacity = ((RESEARCH_FACILITY *) pS->pFunctionality)->capacity;
					j = researchModuleStat;
					break;
				case REF_FACTORY:
				case REF_VTOL_FACTORY:
					ourCapacity = ((FACTORY *) pS->pFunctionality)->capacity;
					j = factoryModuleStat;
					break;
				case REF_POWER_GEN:
					ourCapacity = ((POWER_GEN *) pS->pFunctionality)->capacity;
					j = powerModuleStat;
					break;
				default:
					hasCapacity = false;
					break;
			}

			// So long as the struct has a capacity fetch it from the packet
			if (hasCapacity)
			{
				uint8_t actualCapacity = 0;

				NETuint8_t(&actualCapacity);

				// If our capacity is different upgrade ourself
				for (; ourCapacity < actualCapacity; ourCapacity++)
				{
					debug(LOG_SYNC, "Structure %u out of synch, adding module.", ref);
					buildStructure(&asStructureStats[j], pS->pos.x, pS->pos.y, pS->player, false);

					// Check it is finished
					if (pS->status != SS_BUILT)
					{
						pS->id = ref;
						pS->status = SS_BUILT;
						buildingComplete(pS);
					}
				}
			}

#define MERGEDELTA(x, y, ya, z) if (y != ya) { debug(LOG_SYNC, "Structure %u out of synch, changing "#x" from %"z" to %"z".", ref, x, x + y - ya); x += y - ya; }
			MERGEDELTA(pS->body, body, structureCheckLastBody[player], "u");
			MERGEDELTA(pS->rot.direction, rot.direction, structureCheckLastDirection[player].direction, "d");
			MERGEDELTA(pS->rot.pitch, rot.pitch, structureCheckLastDirection[player].pitch, "d");
			MERGEDELTA(pS->rot.roll, rot.roll, structureCheckLastDirection[player].roll, "d");
#undef MERGEDELTA

			syncDebugStructure(pS, '>');
		}
		else
		{
			debug(LOG_ERROR, "We got a structure %u synch, but can't find the structure.", ref);
		}

	NETend();
	return true;
}