diff --git a/src/main/java/dev/dfonline/codeclient/config/Config.java b/src/main/java/dev/dfonline/codeclient/config/Config.java index b0efed2a..89fcfc38 100644 --- a/src/main/java/dev/dfonline/codeclient/config/Config.java +++ b/src/main/java/dev/dfonline/codeclient/config/Config.java @@ -41,6 +41,7 @@ public class Config { public int ChestHighlightColor = 0x51FFFF; public boolean HighlightChestsWithAir = false; public int HighlightChestDuration = 10; + public boolean UseIForLineScope = false; private void save() { try { @@ -68,6 +69,7 @@ private void save() { object.addProperty("HighlightChestsWithAir",HighlightChestsWithAir); object.addProperty("HighlightChestDuration",HighlightChestDuration); object.addProperty("ChestHighlightColor",ChestHighlightColor); + object.addProperty("UseIForLineScope",UseIForLineScope); FileManager.writeConfig(object.toString()); } catch (Exception e) { CodeClient.LOGGER.info("Couldn't save config: " + e); @@ -354,6 +356,16 @@ public YetAnotherConfigLib getLibConfig() { .controller(TickBoxControllerBuilder::create) .available(false) .build()) + .option(Option.createBuilder(Boolean.class) + .name(Text.literal("Show I On Local Scope")) + .description(OptionDescription.of(Text.literal("In variable icons use I for line variables."))) + .binding( + false, + () -> UseIForLineScope, + opt -> UseIForLineScope = opt + ) + .controller(TickBoxControllerBuilder::create) + .build()) .build()) .category(ConfigCategory.createBuilder() .name(Text.literal("AutoJoin")) diff --git a/src/main/java/dev/dfonline/codeclient/dev/InteractionManager.java b/src/main/java/dev/dfonline/codeclient/dev/InteractionManager.java index d2180e39..bf292e8c 100644 --- a/src/main/java/dev/dfonline/codeclient/dev/InteractionManager.java +++ b/src/main/java/dev/dfonline/codeclient/dev/InteractionManager.java @@ -7,6 +7,7 @@ import dev.dfonline.codeclient.Utility; import dev.dfonline.codeclient.config.Config; import dev.dfonline.codeclient.location.Dev; +import dev.dfonline.codeclient.switcher.ScopeSwitcher; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.block.Block; @@ -15,6 +16,7 @@ import net.minecraft.client.sound.PositionedSoundInstance; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.EntityDimensions; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; @@ -189,7 +191,7 @@ public static BlockPos getPlacePos(BlockHitResult hitResult) { public static BlockHitResult onBlockInteract(BlockHitResult hitResult) { if(CodeClient.location instanceof Dev plot) { BlockPos pos = hitResult.getBlockPos(); - if(plot.isInCodeSpace(pos.getX(), plot.getZ()) && pos.getY() % 5 == 4) { // Is a code space level (glass) + if(plot.isInDev(pos) && pos.getY() % 5 == 4) { // Is a code space level (glass) if(hitResult.getSide() == Direction.UP || hitResult.getSide() == Direction.DOWN) { if(CodeClient.MC.world.getBlockState(pos).isAir() && Config.getConfig().PlaceOnAir) return new BlockHitResult(hitResult.getPos(),Direction.UP,hitResult.getBlockPos().add(0,1,0),hitResult.isInsideBlock()); if(Config.getConfig().CustomBlockInteractions) return new BlockHitResult(hitResult.getPos(), Direction.UP, hitResult.getBlockPos(), hitResult.isInsideBlock()); @@ -202,6 +204,27 @@ public static BlockHitResult onBlockInteract(BlockHitResult hitResult) { } return hitResult; } + + public static boolean onItemInteract(PlayerEntity player, Hand hand) { + if(player.isSneaking()) return false; + + ItemStack stack = player.getStackInHand(hand); + + NbtCompound nbt = stack.getNbt(); + if(nbt == null) return false; + NbtCompound pbv = (NbtCompound) nbt.get("PublicBukkitValues"); + if(pbv == null) return false; + NbtString varItem = (NbtString) pbv.get("hypercube:varitem"); + if(varItem == null) return false; + JsonObject var = JsonParser.parseString(varItem.asString()).getAsJsonObject(); + if(!var.get("id").getAsString().equals("var")) return false; + JsonObject data = var.get("data").getAsJsonObject(); + String scopeName = data.get("scope").getAsString(); + + CodeClient.MC.setScreen(new ScopeSwitcher(scopeName)); + return true; + } + // public static boolean onBlockInteract(ClientPlayerEntity player, Hand hand, BlockHitResult hitResult) { // MinecraftClient MC = CodeClient.MC; // if(CodeClient.location instanceof Dev plot && plot.isInCodeSpace(hitResult.getPos().getX(), hitResult.getPos().getZ())) { @@ -265,7 +288,7 @@ public static BlockHitResult onBlockInteract(BlockHitResult hitResult) { public static VoxelShape customVoxelShape(BlockView world, BlockPos pos) { if(CodeClient.MC != null && CodeClient.MC.player != null && CodeClient.location instanceof Dev plot) { Config.LayerInteractionMode mode = Config.getConfig().CodeLayerInteractionMode; - Boolean isInDev = plot.isInDev(pos.toCenterPos()); + Boolean isInDev = plot.isInDev(pos); boolean isLevel = isInDev != null && isInDev && pos.getY() % 5 == 4; boolean noClipAllowsBlock = Config.getConfig().NoClipEnabled || world.getBlockState(pos).isAir(); boolean hideCodeSpace = diff --git a/src/main/java/dev/dfonline/codeclient/hypercube/item/Scope.java b/src/main/java/dev/dfonline/codeclient/hypercube/item/Scope.java index 5e4b8822..7e3cce03 100644 --- a/src/main/java/dev/dfonline/codeclient/hypercube/item/Scope.java +++ b/src/main/java/dev/dfonline/codeclient/hypercube/item/Scope.java @@ -9,7 +9,7 @@ public enum Scope { unsaved(TextColor.fromFormatting(Formatting.GRAY), "GAME", "G"), local(TextColor.fromFormatting(Formatting.GREEN), "LOCAL", "L"), saved(TextColor.fromFormatting(Formatting.YELLOW), "SAVE", "S"), - line(TextColor.fromRgb(5614335), "LINE", "L"); + line(TextColor.fromRgb(0x55aaff), "LINE", "L"); public final TextColor color; public final String longName; diff --git a/src/main/java/dev/dfonline/codeclient/location/Plot.java b/src/main/java/dev/dfonline/codeclient/location/Plot.java index f071d305..089cd0ac 100644 --- a/src/main/java/dev/dfonline/codeclient/location/Plot.java +++ b/src/main/java/dev/dfonline/codeclient/location/Plot.java @@ -68,14 +68,18 @@ public Boolean isInArea(Vec3d pos) { return inX && inZ; } + + public Boolean isInDev(BlockPos pos) { + return isInDev(new Vec3d(pos.getX(), pos.getY(), pos.getZ())); + } public Boolean isInDev(Vec3d pos) { if(originX == null || originZ == null) return null; - double x = pos.getX(); - double z = pos.getZ(); + int x = (int) pos.getX(); + int z = (int) pos.getZ(); - boolean inX = (x < originX) && ((x >= originX - 20) || ((pos.getY() >= 50) && (x >= originX - 21))); - boolean inZ = (z >= originZ) && (z <= originZ + (size != null ? size.size : 300) + 1); + boolean inX = (x < originX) && ((x >= originX - 19) || (pos.getY() >= 50) && (x >= originX - 20)); + boolean inZ = (z >= originZ) && (z <= originZ + (size != null ? size.size : 300)); return inX && inZ; } diff --git a/src/main/java/dev/dfonline/codeclient/mixin/entity/player/MClientPlayerInteractionManager.java b/src/main/java/dev/dfonline/codeclient/mixin/entity/player/MClientPlayerInteractionManager.java index 05bee13f..45dc0428 100644 --- a/src/main/java/dev/dfonline/codeclient/mixin/entity/player/MClientPlayerInteractionManager.java +++ b/src/main/java/dev/dfonline/codeclient/mixin/entity/player/MClientPlayerInteractionManager.java @@ -9,18 +9,24 @@ import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.client.network.SequencedPacketCreator; +import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.NbtElement; import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.SlotActionType; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; @@ -30,6 +36,8 @@ @Mixin(ClientPlayerInteractionManager.class) public abstract class MClientPlayerInteractionManager { + @Shadow protected abstract void sendSequencedPacket(ClientWorld world, SequencedPacketCreator packetCreator); + private static ItemStack item = null; @Inject(method = "breakBlock", at = @At("HEAD"), cancellable = true) @@ -37,25 +45,35 @@ public void onAttackBlock(BlockPos pos, CallbackInfoReturnable cir) { if(InteractionManager.onBreakBlock(pos)) cir.setReturnValue(false); } - @ModifyVariable(method = "interactBlock", at = @At("HEAD"), argsOnly = true) - private BlockHitResult onBlockInteract(BlockHitResult hitResult) { - if(CodeClient.location instanceof Dev plot && plot.isInCodeSpace(hitResult.getBlockPos().getX(), hitResult.getPos().getZ())) { - return InteractionManager.onBlockInteract(hitResult); - } - return hitResult; - } - @Inject(method = "interactBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;sendSequencedPacket(Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/client/network/SequencedPacketCreator;)V")) public void beforeSendPlace(ClientPlayerEntity player, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable cir) { ItemStack handItem = player.getStackInHand(hand); boolean isTemplate = handItem.hasNbt() && handItem.getNbt() != null && handItem.getNbt().contains("PublicBukkitValues", NbtElement.COMPOUND_TYPE) && handItem.getNbt().getCompound("PublicBukkitValues").contains("hypercube:codetemplatedata", NbtElement.STRING_TYPE); if(!isTemplate) return; + BlockPos place = InteractionManager.getPlacePos(hitResult); + if(place != null && CodeClient.MC.world.getBlockState(place).isSolidBlock(CodeClient.MC.world, place)) { + ClientPlayNetworkHandler net = CodeClient.MC.getNetworkHandler(); + if(!player.isSneaking()) net.sendPacket(new ClientCommandC2SPacket(player, ClientCommandC2SPacket.Mode.PRESS_SHIFT_KEY)); + this.sendSequencedPacket(CodeClient.MC.world, sequence -> new PlayerInteractBlockC2SPacket(Hand.MAIN_HAND, hitResult, sequence)); + if(!player.isSneaking()) net.sendPacket(new ClientCommandC2SPacket(player, ClientCommandC2SPacket.Mode.RELEASE_SHIFT_KEY)); + if(!player.isSneaking()) { + this.sendSequencedPacket(CodeClient.MC.world, sequence -> new PlayerInteractBlockC2SPacket(Hand.MAIN_HAND, new BlockHitResult(place.toCenterPos(), Direction.UP, place, hitResult.isInsideBlock()), sequence)); + } + } ItemStack template = Items.ENDER_CHEST.getDefaultStack(); template.setNbt(handItem.getNbt()); Utility.sendHandItem(template); item = handItem; } + @ModifyVariable(method = "interactBlock", at = @At("HEAD"), argsOnly = true) + private BlockHitResult onBlockInteract(BlockHitResult hitResult) { + if(CodeClient.location instanceof Dev plot && plot.isInCodeSpace(hitResult.getBlockPos().getX(), hitResult.getPos().getZ())) { + return InteractionManager.onBlockInteract(hitResult); + } + return hitResult; + } + @Inject(method = "interactBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;sendSequencedPacket(Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/client/network/SequencedPacketCreator;)V", shift = At.Shift.AFTER)) public void afterSendPlace(ClientPlayerEntity player, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable cir) { if(item != null) { @@ -71,6 +89,13 @@ public void interactItemMovement(ClientPlayNetworkHandler instance, Packet pa } } + @Inject(method = "interactItem", at = @At("HEAD"), cancellable = true) + public void interactItem(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { + if(InteractionManager.onItemInteract(player, hand)) { + cir.setReturnValue(ActionResult.PASS); + } + } + @Inject(method = "clickSlot", at = @At("HEAD"), cancellable = true) private void clickSlot(int syncId, int slotId, int button, SlotActionType actionType, PlayerEntity player, CallbackInfo ci) { if(slotId < 0) return; diff --git a/src/main/java/dev/dfonline/codeclient/mixin/render/hud/MDrawContext.java b/src/main/java/dev/dfonline/codeclient/mixin/render/hud/MDrawContext.java index 26543ee7..d822bb95 100644 --- a/src/main/java/dev/dfonline/codeclient/mixin/render/hud/MDrawContext.java +++ b/src/main/java/dev/dfonline/codeclient/mixin/render/hud/MDrawContext.java @@ -2,6 +2,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import dev.dfonline.codeclient.config.Config; import dev.dfonline.codeclient.hypercube.item.Scope; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; @@ -41,7 +42,7 @@ private void additionalItemRendering(TextRenderer textRenderer, ItemStack stack, this.matrices.translate(0.0F, 0.0F, 200.0F); try { Scope scope = Scope.valueOf(scopeName); - this.drawText(textRenderer,Text.literal(scope.shortName).setStyle(Style.EMPTY.withColor(scope.color)),x,y,0xFFFFFF,true); + this.drawText(textRenderer,Text.literal((Config.getConfig().UseIForLineScope && scope == Scope.line) ? "I" : scope.shortName).setStyle(Style.EMPTY.withColor(scope.color)),x,y,0xFFFFFF,true); } catch (Exception ignored) { this.drawText(textRenderer,Text.literal("?").formatted(Formatting.RED),x,y,0xFFFFFF,true); diff --git a/src/main/java/dev/dfonline/codeclient/switcher/GenericSwitcher.java b/src/main/java/dev/dfonline/codeclient/switcher/GenericSwitcher.java index 9671458d..ff054939 100644 --- a/src/main/java/dev/dfonline/codeclient/switcher/GenericSwitcher.java +++ b/src/main/java/dev/dfonline/codeclient/switcher/GenericSwitcher.java @@ -24,6 +24,7 @@ public abstract class GenericSwitcher extends Screen { private static final Identifier TEXTURE = new Identifier("textures/gui/container/gamemode_switcher.png"); private final List buttons = new ArrayList<>(); private boolean usingMouseToSelect = false; + protected boolean hasClicked = false; private Integer lastMouseX; private Integer lastMouseY; protected Integer selected; @@ -113,9 +114,26 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { return super.keyPressed(keyCode, scanCode, modifiers); } - private boolean checkFinished() { + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + int i = 0; + + for (SelectableButtonWidget widget : buttons) { + if(widget.getX() < mouseX && widget.getX() + 31 > mouseX + && widget.getY() < mouseY && widget.getY() + 31 > mouseY) this.selected = i; + widget.selected = this.selected == i; + if(widget.selected) { + hasClicked = true; + return true; + } + ++i; + } + return super.mouseClicked(mouseX, mouseY, button); + } + + protected boolean checkFinished() { if(this.client == null) return false; - if(!InputUtil.isKeyPressed(this.client.getWindow().getHandle(), HOLD_KEY)) { + if(hasClicked || !InputUtil.isKeyPressed(this.client.getWindow().getHandle(), HOLD_KEY)) { Option selected = getSelected(); if(selected != null) selected.run(); this.client.setScreen(null); @@ -124,7 +142,7 @@ private boolean checkFinished() { return false; } - private Option getSelected() { + protected Option getSelected() { List