This commit is contained in:
expvintl 2023-09-02 22:27:12 +08:00
parent 2084d95ee7
commit 290dd9ea52
37 changed files with 241 additions and 97 deletions

Binary file not shown.

View File

@ -6,21 +6,10 @@ plugins {
version = project.mod_version
group = project.maven_group
repositories {
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
}
dependencies {
// To change the versions see the gradle.properties file
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. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
}
@ -77,9 +66,5 @@ publishing {
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
}
}

View File

@ -10,7 +10,8 @@
"handlePacket": "Lnet/minecraft/class_2535;method_10759(Lnet/minecraft/class_2596;Lnet/minecraft/class_2547;)V"
},
"com/expvintl/mctools/mixin/player/ClientPlayerInteractionManagerMixin": {
"attackBlock": "Lnet/minecraft/class_636;method_2910(Lnet/minecraft/class_2338;Lnet/minecraft/class_2350;)Z"
"attackBlock": "Lnet/minecraft/class_636;method_2910(Lnet/minecraft/class_2338;Lnet/minecraft/class_2350;)Z",
"breakBlock": "Lnet/minecraft/class_636;method_2899(Lnet/minecraft/class_2338;)Z"
},
"com/expvintl/mctools/mixin/player/PlayerEntityMixin": {
"clipAtLedge": "Lnet/minecraft/class_1657;method_21825()Z"
@ -28,7 +29,8 @@
"handlePacket": "Lnet/minecraft/class_2535;method_10759(Lnet/minecraft/class_2596;Lnet/minecraft/class_2547;)V"
},
"com/expvintl/mctools/mixin/player/ClientPlayerInteractionManagerMixin": {
"attackBlock": "Lnet/minecraft/class_636;method_2910(Lnet/minecraft/class_2338;Lnet/minecraft/class_2350;)Z"
"attackBlock": "Lnet/minecraft/class_636;method_2910(Lnet/minecraft/class_2338;Lnet/minecraft/class_2350;)Z",
"breakBlock": "Lnet/minecraft/class_636;method_2899(Lnet/minecraft/class_2338;)Z"
},
"com/expvintl/mctools/mixin/player/PlayerEntityMixin": {
"clipAtLedge": "Lnet/minecraft/class_1657;method_21825()Z"

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,2 +1 @@
v1 named intermediary
METHOD com/expvintl/mctools/mixin/player/ClientPlayerInteractionManagerMixin ()V syncSelectedSlot method_2911

View File

@ -4,4 +4,5 @@ public class FeaturesBool {
public static boolean autoRespawn=false;
public static boolean selfWalk=false;
public static boolean checkBukkitPlugins=false;
public static boolean autoTool=false;
}

View File

@ -1,9 +1,6 @@
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.commands.*;
import com.expvintl.mctools.utils.Utils;
import com.mojang.brigadier.CommandDispatcher;
import net.fabricmc.api.ClientModInitializer;
@ -73,6 +70,7 @@ public class MCToolsClient implements ClientModInitializer {
CFullbirghtCommand.register(dispatcher);
CAutoRespawnCommand.register(dispatcher);
CSafeWalkCommand.register(dispatcher);
CAutoToolCommand.register(dispatcher);
CQServerPluginsCommand.register(dispatcher);
}
}

View File

@ -1,19 +1,26 @@
package com.expvintl.mctools.commands;
import com.expvintl.mctools.FeaturesBool;
import com.expvintl.mctools.events.MCEventBus;
import com.expvintl.mctools.events.client.OpenScreenEvent;
import com.expvintl.mctools.mixin.interfaces.SimpleOptionAccessor;
import com.google.common.eventbus.Subscribe;
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.client.MinecraftClient;
import net.minecraft.client.gui.screen.DeathScreen;
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 {
private static final CAutoRespawnCommand INSTANCE=new CAutoRespawnCommand();
public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher){
MCEventBus.INSTANCE.register(INSTANCE);
dispatcher.register(literal("cautorespawn").then(argument("开关", BoolArgumentType.bool()).executes(CAutoRespawnCommand::execute)));
}
@ -26,4 +33,15 @@ public class CAutoRespawnCommand {
}
return Command.SINGLE_SUCCESS;
}
@Subscribe
private void onOpenScreen(OpenScreenEvent event){
if(FeaturesBool.autoRespawn) {
//自动重生
if (event.screen instanceof DeathScreen) {
if (MinecraftClient.getInstance().player != null) {
MinecraftClient.getInstance().player.requestRespawn();
}
}
}
}
}

View File

@ -0,0 +1,108 @@
package com.expvintl.mctools.commands;
import com.expvintl.mctools.FeaturesBool;
import com.expvintl.mctools.events.MCEventBus;
import com.expvintl.mctools.events.player.PlayerAttackBlockEvent;
import com.expvintl.mctools.events.player.PlayerBreakBlockEvent;
import com.google.common.eventbus.Subscribe;
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.block.BambooBlock;
import net.minecraft.block.BambooSaplingBlock;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ShearsItem;
import net.minecraft.item.SwordItem;
import net.minecraft.item.ToolItem;
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 CAutoToolCommand {
private static final CAutoToolCommand INSTANCE=new CAutoToolCommand();
private int lastSlot=-1;
public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher){
MCEventBus.INSTANCE.register(INSTANCE);
dispatcher.register(literal("cautotool").then(argument("开关", BoolArgumentType.bool()).executes(CAutoToolCommand::execute)));
}
private static int execute(CommandContext<FabricClientCommandSource> context) {
FeaturesBool.autoTool=context.getArgument("开关", Boolean.class);
if(FeaturesBool.autoTool){
context.getSource().getPlayer().sendMessage(Text.literal("已启用智能工具!"));
}else{
context.getSource().getPlayer().sendMessage(Text.literal("已禁用智能工具!"));
}
return Command.SINGLE_SUCCESS;
}
@Subscribe
private void onBreakBlock(PlayerBreakBlockEvent event){
if(!FeaturesBool.autoTool) return;
MinecraftClient mc=MinecraftClient.getInstance();
if (mc.world == null||mc.player==null) return;
if (lastSlot!=-1){
//破坏方块后切换回去
mc.player.getInventory().selectedSlot=lastSlot;
}
}
@Subscribe
private void onAttackBlock(PlayerAttackBlockEvent event){
if(!FeaturesBool.autoTool) return;
//自动工具
MinecraftClient mc=MinecraftClient.getInstance();
if (mc.world == null||mc.player==null) return;
BlockState state= mc.world.getBlockState(event.blockPos);
//跳过不可破坏
if(state.getHardness(mc.world, event.blockPos) < 0) return;
ItemStack currentItem = mc.player.getMainHandStack();
//统计最好的挖掘分数
double bestScore=-1;
//工具槽
int slot=-1;
//遍历每一个物品槽
for(int i=0;i<9;i++){
ItemStack item = mc.player.getInventory().getStack(i);
double score=getScore(item,state);
if(score<0) continue;
//选出最好分数的工具
if(score>bestScore){
bestScore=score;
slot=i;
}
}
//确定已经选择好了工具就切换
if((slot!=-1&&bestScore>getScore(currentItem,state))||shouldStopUsing(currentItem)||!isTools(currentItem)) {
//记住上一次的槽方便恢复
lastSlot=mc.player.getInventory().selectedSlot;
//切换过去
mc.player.getInventory().selectedSlot = slot;
}
if(isTools(currentItem)&&shouldStopUsing(currentItem)) {
mc.options.attackKey.setPressed(false);
}
}
public double getScore(ItemStack item, BlockState state){
double score=0;
//Is Tool!!
if(item.getItem() instanceof ToolItem || item.getItem() instanceof ShearsItem){
//根据挖掘速度提升评分
score+=item.getMiningSpeedMultiplier(state)*10;
if (item.getItem() instanceof SwordItem item1 && (state.getBlock() instanceof BambooBlock || state.getBlock() instanceof BambooSaplingBlock))
//根据挖掘等级加分
score += 90 + (item1.getMaterial().getMiningLevel() * 10);
}
return score;
}
//停用低耐久度
private boolean shouldStopUsing(ItemStack itemStack) {
return (itemStack.getMaxDamage() - itemStack.getDamage()) < (itemStack.getMaxDamage() * 6 / 100);
}
public boolean isTools(ItemStack item){
return item.getItem() instanceof ToolItem || item.getItem() instanceof ShearsItem;
}
}

View File

@ -1,28 +1,32 @@
package com.expvintl.mctools.commands;
import com.expvintl.mctools.FeaturesBool;
import com.expvintl.mctools.mixin.interfaces.SimpleOptionAccessor;
import com.expvintl.mctools.events.MCEventBus;
import com.expvintl.mctools.events.network.PacketEvent;
import com.google.common.eventbus.Subscribe;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.Suggestion;
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.network.packet.s2c.play.CommandSuggestionsS2CPacket;
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 {
private static final CQServerPluginsCommand INSTANCE=new CQServerPluginsCommand();
public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher){
dispatcher.register(literal("cqserverplugins").executes(CQServerPluginsCommand::execute));
}
private static int execute(CommandContext<FabricClientCommandSource> context) {
//注册数据包接受事件
MCEventBus.INSTANCE.register(INSTANCE);
FeaturesBool.checkBukkitPlugins=true;
context.getSource().getPlayer().networkHandler.sendPacket(new RequestCommandCompletionsC2SPacket(new Random().nextInt(200),"bukkit:ver "));
//1秒后关闭避免识别其他命令提示
@ -30,8 +34,28 @@ public class CQServerPluginsCommand {
@Override
public void run() {
FeaturesBool.checkBukkitPlugins=false;
MCEventBus.INSTANCE.unregister(INSTANCE);
}
},1000);
return Command.SINGLE_SUCCESS;
}
@Subscribe
public void onReceivePacket(PacketEvent p){
//探测bukkit服务器插件
if (!MinecraftClient.getInstance().isIntegratedServerRunning()&&FeaturesBool.checkBukkitPlugins) {
if (p.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;
//取消事件注册
MCEventBus.INSTANCE.unregister(INSTANCE);
}
}
}
}

View File

@ -0,0 +1,7 @@
package com.expvintl.mctools.events;
import com.google.common.eventbus.EventBus;
public class MCEventBus {
public static EventBus INSTANCE=new EventBus();
}

View File

@ -0,0 +1,12 @@
package com.expvintl.mctools.events.client;
import net.minecraft.client.gui.screen.Screen;
public class OpenScreenEvent {
private static final OpenScreenEvent INSTANCE=new OpenScreenEvent();
public Screen screen;
public static OpenScreenEvent get(Screen screen){
INSTANCE.screen=screen;
return INSTANCE;
}
}

View File

@ -0,0 +1,12 @@
package com.expvintl.mctools.events.network;
import net.minecraft.network.packet.Packet;
public class PacketEvent {
private static final PacketEvent INSTANCE=new PacketEvent();
public Packet<?> packet;
public static PacketEvent get(Packet<?> pack){
INSTANCE.packet=pack;
return INSTANCE;
}
}

View File

@ -0,0 +1,16 @@
package com.expvintl.mctools.events.player;
import net.minecraft.network.packet.Packet;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
public class PlayerAttackBlockEvent {
private static final PlayerAttackBlockEvent INSTANCE=new PlayerAttackBlockEvent();
public BlockPos blockPos;
public Direction direction;
public static PlayerAttackBlockEvent get(BlockPos blockPos, Direction direction){
INSTANCE.blockPos=blockPos;
INSTANCE.direction=direction;
return INSTANCE;
}
}

View File

@ -0,0 +1,14 @@
package com.expvintl.mctools.events.player;
import net.minecraft.util.math.BlockPos;
import org.lwjgl.system.windows.INPUT;
public class PlayerBreakBlockEvent {
private static final PlayerBreakBlockEvent INSTANCE=new PlayerBreakBlockEvent();
public BlockPos pos;
public static PlayerBreakBlockEvent get(BlockPos blockPos){
INSTANCE.pos=blockPos;
return INSTANCE;
}
}

View File

@ -1,6 +1,8 @@
package com.expvintl.mctools.mixin;
import com.expvintl.mctools.FeaturesBool;
import com.expvintl.mctools.events.MCEventBus;
import com.expvintl.mctools.events.client.OpenScreenEvent;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.DeathScreen;
import net.minecraft.client.gui.screen.Screen;
@ -14,13 +16,6 @@ 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();
}
}
}
MCEventBus.INSTANCE.post(OpenScreenEvent.get(screen));
}
}

View File

@ -1,46 +1,20 @@
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 com.expvintl.mctools.events.MCEventBus;
import com.expvintl.mctools.events.network.PacketEvent;
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;
}
}
//传入事件
MCEventBus.INSTANCE.post(PacketEvent.get(packet));
}
}

View File

@ -1,5 +1,9 @@
package com.expvintl.mctools.mixin.player;
import com.expvintl.mctools.FeaturesBool;
import com.expvintl.mctools.events.MCEventBus;
import com.expvintl.mctools.events.player.PlayerAttackBlockEvent;
import com.expvintl.mctools.events.player.PlayerBreakBlockEvent;
import com.expvintl.mctools.mixin.interfaces.IClientPlayerInteractionManager;
import net.minecraft.block.BambooBlock;
import net.minecraft.block.BambooSaplingBlock;
@ -14,45 +18,20 @@ 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.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ClientPlayerInteractionManager.class)
public abstract class ClientPlayerInteractionManagerMixin implements IClientPlayerInteractionManager {
@Shadow
protected abstract void syncSelectedSlot();
public class ClientPlayerInteractionManagerMixin {
@Inject(method = "breakBlock",at=@At("HEAD"))
private void breakBlock(BlockPos pos, CallbackInfoReturnable<Boolean> cir){
MCEventBus.INSTANCE.post(PlayerBreakBlockEvent.get(pos));
}
@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();
MCEventBus.INSTANCE.post(PlayerAttackBlockEvent.get(blockPos,direction));
}
}