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); } }
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); } } } }
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 ); }