Exemple #1
0
        public static int operator -(Tick a, Tick b)
        {
            RailDebug.Assert(a.IsValid && b.IsValid);
            long difference = a.tickValue - (long)b.tickValue;

            return((int)difference);
        }
Exemple #2
0
        public static int operator +(Tick a, Tick b)
        {
            RailDebug.Assert(a.IsValid && b.IsValid);
            long sum = a.tickValue + (long)b.tickValue;

            return((int)sum);
        }
Exemple #3
0
        /// <summary>
        ///     Remove an entity from being controlled by this peer.
        /// </summary>
        public void RevokeControlInternal(RailEntityBase entity)
        {
            RailDebug.Assert(entity.Controller == this);

            controlledEntities.Remove(entity);
            entity.AssignController(null);
        }
Exemple #4
0
        /// <summary>
        ///     Returns true iff we stored the delta.
        /// </summary>
        public bool ProcessDelta(RailStateDelta delta)
        {
            if (knownEntities.TryGetValue(delta.EntityId, out RailEntityClient entity) == false)
            {
                RailDebug.Assert(delta.IsFrozen == false, "Frozen unknown entity");
                if (delta.IsFrozen || delta.IsRemoving)
                {
                    return(false);
                }

                entity = delta.ProduceEntity(Resource) as RailEntityClient;
                if (entity == null)
                {
                    throw new TypeAccessException(
                              "Got unexpected instance from RailResource. Internal error in type RailRegistry and/or RailResource.");
                }

                entity.AssignId(delta.EntityId);
                entity.PrimeState(delta);
                pendingEntities.Add(entity.Id, entity);
                knownEntities.Add(entity.Id, entity);
            }

            // If we're already removing the entity, we don't care about other deltas
            bool stored = false;

            if (entity.IsRemoving == false)
            {
                stored = entity.ReceiveDelta(delta);
            }
            return(stored);
        }
Exemple #5
0
        public static bool operator !=(SequenceId a, SequenceId b)
        {
            RailDebug.Assert(a.IsValid);
            RailDebug.Assert(b.IsValid);

            return(a.rawValue != b.rawValue);
        }
Exemple #6
0
        public void Deallocate(T instance)
        {
            RailDebug.Assert(instance.Pool == this);

            instance.Reset();
            instance.Pool = null; // Prevent multiple frees
            freeList.Push(instance);
        }
Exemple #7
0
        private static int GetDifference(SequenceId a, SequenceId b)
        {
            RailDebug.Assert(a.IsValid);
            RailDebug.Assert(b.IsValid);

            int difference = (int)((a.rawValue << BIT_SHIFT) - (b.rawValue << BIT_SHIFT));

            return(difference);
        }
Exemple #8
0
        public void SendPacket(RailResource resource, IRailNetPeer peer, RailPacketOutgoing packet)
        {
            bitBuffer.Clear();
            packet.Encode(resource, bitBuffer);
            int length = bitBuffer.Store(bytes);

            RailDebug.Assert(length <= RailConfig.PACKCAP_MESSAGE_TOTAL);
            peer.SendPayload(new ArraySegment <byte>(bytes, 0, length));
        }
Exemple #9
0
        /// <summary>
        ///     Adds an entity to be controlled by this peer.
        /// </summary>
        public void GrantControlInternal(RailEntityBase entity)
        {
            if (entity.Controller == this)
            {
                return;
            }
            RailDebug.Assert(entity.Controller == null);

            controlledEntities.Add(entity);
            entity.AssignController(this);
        }
Exemple #10
0
 /// <summary>
 ///     Queues an event to broadcast to the server with a number of retries.
 /// </summary>
 public void RaiseEvent <T>(Action <T> initializer, ushort attempts = 3)
     where T : RailEvent
 {
     RailDebug.Assert(client.ServerPeer != null);
     if (client.ServerPeer != null)
     {
         T evnt = eventCreator.CreateEvent <T>();
         initializer(evnt);
         client.ServerPeer.SendEvent(evnt, attempts, false);
     }
 }
Exemple #11
0
        /// <summary>
        ///     Packs all elements of an enumerable up to a given size.
        ///     Max MAX_LIST_COUNT elements, by default 255.
        /// </summary>
        public byte PackToSize <T>(
            int maxTotalBytes,
            int maxIndividualBytes,
            IEnumerable <T> elements,
            Action <T, RailBitBuffer> encode,
            Action <T> packed = null)
        {
            const int SIZE_BITS = 8;

            maxTotalBytes -= 1; // Sentinel bit can blow this up
            byte count = 0;

            // Reserve: [Count]
            int countWritePos = writePos;

            Write(SIZE_BITS, 0);

            // Write: [Elements]
            foreach (T val in elements)
            {
                if (count == MAX_LIST_COUNT)
                {
                    break;
                }
                int rollback      = writePos;
                int startByteSize = ByteSize;

                encode.Invoke(val, this);

                int endByteSize   = ByteSize;
                int writeByteSize = endByteSize - startByteSize;
                if (writeByteSize > maxIndividualBytes)
                {
                    writePos = rollback;
                    RailDebug.LogWarning("Skipping " + val + " (" + writeByteSize + "B)");
                }
                else if (endByteSize > maxTotalBytes)
                {
                    writePos = rollback;
                    break;
                }
                else
                {
                    packed?.Invoke(val);
                    count++;
                }
            }

            // Deferred Write: [Count]
            Insert(countWritePos, SIZE_BITS, count);
            return(count);
        }
Exemple #12
0
        private static void EncodeHeader(RailPacketOutgoing packet, RailBitBuffer buffer)
        {
            RailDebug.Assert(packet.SenderTick.IsValid);

            // Write: [LocalTick]
            buffer.WriteTick(packet.SenderTick);

            // Write: [LastAckTick]
            buffer.WriteTick(packet.LastAckTick);

            // Write: [AckReliableEventId]
            buffer.WriteSequenceId(packet.LastAckEventId);
        }
Exemple #13
0
        /// <summary>
        ///     Selects outgoing events to send.
        /// </summary>
        private IEnumerable <RailEvent> FilterOutgoingEvents()
        {
            // The receiving client can only store a limited size sequence history
            // of events in its received buffer, and will skip any events older than
            // its latest received minus that history length, including reliable
            // events. In order to make sure we don't force the client to skip an
            // event with attempts remaining, we will throttle the outgoing events
            // if we've been sending them too fast. For example, if we have a live
            // event with ID 3 pending, and a maximum history length of 64 (see
            // RailConfig.HISTORY_CHUNKS) then the highest ID we can send would be
            // ID 67. Were we to send an event with ID 68, then the client may ignore
            // ID 3 when it comes in for being too old, even though it's still live.
            //
            // In practice this shouldn't be a problem unless we're sending way
            // more events than is reasonable(/possible) in a single packet, or
            // something is wrong with reliable event acking. You can always increase
            // the number of history chunks if this becomes an issue.

            SequenceId firstId = SequenceId.Invalid;

            foreach (RailEvent evnt in outgoingEvents)
            {
                // Ignore dead events, they'll be cleaned up eventually
                if (evnt.Attempts <= 0)
                {
                    continue;
                }

                // Don't send an event if it's out of scope for this peer
                if (Scope != null && Scope.Includes(evnt) == false)
                {
                    // Skipping due to out of scope counts as an attempt
                    evnt.RegisterSkip();
                    continue;
                }

                if (firstId.IsValid == false)
                {
                    firstId = evnt.EventId;
                }
                RailDebug.Assert(firstId <= evnt.EventId);

                if (eventHistory.AreInRange(firstId, evnt.EventId) == false)
                {
                    RailDebug.LogWarning("Throttling events due to lack of ack");
                    break;
                }

                yield return(evnt);
            }
        }
Exemple #14
0
        public void Overwrite(IRailStateConstruction stateCreator, Tick tick, RailState state)
        {
            RailDebug.Assert(tick.IsValid);

            this.tick = tick;
            if (this.state == null)
            {
                this.state = state.Clone(stateCreator);
            }
            else
            {
                this.state.OverwriteFrom(state);
            }
        }
Exemple #15
0
        public static Tick Subtract(Tick a, uint b, bool warnClamp = false)
        {
            long result = a.tickValue - (int)b;

            if (result < 1)
            {
                if (warnClamp)
                {
                    RailDebug.LogWarning("Clamping tick subtraction");
                }
                result = 1;
            }

            return(new Tick((uint)result));
        }
Exemple #16
0
 public uint Pack(int value)
 {
     if ((value < this.minValue) || (value > this.maxValue))
     {
         RailDebug.LogWarning(
             "Clamping value for send! " +
             value +
             " vs. [" +
             this.minValue +
             "," +
             this.maxValue +
             "]");
     }
     return((uint)(value - this.minValue) & this.mask);
 }
Exemple #17
0
        public void Overwrite(
            Tick tick,
            RailState state)
        {
            RailDebug.Assert(tick.IsValid);

            this.tick = tick;
            if (this.state == null)
            {
                this.state = state.Clone();
            }
            else
            {
                this.state.OverwriteFrom(state);
            }
        }
Exemple #18
0
        public ulong Pack(long value)
        {
            if (value < minValue || value > maxValue)
            {
                RailDebug.LogWarning(
                    "Clamping value for send! " +
                    value +
                    " vs. [" +
                    minValue +
                    "," +
                    maxValue +
                    "]");
            }

            return((ulong)(value - minValue) & mask);
        }
        public uint Pack(float value)
        {
            float newValue = RailUtil.Clamp(value, this.minValue, this.maxValue);

            if (newValue != value)
            {
                RailDebug.LogWarning(
                    "Clamping value for send! " +
                    value +
                    " vs. [" +
                    this.minValue +
                    "," +
                    this.maxValue +
                    "]");
            }
            float adjusted = (value - this.minValue) * this.invPrecision;

            return((uint)(adjusted + 0.5f) & this.mask);
        }
Exemple #20
0
        public void WriteString(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            uint length = (uint)value.Length;

            RailDebug.Assert(length <= RailConfig.STRING_LENGTH_MAX, value);
            if (value.Length > RailConfig.STRING_LENGTH_MAX)
            {
                length = RailConfig.STRING_LENGTH_MAX;
            }

            Write(STRING_LENGTH_BITS, length);
            for (int i = 0; i < length; i++)
            {
                Write(ASCII_BITS, ToASCII(value[i]));
            }
        }
Exemple #21
0
        /// <summary>
        ///     Copies the buffer to a byte buffer.
        /// </summary>
        public int Store(byte[] data)
        {
            // Write a sentinel bit to find our position and flash out bad data
            Write(1, 1);

            int numChunks = (writePos >> 5) + 1;

            RailDebug.Assert(data.Length >= numChunks * 4, "Buffer too small");

            for (int i = 0; i < numChunks; i++)
            {
                int  dataIdx = i * 4;
                uint chunk   = chunks[i];
                data[dataIdx]     = (byte)chunk;
                data[dataIdx + 1] = (byte)(chunk >> 8);
                data[dataIdx + 2] = (byte)(chunk >> 16);
                data[dataIdx + 3] = (byte)(chunk >> 24);
            }

            return(ByteSize);
        }
Exemple #22
0
        private static byte ToASCII(char character)
        {
            byte value;

            try
            {
                value = Convert.ToByte(character);
            }
            catch (OverflowException)
            {
                RailDebug.LogWarning("Cannot convert to simple ASCII: " + character);
                return(0);
            }

            if (value > 127)
            {
                RailDebug.LogWarning("Cannot convert to simple ASCII: " + character);
                return(0);
            }

            return(value);
        }
Exemple #23
0
        /// <summary>
        ///     Sets the current server peer.
        /// </summary>
        public void SetPeer(IRailNetPeer netPeer)
        {
            if (netPeer == null)
            {
                if (ServerPeer != null)
                {
                    ServerPeer.PacketReceived -= OnPacketReceived;
                    ServerPeer.EventReceived  -= OnEventReceived;
                    Disconnected?.Invoke(ServerPeer);
                }

                ServerPeer = null;
            }
            else
            {
                RailDebug.Assert(ServerPeer == null, "Overwriting peer");
                ServerPeer = new RailClientPeer(Resource, netPeer, Interpreter);
                ServerPeer.PacketReceived += OnPacketReceived;
                ServerPeer.EventReceived  += OnEventReceived;
                Connected?.Invoke(ServerPeer);
            }
        }
Exemple #24
0
        private void OnPayloadReceived(IRailNetPeer peer, ArraySegment <byte> buffer)
        {
            try
            {
                RailBitBuffer bitBuffer = interpreter.LoadData(buffer);
                reusableIncoming.Reset();
                reusableIncoming.Decode(Resource, bitBuffer);

                if (bitBuffer.IsFinished)
                {
                    ProcessPacket(reusableIncoming, LocalTick);
                }
                else
                {
                    RailDebug.LogError("Bad packet read, discarding...");
                }
            }
            catch (Exception e)
            {
                RailDebug.LogError("Error during packet read: " + e);
            }
        }
Exemple #25
0
        // See http://www.gamedev.net/topic/652186-de-jitter-buffer-on-both-the-client-and-server/
        public void Update()
        {
            if (this.shouldTick == false)
            {
                return; // 0;
            }
            this.estimatedRemote = this.estimatedRemote + 1;
            if (this.shouldUpdateEstimate == false)
            {
                return; // 1;
            }
            int delta = this.latestRemote - this.estimatedRemote;

            if (this.ShouldSnapTick(delta))
            {
                // Reset
                RailDebug.LogMessage("Reset");
                this.estimatedRemote = this.latestRemote - this.delayDesired;
                return; // 0;
            }
            else if (delta > this.delayMax)
            {
                // Jump 1
                RailDebug.LogMessage("Jump 1");
                this.estimatedRemote = this.estimatedRemote + 1;
                return; // 2;
            }
            else if (delta < this.delayMin)
            {
                // Stall 1
                RailDebug.LogMessage("Stall 1");
                this.estimatedRemote = this.estimatedRemote - 1;
                return; // 0;
            }

            this.shouldUpdateEstimate = false;
            return; // 1;
        }
Exemple #26
0
 public virtual void Removed()
 {
     RailDebug.Assert(HasStarted);
     OnRemoved();
 }
Exemple #27
0
 public bool Equals(Tick x, Tick y)
 {
     RailDebug.Assert(x.IsValid);
     RailDebug.Assert(y.IsValid);
     return(x == y);
 }
Exemple #28
0
 public Tick GetNext()
 {
     RailDebug.Assert(IsValid);
     return(new Tick(tickValue + 1));
 }
Exemple #29
0
 public float ToTime(float tickDeltaTime)
 {
     RailDebug.Assert(IsValid);
     return((tickValue - 1) * tickDeltaTime);
 }
Exemple #30
0
 public static Tick operator +(Tick a, uint b)
 {
     RailDebug.Assert(a.IsValid);
     return(new Tick(a.tickValue + b));
 }