Merge branch 'dev' of https://git.fantabos.co/bscv into dev

This commit is contained in:
frelodev 2024-01-10 23:35:23 +01:00
commit 85f8adb577
20 changed files with 611 additions and 98 deletions

3
.gitignore vendored
View file

@ -18,6 +18,9 @@ build
.gradle .gradle
gradle.properties gradle.properties
# ??? gradle again ???
.factorypath
# other # other
eclipse eclipse
run run

View file

@ -8,6 +8,7 @@ import ftbsc.bscv.api.IModule;
import ftbsc.bscv.patches.CommandsPatch.CommandsBuiltEvent; import ftbsc.bscv.patches.CommandsPatch.CommandsBuiltEvent;
import ftbsc.bscv.system.Friends; import ftbsc.bscv.system.Friends;
import ftbsc.bscv.system.ModManager; import ftbsc.bscv.system.ModManager;
import ftbsc.bscv.system.Ruler;
import net.minecraft.client.gui.screen.IngameMenuScreen; import net.minecraft.client.gui.screen.IngameMenuScreen;
import net.minecraft.client.gui.widget.button.Button; import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
@ -42,6 +43,9 @@ public class Boscovicino implements ICommons {
private static Friends friends; private static Friends friends;
public static Friends friends() { return Boscovicino.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() { public Boscovicino() {
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onSetupComplete); FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onSetupComplete);
@ -53,6 +57,8 @@ public class Boscovicino implements ICommons {
Boscovicino.modManager.finish(); Boscovicino.modManager.finish();
Boscovicino.ruler = new Ruler();
Boscovicino.spec = cfg.build(); Boscovicino.spec = cfg.build();
ForgeConfigSpec.Builder friendSpec = new ForgeConfigSpec.Builder(); ForgeConfigSpec.Builder friendSpec = new ForgeConfigSpec.Builder();

View file

@ -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;
});
}
}

View file

@ -4,6 +4,7 @@ import com.google.auto.service.AutoService;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import net.minecraft.block.BlockState;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands; import net.minecraft.command.Commands;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
@ -18,17 +19,18 @@ public class Cursor extends AbstractCommand {
public LiteralArgumentBuilder<CommandSource> register(LiteralArgumentBuilder<CommandSource> builder) { public LiteralArgumentBuilder<CommandSource> register(LiteralArgumentBuilder<CommandSource> builder) {
return builder return builder
.then( .then(
Commands.literal("pos") Commands.literal("info")
.executes(ctx -> { .executes(ctx -> {
switch (MC.hitResult.getType()) { switch (MC.hitResult.getType()) {
case BLOCK: case BLOCK:
BlockRayTraceResult result = (BlockRayTraceResult) MC.hitResult; BlockRayTraceResult result = (BlockRayTraceResult) MC.hitResult;
Direction dir = result.getDirection(); Direction dir = result.getDirection();
BlockPos pos =result.getBlockPos(); BlockPos pos = result.getBlockPos();
log("Block @ %s (%s)", pos.toString(), dir.toString()); BlockState state = MC.level.getBlockState(pos);
log("Block @ %s (%s): %s", pos.toString(), dir.toString(), state.toString());
return 1; return 1;
case ENTITY: case ENTITY:
log("Entity @ %s", MC.hitResult.getLocation().toString()); log("Entity @ %s (TODO!)", MC.hitResult.getLocation().toString());
return 1; return 1;
default: default:
case MISS: case MISS:

View file

@ -1,6 +1,7 @@
package ftbsc.bscv.commands; package ftbsc.bscv.commands;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
@ -8,11 +9,15 @@ import ftbsc.bscv.tools.Inventory;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands; import net.minecraft.command.Commands;
import net.minecraft.inventory.container.Slot; import net.minecraft.inventory.container.Slot;
import net.minecraft.item.Item;
import static ftbsc.bscv.Boscovicino.log; import static ftbsc.bscv.Boscovicino.log;
@AutoService(ILoadable.class) @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) { public LiteralArgumentBuilder<CommandSource> register(LiteralArgumentBuilder<CommandSource> builder) {
return builder return builder
@ -32,6 +37,17 @@ public class Item extends AbstractCommand {
return 1; 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 -> { .executes(ctx -> {
Slot slot = Inventory.hotbar(MC.player).get(MC.player.inventory.selected); Slot slot = Inventory.hotbar(MC.player).get(MC.player.inventory.selected);
if (!slot.hasItem()) return 0; if (!slot.hasItem()) return 0;

View file

@ -9,7 +9,7 @@ import ftbsc.bscv.api.IModule;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands; import net.minecraft.command.Commands;
import static ftbsc.bscv.Boscovicino.log; import java.util.stream.Collectors;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class ModCommands extends AbstractCommand { public class ModCommands extends AbstractCommand {
@ -43,8 +43,11 @@ public class ModCommands extends AbstractCommand {
}) })
) )
.executes(ctx -> { .executes(ctx -> {
log("no args specified"); String mods = Boscovicino.modManager.mods.stream()
return 0; .map(x -> x.getName())
.collect(Collectors.joining(","));
Boscovicino.log("[ %s ]", mods);
return 1;
}); });
} }

View file

@ -1,6 +1,7 @@
package ftbsc.bscv.modules; package ftbsc.bscv.modules;
import ftbsc.bscv.Boscovicino; import ftbsc.bscv.Boscovicino;
import ftbsc.bscv.tools.Keybind;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import net.minecraft.client.util.InputMappings; import net.minecraft.client.util.InputMappings;
import net.minecraftforge.client.event.InputEvent; import net.minecraftforge.client.event.InputEvent;
@ -51,7 +52,7 @@ public abstract class QuickModule extends AbstractModule {
public QuickModule() { public QuickModule() {
super(); 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); ClientRegistry.registerKeyBinding(this.keybind);
// register a separate subclass on the hook, so that it's always listening // 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);
}
} }

View file

@ -52,7 +52,7 @@ public class Aura extends QuickModule {
this.reach = Setting.Decimal.builder() this.reach = Setting.Decimal.builder()
.min(0.) .min(0.)
.fallback(5.) .fallback(4.)
.name("reach") .name("reach")
.comment("aura attack reach") .comment("aura attack reach")
.build(this); .build(this);

View file

@ -4,6 +4,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import ftbsc.bscv.modules.AbstractModule; import ftbsc.bscv.modules.AbstractModule;
import ftbsc.bscv.tools.Inventory;
import ftbsc.bscv.tools.Setting; import ftbsc.bscv.tools.Setting;
import net.minecraft.client.gui.screen.inventory.ContainerScreen; import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.inventory.container.Slot; import net.minecraft.inventory.container.Slot;
@ -48,38 +49,6 @@ public class Highlighter extends AbstractModule {
this.pattern = Pattern.compile(this.query.get()); 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 @SubscribeEvent
public void onGuiContainerDraw(GuiContainerEvent.DrawBackground event) { public void onGuiContainerDraw(GuiContainerEvent.DrawBackground event) {
MatrixStack matrix = event.getMatrixStack(); MatrixStack matrix = event.getMatrixStack();
@ -91,7 +60,7 @@ public class Highlighter extends AbstractModule {
for (Slot slot : screen.getMenu().slots) { for (Slot slot : screen.getMenu().slots) {
ItemStack stack = slot.getItem(); ItemStack stack = slot.getItem();
if (this.matches(stack)) { if (Inventory.matchItem(this.pattern, stack)) {
GuiUtils.drawGradientRect( GuiUtils.drawGradientRect(
matrix.last().pose(), 0, matrix.last().pose(), 0,
slot.x, slot.y, slot.x + 16, slot.y + 16, slot.x, slot.y, slot.x + 16, slot.y + 16,

View file

@ -40,24 +40,24 @@ public class VanillaFlight extends QuickModule {
this.force = Setting.Bool.builder() this.force = Setting.Bool.builder()
.name("force") .name("force")
.comment("force enable flight on user") .comment("force enable flight on user")
.fallback(false) .fallback(true)
.build(this); .build(this);
this.drift = Setting.Bool.builder() this.drift = Setting.Bool.builder()
.name("drift") .name("drift")
.comment("gradually reduce momentum") .comment("gradually reduce momentum")
.fallback(true) .fallback(false)
.build(this); .build(this);
this.speed = Setting.Decimal.builder() this.speed = Setting.Decimal.builder()
.min(0.) .min(0.)
.fallback(0.05) .fallback(0.1)
.name("speed") .name("speed")
.comment("flight speed to set") .comment("flight speed to set")
.build(this); .build(this);
this.antikick = Setting.Switch.builder(AntikickMode.class) this.antikick = Setting.Switch.builder(AntikickMode.class)
.fallback(AntikickMode.NONE) .fallback(AntikickMode.PACKET)
.name("antikick") .name("antikick")
.comment("prevent vanilla flight kick by descending") .comment("prevent vanilla flight kick by descending")
.build(this); .build(this);

View file

@ -1,11 +1,14 @@
package ftbsc.bscv.modules.self; package ftbsc.bscv.modules.self;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import ftbsc.bscv.Boscovicino;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import ftbsc.bscv.modules.AbstractModule; import ftbsc.bscv.modules.AbstractModule;
import ftbsc.bscv.tools.Inventory; import ftbsc.bscv.tools.Inventory;
import ftbsc.bscv.tools.Setting; import ftbsc.bscv.tools.Setting;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.inventory.container.Slot; import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.BlockRayTraceResult;
@ -19,6 +22,7 @@ import java.util.List;
public class AutoTool extends AbstractModule { public class AutoTool extends AbstractModule {
public final ForgeConfigSpec.ConfigValue<Integer> limit; public final ForgeConfigSpec.ConfigValue<Integer> limit;
public final ForgeConfigSpec.ConfigValue<Boolean> prefer_looting;
public AutoTool() { public AutoTool() {
super(); super();
@ -28,6 +32,12 @@ public class AutoTool extends AbstractModule {
.comment("durability limit for tools, set to 0 to destroy them") .comment("durability limit for tools, set to 0 to destroy them")
.fallback(1) .fallback(1)
.build(this); .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) { private boolean itemIsTooDamaged(ItemStack item) {
@ -47,6 +57,12 @@ public class AutoTool extends AbstractModule {
} }
double damage = Inventory.itemDPS(item); 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) { if (damage > current_damage) {
current_slot = i; current_slot = i;
current_damage = damage; current_damage = damage;

View file

@ -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
}
}
}
}

View file

@ -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);
}
}
}

View file

@ -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;
}
}
}

View file

@ -1,4 +1,4 @@
package ftbsc.bscv.modules.hud; package ftbsc.bscv.modules.self;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;

View file

@ -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(); }
}
}

View file

@ -7,13 +7,19 @@ import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.Attributes; import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.inventory.container.ClickType;
import net.minecraft.inventory.container.Slot; import net.minecraft.inventory.container.Slot;
import net.minecraft.item.EnchantedBookItem;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.INBT; import net.minecraft.nbt.INBT;
import net.minecraft.nbt.ListNBT;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.regex.Pattern;
public class Inventory implements ICommons { public class Inventory implements ICommons {
@ -68,4 +74,44 @@ public class Inventory implements ICommons {
return damage / (1. + speed); 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;
}
} }

View file

@ -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);
}
}

View file

@ -1,23 +1,28 @@
package ftbsc.bscv.tools; package ftbsc.bscv.tools;
import com.google.common.collect.Lists;
import com.mojang.brigadier.arguments.*; import com.mojang.brigadier.arguments.*;
import ftbsc.bscv.api.IModule; import ftbsc.bscv.api.IModule;
import net.minecraft.command.Commands; import net.minecraft.command.Commands;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.server.command.EnumArgument; import net.minecraftforge.server.command.EnumArgument;
import java.io.Serializable;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import static ftbsc.bscv.Boscovicino.log; import static ftbsc.bscv.Boscovicino.log;
public abstract class Setting<T> { public abstract class Setting<T, I> {
protected Optional<String> name; protected Optional<String> name;
protected Optional<String> comment; protected Optional<String> comment;
protected Optional<T> fallback; protected Optional<T> fallback;
protected Optional<Consumer<T>> callback; protected Optional<Consumer<I>> callback;
Setting() { Setting() {
this.name = Optional.empty(); this.name = Optional.empty();
@ -26,68 +31,75 @@ public abstract class Setting<T> {
this.callback = Optional.empty(); this.callback = Optional.empty();
} }
public Setting<T> name(String name) { public Setting<T, I> name(String name) {
this.name = Optional.of(name); this.name = Optional.of(name);
return this; return this;
} }
public Setting<T> comment(String comment) { public Setting<T, I> comment(String comment) {
this.comment = Optional.of(comment); this.comment = Optional.of(comment);
return this; return this;
} }
public Setting<T> fallback(T fallback) { public Setting<T, I> fallback(T fallback) {
this.fallback = Optional.of(fallback); this.fallback = Optional.of(fallback);
return this; return this;
} }
public Setting<T> callback(Consumer<T> callback) { public Setting<T, I> callback(Consumer<I> callback) {
this.callback = Optional.of(callback); this.callback = Optional.of(callback);
return this; return this;
} }
abstract ForgeConfigSpec.ConfigValue<T> value(ForgeConfigSpec.Builder builder); abstract ForgeConfigSpec.ConfigValue<T> value(ForgeConfigSpec.Builder builder);
abstract ArgumentType<T> argument(); abstract ArgumentType<I> argument();
abstract Class<T> clazz(); public abstract ForgeConfigSpec.ConfigValue<T> build(IModule module);
public ForgeConfigSpec.ConfigValue<T> build(IModule module) {
ForgeConfigSpec.ConfigValue<T> conf = this.value(module.getConfigBuilder());
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( private static abstract class ValueSetting<T> extends Setting<T, T> {
Commands.literal(module.getName().toLowerCase())
.then( abstract Class<T> clazz();
Commands.literal(optName)
public ForgeConfigSpec.ConfigValue<T> build(IModule module) {
ForgeConfigSpec.ConfigValue<T> conf = this.value(module.getConfigBuilder());
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( .then(
Commands.argument(optName, arg) Commands.literal(optName)
.executes( ctx -> { .then(
T value = ctx.getArgument(optName, clazz); Commands.argument(optName, arg)
if (cb != null) { .executes( ctx -> {
cb.accept(value); T value = ctx.getArgument(optName, clazz);
} if (cb != null) {
conf.set(value); cb.accept(value);
conf.save(); }
log(String.format("> %s -> %s <", String.join(".", conf.getPath()), conf.get().toString())); conf.set(value);
return 1; conf.save();
})) log(String.format("> %s -> %s <", String.join(".", conf.getPath()), conf.get().toString()));
.executes(ctx -> { return 1;
log(String.format("> %s: %s <", optName, conf.get().toString())); }))
return 1; .executes(ctx -> {
}) log(String.format("> %s: %s <", optName, conf.get().toString()));
) return 1;
); })
)
);
return conf; return conf;
}
} }
public static class Bool extends Setting<Boolean> { public static class Bool extends ValueSetting<Boolean> {
public static Bool builder() { return new Bool(); } public static Bool builder() { return new Bool(); }
public Class<Boolean> clazz() { return Boolean.class; } 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> min;
protected Optional<Double> max; 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> min;
protected Optional<Integer> max; 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(); } public static Str builder() { return new Str(); }
protected boolean greedy = false; 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; private final Class<T> enumClazz;
public static<T extends Enum<T>> Switch<T> builder(Class<T> type) { return new Switch<T>(type); } 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;
}
}
} }

View file

@ -5,3 +5,7 @@ public net.minecraft.network.play.client.CPlayerPacket field_149474_g # onGround
public net.minecraft.network.play.client.CPlayerPacket field_149477_b # y public net.minecraft.network.play.client.CPlayerPacket field_149477_b # y
public net.minecraft.client.multiplayer.PlayerController func_78750_j()V # ensureHasSentCarriedItem() public net.minecraft.client.multiplayer.PlayerController func_78750_j()V # ensureHasSentCarriedItem()
public net.minecraft.client.Minecraft field_71467_ac # rightClickDelay public net.minecraft.client.Minecraft field_71467_ac # rightClickDelay
public net.minecraft.client.renderer.FirstPersonRenderer field_187469_f # mainHandHeight
public net.minecraft.client.renderer.FirstPersonRenderer field_187470_g # oMainHandHeight
public net.minecraft.client.renderer.FirstPersonRenderer field_187471_h # offHandHeight
public net.minecraft.client.renderer.FirstPersonRenderer field_187472_i # oOffHandHeight