Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ public static LogEntry of(DamageSource source, LivingEntity target, @Nullable Li
}

private static Path path(Player player, @Nullable LivingEntity other, String type, String time) {
return entityPath(player.getScoreboardName(), other, type, time);
}

private static Path entityPath(UUID uuid, @Nullable LivingEntity other, String type, String time) {
return entityPath(uuid.toString(), other, type, time);
}

private static Path entityPath(String id, @Nullable LivingEntity other, String type, String time) {
String otherType;
if (other == null) {
otherType = "null";
Expand All @@ -40,7 +48,7 @@ private static Path path(Player player, @Nullable LivingEntity other, String typ
otherType = rl.getPath().replaceAll("/", "_");
}
return FMLPaths.GAMEDIR.get().resolve("logs/damage_tracker/" +
player.getScoreboardName() + "-" + type + "/" + otherType + "/" + time + ".txt");
id + "-" + type + "/" + otherType + "/" + time + ".txt");
}

private final DamageSource source;
Expand All @@ -61,8 +69,12 @@ private LogEntry(DamageSource source, LivingEntity target, @Nullable LivingEntit
info = L2DamageTrackerConfig.COMMON.printDamageTrace.get();
if (target instanceof ServerPlayer player && LogHelper.savePlayerHurt(player))
saves.add(path(player, attacker, "hurt", time));
else if (!(target instanceof ServerPlayer) && LogHelper.saveEntityHurt(target))
saves.add(entityPath(target.getUUID(), attacker, "hurt", time));
if (attacker instanceof ServerPlayer player && LogHelper.savePlayerAttack(player))
saves.add(path(player, target, "attack", time));
else if (attacker != null && !(attacker instanceof ServerPlayer) && LogHelper.saveEntityAttack(attacker))
saves.add(entityPath(attacker.getUUID(), target, "attack", time));
trace = !saves.isEmpty();
log = info || trace;
if (log) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,20 @@

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import dev.xkmc.l2damagetracker.init.data.L2DamageTrackerConfig;
import net.minecraft.commands.CommandSource;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.commands.arguments.selector.EntitySelector;
import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.LivingEntity;
import org.jetbrains.annotations.Nullable;

import java.util.*;
Expand All @@ -27,16 +26,12 @@ public enum Type {
ATTACK, HURT
}

private record Key(Type type, UUID uuid) {
private record Key(Type type, UUID uuid) {}

}

private record Val(long time, String playerName, @Nullable CommandSource source) {

}
private record Val(long time, UUID uuid, @Nullable CommandSource source) {}

private static final Map<Key, Val> MAP = new HashMap<>();
private static final Val NULL = new Val(0, "", null);
private static final Val NULL = new Val(0, new UUID(0, 0), null);


public static boolean savePlayerHurt(ServerPlayer player) {
Expand All @@ -53,57 +48,59 @@ private static long time(ServerPlayer player) {
return player.server.overworld().getGameTime();
}

public static boolean saveEntityHurt(LivingEntity entity) {
if (entity.level() instanceof ServerLevel sl)
return MAP.getOrDefault(new Key(Type.HURT, entity.getUUID()), NULL).time() > sl.getGameTime();
return false;
}

public static boolean saveEntityAttack(LivingEntity entity) {
if (entity.level() instanceof ServerLevel sl)
return MAP.getOrDefault(new Key(Type.ATTACK, entity.getUUID()), NULL).time() > sl.getGameTime();
return false;
}

public static void buildCommand(LiteralArgumentBuilder<CommandSourceStack> base) {
base.requires(e -> e.hasPermission(2))
.then(Commands.literal("player")
.then(argument("player", EntityArgument.players())
.then(Commands.literal("attack")
.then(Commands.argument("time", IntegerArgumentType.integer(1, 20 * 60 * 60 * 24))
.executes(ctx -> onStart(ctx, Type.ATTACK))))
.then(Commands.literal("hurt")
.then(Commands.argument("time", IntegerArgumentType.integer(1, 20 * 60 * 60 * 24))
.executes(ctx -> onStart(ctx, Type.HURT)))))
);
.then(Commands.argument("entities", EntityArgument.entities())
.then(Commands.literal("attack")
.then(Commands.argument("time", IntegerArgumentType.integer(1, 20 * 60 * 60 * 24))
.executes(ctx -> onStart(ctx, Type.ATTACK))))
.then(Commands.literal("hurt")
.then(Commands.argument("time", IntegerArgumentType.integer(1, 20 * 60 * 60 * 24))
.executes(ctx -> onStart(ctx, Type.HURT)))));
}

public static void tick(MinecraftServer server) {
Multimap<CommandSource, String> removed = HashMultimap.create();
long gameTime = server.overworld().getGameTime();
MAP.entrySet().removeIf(ent -> {
var player = server.getPlayerList().getPlayer(ent.getKey().uuid());
if (player == null || ent.getValue().time() < time(player)) {
removed.put(ent.getValue().source(), ent.getValue().playerName());
return true;
}
return false;
Val val = ent.getValue();
if (val.time() >= gameTime) return false;
removed.put(val.source(), val.uuid().toString());
return true;
});
for (var ent : removed.asMap().entrySet()) {
String pl = ent.getValue().size() == 1 ? new ArrayList<>(ent.getValue()).get(0) : ent.getValue().size() + " players";
String pl = ent.getValue().size() == 1 ? new ArrayList<>(ent.getValue()).get(0) : ent.getValue().size() + " entities";
ent.getKey().sendSystemMessage(Component.literal("Finished damage profiling for " + pl));
}

}


private static int onStart(CommandContext<CommandSourceStack> ctx, Type type) throws CommandSyntaxException {
int time = ctx.getArgument("time", Integer.class);
EntitySelector sel = ctx.getArgument("player", EntitySelector.class);
var list = sel.findPlayers(ctx.getSource());
var list = EntityArgument.getEntities(ctx, "entities");
long expires = ctx.getSource().getServer().overworld().getGameTime() + time;
for (var e : list) {
MAP.put(new Key(type, e.getUUID()), new Val(e.server.overworld().getGameTime() + time, e.getScoreboardName(), ctx.getSource().source));
MAP.put(new Key(type, e.getUUID()), new Val(expires, e.getUUID(), ctx.getSource().source));
}
int sec = time / 20;
int min = sec / 60;
int hrs = min / 60;
String str = String.format("%02d:%02d:%02d", hrs % 24, min % 60, sec % 60);
String side = type.name().toLowerCase(Locale.ROOT);
String pl = list.size() == 1 ? list.get(0).getScoreboardName() : list.size() + " players";
String pl = list.size() == 1 ? list.iterator().next().getUUID().toString() : list.size() + " entities";
ctx.getSource().sendSuccess(() -> Component.literal("Start profiling " + side + " of " + pl + " with time " + str), true);
return 1;
}

protected static <T> RequiredArgumentBuilder<CommandSourceStack, T> argument(String name, ArgumentType<T> type) {
return RequiredArgumentBuilder.argument(name, type);
}


}