private void ProcessEvent(MyPacket packet) { if (_networkHandlers.Count == 0) { //pass the message back to the game server try { ((MyReplicationLayer)MyMultiplayer.ReplicationLayer).OnEvent(packet); } catch (Exception ex) { ApplicationLog.Error(ex, "~Error processing event!"); //crash after logging, bad things could happen if we continue on with bad data throw; } 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.ReadUInt16(); 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.Id.Value )}:{packet.Sender.Id.Value}. Length {stream.ByteLength}B"); } } #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 => { try { if (handler.CanHandle(site)) { handled |= handler.Handle(packet.Sender.Id.Value, site, stream, obj); } } catch (Exception ex) { ApplicationLog.Error(ex.ToString()); } }); //one of the handlers wants us to discard this packet if (handled) { return; } //pass the message back to the game server try { ((MyReplicationLayer)MyMultiplayer.ReplicationLayer).OnEvent(packet); } catch (Exception ex) { ApplicationLog.Error(ex, "Error when returning control to game server!"); //crash after logging, bad things could happen if we continue on with bad data throw; } }
/// <summary> /// This is the main body of the network intercept system. When messages come in from clients, they are processed here /// before being passed on to the game server. /// /// DO NOT modify this method unless you're absolutely sure of what you're doing. This can very easily destabilize the game! /// </summary> /// <param name="packet"></param> private void OnEvent(MyPacket packet) { if (_networkHandlers.Count == 0) { //pass the message back to the game server try { ((MyReplicationLayer)MyMultiplayer.ReplicationLayer).OnEvent(packet); } catch (Exception ex) { _log.Fatal(ex); _log.Fatal(ex, "~Error processing event!"); //crash after logging, bad things could happen if we continue on with bad data throw; } return; } var stream = new BitStream(); stream.ResetRead(packet); var networkId = stream.ReadNetworkId(); //this value is unused, but removing this line corrupts the rest of the stream var blockedNetworkId = stream.ReadNetworkId(); var eventId = (uint)stream.ReadInt16(); CallSite site; object obj; if (networkId.IsInvalid) // Static event { site = m_typeTable.StaticEventTable.Get(eventId); obj = null; } else // Instance event { var sendAs = ((MyReplicationLayer)MyMultiplayer.ReplicationLayer).GetObjectByNetworkId(networkId); if (sendAs == null) { return; } var typeInfo = m_typeTable.Get(sendAs.GetType()); var 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 } } //we're handling the network live in the game thread, this needs to go as fast as possible var discard = false; foreach (var handler in _networkHandlers) //Parallel.ForEach(_networkHandlers, handler => { try { if (handler.CanHandle(site)) { discard |= handler.Handle(packet.Sender.Id.Value, site, stream, obj, packet); } } catch (Exception ex) { //ApplicationLog.Error(ex.ToString()); _log.Error(ex); } } //one of the handlers wants us to discard this packet if (discard) { return; } //pass the message back to the game server try { ((MyReplicationLayer)MyMultiplayer.ReplicationLayer).OnEvent(packet); } catch (Exception ex) { _log.Fatal(ex); _log.Fatal(ex, "Error when returning control to game server!"); //crash after logging, bad things could happen if we continue on with bad data throw; } }