Compare commits

..

1 commit

Author SHA1 Message Date
33ece210f5 chore: initial work on a better chat patch 2023-03-20 23:28:27 +01:00
44 changed files with 355 additions and 902 deletions

3
.gitignore vendored
View file

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

View file

@ -6,10 +6,12 @@ plugins {
alias libs.plugins.checkerFramework alias libs.plugins.checkerFramework
} }
version = versionDetails().lastTag version = gitVersion()
group = 'ftbsc' group = 'ftbsc'
archivesBaseName = 'bscv' archivesBaseName = 'bscv'
def shortVersion = version.split('-')[0].replaceAll(".dirty", "") // necessary when there are no extra commits on tags, and thus no dash
project.ext { project.ext {
deployJarDo = getProjectProperty("deployJar.do", "false") deployJarDo = getProjectProperty("deployJar.do", "false")
deployJarTargetDir = getProjectProperty("deployJar.targetDir", ".") deployJarTargetDir = getProjectProperty("deployJar.targetDir", ".")
@ -64,11 +66,11 @@ dependencies {
} }
compileJava { //mappings for lillero-processor compileJava { //mappings for lillero-processor
options.compilerArgs << '-AmappingsFile=https://data.fantabos.co/1.16.5.tsrg' options.compilerArgs << '-AmappingsFile=https://data.fantabos.co/output.tsrg'
} }
jar { jar {
archiveFileName = "${jar.archiveBaseName.get()}-${archiveVersion.get()}.${jar.archiveExtension.get()}" archiveFileName = "${jar.archiveBaseName.get()}-${shortVersion}.${jar.archiveExtension.get()}"
manifest { manifest {
attributes([ attributes([
"Specification-Title": "bscv", "Specification-Title": "bscv",

View file

@ -4,8 +4,8 @@ gitVersion = "0.13.0"
minecraft = "1.16.5" minecraft = "1.16.5"
forge = "1.16.5-36.2.34" forge = "1.16.5-36.2.34"
autoService = "1.0.1" autoService = "1.0.1"
lillero = "0.4.1" lillero = "0.3.4"
lilleroProcessor = "0.5.2" lilleroProcessor = "0.4.2"
checkerFramework = "0.6.24" checkerFramework = "0.6.24"
[plugins] [plugins]

View file

@ -8,7 +8,6 @@ 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;
@ -43,9 +42,6 @@ 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);
@ -57,8 +53,6 @@ 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();
@ -77,13 +71,9 @@ public class Boscovicino implements ICommons {
} }
public static void log(String message) { public static void log(String message) {
log(message, true);
}
public static void log(String message, boolean overlay) {
LOGGER.info(message); LOGGER.info(message);
if (MC.player != null) { if (MC.player != null) {
MC.player.displayClientMessage(new StringTextComponent(message), overlay); MC.player.displayClientMessage(new StringTextComponent(message), true);
} }
} }

View file

@ -1,72 +0,0 @@
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 net.minecraft.command.arguments.BlockStateArgument;
import net.minecraft.command.arguments.BlockStateInput;
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;
})
)
)
)
.then(
Commands.literal("id")
.then(
Commands.argument("name", BlockStateArgument.block())
.executes( ctx -> {
BlockStateInput arg = ctx.getArgument("name", BlockStateInput.class);
BlockState state = arg.getState();
int block_id = Block.getId(state);
log("block #[%d:%d] >> %s", block_id >> 4, block_id & 0xF, state.toString());
return 1;
})
)
)
.executes(ctx -> {
log("no block specified");
return 0;
});
}
}

View file

@ -4,7 +4,6 @@ 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;
@ -19,18 +18,17 @@ 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("info") Commands.literal("pos")
.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();
BlockState state = MC.level.getBlockState(pos); log("Block @ %s (%s)", pos.toString(), dir.toString());
log("Block @ %s (%s): %s", pos.toString(), dir.toString(), state.toString());
return 1; return 1;
case ENTITY: case ENTITY:
log("Entity @ %s (TODO!)", MC.hitResult.getLocation().toString()); log("Entity @ %s", MC.hitResult.getLocation().toString());
return 1; return 1;
default: default:
case MISS: case MISS:

View file

@ -1,25 +1,18 @@
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;
import ftbsc.bscv.tools.Inventory; 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.command.arguments.ItemArgument;
import net.minecraft.command.arguments.ItemInput;
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 ItemCommand extends AbstractCommand { public class Item 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
@ -39,29 +32,6 @@ public class ItemCommand 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;
})
)
)
.then(
Commands.literal("id")
.then(
Commands.argument("name", ItemArgument.item())
.executes( ctx -> {
ItemInput arg = ctx.getArgument("name", ItemInput.class);
Item item = arg.getItem();
log("item #[%d] >> %s", Item.getId(item), item.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 java.util.stream.Collectors; import static ftbsc.bscv.Boscovicino.log;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class ModCommands extends AbstractCommand { public class ModCommands extends AbstractCommand {
@ -43,11 +43,8 @@ public class ModCommands extends AbstractCommand {
}) })
) )
.executes(ctx -> { .executes(ctx -> {
String mods = Boscovicino.modManager.mods.stream() log("no args specified");
.map(x -> x.getName()) return 0;
.collect(Collectors.joining(","));
Boscovicino.log("[ %s ]", mods);
return 1;
}); });
} }

View file

@ -1,7 +1,6 @@
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;
@ -52,7 +51,7 @@ public abstract class QuickModule extends AbstractModule {
public QuickModule() { public QuickModule() {
super(); super();
this.keybind = new KeyBinding(Keybind.name(this.getName()), this.getDefaultKey(), Keybind.category()); this.keybind = new KeyBinding(key_name(this.getName()), this.getDefaultKey(), key_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
@ -77,4 +76,12 @@ 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

@ -3,6 +3,7 @@ package ftbsc.bscv.modules.defense;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import ftbsc.bscv.Boscovicino; import ftbsc.bscv.Boscovicino;
import ftbsc.bscv.ICommons;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import ftbsc.bscv.modules.QuickModule; import ftbsc.bscv.modules.QuickModule;
import ftbsc.bscv.modules.self.AutoTool; import ftbsc.bscv.modules.self.AutoTool;
@ -22,7 +23,7 @@ import net.minecraftforge.event.TickEvent.Phase;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class Aura extends QuickModule { public class Aura extends QuickModule implements ICommons {
private enum LookType { private enum LookType {
NONE, NONE,
@ -52,7 +53,7 @@ public class Aura extends QuickModule {
this.reach = Setting.Decimal.builder() this.reach = Setting.Decimal.builder()
.min(0.) .min(0.)
.fallback(4.) .fallback(5.)
.name("reach") .name("reach")
.comment("aura attack reach") .comment("aura attack reach")
.build(this); .build(this);
@ -128,9 +129,6 @@ public class Aura extends QuickModule {
if (MC.player.getAttackStrengthScale(0.f) < this.strenght.get()) return; if (MC.player.getAttackStrengthScale(0.f) < this.strenght.get()) return;
float distance = Float.MAX_VALUE;
Entity target = null;
for (Entity e : MC.level.entitiesForRendering()) { for (Entity e : MC.level.entitiesForRendering()) {
if (e.equals(MC.player)) continue; if (e.equals(MC.player)) continue;
if (!(e instanceof LivingEntity)) continue; if (!(e instanceof LivingEntity)) continue;
@ -145,21 +143,13 @@ public class Aura extends QuickModule {
} }
if (this.trace.get() && !MC.player.canSee(e)) continue; if (this.trace.get() && !MC.player.canSee(e)) continue;
float dist = MC.player.distanceTo(e);
if (dist < distance) {
distance = dist;
target = e;
}
}
if (target != null) {
switch (this.look.get()) { switch (this.look.get()) {
case ONCE: case ONCE:
MC.player.lookAt(Type.EYES, target.getEyePosition(1.0F)); MC.player.lookAt(Type.EYES, e.getEyePosition(1.0F));
MC.player.connection.send(new CPlayerPacket.RotationPacket(MC.player.yRot, MC.player.xRot, MC.player.isOnGround())); MC.player.connection.send(new CPlayerPacket.RotationPacket(MC.player.yRot, MC.player.xRot, MC.player.isOnGround()));
break; break;
case PACKET: case PACKET:
this.lookAtHidden(Type.EYES, target.getEyePosition(1.0F)); this.lookAtHidden(Type.EYES, e.getEyePosition(1.0F));
break; break;
case NONE: break; case NONE: break;
} }
@ -167,10 +157,12 @@ public class Aura extends QuickModule {
if (this.tool.get()) { if (this.tool.get()) {
this.autotool.selectBestWeapon(); this.autotool.selectBestWeapon();
} }
MC.gameMode.attack(MC.player, target); MC.gameMode.attack(MC.player, e);
if (this.swing.get()) { if (this.swing.get()) {
MC.player.swing(Hand.MAIN_HAND); MC.player.swing(Hand.MAIN_HAND);
} }
break; // TODO should find all valid targets and choose one rather than stopping here
} }
} }
} }

View file

@ -4,7 +4,6 @@ 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;
@ -49,6 +48,38 @@ 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();
@ -60,7 +91,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 (Inventory.matchItem(this.pattern, stack)) { if (this.matches(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

@ -175,13 +175,10 @@ public class InfoDisplay extends HudModule {
@SubscribeEvent @SubscribeEvent
public void onRenderOverlay(RenderGameOverlayEvent event) { public void onRenderOverlay(RenderGameOverlayEvent event) {
if ( if (event.getType() == ElementType.POTION_ICONS) {
event.getType() == ElementType.POTION_ICONS if (this.hide_effects.get() && event.isCancelable()) {
&& MC.screen == null event.setCanceled(true);
&& this.hide_effects.get() }
&& event.isCancelable()
) {
event.setCanceled(true);
} }
if (event.getType() != ElementType.TEXT) return; if (event.getType() != ElementType.TEXT) return;

View file

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

View file

@ -1,38 +1,19 @@
package ftbsc.bscv.modules.hud; package ftbsc.bscv.modules.hud;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import ftbsc.bscv.ICommons;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import ftbsc.bscv.modules.HudModule; import ftbsc.bscv.modules.HudModule;
import ftbsc.bscv.tools.Setting;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType; import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import static ftbsc.bscv.tools.Text.TextBuilder; import static ftbsc.bscv.tools.Text.TextBuilder;
import static ftbsc.bscv.Boscovicino.log;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class PlayerList extends HudModule { public class PlayerList extends HudModule implements ICommons {
public final ForgeConfigSpec.ConfigValue<Boolean> notify;
public PlayerList() {
super();
this.notify = Setting.Bool.builder()
.fallback(false)
.name("notify")
.comment("notify when players enter render distance")
.build(this);
}
@SubscribeEvent @SubscribeEvent
public void onRenderOverlay(RenderGameOverlayEvent event) { public void onRenderOverlay(RenderGameOverlayEvent event) {
@ -54,14 +35,4 @@ public class PlayerList extends HudModule {
offset += MC.font.lineHeight; offset += MC.font.lineHeight;
} }
} }
@SubscribeEvent
public void onEntityEntersRenderdistance(EntityJoinWorldEvent event) {
if (!notify.get()) return;
if (event.getEntity() instanceof PlayerEntity){
PlayerEntity player = (PlayerEntity) event.getEntity();
if (MC.player != null && player.getId() == MC.player.getId()) return;
log(String.format("%s spotted", player.getDisplayName().getString()), false);
}
}
} }

View file

@ -0,0 +1,21 @@
package ftbsc.bscv.modules.hud;
import ftbsc.bscv.modules.AbstractModule;
import ftbsc.bscv.tools.Setting;
import net.minecraftforge.common.ForgeConfigSpec;
public class Terminal extends AbstractModule {
public final ForgeConfigSpec.ConfigValue<Integer> msg_count;
public Terminal() {
super();
this.msg_count = Setting.Number.builder()
.min(-1)
.fallback(100)
.name("msg-count")
.comment("How many messages to keep in chat, set to 0 for unlimited")
.build(this);
}
}

View file

@ -1,11 +1,12 @@
package ftbsc.bscv.modules.motion; package ftbsc.bscv.modules.motion;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import ftbsc.bscv.ICommons;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import ftbsc.bscv.modules.QuickModule; import ftbsc.bscv.modules.QuickModule;
import ftbsc.bscv.patches.PacketPatch.PacketEvent; import ftbsc.bscv.patches.PacketPatch.PacketEvent;
import ftbsc.bscv.tools.Keyboard;
import ftbsc.bscv.tools.Setting; import ftbsc.bscv.tools.Setting;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.network.play.client.CPlayerPacket; import net.minecraft.network.play.client.CPlayerPacket;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec;
@ -25,7 +26,6 @@ public class VanillaFlight extends QuickModule {
private static final int MS_PER_TICK = 50; private static final int MS_PER_TICK = 50;
public final ForgeConfigSpec.ConfigValue<Boolean> force; public final ForgeConfigSpec.ConfigValue<Boolean> force;
public final ForgeConfigSpec.ConfigValue<Boolean> drift;
public final ForgeConfigSpec.ConfigValue<Double> speed; public final ForgeConfigSpec.ConfigValue<Double> speed;
public final ForgeConfigSpec.ConfigValue<AntikickMode> antikick; public final ForgeConfigSpec.ConfigValue<AntikickMode> antikick;
public final ForgeConfigSpec.ConfigValue<Double> antikick_magnitude; public final ForgeConfigSpec.ConfigValue<Double> antikick_magnitude;
@ -40,24 +40,18 @@ 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(true)
.build(this);
this.drift = Setting.Bool.builder()
.name("drift")
.comment("gradually reduce momentum")
.fallback(false) .fallback(false)
.build(this); .build(this);
this.speed = Setting.Decimal.builder() this.speed = Setting.Decimal.builder()
.min(0.) .min(0.)
.fallback(0.1) .fallback(0.05)
.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.PACKET) .fallback(AntikickMode.NONE)
.name("antikick") .name("antikick")
.comment("prevent vanilla flight kick by descending") .comment("prevent vanilla flight kick by descending")
.build(this); .build(this);
@ -109,10 +103,6 @@ public class VanillaFlight extends QuickModule {
MC.player.abilities.flying = true; MC.player.abilities.flying = true;
} }
if (!this.drift.get() && !Keyboard.isMoving()) {
MC.player.setDeltaMovement(Vector3d.ZERO);
}
this.tick = ( this.tick + 1 ) % this.antikick_cycle.get(); this.tick = ( this.tick + 1 ) % this.antikick_cycle.get();
Vector3d pos = MC.player.position(); Vector3d pos = MC.player.position();

View file

@ -34,7 +34,7 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class PacketLogger extends QuickModule { public class PacketLogger extends QuickModule {
public static final SimpleDateFormat CAPTURE_DATE_FORMAT = new SimpleDateFormat("yyyy_MM_dd@HH-mm-ss"); public static final SimpleDateFormat CAPTURE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
@Override @Override
public void enable() { public void enable() {

View file

@ -1,6 +1,7 @@
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.ICommons;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import ftbsc.bscv.modules.AbstractModule; import ftbsc.bscv.modules.AbstractModule;
import ftbsc.bscv.patches.PacketPatch.PacketEvent; import ftbsc.bscv.patches.PacketPatch.PacketEvent;
@ -12,7 +13,7 @@ import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class AntiHunger extends AbstractModule { public class AntiHunger extends AbstractModule implements ICommons {
public final ForgeConfigSpec.ConfigValue<Boolean> sprint; public final ForgeConfigSpec.ConfigValue<Boolean> sprint;
public final ForgeConfigSpec.ConfigValue<Boolean> hover; public final ForgeConfigSpec.ConfigValue<Boolean> hover;

View file

@ -1,6 +1,7 @@
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.ICommons;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import ftbsc.bscv.modules.AbstractModule; import ftbsc.bscv.modules.AbstractModule;
import ftbsc.bscv.patches.PacketPatch.PacketEvent; import ftbsc.bscv.patches.PacketPatch.PacketEvent;
@ -12,7 +13,7 @@ import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class AutoDisconnect extends AbstractModule { public class AutoDisconnect extends AbstractModule implements ICommons {
public final ForgeConfigSpec.ConfigValue<Double> threshold; public final ForgeConfigSpec.ConfigValue<Double> threshold;

View file

@ -1,6 +1,7 @@
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.ICommons;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import ftbsc.bscv.modules.AbstractModule; import ftbsc.bscv.modules.AbstractModule;
import ftbsc.bscv.patches.PacketPatch.PacketEvent; import ftbsc.bscv.patches.PacketPatch.PacketEvent;
@ -9,16 +10,14 @@ import net.minecraft.client.Minecraft;
import net.minecraft.network.play.server.SPlaySoundEffectPacket; import net.minecraft.network.play.server.SPlaySoundEffectPacket;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.SoundEvents; import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class AutoFish extends AbstractModule { public class AutoFish extends AbstractModule implements ICommons {
public final ForgeConfigSpec.ConfigValue<Boolean> recast; public final ForgeConfigSpec.ConfigValue<Boolean> recast;
public final ForgeConfigSpec.ConfigValue<Integer> delay; public final ForgeConfigSpec.ConfigValue<Integer> delay;
public final ForgeConfigSpec.ConfigValue<Double> distance;
// public final ForgeConfigSpec.ConfigValue<Long> reaction; // public final ForgeConfigSpec.ConfigValue<Long> reaction;
public AutoFish() { public AutoFish() {
@ -35,23 +34,13 @@ public class AutoFish extends AbstractModule {
.name("delay") .name("delay")
.comment("how long in ms to wait before recasting hook") .comment("how long in ms to wait before recasting hook")
.build(this); .build(this);
this.distance = Setting.Decimal.builder()
.fallback(0.)
.name("distance")
.comment("ignore splashes further than X blocks, set to 0 to disable")
.build(this);
} }
@SubscribeEvent @SubscribeEvent
public void onPacket(PacketEvent.Incoming event) { public void onPacket(PacketEvent.Incoming event) {
if (event.packet instanceof SPlaySoundEffectPacket) { if (event.packet instanceof SPlaySoundEffectPacket) {
SPlaySoundEffectPacket packet = (SPlaySoundEffectPacket) event.packet; SPlaySoundEffectPacket packet = (SPlaySoundEffectPacket) event.packet;
Vector3d location = new Vector3d(packet.getX(), packet.getY(), packet.getZ()); if (packet.getSound().equals(SoundEvents.FISHING_BOBBER_SPLASH)) {
if (
packet.getSound().equals(SoundEvents.FISHING_BOBBER_SPLASH)
&& (this.distance.get() == 0 || MC.player.position().distanceTo(location) < this.distance.get())
) {
MC.gameMode.useItem(MC.player, MC.level, Hand.MAIN_HAND); MC.gameMode.useItem(MC.player, MC.level, Hand.MAIN_HAND);
if (this.recast.get()) { if (this.recast.get()) {
new RecastThread(MC, this.delay.get()).start(); new RecastThread(MC, this.delay.get()).start();
@ -60,7 +49,6 @@ public class AutoFish extends AbstractModule {
} }
} }
// TODO don't spawn a thread, minecraft has a way to schedule actions for later
private class RecastThread extends Thread { private class RecastThread extends Thread {
private long delay; private long delay;
private Minecraft mc; private Minecraft mc;

View file

@ -1,14 +1,12 @@
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.ICommons;
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,10 +17,9 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
import java.util.List; import java.util.List;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class AutoTool extends AbstractModule { public class AutoTool extends AbstractModule implements ICommons {
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();
@ -32,12 +29,6 @@ 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) {
@ -57,12 +48,6 @@ 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

@ -1,79 +0,0 @@
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

@ -1,39 +0,0 @@
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

@ -1,13 +1,18 @@
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.ICommons;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import ftbsc.bscv.modules.QuickModule; import ftbsc.bscv.modules.QuickModule;
import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import java.lang.reflect.Field;
import static ftbsc.bscv.Boscovicino.log;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class FastInteract extends QuickModule { public class FastInteract extends QuickModule implements ICommons {
protected int getDefaultKey() { return UNBOUND; } protected int getDefaultKey() { return UNBOUND; }

View file

@ -2,6 +2,7 @@ package ftbsc.bscv.modules.self;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import ftbsc.bscv.Boscovicino; import ftbsc.bscv.Boscovicino;
import ftbsc.bscv.ICommons;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import ftbsc.bscv.modules.QuickModule; import ftbsc.bscv.modules.QuickModule;
import ftbsc.bscv.patches.PacketPatch.PacketEvent; import ftbsc.bscv.patches.PacketPatch.PacketEvent;
@ -17,7 +18,7 @@ import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class Freecam extends QuickModule { public class Freecam extends QuickModule implements ICommons {
public final ForgeConfigSpec.ConfigValue<Boolean> log; public final ForgeConfigSpec.ConfigValue<Boolean> log;
public final ForgeConfigSpec.ConfigValue<Double> speed; public final ForgeConfigSpec.ConfigValue<Double> speed;

View file

@ -1,72 +0,0 @@
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

@ -5,13 +5,14 @@ import org.lwjgl.opengl.GL11;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import ftbsc.bscv.ICommons;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import ftbsc.bscv.modules.QuickModule; import ftbsc.bscv.modules.QuickModule;
import net.minecraftforge.client.event.RenderLivingEvent; import net.minecraftforge.client.event.RenderLivingEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class Chams extends QuickModule { public class Chams extends QuickModule implements ICommons {
protected int getDefaultKey() { return UNBOUND; } protected int getDefaultKey() { return UNBOUND; }

View file

@ -1,6 +1,7 @@
package ftbsc.bscv.modules.vision; package ftbsc.bscv.modules.vision;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import ftbsc.bscv.ICommons;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import ftbsc.bscv.modules.QuickModule; import ftbsc.bscv.modules.QuickModule;
import net.minecraft.potion.Effect; import net.minecraft.potion.Effect;
@ -11,7 +12,7 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class Fullbright extends QuickModule { public class Fullbright extends QuickModule implements ICommons {
private final static int NIGHT_VISION_ID = 16; private final static int NIGHT_VISION_ID = 16;
private final static int FOUR_MINUTES_TWENTY_SECONDS = 5204; private final static int FOUR_MINUTES_TWENTY_SECONDS = 5204;

View file

@ -1,5 +1,7 @@
package ftbsc.bscv.modules.vision; package ftbsc.bscv.modules.vision;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
@ -9,7 +11,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import ftbsc.bscv.api.ILoadable; import ftbsc.bscv.api.ILoadable;
import ftbsc.bscv.modules.AbstractModule; import ftbsc.bscv.modules.QuickModule;
import ftbsc.bscv.patches.PacketPatch.PacketEvent; import ftbsc.bscv.patches.PacketPatch.PacketEvent;
import ftbsc.bscv.tools.Setting; import ftbsc.bscv.tools.Setting;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
@ -18,10 +20,8 @@ import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.WorldVertexBufferUploader; import net.minecraft.client.renderer.WorldVertexBufferUploader;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.network.play.server.SChangeBlockPacket; import net.minecraft.network.play.server.SChangeBlockPacket;
import net.minecraft.network.play.server.SChunkDataPacket;
import net.minecraft.network.play.server.SMultiBlockChangePacket; import net.minecraft.network.play.server.SMultiBlockChangePacket;
import net.minecraft.util.Tuple; import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3i; import net.minecraft.util.math.vector.Vector3i;
import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.client.event.RenderWorldLastEvent;
@ -31,7 +31,7 @@ import net.minecraftforge.event.TickEvent.Phase;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
@AutoService(ILoadable.class) @AutoService(ILoadable.class)
public class UpdateESP extends AbstractModule { public class UpdateESP extends QuickModule {
public final ForgeConfigSpec.ConfigValue<Integer> duration; public final ForgeConfigSpec.ConfigValue<Integer> duration;
public final ForgeConfigSpec.ConfigValue<Double> alpha; public final ForgeConfigSpec.ConfigValue<Double> alpha;
@ -144,7 +144,7 @@ public class UpdateESP extends AbstractModule {
if (event.packet instanceof SMultiBlockChangePacket) { if (event.packet instanceof SMultiBlockChangePacket) {
SMultiBlockChangePacket packet = (SMultiBlockChangePacket) event.packet; SMultiBlockChangePacket packet = (SMultiBlockChangePacket) event.packet;
packet.runUpdates( (pos, state) -> this.updates.add(new Tuple<>(new BlockPos(pos), System.currentTimeMillis())) ); packet.runUpdates( (pos, state) -> this.updates.add(new Tuple<>(pos, System.currentTimeMillis())) );
} }
} }
} }

View file

@ -5,7 +5,7 @@ import ftbsc.lll.processor.annotations.Find;
import ftbsc.lll.processor.annotations.Injector; import ftbsc.lll.processor.annotations.Injector;
import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.annotations.Patch;
import ftbsc.lll.processor.annotations.Target; import ftbsc.lll.processor.annotations.Target;
import ftbsc.lll.proxies.impl.MethodProxy; import ftbsc.lll.proxies.MethodProxy;
import ftbsc.lll.tools.InsnSequence; import ftbsc.lll.tools.InsnSequence;
import ftbsc.lll.tools.PatternMatcher; import ftbsc.lll.tools.PatternMatcher;
import ftbsc.lll.tools.nodes.MethodProxyInsnNode; import ftbsc.lll.tools.nodes.MethodProxyInsnNode;
@ -20,6 +20,11 @@ import org.objectweb.asm.tree.*;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
public class BackgroundPatch implements ICommons { public class BackgroundPatch implements ICommons {
public static boolean shouldDrawBackground(Screen screen) {
return MinecraftForge.EVENT_BUS.post(new RenderBackgroundEvent(screen));
}
@Cancelable @Cancelable
public static class RenderBackgroundEvent extends Event { public static class RenderBackgroundEvent extends Event {
public final Screen screen; public final Screen screen;
@ -29,21 +34,15 @@ public class BackgroundPatch implements ICommons {
} }
} }
@Patch(Screen.class) @Patch(value = Screen.class, reason = "add hook to cancel background on some screens")
public abstract static class BackgroundOverride implements Opcodes { public abstract static class BackgroundOverride implements Opcodes {
@Find(BackgroundOverride.class) @Find(parent = BackgroundPatch.class)
MethodProxy shouldDrawBackground; abstract MethodProxy shouldDrawBackground();
@Target
@Target(of = "shouldDrawBackground")
public static boolean shouldDrawBackground(Screen screen) {
return MinecraftForge.EVENT_BUS.post(new RenderBackgroundEvent(screen));
}
@Target(of = "injectCancelBackgroundHook")
abstract void renderBackground(MatrixStack stack, int x); abstract void renderBackground(MatrixStack stack, int x);
@Injector(reason = "add hook to cancel background on some screens") @Injector
public void injectCancelBackgroundHook(ClassNode clazz, MethodNode main) { public void inject(ClassNode clazz, MethodNode main) {
AbstractInsnNode found = PatternMatcher.builder() AbstractInsnNode found = PatternMatcher.builder()
.opcodes(ALOAD, ALOAD, ICONST_0, ICONST_0) .opcodes(ALOAD, ALOAD, ICONST_0, ICONST_0)
.ignoreFrames() .ignoreFrames()
@ -56,7 +55,7 @@ public class BackgroundPatch implements ICommons {
LabelNode skip = new LabelNode(); LabelNode skip = new LabelNode();
InsnSequence is = new InsnSequence(); InsnSequence is = new InsnSequence();
is.add(new VarInsnNode(ALOAD, 0)); is.add(new VarInsnNode(ALOAD, 0));
is.add(new MethodProxyInsnNode(INVOKESTATIC, shouldDrawBackground)); is.add(new MethodProxyInsnNode(INVOKESTATIC, shouldDrawBackground()));
is.add(new JumpInsnNode(IFEQ, skip)); is.add(new JumpInsnNode(IFEQ, skip));
is.add(new InsnNode(RETURN)); is.add(new InsnNode(RETURN));
is.add(skip); is.add(skip);

View file

@ -4,7 +4,7 @@ import ftbsc.lll.processor.annotations.Find;
import ftbsc.lll.processor.annotations.Injector; import ftbsc.lll.processor.annotations.Injector;
import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.annotations.Patch;
import ftbsc.lll.processor.annotations.Target; import ftbsc.lll.processor.annotations.Target;
import ftbsc.lll.proxies.impl.MethodProxy; import ftbsc.lll.proxies.MethodProxy;
import ftbsc.lll.tools.InsnSequence; import ftbsc.lll.tools.InsnSequence;
import ftbsc.lll.tools.nodes.MethodProxyInsnNode; import ftbsc.lll.tools.nodes.MethodProxyInsnNode;
import net.minecraft.client.entity.player.ClientPlayerEntity; import net.minecraft.client.entity.player.ClientPlayerEntity;
@ -20,24 +20,23 @@ public class BlockPushPatch {
@Cancelable @Cancelable
public static class PlayerBlockPushEvent extends Event {} public static class PlayerBlockPushEvent extends Event {}
@Patch(ClientPlayerEntity.class) public static boolean shouldCancelBlockCollisions() {
return MinecraftForge.EVENT_BUS.post(new PlayerBlockPushEvent());
}
@Patch(value = ClientPlayerEntity.class, reason = "add hook to cancel block collisions")
public abstract static class BlockCollisionsOverride implements Opcodes { public abstract static class BlockCollisionsOverride implements Opcodes {
@Find(BlockCollisionsOverride.class) @Find(parent = BlockPushPatch.class)
MethodProxy shouldCancelBlockCollisions; abstract MethodProxy shouldCancelBlockCollisions();
@Target(of = "shouldCancelBlockCollisions") @Target
public static boolean shouldCancelBlockCollisions() {
return MinecraftForge.EVENT_BUS.post(new PlayerBlockPushEvent());
}
@Target(of = "injectCancelCollisionsHook")
abstract void moveTowardsClosestSpace(double x, double z); abstract void moveTowardsClosestSpace(double x, double z);
@Injector(reason = "add hook to cancel block collisions") @Injector
public void injectCancelCollisionsHook(ClassNode clazz, MethodNode main) { public void inject(ClassNode clazz, MethodNode main) {
LabelNode skip = new LabelNode(); LabelNode skip = new LabelNode();
InsnSequence is = new InsnSequence(); InsnSequence is = new InsnSequence();
is.add(new MethodProxyInsnNode(INVOKESTATIC, shouldCancelBlockCollisions)); is.add(new MethodProxyInsnNode(INVOKESTATIC, shouldCancelBlockCollisions()));
is.add(new JumpInsnNode(IFEQ, skip)); is.add(new JumpInsnNode(IFEQ, skip));
is.add(new InsnNode(RETURN)); is.add(new InsnNode(RETURN));
is.add(skip); is.add(skip);

View file

@ -5,7 +5,7 @@ import ftbsc.lll.processor.annotations.Find;
import ftbsc.lll.processor.annotations.Injector; import ftbsc.lll.processor.annotations.Injector;
import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.annotations.Patch;
import ftbsc.lll.processor.annotations.Target; import ftbsc.lll.processor.annotations.Target;
import ftbsc.lll.proxies.impl.MethodProxy; import ftbsc.lll.proxies.MethodProxy;
import ftbsc.lll.tools.InsnSequence; import ftbsc.lll.tools.InsnSequence;
import ftbsc.lll.tools.nodes.MethodProxyInsnNode; import ftbsc.lll.tools.nodes.MethodProxyInsnNode;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
@ -30,25 +30,35 @@ public class BoatPatch implements ICommons {
public static class Gravity extends Event { } public static class Gravity extends Event { }
} }
@Patch(BoatEntity.class) public static boolean boatControl() {
return MinecraftForge.EVENT_BUS.post(new BoatEvent.Control());
}
public static boolean boatClampRotation() {
return MinecraftForge.EVENT_BUS.post(new BoatEvent.ClampRotation());
}
public static boolean boatGravityCheck(Entity entity) {
if (MC.player == null) return false;
if (MC.player.getVehicle() == null) return false;
if (MC.player.getVehicle() != entity) return false;
return MinecraftForge.EVENT_BUS.post(new BoatEvent.Gravity());
}
@Patch(value = BoatEntity.class, reason = "add hook to cancel vanilla boat controls")
public abstract static class BoatControlOverride implements Opcodes { public abstract static class BoatControlOverride implements Opcodes {
@Find(BoatControlOverride.class) @Find(parent = BoatPatch.class)
MethodProxy boatControl; abstract MethodProxy boatControl();
@Target(of = "boatControl") @Target
public static boolean boatControl() {
return MinecraftForge.EVENT_BUS.post(new BoatEvent.Control());
}
@Target(of = "injectBoatControlHook")
public abstract void controlBoat(); public abstract void controlBoat();
@Injector(reason = "add hook to cancel vanilla boat controls") @Injector
public void injectBoatControlHook(ClassNode clazz, MethodNode main) { public void inject(ClassNode clazz, MethodNode main) {
// Hook at method start // Hook at method start
LabelNode skip = new LabelNode(); LabelNode skip = new LabelNode();
InsnSequence is = new InsnSequence(); InsnSequence is = new InsnSequence();
is.add(new MethodProxyInsnNode(INVOKESTATIC, boatControl)); is.add(new MethodProxyInsnNode(INVOKESTATIC, boatControl()));
is.add(new JumpInsnNode(IFEQ, skip)); is.add(new JumpInsnNode(IFEQ, skip));
is.add(new InsnNode(RETURN)); is.add(new InsnNode(RETURN));
is.add(skip); is.add(skip);
@ -57,25 +67,20 @@ public class BoatPatch implements ICommons {
} }
} }
@Patch(BoatEntity.class) @Patch(value = BoatEntity.class, reason = "add hook to cancel vanilla boat rotation clamping")
public abstract static class BoatClampOverride implements Opcodes { public abstract static class BoatClampOverride implements Opcodes {
@Find(BoatClampOverride.class) @Find(parent = BoatPatch.class)
MethodProxy boatClampRotation; abstract MethodProxy boatClampRotation();
@Target(of = "boatClampRotation") @Target
public static boolean boatClampRotation() {
return MinecraftForge.EVENT_BUS.post(new BoatEvent.ClampRotation());
}
@Target(of = "injectRotationClampingHook")
public abstract void clampRotation(Entity e); public abstract void clampRotation(Entity e);
@Injector(reason = "add hook to cancel vanilla boat rotation clamping") @Injector
public void injectRotationClampingHook(ClassNode clazz, MethodNode main) { public void inject(ClassNode clazz, MethodNode main) {
// Hook at method start // Hook at method start
LabelNode skip = new LabelNode(); LabelNode skip = new LabelNode();
InsnSequence is = new InsnSequence(); InsnSequence is = new InsnSequence();
is.add(new MethodProxyInsnNode(INVOKESTATIC, boatClampRotation)); is.add(new MethodProxyInsnNode(INVOKESTATIC, boatClampRotation()));
is.add(new JumpInsnNode(IFEQ, skip)); is.add(new JumpInsnNode(IFEQ, skip));
is.add(new InsnNode(RETURN)); is.add(new InsnNode(RETURN));
is.add(skip); is.add(skip);
@ -84,29 +89,21 @@ public class BoatPatch implements ICommons {
} }
} }
@Patch(Entity.class) @Patch(value = Entity.class, reason = "add hook to alter vanilla boat gravity")
public abstract static class BoatGravityOverride implements Opcodes { public abstract static class BoatGravityOverride implements Opcodes {
@Find(BoatGravityOverride.class) @Find(parent = BoatPatch.class)
MethodProxy boatGravityCheck; abstract MethodProxy boatGravityCheck();
@Target(of = "boatGravityCheck") @Target
public static boolean boatGravityCheck(Entity entity) {
if (MC.player == null) return false;
if (MC.player.getVehicle() == null) return false;
if (MC.player.getVehicle() != entity) return false;
return MinecraftForge.EVENT_BUS.post(new BoatEvent.Gravity());
}
@Target(of = "injectGravityHook")
public abstract boolean isNoGravity(); public abstract boolean isNoGravity();
@Injector(reason = "add hook to alter vanilla boat gravity") @Injector
public void injectGravityHook(ClassNode clazz, MethodNode main) { public void inject(ClassNode clazz, MethodNode main) {
// Hook at method start // Hook at method start
LabelNode skip = new LabelNode(); LabelNode skip = new LabelNode();
InsnSequence is = new InsnSequence(); InsnSequence is = new InsnSequence();
is.add(new VarInsnNode(ALOAD, 0)); is.add(new VarInsnNode(ALOAD, 0));
is.add(new MethodProxyInsnNode(INVOKESTATIC, boatGravityCheck)); is.add(new MethodProxyInsnNode(INVOKESTATIC, boatGravityCheck()));
is.add(new JumpInsnNode(IFEQ, skip)); is.add(new JumpInsnNode(IFEQ, skip));
is.add(new InsnNode(ICONST_1)); is.add(new InsnNode(ICONST_1));
is.add(new InsnNode(IRETURN)); is.add(new InsnNode(IRETURN));

View file

@ -1,12 +1,21 @@
package ftbsc.bscv.patches; package ftbsc.bscv.patches;
import ftbsc.bscv.modules.hud.Terminal;
import ftbsc.lll.processor.annotations.Find;
import ftbsc.lll.processor.annotations.Injector; import ftbsc.lll.processor.annotations.Injector;
import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.annotations.Patch;
import ftbsc.lll.processor.annotations.Target; import ftbsc.lll.processor.annotations.Target;
import ftbsc.lll.proxies.FieldProxy;
import ftbsc.lll.tools.InsnSequence; import ftbsc.lll.tools.InsnSequence;
import ftbsc.lll.tools.PatternMatcher; import ftbsc.lll.tools.PatternMatcher;
import ftbsc.lll.tools.debug.BytecodePrinter;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.NewChatGui;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.eventbus.api.Cancelable;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*; import org.objectweb.asm.tree.*;
@ -14,30 +23,55 @@ import org.objectweb.asm.tree.*;
public class ChatPatch { public class ChatPatch {
@Patch(Minecraft.class) @Cancelable
public static class ClearChatEvent extends Event {}
public static boolean shouldPreventChatClearing() {
return MinecraftForge.EVENT_BUS.post(new ClearChatEvent());
}
@Patch(value = Minecraft.class, reason = "add hook to prevent chat from being cleared")
public abstract static class ChatClearInterceptor implements Opcodes { public abstract static class ChatClearInterceptor implements Opcodes {
// TODO this should be optional // TODO this should be optional
@Target(of = "injectClearChatHook") @Target
abstract void setScreen(Screen screen); abstract void setScreen(Screen screen);
@Injector(reason = "skips chat clearing") @Injector
public void injectClearChatHook(ClassNode clazz, MethodNode main) { public void inject(ClassNode clazz, MethodNode method) {
InsnSequence match = PatternMatcher.builder() InsnSequence match = PatternMatcher.builder()
.opcodes(ALOAD, GETFIELD, INVOKEVIRTUAL, ICONST_1, INVOKEVIRTUAL) .opcodes(ALOAD, GETFIELD, INVOKEVIRTUAL, ICONST_1, INVOKEVIRTUAL)
.ignoreLineNumbers() .ignoreLineNumbers()
.ignoreLabels() .ignoreLabels()
.ignoreFrames() .ignoreFrames()
.build() .build()
.find(main); .find(method);
LabelNode skip = new LabelNode(); LabelNode skip = new LabelNode();
JumpInsnNode jump = new JumpInsnNode(GOTO, skip); JumpInsnNode jump = new JumpInsnNode(GOTO, skip);
main.instructions.insertBefore(match.getFirst(), jump); method.instructions.insertBefore(match.getFirst(), jump);
main.instructions.insert(match.getLast(), skip); method.instructions.insert(match.getLast(), skip);
} }
} }
@Patch(value = NewChatGui.class, reason = "make max number of messages in chat configurable (instead of just 100)")
public abstract static class ChatHistoryRemoveInterceptor implements Opcodes {
@Target
abstract void addMessage(ITextComponent txt, int idk1, int idk2, boolean idk3);
@Find(parent = Terminal.class)
abstract FieldProxy msg_count();
@Injector
public void inject(ClassNode clazz, MethodNode method) {
InsnSequence match = PatternMatcher.builder()
.opcodes(ALOAD, ICONST_2, INVOKESPECIAL, INVOKEINTERFACE, GOTO)
.build()
.find(method);
}
}
} }

View file

@ -4,9 +4,10 @@ import ftbsc.lll.processor.annotations.Find;
import ftbsc.lll.processor.annotations.Injector; import ftbsc.lll.processor.annotations.Injector;
import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.annotations.Patch;
import ftbsc.lll.processor.annotations.Target; import ftbsc.lll.processor.annotations.Target;
import ftbsc.lll.proxies.impl.MethodProxy; import ftbsc.lll.proxies.MethodProxy;
import ftbsc.lll.tools.InsnSequence; import ftbsc.lll.tools.InsnSequence;
import ftbsc.lll.tools.PatternMatcher; import ftbsc.lll.tools.PatternMatcher;
import ftbsc.lll.tools.debug.BytecodePrinter;
import ftbsc.lll.tools.nodes.MethodProxyInsnNode; import ftbsc.lll.tools.nodes.MethodProxyInsnNode;
import net.minecraft.client.network.play.ClientPlayNetHandler; import net.minecraft.client.network.play.ClientPlayNetHandler;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
@ -29,21 +30,21 @@ public class CommandsPatch {
} }
} }
@Patch(ClientPlayNetHandler.class) public static void cmdBuilt(CommandDispatcher<CommandSource> dispatcher) {
MinecraftForge.EVENT_BUS.post(new CommandsBuiltEvent(dispatcher));
}
@Patch(value = ClientPlayNetHandler.class, reason = "add hook to insert our command suggestions")
public abstract static class CommandsDispatcherCatcher implements Opcodes { public abstract static class CommandsDispatcherCatcher implements Opcodes {
@Find(CommandsDispatcherCatcher.class) @Find(parent = CommandsPatch.class)
MethodProxy cmdBuilt; abstract MethodProxy cmdBuilt();
@Target(of = "cmdBuilt") @Target
public static void cmdBuilt(CommandDispatcher<CommandSource> dispatcher) {
MinecraftForge.EVENT_BUS.post(new CommandsBuiltEvent(dispatcher));
}
@Target(of = "injectCommandHandler")
abstract void handleCommands(SCommandListPacket pkt); abstract void handleCommands(SCommandListPacket pkt);
@Injector(reason = "add hook to insert our command suggestions") @Injector
public void injectCommandHandler(ClassNode clazz, MethodNode main) { public void inject(ClassNode clazz, MethodNode main) {
BytecodePrinter.logAsmMethod(main, "pre.log");
AbstractInsnNode found = PatternMatcher.builder() AbstractInsnNode found = PatternMatcher.builder()
.opcodes(ALOAD, INVOKEVIRTUAL, INVOKESPECIAL) .opcodes(ALOAD, INVOKEVIRTUAL, INVOKESPECIAL)
.ignoreFrames() .ignoreFrames()
@ -55,9 +56,10 @@ public class CommandsPatch {
InsnSequence is = new InsnSequence(); InsnSequence is = new InsnSequence();
is.add(new InsnNode(DUP)); is.add(new InsnNode(DUP));
is.add(new MethodProxyInsnNode(INVOKESTATIC, cmdBuilt)); is.add(new MethodProxyInsnNode(INVOKESTATIC, cmdBuilt()));
main.instructions.insert(found, is); main.instructions.insert(found, is);
BytecodePrinter.logAsmMethod(main, "post.log");
} }
} }
} }

View file

@ -5,7 +5,7 @@ import ftbsc.lll.processor.annotations.Find;
import ftbsc.lll.processor.annotations.Injector; import ftbsc.lll.processor.annotations.Injector;
import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.annotations.Patch;
import ftbsc.lll.processor.annotations.Target; import ftbsc.lll.processor.annotations.Target;
import ftbsc.lll.proxies.impl.MethodProxy; import ftbsc.lll.proxies.MethodProxy;
import ftbsc.lll.tools.InsnSequence; import ftbsc.lll.tools.InsnSequence;
import ftbsc.lll.tools.nodes.MethodProxyInsnNode; import ftbsc.lll.tools.nodes.MethodProxyInsnNode;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
@ -21,28 +21,27 @@ public class EntityPushPatch implements ICommons {
@Cancelable @Cancelable
public static class PlayerEntityPushEvent extends Event {} public static class PlayerEntityPushEvent extends Event {}
@Patch(Entity.class) public static boolean shouldCancelEntityCollisions(Entity e) {
public abstract static class EntityCollisionsOverride implements Opcodes { if (e.equals(MC.player)) {
@Find(EntityCollisionsOverride.class) return MinecraftForge.EVENT_BUS.post(new PlayerEntityPushEvent());
MethodProxy shouldCancelEntityCollisions;
@Target(of = "shouldCancelEntityCollisions")
public static boolean shouldCancelEntityCollisions(Entity e) {
if (e.equals(MC.player)) {
return MinecraftForge.EVENT_BUS.post(new PlayerEntityPushEvent());
}
return false;
} }
return false;
}
@Target(of = "injectEntityCollisionHook") @Patch(value = Entity.class, reason = "add hook to cancel entity collisions")
public abstract static class EntityCollisionsOverride implements Opcodes {
@Find(parent = EntityPushPatch.class)
abstract MethodProxy shouldCancelEntityCollisions();
@Target
abstract void push(double x, double y, double z); abstract void push(double x, double y, double z);
@Injector(reason = "add hook to cancel entity collisions") @Injector
public void injectEntityCollisionHook(ClassNode clazz, MethodNode main) { public void inject(ClassNode clazz, MethodNode main) {
LabelNode skip = new LabelNode(); LabelNode skip = new LabelNode();
InsnSequence is = new InsnSequence(); InsnSequence is = new InsnSequence();
is.add(new VarInsnNode(ALOAD, 0)); is.add(new VarInsnNode(ALOAD, 0));
is.add(new MethodProxyInsnNode(INVOKESTATIC, shouldCancelEntityCollisions)); is.add(new MethodProxyInsnNode(INVOKESTATIC, shouldCancelEntityCollisions()));
is.add(new JumpInsnNode(IFEQ, skip)); is.add(new JumpInsnNode(IFEQ, skip));
is.add(new InsnNode(RETURN)); is.add(new InsnNode(RETURN));
is.add(skip); is.add(skip);

View file

@ -5,7 +5,7 @@ import ftbsc.lll.processor.annotations.Find;
import ftbsc.lll.processor.annotations.Injector; import ftbsc.lll.processor.annotations.Injector;
import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.annotations.Patch;
import ftbsc.lll.processor.annotations.Target; import ftbsc.lll.processor.annotations.Target;
import ftbsc.lll.proxies.impl.MethodProxy; import ftbsc.lll.proxies.MethodProxy;
import ftbsc.lll.tools.InsnSequence; import ftbsc.lll.tools.InsnSequence;
import ftbsc.lll.tools.nodes.MethodProxyInsnNode; import ftbsc.lll.tools.nodes.MethodProxyInsnNode;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
@ -21,28 +21,27 @@ public class LiquidPushPatch implements ICommons {
@Cancelable @Cancelable
public static class PlayerLiquidPushEvent extends Event {} public static class PlayerLiquidPushEvent extends Event {}
@Patch(PlayerEntity.class) public static boolean shouldCancelLiquidCollisions(PlayerEntity player) {
public abstract static class LiquidCollisionsOverride implements Opcodes { if (player.equals(MC.player)) {
@Find(LiquidCollisionsOverride.class) return MinecraftForge.EVENT_BUS.post(new PlayerLiquidPushEvent());
MethodProxy shouldCancelLiquidCollisions;
@Target(of = "shouldCancelLiquidCollisions")
public static boolean shouldCancelLiquidCollisions(PlayerEntity player) {
if (player.equals(MC.player)) {
return MinecraftForge.EVENT_BUS.post(new PlayerLiquidPushEvent());
}
return false;
} }
return false;
}
@Target(of = "injectLiquidCollisionHook") @Patch(value = PlayerEntity.class, reason = "add hook to cancel liquid collisions")
public abstract static class LiquidCollisionsOverride implements Opcodes {
@Find(parent = LiquidPushPatch.class)
abstract MethodProxy shouldCancelLiquidCollisions();
@Target
abstract boolean isPushedByFluid(); abstract boolean isPushedByFluid();
@Injector(reason = "add hook to cancel liquid collisions") @Injector
public void injectLiquidCollisionHook(ClassNode clazz, MethodNode main) { public void inject(ClassNode clazz, MethodNode main) {
LabelNode skip = new LabelNode(); LabelNode skip = new LabelNode();
InsnSequence is = new InsnSequence(); InsnSequence is = new InsnSequence();
is.add(new VarInsnNode(ALOAD, 0)); is.add(new VarInsnNode(ALOAD, 0));
is.add(new MethodProxyInsnNode(INVOKESTATIC, shouldCancelLiquidCollisions)); is.add(new MethodProxyInsnNode(INVOKESTATIC, shouldCancelLiquidCollisions()));
is.add(new JumpInsnNode(IFEQ, skip)); is.add(new JumpInsnNode(IFEQ, skip));
is.add(new InsnNode(ICONST_0)); is.add(new InsnNode(ICONST_0));
is.add(new InsnNode(IRETURN)); is.add(new InsnNode(IRETURN));

View file

@ -4,7 +4,7 @@ import ftbsc.lll.processor.annotations.Find;
import ftbsc.lll.processor.annotations.Injector; import ftbsc.lll.processor.annotations.Injector;
import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.annotations.Patch;
import ftbsc.lll.processor.annotations.Target; import ftbsc.lll.processor.annotations.Target;
import ftbsc.lll.proxies.impl.MethodProxy; import ftbsc.lll.proxies.MethodProxy;
import ftbsc.lll.tools.InsnSequence; import ftbsc.lll.tools.InsnSequence;
import ftbsc.lll.tools.PatternMatcher; import ftbsc.lll.tools.PatternMatcher;
import ftbsc.lll.tools.nodes.MethodProxyInsnNode; import ftbsc.lll.tools.nodes.MethodProxyInsnNode;
@ -21,22 +21,21 @@ public class NoSlowPatch {
@Cancelable @Cancelable
public static class PlayerSlowDownEvent extends Event { } public static class PlayerSlowDownEvent extends Event { }
@Patch(ClientPlayerEntity.class) public static boolean shouldSlowPlayer() {
return MinecraftForge.EVENT_BUS.post(new PlayerSlowDownEvent());
}
@Patch(value = ClientPlayerEntity.class, reason = "add hook to cancel slowing down effect of using items")
public abstract static class SlowDownOverride implements Opcodes { public abstract static class SlowDownOverride implements Opcodes {
@Find(SlowDownOverride.class) @Find(parent = NoSlowPatch.class)
MethodProxy shouldSlowPlayer; abstract MethodProxy shouldSlowPlayer();
@Target(of = "shouldSlowPlayer") @Target
public static boolean shouldSlowPlayer() {
return MinecraftForge.EVENT_BUS.post(new PlayerSlowDownEvent());
}
@Target(of = "injectNoSlowHook")
abstract void aiStep(); abstract void aiStep();
@Injector(reason = "add hook to cancel slowing down effect of using items") @Injector
public void injectNoSlowHook(ClassNode clazz, MethodNode main) { public void inject(ClassNode clazz, MethodNode main) {
AbstractInsnNode found = PatternMatcher.builder() AbstractInsnNode found = PatternMatcher.builder()
.opcodes(ALOAD, INVOKEVIRTUAL, IFEQ, ALOAD, INVOKEVIRTUAL, IFNE) .opcodes(ALOAD, INVOKEVIRTUAL, IFEQ, ALOAD, INVOKEVIRTUAL, IFNE)
.ignoreFrames() .ignoreFrames()
@ -57,7 +56,7 @@ public class NoSlowPatch {
LabelNode skip = new LabelNode(); // TODO can we get the label that the original IF is jumping to without adding one ourselves? LabelNode skip = new LabelNode(); // TODO can we get the label that the original IF is jumping to without adding one ourselves?
InsnSequence is = new InsnSequence(); InsnSequence is = new InsnSequence();
is.add(new MethodProxyInsnNode(INVOKESTATIC, shouldSlowPlayer)); is.add(new MethodProxyInsnNode(INVOKESTATIC, shouldSlowPlayer()));
is.add(new JumpInsnNode(IFNE, skip)); is.add(new JumpInsnNode(IFNE, skip));
main.instructions.insert(found, is); main.instructions.insert(found, is);

View file

@ -4,9 +4,10 @@ import ftbsc.lll.processor.annotations.Find;
import ftbsc.lll.processor.annotations.Injector; import ftbsc.lll.processor.annotations.Injector;
import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.annotations.Patch;
import ftbsc.lll.processor.annotations.Target; import ftbsc.lll.processor.annotations.Target;
import ftbsc.lll.proxies.impl.MethodProxy; import ftbsc.lll.proxies.MethodProxy;
import ftbsc.lll.tools.InsnSequence; import ftbsc.lll.tools.InsnSequence;
import ftbsc.lll.tools.PatternMatcher; import ftbsc.lll.tools.PatternMatcher;
import ftbsc.lll.tools.debug.BytecodePrinter;
import ftbsc.lll.tools.nodes.MethodProxyInsnNode; import ftbsc.lll.tools.nodes.MethodProxyInsnNode;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Future;
@ -42,21 +43,24 @@ public class PacketPatch {
} }
} }
@Patch(NetworkManager.class) public static boolean pktIn(IPacket<?> pkt) {
return MinecraftForge.EVENT_BUS.post(new PacketEvent.Incoming(pkt));
}
public static boolean pktOut(IPacket<?> pkt) {
return MinecraftForge.EVENT_BUS.post(new PacketEvent.Outgoing(pkt));
}
@Patch(value = NetworkManager.class, reason = "add hook to intercept and alter/cancel incoming packets")
public abstract static class IncomingPacketInterceptor implements Opcodes { public abstract static class IncomingPacketInterceptor implements Opcodes {
@Find(IncomingPacketInterceptor.class) @Find(parent = PacketPatch.class)
MethodProxy pktIn; abstract MethodProxy pktIn();
@Target(of = "pktIn") @Target
public static boolean pktIn(IPacket<?> pkt) { public abstract void channelRead0(ChannelHandlerContext ctx, IPacket<?> pak);
return MinecraftForge.EVENT_BUS.post(new PacketEvent.Incoming(pkt));
}
@Target(of = "injectIncomingInterceptor") @Injector
abstract void channelRead0(ChannelHandlerContext ctx, IPacket<?> pak); public void inject(ClassNode clazz, MethodNode main) {
@Injector(reason = "add hook to intercept and alter/cancel incoming packets")
public void injectIncomingInterceptor(ClassNode clazz, MethodNode main) {
AbstractInsnNode found = PatternMatcher.builder() AbstractInsnNode found = PatternMatcher.builder()
.opcodes(ALOAD, GETFIELD, INVOKEINTERFACE, IFEQ) .opcodes(ALOAD, GETFIELD, INVOKEINTERFACE, IFEQ)
.ignoreFrames() .ignoreFrames()
@ -69,7 +73,7 @@ public class PacketPatch {
LabelNode skip = new LabelNode(); LabelNode skip = new LabelNode();
InsnSequence is = new InsnSequence(); InsnSequence is = new InsnSequence();
is.add(new VarInsnNode(ALOAD, 2)); is.add(new VarInsnNode(ALOAD, 2));
is.add(new MethodProxyInsnNode(INVOKESTATIC, pktIn)); is.add(new MethodProxyInsnNode(INVOKESTATIC, pktIn()));
is.add(new JumpInsnNode(IFEQ, skip)); is.add(new JumpInsnNode(IFEQ, skip));
is.add(new InsnNode(RETURN)); is.add(new InsnNode(RETURN));
is.add(skip); is.add(skip);
@ -78,26 +82,21 @@ public class PacketPatch {
} }
} }
@Patch(NetworkManager.class) @Patch(value = NetworkManager.class, reason = "add hook to intercept and alter/cancel outgoing packets")
public abstract static class OutgoingPacketInterceptor implements Opcodes { public abstract static class OutgoingPacketInterceptor implements Opcodes {
@Find(OutgoingPacketInterceptor.class) @Find(parent = PacketPatch.class)
MethodProxy pktOut; abstract MethodProxy pktOut();
@Target(of = "pktOut") @Target
public static boolean pktOut(IPacket<?> pkt) {
return MinecraftForge.EVENT_BUS.post(new PacketEvent.Outgoing(pkt));
}
@Target(of = "injectOutgoingInterceptor")
public abstract void sendPacket(IPacket<?> pak, GenericFutureListener<? extends Future<? super Void>> gfl); public abstract void sendPacket(IPacket<?> pak, GenericFutureListener<? extends Future<? super Void>> gfl);
@Injector(reason = "add hook to intercept and alter/cancel outgoing packets") @Injector
public void injectOutgoingInterceptor(ClassNode clazz, MethodNode main) { public void inject(ClassNode clazz, MethodNode main) {
// hook at the top // hook at the top
LabelNode skip = new LabelNode(); LabelNode skip = new LabelNode();
InsnSequence is = new InsnSequence(); InsnSequence is = new InsnSequence();
is.add(new VarInsnNode(ALOAD, 1)); is.add(new VarInsnNode(ALOAD, 1));
is.add(new MethodProxyInsnNode(INVOKESTATIC, pktOut)); is.add(new MethodProxyInsnNode(INVOKESTATIC, pktOut()));
is.add(new JumpInsnNode(IFEQ, skip)); is.add(new JumpInsnNode(IFEQ, skip));
is.add(new InsnNode(RETURN)); is.add(new InsnNode(RETURN));
is.add(skip); is.add(skip);

View file

@ -13,12 +13,12 @@ import ftbsc.lll.processor.annotations.Target;
import ftbsc.lll.tools.PatternMatcher; import ftbsc.lll.tools.PatternMatcher;
import net.minecraft.client.entity.player.ClientPlayerEntity; import net.minecraft.client.entity.player.ClientPlayerEntity;
@Patch(ClientPlayerEntity.class) @Patch(value = ClientPlayerEntity.class, reason = "prevent minecraft from force closing guis when entering portals")
public abstract class PortalGuiPatch implements Opcodes { public abstract class PortalGuiPatch implements Opcodes {
@Target(of = "inject") @Target
abstract void handleNetherPortalClient(); abstract void handleNetherPortalClient();
@Injector(reason = "prevent minecraft from force closing guis when entering portals") @Injector
public void inject(ClassNode clazz, MethodNode main) { public void inject(ClassNode clazz, MethodNode main) {
LabelNode skip = new LabelNode(); LabelNode skip = new LabelNode();

View file

@ -1,85 +0,0 @@
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,19 +7,13 @@ 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 {
@ -74,44 +68,4 @@ 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

@ -1,13 +0,0 @@
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,28 +1,23 @@
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, I> { public abstract class Setting<T> {
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<I>> callback; protected Optional<Consumer<T>> callback;
Setting() { Setting() {
this.name = Optional.empty(); this.name = Optional.empty();
@ -31,75 +26,68 @@ public abstract class Setting<T, I> {
this.callback = Optional.empty(); this.callback = Optional.empty();
} }
public Setting<T, I> name(String name) { public Setting<T> name(String name) {
this.name = Optional.of(name); this.name = Optional.of(name);
return this; return this;
} }
public Setting<T, I> comment(String comment) { public Setting<T> comment(String comment) {
this.comment = Optional.of(comment); this.comment = Optional.of(comment);
return this; return this;
} }
public Setting<T, I> fallback(T fallback) { public Setting<T> fallback(T fallback) {
this.fallback = Optional.of(fallback); this.fallback = Optional.of(fallback);
return this; return this;
} }
public Setting<T, I> callback(Consumer<I> callback) { public Setting<T> callback(Consumer<T> 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<I> argument(); abstract ArgumentType<T> 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());
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;
private static abstract class ValueSetting<T> extends Setting<T, T> { module.getDispatcher().register(
Commands.literal(module.getName().toLowerCase())
abstract Class<T> clazz(); .then(
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.literal(optName) Commands.argument(optName, arg)
.then( .executes( ctx -> {
Commands.argument(optName, arg) T value = ctx.getArgument(optName, clazz);
.executes( ctx -> { if (cb != null) {
T value = ctx.getArgument(optName, clazz); cb.accept(value);
if (cb != null) { }
cb.accept(value); conf.set(value);
} conf.save();
conf.set(value); log(String.format("> %s -> %s <", String.join(".", conf.getPath()), conf.get().toString()));
conf.save(); return 1;
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()));
.executes(ctx -> { return 1;
log(String.format("> %s: %s <", optName, conf.get().toString())); })
return 1; )
}) );
)
);
return conf; return conf;
}
} }
public static class Bool extends ValueSetting<Boolean> { public static class Bool extends Setting<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; }
@ -113,7 +101,7 @@ public abstract class Setting<T, I> {
} }
public static class Decimal extends ValueSetting<Double> { public static class Decimal extends Setting<Double> {
protected Optional<Double> min; protected Optional<Double> min;
protected Optional<Double> max; protected Optional<Double> max;
@ -145,7 +133,7 @@ public abstract class Setting<T, I> {
} }
public static class Number extends ValueSetting<Integer> { public static class Number extends Setting<Integer> {
protected Optional<Integer> min; protected Optional<Integer> min;
protected Optional<Integer> max; protected Optional<Integer> max;
@ -177,7 +165,7 @@ public abstract class Setting<T, I> {
} }
public static class Str extends ValueSetting<String> { public static class Str extends Setting<String> {
public static Str builder() { return new Str(); } public static Str builder() { return new Str(); }
protected boolean greedy = false; protected boolean greedy = false;
@ -202,7 +190,7 @@ public abstract class Setting<T, I> {
} }
public static class Switch<T extends Enum<T>> extends ValueSetting<T> { public static class Switch<T extends Enum<T>> extends Setting<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); }
@ -226,102 +214,4 @@ public abstract class Setting<T, I> {
} }
} }
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,7 +5,3 @@ 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