public override void SerializePhysics(BitStream stream, MyNetworkClient sender, bool highOrientationCompression = false) { // Serialize base base.SerializePhysics(stream, sender); Vector3D pos = Entity.WorldMatrix.Translation; if (stream.Writing) { var g = MyCubeGridGroups.Static.Physical.GetGroup(Entity); stream.WriteByte((byte)(g.Nodes.Count - 1)); // Ignoring self foreach (var node in g.Nodes) { // Ignore self, already serialized if (node.NodeData != Entity) { var target = MyMultiplayer.Static.ReplicationLayer.GetProxyTarget((IMyEventProxy)node.NodeData); // ~26.5 bytes per grid, not bad NetworkId networkId = MyMultiplayer.Static.ReplicationLayer.GetNetworkIdByObject(target); PositionUpdateMsg msg = CreatePositionMsg(node.NodeData); stream.WriteNetworkId(networkId); // ~2 bytes HalfVector3 posDelta = (HalfVector3)(Vector3)(msg.Position - pos); stream.Serialize(ref posDelta); // 6 bytes stream.SerializeNorm(ref msg.Orientation); // 6.5 bytes stream.Serialize(ref msg.LinearVelocity); // 6 bytes stream.Serialize(ref msg.AngularVelocity); // 6 bytes } } } else { byte numRecords = stream.ReadByte(); for (int i = 0; i < numRecords; i++) { PositionUpdateMsg msg = default(PositionUpdateMsg); NetworkId networkId = stream.ReadNetworkId(); HalfVector3 posDelta = default(HalfVector3); stream.Serialize(ref posDelta); msg.Position = posDelta + pos; stream.SerializeNorm(ref msg.Orientation); stream.Serialize(ref msg.LinearVelocity); stream.Serialize(ref msg.AngularVelocity); MyCubeGrid grid = MyMultiplayer.Static.ReplicationLayer.GetObjectByNetworkId(networkId) as MyCubeGrid; if (grid != null) { grid.SyncObject.OnPositionUpdate(ref msg, sender); } } } }
void Read(BitStream stream) { // TODO: Read additional client data, context MyNetworkClient sender; if (!Sync.Clients.TryGetClient(EndpointId.Value, out sender)) { Debug.Fail("Unknown sender"); return; } var hasControlledEntity = stream.ReadBool(); if (hasControlledEntity == false) { Vector3D pos = Vector3D.Zero; stream.Serialize(ref pos); // 24B Position = pos; } else { int numEntity = 0; if (stream.BytePosition < stream.ByteLength) { var entityId = stream.ReadInt64(); MyEntity entity; if (!MyEntities.TryGetEntityById(entityId, out entity)) return; MySyncEntity syncEntity = entity.SyncObject as MySyncEntity; if (syncEntity == null) return; Context = (MyContextKind)stream.ReadInt32(2); switch (Context) { case MyContextKind.Inventory: entityId = stream.ReadInt64(); break; case MyContextKind.Terminal: entityId = stream.ReadInt64(); break; case MyContextKind.Production: entityId = stream.ReadInt64(); break; default: entityId = stream.ReadInt64(); break; } MyEntities.TryGetEntityById(entityId, out entity); ContextEntity = entity; if (!syncEntity.ResponsibleForUpdate(sender)) { // Also happens when entering cockpit due to order of operations and responsibility update change //Debug.Fail("Server sending entity update for entity controlled by client, should happen only very rarely (packets out-of-order)"); return; } syncEntity.SerializePhysics(stream, sender); if (numEntity == 0) { Position = syncEntity.Entity.WorldMatrix.Translation; } numEntity++; } } }
/// <summary> /// Shared area for SE and ME. So far it writes whether you have a controlled entity or not. In the latter case you get the spectator position /// </summary> /// <param name="stream"></param> /// <param name="validControlledEntity"></param> private void WriteShared(BitStream stream, MyEntity controlledEntity) { stream.WriteBool(controlledEntity != null); if (controlledEntity == null) { Vector3D pos = MySpectatorCameraController.Static.Position; stream.Serialize(ref pos); } else { stream.WriteInt64(controlledEntity.EntityId); } }
private void ReadShared(BitStream stream, MyNetworkClient sender, out MyEntity controlledEntity) { controlledEntity = null; var hasControlledEntity = stream.ReadBool(); if (!hasControlledEntity) { Vector3D pos = Vector3D.Zero; stream.Serialize(ref pos); // 24B Position = pos; } else { var entityId = stream.ReadInt64(); MyEntity entity; if (!MyEntities.TryGetEntityById(entityId, out entity)) return; Position = entity.WorldMatrix.Translation; // TODO: Obsolete check? MySyncEntity syncEntity = entity.SyncObject as MySyncEntity; if (syncEntity == null) return; controlledEntity = entity; } }
protected bool SerializeServerTransform(BitStream stream, MyEntity entity, Vector3D? deltaPosBase, bool movingOnServer, uint timeStamp, bool lowPrecisionOrientation, float positionTolerancy, ref Vector3D outPosition, ref Quaternion outOrientation, ref MatrixD outWorldMartix, Func<MyEntity, Vector3D, bool> posValidation = null) { stream.Serialize(ref timeStamp); if (stream.Writing) { WriteTransform(stream, entity, deltaPosBase, lowPrecisionOrientation); return true; } else { bool apply = ReadTransform(stream, entity, deltaPosBase, true, movingOnServer,ref outPosition, ref outOrientation, ref outWorldMartix, posValidation); return apply; } }
/// <summary> /// Serializes transform into 10 to 30.5 bytes. /// </summary> protected bool SerializeTransform(BitStream stream, MyEntity entity, Vector3D? deltaPosBase, bool lowPrecisionOrientation, bool applyWhenReading, bool movingOnServer, uint timeStamp, Func<MyEntity, Vector3D, bool> posValidation = null, MovedDelegate moveHandler = null) { stream.Serialize(ref timeStamp); if(stream.Writing) { WriteTransform(stream, entity, deltaPosBase, lowPrecisionOrientation); return true; } else { bool apply = ReadTransform(stream, entity, deltaPosBase, applyWhenReading,movingOnServer, ref m_readTranslation, ref m_readQuaternion, ref m_readMatrix, posValidation, moveHandler); if (apply) { var old = entity.PositionComp.WorldMatrix; entity.PositionComp.SetWorldMatrix(m_readMatrix, null); if (moveHandler != null) { moveHandler(ref old, ref m_readMatrix); } } return apply; } }
/// <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); } }