Chest aura improvements (#208)

This commit is contained in:
Soda5601
2023-01-22 01:29:36 +08:00
committed by GitHub
parent 704b7989f1
commit 6a3a8b6d58
4 changed files with 135 additions and 159 deletions

View File

@@ -0,0 +1,27 @@
package anticope.rejects.mixin.meteor.modules;
import anticope.rejects.mixininterface.IInventoryTweaks;
import meteordevelopment.meteorclient.systems.modules.misc.InventoryTweaks;
import net.minecraft.screen.ScreenHandler;
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 = InventoryTweaks.class, remap = false)
public abstract class InventoryTweaksMixin implements IInventoryTweaks {
private Runnable callback;
@Inject(method = "lambda$steal$3", at = @At("RETURN"))
private void afterSteal(ScreenHandler handler, CallbackInfo info) {
if (callback != null) {
callback.run();
callback = null;
}
}
@Inject(method = "lambda$new$1", at = @At("HEAD"))
private void onStealChanged(Boolean b, CallbackInfo info) {
callback = null;
}
}

View File

@@ -0,0 +1,5 @@
package anticope.rejects.mixininterface;
public interface IInventoryTweaks {
void afterSteal(Runnable callback);
}

View File

@@ -1,57 +1,41 @@
package anticope.rejects.modules; package anticope.rejects.modules;
import anticope.rejects.MeteorRejectsAddon; import anticope.rejects.MeteorRejectsAddon;
import meteordevelopment.orbit.EventHandler; import anticope.rejects.mixininterface.IInventoryTweaks;
import meteordevelopment.meteorclient.events.game.OpenScreenEvent; import com.mojang.blaze3d.systems.RenderSystem;
import meteordevelopment.meteorclient.MeteorClient;
import meteordevelopment.meteorclient.events.packets.InventoryEvent;
import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.meteorclient.events.world.TickEvent;
import meteordevelopment.meteorclient.settings.BlockListSetting; import meteordevelopment.meteorclient.settings.*;
import meteordevelopment.meteorclient.settings.BoolSetting;
import meteordevelopment.meteorclient.settings.DoubleSetting;
import meteordevelopment.meteorclient.settings.EnumSetting;
import meteordevelopment.meteorclient.settings.IntSetting;
import meteordevelopment.meteorclient.settings.Setting;
import meteordevelopment.meteorclient.settings.SettingGroup;
import meteordevelopment.meteorclient.systems.modules.Module; import meteordevelopment.meteorclient.systems.modules.Module;
import meteordevelopment.meteorclient.utils.misc.Pool; import meteordevelopment.meteorclient.systems.modules.Modules;
import meteordevelopment.meteorclient.systems.modules.misc.InventoryTweaks;
import meteordevelopment.meteorclient.utils.Utils;
import meteordevelopment.meteorclient.utils.player.Rotations; import meteordevelopment.meteorclient.utils.player.Rotations;
import meteordevelopment.meteorclient.utils.world.BlockIterator; import meteordevelopment.orbit.EventHandler;
import meteordevelopment.meteorclient.utils.world.BlockUtils; import meteordevelopment.orbit.EventPriority;
import net.minecraft.block.BlockState;
import java.util.ArrayList; import net.minecraft.block.ChestBlock;
import java.util.Arrays; import net.minecraft.block.entity.BlockEntity;
import java.util.List; import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.item.ItemStack;
import net.minecraft.block.AbstractChestBlock; import net.minecraft.screen.ScreenHandler;
import net.minecraft.block.AbstractFurnaceBlock;
import net.minecraft.block.BarrelBlock;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.BrewingStandBlock;
import net.minecraft.block.DispenserBlock;
import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
import net.minecraft.item.Items;
import net.minecraft.network.packet.c2s.play.CloseHandledScreenC2SPacket;
import net.minecraft.screen.GenericContainerScreenHandler;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ChestAura extends Module { public class ChestAura extends Module {
public enum CloseScreen {
Always,
IfEmpty,
Never
}
private final SettingGroup sgGeneral = settings.getDefaultGroup(); private final SettingGroup sgGeneral = settings.getDefaultGroup();
private final Setting<Boolean> rotate = sgGeneral.add(new BoolSetting.Builder() private final Setting<Boolean> rotate = sgGeneral.add(new BoolSetting.Builder()
.name("rotate") .name("rotate")
.description("Rotates when placing") .description("Rotates when opening.")
.defaultValue(true) .defaultValue(true)
.build() .build()
); );
@@ -64,157 +48,116 @@ public class ChestAura extends Module {
.build() .build()
); );
private final Setting<List<Block>> blockTypes = sgGeneral.add(new BlockListSetting.Builder() private final Setting<List<BlockEntityType<?>>> blocks = sgGeneral.add(new StorageBlockListSetting.Builder()
.name("storage-blocks") .name("blocks")
.description("The blocks you open.") .description("The blocks you open.")
.filter(this::predicate) .defaultValue(BlockEntityType.CHEST)
.defaultValue(Arrays.asList(Blocks.CHEST)) .build()
.build()
); );
private final Setting<Integer> bpt = sgGeneral.add(new IntSetting.Builder() private final Setting<Integer> delay = sgGeneral.add(new IntSetting.Builder()
.name("opens-per-tick") .name("delay")
.description("How many blocks to open per tick") .description("Delay between opening chests.")
.defaultValue(2) .defaultValue(10)
.min(1) .sliderMax(20)
.sliderMax(8) .build()
.build()
); );
private final Setting<Integer> forgetAfter = sgGeneral.add(new IntSetting.Builder() private final Setting<Integer> forget = sgGeneral.add(new IntSetting.Builder()
.name("forget-after") .name("forget-after")
.description("How many ticks to wait before forgetting which chest to open. 0 for infinite") .description("How many ticks to wait before forgetting which chest to open. 0 for infinite.")
.defaultValue(0) .defaultValue(0)
.min(0) .min(0)
.sliderMax(1000) .sliderMax(1000)
.build() .build()
); );
private final Setting<CloseScreen> closeScreen = sgGeneral.add(new EnumSetting.Builder<CloseScreen>() private final Setting<CloseCondition> closeCondition = sgGeneral.add(new EnumSetting.Builder<CloseCondition>()
.name("close-screen") .name("close-condition")
.defaultValue(CloseScreen.IfEmpty) .defaultValue(CloseCondition.IfEmpty)
.description("when to close the chest screen") .description("When to close the chest screen.")
.build() .build()
); );
private final Pool<BlockPos.Mutable> blockPosPool = new Pool<>(BlockPos.Mutable::new); private final Map<BlockPos, Integer> openedBlocks = new HashMap<>();
private final List<BlockPos.Mutable> blocks = new ArrayList<>(); private final CloseListener closeListener = new CloseListener();
private final List<BlockPos.Mutable> clickedBlocks = new ArrayList<>();
int cap = 0; private int timer = 0;
int forget = 0;
public ChestAura() { public ChestAura() {
super(MeteorRejectsAddon.CATEGORY, "chest-aura", "Automatically open chests in radius"); super(MeteorRejectsAddon.CATEGORY, "chest-aura", "Automatically open chests in radius");
} }
@Override @Override
public void onDeactivate() { public void onActivate() {
for (BlockPos.Mutable blockPos : blocks) blockPosPool.free(blockPos); timer = 0;
for (BlockPos.Mutable blockPos : clickedBlocks) blockPosPool.free(blockPos); openedBlocks.clear();
blocks.clear();
clickedBlocks.clear();
} }
@EventHandler @EventHandler
private void onTick(TickEvent.Pre event) { private void onTick(TickEvent.Pre event) {
if (forget.get() != 0) {
BlockIterator.register((int) Math.floor(range.get()), (int) Math.floor(range.get()), (blockPos, blockState) -> { for (Map.Entry<BlockPos, Integer> e : new HashMap<>(openedBlocks).entrySet()) {
if (!BlockUtils.canBreak(blockPos, blockState)) return; int time = e.getValue();
if (time > forget.get()) openedBlocks.remove(e.getKey());
if (!(blockTypes.get().contains(blockState.getBlock()))) return; else openedBlocks.replace(e.getKey(), time + 1);
if (clickedBlocks.contains(blockPos)) return;
blocks.add(blockPosPool.get().set(blockPos));
});
if (forgetAfter.get() > 0) {
if (forget >= forgetAfter.get()) {
forget = 0;
for (BlockPos.Mutable blockPos : clickedBlocks) blockPosPool.free(blockPos);
clickedBlocks.clear();
} }
} }
}
@EventHandler if (timer > 0 && mc.currentScreen != null) return;
private void onTickPost(TickEvent.Post event) {
if (mc.currentScreen == null) { for (BlockEntity block : Utils.blockEntities()) {
for (BlockPos blockPos : blocks) { if (!blocks.get().contains(block.getType())) continue;
if (clickedBlocks.contains(blockPos)) continue; if (mc.player.getEyePos().distanceTo(Vec3d.ofCenter(block.getPos())) >= range.get()) continue;
if (mc.currentScreen != null) return;
if (cap >= bpt.get()) { BlockPos pos = block.getPos();
cap = 0; if (openedBlocks.containsKey(pos)) continue;
return;
Runnable click = () -> mc.interactionManager.interactBlock(mc.player, Hand.MAIN_HAND, new BlockHitResult(new Vec3d(pos.getX(), pos.getY(), pos.getZ()), Direction.UP, pos, false));
if (rotate.get()) Rotations.rotate(Rotations.getYaw(pos), Rotations.getPitch(pos), click);
else click.run();
// Double chest compatibility
BlockState state = block.getCachedState();
if (state.contains(ChestBlock.CHEST_TYPE)) {
Direction direction = state.get(ChestBlock.FACING);
switch (state.get(ChestBlock.CHEST_TYPE)) {
case LEFT -> openedBlocks.put(pos.offset(direction.rotateYClockwise()), 0);
case RIGHT -> openedBlocks.put(pos.offset(direction.rotateYCounterclockwise()), 0);
} }
if (rotate.get()) {
Rotations.rotate(Rotations.getYaw(blockPos), Rotations.getPitch(blockPos), () -> {
click(blockPos);
clickedBlocks.add(blockPosPool.get().set(blockPos));
});
} else {
click(blockPos);
clickedBlocks.add(blockPosPool.get().set(blockPos));
}
cap++;
} }
} else if (mc.currentScreen instanceof GenericContainerScreen containerScreen) {
closeIfEmpty(containerScreen.getScreenHandler()); openedBlocks.put(pos, 0);
timer = delay.get();
MeteorClient.EVENT_BUS.subscribe(closeListener);
break;
} }
timer--;
} }
private boolean predicate(Block block) { public class CloseListener {
return ( @EventHandler(priority = EventPriority.HIGH)
block instanceof AbstractChestBlock || private void onInventory(InventoryEvent event) {
block instanceof ShulkerBoxBlock || ScreenHandler handler = mc.player.currentScreenHandler;
block instanceof BarrelBlock || if (event.packet.getSyncId() == handler.syncId) {
block instanceof BrewingStandBlock || switch (closeCondition.get()) {
block instanceof DispenserBlock || case IfEmpty -> {
block instanceof AbstractFurnaceBlock if (handler.getStacks().stream().allMatch(ItemStack::isEmpty))
); mc.player.closeHandledScreen();
} }
case Always -> mc.player.closeHandledScreen();
private void click(BlockPos pos) { case AfterSteal ->
mc.interactionManager.interactBlock(mc.player, Hand.MAIN_HAND, new BlockHitResult( ((IInventoryTweaks) Modules.get().get(InventoryTweaks.class)).afterSteal(() -> RenderSystem.recordRenderCall(() -> mc.player.closeHandledScreen()));
new Vec3d(pos.getX(), pos.getY(), pos.getZ()),
Direction.UP,
pos,
false
));
}
private void closeIfEmpty(GenericContainerScreenHandler handler) {
switch (closeScreen.get()) {
case IfEmpty: {
if (!handler.getInventory().containsAny(item -> {
return !item.isEmpty();
})) {
if (!handler.getCursorStack().isEmpty()) return;
mc.getNetworkHandler().sendPacket(new CloseHandledScreenC2SPacket(handler.syncId));
mc.setScreen(null);
} }
break;
} }
MeteorClient.EVENT_BUS.unsubscribe(this);
case Always: {
mc.getNetworkHandler().sendPacket(new CloseHandledScreenC2SPacket(handler.syncId));
mc.setScreen(null);
break;
}
default:
break;
} }
} }
@EventHandler public enum CloseCondition {
private void onOpenScreen(OpenScreenEvent event) { Always,
if (!(event.screen instanceof GenericContainerScreen containerScreen)) return; IfEmpty,
closeIfEmpty(containerScreen.getScreenHandler()); AfterSteal,
Never
} }
} }

View File

@@ -12,6 +12,7 @@
"DefaultSettingsWidgetFactoryMixin", "DefaultSettingsWidgetFactoryMixin",
"modules.FlightMixin", "modules.FlightMixin",
"modules.NoRenderAccessor", "modules.NoRenderAccessor",
"modules.AutoSignMixin" "modules.AutoSignMixin",
"modules.InventoryTweaksMixin"
] ]
} }