mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-23 12:42:22 -04:00
Upgrade tempranks to new format. Allows temp ranking accurately to exact secons (addresses #277), also ranking deletes temprank, fixes #349
This commit is contained in:
parent
67503ef02a
commit
4b08765c49
@ -89,10 +89,11 @@ namespace MCGalaxy.Commands.Moderation {
|
||||
MessageTooHighRank(p, "change the rank of", false); return false;
|
||||
}
|
||||
if (p != null && newRank.Permission >= p.Rank) {
|
||||
Player.Message(p, "Can only rank up to below {0}", newRank.ColoredName); return false;
|
||||
Player.Message(p, "Cannot rank a player to a rank equal to or higher than yours."); return false;
|
||||
}
|
||||
if (p != null && newRank.Permission >= p.Rank) {
|
||||
Player.Message(p, "Cannot change the rank of a player to a rank equal or higher to yours."); return false;
|
||||
if (newRank.Permission == curRank.Permission) {
|
||||
Player.Message(p, "{0} %Sis already ranked {1}.",
|
||||
PlayerInfo.GetColoredName(p, name), curRank.ColoredName); return false;
|
||||
}
|
||||
|
||||
if (who == null) return true;
|
||||
|
@ -60,7 +60,7 @@ namespace MCGalaxy.Commands.Moderation {
|
||||
TimeSpan duration = TimeSpan.Zero;
|
||||
if (!CommandParser.GetTimespan(p, args[2], ref duration, "temp rank for", 'h')) return;
|
||||
|
||||
foreach (string line in Server.TempRanks.Find(target)) {
|
||||
if (Server.tempRanks.Contains(target)) {
|
||||
Player.Message(p, "&cThe player already has a temporary rank assigned!"); return;
|
||||
}
|
||||
|
||||
@ -78,72 +78,70 @@ namespace MCGalaxy.Commands.Moderation {
|
||||
}
|
||||
|
||||
static void Delete(Player p, string target) {
|
||||
bool assigned = false;
|
||||
StringBuilder all = new StringBuilder();
|
||||
Player who = PlayerInfo.FindExact(target);
|
||||
Group curRank = who != null ? who.group : Group.findPlayerGroup(target);
|
||||
string reason = "temp rank unassigned";
|
||||
|
||||
foreach (string line in File.ReadAllLines(Paths.TempRanksFile)) {
|
||||
if (!line.CaselessStarts(target)) { all.AppendLine(line); continue; }
|
||||
string line = Server.tempRanks.FindData(target);
|
||||
if (line == null) {
|
||||
Player.Message(p, "{0}&c has not been assigned a temp rank.",
|
||||
PlayerInfo.GetColoredName(p, target));
|
||||
return;
|
||||
}
|
||||
|
||||
string[] parts = line.SplitSpaces();
|
||||
Group newRank = Group.Find(parts[2]);
|
||||
if (!CmdSetRank.CanChangeRank(target, curRank, newRank, who, p, ref reason)) return;
|
||||
Player who = PlayerInfo.FindExact(target);
|
||||
Group curRank = who != null ? who.group : Group.findPlayerGroup(target);
|
||||
|
||||
Group oldRank = Group.Find(parts[4 - 1]); // -1 because data, not whole line
|
||||
// Old rank was deleted, can't revert rank
|
||||
if (oldRank == null) {
|
||||
Server.tempRanks.Remove(target);
|
||||
return;
|
||||
}
|
||||
|
||||
string reason = "temp rank unassigned";
|
||||
if (!CmdSetRank.CanChangeRank(target, curRank, oldRank, who, p, ref reason)) return;
|
||||
|
||||
ModAction action = new ModAction(target, p, ModActionType.Rank, reason);
|
||||
action.Metadata = newRank;
|
||||
action.Metadata = oldRank;
|
||||
action.targetGroup = curRank;
|
||||
OnModActionEvent.Call(action);
|
||||
assigned = true;
|
||||
}
|
||||
|
||||
if (!assigned) {
|
||||
Player.Message(p, "&a{0}&c has not been assigned a temp rank.", target); return;
|
||||
}
|
||||
File.WriteAllText(Paths.TempRanksFile, all.ToString());
|
||||
}
|
||||
|
||||
static void Info(Player p, string name) {
|
||||
List<string> rankings = Server.TempRanks.FindMatches(p, name, "temp rank");
|
||||
if (rankings == null) return;
|
||||
|
||||
foreach (string line in rankings) {
|
||||
PrintTempRankInfo(p, line); return;
|
||||
static void Info(Player p, string target) {
|
||||
string line = Server.tempRanks.FindData(target);
|
||||
if (line == null) {
|
||||
Player.Message(p, "{0}&c has not been assigned a temp rank.",
|
||||
PlayerInfo.GetColoredName(p, target));
|
||||
} else {
|
||||
PrintTempRankInfo(p, line);
|
||||
}
|
||||
}
|
||||
|
||||
static void List(Player p) {
|
||||
int count = 0;
|
||||
foreach (string line in File.ReadAllLines(Paths.TempRanksFile)) {
|
||||
if (count == 0)
|
||||
Player.Message(p, "&ePlayers with a temporary rank assigned:");
|
||||
PrintTempRankInfo(p, line);
|
||||
count++;
|
||||
}
|
||||
if (count == 0)
|
||||
List<string> lines = Server.tempRanks.AllLines();
|
||||
if (lines.Count == 0) {
|
||||
Player.Message(p, "&cThere are no players with a temporary rank assigned.");
|
||||
} else {
|
||||
Player.Message(p, "&ePlayers with a temporary rank assigned:");
|
||||
foreach (string line in lines) {
|
||||
PrintTempRankInfo(p, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintTempRankInfo(Player p, string line) {
|
||||
string[] args = line.SplitSpaces();
|
||||
string tempRanker = args[9];
|
||||
string tempRank = Group.GetColoredName(args[1]);
|
||||
string oldRank = Group.GetColoredName(args[2]);
|
||||
string assigner = args[1];
|
||||
DateTime assigned = long.Parse(args[2]).FromUnixTime();
|
||||
DateTime expiry = long.Parse(args[3]).FromUnixTime();
|
||||
string oldRank = Group.GetColoredName(args[4]);
|
||||
string tempRank = Group.GetColoredName(args[5]);
|
||||
|
||||
int min = int.Parse(args[4]), hour = int.Parse(args[5]);
|
||||
int day = int.Parse(args[6]), month = int.Parse(args[7]), year = int.Parse(args[8]);
|
||||
int periodH = int.Parse(args[3]), periodM = 0;
|
||||
if (args.Length > 10) periodM = int.Parse(args[10]);
|
||||
|
||||
DateTime assigned = new DateTime(year, month, day, hour, min, 0);
|
||||
DateTime expiry = assigned.AddHours(periodH).AddMinutes(periodM);
|
||||
TimeSpan delta = DateTime.Now - assigned;
|
||||
TimeSpan expireDelta = expiry - DateTime.Now;
|
||||
|
||||
Player.Message(p, "Temp rank information for {0}:", PlayerInfo.GetColoredName(p, args[0]));
|
||||
TimeSpan assignDelta = DateTime.UtcNow - assigned;
|
||||
TimeSpan expireDelta = expiry - DateTime.UtcNow;
|
||||
Player.Message(p, "Temp rank information for {0}:",
|
||||
PlayerInfo.GetColoredName(p, args[0]));
|
||||
Player.Message(p, " From {0} %Sto {1}%S, by {2} &a{3} %Sago, expires in &a{4}",
|
||||
oldRank, tempRank, tempRanker,
|
||||
delta.Shorten(), expireDelta.Shorten());
|
||||
oldRank, tempRank, assigner,
|
||||
assignDelta.Shorten(), expireDelta.Shorten());
|
||||
}
|
||||
|
||||
public override void Help(Player p) {
|
||||
|
@ -20,6 +20,7 @@ using System;
|
||||
using MCGalaxy.Commands;
|
||||
using MCGalaxy.Commands.Moderation;
|
||||
using MCGalaxy.Events;
|
||||
using MCGalaxy.Tasks;
|
||||
|
||||
namespace MCGalaxy.Core {
|
||||
internal static class ModActionHandler {
|
||||
@ -213,6 +214,10 @@ namespace MCGalaxy.Core {
|
||||
if (who != null) {
|
||||
who.SendMessage("You are now ranked " + newRank.ColoredName + "%S, type /help for your new set of commands.");
|
||||
}
|
||||
if (Server.tempRanks.Remove(e.Target)) {
|
||||
ServerTasks.TemprankCalcNextRun();
|
||||
Server.tempRanks.Save();
|
||||
}
|
||||
|
||||
WriteRankInfo(e, newRank);
|
||||
if (e.Duration != TimeSpan.Zero) AddTempRank(e, newRank);
|
||||
@ -233,13 +238,14 @@ namespace MCGalaxy.Core {
|
||||
}
|
||||
|
||||
static void AddTempRank(ModAction e, Group newRank) {
|
||||
DateTime now = DateTime.Now;
|
||||
long assign = DateTime.UtcNow.ToUnixTime();
|
||||
long expiry = DateTime.UtcNow.Add(e.Duration).ToUnixTime();
|
||||
string assigner = e.Actor == null ? "(console)" : e.Actor.name;
|
||||
int hours = (int)e.Duration.TotalHours;
|
||||
|
||||
string data = e.Target + " " + newRank.name + " " + e.TargetGroup.name + " " + hours + " " + now.Minute + " " +
|
||||
now.Hour + " " + now.Day + " " + now.Month + " " + now.Year + " " + assigner + " " + e.Duration.Minutes;
|
||||
Server.TempRanks.Append(data);
|
||||
string data = assigner + " " + assign + " " + expiry + " " + e.TargetGroup.name + " " + newRank.name;
|
||||
Server.tempRanks.AddOrReplace(e.Target, data);
|
||||
ServerTasks.TemprankCalcNextRun();
|
||||
Server.tempRanks.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,8 @@ namespace MCGalaxy {
|
||||
public string Path;
|
||||
|
||||
List<string> names = new List<string>(), lines = new List<string>();
|
||||
readonly object locker = new object(), saveLocker = new object();
|
||||
internal readonly object locker = new object();
|
||||
readonly object saveLocker = new object();
|
||||
|
||||
/// <summary> Returns a copy of all names in the list. </summary>
|
||||
public List<string> AllNames() {
|
||||
|
@ -29,7 +29,8 @@ namespace MCGalaxy {
|
||||
public string Path;
|
||||
|
||||
List<string> names = new List<string>();
|
||||
readonly object locker = new object(), saveLocker = new object();
|
||||
internal readonly object locker = new object();
|
||||
readonly object saveLocker = new object();
|
||||
|
||||
public PlayerList() { }
|
||||
public PlayerList(string path) { Path = path; }
|
||||
|
@ -58,7 +58,6 @@ namespace MCGalaxy {
|
||||
|
||||
public static PlayerExtList AutoloadMaps;
|
||||
public static PlayerMetaList RankInfo = new PlayerMetaList("text/rankinfo.txt");
|
||||
public static PlayerMetaList TempRanks = new PlayerMetaList("text/tempranks.txt");
|
||||
public static PlayerMetaList Notes = new PlayerMetaList("text/notes.txt");
|
||||
|
||||
/// <summary> *** DO NOT USE THIS! *** Use VersionString, as this field is a constant and is inlined if used. </summary>
|
||||
@ -81,7 +80,7 @@ namespace MCGalaxy {
|
||||
public static CTFGame ctf = null;
|
||||
public static PlayerList bannedIP, whiteList, ircControllers, muted, invalidIds;
|
||||
public static PlayerList ignored, frozen, hidden, agreed, vip, noEmotes, lockdown;
|
||||
public static PlayerExtList jailed, models, skins, reach, tempBans, rotations;
|
||||
public static PlayerExtList jailed, models, skins, reach, tempBans, tempRanks, rotations;
|
||||
|
||||
public static readonly List<string> Devs = new List<string>(), Mods = new List<string>();
|
||||
|
||||
|
@ -72,9 +72,12 @@ namespace MCGalaxy {
|
||||
skins = PlayerExtList.Load("extra/skins.txt");
|
||||
reach = PlayerExtList.Load("extra/reach.txt");
|
||||
invalidIds = PlayerList.Load("extra/invalidids.txt");
|
||||
tempBans = PlayerExtList.Load("text/tempbans.txt");
|
||||
tempBans = PlayerExtList.Load(Paths.TempBansFile);
|
||||
rotations = PlayerExtList.Load("extra/rotations.txt");
|
||||
|
||||
tempRanks = PlayerExtList.Load(Paths.TempRanksFile);
|
||||
ServerTasks.TemprankCalcNextRun();
|
||||
|
||||
if (useWhitelist)
|
||||
whiteList = PlayerList.Load("whitelist.txt");
|
||||
}
|
||||
|
@ -116,11 +116,12 @@ namespace MCGalaxy {
|
||||
Background.QueueOnce(LoadMainLevel);
|
||||
Plugin.Load();
|
||||
Background.QueueOnce(UpgradeTasks.UpgradeOldBlacklist);
|
||||
Background.QueueOnce(LoadPlayerLists);
|
||||
Background.QueueOnce(LoadAutoloadMaps);
|
||||
Background.QueueOnce(UpgradeTasks.MovePreviousLevelFiles);
|
||||
Background.QueueOnce(UpgradeTasks.UpgradeOldLockdown);
|
||||
Background.QueueOnce(UpgradeTasks.UpgradeOldTempranks);
|
||||
Background.QueueOnce(UpgradeTasks.UpgradeDBTimeSpent);
|
||||
Background.QueueOnce(LoadPlayerLists);
|
||||
|
||||
Background.QueueOnce(SetupSocket);
|
||||
Background.QueueOnce(InitTimers);
|
||||
@ -131,15 +132,7 @@ namespace MCGalaxy {
|
||||
Mods.Clear();
|
||||
Background.QueueOnce(InitTasks.UpdateStaffList);
|
||||
|
||||
MainScheduler.QueueRepeat(ServerTasks.TemprankExpiry,
|
||||
null, TimeSpan.FromMinutes(1));
|
||||
MainScheduler.QueueRepeat(ServerTasks.CheckState,
|
||||
null, TimeSpan.FromSeconds(3));
|
||||
|
||||
Background.QueueRepeat(ServerTasks.AutoSave,
|
||||
1, TimeSpan.FromSeconds(Server.backupInterval));
|
||||
Background.QueueRepeat(ServerTasks.BlockUpdates,
|
||||
null, TimeSpan.FromSeconds(Server.blockInterval));
|
||||
ServerTasks.QueueTasks();
|
||||
Background.QueueRepeat(ThreadSafeCache.DBCache.CleanupTask,
|
||||
null, TimeSpan.FromMinutes(5));
|
||||
}
|
||||
@ -159,7 +152,6 @@ namespace MCGalaxy {
|
||||
if (!Directory.Exists("levels")) Directory.CreateDirectory("levels");
|
||||
if (!Directory.Exists("bots")) Directory.CreateDirectory("bots");
|
||||
if (!Directory.Exists("text")) Directory.CreateDirectory("text");
|
||||
TempRanks.EnsureExists();
|
||||
RankInfo.EnsureExists();
|
||||
Ban.EnsureExists();
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using MCGalaxy.Commands.Chatting;
|
||||
@ -26,6 +27,20 @@ using MCGalaxy.Maths;
|
||||
namespace MCGalaxy.Tasks {
|
||||
internal static class ServerTasks {
|
||||
|
||||
static SchedulerTask temprankTask;
|
||||
internal static void QueueTasks() {
|
||||
temprankTask = Server.MainScheduler.QueueRepeat(TemprankExpiry,
|
||||
null, TimeSpan.FromHours(1));
|
||||
Server.MainScheduler.QueueRepeat(CheckState,
|
||||
null, TimeSpan.FromSeconds(3));
|
||||
|
||||
Server.Background.QueueRepeat(AutoSave,
|
||||
1, TimeSpan.FromSeconds(Server.backupInterval));
|
||||
Server.Background.QueueRepeat(BlockUpdates,
|
||||
null, TimeSpan.FromSeconds(Server.blockInterval));
|
||||
}
|
||||
|
||||
|
||||
internal static void LocationChecks(SchedulerTask task) {
|
||||
Player[] players = PlayerInfo.Online.Items;
|
||||
players = PlayerInfo.Online.Items;
|
||||
@ -159,27 +174,48 @@ namespace MCGalaxy.Tasks {
|
||||
}
|
||||
|
||||
internal static void TemprankExpiry(SchedulerTask task) {
|
||||
Player[] players = PlayerInfo.Online.Items;
|
||||
|
||||
foreach (string line in File.ReadAllLines(Paths.TempRanksFile))
|
||||
foreach (Player p in players)
|
||||
{
|
||||
if (!line.CaselessStarts(p.name)) continue;
|
||||
List<string> lines = Server.tempRanks.AllLines();
|
||||
foreach (string line in lines) {
|
||||
string[] args = line.SplitSpaces();
|
||||
if (args.Length < 4) continue;
|
||||
|
||||
int min = int.Parse(args[4]), hour = int.Parse(args[5]);
|
||||
int day = int.Parse(args[6]), month = int.Parse(args[7]), year = int.Parse(args[8]);
|
||||
int periodH = int.Parse(args[3]), periodM = 0;
|
||||
if (args.Length > 10) periodM = int.Parse(args[10]);
|
||||
long expiry;
|
||||
if (!long.TryParse(args[3], out expiry)) continue;
|
||||
|
||||
DateTime expire = new DateTime(year, month, day, hour, min, 0)
|
||||
.AddHours(periodH).AddMinutes(periodM);
|
||||
if (DateTime.Now >= expire)
|
||||
Command.all.Find("temprank").Use(null, p.name + " delete");
|
||||
if (DateTime.UtcNow >= expiry.FromUnixTime()) {
|
||||
Command.all.Find("temprank").Use(null, args[0] + " delete");
|
||||
Server.tempRanks.Remove(args[0]); // handle case of temp rank being same as current rank
|
||||
}
|
||||
}
|
||||
task.Delay = TemprankNextRun();
|
||||
}
|
||||
|
||||
DateTime now = DateTime.UtcNow;
|
||||
task.Delay = TimeSpan.FromSeconds(60 - now.Second); // TODO: down to seconds
|
||||
internal static void TemprankCalcNextRun() {
|
||||
temprankTask.Delay = TemprankNextRun();
|
||||
temprankTask.NextRun = DateTime.UtcNow.Add(temprankTask.Delay);
|
||||
Server.MainScheduler.Recheck();
|
||||
}
|
||||
|
||||
static TimeSpan TemprankNextRun() {
|
||||
DateTime nextRun = DateTime.MaxValue;
|
||||
// Lock because we want to ensure list not modified from under us
|
||||
lock (Server.tempRanks.locker) {
|
||||
List<string> lines = Server.tempRanks.AllLines();
|
||||
// Line format: name assigner assigntime expiretime oldRank tempRank
|
||||
|
||||
foreach (string line in lines) {
|
||||
string[] args = line.SplitSpaces();
|
||||
if (args.Length < 4) continue;
|
||||
|
||||
long expiry;
|
||||
if (!long.TryParse(args[3], out expiry)) continue;
|
||||
|
||||
DateTime expireTime = expiry.FromUnixTime();
|
||||
if (expireTime < nextRun)
|
||||
nextRun = expireTime;
|
||||
}
|
||||
}
|
||||
return nextRun - DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
@ -151,6 +151,36 @@ namespace MCGalaxy.Tasks {
|
||||
Directory.Delete("text/lockdown/map");
|
||||
}
|
||||
|
||||
internal static void UpgradeOldTempranks() {
|
||||
if (!File.Exists(Paths.TempRanksFile)) return;
|
||||
|
||||
// Check if empty, or not old form
|
||||
using (StreamReader reader = new StreamReader(Paths.TempRanksFile)) {
|
||||
string line = reader.ReadLine();
|
||||
if (line == null) return;
|
||||
string[] parts = line.SplitSpaces();
|
||||
if (parts.Length < 9) return;
|
||||
}
|
||||
|
||||
string[] lines = File.ReadAllLines(Paths.TempRanksFile);
|
||||
for (int i = 0; i < lines.Length; i++) {
|
||||
string[] args = lines[i].SplitSpaces();
|
||||
|
||||
int min = int.Parse(args[4]), hour = int.Parse(args[5]);
|
||||
int day = int.Parse(args[6]), month = int.Parse(args[7]), year = int.Parse(args[8]);
|
||||
int periodH = int.Parse(args[3]), periodM = 0;
|
||||
if (args.Length > 10) periodM = int.Parse(args[10]);
|
||||
|
||||
DateTime assigned = new DateTime(year, month, day, hour, min, 0);
|
||||
DateTime expiry = assigned.AddHours(periodH).AddMinutes(periodM);
|
||||
|
||||
// Line format: name assigner assigntime expiretime oldRank tempRank
|
||||
lines[i] = args[0] + " " + args[9] + " " + assigned.ToUnixTime() +
|
||||
" " + expiry.ToUnixTime() + " " + args[2] + " " + args[1];
|
||||
}
|
||||
File.WriteAllLines(Paths.TempRanksFile, lines);
|
||||
}
|
||||
|
||||
internal static void UpgradeDBTimeSpent() {
|
||||
DataTable table = Database.Backend.GetRows(PlayerData.DBTable, "TimeSpent", "LIMIT 1");
|
||||
if (table.Rows.Count == 0) return; // no players
|
||||
|
@ -27,6 +27,16 @@ namespace MCGalaxy {
|
||||
int.Parse(parts[2]), int.Parse(parts[3]));
|
||||
}
|
||||
|
||||
public static DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
public static DateTime FromUnixTime(this long offset) {
|
||||
return UnixEpoch.AddTicks(offset * TimeSpan.TicksPerSecond);
|
||||
}
|
||||
|
||||
public static long ToUnixTime(this DateTime time) {
|
||||
return (long)(time.ToUniversalTime() - UnixEpoch).TotalSeconds;
|
||||
}
|
||||
|
||||
public static bool AddSpamEntry(this List<DateTime> log, int maxEntries, int checkInterval) {
|
||||
DateTime now = DateTime.UtcNow;
|
||||
if (log.Count > 0 && log.Count >= maxEntries)
|
||||
|
@ -23,6 +23,7 @@ namespace MCGalaxy {
|
||||
|
||||
public const string CustomColorsFile = "text/customcolors.txt";
|
||||
public const string TempRanksFile = "text/tempranks.txt";
|
||||
public const string TempBansFile = "text/tempbans.txt";
|
||||
public const string CustomTokensFile = "text/custom$s.txt";
|
||||
public const string BadWordsFile = "text/badwords.txt";
|
||||
public const string EatMessagesFile = "text/eatmessages.txt";
|
||||
|
@ -58,6 +58,14 @@ namespace MCGalaxy.Tasks {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Rechecks minimum delay for next task.
|
||||
/// Useful for when external code changes the delay of a scheduled task. </summary>
|
||||
public void Recheck() {
|
||||
lock (taskLock) {
|
||||
handle.Set();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SchedulerTask EnqueueTask(SchedulerTask task) {
|
||||
lock (taskLock) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user