Advertisement
maxkhl

nClient.cs

Aug 10th, 2015
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 30.07 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Concurrent;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using Lidgren.Network;
  8. using OutpostOmega.Network;
  9. using OutpostOmega.Data;
  10. using OutpostOmega.Game;
  11. using System.Reflection;
  12.  
  13. namespace OutpostOmega.Network
  14. {
  15.     /// <summary>
  16.     /// Client for handling networkstuff on the gameclient
  17.     /// </summary>
  18.     public class nClient : IDisposable
  19.     {
  20.         /// <summary>
  21.         /// Lidgren netClient object
  22.         /// </summary>
  23.         public NetClient netClient { get; set; }
  24.        
  25.         private uint s_timeInitialized = (uint)Environment.TickCount;
  26.  
  27.         public double Clock
  28.         {
  29.             get
  30.             {
  31.                 return this.netClient.Connections[0].GetRemoteTime(NetTime.Now);
  32.                 //return (double)((uint)Environment.TickCount - s_timeInitialized) / 1000.0;
  33.             }
  34.         }
  35.  
  36.         private struct TimedObjectState
  37.         {
  38.             public double Time { get; set; }
  39.             public object Instance { get; set; }
  40.         }
  41.  
  42.         /// <summary>
  43.         /// Contains historical data about properties with enabled client-prediction
  44.         /// </summary>
  45.         private ConcurrentDictionary<object, ConcurrentDictionary<PropertyInfo, ConcurrentQueue<TimedObjectState>>> PredictionData = new ConcurrentDictionary<object, ConcurrentDictionary<PropertyInfo, ConcurrentQueue<TimedObjectState>>>();
  46.  
  47.         /// <summary>
  48.         /// Username of the client
  49.         /// </summary>
  50.         public string Username { get; set; }
  51.  
  52.         /// <summary>
  53.         /// The World this UClient is working with. Can return null if none got transmitted
  54.         /// </summary>
  55.         public World World
  56.         {
  57.             get
  58.             {
  59.                 return _World;
  60.             }
  61.             set
  62.             {
  63.                 if (NewWorldReceived != null)
  64.                     NewWorldReceived(_World, value);
  65.  
  66.                 Output.Enqueue("World '" + value.ID + "' received!");
  67.                 _World = value;
  68.             }
  69.         }
  70.         private World _World = null;
  71.  
  72.  
  73.         public delegate void NewWorldReceivedHandler(World oldWorld, World newWorld);
  74.         public event NewWorldReceivedHandler NewWorldReceived;
  75.  
  76.         public delegate void DisconnectedHandler(nClient sender, string reason);
  77.         public event DisconnectedHandler Disconnected;
  78.  
  79.         /// <summary>
  80.         /// Output queue that stores all the debug/error/warning/status messages (Threadsafe - use TryDequeue)
  81.         /// </summary>
  82.         public NetQueue<string> Output { get; set; }
  83.                
  84.         /// <summary>
  85.         /// Used to determine if there is an active connection to a server. Can be set to false to disconnect. Error when set to true - use Connect()
  86.         /// </summary>
  87.         public bool Online
  88.         {
  89.             get
  90.             {
  91.                 return _Online;
  92.             }
  93.             set
  94.             {
  95.                 if(value)
  96.                     throw new Exception("Please use the Connect()-method to start a connection");
  97.                 else
  98.                     Disconnect();
  99.             }
  100.         }
  101.         private bool _Online = false;
  102.  
  103.         /// <summary>
  104.         /// Constructor. This wont start the communication. Use Connect to connect to a server.
  105.         /// </summary>
  106.         /// <param name="Username"></param>
  107.         public nClient(string Username)
  108.         {
  109.             this.Username = Username;
  110.  
  111.             Output = new NetQueue<string>(100);
  112.  
  113.             if (SynchronizationContext.Current == null)
  114.                 SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
  115.  
  116.             //Establish Connection
  117.             NetPeerConfiguration config = new NetPeerConfiguration("pspace_network");
  118.             config.SimulatedMinimumLatency = 0;
  119.             config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
  120.             netClient = new NetClient(config);
  121.  
  122.             netClient.RegisterReceivedCallback(new SendOrPostCallback(MessageReceived));
  123.  
  124.             ThreadPool.QueueUserWorkItem(new WaitCallback(CalculatePPS));
  125.         }
  126.  
  127.         public void CalculatePPS(object state)
  128.         {
  129.             while (!Disposing)
  130.             {
  131.                 if (DateTime.Now.Subtract(PacketTime).Seconds > 1)
  132.                 {
  133.                     PacketsPerSecond = PacketCounter;
  134.                     PacketCounter = 0;
  135.                     PacketTime = DateTime.Now;
  136.                 }
  137.                 Thread.Sleep(1);
  138.             }
  139.         }
  140.  
  141.         /// <summary>
  142.         /// Tries to connect to the given server. Returns false if connection is already going on. Check 'Online' to see if the client is connected
  143.         /// </summary>
  144.         /// <param name="ServerAdress">Target Serveradress</param>
  145.         /// <param name="ServerPort">Target Port</param>
  146.         /// <returns>True = Initial connection</returns>
  147.         public bool Connect(string ServerAdress, int ServerPort)
  148.         {
  149.  
  150.  
  151.             if( netClient.ConnectionStatus == NetConnectionStatus.None ||
  152.                 netClient.ConnectionStatus == NetConnectionStatus.Disconnected)
  153.             {
  154.                 netClient.Start();
  155.                 var approval = netClient.CreateMessage();
  156.                 approval.Write(Username);
  157.  
  158.                 NetConnection connection = netClient.Connect(ServerAdress, ServerPort, approval);
  159.                 Output.Enqueue("Connecting to " + ServerAdress + ":" + ServerPort.ToString());
  160.                 return true;
  161.             }
  162.             else
  163.                 return false;
  164.         }
  165.  
  166.         /// <summary>
  167.         /// Used to disconnect this client
  168.         /// </summary>
  169.         /// <param name="Reason">Reason for disconnect</param>
  170.         public void Disconnect(string Reason = "Requested by user")
  171.         {
  172.             if (netClient.ConnectionStatus == NetConnectionStatus.Connected)
  173.             {
  174.                 netClient.Disconnect(Reason);
  175.  
  176.                 // Fire Dc Event
  177.                 if (Disconnected != null)
  178.                     Disconnected(this, Reason);
  179.             }
  180.             _Online = false;
  181.         }
  182.  
  183.         /// <summary>
  184.         /// Returns a new NetOutgoingMessage with an assigned Type for this Client. Messages have to contain a type!
  185.         /// </summary>
  186.         /// <param name="Type">Type of the command.</param>
  187.         /// <param name="SecondType">Second command of the package.</param>
  188.         /// <returns>new NetOutgoingMessage</returns>
  189.         public NetOutgoingMessage GetOM(Command Type, SecondCommand SecondType = SecondCommand.Null)
  190.         {
  191.             var om = netClient.CreateMessage();
  192.             om.Write((byte)Type);
  193.             om.Write((byte)SecondType);
  194.             return om;
  195.         }
  196.  
  197.         /// <summary>
  198.         /// Called when the server sends a message
  199.         /// </summary>
  200.         private void MessageReceived(object peer)
  201.         {
  202.             NetIncomingMessage im;
  203.             while (netClient != null && (im = netClient.ReadMessage()) != null)
  204.             {
  205.                 switch (im.MessageType)
  206.                 {
  207.                     case NetIncomingMessageType.DebugMessage:
  208.                     case NetIncomingMessageType.ErrorMessage:
  209.                     case NetIncomingMessageType.WarningMessage:
  210.                     case NetIncomingMessageType.VerboseDebugMessage:
  211.                         string text = im.ReadString();
  212.                         Output.Enqueue(text);
  213.                         break;
  214.                     case NetIncomingMessageType.StatusChanged:
  215.                         NetConnectionStatus status = (NetConnectionStatus)im.ReadByte();
  216.                         if (status == NetConnectionStatus.Connected)
  217.                         {
  218.                             string adress = im.SenderConnection.RemoteEndPoint.Address.ToString();
  219.                             _Online = true;
  220.                             Output.Enqueue("Connected to " + adress);
  221.                             Output.Enqueue("Average roundtrip time is " + im.SenderConnection.AverageRoundtripTime.ToString() + " seconds");
  222.                             Output.Enqueue("Connection status is " + im.SenderConnection.Status.ToString());
  223.                             Output.Enqueue("Logged in as " + Username);
  224.                         }
  225.                         else if (status == NetConnectionStatus.Disconnected)
  226.                         {
  227.                             string Reason = im.ReadString();
  228.                             Output.Enqueue("Disconnected with reason '" + Reason + "'");
  229.  
  230.                             // Fire Dc Event
  231.                             if (Disconnected != null)
  232.                                 Disconnected(this, Reason);
  233.  
  234.                             _Online = false;
  235.                         }
  236.                         break;
  237.                     // Application data
  238.                     case NetIncomingMessageType.Data:
  239.                         AddPackage(im);
  240.                        
  241.                         break;
  242.                     default:
  243.                         string pmsg = im.ReadString();
  244.                         Output.Enqueue("Unknown messagetype '" + im.MessageType.ToString() + "' (" + pmsg + ")");
  245.                         break;
  246.  
  247.                 }
  248.             }
  249.         }
  250.  
  251.         private void WatchPredictionProperties(GameObject gameObject)
  252.         {
  253.             if (PredictionData.ContainsKey(gameObject)) return;
  254.  
  255.             bool NeedsPrediction = false;
  256.  
  257.             foreach(var prop in gameObject.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
  258.             {
  259.                 var attrib = prop.GetCustomAttribute(typeof(OutpostOmega.Game.GameObjects.Attributes.SynchronizationAttr), true);
  260.                 if(attrib != null)
  261.                 {
  262.                     var netAttrib = (OutpostOmega.Game.GameObjects.Attributes.SynchronizationAttr)attrib;
  263.  
  264.                     if(netAttrib.State == Game.GameObjects.Attributes.SynchronizeState.Prediction)
  265.                     {
  266.                         // Build prediction dictionary
  267.                         if (!PredictionData.ContainsKey(gameObject))
  268.                         {
  269.                             if(!PredictionData.TryAdd(gameObject, new ConcurrentDictionary<PropertyInfo,ConcurrentQueue<TimedObjectState>>()))
  270.                                 throw new Exception("Shouldn't happen.. mhm");
  271.                             if(!PredictionData[gameObject].TryAdd(prop, new ConcurrentQueue<TimedObjectState>()))
  272.                                 throw new Exception("Shouldn't happen.. mhm");
  273.                         }
  274.  
  275.                         NeedsPrediction = true;
  276.                     }
  277.                 }
  278.             }
  279.             if(NeedsPrediction)
  280.                 gameObject.PropertyChanged += gameObject_PropertyChanged;
  281.         }
  282.  
  283.         void gameObject_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
  284.         {
  285.             //return;
  286.             if(PredictionData.ContainsKey(sender))
  287.             {
  288.                 var property = sender.GetType().GetProperty(e.PropertyName);
  289.  
  290.                 if (!PredictionData.ContainsKey(sender)) return;
  291.                 if (!PredictionData[sender].ContainsKey(property)) return;
  292.  
  293.                 var states = PredictionData[sender][property].ToArray();
  294.  
  295.                 object delta = null;
  296.                 if(states.Length == 0)
  297.                     delta = GetDelta(property.GetValue(sender), property.GetValue(sender));
  298.                 else
  299.                     delta = GetDelta(states[states.Length-1].Instance, property.GetValue(sender));
  300.  
  301.                 if (delta == null)
  302.                     return;
  303.                    
  304.                 // Add new prediction step
  305.                 PredictionData[sender][property].Enqueue(new TimedObjectState()
  306.                 {
  307.                     Time = Clock,
  308.                     Instance = delta
  309.                 });
  310.  
  311.                 //Clean up old data
  312.                 TimedObjectState oldestState;
  313.                 while (PredictionData[sender][property].TryPeek(out oldestState) && oldestState.Time - Clock < 1) // We buffer max. 1 second
  314.                 {
  315.                     PredictionData[sender][property].TryDequeue(out oldestState); // Dequeue it and ignore it because its too old
  316.                 }
  317.             }
  318.         }
  319.  
  320.         private void ModifyPredictedValue(object Instance, PropertyInfo Property, double Time, ref object Value)
  321.         {
  322.             if (!PredictionData.ContainsKey(Instance)) return;
  323.             if (!PredictionData[Instance].ContainsKey(Property)) return;
  324.  
  325.             //Clean up data older then the current package
  326.             TimedObjectState oldestState;
  327.             while (PredictionData[Instance][Property].TryPeek(out oldestState) && oldestState.Time < Time)
  328.             {
  329.                 PredictionData[Instance][Property].TryDequeue(out oldestState); // Dequeue it and ignore it because its too old
  330.             }
  331.  
  332.             if(PredictionData[Instance][Property].TryPeek(out oldestState))
  333.                 if(oldestState.Time - Time > 1)
  334.                 {
  335.  
  336.                 }
  337.  
  338.  
  339.  
  340.             /*// Find closest historical entry for that specific property
  341.             List<TimedObjectState> PropData;
  342.             if(PredictionData[Instance][Property].Count > 0)
  343.                 PropData = PredictionData[Instance][Property].ToList();
  344.             else
  345.                 PropData = new List<TimedObjectState>();
  346.  
  347.             var result = PropData.Select(p => new { Value = p, Difference = Math.Abs(p.Time - Time) })
  348.                 .OrderBy(p => p.Difference)
  349.                 .FirstOrDefault();
  350.  
  351.             if(result != null)
  352.             {
  353.                 var ClosestData = result.Value;
  354.                 var Index = PropData.IndexOf(ClosestData);
  355.  
  356.                 for (int i = 0; i < PredictionData[Instance][Property].Count; i++)
  357.                 {
  358.                     if (i <= Index)
  359.                         PredictionData[Instance][Property].RemoveAt(i); // Delete values, older then the last server message
  360.                     if (i > Index)
  361.                         Value = Add(Value, PropData[i]);
  362.                 }
  363.             }*/
  364.         }
  365.  
  366.         private NetQueue<NetIncomingMessage> _packetQueue = new NetQueue<NetIncomingMessage>(25);
  367.         private Thread _processThread;
  368.  
  369.         private void AddPackage(NetIncomingMessage im)
  370.         {
  371.             if (_processThread == null ||
  372.                 _processThread.ThreadState != ThreadState.Running)
  373.             {
  374.                 _processThread = new Thread(ProcessPackage);
  375.                 _processThread.Priority = ThreadPriority.Lowest;
  376.                 //Output.Enqueue("Processthread started");
  377.             }
  378.  
  379.             _packetQueue.Enqueue(im);
  380.  
  381.             if (_processThread.ThreadState == ThreadState.Unstarted)
  382.             {
  383.                 try
  384.                 {
  385.                     _processThread.Start();
  386.                 }
  387.                 catch { }
  388.             }
  389.         }
  390.  
  391.         private List<GameObject> _unprocessedObjects = new List<GameObject>();
  392.  
  393.  
  394.         public long PacketsPerSecond { get; private set; }
  395.         private long PacketCounter { get; set; }
  396.  
  397.         private DateTime PacketTime = DateTime.Now;
  398.  
  399.         /// <summary>
  400.         /// Used to process the im queue
  401.         /// </summary>
  402.         public void ProcessPackage()
  403.         {
  404.             NetIncomingMessage im;
  405.             while (_packetQueue.Count > 0 && !Disposing)
  406.             {
  407.                 if (_packetQueue.TryDequeue(out im))
  408.                 {
  409.                     if (im == null)
  410.                         continue;
  411.  
  412.                     var Type = im.ReadByte();
  413.                     var subType = im.ReadByte();
  414.                     switch (Type)
  415.                     {
  416.                         case (byte)Command.Create: // New object received
  417.                             object obj = null;
  418. #if DEBUG
  419.                             obj = NetworkHandler.ReadSerializedData(im.ReadBytes(im.ReadInt32()));
  420. #else
  421.                             try
  422.                             {
  423.                                 obj = NetworkHandler.ReadSerializedData(im.ReadBytes(im.ReadInt32()));
  424.                             }
  425.                             catch (Exception e)
  426.                             {
  427.                                 Output.Enqueue("ERROR: " + e.Message + e.Source);
  428.                             }
  429. #endif
  430.                             if (obj == null)
  431. #if DEBUG
  432.                                 throw new Exception("Could not serialize that shit");
  433. #else
  434.                                 Output.Enqueue("ERROR: New object received but unable to read it");
  435. #endif
  436.  
  437.                             // World
  438.                             if(obj.GetType() == typeof(World))
  439.                             {
  440.                                 this.World = (World)obj;
  441.                                 foreach (GameObject gO in _unprocessedObjects)
  442.                                     this.World.Add(gO);
  443.                                 _unprocessedObjects.Clear();
  444.  
  445.                                 foreach(var gameObject in this.World.AllGameObjects)
  446.                                     WatchPredictionProperties(gameObject);
  447.                             }
  448.  
  449.                             // Gameobjects
  450.                             if(obj.GetType().IsSubclassOf(typeof(GameObject)))
  451.                             {
  452.                                 if (this.World != null)
  453.                                     this.World.Add((GameObject)obj);
  454.                                 else
  455.                                     _unprocessedObjects.Add((GameObject)obj);
  456.  
  457.                                 //WatchPredictionProperties((GameObject)obj);
  458.                             }
  459.                             break;
  460.                         case (byte)Command.Delete:
  461.                             string id = im.ReadString();
  462.                             var delobject = (from gobject in World.AllGameObjects
  463.                                              where gobject.ID == id
  464.                                              select gobject).FirstOrDefault();
  465.                             if (delobject != null)
  466.                                 delobject.Dispose();
  467.  
  468.                             break;
  469.                         // Data update
  470.                         case (byte)Command.Data:
  471.                             switch(subType)
  472.                             {
  473.                                 case (byte)SecondCommand.GameObject:
  474.                                     if (World != null)
  475.                                     {
  476.                                         var gameObject_ID = im.ReadString();
  477.                                         var property_name = im.ReadString();
  478.                                         if (property_name == "TargetGameObject")
  479.                                         { }
  480.  
  481.                                         var gameObject = World.GetGameObject(gameObject_ID);
  482.                                         System.Reflection.PropertyInfo property = null;
  483.                                         if (gameObject != null)
  484.                                             property = gameObject.GetType().GetProperty(property_name);
  485.  
  486.  
  487.                                         if (property == null)
  488.                                             return; //Nothing to do then
  489.                                        
  490.  
  491.                                         bool Predict = false;
  492.                                         double SendTime = 0;
  493.                                         var attribute = property.GetCustomAttribute(typeof(OutpostOmega.Game.GameObjects.Attributes.SynchronizationAttr), true);
  494.                                         if (attribute != null && ((OutpostOmega.Game.GameObjects.Attributes.SynchronizationAttr)attribute).State == Game.GameObjects.Attributes.SynchronizeState.Prediction)
  495.                                         {
  496.                                             SendTime = im.ReadDouble();
  497.                                             Predict = true;
  498.                                         }
  499.  
  500.  
  501.                                         object new_value;
  502.                                         if (!SpecialDeserialize(im, property, out new_value))
  503.                                         {
  504.                                             var data = im.ReadBytes(im.ReadInt32());
  505.                                             new_value = NetworkHandler.ReadSerializedData(data);
  506.                                         }
  507.  
  508.  
  509.                                         object oldvalue = null;
  510.                                         if (gameObject != null)
  511.                                         {
  512.                                             oldvalue = property.GetValue(gameObject);
  513.                                             /*if (Predict)
  514.                                                 ModifyPredictedValue(gameObject, property, SendTime, ref new_value);*/
  515.  
  516.  
  517.                                             property.SetValue(gameObject, new_value, null);
  518.                                         }
  519.                                     }
  520.  
  521.                                     break;
  522.                             }
  523.                             break;
  524.                         case (byte)Command.Message: // Message
  525.                             var message = im.ReadString();
  526.                             Output.Enqueue("Message from Server: " + message);
  527.                             break;
  528.                         default:                            
  529.                             Output.Enqueue("Unknown command received. Type: " + Type.ToString() + " Subtype: " + subType.ToString());
  530.                             break;
  531.                     }
  532.                 }
  533.  
  534.                 PacketCounter++;
  535.                 Thread.Sleep(1);
  536.             }
  537.         }
  538.  
  539.         public bool Disposing = false;
  540.         public void Dispose()
  541.         {
  542.             Disposing = true;
  543.             this.Disconnect("Client closing");
  544.             _packetQueue.Clear();
  545.             PredictionData.Clear();
  546.             Output.Clear();
  547.         }
  548.          /// <summary>
  549.         /// Optimized way of transfering very basic objects. Everything else gets handled by the default compressed xml serialization
  550.         /// </summary>
  551.         private static bool SpecialDeserialize(Lidgren.Network.NetIncomingMessage im, System.Reflection.PropertyInfo property, out object data)
  552.         {
  553.             data = null;
  554.             if(property.PropertyType == typeof(Jitter.LinearMath.JMatrix))
  555.                         data = new Jitter.LinearMath.JMatrix()
  556.                         {
  557.                             M11 = im.ReadFloat(),
  558.                             M12 = im.ReadFloat(),
  559.                             M13 = im.ReadFloat(),
  560.  
  561.                             M21 = im.ReadFloat(),
  562.                             M22 = im.ReadFloat(),
  563.                             M23 = im.ReadFloat(),
  564.  
  565.                             M31 = im.ReadFloat(),
  566.                             M32 = im.ReadFloat(),
  567.                             M33 = im.ReadFloat()
  568.                         };
  569.  
  570.             if(property.PropertyType == typeof(Jitter.LinearMath.JVector))
  571.                         data = new Jitter.LinearMath.JVector()
  572.                         {
  573.                             X = im.ReadFloat(),
  574.                             Y = im.ReadFloat(),
  575.                             Z = im.ReadFloat(),
  576.                         };
  577.  
  578.             if(property.PropertyType == typeof(Jitter.LinearMath.JVector2))
  579.                         data = new Jitter.LinearMath.JVector2()
  580.                         {
  581.                             X = im.ReadFloat(),
  582.                             Y = im.ReadFloat(),
  583.                         };
  584.            
  585.             if(property.PropertyType == typeof(string))
  586.                         data = im.ReadString();
  587.             if(property.PropertyType == typeof(short))
  588.                         data = im.ReadInt16();
  589.             if(property.PropertyType == typeof(int))
  590.                         data = im.ReadInt32();
  591.             if(property.PropertyType == typeof(long))
  592.                         data = im.ReadInt64();
  593.             if(property.PropertyType == typeof(bool))
  594.                         data = im.ReadBoolean();
  595.             if(property.PropertyType == typeof(double))
  596.                         data = im.ReadDouble();
  597.             if(property.PropertyType == typeof(float))
  598.                         data = im.ReadFloat();
  599.  
  600.             if (data == null)
  601.                 return false;
  602.             else
  603.                 return true;
  604.         }
  605.  
  606.         /// <summary>
  607.         /// Tries to compute a delta out of two unknown objects
  608.         /// </summary>
  609.         private static object GetDelta(object oldValue, object newValue)
  610.         {
  611.             if (oldValue == null)
  612.                 return newValue;
  613.  
  614.             if (oldValue == null || newValue == null ||
  615.                 oldValue.GetType() != newValue.GetType()) return null;
  616.  
  617.  
  618.             object Delta = null;
  619.  
  620.             var Type = oldValue.GetType();
  621.  
  622.             if (Type == typeof(float))
  623.                 Delta = (float)newValue - (float)oldValue;
  624.             else if (Type == typeof(decimal))
  625.                 Delta = (decimal)newValue - (decimal)oldValue;
  626.             else if (Type == typeof(short))
  627.                 Delta = (short)newValue - (short)oldValue;
  628.             else if (Type == typeof(int))
  629.                 Delta = (int)newValue - (int)oldValue;
  630.             else if (Type == typeof(long))
  631.                 Delta = (long)newValue - (long)oldValue;
  632.             else if (Type == typeof(Jitter.LinearMath.JVector))
  633.             {
  634.                 var oldVec = (Jitter.LinearMath.JVector)oldValue;
  635.                 var newVec = (Jitter.LinearMath.JVector)newValue;
  636.                 Delta = new Jitter.LinearMath.JVector(
  637.                     (float)GetDelta(oldVec.X, newVec.X),
  638.                     (float)GetDelta(oldVec.Y, newVec.Y),
  639.                     (float)GetDelta(oldVec.Z, newVec.Z));
  640.             }
  641.             else if (Type == typeof(Jitter.LinearMath.JVector2))
  642.             {
  643.                 var oldVec = (Jitter.LinearMath.JVector2)oldValue;
  644.                 var newVec = (Jitter.LinearMath.JVector2)newValue;
  645.                 Delta = new Jitter.LinearMath.JVector2(
  646.                     (float)GetDelta(oldVec.X, newVec.X),
  647.                     (float)GetDelta(oldVec.Y, newVec.Y));
  648.             }
  649.             else if (Type == typeof(Jitter.LinearMath.JMatrix))
  650.             {
  651.                 var oldMat = (Jitter.LinearMath.JMatrix)oldValue;
  652.                 var newMat = (Jitter.LinearMath.JMatrix)newValue;
  653.                 Delta = new Jitter.LinearMath.JMatrix()
  654.                     {
  655.                         M11 = (float)GetDelta(oldMat.M11, oldMat.M11),
  656.                         M12 = (float)GetDelta(oldMat.M12, oldMat.M12),
  657.                         M13 = (float)GetDelta(oldMat.M13, oldMat.M13),
  658.  
  659.                         M21 = (float)GetDelta(oldMat.M21, oldMat.M21),
  660.                         M22 = (float)GetDelta(oldMat.M22, oldMat.M22),
  661.                         M23 = (float)GetDelta(oldMat.M23, oldMat.M23),
  662.  
  663.                         M31 = (float)GetDelta(oldMat.M31, oldMat.M31),
  664.                         M32 = (float)GetDelta(oldMat.M32, oldMat.M32),
  665.                         M33 = (float)GetDelta(oldMat.M33, oldMat.M33),
  666.  
  667.                     };
  668.             }
  669.  
  670.  
  671.             return Delta;
  672.         }
  673.        
  674.         /// <summary>
  675.         /// Tries to compute a addition of two unknown objects
  676.         /// </summary>
  677.         private static object Add(object Value1, object Value2)
  678.         {
  679.             if (Value1 == null || Value2 == null || Value1.GetType() != Value2.GetType()) return null;
  680.  
  681.  
  682.             object NewValue = null;
  683.  
  684.             var Type = Value1.GetType();
  685.  
  686.             if (Type == typeof(float))
  687.                 NewValue = (float)Value2 + (float)Value1;
  688.             else if (Type == typeof(decimal))
  689.                 NewValue = (decimal)Value2 + (decimal)Value1;
  690.             else if (Type == typeof(short))
  691.                 NewValue = (short)Value2 + (short)Value1;
  692.             else if (Type == typeof(int))
  693.                 NewValue = (int)Value2 + (int)Value1;
  694.             else if (Type == typeof(long))
  695.                 NewValue = (long)Value2 + (long)Value1;
  696.             else if (Type == typeof(Jitter.LinearMath.JVector))
  697.             {
  698.                 var oldVec = (Jitter.LinearMath.JVector)Value1;
  699.                 var newVec = (Jitter.LinearMath.JVector)Value2;
  700.                 NewValue = new Jitter.LinearMath.JVector(
  701.                     (float)Add(oldVec.X, newVec.X),
  702.                     (float)Add(oldVec.Y, newVec.Y),
  703.                     (float)Add(oldVec.Z, newVec.Z));
  704.             }
  705.             else if (Type == typeof(Jitter.LinearMath.JVector2))
  706.             {
  707.                 var oldVec = (Jitter.LinearMath.JVector2)Value1;
  708.                 var newVec = (Jitter.LinearMath.JVector2)Value2;
  709.                 NewValue = new Jitter.LinearMath.JVector2(
  710.                     (float)Add(oldVec.X, newVec.X),
  711.                     (float)Add(oldVec.Y, newVec.Y));
  712.             }
  713.             else if (Type == typeof(Jitter.LinearMath.JMatrix))
  714.             {
  715.                 var oldMat = (Jitter.LinearMath.JMatrix)Value1;
  716.                 var newMat = (Jitter.LinearMath.JMatrix)Value2;
  717.                 NewValue = new Jitter.LinearMath.JMatrix()
  718.                 {
  719.                     M11 = (float)Add(oldMat.M11, oldMat.M11),
  720.                     M12 = (float)Add(oldMat.M12, oldMat.M12),
  721.                     M13 = (float)Add(oldMat.M13, oldMat.M13),
  722.  
  723.                     M21 = (float)Add(oldMat.M21, oldMat.M21),
  724.                     M22 = (float)Add(oldMat.M22, oldMat.M22),
  725.                     M23 = (float)Add(oldMat.M23, oldMat.M23),
  726.  
  727.                     M31 = (float)Add(oldMat.M31, oldMat.M31),
  728.                     M32 = (float)Add(oldMat.M32, oldMat.M32),
  729.                     M33 = (float)Add(oldMat.M33, oldMat.M33),
  730.  
  731.                 };
  732.             }
  733.  
  734.             return NewValue;
  735.         }
  736.     }
  737.    
  738.        
  739. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement