private static PositionUpdateMsg CreatePositionMsg(MyEntity entity) { var m = entity.WorldMatrix; PositionUpdateMsg msg = new PositionUpdateMsg(); msg.EntityId = entity.EntityId; msg.Orientation = new HalfVector4(Quaternion.CreateFromForwardUp(m.Forward, m.Up).ToVector4()); msg.Position = m.Translation; if (entity.Physics != null) { if (MyPerGameSettings.EnableMultiplayerVelocityCompensation) { float ratio = MathHelper.Clamp(Sandbox.Engine.Physics.MyPhysics.SimulationRatio, 0, 2); msg.LinearVelocity = entity.Physics.LinearVelocity * ratio; msg.AngularVelocity = entity.Physics.AngularVelocity * ratio; } else { msg.LinearVelocity = entity.Physics.LinearVelocity; msg.AngularVelocity = entity.Physics.AngularVelocity; } } return(msg); }
internal virtual void OnPositionUpdate(ref PositionUpdateMsg msg, MyNetworkClient sender) { // Validate that client sending position update to server is reponsible for update if (Sync.IsServer && !ResponsibleForUpdate(sender)) { return; } if (!Sync.IsServer && ResponsibleForUpdate(Sync.Clients.LocalClient)) { return; } var q = msg.Orientation; var m = Matrix.CreateFromQuaternion(q); var world = MatrixD.CreateWorld(msg.Position, m.Forward, m.Up); Debug.Assert(Entity.PositionComp != null, "Entity doesn't not have position component"); if (Entity.PositionComp != null) { Entity.PositionComp.SetWorldMatrix(world, this); } if (Entity.Physics != null) { Entity.Physics.LinearVelocity = msg.LinearVelocity; Entity.Physics.AngularVelocity = msg.AngularVelocity; if (MyPerGameSettings.EnableMultiplayerVelocityCompensation) { float ratio = MathHelper.Clamp(Sandbox.Engine.Physics.MyPhysics.SimulationRatio, 0.1f, 2); Entity.Physics.LinearVelocity /= ratio; Entity.Physics.AngularVelocity /= ratio; } Entity.Physics.UpdateAccelerations(); if (!Entity.Physics.IsMoving && Entity.Physics.RigidBody != null && Entity.Physics.RigidBody.IsAddedToWorld) { Entity.Physics.RigidBody.Deactivate(); } } if (Sync.IsServer) { MarkPhysicsDirty(); } else { // Store last update from server m_isLocallyDirty = false; m_lastUpdateFrame = MyMultiplayer.Static.FrameCounter; m_lastServerPosition = msg.Position; m_lastServerOrientation = msg.Orientation; } }
internal virtual void OnPositionUpdate(ref PositionUpdateMsg msg, MyNetworkClient sender) { Debug.Assert(false == false, "When interpolation enabled, this should not be called"); if (!ResponsibleForUpdate(sender)) { // This happens when server just accepted state change (e.g. enter cockpit), but some messages about character position will come eventually from client return; } ResetUpdateTimer(); var q = Quaternion.FromVector4(msg.Orientation.ToVector4()); var m = Matrix.CreateFromQuaternion(q); m_interpolator.TargetMatrix = MatrixD.CreateWorld(msg.Position, m.Forward, m.Up); m_interpolator.CurrentMatrix = Entity.WorldMatrix; m_interpolator.Time = 0; MyMultiplayer.Static.RegisterForTick(this); Debug.Assert(Entity.PositionComp != null, "Entity doesn't not have position component"); if (Entity.PositionComp != null) { Entity.PositionComp.SetWorldMatrix(m_interpolator.TargetMatrix, this); } if (Entity.Physics != null) { Entity.Physics.LinearVelocity = msg.LinearVelocity; Entity.Physics.AngularVelocity = msg.AngularVelocity; if (MyPerGameSettings.EnableMultiplayerVelocityCompensation) { float ratio = MathHelper.Clamp(Sandbox.Engine.Physics.MyPhysics.SimulationRatio, 0.1f, 2); Entity.Physics.LinearVelocity /= ratio; Entity.Physics.AngularVelocity /= ratio; } Entity.Physics.UpdateAccelerations(); if (!Entity.Physics.IsMoving && Entity.Physics.RigidBody != null && Entity.Physics.RigidBody.IsAddedToWorld) { Entity.Physics.RigidBody.Deactivate(); } } }
private void SendPositionUpdate() { float epsilonSq = 0.05f * 0.05f; if (m_updateFrameCount == ConstantMovementUpdateCount && (Entity.Physics == null || Entity.Physics.LinearAcceleration.LengthSquared() > epsilonSq || Entity.Physics.AngularAcceleration.LengthSquared() > epsilonSq)) { m_updateFrameCount = DefaultUpdateCount; } if (MyMultiplayer.Static != null && MyMultiplayer.Static.FrameCounter - m_lastUpdateFrame >= m_updateFrameCount) { m_updateFrameCount = ConstantMovementUpdateCount; // TODO: abstraction would be nice var syncGrid = this as MySyncGrid; if (syncGrid != null) { var g = MyCubeGridGroups.Static.Physical.GetGroup(syncGrid.Entity); PositionUpdateBatchMsg msg = new PositionUpdateBatchMsg(); msg.Positions = new List <PositionUpdateMsg>(g.Nodes.Count); foreach (var node in g.Nodes) { msg.Positions.Add(CreatePositionMsg(node.NodeData)); node.NodeData.SyncObject.ResetUpdateTimer(); node.NodeData.SyncObject.m_positionDirty = false; } MySession.Static.SyncLayer.SendMessageToAll(ref msg); } else { ResetUpdateTimer(); PositionUpdateMsg msg = CreatePositionMsg(Entity); MySession.Static.SyncLayer.SendMessageToAll(ref msg); } m_positionDirty = false; } else if (MyMultiplayer.Static != null) { MyMultiplayer.Static.RegisterForTick(this); m_positionDirty = true; } }
/// <summary> /// Serializes sync entity physics, default implementation serializes position, orientation, linear and angular velocity. /// </summary> public virtual void SerializePhysics(BitStream stream, MyNetworkClient sender, bool highOrientationCompression = false) { PositionUpdateMsg msg = stream.Writing ? CreatePositionMsg(Entity) : default(PositionUpdateMsg); stream.Serialize(ref msg.Position); // 24B if (highOrientationCompression) { stream.SerializeNormCompressed(ref msg.Orientation); // 29b } else { stream.SerializeNorm(ref msg.Orientation); // 52b } stream.Serialize(ref msg.LinearVelocity); // 6B stream.Serialize(ref msg.AngularVelocity); // 6B if (stream.Reading) { OnPositionUpdate(ref msg, sender); } }
static void UpdateCallback(MySyncEntity sync, ref PositionUpdateMsg msg, MyNetworkClient sender) { sync.OnPositionUpdate(ref msg, sender); }
internal override void OnPositionUpdate(ref PositionUpdateMsg msg, MyNetworkClient sender) {//TODO consider removing this after new netcode implementation if (Entity.PositionComp != null && Entity.GridSystems.JumpSystem != null) if (!Entity.GridSystems.JumpSystem.CheckReceivedCoordinates(ref msg.Position)) return; base.OnPositionUpdate(ref msg, sender); }
private void SendPositionUpdate() { if (MyMultiplayer.Static == null) { return; } Debug.Assert(MySandboxGame.Static != null); float epsilonSq = 0.05f * 0.05f; if (m_updateFrameCount == ConstantMovementUpdateCount && (Entity.Physics == null || Entity.Physics.LinearAcceleration.LengthSquared() > epsilonSq || Entity.Physics.AngularAcceleration.LengthSquared() > epsilonSq)) { m_updateFrameCount = DefaultUpdateCount; } bool timeForUpdate; if (MyFakes.NEW_POS_UPDATE_TIMING) { timeForUpdate = (MySandboxGame.Static.UpdateTime - m_lastUpdateTime).Seconds > (m_updateFrameCount / MyEngineConstants.UPDATE_STEPS_PER_SECOND); } else { timeForUpdate = MyMultiplayer.Static.FrameCounter - m_lastUpdateFrame >= m_updateFrameCount; } if (timeForUpdate) { m_updateFrameCount = ConstantMovementUpdateCount; // TODO: abstraction would be nice var syncGrid = this as MySyncGrid; if (syncGrid != null) { var g = MyCubeGridGroups.Static.Physical.GetGroup(syncGrid.Entity); PositionUpdateBatchMsg msg = new PositionUpdateBatchMsg(); msg.Positions = new List <PositionUpdateMsg>(g.Nodes.Count); foreach (var node in g.Nodes) { msg.Positions.Add(CreatePositionMsg(node.NodeData)); node.NodeData.SyncObject.ResetUpdateTimer(); node.NodeData.SyncObject.m_positionDirty = false; } MySession.Static.SyncLayer.SendMessageToAll(ref msg); } else { ResetUpdateTimer(); PositionUpdateMsg msg = CreatePositionMsg(Entity); MySession.Static.SyncLayer.SendMessageToAll(ref msg); } m_positionDirty = false; } else if (MyMultiplayer.Static != null) { MyMultiplayer.Static.RegisterForTick(this); m_positionDirty = true; } }
internal virtual void OnPositionUpdate(ref PositionUpdateMsg msg, MyNetworkClient sender) { // Validate that client sending position update to server is reponsible for update if (Sync.IsServer && !ResponsibleForUpdate(sender)) return; if (!Sync.IsServer && ResponsibleForUpdate(Sync.Clients.LocalClient)) return; var q = msg.Orientation; var m = Matrix.CreateFromQuaternion(q); var world = MatrixD.CreateWorld(msg.Position, m.Forward, m.Up); Debug.Assert(Entity.PositionComp != null, "Entity doesn't not have position component"); if (Entity.PositionComp != null) Entity.PositionComp.SetWorldMatrix(world, this); if (Entity.Physics != null) { Entity.Physics.LinearVelocity = msg.LinearVelocity; Entity.Physics.AngularVelocity = msg.AngularVelocity; if (MyPerGameSettings.EnableMultiplayerVelocityCompensation) { float ratio = MathHelper.Clamp(Sandbox.Engine.Physics.MyPhysics.SimulationRatio, 0.1f, 2); Entity.Physics.LinearVelocity /= ratio; Entity.Physics.AngularVelocity /= ratio; } Entity.Physics.UpdateAccelerations(); if (!Entity.Physics.IsMoving && Entity.Physics.RigidBody != null && Entity.Physics.RigidBody.IsAddedToWorld) { Entity.Physics.RigidBody.Deactivate(); } } if (Sync.IsServer) { MarkPhysicsDirty(); } else { // Store last update from server m_isLocallyDirty = false; m_lastUpdateFrame = MyMultiplayer.Static.FrameCounter; m_lastServerPosition = msg.Position; m_lastServerOrientation = msg.Orientation; } }
internal static PositionUpdateMsg CreatePositionMsg(IMyEntity entity) { var m = entity.WorldMatrix; PositionUpdateMsg msg = new PositionUpdateMsg(); msg.EntityId = entity.EntityId; msg.Orientation = Quaternion.CreateFromForwardUp(m.Forward, m.Up); msg.Position = m.Translation; if (entity.Physics != null) { if (MyPerGameSettings.EnableMultiplayerVelocityCompensation) { float ratio = MathHelper.Clamp(Sandbox.Engine.Physics.MyPhysics.SimulationRatio, 0, 2); msg.LinearVelocity = entity.Physics.LinearVelocity * ratio; msg.AngularVelocity = entity.Physics.AngularVelocity * ratio; } else { msg.LinearVelocity = entity.Physics.LinearVelocity; msg.AngularVelocity = entity.Physics.AngularVelocity; } } return msg; }