diff --git a/src/main/java/turniplabs/halplibe/HalpLibe.java b/src/main/java/turniplabs/halplibe/HalpLibe.java index fd6425b..579676e 100644 --- a/src/main/java/turniplabs/halplibe/HalpLibe.java +++ b/src/main/java/turniplabs/halplibe/HalpLibe.java @@ -9,7 +9,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import turniplabs.halplibe.helper.*; -import turniplabs.halplibe.helper.gui.Guis; +import turniplabs.halplibe.helper.gui.packet.PacketGuiButtonClick; import turniplabs.halplibe.helper.gui.packet.PacketOpenBlockGui; import turniplabs.halplibe.helper.gui.packet.PacketOpenGui; import turniplabs.halplibe.helper.gui.packet.PacketOpenItemGui; @@ -88,11 +88,7 @@ public void onInitialize() { NetworkHelper.register(PacketOpenGui.class, false, true); NetworkHelper.register(PacketOpenItemGui.class, false, true); NetworkHelper.register(PacketOpenBlockGui.class, false, true); - try { - Class.forName(Guis.class.getName()); // init vanilla guis - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } + NetworkHelper.register(PacketGuiButtonClick.class, true, true); LOGGER.info("HalpLibe initialized."); } diff --git a/src/main/java/turniplabs/halplibe/helper/gui/GuiHelper.java b/src/main/java/turniplabs/halplibe/helper/gui/GuiHelper.java index 4132b1c..0bc79a5 100644 --- a/src/main/java/turniplabs/halplibe/helper/gui/GuiHelper.java +++ b/src/main/java/turniplabs/halplibe/helper/gui/GuiHelper.java @@ -3,6 +3,7 @@ import net.minecraft.core.data.registry.Registry; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import turniplabs.halplibe.HalpLibe; import turniplabs.halplibe.helper.gui.factory.IGuiFactory; import turniplabs.halplibe.helper.gui.registered.RegisteredGui; @@ -29,7 +30,8 @@ public static RegisteredGui getGui(@NotNull String modId, @NotNull String guiId) return REGISTRY.getItem(modId + ":" + guiId); } - public static RegisteredGui getGui(@NotNull String namespace) { + public static RegisteredGui getGui(@Nullable String namespace) { + if(namespace == null) return null; return REGISTRY.getItem(namespace); } diff --git a/src/main/java/turniplabs/halplibe/helper/gui/GuiScreenAccessor.java b/src/main/java/turniplabs/halplibe/helper/gui/GuiScreenAccessor.java new file mode 100644 index 0000000..4a2314c --- /dev/null +++ b/src/main/java/turniplabs/halplibe/helper/gui/GuiScreenAccessor.java @@ -0,0 +1,19 @@ +package turniplabs.halplibe.helper.gui; + +import turniplabs.halplibe.helper.gui.registered.RegisteredGui; + +public interface GuiScreenAccessor { + + void setGuiNamespace(String namespace); + + String getGuiNamespace(); + + default void setRegisteredGui(RegisteredGui gui) { + setGuiNamespace(gui.getNamespace()); + } + + default RegisteredGui getRegisteredGui() { + return GuiHelper.getGui(getGuiNamespace()); + } + +} diff --git a/src/main/java/turniplabs/halplibe/helper/gui/Guis.java b/src/main/java/turniplabs/halplibe/helper/gui/Guis.java deleted file mode 100644 index 93d22c3..0000000 --- a/src/main/java/turniplabs/halplibe/helper/gui/Guis.java +++ /dev/null @@ -1,182 +0,0 @@ -package turniplabs.halplibe.helper.gui; - -import net.minecraft.client.entity.player.EntityPlayerSP; -import net.minecraft.client.gui.*; -import net.minecraft.core.block.BlockChest; -import net.minecraft.core.block.entity.*; -import net.minecraft.core.entity.player.EntityPlayer; -import net.minecraft.core.item.ItemStack; -import net.minecraft.core.player.inventory.*; -import net.minecraft.server.entity.player.EntityPlayerMP; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import turniplabs.halplibe.helper.gui.factory.base.GuiFactory; -import turniplabs.halplibe.helper.gui.factory.block.BlockGuiFactory; -import turniplabs.halplibe.helper.gui.factory.block.TileGuiFactory; -import turniplabs.halplibe.helper.gui.factory.item.ItemGuiFactory; -import turniplabs.halplibe.helper.gui.registered.RegisteredGui; - -public final class Guis { - - /* ============== - Client Guis - ============== */ - - public static final RegisteredGui EDIT_SIGN = GuiHelper.registerClientGui("minecraft", "edit_sign", new TileGuiFactory() { - @Override - public @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @NotNull TileEntitySign tile) { - return new GuiEditSign(tile); - } - - @Override - public @Nullable Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, @NotNull TileEntitySign tile) { - return null; - } - }); - - public static final RegisteredGui EDIT_LABEL = GuiHelper.registerClientGui("minecraft", "edit_label", new ItemGuiFactory() { - @Override - public @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @NotNull ItemStack itemStack) { - return new GuiEditLabel(itemStack, getSlot(player, itemStack)); - } - - @Override - public @Nullable Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, @NotNull ItemStack itemStack) { - return null; - } - - private int getSlot(EntityPlayer player, ItemStack itemStack) { - for (int i = 0; i < player.inventory.mainInventory.length; ++i) { - if (player.inventory.mainInventory[i] == itemStack) return i; - } - - throw new AssertionError(); - } - }); - - public static final RegisteredGui MOB_SPAWNER_PICKER = GuiHelper.registerClientGui("minecraft", "mob_spawner_picker", new TileGuiFactory() { - @Override - public @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @NotNull TileEntityMobSpawner tile) { - return new GuiPickMonster(tile.getMobId(), tile.x, tile.y, tile.z); - } - - @Override - public @Nullable Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, @NotNull TileEntityMobSpawner tile) { - return null; - } - }); - - public static final RegisteredGui WAND_MONSTER_PICKER = GuiHelper.registerClientGui("minecraft", "wand_monster_picker", new ItemGuiFactory() { - @Override - public @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @NotNull ItemStack itemStack) { - String mobId = itemStack.getData().getStringOrDefault("monster", "Pig"); - return new GuiWandPickerMonster(mobId, itemStack); - } - - @Override - public @Nullable Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, @NotNull ItemStack itemStack) { - return null; - } - }); - - - /* ============== - Server Guis - ============== */ - - public static final RegisteredGui CHEST = GuiHelper.registerServerGui("minecraft", "chest", new BlockGuiFactory() { - @Override - public @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, int x, int y, int z) { - return new GuiChest(player.inventory, BlockChest.getInventory(player.world, x, y, z)); - } - - @Override - public @NotNull Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, int x, int y, int z) { - return new ContainerChest(player.inventory, BlockChest.getInventory(player.world, x, y, z)); - } - }); - - public static final RegisteredGui WORKBENCH = GuiHelper.registerServerGui("minecraft", "workbench", new BlockGuiFactory() { - @Override - public @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, int x, int y, int z) { - return new GuiCrafting(player.inventory, player.world, x, y, z); - } - - @Override - public @NotNull Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, int x, int y, int z) { - return new ContainerWorkbench(player.inventory, player.world, x, y, z); - } - }); - - public static final RegisteredGui FURNACE = GuiHelper.registerServerGui("minecraft", "furnace", new TileGuiFactory() { - @Override - public @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @NotNull TileEntityFurnace tile) { - return new GuiFurnace(player.inventory, tile); - } - - @Override - public @NotNull Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, @NotNull TileEntityFurnace tile) { - return new ContainerFurnace(player.inventory, tile); - } - }); - - public static final RegisteredGui DISPENSER = GuiHelper.registerServerGui("minecraft", "dispenser", new TileGuiFactory() { - @Override - public @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @NotNull TileEntityDispenser tile) { - return new GuiDispenser(player.inventory, tile); - } - - @Override - public @NotNull Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, @NotNull TileEntityDispenser tile) { - return new ContainerDispenser(player.inventory, tile); - } - }); - - public static final RegisteredGui BLAST_FURNACE = GuiHelper.registerServerGui("minecraft", "blast_furnace", new TileGuiFactory() { - @Override - public @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @NotNull TileEntityFurnace tile) { - return new GuiFurnace(player.inventory, tile); - } - - @Override - public @NotNull Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, @NotNull TileEntityFurnace tile) { - return new ContainerFurnace(player.inventory, tile); - } - }); - - public static final RegisteredGui TROMMEL = GuiHelper.registerServerGui("minecraft", "trommel", new TileGuiFactory() { - @Override - public @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @NotNull TileEntityTrommel tile) { - return new GuiTrommel(player.inventory, tile); - } - - @Override - public @NotNull Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, @NotNull TileEntityTrommel tile) { - return new ContainerTrommel(player.inventory, tile); - } - }); - - public static final RegisteredGui PAINTING_PICKER = GuiHelper.registerServerGui("minecraft", "painting_picker", new GuiFactory() { - @Override - public @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player) { - return new GuiPaintingPicker(player); - } - - @Override - public @Nullable Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player) { - return null; - } - }); - - public static final RegisteredGui EDIT_FLAG = GuiHelper.registerServerGui("minecraft", "edit_flag", new TileGuiFactory() { - @Override - public @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @NotNull TileEntityFlag tile) { - return new GuiEditFlag(player, tile); - } - - @Override - public @NotNull Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, @NotNull TileEntityFlag tile) { - return new ContainerFlag(player.inventory, tile); - } - }); -} diff --git a/src/main/java/turniplabs/halplibe/helper/gui/factory/IGuiFactory.java b/src/main/java/turniplabs/halplibe/helper/gui/factory/IGuiFactory.java index 289955d..97e95e0 100644 --- a/src/main/java/turniplabs/halplibe/helper/gui/factory/IGuiFactory.java +++ b/src/main/java/turniplabs/halplibe/helper/gui/factory/IGuiFactory.java @@ -2,9 +2,11 @@ import net.minecraft.client.entity.player.EntityPlayerSP; import net.minecraft.client.gui.GuiScreen; +import net.minecraft.core.entity.player.EntityPlayer; import net.minecraft.core.item.ItemStack; import net.minecraft.core.player.inventory.Container; import net.minecraft.server.entity.player.EntityPlayerMP; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import turniplabs.halplibe.helper.gui.packet.PacketOpenBlockGui; @@ -14,10 +16,52 @@ public interface IGuiFactory { + /** + * Called to create a gui screen on a client. + * + * @param gui the registered gui that needs to create a gui + * @param player the player that will see the gui + * @param itemStack an item, in case the gui is an item gui + * @param x x coordinate, in case the gui is a block gui + * @param y y coordinate, in case the gui is a block gui + * @param z z coordinate, in case the gui is a block gui + * @return a new gui + */ + @ApiStatus.Internal @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @Nullable ItemStack itemStack, int x, int y, int z); + /** + * Called to create a gui container on a server. + * + * @param gui the registered gui that needs to create a container + * @param player the player that will open the container + * @param itemStack an item, in case the gui is an item gui + * @param x x coordinate, in case the gui is a block gui + * @param y y coordinate, in case the gui is a block gui + * @param z z coordinate, in case the gui is a block gui + * @return a new container + */ + @ApiStatus.Internal @Nullable Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, @Nullable ItemStack itemStack, int x, int y, int z); + /** + * Called when a gui interaction happens.

+ * The player and clicker parameter are not the same when a client acknowledges + * that another player has pressed a button.

+ * As an example, if player1 clicked a button on a server, + * this method will be called on player2's client + * with player2 as the player argument and player1 as the clicker argument + * + * @param gui the registered gui that was clicked + * @param player the player that acknowledges that a player has pressed a button + * @param clicker the player that clicked the button + * @param buttonId the id of the button + */ + default void onButtonClick(@NotNull RegisteredGui gui, @NotNull EntityPlayer player, @NotNull EntityPlayer clicker, int buttonId) { + + } + + @ApiStatus.Internal default @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @NotNull PacketOpenGui packet) { if(!gui.isServerSide()) throw new IllegalStateException("Gui is client side!"); @@ -33,6 +77,7 @@ public interface IGuiFactory { return createGui(gui, player, null, 0, -100, 0); } + @ApiStatus.Internal default @NotNull PacketOpenGui createGuiPacket(@NotNull RegisteredGui gui, int windowId, @NotNull EntityPlayerMP player, @Nullable ItemStack itemStack, int x, int y, int z) { if(!gui.isServerSide()) throw new IllegalStateException("Gui is client side!"); @@ -47,6 +92,7 @@ public interface IGuiFactory { return new PacketOpenGui(gui, windowId); } + @ApiStatus.Internal default void throwInvalidException(String message) { throw new IllegalArgumentException(String.format("Invalid arguments for gui factory '%s': %s", getClass(), message)); } diff --git a/src/main/java/turniplabs/halplibe/helper/gui/factory/block/BlockGuiFactory.java b/src/main/java/turniplabs/halplibe/helper/gui/factory/block/BlockGuiFactory.java index 5765832..84160a5 100644 --- a/src/main/java/turniplabs/halplibe/helper/gui/factory/block/BlockGuiFactory.java +++ b/src/main/java/turniplabs/halplibe/helper/gui/factory/block/BlockGuiFactory.java @@ -25,6 +25,7 @@ default GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP @Override default @Nullable Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, @Nullable ItemStack itemStack, int x, int y, int z) { + if(y < 0) throwInvalidException("y value of block coordinates must be set to a positive value. This either means a wrong value has been used as an argument or that the wrong gui method has been called."); return createContainer(gui, player, x, y, z); } } diff --git a/src/main/java/turniplabs/halplibe/helper/gui/packet/PacketGuiButtonClick.java b/src/main/java/turniplabs/halplibe/helper/gui/packet/PacketGuiButtonClick.java new file mode 100644 index 0000000..f5e6703 --- /dev/null +++ b/src/main/java/turniplabs/halplibe/helper/gui/packet/PacketGuiButtonClick.java @@ -0,0 +1,92 @@ +package turniplabs.halplibe.helper.gui.packet; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.EntityPlayerSP; +import net.minecraft.client.world.WorldClient; +import net.minecraft.core.entity.Entity; +import net.minecraft.core.entity.player.EntityPlayer; +import net.minecraft.core.net.handler.NetHandler; +import net.minecraft.core.net.packet.Packet; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.entity.player.EntityPlayerMP; +import turniplabs.halplibe.HalpLibe; +import turniplabs.halplibe.helper.gui.GuiHelper; +import turniplabs.halplibe.helper.gui.registered.RegisteredGui; +import turniplabs.halplibe.util.PlayerUtils; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class PacketGuiButtonClick extends Packet { + + public String guiNamespace; + public int buttonId; + public int clickerId; + + public PacketGuiButtonClick(String guiNamespace, int buttonId, int clickerId) { + this.guiNamespace = guiNamespace; + this.buttonId = buttonId; + this.clickerId = clickerId; + } + + public PacketGuiButtonClick(String guiNamespace, int buttonId) { + this(guiNamespace, buttonId, -1); + } + + public PacketGuiButtonClick() { + } + + + @Override + public void readPacketData(DataInputStream input) throws IOException { + this.guiNamespace = input.readUTF(); + this.buttonId = input.readInt(); + this.clickerId = input.readInt(); + } + + @Override + public void writePacketData(DataOutputStream output) throws IOException { + if(guiNamespace == null) throw new IOException("GUI Namespace can't be null!"); + output.writeUTF(guiNamespace); + output.writeInt(buttonId); + output.writeInt(clickerId); + } + + @Override + public void processPacket(NetHandler netHandler) { + RegisteredGui gui = GuiHelper.getGui(guiNamespace); + if(gui == null) { + HalpLibe.LOGGER.warn("Invalid gui id in packet: " + guiNamespace); + return; + } + + EntityPlayer player = PlayerUtils.getPlayer(netHandler); + EntityPlayer clicker = null; + if(player.craftingInventory == null) return; + + if(player instanceof EntityPlayerMP) { + Packet packet = new PacketGuiButtonClick(guiNamespace, buttonId, player.id); + clicker = player; + + for (EntityPlayerMP other : MinecraftServer.getInstance().playerList.playerEntities) { + if(other == player) continue; + if(other.craftingInventory == null || other.craftingInventory.windowId != player.craftingInventory.windowId) continue; + other.playerNetServerHandler.sendPacket(packet); + } + } + + if(player instanceof EntityPlayerSP) { + WorldClient world = (WorldClient) Minecraft.getMinecraft(this).theWorld; + Entity entity = world.getEntityFromId(clickerId); + if(entity instanceof EntityPlayer) clicker = (EntityPlayer) entity; + } + + if(clicker != null) gui.getFactory().onButtonClick(gui, player, clicker, buttonId); + } + + @Override + public int getPacketSize() { + return guiNamespace.length() + 4 * 2; + } +} diff --git a/src/main/java/turniplabs/halplibe/helper/gui/packet/PacketOpenGui.java b/src/main/java/turniplabs/halplibe/helper/gui/packet/PacketOpenGui.java index f41ea65..56bd75f 100644 --- a/src/main/java/turniplabs/halplibe/helper/gui/packet/PacketOpenGui.java +++ b/src/main/java/turniplabs/halplibe/helper/gui/packet/PacketOpenGui.java @@ -3,6 +3,7 @@ import net.minecraft.core.net.handler.NetHandler; import net.minecraft.core.net.packet.Packet; import org.jetbrains.annotations.NotNull; +import turniplabs.halplibe.HalpLibe; import turniplabs.halplibe.helper.gui.GuiHelper; import turniplabs.halplibe.helper.gui.registered.RegisteredGui; @@ -12,11 +13,11 @@ public class PacketOpenGui extends Packet { - public String namespace; + public String guiNamespace; public int windowId; public PacketOpenGui(@NotNull RegisteredGui gui, int windowId) { - this.namespace = gui.getNamespace(); + this.guiNamespace = gui.getNamespace(); this.windowId = windowId; } @@ -26,24 +27,30 @@ public PacketOpenGui() { @Override public void readPacketData(DataInputStream input) throws IOException { - this.namespace = input.readUTF(); + this.guiNamespace = input.readUTF(); this.windowId = input.readByte(); } @Override public void writePacketData(DataOutputStream output) throws IOException { - if(namespace == null) throw new IOException("Namespace can't be null!"); - output.writeUTF(namespace); + if(guiNamespace == null) throw new IOException("GUI Namespace can't be null!"); + output.writeUTF(guiNamespace); output.writeByte(windowId); } @Override public void processPacket(NetHandler netHandler) { - GuiHelper.getGui(namespace).openPacket(this); + RegisteredGui gui = GuiHelper.getGui(guiNamespace); + if(gui == null) { + HalpLibe.LOGGER.warn("Invalid gui id in packet: " + guiNamespace); + return; + } + + gui.handleOpenPacket(this); } @Override public int getPacketSize() { - return namespace.length() + 1; + return guiNamespace.length() + 1; } } diff --git a/src/main/java/turniplabs/halplibe/helper/gui/registered/RegisteredGui.java b/src/main/java/turniplabs/halplibe/helper/gui/registered/RegisteredGui.java index fadafe7..c7e3081 100644 --- a/src/main/java/turniplabs/halplibe/helper/gui/registered/RegisteredGui.java +++ b/src/main/java/turniplabs/halplibe/helper/gui/registered/RegisteredGui.java @@ -2,10 +2,13 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.entity.player.EntityPlayerSP; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.core.block.entity.TileEntity; import net.minecraft.core.entity.player.EntityPlayer; import net.minecraft.core.item.ItemStack; import net.minecraft.core.player.inventory.Container; import net.minecraft.server.entity.player.EntityPlayerMP; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import turniplabs.halplibe.HalpLibe; @@ -13,8 +16,10 @@ import turniplabs.halplibe.helper.gui.factory.IGuiFactory; import turniplabs.halplibe.helper.gui.factory.base.GuiFactory; import turniplabs.halplibe.helper.gui.factory.block.BlockGuiFactory; +import turniplabs.halplibe.helper.gui.factory.block.TileGuiFactory; import turniplabs.halplibe.helper.gui.factory.item.ItemGuiFactory; import turniplabs.halplibe.helper.gui.packet.PacketOpenGui; +import turniplabs.halplibe.helper.gui.GuiScreenAccessor; import java.util.Random; import java.util.regex.Pattern; @@ -36,43 +41,51 @@ public RegisteredGui(@NotNull String modId, @NotNull String id, @NotNull IGuiFac this.serverSide = serverSide; if (!ID_PATTERN.matcher(modId + id).matches()) - throw new IllegalArgumentException(String.format("Invalid namespace:%s. Must match the following regex '[a-zA-Z0-9_-]+'.", getNamespace())); + throw new IllegalArgumentException(String.format("Invalid namespace: %s. Must match the following regex '[a-zA-Z0-9_-]+'.", getNamespace())); - if(GuiHelper.REGISTRY.getItem(getNamespace()) != null) + if (GuiHelper.REGISTRY.getItem(getNamespace()) != null) throw new IllegalArgumentException(String.format("Duplicate namespace: %s.", getNamespace())); } public void open(@NotNull EntityPlayer player) { - if(!(factory instanceof GuiFactory)) + if (!(factory instanceof GuiFactory)) throw new IllegalStateException("Gui is not an item gui!"); open(player, null, 0, -100, 0); } public void open(@NotNull EntityPlayer player, @NotNull ItemStack itemStack) { - if(!(factory instanceof ItemGuiFactory)) + if (!(factory instanceof ItemGuiFactory)) throw new IllegalStateException("Gui is not an item gui!"); open(player, itemStack, 0, -100, 0); } public void open(@NotNull EntityPlayer player, int x, int y, int z) { - if(!(factory instanceof BlockGuiFactory)) + if (!(factory instanceof BlockGuiFactory)) throw new IllegalStateException("Gui is not a block gui!"); open(player, null, x, y, z); } + public void open(@NotNull EntityPlayer player, TileEntity tile) { + if (!(factory instanceof TileGuiFactory)) + throw new IllegalStateException("Gui is not a tile gui!"); + + open(player, null, tile.x, tile.y, tile.z); + } + protected void open(@NotNull EntityPlayer player, @Nullable ItemStack itemStack, int x, int y, int z) { if (player.world.isClientSide && serverSide) return; if (player instanceof EntityPlayerSP) { - Minecraft.getMinecraft(Minecraft.class).displayGuiScreen(factory.createGui(this, (EntityPlayerSP) player, itemStack, x, y, z)); + EntityPlayerSP playerSP = (EntityPlayerSP) player; + setupAndOpenGui(factory.createGui(this, playerSP, itemStack, x, y, z)); return; } if (player instanceof EntityPlayerMP) { - if(!serverSide) return; + if (!serverSide) return; EntityPlayerMP playerMP = (EntityPlayerMP) player; int windowId = RANDOM.nextInt(100); @@ -91,13 +104,22 @@ protected void open(@NotNull EntityPlayer player, @Nullable ItemStack itemStack, HalpLibe.LOGGER.warn("Tried to open a gui for invalid EntityPlayer: " + player); } - public void openPacket(@NotNull PacketOpenGui packet) { + @ApiStatus.Internal + public void handleOpenPacket(@NotNull PacketOpenGui packet) { Minecraft mc = Minecraft.getMinecraft(RegisteredGui.class); EntityPlayerSP player = mc.thePlayer; - mc.displayGuiScreen(factory.createGui(this, player, packet)); + setupAndOpenGui(factory.createGui(this, player, packet)); player.craftingInventory.windowId = packet.windowId; } + private void setupAndOpenGui(GuiScreen gui) { + ((GuiScreenAccessor) gui).setRegisteredGui(this); + Minecraft mc = Minecraft.getMinecraft(RegisteredGui.class); + mc.displayGuiScreen(gui); + } + + + public String getModId() { return modId; diff --git a/src/main/java/turniplabs/halplibe/mixin/mixins/NetClientHandlerMixin.java b/src/main/java/turniplabs/halplibe/mixin/mixins/NetClientHandlerMixin.java index be655eb..70a5a6c 100644 --- a/src/main/java/turniplabs/halplibe/mixin/mixins/NetClientHandlerMixin.java +++ b/src/main/java/turniplabs/halplibe/mixin/mixins/NetClientHandlerMixin.java @@ -1,38 +1,21 @@ package turniplabs.halplibe.mixin.mixins; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.Minecraft; import net.minecraft.client.net.handler.NetClientHandler; import net.minecraft.core.net.handler.NetHandler; -import net.minecraft.core.net.packet.Packet100OpenWindow; import net.minecraft.core.net.packet.Packet1Login; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -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.callback.CallbackInfo; -import turniplabs.halplibe.helper.gui.GuiHelper; import turniplabs.halplibe.util.RecipeEntrypoint; @Mixin(value = NetClientHandler.class,remap = false) public abstract class NetClientHandlerMixin extends NetHandler { - @Shadow @Final private Minecraft mc; - @Inject(method = "handleLogin", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/crafting/legacy/CraftingManager;reset()V", shift = At.Shift.BEFORE)) public void handleLogin(Packet1Login packet1login, CallbackInfo ci) { FabricLoader.getInstance().getEntrypoints("recipesReady", RecipeEntrypoint.class).forEach(RecipeEntrypoint::initNamespaces); } - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void handleOpenWindow(Packet100OpenWindow packet) { - GuiHelper.reportVanillaGuiCall("Received BTA open window packet"); - } - } diff --git a/src/main/java/turniplabs/halplibe/mixin/mixins/TileEntityMixin.java b/src/main/java/turniplabs/halplibe/mixin/mixins/TileEntityMixin.java deleted file mode 100644 index 609eab6..0000000 --- a/src/main/java/turniplabs/halplibe/mixin/mixins/TileEntityMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package turniplabs.halplibe.mixin.mixins; - -import net.minecraft.core.block.entity.TileEntity; -import net.minecraft.core.net.packet.Packet; -import net.minecraft.core.net.packet.Packet140TileEntityData; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin( - value = TileEntity.class, - remap = false -) -public abstract class TileEntityMixin { - - @Inject( - method = "getDescriptionPacket", - at = @At(value = "HEAD"), - cancellable = true - ) - public void injectGetDescriptionPacket(CallbackInfoReturnable cir) { - cir.setReturnValue(new Packet140TileEntityData((TileEntity) ((Object)this))); - } -} diff --git a/src/main/java/turniplabs/halplibe/mixin/mixins/gui/BlockChestMixin.java b/src/main/java/turniplabs/halplibe/mixin/mixins/gui/BlockChestMixin.java deleted file mode 100644 index bbcd8a7..0000000 --- a/src/main/java/turniplabs/halplibe/mixin/mixins/gui/BlockChestMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -package turniplabs.halplibe.mixin.mixins.gui; - -import net.minecraft.core.block.BlockChest; -import net.minecraft.core.block.BlockTileEntity; -import net.minecraft.core.block.material.Material; -import net.minecraft.core.entity.player.EntityPlayer; -import net.minecraft.core.world.World; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import turniplabs.halplibe.helper.gui.Guis; - -@Mixin( - value = BlockChest.class, - remap = false -) -public abstract class BlockChestMixin extends BlockTileEntity { - - @Shadow public abstract void checkIfOtherHalfExists(World world, int x, int y, int z); - - public BlockChestMixin(String key, int id, Material material) { - super(key, id, material); - } - - @Override - public boolean blockActivated(World world, int x, int y, int z, EntityPlayer player) { - if(!world.isClientSide) checkIfOtherHalfExists(world, x, y, z); - Guis.CHEST.open(player, x, y, z); - return true; - } -} diff --git a/src/main/java/turniplabs/halplibe/mixin/mixins/gui/EntityPlayerMPMixin.java b/src/main/java/turniplabs/halplibe/mixin/mixins/gui/EntityPlayerMPMixin.java deleted file mode 100644 index acebe26..0000000 --- a/src/main/java/turniplabs/halplibe/mixin/mixins/gui/EntityPlayerMPMixin.java +++ /dev/null @@ -1,102 +0,0 @@ -package turniplabs.halplibe.mixin.mixins.gui; - -import net.minecraft.core.block.entity.*; -import net.minecraft.core.net.packet.Packet; -import net.minecraft.core.player.inventory.IInventory; -import net.minecraft.server.entity.player.EntityPlayerMP; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -import turniplabs.halplibe.helper.gui.GuiHelper; -import turniplabs.halplibe.helper.gui.Guis; - -@Mixin( - value = EntityPlayerMP.class, - remap = false -) -public abstract class EntityPlayerMPMixin { - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIEditFlag(TileEntityFlag tile) { - Guis.EDIT_FLAG.open(getPlayer(), tile.x, tile.y, tile.z); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIChest(IInventory iinventory) { - GuiHelper.reportVanillaGuiCall("BTA display gui method called"); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIWorkbench(int x, int y, int z) { - Guis.WORKBENCH.open(getPlayer(), x, y, z); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIPaintingPicker() { - Guis.PAINTING_PICKER.open(getPlayer()); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIFurnace(TileEntityFurnace tile) { - Guis.FURNACE.open(getPlayer(), tile.x, tile.y, tile.z); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUITrommel(TileEntityTrommel tile) { - Guis.TROMMEL.open(getPlayer(), tile.x, tile.y, tile.z); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIDispenser(TileEntityDispenser tile) { - Guis.DISPENSER.open(getPlayer(), tile.x, tile.y, tile.z); - } - - - @Redirect( - method = "getTileEntityInfo", - at = @At(value = "INVOKE", target = "Lnet/minecraft/core/block/entity/TileEntity;getDescriptionPacket()Lnet/minecraft/core/net/packet/Packet;") - ) - public Packet redirectUpdateTileEntity(TileEntity tile) { - Packet packet = tile.getDescriptionPacket(); - if(packet == null) throw new IllegalStateException(String.format("Tile entity '%s' returned null description packet.", tile)); - return packet; - } - - - @Unique - private EntityPlayerMP getPlayer() { - return (EntityPlayerMP) ((Object) this); - } - - -} diff --git a/src/main/java/turniplabs/halplibe/mixin/mixins/gui/EntityPlayerSPMixin.java b/src/main/java/turniplabs/halplibe/mixin/mixins/gui/EntityPlayerSPMixin.java deleted file mode 100644 index 8d9b896..0000000 --- a/src/main/java/turniplabs/halplibe/mixin/mixins/gui/EntityPlayerSPMixin.java +++ /dev/null @@ -1,124 +0,0 @@ -package turniplabs.halplibe.mixin.mixins.gui; - -import net.minecraft.client.entity.player.EntityPlayerSP; -import net.minecraft.core.block.entity.*; -import net.minecraft.core.item.ItemStack; -import net.minecraft.core.player.inventory.IInventory; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Unique; -import turniplabs.halplibe.helper.gui.GuiHelper; -import turniplabs.halplibe.helper.gui.Guis; - -@Mixin( - value = EntityPlayerSP.class, - remap = false -) -public abstract class EntityPlayerSPMixin { - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIEditSign(TileEntitySign tile) { - Guis.EDIT_SIGN.open(getPlayer(), tile.x, tile.y, tile.z); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIEditFlag(TileEntityFlag tile) { - Guis.EDIT_FLAG.open(getPlayer(), tile.x, tile.y, tile.z); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIChest(IInventory iinventory) { - GuiHelper.reportVanillaGuiCall("BTA display gui method called"); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIWorkbench(int x, int y, int z) { - Guis.WORKBENCH.open(getPlayer(), x, y, z); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIEditLabel(ItemStack itemstack, int slot) { - Guis.EDIT_LABEL.open(getPlayer(), itemstack); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIPaintingPicker() { - Guis.PAINTING_PICKER.open(getPlayer()); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIMobSpawnerPicker(int x, int y, int z) { - Guis.MOB_SPAWNER_PICKER.open(getPlayer(), x, y, z); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIWandMonsterPicker(ItemStack stack) { - Guis.WAND_MONSTER_PICKER.open(getPlayer(), stack); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIFurnace(TileEntityFurnace tile) { - Guis.FURNACE.open(getPlayer(), tile.x, tile.y, tile.z); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUITrommel(TileEntityTrommel tile) { - Guis.TROMMEL.open(getPlayer(), tile.x, tile.y, tile.z); - } - - /** - * @author kill05 - * @reason gui rewrite - */ - @Overwrite - public void displayGUIDispenser(TileEntityDispenser tile) { - Guis.DISPENSER.open(getPlayer(), tile.x, tile.y, tile.z); - } - - - @Unique - private EntityPlayerSP getPlayer() { - return (EntityPlayerSP) ((Object) this); - } - -} diff --git a/src/main/java/turniplabs/halplibe/mixin/mixins/gui/GuiScreenMixin.java b/src/main/java/turniplabs/halplibe/mixin/mixins/gui/GuiScreenMixin.java new file mode 100644 index 0000000..a48dfe6 --- /dev/null +++ b/src/main/java/turniplabs/halplibe/mixin/mixins/gui/GuiScreenMixin.java @@ -0,0 +1,63 @@ +package turniplabs.halplibe.mixin.mixins.gui; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.EntityClientPlayerMP; +import net.minecraft.client.entity.player.EntityPlayerSP; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import turniplabs.halplibe.helper.gui.GuiScreenAccessor; +import turniplabs.halplibe.helper.gui.packet.PacketGuiButtonClick; +import turniplabs.halplibe.helper.gui.registered.RegisteredGui; + +import java.util.Iterator; + +@SuppressWarnings("AddedMixinMembersNamePattern") +@Mixin( + value = GuiScreen.class, + remap = false +) +public class GuiScreenMixin implements GuiScreenAccessor { + + @Unique + private String guiNamespace; + + @Inject( + method = "mouseClicked", + locals = LocalCapture.CAPTURE_FAILHARD, + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/sound/SoundManager;playSound(Ljava/lang/String;Lnet/minecraft/core/sound/SoundCategory;FF)V", + shift = At.Shift.AFTER + ) + ) + public void injectMouseClicked(int mouseX, int mouseY, int mouseButton, CallbackInfo ci, Iterator unused, GuiButton button) { + RegisteredGui gui = getRegisteredGui(); + if(gui == null) return; + + EntityPlayerSP player = Minecraft.getMinecraft(GuiScreenMixin.class).thePlayer; + + if (player instanceof EntityClientPlayerMP) { + EntityClientPlayerMP playerMP = (EntityClientPlayerMP) player; + playerMP.sendQueue.addToSendQueue(new PacketGuiButtonClick(getGuiNamespace(), button.id)); + } + + gui.getFactory().onButtonClick(gui, player, player, button.id); + } + + @Override + public void setGuiNamespace(String namespace) { + if(guiNamespace != null) throw new IllegalStateException("Gui namespace has already been set!"); + this.guiNamespace = namespace; + } + + @Override + public String getGuiNamespace() { + return guiNamespace; + } +} diff --git a/src/main/java/turniplabs/halplibe/mixin/mixins/gui/PlayerManager_PlayerInstanceMixin.java b/src/main/java/turniplabs/halplibe/mixin/mixins/gui/PlayerManager_PlayerInstanceMixin.java deleted file mode 100644 index 1428cf6..0000000 --- a/src/main/java/turniplabs/halplibe/mixin/mixins/gui/PlayerManager_PlayerInstanceMixin.java +++ /dev/null @@ -1,24 +0,0 @@ -package turniplabs.halplibe.mixin.mixins.gui; - -import net.minecraft.core.block.entity.TileEntity; -import net.minecraft.core.net.packet.Packet; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin( - targets = "net.minecraft.server.player.PlayerManager$PlayerInstance", - remap = false -) -public abstract class PlayerManager_PlayerInstanceMixin { - - @Redirect( - method = "updateTileEntity", - at = @At(value = "INVOKE", target = "Lnet/minecraft/core/block/entity/TileEntity;getDescriptionPacket()Lnet/minecraft/core/net/packet/Packet;") - ) - public Packet redirectUpdateTileEntity(TileEntity tile) { - Packet packet = tile.getDescriptionPacket(); - if(packet == null) throw new IllegalStateException(String.format("Tile entity '%s' returned null description packet.", tile)); - return packet; - } -} diff --git a/src/main/java/turniplabs/halplibe/util/PlayerUtils.java b/src/main/java/turniplabs/halplibe/util/PlayerUtils.java new file mode 100644 index 0000000..3fd2f0c --- /dev/null +++ b/src/main/java/turniplabs/halplibe/util/PlayerUtils.java @@ -0,0 +1,22 @@ +package turniplabs.halplibe.util; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.entity.player.EntityPlayer; +import net.minecraft.core.net.handler.NetHandler; +import org.apache.commons.lang3.reflect.FieldUtils; + +public final class PlayerUtils { + + public static EntityPlayer getPlayer(NetHandler handler) { + if(handler.isServerHandler()) { + try { + return (EntityPlayer) FieldUtils.readField(handler, "playerEntity", true); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + return Minecraft.getMinecraft(PlayerUtils.class).thePlayer; + } + +} diff --git a/src/main/resources/halplibe.mixins.json b/src/main/resources/halplibe.mixins.json index ec29539..656f6f9 100644 --- a/src/main/resources/halplibe.mixins.json +++ b/src/main/resources/halplibe.mixins.json @@ -17,9 +17,7 @@ "mixins.ContainerPlayerCreativeMixin", "mixins.I18nMixin", "mixins.StatMixin", - "mixins.TileEntityMixin", "mixins.commands.CommandsCoreMixin", - "mixins.gui.BlockChestMixin", "mixins.network.PacketMixin", "mixins.registry.BlockMixin", "mixins.registry.ItemMixin", @@ -34,7 +32,7 @@ "mixins.MinecraftMixin", "mixins.NetClientHandlerMixin", "mixins.commands.CommandsClientMixin", - "mixins.gui.EntityPlayerSPMixin", + "mixins.gui.GuiScreenMixin", "mixins.models.BlockColorDispatcherMixin", "mixins.models.BlockModelDispatcherMixin", "mixins.models.EntityRenderDispatcherMixin", @@ -46,8 +44,6 @@ "server": [ "mixins.MinecraftServerMixin", "mixins.commands.CommandsServerMixin", - "mixins.gui.EntityPlayerMPMixin", - "mixins.gui.PlayerManager_PlayerInstanceMixin", "mixins.network.MinecraftServerMixin", "mixins.version.NetLoginHandlerMixin" ],