remove all the epic stuff

This commit is contained in:
_nebula 2023-06-09 22:06:35 +01:00
parent 7cf24052fd
commit b4a6280e3d
23 changed files with 5 additions and 2166 deletions

View File

@ -1,120 +0,0 @@
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// Copyright
/// MIT License
///
/// Copyright Fizz Cube Ltd(c) 2018
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all
/// copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
/// SOFTWARE.
///
/// ===
///
/// Copyright Marco Hoffmann(c) 2020
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
///furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all
/// copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
/// SOFTWARE.
///
/// MIT License
/// </summary>
namespace EpicTransport {
public class BidirectionalDictionary<T1, T2> : IEnumerable {
private Dictionary<T1, T2> t1ToT2Dict = new Dictionary<T1, T2>();
private Dictionary<T2, T1> t2ToT1Dict = new Dictionary<T2, T1>();
public IEnumerable<T1> FirstTypes => t1ToT2Dict.Keys;
public IEnumerable<T2> SecondTypes => t2ToT1Dict.Keys;
public IEnumerator GetEnumerator() => t1ToT2Dict.GetEnumerator();
public int Count => t1ToT2Dict.Count;
public void Add(T1 key, T2 value) {
t1ToT2Dict[key] = value;
t2ToT1Dict[value] = key;
}
public void Add(T2 key, T1 value) {
t2ToT1Dict[key] = value;
t1ToT2Dict[value] = key;
}
public T2 Get(T1 key) => t1ToT2Dict[key];
public T1 Get(T2 key) => t2ToT1Dict[key];
public bool TryGetValue(T1 key, out T2 value) => t1ToT2Dict.TryGetValue(key, out value);
public bool TryGetValue(T2 key, out T1 value) => t2ToT1Dict.TryGetValue(key, out value);
public bool Contains(T1 key) => t1ToT2Dict.ContainsKey(key);
public bool Contains(T2 key) => t2ToT1Dict.ContainsKey(key);
public void Remove(T1 key) {
if (Contains(key)) {
T2 val = t1ToT2Dict[key];
t1ToT2Dict.Remove(key);
t2ToT1Dict.Remove(val);
}
}
public void Remove(T2 key) {
if (Contains(key)) {
T1 val = t2ToT1Dict[key];
t1ToT2Dict.Remove(val);
t2ToT1Dict.Remove(key);
}
}
public T1 this[T2 key] {
get => t2ToT1Dict[key];
set {
t2ToT1Dict[key] = value;
t1ToT2Dict[value] = key;
}
}
public T2 this[T1 key] {
get => t1ToT2Dict[key];
set {
t1ToT2Dict[key] = value;
t2ToT1Dict[value] = key;
}
}
}
}

View File

@ -1,178 +0,0 @@
using Epic.OnlineServices;
using Epic.OnlineServices.P2P;
using Mirror;
using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
namespace EpicTransport {
public class Client : Common {
public SocketId socketId;
public ProductUserId serverId;
public bool Connected { get; private set; }
public bool Error { get; private set; }
private event Action<byte[], int> OnReceivedData;
private event Action OnConnected;
public event Action OnDisconnected;
// CHANGED
private event Action<TransportError, string> OnReceivedError;
private TimeSpan ConnectionTimeout;
public bool isConnecting = false;
public string hostAddress = "";
private ProductUserId hostProductId = null;
private TaskCompletionSource<Task> connectedComplete;
private CancellationTokenSource cancelToken;
private Client(EosTransport transport) : base(transport) {
ConnectionTimeout = TimeSpan.FromSeconds(Math.Max(1, transport.timeout));
}
public static Client CreateClient(EosTransport transport, string host) {
Client c = new Client(transport);
c.hostAddress = host;
c.socketId = new SocketId() { SocketName = RandomString.Generate(20) };
c.OnConnected += () => transport.OnClientConnected.Invoke();
c.OnDisconnected += () => transport.OnClientDisconnected.Invoke();
c.OnReceivedData += (data, channel) => transport.OnClientDataReceived.Invoke(new ArraySegment<byte>(data), channel);
// CHANGED
c.OnReceivedError += (error, reason) => transport.OnClientError?.Invoke(error, reason);
return c;
}
public async void Connect(string host) {
cancelToken = new CancellationTokenSource();
try {
hostProductId = ProductUserId.FromString(host);
serverId = hostProductId;
connectedComplete = new TaskCompletionSource<Task>();
OnConnected += SetConnectedComplete;
SendInternal(hostProductId, socketId, InternalMessages.CONNECT);
Task connectedCompleteTask = connectedComplete.Task;
if (await Task.WhenAny(connectedCompleteTask, Task.Delay(ConnectionTimeout/*, cancelToken.Token*/)) != connectedCompleteTask) {
// CHANGED
OnReceivedError?.Invoke(TransportError.Timeout, $"Connection to {host} timed out.");
Debug.LogError($"Connection to {host} timed out.");
OnConnected -= SetConnectedComplete;
OnConnectionFailed(hostProductId);
}
OnConnected -= SetConnectedComplete;
} catch (FormatException) {
// CHANGED
OnReceivedError?.Invoke(TransportError.DnsResolve, "Connection string was not in the right format. Did you enter a ProductId?");
Debug.LogError($"Connection string was not in the right format. Did you enter a ProductId?");
Error = true;
OnConnectionFailed(hostProductId);
} catch (Exception ex) {
// CHANGED
OnReceivedError?.Invoke(TransportError.Unexpected, ex.Message);
Debug.LogError(ex.Message);
Error = true;
OnConnectionFailed(hostProductId);
} finally {
if (Error) {
OnConnectionFailed(null);
}
}
}
public void Disconnect() {
if (serverId != null) {
CloseP2PSessionWithUser(serverId, socketId);
serverId = null;
} else {
return;
}
SendInternal(hostProductId, socketId, InternalMessages.DISCONNECT);
Dispose();
cancelToken?.Cancel();
WaitForClose(hostProductId, socketId);
}
private void SetConnectedComplete() => connectedComplete.SetResult(connectedComplete.Task);
protected override void OnReceiveData(byte[] data, ProductUserId clientUserId, int channel) {
if (ignoreAllMessages) {
return;
}
if (clientUserId != hostProductId) {
Debug.LogError("Received a message from an unknown");
return;
}
OnReceivedData.Invoke(data, channel);
}
protected override void OnNewConnection(OnIncomingConnectionRequestInfo result) {
if (ignoreAllMessages) {
return;
}
if (deadSockets.Contains(result.SocketId.SocketName)) {
Debug.LogError("Received incoming connection request from dead socket");
return;
}
if (hostProductId == result.RemoteUserId) {
EOSSDKComponent.GetP2PInterface().AcceptConnection(
new AcceptConnectionOptions() {
LocalUserId = EOSSDKComponent.LocalUserProductId,
RemoteUserId = result.RemoteUserId,
SocketId = result.SocketId
});
} else {
Debug.LogError("P2P Acceptance Request from unknown host ID.");
}
}
protected override void OnReceiveInternalData(InternalMessages type, ProductUserId clientUserId, SocketId socketId) {
if (ignoreAllMessages) {
return;
}
switch (type) {
case InternalMessages.ACCEPT_CONNECT:
Connected = true;
OnConnected.Invoke();
Debug.Log("Connection established.");
break;
case InternalMessages.DISCONNECT:
// CHANGED
OnReceivedError?.Invoke(TransportError.ConnectionClosed, "host disconnected");
Connected = false;
Debug.Log("Disconnected.");
OnDisconnected.Invoke();
break;
default:
Debug.Log("Received unknown message type");
break;
}
}
public void Send(byte[] data, int channelId) => Send(hostProductId, socketId, data, (byte) channelId);
protected override void OnConnectionFailed(ProductUserId remoteId) => OnDisconnected.Invoke();
public void EosNotInitialized() => OnDisconnected.Invoke();
}
}

View File

@ -1,288 +0,0 @@

using Epic.OnlineServices;
using Epic.OnlineServices.P2P;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace EpicTransport {
public abstract class Common {
private PacketReliability[] channels;
private int internal_ch => channels.Length;
protected enum InternalMessages : byte {
CONNECT,
ACCEPT_CONNECT,
DISCONNECT
}
protected struct PacketKey {
public ProductUserId productUserId;
public byte channel;
}
private OnIncomingConnectionRequestCallback OnIncomingConnectionRequest;
ulong incomingNotificationId = 0;
private OnRemoteConnectionClosedCallback OnRemoteConnectionClosed;
ulong outgoingNotificationId = 0;
protected readonly EosTransport transport;
protected List<string> deadSockets;
public bool ignoreAllMessages = false;
// Mapping from PacketKey to a List of Packet Lists
protected Dictionary<PacketKey, List<List<Packet>>> incomingPackets = new Dictionary<PacketKey, List<List<Packet>>>();
protected Common(EosTransport transport) {
channels = transport.Channels;
deadSockets = new List<string>();
AddNotifyPeerConnectionRequestOptions addNotifyPeerConnectionRequestOptions = new AddNotifyPeerConnectionRequestOptions();
addNotifyPeerConnectionRequestOptions.LocalUserId = EOSSDKComponent.LocalUserProductId;
addNotifyPeerConnectionRequestOptions.SocketId = null;
OnIncomingConnectionRequest += OnNewConnection;
OnRemoteConnectionClosed += OnConnectFail;
incomingNotificationId = EOSSDKComponent.GetP2PInterface().AddNotifyPeerConnectionRequest(addNotifyPeerConnectionRequestOptions,
null, OnIncomingConnectionRequest);
AddNotifyPeerConnectionClosedOptions addNotifyPeerConnectionClosedOptions = new AddNotifyPeerConnectionClosedOptions();
addNotifyPeerConnectionClosedOptions.LocalUserId = EOSSDKComponent.LocalUserProductId;
addNotifyPeerConnectionClosedOptions.SocketId = null;
outgoingNotificationId = EOSSDKComponent.GetP2PInterface().AddNotifyPeerConnectionClosed(addNotifyPeerConnectionClosedOptions,
null, OnRemoteConnectionClosed);
if (outgoingNotificationId == 0 || incomingNotificationId == 0) {
Debug.LogError("Couldn't bind notifications with P2P interface");
}
incomingPackets = new Dictionary<PacketKey, List<List<Packet>>>();
this.transport = transport;
}
protected void Dispose() {
EOSSDKComponent.GetP2PInterface().RemoveNotifyPeerConnectionRequest(incomingNotificationId);
EOSSDKComponent.GetP2PInterface().RemoveNotifyPeerConnectionClosed(outgoingNotificationId);
transport.ResetIgnoreMessagesAtStartUpTimer();
}
protected abstract void OnNewConnection(OnIncomingConnectionRequestInfo result);
private void OnConnectFail(OnRemoteConnectionClosedInfo result) {
if (ignoreAllMessages) {
return;
}
OnConnectionFailed(result.RemoteUserId);
switch (result.Reason) {
case ConnectionClosedReason.ClosedByLocalUser:
throw new Exception("Connection cLosed: The Connection was gracecfully closed by the local user.");
case ConnectionClosedReason.ClosedByPeer:
throw new Exception("Connection closed: The connection was gracefully closed by remote user.");
case ConnectionClosedReason.ConnectionClosed:
throw new Exception("Connection closed: The connection was unexpectedly closed.");
case ConnectionClosedReason.ConnectionFailed:
throw new Exception("Connection failed: Failled to establish connection.");
case ConnectionClosedReason.InvalidData:
throw new Exception("Connection failed: The remote user sent us invalid data..");
case ConnectionClosedReason.InvalidMessage:
throw new Exception("Connection failed: The remote user sent us an invalid message.");
case ConnectionClosedReason.NegotiationFailed:
throw new Exception("Connection failed: Negotiation failed.");
case ConnectionClosedReason.TimedOut:
throw new Exception("Connection failed: Timeout.");
case ConnectionClosedReason.TooManyConnections:
throw new Exception("Connection failed: Too many connections.");
case ConnectionClosedReason.UnexpectedError:
throw new Exception("Unexpected Error, connection will be closed");
case ConnectionClosedReason.Unknown:
default:
throw new Exception("Unknown Error, connection has been closed.");
}
}
protected void SendInternal(ProductUserId target, SocketId socketId, InternalMessages type) {
EOSSDKComponent.GetP2PInterface().SendPacket(new SendPacketOptions() {
AllowDelayedDelivery = true,
Channel = (byte) internal_ch,
Data = new byte[] { (byte) type },
LocalUserId = EOSSDKComponent.LocalUserProductId,
Reliability = PacketReliability.ReliableOrdered,
RemoteUserId = target,
SocketId = socketId
});
}
protected void Send(ProductUserId host, SocketId socketId, byte[] msgBuffer, byte channel) {
Result result = EOSSDKComponent.GetP2PInterface().SendPacket(new SendPacketOptions() {
AllowDelayedDelivery = true,
Channel = channel,
Data = msgBuffer,
LocalUserId = EOSSDKComponent.LocalUserProductId,
Reliability = channels[channel],
RemoteUserId = host,
SocketId = socketId
});
if(result != Result.Success) {
Debug.LogError("Send failed " + result);
}
}
private bool Receive(out ProductUserId clientProductUserId, out SocketId socketId, out byte[] receiveBuffer, byte channel) {
Result result = EOSSDKComponent.GetP2PInterface().ReceivePacket(new ReceivePacketOptions() {
LocalUserId = EOSSDKComponent.LocalUserProductId,
MaxDataSizeBytes = P2PInterface.MaxPacketSize,
RequestedChannel = channel
}, out clientProductUserId, out socketId, out channel, out receiveBuffer);
if (result == Result.Success) {
return true;
}
receiveBuffer = null;
clientProductUserId = null;
return false;
}
protected virtual void CloseP2PSessionWithUser(ProductUserId clientUserID, SocketId socketId) {
if (socketId == null) {
Debug.LogWarning("Socket ID == null | " + ignoreAllMessages);
return;
}
if (deadSockets == null) {
Debug.LogWarning("DeadSockets == null");
return;
}
if (deadSockets.Contains(socketId.SocketName)) {
return;
} else {
deadSockets.Add(socketId.SocketName);
}
}
protected void WaitForClose(ProductUserId clientUserID, SocketId socketId) => transport.StartCoroutine(DelayedClose(clientUserID, socketId));
private IEnumerator DelayedClose(ProductUserId clientUserID, SocketId socketId) {
yield return null;
CloseP2PSessionWithUser(clientUserID, socketId);
}
public void ReceiveData() {
try {
// Internal Channel, no fragmentation here
SocketId socketId = new SocketId();
while (transport.enabled && Receive(out ProductUserId clientUserID, out socketId, out byte[] internalMessage, (byte) internal_ch)) {
if (internalMessage.Length == 1) {
OnReceiveInternalData((InternalMessages) internalMessage[0], clientUserID, socketId);
return; // Wait one frame
} else {
Debug.Log("Incorrect package length on internal channel.");
}
}
// Insert new packet at the correct location in the incoming queue
for (int chNum = 0; chNum < channels.Length; chNum++) {
while (transport.enabled && Receive(out ProductUserId clientUserID, out socketId, out byte[] receiveBuffer, (byte) chNum)) {
PacketKey incomingPacketKey = new PacketKey();
incomingPacketKey.productUserId = clientUserID;
incomingPacketKey.channel = (byte)chNum;
Packet packet = new Packet();
packet.FromBytes(receiveBuffer);
if (!incomingPackets.ContainsKey(incomingPacketKey)) {
incomingPackets.Add(incomingPacketKey, new List<List<Packet>>());
}
int packetListIndex = incomingPackets[incomingPacketKey].Count;
for(int i = 0; i < incomingPackets[incomingPacketKey].Count; i++) {
if(incomingPackets[incomingPacketKey][i][0].id == packet.id) {
packetListIndex = i;
break;
}
}
if (packetListIndex == incomingPackets[incomingPacketKey].Count) {
incomingPackets[incomingPacketKey].Add(new List<Packet>());
}
int insertionIndex = -1;
for (int i = 0; i < incomingPackets[incomingPacketKey][packetListIndex].Count; i++) {
if (incomingPackets[incomingPacketKey][packetListIndex][i].fragment > packet.fragment) {
insertionIndex = i;
break;
}
}
if (insertionIndex >= 0) {
incomingPackets[incomingPacketKey][packetListIndex].Insert(insertionIndex, packet);
} else {
incomingPackets[incomingPacketKey][packetListIndex].Add(packet);
}
}
}
// Find fully received packets
List<List<Packet>> emptyPacketLists = new List<List<Packet>>();
foreach(KeyValuePair<PacketKey, List<List<Packet>>> keyValuePair in incomingPackets) {
for(int packetList = 0; packetList < keyValuePair.Value.Count; packetList++) {
bool packetReady = true;
int packetLength = 0;
for (int packet = 0; packet < keyValuePair.Value[packetList].Count; packet++) {
Packet tempPacket = keyValuePair.Value[packetList][packet];
if (tempPacket.fragment != packet || (packet == keyValuePair.Value[packetList].Count - 1 && tempPacket.moreFragments)) {
packetReady = false;
} else {
packetLength += tempPacket.data.Length;
}
}
if (packetReady) {
byte[] data = new byte[packetLength];
int dataIndex = 0;
for (int packet = 0; packet < keyValuePair.Value[packetList].Count; packet++) {
Array.Copy(keyValuePair.Value[packetList][packet].data, 0, data, dataIndex, keyValuePair.Value[packetList][packet].data.Length);
dataIndex += keyValuePair.Value[packetList][packet].data.Length;
}
OnReceiveData(data, keyValuePair.Key.productUserId, keyValuePair.Key.channel);
if(transport.ServerActive() || transport.ClientActive())
emptyPacketLists.Add(keyValuePair.Value[packetList]);
}
}
for (int i = 0; i < emptyPacketLists.Count; i++) {
keyValuePair.Value.Remove(emptyPacketLists[i]);
}
emptyPacketLists.Clear();
}
} catch (Exception e) {
Debug.LogException(e);
}
}
protected abstract void OnReceiveInternalData(InternalMessages type, ProductUserId clientUserID, SocketId socketId);
protected abstract void OnReceiveData(byte[] data, ProductUserId clientUserID, int channel);
protected abstract void OnConnectionFailed(ProductUserId remoteId);
}
}

View File

@ -1,435 +0,0 @@
using Epic.OnlineServices;
using Epic.OnlineServices.Logging;
using Epic.OnlineServices.Platform;
using System;
using System.Runtime.InteropServices;
using UnityEngine;
/// <summary>
/// Manages the Epic Online Services SDK
/// Do not destroy this component!
/// The Epic Online Services SDK can only be initialized once,
/// after releasing the SDK the game has to be restarted in order to initialize the SDK again.
/// In the unity editor the OnDestroy function will not run so that we dont have to restart the editor after play.
/// </summary>
namespace EpicTransport {
[DefaultExecutionOrder(-32000)]
public class EOSSDKComponent : MonoBehaviour {
// Unity Inspector shown variables
[SerializeField]
// CHANGED
public EosApiKey apiKeys;
[Header("User Login")]
public bool authInterfaceLogin = false;
public Epic.OnlineServices.Auth.LoginCredentialType authInterfaceCredentialType = Epic.OnlineServices.Auth.LoginCredentialType.AccountPortal;
public uint devAuthToolPort = 7878;
public string devAuthToolCredentialName = "";
public Epic.OnlineServices.ExternalCredentialType connectInterfaceCredentialType = Epic.OnlineServices.ExternalCredentialType.DeviceidAccessToken;
public string deviceModel = "PC Windows 64bit";
[SerializeField] private string displayName = "User";
public static string DisplayName {
get {
return Instance.displayName;
}
set {
Instance.displayName = value;
}
}
[Header("Misc")]
public LogLevel epicLoggerLevel = LogLevel.Error;
[SerializeField] private bool collectPlayerMetrics = true;
public static bool CollectPlayerMetrics {
get {
return Instance.collectPlayerMetrics;
}
}
public bool checkForEpicLauncherAndRestart = false;
public bool delayedInitialization = false;
public float platformTickIntervalInSeconds = 0.0f;
private float platformTickTimer = 0f;
public uint tickBudgetInMilliseconds = 0;
// End Unity Inspector shown variables
private ulong authExpirationHandle;
private string authInterfaceLoginCredentialId = null;
public static void SetAuthInterfaceLoginCredentialId(string credentialId) => Instance.authInterfaceLoginCredentialId = credentialId;
private string authInterfaceCredentialToken = null;
public static void SetAuthInterfaceCredentialToken(string credentialToken) => Instance.authInterfaceCredentialToken = credentialToken;
private string connectInterfaceCredentialToken = null;
public static void SetConnectInterfaceCredentialToken(string credentialToken) => Instance.connectInterfaceCredentialToken = credentialToken;
private PlatformInterface EOS;
// Interfaces
public static Epic.OnlineServices.Achievements.AchievementsInterface GetAchievementsInterface() => Instance.EOS.GetAchievementsInterface();
public static Epic.OnlineServices.Auth.AuthInterface GetAuthInterface() => Instance.EOS.GetAuthInterface();
public static Epic.OnlineServices.Connect.ConnectInterface GetConnectInterface() => Instance.EOS.GetConnectInterface();
public static Epic.OnlineServices.Ecom.EcomInterface GetEcomInterface() => Instance.EOS.GetEcomInterface();
public static Epic.OnlineServices.Friends.FriendsInterface GetFriendsInterface() => Instance.EOS.GetFriendsInterface();
public static Epic.OnlineServices.Leaderboards.LeaderboardsInterface GetLeaderboardsInterface() => Instance.EOS.GetLeaderboardsInterface();
public static Epic.OnlineServices.Lobby.LobbyInterface GetLobbyInterface() => Instance.EOS.GetLobbyInterface();
public static Epic.OnlineServices.Metrics.MetricsInterface GetMetricsInterface() => Instance.EOS.GetMetricsInterface(); // Handled by the transport automatically, only use this interface if Mirror is not used for singleplayer
public static Epic.OnlineServices.Mods.ModsInterface GetModsInterface() => Instance.EOS.GetModsInterface();
public static Epic.OnlineServices.P2P.P2PInterface GetP2PInterface() => Instance.EOS.GetP2PInterface();
public static Epic.OnlineServices.PlayerDataStorage.PlayerDataStorageInterface GetPlayerDataStorageInterface() => Instance.EOS.GetPlayerDataStorageInterface();
public static Epic.OnlineServices.Presence.PresenceInterface GetPresenceInterface() => Instance.EOS.GetPresenceInterface();
public static Epic.OnlineServices.Sessions.SessionsInterface GetSessionsInterface() => Instance.EOS.GetSessionsInterface();
public static Epic.OnlineServices.TitleStorage.TitleStorageInterface GetTitleStorageInterface() => Instance.EOS.GetTitleStorageInterface();
public static Epic.OnlineServices.UI.UIInterface GetUIInterface() => Instance.EOS.GetUIInterface();
public static Epic.OnlineServices.UserInfo.UserInfoInterface GetUserInfoInterface() => Instance.EOS.GetUserInfoInterface();
protected EpicAccountId localUserAccountId;
public static EpicAccountId LocalUserAccountId {
get {
return Instance.localUserAccountId;
}
}
protected string localUserAccountIdString;
public static string LocalUserAccountIdString {
get {
return Instance.localUserAccountIdString;
}
}
protected ProductUserId localUserProductId;
public static ProductUserId LocalUserProductId {
get {
return Instance.localUserProductId;
}
}
protected string localUserProductIdString;
public static string LocalUserProductIdString {
get {
return Instance.localUserProductIdString;
}
}
protected bool initialized;
public static bool Initialized {
get {
return Instance.initialized;
}
}
protected bool isConnecting;
public static bool IsConnecting {
get {
return Instance.isConnecting;
}
}
protected static EOSSDKComponent instance;
protected static EOSSDKComponent Instance {
get {
if (instance == null) {
return new GameObject("EOSSDKComponent").AddComponent<EOSSDKComponent>();
} else {
return instance;
}
}
}
public static void Tick() {
instance.platformTickTimer -= Time.deltaTime;
instance.EOS.Tick();
}
// If we're in editor, we should dynamically load and unload the SDK between play sessions.
// This allows us to initialize the SDK each time the game is run in editor.
#if UNITY_EDITOR_WIN
[DllImport("Kernel32.dll")]
private static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("Kernel32.dll")]
private static extern int FreeLibrary(IntPtr hLibModule);
[DllImport("Kernel32.dll")]
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
private IntPtr libraryPointer;
#endif
#if UNITY_EDITOR_LINUX
[DllImport("libdl.so", EntryPoint = "dlopen")]
private static extern IntPtr LoadLibrary(String lpFileName, int flags = 2);
[DllImport("libdl.so", EntryPoint = "dlclose")]
private static extern int FreeLibrary(IntPtr hLibModule);
[DllImport("libdl.so")]
private static extern IntPtr dlsym(IntPtr handle, String symbol);
[DllImport("libdl.so")]
private static extern IntPtr dlerror();
private static IntPtr GetProcAddress(IntPtr hModule, string lpProcName) {
// clear previous errors if any
dlerror();
var res = dlsym(hModule, lpProcName);
var errPtr = dlerror();
if (errPtr != IntPtr.Zero) {
throw new Exception("dlsym: " + Marshal.PtrToStringAnsi(errPtr));
}
return res;
}
private IntPtr libraryPointer;
#endif
private void Awake() {
// Initialize Java version of the SDK with a reference to the VM with JNI
// See https://eoshelp.epicgames.com/s/question/0D54z00006ufJBNCA2/cant-get-createdeviceid-to-work-in-unity-android-c-sdk?language=en_US
if (Application.platform == RuntimePlatform.Android)
{
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject context = activity.Call<AndroidJavaObject>("getApplicationContext");
AndroidJavaClass EOS_SDK_JAVA = new AndroidJavaClass("com.epicgames.mobile.eossdk.EOSSDK");
EOS_SDK_JAVA.CallStatic("init", context);
}
// Prevent multiple instances
if (instance != null) {
Destroy(gameObject);
return;
}
instance = this;
#if UNITY_EDITOR
var libraryPath = "Assets/Mirror/Runtime/Transport/EpicOnlineTransport/EOSSDK/" + Config.LibraryName;
libraryPointer = LoadLibrary(libraryPath);
if (libraryPointer == IntPtr.Zero) {
throw new Exception("Failed to load library" + libraryPath);
}
Bindings.Hook(libraryPointer, GetProcAddress);
#endif
if (!delayedInitialization) {
Initialize();
}
}
protected void InitializeImplementation() {
isConnecting = true;
var initializeOptions = new InitializeOptions() {
ProductName = apiKeys.epicProductName,
ProductVersion = apiKeys.epicProductVersion
};
var initializeResult = PlatformInterface.Initialize(initializeOptions);
// This code is called each time the game is run in the editor, so we catch the case where the SDK has already been initialized in the editor.
var isAlreadyConfiguredInEditor = Application.isEditor && initializeResult == Result.AlreadyConfigured;
if (initializeResult != Result.Success && !isAlreadyConfiguredInEditor) {
throw new System.Exception("Failed to initialize platform: " + initializeResult);
}
// The SDK outputs lots of information that is useful for debugging.
// Make sure to set up the logging interface as early as possible: after initializing.
LoggingInterface.SetLogLevel(LogCategory.AllCategories, epicLoggerLevel);
LoggingInterface.SetCallback(message => Logger.EpicDebugLog(message));
var options = new Options() {
ProductId = apiKeys.epicProductId,
SandboxId = apiKeys.epicSandboxId,
DeploymentId = apiKeys.epicDeploymentId,
ClientCredentials = new ClientCredentials() {
ClientId = apiKeys.epicClientId,
ClientSecret = apiKeys.epicClientSecret
},
TickBudgetInMilliseconds = tickBudgetInMilliseconds
};
EOS = PlatformInterface.Create(options);
if (EOS == null) {
throw new System.Exception("Failed to create platform");
}
if (checkForEpicLauncherAndRestart) {
Result result = EOS.CheckForLauncherAndRestart();
// If not started through epic launcher the app will be restarted and we can quit
if (result != Result.NoChange) {
// Log error if launcher check failed, but still quit to prevent hacking
if (result == Result.UnexpectedError) {
Debug.LogError("Unexpected Error while checking if app was started through epic launcher");
}
Application.Quit();
}
}
// If we use the Auth interface then only login into the Connect interface after finishing the auth interface login
// If we don't use the Auth interface we can directly login to the Connect interface
if (authInterfaceLogin) {
if (authInterfaceCredentialType == Epic.OnlineServices.Auth.LoginCredentialType.Developer) {
authInterfaceLoginCredentialId = "localhost:" + devAuthToolPort;
authInterfaceCredentialToken = devAuthToolCredentialName;
}
// Login to Auth Interface
Epic.OnlineServices.Auth.LoginOptions loginOptions = new Epic.OnlineServices.Auth.LoginOptions() {
Credentials = new Epic.OnlineServices.Auth.Credentials() {
Type = authInterfaceCredentialType,
Id = authInterfaceLoginCredentialId,
Token = authInterfaceCredentialToken
},
ScopeFlags = Epic.OnlineServices.Auth.AuthScopeFlags.BasicProfile | Epic.OnlineServices.Auth.AuthScopeFlags.FriendsList | Epic.OnlineServices.Auth.AuthScopeFlags.Presence
};
EOS.GetAuthInterface().Login(loginOptions, null, OnAuthInterfaceLogin);
} else {
// Login to Connect Interface
if (connectInterfaceCredentialType == Epic.OnlineServices.ExternalCredentialType.DeviceidAccessToken) {
Epic.OnlineServices.Connect.CreateDeviceIdOptions createDeviceIdOptions = new Epic.OnlineServices.Connect.CreateDeviceIdOptions();
createDeviceIdOptions.DeviceModel = deviceModel;
EOS.GetConnectInterface().CreateDeviceId(createDeviceIdOptions, null, OnCreateDeviceId);
} else {
ConnectInterfaceLogin();
}
}
}
public static void Initialize() {
if (Instance.initialized || Instance.isConnecting) {
return;
}
Instance.InitializeImplementation();
}
private void OnAuthInterfaceLogin(Epic.OnlineServices.Auth.LoginCallbackInfo loginCallbackInfo) {
if (loginCallbackInfo.ResultCode == Result.Success) {
Debug.Log("Auth Interface Login succeeded");
string accountIdString;
Result result = loginCallbackInfo.LocalUserId.ToString(out accountIdString);
if (Result.Success == result) {
Debug.Log("EOS User ID:" + accountIdString);
localUserAccountIdString = accountIdString;
localUserAccountId = loginCallbackInfo.LocalUserId;
}
ConnectInterfaceLogin();
} else if(Epic.OnlineServices.Common.IsOperationComplete(loginCallbackInfo.ResultCode)){
Debug.Log("Login returned " + loginCallbackInfo.ResultCode);
}
}
private void OnCreateDeviceId(Epic.OnlineServices.Connect.CreateDeviceIdCallbackInfo createDeviceIdCallbackInfo) {
if (createDeviceIdCallbackInfo.ResultCode == Result.Success || createDeviceIdCallbackInfo.ResultCode == Result.DuplicateNotAllowed) {
ConnectInterfaceLogin();
} else if(Epic.OnlineServices.Common.IsOperationComplete(createDeviceIdCallbackInfo.ResultCode)) {
Debug.Log("Device ID creation returned " + createDeviceIdCallbackInfo.ResultCode);
}
}
private void ConnectInterfaceLogin() {
var loginOptions = new Epic.OnlineServices.Connect.LoginOptions();
if (connectInterfaceCredentialType == Epic.OnlineServices.ExternalCredentialType.Epic) {
Epic.OnlineServices.Auth.Token token;
Result result = EOS.GetAuthInterface().CopyUserAuthToken(new Epic.OnlineServices.Auth.CopyUserAuthTokenOptions(), localUserAccountId, out token);
if (result == Result.Success) {
connectInterfaceCredentialToken = token.AccessToken;
} else {
Debug.LogError("Failed to retrieve User Auth Token");
}
} else if (connectInterfaceCredentialType == Epic.OnlineServices.ExternalCredentialType.DeviceidAccessToken) {
loginOptions.UserLoginInfo = new Epic.OnlineServices.Connect.UserLoginInfo();
loginOptions.UserLoginInfo.DisplayName = displayName;
}
loginOptions.Credentials = new Epic.OnlineServices.Connect.Credentials();
loginOptions.Credentials.Type = connectInterfaceCredentialType;
loginOptions.Credentials.Token = connectInterfaceCredentialToken;
EOS.GetConnectInterface().Login(loginOptions, null, OnConnectInterfaceLogin);
}
private void OnConnectInterfaceLogin(Epic.OnlineServices.Connect.LoginCallbackInfo loginCallbackInfo) {
if (loginCallbackInfo.ResultCode == Result.Success) {
Debug.Log("Connect Interface Login succeeded");
string productIdString;
Result result = loginCallbackInfo.LocalUserId.ToString(out productIdString);
if (Result.Success == result) {
Debug.Log("EOS User Product ID:" + productIdString);
localUserProductIdString = productIdString;
localUserProductId = loginCallbackInfo.LocalUserId;
}
initialized = true;
isConnecting = false;
var authExpirationOptions = new Epic.OnlineServices.Connect.AddNotifyAuthExpirationOptions();
authExpirationHandle = EOS.GetConnectInterface().AddNotifyAuthExpiration(authExpirationOptions, null, OnAuthExpiration);
} else if (Epic.OnlineServices.Common.IsOperationComplete(loginCallbackInfo.ResultCode)) {
Debug.Log("Login returned " + loginCallbackInfo.ResultCode + "\nRetrying...");
EOS.GetConnectInterface().CreateUser(new Epic.OnlineServices.Connect.CreateUserOptions() { ContinuanceToken = loginCallbackInfo.ContinuanceToken }, null, (Epic.OnlineServices.Connect.CreateUserCallbackInfo cb) => {
if (cb.ResultCode != Result.Success) { Debug.Log(cb.ResultCode); return; }
localUserProductId = cb.LocalUserId;
ConnectInterfaceLogin();
});
}
}
private void OnAuthExpiration(Epic.OnlineServices.Connect.AuthExpirationCallbackInfo authExpirationCallbackInfo) {
Debug.Log("AuthExpiration callback");
EOS.GetConnectInterface().RemoveNotifyAuthExpiration(authExpirationHandle);
ConnectInterfaceLogin();
}
// Calling tick on a regular interval is required for callbacks to work.
private void LateUpdate() {
if (EOS != null) {
platformTickTimer += Time.deltaTime;
if (platformTickTimer >= platformTickIntervalInSeconds) {
platformTickTimer = 0;
EOS.Tick();
}
}
}
private void OnApplicationQuit() {
if (EOS != null) {
EOS.Release();
EOS = null;
PlatformInterface.Shutdown();
}
// Unhook the library in the editor, this makes it possible to load the library again after stopping to play
#if UNITY_EDITOR
if (libraryPointer != IntPtr.Zero) {
Bindings.Unhook();
// Free until the module ref count is 0
while (FreeLibrary(libraryPointer) != 0) { }
libraryPointer = IntPtr.Zero;
}
#endif
}
}
}

View File

@ -1,23 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Create an instance of this scriptable object and assign your eos api keys to it
/// Then add a reference to it to the EOSSDKComponent
///
/// You can right click in your Project view in unity and choose:
/// Create -> EOS -> API Key
/// in order to create an instance of this scriptable object
/// </summary>
[CreateAssetMenu(fileName = "EosApiKey", menuName = "EOS/API Key", order = 1)]
public class EosApiKey : ScriptableObject {
public string epicProductName = "MyApplication";
public string epicProductVersion = "1.0";
public string epicProductId = "";
public string epicSandboxId = "";
public string epicDeploymentId = "";
public string epicClientId = "";
public string epicClientSecret = "";
}

View File

@ -1,331 +0,0 @@
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) {
if (client == null)
{
OnClientDisconnected.Invoke();
return;
}
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();
}
}
}
}

View File

@ -1,20 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>EpicTransport</RootNamespace>
<Title>EpicOnlineTransport</Title>
<Authors>Nudge Nudge Games</Authors>
<Company>Nudge Nudge Games</Company>
<Copyright>Copyright © 2021 Nudge Nudge Games</Copyright>
<PackageLicenseFile>License.md</PackageLicenseFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OuterWildsGameLibs" Version="1.1.13.393" IncludeAssets="compile" />
<Reference Include="../Mirror/*.dll" />
</ItemGroup>
<ItemGroup>
<None Update="License.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
</Project>

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2021 Nudge Nudge Games
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,30 +0,0 @@
using Epic.OnlineServices.Logging;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace EpicTransport {
public static class Logger {
public static void EpicDebugLog(LogMessage message) {
switch (message.Level) {
case LogLevel.Info:
Debug.Log($"Epic Manager: Category - {message.Category} Message - {message.Message}");
break;
case LogLevel.Error:
Debug.LogError($"Epic Manager: Category - {message.Category} Message - {message.Message}");
break;
case LogLevel.Warning:
Debug.LogWarning($"Epic Manager: Category - {message.Category} Message - {message.Message}");
break;
case LogLevel.Fatal:
Debug.LogException(new Exception($"Epic Manager: Category - {message.Category} Message - {message.Message}"));
break;
default:
Debug.Log($"Epic Manager: Unknown log processing. Category - {message.Category} Message - {message.Message}");
break;
}
}
}
}

View File

@ -1,47 +0,0 @@
using System;
namespace EpicTransport {
public struct Packet {
public const int headerSize = sizeof(uint) + sizeof(uint) + 1;
public int size => headerSize + data.Length;
// header
public int id;
public int fragment;
public bool moreFragments;
// body
public byte[] data;
public byte[] ToBytes() {
byte[] array = new byte[size];
// Copy id
array[0] = (byte) id;
array[1] = (byte) (id >> 8);
array[2] = (byte) (id >> 0x10);
array[3] = (byte) (id >> 0x18);
// Copy fragment
array[4] = (byte) fragment;
array[5] = (byte) (fragment >> 8);
array[6] = (byte) (fragment >> 0x10);
array[7] = (byte) (fragment >> 0x18);
array[8] = moreFragments ? (byte)1 : (byte)0;
Array.Copy(data, 0, array, 9, data.Length);
return array;
}
public void FromBytes(byte[] array) {
id = BitConverter.ToInt32(array, 0);
fragment = BitConverter.ToInt32(array, 4);
moreFragments = array[8] == 1;
data = new byte[array.Length - 9];
Array.Copy(array, 9, data, 0, data.Length);
}
}
}

View File

@ -1,36 +0,0 @@
using System;
using System.Text;
public class RandomString {
// Generates a random string with a given size.
public static string Generate(int size) {
var builder = new StringBuilder(size);
Random random = new Random();
// Unicode/ASCII Letters are divided into two blocks
// (Letters 6590 / 97122):
// The first group containing the uppercase letters and
// the second group containing the lowercase.
// char is a single Unicode character
char offsetLowerCase = 'a';
char offsetUpperCase = 'A';
const int lettersOffset = 26; // A...Z or a..z: length=26
for (var i = 0; i < size; i++) {
char offset;
if(random.Next(0,2) == 0) {
offset = offsetLowerCase;
} else {
offset = offsetUpperCase;
}
var @char = (char) random.Next(offset, offset + lettersOffset);
builder.Append(@char);
}
return builder.ToString();
}
}

View File

@ -1,192 +0,0 @@
using Epic.OnlineServices;
using Epic.OnlineServices.P2P;
using Mirror;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace EpicTransport {
public class Server : Common {
private event Action<int> OnConnected;
private event Action<int, byte[], int> OnReceivedData;
private event Action<int> OnDisconnected;
// CHANGED
private event Action<int, TransportError, string> OnReceivedError;
private BidirectionalDictionary<ProductUserId, int> epicToMirrorIds;
private Dictionary<ProductUserId, SocketId> epicToSocketIds;
private int maxConnections;
private int nextConnectionID;
public static Server CreateServer(EosTransport transport, int maxConnections) {
Server s = new Server(transport, maxConnections);
s.OnConnected += (id) => transport.OnServerConnected.Invoke(id);
s.OnDisconnected += (id) => transport.OnServerDisconnected.Invoke(id);
s.OnReceivedData += (id, data, channel) => transport.OnServerDataReceived.Invoke(id, new ArraySegment<byte>(data), channel);
// CHANGED
s.OnReceivedError += (id, error, reason) => transport.OnServerError?.Invoke(id, error, reason);
if (!EOSSDKComponent.Initialized) {
Debug.LogError("EOS not initialized.");
}
return s;
}
private Server(EosTransport transport, int maxConnections) : base(transport) {
this.maxConnections = maxConnections;
epicToMirrorIds = new BidirectionalDictionary<ProductUserId, int>();
epicToSocketIds = new Dictionary<ProductUserId, SocketId>();
nextConnectionID = 1;
}
protected override void OnNewConnection(OnIncomingConnectionRequestInfo result) {
if (ignoreAllMessages) {
return;
}
if (deadSockets.Contains(result.SocketId.SocketName)) {
Debug.LogError("Received incoming connection request from dead socket");
return;
}
EOSSDKComponent.GetP2PInterface().AcceptConnection(
new AcceptConnectionOptions() {
LocalUserId = EOSSDKComponent.LocalUserProductId,
RemoteUserId = result.RemoteUserId,
SocketId = result.SocketId
});
}
protected override void OnReceiveInternalData(InternalMessages type, ProductUserId clientUserId, SocketId socketId) {
if (ignoreAllMessages) {
return;
}
switch (type) {
case InternalMessages.CONNECT:
if (epicToMirrorIds.Count >= maxConnections) {
Debug.LogError("Reached max connections");
//CloseP2PSessionWithUser(clientUserId, socketId);
SendInternal(clientUserId, socketId, InternalMessages.DISCONNECT);
return;
}
SendInternal(clientUserId, socketId, InternalMessages.ACCEPT_CONNECT);
int connectionId = nextConnectionID++;
epicToMirrorIds.Add(clientUserId, connectionId);
epicToSocketIds.Add(clientUserId, socketId);
OnConnected.Invoke(connectionId);
string clientUserIdString;
clientUserId.ToString(out clientUserIdString);
Debug.Log($"Client with Product User ID {clientUserIdString} connected. Assigning connection id {connectionId}");
break;
case InternalMessages.DISCONNECT:
if (epicToMirrorIds.TryGetValue(clientUserId, out int connId)) {
OnDisconnected.Invoke(connId);
//CloseP2PSessionWithUser(clientUserId, socketId);
epicToMirrorIds.Remove(clientUserId);
epicToSocketIds.Remove(clientUserId);
Debug.Log($"Client with Product User ID {clientUserId} disconnected.");
} else {
// CHANGED
OnReceivedError?.Invoke(-1, TransportError.InvalidReceive, "ERROR Unknown Product User ID");
}
break;
default:
Debug.Log("Received unknown message type");
break;
}
}
protected override void OnReceiveData(byte[] data, ProductUserId clientUserId, int channel) {
if (ignoreAllMessages) {
return;
}
if (epicToMirrorIds.TryGetValue(clientUserId, out int connectionId)) {
OnReceivedData.Invoke(connectionId, data, channel);
} else {
SocketId socketId;
epicToSocketIds.TryGetValue(clientUserId, out socketId);
CloseP2PSessionWithUser(clientUserId, socketId);
string productId;
clientUserId.ToString(out productId);
Debug.LogError("Data received from epic client thats not known " + productId);
// CHANGED
OnReceivedError?.Invoke(-1, TransportError.InvalidReceive, "ERROR Unknown product ID");
}
}
public void Disconnect(int connectionId) {
if (epicToMirrorIds.TryGetValue(connectionId, out ProductUserId userId)) {
SocketId socketId;
epicToSocketIds.TryGetValue(userId, out socketId);
SendInternal(userId, socketId, InternalMessages.DISCONNECT);
epicToMirrorIds.Remove(userId);
epicToSocketIds.Remove(userId);
} else {
Debug.LogWarning("Trying to disconnect unknown connection id: " + connectionId);
}
}
public void Shutdown() {
foreach (KeyValuePair<ProductUserId, int> client in epicToMirrorIds) {
Disconnect(client.Value);
SocketId socketId;
epicToSocketIds.TryGetValue(client.Key, out socketId);
WaitForClose(client.Key, socketId);
}
ignoreAllMessages = true;
ReceiveData();
Dispose();
}
public void SendAll(int connectionId, byte[] data, int channelId) {
if (epicToMirrorIds.TryGetValue(connectionId, out ProductUserId userId)) {
SocketId socketId;
epicToSocketIds.TryGetValue(userId, out socketId);
Send(userId, socketId, data, (byte)channelId);
} else {
Debug.LogError("Trying to send on unknown connection: " + connectionId);
// CHANGED
OnReceivedError?.Invoke(connectionId, TransportError.InvalidSend, "ERROR Unknown Connection");
}
}
public string ServerGetClientAddress(int connectionId) {
if (epicToMirrorIds.TryGetValue(connectionId, out ProductUserId userId)) {
string userIdString;
userId.ToString(out userIdString);
return userIdString;
} else {
Debug.LogError("Trying to get info on unknown connection: " + connectionId);
// CHANGED
OnReceivedError?.Invoke(connectionId, TransportError.Unexpected, "ERROR Unknown Connection");
return string.Empty;
}
}
protected override void OnConnectionFailed(ProductUserId remoteId) {
if (ignoreAllMessages) {
return;
}
int connectionId = epicToMirrorIds.TryGetValue(remoteId, out int connId) ? connId : nextConnectionID++;
OnDisconnected.Invoke(connectionId);
Debug.LogError("Connection Failed, removing user");
epicToMirrorIds.Remove(remoteId);
epicToSocketIds.Remove(remoteId);
}
}
}

View File

@ -1,20 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<Title>Epic Rerouter</Title>
<Company>William Corby, Henry Pointer</Company>
<Authors>William Corby, Henry Pointer</Authors>
<Copyright>Copyright © William Corby, Henry Pointer 2022-2023</Copyright>
</PropertyGroup>
<ItemGroup>
<None Include="..\LICENSE">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="OuterWildsGameLibs" Version="1.1.13.393" IncludeAssets="compile" />
<PackageReference Include="OWML" Version="2.9.0" IncludeAssets="compile" />
</ItemGroup>
</Project>

View File

@ -1,52 +0,0 @@
using Epic.OnlineServices;
using Epic.OnlineServices.Ecom;
namespace EpicRerouter.ExeSide;
public static class EpicEntitlementRetriever
{
private const string _eosDlcItemID = "49a9ac61fe464cbf8c8c73f46b3f1133";
private static EcomInterface _ecomInterface;
private static OwnershipStatus _epicDlcOwnershipStatus;
private static bool _epicResultReceived;
public static void Init() =>
EpicPlatformManager.OnAuthSuccess += EOSQueryOwnership;
public static void Uninit() =>
EpicPlatformManager.OnAuthSuccess -= EOSQueryOwnership;
public static EntitlementsManager.AsyncOwnershipStatus GetOwnershipStatus()
{
if (!_epicResultReceived)
{
return EntitlementsManager.AsyncOwnershipStatus.NotReady;
}
return _epicDlcOwnershipStatus == OwnershipStatus.Owned ?
EntitlementsManager.AsyncOwnershipStatus.Owned : EntitlementsManager.AsyncOwnershipStatus.NotOwned;
}
private static void EOSQueryOwnership()
{
Program.Log("[EOS] querying DLC ownership");
_ecomInterface = EpicPlatformManager.PlatformInterface.GetEcomInterface();
var queryOwnershipOptions = new QueryOwnershipOptions
{
LocalUserId = EpicPlatformManager.LocalUserId,
CatalogItemIds = new[] { _eosDlcItemID }
};
_ecomInterface.QueryOwnership(queryOwnershipOptions, null, OnEOSQueryOwnershipComplete);
}
private static void OnEOSQueryOwnershipComplete(QueryOwnershipCallbackInfo data)
{
if (data.ResultCode == Result.Success)
{
_epicDlcOwnershipStatus = data.ItemOwnership[0].OwnershipStatus;
_epicResultReceived = true;
Program.Log($"[EOS] Query DLC ownership complete: {_epicDlcOwnershipStatus}");
}
}
}

View File

@ -1,140 +0,0 @@
using Epic.OnlineServices;
using Epic.OnlineServices.Auth;
using Epic.OnlineServices.Platform;
using System;
using System.Threading;
namespace EpicRerouter.ExeSide;
public static class EpicPlatformManager
{
private const string _eosProductID = "prod-starfish";
private const string _eosSandboxID = "starfish";
private const string _eosDeploymentID = "e176ecc84fbc4dd8934664684f44dc71";
private const string _eosClientID = "5c553c6accee4111bc8ea3a3ae52229b";
private const string _eosClientSecret = "k87Nfp75BzPref4nJFnnbNjYXQQR";
private const float _tickInterval = 0.1f;
public static PlatformInterface PlatformInterface;
public static EpicAccountId LocalUserId;
public static OWEvent OnAuthSuccess = new(1);
public static void Init()
{
if (PlatformInterface == null)
{
try
{
InitPlatform();
}
catch (EOSInitializeException ex)
{
if (ex.Result == Result.AlreadyConfigured)
{
throw new Exception("[EOS] platform already configured!");
}
}
}
Auth();
}
public static void Tick()
{
PlatformInterface.Tick();
Thread.Sleep(TimeSpan.FromSeconds(_tickInterval));
}
public static void Uninit()
{
PlatformInterface.Release();
PlatformInterface = null;
PlatformInterface.Shutdown();
}
private static void InitPlatform()
{
var result = PlatformInterface.Initialize(new InitializeOptions
{
ProductName = Program.ProductName,
ProductVersion = Program.Version
});
if (result != Result.Success)
{
throw new EOSInitializeException("Failed to initialize Epic Online Services platform: ", result);
}
var options = new Options
{
ProductId = _eosProductID,
SandboxId = _eosSandboxID,
ClientCredentials = new ClientCredentials
{
ClientId = _eosClientID,
ClientSecret = _eosClientSecret
},
DeploymentId = _eosDeploymentID
};
PlatformInterface = PlatformInterface.Create(options);
Program.Log("[EOS] Platform interface has been created");
}
private static void Auth()
{
Program.Log("[EOS] Authenticating...");
var loginOptions = new LoginOptions
{
Credentials = new Credentials
{
Type = LoginCredentialType.ExchangeCode,
Id = null,
Token = GetPasswordFromCommandLine()
},
ScopeFlags = 0
};
if (PlatformInterface == null)
{
throw new Exception("[EOS] Platform interface is null!");
}
PlatformInterface.GetAuthInterface().Login(loginOptions, null, OnLogin);
}
private static string GetPasswordFromCommandLine()
{
var commandLineArgs = Environment.GetCommandLineArgs();
foreach (var arg in commandLineArgs)
{
if (arg.Contains("AUTH_PASSWORD"))
{
return arg.Split('=')[1];
}
}
return null;
}
private static void OnLogin(LoginCallbackInfo loginCallbackInfo)
{
if (loginCallbackInfo.ResultCode == Result.Success)
{
LocalUserId = loginCallbackInfo.LocalUserId;
LocalUserId.ToString(out var s);
Program.Log($"[EOS SDK] login success! user ID: {s}");
OnAuthSuccess.Invoke();
return;
}
throw new Exception("[EOS SDK] Login failed");
}
private class EOSInitializeException : Exception
{
public readonly Result Result;
public EOSInitializeException(string msg, Result initResult) :
base(msg) =>
Result = initResult;
}
}

View File

@ -1,56 +0,0 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
namespace EpicRerouter.ExeSide;
public static class Program
{
public static string ProductName;
public static string Version;
private static void Main(string[] args)
{
ProductName = args[0];
Log($"product name = {ProductName}");
Version = args[1];
Log($"version = {Version}");
var managedDir = args[2];
Log($"managed dir = {managedDir}");
var gameArgs = args.Skip(3).ToArray();
Log($"game args = {string.Join(", ", gameArgs)}");
AppDomain.CurrentDomain.AssemblyResolve += (_, e) =>
{
var name = new AssemblyName(e.Name).Name + ".dll";
var path = Path.Combine(managedDir, name);
return File.Exists(path) ? Assembly.LoadFile(path) : null;
};
Go();
}
private static void Go()
{
try
{
EpicPlatformManager.Init();
EpicEntitlementRetriever.Init();
while (EpicEntitlementRetriever.GetOwnershipStatus() == EntitlementsManager.AsyncOwnershipStatus.NotReady)
{
EpicPlatformManager.Tick();
}
}
finally
{
EpicEntitlementRetriever.Uninit();
EpicPlatformManager.Uninit();
Environment.Exit((int)EpicEntitlementRetriever.GetOwnershipStatus());
}
}
public static void Log(object msg) => Console.Error.WriteLine(msg);
}

View File

@ -1,68 +0,0 @@
using HarmonyLib;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace EpicRerouter.ModSide;
public static class Interop
{
public static EntitlementsManager.AsyncOwnershipStatus OwnershipStatus = EntitlementsManager.AsyncOwnershipStatus.NotReady;
public static void Go()
{
if (typeof(EpicPlatformManager).GetField("_platformInterface", BindingFlags.NonPublic | BindingFlags.Instance) == null)
{
Log("not epic. don't reroute");
return;
}
Log("go");
Patches.Apply();
var processPath = Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!,
"EpicRerouter.exe"
);
Log($"process path = {processPath}");
var gamePath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(typeof(EpicPlatformManager).Assembly.Location)!, ".."));
Log($"game path = {gamePath}");
var workingDirectory = Path.Combine(gamePath, "Plugins", "x86_64");
Log($"working dir = {workingDirectory}");
var args = new[]
{
Application.productName,
Application.version,
Path.Combine(gamePath, "Managed")
};
Log($"args = {args.Join()}");
var gameArgs = Environment.GetCommandLineArgs();
Log($"game args = {gameArgs.Join()}");
var process = Process.Start(new ProcessStartInfo
{
FileName = processPath,
WorkingDirectory = workingDirectory,
Arguments = args
.Concat(gameArgs)
.Join(x => $"\"{x}\"", " "),
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true
});
process!.WaitForExit();
OwnershipStatus = (EntitlementsManager.AsyncOwnershipStatus)process.ExitCode;
Log($"ownership status = {OwnershipStatus}");
Log($"output:\n{process.StandardOutput.ReadToEnd()}");
Log($"error:\n{process.StandardError.ReadToEnd()}");
}
public static void Log(object msg) => Debug.Log($"[EpicRerouter] {msg}");
}

View File

@ -1,65 +0,0 @@
using HarmonyLib;
using UnityEngine;
using static EntitlementsManager;
namespace EpicRerouter.ModSide;
[HarmonyPatch(typeof(EpicPlatformManager))]
public static class Patches
{
public static void Apply()
{
var harmony = new Harmony(typeof(Patches).FullName);
harmony.PatchAll(typeof(EntitlementsManagerPatches));
harmony.PatchAll(typeof(EpicPlatformManagerPatches));
}
[HarmonyPatch(typeof(EntitlementsManager))]
private static class EntitlementsManagerPatches
{
[HarmonyPrefix]
[HarmonyPatch(nameof(EntitlementsManager.InitializeOnAwake))]
private static bool InitializeOnAwake(EntitlementsManager __instance)
{
Object.Destroy(__instance);
return false;
}
[HarmonyPrefix]
[HarmonyPatch(nameof(EntitlementsManager.Start))]
private static bool Start() => false;
[HarmonyPrefix]
[HarmonyPatch(nameof(EntitlementsManager.OnDestroy))]
private static bool OnDestroy() => false;
[HarmonyPrefix]
[HarmonyPatch(nameof(EntitlementsManager.IsDlcOwned))]
private static bool IsDlcOwned(out AsyncOwnershipStatus __result)
{
__result = Interop.OwnershipStatus;
Interop.Log($"ownership status = {__result}");
return false;
}
}
[HarmonyPatch(typeof(EpicPlatformManager))]
private static class EpicPlatformManagerPatches
{
[HarmonyPrefix]
[HarmonyPatch("Awake")]
private static bool Awake(EpicPlatformManager __instance)
{
Object.Destroy(__instance);
return false;
}
[HarmonyPrefix]
[HarmonyPatch("Start")]
private static bool Start() => false;
[HarmonyPrefix]
[HarmonyPatch("OnDestroy")]
private static bool OnDestroy() => false;
}
}

12
QSB.sln
View File

@ -15,10 +15,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MirrorWeaver", "MirrorWeaver\MirrorWeaver.csproj", "{DA8A467E-15BA-456C-9034-6EB80BAF1FF9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EpicOnlineTransport", "EpicOnlineTransport\EpicOnlineTransport.csproj", "{971AA4A1-6729-40DE-AADF-2754F1E8783A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EpicRerouter", "EpicRerouter\EpicRerouter.csproj", "{639EFAEE-C4A1-4DA2-8457-D0472A9F6343}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -33,14 +29,6 @@ Global
{DA8A467E-15BA-456C-9034-6EB80BAF1FF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA8A467E-15BA-456C-9034-6EB80BAF1FF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA8A467E-15BA-456C-9034-6EB80BAF1FF9}.Release|Any CPU.Build.0 = Release|Any CPU
{971AA4A1-6729-40DE-AADF-2754F1E8783A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{971AA4A1-6729-40DE-AADF-2754F1E8783A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{971AA4A1-6729-40DE-AADF-2754F1E8783A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{971AA4A1-6729-40DE-AADF-2754F1E8783A}.Release|Any CPU.Build.0 = Release|Any CPU
{639EFAEE-C4A1-4DA2-8457-D0472A9F6343}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{639EFAEE-C4A1-4DA2-8457-D0472A9F6343}.Debug|Any CPU.Build.0 = Debug|Any CPU
{639EFAEE-C4A1-4DA2-8457-D0472A9F6343}.Release|Any CPU.ActiveCfg = Release|Any CPU
{639EFAEE-C4A1-4DA2-8457-D0472A9F6343}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,5 +1,4 @@
using EpicTransport;
using Mirror;
using Mirror;
using OWML.Common;
using QSB.Localization;
using QSB.Messaging;
@ -635,7 +634,7 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
if (!QSBCore.UseKcpTransport)
{
var productUserId = EOSSDKComponent.LocalUserProductIdString;
/*var productUserId = EOSSDKComponent.LocalUserProductIdString;
PopupClose += confirm =>
{
@ -650,7 +649,7 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
OpenInfoPopup(string.Format(QSBLocalization.Current.CopyProductUserIDToClipboard, productUserId)
, QSBLocalization.Current.Yes
, QSBLocalization.Current.No);
, QSBLocalization.Current.No);*/
}
else
{

View File

@ -72,8 +72,6 @@
<PackageReference Include="OWML" Version="2.9.0" IncludeAssets="compile" />
<Reference Include="..\Mirror\*.dll" />
<Reference Include="..\UniTask\*.dll" />
<ProjectReference Include="..\EpicOnlineTransport\EpicOnlineTransport.csproj" />
<ProjectReference Include="..\EpicRerouter\EpicRerouter.csproj" />
<ProjectReference Include="..\MirrorWeaver\MirrorWeaver.csproj" ReferenceOutputAssembly="false" />
</ItemGroup>
</Project>

View File

@ -115,8 +115,6 @@ public class QSBCore : ModBehaviour
public void Awake()
{
EpicRerouter.ModSide.Interop.Go();
// no, we cant localize this - languages are loaded after the splash screen
UIHelper.ReplaceUI(UITextType.PleaseUseController,
"<color=orange>Quantum Space Buddies</color> is best experienced with friends...");

View File

@ -1,5 +1,4 @@
using Epic.OnlineServices.Logging;
using EpicTransport;
using Mirror;
using OWML.Common;
using OWML.Utils;
@ -68,7 +67,6 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
private (TransportError error, string reason) _lastTransportError = (TransportError.Unexpected, "transport did not give an error. uh oh");
private static kcp2k.KcpTransport _kcpTransport;
private static EosTransport _eosTransport;
public override void Awake()
{
@ -77,24 +75,8 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
{
_kcpTransport = gameObject.AddComponent<kcp2k.KcpTransport>();
}
{
// https://dev.epicgames.com/portal/en-US/qsb/sdk/credentials/qsb
var eosApiKey = ScriptableObject.CreateInstance<EosApiKey>();
eosApiKey.epicProductName = "QSB";
eosApiKey.epicProductVersion = "1.0";
eosApiKey.epicProductId = "d4623220acb64419921c72047931b165";
eosApiKey.epicSandboxId = "d9bc4035269747668524931b0840ca29";
eosApiKey.epicDeploymentId = "1f164829371e4cdcb23efedce98d99ad";
eosApiKey.epicClientId = "xyza7891TmlpkaiDv6KAnJH0f07aAbTu";
eosApiKey.epicClientSecret = "ft17miukylHF877istFuhTgq+Kw1le3Pfigvf9Dtu20";
var eosSdkComponent = gameObject.AddComponent<EOSSDKComponent>();
eosSdkComponent.apiKeys = eosApiKey;
eosSdkComponent.epicLoggerLevel = LogLevel.VeryVerbose;
_eosTransport = gameObject.AddComponent<EosTransport>();
}
transport = QSBCore.UseKcpTransport ? _kcpTransport : _eosTransport;
transport = QSBCore.UseKcpTransport ? _kcpTransport : null;
gameObject.SetActive(true);
@ -165,7 +147,7 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
}
if (singleton != null)
{
singleton.transport = Transport.active = QSBCore.UseKcpTransport ? _kcpTransport : _eosTransport;
singleton.transport = Transport.active = QSBCore.UseKcpTransport ? _kcpTransport : null;
}
if (MenuManager.Instance != null)
{
@ -201,10 +183,6 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
DebugLog.ToConsole($"Error - Exception when getting player name : {ex}", MessageType.Error);
PlayerName = "Player";
}
{
EOSSDKComponent.DisplayName = PlayerName;
}
});
/// create a new network prefab from the network object prefab template.