EpicOnlineTransport icon indicating copy to clipboard operation
EpicOnlineTransport copied to clipboard

No suitable method found to override

Open RoxyBoxxy opened this issue 3 years ago • 2 comments

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)'

RoxyBoxxy avatar Dec 12 '21 23:12 RoxyBoxxy

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

CreepyAnt avatar Dec 14 '21 07:12 CreepyAnt

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.

BlissGDev avatar Jan 19 '22 11:01 BlissGDev