Discord integration for Gamecraft
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Plugin.cs 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.Reflection;
  3. using IllusionPlugin;
  4. using GamecraftModdingAPI.Events;
  5. using GamecraftModdingAPI.Commands;
  6. using Discord;
  7. namespace GamecraftRPC
  8. {
  9. public class Plugin : IPlugin // the Illusion Plugin Architecture (IPA) will ignore classes that don't implement IPlugin'
  10. {
  11. public string Name { get; } = Assembly.GetExecutingAssembly().GetName().Name;
  12. public string Version { get; } = Assembly.GetExecutingAssembly().GetName().Version.ToString();
  13. private static readonly long CLIENT_ID =
  14. #if DEBUG
  15. 692733325902872619;
  16. #else
  17. 696732441012076605;
  18. #endif
  19. private Discord.Discord discordRPC;
  20. // called when Gamecraft shuts down
  21. public void OnApplicationQuit()
  22. {
  23. // Shutdown this mod
  24. if (discordRPC != null)
  25. {
  26. discordRPC.GetActivityManager().ClearActivity((result) => { GamecraftModdingAPI.Utility.Logging.LogDebug($"Cleared status: {result}"); });
  27. discordRPC.Dispose();
  28. }
  29. GamecraftModdingAPI.Utility.Logging.LogDebug($"{Name} has shutdown");
  30. // Shutdown the Gamecraft modding API last
  31. GamecraftModdingAPI.Main.Shutdown();
  32. }
  33. // called when Gamecraft starts up
  34. public void OnApplicationStart()
  35. {
  36. // Initialize the Gamecraft modding API first
  37. GamecraftModdingAPI.Main.Init();
  38. // Initialize this mod
  39. discordRPC = new Discord.Discord(CLIENT_ID, (UInt64)Discord.CreateFlags.Default);
  40. discordRPC.SetLogHook(LogLevel.Debug, (_, msg) => { GamecraftModdingAPI.Utility.Logging.MetaLog(msg); });
  41. discordRPC.GetRelationshipManager().OnRefresh += () =>
  42. {
  43. discordRPC.GetRelationshipManager().Filter((ref Relationship r) => { return r.Presence.Status == Status.Online && r.Type == RelationshipType.Friend; });
  44. PresenceUtility.Users = new Relationship[discordRPC.GetRelationshipManager().Count()];
  45. for (uint i = 0; i < discordRPC.GetRelationshipManager().Count(); i++)
  46. {
  47. PresenceUtility.Users[i] = discordRPC.GetRelationshipManager().GetAt(i);
  48. }
  49. };
  50. SetDiscordActivity(discordRPC, state: "Loading...", details: "Initializing Gamecraft", start: (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
  51. EventManager.AddEventHandler(new Events.GamePresenceHandler(discordRPC));
  52. EventManager.AddEventHandler(new Events.MenuPresenceHandler(discordRPC));
  53. EventManager.AddEventHandler(new Events.EditPresenceHandler(discordRPC));
  54. EventManager.AddEventHandler(new Events.SimulatePresenceHandler(discordRPC));
  55. SimpleCustomCommandEngine<string> rpcCommand = new SimpleCustomCommandEngine<string>(
  56. (s) => { SetDiscordActivity(discordRPC, state: s); }, // TODO: command action
  57. "SetRichPresence", // command name (used to invoke it in the console)
  58. "Set Discord status (experimental)" // command description (displayed when help command is executed)
  59. ); // this command can also be executed using the Command Computer
  60. SimpleCustomCommandEngine inviteNGniusCommand = new SimpleCustomCommandEngine(() =>
  61. discordRPC.GetActivityManager().SendInvite(106537989684887552, ActivityActionType.Join, "Join the Borg", (res) => { GamecraftModdingAPI.Utility.Logging.LogDebug($"Send invite {res}"); }),
  62. "InviteNGnius",
  63. "Send a Discord lobby invite to NGnius");
  64. SimpleCustomCommandEngine<long> inviteDiscordCommand = new SimpleCustomCommandEngine<long>((id) =>
  65. discordRPC.GetActivityManager().SendInvite(id, ActivityActionType.Join, "Join the Borg", (res) => { GamecraftModdingAPI.Utility.Logging.LogDebug($"Send invite {res}"); }),
  66. "InviteDiscord",
  67. "Send a game invite to a Discord user");
  68. SimpleCustomCommandEngine listDiscordUsersCommand = new SimpleCustomCommandEngine(
  69. () =>
  70. {
  71. string result = "Online Friends\n";
  72. for (int i = 0; i < PresenceUtility.Users.Length; i++)
  73. {
  74. result += $"{PresenceUtility.Users[i].User.Username} ({PresenceUtility.Users[i].User.Id})\n";
  75. }
  76. GamecraftModdingAPI.Utility.Logging.CommandLog(result);
  77. },
  78. "ListDiscordUsers",
  79. "List online Discord friends");
  80. // register the command so the modding API knows about it
  81. CommandManager.AddCommand(rpcCommand);
  82. CommandManager.AddCommand(inviteNGniusCommand);
  83. CommandManager.AddCommand(inviteDiscordCommand);
  84. CommandManager.AddCommand(listDiscordUsersCommand);
  85. GamecraftModdingAPI.Utility.GameEngineManager.AddGameEngine(new Engines.PlayerCountEngine(discordRPC));
  86. GamecraftModdingAPI.Utility.Logging.LogDebug($"{Name} has started up");
  87. }
  88. // unused methods
  89. public void OnFixedUpdate() { } // called once per physics update
  90. public void OnLevelWasInitialized(int level) { } // called after a level is initialized
  91. public void OnLevelWasLoaded(int level) { } // called after a level is loaded
  92. public void OnUpdate() // called once per rendered frame (frame update)
  93. {
  94. if (discordRPC != null ) discordRPC.RunCallbacks();
  95. }
  96. public static void SetDiscordActivity(Discord.Discord discordRPC, string state = null, string details = null, int start = 0, int 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 = "")
  97. {
  98. if (discordRPC == null) return;
  99. ref Activity activity = ref PresenceUtility.Activity;
  100. activity.Instance = instance;
  101. if (state != null) activity.State = state;
  102. if (details != null) activity.Details = details;
  103. if (start != 0) activity.Timestamps.Start = start;
  104. if (end != 0) activity.Timestamps.End = end;
  105. if (!string.IsNullOrEmpty(largeImg))
  106. {
  107. activity.Assets.LargeImage = largeImg;
  108. activity.Assets.LargeText = largeTxt;
  109. }
  110. if (!string.IsNullOrEmpty(smallImg))
  111. {
  112. activity.Assets.SmallImage = smallImg;
  113. activity.Assets.SmallText = smallTxt;
  114. }
  115. if (!string.IsNullOrEmpty(partyId))
  116. {
  117. activity.Party.Id = partyId;
  118. activity.Party.Size.CurrentSize = partyCurrentSize;
  119. activity.Party.Size.MaxSize = partyMaxSize;
  120. }
  121. if (!string.IsNullOrEmpty(matchSecret) || !string.IsNullOrEmpty(joinSecret) || !string.IsNullOrEmpty(spectateSecret))
  122. {
  123. activity.Secrets.Match = matchSecret;
  124. activity.Secrets.Join = joinSecret;
  125. activity.Secrets.Spectate = spectateSecret;
  126. }
  127. discordRPC.GetActivityManager().UpdateActivity(activity, result =>
  128. {
  129. GamecraftModdingAPI.Utility.Logging.MetaLog($"Update Activity Result: {result} {debug}");
  130. });
  131. }
  132. public static void SetDiscordActivity(Discord.Discord discordRPC, Discord.Activity activity, string debug = "")
  133. {
  134. PresenceUtility.Activity = activity;
  135. discordRPC.GetActivityManager().UpdateActivity(PresenceUtility.Activity, result =>
  136. {
  137. GamecraftModdingAPI.Utility.Logging.MetaLog($"Update Activity Result: {result} {debug}");
  138. });
  139. }
  140. public static void SetDiscordActivity(Discord.Discord discordRPC, string debug = "")
  141. {
  142. discordRPC.GetActivityManager().UpdateActivity(PresenceUtility.Activity, result =>
  143. {
  144. GamecraftModdingAPI.Utility.Logging.MetaLog($"Update Activity Result: {result} {debug}");
  145. });
  146. }
  147. }
  148. }