/// <summary> /// Creates the package that contains the description of the isometric tiles of the given map. /// </summary> /// <param name="map">Reference to the map.</param> /// <returns>The data package that contains the description of the isometric tiles of the given map.</returns> private RCPackage CreateIsoTileListPackage(IMapAccess map) { RCPackage isotileList = RCPackage.CreateCustomDataPackage(MapFileFormat.ISOTILE_LIST); /// Create the terrain type index table. List <string> terrainTypeList = new List <string>(); Dictionary <ITerrainType, int> terrainTypeIndexTable = new Dictionary <ITerrainType, int>(); int terrainTypeIndex = 0; foreach (ITerrainType terrainType in map.Tileset.TerrainTypes) { terrainTypeList.Add(terrainType.Name); terrainTypeIndexTable.Add(terrainType, terrainTypeIndex); terrainTypeIndex++; } isotileList.WriteStringArray(0, terrainTypeList.ToArray()); /// Create the packages of the isometric tiles. RCSet <IIsoTile> processedIsoTiles = new RCSet <IIsoTile>(); List <RCPackage> isotilePackages = new List <RCPackage>(); int isotileInfoLength = 0; for (int row = 0; row < map.Size.Y; row++) { for (int column = 0; column < map.Size.X; column++) { IIsoTile currIsoTile = map.GetQuadTile(new RCIntVector(column, row)).PrimaryIsoTile; if (!processedIsoTiles.Contains(currIsoTile)) { RCPackage isotilePackage = RCPackage.CreateCustomDataPackage(MapFileFormat.ISOTILE); isotilePackage.WriteShort(0, (short)column); isotilePackage.WriteShort(1, (short)row); isotilePackage.WriteByte(2, (byte)terrainTypeIndexTable[currIsoTile.Type.TerrainA]); isotilePackage.WriteByte(3, currIsoTile.Type.TerrainB != null ? (byte)terrainTypeIndexTable[currIsoTile.Type.TerrainB] : (byte)0); isotilePackage.WriteByte(4, (byte)currIsoTile.Type.Combination); isotilePackage.WriteByte(5, (byte)currIsoTile.VariantIdx); isotilePackages.Add(isotilePackage); processedIsoTiles.Add(currIsoTile); isotileInfoLength += isotilePackage.PackageLength; } } } /// Write the isometric tile packages into the final package byte[] isotileInfoBytes = new byte[isotileInfoLength]; int offset = 0; foreach (RCPackage isotilePackage in isotilePackages) { offset += isotilePackage.WritePackageToBuffer(isotileInfoBytes, offset); } isotileList.WriteByteArray(1, isotileInfoBytes); return(isotileList); }
/// <see cref="IScenarioLoader.SaveScenario"/> public byte[] SaveScenario(Scenario scenario) { if (scenario == null) { throw new ArgumentNullException("scenario"); } /// Create the packages that describes the entities of the scenario. List <RCPackage> entityPackages = new List <RCPackage>(); int retArrayLength = 0; foreach (MineralField mineralField in scenario.GetAllElements <MineralField>()) { RCIntVector lastKnownQuadCoords = mineralField.MapObject.QuadraticPosition.Location; RCPackage mineralFieldPackage = RCPackage.CreateCustomDataPackage(ScenarioFileFormat.MINERAL_FIELD); mineralFieldPackage.WriteShort(0, (short)lastKnownQuadCoords.X); mineralFieldPackage.WriteShort(1, (short)lastKnownQuadCoords.Y); mineralFieldPackage.WriteInt(2, mineralField.ResourceAmount.Read()); entityPackages.Add(mineralFieldPackage); retArrayLength += mineralFieldPackage.PackageLength; } foreach (VespeneGeyser vespeneGeyser in scenario.GetAllElements <VespeneGeyser>()) { RCIntVector lastKnownQuadCoords = vespeneGeyser.MapObject.QuadraticPosition.Location; RCPackage vespeneGeyserPackage = RCPackage.CreateCustomDataPackage(ScenarioFileFormat.VESPENE_GEYSER); vespeneGeyserPackage.WriteShort(0, (short)lastKnownQuadCoords.X); vespeneGeyserPackage.WriteShort(1, (short)lastKnownQuadCoords.Y); vespeneGeyserPackage.WriteInt(2, vespeneGeyser.ResourceAmount.Read()); entityPackages.Add(vespeneGeyserPackage); retArrayLength += vespeneGeyserPackage.PackageLength; } foreach (StartLocation startLocation in scenario.GetAllElements <StartLocation>()) { RCIntVector lastKnownQuadCoords = startLocation.MapObject.QuadraticPosition.Location; RCPackage startLocationPackage = RCPackage.CreateCustomDataPackage(ScenarioFileFormat.START_LOCATION); startLocationPackage.WriteShort(0, (short)lastKnownQuadCoords.X); startLocationPackage.WriteShort(1, (short)lastKnownQuadCoords.Y); startLocationPackage.WriteByte(2, (byte)startLocation.PlayerIndex); entityPackages.Add(startLocationPackage); retArrayLength += startLocationPackage.PackageLength; } /// Write the packages into the returned byte array. byte[] retArray = new byte[retArrayLength]; int offset = 0; foreach (RCPackage package in entityPackages) { offset += package.WritePackageToBuffer(retArray, offset); } return(retArray); }
/// <summary> /// Sends reports about the given line states to all connected clients and to the listener of this server. /// </summary> private void SendLineStateReports(LobbyLineState[] lineStates) { for (int i = 0; i < this.connections.Length; i++) { if (this.connections[i].ConnectionState == LobbyConnectionState.Connected) { RCPackage lineStateReport = RCPackage.CreateNetworkControlPackage(Network.FORMAT_LOBBY_LINE_STATE_REPORT); lineStateReport.WriteShort(0, (short)(i + 1)); /// The ID of the client that receives the report. byte[] lineStatesBytes = new byte[lineStates.Length]; for (int j = 0; j < lineStatesBytes.Length; j++) { lineStatesBytes[j] = (byte)lineStates[j]; } lineStateReport.WriteByteArray(1, lineStatesBytes); /// The list of the line states on this server. /// Send the package if (!this.connections[i].SendPackage(lineStateReport)) { /// In case of error, shutdown the connection and notify the other clients again. this.connections[i].Shutdown(); this.connections[i].LineState = LobbyLineState.Opened; /// Keep it opened for other clients. SendLineStateReports(); } } } this.listener.LineStateReport(0, lineStates); }
/// <summary> /// Sends a commit for this.nextNextRound to the lobby. /// </summary> /// <remarks> /// Call this function only if this.currentRound has been finished. /// </remarks> private void SendCommit() { if (!this.initialized) { throw new DssException("DssSimulationMgr is uninitialized!"); } if (this.currentRound.StepNextFrame()) { throw new DssException("DssSimulationMgr.SendCommit() denied!"); } if (!this.hostLeft) { byte[] stateHash = this.root.SimulatorIface.StateHash; int highestAPT = this.HighestAPT; /// Generate a ticket for the commit. int ticket = -1; do { ticket = RandomService.DefaultGenerator.Next(); } while (this.commitAwMonitors.ContainsKey(ticket)); /// Create the commit package. RCPackage commitPackage = RCPackage.CreateNetworkCustomPackage(DssRoot.DSS_COMMIT); commitPackage.WriteShort(0, (short)this.aftCalculator.Average); commitPackage.WriteShort(1, (short)highestAPT); /// The highest measured APT commitPackage.WriteInt(2, this.nextNextRound.RoundIndex); /// Round index of the commit commitPackage.WriteInt(3, ticket); /// Commit answer ticket commitPackage.WriteByteArray(4, stateHash != null ? stateHash : new byte[0] { }); /// State-hash value /// Send the commit package to the lobby. this.root.LobbyIface.SendPackage(commitPackage); RegisterCommitMonitor(ticket); TraceManager.WriteAllTrace(string.Format("Self commit round {0}", this.nextNextRound.RoundIndex), DssTraceFilters.SIMULATION_INFO); if (!this.nextNextRound.Commit(this.root.IdOfThisPeer, this.aftCalculator.Average, highestAPT, stateHash)) { SimulationStageError(string.Format("Commit of round-{0} failed!", this.nextNextRound.RoundIndex), new byte[0] { }); } } }
/// <summary> /// Creates the header package of the given map. /// </summary> /// <param name="map">Reference to the map.</param> /// <returns>The data package that contains the header of the given map.</returns> private RCPackage CreateMapHeaderPackage(IMapAccess map) { RCPackage mapHeader = RCPackage.CreateCustomDataPackage(MapFileFormat.MAP_HEADER); Version appVersion = new Version(ConstantsTable.Get <string>("RC.App.Version")); mapHeader.WriteInt(0, appVersion.Major); mapHeader.WriteInt(1, appVersion.Minor); mapHeader.WriteInt(2, appVersion.Build); mapHeader.WriteInt(3, appVersion.Revision); mapHeader.WriteString(4, map.MapName); mapHeader.WriteString(5, map.Tileset.Name); mapHeader.WriteShort(6, (short)map.Size.X); mapHeader.WriteShort(7, (short)map.Size.Y); mapHeader.WriteByte(8, (byte)8); // TODO: get the maximum number of players mapHeader.WriteIntArray(9, new int[0] { }); // TODO: get checksum values of the map return(mapHeader); }
/// <summary> /// Creates the package that contains the description of the terrain objects of the given map. /// </summary> /// <param name="map">Reference to the map.</param> /// <returns>The data package that contains the description of the terrain objects of the given map.</returns> private RCPackage CreateTerrainObjListPackage(IMapAccess map) { RCPackage terrainObjList = RCPackage.CreateCustomDataPackage(MapFileFormat.TERRAINOBJ_LIST); /// Create the terrain object type index table. List <string> terrainObjTypeList = new List <string>(); Dictionary <ITerrainObjectType, int> terrainObjTypeIndexTable = new Dictionary <ITerrainObjectType, int>(); int terrainObjTypeIndex = 0; foreach (ITerrainObjectType terrainObjType in map.Tileset.TerrainObjectTypes) { terrainObjTypeList.Add(terrainObjType.Name); terrainObjTypeIndexTable.Add(terrainObjType, terrainObjTypeIndex); terrainObjTypeIndex++; } terrainObjList.WriteStringArray(0, terrainObjTypeList.ToArray()); /// Create the packages of the terrain objects. List <RCPackage> terrainObjPackages = new List <RCPackage>(); int terrainObjInfoLength = 0; foreach (ITerrainObject terrainObj in map.TerrainObjects) { RCPackage terrainObjPackage = RCPackage.CreateCustomDataPackage(MapFileFormat.TERRAINOBJ); terrainObjPackage.WriteShort(0, (short)terrainObj.MapCoords.X); terrainObjPackage.WriteShort(1, (short)terrainObj.MapCoords.Y); terrainObjPackage.WriteByte(2, (byte)terrainObjTypeIndexTable[terrainObj.Type]); terrainObjPackages.Add(terrainObjPackage); terrainObjInfoLength += terrainObjPackage.PackageLength; } /// Write the terrain object packages into the final package byte[] terrainObjInfoBytes = new byte[terrainObjInfoLength]; int offset = 0; foreach (RCPackage terrainObjPackage in terrainObjPackages) { offset += terrainObjPackage.WritePackageToBuffer(terrainObjInfoBytes, offset); } terrainObjList.WriteByteArray(1, terrainObjInfoBytes); return(terrainObjList); }
/// <summary> /// Resets the state of the DssSimulationMgr. Call this function every time you start a simulation stage. /// </summary> /// <param name="opFlags"> /// The current operator flag array. See the comment at this.operatorFlags for more information. /// </param> public void Reset(bool[] opFlags) { if (opFlags == null) { throw new ArgumentNullException("opFlags"); } if (opFlags.Length != this.root.OpCount) { throw new ArgumentException("Array length mismatch.", "opFlags"); } this.aftCalculator = new AverageCalculator(DssConstants.AVG_CALC_VECTOR_LENGTH, DssConstants.INITIAL_AFT); this.aptCalculators = new AverageCalculator[this.root.OpCount]; for (int i = 0; i < this.aptCalculators.Length; i++) { this.aptCalculators[i] = new AverageCalculator(DssConstants.AVG_CALC_VECTOR_LENGTH, DssConstants.INITIAL_APT); } if (this.commitAwTimeouts != null) { foreach (KeyValuePair <AlarmClock, CommitMonitor> item in this.commitAwTimeouts) { item.Key.Cancel(); } } this.commitAwMonitors = new Dictionary <int, CommitMonitor>(); this.commitAwTimeouts = new Dictionary <AlarmClock, CommitMonitor>(); StopCommitTimeoutClock(); StopSimulationFrameClock(); this.operatorFlags = opFlags; this.currentRound = new SimulationRound(this.operatorFlags); this.currentRound.Reset(true, 0); this.currentRound.ComputeSpeedControl(); this.nextRound = new SimulationRound(this.operatorFlags); this.nextRound.Reset(false, 1); this.nextNextRound = new SimulationRound(this.operatorFlags); this.nextNextRound.Reset(false, 2); this.nextNextNextRound = new SimulationRound(this.operatorFlags); this.nextNextNextRound.Reset(false, 3); this.waitingForCommit = false; this.initialized = true; this.hostLeft = false; int ticket = RandomService.DefaultGenerator.Next(); byte[] stateHash = this.root.SimulatorIface.StateHash; int highestAPT = this.HighestAPT; this.commitTimeoutClock = this.root.AlarmClkMgr.SetAlarmClock(DssRoot.Time + DssConstants.COMMIT_TIMEOUT, this.CommitTimeout); /// Create the first commit package. RCPackage commitPackage = RCPackage.CreateNetworkCustomPackage(DssRoot.DSS_COMMIT); commitPackage.WriteShort(0, (short)this.aftCalculator.Average); commitPackage.WriteShort(1, (short)highestAPT); /// The highest measured APT commitPackage.WriteInt(2, 1); /// Round index of the commit is 1 (next round is committed) commitPackage.WriteInt(3, ticket); /// Commit answer ticket commitPackage.WriteByteArray(4, stateHash != null ? stateHash : new byte[0] { }); /// State-hash value /// Send the commit package to the lobby. this.root.LobbyIface.SendPackage(commitPackage); RegisterCommitMonitor(ticket); TraceManager.WriteAllTrace(string.Format("Self commit round {0}", this.nextRound.RoundIndex), DssTraceFilters.SIMULATION_INFO); if (!this.nextRound.Commit(this.root.IdOfThisPeer, this.aftCalculator.Average, highestAPT, stateHash)) { SimulationStageError(string.Format("Commit of round-{0} failed!", this.nextRound.RoundIndex), new byte[0] { }); } }
public static RCPackage GenerateRandomPackage() { int rndType = rnd.Next(0, 3); int rndFormat = rnd.Next(0, 3); RCPackage retPack = null; if (rndType == 0) { retPack = RCPackage.CreateNetworkPingPackage(); return(retPack); } else if (rndType == 1) { retPack = RCPackage.CreateCustomDataPackage(rndFormat); } else if (rndType == 2) { retPack = RCPackage.CreateNetworkCustomPackage(rndFormat); } RCPackageFormat format = RCPackageFormat.GetPackageFormat(rndFormat); for (int i = 0; i < format.NumOfFields; i++) { RCPackageFieldType datatype = format.GetFieldType(i); if (datatype == RCPackageFieldType.BYTE) { retPack.WriteByte(i, (byte)rnd.Next(byte.MinValue, byte.MaxValue)); } else if (datatype == RCPackageFieldType.SHORT) { retPack.WriteShort(i, (short)rnd.Next(short.MinValue, short.MaxValue)); } else if (datatype == RCPackageFieldType.INT) { retPack.WriteInt(i, (int)rnd.Next(int.MinValue, int.MaxValue)); } else if (datatype == RCPackageFieldType.LONG) { retPack.WriteLong(i, (long)rnd.Next(int.MinValue, int.MaxValue)); } else if (datatype == RCPackageFieldType.STRING) { int strIdx = rnd.Next(0, 10); retPack.WriteString(i, strCollection[strIdx]); } else if (datatype == RCPackageFieldType.BYTE_ARRAY) { int arrLen = rnd.Next(0, 10); byte[] arr = new byte[arrLen]; rnd.NextBytes(arr); retPack.WriteByteArray(i, arr); } else if (datatype == RCPackageFieldType.SHORT_ARRAY) { int arrLen = rnd.Next(0, 10); short[] arr = new short[arrLen]; for (int j = 0; j < arrLen; ++j) { arr[j] = (short)rnd.Next(short.MinValue, short.MaxValue); } retPack.WriteShortArray(i, arr); } else if (datatype == RCPackageFieldType.INT_ARRAY) { int arrLen = rnd.Next(0, 10); int[] arr = new int[arrLen]; for (int j = 0; j < arrLen; ++j) { arr[j] = (int)rnd.Next(int.MinValue, int.MaxValue); } retPack.WriteIntArray(i, arr); } else if (datatype == RCPackageFieldType.LONG_ARRAY) { int arrLen = rnd.Next(0, 10); long[] arr = new long[arrLen]; for (int j = 0; j < arrLen; ++j) { arr[j] = (long)rnd.Next(int.MinValue, int.MaxValue); } retPack.WriteLongArray(i, arr); } else if (datatype == RCPackageFieldType.STRING_ARRAY) { int arrLen = rnd.Next(0, 10); string[] arr = new string[arrLen]; for (int j = 0; j < arrLen; ++j) { int strIdx = rnd.Next(0, 10); arr[j] = strCollection[strIdx]; } retPack.WriteStringArray(i, arr); } else { throw new NetworkingSystemException("Unknown datatype"); } } return(retPack); }