This commit is contained in:
expvintl
2023-09-02 00:50:36 +08:00
commit 2084d95ee7
343 changed files with 1722 additions and 0 deletions

View File

@ -0,0 +1,7 @@
package com.expvintl.mctools;
public class FeaturesBool {
public static boolean autoRespawn=false;
public static boolean selfWalk=false;
public static boolean checkBukkitPlugins=false;
}

View File

@ -0,0 +1,78 @@
package com.expvintl.mctools;
import com.expvintl.mctools.commands.CAutoRespawnCommand;
import com.expvintl.mctools.commands.CFullbirghtCommand;
import com.expvintl.mctools.commands.CQServerPluginsCommand;
import com.expvintl.mctools.commands.CSafeWalkCommand;
import com.expvintl.mctools.utils.Utils;
import com.mojang.brigadier.CommandDispatcher;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.Colors;
import net.minecraft.util.math.Vec3d;
import java.util.Objects;
public class MCToolsClient implements ClientModInitializer {
private static int infoY=1;
@Override
public void onInitializeClient() {
//初始化命令注册回调
ClientCommandRegistrationCallback.EVENT.register(MCToolsClient::registerCommands);
HudRenderCallback.EVENT.register(MCToolsClient::drawHUD);
}
private static void drawHUD(DrawContext drawContext, float v) {
MinecraftClient mc=MinecraftClient.getInstance();
//跳过调试
if(mc.options.debugEnabled) 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,%d]",mc.player.getChunkPos().x,mc.player.getChunkPos().z));
}
}
private static void AddText(DrawContext drawContext,String text){
TextRenderer renderer=MinecraftClient.getInstance().textRenderer;
drawContext.drawText(renderer,text,0,infoY,Colors.GRAY,false);
infoY+=10;
}
private static void registerCommands(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
//注册命令
CFullbirghtCommand.register(dispatcher);
CAutoRespawnCommand.register(dispatcher);
CSafeWalkCommand.register(dispatcher);
CQServerPluginsCommand.register(dispatcher);
}
}

View File

@ -0,0 +1,29 @@
package com.expvintl.mctools.commands;
import com.expvintl.mctools.FeaturesBool;
import com.expvintl.mctools.mixin.interfaces.SimpleOptionAccessor;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.context.CommandContext;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.text.Text;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
public class CAutoRespawnCommand {
public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher){
dispatcher.register(literal("cautorespawn").then(argument("开关", BoolArgumentType.bool()).executes(CAutoRespawnCommand::execute)));
}
private static int execute(CommandContext<FabricClientCommandSource> context) {
FeaturesBool.autoRespawn=context.getArgument("开关", Boolean.class);
if(FeaturesBool.autoRespawn){
context.getSource().getPlayer().sendMessage(Text.literal("已启用自动重生!"));
}else{
context.getSource().getPlayer().sendMessage(Text.literal("已禁用自动重生!"));
}
return Command.SINGLE_SUCCESS;
}
}

View File

@ -0,0 +1,23 @@
package com.expvintl.mctools.commands;
import com.expvintl.mctools.mixin.interfaces.SimpleOptionAccessor;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.text.Text;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
public class CFullbirghtCommand{
public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher){
dispatcher.register(literal("cfullbirght").executes(CFullbirghtCommand::execute));
}
private static int execute(CommandContext<FabricClientCommandSource> context) {
((SimpleOptionAccessor)(Object)context.getSource().getClient().options.getGamma()).forceSetValue(32767.0);
context.getSource().getPlayer().sendMessage(Text.literal("已应用高亮"));
return Command.SINGLE_SUCCESS;
}
}

View File

@ -0,0 +1,37 @@
package com.expvintl.mctools.commands;
import com.expvintl.mctools.FeaturesBool;
import com.expvintl.mctools.mixin.interfaces.SimpleOptionAccessor;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.MinecraftClient;
import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket;
import net.minecraft.text.Text;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
public class CQServerPluginsCommand {
public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher){
dispatcher.register(literal("cqserverplugins").executes(CQServerPluginsCommand::execute));
}
private static int execute(CommandContext<FabricClientCommandSource> context) {
FeaturesBool.checkBukkitPlugins=true;
context.getSource().getPlayer().networkHandler.sendPacket(new RequestCommandCompletionsC2SPacket(new Random().nextInt(200),"bukkit:ver "));
//1秒后关闭避免识别其他命令提示
new Timer().schedule(new TimerTask() {
@Override
public void run() {
FeaturesBool.checkBukkitPlugins=false;
}
},1000);
return Command.SINGLE_SUCCESS;
}
}

View File

@ -0,0 +1,28 @@
package com.expvintl.mctools.commands;
import com.expvintl.mctools.FeaturesBool;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.context.CommandContext;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.text.Text;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
public class CSafeWalkCommand {
public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher){
dispatcher.register(literal("cselfwalk").then(argument("开关", BoolArgumentType.bool()).executes(CSafeWalkCommand::execute)));
}
private static int execute(CommandContext<FabricClientCommandSource> context) {
FeaturesBool.selfWalk=context.getArgument("开关", Boolean.class);
if(FeaturesBool.selfWalk){
context.getSource().getPlayer().sendMessage(Text.literal("已启用自动挂边!"));
}else{
context.getSource().getPlayer().sendMessage(Text.literal("已禁用自动挂边!"));
}
return Command.SINGLE_SUCCESS;
}
}

View File

@ -0,0 +1,26 @@
package com.expvintl.mctools.mixin;
import com.expvintl.mctools.FeaturesBool;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.DeathScreen;
import net.minecraft.client.gui.screen.Screen;
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(value = MinecraftClient.class,priority = 1001)
public class MinecraftClientMixin {
@Inject(method = "setScreen",at=@At("HEAD"))
//挂钩设置界面函数
private void onSetScreen(Screen screen, CallbackInfo info){
if(FeaturesBool.autoRespawn) {
//自动重生
if (screen instanceof DeathScreen) {
if (MinecraftClient.getInstance().player != null) {
MinecraftClient.getInstance().player.requestRespawn();
}
}
}
}
}

View File

@ -0,0 +1,5 @@
package com.expvintl.mctools.mixin.interfaces;
public interface IClientPlayerInteractionManager {
void syncSelected();
}

View File

@ -0,0 +1,11 @@
package com.expvintl.mctools.mixin.interfaces;
import net.minecraft.client.option.SimpleOption;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(SimpleOption.class)
public interface SimpleOptionAccessor {
@Accessor("value")
<T> void forceSetValue(T value);
}

View File

@ -0,0 +1,46 @@
package com.expvintl.mctools.mixin.network;
import com.expvintl.mctools.FeaturesBool;
import com.google.common.eventbus.EventBus;
import com.mojang.brigadier.suggestion.Suggestion;
import net.minecraft.client.MinecraftClient;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.listener.ClientPlayPacketListener;
import net.minecraft.network.listener.PacketListener;
import net.minecraft.network.packet.BundlePacket;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket;
import net.minecraft.network.packet.s2c.play.BundleS2CPacket;
import net.minecraft.network.packet.s2c.play.CommandSuggestionsS2CPacket;
import net.minecraft.text.Text;
import org.slf4j.Logger;
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;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Iterator;
@Mixin(ClientConnection.class)
public class ClientConnectionMixin {
@Inject(method = "handlePacket",at=@At("HEAD"))
private static <T extends PacketListener> void onHandlePacket(Packet<T> packet, PacketListener listener, CallbackInfo info) {
//检查bukkit服务器插件
if (!MinecraftClient.getInstance().isIntegratedServerRunning()&&FeaturesBool.checkBukkitPlugins) {
if (packet instanceof CommandSuggestionsS2CPacket sg) {
StringBuilder buf=new StringBuilder();
buf.append(String.format("找到%d个插件:",sg.getSuggestions().getList().size())).append('\n');
for(Suggestion s:sg.getSuggestions().getList()){
buf.append('[').append(s.getText()).append(']').append(' ');
}
if(MinecraftClient.getInstance().player!=null){
MinecraftClient.getInstance().player.sendMessage(Text.literal(buf.toString()));
}
FeaturesBool.checkBukkitPlugins=false;
}
}
}
}

View File

@ -0,0 +1,58 @@
package com.expvintl.mctools.mixin.player;
import com.expvintl.mctools.mixin.interfaces.IClientPlayerInteractionManager;
import net.minecraft.block.BambooBlock;
import net.minecraft.block.BambooSaplingBlock;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ShearsItem;
import net.minecraft.item.SwordItem;
import net.minecraft.item.ToolItem;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ClientPlayerInteractionManager.class)
public abstract class ClientPlayerInteractionManagerMixin implements IClientPlayerInteractionManager {
@Shadow
protected abstract void syncSelectedSlot();
@Inject(method = "attackBlock",at=@At("HEAD"))
private void onAttackBlock(BlockPos blockPos, Direction direction, CallbackInfoReturnable<Boolean> info){
//自动工具
MinecraftClient mc=MinecraftClient.getInstance();
if (mc.world == null) return;
BlockState state= mc.world.getBlockState(blockPos);
if(state.getHardness(mc.world, blockPos) < 0) return;
if(mc.player==null) return;
ItemStack currentItem = mc.player.getMainHandStack();
double bestScore=-1;
int slot=0;
for(int i=0;i<9;i++){
ItemStack item = mc.player.getInventory().getStack(i);
//Is Tool!!
if(item.getItem() instanceof ToolItem || item.getItem() instanceof ShearsItem){
double score=0;
score+=item.getMiningSpeedMultiplier(state)*1000;
if (item.getItem() instanceof SwordItem item1 && (state.getBlock() instanceof BambooBlock || state.getBlock() instanceof BambooSaplingBlock))
score += 9000 + (item1.getMaterial().getMiningLevel() * 1000);
if(score<0) continue;
if(score>bestScore){
bestScore=score;
slot=i;
}
}
}
mc.player.getInventory().selectedSlot=slot;
((IClientPlayerInteractionManager)mc.interactionManager).syncSelected();
}
@Override
public void syncSelected() {
syncSelectedSlot();
}
}

View File

@ -0,0 +1,21 @@
package com.expvintl.mctools.mixin.player;
import com.expvintl.mctools.FeaturesBool;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
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.CallbackInfoReturnable;
@Mixin(PlayerEntity.class)
public class PlayerEntityMixin {
@Inject(method = "clipAtLedge",at = @At("HEAD"), cancellable = true)
private void onLedge(CallbackInfoReturnable<Boolean> cir){
if(MinecraftClient.getInstance().world!=null&&MinecraftClient.getInstance().player!=null) {
if (!MinecraftClient.getInstance().world.isClient) return;
//挂住边缘
if (FeaturesBool.selfWalk && !MinecraftClient.getInstance().player.isSneaking()) cir.setReturnValue(true);
}
}
}

View File

@ -0,0 +1,102 @@
package com.expvintl.mctools.utils;
import net.minecraft.client.MinecraftClient;
import net.minecraft.registry.RegistryKey;
import net.minecraft.world.biome.Biome;
import java.util.Objects;
import java.util.Optional;
public class Utils {
private static final MinecraftClient mc=MinecraftClient.getInstance();
public static String getCurrentDimensionName(){
if(mc.world!=null){
String dismenName=mc.world.getDimensionKey().getValue().toString();
switch (dismenName){
case "minecraft:overworld":
return "主世界";
case "minecraft:the_nether":
return "下界";
case "minecraft:the_end":
return "末地";
default: return dismenName;
}
}
return "未知";
}
public static String getCurrentBiomeName(){
if(Objects.nonNull(mc.world)&&Objects.nonNull(mc.player)){
Optional<RegistryKey<Biome>> biomeName=mc.world.getBiome(mc.player.getBlockPos()).getKey();
if(biomeName.isPresent()){
String name=biomeName.get().getValue().toString();
switch (name){
case "minecraft:badlands": return "恶地 (badlands)";
case "minecraft:bamboo_jungle": return "竹林 (bamboo_jungle)";
case "minecraft:basalt_deltas": return "玄武岩三角洲 (basalt_deltas)";
case "minecraft:beach":return "沙滩 (beach)";
case "minecraft:ocean": return "海洋 (ocean)";
case "minecraft:plains": return "平原 (plains)";
case "minecraft:river": return "河流 (river)";
case "minecraft:birch_forest":return "桦木森林 (birch_forest)";
case "minecraft:cherry_grove":return "樱花树林 (cherry_grove)";
case "minecraft:cold_ocean": return "冷水海洋 (cold_ocean)";
case "minecraft:crimson_forest": return "绯红森林 (crimson_forest)";
case "minecraft:dark_forest": return "黑森林 (dark_forest)";
case "minecraft:deep_cold_ocean": return "冷水深海 (deep_cold_ocean)";
case "minecraft:deep_dark": return "深暗之域 (deep_dark)";
case "minecraft:deep_frozen_ocean": return "冰冻深海 (deep_frozen_ocean)";
case "minecraft:deep_lukewarm_ocean":return "温水深海 (deep_lukewarm_ocean)";
case "minecraft:deep_ocean":return "深海 (deep_ocean)";
case "minecraft:desert":return "沙漠 (desert)";
case "minecraft:dripstone_caves":return "溶洞 (dripstone_caves)";
case "minecraft:end_barrens": return "末地荒地 (end_barrens)";
case "minecraft:end_highlands": return "末地高地 (end_highlands)";
case "minecraft:eroded_badlands": return "风蚀恶地 (eroded_badlands)";
case "minecraft:flower_forest":return "繁花森林 (flower_forest)";
case "minecraft:forest":return "森林 (forest)";
case "minecraft:frozen_ocean":return "冻洋 (frozen_ocean)";
case "minecraft:frozen_peaks":return "冰封山峰 (frozen_peaks)";
case "minecraft:frozen_river":return "冻河 (frozen_river)";
case "minecraft:grove": return "雪林 (grove)";
case "minecraft:ice_spikes": return "冰刺之地 (ice_spikes)";
case "minecraft:jagged_peaks": return "尖峭山峰 (jagged_peaks)";
case "minecraft:jungle":return "丛林 (jungle)";
case "minecraft:lukewarm_ocean":return "温水海洋 (lukewarm_ocean)";
case "minecraft:lush_caves":return "繁茂洞穴 (lush_caves)";
case "minecraft:mangrove_swamp":return "红树林沼泽 (mangrove_swamp)";
case "minecraft:meadow":return "草甸 (meadow)";
case "minecraft:mushroom_fields": return "蘑菇岛 (mushroom_fields)";
case "minecraft:nether_wastes": return "下界荒地 (nether_wastes)";
case "minecraft:old_growth_birch_forest":return "原始桦木森林 (old_growth_birch_forest)";
case "minecraft:old_growth_pine_taiga":return "原始松木针叶林 (old_growth_pine_taiga)";
case "minecraft:old_growth_spruce_taiga":return "原始云杉针叶林 (old_growth_spruce_taiga)";
case "minecraft:savanna":return "热带草原 (savanna)";
case "minecraft:savanna_plateau": return "热带高原 (savanna_plateau)";
case "minecraft:small_end_islands":return "末地小型岛屿 (small_end_islands)";
case "minecraft:snowy_beach":return "积雪沙滩 (snowy_beach)";
case "minecraft:snowy_plains":return "雪原 (snowy_plains)";
case "minecraft:snowy_slopes": return "积雪山坡 (snowy_slopes)";
case "minecraft:snowy_taiga":return "积雪针叶林 (snowy_taiga)";
case "minecraft:soul_sand_valley":return "灵魂沙峡谷 (soul_sand_valley)";
case "minecraft:sparse_jungle": return "稀疏丛林 (sparse_jungle)";
case "minecraft:stony_peaks": return "裸岩山峰 (stony_peaks)";
case "minecraft:stony_shore": return "石岸 (stony_shore)";
case "minecraft:sunflower_plains": return "向日葵平原 (sunflower_plains)";
case "minecraft:swamp":return "沼泽 (swamp)";
case "minecraft:taiga":return "针叶林 (taiga)";
case "minecraft:the_end":return "末地 (the_end)";
case "minecraft:the_void": return "虚空 (the_void)";
case "minecraft:warm_ocean":return "暖水海洋 (warm_ocean)";
case "minecraft:warped_forest":return "诡异森林 (warped_forest)";
case "minecraft:windswept_forest":return "风袭森林 (windswept_forest)";
case "minecraft:windswept_gravelly_hills":return "风袭沙砾丘陵 (windswept_gravelly_hills)";
case "minecraft:windswept_hills":return "风袭丘陵 (windswept_hills)";
case "minecraft:windswept_savanna":return "风袭热带草原 (windswept_savanna)";
case "minecraft:wooded_badlands":return "疏林恶地 (wooded_badlands)";
default:return name;
}
}
}
return "未知";
}
}

View File

@ -0,0 +1,27 @@
{
"schemaVersion": 1,
"id": "mctools",
"version": "${version}",
"name": "MCTools",
"description": "",
"authors": [],
"contact": {
"repo": "https://github.com/undefined/MCTools"
},
"license": "All-Rights-Reserved",
"icon": "assets/mctools/icon.png",
"environment": "client",
"entrypoints": {
"client": [
"com.expvintl.mctools.MCToolsClient"
]
},
"mixins": [
"mctools.mixins.json"
],
"depends": {
"fabricloader": ">=${loader_version}",
"fabric": "*",
"minecraft": "${minecraft_version}"
}
}

View File

@ -0,0 +1,18 @@
{
"required": true,
"minVersion": "0.8",
"package": "com.expvintl.mctools.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"network.ClientConnectionMixin",
"player.PlayerEntityMixin"
],
"client": [
"MinecraftClientMixin",
"interfaces.SimpleOptionAccessor",
"player.ClientPlayerInteractionManagerMixin"
],
"injectors": {
"defaultRequire": 1
}
}