FakeByte / EpicOnlineTransport

A Transport for Mirror using Epic Online Services
MIT License
252 stars 52 forks source link

No suitable method found to override #23

Open RoxyBoxxy opened 2 years ago

RoxyBoxxy commented 2 years ago

Unity: 2020.3.24.f1

I get 5 errors these are the errors

Assets\Mirror\Runtime\Transport\EpicOnlineTransport\EosTransport.cs(156,30): error CS0115: 'EosTransport.ClientSend(int, ArraySegment<byte>)': no suitable method found to override
Assets\Mirror\Runtime\Transport\EpicOnlineTransport\EosTransport.cs(216,30): error CS0115: 'EosTransport.ServerSend(int, int, ArraySegment<byte>)': no suitable method found to override
Assets\Mirror\Runtime\Transport\EpicOnlineTransport\EosTransport.cs(286,29): error CS0115: 'EosTransport.GetMaxBatchSize(int)': no suitable method found to override
Assets\Mirror\Runtime\Transport\EpicOnlineTransport\EosTransport.cs(16,18): error CS0534: 'EosTransport' does not implement inherited abstract member 'Transport.ServerSend(int, ArraySegment<byte>, int)'
Assets\Mirror\Runtime\Transport\EpicOnlineTransport\EosTransport.cs(16,18): error CS0534: 'EosTransport' does not implement inherited abstract member 'Transport.ClientSend(ArraySegment<byte>, int)'
CreepyAnt commented 2 years ago

It's because some of the parameters are reversed in Mirror's latest version You can replace EosTransport.cs' script with this one:

using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using Epic.OnlineServices.P2P;
using Epic.OnlineServices;
using Mirror;
using Epic.OnlineServices.Metrics;
using System.Collections;

namespace EpicTransport {

    /// <summary>
    /// EOS Transport following the Mirror transport standard
    /// </summary>
    public class EosTransport : Transport {
        private const string EPIC_SCHEME = "epic";

        private Client client;
        private Server server;

        private Common activeNode;

        [SerializeField]
        public PacketReliability[] Channels = new PacketReliability[2] { PacketReliability.ReliableOrdered, PacketReliability.UnreliableUnordered };

        [Tooltip("Timeout for connecting in seconds.")]
        public int timeout = 25;

        [Tooltip("The max fragments used in fragmentation before throwing an error.")]
        public int maxFragments = 55;

        public float ignoreCachedMessagesAtStartUpInSeconds = 2.0f;
        private float ignoreCachedMessagesTimer = 0.0f;

        public RelayControl relayControl = RelayControl.AllowRelays;

        [Header("Info")]
        [Tooltip("This will display your Epic Account ID when you start or connect to a server.")]
        public ProductUserId productUserId;

        private int packetId = 0;

        private void Awake() {
            Debug.Assert(Channels != null && Channels.Length > 0, "No channel configured for EOS Transport.");
            Debug.Assert(Channels.Length < byte.MaxValue, "Too many channels configured for EOS Transport");

            if(Channels[0] != PacketReliability.ReliableOrdered) {
                Debug.LogWarning("EOS Transport Channel[0] is not ReliableOrdered, Mirror expects Channel 0 to be ReliableOrdered, only change this if you know what you are doing.");
            }
            if (Channels[1] != PacketReliability.UnreliableUnordered) {
                Debug.LogWarning("EOS Transport Channel[1] is not UnreliableUnordered, Mirror expects Channel 1 to be UnreliableUnordered, only change this if you know what you are doing.");
            }

            StartCoroutine("FetchEpicAccountId");
            StartCoroutine("ChangeRelayStatus");
        }

        public override void ClientEarlyUpdate() {
            EOSSDKComponent.Tick();

            if (activeNode != null) {
                ignoreCachedMessagesTimer += Time.deltaTime;

                if (ignoreCachedMessagesTimer <= ignoreCachedMessagesAtStartUpInSeconds) {
                    activeNode.ignoreAllMessages = true;
                } else {
                    activeNode.ignoreAllMessages = false;

                    if (client != null && !client.isConnecting) {
                        if (EOSSDKComponent.Initialized) {
                            client.Connect(client.hostAddress);
                        } else {
                            Debug.LogError("EOS not initialized");
                            client.EosNotInitialized();
                        }
                        client.isConnecting = true;
                    }
                }
            }

            if (enabled) {
                activeNode?.ReceiveData();
            }
        }

        public override void ClientLateUpdate() {}

        public override void ServerEarlyUpdate() {
            EOSSDKComponent.Tick();

            if (activeNode != null) {
                ignoreCachedMessagesTimer += Time.deltaTime;

                if (ignoreCachedMessagesTimer <= ignoreCachedMessagesAtStartUpInSeconds) {
                    activeNode.ignoreAllMessages = true;
                } else {
                    activeNode.ignoreAllMessages = false;
                }
            }

            if (enabled) {
                activeNode?.ReceiveData();
            }
        }

        public override void ServerLateUpdate() {}

        public override bool ClientConnected() => ClientActive() && client.Connected;
        public override void ClientConnect(string address) {
            if (!EOSSDKComponent.Initialized) {
                Debug.LogError("EOS not initialized. Client could not be started.");
                OnClientDisconnected.Invoke();
                return;
            }

            StartCoroutine("FetchEpicAccountId");

            if (ServerActive()) {
                Debug.LogError("Transport already running as server!");
                return;
            }

            if (!ClientActive() || client.Error) {
                Debug.Log($"Starting client, target address {address}.");

                client = Client.CreateClient(this, address);
                activeNode = client;

                if (EOSSDKComponent.CollectPlayerMetrics) {
                    // Start Metrics colletion session
                    BeginPlayerSessionOptions sessionOptions = new BeginPlayerSessionOptions();
                    sessionOptions.AccountId = EOSSDKComponent.LocalUserAccountId;
                    sessionOptions.ControllerType = UserControllerType.Unknown;
                    sessionOptions.DisplayName = EOSSDKComponent.DisplayName;
                    sessionOptions.GameSessionId = null;
                    sessionOptions.ServerIp = null;
                    Result result = EOSSDKComponent.GetMetricsInterface().BeginPlayerSession(sessionOptions);

                    if(result == Result.Success) {
                        Debug.Log("Started Metric Session");
                    }
                }
            } else {
                Debug.LogError("Client already running!");
            }
        }

        public override void ClientConnect(Uri uri) {
            if (uri.Scheme != EPIC_SCHEME)
                throw new ArgumentException($"Invalid url {uri}, use {EPIC_SCHEME}://EpicAccountId instead", nameof(uri));

            ClientConnect(uri.Host);
        }

        public override void ClientSend(ArraySegment<byte> segment, int channelId) {
            Send(channelId, segment);
        }

        public override void ClientDisconnect() {
            if (ClientActive()) {
                Shutdown();
            }
        }
        public bool ClientActive() => client != null;

        public override bool ServerActive() => server != null;
        public override void ServerStart() {
            if (!EOSSDKComponent.Initialized) {
                Debug.LogError("EOS not initialized. Server could not be started.");
                return;
            }

            StartCoroutine("FetchEpicAccountId");

            if (ClientActive()) {
                Debug.LogError("Transport already running as client!");
                return;
            }

            if (!ServerActive()) {
                Debug.Log("Starting server.");

                server = Server.CreateServer(this, NetworkManager.singleton.maxConnections);
                activeNode = server;

                if (EOSSDKComponent.CollectPlayerMetrics) {
                    // Start Metrics colletion session
                    BeginPlayerSessionOptions sessionOptions = new BeginPlayerSessionOptions();
                    sessionOptions.AccountId = EOSSDKComponent.LocalUserAccountId;
                    sessionOptions.ControllerType = UserControllerType.Unknown;
                    sessionOptions.DisplayName = EOSSDKComponent.DisplayName;
                    sessionOptions.GameSessionId = null;
                    sessionOptions.ServerIp = null;
                    Result result = EOSSDKComponent.GetMetricsInterface().BeginPlayerSession(sessionOptions);

                    if (result == Result.Success) {
                        Debug.Log("Started Metric Session");
                    }
                }
            } else {
                Debug.LogError("Server already started!");
            }
        }

        public override Uri ServerUri() {
            UriBuilder epicBuilder = new UriBuilder { 
                Scheme = EPIC_SCHEME,
                Host = EOSSDKComponent.LocalUserProductIdString
            };

            return epicBuilder.Uri;
        }

        public override void ServerSend(int connectionId, ArraySegment<byte> segment, int channelId) {
            if (ServerActive()) {
                Send( channelId, segment, connectionId);
            }
        }
        public override void ServerDisconnect(int connectionId) => server.Disconnect(connectionId);
        public override string ServerGetClientAddress(int connectionId) => ServerActive() ? server.ServerGetClientAddress(connectionId) : string.Empty;
        public override void ServerStop() {
            if (ServerActive()) {
                Shutdown();
            }
        }

        private void Send(int channelId, ArraySegment<byte> segment, int connectionId = int.MinValue) {
            Packet[] packets = GetPacketArray(channelId, segment);

            for(int i  = 0; i < packets.Length; i++) {
                if (connectionId == int.MinValue) {
                    client.Send(packets[i].ToBytes(), channelId);
                } else {
                    server.SendAll(connectionId, packets[i].ToBytes(), channelId);
                }
            }

            packetId++;
        }

        private Packet[] GetPacketArray(int channelId, ArraySegment<byte> segment) {
            int packetCount = Mathf.CeilToInt((float) segment.Count / (float)GetMaxSinglePacketSize(channelId));
            Packet[] packets = new Packet[packetCount];

            for (int i = 0; i < segment.Count; i += GetMaxSinglePacketSize(channelId)) {
                int fragment = i / GetMaxSinglePacketSize(channelId);

                packets[fragment] = new Packet();
                packets[fragment].id = packetId;
                packets[fragment].fragment = fragment;
                packets[fragment].moreFragments = (segment.Count - i) > GetMaxSinglePacketSize(channelId);
                packets[fragment].data = new byte[segment.Count - i > GetMaxSinglePacketSize(channelId) ? GetMaxSinglePacketSize(channelId) : segment.Count - i];
                Array.Copy(segment.Array, i, packets[fragment].data, 0, packets[fragment].data.Length);
            }

            return packets;
        }

        public override void Shutdown() {
            if (EOSSDKComponent.CollectPlayerMetrics) {
                // Stop Metrics collection session
                EndPlayerSessionOptions endSessionOptions = new EndPlayerSessionOptions();
                endSessionOptions.AccountId = EOSSDKComponent.LocalUserAccountId;
                Result result = EOSSDKComponent.GetMetricsInterface().EndPlayerSession(endSessionOptions);

                if (result == Result.Success) {
                    Debug.LogError("Stopped Metric Session");
                }
            }

            server?.Shutdown();
            client?.Disconnect();

            server = null;
            client = null;
            activeNode = null;
            Debug.Log("Transport shut down.");
        }

        public int GetMaxSinglePacketSize(int channelId) => P2PInterface.MaxPacketSize - 10; // 1159 bytes, we need to remove 10 bytes for the packet header (id (4 bytes) + fragment (4 bytes) + more fragments (1 byte)) 

        public override int GetMaxPacketSize(int channelId) => P2PInterface.MaxPacketSize * maxFragments; 

        public override int GetBatchThreshold(int channelId) => P2PInterface.MaxPacketSize; // Use P2PInterface.MaxPacketSize as everything above will get fragmentated and will be counter effective to batching

        public override bool Available() {
            try {
                return EOSSDKComponent.Initialized;
            } catch {
                return false;
            }
        }

        private IEnumerator FetchEpicAccountId() {
            while (!EOSSDKComponent.Initialized) {
                yield return null;
            }

            productUserId = EOSSDKComponent.LocalUserProductId;
        }

        private IEnumerator ChangeRelayStatus() {
            while (!EOSSDKComponent.Initialized) {
                yield return null;
            }

            SetRelayControlOptions setRelayControlOptions = new SetRelayControlOptions();
            setRelayControlOptions.RelayControl = relayControl;

            EOSSDKComponent.GetP2PInterface().SetRelayControl(setRelayControlOptions);
        }

        public void ResetIgnoreMessagesAtStartUpTimer() {
            ignoreCachedMessagesTimer = 0;
        }

        private void OnDestroy() {
            if (activeNode != null) {
                Shutdown();
            }
        }
    }
}
BlissGDev commented 2 years ago

It would be great that along the package, the compatible Mirror versions where listed. At least, the one that's currently supported by the EpicOnlineTransport version.