-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWickerServer.cs
162 lines (138 loc) · 5.85 KB
/
WickerServer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
using MelonLoader;
using MelonLoader.Utils;
using System.Net;
namespace WickerREST
{
public static class BuildInfo
{
public const string Name = "WickerREST";
public const string Description = "WickerREST";
public const string Author = "Skrip";
public const string Version = "0.95.2";
public const string DownloadLink = "";
}
public class WickerServer : MelonMod
{
internal static string userDataPath = "WickerREST";
internal static string resourcesPath = userDataPath + "/resources";
private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
private Queue<(Action, HttpListenerResponse)> mainThreadActions = new Queue<(Action, HttpListenerResponse)>();
private MelonPreferences_Category? modCategory;
private MelonPreferences_Entry<string>? frontEnd;
private MelonPreferences_Entry<int>? listeningPort;
private MelonPreferences_Entry<int>? debugLevel;
// Instance of this class
private static WickerServer? instance;
// Singleton pattern
public static WickerServer Instance
{
get
{
if (instance == null)
{
instance = new WickerServer();
}
return instance;
}
private set
{
instance = value;
}
}
public MelonPreferences_Entry<string>? FrontEnd { get => frontEnd; set => frontEnd = value; }
public override void OnInitializeMelon()
{
Instance = this;
userDataPath = Path.Combine(MelonEnvironment.UserDataDirectory, userDataPath);
Directory.CreateDirectory(userDataPath);
resourcesPath = Path.Combine(MelonEnvironment.UserDataDirectory, resourcesPath);
Directory.CreateDirectory(resourcesPath);
modCategory = MelonPreferences.CreateCategory("WickerREST");
modCategory.SetFilePath(Path.Combine(userDataPath, "WickerREST.cfg"));
FrontEnd = modCategory.CreateEntry("FrontEnd", "index.html", description: "Specify the file for the front end to use (default, index.html). These files by default are in ..\\UserData\\WickerREST\\resources\\");
listeningPort = modCategory.CreateEntry("ListeningPort", 6103, description: "Port server will listen on");
debugLevel = modCategory.CreateEntry("DebugLevel", 0, description: "Debug level for logging (0: None, 1: Raised, 2: Verbose)");
if (!File.Exists(Path.Combine(userDataPath, "WickerREST.cfg")))
{
MelonPreferences.Save();
}
//Verify listening port is valid, otherwise set to default 6103. Notify it was reset
if (listeningPort.Value < 1 || listeningPort.Value > 65535)
{
listeningPort.Value = 6103;
LogMessage("Listening port was invalid. Reset to default 6103.");
MelonPreferences.Save();
}
//Verify debug level is valid, otherwise set to default 0. Notify it was reset
if (debugLevel.Value < 0 || debugLevel.Value > 2)
{
debugLevel.Value = 0;
LogMessage("Debug level was invalid. Reset to default 0.");
MelonPreferences.Save();
}
var discoveryThread = new Thread(() =>
{
Commands.Instance.DiscoverHandlersAndVariables(); // Discover command handlers and game variables
});
discoveryThread.Start();
WickerNetwork.Instance.StartServer(listeningPort.Value, cancellationTokenSource);
LoggerInstance.WriteLine(39);
LogMessage($"Server initialized on port {listeningPort.Value}");
LogMessage($"Navigate to: http://localhost:{listeningPort.Value}/");
LoggerInstance.WriteLine(39);
}
public override void OnUpdate()
{
try
{
while (mainThreadActions.Count > 0)
{
var (action, response) = mainThreadActions.Dequeue();
try
{
action.Invoke();
}
finally
{
// Try to close the response in case the action failed or didn't send a response
try
{
response.Close();
}
catch (Exception)
{
// No need to log this exception, it's a cleanup in case this didn't already happen
}
}
}
}
catch (Exception ex)
{
LoggerInstance.Error(ex.ToString());
}
}
internal void ExecuteOnMainThread(Action action, HttpListenerResponse response)
{
mainThreadActions.Enqueue((action, response));
}
/// <summary>
/// Log a message to the console with debug level check
/// </summary>
/// <param name="message"></param>
/// <param name="requiredDebugLevel"></param>
public void LogMessage(string message, int requiredDebugLevel = 0)
{
// Check if current debug level allows logging this message
if ((debugLevel == null && requiredDebugLevel == 0)
|| (debugLevel != null && debugLevel.Value >= requiredDebugLevel))
{
LoggerInstance.Msg(message);
}
}
public override void OnApplicationQuit()
{
WickerNetwork.Instance.StopServer();
base.OnApplicationQuit();
}
}
}