added http and settings
This commit is contained in:
parent
3c4bfbe772
commit
0f404019b6
6 changed files with 327 additions and 2 deletions
105
MosswartMassacre/HttpCommandServer.cs
Normal file
105
MosswartMassacre/HttpCommandServer.cs
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Decal.Adapter;
|
||||||
|
|
||||||
|
namespace MosswartMassacre
|
||||||
|
{
|
||||||
|
public static class HttpCommandServer
|
||||||
|
{
|
||||||
|
private static HttpListener listener;
|
||||||
|
private static CancellationTokenSource cts;
|
||||||
|
private static bool isRunning = false;
|
||||||
|
|
||||||
|
public static bool IsRunning => isRunning;
|
||||||
|
|
||||||
|
public static void Start()
|
||||||
|
{
|
||||||
|
if (isRunning) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
listener = new HttpListener();
|
||||||
|
listener.Prefixes.Add("http://localhost:8085/");
|
||||||
|
listener.Start();
|
||||||
|
cts = new CancellationTokenSource();
|
||||||
|
Task.Run(() => ListenLoop(cts.Token));
|
||||||
|
|
||||||
|
isRunning = true;
|
||||||
|
PluginCore.WriteToChat("[HTTP] Server started on port 8085.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
PluginCore.WriteToChat("[HTTP] Error starting server: " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Stop()
|
||||||
|
{
|
||||||
|
if (!isRunning) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cts.Cancel();
|
||||||
|
listener.Stop();
|
||||||
|
listener.Close();
|
||||||
|
listener = null;
|
||||||
|
isRunning = false;
|
||||||
|
PluginCore.WriteToChat("[HTTP] Server stopped.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
PluginCore.WriteToChat("[HTTP] Error stopping server: " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task ListenLoop(CancellationToken token)
|
||||||
|
{
|
||||||
|
while (!token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
HttpListenerContext context = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
context = await listener.GetContextAsync();
|
||||||
|
}
|
||||||
|
catch (HttpListenerException)
|
||||||
|
{
|
||||||
|
break; // Listener was stopped
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context == null) continue;
|
||||||
|
|
||||||
|
string requestBody = new System.IO.StreamReader(context.Request.InputStream).ReadToEnd();
|
||||||
|
|
||||||
|
PluginCore.WriteToChat("[HTTP] Received request: " + requestBody);
|
||||||
|
|
||||||
|
// Parse simple format: target=Name&command=/say hello
|
||||||
|
string target = "";
|
||||||
|
string command = "";
|
||||||
|
foreach (var pair in requestBody.Split('&'))
|
||||||
|
{
|
||||||
|
var parts = pair.Split('=');
|
||||||
|
if (parts.Length == 2)
|
||||||
|
{
|
||||||
|
if (parts[0] == "target") target = WebUtility.UrlDecode(parts[1]);
|
||||||
|
else if (parts[0] == "command") command = WebUtility.UrlDecode(parts[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(target) && !string.IsNullOrWhiteSpace(command))
|
||||||
|
{
|
||||||
|
string tellCmd = $"/a {target} {command}";
|
||||||
|
CoreManager.Current.Actions.InvokeChatParser(tellCmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] buffer = Encoding.UTF8.GetBytes("Command received.");
|
||||||
|
context.Response.ContentLength64 = buffer.Length;
|
||||||
|
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||||
|
context.Response.OutputStream.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -59,8 +59,13 @@
|
||||||
<Reference Include="VirindiViewService">
|
<Reference Include="VirindiViewService">
|
||||||
<HintPath>lib\VirindiViewService.dll</HintPath>
|
<HintPath>lib\VirindiViewService.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="YamlDotNet, Version=16.0.0.0, Culture=neutral, PublicKeyToken=ec19458f3c15af5e, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\YamlDotNet.16.3.0\lib\net47\YamlDotNet.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="PluginSettings.cs" />
|
||||||
|
<Compile Include="HttpCommandServer.cs" />
|
||||||
<Compile Include="DelayedCommandManager.cs" />
|
<Compile Include="DelayedCommandManager.cs" />
|
||||||
<Compile Include="MainView.cs" />
|
<Compile Include="MainView.cs" />
|
||||||
<Compile Include="PluginCore.cs" />
|
<Compile Include="PluginCore.cs" />
|
||||||
|
|
@ -85,5 +90,9 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="ViewXML\mainView.xml" />
|
<EmbeddedResource Include="ViewXML\mainView.xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="app.config" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -19,7 +19,10 @@ namespace MosswartMassacre
|
||||||
internal static double killsPerHour = 0;
|
internal static double killsPerHour = 0;
|
||||||
internal static DateTime statsStartTime = DateTime.Now;
|
internal static DateTime statsStartTime = DateTime.Now;
|
||||||
internal static Timer updateTimer;
|
internal static Timer updateTimer;
|
||||||
public static bool RareMetaEnabled { get; private set; } = true;
|
public static bool RareMetaEnabled { get; set; } = true;
|
||||||
|
public static bool RemoteCommandsEnabled { get; set; } = false;
|
||||||
|
public static bool HttpServerEnabled { get; set; } = false;
|
||||||
|
public static string CharTag { get; set; } = "";
|
||||||
private static Queue<string> rareMessageQueue = new Queue<string>();
|
private static Queue<string> rareMessageQueue = new Queue<string>();
|
||||||
private static DateTime _lastSent = DateTime.MinValue;
|
private static DateTime _lastSent = DateTime.MinValue;
|
||||||
private static readonly Queue<string> _chatQueue = new Queue<string>();
|
private static readonly Queue<string> _chatQueue = new Queue<string>();
|
||||||
|
|
@ -29,11 +32,13 @@ namespace MosswartMassacre
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
MyHost = Host;
|
MyHost = Host;
|
||||||
|
|
||||||
WriteToChat("Mosswart Massacre has started!");
|
WriteToChat("Mosswart Massacre has started!");
|
||||||
|
|
||||||
// Subscribe to chat message event
|
// Subscribe to chat message event
|
||||||
CoreManager.Current.ChatBoxMessage += new EventHandler<ChatTextInterceptEventArgs>(OnChatText);
|
CoreManager.Current.ChatBoxMessage += new EventHandler<ChatTextInterceptEventArgs>(OnChatText);
|
||||||
CoreManager.Current.CommandLineText += OnChatCommand;
|
CoreManager.Current.CommandLineText += OnChatCommand;
|
||||||
|
CoreManager.Current.CharacterFilter.LoginComplete += CharacterFilter_LoginComplete;
|
||||||
|
|
||||||
// Initialize the timer
|
// Initialize the timer
|
||||||
updateTimer = new Timer(1000); // Update every second
|
updateTimer = new Timer(1000); // Update every second
|
||||||
|
|
@ -53,6 +58,7 @@ namespace MosswartMassacre
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
PluginSettings.Save();
|
||||||
WriteToChat("Mosswart Massacre is shutting down...");
|
WriteToChat("Mosswart Massacre is shutting down...");
|
||||||
|
|
||||||
// Unsubscribe from chat message event
|
// Unsubscribe from chat message event
|
||||||
|
|
@ -76,6 +82,20 @@ namespace MosswartMassacre
|
||||||
WriteToChat("Error during shutdown: " + ex.Message);
|
WriteToChat("Error during shutdown: " + ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private void CharacterFilter_LoginComplete(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
CoreManager.Current.CharacterFilter.LoginComplete -= CharacterFilter_LoginComplete;
|
||||||
|
|
||||||
|
PluginSettings.Initialize(); // Safe to call now
|
||||||
|
|
||||||
|
// Apply the values
|
||||||
|
RareMetaEnabled = PluginSettings.Instance.RareMetaEnabled;
|
||||||
|
RemoteCommandsEnabled = PluginSettings.Instance.RemoteCommandsEnabled;
|
||||||
|
HttpServerEnabled = PluginSettings.Instance.HttpServerEnabled;
|
||||||
|
MainView.SetRareMetaToggleState(RareMetaEnabled);
|
||||||
|
|
||||||
|
WriteToChat("Settings loaded.");
|
||||||
|
}
|
||||||
|
|
||||||
private void OnChatText(object sender, ChatTextInterceptEventArgs e)
|
private void OnChatText(object sender, ChatTextInterceptEventArgs e)
|
||||||
{
|
{
|
||||||
|
|
@ -133,6 +153,39 @@ namespace MosswartMassacre
|
||||||
WriteToChat($"[Mosswart Massacre] Reporting to allegiance: {reportMessage}");
|
WriteToChat($"[Mosswart Massacre] Reporting to allegiance: {reportMessage}");
|
||||||
MyHost.Actions.InvokeChatParser($"/a {reportMessage}");
|
MyHost.Actions.InvokeChatParser($"/a {reportMessage}");
|
||||||
}
|
}
|
||||||
|
if (RemoteCommandsEnabled && e.Color == 18)
|
||||||
|
{
|
||||||
|
string characterName = Regex.Escape(CoreManager.Current.CharacterFilter.Name);
|
||||||
|
string pattern = $@"^\[Allegiance\].*Dunking Rares.*say[s]?, \""!do {characterName} (?<command>.+)\""$";
|
||||||
|
string tag = Regex.Escape(PluginCore.CharTag);
|
||||||
|
string patterntag = $@"^\[Allegiance\].*Dunking Rares.*say[s]?, \""!dot {tag} (?<command>.+)\""$";
|
||||||
|
|
||||||
|
|
||||||
|
var match = Regex.Match(e.Text, pattern);
|
||||||
|
var matchtag = Regex.Match(e.Text, patterntag);
|
||||||
|
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
string command = match.Groups["command"].Value;
|
||||||
|
DispatchChatToBoxWithPluginIntercept(command);
|
||||||
|
DelayedCommandManager.AddDelayedCommand($"/a [Remote] Executing: {command}", 2000);
|
||||||
|
}
|
||||||
|
else if (matchtag.Success)
|
||||||
|
{
|
||||||
|
string command = matchtag.Groups["command"].Value;
|
||||||
|
DispatchChatToBoxWithPluginIntercept(command);
|
||||||
|
DelayedCommandManager.AddDelayedCommand($"/a [Remote] Executing: {command}", 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -268,7 +321,8 @@ namespace MosswartMassacre
|
||||||
}
|
}
|
||||||
public static void ToggleRareMeta()
|
public static void ToggleRareMeta()
|
||||||
{
|
{
|
||||||
RareMetaEnabled = !RareMetaEnabled;
|
PluginSettings.Instance.RareMetaEnabled = !PluginSettings.Instance.RareMetaEnabled;
|
||||||
|
RareMetaEnabled = PluginSettings.Instance.RareMetaEnabled;
|
||||||
MainView.SetRareMetaToggleState(RareMetaEnabled);
|
MainView.SetRareMetaToggleState(RareMetaEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,6 +368,8 @@ namespace MosswartMassacre
|
||||||
WriteToChat("/mm report - Show current stats");
|
WriteToChat("/mm report - Show current stats");
|
||||||
WriteToChat("/mm reset - Reset all counters");
|
WriteToChat("/mm reset - Reset all counters");
|
||||||
WriteToChat("/mm meta - Toggle rare meta state");
|
WriteToChat("/mm meta - Toggle rare meta state");
|
||||||
|
WriteToChat("/mm http - http server enable|disable");
|
||||||
|
WriteToChat("/mm remotecommand - Listen to remote commands enable|disable");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "report":
|
case "report":
|
||||||
|
|
@ -331,6 +387,58 @@ namespace MosswartMassacre
|
||||||
WriteToChat($"Rare meta state is now {(RareMetaEnabled ? "ON" : "OFF")}");
|
WriteToChat($"Rare meta state is now {(RareMetaEnabled ? "ON" : "OFF")}");
|
||||||
MainView.SetRareMetaToggleState(RareMetaEnabled); // <-- sync the UI
|
MainView.SetRareMetaToggleState(RareMetaEnabled); // <-- sync the UI
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "http":
|
||||||
|
if (args.Length > 1)
|
||||||
|
{
|
||||||
|
if (args[1].Equals("enable", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
PluginSettings.Instance.HttpServerEnabled = true;
|
||||||
|
HttpServerEnabled = true;
|
||||||
|
HttpCommandServer.Start();
|
||||||
|
}
|
||||||
|
else if (args[1].Equals("disable", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
PluginSettings.Instance.HttpServerEnabled = false;
|
||||||
|
HttpServerEnabled = false;
|
||||||
|
HttpCommandServer.Stop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteToChat("Usage: /mm http <enable|disable>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteToChat("Usage: /mm http <enable|disable>");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "remotecommands":
|
||||||
|
if (args.Length > 1)
|
||||||
|
{
|
||||||
|
if (args[1].Equals("enable", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
PluginSettings.Instance.RemoteCommandsEnabled = true;
|
||||||
|
RemoteCommandsEnabled = true;
|
||||||
|
WriteToChat("Remote command listening is now ENABLED.");
|
||||||
|
}
|
||||||
|
else if (args[1].Equals("disable", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
PluginSettings.Instance.RemoteCommandsEnabled = false;
|
||||||
|
RemoteCommandsEnabled = false;
|
||||||
|
WriteToChat("Remote command listening is now DISABLED.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteToChat("Invalid remotecommands argument. Use 'enable' or 'disable'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteToChat("Usage: /mm remotecommands <enable|disable>");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WriteToChat($"Unknown /mm command: {subCommand}. Try /mm help");
|
WriteToChat($"Unknown /mm command: {subCommand}. Try /mm help");
|
||||||
|
|
|
||||||
80
MosswartMassacre/PluginSettings.cs
Normal file
80
MosswartMassacre/PluginSettings.cs
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using YamlDotNet.Serialization;
|
||||||
|
using YamlDotNet.Serialization.NamingConventions;
|
||||||
|
using Decal.Adapter;
|
||||||
|
|
||||||
|
namespace MosswartMassacre
|
||||||
|
{
|
||||||
|
public class PluginSettings
|
||||||
|
{
|
||||||
|
private static PluginSettings _instance;
|
||||||
|
private static string _filePath;
|
||||||
|
private bool _remoteCommandsEnabled = false;
|
||||||
|
private bool _rareMetaEnabled = true;
|
||||||
|
private bool _httpServerEnabled = false;
|
||||||
|
private string _charTag = "default";
|
||||||
|
public static PluginSettings Instance => _instance;
|
||||||
|
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
string characterName = CoreManager.Current.CharacterFilter.Name;
|
||||||
|
string pluginFolder = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
|
||||||
|
_filePath = Path.Combine(pluginFolder, $"{characterName}.yaml");
|
||||||
|
|
||||||
|
if (File.Exists(_filePath))
|
||||||
|
{
|
||||||
|
var deserializer = new DeserializerBuilder()
|
||||||
|
.WithNamingConvention(UnderscoredNamingConvention.Instance)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
string yaml = File.ReadAllText(_filePath);
|
||||||
|
_instance = deserializer.Deserialize<PluginSettings>(yaml);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_instance = new PluginSettings();
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply settings to runtime state
|
||||||
|
PluginCore.RareMetaEnabled = _instance.RareMetaEnabled;
|
||||||
|
PluginCore.RemoteCommandsEnabled = _instance.RemoteCommandsEnabled;
|
||||||
|
PluginCore.HttpServerEnabled = _instance.HttpServerEnabled;
|
||||||
|
PluginCore.CharTag = _instance.CharTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Save()
|
||||||
|
{
|
||||||
|
var serializer = new SerializerBuilder()
|
||||||
|
.WithNamingConvention(UnderscoredNamingConvention.Instance)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
string yaml = serializer.Serialize(_instance);
|
||||||
|
File.WriteAllText(_filePath, yaml);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoteCommandsEnabled
|
||||||
|
{
|
||||||
|
get => _remoteCommandsEnabled;
|
||||||
|
set { _remoteCommandsEnabled = value; Save(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RareMetaEnabled
|
||||||
|
{
|
||||||
|
get => _rareMetaEnabled;
|
||||||
|
set { _rareMetaEnabled = value; Save(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HttpServerEnabled
|
||||||
|
{
|
||||||
|
get => _httpServerEnabled;
|
||||||
|
set { _httpServerEnabled = value; Save(); }
|
||||||
|
}
|
||||||
|
public string CharTag
|
||||||
|
{
|
||||||
|
get => _charTag;
|
||||||
|
set { _charTag = value; Save(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
MosswartMassacre/app.config
Normal file
19
MosswartMassacre/app.config
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Decal.Interop.Core" publicKeyToken="481f17d392f1fb65" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-2.9.8.3" newVersion="2.9.8.3" />
|
||||||
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Decal.Adapter" publicKeyToken="bd1c8ce002ce221e" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-2.9.8.3" newVersion="2.9.8.3" />
|
||||||
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Decal.Interop.Inject" publicKeyToken="481f17d392f1fb65" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-2.9.8.3" newVersion="2.9.8.3" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
||||||
4
MosswartMassacre/packages.config
Normal file
4
MosswartMassacre/packages.config
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="YamlDotNet" version="16.3.0" targetFramework="net48" />
|
||||||
|
</packages>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue