This repository has moved! Please check out the latest version at the new location https://git.exmods.org/NGnius/GameSDKcraft
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

239 lines
8.9KB

  1. using System;
  2. using System.Reflection;
  3. //using Microsoft.Win32;
  4. using IllusionPlugin;
  5. using GamecraftModdingAPI.App;
  6. using GamecraftModdingAPI.Commands;
  7. using Discord;
  8. namespace GamecraftRPC
  9. {
  10. public class Plugin : IPlugin // the Illusion Plugin Architecture (IPA) will ignore classes that don't implement IPlugin'
  11. {
  12. public string Name { get; } = Assembly.GetExecutingAssembly().GetName().Name;
  13. public string Version { get; } =
  14. #if DEBUG
  15. Assembly.GetExecutingAssembly().GetName().Version.ToString() + "alpha";
  16. #else
  17. Assembly.GetExecutingAssembly().GetName().Version.ToString();
  18. #endif
  19. private const long CLIENT_ID =
  20. #if DEBUG
  21. 692733325902872619;
  22. #else
  23. 696732441012076605;
  24. #endif
  25. private const LogLevel LOG_LEVEL =
  26. #if DEBUG
  27. LogLevel.Debug;
  28. #else
  29. LogLevel.Warn;
  30. #endif
  31. internal static Discord.Discord DiscordRPC;
  32. // called when Gamecraft shuts down
  33. public void OnApplicationQuit()
  34. {
  35. // Shutdown this mod
  36. if (DiscordRPC != null)
  37. {
  38. DiscordRPC.GetActivityManager().ClearActivity((result) => { GamecraftModdingAPI.Utility.Logging.LogDebug($"Cleared status: {result}"); DiscordRPC.Dispose(); });
  39. }
  40. GamecraftModdingAPI.Utility.Logging.LogDebug($"{Name} has shutdown");
  41. // Shutdown the Gamecraft modding API last
  42. GamecraftModdingAPI.Main.Shutdown();
  43. }
  44. // called when Gamecraft starts up
  45. public void OnApplicationStart()
  46. {
  47. // Initialize the Gamecraft modding API first
  48. GamecraftModdingAPI.Main.Init();
  49. // detect Wine (maybe?)
  50. bool isWineDetected = false;
  51. foreach (var key in Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software").GetSubKeyNames())
  52. {
  53. if (key == "Wine")
  54. {
  55. isWineDetected = true;
  56. break;
  57. }
  58. }
  59. if (isWineDetected)
  60. {
  61. // info for getting this to work through Wine/Proton
  62. 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--------------------------------");
  63. }
  64. // Initialize this mod
  65. DiscordRPC = new Discord.Discord(CLIENT_ID, (UInt64)Discord.CreateFlags.NoRequireDiscord);
  66. DiscordRPC.SetLogHook(LOG_LEVEL, (_, msg) => { GamecraftModdingAPI.Utility.Logging.MetaLog(msg); });
  67. //DiscordRPC.GetActivityManager().RegisterSteam(1078000);
  68. ActivityManager am = DiscordRPC.GetActivityManager();
  69. am.OnActivityJoinRequest += CallbackUtility.ActivityJoinRequest;
  70. am.OnActivityJoin += CallbackUtility.ActivityJoin;
  71. am.OnActivityInvite += CallbackUtility.ActivityInvite;
  72. LobbyManager lm = DiscordRPC.GetLobbyManager();
  73. lm.OnMemberConnect += CallbackUtility.DiscordUserJoin;
  74. SetDiscordActivity(state: $"{UnityEngine.Application.version} ({Version})", details: $"Initializing...", start: (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
  75. Game.Edit += CallbackUtility.BuildEnter;
  76. Game.Enter += CallbackUtility.GameEnter;
  77. Game.Simulate += CallbackUtility.SimulationEnter;
  78. Client.EnterMenu += CallbackUtility.MenuEnter;
  79. GamecraftModdingAPI.Utility.GameEngineManager.AddGameEngine(new Engines.PlayerCountEngine());
  80. CommandBuilder.Builder()
  81. .Name("JoinDiscord")
  82. .Description("Join the Exmods server for help or more information")
  83. .Action(() =>
  84. {
  85. if (DiscordRPC != null)
  86. {
  87. DiscordRPC.GetOverlayManager().OpenGuildInvite("2CtWzZT", CallbackUtility.NobodyCares);
  88. }
  89. else
  90. {
  91. GamecraftModdingAPI.Utility.Logging.CommandLogError("Discord GameSDK functionality is unavailable. Please make sure Discord is open when launching Gamecraft.");
  92. }
  93. })
  94. .Build();
  95. CommandBuilder.Builder()
  96. .Name("InviteDiscordUser")
  97. .Description("Invite a Discord user (by id) to your game")
  98. .Action<long>((userId) =>
  99. {
  100. if (DiscordRPC != null)
  101. {
  102. Game game = Game.CurrentGame();
  103. DiscordRPC.GetActivityManager().SendInvite(userId, Discord.ActivityActionType.Join, $"Let's play Gamecraft together! (requires the GamecraftRPC mod)", CallbackUtility.NobodyCares);
  104. }
  105. else
  106. {
  107. GamecraftModdingAPI.Utility.Logging.CommandLogError("Discord GameSDK functionality is unavailable. Please make sure Discord is open when launching Gamecraft.");
  108. }
  109. })
  110. .Build();
  111. CommandBuilder.Builder()
  112. .Name(Name + "Info")
  113. .Description("Build information for the GamecraftRPC mod.")
  114. .Action(() =>
  115. {
  116. if (DiscordRPC != null)
  117. {
  118. Game game = Game.CurrentGame();
  119. Client client = new Client();
  120. GamecraftModdingAPI.Utility.Logging.CommandLog($"Gamecraft {client.Version}\nUnity {client.UnityVersion}\n{Name} {Version}\nSDK {DiscordRPC.ToString()}\nGame {game.Name}");
  121. }
  122. else
  123. {
  124. GamecraftModdingAPI.Utility.Logging.CommandLogError("Discord GameSDK functionality is unavailable. Please make sure Discord is open when launching Gamecraft.");
  125. }
  126. })
  127. .Build();
  128. #if !RELEASE
  129. bool alreadyWarned = false;
  130. Client.EnterMenu += (_, args) =>
  131. {
  132. if (alreadyWarned) return;
  133. //GamecraftModdingAPI.Utility.Logging.LogDebug($"Displaying {Name} {Version} DEBUG warning");
  134. /*
  135. RobocraftX.Services.ErrorBuilder.DisplayCustomError(
  136. $"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.",
  137. "Discord", () => { UnityEngine.Application.OpenURL("https://discord.exmods.org"); },
  138. "Ok!", () => { GamecraftModdingAPI.Utility.Logging.LogDebug($"Dismissed {Name} {Version} DEBUG warning"); }
  139. );
  140. */
  141. 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.");
  142. alreadyWarned = true;
  143. };
  144. #endif
  145. GamecraftModdingAPI.Utility.Logging.LogDebug($"{Name} has started up");
  146. }
  147. public void OnFixedUpdate() { } // called once per physics update
  148. public void OnLevelWasInitialized(int level) { } // called after a level is initialized
  149. public void OnLevelWasLoaded(int level) { } // called after a level is loaded
  150. public void OnUpdate() // called once per rendered frame (frame update)
  151. {
  152. if (DiscordRPC != null ) DiscordRPC.RunCallbacks();
  153. }
  154. 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 = "")
  155. {
  156. if (DiscordRPC == null) return;
  157. ref Activity activity = ref PresenceUtility.Activity;
  158. activity.Instance = instance;
  159. if (state != null) activity.State = state;
  160. if (details != null) activity.Details = details;
  161. if (start != 0) activity.Timestamps.Start = start;
  162. if (end != 0) activity.Timestamps.End = end;
  163. if (!string.IsNullOrEmpty(largeImg))
  164. {
  165. activity.Assets.LargeImage = largeImg;
  166. activity.Assets.LargeText = largeTxt;
  167. }
  168. if (!string.IsNullOrEmpty(smallImg))
  169. {
  170. activity.Assets.SmallImage = smallImg;
  171. activity.Assets.SmallText = smallTxt;
  172. }
  173. if (!string.IsNullOrEmpty(partyId))
  174. {
  175. activity.Party.Id = partyId;
  176. activity.Party.Size.CurrentSize = partyCurrentSize;
  177. activity.Party.Size.MaxSize = partyMaxSize;
  178. }
  179. if (!string.IsNullOrEmpty(matchSecret) || !string.IsNullOrEmpty(joinSecret) || !string.IsNullOrEmpty(spectateSecret))
  180. {
  181. activity.Secrets.Match = matchSecret;
  182. activity.Secrets.Join = joinSecret;
  183. activity.Secrets.Spectate = spectateSecret;
  184. }
  185. DiscordRPC.GetActivityManager().UpdateActivity(activity, result =>
  186. {
  187. GamecraftModdingAPI.Utility.Logging.MetaLog($"Update Activity Result: {result} {debug}");
  188. });
  189. }
  190. public static void SetDiscordActivity(Discord.Activity activity, string debug = "")
  191. {
  192. if (DiscordRPC == null) return;
  193. PresenceUtility.Activity = activity;
  194. DiscordRPC.GetActivityManager().UpdateActivity(PresenceUtility.Activity, result =>
  195. {
  196. GamecraftModdingAPI.Utility.Logging.MetaLog($"Update Activity Result: {result} {debug}");
  197. });
  198. }
  199. public static void SetDiscordActivity(string debug = "")
  200. {
  201. if (DiscordRPC == null) return;
  202. DiscordRPC.GetActivityManager().UpdateActivity(PresenceUtility.Activity, result =>
  203. {
  204. GamecraftModdingAPI.Utility.Logging.MetaLog($"Update Activity Result: {result} {debug}");
  205. });
  206. }
  207. }
  208. }