mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-22 20:16:36 -04:00
Allow custom categories for /cmd
This commit is contained in:
parent
589050848a
commit
3d2441eb4f
61
CmdPruneDB/CmdPruneDB.csproj
Normal file
61
CmdPruneDB/CmdPruneDB.csproj
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{6AAEC8C6-6A45-4490-8A60-937F287E3D78}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>CmdPruneDB</RootNamespace>
|
||||
<AssemblyName>CmdPruneDB</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<NoWin32Manifest>False</NoWin32Manifest>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
<NoStdLib>False</NoStdLib>
|
||||
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
|
||||
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<BaseAddress>4194304</BaseAddress>
|
||||
<RegisterForComInterop>False</RegisterForComInterop>
|
||||
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>Full</DebugType>
|
||||
<Optimize>False</Optimize>
|
||||
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DebugSymbols>False</DebugSymbols>
|
||||
<DebugType>None</DebugType>
|
||||
<Optimize>True</Optimize>
|
||||
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="MyClass.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MCGalaxy\MCGalaxy_.csproj">
|
||||
<Project>{12597DB0-7C34-4DE1-88EA-9250FF3372EB}</Project>
|
||||
<Name>MCGalaxy_</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
147
CmdPruneDB/MyClass.cs
Normal file
147
CmdPruneDB/MyClass.cs
Normal file
@ -0,0 +1,147 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCGalaxy.DB;
|
||||
using MCGalaxy.Maths;
|
||||
using MCGalaxy.Util;
|
||||
|
||||
namespace MCGalaxy.Commands.Moderation {
|
||||
public class CmdPruneDB : Command2 {
|
||||
public override string name { get { return "PruneDB"; } }
|
||||
public override string type { get { return CommandTypes.Moderation; } }
|
||||
public override LevelPermission defaultRank { get { return LevelPermission.Admin; } }
|
||||
public override bool SuperUseable { get { return false; } }
|
||||
|
||||
public unsafe override void Use(Player p, string message, CommandData data) {
|
||||
if (message.Length == 0) { Player.Message(p, "You need to provide a player name."); return; }
|
||||
|
||||
string[] parts = message.SplitSpaces(), names = null;
|
||||
int[] ids = GetIds(p, data, parts, out names);
|
||||
if (ids == null) return;
|
||||
|
||||
TimeSpan delta = GetDelta(p, parts[0], parts, 1);
|
||||
if (delta == TimeSpan.MinValue) return;
|
||||
|
||||
BlockDB db = p.level.BlockDB;
|
||||
DateTime startTime = DateTime.UtcNow - delta;
|
||||
|
||||
Vec3U16 dims;
|
||||
FastList<BlockDBEntry> entries = new FastList<BlockDBEntry>(4096);
|
||||
byte[] bulk = new byte[BlockDBFile.BulkEntries * BlockDBFile.EntrySize];
|
||||
int start = (int)((startTime - BlockDB.Epoch).TotalSeconds);
|
||||
long total;
|
||||
int changed = 0;
|
||||
|
||||
using (IDisposable locker = db.Locker.AccquireWrite()) {
|
||||
if (!File.Exists(db.FilePath)) {
|
||||
Player.Message(p, "BlockDB file for this map doesn't exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
using (Stream src = OpenRead(db.FilePath), dst = OpenWrite(db.FilePath + ".tmp")) {
|
||||
BlockDBFile format = BlockDBFile.ReadHeader(src, out dims);
|
||||
BlockDBFile.WriteHeader(dst, dims);
|
||||
total = format.CountEntries(src);
|
||||
|
||||
src.Position = src.Length;
|
||||
fixed (byte* ptr = bulk) {
|
||||
while (true) {
|
||||
BlockDBEntry* entry = (BlockDBEntry*)ptr;
|
||||
int count = format.ReadBackward(src, bulk, entry);
|
||||
if (count == 0) break;
|
||||
entry += (count - 1);
|
||||
|
||||
for (int i = count - 1; i >= 0; i--, entry--) {
|
||||
if (entry->TimeDelta < start) goto finished;
|
||||
for (int j = 0; j < ids.Length; j++) {
|
||||
|
||||
if (entry->PlayerID != ids[j]) continue;
|
||||
changed++;
|
||||
entries.Add(*entry);
|
||||
|
||||
if (entries.Count == 4096) {
|
||||
format.WriteEntries(dst, entries);
|
||||
entries.Count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finished:
|
||||
// flush remaining few entries
|
||||
if (entries.Count > 0) format.WriteEntries(dst, entries);
|
||||
}
|
||||
|
||||
string namesStr = names.Join(name => PlayerInfo.GetColoredName(p, name));
|
||||
if (changed > 0) {
|
||||
File.Delete(db.FilePath);
|
||||
File.Move(db.FilePath + ".tmp", db.FilePath);
|
||||
p.Message("Pruned {2} changes by {1}%S's in the past &b{0} %S({3} entries left)",
|
||||
delta.Shorten(true), namesStr, changed, total - changed);
|
||||
} else {
|
||||
File.Delete(db.FilePath + ".tmp");
|
||||
p.Message("No changes found by {1} %Sin the past &b{0}",
|
||||
delta.Shorten(true), namesStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// all this copy paste makes me sad
|
||||
|
||||
static FileStream OpenWrite(string path) {
|
||||
return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
|
||||
}
|
||||
|
||||
static FileStream OpenRead(string path) {
|
||||
return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite);
|
||||
}
|
||||
|
||||
static int[] GetIds(Player p, CommandData data, string[] parts, out string[] names) {
|
||||
int count = Math.Max(1, parts.Length - 1);
|
||||
List<int> ids = new List<int>();
|
||||
names = new string[count];
|
||||
|
||||
for (int i = 0; i < names.Length; i++) {
|
||||
p.Message("Searching PlayerDB for \"{0}\"..", parts[i]);
|
||||
names[i] = PlayerDB.MatchNames(p, parts[i]);
|
||||
if (names[i] == null) return null;
|
||||
|
||||
if (!p.name.CaselessEq(names[i])) {
|
||||
Group grp = Group.GroupIn(names[i]);
|
||||
if (!CheckRank(p, data, grp.Permission, "undo", false)) return null;
|
||||
}
|
||||
ids.AddRange(NameConverter.FindIds(names[i]));
|
||||
}
|
||||
return ids.ToArray();
|
||||
}
|
||||
|
||||
static TimeSpan GetDelta(Player p, string name, string[] parts, int offset) {
|
||||
TimeSpan delta = TimeSpan.Zero;
|
||||
string timespan = parts.Length > offset ? parts[parts.Length - 1] : "30m";
|
||||
bool self = p.name.CaselessEq(name);
|
||||
|
||||
if (timespan.CaselessEq("all")) {
|
||||
return self ? TimeSpan.FromSeconds(int.MaxValue) : p.group.MaxUndo;
|
||||
} else if (!CommandParser.GetTimespan(p, timespan, ref delta, "undo the past", "s")) {
|
||||
return TimeSpan.MinValue;
|
||||
}
|
||||
|
||||
if (delta.TotalSeconds == 0)
|
||||
delta = TimeSpan.FromMinutes(90);
|
||||
if (!self && delta > p.group.MaxUndo) {
|
||||
p.Message("{0}%Ss may only undo up to {1}",
|
||||
p.group.ColoredName, p.group.MaxUndo.Shorten(true, true));
|
||||
return p.group.MaxUndo;
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
|
||||
|
||||
public override void Help(Player p) {
|
||||
p.Message("%T/PruneDB [player1] <player2..> <timespan>");
|
||||
p.Message("%HDeletes the block changes of [players] in the past <timespan> from BlockDB.");
|
||||
p.Message("&cSlow and dangerous. Use with care.");
|
||||
}
|
||||
}
|
||||
}
|
31
CmdPruneDB/Properties/AssemblyInfo.cs
Normal file
31
CmdPruneDB/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,31 @@
|
||||
#region Using directives
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
#endregion
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("CmdPruneDB")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("CmdPruneDB")]
|
||||
[assembly: AssemblyCopyright("Copyright 2018")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// This sets the default COM visibility of types in the assembly to invisible.
|
||||
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The assembly version has following format :
|
||||
//
|
||||
// Major.Minor.Build.Revision
|
||||
//
|
||||
// You can specify all the values or you can use the default the Revision and
|
||||
// Build Numbers by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
@ -43,47 +43,21 @@ namespace MCGalaxy.Commands.Info {
|
||||
}
|
||||
}
|
||||
|
||||
switch (args[0].ToLower()) {
|
||||
case "build":
|
||||
case "building":
|
||||
PrintHelpForGroup(p, sort, modifier, "build", "Building"); break;
|
||||
case "chat":
|
||||
PrintHelpForGroup(p, sort, modifier, "chat", "Chat"); break;
|
||||
case "eco":
|
||||
case "economy":
|
||||
PrintHelpForGroup(p, sort, modifier, "eco", "Economy"); break;
|
||||
case "mod":
|
||||
case "moderation":
|
||||
PrintHelpForGroup(p, sort, modifier, "mod", "Moderation"); break;
|
||||
case "info":
|
||||
case "information":
|
||||
PrintHelpForGroup(p, sort, modifier, "info", "Information"); break;
|
||||
case "game":
|
||||
case "games":
|
||||
PrintHelpForGroup(p, sort, modifier, "game", "Game"); break;
|
||||
case "other":
|
||||
case "others":
|
||||
PrintHelpForGroup(p, sort, modifier, "other", "Other"); break;
|
||||
case "maps":
|
||||
case "world":
|
||||
PrintHelpForGroup(p, sort, modifier, "world", "World"); break;
|
||||
case "short":
|
||||
case "shortcut":
|
||||
case "shortcuts":
|
||||
PrintShortcuts(p, sort); break;
|
||||
case "old":
|
||||
case "oldmenu":
|
||||
case "command":
|
||||
case "":
|
||||
PrintRankCommands(p, sort, modifier, p.group, true); break;
|
||||
case "commandsall":
|
||||
case "commandall":
|
||||
case "all":
|
||||
PrintAllCommands(p, sort, modifier); break;
|
||||
default:
|
||||
Group grp = Group.Find(args[0]);
|
||||
if (grp == null) return false;
|
||||
PrintRankCommands(p, sort, modifier, grp, false); break;
|
||||
string type = args[0].ToLower();
|
||||
if (type == "short" || type == "shortcut" || type == "shortcuts") {
|
||||
PrintShortcuts(p, sort);
|
||||
} else if (type == "old" || type == "oldmenu" || type == "" || type == "command") {
|
||||
PrintRankCommands(p, sort, modifier, p.group, true);
|
||||
} else if (type == "all" || type == "commandall" || type == "commandsall") {
|
||||
PrintAllCommands(p, sort, modifier);
|
||||
} else {
|
||||
bool any = PrintCategoryCommands(p, sort, modifier, type);
|
||||
if (any) return true;
|
||||
|
||||
// list commands a rank can use
|
||||
Group grp = Group.Find(type);
|
||||
if (grp == null) return false;
|
||||
PrintRankCommands(p, sort, modifier, grp, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -105,9 +79,7 @@ namespace MCGalaxy.Commands.Info {
|
||||
List<Command> cmds = new List<Command>();
|
||||
foreach (Command c in Command.allCmds) {
|
||||
string disabled = Command.GetDisabledReason(c.Enabled);
|
||||
if (disabled != null || c.name == null) continue;
|
||||
if (!group.Commands.Contains(c)) continue;
|
||||
cmds.Add(c);
|
||||
if (disabled == null && group.Commands.Contains(c)) cmds.Add(c);
|
||||
}
|
||||
|
||||
if (cmds.Count == 0) {
|
||||
@ -140,29 +112,44 @@ namespace MCGalaxy.Commands.Info {
|
||||
p.Message("Type %T/Help <command> %Sfor more help on a command.");
|
||||
}
|
||||
|
||||
static void PrintHelpForGroup(Player p, string sort, string modifier,
|
||||
string type, string category) {
|
||||
static string GetCategory(string type) {
|
||||
if (type.CaselessEq("building")) return CommandTypes.Building;
|
||||
if (type.CaselessEq("eco")) return CommandTypes.Economy;
|
||||
if (type.CaselessEq("games")) return CommandTypes.Games;
|
||||
if (type.CaselessEq("info")) return CommandTypes.Information;
|
||||
if (type.CaselessEq("moderation")) return CommandTypes.Moderation;
|
||||
if (type.CaselessEq("others")) return CommandTypes.Other;
|
||||
if (type.CaselessEq("maps")) return CommandTypes.World;
|
||||
return type;
|
||||
}
|
||||
|
||||
static bool PrintCategoryCommands(Player p, string sort, string modifier, string type) {
|
||||
List<Command> cmds = new List<Command>();
|
||||
string category = GetCategory(type);
|
||||
bool any = false;
|
||||
|
||||
foreach (Command c in Command.allCmds) {
|
||||
string disabled = Command.GetDisabledReason(c.Enabled);
|
||||
if (p.CanUse(c) && disabled == null) {
|
||||
if (!c.type.CaselessContains(type) || c.name == null) continue;
|
||||
cmds.Add(c);
|
||||
}
|
||||
if (!c.type.CaselessContains(category)) continue;
|
||||
|
||||
if (disabled == null && p.CanUse(c)) cmds.Add(c);
|
||||
any = true;
|
||||
}
|
||||
|
||||
if (cmds.Count == 0) {
|
||||
p.Message("You cannot use any of the " + category + " commands."); return;
|
||||
p.Message("You cannot use any of the " + category + " commands."); return any;
|
||||
}
|
||||
SortCommands(cmds, sort);
|
||||
p.Message(category + " commands you may use:");
|
||||
|
||||
type = "Commands " + category;
|
||||
type = "Commands " + type;
|
||||
if (sort.Length > 0) type += " " + sort;
|
||||
MultiPageOutput.Output(p, cmds,
|
||||
(cmd) => CmdHelp.GetColor(cmd) + cmd.name,
|
||||
type, "commands", modifier, false);
|
||||
|
||||
p.Message("Type %T/Help <command> %Sfor more help on a command.");
|
||||
return any;
|
||||
}
|
||||
|
||||
static void SortCommands(List<Command> cmds, string sort) {
|
||||
|
@ -133,7 +133,7 @@ namespace MCGalaxy.Commands.World {
|
||||
#region Help messages
|
||||
|
||||
static string[] blockPropsHelp = new string[] {
|
||||
"%T/os blockprops [id] [action] <args> %H- Manages properties for custom blocks on your map.",
|
||||
"%T/os blockprops [id] [action] <args> %H- Changes properties of blocks in your map.",
|
||||
"%H See %T/Help blockprops %Hfor a list of actions",
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user