private void HandleClient(AuthoritativeFrameType type, Vector3 currentValue, ref Vector3 previousValue)
			{
				byte currentFrame = NetworkingManager.Instance.CurrentFrame;
				bool valueChanged = Vector3.Distance(currentValue, previousValue) > 0.01f;
				bool frameFound = false;
				switch (type)
				{
					case AuthoritativeFrameType.Position:
						if (currentFrame != _previousPosFrame || valueChanged)
						{
							if (valueChanged)
								_posTimeStamp = Time.time;

							Vector3 delta = Vector3.zero;
							Vector3 previous = previousValue;

							_previousPosFrame = currentFrame;

							if (_positionFrameHistory.Count > 0)
							{
								for (int i = _positionFrameHistory.Count - 1; i >= 0; --i)
								{
									if (_positionFrameHistory[i].Frame == currentFrame)
									{
										frameFound = true;
										_positionFrameHistory[i].FrameActualValue = currentValue;
										_positionFrameHistory[i].UpdateDelta();
										break;
									}
								}

								if (!frameFound)
								{
									delta = currentValue - _positionFrameHistory[_positionFrameHistory.Count - 1].FrameActualValue;

									previousValue = currentValue;
								}

								previous = _positionFrameHistory[_positionFrameHistory.Count - 1].FrameActualValue;
							}

							if (!frameFound)
							{
								AuthoritativeFrame tempNewFrame = new AuthoritativeFrame(currentFrame, currentValue, delta, previous);
								_positionFrameHistory.Add(tempNewFrame);
							}

							if (_positionFrameHistory.Count > byte.MaxValue)
								_positionFrameHistory.RemoveRange(0, (int)(_positionFrameHistory.Count * 0.8f));
						}
						break;
					case AuthoritativeFrameType.Rotation:
						if (currentFrame != _previousRotFrame || valueChanged)
						{
							if (valueChanged)
								_rotTimeStamp = Time.time;

							Vector3 delta = Vector3.zero;
							Vector3 previous = previousValue;

							_previousRotFrame = currentFrame;

							if (_rotationFrameHistory.Count > 0)
							{
								for (int i = _rotationFrameHistory.Count - 1; i >= 0; --i)
								{
									if (_rotationFrameHistory[i].Frame == currentFrame)
									{
										frameFound = true;
										_rotationFrameHistory[i].FrameActualValue = currentValue;
										_rotationFrameHistory[i].UpdateDelta();
										break;
									}
								}

								if (!frameFound)
								{
									delta = currentValue - _rotationFrameHistory[_rotationFrameHistory.Count - 1].FrameActualValue;

									previousValue = currentValue;
								}

								previous = _rotationFrameHistory[_rotationFrameHistory.Count - 1].FrameActualValue;
							}

							if (!frameFound)
							{
								AuthoritativeFrame tempNewFrame = new AuthoritativeFrame(currentFrame, currentValue, delta, previous);
								_rotationFrameHistory.Add(tempNewFrame);
							}

							if (_rotationFrameHistory.Count > byte.MaxValue)
								_rotationFrameHistory.RemoveRange(0, (int)(_rotationFrameHistory.Count * 0.8f));
						}
						break;
					case AuthoritativeFrameType.Scale:
						if (currentFrame != _previousScaFrame || valueChanged)
						{
							if (valueChanged)
								_scaTimeStamp = Time.time;

							Vector3 delta = Vector3.zero;
							Vector3 previous = previousValue;

							_previousScaFrame = currentFrame;

							if (_scaleFrameHistory.Count > 0)
							{
								for (int i = _scaleFrameHistory.Count - 1; i >= 0; --i)
								{
									if (_scaleFrameHistory[i].Frame == currentFrame)
									{
										frameFound = true;
										_scaleFrameHistory[i].FrameActualValue = currentValue;
										_scaleFrameHistory[i].UpdateDelta();
										break;
									}
								}

								if (!frameFound)
								{
									delta = currentValue - _scaleFrameHistory[_scaleFrameHistory.Count - 1].FrameActualValue;

									previousValue = currentValue;
								}

								previous = _scaleFrameHistory[_scaleFrameHistory.Count - 1].FrameActualValue;
							}

							if (!frameFound)
							{
								AuthoritativeFrame tempNewFrame = new AuthoritativeFrame(currentFrame, currentValue, delta, previous);
								_scaleFrameHistory.Add(tempNewFrame);
							}

							if (_scaleFrameHistory.Count > byte.MaxValue)
								_scaleFrameHistory.RemoveRange(0, (int)(_scaleFrameHistory.Count * 0.8f));
						}
						break;
				}
			}
			private Vector3 FinishFrame(NetWorker owningNetworker, AuthoritativeFrameType type, Vector3 currentValue, byte serverFrame, Vector3 serverValue)
			{
				bool frameFound = false;
				int iter = 0;
				Vector3 pos = currentValue;
				switch (type)
				{
					case AuthoritativeFrameType.Position:
						if (_posLastFrame != serverFrame)
						{
							_posLastFrame = serverFrame;
							_posTimeStamp = Time.time;
							
							if (_positionFrameHistory.Count > 0)
							{
								for (int i = _positionFrameHistory.Count - 1; i >= 0; --i)
								{
									if (_positionFrameHistory[i].Frame == serverFrame)
									{
										frameFound = true;
										iter = i;
										break;
									}
								}

								if (frameFound)
								{
									_positionFrameHistory.RemoveRange(0, iter);

									_positionFrameHistory[0].FrameActualValue = serverValue;
									_positionFrameHistory[0].FrameValue = Vector3.zero;

									if (_positionFrameHistory.Count > 1)
									{
										_positionFrameHistory[1].FramePrevious = _positionFrameHistory[0].FrameActualValue;
										_positionFrameHistory[1].UpdateDelta();
									}

									pos = serverValue;
									for (int i = 0; i < _positionFrameHistory.Count; ++i)
										pos += _positionFrameHistory[i].FrameValue; //Get the delta distance
								}
							}

							currentValue = pos;
						}
						else
						{
							if ((Time.time - _posTimeStamp) * 1000 > owningNetworker.PreviousServerPing + 100)
							{
								_posTimeStamp = Time.time;
								if (Vector3.Distance(currentValue, serverValue) > 0.1f)
								{
									currentValue = serverValue;
									_positionFrameHistory.Clear();
								}
							}
						}
						break;
					case AuthoritativeFrameType.Rotation:
						if (_rotLastFrame != serverFrame)
						{
							_rotLastFrame = serverFrame;
							_rotTimeStamp = Time.time;

							if (_rotationFrameHistory.Count > 0)
							{
								for (int i = _rotationFrameHistory.Count - 1; i >= 0; --i)
								{
									if (_rotationFrameHistory[i].Frame == serverFrame)
									{
										frameFound = true;
										iter = i;
										break;
									}
								}

								if (frameFound)
								{
									_rotationFrameHistory.RemoveRange(0, iter);

									_rotationFrameHistory[0].FrameActualValue = serverValue;
									_rotationFrameHistory[0].FrameValue = Vector3.zero;

									if (_rotationFrameHistory.Count > 1)
									{
										_rotationFrameHistory[1].FramePrevious = _rotationFrameHistory[0].FrameActualValue;
										_rotationFrameHistory[1].UpdateDelta();
									}

									pos = serverValue;
									for (int i = 0; i < _rotationFrameHistory.Count; ++i)
										pos += _rotationFrameHistory[i].FrameValue; //Get the delta distance
								}
							}

							currentValue = pos;
						}
						else
						{
							if ((Time.time - _rotTimeStamp) * 1000 > owningNetworker.PreviousServerPing + 100)
							{
								_rotTimeStamp = Time.time;
								if (Vector3.Distance(currentValue, serverValue) > 0.1f)
								{
									currentValue = serverValue;
									_rotationFrameHistory.Clear();
								}
							}
						}
						break;
					case AuthoritativeFrameType.Scale:
						if (_scaLastFrame != serverFrame)
						{
							_scaLastFrame = serverFrame;
							_scaTimeStamp = Time.time;

							if (_scaleFrameHistory.Count > 0)
							{
								for (int i = _scaleFrameHistory.Count - 1; i >= 0; --i)
								{
									if (_scaleFrameHistory[i].Frame == serverFrame)
									{
										frameFound = true;
										iter = i;
										break;
									}
								}

								if (frameFound)
								{
									_scaleFrameHistory.RemoveRange(0, iter);

									_scaleFrameHistory[0].FrameActualValue = serverValue;
									_scaleFrameHistory[0].FrameValue = Vector3.zero;

									if (_scaleFrameHistory.Count > 1)
									{
										_scaleFrameHistory[1].FramePrevious = _scaleFrameHistory[0].FrameActualValue;
										_scaleFrameHistory[1].UpdateDelta();
									}

									pos = serverValue;
									for (int i = 0; i < _scaleFrameHistory.Count; ++i)
										pos += _scaleFrameHistory[i].FrameValue; //Get the delta distance
								}
							}

							currentValue = pos;
						}
						else
						{
							if ((Time.time - _scaTimeStamp) * 1000 > owningNetworker.PreviousServerPing + 100)
							{
								_scaTimeStamp = Time.time;
								if (Vector3.Distance(currentValue, serverValue) > 0.1f)
								{
									currentValue = serverValue;
									_scaleFrameHistory.Clear();
								}
							}
						}
						break;
				}

				return currentValue;
			}
			/// <summary>
			/// Gets the updated frame of a given type, number, target value, and current value
			/// </summary>
			/// <param name="type">Type of frame we want to update</param>
			/// <param name="frameNumber">The frame number of what the server is</param>
			/// <param name="value">The target value of the server</param>
			/// <param name="currentValue">The current value of the client</param>
			/// <returns></returns>
			public Vector3 UpdateFrame(NetWorker owningNetworker, AuthoritativeFrameType type, Vector3 currentValue, byte serverFrame, Vector3 serverValue, ref Vector3 previousValue)
			{
				switch (type)
				{
					case AuthoritativeFrameType.Position:
						if (!_trackPos)
							return currentValue;
						break;
					case AuthoritativeFrameType.Rotation:
						if (!_trackRotation)
							return currentValue;
						break;
					case AuthoritativeFrameType.Scale:
						if (!_trackScale)
							return currentValue;
						break;
				}
				//ADD/UPDATE CLIENT FRAME
				HandleClient(type, currentValue, ref previousValue);
				
				return FinishFrame(owningNetworker, type, currentValue, serverFrame, serverValue);
			}