Skip to content

Commit 4cc1aab

Browse files
committed
More fixes and documentation. Should be ready for release now.
1 parent ce8893b commit 4cc1aab

File tree

4 files changed

+80
-22
lines changed

4 files changed

+80
-22
lines changed

README.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,32 @@ Prerequisite: [.NET 6](https://dotnet.microsoft.com/en-us/)
3131
- Make sure the service shows as `Running`, and you receive no errors trying to start it.
3232
- Your Minecraft server should be running. You're done!
3333

34-
You can install multiple servers, by reusing the same SMSM files, and simply creating another `config.json` pointing to a different server. Just repeat the above steps for the second config.
34+
You can install multiple servers, by reusing the same SMSM files, and simply creating another config `.json` pointing to a different server. Just repeat the above steps for the second config.
3535

3636
## Management
37-
To manage the server, start the management utility from an **administrator** PowerShell window: `.\SMSMRemoteTool.exe <Name>`, where `Name` is the name used to install the service (should be the `Name` in the `config.json`).
37+
To manage the server, start the management utility from an **administrator** PowerShell window: `.\SMSMRemoteTool.exe <Name>`, where `Name` is the name used to install the service (should be the `Name` in the config `.json`).
3838
If you are successfully connected, you should see `-> Connected to management interface on "<Name>".`
3939
You can now enter any command from the section below.
4040
Once you are done, type `exit` and press enter. This stops the remote session, but does **not** turn off the server. To completely shut down the server, use the `stop` command, and then stop the service.
4141

42+
## Configuration
43+
All settings are configured in the config `.json` file you selected when installing the service. The below table explains the options available.
44+
45+
| Option | Required? | Default | Type | Description |
46+
|---|---|---|---|---|
47+
| `Name` | **Required** | N/A | string | The name of this instance. Used to name the service, access the management interface, and in various other locations. A name without spaces is recommended. |
48+
| `ServerDir` | **Required** | N/A | Path string | The location of the Minecraft server files. The server JAR should be located in this folder. |
49+
| `JavaPath` | Recommended | Java on PATH | Path string | A path to `java.exe`, including the filename. If not specified, SMSM attempts to use your system default Java installation, which may be incorrect, so it is recommended to set this. |
50+
| `MinRAM` | Optional | 1024 | int | The amount of RAM to assign as the minimum, in MB. |
51+
| `MaxRAM` | Optional | 2048 | int | The amount of RAM to assign as the maximum, in MB. |
52+
| `JavaArgs` | Optional | `""` | string | Additional arguments to pass to Java (not the server). |
53+
| `ServerJar` | **Required** | N/A | string | The name of the server JAR file. Do not include the path. |
54+
| `ServerArgs` | Optional | `""` | string | Additional arguments to pass to the server (not Java). |
55+
| `AutoStart` | Optional | `true` | bool | Whether to start the Minecraft server when SMSM starts. |
56+
| `BackupsToKeep` | Optional | `20` | int | The number of backup ZIP files to keep. If there are more than this number, the oldest ones will be deleted until this number is reached. |
57+
| `BackupExclusions` | Optional | None | string array | A list of non-case-sensitive exclusion patterns for files and directories to exclude from being backed up. Wildcards are supported, such as `?`,`*`,`**`. |
58+
| `Schedule` | Optional | None | object array | A list of scheduled tasks that SMSM will do, regardless of whether the Minecraft server is running or not. See the below section for further details. |
59+
4260
## Commands
4361
These are used both by the remote management tool, and by the task scheduler.
4462
| Task | Argument | Description |

SMSMService/ConfigReader.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public static bool ReadConfig(string path)
2121
string JavaArgs = ReadProperty(JSON, "JavaArgs", "", false);
2222
string? ServerJar = ReadProperty<string?>(JSON, "ServerJar", null, true);
2323
string ServerArgs = ReadProperty(JSON, "ServerArgs", "", false);
24+
bool AutoStart = ReadProperty(JSON, "AutoStart", true, false);
2425
int BackupsToKeep = ReadProperty(JSON, "BackupsToKeep", 20, true);
2526
string[] BackupExclusions = ReadArray(JSON, "BackupExclusions", Array.Empty<string>(), false);
2627

@@ -117,6 +118,7 @@ public static bool ReadConfig(string path)
117118
SMSM.JavaArgs = Arguments;
118119
SMSM.ServerDir = ServerDir;
119120
SMSM.ServerName = Name;
121+
SMSM.AutoStart = AutoStart;
120122
Scheduler.Tasks = Schedule;
121123
BackupTask.MaxBackupCount = BackupsToKeep;
122124
BackupTask.Exclusions = BackupExclusions;
@@ -133,8 +135,11 @@ public static bool ReadConfig(string path)
133135
/// <returns>A property value, either from JSON or the default</returns>
134136
private static T ReadProperty<T>(JObject source, string name, T defaultValue, bool warnIfNotFound)
135137
{
136-
T? Result = source.Value<T>(name);
137-
if (Result != null) { return Result; }
138+
if (source.ContainsKey(name))
139+
{
140+
T? Result = source.Value<T>(name);
141+
if (Result != null) { return Result; }
142+
}
138143

139144
if (warnIfNotFound) { Log.Warn($"'{name}' was not found in the config file. Using defautl value of '{defaultValue}'."); }
140145
return defaultValue;

SMSMService/SMSM.cs

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using SMSMService.Tasks;
1+
using Microsoft.Extensions.Hosting.WindowsServices;
2+
using SMSMService.Tasks;
23

34
namespace SMSMService;
45
public class SMSM : BackgroundService
@@ -9,43 +10,75 @@ public class SMSM : BackgroundService
910
public static string? JavaArgs;
1011
public static string? ServerDir;
1112
public static string ServerName = "No Name";
13+
public static bool AutoStart = true;
1214

1315
private readonly ILogger<SMSM> Logger;
16+
private readonly IHostApplicationLifetime Lifetime;
1417

15-
public SMSM(ILogger<SMSM> logger)
18+
public SMSM(ILogger<SMSM> logger, IHostApplicationLifetime lifetime)
1619
{
1720
this.Logger = logger;
21+
this.Lifetime = lifetime;
22+
this.Lifetime.ApplicationStopping.Register(Stop);
23+
if (this.Lifetime is WindowsServiceLifetime ServiceLife)
24+
{
25+
ServiceLife.CanStop = true;
26+
ServiceLife.CanShutdown = true;
27+
}
1828
}
1929

20-
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
30+
protected override async Task ExecuteAsync(CancellationToken stoppingToken) => await Task.Run(async () =>
2131
{
22-
TaskHandler.AddTasks();
23-
24-
if (ConfigFile == null) { return; }
25-
bool ConfigResult = ConfigReader.ReadConfig(ConfigFile);
26-
if (!ConfigResult)
32+
try
2733
{
28-
Log.Error("The configuration could not be parsed, and SMSM will now exit.");
29-
Environment.Exit(-2);
30-
}
31-
BackupTask.Init();
34+
TaskHandler.AddTasks();
3235

33-
Scheduler.Start();
36+
if (ConfigFile == null) { return; }
37+
bool ConfigResult = ConfigReader.ReadConfig(ConfigFile);
38+
if (!ConfigResult)
39+
{
40+
Log.Error("The configuration could not be parsed, and SMSM will now exit.");
41+
Environment.Exit(-2);
42+
}
43+
BackupTask.Init();
3444

35-
RemoteConnector.Start(ServerName);
45+
Scheduler.Start();
3646

37-
while (!stoppingToken.IsCancellationRequested)
38-
{
39-
await Task.Delay(1000, stoppingToken);
47+
RemoteConnector.Start(ServerName);
48+
49+
if (AutoStart)
50+
{
51+
bool Started = Server.StartServer();
52+
if (!Started) { Log.Error("Server could not be auto-started."); }
53+
}
54+
55+
while (!stoppingToken.IsCancellationRequested)
56+
{
57+
await Task.Delay(1000, stoppingToken);
58+
}
4059
}
60+
catch (Exception Exc) { Log.Error(Exc.ToString()); }
61+
finally { Stop(); }
62+
});
63+
64+
public override async Task StopAsync(CancellationToken stoppingToken)
65+
{
66+
Stop();
67+
await base.StopAsync(stoppingToken);
4168
}
4269

4370
public static void Stop()
4471
{
4572
Log.Info("SMSM exit requested.");
73+
Server.SendInput("/say Server shutting down because the management service is stopping");
74+
Server.SendInput("/save-all");
4675
Server.SendInput("/stop");
76+
Server.WaitForExit();
4777
RemoteConnector.Stop();
4878
Scheduler.Stop();
79+
Log.Info("SMSM exit completed.");
4980
}
50-
81+
82+
public static void OnShutdown() => Stop();
83+
5184
}

SMSMService/Start.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ public static async Task Main(string[] args)
66
{
77
if (args.Length != 1) { Console.WriteLine("Please specify the config file path as command-line argument."); Environment.Exit(-3); }
88
SMSM.ConfigFile = args[0];
9+
//Console.TreatControlCAsInput = true;
910

1011
IHost host = Host.CreateDefaultBuilder(args)
1112
.UseWindowsService(options =>
1213
{
1314
options.ServiceName = "SMSM Minecraft Server";
1415
})
16+
.ConfigureHostOptions(options => options.ShutdownTimeout = TimeSpan.FromSeconds(60))
1517
.ConfigureServices(services =>
1618
{
1719
services.AddHostedService<SMSM>();

0 commit comments

Comments
 (0)