summaryrefslogtreecommitdiff
path: root/src/main/java/ftbsc
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/ftbsc')
-rw-r--r--src/main/java/ftbsc/bscv/BoSCoVicino.java181
-rw-r--r--src/main/java/ftbsc/bscv/module/HudModule.java47
-rw-r--r--src/main/java/ftbsc/bscv/module/Module.java154
-rw-r--r--src/main/java/ftbsc/bscv/module/QuickModule.java90
-rw-r--r--src/main/java/ftbsc/bscv/module/hud/ActiveModules.java40
-rw-r--r--src/main/java/ftbsc/bscv/module/hud/Coordinates.java37
-rw-r--r--src/main/java/ftbsc/bscv/module/hud/EntityList.java59
-rw-r--r--src/main/java/ftbsc/bscv/module/hud/InfoDisplay.java134
-rw-r--r--src/main/java/ftbsc/bscv/module/motion/VanillaFlight.java108
-rw-r--r--src/main/java/ftbsc/bscv/module/self/FastInteract.java46
-rw-r--r--src/main/java/ftbsc/bscv/module/vision/Fullbright.java47
-rw-r--r--src/main/java/ftbsc/bscv/patches/TestPatch.java51
-rw-r--r--src/main/java/ftbsc/bscv/tools/Anchor.java51
-rw-r--r--src/main/java/ftbsc/bscv/tools/Text.java89
-rw-r--r--src/main/java/ftbsc/bscv/tools/Utils.java10
15 files changed, 1144 insertions, 0 deletions
diff --git a/src/main/java/ftbsc/bscv/BoSCoVicino.java b/src/main/java/ftbsc/bscv/BoSCoVicino.java
new file mode 100644
index 0000000..5ea29b1
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/BoSCoVicino.java
@@ -0,0 +1,181 @@
+package ftbsc.bscv;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.player.ClientPlayerEntity;
+import net.minecraft.command.CommandSource;
+import net.minecraft.command.Commands;
+import net.minecraft.util.text.StringTextComponent;
+import net.minecraftforge.client.event.ClientChatEvent;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.event.RegistryEvent;
+import net.minecraftforge.event.world.WorldEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.ModLoadingContext;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.config.ModConfig.Type;
+import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
+import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import ftbsc.bscv.module.Module;
+import ftbsc.bscv.module.vision.*;
+import ftbsc.bscv.module.motion.*;
+import ftbsc.bscv.module.self.*;
+import ftbsc.bscv.module.hud.*;
+
+// The value here should match an entry in the META-INF/mods.toml file
+@Mod("bscv")
+public class BoSCoVicino {
+ public static String MOD_ID = "bscv";
+
+ // Directly reference a log4j logger.
+ public static final Logger LOGGER = LogManager.getLogger();
+
+ public static Minecraft minecraft;
+
+ public static List<Module> mods;
+
+ private final CommandDispatcher<CommandSource> dispatcher = new CommandDispatcher<>();
+
+ public static ForgeConfigSpec spec;
+
+ public BoSCoVicino() {
+ // Register the setup method for modloading
+ FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup);
+
+ // Store minecraft instance
+ BoSCoVicino.minecraft = Minecraft.getInstance();
+
+ // load and register mods
+ BoSCoVicino.mods = new ArrayList<Module>();
+
+ ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
+
+ // TODO also push!
+ // modules cannot easily pop from their builder, but here we can't easily get
+ // the module name yet. We should push and pop the builder ourselves and not
+ // bother the modules themselves.
+
+ BoSCoVicino.mods.add(new Fullbright(builder, this.dispatcher));
+ builder.pop();
+ BoSCoVicino.mods.add(new VanillaFlight(builder, this.dispatcher));
+ builder.pop();
+ BoSCoVicino.mods.add(new FastInteract(builder, this.dispatcher));
+ builder.pop();
+ BoSCoVicino.mods.add(new InfoDisplay(builder, this.dispatcher));
+ builder.pop();
+ BoSCoVicino.mods.add(new Coordinates(builder, this.dispatcher));
+ builder.pop();
+ BoSCoVicino.mods.add(new EntityList(builder, this.dispatcher));
+ builder.pop();
+ BoSCoVicino.mods.add(new ActiveModules(builder, this.dispatcher));
+ builder.pop();
+
+ BoSCoVicino.spec = builder.build();
+
+ // register config handler
+ ModLoadingContext.get().registerConfig(Type.CLIENT, spec, "bscv.toml");
+
+ // Register ourselves for server and other game events we are interested in
+ MinecraftForge.EVENT_BUS.register(this);
+ }
+
+ public static void log(String message) {
+ BoSCoVicino.minecraft.gui.getChat().addMessage(new StringTextComponent(message));
+ }
+
+ private void clientSetup(final FMLClientSetupEvent event) {
+ LOGGER.info("Initializing modules");
+
+ for (Module m : BoSCoVicino.mods) {
+ if (m.enabled.get()) m.enable();
+ }
+
+ // TEMPORARY! add command to regenerate suggestions
+ dispatcher.register(
+ Commands.literal("hints")
+ .executes(ctx -> {
+ ClientPlayerEntity player = BoSCoVicino.minecraft.player;
+ if (player != null) {
+ try {
+ Field commands = player.connection.getClass().getDeclaredField("field_195517_n"); // "commands", it's obfuscated
+ commands.setAccessible(true);
+ commands.set(player.connection, this.dispatcher);
+ LOGGER.info("Rebuild HINTS");
+ log("> rebuilt hints");
+ return 1;
+ } catch (NoSuchFieldException e) {
+ log("! no such field error");
+ LOGGER.error("No such field Exception while rebuilding hints");
+ return 0;
+ } catch (IllegalAccessException e) {
+ log("! illegal access error");
+ LOGGER.error("Illegal Access Exception while rebuilding hints");
+ return 0;
+ }
+ } else {
+ log("! local player is NULL");
+ LOGGER.error("Local player is NULL");
+ return 0;
+ }
+ })
+ );
+ }
+
+ @SubscribeEvent
+ public void onClientChatEvent(ClientChatEvent event) {
+ if (event.getMessage().startsWith("/")) {
+ CommandSource source = BoSCoVicino.minecraft.player.createCommandSourceStack(); // TODO player could be NULL
+ try {
+ LOGGER.info(String.format("Running command %s", event.getMessage()));
+ this.dispatcher.execute(event.getMessage().substring(1), source);
+ BoSCoVicino.minecraft.gui.getChat().addRecentChat(event.getMessage());
+ event.setCanceled(true);
+ } catch (CommandSyntaxException e) {
+ LOGGER.error(String.format("Syntax error in command : %s", e.toString()));
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onWorldLoad(WorldEvent.Load event) {
+ // TEMPORARY! add command to regenerate suggestions
+ ClientPlayerEntity player = BoSCoVicino.minecraft.player;
+ if (player != null) {
+ try {
+ Field commands = player.connection.getClass().getDeclaredField("field_195517_n"); // "commands", it's obfuscated
+ commands.setAccessible(true);
+ commands.set(player.connection, this.dispatcher);
+ LOGGER.info("Rebuild HINTS");
+ log("> rebuilt hints");
+ } catch (NoSuchFieldException e) {
+ LOGGER.error("No such field Exception while rebuilding hints");
+ } catch (IllegalAccessException e) {
+ LOGGER.error("Illegal Access Exception while rebuilding hints");
+ }
+ } else {
+ LOGGER.error("Local player is NULL");
+ }
+ }
+
+ // You can use EventBusSubscriber to automatically subscribe events on the contained class (this is subscribing to the MOD
+ // Event bus for receiving Registry Events)
+ @Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
+ public static class RegistryEvents {
+ @SubscribeEvent
+ public static void onBlocksRegistry(final RegistryEvent.Register<Block> blockRegistryEvent) {
+ // register a new block here
+ LOGGER.info("HELLO from Register Block");
+ }
+ }
+}
diff --git a/src/main/java/ftbsc/bscv/module/HudModule.java b/src/main/java/ftbsc/bscv/module/HudModule.java
new file mode 100644
index 0000000..d1f0842
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/module/HudModule.java
@@ -0,0 +1,47 @@
+package ftbsc.bscv.module;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.DoubleArgumentType;
+import com.mojang.brigadier.arguments.IntegerArgumentType;
+
+import ftbsc.bscv.tools.Anchor;
+import net.minecraft.command.CommandSource;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.server.command.EnumArgument;
+
+public abstract class HudModule extends Module {
+
+ public final ForgeConfigSpec.ConfigValue<Integer> x;
+ public final ForgeConfigSpec.ConfigValue<Integer> y;
+ public final ForgeConfigSpec.ConfigValue<Double> scale;
+ public final ForgeConfigSpec.EnumValue<Anchor> anchor;
+
+ protected HudModule(String name, ForgeConfigSpec.Builder builder, CommandDispatcher<CommandSource> dispatcher) {
+ super(name, Group.HUD, builder, dispatcher);
+
+ this.x = this.option(
+ "x", "horizontal offset", 0,
+ IntegerArgumentType.integer(0), Integer.class,
+ builder, dispatcher
+ );
+
+ this.y = this.option(
+ "y", "vertical offset", 0,
+ IntegerArgumentType.integer(0), Integer.class,
+ builder, dispatcher
+ );
+
+ this.scale = this.option(
+ "scale", "scale of element", 1.0,
+ DoubleArgumentType.doubleArg(0.0), Double.class,
+ builder, dispatcher
+ );
+
+ this.anchor = this.optionEnum(
+ "anchor", "origin point for coordinates", Anchor.TOPLEFT,
+ EnumArgument.enumArgument(Anchor.class), Anchor.class,
+ builder, dispatcher
+ );
+ }
+
+}
diff --git a/src/main/java/ftbsc/bscv/module/Module.java b/src/main/java/ftbsc/bscv/module/Module.java
new file mode 100644
index 0000000..d5ba285
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/module/Module.java
@@ -0,0 +1,154 @@
+package ftbsc.bscv.module;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.ArgumentType;
+
+import ftbsc.bscv.BoSCoVicino;
+import net.minecraft.command.CommandSource;
+import net.minecraft.command.Commands;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.common.MinecraftForge;
+
+import static ftbsc.bscv.BoSCoVicino.log;
+
+public abstract class Module {
+ public enum Group {
+ SELF,
+ HUD,
+ BUILD,
+ DEFENSE,
+ VISION,
+ MOTION,
+ }
+
+ public final String name;
+ public final Group group;
+ public final ForgeConfigSpec.ConfigValue<Boolean> enabled;
+
+ protected Module(String name, Group group, ForgeConfigSpec.Builder builder, CommandDispatcher<CommandSource> dispatcher) {
+ this.name = name;
+ this.group = group;
+
+ builder.push(this.name.toLowerCase());
+ this.enabled = builder
+ .comment(String.format("Enables %s", this.name))
+ .define("enabled", false);
+
+ dispatcher.register(
+ Commands.literal(this.name.toLowerCase())
+ .then(
+ Commands.literal("toggle")
+ .executes(ctx -> {
+ this.toggle();
+ return 1;
+ })
+ )
+ .executes(ctx -> {
+ log(String.format("=[ %s ]%s", this.name, this.enabled.get() ? "+" : ""));
+ // TODO: print all mod options!
+ return 1;
+ })
+ );
+ }
+
+
+ // TODO can I merge these two option into one? Maybe redo with builder pattern?
+
+ public <T extends Enum<T>> ForgeConfigSpec.EnumValue<T> optionEnum(
+ String name,
+ String comment,
+ T fallback,
+ ArgumentType<T> argument,
+ Class<T> clazz,
+ ForgeConfigSpec.Builder builder,
+ CommandDispatcher<CommandSource> dispatcher
+ ) {
+ ForgeConfigSpec.EnumValue<T> conf = builder
+ .comment(comment)
+ .defineEnum(name, fallback);
+
+ dispatcher.register(
+ Commands.literal(this.name.toLowerCase())
+ .then(
+ Commands.literal(name)
+ .then(
+ Commands.argument(name, argument)
+ .executes( ctx -> {
+ T value = ctx.getArgument(name, clazz);
+ 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", String.join(".", conf.getPath()), conf.get().toString()));
+ return 1;
+ })
+ )
+ );
+
+ return conf;
+ }
+
+ public <T> ForgeConfigSpec.ConfigValue<T> option(
+ String name,
+ String comment,
+ T fallback,
+ ArgumentType<T> argument,
+ Class<T> clazz,
+ ForgeConfigSpec.Builder builder,
+ CommandDispatcher<CommandSource> dispatcher
+ ) {
+ ForgeConfigSpec.ConfigValue<T> conf = builder
+ .comment(comment)
+ .define(name, fallback);
+
+ dispatcher.register(
+ Commands.literal(this.name.toLowerCase())
+ .then(
+ Commands.literal(name)
+ .then(
+ Commands.argument(name, argument)
+ .executes( ctx -> {
+ T value = ctx.getArgument(name, clazz);
+ 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", name, conf.get().toString()));
+ return 1;
+ })
+ )
+ );
+
+ return conf;
+ }
+
+ protected void onEnabled() {}
+ protected void onDisabled() {}
+
+ public final void toggle() {
+ if (this.enabled.get()) this.disable();
+ else this.enable();
+ }
+
+ public final void enable() {
+ MinecraftForge.EVENT_BUS.register(this);
+ this.enabled.set(true);
+ // this.enabled.save();
+ this.onEnabled();
+ log(String.format("%s enabled", this.name));
+ BoSCoVicino.LOGGER.info(String.format("%s enabled", this.name));
+ }
+
+ public final void disable() {
+ MinecraftForge.EVENT_BUS.unregister(this);
+ this.enabled.set(false);
+ // this.enabled.save();
+ this.onDisabled();
+ log(String.format("%s disabled", this.name));
+ BoSCoVicino.LOGGER.info(String.format("%s disabled", this.name));
+ }
+}
diff --git a/src/main/java/ftbsc/bscv/module/QuickModule.java b/src/main/java/ftbsc/bscv/module/QuickModule.java
new file mode 100644
index 0000000..8eefa55
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/module/QuickModule.java
@@ -0,0 +1,90 @@
+package ftbsc.bscv.module;
+
+import com.mojang.brigadier.CommandDispatcher;
+
+import net.minecraft.client.settings.KeyBinding;
+import net.minecraft.client.util.InputMappings;
+import net.minecraft.command.CommandSource;
+import net.minecraftforge.client.event.InputEvent;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.client.registry.ClientRegistry;
+
+import ftbsc.bscv.BoSCoVicino;
+
+// TODO rename
+public class QuickModule extends Module {
+
+ public static final int UNBOUND = InputMappings.UNKNOWN.getValue();
+
+ private class ToggleHook {
+ private final KeyBinding key;
+ private final Module mod;
+ 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, Module mod) {
+ this.key = key;
+ this.mod = mod;
+ this.debounce = false;
+ }
+
+ private void onInput() {
+ if (this.debounce) {
+ if (!this.key.isDown()) {
+ this.debounce = false;
+ }
+ } else {
+ if (this.key.isDown()) {
+ this.mod.toggle();
+ this.debounce = true;
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onKeyPress(InputEvent.KeyInputEvent event) { this.onInput(); }
+ @SubscribeEvent
+ public void onKeyPress(InputEvent.MouseInputEvent event) { this.onInput(); }
+ }
+
+ public final KeyBinding keybind;
+
+ public QuickModule(String name, Group group, int default_key, ForgeConfigSpec.Builder builder, CommandDispatcher<CommandSource> dispatcher) {
+ super(name, group, builder, dispatcher);
+
+ this.keybind = new KeyBinding(key_name(name), default_key, key_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, this));
+
+ // 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;
+ // })
+ // )
+ // )
+ // );
+ }
+
+ 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/module/hud/ActiveModules.java b/src/main/java/ftbsc/bscv/module/hud/ActiveModules.java
new file mode 100644
index 0000000..5a1d8ab
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/module/hud/ActiveModules.java
@@ -0,0 +1,40 @@
+package ftbsc.bscv.module.hud;
+
+import static ftbsc.bscv.tools.Text.TextBuilder;
+
+import com.mojang.brigadier.CommandDispatcher;
+
+import ftbsc.bscv.BoSCoVicino;
+import net.minecraft.command.CommandSource;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import ftbsc.bscv.module.HudModule;
+import ftbsc.bscv.module.Module;
+
+public class ActiveModules extends HudModule {
+
+ public ActiveModules(ForgeConfigSpec.Builder builder, CommandDispatcher<CommandSource> dispatcher) {
+ super("ActiveModules", builder, dispatcher);
+ }
+
+ @SubscribeEvent
+ public void onRenderOverlay(RenderGameOverlayEvent event) {
+ if (event.getType() == ElementType.TEXT) {
+ int offset = 0;
+ for (Module m : BoSCoVicino.mods) {
+ if (m.enabled.get() && m.group != Group.HUD) {
+ TextBuilder()
+ .txt(String.format("%s <", m.name))
+ .anchor(this.anchor.get())
+ .x(this.x.get())
+ .y(this.y.get() + offset)
+ .scale(this.scale.get())
+ .render(event.getMatrixStack(), event.getWindow());
+ offset += BoSCoVicino.minecraft.font.lineHeight;
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/ftbsc/bscv/module/hud/Coordinates.java b/src/main/java/ftbsc/bscv/module/hud/Coordinates.java
new file mode 100644
index 0000000..75c88b9
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/module/hud/Coordinates.java
@@ -0,0 +1,37 @@
+package ftbsc.bscv.module.hud;
+
+import com.mojang.brigadier.CommandDispatcher;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.command.CommandSource;
+import net.minecraft.util.math.vector.Vector3d;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+
+import static ftbsc.bscv.tools.Text.TextBuilder;
+import ftbsc.bscv.BoSCoVicino;
+import ftbsc.bscv.module.HudModule;
+
+public class Coordinates extends HudModule {
+
+ public Coordinates(ForgeConfigSpec.Builder builder, CommandDispatcher<CommandSource> dispatcher) {
+ super("Coordinates", builder, dispatcher);
+ }
+
+ @SubscribeEvent
+ public void onRenderOverlay(RenderGameOverlayEvent event) {
+ Minecraft mc = BoSCoVicino.minecraft;
+ if (event.getType() == ElementType.TEXT && mc.player != null) {
+ Vector3d position = mc.player.position();
+ TextBuilder()
+ .txt(String.format("[ X %.1f | %.1f Z ] %.1f Y", position.x(), position.z(), position.y()))
+ .anchor(this.anchor.get())
+ .x(this.x.get())
+ .y(this.y.get())
+ .scale(this.scale.get())
+ .render(event.getMatrixStack(), event.getWindow());
+ }
+ }
+}
diff --git a/src/main/java/ftbsc/bscv/module/hud/EntityList.java b/src/main/java/ftbsc/bscv/module/hud/EntityList.java
new file mode 100644
index 0000000..ab6707e
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/module/hud/EntityList.java
@@ -0,0 +1,59 @@
+package ftbsc.bscv.module.hud;
+
+import static ftbsc.bscv.tools.Text.TextBuilder;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.mojang.brigadier.CommandDispatcher;
+
+import ftbsc.bscv.BoSCoVicino;
+import ftbsc.bscv.module.HudModule;
+import net.minecraft.command.CommandSource;
+import net.minecraft.entity.Entity;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+
+public class EntityList extends HudModule {
+
+ public EntityList(ForgeConfigSpec.Builder builder, CommandDispatcher<CommandSource> dispatcher) {
+ super("EntityList", builder, dispatcher);
+ }
+
+ @SubscribeEvent
+ public void onRenderOverlay(RenderGameOverlayEvent event) {
+ if (event.getType() != ElementType.TEXT) return;
+
+ List<String> entities = new ArrayList<>();
+ for (Entity e : BoSCoVicino.minecraft.level.entitiesForRendering()) {
+ // TODO do some filtering here?
+ entities.add(e.getName().getString());
+ }
+
+ List<String> uniques = new ArrayList<>();
+ for (String s : entities.stream().distinct().collect(Collectors.toList())) {
+ int num = Collections.frequency(entities, s);
+ if (num > 1) {
+ uniques.add(String.format("%s (%d)", s, num));
+ } else {
+ uniques.add(s);
+ }
+ }
+
+ int offset = 0;
+ for (String u : uniques) {
+ TextBuilder()
+ .txt(String.format("%s", u))
+ .anchor(this.anchor.get())
+ .x(this.x.get())
+ .y(this.y.get() + offset)
+ .scale(this.scale.get())
+ .render(event.getMatrixStack(), event.getWindow());
+ offset += BoSCoVicino.minecraft.font.lineHeight;
+ }
+ }
+}
diff --git a/src/main/java/ftbsc/bscv/module/hud/InfoDisplay.java b/src/main/java/ftbsc/bscv/module/hud/InfoDisplay.java
new file mode 100644
index 0000000..3a6e6eb
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/module/hud/InfoDisplay.java
@@ -0,0 +1,134 @@
+package ftbsc.bscv.module.hud;
+
+import static ftbsc.bscv.tools.Text.TextBuilder;
+
+import java.util.ArrayDeque;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.BoolArgumentType;
+
+import ftbsc.bscv.BoSCoVicino;
+import ftbsc.bscv.module.HudModule;
+import net.minecraft.client.Minecraft;
+import net.minecraft.command.CommandSource;
+import net.minecraft.util.math.vector.Vector3d;
+import net.minecraft.util.text.Color;
+import net.minecraft.util.text.Style;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.event.TickEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+
+public class InfoDisplay extends HudModule {
+
+
+ private Vector3d last_position = new Vector3d(0.0, 0.0, 0.0);
+ private double instant_speed = 0.0;
+ private double average_speed = 0.0;
+ private ArrayDeque<Double> history_speed = new ArrayDeque<>();
+
+ public final ForgeConfigSpec.ConfigValue<Boolean> logo;
+ public final ForgeConfigSpec.ConfigValue<Boolean> speed;
+ public final ForgeConfigSpec.ConfigValue<Boolean> time;
+ // public final ForgeConfigSpec.ConfigValue<Boolean> fps;
+ // public final ForgeConfigSpec.ConfigValue<Boolean> biome;
+ // public final ForgeConfigSpec.ConfigValue<Boolean> latency;
+ // public final ForgeConfigSpec.ConfigValue<Boolean> tps;
+ // public final ForgeConfigSpec.ConfigValue<Boolean> light;
+ // public final ForgeConfigSpec.ConfigValue<Boolean> saturation;
+ // public final ForgeConfigSpec.ConfigValue<Boolean> system_time;
+ // public final ForgeConfigSpec.ConfigValue<Boolean> damage_value;
+ // public final ForgeConfigSpec.ConfigValue<Boolean> effects_list;
+ // public final ForgeConfigSpec.ConfigValue<Boolean> item_quantity;
+ // public final ForgeConfigSpec.ConfigValue<Boolean> client_chunk_size;
+
+ public InfoDisplay(ForgeConfigSpec.Builder builder, CommandDispatcher<CommandSource> dispatcher) {
+ super("InfoDisplay", builder, dispatcher);
+
+ this.logo = this.option(
+ "logo", "show logo at top of list", true,
+ BoolArgumentType.bool(), Boolean.class,
+ builder, dispatcher
+ );
+
+ this.speed = this.option(
+ "speed", "show speed meter", true,
+ BoolArgumentType.bool(), Boolean.class,
+ builder, dispatcher
+ );
+
+ this.time = this.option(
+ "time", "show world time", true,
+ BoolArgumentType.bool(), Boolean.class,
+ builder, dispatcher
+ );
+ }
+
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent event) {
+ if (!this.speed.get()) return;
+ if (BoSCoVicino.minecraft.player != null) {
+ this.instant_speed =
+ this.last_position.distanceTo(BoSCoVicino.minecraft.player.position());
+ this.last_position = BoSCoVicino.minecraft.player.position();
+ } else {
+ this.instant_speed = 0.0;
+ }
+
+ this.history_speed.push(this.instant_speed);
+ while (this.history_speed.size() >= 100) { // TODO customize this parameter
+ this.history_speed.pop();
+ }
+
+ double buf = 0.0;
+ for (double v : this.history_speed) { buf += v; }
+ this.average_speed = buf / this.history_speed.size();
+ }
+
+ @SubscribeEvent
+ public void onRenderOverlay(RenderGameOverlayEvent event) {
+ if (event.getType() != ElementType.TEXT) return;
+
+ Minecraft mc = BoSCoVicino.minecraft;
+ int offset = 0;
+ double scale = this.scale.get();
+ if (this.logo.get()) {
+ TextBuilder()
+ .txt("BSCV")
+ .anchor(this.anchor.get())
+ .x(this.x.get() / 4)
+ .y(this.y.get() / 4)
+ .style(Style.EMPTY.withColor(Color.fromRgb(12542314)).withBold(true))
+ .scale(scale * 4.0)
+ .render(event.getMatrixStack(), event.getWindow());
+ offset += mc.font.lineHeight * scale * 4.0;
+ }
+
+ if (this.time.get()) {
+ long daytime = 0;
+ if (mc.level != null) {
+ daytime = mc.level.dayTime();
+ }
+ TextBuilder()
+ .txt(String.format("> time: %d/1200 (%d day)", (daytime / 20) % 1200, daytime / (20 * 1200) ))
+ .anchor(this.anchor.get())
+ .x(this.x.get())
+ .y(this.y.get() + offset)
+ .scale(scale)
+ .render(event.getMatrixStack(), event.getWindow());
+ offset += mc.font.lineHeight * scale;
+ }
+
+ if (this.speed.get()) {
+ TextBuilder()
+ .txt(String.format("> speed: %.1f [%.1f] m/s", this.instant_speed * 20.0, this.average_speed * 20.0))
+ .anchor(this.anchor.get())
+ .x(this.x.get())
+ .y(this.y.get() + offset)
+ .scale(scale)
+ .render(event.getMatrixStack(), event.getWindow());
+ offset += mc.font.lineHeight * scale;
+ }
+ }
+}
diff --git a/src/main/java/ftbsc/bscv/module/motion/VanillaFlight.java b/src/main/java/ftbsc/bscv/module/motion/VanillaFlight.java
new file mode 100644
index 0000000..3e99f7d
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/module/motion/VanillaFlight.java
@@ -0,0 +1,108 @@
+package ftbsc.bscv.module.motion;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.BoolArgumentType;
+import com.mojang.brigadier.arguments.DoubleArgumentType;
+import com.mojang.brigadier.arguments.IntegerArgumentType;
+
+import ftbsc.bscv.BoSCoVicino;
+import ftbsc.bscv.module.QuickModule;
+import net.minecraft.client.entity.player.ClientPlayerEntity;
+import net.minecraft.command.CommandSource;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.event.TickEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+
+public class VanillaFlight extends QuickModule {
+
+ public final ForgeConfigSpec.ConfigValue<Boolean> force;
+ public final ForgeConfigSpec.ConfigValue<Double> speed;
+ public final ForgeConfigSpec.ConfigValue<Boolean> antikick;
+ public final ForgeConfigSpec.ConfigValue<Double> antikick_magnitude;
+ public final ForgeConfigSpec.ConfigValue<Integer> antikick_cycle;
+
+ private final float minDescent = 0.03125f;
+ private final int maxTicks = 80;
+ private int tick = 0;
+
+ public VanillaFlight(ForgeConfigSpec.Builder builder, CommandDispatcher<CommandSource> dispatcher) {
+ super("VanillaFlight", Group.MOTION, UNBOUND, builder, dispatcher);
+
+ this.force = this.option(
+ "force", "force enable flight on user", false,
+ BoolArgumentType.bool(), Boolean.class,
+ builder, dispatcher
+ );
+
+ this.speed = this.option(
+ "speed", "flight speed to set", 0.05,
+ DoubleArgumentType.doubleArg(0.0), Double.class,
+ builder, dispatcher
+ );
+
+ this.antikick = this.option(
+ "antikick", "prevent vanilla flight kick by descending", false,
+ BoolArgumentType.bool(), Boolean.class,
+ builder, dispatcher
+ );
+
+ this.antikick_magnitude = this.option(
+ "magnitude", "magnitude of antikick push", 1.0,
+ DoubleArgumentType.doubleArg(0.0), Double.class,
+ builder, dispatcher
+ );
+
+ this.antikick_cycle = this.option(
+ "cycle", "how often to run antikick routine", 0,
+ IntegerArgumentType.integer(0, 79), Integer.class,
+ builder, dispatcher
+ );
+ }
+
+ private boolean couldFlyBefore = false;
+ private float flyingSpeedBefore = 0.05f;
+
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent event) {
+ ClientPlayerEntity player = BoSCoVicino.minecraft.player;
+ if (player == null) return;
+
+ player.abilities.mayfly = true;
+ player.abilities.setFlyingSpeed(this.speed.get().floatValue());
+ if (this.force.get()) {
+ player.abilities.flying = true;
+ }
+ if (this.antikick.get()) {
+ if (this.tick != 0 && this.tick % (maxTicks - this.antikick_cycle.get()) == 0) {
+ player.push(0.0, -(this.antikick_magnitude.get() * minDescent), 0.0);
+ this.tick = 0;
+ } else if (this.tick == 0) {
+ player.push(0.0, this.antikick_magnitude.get() * minDescent, 0.0);
+ this.tick++;
+ } else {
+ this.tick++;
+ }
+ }
+ }
+
+ @Override
+ protected void onEnabled() {
+ if (BoSCoVicino.minecraft.player != null) {
+ this.couldFlyBefore = BoSCoVicino.minecraft.player.abilities.mayfly;
+ this.flyingSpeedBefore = BoSCoVicino.minecraft.player.abilities.getFlyingSpeed();
+ BoSCoVicino.log(String.format("Flying speed before = %f", this.flyingSpeedBefore));
+ }
+ }
+
+ @Override
+ protected void onDisabled() {
+ ClientPlayerEntity player = BoSCoVicino.minecraft.player;
+ if (player != null) {
+ player.abilities.mayfly = this.couldFlyBefore;
+ player.abilities.setFlyingSpeed(this.flyingSpeedBefore);
+ if (this.force.get()) {
+ player.abilities.flying = false;
+ }
+ }
+ }
+}
diff --git a/src/main/java/ftbsc/bscv/module/self/FastInteract.java b/src/main/java/ftbsc/bscv/module/self/FastInteract.java
new file mode 100644
index 0000000..2806ba8
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/module/self/FastInteract.java
@@ -0,0 +1,46 @@
+package ftbsc.bscv.module.self;
+
+import static ftbsc.bscv.BoSCoVicino.log;
+
+import java.lang.reflect.Field;
+
+import com.mojang.brigadier.CommandDispatcher;
+
+import net.minecraft.command.CommandSource;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.event.TickEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+
+import ftbsc.bscv.module.QuickModule;
+import ftbsc.bscv.BoSCoVicino;
+
+public class FastInteract extends QuickModule {
+
+ Field delayField;
+
+ public FastInteract(ForgeConfigSpec.Builder builder, CommandDispatcher<CommandSource> dispatcher) {
+ super("FastInteract", Group.SELF, UNBOUND, builder, dispatcher);
+ }
+
+ @Override
+ protected void onEnabled() {
+ try {
+ delayField = BoSCoVicino.minecraft.getClass().getDeclaredField("field_71467_ac");
+ delayField.setAccessible(true);
+ } catch (NoSuchFieldException e) {
+ log("! failed accessing delay field");
+ this.disable();
+ }
+ }
+
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent event) {
+ if (BoSCoVicino.minecraft == null) return;
+ try {
+ this.delayField.set(BoSCoVicino.minecraft, 0);
+ } catch (IllegalAccessException e) {
+ log("! failed accessing delay field");
+ this.disable();
+ }
+ }
+}
diff --git a/src/main/java/ftbsc/bscv/module/vision/Fullbright.java b/src/main/java/ftbsc/bscv/module/vision/Fullbright.java
new file mode 100644
index 0000000..c35748e
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/module/vision/Fullbright.java
@@ -0,0 +1,47 @@
+package ftbsc.bscv.module.vision;
+
+import java.awt.event.KeyEvent;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.StringArgumentType;
+
+import net.minecraft.command.CommandSource;
+import net.minecraft.potion.Effect;
+import net.minecraft.potion.EffectInstance;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.event.TickEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+
+import ftbsc.bscv.module.QuickModule;
+import ftbsc.bscv.BoSCoVicino;
+
+public class Fullbright extends QuickModule {
+
+ private final ForgeConfigSpec.ConfigValue<String> mode;
+
+ public Fullbright(ForgeConfigSpec.Builder builder, CommandDispatcher<CommandSource> dispatcher) {
+ super("Fullbright", Group.VISION, KeyEvent.VK_V, builder, dispatcher);
+
+ this.mode = this.option(
+ "mode", "either potion or potion", "potion",
+ StringArgumentType.string(), String.class,
+ builder, dispatcher
+ );
+ }
+
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent event) {
+ if (BoSCoVicino.minecraft == null) return;
+ if (BoSCoVicino.minecraft.player == null) return;
+ if (this.mode.get().equals("potion")) {
+ BoSCoVicino.minecraft.player.addEffect(new EffectInstance(Effect.byId(16), 5204));
+ }
+ }
+
+ @Override
+ protected void onDisabled() {
+ if (this.mode.get().equals("potion")) {
+ BoSCoVicino.minecraft.player.removeEffect(Effect.byId(16));
+ }
+ }
+}
diff --git a/src/main/java/ftbsc/bscv/patches/TestPatch.java b/src/main/java/ftbsc/bscv/patches/TestPatch.java
new file mode 100644
index 0000000..5c6c152
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/patches/TestPatch.java
@@ -0,0 +1,51 @@
+package ftbsc.bscv.patches;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.InsnList;
+import org.objectweb.asm.tree.InsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+import ftbsc.lll.IInjector;
+
+/**
+ * When working as intended, this patch will crash the game
+ * as soon it finished loading with a NegativeArraySizeException.
+ */
+public class TestPatch {
+
+ public static class FramerateFix implements IInjector, Opcodes {
+ public String name() { return "FramerateFix"; }
+ public String targetClass() { return "net.minecraft.client.Minecraft"; }
+ public String methodName() { return "func_213243_aC"; } // getFramerateLimit()
+ public String methodDesc() { return "()I"; }
+
+ public void inject(ClassNode clazz, MethodNode main) {
+ // InsnList insnList = new InsnList();
+ // insnList.add(new InsnNode(POP));
+ // main.instructions.insert(insnList);
+ }
+ }
+
+
+ public static class TickPatch implements IInjector, Opcodes {
+ public String name() { return "TickPatch"; }
+ public String targetClass() { return "net.minecraft.client.Minecraft"; }
+ public String methodName() { return "func_71407_l"; } // tick()
+ public String methodDesc() { return "()V"; }
+
+ public void inject(ClassNode clazz, MethodNode main) {
+ // InsnList insnList = new InsnList();
+ // insnList.add(new InsnNode(POP));
+ // insnList.add(new InsnNode(POP));
+ // insnList.add(new InsnNode(POP));
+ // insnList.add(new InsnNode(POP));
+ // insnList.add(new InsnNode(POP));
+ // insnList.add(new InsnNode(POP));
+ // insnList.add(new InsnNode(POP));
+ // insnList.add(new InsnNode(POP));
+ // main.instructions.insert(insnList);
+ }
+ }
+
+}
diff --git a/src/main/java/ftbsc/bscv/tools/Anchor.java b/src/main/java/ftbsc/bscv/tools/Anchor.java
new file mode 100644
index 0000000..29e4da7
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/tools/Anchor.java
@@ -0,0 +1,51 @@
+package ftbsc.bscv.tools;
+
+import ftbsc.bscv.BoSCoVicino;
+import net.minecraft.client.MainWindow;
+import net.minecraft.client.gui.screen.ChatScreen;
+import net.minecraft.util.math.vector.Vector2f;
+
+public enum Anchor {
+
+ TOPLEFT("TOPLEFT"), TOPCENTER("TOPCENTER"), TOPRIGHT("TOPRIGHT"),
+ MIDDLELEFT("MIDDLELEFT"), MIDDLECENTER("MIDDLECENTER"), MIDDLERIGHT("MIDDLERIGHT"),
+ BOTTOMLEFT("BOTTOMLEFT"), BOTTOMCENTER("BOTTOMCENTER"), BOTTOMRIGHT("BOTTOMRIGHT");
+
+ private Anchor(String in) { }
+
+ public Vector2f translate(Vector2f in, int textWidth, int lineHeight, float scale, MainWindow window) {
+ int offset = 0;
+ switch (this) {
+ case BOTTOMLEFT:
+ case BOTTOMCENTER:
+ case BOTTOMRIGHT:
+ if (BoSCoVicino.minecraft.screen instanceof ChatScreen) {
+ offset = 15;
+ }
+ default:
+ }
+ // TODO de-spaghetti this mess
+ switch (this) {
+ case TOPLEFT:
+ return new Vector2f(in.x, in.y);
+ case TOPCENTER:
+ return new Vector2f((window.getWidth() / (scale * 4.0f)) + in.x - (textWidth / 2), in.y);
+ case TOPRIGHT:
+ return new Vector2f((window.getWidth() / (scale * 2.0f)) - (in.x + textWidth), in.y);
+ case MIDDLELEFT:
+ return new Vector2f(in.x, (window.getHeight() / (scale * 4.0f)) + in.y - (lineHeight / 2));
+ case MIDDLECENTER:
+ return new Vector2f((window.getWidth() / (scale * 4.0f)) + in.x - (textWidth / 2), (window.getHeight() / (scale * 4.0f)) + in.y - (lineHeight / 2));
+ case MIDDLERIGHT:
+ return new Vector2f((window.getWidth() / (scale * 2.0f)) - (in.x + textWidth ), (window.getHeight() / (scale * 4.0f)) + in.y - (lineHeight / 2));
+ case BOTTOMLEFT:
+ return new Vector2f(in.x, (window.getHeight() / (scale * 2.0f)) - (in.y + lineHeight + offset));
+ case BOTTOMCENTER:
+ return new Vector2f((window.getWidth() / (scale * 4.0f)) + in.x - (textWidth / 2), (window.getHeight() / (scale * 2.0f)) - (in.y + lineHeight + offset));
+ case BOTTOMRIGHT:
+ return new Vector2f((window.getWidth() / (scale * 4.0f)) - (in.x + textWidth), (window.getHeight() / (scale * 2.0f)) - (in.y + lineHeight + offset));
+ default:
+ return new Vector2f(0.0f, 0.0f);
+ }
+ }
+}
diff --git a/src/main/java/ftbsc/bscv/tools/Text.java b/src/main/java/ftbsc/bscv/tools/Text.java
new file mode 100644
index 0000000..c1fa746
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/tools/Text.java
@@ -0,0 +1,89 @@
+package ftbsc.bscv.tools;
+
+import com.mojang.blaze3d.matrix.MatrixStack;
+import com.mojang.blaze3d.systems.RenderSystem;
+
+import ftbsc.bscv.BoSCoVicino;
+import net.minecraft.client.MainWindow;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.util.math.vector.Vector2f;
+import net.minecraft.util.text.Color;
+import net.minecraft.util.text.ITextComponent;
+import net.minecraft.util.text.StringTextComponent;
+import net.minecraft.util.text.Style;
+
+
+public final class Text {
+ String text;
+ Anchor anchor;
+ Style style;
+ int x;
+ int y;
+ double scale;
+
+ private Text() {
+ this.text = "";
+ this.anchor = Anchor.TOPLEFT;
+ this.style = Style.EMPTY.withColor(Color.fromRgb(16777215));
+ this.x = 0;
+ this.y = 0;
+ this.scale = 1.0;
+ }
+
+ public static Text TextBuilder() {
+ return new Text();
+ }
+
+ public Text txt(String txt) {
+ this.text = txt;
+ return this;
+ }
+
+ public Text anchor(Anchor a) {
+ this.anchor = a;
+ return this;
+ }
+
+ public Text style(Style in) {
+ this.style = in;
+ return this;
+ }
+
+ public Text x(int x) {
+ this.x = x;
+ return this;
+ }
+
+ public Text y(int y) {
+ this.y = y;
+ return this;
+ }
+
+ public Text scale(double scale) {
+ this.scale = scale;
+ return this;
+ }
+
+ public void render(MatrixStack stack, MainWindow window) {
+ FontRenderer font = BoSCoVicino.minecraft.font;
+ ITextComponent text = new StringTextComponent(this.text).setStyle(this.style);
+ Vector2f abs_coords = this.anchor.translate(
+ new Vector2f(this.x, this.y),
+ font.width(text),
+ font.lineHeight,
+ (float) this.scale,
+ window
+ );
+ // TODO is there any non-deprecated way?
+ RenderSystem.pushMatrix();
+ RenderSystem.scaled(this.scale, this.scale, this.scale);
+ font.drawShadow(
+ stack,
+ text,
+ abs_coords.x,
+ abs_coords.y,
+ 10 // ???? TODO!
+ );
+ RenderSystem.popMatrix();
+ }
+}
diff --git a/src/main/java/ftbsc/bscv/tools/Utils.java b/src/main/java/ftbsc/bscv/tools/Utils.java
new file mode 100644
index 0000000..e9a068f
--- /dev/null
+++ b/src/main/java/ftbsc/bscv/tools/Utils.java
@@ -0,0 +1,10 @@
+package ftbsc.bscv.tools;
+
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public class Utils {
+ public static <I, O> O coalesce(I val, Function<I, O> f, Supplier<O> fallback) {
+ return val == null ? fallback.get() : f.apply(val);
+ }
+}