public PartialGameStateUpdateAction(GameCore game, PseudoFullGameWorldState last = null) { if (last != null) { StatePartial = PseudoFullGameWorldState.Create(game).MakeDelta(last); } else { StatePartial = PseudoFullGameWorldState.Create(game); } }
public ServerPlayer AddPlayer(ServerPlayer player) { if (Players.Contains(player)) { return(player); } player.Player.Id = Game.AvailablePlayerId; Game.AddPlayer(player.Player); _players.Add(player); //Queue the game state for them, delaying 1sec for connect messages to be processed fully Timers.CreateTimer(a => { MessageProcessor.SendPrivateMessage(player, new GameCreatedAction()); MessageProcessor.SendPrivateMessage(player, new FullGameStateSentAction(Game)); }, TimeSpan.FromSeconds(1)); //Announce that they joined ChatHandler.SendMessage($"{player.Player.Username} joined the server"); player.LastSentState = PseudoFullGameWorldState.Create(Game); player.Player.OnPropertyChanged -= Player_PropertyChanged; player.Player.OnPropertyChanged += Player_PropertyChanged; MessageProcessor.SendMessage(new PlayerUpdateAction(player.Player, Game)); //Create a state sync loop Timers.CreateReccuringTimer(t => { if (Players.Contains(player)) { var message = new PartialGameStateUpdateAction(Game, player.LastSentState); player.LastSentState = message.StatePartial; //do state sync MessageProcessor.SendPrivateMessage(player, message); } else { //Disconnect Timers.RemoveTimer(t); } }, Configuration.StateSyncRate); //Special case for hotjoin if (Game.HasStarted && Game.Gamemode.HotJoinEnabled) { var time = ServerSettings.Instance.TimeToWaitForPlayersReady.Value; Timers.CreateReccuringTimer((t) => { if (!Game.Running || !Game.Gamemode.HotJoinEnabled) { t.Remove(); } MessageProcessor.SendPrivateMessage(player, new CountdownStartedAction(time)); time -= TimeSpan.FromMilliseconds(16.666); if (time < TimeSpan.Zero) { t.Remove(); } if (player.IsReady) { t.Remove(); MessageProcessor.SendPrivateMessage(player, new CountdownStartedAction(TimeSpan.FromSeconds(-1))); } }, TimeSpan.FromSeconds(0.01)); } return(player); }
public PseudoFullGameWorldState GetDeltaState(PseudoFullGameWorldState lastSentState) => CurrentState.MakeDelta(lastSentState);
public void Compute(GameCore game, PseudoFullGameWorldState state) { ElapsedTime = TimeSpan.Zero; _game = game; _corrections.Clear(); foreach (var obj in state.ObjectStates) { if (_game.GameObjectsById.ContainsKey(obj.Key)) { var gameObj = _game.GameObjectsById[obj.Key]; if (!obj.Value.PositionChanged && !obj.Value.RotationChanged) { continue; } //Handle destroyed if (obj.Value.WasDestroyed) { game.ImmediatelyForceObjectDestruction(gameObj); continue; } //Apply the non interpolated updates gameObj.IsSensor = obj.Value.IsSensorObject; gameObj.IsStatic = obj.Value.IsStaticObject; if (obj.Value.RestitutionChanged) { gameObj.Restitution = obj.Value.Restitution; } if (obj.Value.RotationChanged) { gameObj.Rotation = obj.Value.Rotation; } if (obj.Value.RotationVelocityChanged) { gameObj.AngularVelocity = obj.Value.RotationVelocity; } if (obj.Value.SizeChanged) { gameObj.Size = obj.Value.Size.ToVector2(); } if (obj.Value.VelocityChanged) { gameObj.LinearVelocity = obj.Value.Velocity.ToVector2(); } Vector2 dist; if (obj.Value.PositionChanged) { dist = obj.Value.Position - gameObj.Position; } else { dist = Vector2.Zero; } float rot; if (obj.Value.RotationChanged) { rot = obj.Value.Rotation - gameObj.Rotation; } else { rot = 0; } //Apply directly if it's too large if (DistanceCorrectionLimit < Math.Abs(dist.X) || DistanceCorrectionLimit < Math.Abs(dist.Y) || RotationCorrectionLimit < rot) { gameObj.Position = obj.Value.Position; gameObj.Rotation = obj.Value.Rotation; } else { //Correct slowly if it's small var corr = new PseudoStateObjectCorrection(); corr.DistanceOffset = dist; corr.RotationOffset = rot; corr.Object = gameObj; _corrections.Add(corr); } } } }
protected override void DeserializeInternal(NetIncomingMessage message) { StatePartial = PseudoFullGameWorldState.Read(message); }