Esempio n. 1
0
        public void ServerQueueSecondDestruct(ushort eid)
        {
            SecondDestructQueue.Add(eid);
            SecondDestructQueueTime.Add(CurrentTime);

            NetSnapper.ServerSendDeghostSecondAll(eid);
        }
Esempio n. 2
0
        private bool UnpackDelta(ReArrayIdPool <SnapHistory <TSnap, TStatic> > data,
                                 int innerid,
                                 byte[] blob, int blobstart, int blobcount,
                                 ushort timestamp, ushort basisTimestamp)
        {
            SnapHistory <TSnap, TStatic> sh = data.Values[data.IdsToIndices[innerid]];

            int index = sh.FindIndex(timestamp);

            if (index < 0 || index >= sh.Shots.Length)
            {
                return(false); // out of bounds
            }
            int basisIndex = sh.FindIndex(basisTimestamp);

            if (basisIndex < 0 || basisIndex >= sh.Shots.Length)
            {
                return(false); // out of bounds
            }
            Packer.UnpackDelta(ref sh.Shots[index], sh.Shots[basisIndex], blob, blobstart, blobcount);
            sh.Timestamps[index] = timestamp;
            sh.Flags[index]      = SnapHistory <TSnap, TStatic> .FlagGold;

            // ask the server to resimulate from this timestamp
            // to ensure our silver guesses get updated
            NetSnapper.RequestResimulate(timestamp);

            return(true);
        }
Esempio n. 3
0
        // queue destruction of an entity. It will be deghosted first and then
        // destroyed later once enough time has passed.
        public void ServerQueueFirstDestruct(byte eid)
        {
            FirstDestructQueue.Add(eid);
            FirstDestructQueueTime.Add(CurrentTime);

            NetSnapper.ServerSendDeghostFirstAll(eid);
        }
Esempio n. 4
0
        public bool ServerAddEntitySecond(TSnap initalSnap, TStatic staticData, out ushort eid,
                                          bool ghostAll = true)
        {
            if (!NetSnapper.ServerRequestEntitySecond(EntityType, out eid))
            {
                return(false); // NetSnapper says: no entity space available
            }

            if (SecondEntityIdToInnerId.Length <= eid)
            {
                ExpandSecondEntityIdMap(eid);
            }

            SnapHistory <TSnap, TStatic> h = SecondData.Request();

            h.StaticData = staticData;

            h.EntityId      = eid;
            h.Timestamps[0] = NetSnapper.CurrentTime;
            h.Flags[0]      = SnapHistory <TSnap, TStatic> .FlagGold;
            h.LeadingIndex  = 0;
            h.Shots[0]      = initalSnap;

            SecondEntityIdToInnerId[eid] = h.PoolId;

            if (ghostAll)
            {
                // ghost the new entity to all players
                NetSnapper.ServerSendGhostAllSecond(eid, EntityType);
            }

            return(true);
        }
Esempio n. 5
0
        // Simulant Helpers
        public void ServerSaveSimIntoCurrent(SnapHistory <TSnap, TStatic> ent)
        {
            ent.Flags[ent.CurrentIndex] = SnapHistory <TSnap, TStatic> .FlagGold;

            if (ent.First)
            {
                NetSnapper.ServerSendDeltaAllFirst((byte)ent.EntityId, EntityType);
            }
            else
            {
                NetSnapper.ServerSendDeltaAllSecond(ent.EntityId, EntityType);
            }
        }
Esempio n. 6
0
        private bool UnpackFull(ReArrayIdPool <SnapHistory <TSnap, TStatic> > data,
                                int innerid,
                                byte[] blob, int blobstart, int blobcount,
                                ushort timestamp)
        {
            SnapHistory <TSnap, TStatic> sh = data.Values[data.IdsToIndices[innerid]];

            int index = sh.FindIndex(timestamp);

            if (index < 0)
            {
                return(false); // out of bounds-- too far in future or past
            }
            Packer.UnpackFull(ref sh.Shots[index], ref sh.StaticData, blob, blobstart, blobcount);
            sh.Timestamps[index] = timestamp;
            sh.Flags[index]      = SnapHistory <TSnap, TStatic> .FlagGold;

            // ask the server to resimulate from this timestamp
            // to ensure our silver guesses get updated
            NetSnapper.RequestResimulate(timestamp);

            return(true);
        }
Esempio n. 7
0
        // Prime Logic

        // Advancement occurs every tick
        public void Advance(ushort currentTime)
        {
            CurrentTime = currentTime;

            // when we advance, push every leading edge forward
            for (int i = 0; i < FirstData.Count; i++)
            {
                SnapHistory <TSnap, TStatic> sh = FirstData.Values[i];
                ushort last       = sh.Timestamps[sh.LeadingIndex];
                ushort next       = last == ushort.MaxValue ? (ushort)0 : (ushort)(last + 1);
                int    startIndex = sh.LeadingIndex;

                sh.LeadingIndex++;
                if (sh.LeadingIndex == sh.Shots.Length)
                {
                    sh.LeadingIndex = 0;
                }

                if (sh.Timestamps[sh.LeadingIndex] != next)
                {
                    // we haven't received the next snap yet, so destroy it and
                    // ensure that it is empty for the simulator
                    sh.Timestamps[sh.LeadingIndex] = next;
                    sh.Flags[sh.LeadingIndex]      = SnapHistory <TSnap, TStatic> .FlagEmpty;

                    // note: we don't need to actually call Clear on the snapshot
                    // since the fact that it's marked with an empty flag means
                    // the simulator should avoid using it.

                    // if the previous snapshot was deghosted,
                    // deghost this one as well.
                    if (sh.Flags[startIndex] == SnapHistory <TSnap, TStatic> .FlagDeghosted)
                    {
                        sh.Flags[sh.LeadingIndex] = SnapHistory <TSnap, TStatic> .FlagDeghosted;
                    }
                }
            }

            // same logic as above but for second data
            // only reason we don't use a method for this is having that many method
            // calls seems like a waste.
            for (int i = 0; i < SecondData.Count; i++)
            {
                SnapHistory <TSnap, TStatic> sh = SecondData.Values[i];
                ushort last       = sh.Timestamps[sh.LeadingIndex];
                ushort next       = last == ushort.MaxValue ? (ushort)0 : (ushort)(last + 1);
                int    startIndex = sh.LeadingIndex;

                sh.LeadingIndex++;
                if (sh.LeadingIndex == sh.Shots.Length)
                {
                    sh.LeadingIndex = 0;
                }

                if (sh.Timestamps[sh.LeadingIndex] != next)
                {
                    sh.Timestamps[sh.LeadingIndex] = next;
                    sh.Flags[sh.LeadingIndex]      = SnapHistory <TSnap, TStatic> .FlagEmpty;

                    if (sh.Flags[startIndex] == SnapHistory <TSnap, TStatic> .FlagDeghosted)
                    {
                        sh.Flags[sh.LeadingIndex] = SnapHistory <TSnap, TStatic> .FlagDeghosted;
                    }
                }
            }

            // now check our destruct queues
            if (FirstDestructQueue.Count > 0)
            {
                for (int i = FirstDestructQueue.Count - 1; i >= 0; i--)
                {
                    ushort destructTime = FirstDestructQueueTime[i];

                    int dist = 0;
                    if (currentTime < destructTime)
                    {
                        dist = (ushort.MaxValue - destructTime) + currentTime;
                    }
                    else
                    {
                        dist = currentTime - destructTime;
                    }

                    if (dist < FirstWindowLength)
                    {
                        break;
                    }

                    NetSnapper.ServerDestructFirst(FirstDestructQueue[i]);
                    FirstDestructQueue.RemoveAt(i);
                    FirstDestructQueueTime.RemoveAt(i);
                }
            }

            if (SecondDestructQueue.Count > 0)
            {
                for (int i = SecondDestructQueue.Count - 1; i >= 0; i--)
                {
                    ushort destructTime = SecondDestructQueueTime[i];

                    int dist = 0;
                    if (currentTime < destructTime)
                    {
                        dist = (ushort.MaxValue - destructTime) + currentTime;
                    }
                    else
                    {
                        dist = currentTime - destructTime;
                    }

                    if (dist < FirstWindowLength)
                    {
                        break;
                    }

                    NetSnapper.ServerDestructSecond(SecondDestructQueue[i]);
                    SecondDestructQueue.RemoveAt(i);
                    SecondDestructQueueTime.RemoveAt(i);
                }
            }
        }
Esempio n. 8
0
        private void Rollover(SnapHistory <TSnap, TStatic> sh, int index, ushort timestamp)
        {
            // this whole idea has to be reworked
            // I guess an issue is that one of our key assumptions
            // is that the indices will always be populated with timestamps
            // so we need to have some kind of rollover
            // but doing the extrap action here is not good
            // 1. it's not real simulated
            // 2. why not do interp when available?

            // one option would be to do simple extrap/interp here
            // or even just copy the same snapshot over and over
            // and then, when we get an older timestamp, flag the simulator
            // as "needs rollback calculation" (ONLY IF WE ACTUALLY HAVE ANY
            // SILVER SNAPSHOTS AHEAD OF THIS TIMESTAMP)

            // then, at the end of each processing, if the simulator has
            // this flag set, it will run again from whatever the oldest time
            // flagged was (need to track the timestamp of each flagging as well)
            // this will generate new silver snapshots, and they'll be accurate to boot.

            // RE: THIS DISCUSSION
            // we decided to do the "resimulate flagging" approach
            // so the way this works now is that if we receive a timestamp,
            // and there's unknowns in front of it,
            // the system gets asked to resimulate from that timestamp

            int    nindex   = index + 1;
            ushort nextTime = timestamp;

            if (nindex == sh.Shots.Length)
            {
                nindex = 0;
            }

            if (nextTime == ushort.MaxValue)
            {
                nextTime = 0;
            }
            else
            {
                nextTime++;
            }

            // we can only rollover onto silver flags
            if (sh.Flags[nindex] != SnapHistory <TSnap, TStatic> .FlagSilver && sh.Flags[nindex] != SnapHistory <TSnap, TStatic> .FlagEmpty)
            {
                return;
            }

            // can only rollover onto subsequent timestamps
            if (sh.Timestamps[nindex] != nextTime)
            {
                return;
            }

            // if we get here, then we hit a silver or an empty that must be filled out
            // tell the snap system to resimulate
            NetSnapper.RequestResimulate(timestamp);


            // VVVV OLD VVVV

            /*
             * // flags need to act a certain way to allow us to have
             * // snapshots roll over when no changes are needed
             * // e.g.:
             * // 1 = from server (GOLD STANDARD)
             * // 2 = roll over, this occurs when no snapshot is received
             * //     we assume shot is unchanged and use it again for next
             * //     timestamp
             * // now imagine we have some snaps:
             * // aaaaabb
             * // 1222212
             * //   ^ and here we receive a new snapshot c
             * // we SCROLL FORWARD and replace all 2s with the new snapshot:
             * // aacccbb
             * // 1212212
             * // this way we can let client continue to scroll forward but
             * // also correct itself properly
             * int nindex = index + 1;
             * ushort nextTime = timestamp;
             * int rolls = 1;
             * while (true)
             * {
             *  if (nindex == sh.Shots.Length)
             *      nindex = 0;
             *
             *  if (nextTime == ushort.MaxValue)
             *      nextTime = 0;
             *  else
             *      nextTime++;
             *
             *  // we can only rollover onto silver flags
             *  if (sh.Flags[nindex] != SnapHistory<T>.FlagSilver && sh.Flags[nindex] != SnapHistory<T>.FlagEmpty)
             *      break;
             *
             *  // can only rollover onto subsequent timestamps
             *  if (sh.Timestamps[nindex] != nextTime)
             *      break;
             *
             *  // now we're ready to roll
             *  ExtrapolateAction(ref sh.Shots[nindex], sh.Shots[index], TickMS * rolls);
             *  rolls++;
             *
             *  nindex++;
             * }*/
        }