feat: Adds auto archiving (#794)
## Adds Auto Archiving Backups are archived once an hour, day, and month. Archives older than 60 days are pruned automatically. _Note: Automatic pruning is off by default_ ### Archive compression format The following formats are supported: * Zstd (The fastest with best compression ratio) * GZip * Zip * None (Tar) _Note: By default archives use [zstandard](http://facebook.github.io/zstd/) format. The archive format can be changed in modernuo.json `autoArchive.compressionFormat`_ ### Restoring world from archive Move the archive to the Saves folder (tar.zst file). On startup the server will extract the file and restore the latest save. See pictures below. ### Manually extracting an archives #### Windows * Use the latest version of [7-zip w/ ZStandard](https://github.com/mcmilk/7-Zip-zstd/releases/latest) 1. Extract the `.tar.zst` file. 2. Extract the `.tar` file. (Yes you have to do it in two steps) * On Windows 10 you can use the command line. `zstd.exe` is in the Assemblies folder after building ModernUO. 1. `tar --use-compress-program "Distribution\Assemblies\zstd.exe -d" -xvf "Archives\Hourly\archivefile.tar.zst" -C "path to where you want to extract it"` #### Mac * Install [Keka](https://www.keka.io) 1. Drop the .tar.zst onto the keka interface. #### Linux 1. Install zstd from a package manager 2. Run `tar -I zstd -xvf "Archives\Hourly\archivefile.tar.zst" -C "path to where you want to extract it"` ### Other changes * Changes Autosave to occur at the same time no matter when the server is booted. * Adds `[SaveFrequency <delay> [warning]`command to set save frequency and warning frequency in-game. * Adds support for time zones that are configurable. The system timezone can also be manually configured. Check `TimeZoneHandler.cs` for details. <img width="257" alt="Screen Shot 2021-09-22 at 11 23 18 PM" src="https://user-images.githubusercontent.com/3953314/134464929-a5bf3cd8-2ef0-4476-a9ad-71d0816a19ac.png"> <img width="241" alt="Screen Shot 2021-09-22 at 11 23 39 PM" src="https://user-images.githubusercontent.com/3953314/134464945-5f6f96dc-3d1e-434d-8256-5c6b3705e786.png"> <img width="836" alt="Screen Shot 2021-09-22 at 11 34 39 PM" src="https://user-images.githubusercontent.com/3953314/134464957-625e57f2-ef47-4ca1-a0a7-cd40c9b6539c.png"> <img width="631" alt="Screen Shot 2021-09-22 at 11 34 50 PM" src="https://user-images.githubusercontent.com/3953314/134464969-b2d65c0d-f8f5-497a-a832-5d805e8e0b22.png">
This commit is contained in:
parent
2f5b26ae68
commit
3f6a87483b
22 changed files with 2150 additions and 149 deletions
|
|
@ -181,6 +181,20 @@ namespace Server
|
|||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static void EnsureDirectory(FileInfo fi)
|
||||
{
|
||||
var dir = fi.DirectoryName;
|
||||
if (dir != null)
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnsureDirectory(DirectoryInfo di)
|
||||
{
|
||||
Directory.CreateDirectory(di.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
public class TypeCache
|
||||
|
|
|
|||
24
Projects/Server/Comparers/DescendingComparer.cs
Normal file
24
Projects/Server/Comparers/DescendingComparer.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2021 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: DescendingComparer.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class DescendingComparer<T> : IComparer<T> where T : IComparable<T> {
|
||||
public int Compare(T x, T y) => y?.CompareTo(x) ?? 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -169,6 +169,17 @@ namespace Server
|
|||
return value;
|
||||
}
|
||||
|
||||
public static void SetSetting(string key, TimeSpan value) => SetSetting(key, value.ToString());
|
||||
|
||||
public static void SetSetting(string key, int value) => SetSetting(key, value.ToString());
|
||||
|
||||
public static void SetSetting(string key, long value) => SetSetting(key, value.ToString());
|
||||
|
||||
public static void SetSetting(string key, bool value) => SetSetting(key, value.ToString());
|
||||
|
||||
public static void SetSetting<T>(string key, T value) where T : struct, Enum =>
|
||||
SetSetting(key, value.ToString());
|
||||
|
||||
public static void SetSetting(string key, string value)
|
||||
{
|
||||
m_Settings.Settings[key] = value;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
|
|
|
|||
|
|
@ -494,7 +494,7 @@ namespace Server
|
|||
try
|
||||
{
|
||||
#if DEBUG
|
||||
var idleCPU = true;
|
||||
const bool idleCPU = true;
|
||||
#else
|
||||
var idleCPU = ServerConfiguration.GetOrUpdateSetting("core.enableIdleCPU", false);
|
||||
#endif
|
||||
|
|
|
|||
80
Projects/Server/TimeZones/TimeZoneHandler.cs
Normal file
80
Projects/Server/TimeZones/TimeZoneHandler.cs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2021 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: TimeZoneHandler.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Server.Json;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
/**
|
||||
* TimeZoneHandler provides a cross platform compatible way to handle system timezones.
|
||||
*
|
||||
* By default the system timezone is used.
|
||||
* To manually configure the local timezone add the following setting to modernuo.json:
|
||||
* "system.localTimeZone": "Pacific Standard Time"
|
||||
* All valid timezones can be found in the Distribution/Data/timezones.json file.
|
||||
*
|
||||
* Notes for timezones.json:
|
||||
* By default, Windows will use the values in the "timezone" property.
|
||||
* By default, Unix/MacOS will use the values in the "region" property.
|
||||
* system.localTimeZone can be either timezone or a region.
|
||||
*
|
||||
* Example:
|
||||
* "system.localTimeZone": "Europe/Lisbon"
|
||||
*/
|
||||
public static class TimeZoneHandler
|
||||
{
|
||||
private static readonly Dictionary<string, TimeZoneInfo> _timeZoneById = new();
|
||||
public static TimeZoneInfo SystemTimeZone { get; private set; }
|
||||
|
||||
static TimeZoneHandler()
|
||||
{
|
||||
var timezones = JsonConfig.Deserialize<TimeZoneWithRegions[]>(Path.Combine(Core.BaseDirectory, "Data/timezones.json"));
|
||||
foreach (var tz in timezones)
|
||||
{
|
||||
// Get the timezone if we are on Windows
|
||||
var tzInfo = Core.IsWindows ? TimeZoneInfo.FindSystemTimeZoneById(tz.TimeZone) : null;
|
||||
|
||||
foreach (var region in tz.Regions)
|
||||
{
|
||||
// Get the timezone by region if we are on linux
|
||||
tzInfo ??= TimeZoneInfo.FindSystemTimeZoneById(region);
|
||||
_timeZoneById[region] = tzInfo;
|
||||
}
|
||||
|
||||
_timeZoneById[tz.TimeZone] = tzInfo;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
var tzId = ServerConfiguration.GetSetting("system.localTimeZone", TimeZoneInfo.Local.Id);
|
||||
SystemTimeZone = FindTimeZoneById(tzId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross platform version of TimeZoneInfo.FindSystemTimeZoneById
|
||||
*/
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static TimeZoneInfo FindTimeZoneById(string id) => _timeZoneById[id];
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static DateTime ToSystemLocalTime(this DateTime date) =>
|
||||
TimeZoneInfo.ConvertTimeFromUtc(date, SystemTimeZone);
|
||||
}
|
||||
}
|
||||
28
Projects/Server/TimeZones/TimeZoneWithRegions.cs
Normal file
28
Projects/Server/TimeZones/TimeZoneWithRegions.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2021 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: TimeZoneWithRegions.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public record TimeZoneWithRegions
|
||||
{
|
||||
[JsonPropertyName("timezone")]
|
||||
public string TimeZone { get; init; }
|
||||
|
||||
[JsonPropertyName("regions")]
|
||||
public string[] Regions { get; init; }
|
||||
}
|
||||
}
|
||||
|
|
@ -35,9 +35,9 @@ namespace Server
|
|||
private Timer _nextTimer;
|
||||
private Timer _prevTimer;
|
||||
|
||||
public Timer(TimeSpan delay) : this(delay, TimeSpan.Zero, 1)
|
||||
{
|
||||
}
|
||||
public Timer(TimeSpan delay) => Init(delay, TimeSpan.Zero, 1);
|
||||
|
||||
public Timer(TimeSpan interval, int count) => Init(interval, interval, count);
|
||||
|
||||
public Timer(TimeSpan delay, TimeSpan interval, int count = 0) => Init(delay, interval, count);
|
||||
|
||||
|
|
|
|||
|
|
@ -927,14 +927,11 @@ namespace Server
|
|||
return outputList;
|
||||
}
|
||||
|
||||
public static bool ToBoolean(string value)
|
||||
{
|
||||
#pragma warning disable CA1806 // Do not ignore method results
|
||||
bool.TryParse(value, out var b);
|
||||
#pragma warning restore CA1806 // Do not ignore method results
|
||||
|
||||
return b;
|
||||
}
|
||||
public static bool ToBoolean(string value) =>
|
||||
bool.TryParse(value, out var b) && b ||
|
||||
value.InsensitiveEquals("enabled") ||
|
||||
value.InsensitiveEquals("on") ||
|
||||
!value.InsensitiveEquals("disabled") && !value.InsensitiveEquals("off");
|
||||
|
||||
public static double ToDouble(string value)
|
||||
{
|
||||
|
|
@ -1484,7 +1481,10 @@ namespace Server
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string GetTimeStamp() => Core.Now.ToString("yyyy-MM-dd-HH-mm-ss");
|
||||
public static string GetTimeStamp() => Core.Now.ToTimeStamp();
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string ToTimeStamp(this DateTime dt) => dt.ToString("yyyy-MM-dd-HH-mm-ss");
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Add<T>(ref List<T> list, T value)
|
||||
|
|
@ -1639,5 +1639,26 @@ namespace Server
|
|||
dict.Clear();
|
||||
dict = null;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void DateToComponents(
|
||||
DateTime date,
|
||||
out int year,
|
||||
out int month,
|
||||
out int day,
|
||||
out DayOfWeek dayOfWeek,
|
||||
out int hour,
|
||||
out int min,
|
||||
out int sec
|
||||
)
|
||||
{
|
||||
year = date.Year;
|
||||
month = date.Month;
|
||||
day = date.Day;
|
||||
dayOfWeek = date.DayOfWeek;
|
||||
hour = date.Hour;
|
||||
min = date.Minute;
|
||||
sec = date.Second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ namespace Server
|
|||
|
||||
public static WorldState WorldState { get; private set; }
|
||||
public static bool Saving => WorldState == WorldState.Saving;
|
||||
public static bool Running => WorldState != WorldState.Loading && WorldState != WorldState.Initial;
|
||||
public static bool Running => WorldState == WorldState.Running;
|
||||
public static bool Loading => WorldState == WorldState.Loading;
|
||||
|
||||
public static Dictionary<Serial, Mobile> Mobiles { get; private set; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue