/// <summary> /// Write each player's turns into the replay. /// </summary> public void ReplayWriteTurns(int Turn, CActionTurn[] Turns) { if (_replayState == EReplayState.RS_RECORD) { _replayWriter.Write((byte)1); _replayWriter.Write(Turn); for (int j = 0; j < Turns.Length; ++j) { CActionTurn turn = Turns[j]; _replayWriter.Write((byte)2); _replayWriter.Write((byte)turn.mPlayerID); _replayWriter.Write((byte)turn.mActionBuffer.Count); for (int i = 0; i < turn.mActionBuffer.Count; ++i) { CUserAction action = turn.mActionBuffer[i]; _replayWriter.Write((int)action.mID); _replayWriter.Write(action.mInfo); _replayWriter.Write(action.mX); _replayWriter.Write(action.mY); } } _replayWriter.Flush(); } }
private void _SendCurrentLocalActions(int PlayerID, int Turn) { CActionTurn localTurn = new CActionTurn(PlayerID, Turn); localTurn.mHash = _world.GetWorldHash(); // Hash calculated for current _simTickCount localTurn.CopyActionBuffer(_localActionBuffer); _localActionBuffer.Clear(); _actionTurns.Add(localTurn); if (CGame.Net != null) { CGame.Net.SendRequest(new CSendMsgTurn(localTurn)); } }
override protected void _Deserialize() { int currentTurn = _reader.ReadInt32(); int playerID = _reader.ReadByte(); int actionCount = _reader.ReadByte(); int hash = _reader.ReadInt32(); mTurn = new CActionTurn(playerID, currentTurn); mTurn.mHash = hash; for (int i = 0; i < actionCount; ++i) { CUserAction action = new CUserAction(); action.mID = (CUserAction.EType)_reader.ReadInt32(); action.mInfo = _reader.ReadInt32(); action.mX = _reader.ReadInt32(); action.mY = _reader.ReadInt32(); action.mPlayerID = playerID; action.mTurn = currentTurn; mTurn.mActionBuffer.Add(action); //Debug.Log("Got Action " + action.mPlayerID + " " + action.mID.ToString()); } }
/// <summary> /// Get actions up to and including the specified game frame. /// </summary> public void ReplayGetTurns(int Turn, List <CActionTurn> ActionTurns) { if (_replayState != EReplayState.RS_VIEW) { return; } int currentTurn = 0; try { while (true) { int blockType = _replayReader.ReadByte(); if (blockType == 1) { currentTurn = _replayReader.ReadInt32(); if (currentTurn > Turn) { _replayReader.BaseStream.Seek(-5, SeekOrigin.Current); return; } else if (currentTurn < Turn) { Debug.LogError("Can't be reading a turn less than current!"); return; } } else if (blockType == 2) { int playerID = _replayReader.ReadByte(); int actionCount = _replayReader.ReadByte(); CActionTurn turn = new CActionTurn(playerID, currentTurn); for (int i = 0; i < actionCount; ++i) { CUserAction action = new CUserAction(); action.mID = (CUserAction.EType)_replayReader.ReadInt32(); action.mInfo = _replayReader.ReadInt32(); action.mX = _replayReader.ReadInt32(); action.mY = _replayReader.ReadInt32(); action.mPlayerID = playerID; action.mTurn = currentTurn; turn.mActionBuffer.Add(action); } ActionTurns.Add(turn); } } } catch (Exception e) { Debug.Log("Replay has ended: " + e.Message); _replayState = EReplayState.RS_NONE; return; } }
public CSendMsgTurn(CActionTurn Turn) { mTurn = Turn; }
private void _Tick() { bool gatheringTurns = true; bool waitingForTurns = false; while (gatheringTurns) { if (!_ParseEventQueue()) { return; } if (!waitingForTurns) { _SendCurrentLocalActions(_currentPlayer, _simTickCount); ++_simTickCount; } //_TickNetwork(); if (_simTickCount >= LATENCY_TICKS) { int executeTurn = _simTickCount - LATENCY_TICKS; CActionTurn[] playerTurns = new CActionTurn[CWorld.MAX_PLAYERS]; // Time to execute turn, so query Game Session for all the player turns for turn X. // Get replay turns from journal _replay.ReplayGetTurns(executeTurn, _actionTurns); // TODO: Since we are moving journal 'up a level' don't search entire actionTurns, // only search until all players have a valid turn (combine get and check steps). // Get all player turns for (int i = 0; i < _actionTurns.Count; ++i) { if (_actionTurns[i].mTurn == executeTurn) { playerTurns[_actionTurns[i].mPlayerID] = _actionTurns[i]; } } bool turnsMissing = false; // If there are turns missing then halt the simulation for (int i = 0; i < CWorld.MAX_PLAYERS; ++i) { if (_world.mPlayers[i].mHumanInput && playerTurns[i] == null) { turnsMissing = true; break; } } if (!waitingForTurns && turnsMissing) { Debug.LogError("Simulation Wait " + _simTickCount); } if (!turnsMissing) { // At this point we have all required turns for this simulation tick gatheringTurns = false; if (waitingForTurns) { Debug.LogError("Simulation Resumed " + _simTickCount); } int compareHash = -1; // Execute all the turns & remove from recvd turns for (int i = 0; i < CWorld.MAX_PLAYERS; ++i) { if (_world.mPlayers[i].mHumanInput) { if (compareHash == -1) { compareHash = playerTurns[i].mHash; } else { if (compareHash != playerTurns[i].mHash) { // TODO: Inform player & unity thread we are out of sync! //CGame.UIManager.DisplayLargeMessage("Out of Sync!"); Debug.LogError("Out Of Sync"); _running = false; return; } } _actionTurns.Remove(playerTurns[i]); _world.ExecuteTurnActions(playerTurns[i]); } } _replay.ReplayWriteTurns(executeTurn, playerTurns); } } } // If we get this far then we can do a game tick. //Debug.Log("Sim Tick " + _simTickCount + " " + (_simTickCount - LATENCY_TICKS) + " " + (_GetTimeUS() / 1000) + "ms"); //Debug.Log("ST: " + ((double)System.Diagnostics.Stopwatch.GetTimestamp() / (double)System.Diagnostics.Stopwatch.Frequency - 198000.0)); _world.SimTick(); }