예제 #1
0
        public bool AddLocalInput(int queue, ref GameInput input)
        {
            int framesBehind = FrameCount - lastConfirmedFrame;

            if (FrameCount >= maxPredictionFrames && framesBehind >= maxPredictionFrames)
            {
                Log("Rejecting input from emulator: reached prediction barrier.");
                return(false);
            }

            if (FrameCount == 0)
            {
                SaveCurrentFrame();
            }

            Log($"Sending undelayed local frame {FrameCount} to queue {queue}.");
            input.frame = FrameCount;
            inputQueues[queue].AddInput(ref input);

            return(true);
        }
예제 #2
0
        public int SyncrhonizeInputs(ref byte[] values)
        {
            int disconnect_flags = 0;

            Debug.Assert(values.Length >= config.numPlayers * config.inputSize);

            Unsafe.InitBlock(ref values[0], 0, (uint)values.Length);
            for (int i = 0; i < config.numPlayers; i++)
            {
                var input = new GameInput(GameInput.NullFrame, null, (uint)config.inputSize);
                if (localConnectStatus[i].Disconnected && FrameCount > localConnectStatus[i].LastFrame)
                {
                    disconnect_flags |= (1 << i);
                }
                else
                {
                    inputQueues[i].GetInput(FrameCount, ref input);
                }
                Unsafe.CopyBlock(ref values[i * config.inputSize], ref input.bits[0], (uint)config.inputSize);
            }
            return(disconnect_flags);
        }
예제 #3
0
        public void AddInput(ref GameInput input)
        {
            int newFrame;

            Log($"adding input frame number {input.frame} to queue.");

            // These next two lines simply verify that inputs are passed in
            // sequentially by the user, regardless of frame delay.
            Debug.Assert(lastUserAddedFrame == GameInput.NullFrame || input.frame == lastUserAddedFrame + 1);
            lastUserAddedFrame = input.frame;

            // Move the queue head to the correct point in preparation to
            // input the frame into the queue.
            newFrame = AdvanceQueueHead(input.frame);
            if (newFrame != GameInput.NullFrame)
            {
                AddDelayedInputToQueue(ref input, newFrame);
            }

            // Update the frame number for the input.  This will also set the
            // frame to GameInput::NullFrame for frames that get dropped (by
            // design).
            input.frame = newFrame;
        }
예제 #4
0
        public bool GetInput(int requestedFrame, ref GameInput input)
        {
            Log($"requesting input frame {requestedFrame}.");


            // No one should ever try to grab any input when we have a prediction
            // error.  Doing so means that we're just going further down the wrong
            // path.  ASSERT this to verify that it's true.
            Debug.Assert(firstIncorrectFrame == GameInput.NullFrame);

            // Remember the last requested frame number for later.  We'll need
            // this in AddInput() to drop out of prediction mode.
            lastFrameRequested = requestedFrame;

            Debug.Assert(requestedFrame >= inputs[tail].frame);

            if (prediction.frame == GameInput.NullFrame)
            {
                // If the frame requested is in our range, fetch it out of the queue and
                // return it.
                int offset = requestedFrame - inputs[tail].frame;

                if (offset < length)
                {
                    offset = (offset + tail) % inputs.Length;
                    Debug.Assert(inputs[offset].frame == requestedFrame);
                    input = inputs[offset];
                    Log($"returning confirmed frame number {input.frame}.");
                    return(true);
                }

                // The requested frame isn't in the queue.  Bummer.  This means we need
                // to return a prediction frame.  Predict that the user will do the
                // same thing they did last time.
                if (requestedFrame == 0)
                {
                    Log("basing new prediction frame from nothing, you're client wants frame 0.");
                    prediction.Erase();
                }
                else if (lastAddedFrame == GameInput.NullFrame)
                {
                    Log("basing new prediction frame from nothing, since we have no frames yet.");
                    prediction.Erase();
                }
                else
                {
                    Log($"basing new prediction frame from previously added frame (queue entry:{PreviousFrame(head)}, frame:{inputs[PreviousFrame(head)].frame}).");
                    prediction = inputs[PreviousFrame(head)];
                }
                prediction.frame++;
            }

            Debug.Assert(prediction.frame >= 0);

            // If we've made it this far, we must be predicting.  Go ahead and
            // forward the prediction frame contents.  Be sure to return the
            // frame number requested by the client, though.
            input       = prediction;
            input.frame = requestedFrame;
            Log($"returning prediction frame number {input.frame} ({prediction.frame}).");

            return(false);
        }
예제 #5
0
 public void AddRemoteInput(int queue, ref GameInput input)
 {
     inputQueues[queue].AddInput(ref input);
 }