using System; using System.Reflection; //using Microsoft.Win32; using IllusionPlugin; using GamecraftModdingAPI.App; using GamecraftModdingAPI.Commands; using Discord; namespace GamecraftRPC { public class Plugin : IPlugin // the Illusion Plugin Architecture (IPA) will ignore classes that don't implement IPlugin' { public string Name { get; } = Assembly.GetExecutingAssembly().GetName().Name; public string Version { get; } = #if DEBUG Assembly.GetExecutingAssembly().GetName().Version.ToString() + "alpha"; #else Assembly.GetExecutingAssembly().GetName().Version.ToString(); #endif private const long CLIENT_ID = #if DEBUG 692733325902872619; #else 696732441012076605; #endif private const LogLevel LOG_LEVEL = #if DEBUG LogLevel.Debug; #else LogLevel.Warn; #endif internal static Discord.Discord DiscordRPC; // called when Gamecraft shuts down public void OnApplicationQuit() { // Shutdown this mod if (DiscordRPC != null) { DiscordRPC.GetActivityManager().ClearActivity((result) => { GamecraftModdingAPI.Utility.Logging.LogDebug($"Cleared status: {result}"); DiscordRPC.Dispose(); }); } GamecraftModdingAPI.Utility.Logging.LogDebug($"{Name} has shutdown"); // Shutdown the Gamecraft modding API last GamecraftModdingAPI.Main.Shutdown(); } // called when Gamecraft starts up public void OnApplicationStart() { // Initialize the Gamecraft modding API first GamecraftModdingAPI.Main.Init(); // detect Wine (maybe?) bool isWineDetected = false; foreach (var key in Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software").GetSubKeyNames()) { if (key == "Wine") { isWineDetected = true; break; } } if (isWineDetected) { // info for getting this to work through Wine/Proton GamecraftModdingAPI.Utility.Logging.MetaLog("\n--------------------------------\n\nIt looks like you may be using Wine/Proton, cool!\nPlease install https://github.com/0e4ef622/wine-discord-ipc-bridge to get this to work.\n\n--------------------------------"); } // Initialize this mod DiscordRPC = new Discord.Discord(CLIENT_ID, (UInt64)Discord.CreateFlags.NoRequireDiscord); DiscordRPC.SetLogHook(LOG_LEVEL, (_, msg) => { GamecraftModdingAPI.Utility.Logging.MetaLog(msg); }); //DiscordRPC.GetActivityManager().RegisterSteam(1078000); ActivityManager am = DiscordRPC.GetActivityManager(); am.OnActivityJoinRequest += CallbackUtility.ActivityJoinRequest; am.OnActivityJoin += CallbackUtility.ActivityJoin; am.OnActivityInvite += CallbackUtility.ActivityInvite; LobbyManager lm = DiscordRPC.GetLobbyManager(); lm.OnMemberConnect += CallbackUtility.DiscordUserJoin; SetDiscordActivity(state: $"{UnityEngine.Application.version} ({Version})", details: $"Initializing...", start: (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds); Game.Edit += CallbackUtility.BuildEnter; Game.Enter += CallbackUtility.GameEnter; Game.Simulate += CallbackUtility.SimulationEnter; Client.EnterMenu += CallbackUtility.MenuEnter; GamecraftModdingAPI.Utility.GameEngineManager.AddGameEngine(new Engines.PlayerCountEngine()); CommandBuilder.Builder() .Name("JoinDiscord") .Description("Join the Exmods server for help or more information") .Action(() => { if (DiscordRPC != null) { DiscordRPC.GetOverlayManager().OpenGuildInvite("2CtWzZT", CallbackUtility.NobodyCares); } else { GamecraftModdingAPI.Utility.Logging.CommandLogError("Discord GameSDK functionality is unavailable. Please make sure Discord is open when launching Gamecraft."); } }) .Build(); CommandBuilder.Builder() .Name("InviteDiscordUser") .Description("Invite a Discord user (by id) to your game") .Action((userId) => { if (DiscordRPC != null) { Game game = Game.CurrentGame(); DiscordRPC.GetActivityManager().SendInvite(userId, Discord.ActivityActionType.Join, $"Let's play Gamecraft together! (requires the GamecraftRPC mod)", CallbackUtility.NobodyCares); } else { GamecraftModdingAPI.Utility.Logging.CommandLogError("Discord GameSDK functionality is unavailable. Please make sure Discord is open when launching Gamecraft."); } }) .Build(); CommandBuilder.Builder() .Name(Name + "Info") .Description("Build information for the GamecraftRPC mod.") .Action(() => { if (DiscordRPC != null) { Game game = Game.CurrentGame(); Client client = new Client(); GamecraftModdingAPI.Utility.Logging.CommandLog($"Gamecraft {client.Version}\nUnity {client.UnityVersion}\n{Name} {Version}\nSDK {DiscordRPC.ToString()}\nGame {game.Name}"); } else { GamecraftModdingAPI.Utility.Logging.CommandLogError("Discord GameSDK functionality is unavailable. Please make sure Discord is open when launching Gamecraft."); } }) .Build(); CommandBuilder.Builder() .Name("DiscordVoice") .Description("Connect to Discord Voice Lobby") .Action(() => { if (DiscordRPC != null) { GamecraftModdingAPI.Utility.Logging.CommandLogError("Discord GameSDK is unavailable. Please make sure Discord is open when launching Gamecraft."); return; } if (PresenceUtility.Lobby.HasValue) { //LobbyManager lm = DiscordRPC.GetLobbyManager(); if (PresenceUtility.IsVoiceConnected) { lm.DisconnectLobby(PresenceUtility.Lobby.Value.Id, (result) => { GamecraftModdingAPI.Utility.Logging.CommandLog($"Disconnected voice (Result: {result})"); }); PresenceUtility.IsVoiceConnected = false; } else { lm.ConnectVoice(PresenceUtility.Lobby.Value.Id, (result) => { GamecraftModdingAPI.Utility.Logging.CommandLog($"Connected voice (Result: {result})"); }); PresenceUtility.IsVoiceConnected = true; } } }) .Build(); #if !RELEASE bool alreadyWarned = false; Client.EnterMenu += (_, args) => { if (alreadyWarned) return; //GamecraftModdingAPI.Utility.Logging.LogDebug($"Displaying {Name} {Version} DEBUG warning"); /* RobocraftX.Services.ErrorBuilder.DisplayCustomError( $"THIS IS NOT ACTUALLY AN ERROR! {Name} v{Version} is a pre-release. If you encounter a bug or other issue, please report it to NGnius or Exmods on Discord.", "Discord", () => { UnityEngine.Application.OpenURL("https://discord.exmods.org"); }, "Ok!", () => { GamecraftModdingAPI.Utility.Logging.LogDebug($"Dismissed {Name} {Version} DEBUG warning"); } ); */ RobocraftX.Services.ErrorBuilder.DisplayWarning($"{Name} v{Version} is a pre-release. If you encounter a bug or other issue, please report it to NGnius or Exmods on Discord."); alreadyWarned = true; }; #endif GamecraftModdingAPI.Utility.Logging.LogDebug($"{Name} has started up"); } public void OnFixedUpdate() { } // called once per physics update public void OnLevelWasInitialized(int level) { } // called after a level is initialized public void OnLevelWasLoaded(int level) { } // called after a level is loaded public void OnUpdate() // called once per rendered frame (frame update) { if (DiscordRPC != null ) DiscordRPC.RunCallbacks(); } public static void SetDiscordActivity(string state = null, string details = null, long start = 0, long end = 0, string largeImg = "gamecraft-logo-g", string largeTxt = "Gamecraft", string smallImg = "exmods-logo-xm2", string smallTxt = "Exmods", string partyId = null, int partyCurrentSize = 0, int partyMaxSize = 0, string matchSecret = null, string joinSecret = null, string spectateSecret = null, bool instance = true, string debug = "") { if (DiscordRPC == null) return; ref Activity activity = ref PresenceUtility.Activity; activity.Instance = instance; if (state != null) activity.State = state; if (details != null) activity.Details = details; if (start != 0) activity.Timestamps.Start = start; if (end != 0) activity.Timestamps.End = end; if (!string.IsNullOrEmpty(largeImg)) { activity.Assets.LargeImage = largeImg; activity.Assets.LargeText = largeTxt; } if (!string.IsNullOrEmpty(smallImg)) { activity.Assets.SmallImage = smallImg; activity.Assets.SmallText = smallTxt; } if (!string.IsNullOrEmpty(partyId)) { activity.Party.Id = partyId; activity.Party.Size.CurrentSize = partyCurrentSize; activity.Party.Size.MaxSize = partyMaxSize; } if (!string.IsNullOrEmpty(matchSecret) || !string.IsNullOrEmpty(joinSecret) || !string.IsNullOrEmpty(spectateSecret)) { activity.Secrets.Match = matchSecret; activity.Secrets.Join = joinSecret; activity.Secrets.Spectate = spectateSecret; } DiscordRPC.GetActivityManager().UpdateActivity(activity, result => { GamecraftModdingAPI.Utility.Logging.MetaLog($"Update Activity Result: {result} {debug}"); }); } public static void SetDiscordActivity(Discord.Activity activity, string debug = "") { if (DiscordRPC == null) return; PresenceUtility.Activity = activity; DiscordRPC.GetActivityManager().UpdateActivity(PresenceUtility.Activity, result => { GamecraftModdingAPI.Utility.Logging.MetaLog($"Update Activity Result: {result} {debug}"); }); } public static void SetDiscordActivity(string debug = "") { if (DiscordRPC == null) return; DiscordRPC.GetActivityManager().UpdateActivity(PresenceUtility.Activity, result => { GamecraftModdingAPI.Utility.Logging.MetaLog($"Update Activity Result: {result} {debug}"); }); } } }