示例#1
0
        public override int UniformRunLength(int irun)
        {
            TsRunInfo info;

            Tss.FetchRunInfo(irun, out info);
            return(info.ichLim - info.ichMin);
        }
示例#2
0
        /// <summary>
        /// Creates a new server listening on the specified port and allowing
        /// for the specified number of players.
        /// </summary>
        /// <param name="port">The port to listen on.</param>
        /// <param name="maxPlayers">The maximum number of players supported.</param>
        /// <param name="commandHandler">The command handler to use in the
        /// simulation.</param>
        public SimpleServerController(ushort port, int maxPlayers, CommandHandler commandHandler)
            : base(new HybridServerSession <TPlayerData>(port, maxPlayers))
        {
            var simulation = new DefaultSimulation();

            simulation.Command += commandHandler;
            Tss.Initialize(simulation);
        }
示例#3
0
        /// <summary>
        /// Creates a new game client, ready to connect to an open game.
        /// </summary>
        /// <param name="commandHandler">The command handler to use.</param>
        public SimpleClientController(CommandHandler commandHandler)
            : base(new HybridClientSession <TPlayerData>())
        {
            var simulation = new DefaultSimulation();

            simulation.Command += commandHandler;
            Tss.Initialize(simulation);
        }
示例#4
0
        public override string UniformRunText(int irun)
        {
            TsRunInfo info;

            Tss.FetchRunInfo(irun, out info);
            var result = Tss.GetChars(info.ichMin, info.ichLim);

            if (result == null)
            {
                return("");
            }
            return(result);
        }
示例#5
0
        /// <summary>
        /// Return an otherwise equivalent Tss client run that has the specified Contents.
        /// Subclasses should override to return the appropriate subclass and copy any additional information.
        /// </summary>
        internal override TssClientRun CopyWithNewContents(ITsString newContents)
        {
            ITsString tss = newContents;
            int       var;

            if (tss == null)
            {
                tss = TsStrFactoryClass.Create().EmptyString(Tss.get_Properties(0).GetIntPropValues((int)FwTextPropType.ktptWs, out var));
            }
            var result = new SubstituteTssClientRun(tss, Style, m_substitute, m_substituteStyle);

            result.Hookup = Hookup;
            return(result);
        }
示例#6
0
        public override AssembledStyles UniformRunStyles(int irun)
        {
            ITsTextProps props = Tss.get_Properties(irun);

            return(Style.ApplyTextProps(props));
        }
示例#7
0
        /// <summary>
        /// Takes care of client side TSS synchronization logic.
        /// </summary>
        protected override FrameCommand UnwrapDataForReceive(SessionDataEventArgs e)
        {
            var args = (ClientDataEventArgs)e;
            var type = (TssControllerMessage)args.Data.ReadByte();

            switch (type)
            {
            case TssControllerMessage.Command:
            {
                // Normal command, forward it.
                var command = base.UnwrapDataForReceive(e);

                // Test if we got the message from the server, to mark the command accordingly.
                command.IsAuthoritative = args.IsAuthoritative;

                // Return the deserialized command.
                return(command);
            }

            case TssControllerMessage.Synchronize:
            {
                // Answer to a synchronization request.
                // Only accept these when they come from the server, and disregard if
                // we're waiting for a snapshot of the simulation.
                if (args.IsAuthoritative && !Tss.WaitingForSynchronization)
                {
                    // This calculation follows algorithm described here:
                    // http://www.mine-control.com/zack/timesync/timesync.html
                    var sentFrame   = args.Data.ReadInt64();
                    var serverFrame = args.Data.ReadInt64();

                    // We also adjust the game speed to accommodate slow
                    // machines. That's the speed we get in this step.
                    AdjustedSpeed = args.Data.ReadSingle();

                    var latency           = (Tss.CurrentFrame - sentFrame) / 2;
                    var clientServerDelta = (serverFrame - Tss.CurrentFrame);
                    var frameDelta        = clientServerDelta + latency / 2;

                    _frameDiff.Put((int)frameDelta);
                    var median = _frameDiff.Median();
                    var stdDev = _frameDiff.StandardDeviation();

                    if (System.Math.Abs(frameDelta) > 1 && frameDelta < (int)(median + stdDev))
                    {
                        Logger.Trace("Correcting for {0} frames.", frameDelta);

                        // Adjust the current frame of the simulation.
                        ScheduleFrameskip(frameDelta);
                    }
                }
                break;
            }

            case TssControllerMessage.HashCheck:
            {
                // Only accept these when they come from the server.
                if (args.IsAuthoritative)
                {
                    // Get the frame this hash data is for.
                    var hashFrame = args.Data.ReadInt64();
                    Debug.Assert(hashFrame > _lastServerHashedFrame);
                    _lastServerHashedFrame = hashFrame;

                    // Read hash values.
                    var hashValue = args.Data.ReadUInt32();

                    // And perform hash check.
                    PerformHashCheck(hashValue, hashFrame, Tss.TrailingFrame < _lastServerHashedFrame);
                }
                break;
            }

            case TssControllerMessage.GameState:
            {
                // Got a simulation snap shot (normally after requesting it due to
                // our simulation going out of scope for an older event).
                // Only accept these when they come from the server.
                if (args.IsAuthoritative)
                {
                    // Read data.
                    var serverHash = args.Data.ReadUInt32();
                    args.Data.ReadPacketizableInto(Tss);

                    // Validate the data we got.
                    var hasher = new Hasher();
                    hasher.Write(Tss.TrailingSimulation);
                    if (hasher.Value != serverHash)
                    {
                        Logger.Error("Hash mismatch after deserialization.");
                        Session.Leave();
                    }

                    // Run to current frame to avoid slow interpolation to current frame.
                    // Take into account the time we need to get there.
                    var delta = 0L;
                    do
                    {
                        // Remember when we started, see below.
                        var started = DateTime.UtcNow;

                        // Do the actual update, run to where we want to be.
                        Tss.RunToFrame(Tss.CurrentFrame + delta);

                        // See how long we took for this update, and compute the number
                        // of updates we'd otherwise have made in that time.
                        delta = (long)((DateTime.UtcNow - started).TotalMilliseconds / TargetElapsedMilliseconds);

                        // Continue until we're close enough with the *actual* current
                        // frame to what we want to be at.
                    } while (delta > 10);
                }
                break;
            }

            case TssControllerMessage.RemoveGameObject:
            {
                // Only accept these when they come from the server.
                if (args.IsAuthoritative)
                {
                    var removeFrame = args.Data.ReadInt64();
                    var entityUid   = args.Data.ReadInt32();
                    Tss.RemoveEntity(entityUid, removeFrame);
                }
                break;
            }
            }
            return(null);
        }
示例#8
0
 /// <summary>
 /// A server sent us a response to our request to join his game.
 /// </summary>
 /// <param name="sender">the underlying session.</param>
 /// <param name="e">information of the type <c>JoinResponseEventArgs</c>.</param>
 private void HandleJoinResponse(object sender, JoinResponseEventArgs e)
 {
     // OK, we were allowed to join, invalidate our simulation to request
     // the current state.
     Tss.Invalidate();
 }