/// <summary> /// Private method used by all gets that handles getting a parameter. /// Note that if a parameter is not defined, the default for that type is returned /// </summary> /// <typeparam name="T">The type of the parameter to get</typeparam> /// <param name="name">The name of the parameter to get</param> /// <param name="serverSide">True if this parameter should be NOT syncronized with peers</param> private T GetValueInternal <T>(string name, bool serverSide = false) { // If we have that parameter, then get it if (myParameters.ContainsKey(name)) { // Get the object value object value = myParameters[name].RawValue; // Verify type before returning if (value == null) { return(default(T)); } else if (typeof(T).IsAssignableFrom(value.GetType())) { return((T)value); } else if (Utils.CanChangeType(value, typeof(T))) { return((T)Convert.ChangeType(value, typeof(T))); } else { throw new InvalidCastException(string.Format("Cannot cast {0} to {1}", value.GetType().Name, typeof(T).Name)); } } // Otherwise make a default one else { // Add and return a default parameter of type T myParameters.Add(name, StateParameter.Construct(name, default(T), !serverSide)); return(myParameters[name].GetValueInternal <T>()); } }
/// <summary> /// Decodes a state parameter from the message, using a game state /// to update /// </summary> /// <param name="msg">The message to decode from</param> /// <param name="state">The game state to update</param> /// <returns>The state parameter loaded from the message</returns> public static StateParameter Decode(NetIncomingMessage msg, GameState state) { // Read the name and type string name = msg.ReadString(); Type type = (Type)msg.ReadByte(); // Get result from state StateParameter result = null; switch (type) { case Type.Byte: result = state.GetParameter <byte>(name); break; case Type.Char: result = state.GetParameter <char>(name); break; case Type.Short: result = state.GetParameter <short>(name); break; case Type.Int: result = state.GetParameter <int>(name); break; case Type.Bool: result = state.GetParameter <bool>(name); break; case Type.CardSuit: result = state.GetParameter <CardSuit>(name); break; case Type.CardRank: result = state.GetParameter <CardRank>(name); break; case Type.String: result = state.GetParameter <String>(name); break; case Type.PlayingCard: result = state.GetParameter <PlayingCard>(name); break; case Type.CardCollection: result = state.GetParameter <CardCollection>(name); break; } // Decode the value result.DecodeInternal(msg); state.InvokeUpdated(result); // Return the result return(result); }
/// <summary> /// Decodes this game state from the given message /// </summary> /// <param name="msg">the message to read from</param> public void Decode(NetIncomingMessage msg) { // Read the number of parameters int numParams = msg.ReadInt32(); // Read each parameter for (int index = 0; index < numParams; index++) { StateParameter.Decode(msg, this); } }
/// <summary> /// Updates a state parameter in this game state /// </summary> /// <param name="parameter"></param> public void UpdateParam(StateParameter parameter) { if (myParameters.ContainsKey(parameter.Name)) { InternalSet(parameter.Name, parameter.RawValue, !parameter.IsSynced); } else { myParameters.Add(parameter.Name, parameter); } }
/// <summary> /// Gets the state parameter with the given name /// </summary> /// <param name="name">The name of the parameter</param> /// <param name="serverSide">Whether or not this game state is not syncronized</param> /// <returns>The parameter with the given name</returns> public StateParameter GetParameter <T>(string name, bool serverSide = false) { // If we don't have that parameter, make it if (!myParameters.ContainsKey(name)) { myParameters.Add(name, StateParameter.Construct <T>(name, (T)Activator.CreateInstance(typeof(T)), serverSide)); } // Get the parameter return(myParameters[name]); }
/// <summary> /// Constructs a new state parameter of the given type /// </summary> /// <typeparam name="T">The type of parameter to create</typeparam> /// <param name="name">The name of the parameter</param> /// <param name="value">The value of the parameter</param> /// <param name="syncronize">True if this parameter should be syncronized across all peers</param> public static StateParameter Construct <T>(string name, T value, bool syncronize) { StateParameter result = new StateParameter(); result.myName = name; result.myType = SUPPORTED_TYPES[typeof(T)]; result.myValue = value; result.IsSynced = syncronize; return(result); }
/// <summary> /// Private method used by all sets that handles setting a parameter /// </summary> /// <typeparam name="T">The type of the parameter to set</typeparam> /// <param name="name">The name of the parameter to set</param> /// <param name="value">The value to set</param> /// <param name="serverSide">True if this parameter should be NOT syncronized with peers</param> private void InternalSet <T>(string name, T value, bool serverSide) { // If the parameter does not exist, add it, otherwise update it if (!myParameters.ContainsKey(name)) { myParameters.Add(name, StateParameter.Construct(name, value, !serverSide)); } else { myParameters[name].SetValueInternal(value); } InvokeUpdated(myParameters[name]); }
/// <summary> /// Invokes the updated parameter event with the given paramater /// </summary> /// <param name="stateParameter">The parameter that has been updated</param> internal void InvokeUpdated(StateParameter stateParameter) { // if the parameter is not null if (stateParameter != null) { // if we are not in silent sets mode and we have a state changed event, invoke it if (!SilentSets && OnStateChanged != null) { OnStateChanged(this, stateParameter); } // If we have an un-silencable event listening on changes, invoke it if (OnStateChangedUnSilenceable != null) { OnStateChangedUnSilenceable(this, stateParameter); } // If we have a changed listener on the parameters name, invoke it if (myChangedEvents.ContainsKey(stateParameter.Name)) { myChangedEvents[stateParameter.Name](this, stateParameter); } else { // Here we check to see if we have any array listeners string name = myChangedEvents.Keys.FirstOrDefault(X => stateParameter.Name.Substring(1, stateParameter.Name.Length - 1) == X); // If we found one, invoke that shit if (name != null) { myChangedEvents[name](this, stateParameter); } } // Get the key from the parameter name Tuple <string, object> key = myStateEqualsEvents.Keys.FirstOrDefault(X => X.Item1 == stateParameter.Name); // If we have a listener, invoke it if (key != null && stateParameter.RawValue.Equals(key.Item2)) { myStateEqualsEvents[key](this, stateParameter); } } }