protected override void ServerRead(VRage.Library.Collections.BitStream stream, ulong clientId,uint timestamp) { base.ServerRead(stream, clientId, timestamp); if (stream.ReadBool()) { if (m_grid != null) { bool isStatic = stream.ReadBool(); if (isStatic == false) { if (stream.ReadBool()) { long entityId = stream.ReadInt64(); Vector2 rotation = new Vector2(); rotation.X = stream.ReadFloat(); rotation.Y = stream.ReadFloat(); float roll = stream.ReadHalf(); Vector3 move = new Vector3(); move.X = stream.ReadHalf(); move.Y = stream.ReadHalf(); move.Z = stream.ReadHalf(); MyShipController controller; if (MyEntities.TryGetEntityById<MyShipController>(entityId, out controller)) { controller.CacheMoveAndRotate(ref move, ref rotation, roll); } } } } } }
protected override void ServerRead(VRage.Library.Collections.BitStream stream, ulong clientId,uint timestamp) { base.ServerRead(stream, clientId, timestamp); if (m_additionalServerClientData == null) { m_additionalServerClientData = new Dictionary<ulong, Vector3D>(); } m_additionalServerClientData[clientId] = stream.ReadVector3D(); if (stream.ReadBool()) { if (m_grid != null) { bool isStatic = stream.ReadBool(); if (isStatic == false) { if (stream.ReadBool()) { long entityId = stream.ReadInt64(); Vector2 rotation = new Vector2(); rotation.X = stream.ReadFloat(); rotation.Y = stream.ReadFloat(); float roll = stream.ReadHalf(); Vector3 move = new Vector3(); move.X = stream.ReadHalf(); move.Y = stream.ReadHalf(); move.Z = stream.ReadHalf(); Vector3D gridPos = Vector3D.Zero; MyShipController controller; if (MyEntities.TryGetEntityById<MyShipController>(entityId, out controller)) { controller.CacheMoveAndRotate(move, rotation, roll); gridPos = controller.CubeGrid.PositionComp.GetPosition(); } MyGridPhysicsStateGroup.ReadSubGrids(stream, timestamp,true,m_lowPositionOrientation,ref gridPos); } } } } }
protected override void CustomClientRead(uint timeStamp, ref MyTransformD serverPositionAndOrientation, VRage.Library.Collections.BitStream stream) { bool hasSupport = stream.ReadBool(); if (hasSupport) { long entityId = stream.ReadInt64(); Vector3D serverSupportPos = stream.ReadVector3D(); if (!MyEntities.EntityExists(entityId)) return; MyEntity support = MyEntities.GetEntityById(entityId); MyTimeStampValues? clientTransform = m_timestamp.GetTransform(timeStamp); Vector3D clientPosition = Vector3D.Zero; Vector3D clientSupportPosition = Vector3D.Zero; Quaternion rotationComp = Quaternion.Identity; if (clientTransform != null) { if(m_supportTimeStamp == null) { return; } MyTimeStampValues? supportTransform = m_supportTimeStamp.GetTransform(timeStamp); Vector3D supportPosition = support.PositionComp.WorldMatrix.Translation; if (supportTransform.HasValue) { supportPosition = supportTransform.Value.Transform.Position; if(supportTransform.Value.EntityId != entityId) { return; } } clientPosition = clientTransform.Value.Transform.Position; clientSupportPosition = supportPosition; rotationComp = Quaternion.Inverse(clientTransform.Value.Transform.Rotation); } else { m_character.PositionComp.SetWorldMatrix(serverPositionAndOrientation.TransformMatrix, null, true); return; } MyTransformD delta = new MyTransformD(); delta.Rotation = Quaternion.Identity; Vector3D characterDelta = serverPositionAndOrientation.Position - clientPosition; Vector3D supportDelta = serverSupportPos - clientSupportPosition; delta.Position = characterDelta - supportDelta; m_character.CacheMoveDelta(ref delta.Position); m_timestamp.UpdateDeltaPosition(timeStamp, ref delta); } else { base.CustomClientRead(timeStamp, ref serverPositionAndOrientation, stream); } }
protected override void ServerRead(VRage.Library.Collections.BitStream stream, ulong clientId, uint timestamp) { base.ServerRead(stream, clientId, timestamp); bool clientHasCharacter = stream.ReadBool(); if (clientHasCharacter) { MyEntity support; bool hasSupport = stream.ReadBool(); Vector3D supportPosition = Vector3D.Zero; if (m_character != null) { var physGroup = MyExternalReplicable.FindByObject(m_character).FindStateGroup<MyCharacterPhysicsStateGroup>(); if (physGroup != null) { m_support = MySupportHelper.FindSupportForCharacterAABB(m_character); physGroup.SetSupport(MySupportHelper.FindPhysics(m_support)); } } if (hasSupport) { long supportId = stream.ReadInt64(); bool apply = MyEntities.TryGetEntityById(supportId, out support); supportPosition = stream.ReadVector3D(); } if(m_additionalServerClientData == null) { m_additionalServerClientData = new Dictionary<ulong, ClientData>(); } m_additionalServerClientData[clientId] = new ClientData() { HasSupport = hasSupport, SupportPosition = supportPosition }; Vector3 move = new Vector3(); move.X = stream.ReadHalf(); move.Y = stream.ReadHalf(); move.Z = stream.ReadHalf(); Vector2 rotate = new Vector2(); rotate.X = stream.ReadFloat(); rotate.Y = stream.ReadFloat(); float roll = stream.ReadFloat(); MyCharacterMovementEnum MovementState = (MyCharacterMovementEnum)stream.ReadUInt16(); MyCharacterMovementFlags MovementFlag = (MyCharacterMovementFlags)stream.ReadUInt16(); bool Jetpack = stream.ReadBool(); bool Dampeners = stream.ReadBool(); bool Lights = stream.ReadBool(); // TODO: Remove bool Ironsight = stream.ReadBool(); bool Broadcast = stream.ReadBool(); // TODO: Remove bool TargetFromCamera = stream.ReadBool(); float headXAngle = stream.ReadFloat(); float headYAngle = stream.ReadFloat(); if(m_character == null) { return; } if (m_character.IsUsing != null) { return; } var jetpack = m_character.JetpackComp; if (jetpack != null) { if (Jetpack != jetpack.TurnedOn) { jetpack.TurnOnJetpack(Jetpack, true); } if (Dampeners != jetpack.DampenersTurnedOn) { jetpack.EnableDampeners(Dampeners, false); } } if (Lights != m_character.LightEnabled) { m_character.EnableLights(Lights); } if (m_character.RadioBroadcaster != null && Broadcast != m_character.RadioBroadcaster.Enabled) { m_character.EnableBroadcasting(Broadcast); } m_character.TargetFromCamera = TargetFromCamera; // Set client movement state directly and don't perform other operations // that may have side-effects to let server side Character.UpdateAfterSimulation() // perform exactly same operations as on client m_character.MovementFlags = MovementFlag; if (m_character.IsDead == false) { m_character.SetCurrentMovementState(MovementState); } m_character.HeadLocalXAngle = headXAngle; m_character.HeadLocalYAngle = headYAngle; if (m_commandsApplied == null) { m_commandsApplied = new Dictionary<ulong, bool>(); } if (Vector3.IsZero(move, 0.01f) == false || Vector2.IsZero(ref rotate, 0.01f) == false || Math.Abs(roll - 0.0) > 0.01f) { m_commandsApplied[clientId] = true; } m_character.CacheMove(ref move, ref rotate, ref roll); } }
void ClientRead(VRage.Library.Collections.BitStream stream) { bool hasClientData= stream.ReadBool(); uint? timeStamp = null; if (hasClientData) { timeStamp = stream.ReadUInt32(); m_lastRecievedTimeStamp = timeStamp.Value; bool isUpdate = stream.ReadBool(); if (isUpdate) { MyTransformD serverTransform = new MyTransformD(); serverTransform.Position = stream.ReadVector3D(); serverTransform.Rotation = Quaternion.Identity; CustomClientRead(timeStamp.Value, ref serverTransform, stream); } } Vector3 serverLinearVelocity = stream.ReadVector3(); Vector3 serverAngularVelocity = stream.ReadVector3(); MyTimeStampValues? clientData = null; if (timeStamp.HasValue) { clientData = m_timestamp.GetTransform(timeStamp.Value); } if (clientData.HasValue) { Vector3 linearDelta = serverLinearVelocity / MyEntityPhysicsStateGroup.EffectiveSimulationRatio - clientData.Value.LinearVelocity; Entity.Physics.LinearVelocity += Vector3.Round(linearDelta, 2); Vector3 angularDelta = serverAngularVelocity / MyEntityPhysicsStateGroup.EffectiveSimulationRatio - clientData.Value.AngularVelocity; Entity.Physics.AngularVelocity += Vector3.Round(angularDelta, 2); m_timestamp.UpdateDeltaVelocities(timeStamp.Value, ref linearDelta, ref angularDelta); } else { Vector3 linearVelocity = serverLinearVelocity / MyEntityPhysicsStateGroup.EffectiveSimulationRatio; Entity.Physics.LinearVelocity = Vector3.Round(linearVelocity, 2); Vector3 angularVelocity = serverAngularVelocity / MyEntityPhysicsStateGroup.EffectiveSimulationRatio; Entity.Physics.AngularVelocity = Vector3.Round(angularVelocity, 2); } }
protected override void CustomClientRead(uint timeStamp, ref MyTimeStampValues serverPositionAndOrientation, VRage.Library.Collections.BitStream stream) { bool hasSupport = stream.ReadBool(); if (hasSupport) { long entityId = stream.ReadInt64(); Vector3D serverDelta = stream.ReadVector3D(); Vector3D serverSupportPos = stream.ReadVector3D(); if (!MyEntities.EntityExists(entityId)) return; MyEntity support = MyEntities.GetEntityById(entityId); MyTimeStampValues? clientTransform = m_timestamp.GetTransform(timeStamp); Vector3D clientDelta = Vector3.Zero; Vector3D clientVelocity = Vector3D.Zero; Quaternion rotationComp = Quaternion.Identity; if (clientTransform != null) { if(m_supportTimeStamp == null) { return; } MyTimeStampValues? supportTransform = m_supportTimeStamp.GetTransform(timeStamp); Vector3D supportPosition = support.PositionComp.WorldMatrix.Translation; if (supportTransform.HasValue) { supportPosition = supportTransform.Value.Transform.Position; if(supportTransform.Value.EntityId != entityId) { supportPosition = serverSupportPos; return; } } clientDelta = supportPosition - clientTransform.Value.Transform.Position; clientVelocity = clientTransform.Value.LinearVelocity; rotationComp = Quaternion.Inverse(clientTransform.Value.Transform.Rotation); } else { m_character.PositionComp.SetWorldMatrix(serverPositionAndOrientation.Transform.TransformMatrix, null, true); return; } MyTimeStampValues delta = new MyTimeStampValues(); Quaternion.Multiply(ref serverPositionAndOrientation.Transform.Rotation, ref rotationComp, out delta.Transform.Rotation); delta.Transform.Position = clientDelta - serverDelta; delta.LinearVelocity = serverPositionAndOrientation.LinearVelocity - clientVelocity; double deltaL = delta.Transform.Position.Length(); //if difference is more than if (deltaL < (MyGridPhysics.ShipMaxLinearVelocity() * Sync.RelativeSimulationRatio)) { delta.Transform.Position = delta.Transform.Position * 0.2; delta.Transform.Rotation = Quaternion.Slerp(delta.Transform.Rotation,Quaternion.Identity,0.2f); } Quaternion normalized = delta.Transform.Rotation; normalized.Normalize(); delta.Transform.Rotation = normalized; normalized = serverPositionAndOrientation.Transform.Rotation; normalized.Normalize(); serverPositionAndOrientation.Transform.Rotation = normalized; Quaternion clientNormalized = clientTransform.Value.Transform.Rotation; clientNormalized.Normalize(); double eps = 0.001; bool hasJetpack = m_character.JetpackComp != null; if (hasJetpack && m_character.JetpackComp.TurnedOn && m_character.IsDead == false) { if (Math.Abs(Quaternion.Dot(serverPositionAndOrientation.Transform.Rotation, clientNormalized)) < 1 - eps ) { Quaternion currentOrientation = Quaternion.CreateFromForwardUp(m_character.WorldMatrix.Forward, m_character.WorldMatrix.Up); Quaternion.Multiply(ref delta.Transform.Rotation, ref currentOrientation, out currentOrientation); MatrixD matrix = MatrixD.CreateFromQuaternion(currentOrientation); MatrixD currentMatrix = m_character.PositionComp.WorldMatrix; currentMatrix.Translation = Vector3D.Zero; if (currentMatrix.EqualsFast(ref matrix) == false) { if (m_character.Physics.CharacterProxy != null) { m_character.Physics.CharacterProxy.Forward = matrix.Forward; m_character.Physics.CharacterProxy.Up = matrix.Up; } } } } if (deltaL > (MyGridPhysics.ShipMaxLinearVelocity() * Sync.RelativeSimulationRatio)) { m_character.PositionComp.SetPosition(serverPositionAndOrientation.Transform.Position); m_character.Physics.LinearVelocity = serverPositionAndOrientation.LinearVelocity; m_timestamp.OverwriteServerPosition(timeStamp, ref serverPositionAndOrientation); return; } else if (deltaL > 5.0f*MyTimestampHelper.POSITION_TOLERANCE) { m_character.CacheMoveDelta(ref delta.Transform.Position); } m_character.Physics.LinearVelocity += delta.LinearVelocity; m_timestamp.UpdateDeltaPosition(timeStamp, ref delta); } else { base.CustomClientRead(timeStamp, ref serverPositionAndOrientation, stream); } }
protected override void ServerRead(VRage.Library.Collections.BitStream stream, ulong clientId, uint timestamp) { base.ServerRead(stream, clientId, timestamp); bool clientHasCharacter = stream.ReadBool(); if (clientHasCharacter) { MyEntity support; if (stream.ReadBool()) { bool apply = MyEntities.TryGetEntityById(stream.ReadInt64(), out support); if (m_character != null) { var physGroup = MyExternalReplicable.FindByObject(m_character).FindStateGroup<MyCharacterPhysicsStateGroup>(); if (physGroup != null && apply) { physGroup.SetSupport(MySupportHelper.FindPhysics(support)); } } } Vector3 move = new Vector3(); move.X = stream.ReadHalf(); move.Y = stream.ReadHalf(); move.Z = stream.ReadHalf(); Vector2 rotate = new Vector2(); rotate.X = stream.ReadFloat(); rotate.Y = stream.ReadFloat(); float roll = stream.ReadFloat(); MyCharacterMovementEnum MovementState = (MyCharacterMovementEnum)stream.ReadUInt16(); MyCharacterMovementFlags MovementFlag = (MyCharacterMovementFlags)stream.ReadUInt16(); bool Jetpack = stream.ReadBool(); bool Dampeners = stream.ReadBool(); bool Lights = stream.ReadBool(); // TODO: Remove bool Ironsight = stream.ReadBool(); bool Broadcast = stream.ReadBool(); // TODO: Remove bool TargetFromCamera = stream.ReadBool(); float headXAngle = stream.ReadFloat(); float headYAngle = stream.ReadFloat(); Quaternion rotation = Quaternion.Identity; if (Jetpack == false) { rotation = stream.ReadQuaternionNorm(); } if(m_character == null) { return; } if (m_character.IsDead || m_character.IsUsing != null) { return; } var jetpack = m_character.JetpackComp; if (jetpack != null) { if (Jetpack != jetpack.TurnedOn) { jetpack.TurnOnJetpack(Jetpack, true); } if (Dampeners != jetpack.DampenersTurnedOn) { jetpack.EnableDampeners(Dampeners, false); } } if (Lights != m_character.LightEnabled) { m_character.EnableLights(Lights); } if (m_character.RadioBroadcaster != null && Broadcast != m_character.RadioBroadcaster.Enabled) { m_character.EnableBroadcasting(Broadcast); } m_character.TargetFromCamera = TargetFromCamera; // Set client movement state directly and don't perform other operations // that may have side-effects to let server side Character.UpdateAfterSimulation() // perform exactly same operations as on client m_character.MovementFlags = MovementFlag; m_character.SetCurrentMovementState(MovementState); m_character.HeadLocalXAngle = headXAngle; m_character.HeadLocalYAngle = headYAngle; m_character.CacheMove(ref move, ref rotate, ref roll); if (Jetpack == false) { m_character.CacheRotation(ref rotation); } } }