private void SerializeRopeData(BitStream stream, bool applyWhenReading, List<MyCubeGrid> gridsGroup = null) { if (MyRopeComponent.Static == null) return; if (stream.Writing) { m_tmpRopes.Clear(); m_tmpRopeGrids.Clear(); m_tmpRopeGrids.Add(Entity); Debug.Assert(gridsGroup != null); if (gridsGroup != null) { foreach (var grid in gridsGroup) m_tmpRopeGrids.Add(grid); } MyRopeComponent.Static.GetRopesForGrids(m_tmpRopeGrids, m_tmpRopes); MyRopeData ropeData; stream.WriteUInt16((ushort)m_tmpRopes.Count); foreach (var rope in m_tmpRopes) { var ropeProxyTarget = MyMultiplayer.Static.ReplicationLayer.GetProxyTarget((IMyEventProxy)rope); NetworkId ropeNetworkId = MyMultiplayer.Static.ReplicationLayer.GetNetworkIdByObject(ropeProxyTarget); stream.WriteNetworkId(ropeNetworkId); //TODO - MyRopeComponent should be rewritten to singleton MyRopeComponent.GetRopeData(rope.EntityId, out ropeData); stream.WriteFloat(ropeData.CurrentRopeLength); } m_tmpRopes.Clear(); m_tmpRopeGrids.Clear(); } else { uint ropesCount = stream.ReadUInt16(); for (uint i = 0; i < ropesCount; ++i) { NetworkId ropeNetworkId = stream.ReadNetworkId(); float ropeLength = stream.ReadFloat(); MyRopeReplicable replicable = MyMultiplayer.Static.ReplicationLayer.GetObjectByNetworkId(ropeNetworkId) as MyRopeReplicable; MyRope rope = replicable != null ? replicable.Instance : null; if (rope != null && applyWhenReading) MyRopeComponent.Static.SetRopeLengthSynced(rope.EntityId, ropeLength); } } }
public override bool Serialize(BitStream stream, EndpointId forClient,uint timestamp, byte packetId, int maxBitPosition) { // Client does not care about slave grids, he always synced group through controlled object Debug.Assert(stream.Reading || !Sync.IsServer || Entity == GetMasterGrid(Entity), "Writing data from SlaveGrid!"); bool apply = !IsControlledLocally; bool moving = false; if (stream.Writing) { moving = IsMoving(Entity); stream.WriteBool(moving); } else { moving = stream.ReadBool(); } // Serialize this grid apply = SerializeTransform(stream, Entity, null, m_lowPrecisionOrientation, apply,moving, timestamp, m_positionValidation, MoveHandler); SerializeVelocities(stream, Entity, EffectiveSimulationRatio, apply, moving,VelocityHandler); // Serialize other grids in group Vector3D basePos = Entity.WorldMatrix.Translation; if (stream.Writing) { bool fullyWritten = true; UpdateGridMaxSpeed(Entity, Sync.IsServer); var g = MyCubeGridGroups.Static.PhysicalDynamic.GetGroup(Entity); if (g == null) { stream.WriteBool(false); } else { m_groups.Clear(); int i = 0; foreach (var node in g.Nodes) { i++; if (ResponsibleForUpdate(node.NodeData, forClient)) { continue; } if(i < m_currentSentPosition) { continue; } var target = MyMultiplayer.Static.ReplicationLayer.GetProxyTarget((IMyEventProxy)node.NodeData); int pos = stream.BitPosition; if (node.NodeData != Entity && !node.NodeData.IsStatic && target != null) { stream.WriteBool(true); // ~26.5 bytes per grid, not bad NetworkId networkId = MyMultiplayer.Static.ReplicationLayer.GetNetworkIdByObject(target); stream.WriteNetworkId(networkId); // ~2 bytes moving = IsMoving(node.NodeData); stream.WriteBool(moving); SerializeTransform(stream, node.NodeData, basePos, m_lowPrecisionOrientation, apply, moving, timestamp, null, null); // 12.5 bytes SerializeVelocities(stream, node.NodeData, EffectiveSimulationRatio, apply, moving); // 12 byte UpdateGridMaxSpeed(node.NodeData, Sync.IsServer); m_groups.Add(node.NodeData); m_currentSentPosition++; } if (stream.BitPosition > maxBitPosition) { stream.SetBitPositionWrite(pos); fullyWritten = false; m_currentSentPosition--; break; } if (i == g.Nodes.Count) { m_currentSentPosition = 0; } } stream.WriteBool(false); } stream.WriteBool(fullyWritten); if (fullyWritten) { SerializeRopeData(stream, apply, gridsGroup: m_groups); } return fullyWritten; } else { UpdateGridMaxSpeed(Entity, !Sync.IsServer); while (stream.ReadBool()) { NetworkId networkId = stream.ReadNetworkId(); // ~2 bytes MyCubeGridReplicable replicable = MyMultiplayer.Static.ReplicationLayer.GetObjectByNetworkId(networkId) as MyCubeGridReplicable; MyCubeGrid grid = replicable != null ? replicable.Grid : null; moving = stream.ReadBool(); SerializeTransform(stream, grid, basePos, m_lowPrecisionOrientation, apply && grid != null, moving, timestamp, null, null); // 12.5 bytes SerializeVelocities(stream, grid, EffectiveSimulationRatio, apply && grid != null, moving); // 12 bytes UpdateGridMaxSpeed(grid,!Sync.IsServer); } if (stream.ReadBool()) { SerializeRopeData(stream, apply); } } return true; }
public static void ReadSubGrids(BitStream stream, uint timestamp, bool apply,bool lowPrecisionOrientation, ref Vector3D basePos) { while (stream.ReadBool()) { NetworkId networkId = stream.ReadNetworkId(); // ~2 bytes MyCubeGridReplicable replicable = MyMultiplayer.Static.ReplicationLayer.GetObjectByNetworkId(networkId) as MyCubeGridReplicable; MyCubeGrid grid = replicable != null ? replicable.Grid : null; bool moving = stream.ReadBool(); SerializeTransform(stream, grid, basePos, lowPrecisionOrientation, apply && grid != null, moving, timestamp, null, null); // 12.5 bytes SerializeVelocities(stream, grid, EffectiveSimulationRatio, apply && grid != null, moving); // 12 bytes UpdateGridMaxSpeed(grid, !Sync.IsServer); } }
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); } } } }
public override void Serialize(BitStream stream, MyClientStateBase forClient, byte packetId, int maxBitPosition) { // Client does not care about slave grids, he always synced group through controlled object Debug.Assert(stream.Reading || !Sync.IsServer || Entity == GetMasterGrid(Entity), "Writing data from SlaveGrid!"); bool apply = !IsControlledLocally; bool moving = false; if (stream.Writing) { moving = IsMoving(Entity); stream.WriteBool(moving); } else { moving = stream.ReadBool(); } // Serialize this grid apply = SerializeTransform(stream, Entity, null, m_lowPrecisionOrientation, apply,moving, m_positionValidation, MoveHandler); SerializeVelocities(stream, Entity, EffectiveSimulationRatio, apply, moving,VelocityHandler); // Serialize other grids in group Vector3D basePos = Entity.WorldMatrix.Translation; if (stream.Writing) { UpdateGridMaxSpeed(Entity, Sync.IsServer); var g = MyCubeGridGroups.Static.PhysicalDynamic.GetGroup(Entity); if (g == null) { stream.WriteByte(0); } else { m_groups.Clear(); int i= -1; foreach (var node in g.Nodes) { i++; if(i < m_currentSentPosition) { continue; } if (i == m_currentSentPosition + NUM_NODES_TO_SEND_ALL) { break; } var target = MyMultiplayer.Static.ReplicationLayer.GetProxyTarget((IMyEventProxy)node.NodeData); if (node.NodeData != Entity && !node.NodeData.IsStatic && target != null) { m_groups.Add(node.NodeData); } } m_currentSentPosition = i; if (m_currentSentPosition >= g.Nodes.Count-1) { m_currentSentPosition = 0; } stream.WriteByte((byte)m_groups.Count); // Ignoring self foreach (var node in m_groups) { var target = MyMultiplayer.Static.ReplicationLayer.GetProxyTarget((IMyEventProxy)node); // ~26.5 bytes per grid, not bad NetworkId networkId = MyMultiplayer.Static.ReplicationLayer.GetNetworkIdByObject(target); stream.WriteNetworkId(networkId); // ~2 bytes moving = IsMoving(node); stream.WriteBool(moving); SerializeTransform(stream, node, basePos, true, apply, moving,null, null); // 12.5 bytes SerializeVelocities(stream, node, EffectiveSimulationRatio, apply, moving); // 12 byte UpdateGridMaxSpeed(node, Sync.IsServer); } } SerializeRopeData(stream, apply, gridsGroup: m_groups); } else { UpdateGridMaxSpeed(Entity, !Sync.IsServer); byte numRecords = stream.ReadByte(); for (int i = 0; i < numRecords; i++) { NetworkId networkId = stream.ReadNetworkId(); // ~2 bytes MyCubeGridReplicable replicable = MyMultiplayer.Static.ReplicationLayer.GetObjectByNetworkId(networkId) as MyCubeGridReplicable; MyCubeGrid grid = replicable != null ? replicable.Grid : null; moving = stream.ReadBool(); SerializeTransform(stream, grid, basePos, true, apply && grid != null,moving, null, null); // 12.5 bytes SerializeVelocities(stream, grid, EffectiveSimulationRatio, apply && grid != null, moving); // 12 bytes UpdateGridMaxSpeed(grid,!Sync.IsServer); } SerializeRopeData(stream, apply); } }
private void ProcessEvent( MyPacket packet ) { if ( _networkHandlers.Count == 0 ) { ((MyReplicationLayer)MyMultiplayer.ReplicationLayer).ProcessEvent(packet); return; } //magic: DO NOT TOUCH BitStream stream = new BitStream(); stream.ResetRead( packet ); NetworkId networkId = stream.ReadNetworkId(); //this value is unused, but removing this line corrupts the rest of the stream NetworkId blockedNetworkId = stream.ReadNetworkId(); uint eventId = (uint)stream.ReadByte(); CallSite site; IMyNetObject sendAs; object obj; if ( networkId.IsInvalid ) // Static event { site = m_typeTable.StaticEventTable.Get( eventId ); sendAs = null; obj = null; } else // Instance event { sendAs = ( (MyReplicationLayer)MyMultiplayer.ReplicationLayer ).GetObjectByNetworkId( networkId ); if ( sendAs == null ) { return; } var typeInfo = m_typeTable.Get( sendAs.GetType() ); int eventCount = typeInfo.EventTable.Count; if ( eventId < eventCount ) // Directly { obj = sendAs; site = typeInfo.EventTable.Get( eventId ); } else // Through proxy { obj = ( (IMyProxyTarget)sendAs ).Target; typeInfo = m_typeTable.Get( obj.GetType() ); site = typeInfo.EventTable.Get( eventId - (uint)eventCount ); // Subtract max id of Proxy } } #if DEBUG if ( ExtenderOptions.IsDebugging ) { if ( !site.MethodInfo.Name.Contains( "SyncPropertyChanged" ) && !site.MethodInfo.Name.Contains( "OnSimulationInfo" ) ) ApplicationLog.Error( $"Caught event {site.MethodInfo.Name} from user {PlayerMap.Instance.GetFastPlayerNameFromSteamId( packet.Sender.Value )}:{packet.Sender.Value}" ); } #endif //we're handling the network live in the game thread, this needs to go as fast as possible bool handled = false; Parallel.ForEach( _networkHandlers, handler => { if ( handler.CanHandle( site ) ) handled |= handler.Handle( packet.Sender.Value, site, stream, obj ); } ); if ( !handled ) ( (MyReplicationLayer)MyMultiplayer.ReplicationLayer ).ProcessEvent( packet ); }