/// <summary> /// Event called when any client or host connection has a change in a network data collection. /// </summary> /// <param name="packet">The base packet containing the raw data.</param> /// <param name="data">NetworkEvent data containing the contents of the NetworkPacket in a parsed format.</param> private void ConnectionCollectionChanged(NetworkPacket packet, NetworkEventArgs data) { try { //Make sure the data is of the correct type. if (data.DataType == typeof(NotifyCollectionChangedEventArgs)) { //Grab the collection changed information from the data. NotifyCollectionChangedEventArgs args = data.Data as NotifyCollectionChangedEventArgs; //Check if we have the source collection whose items was changed. if (_registeredObjects.ContainsKey(data.NetworkDataId)) { //Get the source collection we want to manipulate IList collection = _registeredObjects[data.NetworkDataId] as IList; //Disable the listener for this object while we do our changes. ListenerDisable((INetworkData)collection); //apply the changes that occured at the client/host to our collection. switch (args.Action) { case NotifyCollectionChangedAction.Add: for (int i = 0; i < args.NewItems.Count; i++) collection.Insert(args.NewStartingIndex + i, args.NewItems[i]); break; case NotifyCollectionChangedAction.Move: for (int i = 0; i < args.NewItems.Count; i++) { object temp = collection[args.OldStartingIndex + (args.OldStartingIndex > args.NewStartingIndex ? i : 0)]; collection.Remove(temp); collection.Insert(args.NewStartingIndex + i, temp); } break; case NotifyCollectionChangedAction.Remove: for (int i = 0; i < args.OldItems.Count; i++) collection.RemoveAt(args.OldStartingIndex + i); break; case NotifyCollectionChangedAction.Replace: for (int i = 0; i < args.NewItems.Count; i++) collection[args.OldStartingIndex + i] = args.NewItems[i]; break; case NotifyCollectionChangedAction.Reset: collection.Clear(); break; } //Enable the listener for our collection. ListenerEnable((INetworkData)collection); //Forward if necessary. data.Forward(); } else if (OnNotificationOccured != null) OnNotificationOccured(data, string.Format("A CollectionChanged packet was received for a collection on a network id but the network id object was not found in registered objects.")); } else if (OnNotificationOccured != null) OnWarningOccured(data, new Warning(string.Format("A network packet for collection changed was received but that data was of an invalid type. Expected a type of '{0}' but received '{1}'.", typeof(NotifyCollectionChangedEventArgs).FullName, data.DataType.FullName))); } catch (Exception e) { ThrowException(data, e); } }
/// <summary> /// Event called when any client or host connection has had any of its registered network data changed property. /// </summary> /// <param name="packet">The base packet containing the raw data.</param> /// <param name="data">NetworkEvent data containing the contents of the NetworkPacket in a parsed format.</param> /// <exception cref="NetworkLibrary.Exceptions.ParsingException" /> /// <exception cref="System.Exception" /> private void ConnectionPropertyChanged(NetworkPacket packet, NetworkEventArgs data) { try { //Check to see if the property changed packet we recieved was found in the registered objects collection. if (_registeredObjects.ContainsKey(data.NetworkDataId) && data.PropertyName != "Count") { try { //Disable listening on the object while we pass in the value. //This is done so that it doesn't end in an infinite loop between the host and the client. this.ListenerDisable(_registeredObjects[data.NetworkDataId]); //Set the value of the property on the object _registeredObjects[data.NetworkDataId].GetType().GetProperty(data.PropertyName).SetValue(_registeredObjects[data.NetworkDataId], data.Data, null); this.ListenerEnable(_registeredObjects[data.NetworkDataId]); } catch (Exception e) { throw new ParsingException(string.Format("Error while passing the value '{0}' of type '{1}' to the following property '{2}' on an object of type '{3}'. Error message received: {4}", data.Data, data.DataType.FullName, data.PropertyName, _registeredObjects[data.NetworkDataId].GetType().FullName, e.Message)); } } } catch (Exception e) { ThrowException(this, e); } }
/// <summary> /// Event that is called automatically when a NetworkRequest was recieved. /// </summary> /// <param name="packet">The base packet containing the raw data.</param> /// <param name="data">NetworkEvent data containing the contents of the NetworkPacket in a parsed format.</param> private void ReceivedNetworkRequest(NetworkPacket packet, NetworkEventArgs data) { //Prelimenary checking on whether the data is of correct type if (data.DataType == typeof(RequestNetworkData)) { // The data passed over the network is a real Request. Processing the request. try { //Create the response for the request and pass in all data of the request over to the //the response. This is done so the InternalName as well as other data is passed over. RequestNetworkData response = new RequestNetworkData(data.Data as RequestNetworkData); //Start processing the request. switch (response.RequestType) { case RequestNetworkDataType.RequestType: //The connection is requesting a data of specific type. Search the registered //objects for any objects that fit the description. for (int i = 0; i < _registeredObjects.Count; i++) if (_registeredObjects.ElementAt(i).Value.GetType().FullName == response.ClassTypeName) { response.Data = _registeredObjects.ElementAt(i).Value; break; } break; case RequestNetworkDataType.RequestName: //The connection is requesting name for it's object. Pass in a random //generated identifier. response.NetworkId = GetNewNetworkId(response.ClassTypeName); break; case RequestNetworkDataType.RequestData: //The connection is requesting a data with specific NetworkId. //Return the object containing that NetworkId. response.Data = this._registeredObjects[response.NetworkId]; break; } //Send the response over the network to the client/host. _network.SendSingleRawEvent((int)CorePacketCode.NetworkDataRequestResponse, new Serialiser(true).Serialise(response), packet.Source); } catch (Exception e) { //An unknown error occured. Since this is not critical part of the NetworkLibrary we //pass it on as a Warning. if (OnWarningOccured != null) OnWarningOccured(this, new Warning("A network request was received but an unknown error occured while processing the request.", e)); } } //Received a packet containing the code for a Request but the data was of an invalid type. //Since this is not a critical part of the NetworkLibrary we pass it on as a Warning. else if (OnWarningOccured != null) OnWarningOccured(this, new Warning("A network request was received but was of an invalid format. Request was truncated.")); }
/// <summary> /// Event that is called automatically when receiving a response to a Network Request. /// </summary> /// <param name="packet">The base packet containing the raw data.</param> /// <param name="data">NetworkEvent data containing the contents of the NetworkPacket in a parsed format.</param> private void ReceivedNetworkRequestResponse(NetworkPacket packet, NetworkEventArgs data) { //Prelimenary checking on whether the data is of correct type if (data.DataType == typeof(RequestNetworkData)) { // The data passed over the network is a real Response. Processing the response. try { //Retreave the original request that was the source of the response. RequestNetworkData internalRequest = _requestedData[(data.Data as RequestNetworkData).InternalName]; //Pass all data retreived from the response into the request. internalRequest.NetworkId = (data.Data as RequestNetworkData).NetworkId; internalRequest.Data = (data.Data as RequestNetworkData).Data; //Check whether the request was requesting data or type of an object. //If it is, we register into our local NetworkLibrary automatically. if ((internalRequest.RequestType == RequestNetworkDataType.RequestData || internalRequest.RequestType == RequestNetworkDataType.RequestType) && internalRequest.Data != null) //The request was requesting data. Registering it automatically. RegisterRecursive(internalRequest.Data as INetworkData); lock (internalRequest) { //This is important. In many cases when processing data in the NetworkLibrary and data //needs to be requested, the request is sent and the thread that is doing the processing //is put on sleep. With this we send a pulse into the thread to wake it up so it can continue //on the processing and finish the process it started. Monitor.Pulse(internalRequest); } //Remove the request from our collection. Since the request has been sent, processed and finished //we don't need it anymore. _requestedData.Remove(internalRequest.InternalName); } catch (Exception e) { //An unknown error occured. Since this could result in a method or a thread being paused forever //we pass it on as a real Exception. ThrowException(this, new Exception("A network response was received but an unknown error occured while processing the request.", e)); } } //Received a packet containing the code for a Request but the data was of an invalid type. //Since this could be random junk we pass it on as a Warning. else if (OnWarningOccured != null) OnWarningOccured(this, new Warning("A network request response was received but was of an invalid format. Request was truncated.")); }
protected void StartGame(object source, NetworkEventArgs args) { Game.Network.UnregisterEvent((int)PacketCode.NewPlayer, NewPlayer); Game.Network.UnregisterEvent((int)PacketCode.Chat, NewChat); Game.Network.UnregisterEvent((int)PacketCode.StartGame, StartGame); Game.Network.UnregisterEvent((int)CorePacketCode.PropertyUpdated, UpdateGameSettings); string map = args.Data as string; string[] splitted = map.Split('\n'); _game.Board = new Board(_game, _game.Map); if (Game.Network.NetworkType == NetworkType.Host) { _game.Board.Load(map.Replace("\n", ""), splitted[0].Length, splitted.Length); Game.Network.NetworkDataHandler.RegisterRecursive(_game.Board); } _mainMenu.Options.Insert(8, new Option("Start", 10)); _mainMenu.Options.Insert(8, new Option("-", 10)); _mainMenu.ReDraw(); string text = "-- Host has started the game, please click Start --"; for (int i = _chat.Length - 1; i >= 0; i--) { string temp = _chat[i].Text; _chat[i].Text = text; text = temp; _chat[i].Draw(); } }
/// <summary> /// Event callback method to handle when a new client has been connected. /// </summary> /// <param name="packet">The source network packet.</param> /// <param name="args">The NetworkEventArgs containing all the data of the packet.</param> private void ClientConnected(NetworkPacket packet, NetworkEventArgs args) { //Check to see if the version of the network library matches. if (args.BasePacket.Header.GetValue<int>("ver") != this._header.GetValue<int>("ver")) { //The client is using a different version. We therefore disconnect him. Disconnect(args.SourceConnection); //Set handled to true so other events don't get called. args.Handled = true; } else _clientConnections.Add(args.SourceConnection); }
/// <summary> /// Run a registered event with the relevant arguments. /// </summary> /// <param name="method">The method to be run.</param> /// <param name="eventArgs">Arguments to pass the the method.</param> private void ExecuteEvent(delegateNetworkEvent method, NetworkEventArgs eventArgs) { try { method(eventArgs.BasePacket, eventArgs); } catch (Exception e) { ThrowOnExceptionOccured(this, e); } }
protected void NewPlayer(object source, NetworkEventArgs args) { if (args.BasePacket.Header.GetValue<string>("prog") != "shooter" && Game.Network.NetworkType == NetworkType.Host) { (Game.Network as ConnectionHost).Disconnect(args.SourceConnection); return; } Player p = args.Data as Player; p.Connection = args.SourceConnection; int index = 0; for (; index < _game.Players.Length; index++) { if (_game.Players[index] == null) break; } if (index == 4) { if (Game.Network.NetworkType == NetworkType.Host) (Game.Network as ConnectionHost).Disconnect(args.SourceConnection); return; } _game.Players[index] = p; args.Forward(); if (Game.Network.NetworkType == NetworkType.Host) { Game.Network.SendEvent((int)PacketCode.Chat, "-- player " + p.Name + " has connected --", true, args.SourceConnection); args.SendReply((int)CorePacketCode.AssignNewHeaderValue, new NetworkLibrary.Utilities.Header("id", index)); } UpdatePlayers(); }
protected void PlayerDisconnected(object source, NetworkEventArgs args) { Player p = args.Data as Player; for (int i = 0; i < _game.Players.Length; i++) if (_game.Players[i] == p) { if ((_playerIndex == 0 && i < 2) || (_playerIndex == 2 && i >= 2)) Game.Network.SendEvent((int)PacketCode.PlayerSelectionChanged, new int[] { i % 2, -1 }, true); break; } }
/// <summary> /// Event callback to handle a new value assignment for the header. /// </summary> /// <param name="packet">The source network packet.</param> /// <param name="data">NetworkEventArgs containing all relevant data.</param> private void AssignValueInHeader(NetworkPacket packet, NetworkEventArgs data) { if (data.DataType == typeof(Header)) this._header.Add(data.Data as Header); }
void PlayerSelectionChanged(object source, NetworkEventArgs args) { int[] values = args.Data as int[]; DrawOption(values[0], _playerSelection[values[0]], false); _playerSelection[values[0]] = values[1]; if (_playerSelection[values[0]] != -1) DrawOption(values[0], _playerSelection[values[0]], true); else { DrawOption(values[0], _guns.Count, true); if (_playerSelection[0] == -1 && _playerSelection[1] == -1) { Menu m = new Menu(Label.CreateLabelArrayFromText("Press any key to continue.")); m.Start(-1, 5); } } args.Forward(); }
//Network related code void PlayerNetworkBuys(object source, NetworkEventArgs args) { UpdatePlayer((int)args.Data); DrawOption((int)args.Data, _playerSelection[(int)args.Data], true); args.Forward(); }
private void PropertyUpdated(NetworkPacket packet, NetworkEventArgs args) { SendPacket(packet, packet.Source); }
private void ClearBullet(object sender, NetworkEventArgs args) { (args.Data as Shot).Clear(); }
/// <summary> /// Execute all registered event with specific code id in the dictionary. /// </summary> /// <param name="eventArgs">The event data containing the packet in a parsed format.</param> /// <param name="id">The id of the event to execute.</param> /// <exception cref="System.Exception" /> private void ExecuteEventsWithId(NetworkEventArgs eventArgs, int id) { //Check to see if we have any registered events for that event id. if (_registeredEvents.ContainsKey(id)) //Run all registered events in order. for (int i = 0; i < _registeredEvents[id].Count; i++) { //Check to see if we have a dispatcher that we can use to run the event //in a threadsafe enviroment if (_dispatcher != null) _dispatcher.Invoke((delegateEmpty)delegate { ExecuteEvent(_registeredEvents[id][i], eventArgs); }); //Since we don't have a dispacher we check to see if we are allowed to ignoer it. else if (_ignoreDispatcher) //We are allowed to ignore the dispatcher. This will run the event directly in //an unsafe multithread form. The programmer will have to take care of all the locks //and such. ExecuteEvent(_registeredEvents[id][i], eventArgs); else //Throw an exception on the fact that dispatcher had not been properly //assigned. ThrowOnExceptionOccured(this, new Exception("Dispatcher had not been specified and ignoring it was disabled")); if (_disposed || eventArgs.Handled) return; } }
protected void NewChat(object source, NetworkEventArgs args) { string text = args.Data as string; for (int i = _chat.Length - 1; i >= 0; i--) { string temp = _chat[i].Text; _chat[i].Text = text; text = temp; _chat[i].Draw(); } args.Forward(); }
/// <summary> /// Execute all registerd events for a specific packet code. /// </summary> /// <param name="packet">The source packet to send to the events.</param> private void ExecuteRegisteredEvents(NetworkPacket packet) { NetworkEventArgs args; if (_packetParsers.ContainsKey(packet.Id)) { args = _packetParsers[packet.Id].ParsePacket(packet); if (args == null) return; } else { args = new NetworkEventArgs(packet); if (packet.Message != null) { try { args.Data = new Serialiser().Deserialise(packet.Message); } catch (Exception e) { ThrowOnExceptionOccured(packet, e); return; } } else args.Data = null; } ExecuteEventsWithId(args, (int)CorePacketCode.PreviewPacket); if (packet.Id == (int)CorePacketCode.PropertyUpdated) ExecuteEventsWithId(args, (int)CorePacketCode.PreviewPropertyUpdated); if (packet.Id == (int)CorePacketCode.CollectionChanged) ExecuteEventsWithId(args, (int)CorePacketCode.PreviewCollectionChanged); ExecuteEventsWithId(args, packet.Id); }
protected void PlayerDisconnected(object source, NetworkEventArgs args) { Player p = args.Data as Player; for (int i = 0; i < _game.Players.Length; i++) if (_game.Players[i] == p) { _game.Players[i] = null; break; } if (_active) UpdatePlayers(); }
/// <summary> /// Parse an incoming string from an incoming packet and return a specialised NetworkEventArgs containg property changed information. /// </summary> /// <param name="item">The packet to parse.</param> /// <returns>Specialised NetworkEventArgs.</returns> public NetworkEventArgs ParsePacket(NetworkPacket packet) { //Split the message into maximum 3 parts because of the property changed packet format: //networkid:property_name:value string[] data = packet.Message.Split(new char[] { ':' }, 3); //Create the holder for our results. NetworkEventArgs result = new NetworkEventArgs(packet); //Make sure the message was correct. if (data.Length == 3) { INetworkDataHandler dataHandler = ObjectFactory.GetInstance<INetworkDataHandler>(); //Check to see if we have the object that had it's property changed. if (dataHandler.RegisteredObjects.ContainsKey(data[0])) { //We have the object so now we extract the information we want from the packet. result.NetworkDataId = data[0]; result.PropertyName = data[1]; try { //Deserialise the property value. result.Data = new Serialiser().Deserialise(data[2]); //Return our results. return result; } catch (Exception e) { //We received a valid packet but encountered an error while deserialising. //We pass this on as a warning. if (OnWarningOccured != null) OnWarningOccured(packet, new Warning(string.Format("Error while deserialising a property changed packet. Error message received: {0}.", e.Message), e)); } } else if (OnNotificationOccured != null) OnNotificationOccured(packet, string.Format("Error while processing an incoming property changed packet. Network object name of '{0}' was not found in the collection", data[0])); } else if (OnNotificationOccured != null) OnNotificationOccured(packet, "Property updated was not in a correct format. Acepting a message in format of 'name:property:value'"); //If we ever get here it means we encountered an error. We therefore return a null value. return null; }
protected void UpdateGameSettings(object source, NetworkEventArgs args) { lock (_menuSettings) { bool changed = false; (_menuSettings.Options[1] as OptionValue).Content = "<none>"; if (_game.Map != null) if (!string.IsNullOrEmpty(_game.Map.Description)) if ((_menuSettings.Options[1] as OptionValue).Content != _game.Map.Description) { (_menuSettings.Options[1] as OptionValue).Content = _game.Map.Description; changed = true; } if ((_menuSettings.Options[0] as OptionNumeric).Value != _game.DefaultHealth) { (_menuSettings.Options[0] as OptionNumeric).Value = _game.DefaultHealth; changed = true; } if (changed) _menuSettings.ReDraw(); } }
/// <summary> /// Parse an incoming string from an incoming packet and return a specialised NetworkEventArgs. /// </summary> /// <param name="item">The packet to parse.</param> /// <returns>Specialised NetworkEventArgs.</returns> public NetworkEventArgs ParsePacket(NetworkPacket packet) { //Split the message into maximum 6 parts so we can extract it's data. The format is as follows: //networkid:collectionChangedAction:startingIndexForNewItems:startingIndexForOldItems:ListOfItemsRemovedOrAdded string[] data = packet.Message.Split(new char[] { ':' }, 6); //Make sure the maximum length was archieved. if (data.Length == 6) { //Get the data handler. INetworkDataHandler dataHandler = ObjectFactory.GetInstance<INetworkDataHandler>(); //Make sure we have the item whose collection was changed. if (dataHandler.RegisteredObjects.ContainsKey(data[0])) { //Create the holder for our results. NetworkEventArgs result = new NetworkEventArgs(packet); //Assign the relevant values. result.NetworkDataId = data[0]; IList itemList; int newIndex, oldIndex, oldCount, intAction; try { //Deserialise and convert the data to it's correct form. itemList = new Serialiser().Deserialise(data[5]) as IList; intAction = Convert.ToInt32(data[1]); newIndex = Convert.ToInt32(data[2]); oldIndex = Convert.ToInt32(data[3]); oldCount = Convert.ToInt32(data[4]); } catch (Exception e) { if (OnWarningOccured != null) OnWarningOccured(packet, new Warning("An unknown error occured while deserialising a collection changed packet that was received. Message received: " + e.Message, e)); return null; } NotifyCollectionChangedAction action = (NotifyCollectionChangedAction)intAction; //Create a new instance of notify collection changed that contains the relevant //information about the changes in the collection. switch (action) { case NotifyCollectionChangedAction.Add: result.Data = new NotifyCollectionChangedEventArgs(action, itemList, newIndex); break; case NotifyCollectionChangedAction.Move: result.Data = new NotifyCollectionChangedEventArgs(action, itemList, newIndex, oldIndex); break; case NotifyCollectionChangedAction.Remove: result.Data = new NotifyCollectionChangedEventArgs(action, itemList, oldIndex); break; case NotifyCollectionChangedAction.Replace: result.Data = new NotifyCollectionChangedEventArgs(action, itemList, new bool[oldCount], newIndex); break; case NotifyCollectionChangedAction.Reset: result.Data = new NotifyCollectionChangedEventArgs(action); break; } //Return our results. return result; } else if (OnNotificationOccured != null) OnNotificationOccured(packet, string.Format("Collection changed parser was called but the network id of '{0}' was not found in the registered objects.", data[0])); } else if (OnNotificationOccured != null) OnNotificationOccured(packet, "Collection changed packet was not in a correct format. Acepting a message in format of 'name:newstartindex:oldstartindex:value'"); //If we ever get here it means we encountered an error. We therefore return a null value. return null; }