/// <summary> /// Call this function to initialize the UI for the setup stage and send reset messages to the connected guests. /// </summary> private void FirstSetupStep(IDssGuestChannel[] channelsToGuests) { /// Reset the UI this.simulator.GetPlayer(0).Reset(); this.simulator.GetPlayer(0).Activate(); this.uiCallMarshal.SetMainControlStatus(FormStatus.HostSide); this.uiCallMarshal.SelectNewHostColor(this.simulator.GetPlayer(0).Color); this.uiCallMarshal.SetHostControlStatus(HostControlStatus.AccessGranted); this.previousChannelStates = new DssChannelState[channelsToGuests.Length]; for (int i = 0; i < this.previousChannelStates.Length; i++) { this.simulator.GetPlayer(i + 1).Reset(); this.previousChannelStates[i] = channelsToGuests[i].ChannelState; if (channelsToGuests[i].ChannelState == DssChannelState.CHANNEL_OPENED) { this.uiCallMarshal.SetGuestControlStatus(i, GuestControlStatus.HostSideOpened); } else if (channelsToGuests[i].ChannelState == DssChannelState.CHANNEL_CLOSED) { this.uiCallMarshal.SetGuestControlStatus(i, GuestControlStatus.HostSideClosed); } else if (channelsToGuests[i].ChannelState == DssChannelState.GUEST_CONNECTED) { this.simulator.GetPlayer(i + 1).Activate(); this.uiCallMarshal.SelectNewGuestColor(i, this.simulator.GetPlayer(i + 1).Color); this.uiCallMarshal.SetGuestControlStatus(i, GuestControlStatus.HostSideEngaged); } } /// Send reset messages for (int i = 0; i < channelsToGuests.Length; i++) { if (channelsToGuests[i].ChannelState == DssChannelState.GUEST_CONNECTED) { byte[] colors = new byte[this.simulator.MaxNumOfPlayers]; int[] xCoords = new int[this.simulator.MaxNumOfPlayers]; int[] yCoords = new int[this.simulator.MaxNumOfPlayers]; for (int j = 0; j < colors.Length; j++) { colors[j] = (byte)this.simulator.GetPlayer(j).Color; xCoords[j] = this.simulator.GetPlayer(j).Position.X; yCoords[j] = this.simulator.GetPlayer(j).Position.Y; } RCPackage reset = RCPackage.CreateNetworkControlPackage(TestClientMessages.RESET); reset.WriteByteArray(0, colors); reset.WriteIntArray(1, xCoords); reset.WriteIntArray(2, yCoords); this.rqs[i].Add(reset); } } }
/// <summary> /// Creates an RCPackage from this command. /// </summary> /// <returns>The created RCPackage.</returns> public RCPackage ToPackage() { RCPackage package = RCPackage.CreateCustomDataPackage(RCCommand.COMMAND_PACKAGEFORMAT); package.WriteString(0, this.commandType ?? string.Empty); package.WriteIntArray(1, this.recipientEntities); package.WriteInt(2, this.targetPosition != RCNumVector.Undefined ? this.targetPosition.X.Bits : -1); package.WriteInt(3, this.targetPosition != RCNumVector.Undefined ? this.targetPosition.Y.Bits : -1); package.WriteInt(4, this.targetEntity); package.WriteString(5, this.parameter ?? string.Empty); return(package); }
/// <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> /// Processes the channel events and incoming answers arrived from the guests. /// </summary> private void ProcessGuestChannels(IDssGuestChannel[] channelsToGuests) { RCSet <int> newGuests = new RCSet <int>(); /// First collect the new guests for (int i = 0; i < this.previousChannelStates.Length; i++) { if (this.previousChannelStates[i] != channelsToGuests[i].ChannelState) { /// The state of a channel has changed this.previousChannelStates[i] = channelsToGuests[i].ChannelState; if (channelsToGuests[i].ChannelState == DssChannelState.CHANNEL_OPENED) { this.uiCallMarshal.SetGuestControlStatus(i, GuestControlStatus.HostSideOpened); } else if (channelsToGuests[i].ChannelState == DssChannelState.CHANNEL_CLOSED) { this.uiCallMarshal.SetGuestControlStatus(i, GuestControlStatus.HostSideClosed); } else if (channelsToGuests[i].ChannelState == DssChannelState.GUEST_CONNECTED) { this.uiCallMarshal.SetGuestControlStatus(i, GuestControlStatus.HostSideEngaged); this.simulator.GetPlayer(i + 1).Activate(); newGuests.Add(i); } } } /// Then process the answers of any other guests. for (int i = 0; i < this.previousChannelStates.Length; i++) { if (!newGuests.Contains(i) && channelsToGuests[i].ChannelState == DssChannelState.GUEST_CONNECTED) { /// If a guest is connected to this channel, process it's answer. RCPackage[] answerFromGuest = channelsToGuests[i].AnswerFromGuest; for (int j = 0; j < answerFromGuest.Length; j++) { if (answerFromGuest[j].PackageFormat.ID == TestClientMessages.COLOR_CHANGE_REQUEST) { /// Color change request arrived from the guest. PlayerColor newColor = (PlayerColor)answerFromGuest[j].ReadByte(0); this.simulator.GetPlayer(i + 1).Color = newColor; /// Notify the other connected guests. for (int k = 0; k < channelsToGuests.Length; k++) { if (!newGuests.Contains(k) && i != k && channelsToGuests[k].ChannelState == DssChannelState.GUEST_CONNECTED) { RCPackage colorChgNotif = RCPackage.CreateNetworkControlPackage(TestClientMessages.COLOR_CHANGE_NOTIFICATION); colorChgNotif.WriteInt(0, i + 1); colorChgNotif.WriteByte(1, (byte)newColor); this.rqs[k].Add(colorChgNotif); } } /// Notify the UI this.uiCallMarshal.SelectNewGuestColor(i, newColor); break; /// Ignore the remaining messages } } } } /// Send a reset message to the new guests foreach (int newGuestIdx in newGuests) { byte[] colors = new byte[this.simulator.MaxNumOfPlayers]; int[] xCoords = new int[this.simulator.MaxNumOfPlayers]; int[] yCoords = new int[this.simulator.MaxNumOfPlayers]; for (int j = 0; j < colors.Length; j++) { colors[j] = (byte)this.simulator.GetPlayer(j).Color; xCoords[j] = this.simulator.GetPlayer(j).Position.X; yCoords[j] = this.simulator.GetPlayer(j).Position.Y; } RCPackage reset = RCPackage.CreateNetworkControlPackage(TestClientMessages.RESET); reset.WriteByteArray(0, colors); reset.WriteIntArray(1, xCoords); reset.WriteIntArray(2, yCoords); this.rqs[newGuestIdx].Add(reset); } }
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); }
/// <summary> /// Starts the simulation. /// </summary> private void StartSimulation() { /// Collect opFlags and channel state informations. byte[] chStates = new byte[this.channelProxies.Length]; bool[] opFlags = new bool[this.hostRoot.OpCount]; opFlags[0] = true; for (int i = 0; i < chStates.Length; i++) { if (this.channels[i].CurrentState == this.channels[i].Opened) { /// If the channel is opened then it will be closed. //this.channels[i].CloseChannel(); this.channels[i].PermanentlyClose(); chStates[i] = (byte)DssChannelState.CHANNEL_CLOSED;//CHANNEL_OPENED; opFlags[i + 1] = false; } else if (this.channels[i].CurrentState == this.channels[i].Closed) { /// If the channel is closed then it will remain closed. this.channels[i].PermanentlyClose(); chStates[i] = (byte)DssChannelState.CHANNEL_CLOSED; opFlags[i + 1] = false; } else if (this.channels[i].CurrentState == this.channels[i].Engaged) { /// If the channel is engaged then we have to check whether the guest will be dropped or not. if (this.channelProxies[i].TaskToPerform == DssChannelTask.DROP_AND_OPEN || this.channelProxies[i].TaskToPerform == DssChannelTask.DROP_AND_CLOSE) { /// Close channel permanently. this.channels[i].PermanentlyClose(); this.hostRoot.GuestLeftDss(i); chStates[i] = (byte)DssChannelState.CHANNEL_CLOSED; opFlags[i + 1] = false; } else { /// Don't drop guest, it will participate in the simulation stage. chStates[i] = (byte)DssChannelState.GUEST_CONNECTED; opFlags[i + 1] = true; } } else { throw new DssException("Unexpected channel state!"); } } int[] leftList = null; int[] lostList = null; this.hostRoot.GetGuestEvents(out leftList, out lostList); RCPackage startSimMsg = RCPackage.CreateNetworkControlPackage(DssRoot.DSS_CTRL_START_SIMULATION); startSimMsg.WriteIntArray(0, leftList); startSimMsg.WriteIntArray(1, lostList); startSimMsg.WriteByteArray(2, chStates); /// Send the DSS_CTRL_START_SIMULATION message to every engaged channels for (int i = 0; i < this.sessions.Length; i++) { if (opFlags[i + 1]) { /// Push the corresponding session and channel to the Simulating state this.channels[i].StartSimulation(); this.sessions[i].StartSimulation(); /// Send the start message to the corresponding guest this.hostRoot.Lobby.SendControlPackage(startSimMsg, i + 1); } } /// Reset the simulation manager and ask it to execute the next frame immediately. this.hostRoot.SimulationMgr.Reset(opFlags); this.hostRoot.SimulationMgr.SetNextFrameExecutionTime(DssRoot.Time); /// And finally go to the SimulationStage. this.SendingSetupStepRQs_SimulationStage.Fire(); }