MyEntityPhysicsStateGroup FindSupport()
 {
     return(MySupportHelper.FindSupportForCharacter(Instance));
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Serializes physics and takes into account support (what's entity standing on)
        /// </summary>
        private void SerializePhysicsWithSupport(BitStream stream, EndpointId forClient, uint timestamp, byte packetId, int maxBitPosition)
        {
            if (stream.Writing)
            {
                // TODO: only prototype implementation
                SetSupport(FindSupportDelegate());

                stream.WriteBool(m_supportPhysics != null);
                if (m_supportPhysics != null)
                {
                    stream.WriteInt64(m_supportPhysics.Entity.EntityId);
                    var localToParent = Entity.WorldMatrix * MatrixD.Invert(m_supportPhysics.Entity.PositionComp.WorldMatrix);
                    stream.Write(localToParent.Translation);
                    stream.Write(Quaternion.CreateFromForwardUp(localToParent.Forward, localToParent.Up).ToVector4());
                    bool moving = IsMoving(Entity);
                    stream.WriteBool(moving);

                    SerializeVelocities(stream, Entity, EffectiveSimulationRatio, !IsControlledLocally, moving);
                }
                else
                {
                    base.Serialize(stream, forClient, timestamp, packetId, maxBitPosition);
                }
            }
            else
            {
                if (stream.ReadBool())
                {
                    MyEntity support;
                    bool     apply = MyEntities.TryGetEntityById(stream.ReadInt64(), out support) && !IsControlledLocally;

                    var pos    = stream.ReadVector3D();
                    var orient = Quaternion.FromVector4(stream.ReadVector4());

                    if (apply)
                    {
                        var old = Entity.PositionComp.WorldMatrix;

                        MatrixD localToParent = MatrixD.CreateFromQuaternion(orient);
                        localToParent.Translation = pos;
                        MatrixD matrix = localToParent * support.WorldMatrix;
                        Entity.PositionComp.SetWorldMatrix(matrix, null, true);

                        SetSupport(MySupportHelper.FindPhysics(support));

                        var handler = MoveHandler;
                        if (handler != null)
                        {
                            handler(ref old, ref matrix);
                        }
                    }
                    else
                    {
                        SetSupport(null);
                    }
                    bool moving = stream.ReadBool();
                    SerializeVelocities(stream, Entity, EffectiveSimulationRatio, apply, moving);
                }
                else
                {
                    SetSupport(null);
                    base.Serialize(stream, forClient, timestamp, packetId, maxBitPosition);
                }
            }
        }
 public MySmallObjectPhysicsStateGroup(MyEntity entity, IMyReplicable owner)
     : base(entity, owner)
 {
     m_positionValidation = ValidatePosition;
     FindSupportDelegate  = () => MySupportHelper.FindSupportForCharacter(Entity);
 }
        void ServerWrite(VRage.Library.Collections.BitStream stream, ulong clientId)
        {
            bool clientUpdate = m_clientUpdateFlag[clientId];

            stream.WriteBool(clientUpdate);
            if (clientUpdate)
            {
                ClientData clientData = m_serverClientData[clientId];
                m_clientUpdateFlag[clientId] = false;

                stream.WriteUInt32(clientData.TimeStamp);

                MyTransformD serverData = new MyTransformD(Entity.WorldMatrix);


                //rotation is calculated same way for both
                Quaternion serverRotation = serverData.Rotation;
                serverRotation.Normalize();
                clientData.Transform.Rotation.Normalize();

                MyTimeStampValues delta = new MyTimeStampValues();

                serverRotation = Quaternion.Inverse(serverRotation);
                Quaternion.Multiply(ref clientData.Transform.Rotation, ref serverRotation, out delta.Transform.Rotation);

                bool   applyRotation = false;
                double eps           = 0.001;
                if (Math.Abs(Quaternion.Dot(clientData.Transform.Rotation, serverData.Rotation)) < 1 - eps)
                {
                    applyRotation = true;
                }

                bool isValidPosition       = true;
                bool correctServerPosition = false;

                CalculatePositionDifference(clientId, out isValidPosition, out correctServerPosition, out delta.Transform.Position);

                bool isValidClientPosition = isValidPosition;

                if ((correctServerPosition && isValidPosition) || applyRotation)
                {
                    MatrixD matrix           = Entity.WorldMatrix;
                    MatrixD correctionMatrix = MatrixD.Multiply(matrix.GetOrientation(), delta.Transform.TransformMatrix);
                    correctionMatrix.Translation += Entity.WorldMatrix.Translation;

                    if (correctServerPosition)
                    {
                        isValidClientPosition = IsPositionValid(new MyTransformD(correctionMatrix));
                    }

                    if (isValidClientPosition)
                    {
                        Entity.PositionComp.SetWorldMatrix(correctionMatrix, null, true);
                        MyEntityPhysicsStateGroup support = MySupportHelper.FindPhysics(Entity);
                        if (support != null && support.MoveHandler != null)
                        {
                            support.MoveHandler(ref matrix, ref correctionMatrix);
                        }
                    }
                    else if (applyRotation)
                    {
                        correctionMatrix.Translation = Entity.WorldMatrix.Translation;
                        Entity.PositionComp.SetWorldMatrix(correctionMatrix, null, true);
                    }
                }

                stream.WriteBool(!isValidClientPosition);

                if (!isValidClientPosition)
                {
                    serverData = new MyTransformD(Entity.WorldMatrix);
                    stream.Write(serverData.Position);

                    CustomServerWrite(m_serverClientData[clientId].TimeStamp, clientId, stream);
                }
            }

            stream.Write(Entity.Physics != null ? Entity.Physics.LinearVelocity * MyEntityPhysicsStateGroup.EffectiveSimulationRatio : Vector3.Zero);
            stream.Write(Entity.Physics != null ? Entity.Physics.AngularVelocity * MyEntityPhysicsStateGroup.EffectiveSimulationRatio : Vector3.Zero);
        }
        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);
                }
            }
        }