예제 #1
0
        /// <summary>
        /// Stores a value. Will not replace a stored value with an older one.
        /// </summary>
        public bool Store(T value)
        {
            int  index = this.TickToIndex(value.Tick);
            bool store = false;

            if (this.latestIdx < 0)
            {
                store = true;
            }
            else
            {
                T latest = this.data[this.latestIdx];
                if (value.Tick >= latest.Tick)
                {
                    store = true;
                }
            }

            if (store)
            {
                RailPool.SafeReplace(ref this.data[index], value);
                this.latestIdx = index;
            }
            return(store);
        }
예제 #2
0
        private void ProcessCommandUpdate(
            RailServerPeer peer,
            RailCommandUpdate update)
        {
            RailEntity entity;

            if (this.Room.TryGet(update.EntityId, out entity))
            {
                if (entity.Controller == peer)
                {
                    foreach (RailCommand command in update.Commands)
                    {
                        entity.ReceiveCommand(command);
                    }
                }
                else
                {
                    // Can't send commands to that entity, so dump them
                    foreach (RailCommand command in update.Commands)
                    {
                        RailPool.Free(command);
                    }
                }
            }
        }
예제 #3
0
        internal void ReceiveDelta(RailStateDelta delta)
        {
            bool stored = false;

            if (delta.IsFrozen)
            {
                // Frozen deltas have no state data, so we need to treat them
                // separately when doing checks based on state content
                stored = this.incomingStates.Store(delta);
            }
            else
            {
                if (delta.IsDestroyed)
                {
                    this.RemovedTick = delta.RemovedTick;
                }
                else
                {
                    stored = this.incomingStates.Store(delta);
                }

                if (delta.HasControllerData)
                {
                    this.CleanCommands(delta.CommandAck);
                }
            }

            // We never stored it, so free the delta
            if (stored == false)
            {
                RailPool.Free(delta);
            }
        }
예제 #4
0
        /// <summary>
        /// Removes any acked or expired outgoing events.
        /// </summary>
        private void CleanOutgoingEvents(
            SequenceId ackedEventId)
        {
            if (ackedEventId.IsValid == false)
            {
                return;
            }

            while (this.outgoingEvents.Count > 0)
            {
                RailEvent top = this.outgoingEvents.Peek();

                // Stop if we hit an un-acked reliable event
                if (top.IsReliable)
                {
                    if (top.EventId > ackedEventId)
                    {
                        break;
                    }
                }
                // Stop if we hit an unreliable event with remaining attempts
                else
                {
                    if (top.Attempts > 0)
                    {
                        break;
                    }
                }

                RailPool.Free(this.outgoingEvents.Dequeue());
            }
        }
예제 #5
0
        private void Reset()
        {
            this.Room = null;

            this.Id         = EntityId.INVALID;
            this.Controller = null;
            this.hasStarted = false;

            // We always notify a controller change at start
            this.deferNotifyControllerChanged = true;

#if SERVER
            this.IsFrozen = false; // Entities never freeze on server

            this.outgoingStates.Clear();
            this.incomingCommands.Clear();
#endif
#if CLIENT
            this.LastSentCommandTick = Tick.START;
            this.IsFrozen            = true; // Entities start frozen on client
            this.shouldBeFrozen      = true;

            this.incomingStates.Clear();
            RailPool.DrainQueue(this.outgoingCommands);

            this.authTick = Tick.START;
            this.nextTick = Tick.INVALID;
#endif

            this.ResetStates();
            this.OnReset();
        }
예제 #6
0
 /// <summary>
 /// Clears the buffer, freeing all contents.
 /// </summary>
 public void Clear()
 {
     for (int i = 0; i < this.data.Length; i++)
     {
         RailPool.SafeReplace(ref this.data[i], null);
     }
     this.latestIdx = -1;
 }
예제 #7
0
 public static void DrainQueue <T>(Queue <T> queue)
     where T : IRailPoolable <T>
 {
     while (queue.Count > 0)
     {
         RailPool.Free(queue.Dequeue());
     }
 }
예제 #8
0
 public static void SafeReplace <T>(ref T destination, T obj)
     where T : IRailPoolable <T>
 {
     if (destination != null)
     {
         RailPool.Free(destination);
     }
     destination = obj;
 }
예제 #9
0
 /// <summary>
 /// Clears the buffer, freeing all contents.
 /// </summary>
 public void Clear()
 {
     foreach (T val in this.data)
     {
         RailPool.Free(val);
     }
     this.data.Clear();
     this.Latest = null;
 }
예제 #10
0
 public void Store(T val)
 {
     if (this.data.Count >= this.capacity)
     {
         RailPool.Free(this.data.Dequeue());
     }
     this.data.Enqueue(val);
     this.Latest = val;
 }
예제 #11
0
 internal void ReceiveCommand(RailCommand command)
 {
     if (this.incomingCommands.Store(command))
     {
         command.IsNewCommand = true;
     }
     else
     {
         RailPool.Free(command);
     }
 }
예제 #12
0
        public void Clear()
        {
#if CLIENT
            // We don't free the received values as they will be passed elsewhere
            this.received.Clear();
#endif
#if SERVER
            // Everything in sent is also in pending, so only free pending
            foreach (T value in this.pending)
            {
                RailPool.Free(value);
            }
            this.pending.Clear();
            this.sent.Clear();
#endif
        }
예제 #13
0
        private void CleanCommands(Tick ackTick)
        {
            if (ackTick.IsValid == false)
            {
                return;
            }

            while (this.outgoingCommands.Count > 0)
            {
                RailCommand command = this.outgoingCommands.Peek();
                if (command.ClientTick > ackTick)
                {
                    break;
                }
                RailPool.Free(this.outgoingCommands.Dequeue());
            }
        }
예제 #14
0
        private void ResetStates()
        {
            if (this.StateBase != null)
            {
                RailPool.Free(this.StateBase);
            }
#if CLIENT
            if (this.AuthStateBase != null)
            {
                RailPool.Free(this.AuthStateBase);
            }
            if (this.NextStateBase != null)
            {
                RailPool.Free(this.NextStateBase);
            }
#endif

            this.StateBase = null;
#if CLIENT
            this.AuthStateBase = null;
            this.NextStateBase = null;
#endif
        }