コード例 #1
0
ファイル: gtime.cpp プロジェクト: michederoide/warzone2100
void recvPlayerGameTime(NETQUEUE queue)
{
	uint32_t latencyTicks = 0;
	uint32_t checkTime = 0;
	uint32_t checkCrc = 0;

	NETbeginDecode(queue, GAME_GAME_TIME);
		NETuint32_t(&latencyTicks);
		NETuint32_t(&checkTime);
		NETuint32_tLarge(&checkCrc);
		NETuint16_t(&wantedLatencies[queue.index]);
	NETend();

	gameQueueTime[queue.index] = checkTime + latencyTicks * GAME_TICKS_PER_UPDATE;  // gameTime when future messages shall be processed.

	gameQueueCheckTime[queue.index] = checkTime;
	gameQueueCheckCrc[queue.index] = checkCrc;
	if (!checkDebugSync(checkTime, checkCrc))
	{
		crcError = true;
		if (NetPlay.players[queue.index].allocated)
		{
			NETsetPlayerConnectionStatus(CONNECTIONSTATUS_DESYNC, queue.index);
		}
	}

	if (updateReadyTime == 0 && checkPlayerGameTime(NET_ALL_PLAYERS))
	{
		updateReadyTime = wzGetTicks();  // This is the time we were able to tick.
	}
}
コード例 #2
0
ファイル: multijoin.cpp プロジェクト: CalculusWZ/warzone2100
void recvPlayerLeft(NETQUEUE queue)
{
	uint32_t playerIndex = 0;
	NETbeginDecode(queue, GAME_PLAYER_LEFT);
	NETuint32_t(&playerIndex);
	NETend();

	addConsolePlayerLeftMessage(playerIndex);

	if (whosResponsible(playerIndex) != queue.index)
	{
		return;
	}

	turnOffMultiMsg(true);
	clearPlayer(playerIndex, false);  // don't do it quietly
	turnOffMultiMsg(false);
	NetPlay.players[playerIndex].allocated = false;

	NETsetPlayerConnectionStatus(CONNECTIONSTATUS_PLAYER_DROPPED, playerIndex);

	debug(LOG_INFO, "** player %u has dropped, in-game!", playerIndex);
}
コード例 #3
0
ファイル: multijoin.cpp プロジェクト: GhostKing/warzone2100
void recvPlayerLeft(NETQUEUE queue)
{
	uint32_t playerIndex = 0;
	NETbeginDecode(queue, GAME_PLAYER_LEFT);
		NETuint32_t(&playerIndex);
	NETend();
	if (whosResponsible(playerIndex) != queue.index)
	{
		return;
	}

	turnOffMultiMsg(true);
	clearPlayer(playerIndex, false);  // don't do it quietly
	turnOffMultiMsg(false);
	NetPlay.players[playerIndex].allocated = false;

	char buf[256];
	ssprintf(buf, _("%s has Left the Game"), getPlayerName(playerIndex));
	addConsoleMessage(buf, DEFAULT_JUSTIFY, SYSTEM_MESSAGE);
	NETsetPlayerConnectionStatus(CONNECTIONSTATUS_PLAYER_DROPPED, playerIndex);

	debug(LOG_INFO, "** player %u has dropped, in-game!", playerIndex);
}
コード例 #4
0
ファイル: gtime.cpp プロジェクト: michederoide/warzone2100
/* Call this each loop to update the game timer */
void gameTimeUpdate()
{
	uint32_t currTime = wzGetTicks();

	if (currTime < baseTime)
	{
		// Warzone 2100, the first relativistic computer game!
		// Exhibit A: Time travel
		// force a rebase
		debug(LOG_WARNING, "Time travel is occurring! Clock went back in time a bit from %d to %d!\n", baseTime, currTime);
		baseTime = currTime;
		timeOffset = graphicsTime;
	}

	// Do not update the game time if gameTimeStop has been called
	if (stopCount == 0)
	{
		bool mayUpdate = true;

		// Calculate the new game time
		uint32_t scaledCurrTime = (currTime - baseTime)*modifier + timeOffset;
		if (scaledCurrTime < graphicsTime)  // Make sure the clock doesn't step back at all.
		{
			debug(LOG_WARNING, "Rescaled clock went back in time a bit from %d to %d!\n", graphicsTime, scaledCurrTime);
			scaledCurrTime = graphicsTime;
			baseTime = currTime;
			timeOffset = graphicsTime;
		}

		if (updateWantedTime == 0 && scaledCurrTime >= gameTime)
		{
			updateWantedTime = currTime;  // This is the time that we wanted to tick.
		}

		if (scaledCurrTime >= gameTime && !checkPlayerGameTime(NET_ALL_PLAYERS))
		{
			unsigned player;

			// Pause time at current game time, since we are waiting GAME_GAME_TIME from other players.
			scaledCurrTime = gameTime;
			baseTime = currTime;
			timeOffset = gameTime;

			debug(LOG_SYNC, "Waiting for other players. gameTime = %u, player times are {%s}", gameTime, listToString("%u", ", ", gameQueueTime, gameQueueTime + game.maxPlayers).c_str());
			mayUpdate = false;

			for (player = 0; player < game.maxPlayers; ++player)
			{
				if (!checkPlayerGameTime(player))
				{
					NETsetPlayerConnectionStatus(CONNECTIONSTATUS_WAITING_FOR_PLAYER, player);
					break;  // GAME_GAME_TIME is processed serially, so don't know if waiting for more players.
				}
			}
		}

		// Calculate the time for this frame
		deltaGraphicsTime = scaledCurrTime - graphicsTime;

		// Adjust deltas.
		if (scaledCurrTime >= gameTime && mayUpdate)
		{
			if (scaledCurrTime > gameTime + GAME_TICKS_PER_SEC*MAXIMUM_SPF)
			{
				// Game isn't updating fast enough...
				uint32_t slideBack = deltaGraphicsTime - GAME_TICKS_PER_SEC*MAXIMUM_SPF;
				baseTime += slideBack / modifier;  // adjust the addition to base time
				deltaGraphicsTime -= slideBack;
			}

			deltaGameTime = GAME_TICKS_PER_UPDATE;

			updateLatency();
			if (crcError)
			{
				debug(LOG_ERROR, "Synch error, gameTimes were: {%s}", listToString("%10u", ", ", gameQueueCheckTime, gameQueueCheckTime + game.maxPlayers).c_str());
				debug(LOG_ERROR, "Synch error, CRCs were:      {%s}", listToString("0x%08X", ", ", gameQueueCheckCrc, gameQueueCheckCrc + game.maxPlayers).c_str());
				crcError = false;
			}
		}
		else
		{
			deltaGameTime = 0;
		}

		if (deltaGameTime != 0)
		{
			deltaGraphicsTime = 0;  // Don't update graphics until game state is updated.
		}

		// Store the game and graphics times
		gameTime     += deltaGameTime;
		graphicsTime += deltaGraphicsTime;
	}
	else
	{
		// The game is paused, so the change in time is zero.
		deltaGameTime = 0;
		deltaGraphicsTime = 0;
	}

	// Pre-calculate fraction used in timeAdjustedIncrement
	graphicsTimeFraction = (float)deltaGraphicsTime / (float)GAME_TICKS_PER_SEC;

	ASSERT(graphicsTime <= gameTime, "Trying to see the future.");
}
コード例 #5
0
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// 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;
}