Skip to content

Instantly share code, notes, and snippets.

@RyanGarber
Created September 6, 2023 12:42
Show Gist options
  • Save RyanGarber/97248fcfe672dcaedd54c75fe4dd4696 to your computer and use it in GitHub Desktop.
Save RyanGarber/97248fcfe672dcaedd54c75fe4dd4696 to your computer and use it in GitHub Desktop.
Improved Photon Realtime Transport for FishNet
public class NetworkTransport : Transport, IOnEventCallback, IMatchmakingCallbacks, IInRoomCallbacks
{
public LoadBalancingClient Photon = new();
public override void Initialize(NetworkManager networkManager, int transportIndex)
{
base.Initialize(networkManager, transportIndex);
Photon.AddCallbackTarget(this);
}
public override string GetConnectionAddress(int connectionId) => (connectionId + 1).ToString();
public override LocalConnectionState GetConnectionState(bool server) => Photon.State switch
{
ClientState.Joining => LocalConnectionState.Starting,
ClientState.Joined => LocalConnectionState.Started,
ClientState.Leaving => LocalConnectionState.Stopping,
_ => LocalConnectionState.Stopped
};
public override RemoteConnectionState GetConnectionState(int connectionId) =>
Photon.CurrentRoom.Players[connectionId].IsInactive ? RemoteConnectionState.Stopped : RemoteConnectionState.Started;
public override void SendToClient(byte channelId, ArraySegment<byte> segment, int connectionId)
{
SetChannel(ref segment, out SendOptions options, channelId);
Photon.OpRaiseEvent((byte)EventCode.ToClient, segment, new() { TargetActors = new[] { connectionId + 1 } }, options);
}
public override void SendToServer(byte channelId, ArraySegment<byte> segment)
{
SetChannel(ref segment, out SendOptions options, channelId);
Photon.OpRaiseEvent((byte)EventCode.ToServer, segment, new() { TargetActors = new[] { Photon.CurrentRoom.MasterClientId } }, options);
}
void IOnEventCallback.OnEvent(EventData photonEvent)
{
if (photonEvent.Code >= 200) return;
using (ByteArraySlice slice = photonEvent.CustomData as ByteArraySlice)
{
ArraySegment<byte> segment = new(slice.Buffer, slice.Offset, slice.Count);
GetChannel(ref segment, out Channel channel);
if (photonEvent.Code == (byte)EventCode.ToClient) HandleClientReceivedDataArgs(new(segment, channel, Index));
if (photonEvent.Code == (byte)EventCode.ToServer) HandleServerReceivedDataArgs(new(segment, channel, photonEvent.Sender - 1, Index));
}
}
void IMatchmakingCallbacks.OnJoinedRoom()
{
if (Photon.LocalPlayer.IsMasterClient)
{
HandleServerConnectionState(new(LocalConnectionState.Started, Index));
HandleRemoteConnectionState(new(RemoteConnectionState.Started, 0, Index));
}
HandleClientConnectionState(new(LocalConnectionState.Started, Index));
}
void IMatchmakingCallbacks.OnLeftRoom()
{
HandleClientConnectionState(new(LocalConnectionState.Stopped, Index));
if (NetworkManager.IsServer)
{
HandleRemoteConnectionState(new(RemoteConnectionState.Stopped, 0, Index));
HandleServerConnectionState(new(LocalConnectionState.Stopped, Index));
}
}
void IInRoomCallbacks.OnPlayerEnteredRoom(Photon.Realtime.Player newPlayer)
{
if (NetworkManager.IsServer)
{
HandleRemoteConnectionState(new(RemoteConnectionState.Started, newPlayer.ActorNumber - 1, Index));
}
}
void IInRoomCallbacks.OnPlayerLeftRoom(Photon.Realtime.Player otherPlayer)
{
if (NetworkManager.IsServer)
{
HandleRemoteConnectionState(new(RemoteConnectionState.Stopped, otherPlayer.ActorNumber - 1, Index));
}
}
public override void Shutdown()
{
}
public override bool StartConnection(bool server)
{
return true;
}
public override bool StopConnection(bool server)
{
return true;
}
public override bool StopConnection(int connectionId, bool immediately)
{
return true;
}
public void SetChannel(ref ArraySegment<byte> segment, out SendOptions options, byte channelId)
{
byte[] array = segment.Array;
if (segment.Offset + segment.Count >= array.Length)
{
Array.Resize(ref array, array.Length + 1);
array[^1] = channelId;
}
else
{
array[segment.Offset + segment.Count] = channelId;
}
segment = new ArraySegment<byte>(array, segment.Offset, segment.Count + 1);
options = channelId == (byte)Channel.Reliable ? SendOptions.SendReliable : SendOptions.SendUnreliable;
}
public void GetChannel(ref ArraySegment<byte> segment, out Channel channel)
{
channel = (Channel)segment[^1];
segment = new(segment.Array, segment.Offset, segment.Count - 1);
}
public override int GetMTU(byte channel) => 1200;
public override void IterateIncoming(bool server) { }
public override void IterateOutgoing(bool server) { }
void IMatchmakingCallbacks.OnFriendListUpdate(List<FriendInfo> friendList) { }
void IMatchmakingCallbacks.OnCreatedRoom() { }
void IMatchmakingCallbacks.OnCreateRoomFailed(short returnCode, string message) { }
void IMatchmakingCallbacks.OnJoinRoomFailed(short returnCode, string message) { }
void IMatchmakingCallbacks.OnJoinRandomFailed(short returnCode, string message) { }
void IInRoomCallbacks.OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) { }
void IInRoomCallbacks.OnPlayerPropertiesUpdate(Photon.Realtime.Player targetPlayer, Hashtable changedProps) { }
void IInRoomCallbacks.OnMasterClientSwitched(Photon.Realtime.Player newMasterClient) { }
public override void HandleClientConnectionState(ClientConnectionStateArgs connectionStateArgs) => OnClientConnectionState?.Invoke(connectionStateArgs);
public override event Action<ClientConnectionStateArgs> OnClientConnectionState;
public override void HandleClientReceivedDataArgs(ClientReceivedDataArgs receivedDataArgs) => OnClientReceivedData?.Invoke(receivedDataArgs);
public override event Action<ClientReceivedDataArgs> OnClientReceivedData;
public override void HandleRemoteConnectionState(RemoteConnectionStateArgs connectionStateArgs) => OnRemoteConnectionState?.Invoke(connectionStateArgs);
public override event Action<RemoteConnectionStateArgs> OnRemoteConnectionState;
public override void HandleServerConnectionState(ServerConnectionStateArgs connectionStateArgs) => OnServerConnectionState?.Invoke(connectionStateArgs);
public override event Action<ServerConnectionStateArgs> OnServerConnectionState;
public override void HandleServerReceivedDataArgs(ServerReceivedDataArgs receivedDataArgs) => OnServerReceivedData?.Invoke(receivedDataArgs);
public override event Action<ServerReceivedDataArgs> OnServerReceivedData;
}
public enum EventCode
{
ToClient,
ToServer
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment