diff options
Diffstat (limited to 'src')
5 files changed, 89 insertions, 46 deletions
diff --git a/src/main/java/com/keuin/blame/Blame.java b/src/main/java/com/keuin/blame/Blame.java index 389c14c..ead8dce 100644 --- a/src/main/java/com/keuin/blame/Blame.java +++ b/src/main/java/com/keuin/blame/Blame.java @@ -13,6 +13,7 @@ import com.keuin.blame.util.PrintUtil; import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.LongArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; @@ -21,12 +22,14 @@ import net.minecraft.command.CommandSource; import net.minecraft.command.argument.BlockPosArgumentType; import net.minecraft.command.argument.DimensionArgumentType; import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; import java.io.File; import java.io.IOException; import java.io.Reader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.util.Arrays; import java.util.logging.Logger; public class Blame implements ModInitializer { @@ -89,19 +92,29 @@ public class Blame implements ModInitializer { // register CommandRegistrationCallback.EVENT.register((commandDispatcher, b) -> { + final LiteralArgumentBuilder<ServerCommandSource> amountLimitArgument = CommandManager.literal("limit") + .then(CommandManager.argument("amount", IntegerArgumentType.integer()) + .suggests((ctx, builder) -> CommandSource.suggestMatching(Arrays.asList("1", "5", "10"), builder)) + .executes(BlameBlockCommand::blameGivenBlockPos) + ).executes(BlameBlockCommand::blameGivenBlockPos); + final LiteralArgumentBuilder<ServerCommandSource> timeRangeArgument = CommandManager.literal("last") + .then(CommandManager.argument("time_range", LongArgumentType.longArg()) + .executes(BlameBlockCommand::blameGivenBlockPos) + .then(CommandManager.argument("time_unit", StringArgumentType.word()) + .suggests((ctx, builder) -> CommandSource.suggestMatching(BlameBlockCommand.timeUnits, builder)) + .executes(BlameBlockCommand::blameGivenBlockPos) + .then(amountLimitArgument) + ) + + ); commandDispatcher.register( CommandManager.literal("blame").then(CommandManager.literal("block") .then(CommandManager.argument("pos", BlockPosArgumentType.blockPos()) .executes(BlameBlockCommand::blameGivenBlockPos) .then(CommandManager.argument("world", DimensionArgumentType.dimension()) .executes(BlameBlockCommand::blameGivenBlockPos) - .then(CommandManager.literal("last") - .then(CommandManager.argument("time_range", LongArgumentType.longArg()) - .executes(BlameBlockCommand::blameGivenBlockPos) - .then(CommandManager.argument("time_unit", StringArgumentType.word()) - .suggests((ctx, builder) -> CommandSource.suggestMatching(BlameBlockCommand.timeUnits, builder)) - .executes(BlameBlockCommand::blameGivenBlockPos)) - )) + .then(timeRangeArgument) + .then(amountLimitArgument) ))) ); commandDispatcher.register( diff --git a/src/main/java/com/keuin/blame/command/BlameBlockCommand.java b/src/main/java/com/keuin/blame/command/BlameBlockCommand.java index eb1888d..eb82fd5 100644 --- a/src/main/java/com/keuin/blame/command/BlameBlockCommand.java +++ b/src/main/java/com/keuin/blame/command/BlameBlockCommand.java @@ -6,6 +6,7 @@ import com.keuin.blame.lookup.*; import com.keuin.blame.util.MinecraftUtil; import com.keuin.blame.util.PrettyUtil; import com.keuin.blame.util.PrintUtil; +import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.LongArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; @@ -44,6 +45,7 @@ public class BlameBlockCommand { Entity entity = context.getSource().getEntity(); if (!(entity instanceof ServerPlayerEntity)) { // can only be executed by player + PrintUtil.error(context, "This command cannot be used in server console."); return FAILED; } @@ -63,8 +65,10 @@ public class BlameBlockCommand { long timeRange; try { timeRange = LongArgumentType.getLong(context, "time_range"); - if (timeRange < 0) + if (timeRange < 0) { + PrintUtil.error(context, "Time range must be positive."); return FAILED; + } } catch (IllegalArgumentException e) { timeRange = -1; } @@ -73,8 +77,10 @@ public class BlameBlockCommand { try { final String timeUnit = StringArgumentType.getString(context, "time_unit"); amplifier = timeUnitAmplifierMap.getOrDefault(timeUnit, -1); - if (amplifier < 0) + if (amplifier < 0) { + PrintUtil.error(context, "Invalid time unit."); return FAILED; + } } catch (IllegalArgumentException e) { amplifier = 1; } @@ -85,6 +91,17 @@ public class BlameBlockCommand { return FAILED; } + int amountLimit; + try { + amountLimit = IntegerArgumentType.getInteger(context, "amount"); + if (amountLimit <= 0) { + PrintUtil.error(context, "Amount must be positive."); + return FAILED; + } + } catch (IllegalArgumentException e) { + amountLimit = BlameLimitCommand.DEFAULT_LOOKUP_LIMIT; + } + // String world = MinecraftUtil.worldToString(playerEntity.world); WorldPos blockPos = new WorldPos(world, x, y, z); AbstractLookupFilter filter; @@ -97,7 +114,7 @@ public class BlameBlockCommand { LookupManager.INSTANCE.lookup( filter, new Callback(context), - BlameLimitCommand.getLookupLimit(playerEntity.getUuid()) + amountLimit ); return SUCCESS; @@ -123,13 +140,13 @@ public class BlameBlockCommand { boolean isFirst = true; for (LogEntry logEntry : logEntries) { if (!isFirst) - printer.append("\n"); - printer.append(Formatting.YELLOW, "Time: ", PrettyUtil.timestampToString(logEntry.timeMillis), "\n") - .append(Formatting.YELLOW, "Subject: ", Formatting.AQUA, logEntry.subjectId, "{", logEntry.subjectUUID, "} @ ", logEntry.subjectPos, "\n") - .append(Formatting.YELLOW, "Action: ", Formatting.AQUA, logEntry.actionType, "\n") - .append(Formatting.YELLOW, "Object: ", Formatting.AQUA, logEntry.objectType, "[", logEntry.objectId, "] @ ", logEntry.objectPos, "\n") - .append(Formatting.YELLOW, "Log version: ", logEntry.version, "\n") - .append(Formatting.YELLOW, "Game version: ", logEntry.gameVersion, "\n") + printer.newline(); + printer.append(Formatting.YELLOW, "Time: ", PrettyUtil.timestampToString(logEntry.timeMillis)).newline() + .append(Formatting.YELLOW, "Subject: ", Formatting.AQUA, logEntry.subjectId, "{", logEntry.subjectUUID, "} @ ", logEntry.subjectPos).newline() + .append(Formatting.YELLOW, "Action: ", Formatting.AQUA, logEntry.actionType).newline() + .append(Formatting.YELLOW, "Object: ", Formatting.AQUA, logEntry.objectType, "[", logEntry.objectId, "] @ ", logEntry.objectPos).newline() + .append(Formatting.YELLOW, "Log version: ", logEntry.version).newline() + .append(Formatting.YELLOW, "Game version: ", logEntry.gameVersion).newline() .append("================"); ++printCount; isFirst = false; diff --git a/src/main/java/com/keuin/blame/command/BlameLimitCommand.java b/src/main/java/com/keuin/blame/command/BlameLimitCommand.java index a31a2f9..c79d245 100644 --- a/src/main/java/com/keuin/blame/command/BlameLimitCommand.java +++ b/src/main/java/com/keuin/blame/command/BlameLimitCommand.java @@ -17,7 +17,7 @@ import static com.keuin.blame.command.Commands.SUCCESS; public class BlameLimitCommand { private static final Map<UUID, Integer> maxLookupCount = new ConcurrentHashMap<>(); - private static final int DEFAULT_LOOKUP_LIMIT = 5; + public static final int DEFAULT_LOOKUP_LIMIT = 5; public static int setLimit(CommandContext<ServerCommandSource> context) { Entity entity = context.getSource().getEntity(); @@ -49,6 +49,7 @@ public class BlameLimitCommand { * @param playerUUID the player's uuid. * @return the limit. */ + @Deprecated public static int getLookupLimit(UUID playerUUID) { return maxLookupCount.getOrDefault(playerUUID, DEFAULT_LOOKUP_LIMIT); } diff --git a/src/main/java/com/keuin/blame/command/BlameStatCommand.java b/src/main/java/com/keuin/blame/command/BlameStatCommand.java index fade0a1..c42fa8f 100644 --- a/src/main/java/com/keuin/blame/command/BlameStatCommand.java +++ b/src/main/java/com/keuin/blame/command/BlameStatCommand.java @@ -12,6 +12,7 @@ import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.util.Formatting; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -22,26 +23,25 @@ public class BlameStatCommand { private static final Logger logger = Logger.getLogger(BlameStatCommand.class.getName()); public static int showStat(CommandContext<ServerCommandSource> context) { - PrintUtil.msgInfo(context, "Collecting statistics. This may take a few seconds..."); - showStat(new ShowStatCallback() { - @Override - public void showStat(@Nullable BlameStat stat) { - StringBuilder sb = new StringBuilder(); - if (stat != null) { - sb.append("Statistics\n"); - sb.append("====\n"); - sb.append("# Count by subjects\n"); - stat.getCountMap().forEach((subjectId, count) -> { - sb.append("<").append( - Optional.ofNullable(Strings.emptyToNull(subjectId)).orElse("null") - ).append(">: ").append(count).append("\n"); - }); - sb.append("=== END ==="); - } else { - sb.append("Failed to get statistics. Please refer to server log for more information."); + PrintUtil.message(context, Formatting.ITALIC, "Collecting statistics. This may take a few seconds..."); + showStat(stat -> { + PrintUtil.Printer sb = PrintUtil.newPrinter(); + if (stat != null) { + sb.append("Logs grouped by subjects:").newline(); + boolean isFirst = true; + for (Map.Entry<String, Long> entry : stat.getCountMap().entrySet()) { + if (!isFirst) + sb.newline(); + isFirst = false; + final String subjectId = entry.getKey(); + final long count = entry.getValue(); + sb.append(Formatting.YELLOW, Optional.ofNullable(Strings.emptyToNull(subjectId)).orElse("null")) + .append(": ").append(count); } - PrintUtil.msgInfo(context, sb.toString()); + } else { + sb.append(Formatting.RED, "Failed to get statistics. Please refer to server log for more information."); } + sb.sendTo(context); }); return Commands.SUCCESS; } diff --git a/src/main/java/com/keuin/blame/util/PrintUtil.java b/src/main/java/com/keuin/blame/util/PrintUtil.java index f1d8695..d869a8b 100644 --- a/src/main/java/com/keuin/blame/util/PrintUtil.java +++ b/src/main/java/com/keuin/blame/util/PrintUtil.java @@ -1,13 +1,15 @@ package com.keuin.blame.util; import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.minecraft.network.MessageType; import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerManager; import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.*; +import net.minecraft.text.BaseText; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Style; +import net.minecraft.text.Text; import net.minecraft.util.Formatting; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -139,16 +141,23 @@ public final class PrintUtil implements ServerLifecycleEvents.ServerStarted { } public static void message(CommandContext<ServerCommandSource> context, Object... objects) { - new Printer().append(objects).sendTo(context); + new Printer(false).append(objects).sendTo(context); + } + + public static void error(CommandContext<ServerCommandSource> context, Object... objects) { + new Printer(true).append(objects).sendTo(context); } public static Printer newPrinter() { - return new Printer(); + return new Printer(false); } public static class Printer { private final BaseText message = new LiteralText(""); - public Printer() { + private final boolean error; + + public Printer(boolean error) { + this.error = error; } public Printer append(Object... objects) { @@ -171,16 +180,19 @@ public final class PrintUtil implements ServerLifecycleEvents.ServerStarted { return this; } + public Printer newline() { + return this.append("\n"); + } + public void sendTo(Consumer<Text> receiver) { receiver.accept(message); } public void sendTo(CommandContext<ServerCommandSource> context) { - try { - context.getSource().getPlayer().sendSystemMessage(message, UUID_NULL); - } catch (CommandSyntaxException e) { - throw new IllegalArgumentException("CommandContext must be of a player"); - } + if (error) + context.getSource().sendError(message); + else + context.getSource().sendFeedback(message, false); } } |