diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..007bc54 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,32 @@ +name: "Build mod" +on: + push: + pull_request: + +jobs: + build: + strategy: + matrix: + java: [17] + os: [ubuntu-20.04] + runs-on: ${{ matrix.os }} + steps: + - name: checkout repository + uses: actions/checkout@v2 + - name: validate gradle wrapper + uses: gradle/wrapper-validation-action@v1 + - name: setup jdk ${{ matrix.java }} + uses: actions/setup-java@v2 + with: + distribution: adopt + java-version: ${{ matrix.java }} + - name: make gradle wrapper executable + if: ${{ runner.os != 'Windows' }} + run: chmod +x ./gradlew + - name: build + run: ./gradlew build + - name: capture build artifacts + uses: actions/upload-artifact@v2 + with: + name: Artifacts + path: build/libs/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd2d25a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +# gradle + +.gradle/ +build/ +out/ +classes/ + +# eclipse + +*.launch + +# idea + +.idea/ +*.iml +*.ipr +*.iws + +# vscode + +.settings/ +.vscode/ +bin/ +.classpath +.project + +# macos + +*.DS_Store + +# fabric + +run/ \ No newline at end of file diff --git a/README.md b/README.md index 9bd055b..4e2e630 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ -# 猎人游戏 Manhunt +# Manhunt A Minecraft Manhunt Mod for Fabric Server. (requires Fabric API) -# 如何使用 How 2 Use - On server is initialized, the hunters and runners teams will be automatically added, players can use command "/mh join " to join teams. - Hunters will have a tracker, left-click to select a runner, right-click to update the coordinates. - Furthermore, you can use command "/mh cure " to cure players, "/mh freezeAllHunters " to freeze hunters (if you are an admin). +## How to use + - In order to join teams you need to type `/mh join `. + - Hunters will get the compass. Left-click to select the runner and right-click to update the coordinates of the runner. - 服务器初始化后,会自动添加猎人和逃者队伍,玩家可以使用命令“/mh join ”加入队伍。 - 猎人会有一个追踪器,左键可以选择逃者,右键更新坐标。 - 另外,你还可以使用命令“/mh cure <玩家选择器>”来治愈玩家,“/mh freezeAllHunters <秒>”来冻结猎人(如果你是管理的话)。 +## Commands + - `/mh join ` allows you to join **hunters** or **runners** teams + - `/mh compassDelay ` changes compass usage delay. + - `/mh freeze ` freezes hunters for \ + - `/mh cure ` heals \ + - `/mh setColor ` sets the \ of the \ + - `/mh reload` reloads config file diff --git a/build.gradle b/build.gradle index a39c379..b502bb5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '0.10-SNAPSHOT' + id 'fabric-loom' version '1.0-SNAPSHOT' id 'maven-publish' } @@ -12,15 +12,33 @@ group = project.maven_group repositories { maven { url "https://maven.shedaniel.me/" } + maven { url "https://jitpack.io" } + maven { url 'https://maven.nucleoid.xyz/' } + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + content { + includeGroup "maven.modrinth" + } + } } dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - //Fabric api - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + //Server translations API + include(modImplementation("fr.catcore:server-translations-api:${project.server_translations_version}")) + //Carpet for fake players + modImplementation "com.github.gnembon:fabric-carpet:${project.carpet_version}" + //optimizations + modImplementation "maven.modrinth:lazydfu:0.1.3" + //modImplementation "maven.modrinth:starlight:1.1.1+1.19" + //modImplementation "maven.modrinth:lithium:mc1.19.2-0.8.3" + //modImplementation "maven.modrinth:ferrite-core:5.0.0-fabric" } processResources { diff --git a/gradle.properties b/gradle.properties index 75d887f..476a3d6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,13 +2,18 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties -minecraft_version=1.18.1 -yarn_mappings=1.18.1+build.18 -loader_version=0.12.12 - -fabric_version=0.46.0+1.18 +minecraft_version=1.19.2 +yarn_mappings=1.19.2+build.28 +loader_version=0.14.10 +fabric_version=0.64.0+1.19.2 # Mod Properties -mod_version = 1.0.2 +mod_version = 1.0.6 maven_group = cn.noryea archives_base_name = manhunt-fabric + +# External mods +# Permissions API +server_translations_version = 1.4.18+1.19.2 +# Carpet snapshot +carpet_version = 1.4.84 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 69a9715..2d2fd7c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/src/main/java/cn/noryea/manhunt/Manhunt.java b/src/main/java/cn/noryea/manhunt/Manhunt.java index fcde9ca..61d43cd 100644 --- a/src/main/java/cn/noryea/manhunt/Manhunt.java +++ b/src/main/java/cn/noryea/manhunt/Manhunt.java @@ -1,65 +1,65 @@ package cn.noryea.manhunt; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.minecraft.scoreboard.AbstractTeam; import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.Team; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.LiteralText; -import net.minecraft.util.Formatting; +import net.minecraft.text.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.LinkedList; import java.util.List; public class Manhunt implements ModInitializer { - public static List allPlayers; - public static List allRunners; - - public static final Formatting huntersColor = Formatting.RED; - public static final Formatting runnersColor = Formatting.GREEN; - - - @Override - public void onInitialize() { - - ServerTickEvents.START_WORLD_TICK.register((world) -> { - - //删除追踪器实体 - world.getServer().getCommandManager().execute(world.getServer().getCommandSource().withSilent(),"kill @e[type=item,nbt={Item:{tag:{Tracker:1b}}}]"); - - //创建队伍 - Scoreboard scoreboard = world.getServer().getScoreboard(); - if (scoreboard.getTeam("hunters") == null) { - Team team = scoreboard.addTeam("hunters"); - team.setDisplayName(new LiteralText("猎人")); - team.setColor(huntersColor); - } - - if (scoreboard.getTeam("runners") == null) { - Team team = scoreboard.addTeam("runners"); - team.setDisplayName(new LiteralText("逃者")); - team.setColor(runnersColor); - } - - //获取玩家列表 - allPlayers = world.getServer().getPlayerManager().getPlayerList(); - allRunners = new LinkedList<>(); - - Team runners = scoreboard.getTeam("runners"); - for (ServerPlayerEntity x : allPlayers) { - if (x != null) { - if (x.isTeamPlayer(runners)) { - allRunners.add(x); - } - } - } - - }); - - //命令注册 - CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> ManhuntCommand.registerCommands(dispatcher)); - - } + public static List allPlayers; + public static List allRunners; + + public static Logger LOGGER = LoggerFactory.getLogger("manhunt"); + + @Override + public void onInitialize() { + ManhuntConfig config = ManhuntConfig.INSTANCE; + config.load(); + ServerTickEvents.START_WORLD_TICK.register((world) -> { + world.getServer().getCommandManager().executeWithPrefix(world.getServer().getCommandSource().withSilent(), "kill @e[type=item,nbt={Item:{tag:{Tracker:1b}}}]"); + + Scoreboard scoreboard = world.getServer().getScoreboard(); + if (scoreboard.getTeam("hunters") == null) { + Team team = scoreboard.addTeam("hunters"); + team.setDisplayName(Text.translatable("manhunt.teams.hunters.name")); + team.setCollisionRule(AbstractTeam.CollisionRule.ALWAYS); + team.setShowFriendlyInvisibles(false); + } + scoreboard.getTeam("hunters").setColor(config.getHuntersColor()); + + if (scoreboard.getTeam("runners") == null) { + Team team = scoreboard.addTeam("runners"); + team.setDisplayName(Text.translatable("manhunt.teams.runners.name")); + team.setCollisionRule(AbstractTeam.CollisionRule.ALWAYS); + team.setShowFriendlyInvisibles(false); + } + scoreboard.getTeam("runners").setColor(config.getRunnersColor()); + + allPlayers = world.getServer().getPlayerManager().getPlayerList(); + allRunners = new LinkedList<>(); + + Team runners = scoreboard.getTeam("runners"); + for (ServerPlayerEntity x : allPlayers) { + if (x != null) { + if (x.isTeamPlayer(runners)) { + allRunners.add(x); + } + } + } + + }); + + CommandRegistrationCallback.EVENT.register(ManhuntCommand::registerCommands); + + } } diff --git a/src/main/java/cn/noryea/manhunt/ManhuntCommand.java b/src/main/java/cn/noryea/manhunt/ManhuntCommand.java index a351ec3..85046df 100644 --- a/src/main/java/cn/noryea/manhunt/ManhuntCommand.java +++ b/src/main/java/cn/noryea/manhunt/ManhuntCommand.java @@ -1,111 +1,137 @@ package cn.noryea.manhunt; import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.command.argument.ColorArgumentType; import net.minecraft.command.argument.EntityArgumentType; import net.minecraft.command.argument.TeamArgumentType; import net.minecraft.entity.Entity; -import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffects; -import net.minecraft.network.MessageType; -import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket; -import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.Team; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.LiteralText; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.Util; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import java.util.Collection; -import java.util.Iterator; public class ManhuntCommand { - public static void registerCommands(CommandDispatcher dispatcher) { - - dispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)(LiteralArgumentBuilder)((LiteralArgumentBuilder)CommandManager.literal("mh").requires((source) -> { - return source.hasPermissionLevel(0); - })).then(CommandManager.literal("join").then(CommandManager.argument("team", TeamArgumentType.team()).executes((context) -> { - return executeJoin((ServerCommandSource)context.getSource(), TeamArgumentType.getTeam(context, "team")); - })))).then(CommandManager.literal("cure").then(CommandManager.argument("targets", EntityArgumentType.players()).executes((context) -> { - return executeCure((ServerCommandSource)context.getSource(), EntityArgumentType.getPlayers(context, "targets")); - }))).then(CommandManager.literal("freezeAllHunters").then(CommandManager.argument("seconds", IntegerArgumentType.integer(1, 100)).executes((context) -> { - return executeFreeze((ServerCommandSource)context.getSource(), IntegerArgumentType.getInteger(context, "seconds")); - })))); + private static ManhuntConfig config = ManhuntConfig.INSTANCE; + + @SuppressWarnings("unused") + public static void registerCommands(CommandDispatcher dis, CommandRegistryAccess reg, CommandManager.RegistrationEnvironment env) { + + dis.register(CommandManager.literal("mh") + .then(CommandManager.literal("join") + .then(CommandManager.argument("team", TeamArgumentType.team()) + .executes((ctx) -> executeJoin(ctx.getSource(), TeamArgumentType.getTeam(ctx, "team"))))) + .then(CommandManager.literal("cure").requires((src) -> src.hasPermissionLevel(2)) + .then(CommandManager.argument("targets", EntityArgumentType.players()) + .executes((ctx) -> executeCure(ctx.getSource(), EntityArgumentType.getPlayers(ctx, "targets"))))) + .then(CommandManager.literal("freeze").requires((src) -> src.hasPermissionLevel(2)) + .then(CommandManager.argument("seconds", IntegerArgumentType.integer(1, 120)) + .executes((ctx) -> executeFreeze(ctx.getSource(), IntegerArgumentType.getInteger(ctx, "seconds"))))) + .then(CommandManager.literal("compassDelay").requires((src) -> src.hasPermissionLevel(2)) + .then(CommandManager.argument("seconds", IntegerArgumentType.integer(0, 120)) + .executes((ctx) -> executeCompassDelay(ctx.getSource(), IntegerArgumentType.getInteger(ctx, "seconds"))))) + .then(CommandManager.literal("runnersWinOnDragonDeath").requires((src) -> src.hasPermissionLevel(2)) + .then(CommandManager.argument("boolean", BoolArgumentType.bool()) + .executes((ctx) -> setRunnersWinOnDragonDeath(ctx.getSource(), BoolArgumentType.getBool(ctx, "boolean"))))) + .then(CommandManager.literal("setColor").requires((src) -> src.hasPermissionLevel(2)) + .then(CommandManager.argument("team", TeamArgumentType.team()) + .then(CommandManager.argument("color", ColorArgumentType.color()) + .executes((ctx) -> executeChangeTeamColor(ctx.getSource(), TeamArgumentType.getTeam(ctx, "team"), ColorArgumentType.getColor(ctx, "color")))))) + .then(CommandManager.literal("reload").requires((src) -> src.hasPermissionLevel(2)) + .executes((ctx) -> executeReload(ctx.getSource()))) + ); + } + + private static int executeJoin(ServerCommandSource source, Team team) { + Scoreboard scoreboard = source.getServer().getScoreboard(); + + scoreboard.addPlayerToTeam(source.getPlayer().getName().getString(), team); + source.sendFeedback(Text.translatable("commands.team.join.success.single", source.getPlayer().getName(), team.getFormattedName()), true); + + return 1; + } + + private static int executeCompassDelay(ServerCommandSource source, Integer delay) { + config.setDelay(delay); + source.sendFeedback(Text.translatable("manhunt.commands.delay", delay), true); + + return 1; + } + + private static int setRunnersWinOnDragonDeath(ServerCommandSource source, boolean bool) { + config.setRunnersWinOnDragonDeath(bool); + source.sendFeedback(Text.translatable("manhunt.commands.runnerswinset", bool), true); + + return 1; + } + + private static int executeCure(ServerCommandSource source, Collection targets) { + for (Entity target : targets) { + ServerPlayerEntity player = (ServerPlayerEntity) target; + + player.clearStatusEffects(); + player.setHealth(player.getMaxHealth()); + player.getHungerManager().setFoodLevel(20); + player.getHungerManager().setSaturationLevel(8.5F); } + source.sendFeedback(Text.translatable("manhunt.commands.cured", targets.size()), true); + return targets.size(); + } - private static int executeJoin(ServerCommandSource source, Team team) throws CommandSyntaxException { - Scoreboard scoreboard = source.getServer().getScoreboard(); + private static int executeFreeze(ServerCommandSource source, int time) throws CommandSyntaxException { + MinecraftServer server = source.getEntityOrThrow().getServer(); - scoreboard.addPlayerToTeam(source.getPlayer().getName().asString(), team); - source.sendFeedback(new TranslatableText("commands.team.join.success.single", source.getPlayer().getName(), team.getFormattedName()), true); + for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) { - return 1; - } - - private static int executeCure(ServerCommandSource source, Collection targets) { - if (source.hasPermissionLevel(2)) { - Iterator var3 = targets.iterator(); - - while (var3.hasNext()) { - ServerPlayerEntity player = (ServerPlayerEntity) var3.next(); + if (player.isTeamPlayer(server.getScoreboard().getTeam("hunters"))) { - player.clearStatusEffects(); - player.setHealth(player.getMaxHealth()); - player.getHungerManager().setFoodLevel(20); - player.getHungerManager().setSaturationLevel(8.5F); + player.clearStatusEffects(); + player.setHealth(player.getMaxHealth()); + player.getHungerManager().setFoodLevel(20); + player.getHungerManager().setSaturationLevel(8.5F); - } - source.sendFeedback(new LiteralText("已治愈" + targets.size() + "名玩家"), true); - return targets.size(); - - } else { - source.sendFeedback(new LiteralText("\u00a7c宁不配"), false); - return 0; - } + player.addStatusEffect(new StatusEffectInstance(StatusEffects.BLINDNESS, time * 20, 255, false, true)); + player.addStatusEffect(new StatusEffectInstance(StatusEffects.SLOWNESS, time * 20, 255, false, false)); + player.addStatusEffect(new StatusEffectInstance(StatusEffects.JUMP_BOOST, time * 20, 248, false, false)); + player.addStatusEffect(new StatusEffectInstance(StatusEffects.MINING_FATIGUE, (time - 1) * 20, 255, false, false)); + player.addStatusEffect(new StatusEffectInstance(StatusEffects.RESISTANCE, time * 20, 255, false, false)); + player.addStatusEffect(new StatusEffectInstance(StatusEffects.WEAKNESS, time * 20, 255, false, false)); + } } - private static int executeFreeze(ServerCommandSource source, int time) throws CommandSyntaxException { - if (source.hasPermissionLevel(2)) { - - MinecraftServer server = source.getEntityOrThrow().getServer(); - Iterator vec3 = server.getPlayerManager().getPlayerList().listIterator(); - - while (vec3.hasNext()) { + source.sendFeedback(Text.translatable("manhunt.commands.freeze", time), true); - ServerPlayerEntity player = vec3.next(); + return 1; + } - if (player.isTeamPlayer( server.getScoreboard().getTeam("hunters") )) { - - player.clearStatusEffects(); - player.setHealth(player.getMaxHealth()); - player.getHungerManager().setFoodLevel(20); - player.getHungerManager().setSaturationLevel(8.5F); - - player.addStatusEffect(new StatusEffectInstance(StatusEffects.BLINDNESS, time * 20, 255, false, true)); - player.addStatusEffect(new StatusEffectInstance(StatusEffects.SLOWNESS, time * 20, 255, false, false)); - player.addStatusEffect(new StatusEffectInstance(StatusEffects.JUMP_BOOST, time * 20, 248, false, false)); - player.addStatusEffect(new StatusEffectInstance(StatusEffects.MINING_FATIGUE, (time - 1) * 20, 255, false, false)); - player.addStatusEffect(new StatusEffectInstance(StatusEffects.RESISTANCE, time * 20, 255, false, false)); - player.addStatusEffect(new StatusEffectInstance(StatusEffects.WEAKNESS, time * 20, 255, false, false)); - - } - } - - source.sendFeedback(new LiteralText("\u00a7f猎人将在\u00a7b" + time + "\u00a7f秒内原地不动"), true); + private static int executeChangeTeamColor(ServerCommandSource source, Team team, Formatting color) { + if(team.getName().equals("hunters")) { config.setHuntersColor(color); } + else if(team.getName().equals("runners")) { config.setRunnersColor(color); } + else { + source.sendFeedback(Text.translatable("manhunt.commands.teamColor.badTeam", Text.translatable("manhunt.teams.hunters.name"), Text.translatable("manhunt.teams.runners.name")), true); + return -1; + } - return 1; + team.setColor(color); + source.sendFeedback(Text.translatable("manhunt.commands.teamColor.success", Text.translatable("manhunt.teams." + team.getName() + ".name"), color.getName()), true); + return 1; + } - } else { - source.sendFeedback(new LiteralText("\u00a7c宁不配"), false); - return 0; - } - } + private static int executeReload(ServerCommandSource source) { + config.load(); + source.sendFeedback(Text.translatable("manhunt.commands.reload"), true); + return 1; + } } diff --git a/src/main/java/cn/noryea/manhunt/ManhuntConfig.java b/src/main/java/cn/noryea/manhunt/ManhuntConfig.java new file mode 100644 index 0000000..9304971 --- /dev/null +++ b/src/main/java/cn/noryea/manhunt/ManhuntConfig.java @@ -0,0 +1,92 @@ +package cn.noryea.manhunt; + +import com.google.gson.*; +import net.minecraft.util.Formatting; + +import java.io.*; + +import static cn.noryea.manhunt.Manhunt.LOGGER; + +public class ManhuntConfig { + + private ManhuntConfig() { + } + + //Config instance. + public static final ManhuntConfig INSTANCE = new ManhuntConfig(); + private final File confFile = new File("./config/manhunt.json"); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + private Formatting huntersColor = Formatting.RED; + private Formatting runnersColor = Formatting.GREEN; + private int delay = 0; + private boolean runnersWinOnDragonDeath = true; + + //Getters + public Formatting getHuntersColor() { + return huntersColor; + } + public Formatting getRunnersColor() { + return runnersColor; + } + public int getDelay() { + return delay; + } + public boolean isRunnersWinOnDragonDeath() { + return runnersWinOnDragonDeath; + } + + //Setters + public void setHuntersColor(Formatting color) { + if(color == null) color = Formatting.WHITE; + huntersColor = color; + save(); + } + public void setRunnersColor(Formatting color) { + if(color == null) color = Formatting.WHITE; + runnersColor = color; + save(); + } + public void setDelay(int time) { + delay = time; + save(); + } + public void setRunnersWinOnDragonDeath(boolean bool) { + runnersWinOnDragonDeath = bool; + save(); + } + + public void load() { + if (!confFile.exists() || confFile.length() == 0) save(); + try { + JsonObject jo = gson.fromJson(new FileReader(confFile), JsonObject.class); + JsonElement je; + + if((je = jo.get("huntersColor")) != null) huntersColor = Formatting.byName(je.getAsString()); + if((je = jo.get("runnersColor")) != null) runnersColor = Formatting.byName(je.getAsString()); + if((je = jo.get("compassDelay")) != null) delay = je.getAsInt(); + if((je = jo.get("runnersWinOnDragonDeath")) != null) runnersWinOnDragonDeath = je.getAsBoolean(); + } catch (FileNotFoundException ex) { + LOGGER.trace("Couldn't load configuration file", ex); + } + } + + public void save() { + try { + if (!confFile.exists()) { confFile.getParentFile().mkdirs(); confFile.createNewFile(); } + + JsonObject jo = new JsonObject(); + jo.add("_ColorsList", new JsonPrimitive(String.join(", ", Formatting.getNames(true, false)))); + jo.add("huntersColor", new JsonPrimitive(huntersColor.getName())); + jo.add("runnersColor", new JsonPrimitive(runnersColor.getName())); + jo.add("compassDelay", new JsonPrimitive(delay)); + jo.add("runnersWinOnDragonDeath", new JsonPrimitive(runnersWinOnDragonDeath)); + + PrintWriter printwriter = new PrintWriter(new FileWriter(confFile)); + printwriter.print(gson.toJson(jo)); + printwriter.close(); + } catch (IOException ex) { + LOGGER.trace("Couldn't save configuration file", ex); + } + } +} diff --git a/src/main/java/cn/noryea/manhunt/Utils.java b/src/main/java/cn/noryea/manhunt/Utils.java new file mode 100644 index 0000000..af94104 --- /dev/null +++ b/src/main/java/cn/noryea/manhunt/Utils.java @@ -0,0 +1,4 @@ +package cn.noryea.manhunt; + +public class Utils { +} diff --git a/src/main/java/cn/noryea/manhunt/mixin/CompassItemMixin.java b/src/main/java/cn/noryea/manhunt/mixin/CompassItemMixin.java index 3a1ca31..f4b698b 100644 --- a/src/main/java/cn/noryea/manhunt/mixin/CompassItemMixin.java +++ b/src/main/java/cn/noryea/manhunt/mixin/CompassItemMixin.java @@ -11,12 +11,12 @@ @Mixin(CompassItem.class) public abstract class CompassItemMixin extends Item { - public CompassItemMixin(Settings settings) { - super(settings); - } + public CompassItemMixin(Settings settings) { + super(settings); + } - public boolean canMine(BlockState state, World world, BlockPos pos, PlayerEntity miner) { - return !(miner.getMainHandStack().getOrCreateNbt().getBoolean("Tracker") && miner.isCreative()); - } + public boolean canMine(BlockState state, World world, BlockPos pos, PlayerEntity miner) { + return !(miner.getMainHandStack().getOrCreateNbt().getBoolean("Tracker") && miner.isCreative()); + } } diff --git a/src/main/java/cn/noryea/manhunt/mixin/EnderDragonEntityMixin.java b/src/main/java/cn/noryea/manhunt/mixin/EnderDragonEntityMixin.java new file mode 100644 index 0000000..79aa762 --- /dev/null +++ b/src/main/java/cn/noryea/manhunt/mixin/EnderDragonEntityMixin.java @@ -0,0 +1,24 @@ +package cn.noryea.manhunt.mixin; + +import cn.noryea.manhunt.ManhuntConfig; +import net.minecraft.entity.boss.dragon.EnderDragonEntity; +import net.minecraft.server.MinecraftServer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(EnderDragonEntity.class) +public class EnderDragonEntityMixin { + + //End the game when runners kill the enderdragon + @Inject(method = "updatePostDeath", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/GameRules;getBoolean(Lnet/minecraft/world/GameRules$Key;)Z")) + private void runnersWon(CallbackInfo ci) { + EnderDragonEntity dragon = ((EnderDragonEntity)(Object) this); + MinecraftServer server = dragon.getServer(); + if(ManhuntConfig.INSTANCE.isRunnersWinOnDragonDeath() && !server.getScoreboard().getTeam("runners").getPlayerList().isEmpty() && dragon.ticksSinceDeath == 1) { + server.getCommandManager().executeWithPrefix(server.getCommandSource().withSilent().withLevel(2), "title @a subtitle {\"translate\":\"manhunt.win.runners.subtitle\",\"color\":\"white\"}"); + server.getCommandManager().executeWithPrefix(server.getCommandSource().withSilent().withLevel(2), "title @a title {\"translate\":\"manhunt.win.runners.title\",\"color\":\"white\"}"); + } + } +} diff --git a/src/main/java/cn/noryea/manhunt/mixin/PlayerEntityMixin.java b/src/main/java/cn/noryea/manhunt/mixin/PlayerEntityMixin.java index d946e48..dce8b67 100644 --- a/src/main/java/cn/noryea/manhunt/mixin/PlayerEntityMixin.java +++ b/src/main/java/cn/noryea/manhunt/mixin/PlayerEntityMixin.java @@ -6,7 +6,8 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.*; import net.minecraft.world.World; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -17,40 +18,40 @@ @Mixin(PlayerEntity.class) public abstract class PlayerEntityMixin extends LivingEntity { - NbtList positions = new NbtList(); - - protected PlayerEntityMixin(EntityType entityType, World world) { - super(entityType, world); - } - - @Inject(method = "tick", at = @At("HEAD")) - public void tick(CallbackInfo ci) { - //同步坐标 - DataResult var10000 = World.CODEC.encodeStart(NbtOps.INSTANCE, world.getRegistryKey()); - Logger logger = LOGGER; - Objects.requireNonNull(logger); - var10000.resultOrPartial(logger::error).ifPresent((dimension) -> { - for(int i = 0; i < positions.size(); ++i) { - NbtCompound compound = positions.getCompound(i); - if (Objects.equals(compound.getString("LodestoneDimension"), dimension.asString())) { - positions.remove(compound); - } - } - NbtCompound nbtCompound = new NbtCompound(); - nbtCompound.put("LodestonePos", NbtHelper.fromBlockPos(this.getBlockPos())); - nbtCompound.put("LodestoneDimension", dimension); - positions.add(nbtCompound); - }); - } - - @Inject(method = "writeCustomDataToNbt", at = @At("RETURN")) - public void writeCustomDataToNbt(NbtCompound nbt, CallbackInfo cbi) { - nbt.putBoolean("manhuntModded", true); - nbt.put("Positions", positions); - } - - @Inject(method = "readCustomDataFromNbt", at = @At("RETURN")) - public void readCustomDataFromNbt(NbtCompound nbt, CallbackInfo cbi) { - this.positions = nbt.getList("Positions", 10); - } + NbtList positions = new NbtList(); + + protected PlayerEntityMixin(EntityType entityType, World world) { + super(entityType, world); + } + + @Inject(method = "tick", at = @At("HEAD")) + public void tick(CallbackInfo ci) { + + DataResult var10000 = World.CODEC.encodeStart(NbtOps.INSTANCE, world.getRegistryKey()); + Logger logger = LoggerFactory.getLogger("Manhunt"); + Objects.requireNonNull(logger); + var10000.resultOrPartial(logger::error).ifPresent((dimension) -> { + for (int i = 0; i < positions.size(); ++i) { + NbtCompound compound = positions.getCompound(i); + if (Objects.equals(compound.getString("LodestoneDimension"), dimension.asString())) { + positions.remove(compound); + } + } + NbtCompound nbtCompound = new NbtCompound(); + nbtCompound.put("LodestonePos", NbtHelper.fromBlockPos(this.getBlockPos())); + nbtCompound.put("LodestoneDimension", dimension); + positions.add(nbtCompound); + }); + } + + @Inject(method = "writeCustomDataToNbt", at = @At("RETURN")) + public void writeCustomDataToNbt(NbtCompound nbt, CallbackInfo cbi) { + nbt.putBoolean("manhuntModded", true); + nbt.put("Positions", positions); + } + + @Inject(method = "readCustomDataFromNbt", at = @At("RETURN")) + public void readCustomDataFromNbt(NbtCompound nbt, CallbackInfo cbi) { + this.positions = nbt.getList("Positions", 10); + } } diff --git a/src/main/java/cn/noryea/manhunt/mixin/ServerPlayerEntityMixin.java b/src/main/java/cn/noryea/manhunt/mixin/ServerPlayerEntityMixin.java index dc79af8..6566383 100644 --- a/src/main/java/cn/noryea/manhunt/mixin/ServerPlayerEntityMixin.java +++ b/src/main/java/cn/noryea/manhunt/mixin/ServerPlayerEntityMixin.java @@ -7,6 +7,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.encryption.PlayerPublicKey; import net.minecraft.network.packet.s2c.play.OverlayMessageS2CPacket; import net.minecraft.scoreboard.Scoreboard; import net.minecraft.server.MinecraftServer; @@ -16,6 +17,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.GameMode; import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -27,83 +29,128 @@ @Mixin(ServerPlayerEntity.class) public abstract class ServerPlayerEntityMixin extends PlayerEntity { - @Shadow public MinecraftServer server; - @Shadow public ServerPlayNetworkHandler networkHandler; + @Final + @Shadow + public MinecraftServer server; + @Shadow + public ServerPlayNetworkHandler networkHandler; + + @Shadow + public abstract boolean changeGameMode(GameMode gameMode); + + boolean holding; + + public ServerPlayerEntityMixin(World world, BlockPos pos, float yaw, GameProfile profile, PlayerPublicKey key) { + super(world, pos, yaw, profile, key); + } + + @Inject(method = "tick", at = @At("HEAD")) + public void tick(CallbackInfo ci) { + if (this.isTeamPlayer(server.getScoreboard().getTeam("hunters")) && this.isAlive()) { + if (!hasTracker()) { + NbtCompound nbt = new NbtCompound(); + nbt.putBoolean("Tracker", true); + nbt.putBoolean("LodestoneTracked", false); + nbt.putString("LodestoneDimension", "minecraft:overworld"); + nbt.putInt("HideFlags", 1); + nbt.put("Info", new NbtCompound()); + nbt.put("display", new NbtCompound()); + nbt.getCompound("display").putString("Name", "{\"translate\": \"manhunt.item.tracker\",\"italic\": false,\"color\": \"white\"}"); + + ItemStack stack = new ItemStack(Items.COMPASS); + stack.setNbt(nbt); + stack.addEnchantment(Enchantments.VANISHING_CURSE, 1); + + this.giveItemStack(stack); + } + + + if (holdingTracker()) { + holding = true; + if (this.getMainHandStack().getNbt() != null && this.getMainHandStack().getNbt().getBoolean("Tracker")) { + NbtCompound info = this.getMainHandStack().getNbt().getCompound("Info"); + if (server.getPlayerManager().getPlayer(info.getString("Name")) != null) { + showInfo(info); + } + } else if (this.getOffHandStack().getNbt() != null) { + NbtCompound info = this.getOffHandStack().getNbt().getCompound("Info"); + if (server.getPlayerManager().getPlayer(info.getString("Name")) != null) { + showInfo(info); + } + } + } else { + if (holding) { + this.networkHandler.sendPacket(new OverlayMessageS2CPacket(Text.of(""))); + holding = false; + } + } - @Shadow - public abstract boolean changeGameMode(GameMode gameMode); + } + } - boolean holding; + @Inject(method = "onDeath", at = @At("HEAD")) + public void onDeath(DamageSource source, CallbackInfo ci) { + Scoreboard scoreboard = server.getScoreboard(); - public ServerPlayerEntityMixin(World world, BlockPos pos, float yaw, GameProfile profile) { - super(world, pos, yaw, profile); - } + if (this.getScoreboardTeam() != null) { + if (this.getScoreboardTeam().isEqual(scoreboard.getTeam("runners"))) { - @Inject(method = "tick", at = @At("HEAD")) - public void tick(CallbackInfo ci) { - //猎人追踪器功能 - if (this.isTeamPlayer(server.getScoreboard().getTeam("hunters")) && this.isAlive()) { - if (!hasTracker()) { - NbtCompound nbt = new NbtCompound(); - nbt.putBoolean("Tracker", true); - nbt.putBoolean("LodestoneTracked", false); - nbt.putString("LodestoneDimension", "minecraft:overworld"); - nbt.putInt("HideFlags", 1); - nbt.put("Info", new NbtCompound()); - nbt.put("display", new NbtCompound()); - nbt.getCompound("display").putString("Name", "{\"text\": \"追踪器\",\"italic\": false,\"color\": \"white\"}"); - - ItemStack stack = new ItemStack(Items.COMPASS); - stack.setNbt(nbt); - stack.addEnchantment(Enchantments.VANISHING_CURSE, 1); - - this.giveItemStack(stack); //给予 - } - - //显示信息 - if (holdingTracker()) { - holding = true; - if (this.getMainHandStack().getNbt() != null && this.getMainHandStack().getNbt().getBoolean("Tracker")) { - NbtCompound info = this.getMainHandStack().getNbt().getCompound("Info"); - if (server.getPlayerManager().getPlayer(info.getString("Name")) != null) { - showInfo(info); - } - } else if (this.getOffHandStack().getNbt() != null) { - NbtCompound info = this.getOffHandStack().getNbt().getCompound("Info"); - if (server.getPlayerManager().getPlayer(info.getString("Name")) != null) { - showInfo(info); - } - } - } else { - if (holding) { - this.networkHandler.sendPacket(new OverlayMessageS2CPacket(new LiteralText(""))); - holding = false; - } - } + changeGameMode(GameMode.SPECTATOR); + scoreboard.clearPlayerTeam(this.getName().getString()); + if (server.getScoreboard().getTeam("runners").getPlayerList().isEmpty()) { + server.getCommandManager().executeWithPrefix(this.getCommandSource().withSilent().withLevel(2), "title @a subtitle {\"translate\":\"manhunt.win.hunters.subtitle\",\"color\":\"white\"}"); + server.getCommandManager().executeWithPrefix(this.getCommandSource().withSilent().withLevel(2), "title @a title {\"translate\":\"manhunt.win.hunters.title\",\"color\":\"white\"}"); } + } + } + } + + private void showInfo(NbtCompound info) { + String dim = info.getString("Dimension"); + MutableText dimension = Text.literal(dim); + if (!info.contains("Dimension")) { + dimension = Text.translatable("manhunt.scoreboard.world.unknown"); + } else if (Objects.equals(dim, "minecraft:overworld")) { + dimension = Text.translatable("manhunt.scoreboard.world.overworld"); + } else if (Objects.equals(dim, "minecraft:the_nether")) { + dimension = Text.translatable("manhunt.scoreboard.world.the_nether"); + } else if (Objects.equals(dim, "minecraft:the_end")) { + dimension = Text.translatable("manhunt.scoreboard.world.the_end"); } - //逃者死亡事件 - @Inject(method = "onDeath", at = @At("HEAD")) - public void onDeath(DamageSource source, CallbackInfo ci) { - Scoreboard scoreboard = server.getScoreboard(); + this.networkHandler.sendPacket(new OverlayMessageS2CPacket(Text.translatable("manhunt.scoreboard.target.text", info.getString("Name"), dimension))); + } + + private boolean hasTracker() { + boolean n = false; + for (ItemStack item : this.getInventory().main) { + if (item.getItem().equals(Items.COMPASS) && item.getNbt() != null && item.getNbt().getBoolean("Tracker")) { + n = true; + break; + } + } - if (this.getScoreboardTeam() != null) { - if (this.getScoreboardTeam().isEqual(scoreboard.getTeam("runners"))) { + if (this.playerScreenHandler.getCursorStack().getNbt() != null && this.playerScreenHandler.getCursorStack().getNbt().getBoolean("Tracker")) { + n = true; + } else if (this.getOffHandStack().getNbt() != null && this.getOffHandStack().getNbt().getBoolean("Tracker")) { + n = true; + } - changeGameMode(GameMode.SPECTATOR); - scoreboard.clearPlayerTeam(this.getName().asString()); + return n; + } - if (server.getScoreboard().getTeam("runners").getPlayerList().isEmpty()) { - server.getCommandManager().execute(this.getCommandSource().withSilent().withLevel(2), "title @a subtitle {\"text\":\"所有逃者已阵亡\",\"color\":\"white\"}"); - server.getCommandManager().execute(this.getCommandSource().withSilent().withLevel(2), "title @a title {\"text\":\"猎人胜利!\",\"color\":\"red\"}"); - } - } - } + private boolean holdingTracker() { + boolean n = false; + if (this.getMainHandStack().getNbt() != null && this.getMainHandStack().getNbt().getBoolean("Tracker") && this.getMainHandStack().getNbt().getCompound("Info").contains("Name")) { + n = true; + } else if (this.getOffHandStack().getNbt() != null && this.getOffHandStack().getNbt().getBoolean("Tracker") && this.getOffHandStack().getNbt().getCompound("Info").contains("Name")) { + n = true; } + return n; + } - //玩家列表的名字 +// 玩家列表的名字 // @Inject(method = "getPlayerListName", at = @At("TAIL"), cancellable = true) // private void replacePlayerListName(CallbackInfoReturnable cir) { // try { @@ -129,57 +176,4 @@ public void onDeath(DamageSource source, CallbackInfo ci) { // e.printStackTrace(); // } // } - - private void showInfo(NbtCompound info) { - String text_color = "\u00a7a"; - - String actionbar = "目标: "; - actionbar += text_color + info.getString("Name"); - actionbar += " \u00a7f"; - actionbar += " 维度: "; - - String dimension = info.getString("Dimension"); - if (!info.contains("Dimension")) { - dimension = "\u00a7e?"; - } else if (Objects.equals(dimension, "minecraft:overworld")) { - dimension = "主世界"; - } else if (Objects.equals(dimension, "minecraft:the_nether")) { - dimension = "下界"; - } else if (Objects.equals(dimension, "minecraft:the_end")) { - dimension = "末地"; - } - - actionbar += text_color + dimension; - - this.networkHandler.sendPacket(new OverlayMessageS2CPacket(new LiteralText(actionbar))); - } - - private boolean hasTracker() { - boolean n = false; - for (ItemStack item : this.getInventory().main) { - if (item.getItem().equals(Items.COMPASS) && item.getNbt() != null && item.getNbt().getBoolean("Tracker")) { - n = true; - break; - } - } - - if (this.playerScreenHandler.getCursorStack().getNbt() != null && this.playerScreenHandler.getCursorStack().getNbt().getBoolean("Tracker")) { - n = true; - } else if (this.getOffHandStack().getNbt() != null && this.getOffHandStack().getNbt().getBoolean("Tracker")) { - n = true; - } - - return n; - } - - private boolean holdingTracker() { - boolean n = false; - if (this.getMainHandStack().getNbt() != null && this.getMainHandStack().getNbt().getBoolean("Tracker") && this.getMainHandStack().getNbt().getCompound("Info").contains("Name")) { - n = true; - } else if (this.getOffHandStack().getNbt() != null && this.getOffHandStack().getNbt().getBoolean("Tracker") && this.getOffHandStack().getNbt().getCompound("Info").contains("Name")) { - n = true; - } - return n; - } - } diff --git a/src/main/java/cn/noryea/manhunt/mixin/ServerPlayerInteractionManagerMixin.java b/src/main/java/cn/noryea/manhunt/mixin/ServerPlayerInteractionManagerMixin.java index 75c70e2..9f5d75e 100644 --- a/src/main/java/cn/noryea/manhunt/mixin/ServerPlayerInteractionManagerMixin.java +++ b/src/main/java/cn/noryea/manhunt/mixin/ServerPlayerInteractionManagerMixin.java @@ -1,25 +1,25 @@ package cn.noryea.manhunt.mixin; import cn.noryea.manhunt.Manhunt; +import cn.noryea.manhunt.ManhuntConfig; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtList; -import net.minecraft.network.MessageType; import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerInteractionManager; import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvents; -import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; -import net.minecraft.util.Util; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -31,106 +31,109 @@ @Mixin(ServerPlayerInteractionManager.class) public abstract class ServerPlayerInteractionManagerMixin { - @Shadow - protected ServerPlayerEntity player; - - - @Inject(method = "processBlockBreakingAction", at = @At("HEAD"), cancellable = true) - public void processBlockBreakingAction(BlockPos pos, PlayerActionC2SPacket.Action action, Direction direction, int worldHeight, CallbackInfo ci) { - if (action.equals(PlayerActionC2SPacket.Action.ABORT_DESTROY_BLOCK)) { - cycleTrackedPlayer(this.player, this.player.getMainHandStack().getNbt()); - } - } - - @Inject(method = "tryBreakBlock", at = @At("HEAD"), cancellable = true) - public void tryBreakBlock(BlockPos pos, CallbackInfoReturnable ci) { - cycleTrackedPlayer(this.player, this.player.getMainHandStack().getNbt()); - } - - @Inject(method = "interactItem(Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/world/World;Lnet/minecraft/item/ItemStack;Lnet/minecraft/util/Hand;)Lnet/minecraft/util/ActionResult;", at = @At("HEAD"), cancellable = true) - public void interactItem(ServerPlayerEntity player, World world, ItemStack stack, Hand hand, CallbackInfoReturnable cbi) { - if(stack.getNbt() != null && stack.getNbt().getBoolean("Tracker") && !player.isSpectator() && player.isTeamPlayer(world.getScoreboard().getTeam("hunters"))) { - if (!stack.getOrCreateNbt().contains("Info")) { - stack.getOrCreateNbt().put("Info",new NbtCompound()); - } - NbtCompound info = stack.getOrCreateNbt().getCompound("Info"); - - if (!info.contains("Name", NbtElement.STRING_TYPE) && !Manhunt.allRunners.isEmpty()) { - info.putString("Name", Manhunt.allRunners.get(0).getName().asString()); - } - - ServerPlayerEntity trackedPlayer = world.getServer().getPlayerManager().getPlayer(info.getString("Name")); - - if (trackedPlayer != null) { - player.networkHandler.sendPacket(new PlaySoundS2CPacket(SoundEvents.UI_BUTTON_CLICK, SoundCategory.PLAYERS, player.getX(), player.getY(), player.getZ(), 0.85f ,0.95f)); - updateCompass(player, stack.getOrCreateNbt(), trackedPlayer); - } - } - } - - //循环选择目标 - private void cycleTrackedPlayer(ServerPlayerEntity player, @Nullable NbtCompound stackNbt) { - if (stackNbt != null && stackNbt.getBoolean("Tracker") && player.isTeamPlayer(player.getServer().getScoreboard().getTeam("hunters"))) { - if (!stackNbt.contains("Info")) { - stackNbt.put("Info",new NbtCompound()); - } - - int next; - int previous = -1; - NbtCompound info = stackNbt.getCompound("Info"); - - if (Manhunt.allRunners.isEmpty()) { player.sendMessage(new LiteralText("\u00a7c目标队伍成员为空"), MessageType.GAME_INFO, Util.NIL_UUID); } - else { - //旧的目标序号 - for (int i = 0; i < Manhunt.allRunners.size(); i++) { - ServerPlayerEntity x = Manhunt.allRunners.get(i); - if (x != null) { - if (Objects.equals(x.getName().asString(), info.getString("Name"))) { - previous = i; - } - } - } - - //切换目标 - if (previous + 1 >= Manhunt.allRunners.size()) { - next = 0; - } else { - next = previous + 1; - } - - if (previous != next) { - updateCompass(player, stackNbt, Manhunt.allRunners.get(next)); - player.sendMessage(new LiteralText("\u00a7a目标切换至: " + Manhunt.allRunners.get(next).getName().asString()), MessageType.CHAT, Util.NIL_UUID); - } - - } - - } - } - - //更新指南针 - private void updateCompass(ServerPlayerEntity player, NbtCompound nbt, ServerPlayerEntity trackedPlayer) { - nbt.remove("LodestonePos"); - nbt.remove("LodestoneDimension"); - nbt.put("Info", new NbtCompound()); - - if (Objects.equals(Objects.requireNonNull(trackedPlayer.getScoreboardTeam()).getName(), "runners")) { - NbtCompound playerTag = trackedPlayer.writeNbt(new NbtCompound()); - NbtList positions = playerTag.getList("Positions", 10); - int i; - for (i = 0; i < positions.size(); ++i) { - NbtCompound compound = positions.getCompound(i); - if (Objects.equals(compound.getString("LodestoneDimension"), player.writeNbt(new NbtCompound()).getString("Dimension"))) { - nbt.copyFrom(compound); - break; - } - } - - NbtCompound info = nbt.getCompound("Info"); - info.putLong("LastUpdateTime", player.getWorld().getTime()); - info.putString("Name", trackedPlayer.getEntityName()); - info.putString("Dimension", playerTag.getString("Dimension")); - } - - } + + private ManhuntConfig config = ManhuntConfig.INSTANCE; + + @Final + @Shadow + protected ServerPlayerEntity player; + + @Inject(method = "processBlockBreakingAction", at = @At("HEAD")) + public void processBlockBreakingAction(BlockPos pos, PlayerActionC2SPacket.Action action, Direction direction, int worldHeight, int sequence, CallbackInfo ci) { + if (action.equals(PlayerActionC2SPacket.Action.ABORT_DESTROY_BLOCK)) { + cycleTrackedPlayer(this.player, this.player.getMainHandStack().getNbt()); + } + } + + @Inject(method = "tryBreakBlock", at = @At("HEAD")) + public void tryBreakBlock(BlockPos pos, CallbackInfoReturnable ci) { + cycleTrackedPlayer(this.player, this.player.getMainHandStack().getNbt()); + } + + @Inject( + method = "interactItem", + at = @At( + target = "Lnet/minecraft/item/ItemStack;use(Lnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/Hand;)Lnet/minecraft/util/TypedActionResult;", + value = "INVOKE" + )) + public void interactItem(ServerPlayerEntity player, World world, ItemStack stack, Hand hand, CallbackInfoReturnable cbi) { + if (stack.getNbt() != null && stack.getNbt().getBoolean("Tracker") && !player.isSpectator() && player.isTeamPlayer(world.getScoreboard().getTeam("hunters"))) { + player.getItemCooldownManager().set(stack.getItem(), config.getDelay() * 20); + if (!stack.getOrCreateNbt().contains("Info")) { + stack.getOrCreateNbt().put("Info", new NbtCompound()); + } + NbtCompound info = stack.getOrCreateNbt().getCompound("Info"); + + if (!info.contains("Name", NbtElement.STRING_TYPE) && !Manhunt.allRunners.isEmpty()) { + info.putString("Name", Manhunt.allRunners.get(0).getName().getString()); + } + + ServerPlayerEntity trackedPlayer = world.getServer().getPlayerManager().getPlayer(info.getString("Name")); + + if (trackedPlayer != null) { + player.networkHandler.sendPacket(new PlaySoundS2CPacket(SoundEvents.UI_BUTTON_CLICK, SoundCategory.PLAYERS, player.getX(), player.getY(), player.getZ(), 0.85f, 0.95f, 0)); + updateCompass(player, stack.getOrCreateNbt(), trackedPlayer); + } + } + } + + private void cycleTrackedPlayer(ServerPlayerEntity player, @Nullable NbtCompound stackNbt) { + if (stackNbt != null && stackNbt.getBoolean("Tracker") && player.isTeamPlayer(player.getServer().getScoreboard().getTeam("hunters"))) { + if (!stackNbt.contains("Info")) { + stackNbt.put("Info", new NbtCompound()); + } + + int next; + int previous = -1; + NbtCompound info = stackNbt.getCompound("Info"); + + if (Manhunt.allRunners.isEmpty()) player.sendMessage(Text.translatable("manhunt.item.tracker.noRunners")); + else { + for (int i = 0; i < Manhunt.allRunners.size(); i++) { + ServerPlayerEntity x = Manhunt.allRunners.get(i); + if (x != null) { + if (Objects.equals(x.getName().getString(), info.getString("Name"))) { + previous = i; + } + } + } + + if (previous + 1 >= Manhunt.allRunners.size()) { + next = 0; + } else { + next = previous + 1; + } + + if (previous != next) { + updateCompass(player, stackNbt, Manhunt.allRunners.get(next)); + player.sendMessage(Text.translatable("manhunt.item.tracker.switchRunner", Manhunt.allRunners.get(next).getName().getString())); + } + } + } + } + + private void updateCompass(ServerPlayerEntity player, NbtCompound nbt, ServerPlayerEntity trackedPlayer) { + nbt.remove("LodestonePos"); + nbt.remove("LodestoneDimension"); + + nbt.put("Info", new NbtCompound()); + if (trackedPlayer.getScoreboardTeam() != null && Objects.equals(trackedPlayer.getScoreboardTeam().getName(), "runners")) { + NbtCompound playerTag = trackedPlayer.writeNbt(new NbtCompound()); + NbtList positions = playerTag.getList("Positions", 10); + int i; + for (i = 0; i < positions.size(); ++i) { + NbtCompound compound = positions.getCompound(i); + if (Objects.equals(compound.getString("LodestoneDimension"), player.writeNbt(new NbtCompound()).getString("Dimension"))) { + nbt.copyFrom(compound); + break; + } + } + + NbtCompound info = nbt.getCompound("Info"); + info.putLong("LastUpdateTime", player.getWorld().getTime()); + info.putString("Name", trackedPlayer.getEntityName()); + info.putString("Dimension", playerTag.getString("Dimension")); + } + + } } diff --git a/src/main/resources/data/manhunt/lang/en_us.json b/src/main/resources/data/manhunt/lang/en_us.json new file mode 100644 index 0000000..361a9ce --- /dev/null +++ b/src/main/resources/data/manhunt/lang/en_us.json @@ -0,0 +1,23 @@ +{ + "manhunt.item.tracker": "§dTracker", + "manhunt.item.tracker.switchRunner": "§7Compass is now pointing to §f%s", + "manhunt.item.tracker.noRunners": "§cThere is no runners", + "manhunt.commands.delay": "§7Set delay to: §f%d §7seconds", + "manhunt.commands.runnerswinset": "§7Set runnersWinOnDragonDeath to: §f%s", + "manhunt.commands.cured": "§7Cured §f%d §7targets", + "manhunt.commands.freeze": "§7Hunters will be frozen for §f%d§7 seconds", + "manhunt.commands.teamColor.badTeam": "§cYou can only change colors of §f%1$s §cand §f%2$s §cteams", + "manhunt.commands.teamColor.success": "§7Changed color of §f%1$s §7team to §f%2$s", + "manhunt.commands.reload": "§7Succesfully reloaded configuration file", + "manhunt.teams.hunters.name": "§cHunters", + "manhunt.teams.runners.name": "§aRunners", + "manhunt.win.hunters.title": "§cHunters won!", + "manhunt.win.hunters.subtitle": "§7Runner(s) got killed", + "manhunt.win.runners.title": "§cRunners won!", + "manhunt.win.runners.subtitle": "§7Dragon was killed", + "manhunt.scoreboard.target.text": "§7Target: §f%1$s§f, §7Dimension: %2$s", + "manhunt.scoreboard.world.overworld": "§2Overworld", + "manhunt.scoreboard.world.the_nether": "§4The Nether", + "manhunt.scoreboard.world.the_end": "§dThe End", + "manhunt.scoreboard.world.unknown": "§6Unknown" +} \ No newline at end of file diff --git a/src/main/resources/data/manhunt/lang/ru_ru.json b/src/main/resources/data/manhunt/lang/ru_ru.json new file mode 100644 index 0000000..58d17ab --- /dev/null +++ b/src/main/resources/data/manhunt/lang/ru_ru.json @@ -0,0 +1,23 @@ +{ + "manhunt.item.tracker": "§dТрекер", + "manhunt.item.tracker.switchRunner": "§7Компас теперь указывает на §f%s", + "manhunt.item.tracker.noRunners": "§cКоманда бегунов пуста", + "manhunt.commands.delay": "§7Задержка установлена на: %d секунд", + "manhunt.commands.runnerswinset": "§7runnersWinOnDragonDeath теперь §f%s", + "manhunt.commands.cured": "§f%d §7игроков вылечено", + "manhunt.commands.freeze": "§7Охотники будут заморожены на §f%d§7 секунд", + "manhunt.commands.teamColor.badTeam": "§cВы можете менять цвет только у команд §f%1$s §cи §f%2$s", + "manhunt.commands.teamColor.success": "§7Сменили цвет команды \"§f%1$s§7\" на §f%2$s", + "manhunt.commands.reload": "§7Файл конфигурации успешно перезагружен", + "manhunt.teams.hunters.name": "§cОхотники", + "manhunt.teams.runners.name": "§aБегуны", + "manhunt.win.hunters.title": "§cОхотники победили!", + "manhunt.win.hunters.subtitle": "§7Бегун(ы) были убиты", + "manhunt.win.runners.title": "§cБегун(ы) победили!", + "manhunt.win.runners.subtitle": "§7Дракон был убит", + "manhunt.scoreboard.target.text": "§7Цель: §f%1$s, §7Мир: %2$s", + "manhunt.scoreboard.world.overworld": "§2Верхний мир", + "manhunt.scoreboard.world.the_nether": "§4Нижний мир", + "manhunt.scoreboard.world.the_end": "§dКрай", + "manhunt.scoreboard.world.unknown": "§6Неизвестно" +} \ No newline at end of file diff --git a/src/main/resources/data/manhunt/lang/zh_cn.json b/src/main/resources/data/manhunt/lang/zh_cn.json new file mode 100644 index 0000000..75aff31 --- /dev/null +++ b/src/main/resources/data/manhunt/lang/zh_cn.json @@ -0,0 +1,23 @@ +{ + "manhunt.item.tracker": "§d追踪器", + "manhunt.item.tracker.switchRunner": "§7目标切换至§f%s", + "manhunt.item.tracker.noRunners": "§c目标队伍成员为空", + "manhunt.commands.delay": "§7Set delay to: §f%d §7seconds", + "manhunt.commands.runnerswinset": "§7Set runnersWinOnDragonDeath to: §f%s", + "manhunt.commands.cured": "§7已治愈 §f%d §7名玩家", + "manhunt.commands.freeze": "§7猎人将在 §f%d§7 秒内原地不动", + "manhunt.commands.teamColor.badTeam": "§cYou can only change colors of §f%1$s §cand §f%2$s §cteams", + "manhunt.commands.teamColor.success": "§7Changed color of §f%1$s §7team to §f%2$s", + "manhunt.commands.reload": "§7Succesfully reloaded configuration file", + "manhunt.teams.hunters.name": "§c猎人", + "manhunt.teams.runners.name": "§a逃者", + "manhunt.win.hunters.title": "§c猎人胜利!", + "manhunt.win.hunters.subtitle": "§7所有逃者已阵亡", + "manhunt.win.runners.title": "§c逃者胜利!", + "manhunt.win.runners.subtitle": "§7龙被杀了", + "manhunt.scoreboard.target.text": "§7目标: §f%1$s§f, §7维度: %2$s", + "manhunt.scoreboard.world.overworld": "§2主世界", + "manhunt.scoreboard.world.the_nether": "§4下界", + "manhunt.scoreboard.world.the_end": "§d末地", + "manhunt.scoreboard.world.unknown": "§6未知" +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index a09ca6a..1fa4f50 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,15 +1,15 @@ { "schemaVersion": 1, "id": "manhunt", - "version": "1.0.2", + "version": "${version}", "name": "Manhunt", - "description": "Fabric下的猎人游戏模组 | Manhunt mod for Fabric.", + "description": "Fork of Noryea's manhunt mod for Fabric.", "authors": [ - "Noryea" + "Noryea", + "AqUpd" ], "contact": { - "homepage": "https://github.com/Noryea/manhunt-fabric", - "sources": "https://github.com/Noryea/manhunt-fabric" + "sources": "https://github.com/Ivan-Khar/manhunt-fabric" }, "license": "GNU General Public License v3.0", "environment": "*", diff --git a/src/main/resources/manhunt.mixins.json b/src/main/resources/manhunt.mixins.json index 7a179aa..6b0d161 100644 --- a/src/main/resources/manhunt.mixins.json +++ b/src/main/resources/manhunt.mixins.json @@ -5,6 +5,7 @@ "compatibilityLevel": "JAVA_17", "mixins": [ "CompassItemMixin", + "EnderDragonEntityMixin", "PlayerEntityMixin", "ServerPlayerEntityMixin", "ServerPlayerInteractionManagerMixin"