Skip to content

Commit 9f0137a

Browse files
authored
Merge pull request #46 from TorchAPI/feature-merge
Feature merge
2 parents b0e8d16 + 0bc78d2 commit 9f0137a

14 files changed

Lines changed: 889 additions & 145 deletions

‎Essentials/AutoCommand.cs‎

Lines changed: 163 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,195 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
2+
using System.Collections.ObjectModel;
3+
using System.Runtime.CompilerServices;
54
using System.Threading;
65
using System.Threading.Tasks;
6+
using NLog;
77
using Torch;
88
using Torch.API;
9-
using Torch.Commands;
109
using Torch.API.Managers;
10+
using Torch.Commands;
1111
using Torch.Server;
12+
using Torch.Views;
1213

1314
namespace Essentials
1415
{
15-
public class AutoCommand : ViewModel, IDisposable
16+
public class AutoCommand : ViewModel
1617
{
17-
private Timer _timer;
18-
18+
private TimeSpan _scheduledTime = TimeSpan.Zero;
19+
private static readonly Logger Log = LogManager.GetLogger("Essentials");
20+
private TimeSpan _interval = TimeSpan.Zero;
21+
private DateTime _nextRun = DateTime.MinValue;
22+
private DayOfWeek _day = DayOfWeek.All;
23+
private int _currentStep;
24+
private string _name;
1925
private bool _enabled;
20-
public bool Enabled { get => _enabled; set { _enabled = value; OnTimerChanged(); OnPropertyChanged(); } }
21-
private string _command;
22-
public string Command { get => _command; set { _command = value; OnTimerChanged(); OnPropertyChanged(); } }
23-
private int _dueTime;
24-
public int DueTime { get => _dueTime / 1000; set { _dueTime = value * 1000; OnTimerChanged(); OnPropertyChanged(); } }
25-
private int _period;
26-
public int Period { get => _period / 1000; set { _period = value * 1000; OnTimerChanged(); OnPropertyChanged(); } }
27-
28-
private void OnTimerChanged()
26+
27+
[Display(Description = "Enables or disables this command. NOTE: !admin runauto does NOT respect this setting!")]
28+
public bool Enabled
29+
{
30+
get => _enabled;
31+
set => SetValue(ref _enabled, value);
32+
}
33+
34+
[Display(Description = "Sets the name of this command. Use this name in conjunction with !admin runauto to trigger the command from ingame or from other auto commands.")]
35+
public string Name
2936
{
30-
_timer?.Dispose();
31-
if (Enabled && Period > 0)
32-
_timer = new Timer(RunCommand, this, _dueTime, _period);
37+
get => _name;
38+
set => SetValue(ref _name, value);
3339
}
3440

35-
private void RunCommand(object state)
41+
[Display(Name = "Scheduled Time", GroupName = "Schedule", Description = "Sets a time of day for this command to be run. Format is HH:MM:SS. MUST use 24 hour format! Will be reset to zero if Interval is set.")]
42+
public string ScheduledTime
3643
{
37-
if (((TorchServer)TorchBase.Instance).State != ServerState.Running)
44+
get => _scheduledTime.ToString();
45+
set
46+
{
47+
_scheduledTime = TimeSpan.Parse(value);
48+
OnPropertyChanged();
49+
if (_scheduledTime != TimeSpan.Zero)
50+
{
51+
Interval = TimeSpan.Zero.ToString();
52+
_nextRun = DateTime.Now.Date + _scheduledTime;
53+
if (_nextRun < DateTime.Now)
54+
_nextRun += TimeSpan.FromDays(1);
55+
}
56+
}
57+
}
58+
59+
[Display(Description = "Sets an interval for this command to be repeated. Format is HH:MM:SS. Will be reset to zero if Scheduled Time is set!")]
60+
public string Interval
61+
{
62+
get => _interval.ToString();
63+
set
64+
{
65+
_interval = TimeSpan.Parse(value);
66+
OnPropertyChanged();
67+
if (_interval != TimeSpan.Zero)
68+
{
69+
ScheduledTime = TimeSpan.Zero.ToString(); //I hate myself for this
70+
_nextRun = DateTime.Now + _interval;
71+
}
72+
}
73+
}
74+
75+
[Display(Name = "Day of week", GroupName = "Schedule", Description = "Combined with Scheduled Time, will run the command on the given day of the week at the set time.")]
76+
public DayOfWeek DayOfWeek
77+
{
78+
get => _day;
79+
set => SetValue(ref _day, value);
80+
}
81+
82+
[Display(Description = "Sub-command steps that will be iterated through once the Interval or Scheduled time is reached.")]
83+
public ObservableCollection<CommandStep> Steps { get; } = new ObservableCollection<CommandStep>();
84+
85+
public AutoCommand()
86+
{
87+
Steps.CollectionChanged += (sender, args) => OnPropertyChanged();
88+
}
89+
90+
public void Update()
91+
{
92+
if (DateTime.Now < _nextRun)
93+
return;
94+
95+
//double cast here as I'm unsure how casting directly between enum types will work
96+
if (DayOfWeek != DayOfWeek.All && DateTime.Now.DayOfWeek != (System.DayOfWeek)(int)DayOfWeek)
97+
{
98+
//adding one day because I can't be bothered to calculate exact interval
99+
_nextRun += TimeSpan.FromDays(1);
38100
return;
101+
}
102+
103+
if (Steps.Count <= 0)
104+
return;
105+
106+
var step = Steps[_currentStep];
107+
108+
step.RunStep();
109+
_currentStep++;
110+
_nextRun += step.DelaySpan;
39111

40-
var autoCommand = (AutoCommand)state;
41-
TorchBase.Instance.Invoke(() =>
112+
if (_currentStep >= Steps.Count)
42113
{
43-
var manager = TorchBase.Instance.CurrentSession.Managers.GetManager<CommandManager>();
44-
manager?.HandleCommandFromServer(autoCommand.Command);
45-
});
114+
_currentStep = 0;
115+
if (_scheduledTime != TimeSpan.Zero)
116+
_nextRun = DateTime.Now.Date + _scheduledTime + TimeSpan.FromDays(1);
117+
else
118+
_nextRun = DateTime.Now + _interval;
119+
}
46120
}
47121

48-
~AutoCommand()
122+
public class CommandStep : ViewModel
49123
{
50-
try
124+
internal TimeSpan DelaySpan;
125+
private string _command;
126+
127+
[Display(Description = "Delay AFTER this step and BEFORE the next step. Format is HH:MM:SS.")]
128+
public string Delay
51129
{
52-
Dispose();
130+
get => DelaySpan.ToString();
131+
set => SetValue(ref DelaySpan, TimeSpan.Parse(value));
53132
}
54-
catch
133+
134+
[Display(Description = "Command to be run as the server.")]
135+
public string Command
55136
{
56-
// ignored
137+
get => _command;
138+
set => SetValue(ref _command, value);
57139
}
140+
141+
public void RunStep()
142+
{
143+
if (((TorchServer)EssentialsPlugin.Instance.Torch).State != ServerState.Running)
144+
return;
145+
146+
if (string.IsNullOrEmpty(Command))
147+
return;
148+
149+
EssentialsPlugin.Instance.Torch.Invoke(() =>
150+
{
151+
var manager = EssentialsPlugin.Instance.Torch.CurrentSession.Managers.GetManager<CommandManager>();
152+
manager?.HandleCommandFromServer(Command);
153+
});
154+
}
155+
156+
public override string ToString()
157+
{
158+
return Command;
159+
}
160+
}
161+
162+
163+
/// <summary>
164+
/// Runs the command and all steps immediately, in a new thread
165+
/// </summary>
166+
internal void RunNow()
167+
{
168+
Task.Run(() =>
169+
{
170+
foreach (var step in Steps)
171+
{
172+
step.RunStep();
173+
Thread.Sleep(step.DelaySpan);
174+
}
175+
});
58176
}
59177

60-
/// <inheritdoc />
61-
public void Dispose()
178+
public override string ToString()
62179
{
63-
_timer?.Dispose();
180+
return $"{Name} : {(Enabled ? "Enabled" : "Disabled")} : {Steps.Count}";
64181
}
65182
}
183+
184+
public enum DayOfWeek
185+
{
186+
All = -1,
187+
Sunday = System.DayOfWeek.Sunday,
188+
Monday = System.DayOfWeek.Monday,
189+
Tuesday = System.DayOfWeek.Tuesday,
190+
Wednesday = System.DayOfWeek.Wednesday,
191+
Thursday = System.DayOfWeek.Thursday,
192+
Friday = System.DayOfWeek.Friday,
193+
Saturday = System.DayOfWeek.Saturday
194+
}
66195
}

‎Essentials/AutoCommands.cs‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Timers;
6+
using NLog;
7+
8+
namespace Essentials
9+
{
10+
public class AutoCommands : IDisposable
11+
{
12+
private static AutoCommands _instance;
13+
public static AutoCommands Instance => _instance ?? (_instance = new AutoCommands());
14+
private static readonly Logger Log = LogManager.GetLogger("Essentials");
15+
16+
private Timer _timer;
17+
18+
public void Start()
19+
{
20+
_timer = new Timer(1000);
21+
_timer.Elapsed += TimerElapsed;
22+
_timer.AutoReset = true;
23+
_timer.Start();
24+
}
25+
26+
private void TimerElapsed(object sender, ElapsedEventArgs e)
27+
{
28+
foreach (var command in EssentialsPlugin.Instance.Config.AutoCommands)
29+
{
30+
if(!command.Enabled)
31+
continue;
32+
33+
try
34+
{
35+
command.Update();
36+
}
37+
catch (Exception ex)
38+
{
39+
Log.Error(ex, "Error encountered during autocommand update!");
40+
}
41+
}
42+
}
43+
44+
public void Dispose()
45+
{
46+
_timer?.Dispose();
47+
}
48+
}
49+
}

‎Essentials/Commands/AdminModule.cs‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Sandbox.Engine.Multiplayer;
7+
using Torch.Commands;
8+
using Torch.Commands.Permissions;
9+
using Torch.Mod;
10+
using Torch.Mod.Messages;
11+
using VRage.Game.ModAPI;
12+
using VRageRender.Utils;
13+
14+
namespace Essentials.Commands
15+
{
16+
[Category("admin")]
17+
public class AdminModule : CommandModule
18+
{
19+
[Command("stats", "Get performance statistics of the server")]
20+
[Permission(MyPromoteLevel.Admin)]
21+
public void Statistics()
22+
{
23+
var sb = new StringBuilder();
24+
sb.AppendLine("Generic:");
25+
Stats.Generic.WriteTo(sb);
26+
sb.AppendLine("Network:");
27+
Stats.Network.WriteTo(sb);
28+
sb.AppendLine("Timing:");
29+
Stats.Timing.WriteTo(sb);
30+
31+
ModCommunication.SendMessageTo(new DialogMessage("Statistics", null, sb.ToString()) , Context.Player.SteamUserId);
32+
}
33+
34+
[Command("playercount", "Gets or sets the max number of players on the server")]
35+
[Permission(MyPromoteLevel.Admin)]
36+
public void PlayerCount(int count = -1)
37+
{
38+
if (count == -1)
39+
{
40+
Context.Respond($"Nax player count: {MyMultiplayer.Static.MemberLimit}. Current online players: {MyMultiplayer.Static.MemberCount - 1}");
41+
return;
42+
}
43+
44+
MyMultiplayer.Static.MemberLimit = count;
45+
Context.Respond($"Nax player count: {MyMultiplayer.Static.MemberLimit}. Current online players: {MyMultiplayer.Static.MemberCount - 1}");
46+
}
47+
48+
[Command("runauto", "Runs the auto command with the given name immediately")]
49+
[Permission(MyPromoteLevel.Admin)]
50+
public void RunAuto(string name)
51+
{
52+
var command = EssentialsPlugin.Instance.Config.AutoCommands.FirstOrDefault(c => c.Name.Equals(name));
53+
if (command == null)
54+
{
55+
Context.Respond($"Couldn't find an auto command with the name {name}");
56+
return;
57+
}
58+
59+
command.RunNow();
60+
}
61+
}
62+
}

0 commit comments

Comments
 (0)