diff options
Diffstat (limited to 'src/main/java')
18 files changed, 605 insertions, 99 deletions
diff --git a/src/main/java/ftbsc/bscv/Boscovicino.java b/src/main/java/ftbsc/bscv/Boscovicino.java index a720cb0..930e457 100644 --- a/src/main/java/ftbsc/bscv/Boscovicino.java +++ b/src/main/java/ftbsc/bscv/Boscovicino.java @@ -8,6 +8,7 @@ import ftbsc.bscv.api.IModule; import ftbsc.bscv.patches.CommandsPatch.CommandsBuiltEvent; import ftbsc.bscv.system.Friends; import ftbsc.bscv.system.ModManager; +import ftbsc.bscv.system.Ruler; import net.minecraft.client.gui.screen.IngameMenuScreen; import net.minecraft.client.gui.widget.button.Button; import net.minecraft.command.CommandSource; @@ -42,6 +43,9 @@ public class Boscovicino implements ICommons { private static Friends friends; public static Friends friends() { return Boscovicino.friends; } + @SuppressWarnings("unused") // it just needs to exist to be used by player + private static Ruler ruler; + public Boscovicino() { FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onSetupComplete); @@ -53,6 +57,8 @@ public class Boscovicino implements ICommons { Boscovicino.modManager.finish(); + Boscovicino.ruler = new Ruler(); + Boscovicino.spec = cfg.build(); ForgeConfigSpec.Builder friendSpec = new ForgeConfigSpec.Builder(); diff --git a/src/main/java/ftbsc/bscv/commands/BlockSearch.java b/src/main/java/ftbsc/bscv/commands/BlockSearch.java new file mode 100644 index 0000000..dd5f663 --- /dev/null +++ b/src/main/java/ftbsc/bscv/commands/BlockSearch.java @@ -0,0 +1,57 @@ +package ftbsc.bscv.commands; + +import com.google.auto.service.AutoService; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; + +import ftbsc.bscv.api.ILoadable; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.command.CommandSource; +import net.minecraft.command.Commands; + +import static ftbsc.bscv.Boscovicino.log; + +@AutoService(ILoadable.class) +public class BlockSearch extends AbstractCommand { + + @Override + public String getName() { return "block"; } + + public LiteralArgumentBuilder<CommandSource> register(LiteralArgumentBuilder<CommandSource> builder) { + return builder + .then( + Commands.literal("search") + .then( + Commands.argument("id", IntegerArgumentType.integer(0)) + .executes( ctx -> { + int block_id = ctx.getArgument("id", Integer.class); + int block_number = block_id >> 4; + int block_meta = block_id & 0b1111; + BlockState state = Block.stateById(block_id); + log("block #[%d:%d]::%d >> %s", block_number, block_meta, block_id, state.toString()); + return 1; + }) + ) + .then( + Commands.argument("number", IntegerArgumentType.integer(0)) + .then( + Commands.argument("meta", IntegerArgumentType.integer(0)) + .executes( ctx -> { + int block_number = ctx.getArgument("number", Integer.class); + int block_meta = ctx.getArgument("meta", Integer.class); + int block_id = (block_number << 4) | block_meta; + BlockState state = Block.stateById(block_id); + log("block #[%d:%d]::%d >> %s", block_number, block_meta, block_id, state.toString()); + return 1; + }) + ) + ) + ) + .executes(ctx -> { + log("no block specified"); + return 0; + }); + } + +} diff --git a/src/main/java/ftbsc/bscv/commands/Cursor.java b/src/main/java/ftbsc/bscv/commands/Cursor.java index 49a93aa..a54433d 100644 --- a/src/main/java/ftbsc/bscv/commands/Cursor.java +++ b/src/main/java/ftbsc/bscv/commands/Cursor.java @@ -4,6 +4,7 @@ import com.google.auto.service.AutoService; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import ftbsc.bscv.api.ILoadable; +import net.minecraft.block.BlockState; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; import net.minecraft.util.Direction; @@ -18,17 +19,18 @@ public class Cursor extends AbstractCommand { public LiteralArgumentBuilder<CommandSource> register(LiteralArgumentBuilder<CommandSource> builder) { return builder .then( - Commands.literal("pos") + Commands.literal("info") .executes(ctx -> { switch (MC.hitResult.getType()) { case BLOCK: BlockRayTraceResult result = (BlockRayTraceResult) MC.hitResult; Direction dir = result.getDirection(); - BlockPos pos =result.getBlockPos(); - log("Block @ %s (%s)", pos.toString(), dir.toString()); + BlockPos pos = result.getBlockPos(); + BlockState state = MC.level.getBlockState(pos); + log("Block @ %s (%s): %s", pos.toString(), dir.toString(), state.toString()); return 1; case ENTITY: - log("Entity @ %s", MC.hitResult.getLocation().toString()); + log("Entity @ %s (TODO!)", MC.hitResult.getLocation().toString()); return 1; default: case MISS: diff --git a/src/main/java/ftbsc/bscv/commands/Item.java b/src/main/java/ftbsc/bscv/commands/ItemCommand.java index 2d4bd7f..e1e1b80 100644 --- a/src/main/java/ftbsc/bscv/commands/Item.java +++ b/src/main/java/ftbsc/bscv/commands/ItemCommand.java @@ -1,6 +1,7 @@ package ftbsc.bscv.commands; import com.google.auto.service.AutoService; +import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import ftbsc.bscv.api.ILoadable; @@ -8,11 +9,15 @@ import ftbsc.bscv.tools.Inventory; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; import net.minecraft.inventory.container.Slot; +import net.minecraft.item.Item; import static ftbsc.bscv.Boscovicino.log; @AutoService(ILoadable.class) -public class Item extends AbstractCommand { +public class ItemCommand extends AbstractCommand { + + @Override + public String getName() { return "item"; } public LiteralArgumentBuilder<CommandSource> register(LiteralArgumentBuilder<CommandSource> builder) { return builder @@ -32,6 +37,17 @@ public class Item extends AbstractCommand { return 1; }) ) + .then( + Commands.literal("search") + .then( + Commands.argument("id", IntegerArgumentType.integer(0)) + .executes(ctx -> { + int item_id = ctx.getArgument("id", Integer.class); + log("item #[%d] >> %s", item_id, Item.byId(item_id).toString()); + return 1; + }) + ) + ) .executes(ctx -> { Slot slot = Inventory.hotbar(MC.player).get(MC.player.inventory.selected); if (!slot.hasItem()) return 0; diff --git a/src/main/java/ftbsc/bscv/commands/ModCommands.java b/src/main/java/ftbsc/bscv/commands/ModCommands.java index 82e8661..57e1887 100644 --- a/src/main/java/ftbsc/bscv/commands/ModCommands.java +++ b/src/main/java/ftbsc/bscv/commands/ModCommands.java @@ -9,7 +9,7 @@ import ftbsc.bscv.api.IModule; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; -import static ftbsc.bscv.Boscovicino.log; +import java.util.stream.Collectors; @AutoService(ILoadable.class) public class ModCommands extends AbstractCommand { @@ -43,8 +43,11 @@ public class ModCommands extends AbstractCommand { }) ) .executes(ctx -> { - log("no args specified"); - return 0; + String mods = Boscovicino.modManager.mods.stream() + .map(x -> x.getName()) + .collect(Collectors.joining(",")); + Boscovicino.log("[ %s ]", mods); + return 1; }); } diff --git a/src/main/java/ftbsc/bscv/modules/QuickModule.java b/src/main/java/ftbsc/bscv/modules/QuickModule.java index 009a057..648b020 100644 --- a/src/main/java/ftbsc/bscv/modules/QuickModule.java +++ b/src/main/java/ftbsc/bscv/modules/QuickModule.java @@ -1,6 +1,7 @@ package ftbsc.bscv.modules; import ftbsc.bscv.Boscovicino; +import ftbsc.bscv.tools.Keybind; import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.util.InputMappings; import net.minecraftforge.client.event.InputEvent; @@ -51,7 +52,7 @@ public abstract class QuickModule extends AbstractModule { public QuickModule() { super(); - this.keybind = new KeyBinding(key_name(this.getName()), this.getDefaultKey(), key_category()); + this.keybind = new KeyBinding(Keybind.name(this.getName()), this.getDefaultKey(), Keybind.category()); ClientRegistry.registerKeyBinding(this.keybind); // register a separate subclass on the hook, so that it's always listening @@ -76,12 +77,4 @@ public abstract class QuickModule extends AbstractModule { // ); } - private static String key_name(String name) { - return String.format("key.%s.%s", Boscovicino.MOD_ID, name); - } - - private static String key_category() { - return String.format("key.category.%s", Boscovicino.MOD_ID); - } - } diff --git a/src/main/java/ftbsc/bscv/modules/defense/Aura.java b/src/main/java/ftbsc/bscv/modules/defense/Aura.java index f031f2c..e38be1e 100644 --- a/src/main/java/ftbsc/bscv/modules/defense/Aura.java +++ b/src/main/java/ftbsc/bscv/modules/defense/Aura.java @@ -52,7 +52,7 @@ public class Aura extends QuickModule { this.reach = Setting.Decimal.builder() .min(0.) - .fallback(5.) + .fallback(4.) .name("reach") .comment("aura attack reach") .build(this); diff --git a/src/main/java/ftbsc/bscv/modules/hud/Highlighter.java b/src/main/java/ftbsc/bscv/modules/hud/Highlighter.java index a5fa0e5..f5cc542 100644 --- a/src/main/java/ftbsc/bscv/modules/hud/Highlighter.java +++ b/src/main/java/ftbsc/bscv/modules/hud/Highlighter.java @@ -4,6 +4,7 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import ftbsc.bscv.modules.AbstractModule; +import ftbsc.bscv.tools.Inventory; import ftbsc.bscv.tools.Setting; import net.minecraft.client.gui.screen.inventory.ContainerScreen; import net.minecraft.inventory.container.Slot; @@ -48,38 +49,6 @@ public class Highlighter extends AbstractModule { this.pattern = Pattern.compile(this.query.get()); } - private List<String> enchantments(ItemStack stack) { - final ListNBT tags; - if (Items.ENCHANTED_BOOK.equals(stack.getItem())) { - tags = EnchantedBookItem.getEnchantments(stack); // special case to also search book enchants - } else { - tags = stack.getEnchantmentTags(); - } - - List<String> out = new ArrayList<>(); - for (int i = 0; i < tags.size(); i++) { - CompoundNBT tag = tags.getCompound(i); - out.add(String.format("%s %s", tag.getString("id"), tag.getInt("lvl"))); - } - - return out; - } - - private boolean matches(ItemStack stack) { - if (stack.isEmpty()) return false; - - String displayName = stack.getDisplayName().getString(); - if (this.pattern.matcher(displayName).find()) return true; - - if (Items.ENCHANTED_BOOK.equals(stack.getItem()) || stack.isEnchanted()) { - for (String ench : this.enchantments(stack)) { - if (this.pattern.matcher(ench).find()) return true; - } - } - - return false; - } - @SubscribeEvent public void onGuiContainerDraw(GuiContainerEvent.DrawBackground event) { MatrixStack matrix = event.getMatrixStack(); @@ -91,7 +60,7 @@ public class Highlighter extends AbstractModule { for (Slot slot : screen.getMenu().slots) { ItemStack stack = slot.getItem(); - if (this.matches(stack)) { + if (Inventory.matchItem(this.pattern, stack)) { GuiUtils.drawGradientRect( matrix.last().pose(), 0, slot.x, slot.y, slot.x + 16, slot.y + 16, diff --git a/src/main/java/ftbsc/bscv/modules/motion/VanillaFlight.java b/src/main/java/ftbsc/bscv/modules/motion/VanillaFlight.java index df00eda..0d1d736 100644 --- a/src/main/java/ftbsc/bscv/modules/motion/VanillaFlight.java +++ b/src/main/java/ftbsc/bscv/modules/motion/VanillaFlight.java @@ -40,24 +40,24 @@ public class VanillaFlight extends QuickModule { this.force = Setting.Bool.builder() .name("force") .comment("force enable flight on user") - .fallback(false) + .fallback(true) .build(this); this.drift = Setting.Bool.builder() .name("drift") .comment("gradually reduce momentum") - .fallback(true) + .fallback(false) .build(this); this.speed = Setting.Decimal.builder() .min(0.) - .fallback(0.05) + .fallback(0.1) .name("speed") .comment("flight speed to set") .build(this); this.antikick = Setting.Switch.builder(AntikickMode.class) - .fallback(AntikickMode.NONE) + .fallback(AntikickMode.PACKET) .name("antikick") .comment("prevent vanilla flight kick by descending") .build(this); diff --git a/src/main/java/ftbsc/bscv/modules/self/AutoTool.java b/src/main/java/ftbsc/bscv/modules/self/AutoTool.java index 1474085..c37a8a2 100644 --- a/src/main/java/ftbsc/bscv/modules/self/AutoTool.java +++ b/src/main/java/ftbsc/bscv/modules/self/AutoTool.java @@ -1,11 +1,14 @@ package ftbsc.bscv.modules.self; import com.google.auto.service.AutoService; + +import ftbsc.bscv.Boscovicino; import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.modules.AbstractModule; import ftbsc.bscv.tools.Inventory; import ftbsc.bscv.tools.Setting; import net.minecraft.block.BlockState; +import net.minecraft.enchantment.Enchantments; import net.minecraft.inventory.container.Slot; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockRayTraceResult; @@ -19,6 +22,7 @@ import java.util.List; public class AutoTool extends AbstractModule { public final ForgeConfigSpec.ConfigValue<Integer> limit; + public final ForgeConfigSpec.ConfigValue<Boolean> prefer_looting; public AutoTool() { super(); @@ -28,6 +32,12 @@ public class AutoTool extends AbstractModule { .comment("durability limit for tools, set to 0 to destroy them") .fallback(1) .build(this); + + this.prefer_looting = Setting.Bool.builder() + .name("prefer-looting") + .comment("when picking best weapon, prefer looting over slight more DPS") + .fallback(true) + .build(this); } private boolean itemIsTooDamaged(ItemStack item) { @@ -47,6 +57,12 @@ public class AutoTool extends AbstractModule { } double damage = Inventory.itemDPS(item); + + int looting = Inventory.getEnchLevel(item, Enchantments.MOB_LOOTING); + if (this.prefer_looting.get() && looting > 0) { + damage += 0.1 * looting; + } + if (damage > current_damage) { current_slot = i; current_damage = damage; diff --git a/src/main/java/ftbsc/bscv/modules/self/ContainerCleaner.java b/src/main/java/ftbsc/bscv/modules/self/ContainerCleaner.java new file mode 100644 index 0000000..c53fed0 --- /dev/null +++ b/src/main/java/ftbsc/bscv/modules/self/ContainerCleaner.java @@ -0,0 +1,79 @@ +package ftbsc.bscv.modules.self; + +import java.util.ArrayList; +import java.util.List; + +import com.google.auto.service.AutoService; + +import ftbsc.bscv.api.ILoadable; +import ftbsc.bscv.modules.AbstractModule; +import ftbsc.bscv.tools.Inventory; +import ftbsc.bscv.tools.Setting; +import net.minecraft.client.gui.screen.inventory.ContainerScreen; +import net.minecraft.command.arguments.ItemArgument; +import net.minecraft.command.arguments.ItemInput; +import net.minecraft.inventory.container.ClickType; +import net.minecraft.inventory.container.Slot; +import net.minecraft.item.Item; +import net.minecraftforge.common.ForgeConfigSpec; +import net.minecraftforge.event.TickEvent.ClientTickEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +@AutoService(ILoadable.class) +public class ContainerCleaner extends AbstractModule { + + public final ForgeConfigSpec.ConfigValue<Integer> cooldown; + public final ForgeConfigSpec.ConfigValue<Boolean> limit; + public final ForgeConfigSpec.ConfigValue<Boolean> all; + public final ForgeConfigSpec.ConfigValue<List<? extends Integer>> blacklist; + private int counter; + + public ContainerCleaner() { + super(); + + this.counter = 0; + this.cooldown = Setting.Number.builder() + .fallback(0) + .name("cooldown") + .comment("ticks before throwing next item") + .build(this); + + this.limit = Setting.Bool.builder() + .fallback(true) + .name("limit") + .comment("limit to one action per tick") + .build(this); + + this.all = Setting.Bool.builder() + .fallback(true) + .name("all") + .comment("throw whole stacks instead of single items") + .build(this); + + this.blacklist = new Setting.Many<ItemInput, Integer>(ItemArgument.item(), ItemInput.class) + .writer(x -> Item.getId(x.getItem())) + .fallback(new ArrayList<Integer>()) + .name("blacklist") + .comment("items to throw away") + .build(this); + } + + @SubscribeEvent + public void onTick(ClientTickEvent event) { + if (MC.screen == null) return; + if (!(MC.screen instanceof ContainerScreen)) return; + if (this.counter > 0) { + this.counter -= 1; + return; + } + ContainerScreen<?> screen = (ContainerScreen<?>) MC.screen; + for (Slot slot : screen.getMenu().slots) { + if (this.blacklist.get().contains(Item.getId(slot.getItem().getItem()))) { + int button = this.all.get() ? 1 : 0; + Inventory.clickSlot(screen.getMenu().containerId, slot.index, button, ClickType.THROW); + this.counter = this.cooldown.get(); + if (this.limit.get()) return; // only throw one item per tick + } + } + } +} diff --git a/src/main/java/ftbsc/bscv/modules/self/FastCraft.java b/src/main/java/ftbsc/bscv/modules/self/FastCraft.java new file mode 100644 index 0000000..d4aaa77 --- /dev/null +++ b/src/main/java/ftbsc/bscv/modules/self/FastCraft.java @@ -0,0 +1,39 @@ +package ftbsc.bscv.modules.self; + +import com.google.auto.service.AutoService; +import ftbsc.bscv.api.ILoadable; +import ftbsc.bscv.modules.AbstractModule; +import ftbsc.bscv.tools.Inventory; +import ftbsc.bscv.tools.Setting; +import net.minecraft.client.gui.screen.inventory.InventoryScreen; +import net.minecraft.inventory.container.ClickType; +import net.minecraftforge.common.ForgeConfigSpec; +import net.minecraftforge.event.TickEvent.ClientTickEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +@AutoService(ILoadable.class) +public class FastCraft extends AbstractModule { + + public final ForgeConfigSpec.ConfigValue<Boolean> drop; + + public FastCraft() { + super(); + + this.drop = Setting.Bool.builder() + .fallback(false) + .name("drop") + .comment("throw cradted items away instead of moving them back in inventory") + .build(this); + } + + @SubscribeEvent + public void onTick(ClientTickEvent event) { + if (MC.screen == null) return; + if (!(MC.screen instanceof InventoryScreen)) return; + InventoryScreen inventory = (InventoryScreen) MC.screen; + if (inventory.getMenu().slots.get(0).hasItem()) { + // TODO can we throw them all? like this it throws one by one + Inventory.clickSlot(0, this.drop.get() ? ClickType.THROW : ClickType.QUICK_MOVE); + } + } +} diff --git a/src/main/java/ftbsc/bscv/modules/self/HandChanger.java b/src/main/java/ftbsc/bscv/modules/self/HandChanger.java new file mode 100644 index 0000000..c7f8a03 --- /dev/null +++ b/src/main/java/ftbsc/bscv/modules/self/HandChanger.java @@ -0,0 +1,72 @@ +package ftbsc.bscv.modules.self; + +import com.google.auto.service.AutoService; +import ftbsc.bscv.api.ILoadable; +import ftbsc.bscv.modules.AbstractModule; +import ftbsc.bscv.tools.Setting; +import net.minecraftforge.client.event.RenderHandEvent; +import net.minecraftforge.common.ForgeConfigSpec; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +@AutoService(ILoadable.class) +public class HandChanger extends AbstractModule { + + public final ForgeConfigSpec.ConfigValue<Double> main; + public final ForgeConfigSpec.ConfigValue<Double> off; + public final ForgeConfigSpec.ConfigValue<Boolean> cancel_main; + public final ForgeConfigSpec.ConfigValue<Boolean> cancel_off; + + public HandChanger() { + super(); + + this.main = Setting.Decimal.builder() + .min(0.) + .max(1.) + .name("main") + .comment("height of main hand") + .fallback(1.) + .build(this); + + this.off = Setting.Decimal.builder() + .min(0.) + .max(1.) + .name("off") + .comment("height of off hand") + .fallback(1.) + .build(this); + + this.cancel_main = Setting.Bool.builder() + .name("cancel-main") + .comment("completely prevent main hand rendering") + .fallback(false) + .build(this); + + this.cancel_off = Setting.Bool.builder() + .name("cancel-off") + .comment("completely prevent off hand rendering") + .fallback(false) + .build(this); + } + + @SubscribeEvent + public void onRenderHands(RenderHandEvent event) { + switch (event.getHand()) { + case MAIN_HAND: + if (this.cancel_main.get()) { + event.setCanceled(true); + } else if (this.main.get() != 1.0) { + MC.gameRenderer.itemInHandRenderer.mainHandHeight = this.main.get().floatValue(); // ACCESSTRANSFORMER public net.minecraft.client.renderer.FirstPersonRenderer field_187469_f + MC.gameRenderer.itemInHandRenderer.oMainHandHeight = this.main.get().floatValue(); // ACCESSTRANSFORMER public net.minecraft.client.renderer.FirstPersonRenderer field_187469_f + } + break; + case OFF_HAND: + if (this.cancel_off.get()) { + event.setCanceled(true); + } else if (this.off.get() != 1.0) { + MC.gameRenderer.itemInHandRenderer.offHandHeight = this.off.get().floatValue(); // ACCESSTRANSFORMER public net.minecraft.client.renderer.FirstPersonRenderer field_187470_g + MC.gameRenderer.itemInHandRenderer.oOffHandHeight = this.off.get().floatValue(); // ACCESSTRANSFORMER public net.minecraft.client.renderer.FirstPersonRenderer field_187470_g + } + break; + } + } +} diff --git a/src/main/java/ftbsc/bscv/modules/hud/NoOverlay.java b/src/main/java/ftbsc/bscv/modules/self/NoOverlay.java index 474c759..d2b02cf 100644 --- a/src/main/java/ftbsc/bscv/modules/hud/NoOverlay.java +++ b/src/main/java/ftbsc/bscv/modules/self/NoOverlay.java @@ -1,4 +1,4 @@ -package ftbsc.bscv.modules.hud; +package ftbsc.bscv.modules.self; import com.google.auto.service.AutoService; diff --git a/src/main/java/ftbsc/bscv/system/Ruler.java b/src/main/java/ftbsc/bscv/system/Ruler.java new file mode 100644 index 0000000..bb4c012 --- /dev/null +++ b/src/main/java/ftbsc/bscv/system/Ruler.java @@ -0,0 +1,85 @@ +package ftbsc.bscv.system; + +import ftbsc.bscv.ICommons; +import ftbsc.bscv.tools.Keybind; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.client.util.InputMappings; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.RayTraceResult.Type; +import net.minecraftforge.client.event.InputEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.client.registry.ClientRegistry; + +import static ftbsc.bscv.Boscovicino.log; + +public class Ruler implements ICommons { + + public final KeyBinding keybind; + + public Ruler() { + super(); + + this.keybind = new KeyBinding(Keybind.name("Ruler"), InputMappings.UNKNOWN.getValue(), Keybind.category()); + ClientRegistry.registerKeyBinding(this.keybind); + + // register a separate subclass on the hook, so that it's always listening + MinecraftForge.EVENT_BUS.register(new ToggleHook(this.keybind)); + + // dispatcher.register( + // Commands.literal(this.name.toLowerCase()) + // .then( + // Commands.literal("bind") + // .then( + // Commands.argument("key", StringArgumentType.word()) + // .executes( ctx -> { + // this.keybind.setKey( + // InputMappings.getKey( // TODO it's not this easy! + // StringArgumentType.getString(ctx, "key") + // ) + // ); + // return 1; + // }) + // ) + // ) + // ); + } + + public static void measure() { + RayTraceResult aim = MC.player.pick(1024, 0, false); // will 1024 be enough? + double distance = Math.sqrt(aim.distanceTo(MC.player)); + if (aim.getType() == Type.BLOCK) { + log("distance: %.1fm", distance); + } + } + + // TODO can this be made an util or a global event listener? + private class ToggleHook { + private final KeyBinding key; + private boolean debounce; + // TODO all examples show isPressed() to get a debounced value + // but it seems to be missing? making my own debounce for now + protected ToggleHook(KeyBinding key) { + this.key = key; + this.debounce = false; + } + + private void onInput() { + if (this.debounce) { + if (!this.key.isDown()) { + this.debounce = false; + } + } else { + if (this.key.isDown()) { + Ruler.measure(); + this.debounce = true; + } + } + } + + @SubscribeEvent + public void onKeyPress(InputEvent.KeyInputEvent event) { this.onInput(); } + @SubscribeEvent + public void onKeyPress(InputEvent.MouseInputEvent event) { this.onInput(); } + } +} diff --git a/src/main/java/ftbsc/bscv/tools/Inventory.java b/src/main/java/ftbsc/bscv/tools/Inventory.java index 8f1e2f5..ec36e89 100644 --- a/src/main/java/ftbsc/bscv/tools/Inventory.java +++ b/src/main/java/ftbsc/bscv/tools/Inventory.java @@ -7,13 +7,19 @@ import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.inventory.EquipmentSlotType; +import net.minecraft.inventory.container.ClickType; import net.minecraft.inventory.container.Slot; +import net.minecraft.item.EnchantedBookItem; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.INBT; +import net.minecraft.nbt.ListNBT; +import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.regex.Pattern; public class Inventory implements ICommons { @@ -68,4 +74,44 @@ public class Inventory implements ICommons { return damage / (1. + speed); } + + public static List<String> itemEnchantments(ItemStack stack) { + final ListNBT tags; + if (Items.ENCHANTED_BOOK.equals(stack.getItem())) { + tags = EnchantedBookItem.getEnchantments(stack); // special case to also search book enchants + } else { + tags = stack.getEnchantmentTags(); + } + + List<String> out = new ArrayList<>(); + for (int i = 0; i < tags.size(); i++) { + CompoundNBT tag = tags.getCompound(i); + out.add(String.format("%s %s", tag.getString("id"), tag.getInt("lvl"))); + } + + return out; + } + + public static void clickSlot(int slot_index, ClickType click) { clickSlot(0, slot_index, 0, click); } + public static void clickSlot(Slot slot, int button, ClickType click) { clickSlot(0, slot.index, button, click); } + public static void clickSlot(int container, int slot_index, ClickType click) { clickSlot(container, slot_index, 0, click); } + + public static void clickSlot(int container, int slot_index, int button, ClickType click) { + MC.gameMode.handleInventoryMouseClick(container, slot_index, button, click, MC.player); + } + + public static boolean matchItem(Pattern pattern, ItemStack stack) { + if (stack.isEmpty()) return false; + + String displayName = stack.getDisplayName().getString(); + if (pattern.matcher(displayName).find()) return true; + + if (Items.ENCHANTED_BOOK.equals(stack.getItem()) || stack.isEnchanted()) { + for (String ench : itemEnchantments(stack)) { + if (pattern.matcher(ench).find()) return true; + } + } + + return false; + } } diff --git a/src/main/java/ftbsc/bscv/tools/Keybind.java b/src/main/java/ftbsc/bscv/tools/Keybind.java new file mode 100644 index 0000000..64fe1ad --- /dev/null +++ b/src/main/java/ftbsc/bscv/tools/Keybind.java @@ -0,0 +1,13 @@ +package ftbsc.bscv.tools; + +import ftbsc.bscv.Boscovicino; + +public class Keybind { + public static String name(String name) { + return String.format("key.%s.%s", Boscovicino.MOD_ID, name); + } + + public static String category() { + return String.format("key.category.%s", Boscovicino.MOD_ID); + } +} diff --git a/src/main/java/ftbsc/bscv/tools/Setting.java b/src/main/java/ftbsc/bscv/tools/Setting.java index 99f5480..427e22e 100644 --- a/src/main/java/ftbsc/bscv/tools/Setting.java +++ b/src/main/java/ftbsc/bscv/tools/Setting.java @@ -1,23 +1,28 @@ package ftbsc.bscv.tools; +import com.google.common.collect.Lists; import com.mojang.brigadier.arguments.*; + import ftbsc.bscv.api.IModule; import net.minecraft.command.Commands; import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.server.command.EnumArgument; +import java.io.Serializable; +import java.util.List; import java.util.Optional; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; import static ftbsc.bscv.Boscovicino.log; -public abstract class Setting<T> { +public abstract class Setting<T, I> { protected Optional<String> name; protected Optional<String> comment; protected Optional<T> fallback; - protected Optional<Consumer<T>> callback; - + protected Optional<Consumer<I>> callback; Setting() { this.name = Optional.empty(); @@ -26,68 +31,75 @@ public abstract class Setting<T> { this.callback = Optional.empty(); } - public Setting<T> name(String name) { + public Setting<T, I> name(String name) { this.name = Optional.of(name); return this; } - public Setting<T> comment(String comment) { + public Setting<T, I> comment(String comment) { this.comment = Optional.of(comment); return this; } - public Setting<T> fallback(T fallback) { + public Setting<T, I> fallback(T fallback) { this.fallback = Optional.of(fallback); return this; } - public Setting<T> callback(Consumer<T> callback) { + public Setting<T, I> callback(Consumer<I> callback) { this.callback = Optional.of(callback); return this; } abstract ForgeConfigSpec.ConfigValue<T> value(ForgeConfigSpec.Builder builder); - abstract ArgumentType<T> argument(); + abstract ArgumentType<I> argument(); + + public abstract ForgeConfigSpec.ConfigValue<T> build(IModule module); + - abstract Class<T> clazz(); - public ForgeConfigSpec.ConfigValue<T> build(IModule module) { - ForgeConfigSpec.ConfigValue<T> conf = this.value(module.getConfigBuilder()); + private static abstract class ValueSetting<T> extends Setting<T, T> { + + abstract Class<T> clazz(); - String optName = this.name.get(); - Class<T> clazz = this.clazz(); - ArgumentType<T> arg = this.argument(); - Consumer<T> cb = this.callback.isPresent() ? this.callback.get() : null; + public ForgeConfigSpec.ConfigValue<T> build(IModule module) { + ForgeConfigSpec.ConfigValue<T> conf = this.value(module.getConfigBuilder()); - module.getDispatcher().register( - Commands.literal(module.getName().toLowerCase()) - .then( - Commands.literal(optName) + String optName = this.name.get(); + Class<T> clazz = this.clazz(); + ArgumentType<T> arg = this.argument(); + Consumer<T> cb = this.callback.isPresent() ? this.callback.get() : null; + + module.getDispatcher().register( + Commands.literal(module.getName().toLowerCase()) .then( - Commands.argument(optName, arg) - .executes( ctx -> { - T value = ctx.getArgument(optName, clazz); - if (cb != null) { - cb.accept(value); - } - conf.set(value); - conf.save(); - log(String.format("> %s -> %s <", String.join(".", conf.getPath()), conf.get().toString())); - return 1; - })) - .executes(ctx -> { - log(String.format("> %s: %s <", optName, conf.get().toString())); - return 1; - }) - ) - ); - - return conf; + Commands.literal(optName) + .then( + Commands.argument(optName, arg) + .executes( ctx -> { + T value = ctx.getArgument(optName, clazz); + if (cb != null) { + cb.accept(value); + } + conf.set(value); + conf.save(); + log(String.format("> %s -> %s <", String.join(".", conf.getPath()), conf.get().toString())); + return 1; + })) + .executes(ctx -> { + log(String.format("> %s: %s <", optName, conf.get().toString())); + return 1; + }) + ) + ); + + return conf; + } } - public static class Bool extends Setting<Boolean> { + public static class Bool extends ValueSetting<Boolean> { public static Bool builder() { return new Bool(); } public Class<Boolean> clazz() { return Boolean.class; } @@ -101,7 +113,7 @@ public abstract class Setting<T> { } - public static class Decimal extends Setting<Double> { + public static class Decimal extends ValueSetting<Double> { protected Optional<Double> min; protected Optional<Double> max; @@ -133,7 +145,7 @@ public abstract class Setting<T> { } - public static class Number extends Setting<Integer> { + public static class Number extends ValueSetting<Integer> { protected Optional<Integer> min; protected Optional<Integer> max; @@ -165,7 +177,7 @@ public abstract class Setting<T> { } - public static class Str extends Setting<String> { + public static class Str extends ValueSetting<String> { public static Str builder() { return new Str(); } protected boolean greedy = false; @@ -190,7 +202,7 @@ public abstract class Setting<T> { } - public static class Switch<T extends Enum<T>> extends Setting<T> { + public static class Switch<T extends Enum<T>> extends ValueSetting<T> { private final Class<T> enumClazz; public static<T extends Enum<T>> Switch<T> builder(Class<T> type) { return new Switch<T>(type); } @@ -214,4 +226,102 @@ public abstract class Setting<T> { } } + public static class Many<T, S extends Serializable> extends Setting<List<? extends S>, T> { + private Predicate<Object> validator; + private Function<T, S> writer; + private final ArgumentType<T> argument_type; + private final Class<T> clazz; + + // TODO can we infer clazz from the argument type without needing the second argument??? + public Many(ArgumentType<T> argument, Class<T> clazz) { + super(); + this.validator = x -> true; + this.writer = x -> (S) x; // TODO this works ootb if it's just the same type but crashes at runtime for everything else + this.argument_type = argument; + this.clazz = clazz; + } + + public static<T, S extends Serializable> Many<T, S> builder(ArgumentType<T> argument, Class<T> clazz) { return new Many<T, S>(argument, clazz); } + + public Many<T, S> validator(Predicate<Object> validator) { + this.validator = validator; + return this; + } + + public Many<T, S> writer(Function<T, S> writer) { + this.writer = writer; + return this; + } + + public ArgumentType<T> argument() { + return this.argument_type; + } + + public ForgeConfigSpec.ConfigValue<List<? extends S>> value(ForgeConfigSpec.Builder builder) { + return builder + .comment(this.comment.get()) + .defineList( + this.name.get(), + this.fallback.get(), + this.validator + ); + } + + public ForgeConfigSpec.ConfigValue<List<? extends S>> build(IModule module) { + ForgeConfigSpec.ConfigValue<List<? extends S>> conf = this.value(module.getConfigBuilder()); + + String optName = this.name.get(); + ArgumentType<T> arg = this.argument(); + Consumer<T> cb = this.callback.isPresent() ? this.callback.get() : null; + + module.getDispatcher().register( + Commands.literal(module.getName().toLowerCase()) + .then( + Commands.literal(optName) + .then( + Commands.literal("add") + .then( + Commands.argument(optName, arg) + .executes( ctx -> { + T value = ctx.getArgument(optName, this.clazz); + if (cb != null) { + cb.accept(value); + } + List<S> botch = Lists.newArrayList(conf.get()); + botch.add(this.writer.apply(value)); + conf.set(botch); + conf.save(); + log(String.format("> %s -++> %s <", String.join(".", conf.getPath()), conf.get().toString())); + return 1; + }) + ) + ) + .then( + Commands.literal("remove") + .then( + Commands.argument(optName, arg) + .executes( ctx -> { + T value = ctx.getArgument(optName, clazz); + if (cb != null) { + cb.accept(value); + } + List<S> botch = Lists.newArrayList(conf.get()); + boolean removed = botch.remove(this.writer.apply(value)); + conf.set(botch); + conf.save(); + log(String.format("> %s -%s> %s <", String.join(".", conf.getPath()), removed ? "//" : "--", conf.get().toString())); + return 1; + }) + ) + ) + .executes(ctx -> { + log(String.format("> %s: %s <", optName, conf.get().toString())); + return 1; + }) + ) + ); + + return conf; + } + } } |