using System; using System.Collections.Generic; using FlatBuffers; using MoleMole.MPProtocol; namespace MoleMole { public abstract class BaseMPManager { private const int BUFFER_SIZE = 1024; private const int TOTAL_HEADER_BYTE = 6; protected MPPeer _peer; protected bool _isMaster; private int _peerID; private byte[] _sendBuffer; private byte[] _recvBuffer; private byte[] _tmpBuffer; private FlatBufferBuilder _defaultSendBuilder; private FlatBufferBuilder _instantiateBuilder; private ByteBuffer _recvByteBuffer; private SprotoPack _bitPacker; private Dictionary _identities; private List _identitiesList; private BaseMPIdentity[] _identitiesBuffer = new BaseMPIdentity[64]; private Dictionary _pendingInstantiates; private bool[] _channelOccupiedMap; private Dictionary _runtimeIDChannelMap; public int peerID { get { return _peerID; } } public bool isMaster { get { return _isMaster; } } public BaseMPManager() { _bitPacker = new SprotoPack(); _sendBuffer = new byte[1024]; _recvBuffer = new byte[1024]; _tmpBuffer = new byte[1024]; _recvByteBuffer = new ByteBuffer(_recvBuffer); _defaultSendBuilder = new FlatBufferBuilder(1024); _instantiateBuilder = new FlatBufferBuilder(32); _identities = new Dictionary(); _identitiesList = new List(); _pendingInstantiates = new Dictionary(); _peer = IdleMPPeer.IDLE_PEER; MPMappings.InitMPMappings(); } public void SetupPeer(MPPeer peer, bool isMasterClient) { _peer = peer; _isMaster = isMasterClient; _peerID = peer.peerID; _peer.onPacket = OnPeerPacketCallback; InitChannelManagement(); } public MPSendPacketContainer CreateSendPacket() where T : Table { return CreateSendPacket(_defaultSendBuilder); } public MPSendPacketContainer CreateSendPacket(FlatBufferBuilder builder) where T : Table { return CreateSendPacket(typeof(T), builder); } public MPSendPacketContainer CreateSendPacket(Type type, FlatBufferBuilder builder) { return new MPSendPacketContainer { packetTypeID = MPMappings.MPPacketMapping.Get(type), builder = builder }; } public void SendReliableToOthers(uint runtimeID, MPSendPacketContainer pc) { pc.runtimeID = runtimeID; SendByChannel(7, _peer.reliableChannel, pc); } public void SendReliableToPeer(uint runtimeID, int peerID, MPSendPacketContainer pc) { pc.runtimeID = runtimeID; SendByChannel(peerID, _peer.reliableChannel, pc); } public void SendStateUpdateToOthers(uint runtimeID, MPSendPacketContainer pc) { pc.runtimeID = runtimeID; SendByChannel(7, _peer.stateUpdateChannel, pc); } private void SendByChannel(int peerID, int channel, MPSendPacketContainer pc) { ByteBuffer dataBuffer = pc.builder.DataBuffer; int num = dataBuffer.Position - 6; dataBuffer.PutByte(num, (byte)pc.packetTypeID); dataBuffer.PutByte(num + 1, PackControlByte(_peerID)); dataBuffer.PutUint(num + 2, pc.runtimeID); dataBuffer.Position = num; int num2 = dataBuffer.Length - dataBuffer.Position; Buffer.BlockCopy(dataBuffer.Data, dataBuffer.Position, _tmpBuffer, 0, num2); int num3 = _bitPacker.pack(_tmpBuffer, _bitPacker.RoundUpTo8(num2), _sendBuffer, 1); num2 = num3; pc.builder.Clear(); _sendBuffer[0] = _peer.PackHeader((byte)peerID, 31); int channelSequence = _runtimeIDChannelMap[pc.runtimeID]; _peer.SendByChannel(_sendBuffer, num2 + 1, channel, channelSequence); pc.state = MPSendContainerState.Sent; } private void OnPeerPacketCallback(byte[] buffer, int len, int offset, int channel) { Buffer.BlockCopy(buffer, offset, _tmpBuffer, 0, len); _bitPacker.unpack(_tmpBuffer, len, _recvBuffer, 0); _recvByteBuffer.Reset(); int num = _recvByteBuffer.Get(0); int controlByte = _recvByteBuffer.Get(1); int fromPeerID = ParseControlByteSenderPeerID(controlByte); uint runtimeID = _recvByteBuffer.GetUint(2); Type type = MPMappings.MPPacketMapping.Get(num); Table table = MPMappings.cachedRecvPackets[num]; _recvByteBuffer.Position = 6; table.ResetAndInitTo(_recvByteBuffer); MPRecvPacketContainer pc = new MPRecvPacketContainer { runtimeID = runtimeID, channel = channel, fromPeerID = fromPeerID, packet = table }; DispatchPacket(pc); } public void InitAtAwake() { } public void InitAtStart() { } protected virtual void DispatchPacket(MPRecvPacketContainer pc) { BaseMPIdentity value; if (pc.packet is Packet_Basic_Instantiate) { Packet_Basic_Instantiate packet_Basic_Instantiate = pc.As(); BindImportantFixedChannel(pc.runtimeID, packet_Basic_Instantiate.ChannelSequence); _pendingInstantiates.Add(pc.runtimeID, packet_Basic_Instantiate.PeerType); } else if (pc.packet is Packet_Basic_Destroy) { RemoveMPIdentity(pc.runtimeID); } else if (_pendingInstantiates.ContainsKey(pc.runtimeID)) { Type type = MPMappings.MPPeerMapping.Get(_pendingInstantiates[pc.runtimeID]); CreateRemoteMPIdentity(type, pc.runtimeID, pc); _pendingInstantiates.Remove(pc.runtimeID); } else if (pc.channel == _peer.reliableChannel) { _identities[pc.runtimeID].OnReliablePacket(pc); } else if (pc.channel == _peer.stateUpdateChannel && _identities.TryGetValue(pc.runtimeID, out value)) { value.OnStateUpdatePacket(pc); } } public virtual void Core() { _peer.Core(); if (_identitiesList.Count > _identitiesBuffer.Length) { _identitiesBuffer = new BaseMPIdentity[_identitiesBuffer.Length * 2]; } int count = _identitiesList.Count; _identitiesList.CopyTo(_identitiesBuffer); for (int i = 0; i < count; i++) { _identitiesBuffer[i].Core(); } } public virtual void PostCore() { } public void Destroy() { } public T GetIdentity(uint runtimeID) where T : BaseMPIdentity { return (T)_identities[runtimeID]; } public T TryGetIdentity(uint runtimeID) where T : BaseMPIdentity { BaseMPIdentity value; _identities.TryGetValue(runtimeID, out value); return value as T; } public BaseMPIdentity TryGetIdentity(uint runtimeID) { BaseMPIdentity value; _identities.TryGetValue(runtimeID, out value); return value; } public T InstantiateMPIdentity(uint runtimeID, MPSendPacketContainer initPc) where T : BaseMPIdentity, new() { int num = AllocChannelSequenceForRuntimeID(runtimeID); MPSendPacketContainer pc = CreateSendPacket(_instantiateBuilder); Packet_Basic_Instantiate.StartPacket_Basic_Instantiate(pc.builder); Packet_Basic_Instantiate.AddPeerType(pc.builder, (byte)MPMappings.MPPeerMapping.Get(typeof(T))); Packet_Basic_Instantiate.AddChannelSequence(pc.builder, (byte)num); pc.Finish(Packet_Basic_Instantiate.EndPacket_Basic_Instantiate(pc.builder)); SendReliableToOthers(runtimeID, pc); SendReliableToOthers(runtimeID, initPc); return CreateMPIdentity(runtimeID); } public void DestroyMPIdentity(uint runtimeID) { MPSendPacketContainer pc = CreateSendPacket(); Packet_Basic_Destroy.StartPacket_Basic_Destroy(pc.builder); pc.Finish(Packet_Basic_Destroy.EndPacket_Basic_Destroy(pc.builder)); SendReliableToOthers(runtimeID, pc); RemoveMPIdentity(runtimeID); } public void RegisterIdentity(uint runtimeID, int channelSequence, BaseMPIdentity identity) { BindImportantFixedChannel(runtimeID, channelSequence); InitializeIdentity(identity, runtimeID); } private BaseMPIdentity CreateRemoteMPIdentity(Type type, uint runtimeID, MPRecvPacketContainer pc) { object obj = Activator.CreateInstance(type); BaseMPIdentity baseMPIdentity = (BaseMPIdentity)obj; baseMPIdentity.PreInitReplicateRemote(pc); InitializeIdentity(baseMPIdentity, runtimeID); return baseMPIdentity; } private T CreateMPIdentity(uint runtimeID) where T : BaseMPIdentity, new() { T val = new T(); InitializeIdentity(val, runtimeID); return val; } private void InitializeIdentity(BaseMPIdentity identity, uint runtimeID) { identity.runtimeID = runtimeID; identity.isOwner = identity.GetPeerID() == _peer.peerID; _identities.Add(runtimeID, identity); _identitiesList.Add(identity); identity.Init(); if (identity.isAuthority) { identity.OnAuthorityStart(); } else { identity.OnRemoteStart(); } } private void RemoveMPIdentity(uint runtimeID) { RemoveMPIdentity(_identities[runtimeID]); } private void RemoveMPIdentity(BaseMPIdentity identity) { ReleaseChannelSequenceForRuntimeID(identity.runtimeID); identity.OnRemoval(); bool flag = _identitiesList.Remove(identity); flag &= _identities.Remove(identity.runtimeID); } private byte PackControlByte(int selfPeerID) { return (byte)((byte)peerID << 5); } private int ParseControlByteSenderPeerID(int controlByte) { return (controlByte & 0xE0) >> 5; } private void InitChannelManagement() { _runtimeIDChannelMap = new Dictionary(); _channelOccupiedMap = new bool[_peer.channelSequenceCapacity]; _channelOccupiedMap[_peer.channelSequenceCapacity - 1] = true; } public void BindImportantFixedChannel(uint runtimeID, int channel) { _channelOccupiedMap[channel] = true; _runtimeIDChannelMap[runtimeID] = channel; } private int AllocChannelSequenceForRuntimeID(uint runtimeID) { if (_runtimeIDChannelMap.ContainsKey(runtimeID)) { return _runtimeIDChannelMap[runtimeID]; } int i; for (i = 0; i < _channelOccupiedMap.Length - 1 && _channelOccupiedMap[i]; i++) { } if (i != _peer.channelSequenceCapacity - 1) { _channelOccupiedMap[i] = true; } _runtimeIDChannelMap.Add(runtimeID, i); return i; } private void ReleaseChannelSequenceForRuntimeID(uint runtimeID) { int num = _runtimeIDChannelMap[runtimeID]; if (num != _peer.channelSequenceCapacity - 1) { _channelOccupiedMap[num] = false; } _runtimeIDChannelMap.Remove(runtimeID); } public int GetAllocedChannelID(uint runtimeID) { return _runtimeIDChannelMap[runtimeID]; } } }