public static void ReadBuffer(byte[] buffer) { int pos = 0; int parsedBytes = 0; RCPackage currPackage = null; while (true) { pos += parsedBytes; currPackage = RCPackage.Parse(buffer, pos, 4, out parsedBytes); if (currPackage != null) { while (!currPackage.IsCommitted) { pos += parsedBytes; if (!currPackage.ContinueParse(buffer, pos, 4, out parsedBytes)) { TraceManager.WriteAllTrace("Syntax error", TraceManager.GetTraceFilterID("RC.NetworkingSystem.TestConsole.Info")); return; } } TraceManager.WriteAllTrace("Package arrived", TraceManager.GetTraceFilterID("RC.NetworkingSystem.TestConsole.Info")); } else { TraceManager.WriteAllTrace("Syntax error", TraceManager.GetTraceFilterID("RC.NetworkingSystem.TestConsole.Info")); return; } } }
/// <see cref="IComponent.Start"/> public void Start() { this.tilesetLoader = ComponentManager.GetInterface <ITileSetLoader>(); /// Load the tilesets from the configured directory DirectoryInfo rootDir = new DirectoryInfo(BizLogicConstants.TILESET_DIR); FileInfo[] tilesetFiles = rootDir.GetFiles("*.xml", SearchOption.AllDirectories); foreach (FileInfo tilesetFile in tilesetFiles) { /// TODO: this is a hack! Later we will have binary tileset format. string xmlStr = File.ReadAllText(tilesetFile.FullName); string imageDir = tilesetFile.DirectoryName; RCPackage tilesetPackage = RCPackage.CreateCustomDataPackage(PackageFormats.TILESET_FORMAT); tilesetPackage.WriteString(0, xmlStr); tilesetPackage.WriteString(1, imageDir); byte[] buffer = new byte[tilesetPackage.PackageLength]; tilesetPackage.WritePackageToBuffer(buffer, 0); ITileSet tileset = this.tilesetLoader.LoadTileSet(buffer); if (this.loadedTilesets.ContainsKey(tileset.Name)) { throw new InvalidOperationException(string.Format("Tileset with name '{0}' already loaded!", tileset.Name)); } this.loadedTilesets.Add(tileset.Name, tileset); } }
/// <summary> /// Continues the connection procedure to the server. /// </summary> /// <returns>False in case of any error or timeout, true otherwise.</returns> /// <remarks> /// Calling this function is only allowed on connecting, client-side connections. /// This function is called by the connection manager thread from the corresponding LobbyClient. /// After calling this function you have to check whether the connection procedure has been finished. /// You can do this by reading the out parameter lineStateReport. If this is not null then the /// connection procedure has been finished, otherwise you have to wait. /// </remarks> public bool ContinueConnectToTheServer(out RCPackage lineStateReport) { if (this.side != LobbyConnectionType.CLIENT_SIDE) { throw new NetworkingSystemException("Continue connect to server is only allowed on client side LobbyConnections!"); } if (this.connectionState != LobbyConnectionState.Connecting) { throw new NetworkingSystemException("Continue connect to server is only allowed on connecting LobbyConnections!"); } lineStateReport = null; RCPackage incomingMessage = null; do { if (ReceivePackage_i(out incomingMessage)) { if (incomingMessage != null) { if (incomingMessage.IsCommitted && incomingMessage.PackageType == RCPackageType.NETWORK_CONTROL_PACKAGE && incomingMessage.PackageFormat.ID == Network.FORMAT_LOBBY_LINE_STATE_REPORT) { lineStateReport = incomingMessage; this.connectAckMsgTimer.Stop(); this.connectAckMsgTimer.Reset(); this.connectionState = LobbyConnectionState.Connected; this.lastIncomingMsgTimer.Start(); this.lastOutgoingMsgTimer.Start(); return(true); } else if (incomingMessage.IsCommitted && incomingMessage.PackageType == RCPackageType.NETWORK_CONTROL_PACKAGE && incomingMessage.PackageFormat.ID == Network.FORMAT_DISCONNECT_INDICATOR) { /// Connection request is rejected by the server. this.connectAckMsgTimer.Stop(); this.connectAckMsgTimer.Reset(); this.connectionState = LobbyConnectionState.Disconnected; return(false); } } } else { /// Syntax error --> immediate shutdown return(false); } } while (incomingMessage != null); if (this.connectAckMsgTimer.ElapsedMilliseconds > NetworkingSystemConstants.CONNECT_ACK_TIMEOUT) { /// Connection timeout --> immedate shutdown return(false); } else { /// Continue the connection procedure a bit later. return(true); } }
/// <summary> /// Creates a LobbyInfo structure with custom data. /// </summary> public LobbyInfo(Guid id, string ipAddress, int portNumber, RCPackage customData) { if (id == Guid.Empty) { throw new ArgumentException("Guid.NULL", "id"); } if (ipAddress == null) { throw new ArgumentNullException("ipAddress"); } if (portNumber < IPEndPoint.MinPort || portNumber > IPEndPoint.MaxPort) { throw new ArgumentOutOfRangeException("portNumber"); } this.ID = id; this.IPAddress = ipAddress; this.PortNumber = portNumber; if (null == customData) { this.CustomData = null; } else { if (customData.IsCommitted) { this.CustomData = customData; } else { TraceManager.WriteAllTrace("LobbyInfo.LobbyInfo warning: CustomData is not committed.", NetworkingSystemTraceFilters.INFO); this.CustomData = null; } } }
/// <see cref="ILobby.SendPackage"/> public bool SendPackage(RCPackage package, int[] targets) { if (package == null) { throw new ArgumentNullException("package"); } if (targets == null || targets.Length == 0) { throw new ArgumentNullException("targets"); } if (package.IsCommitted && package.PackageType == RCPackageType.NETWORK_CUSTOM_PACKAGE && package.PackageFormat.ID != Network.FORMAT_DEDICATED_MESSAGE && package.PackageFormat.ID != Network.FORMAT_DISCONNECT_ACK && package.PackageFormat.ID != Network.FORMAT_DISCONNECT_INDICATOR && package.PackageFormat.ID != Network.FORMAT_LOBBY_INFO && package.PackageFormat.ID != Network.FORMAT_LOBBY_INFO_VANISHED && package.PackageFormat.ID != Network.FORMAT_LOBBY_LINE_STATE_REPORT) { lock (this.tasks) { package.Sender = 0; /// Indicate that this package is sent by the server this.tasks.Add(NetworkingTaskType.OUTGOING_MESSAGE); this.outgoingPackages.Push(package); this.outgoingPackageTargets.Push(targets); return(true); } } return(false); }
/// <summary> /// Creates an RCCommand object from the given RCPackage. /// </summary> /// <param name="cmdPackage">The RCPackage to be deserialized.</param> /// <returns>The created RCCommand.</returns> public static RCCommand FromPackage(RCPackage cmdPackage) { if (cmdPackage == null) { throw new ArgumentNullException("cmdPackage"); } if (!cmdPackage.IsCommitted) { throw new ArgumentException("The incoming package is not committed!", "cmdPackage"); } if (cmdPackage.PackageFormat.ID != RCCommand.COMMAND_PACKAGEFORMAT) { throw new ArgumentException("The incoming package is not a command package!", "cmdPackage"); } RCNumVector targetPosition = RCNumVector.Undefined; int targetPositionX = cmdPackage.ReadInt(2); int targetPositionY = cmdPackage.ReadInt(3); if (targetPositionX != -1 && targetPositionY != -1) { targetPosition = new RCNumVector(new RCNumber(targetPositionX), new RCNumber(targetPositionY)); } return(new RCCommand( cmdPackage.ReadString(0), cmdPackage.ReadIntArray(1), targetPosition, cmdPackage.ReadInt(4), cmdPackage.ReadString(5))); }
/// <see cref="IMapLoader.SaveMap"/> public byte[] SaveMap(IMapAccess map) { if (!this.initThreadStarted) { throw new InvalidOperationException("Component has not yet been started!"); } this.initThread.Join(); if (map == null) { throw new ArgumentNullException("map"); } RCPackage mapHeader = this.CreateMapHeaderPackage(map); RCPackage isotileList = this.CreateIsoTileListPackage(map); RCPackage terrainObjList = this.CreateTerrainObjListPackage(map); byte[] retArray = new byte[mapHeader.PackageLength + isotileList.PackageLength + terrainObjList.PackageLength]; int offset = 0; offset += mapHeader.WritePackageToBuffer(retArray, offset); offset += isotileList.WritePackageToBuffer(retArray, offset); offset += terrainObjList.WritePackageToBuffer(retArray, offset); return(retArray); }
/// <see cref="ILobbyListener.PackageArrived"/> public void PackageArrived(RCPackage package, int senderID) { //lock (this.disposeLock) { if (this.objectDisposed) { throw new ObjectDisposedException("DssEventQueue"); } } int timestamp = DssRoot.Time; /// Preprocess the event in the context of the caller thread. lock (this.eventPreprocessors) { foreach (DssEventPreprocessor preprocessor in this.eventPreprocessors) { if (!preprocessor.PackageArrivedPre(package, senderID)) { TraceManager.WriteAllTrace(string.Format("Ignoring PACKAGE_ARRIVED({0} ; {1})", package, senderID), DssTraceFilters.EVENT_QUEUE_INFO); return; } } } /// Insert the event to the queue after a successfull preprocess. lock (this.queueLock) { this.eventTypeFifo.Push(DssEventType.PACKAGE_ARRIVED); this.packageArgFifo.Push(package); this.intArgFifo.Push(senderID); this.eventTimestamps.Push(timestamp); this.readSemaphore.Release(); } }
/// <see cref="ILobbyListener.ControlPackageArrived"/> public void ControlPackageArrived(RCPackage package) { //lock (this.disposeLock) { if (this.objectDisposed) { throw new ObjectDisposedException("DssEventQueue"); } } int timestamp = DssRoot.Time; /// Preprocess the event in the context of the caller thread. lock (this.eventPreprocessors) { foreach (DssEventPreprocessor preprocessor in this.eventPreprocessors) { if (!preprocessor.ControlPackageFromServerPre(package)) { TraceManager.WriteAllTrace(string.Format("Ignoring CONTROL_PACKAGE_FROM_SERVER({0})", package), DssTraceFilters.EVENT_QUEUE_INFO); return; } } } /// Insert the event to the queue after a successfull preprocess. lock (this.queueLock) { this.eventTypeFifo.Push(DssEventType.CONTROL_PACKAGE_FROM_SERVER); this.packageArgFifo.Push(package); this.eventTimestamps.Push(timestamp); this.readSemaphore.Release(); } }
/// <summary> /// Initializes the isometric tiles of the map structure. /// </summary> /// <param name="isotileListPackage">The package that contains the isometric tile informations.</param> private void LoadIsoTiles(RCPackage isotileListPackage) { string[] terrainIndexTable = isotileListPackage.ReadStringArray(0); byte[] isotileInfoBytes = isotileListPackage.ReadByteArray(1); int offset = 0; while (offset < isotileInfoBytes.Length) { int parsedBytes; RCPackage package = RCPackage.Parse(isotileInfoBytes, offset, isotileInfoBytes.Length - offset, out parsedBytes); if (package == null || !package.IsCommitted) { throw new MapException("Syntax error!"); } offset += parsedBytes; if (package.PackageFormat.ID == MapFileFormat.ISOTILE) { RCIntVector quadCoords = new RCIntVector(package.ReadShort(0), package.ReadShort(1)); TerrainCombination terrainCombo = (TerrainCombination)package.ReadByte(4); string terrainA = terrainIndexTable[package.ReadByte(2)]; string terrainB = terrainCombo != TerrainCombination.Simple ? terrainIndexTable[package.ReadByte(3)] : null; int variantIdx = package.ReadByte(5); this.mapStructure.InitIsoTile(quadCoords, terrainCombo == TerrainCombination.Simple ? this.mapStructure.Tileset.GetIsoTileType(terrainA) : this.mapStructure.Tileset.GetIsoTileType(terrainA, terrainB, terrainCombo), variantIdx); } } }
protected override RCPackage ReadPackage_i(ref IPAddress sender) { try { if (this.udpSocket.Available >= NetworkingSystemConstants.ANNOUNCEMENT_UDP_POCKET_SIZE) { EndPoint rcvFrom = new IPEndPoint(0, 0); int bytesReceived = this.udpSocket.ReceiveFrom(this.buffer, NetworkingSystemConstants.ANNOUNCEMENT_UDP_POCKET_SIZE, SocketFlags.None, ref rcvFrom); if (bytesReceived == NetworkingSystemConstants.ANNOUNCEMENT_UDP_POCKET_SIZE) { int parsedBytes = 0; RCPackage retPackage = RCPackage.Parse(this.buffer, 0, NetworkingSystemConstants.ANNOUNCEMENT_UDP_POCKET_SIZE, out parsedBytes); if (retPackage != null && retPackage.IsCommitted) { IPEndPoint senderEndpoint = (IPEndPoint)rcvFrom; sender = senderEndpoint.Address; return(retPackage); } } } } catch (Exception ex) { TraceManager.WriteExceptionAllTrace(ex, false); } sender = IPAddress.Any; return(null); }
/// <see cref="IMapLoader.LoadMapHeader"/> public MapHeader LoadMapHeader(byte[] data) { if (!this.initThreadStarted) { throw new InvalidOperationException("Component has not yet been started!"); } this.initThread.Join(); if (data == null) { throw new ArgumentNullException("data"); } int offset = 0; while (offset < data.Length) { int parsedBytes; RCPackage package = RCPackage.Parse(data, offset, data.Length - offset, out parsedBytes); if (package == null || !package.IsCommitted) { throw new MapException("Syntax error!"); } offset += parsedBytes; if (package.PackageFormat.ID == MapFileFormat.MAP_HEADER) { return(MapHeader.FromPackage(package)); } } throw new MapException("Map header information not found!"); }
/// <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); }
/// <see cref="ITrace.WriteFork"/> public void WriteFork(RCThread newThread, RCThread parentThread) { if (newThread == null) { throw new ArgumentNullException("newThread"); } if (parentThread == null) { throw new ArgumentNullException("parentThread"); } RCPackage packageToWrite = RCPackage.CreateCustomDataPackage(RCL_FORK_FORMAT); packageToWrite.WriteInt(0, newThread.WrappedThread.ManagedThreadId); packageToWrite.WriteString(1, newThread.Name); packageToWrite.WriteInt(2, parentThread.WrappedThread.ManagedThreadId); packageToWrite.WriteString(3, parentThread.Name); packageToWrite.WriteLong(4, timer.ElapsedMilliseconds); byte[] buffer = new byte[packageToWrite.PackageLength]; packageToWrite.WritePackageToBuffer(buffer, 0); this.outputWriter.Write(buffer); this.outputWriter.Flush(); this.outputStream.Flush(); }
/// <summary> /// /// </summary> /// <param name="byteArray"></param> private List <RCPackage> GetLogPackages(byte[] byteArray) { int offset = 0; int remaining = byteArray.Length; List <RCPackage> packages = new List <RCPackage>(); while (offset < byteArray.Length) { int parsedBytes; RCPackage logPackage = RCPackage.Parse(byteArray, offset, remaining, out parsedBytes); if (logPackage.IsCommitted && (logPackage.PackageFormat.ID == Program.EVENT_FORMAT || logPackage.PackageFormat.ID == Program.FORK_FORMAT || logPackage.PackageFormat.ID == Program.JOIN_FORMAT || logPackage.PackageFormat.ID == Program.EXCEPTION_FORMAT)) { packages.Add(logPackage); } else { throw new Exception(string.Format("Unexpected package format ID: {0}", logPackage.PackageFormat.ID)); } offset += parsedBytes; remaining -= parsedBytes; } return(packages); }
/// <see cref="ITrace.WriteLine"/> public void WriteLine(object obj) { if (obj == null) { throw new ArgumentNullException("obj"); } string strToWrite = obj.ToString(); if (strToWrite == null) { strToWrite = string.Empty; } RCPackage packageToWrite = RCPackage.CreateCustomDataPackage(RCL_EVENT_FORMAT); packageToWrite.WriteInt(0, RCThread.CurrentThread.WrappedThread.ManagedThreadId); packageToWrite.WriteString(1, RCThread.CurrentThread.Name); packageToWrite.WriteLong(2, timer.ElapsedMilliseconds); packageToWrite.WriteString(3, strToWrite); byte[] buffer = new byte[packageToWrite.PackageLength]; packageToWrite.WritePackageToBuffer(buffer, 0); this.outputWriter.Write(buffer); this.outputWriter.Flush(); this.outputStream.Flush(); }
/// <see cref="ITrace.WriteLine"/> public void WriteException(Exception ex, bool isFatal) { if (ex == null) { throw new ArgumentNullException("ex"); } string strToWrite = ex.ToString(); if (strToWrite == null) { strToWrite = string.Empty; } RCPackage packageToWrite = RCPackage.CreateCustomDataPackage(RCL_EXCEPTION_FORMAT); packageToWrite.WriteInt(0, RCThread.CurrentThread.WrappedThread.ManagedThreadId); packageToWrite.WriteString(1, RCThread.CurrentThread.Name); packageToWrite.WriteLong(2, timer.ElapsedMilliseconds); packageToWrite.WriteByte(3, isFatal ? (byte)0x01 : (byte)0x00); packageToWrite.WriteString(4, strToWrite); byte[] buffer = new byte[packageToWrite.PackageLength]; packageToWrite.WritePackageToBuffer(buffer, 0); this.outputWriter.Write(buffer); this.outputWriter.Flush(); this.outputStream.Flush(); }
/// <see cref="ITrace.WriteJoin"/> public void WriteJoin(RCThread runningThread, RCThread waitingThread) { if (runningThread == null) { throw new ArgumentNullException("runningThread"); } if (waitingThread == null) { throw new ArgumentNullException("waitingThread"); } RCPackage packageToWrite = RCPackage.CreateCustomDataPackage(RCL_JOIN_FORMAT); packageToWrite.WriteInt(0, runningThread.WrappedThread.ManagedThreadId); packageToWrite.WriteString(1, runningThread.Name); packageToWrite.WriteInt(2, waitingThread.WrappedThread.ManagedThreadId); packageToWrite.WriteString(3, waitingThread.Name); packageToWrite.WriteLong(4, timer.ElapsedMilliseconds); byte[] buffer = new byte[packageToWrite.PackageLength]; packageToWrite.WritePackageToBuffer(buffer, 0); this.outputWriter.Write(buffer); this.outputWriter.Flush(); this.outputStream.Flush(); }
/// <summary> /// Call this function when an error occurs during the simulation stage. /// </summary> /// <param name="reason">The reason of the error.</param> /// <param name="customData">Custom data about the error.</param> public void SimulationStageError(string reason, byte[] customData) { if (!this.initialized) { throw new DssException("DssSimulationMgr is uninitialized!"); } /// If we are currently finishing the simulation --> do nothing if (this.hostLeft) { return; } /// Stop the alarm clocks StopCommitTimeoutClock(); StopSimulationFrameClock(); UnregisterAllCommitMonitors(); /// Send the DSS_SIM_ERROR message to the others RCPackage errPackage = RCPackage.CreateNetworkCustomPackage(DssRoot.DSS_SIM_ERROR); errPackage.WriteString(0, reason); errPackage.WriteByteArray(1, customData); this.root.LobbyIface.SendPackage(errPackage); /// Quit from the DSS immediately this.root.SimulatorIface.SimulationError(reason, customData); this.root.EventQueue.ExitEventLoop(); }
/// <see cref="ILobby.SendPackage"/> public bool SendPackage(RCPackage package, int[] targets) { if (package == null) { throw new ArgumentNullException("package"); } if (targets == null || targets.Length == 0) { throw new ArgumentNullException("targets"); } if (package.IsCommitted && package.PackageType == RCPackageType.NETWORK_CUSTOM_PACKAGE && package.PackageFormat.ID != Network.FORMAT_DEDICATED_MESSAGE && package.PackageFormat.ID != Network.FORMAT_DISCONNECT_ACK && package.PackageFormat.ID != Network.FORMAT_DISCONNECT_INDICATOR && package.PackageFormat.ID != Network.FORMAT_LOBBY_INFO && package.PackageFormat.ID != Network.FORMAT_LOBBY_INFO_VANISHED && package.PackageFormat.ID != Network.FORMAT_LOBBY_LINE_STATE_REPORT) { lock (this.outgoingPackages) { this.outgoingPackages.Add(package); this.outgoingPackageTargets.Add(targets); return(true); } } return(false); }
/// <see cref="ILobbyServer.SendControlPackage"/> public bool SendControlPackage(RCPackage package, int target) { if (package == null) { throw new ArgumentNullException("package"); } if (target == 0) { throw new ArgumentException("Internal message can only be sent to a client!", "target"); } if (package.IsCommitted && package.PackageType == RCPackageType.NETWORK_CONTROL_PACKAGE && package.PackageFormat.ID != Network.FORMAT_DEDICATED_MESSAGE && package.PackageFormat.ID != Network.FORMAT_DISCONNECT_ACK && package.PackageFormat.ID != Network.FORMAT_DISCONNECT_INDICATOR && package.PackageFormat.ID != Network.FORMAT_LOBBY_INFO && package.PackageFormat.ID != Network.FORMAT_LOBBY_INFO_VANISHED && package.PackageFormat.ID != Network.FORMAT_LOBBY_LINE_STATE_REPORT) { lock (this.tasks) { this.tasks.Add(NetworkingTaskType.OUTGOING_MESSAGE); this.outgoingPackages.Push(package); this.outgoingPackageTargets.Push(new int[1] { target }); return(true); } } return(false); }
/// <summary> /// The starting function of the announcer thread. /// </summary> private void AnnounceProc() { while (!this.announcementFinished.WaitOne(NetworkingSystemConstants.ANNOUNCEMENT_FREQUENCY)) { LobbyInfo lobbyInfo = new LobbyInfo(this.announcedLobby.Id, "", this.announcedLobby.PortNum); if (null != this.customDataProvider) { lobbyInfo.CustomData = this.customDataProvider.CustomData; } RCPackage lobbyInfoPackage = lobbyInfo.Package; BroadcastPackage_i(lobbyInfoPackage); } /// Announce finished so we broadcast a FORMAT_LOBBY_INFO_VANISHED message. RCPackage lobbyVanishedPackage = RCPackage.CreateCustomDataPackage(Network.FORMAT_LOBBY_INFO_VANISHED); lobbyVanishedPackage.WriteString(0, this.announcedLobby.Id.ToString()); for (int i = 0; i < NetworkingSystemConstants.ANNOUNCEMENT_BROADCAST_MULTIPLICITY; i++) { /// Broadcast more than once because of possible package lost on UDP. BroadcastPackage_i(lobbyVanishedPackage); } }
/// <see cref="ITileSetLoader.LoadTileSet"/> public ITileSet LoadTileSet(byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } int parsedBytes; RCPackage package = RCPackage.Parse(data, 0, data.Length, out parsedBytes); if (!package.IsCommitted) { throw new ArgumentException("TileSet data package is not committed!", "data"); } if (package.PackageType != RCPackageType.CUSTOM_DATA_PACKAGE) { throw new ArgumentException("TileSet data package must be RCPackageType.CUSTOM_DATA_PACKAGE!", "data"); } if (package.PackageFormat.ID != PackageFormats.TILESET_FORMAT) { throw new ArgumentException("Format of TileSet data package must be RC.Engine.Maps.TileSetFormat!", "data"); } TileSet tileset = XmlTileSetReader.Read(package.ReadString(0), package.ReadString(1)); return(tileset); }
/// <summary> /// Called when a NETWORK_CUSTOM_PACKAGE has arrived from the lobby. /// </summary> /// <remarks>Must be implemented at both server and client side.</remarks> public virtual void PackageArrivedHdl(int timestamp, RCPackage package, int senderID) { if (IsSimulationRunning_i()) { /// Package arrived during simulation stage must be handled. if (package.PackageFormat.ID == DssRoot.DSS_COMMAND) { if (!CommandPackageArrived(package, senderID)) { this.root.SimulationMgr.SimulationStageError(string.Format("Processing incoming DSS_COMMAND package failed. Sender: {0}. Package: {1}", senderID, package.ToString()), new byte[] { }); } } else if (package.PackageFormat.ID == DssRoot.DSS_COMMIT) { if (!this.root.SimulationMgr.RegisterCommit(package, senderID)) { this.root.SimulationMgr.SimulationStageError(string.Format("Processing incoming DSS_COMMIT package failed. Sender: {0}. Package: {1}", senderID, package.ToString()), new byte[] { }); } } else if (package.PackageFormat.ID == DssRoot.DSS_COMMIT_ANSWER) { if (!this.root.SimulationMgr.RegisterCommitAnswer(package, senderID)) { this.root.SimulationMgr.SimulationStageError(string.Format("Processing incoming DSS_COMMIT_ANSWER package failed. Sender: {0}. Package: {1}", senderID, package.ToString()), new byte[] { }); } } else if (package.PackageFormat.ID == DssRoot.DSS_LEAVE) { if (this.root.SimulationMgr.RegisterLeaveMessage(package, senderID)) { this.root.OperatorLeftSimulationStage(senderID); } else { this.root.SimulationMgr.SimulationStageError(string.Format("Processing incoming DSS_LEAVE package failed. Sender: {0}. Package: {1}", senderID, package.ToString()), new byte[] { }); } } else if (package.PackageFormat.ID == DssRoot.DSS_SIM_ERROR) { string errorDescr = package.ReadString(0); byte[] customData = package.ReadByteArray(1); this.root.SimulationMgr.SimulationStageErrorReceived(string.Format("DSS_SIM_ERROR received from operator-{0}: {1}", senderID, errorDescr), customData); } else { this.root.SimulationMgr.SimulationStageError(string.Format("Unexpected package arrived from operator-{0}: {1}", senderID, package.ToString()), new byte[] { }); } } else { /// Package arrived during setup stage is not allowed. PackageArrivedDuringSetupStage_i(package, senderID); } }
/// <see cref="IScenarioLoader.LoadScenario"/> public Scenario LoadScenario(IMapAccess map, byte[] data) { if (map == null) { throw new ArgumentNullException("map"); } if (data == null) { throw new ArgumentNullException("data"); } /// Load the packages from the byte array. int offset = 0; Scenario scenario = new Scenario(map); while (offset < data.Length) { int parsedBytes; RCPackage package = RCPackage.Parse(data, offset, data.Length - offset, out parsedBytes); if (package == null || !package.IsCommitted) { throw new SimulatorException("Syntax error!"); } offset += parsedBytes; if (package.PackageFormat.ID == ScenarioFileFormat.MINERAL_FIELD) { IQuadTile quadTile = map.GetQuadTile(new RCIntVector(package.ReadShort(0), package.ReadShort(1))); MineralField mineralField = new MineralField(); mineralField.ResourceAmount.Write(package.ReadInt(2)); scenario.AddElementToScenario(mineralField); mineralField.AttachToMap(quadTile); } else if (package.PackageFormat.ID == ScenarioFileFormat.VESPENE_GEYSER) { IQuadTile quadTile = map.GetQuadTile(new RCIntVector(package.ReadShort(0), package.ReadShort(1))); VespeneGeyser vespeneGeyser = new VespeneGeyser(); vespeneGeyser.ResourceAmount.Write(package.ReadInt(2)); scenario.AddElementToScenario(vespeneGeyser); vespeneGeyser.AttachToMap(quadTile); } else if (package.PackageFormat.ID == ScenarioFileFormat.START_LOCATION) { IQuadTile quadTile = map.GetQuadTile(new RCIntVector(package.ReadShort(0), package.ReadShort(1))); StartLocation startLocation = new StartLocation(package.ReadByte(2)); scenario.AddElementToScenario(startLocation); startLocation.AttachToMap(quadTile); } } /// Check the constraints of the visible entities. foreach (Entity entity in scenario.GetElementsOnMap <Entity>(MapObjectLayerEnum.GroundObjects, MapObjectLayerEnum.AirObjects)) { if (entity.CheckPlacementConstraints(entity.MapObject.QuadraticPosition.Location, new RCSet <Entity>()).Count != 0) { throw new MapException(string.Format("Entity at {0} is voilating its placement constraints!", entity.MapObject.QuadraticPosition.Location)); } } return(scenario); }
/// <summary> /// Pushes a command into the incoming command queue. /// </summary> /// <param name="commandPackage">The command to push.</param> public void PushIncomingCommand(RCPackage commandPackage) { if (commandPackage == null) { throw new ArgumentNullException("commandPackage"); } this.incomingCommands.Add(commandPackage); }
public void GuestCommand(int guestIndex, RCPackage command) { if (command.PackageFormat.ID == TestClientMessages.COMMAND) { PlayerDirection dir = (PlayerDirection)command.ReadByte(0); this.simulator.GetPlayer(guestIndex + 1).Direction = dir; } }
/// <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); }
/// <summary> /// Registers the given commit answer arrived from the given operator. /// </summary> /// <param name="commit">The arrived commit answer package.</param> /// <param name="senderID">The sender operator.</param> /// <returns>True in case of success, false otherwise.</returns> public bool RegisterCommitAnswer(RCPackage commitAw, int senderID) { if (!this.initialized) { throw new DssException("DssSimulationMgr is uninitialized!"); } /// If we are currently finishing the simulation --> do nothing if (this.hostLeft) { return(true); } if (commitAw == null || !commitAw.IsCommitted) { throw new ArgumentException("commitAw"); } if (senderID == this.root.IdOfThisPeer) { throw new DssException("Unexpected commit answer sender!"); } if (senderID < 0 || senderID >= this.root.OpCount) { throw new ArgumentException("senderID"); } if (commitAw.PackageFormat.ID != DssRoot.DSS_COMMIT_ANSWER) { /// Package format error. return(false); } int ticket = commitAw.ReadInt(0); if (!this.commitAwMonitors.ContainsKey(ticket)) { /// Unexpected ticket. return(false); } CommitMonitor monitor = this.commitAwMonitors[ticket]; int pingTime = -1; if (monitor.AnswerArrived(senderID, out pingTime)) { this.aptCalculators[senderID].NewItem(pingTime); if (monitor.IsCommitAnswered) { UnregisterCommitMonitor(ticket); } return(true); } else { /// Ping already answered by the sender. return(false); } }
/// <summary> /// Initializes the terrain objects of the map. /// </summary> /// <param name="terrainObjListPackage">The package that contains the terrain object informations.</param> /// <param name="map">Reference to the map.</param> private void LoadTerrainObjects(RCPackage terrainObjListPackage, IMapAccess map) { /// TODO: Avoid this downcast! MapAccess mapObj = map as MapAccess; if (mapObj == null) { throw new ArgumentException("The given map cannot be handled by the MapEditor!", "map"); } string[] terrainObjIndexTable = terrainObjListPackage.ReadStringArray(0); byte[] terrainObjInfoBytes = terrainObjListPackage.ReadByteArray(1); int offset = 0; while (offset < terrainObjInfoBytes.Length) { int parsedBytes; RCPackage package = RCPackage.Parse(terrainObjInfoBytes, offset, terrainObjInfoBytes.Length - offset, out parsedBytes); if (package == null || !package.IsCommitted) { throw new MapException("Syntax error!"); } offset += parsedBytes; if (package.PackageFormat.ID == MapFileFormat.TERRAINOBJ) { RCIntVector quadCoords = new RCIntVector(package.ReadShort(0), package.ReadShort(1)); ITerrainObjectType terrainObjType = this.mapStructure.Tileset.GetTerrainObjectType(terrainObjIndexTable[package.ReadByte(2)]); /// TODO: Might be better to create the TerrainObject with a factory? ITerrainObject newObj = new TerrainObject(map, terrainObjType, quadCoords); foreach (ICellDataChangeSet changeset in newObj.Type.CellDataChangesets) { changeset.Apply(newObj); } mapObj.AttachTerrainObject(newObj); } } /// Check the constraints of the terrain objects. List <ITerrainObject> terrainObjects = new List <ITerrainObject>(map.TerrainObjects); foreach (ITerrainObject terrainObj in terrainObjects) { mapObj.DetachTerrainObject(terrainObj); if (terrainObj.Type.CheckConstraints(map, terrainObj.MapCoords).Count != 0) { throw new MapException(string.Format("Terrain object at {0} is voilating the tileset constraints!", terrainObj.MapCoords)); } if (terrainObj.Type.CheckTerrainObjectIntersections(map, terrainObj.MapCoords).Count != 0) { throw new MapException(string.Format("Terrain object at {0} intersects other terrain objects!", terrainObj.MapCoords)); } mapObj.AttachTerrainObject(terrainObj); } }