From d5ee80a70a17ee60fea2bf63ec704771f8b4272b Mon Sep 17 00:00:00 2001 From: tterrag Date: Mon, 10 Jun 2019 18:14:09 -0400 Subject: [PATCH] Add IContainerFactory for reading custom container data on the client --- .../client/gui/ScreenManager.java.patch | 25 ++++++++++++ .../container/ContainerType.java.patch | 17 +++++++- .../extensions/IForgeContainerType.java | 16 ++++++++ .../fml/network/FMLPlayMessages.java | 12 +++++- .../fml/network/IContainerFactory.java | 17 ++++++++ .../debug/misc/ContainerTypeTest.java | 39 ++++++++++++++++--- 6 files changed, 117 insertions(+), 9 deletions(-) create mode 100644 patches/minecraft/net/minecraft/client/gui/ScreenManager.java.patch create mode 100644 src/main/java/net/minecraftforge/common/extensions/IForgeContainerType.java create mode 100644 src/main/java/net/minecraftforge/fml/network/IContainerFactory.java diff --git a/patches/minecraft/net/minecraft/client/gui/ScreenManager.java.patch b/patches/minecraft/net/minecraft/client/gui/ScreenManager.java.patch new file mode 100644 index 000000000..59b9cea2f --- /dev/null +++ b/patches/minecraft/net/minecraft/client/gui/ScreenManager.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/client/gui/ScreenManager.java ++++ b/net/minecraft/client/gui/ScreenManager.java +@@ -39,6 +39,10 @@ + private static final Map, ScreenManager.IScreenFactory> field_216914_b = Maps.newHashMap(); + + public static void func_216909_a(@Nullable ContainerType p_216909_0_, Minecraft p_216909_1_, int p_216909_2_, ITextComponent p_216909_3_) { ++ getScreenFactory(p_216909_0_, p_216909_1_, p_216909_2_, p_216909_3_).ifPresent(f -> f.func_216908_a(p_216909_3_, p_216909_0_, p_216909_1_, p_216909_2_)); ++ } ++ ++ public static java.util.Optional> getScreenFactory(@Nullable ContainerType p_216909_0_, Minecraft p_216909_1_, int p_216909_2_, ITextComponent p_216909_3_) { + if (p_216909_0_ == null) { + field_216913_a.warn("Trying to open invalid screen with name: {}", (Object)p_216909_3_.getString()); + } else { +@@ -46,9 +50,10 @@ + if (iscreenfactory == null) { + field_216913_a.warn("Failed to create screen for menu type: {}", (Object)Registry.field_218366_G.func_177774_c(p_216909_0_)); + } else { +- iscreenfactory.func_216908_a(p_216909_3_, p_216909_0_, p_216909_1_, p_216909_2_); ++ return java.util.Optional.of(iscreenfactory); + } + } ++ return java.util.Optional.empty(); + } + + @Nullable diff --git a/patches/minecraft/net/minecraft/inventory/container/ContainerType.java.patch b/patches/minecraft/net/minecraft/inventory/container/ContainerType.java.patch index 29e0cfb73..d73023fcd 100644 --- a/patches/minecraft/net/minecraft/inventory/container/ContainerType.java.patch +++ b/patches/minecraft/net/minecraft/inventory/container/ContainerType.java.patch @@ -5,7 +5,22 @@ import net.minecraftforge.api.distmarker.OnlyIn; -public class ContainerType { -+public class ContainerType extends net.minecraftforge.registries.ForgeRegistryEntry> { ++public class ContainerType extends net.minecraftforge.registries.ForgeRegistryEntry> implements net.minecraftforge.common.extensions.IForgeContainerType { public static final ContainerType field_221507_a = func_221505_a("generic_9x1", ChestContainer::func_216986_a); public static final ContainerType field_221508_b = func_221505_a("generic_9x2", ChestContainer::func_216987_b); public static final ContainerType field_221509_c = func_221505_a("generic_9x3", ChestContainer::func_216988_c); +@@ -45,6 +45,14 @@ + public T func_221506_a(int p_221506_1_, PlayerInventory p_221506_2_) { + return this.field_221530_x.create(p_221506_1_, p_221506_2_); + } ++ ++ @Override ++ public T create(int windowId, PlayerInventory playerInv, net.minecraft.network.PacketBuffer extraData) { ++ if (this.field_221530_x instanceof net.minecraftforge.fml.network.IContainerFactory) { ++ return ((net.minecraftforge.fml.network.IContainerFactory) this.field_221530_x).create(windowId, playerInv, extraData); ++ } ++ return func_221506_a(windowId, playerInv); ++ } + + public interface IFactory { + @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgeContainerType.java b/src/main/java/net/minecraftforge/common/extensions/IForgeContainerType.java new file mode 100644 index 000000000..0f60b3821 --- /dev/null +++ b/src/main/java/net/minecraftforge/common/extensions/IForgeContainerType.java @@ -0,0 +1,16 @@ +package net.minecraftforge.common.extensions; + +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.ContainerType; +import net.minecraft.network.PacketBuffer; + +public interface IForgeContainerType +{ + static ContainerType create(net.minecraftforge.fml.network.IContainerFactory factory) + { + return new ContainerType<>(factory); + } + + T create(int windowId, PlayerInventory playerInv, PacketBuffer extraData); +} diff --git a/src/main/java/net/minecraftforge/fml/network/FMLPlayMessages.java b/src/main/java/net/minecraftforge/fml/network/FMLPlayMessages.java index 38b113f82..0a2a2b370 100644 --- a/src/main/java/net/minecraftforge/fml/network/FMLPlayMessages.java +++ b/src/main/java/net/minecraftforge/fml/network/FMLPlayMessages.java @@ -21,11 +21,13 @@ package net.minecraftforge.fml.network; import io.netty.buffer.Unpooled; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.IHasContainer; import net.minecraft.client.gui.ScreenManager; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; +import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.ContainerType; import net.minecraft.network.PacketBuffer; import net.minecraft.util.ResourceLocation; @@ -208,8 +210,14 @@ public class FMLPlayMessages public static void handle(OpenContainer msg, Supplier ctx) { ctx.get().enqueueWork(() -> { - // TODO extend IScreenFactory to allow for extra data - ScreenManager.openScreen(msg.getType(), Minecraft.getInstance(), msg.getWindowId(), msg.getName()); + ScreenManager.getScreenFactory(msg.getType(), Minecraft.getInstance(), msg.getWindowId(), msg.getName()) + .ifPresent(f -> { + Container c = msg.getType().create(msg.getWindowId(), Minecraft.getInstance().player.inventory, msg.getAdditionalData()); + @SuppressWarnings("unchecked") + Screen s = ((ScreenManager.IScreenFactory)f).create(c, Minecraft.getInstance().player.inventory, msg.getName()); + Minecraft.getInstance().player.openContainer = ((IHasContainer)s).getContainer(); + Minecraft.getInstance().displayGuiScreen(s); + }); }); ctx.get().setPacketHandled(true); } diff --git a/src/main/java/net/minecraftforge/fml/network/IContainerFactory.java b/src/main/java/net/minecraftforge/fml/network/IContainerFactory.java new file mode 100644 index 000000000..1ba71d86e --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/network/IContainerFactory.java @@ -0,0 +1,17 @@ +package net.minecraftforge.fml.network; + +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.ContainerType; +import net.minecraft.network.PacketBuffer; + +public interface IContainerFactory extends ContainerType.IFactory +{ + T create(int windowId, PlayerInventory inv, PacketBuffer data); + + @Override + default T create(int p_create_1_, PlayerInventory p_create_2_) + { + return create(p_create_1_, p_create_2_, null); + } +} diff --git a/src/test/java/net/minecraftforge/debug/misc/ContainerTypeTest.java b/src/test/java/net/minecraftforge/debug/misc/ContainerTypeTest.java index d41bc9bfd..3abaf4f96 100644 --- a/src/test/java/net/minecraftforge/debug/misc/ContainerTypeTest.java +++ b/src/test/java/net/minecraftforge/debug/misc/ContainerTypeTest.java @@ -24,18 +24,26 @@ import net.minecraft.client.gui.ScreenManager; import net.minecraft.client.gui.screen.inventory.ContainerScreen; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.inventory.Inventory; import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.ContainerType; import net.minecraft.inventory.container.INamedContainerProvider; +import net.minecraft.inventory.container.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.Hand; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.extensions.IForgeContainerType; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.registries.ObjectHolder; @Mod("containertypetest") @@ -45,9 +53,21 @@ public class ContainerTypeTest public static final ContainerType TYPE = null; public class TestContainer extends Container { - protected TestContainer(int windowId, PlayerInventory inv) + private final String text; + + protected TestContainer(int windowId, PlayerInventory playerInv, PacketBuffer extraData) + { + this(windowId, new Inventory(9), extraData.readString(128)); + } + + public TestContainer(int windowId, Inventory inv, String text) { super(TYPE, windowId); + this.text = text; + for (int i = 0; i < 9; i++) + { + this.addSlot(new Slot(inv, i, (i % 3) * 18, (i / 3) * 18)); + } } @Override @@ -67,7 +87,7 @@ public class ContainerTypeTest @Override protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { - drawString(this.font, "Hello World!", mouseX, mouseY, -1); + drawString(this.font, getContainer().text, mouseX, mouseY, -1); } } @@ -80,7 +100,7 @@ public class ContainerTypeTest private void registerContainers(final RegistryEvent.Register> event) { - event.getRegistry().register(new ContainerType(TestContainer::new).setRegistryName("container")); + event.getRegistry().register(IForgeContainerType.create(TestContainer::new).setRegistryName("container")); } private void setup(FMLClientSetupEvent event) @@ -94,13 +114,18 @@ public class ContainerTypeTest { if (event.getWorld().getBlockState(event.getPos()).getBlock() == Blocks.SPONGE) { - event.getEntityPlayer().openContainer(new INamedContainerProvider() + String text = "Hello World!"; + NetworkHooks.openGui((ServerPlayerEntity) event.getEntityPlayer(), new INamedContainerProvider() { - @Override public Container createMenu(int p_createMenu_1_, PlayerInventory p_createMenu_2_, PlayerEntity p_createMenu_3_) { - return TYPE.func_221506_a(p_createMenu_1_, p_createMenu_2_); + Inventory inv = new Inventory(9); + for (int i = 0; i < inv.getSizeInventory(); i++) + { + inv.setInventorySlotContents(i, new ItemStack(Items.DIAMOND)); + } + return new TestContainer(p_createMenu_1_, inv, text); } @Override @@ -108,6 +133,8 @@ public class ContainerTypeTest { return new StringTextComponent("Test"); } + }, extraData -> { + extraData.writeString(text); }); } }