Administrator's Toolkit VS plugin
修訂 | ca020bd7e84d5eac7c46196a961842afa9d52513 (tree) |
---|---|
時間 | 2019-08-13 05:36:53 |
作者 | melchior <melchior@user...> |
Commiter | melchior |
re-cyclic backup process,
changed messages,
altering count now supported
@@ -37,15 +37,22 @@ namespace AdminToolkit | ||
37 | 37 | /// <value>The backup count.</value> |
38 | 38 | public uint BackupCount { get; set;} |
39 | 39 | |
40 | + /// <summary> | |
41 | + /// If auto-enable delayed backup cycle on server start | |
42 | + /// </summary> | |
43 | + /// <value>The autobackup.</value> | |
44 | + public bool Autobackup { get; set; } | |
45 | + | |
46 | + | |
40 | 47 | public AdminModConfig( ) |
41 | 48 | { |
42 | 49 | this.PlayerRoleRestrain = "suvisitor"; |
43 | 50 | this.PlayerRoleNormal = "suplayer"; |
44 | 51 | this.RuleRoleChangerEnabled = false; |
45 | 52 | |
46 | - this.BackupDelay = new TimeSpan(1, 0, 0); | |
47 | - this.BackupCount = 10; | |
48 | - | |
53 | + this.BackupDelay = new TimeSpan(4, 0, 0); | |
54 | + this.BackupCount = 6; | |
55 | + this.Autobackup = false; | |
49 | 56 | } |
50 | 57 | |
51 | 58 |
@@ -95,6 +95,7 @@ namespace AdminToolkit | ||
95 | 95 | this.ServerAPI.RegisterCommand(new BackupCycleCommand(this.ServerAPI) ); |
96 | 96 | |
97 | 97 | this.ServerAPI.Event.PlayerChat += BoomingVoiceOfAuthority; |
98 | + this.ServerAPI.Event.ServerRunPhase(EnumServerRunPhase.Shutdown, SaveConfigSettings); | |
98 | 99 | } |
99 | 100 | |
100 | 101 | private void PopulateAdminRoleTable( ) |
@@ -157,12 +158,13 @@ namespace AdminToolkit | ||
157 | 158 | return message; |
158 | 159 | } |
159 | 160 | |
160 | - | |
161 | - | |
162 | - | |
163 | - | |
164 | - | |
165 | - | |
161 | + private void SaveConfigSettings( ) | |
162 | + { | |
163 | + if (this.CachedConfiguration != null) { | |
164 | + Mod.Logger.Notification("Persisting configuration."); | |
165 | + ServerAPI.StoreModConfig<AdminModConfig>(this.CachedConfiguration, _configFilename); | |
166 | + } | |
167 | + } | |
166 | 168 | |
167 | 169 | } |
168 | 170 | } |
@@ -18,6 +18,10 @@ namespace AdminToolkit | ||
18 | 18 | private const string _timeFormat = @"d\D\ hh\H\ mm\M\ ss\S"; |
19 | 19 | private MechTurk mechanicalTurk; |
20 | 20 | |
21 | + private DateTimeOffset _lastBackupTime = DateTimeOffset.MinValue; | |
22 | + | |
23 | + private string fileFilter; | |
24 | + | |
21 | 25 | public BackupCycleCommand(ICoreServerAPI _serverAPI) : base(_serverAPI) |
22 | 26 | { |
23 | 27 | this.Command = "backups"; |
@@ -27,6 +31,13 @@ namespace AdminToolkit | ||
27 | 31 | this.Syntax = "enable / disable / delay [hours] / stats"; |
28 | 32 | |
29 | 33 | mechanicalTurk = new MechTurk(ServerAPI.Server.Config.Roles.Find(ro => ro.Code == "admin"), this.Logger); |
34 | + | |
35 | + ServerAPI.Event.ServerRunPhase(EnumServerRunPhase.RunGame, ServerStarts); | |
36 | + } | |
37 | + | |
38 | + public bool Enabled { | |
39 | + | |
40 | + get { return this.backupTickerID != 0; } | |
30 | 41 | } |
31 | 42 | |
32 | 43 | private void BackupCommandParser(IServerPlayer player, int groupId, CmdArgs args) |
@@ -35,7 +46,7 @@ namespace AdminToolkit | ||
35 | 46 | |
36 | 47 | StringBuilder msgLine = new StringBuilder( ); |
37 | 48 | bool success = false; |
38 | - int? delay; | |
49 | + int? delay, count; | |
39 | 50 | |
40 | 51 | if (args.Length > 0) { |
41 | 52 | string command = args.PopWord( ); |
@@ -46,12 +57,12 @@ namespace AdminToolkit | ||
46 | 57 | |
47 | 58 | switch (command) { |
48 | 59 | case "enable": |
49 | - success = EnableBackupCycle(true); | |
50 | - if (success) msgLine.AppendFormat("Enabled, with delay: {0}\n", this.CachedConfiguration.BackupDelay.ToString(_timeFormat)); | |
60 | + success = ToggleBackupCycle(true); | |
61 | + if (success) msgLine.AppendFormat("Enabled, with delay: {0}, next: {1}\n", this.CachedConfiguration.BackupDelay.ToString(_timeFormat), DateTimeOffset.UtcNow.Add(this.CachedConfiguration.BackupDelay).ToString("u")); | |
51 | 62 | break; |
52 | 63 | |
53 | 64 | case "disable": |
54 | - success = EnableBackupCycle(false); | |
65 | + success = ToggleBackupCycle(false); | |
55 | 66 | if (success) msgLine.AppendLine("Disabled."); |
56 | 67 | break; |
57 | 68 |
@@ -68,10 +79,24 @@ namespace AdminToolkit | ||
68 | 79 | |
69 | 80 | break; |
70 | 81 | |
71 | - case "stats": | |
82 | + case "count": | |
83 | + count = args.PopInt( ); | |
72 | 84 | |
85 | + if (count.HasValue && count.Value >= 4) { | |
86 | + this.CachedConfiguration.BackupCount = (uint)count.Value; | |
87 | + msgLine.AppendFormat("Changed count to: {0} ", this.CachedConfiguration.BackupCount); | |
88 | + success = true; | |
89 | + } else { | |
90 | + msgLine.AppendLine("Wrong quantity value; must be positive integer 4 or more (count) "); | |
91 | + } | |
73 | 92 | |
93 | + break; | |
74 | 94 | |
95 | + case "state": | |
96 | + case "status": | |
97 | + case "stats": | |
98 | + StatusLine(msgLine); | |
99 | + success = true; | |
75 | 100 | break; |
76 | 101 | |
77 | 102 | default: |
@@ -91,23 +116,29 @@ namespace AdminToolkit | ||
91 | 116 | player.SendMessage(groupId, msgLine.ToString( ), success ? EnumChatType.CommandSuccess : EnumChatType.CommandError); |
92 | 117 | } |
93 | 118 | |
94 | - private bool EnableBackupCycle(bool enable) | |
119 | + /// <summary> | |
120 | + /// Toggles the backup cycle. | |
121 | + /// </summary> | |
122 | + /// <returns>The backup cycle.</returns> | |
123 | + /// <param name="enable">Enable.</param> | |
124 | + private bool ToggleBackupCycle(bool enable) | |
95 | 125 | { |
96 | 126 | if (enable) |
97 | 127 | { |
98 | - if (backupTickerID == 0) | |
128 | + if (!this.Enabled) | |
99 | 129 | { |
100 | 130 | this.backupTickerID = ServerAPI.Event.RegisterCallback(BackupCycleHandler, (int)this.CachedConfiguration.BackupDelay.TotalMilliseconds); |
101 | - Logger.VerboseDebug("BackupCycle enabled, delay: {0}", this.CachedConfiguration.BackupDelay.ToString(_timeFormat)); | |
131 | + Logger.Notification("BackupCycle enabled, delay: {0}", this.CachedConfiguration.BackupDelay.ToString(_timeFormat)); | |
102 | 132 | return true; |
103 | 133 | } |
104 | 134 | } |
105 | 135 | else |
106 | 136 | { |
107 | - if (backupTickerID != 0) | |
137 | + if (this.Enabled) | |
108 | 138 | { |
109 | - ServerAPI.Event.UnregisterCallback(backupTickerID); | |
110 | - Logger.VerboseDebug("BackupCycle disabled"); | |
139 | + ServerAPI.Event.UnregisterCallback(backupTickerID); | |
140 | + this.backupTickerID = 0; | |
141 | + Logger.Notification("BackupCycle disabled"); | |
111 | 142 | return true; |
112 | 143 | } |
113 | 144 | } |
@@ -117,26 +148,26 @@ namespace AdminToolkit | ||
117 | 148 | |
118 | 149 | |
119 | 150 | private void BackupCycleHandler(float elapsed) |
120 | - { | |
121 | - Logger.Event("Automatic Backup triggered, elasped {0} @{1} Uptime",elapsed, ServerAPI.Server.ServerUptimeSeconds ); | |
151 | + { | |
152 | + Logger.Event("Backup cycle triggered, elasped {0} @{1} Uptime", elapsed, ServerAPI.Server.ServerUptimeSeconds); | |
122 | 153 | //Peek at backup DIR, count files of the backup type |
123 | 154 | var backupDir = new DirectoryInfo(GamePaths.Backups); |
124 | 155 | |
125 | 156 | if (backupDir.Exists) { |
126 | - var files = backupDir.GetFiles("*" + GlobalConstants.WorldSaveExtension); | |
157 | + | |
158 | + var files = backupDir.GetFiles(fileFilter); | |
127 | 159 | |
128 | 160 | if (files.Length > this.CachedConfiguration.BackupCount) { |
129 | 161 | Logger.VerboseDebug("There are {0} backup files, over set limit", files.Length); |
130 | - var oldest = files.OrderByDescending(fi => fi.CreationTimeUtc).FirstOrDefault( ); | |
162 | + var oldest = files.OrderBy(fi => fi.CreationTimeUtc).FirstOrDefault( ); | |
131 | 163 | |
132 | 164 | if (oldest != null) { |
133 | - Logger.VerboseDebug("Oldest backup file: {0}", oldest.Name); | |
165 | + Logger.VerboseDebug("Oldest backup file: {0}", oldest.FullName); | |
134 | 166 | oldest.Delete( ); |
135 | - Logger.Notification("Deleted old Backup: {0}", oldest.FullName); | |
167 | + Logger.Notification("Deleted old Backup: {0}", oldest.Name); | |
136 | 168 | } |
137 | 169 | } |
138 | - } else | |
139 | - { | |
170 | + } else { | |
140 | 171 | Logger.VerboseDebug("Could not open backup directory"); |
141 | 172 | } |
142 | 173 |
@@ -145,17 +176,21 @@ namespace AdminToolkit | ||
145 | 176 | |
146 | 177 | ServerMain serverMain = ServerAPI.World as ServerMain; |
147 | 178 | serverMain.EventManager.TriggerChatCommand(mechanicalTurk, GlobalConstants.ServerInfoChatGroup, @"genbackup", new CmdArgs( )); |
148 | - | |
149 | - } else | |
150 | - { | |
179 | + _lastBackupTime = DateTimeOffset.UtcNow; | |
180 | + } else { | |
151 | 181 | Logger.Warning("Could not invoke backup command - API (implimentation) has changed, Contact Developer!"); |
182 | + this.backupTickerID = 0; | |
183 | + return; | |
152 | 184 | } |
153 | 185 | |
186 | + this.backupTickerID = ServerAPI.Event.RegisterCallback(BackupCycleHandler, ( int )this.CachedConfiguration.BackupDelay.TotalMilliseconds); | |
187 | + Logger.Notification("BackupCycle re-engaged, delay: {0} next time: {1}", this.CachedConfiguration.BackupDelay.ToString(_timeFormat), DateTimeOffset.UtcNow.Add(this.CachedConfiguration.BackupDelay).ToString("u")); | |
154 | 188 | |
155 | 189 | //GlobalConstants.ConsoleGroup |
156 | 190 | /* |
157 | 191 | backupFileName = Path.GetFileName(server.Config.WorldConfig.SaveFileLocation).Replace(GlobalConstants.WorldSaveExtension, "") + "-" + string.Format("{0:yyyy-MM-dd_HH-mm-ss}", DateTime.Now) + GlobalConstants.WorldSaveExtension; |
158 | 192 | */ |
193 | + | |
159 | 194 | } |
160 | 195 | |
161 | 196 | private void AlterTimeDelay(int delay) |
@@ -164,11 +199,97 @@ namespace AdminToolkit | ||
164 | 199 | delay = Math.Min(delay, 500);//Limited by callback set in milliseconds |
165 | 200 | |
166 | 201 | this.CachedConfiguration.BackupDelay = new TimeSpan(delay, 0, 0); |
202 | + | |
203 | + if (this.Enabled) | |
204 | + { | |
205 | + ToggleBackupCycle(false); | |
206 | + ToggleBackupCycle(true); | |
207 | + } | |
167 | 208 | } |
168 | 209 | |
169 | - private void UseAMacro( ) | |
210 | + private void StatusLine(StringBuilder msgLine) | |
170 | 211 | { |
171 | - | |
212 | + msgLine.AppendFormat("Delay: {0}, Max Backups:{1}, Auto-start:{2}, ", CachedConfiguration.BackupDelay.ToString(_timeFormat),CachedConfiguration.BackupCount,CachedConfiguration.Autobackup ); | |
213 | + | |
214 | + if (this.Enabled) { | |
215 | + msgLine.AppendFormat("<font color='lime'>Currently enabled: YES</font>\n"); | |
216 | + } else { | |
217 | + msgLine.AppendFormat("<font color='red'>Currently enabled: NO</font>\n"); | |
218 | + } | |
219 | + | |
220 | + if (_lastBackupTime != DateTimeOffset.MinValue) | |
221 | + { | |
222 | + msgLine.AppendFormat("Last Backup attempt: {0} ", _lastBackupTime.ToString("u") ); | |
223 | + msgLine.AppendFormat("Next backup due: {0}\n",_lastBackupTime.Add(CachedConfiguration.BackupDelay).ToString("u") ); | |
224 | + } | |
225 | + | |
226 | + var backupDir = new DirectoryInfo(GamePaths.Backups); | |
227 | + long totalBackupSize = 0; | |
228 | + | |
229 | + if (backupDir.Exists) | |
230 | + { | |
231 | + var backups = backupDir.GetFiles(fileFilter); | |
232 | + | |
233 | + foreach (FileInfo backFile in backups) | |
234 | + { | |
235 | + msgLine.AppendFormat("<font color='white'> '{0}' Size: {1} Written: {2} </font>\n", backFile.Name, FileSizeReadable(backFile.Length), backFile.LastWriteTimeUtc.ToString("u")); | |
236 | + totalBackupSize += backFile.Length; | |
237 | + } | |
238 | + | |
239 | + msgLine.AppendFormat("Total size: {0} in {1} files.\n", FileSizeReadable(totalBackupSize),backups.Length); | |
240 | + | |
241 | + } | |
242 | + } | |
243 | + | |
244 | + public static string FileSizeReadable(long i) | |
245 | + { | |
246 | + // Get absolute value | |
247 | + long absolute_i = (i < 0 ? -i : i); | |
248 | + // Determine the suffix and readable value | |
249 | + string suffix; | |
250 | + double readable; | |
251 | + if (absolute_i >= 0x1000000000000000) // Exabyte | |
252 | + { | |
253 | + suffix = "EB"; | |
254 | + readable = (i >> 50); | |
255 | + } else if (absolute_i >= 0x4000000000000) // Petabyte | |
256 | + { | |
257 | + suffix = "PB"; | |
258 | + readable = (i >> 40); | |
259 | + } else if (absolute_i >= 0x10000000000) // Terabyte | |
260 | + { | |
261 | + suffix = "TB"; | |
262 | + readable = (i >> 30); | |
263 | + } else if (absolute_i >= 0x40000000) // Gigabyte | |
264 | + { | |
265 | + suffix = "GB"; | |
266 | + readable = (i >> 20); | |
267 | + } else if (absolute_i >= 0x100000) // Megabyte | |
268 | + { | |
269 | + suffix = "MB"; | |
270 | + readable = (i >> 10); | |
271 | + } else if (absolute_i >= 0x400) // Kilobyte | |
272 | + { | |
273 | + suffix = "KB"; | |
274 | + readable = i; | |
275 | + } else { | |
276 | + return i.ToString("0 B"); // Byte | |
277 | + } | |
278 | + // Divide by 1024 to get fractional value | |
279 | + readable = (readable / 1024); | |
280 | + // Return formatted number with suffix | |
281 | + return readable.ToString("0.### ") + suffix; | |
282 | + } | |
283 | + | |
284 | + private void ServerStarts( ) | |
285 | + { | |
286 | + //ServerAPI.WorldManager.CurrentWorldName | |
287 | + //ServerAPI.WorldManager.SaveGame.WorldName | |
288 | + string worldNameTrimmed = Path.GetFileNameWithoutExtension(ServerAPI.WorldManager.CurrentWorldName); | |
289 | + fileFilter = $"{worldNameTrimmed}-*{GlobalConstants.WorldSaveExtension}"; | |
290 | + Logger.VerboseDebug("File Filter: {0}", fileFilter); | |
291 | + | |
292 | + if (CachedConfiguration.Autobackup) { ToggleBackupCycle(true); } | |
172 | 293 | } |
173 | 294 | } |
174 | 295 |