diff --git a/.idea/misc.xml b/.idea/misc.xml index ec55a2e..9d0bbd3 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 81526cf..55c33c0 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -3,7 +3,9 @@ + + diff --git a/.idea/modules/MCTools.main.iml b/.idea/modules/MCTools.main.iml index 2e14514..356a8e3 100644 --- a/.idea/modules/MCTools.main.iml +++ b/.idea/modules/MCTools.main.iml @@ -14,4 +14,8 @@ + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Minecraft_Server.xml b/.idea/runConfigurations/Minecraft_Server.xml index 9710d0e..aff153d 100644 --- a/.idea/runConfigurations/Minecraft_Server.xml +++ b/.idea/runConfigurations/Minecraft_Server.xml @@ -12,5 +12,5 @@ - + \ No newline at end of file diff --git a/src/main/java/com/expvintl/mctools/MCToolsClient.java b/src/main/java/com/expvintl/mctools/MCToolsClient.java index a0cc78d..bc646f7 100644 --- a/src/main/java/com/expvintl/mctools/MCToolsClient.java +++ b/src/main/java/com/expvintl/mctools/MCToolsClient.java @@ -3,6 +3,8 @@ package com.expvintl.mctools; import com.expvintl.mctools.commands.*; import com.expvintl.mctools.modules.BetterTooltip; import com.expvintl.mctools.modules.PlayerListTextLatency; +import com.expvintl.mctools.texthud.MCInfo; +import com.expvintl.mctools.texthud.PotionInfo; import com.expvintl.mctools.utils.Utils; import com.mojang.brigadier.CommandDispatcher; import net.fabricmc.api.ClientModInitializer; @@ -21,87 +23,19 @@ import net.minecraft.util.math.Vec3d; public class MCToolsClient implements ClientModInitializer { - private static int infoY=1; @Override public void onInitializeClient() { //初始化命令注册回调 ClientCommandRegistrationCallback.EVENT.register(MCToolsClient::registerCommands); - HudRenderCallback.EVENT.register(MCToolsClient::drawHUD); + HudRenderCallback.EVENT.register(MCInfo::drawHUD); + HudRenderCallback.EVENT.register(PotionInfo::drawHUD); InitModules(); } public void InitModules(){ BetterTooltip.INSTANCE.init(); PlayerListTextLatency.INSTANCE.init(); } - private static String gameDayToRealTimeFormat(long gameDays) { - // 游戏 1 小时等于 20 分钟 - long totalMinutes = gameDays * 20; - long days = totalMinutes / (60 * 24); // 计算天数 - long remainingMinutesAfterDays = totalMinutes % (60 * 24); - - long hours = remainingMinutesAfterDays / 60; // 计算小时数 - long minutes = remainingMinutesAfterDays % 60; // 计算剩余分钟数 - - StringBuilder timeString = new StringBuilder(); - - if (days > 0) { - timeString.append(days).append(" 天"); - } - if (hours > 0) { - if (!timeString.isEmpty()) { - timeString.append(" "); - } - timeString.append(hours).append(" 小时"); - } - if (minutes > 0 || timeString.isEmpty()) { - if (!timeString.isEmpty()) { - timeString.append(" "); - } - timeString.append(minutes).append(" 分钟"); - } - - return timeString.toString(); - } - private static void drawHUD(DrawContext drawContext, RenderTickCounter v) { - MinecraftClient mc=MinecraftClient.getInstance(); - //跳过调试 - if(mc.getDebugHud().shouldShowDebugHud()||mc.options.hudHidden) return; - - if(mc.world!=null&&mc.player!=null) { - infoY=1; - int selfPing=0; - ClientPlayerEntity p=mc.player; - if(mc.getNetworkHandler()!=null&&mc.getNetworkHandler().getPlayerListEntry(mc.player.getGameProfile().getId())!=null) { - selfPing=mc.getNetworkHandler().getPlayerListEntry(mc.player.getGameProfile().getId()).getLatency(); - } - Vec3d playerPos=p.getPos(); - AddText(drawContext,String.format("%d FPS",mc.getCurrentFps())); - AddText(drawContext,String.format("Ping: %d 毫秒",selfPing)); - AddText(drawContext,String.format("亮度:%d",mc.world.getLightLevel(p.getBlockPos()))); - AddText(drawContext,String.format("当前维度:%s", Utils.getCurrentDimensionName())); - AddText(drawContext,String.format("当前群系:%s",Utils.getCurrentBiomeName())); - if(Utils.getCurrentDimensionName().equals("下界")){ - AddText(drawContext,String.format("X:%.2f Y:%.2f Z:%.2f (主世界 X:%.2f Z:%.2f)",playerPos.x,playerPos.y,playerPos.z,playerPos.x*8,playerPos.z*8)); - }else if(Utils.getCurrentDimensionName().equals("主世界")){ - AddText(drawContext,String.format("X:%.2f Y:%.2f Z:%.2f (下界 X:%.2f Z:%.2f)",playerPos.x,playerPos.y,playerPos.z,playerPos.x/8,playerPos.z/8)); - }else{ - AddText(drawContext,String.format("X:%.2f Y:%.2f Z:%.2f",playerPos.x,playerPos.y,playerPos.z)); - } - AddText(drawContext,String.format("世界时间: %d天 (%s)",mc.world.getTimeOfDay()/24000,gameDayToRealTimeFormat(mc.world.getTimeOfDay()/24000))); - AddText(drawContext,String.format("当前区块: [%d,%d]",mc.player.getChunkPos().x,mc.player.getChunkPos().z)); - AddText(drawContext,String.format("本地难度:%.2f",mc.world.getLocalDifficulty(mc.player.getBlockPos()).getLocalDifficulty())); - ItemStack currentItem=p.getInventory().getMainHandStack(); - if(currentItem!=null&¤tItem.isDamageable()){ - AddText(drawContext,String.format("耐久度:%d/%d",currentItem.getMaxDamage()-currentItem.getDamage(),currentItem.getMaxDamage())); - } - } - } - private static void AddText(DrawContext drawContext,String text){ - TextRenderer renderer=MinecraftClient.getInstance().textRenderer; - drawContext.drawText(renderer,text,0,infoY,Colors.WHITE,false); - infoY+=10; - } private static void registerCommands(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess) { //注册命令 CFullbirghtCommand.register(dispatcher); @@ -112,6 +46,6 @@ public class MCToolsClient implements ClientModInitializer { CQServerPluginsCommand.register(dispatcher); CNoFallPacketCommand.register(dispatcher); CFindBlockCommand.register(dispatcher); - CFastDropCommand.register(dispatcher); + CFastDropCommand.register(dispatcher,registryAccess); } } diff --git a/src/main/java/com/expvintl/mctools/commands/CFastDropCommand.java b/src/main/java/com/expvintl/mctools/commands/CFastDropCommand.java index 6539bf1..b7b6d77 100644 --- a/src/main/java/com/expvintl/mctools/commands/CFastDropCommand.java +++ b/src/main/java/com/expvintl/mctools/commands/CFastDropCommand.java @@ -1,27 +1,79 @@ package com.expvintl.mctools.commands; -import com.expvintl.mctools.mixin.interfaces.SimpleOptionAccessor; import com.expvintl.mctools.utils.PlayerUtils; import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.command.argument.ItemStackArgumentType; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; +import net.minecraft.registry.Registries; import net.minecraft.text.Text; +import net.minecraft.util.Identifier; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CompletableFuture; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; public class CFastDropCommand { public static List trashItem=new ArrayList<>(); - public static void register(CommandDispatcher dispatcher){ + public static void register(CommandDispatcher dispatcher , CommandRegistryAccess access){ dispatcher.register(literal("cfastdrop").executes(CFastDropCommand::execute)); + dispatcher.register(literal("cfastdrop").then(literal("list").executes((context -> { + StringBuilder sb=new StringBuilder(); + sb.append("已添加:\n"); + for(Item i:trashItem){ + sb.append(i.getName().getString()).append(","); + } + context.getSource().getPlayer().sendMessage(Text.literal(sb.toString())); + return Command.SINGLE_SUCCESS; + })))); + dispatcher.register(literal("cfastdrop").then(literal("clear").executes((context -> { + trashItem.clear(); + context.getSource().getPlayer().sendMessage(Text.literal("已清除全部物品!")); + return Command.SINGLE_SUCCESS; + })))); + dispatcher.register(literal("cfastdrop").then(literal("del").then(argument("物品", ItemStackArgumentType.itemStack(access)).suggests(((context, builder) -> suggestItems(builder))).executes(cmd->{ + Item item=ItemStackArgumentType.getItemStackArgument(cmd,"物品").getItem(); + if (item != Items.AIR) { // 确保找到的物品是有效的 + if (trashItem.contains(item)) { + trashItem.remove(item); + cmd.getSource().getPlayer().sendMessage(Text.literal("已移除 " + item.getName().getString())); + }else{ + cmd.getSource().getPlayer().sendMessage(Text.literal("没有找到 " + item.getName().getString())); + } + }else{ + cmd.getSource().getPlayer().sendMessage(Text.literal("无效物品!")); + return 0; + } + return Command.SINGLE_SUCCESS; + })))); + dispatcher.register(literal("cfastdrop").then(literal("add").then(argument("物品", ItemStackArgumentType.itemStack(access)).suggests(((context, builder) -> suggestItems(builder))).executes(cmd->{ + Item item=ItemStackArgumentType.getItemStackArgument(cmd,"物品").getItem(); + if (item != Items.AIR) { // 确保找到的物品是有效的 + if(trashItem.contains(item)){ + cmd.getSource().getPlayer().sendMessage(Text.literal( item.getName().getString() + " 已存在!")); + }else { + trashItem.add(item); + cmd.getSource().getPlayer().sendMessage(Text.literal("已添加 " + item.getName().getString() + " 到垃圾物品列表")); + } + }else{ + cmd.getSource().getPlayer().sendMessage(Text.literal("无效物品!")); + return 0; + } + return Command.SINGLE_SUCCESS; + })))); trashItem.add(Items.COBBLESTONE); trashItem.add(Items.GRANITE);//花岗岩 trashItem.add(Items.ANDESITE);//安山岩 @@ -35,8 +87,17 @@ public class CFastDropCommand { trashItem.add(Items.DANDELION); trashItem.add(Items.SUNFLOWER); trashItem.add(Items.CORNFLOWER); + trashItem.add(Items.TUFF); //凝灰岩 + trashItem.add(Items.DEEPSLATE); //深板岩 + trashItem.add(Items.SANDSTONE); //砂岩 + trashItem.add(Items.DEEPSLATE_BRICKS);//深板岩砖 + trashItem.add(Items.COBBLED_DEEPSLATE); //深板岩圆石 + } + private static CompletableFuture suggestItems(SuggestionsBuilder builder) { + // 遍历所有注册的物品并将其添加到建议列表中 + Registries.ITEM.getIds().forEach(id -> builder.suggest(id.toString())); + return builder.buildFuture(); } - private static int execute(CommandContext context) { ClientPlayerEntity player=context.getSource().getPlayer(); if(player==null){ diff --git a/src/main/java/com/expvintl/mctools/mixin/hud/ChatHudMixin.java b/src/main/java/com/expvintl/mctools/mixin/hud/ChatHudMixin.java index e823f8f..d3f0f00 100644 --- a/src/main/java/com/expvintl/mctools/mixin/hud/ChatHudMixin.java +++ b/src/main/java/com/expvintl/mctools/mixin/hud/ChatHudMixin.java @@ -11,6 +11,7 @@ import net.minecraft.client.gui.hud.ChatHudLine; import net.minecraft.text.OrderedText; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; @Mixin(ChatHud.class) public class ChatHudMixin { diff --git a/src/main/java/com/expvintl/mctools/mixin/hud/PlayerListHudMixin.java b/src/main/java/com/expvintl/mctools/mixin/hud/PlayerListHudMixin.java index 9ecc1ce..e8f7e20 100644 --- a/src/main/java/com/expvintl/mctools/mixin/hud/PlayerListHudMixin.java +++ b/src/main/java/com/expvintl/mctools/mixin/hud/PlayerListHudMixin.java @@ -12,6 +12,7 @@ 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.ModifyArg; +import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -25,6 +26,7 @@ public class PlayerListHudMixin { private void getPlayerName(PlayerListEntry entry, CallbackInfoReturnable info){ if(Utils.isReady()){ Text name=entry.getDisplayName(); + if(MinecraftClient.getInstance().player==null||name==null) return; if(entry.getProfile().getId().toString().equals(MinecraftClient.getInstance().player.getGameProfile().getId().toString())){ info.setReturnValue(Text.literal(name.getString()).setStyle(name.getStyle().withColor(0xff0000))); } @@ -35,4 +37,10 @@ public class PlayerListHudMixin { private void onRenderLatencyIcon(DrawContext draw, int width, int x, int y, PlayerListEntry entry, CallbackInfo info){ MCEventBus.INSTANCE.post(RenderLatencyIconEvent.get(draw,width,x,y,entry,info)); } + + //强制启用Tab列表玩家头像 + @ModifyVariable(method = "render",at = @At(value = "STORE",ordinal = 0),ordinal = 0) + private boolean hackShowPlayerHeadIcon(boolean b1){ + return true; + } } diff --git a/src/main/java/com/expvintl/mctools/texthud/MCInfo.java b/src/main/java/com/expvintl/mctools/texthud/MCInfo.java new file mode 100644 index 0000000..d42e96c --- /dev/null +++ b/src/main/java/com/expvintl/mctools/texthud/MCInfo.java @@ -0,0 +1,78 @@ +package com.expvintl.mctools.texthud; + +import com.expvintl.mctools.utils.DrawUtils; +import com.expvintl.mctools.utils.Utils; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.render.RenderTickCounter; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Colors; +import net.minecraft.util.math.Vec3d; + +public class MCInfo { + private static String gameDayToRealTimeFormat(long gameDays) { + // 游戏 1 小时等于 20 分钟 + long totalMinutes = gameDays * 20; + + long days = totalMinutes / (60 * 24); // 计算天数 + long remainingMinutesAfterDays = totalMinutes % (60 * 24); + + long hours = remainingMinutesAfterDays / 60; // 计算小时数 + long minutes = remainingMinutesAfterDays % 60; // 计算剩余分钟数 + + StringBuilder timeString = new StringBuilder(); + + if (days > 0) { + timeString.append(days).append(" 天"); + } + if (hours > 0) { + if (!timeString.isEmpty()) { + timeString.append(" "); + } + timeString.append(hours).append(" 小时"); + } + if (minutes > 0 || timeString.isEmpty()) { + if (!timeString.isEmpty()) { + timeString.append(" "); + } + timeString.append(minutes).append(" 分钟"); + } + + return timeString.toString(); + } + public static void drawHUD(DrawContext drawContext, RenderTickCounter v) { + MinecraftClient mc=MinecraftClient.getInstance(); + //跳过调试 + if(mc.getDebugHud().shouldShowDebugHud()||mc.options.hudHidden) return; + if(mc.world!=null&&mc.player!=null) { + DrawUtils.leftTextY =1; + int selfPing=0; + ClientPlayerEntity p=mc.player; + if(mc.getNetworkHandler()!=null&&mc.getNetworkHandler().getPlayerListEntry(mc.player.getGameProfile().getId())!=null) { + selfPing=mc.getNetworkHandler().getPlayerListEntry(mc.player.getGameProfile().getId()).getLatency(); + } + Vec3d playerPos=p.getPos(); + DrawUtils.AddLeftText(drawContext,String.format("%d FPS",mc.getCurrentFps())); + DrawUtils.AddLeftText(drawContext,String.format("Ping: %d 毫秒",selfPing)); + DrawUtils.AddLeftText(drawContext,String.format("亮度:%d",mc.world.getLightLevel(p.getBlockPos()))); + DrawUtils.AddLeftText(drawContext,String.format("当前维度:%s", Utils.getCurrentDimensionName())); + DrawUtils.AddLeftText(drawContext,String.format("当前群系:%s",Utils.getCurrentBiomeName())); + if(Utils.getCurrentDimensionName().equals("下界")){ + DrawUtils.AddLeftText(drawContext,String.format("X:%.2f Y:%.2f Z:%.2f (主世界 X:%.2f Z:%.2f)",playerPos.x,playerPos.y,playerPos.z,playerPos.x*8,playerPos.z*8)); + }else if(Utils.getCurrentDimensionName().equals("主世界")){ + DrawUtils.AddLeftText(drawContext,String.format("X:%.2f Y:%.2f Z:%.2f (下界 X:%.2f Z:%.2f)",playerPos.x,playerPos.y,playerPos.z,playerPos.x/8,playerPos.z/8)); + }else{ + DrawUtils.AddLeftText(drawContext,String.format("X:%.2f Y:%.2f Z:%.2f",playerPos.x,playerPos.y,playerPos.z)); + } + DrawUtils.AddLeftText(drawContext,String.format("世界时间: %d天 (%s)",mc.world.getTimeOfDay()/24000,gameDayToRealTimeFormat(mc.world.getTimeOfDay()/24000))); + DrawUtils.AddLeftText(drawContext,String.format("当前区块: [%d,%d]",mc.player.getChunkPos().x,mc.player.getChunkPos().z)); + DrawUtils.AddLeftText(drawContext,String.format("本地难度:%.2f",mc.world.getLocalDifficulty(mc.player.getBlockPos()).getLocalDifficulty())); + ItemStack currentItem=p.getInventory().getMainHandStack(); + if(currentItem!=null&¤tItem.isDamageable()){ + DrawUtils.AddLeftText(drawContext,String.format("耐久度:%d/%d",currentItem.getMaxDamage()-currentItem.getDamage(),currentItem.getMaxDamage())); + } + } + } +} diff --git a/src/main/java/com/expvintl/mctools/texthud/PotionInfo.java b/src/main/java/com/expvintl/mctools/texthud/PotionInfo.java new file mode 100644 index 0000000..295ba93 --- /dev/null +++ b/src/main/java/com/expvintl/mctools/texthud/PotionInfo.java @@ -0,0 +1,41 @@ +package com.expvintl.mctools.texthud; + +import com.expvintl.mctools.utils.DrawUtils; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.RenderTickCounter; +import net.minecraft.client.resource.language.I18n; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.util.Colors; + +import java.util.Collection; + +public class PotionInfo { + public static void drawHUD(DrawContext drawContext, RenderTickCounter v) { + MinecraftClient mc=MinecraftClient.getInstance(); + //跳过调试 + if(mc.getDebugHud().shouldShowDebugHud()||mc.options.hudHidden) return; + + if(mc.world!=null&&mc.player!=null) { + DrawUtils.rightBottomY=1; + Collection effects=mc.player.getStatusEffects(); + for(StatusEffectInstance instance:effects){ + DrawUtils.AddRightBottomText(drawContext,String.format("%s%d (%s)", I18n.translate(instance.getTranslationKey()), + instance.getAmplifier()+1, + instance.isInfinite()?"无限":formatPotionDuration(instance.getDuration()))); + } + } + } + public static String formatPotionDuration(int ticks) { + int totalSeconds = ticks / 20; // 将ticks转换为秒 + int hours = totalSeconds / 3600; // 1小时 = 3600秒 + int minutes = (totalSeconds % 3600) / 60; // 获取剩余的分钟 + int seconds = totalSeconds % 60; // 获取剩余的秒数 + + if (hours > 0) { + return String.format("%d:%02d:%02d", hours, minutes, seconds); + } else { + return String.format("%02d:%02d", minutes, seconds); + } + } +} diff --git a/src/main/java/com/expvintl/mctools/utils/DrawUtils.java b/src/main/java/com/expvintl/mctools/utils/DrawUtils.java new file mode 100644 index 0000000..0ee749c --- /dev/null +++ b/src/main/java/com/expvintl/mctools/utils/DrawUtils.java @@ -0,0 +1,26 @@ +package com.expvintl.mctools.utils; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.util.Colors; + +public class DrawUtils { + public static int leftTextY=1; + public static int rightTextY=1; + public static int rightBottomY=1; + public static void AddLeftText(DrawContext drawContext, String text){ + MinecraftClient mc=MinecraftClient.getInstance(); + drawContext.drawText(mc.textRenderer,text,0,leftTextY, Colors.WHITE,false); + leftTextY+=10; + } + public static void AddRightText(DrawContext drawContext, String text){ + MinecraftClient mc=MinecraftClient.getInstance(); + drawContext.drawText(mc.textRenderer,text,drawContext.getScaledWindowWidth()-2-mc.textRenderer.getWidth(text),rightTextY, Colors.WHITE,false); + rightTextY+=10; + } + public static void AddRightBottomText(DrawContext drawContext, String text){ + MinecraftClient mc=MinecraftClient.getInstance(); + drawContext.drawText(mc.textRenderer,text,drawContext.getScaledWindowWidth()-2-mc.textRenderer.getWidth(text),drawContext.getScaledWindowHeight()-10-rightBottomY, Colors.WHITE,false); + rightBottomY+=10; + } +}