diff --git a/GCDC/DiscordEngineInjectionPatch.cs b/GCDC/DiscordEngineInjectionPatch.cs index 8c7eec9..763eb2b 100644 --- a/GCDC/DiscordEngineInjectionPatch.cs +++ b/GCDC/DiscordEngineInjectionPatch.cs @@ -7,7 +7,6 @@ using RobocraftX.GUI.CommandLine; using RobocraftX.Multiplayer; using RobocraftX.Services.MultiplayerNetworking; using RobocraftX.StateSync; -using Svelto.Context; using Svelto.ECS; using Unity.Entities; using UnityEngine; @@ -17,11 +16,11 @@ namespace GCDC [HarmonyPatch] public class DiscordEngineInjectionPatch { - static void Postfix(EnginesRoot enginesRoot, ref StateSyncRegistrationHelper stateSyncReg, bool isAuthoritative) + static void Postfix(EnginesRoot enginesRoot, in StateSyncRegistrationHelper stateSyncReg, bool isAuthoritative) { if (isAuthoritative) { - stateSyncReg.AddEngine(new TextBlockUpdateEngine()); + stateSyncReg.AddDeterministicEngine(new TextBlockUpdateEngine()); Debug.Log($"Added Discord text block update engine"); } else @@ -33,7 +32,7 @@ namespace GCDC return _ComposeMethodInfo(ConsoleBlockCompositionRoot.Compose); } - private delegate void ComposeAction(EnginesRoot er, ref StateSyncRegistrationHelper ssrh, + private delegate void ComposeAction(EnginesRoot er, in StateSyncRegistrationHelper ssrh, NetworkReceivers networkReceivers, NetworkSender networkSende, bool isAuthoritative); private static MethodInfo _ComposeMethodInfo(ComposeAction a) { diff --git a/GCDC/GCDC.csproj b/GCDC/GCDC.csproj index a08301f..517b897 100644 --- a/GCDC/GCDC.csproj +++ b/GCDC/GCDC.csproj @@ -32,26 +32,35 @@ 4 + + ref\BlockEntityFactory.dll + ref\CommandLine.dll + + ref\DataLoader.dll + ref\FullGame.dll ref\Gamecraft.Blocks.ConsoleBlock.dll + + ..\..\GamecraftModdingAPI\GamecraftModdingAPI\bin\Debug\net472\GamecraftModdingAPI.dll + IllusionPlugin.dll ref\MultiplayerNetworking.dll - + ref\Newtonsoft.Json.dll - - ref\Robocraft.MainGame.AutoEnterSimulation.dll + + ref\Newtonsoft.Json.dll ref\RobocraftX.AccountPreferences.dll @@ -74,15 +83,9 @@ ref\RobocraftX.Crosshair.dll - - ref\RobocraftX.EntityStreamUtility.dll - ref\RobocraftX.FrontEnd.dll - - ref\RobocraftX.GameSignalHandling.dll - ref\RobocraftX.GUI.dll @@ -95,18 +98,12 @@ ref\RobocraftX.GUI.ScaleGhost.dll - - ref\RobocraftX.GUI.SignalLabel.dll - ref\RobocraftX.GUIs.WorkshopPrefabs.dll ref\RobocraftX.Input.dll - - ref\RobocraftX.Inventory.dll - ref\RobocraftX.MachineEditor.dll @@ -140,9 +137,6 @@ ref\RobocraftX.Player.dll - - ref\RobocraftX.Priority.dll - ref\RobocraftX.Rendering.dll @@ -176,9 +170,6 @@ ref\RobocratX.SimulationCompositionRoot.dll - - ref\Svelto.Common.dll - ref\Svelto.ECS.dll @@ -192,6 +183,9 @@ ref\Unity.Entities.dll + + ref\Unity.Mathematics.dll + ref\Unity.Physics.dll diff --git a/GCDC/TextBlockUpdateEngine.cs b/GCDC/TextBlockUpdateEngine.cs index 2ca5644..1f70f48 100644 --- a/GCDC/TextBlockUpdateEngine.cs +++ b/GCDC/TextBlockUpdateEngine.cs @@ -1,15 +1,19 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; +using System.Net; using System.Net.Http; +using System.Net.Mime; using System.Reflection; +using System.Threading; using System.Threading.Tasks; using Discord; using Discord.WebSocket; +using GamecraftModdingAPI.Utility; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using RobocraftX.Blocks.GUI; using RobocraftX.Common; using RobocraftX.Common.Input; using RobocraftX.Common.Utilities; @@ -23,84 +27,114 @@ using uREPL; namespace GCDC { - public class TextBlockUpdateEngine : IQueryingEntitiesEngine, IDeterministicSim, IInitializeOnBuildStart + public class TextBlockUpdateEngine : IDeterministicSim, IInitializeOnBuildStart, IApiEngine { - private DiscordSocketClient _client; + private string _token; + private bool _running; + private Thread _rect; public void Ready() { + if (!RuntimeCommands.HasRegistered("dc")) + RuntimeCommands.Register("dc", SendMessage); + if (!RuntimeCommands.HasRegistered("dcsetup")) + RuntimeCommands.Register("dcsetup", Setup); + if (File.Exists("gcdc.json")) + { + var jo = JObject.Load(new JsonTextReader(File.OpenText("gcdc.json"))); + _token = jo["token"]?.Value(); + } + + if (_token != null) + Start(); + } + + public void Setup(string token) + { + if (string.IsNullOrWhiteSpace(token)) + { + Process.Start( + "https://discordapp.com/oauth2/authorize?client_id=680138144812892371&redirect_uri=https%3A%2F%2Fgcdc.herokuapp.com%2Fapi%2Fusers%2Fregister&response_type=code&scope=identify&state=551075431336378398"); + Log.Output( + "Please authorize the GCDC app on the page that should open. This connection is only used to avoid account spam and to display your Discord name."); + } + else + { + _token = token; + try + { + if (JObject.Parse(WebUtils.Request("users/get?token=" + token))["response"].Value() == "OK") + { + var jo = new JObject(); + jo["token"] = token; + File.WriteAllText("gcdc.json", jo.ToString()); + Start(); + Log.Output( + "Successfully logged in. You can now use a text block named Discord and the dc command."); + } + else + Log.Error("Failed to verify login. Please try again."); + } + catch (Exception e) + { + Log.Error("Failed to verify login. Please try again. (Error logged.)"); + Console.WriteLine(e); + } + } + } + + public void SendMessage(string message) + { + if (!_running) + { + Log.Error("Run dcsetup first."); + return; + } + try { - /*Console.WriteLine("Current directory: " + Environment.CurrentDirectory); - Console.WriteLine(Assembly.LoadFrom("Discord.Net.WebSocket.dll")?.DefinedTypes?.Select(t => t.FullName) - .Aggregate((a, b) => a + "\n" + b));*/ //Spent a couple hours trying to figure out why it doesn't even load anymore - somehow I got a completely different System.Collections.Immutable.dll - if (!RuntimeCommands.HasRegistered("dc")) - RuntimeCommands.Register("dc", AddMessage); - Start(); + var parameters = "token=" + _token + "&message=" + message; + var resp = JObject.Parse(WebUtils.Request("messages/send?" + parameters, "")); + if (resp["response"] + .Value() == "OK") + { + AddMessage("<" + resp["username"] + "> " + message); + Log.Output("Message sent"); + } + else + Log.Error("Failed to send message"); } - catch (TypeLoadException e) + catch (Exception e) { - Console.WriteLine("Type load exception for type: "+e.TypeName); + Log.Error("Failed to send message (error logged)."); Console.WriteLine(e); } } - private void Start() + public void Start() { - _client=new DiscordSocketClient(new DiscordSocketConfig() + if (_running) return; + _running = true; + _rect = new Thread(() => { - LogLevel = LogSeverity.Debug, - DefaultRetryMode = RetryMode.RetryRatelimit - }); - _client.Log += msg=> - { - Log.Output(msg.Message); - //Window.selected.OutputLog(new Log.Data(msg.Message, "Discord", Log.Level.Verbose)); - return Task.CompletedTask; - }; - Setup(); - } - private async void Setup() - { - try - { - const string path = "discordToken.json"; - const string notoken = - "Please add your bot token to the discordToken.json file in game files and run this again."; - if (!File.Exists(path)) + Console.WriteLine("Starting DC receiver thread..."); + while (_running) { - var obj = new JObject {["token"] = "Put your token here"}; - File.WriteAllText(path, obj.ToString()); - Log.Error(notoken); - return; - } - - string token; - try - { - token = (string) JObject.Parse(File.ReadAllText(path))["token"]; - if (token.Contains(" ")) + try { - Log.Error(notoken); - return; + string resp = WebUtils.Request("messages/get?token=" + _token); + var jo = JObject.Parse(resp); + AddMessage("<" + jo["username"] + "> " + jo["message"]); + } + catch (WebException) + { + // ignored } - } - catch (JsonReaderException exception) - { - Log.Error("Failed to read token! " + exception); - return; - } - - await _client.LoginAsync(TokenType.Bot, token); - await _client.StartAsync(); - } - catch (Exception e) - { - Log.Error(e.ToString()); - } + }) {Name = "DC Receiver Thread"}; + _rect.Start(); } - public IEntitiesDB entitiesDB { get; set; } + public EntitiesDB entitiesDB { get; set; } public string name { get; } = "GCDC-TextUpdate"; private volatile Queue messages = new Queue(); private volatile bool updatedTextBlock; @@ -132,5 +166,13 @@ namespace GCDC updatedTextBlock = false; //Update text block return new JobHandle(); } + + public void Dispose() + { + _running = false; + _rect.Interrupt(); + } + + public string Name { get; } = "GCDCEngine"; } } \ No newline at end of file diff --git a/GCDC/WebUtils.cs b/GCDC/WebUtils.cs new file mode 100644 index 0000000..15fc520 --- /dev/null +++ b/GCDC/WebUtils.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; +using System.Net; +using System.Text; + +namespace GCDC +{ + public static class WebUtils + { + public static string Request(string url, string post = null) + { + WebRequest request = WebRequest.CreateHttp("https://gcdc.herokuapp.com/api/" + url); + request.Method = post != null ? "POST" : "GET"; + + Stream dataStream; + if (post != null) + { + byte[] byteArray = Encoding.UTF8.GetBytes(post); + + request.ContentType = "application/x-www-form-urlencoded"; + request.ContentLength = byteArray.Length; + + dataStream = request.GetRequestStream(); + dataStream.Write(byteArray, 0, byteArray.Length); + dataStream.Close(); + } + + WebResponse response = request.GetResponse(); + Console.WriteLine(((HttpWebResponse) response).StatusDescription); + + string responseFromServer; + using (dataStream = response.GetResponseStream()) + { + StreamReader reader = new StreamReader(dataStream); + responseFromServer = reader.ReadToEnd(); + } + + response.Close(); + return responseFromServer; + } + } +} \ No newline at end of file