From 045df74fe0824e0def7725e21eeaea6f648e79bb Mon Sep 17 00:00:00 2001 From: Juuxel <6596629+Juuxel@users.noreply.github.com> Date: Tue, 16 Jun 2020 00:00:54 +0300 Subject: [PATCH] Screen handler API (#584) * Add screen handler API * Use more descriptive letters for FabricHandledScreens generics * Add missing Deprecated annotations * Bump fabric-containers-v0 version * Remove unused ServerPlayerEntityAccessor * Remove [Fabric] from log messages * Convert FabricHandledScreens to a class * Add dependency on networking-v0 * Resolve threading issues with NetworkingClient * Use Identifiers instead of int IDs, make ScreenHandlers a class Also added a private constructor to FabricHandledScreens. * NetworkingClient -> ClientNetworking * Use more descriptive names for injections * Use ID parameter instead of fetching again * Add clarifying comment * Port changes from FabLabs * Fix compilation * Replace the content of links in FabricHandledScreens for readability * Sync with FabLabs * Add test mod * I suppose IInv shouldn't have CC0 anymore :eyes: * Improve logging - Networking now uses a logger instead of an exception - The loggers are now suffixed with their side - Fixed the client unregistered screen message using the title instead of the ID * Fix test mod on 20w21a * Fix ExtendedScreenHandlerFactory javadoc referencing old names * Update test mod to 1.16-pre2 Just a simple mapping update. :) * Fix incorrect javadoc references to screen-handler-api in containers-v0 * Remove Minecraft exclusion from build.gradle (thanks to Loom 0.4) + testmod change Resource loader v0 is now testmodRuntimeOnly as it's not needed for compiling. --- fabric-containers-v0/build.gradle | 2 +- .../client/screen/ContainerScreenFactory.java | 4 + .../client/screen/ScreenProviderRegistry.java | 4 + .../api/container/ContainerFactory.java | 4 + .../container/ContainerProviderRegistry.java | 4 + fabric-screen-handler-api-v1/build.gradle | 12 + .../screenhandler/v1/ScreenRegistry.java | 87 +++++++ .../client/screenhandler/v1/package-info.java | 20 ++ .../v1/ExtendedScreenHandlerFactory.java | 36 +++ .../v1/ScreenHandlerRegistry.java | 140 +++++++++++ .../api/screenhandler/v1/package-info.java | 20 ++ .../ExtendedScreenHandlerType.java | 46 ++++ .../fabric/impl/screenhandler/Networking.java | 72 ++++++ .../client/ClientNetworking.java | 87 +++++++ .../ServerPlayerEntityMixin.java | 81 ++++++ .../fabric-screen-handler-api-v1/icon.png | Bin 0 -> 1579 bytes ...fabric-screen-handler-api-v1.accesswidener | 8 + .../fabric-screen-handler-api-v1.mixins.json | 13 + .../src/main/resources/fabric.mod.json | 31 +++ .../test/screenhandler/ScreenHandlerTest.java | 64 +++++ .../test/screenhandler/block/BoxBlock.java | 81 ++++++ .../screenhandler/block/BoxBlockEntity.java | 69 ++++++ .../client/ClientScreenHandlerTest.java | 40 +++ .../client/PositionedScreen.java | 62 +++++ .../test/screenhandler/item/BagInventory.java | 47 ++++ .../test/screenhandler/item/BagItem.java | 47 ++++ .../item/ImplementedInventory.java | 232 ++++++++++++++++++ .../screenhandler/item/PositionedBagItem.java | 76 ++++++ .../screen/BagScreenHandler.java | 65 +++++ .../screen/BoxScreenHandler.java | 50 ++++ .../screen/PositionedBagScreenHandler.java | 49 ++++ .../screen/PositionedScreenHandler.java | 23 ++ .../blockstates/box.json | 5 + .../lang/en_us.json | 5 + .../models/block/box.json | 6 + .../models/item/bag.json | 6 + .../models/item/box.json | 3 + .../models/item/positioned_bag.json | 6 + .../textures/block/box.png | Bin 0 -> 616 bytes .../textures/item/bag.png | Bin 0 -> 837 bytes .../textures/item/positioned_bag.png | Bin 0 -> 2064 bytes .../loot_tables/blocks/box.json | 19 ++ .../src/testmod/resources/fabric.mod.json | 20 ++ settings.gradle | 1 + 44 files changed, 1646 insertions(+), 1 deletion(-) create mode 100644 fabric-screen-handler-api-v1/build.gradle create mode 100644 fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/client/screenhandler/v1/ScreenRegistry.java create mode 100644 fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/client/screenhandler/v1/package-info.java create mode 100644 fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ExtendedScreenHandlerFactory.java create mode 100644 fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ScreenHandlerRegistry.java create mode 100644 fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/package-info.java create mode 100644 fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/ExtendedScreenHandlerType.java create mode 100644 fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/Networking.java create mode 100644 fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/client/ClientNetworking.java create mode 100644 fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/mixin/screenhandler/ServerPlayerEntityMixin.java create mode 100644 fabric-screen-handler-api-v1/src/main/resources/assets/fabric-screen-handler-api-v1/icon.png create mode 100644 fabric-screen-handler-api-v1/src/main/resources/fabric-screen-handler-api-v1.accesswidener create mode 100644 fabric-screen-handler-api-v1/src/main/resources/fabric-screen-handler-api-v1.mixins.json create mode 100644 fabric-screen-handler-api-v1/src/main/resources/fabric.mod.json create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/ScreenHandlerTest.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/block/BoxBlock.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/block/BoxBlockEntity.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/client/ClientScreenHandlerTest.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/client/PositionedScreen.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/BagInventory.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/BagItem.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/ImplementedInventory.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/PositionedBagItem.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/BagScreenHandler.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/BoxScreenHandler.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/PositionedBagScreenHandler.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/PositionedScreenHandler.java create mode 100644 fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/blockstates/box.json create mode 100644 fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/lang/en_us.json create mode 100644 fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/block/box.json create mode 100644 fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/item/bag.json create mode 100644 fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/item/box.json create mode 100644 fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/item/positioned_bag.json create mode 100644 fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/textures/block/box.png create mode 100644 fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/textures/item/bag.png create mode 100644 fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/textures/item/positioned_bag.png create mode 100644 fabric-screen-handler-api-v1/src/testmod/resources/data/fabric-screen-handler-api-v1-testmod/loot_tables/blocks/box.json create mode 100644 fabric-screen-handler-api-v1/src/testmod/resources/fabric.mod.json diff --git a/fabric-containers-v0/build.gradle b/fabric-containers-v0/build.gradle index e866ea231..e79c36dac 100644 --- a/fabric-containers-v0/build.gradle +++ b/fabric-containers-v0/build.gradle @@ -1,5 +1,5 @@ archivesBaseName = "fabric-containers-v0" -version = getSubprojectVersion(project, "0.1.7") +version = getSubprojectVersion(project, "0.1.8") dependencies { compile project(path: ':fabric-api-base', configuration: 'dev') diff --git a/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/client/screen/ContainerScreenFactory.java b/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/client/screen/ContainerScreenFactory.java index db4b2d196..163c5a23d 100644 --- a/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/client/screen/ContainerScreenFactory.java +++ b/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/client/screen/ContainerScreenFactory.java @@ -19,6 +19,10 @@ package net.fabricmc.fabric.api.client.screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.screen.ScreenHandler; +/** + * @deprecated Use {@link net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry.Factory} instead. + */ +@Deprecated @FunctionalInterface public interface ContainerScreenFactory<C extends ScreenHandler> { HandledScreen create(C container); diff --git a/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/client/screen/ScreenProviderRegistry.java b/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/client/screen/ScreenProviderRegistry.java index a132b746f..7047db7cf 100644 --- a/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/client/screen/ScreenProviderRegistry.java +++ b/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/client/screen/ScreenProviderRegistry.java @@ -24,6 +24,10 @@ import net.fabricmc.fabric.api.container.ContainerFactory; import net.fabricmc.fabric.api.container.ContainerProviderRegistry; import net.fabricmc.fabric.impl.client.container.ScreenProviderRegistryImpl; +/** + * @deprecated Use {@link net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry} instead. + */ +@Deprecated public interface ScreenProviderRegistry { ScreenProviderRegistry INSTANCE = ScreenProviderRegistryImpl.INSTANCE; diff --git a/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/container/ContainerFactory.java b/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/container/ContainerFactory.java index 4a5c0cee1..15daa3dd2 100644 --- a/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/container/ContainerFactory.java +++ b/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/container/ContainerFactory.java @@ -20,6 +20,10 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.Identifier; import net.minecraft.network.PacketByteBuf; +/** + * @deprecated Use {@link net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry.ExtendedClientHandlerFactory} instead. + */ +@Deprecated @FunctionalInterface public interface ContainerFactory<T> { /** diff --git a/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/container/ContainerProviderRegistry.java b/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/container/ContainerProviderRegistry.java index 7d82f98a4..2dd365c6b 100644 --- a/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/container/ContainerProviderRegistry.java +++ b/fabric-containers-v0/src/main/java/net/fabricmc/fabric/api/container/ContainerProviderRegistry.java @@ -27,6 +27,10 @@ import net.minecraft.network.PacketByteBuf; import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry; import net.fabricmc.fabric.impl.container.ContainerProviderImpl; +/** + * @deprecated Use {@link net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry} instead. + */ +@Deprecated public interface ContainerProviderRegistry { ContainerProviderRegistry INSTANCE = ContainerProviderImpl.INSTANCE; diff --git a/fabric-screen-handler-api-v1/build.gradle b/fabric-screen-handler-api-v1/build.gradle new file mode 100644 index 000000000..1a3f806c1 --- /dev/null +++ b/fabric-screen-handler-api-v1/build.gradle @@ -0,0 +1,12 @@ +archivesBaseName = "fabric-screen-handler-api-v1" +version = getSubprojectVersion(project, "1.0.0") + +minecraft { + accessWidener = file('src/main/resources/fabric-screen-handler-api-v1.accesswidener') +} + +dependencies { + compile(project(path: ':fabric-api-base', configuration: 'dev')) + compile(project(path: ':fabric-networking-v0', configuration: 'dev')) + testmodRuntimeOnly(project(path: ':fabric-resource-loader-v0', configuration: 'dev')) +} diff --git a/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/client/screenhandler/v1/ScreenRegistry.java b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/client/screenhandler/v1/ScreenRegistry.java new file mode 100644 index 000000000..725859b59 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/client/screenhandler/v1/ScreenRegistry.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.client.screenhandler.v1; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.HandledScreens; +import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.text.Text; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +/** + * An API for registering handled screens that represent screen handlers on the client. + * Exposes vanilla's private {@link HandledScreens#register HandledScreens.register()} to modders as {@link #register ScreenRegistry.register()}. + * + * <h2>Example</h2> + * <pre> + * {@code + * // In a client-side initialization method: + * ScreenRegistry.register(MyScreenHandlers.OVEN, OvenScreen::new); + * + * // Screen class + * public class OvenScreen extends HandledScreen<OvenScreenHandler> { + * public OvenScreen(OvenScreenHandler handler, PlayerInventory inventory, Text title) { + * super(handler, inventory, title); + * } + * } + * } + * </pre> + * + * @see net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry registering screen handlers + */ +@Environment(EnvType.CLIENT) +public final class ScreenRegistry { + private ScreenRegistry() { + } + + /** + * Registers a new screen factory for a screen handler type. + * + * @param type the screen handler type object + * @param screenFactory the screen handler factory + * @param <H> the screen handler type + * @param <S> the screen type + */ + public static <H extends ScreenHandler, S extends Screen & ScreenHandlerProvider<H>> void register(ScreenHandlerType<? extends H> type, Factory<? super H, ? extends S> screenFactory) { + // Convert our factory to the vanilla provider here as the vanilla interface won't be available to modders. + HandledScreens.<H, S>register(type, screenFactory::create); + } + + /** + * A factory for handled screens. + * + * @param <H> the screen handler type + * @param <S> the screen type + */ + @FunctionalInterface + public interface Factory<H extends ScreenHandler, S extends Screen & ScreenHandlerProvider<H>> { + /** + * Creates a new handled screen. + * + * @param handler the screen handler + * @param inventory the player inventory + * @param title the title of the screen + * @return the created screen + */ + S create(H handler, PlayerInventory inventory, Text title); + } +} diff --git a/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/client/screenhandler/v1/package-info.java b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/client/screenhandler/v1/package-info.java new file mode 100644 index 000000000..47bd0433c --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/client/screenhandler/v1/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * API for working with screen handlers on the client. + */ +package net.fabricmc.fabric.api.client.screenhandler.v1; diff --git a/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ExtendedScreenHandlerFactory.java b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ExtendedScreenHandlerFactory.java new file mode 100644 index 000000000..e1fb76878 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ExtendedScreenHandlerFactory.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.screenhandler.v1; + +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.server.network.ServerPlayerEntity; + +/** + * An extension of {@code NamedScreenHandlerFactory} that can write additional data to a screen opening packet. + * + * @see ScreenHandlerRegistry#registerExtended(net.minecraft.util.Identifier, ScreenHandlerRegistry.ExtendedClientHandlerFactory) + */ +public interface ExtendedScreenHandlerFactory extends NamedScreenHandlerFactory { + /** + * Writes additional server -> client screen opening data to the buffer. + * + * @param player the player that is opening the screen + * @param buf the packet buffer + */ + void writeScreenOpeningData(ServerPlayerEntity player, PacketByteBuf buf); +} diff --git a/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ScreenHandlerRegistry.java b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ScreenHandlerRegistry.java new file mode 100644 index 000000000..2a93d0fed --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ScreenHandlerRegistry.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.screenhandler.v1; + +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.impl.screenhandler.ExtendedScreenHandlerType; + +/** + * An API for creating and registering {@linkplain ScreenHandlerType screen handler types}. + * + * <p>This class exposes the private {@link ScreenHandlerType} constructor, + * as well as adds support for creating types using Fabric's extended screen handler API. + * + * <p>Screen handlers types are used to synchronize {@linkplain ScreenHandler screen handlers} + * between the server and the client. Screen handlers manage the items and integer properties that are + * needed to show on screens, such as the items in a chest or the progress of a furnace. + * + * <h2>Simple and extended screen handlers</h2> + * Simple screen handlers are the type of screen handlers used in vanilla. + * They can automatically synchronize items and integer properties between the server and the client, + * but they don't support having custom data sent in the opening packet. + * + * <p>This module adds <i>extended screen handlers</i> that can synchronize their own custom data + * when they are opened, which can be useful for defining additional properties of a screen on the server. + * For example, a mod can synchronize text that will show up as a label. + * + * <h2>Example</h2> + * <pre> + * {@code + * // Creating the screen handler type + * public static final ScreenHandlerType<OvenScreenHandler> OVEN = ScreenHandlerRegistry.registerSimple(new Identifier("my_mod", "oven"), OvenScreenHandler::new); + * + * // Screen handler class + * public class OvenScreenHandler extends ScreenHandler { + * public OvenScreenHandler(int syncId) { + * super(MyScreenHandlers.OVEN, syncId); + * } + * } + * + * // Opening the screen + * NamedScreenHandlerFactory factory = ...; + * player.openHandledScreen(factory); // only works on ServerPlayerEntity instances + * } + * </pre> + * + * @see net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry registering screens for screen handlers + */ +public final class ScreenHandlerRegistry { + private ScreenHandlerRegistry() { + } + + /** + * Creates and registers a new {@code ScreenHandlerType} that creates client-sided screen handlers using the factory. + * + * @param id the registry ID + * @param factory the client-sided screen handler factory + * @param <T> the screen handler type + * @return the created type object + */ + public static <T extends ScreenHandler> ScreenHandlerType<T> registerSimple(Identifier id, SimpleClientHandlerFactory<T> factory) { + // Wrap our factory in vanilla's factory; it will not be public for users. + ScreenHandlerType<T> type = new ScreenHandlerType<>(factory::create); + return Registry.register(Registry.SCREEN_HANDLER, id, type); + } + + /** + * Creates and registers a new {@code ScreenHandlerType} that creates client-sided screen handlers with additional + * networked opening data. + * + * <p>These screen handlers must be opened with a {@link ExtendedScreenHandlerFactory}. + * + * @param id the registry ID + * @param factory the client-sided screen handler factory + * @param <T> the screen handler type + * @return the created type object + */ + public static <T extends ScreenHandler> ScreenHandlerType<T> registerExtended(Identifier id, ExtendedClientHandlerFactory<T> factory) { + ScreenHandlerType<T> type = new ExtendedScreenHandlerType<>(factory); + return Registry.register(Registry.SCREEN_HANDLER, id, type); + } + + /** + * A factory for client-sided screen handler instances. + * + * @param <T> the screen handler type + */ + public interface SimpleClientHandlerFactory<T extends ScreenHandler> { + /** + * Creates a new client-sided screen handler. + * + * @param syncId the synchronization ID + * @param inventory the player inventory + * @return the created screen handler + */ + @Environment(EnvType.CLIENT) + T create(int syncId, PlayerInventory inventory); + } + + /** + * A factory for client-sided screen handler instances + * with additional screen opening data. + * + * @param <T> the screen handler type + * @see ExtendedScreenHandlerFactory + */ + public interface ExtendedClientHandlerFactory<T extends ScreenHandler> { + /** + * Creates a new client-sided screen handler with additional screen opening data. + * + * @param syncId the synchronization ID + * @param inventory the player inventory + * @param buf the packet buffer + * @return the created screen handler + */ + @Environment(EnvType.CLIENT) + T create(int syncId, PlayerInventory inventory, PacketByteBuf buf); + } +} diff --git a/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/package-info.java b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/package-info.java new file mode 100644 index 000000000..3d1ff2e3d --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The Fabric screen handler API for creating screen handlers. + */ +package net.fabricmc.fabric.api.screenhandler.v1; diff --git a/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/ExtendedScreenHandlerType.java b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/ExtendedScreenHandlerType.java new file mode 100644 index 000000000..951338f03 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/ExtendedScreenHandlerType.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.screenhandler; + +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.ScreenHandlerType; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; + +public final class ExtendedScreenHandlerType<T extends ScreenHandler> extends ScreenHandlerType<T> { + private final ScreenHandlerRegistry.ExtendedClientHandlerFactory<T> factory; + + public ExtendedScreenHandlerType(ScreenHandlerRegistry.ExtendedClientHandlerFactory<T> factory) { + super(null); + this.factory = factory; + } + + @Environment(EnvType.CLIENT) + @Override + public T create(int syncId, PlayerInventory inventory) { + throw new UnsupportedOperationException("Use ExtendedScreenHandlerType.create(int, PlayerInventory, PacketByteBuf)!"); + } + + @Environment(EnvType.CLIENT) + public T create(int syncId, PlayerInventory inventory, PacketByteBuf buf) { + return factory.create(syncId, inventory, buf); + } +} diff --git a/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/Networking.java b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/Networking.java new file mode 100644 index 000000000..07ab4eb6b --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/Networking.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.screenhandler; + +import java.util.Objects; + +import io.netty.buffer.Unpooled; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +import net.fabricmc.fabric.api.network.ServerSidePacketRegistry; +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; + +public final class Networking { + private static final Logger LOGGER = LogManager.getLogger("fabric-screen-handler-api-v1/server"); + + // [Packet format] + // typeId: identifier + // syncId: varInt + // title: text + // customData: buf + public static final Identifier OPEN_ID = new Identifier("fabric-screen-handler-api-v1", "open_screen"); + + /** + * Opens an extended screen handler by sending a custom packet to the client. + * + * @param player the player + * @param factory the screen handler factory + * @param handler the screen handler instance + * @param syncId the synchronization ID + */ + public static void sendOpenPacket(ServerPlayerEntity player, ExtendedScreenHandlerFactory factory, ScreenHandler handler, int syncId) { + Objects.requireNonNull(player, "player is null"); + Objects.requireNonNull(factory, "factory is null"); + Objects.requireNonNull(handler, "handler is null"); + + Identifier typeId = Registry.SCREEN_HANDLER.getId(handler.getType()); + + if (typeId == null) { + LOGGER.warn("Trying to open unregistered screen handler {}", handler); + return; + } + + PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer()); + buf.writeIdentifier(typeId); + buf.writeVarInt(syncId); + buf.writeText(factory.getDisplayName()); + factory.writeScreenOpeningData(player, buf); + + ServerSidePacketRegistry.INSTANCE.sendToPlayer(player, OPEN_ID, buf); + } +} diff --git a/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/client/ClientNetworking.java b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/client/ClientNetworking.java new file mode 100644 index 000000000..7f4058de0 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/client/ClientNetworking.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.screenhandler.client; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.HandledScreens; +import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; +import net.fabricmc.fabric.impl.screenhandler.ExtendedScreenHandlerType; +import net.fabricmc.fabric.impl.screenhandler.Networking; + +@Environment(EnvType.CLIENT) +public final class ClientNetworking implements ClientModInitializer { + private static final Logger LOGGER = LogManager.getLogger("fabric-screen-handler-api-v1/client"); + + @Override + public void onInitializeClient() { + ClientSidePacketRegistry.INSTANCE.register(Networking.OPEN_ID, (ctx, buf) -> { + Identifier typeId = buf.readIdentifier(); + int syncId = buf.readVarInt(); + Text title = buf.readText(); + buf.retain(); + ctx.getTaskQueue().execute(() -> openScreen(typeId, syncId, title, buf)); + }); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private void openScreen(Identifier typeId, int syncId, Text title, PacketByteBuf buf) { + ScreenHandlerType<?> type = Registry.SCREEN_HANDLER.get(typeId); + + if (type == null) { + LOGGER.warn("Unknown screen handler ID: {}", typeId); + return; + } + + if (!(type instanceof ExtendedScreenHandlerType<?>)) { + LOGGER.warn("Received extended opening packet for non-extended screen handler {}", typeId); + return; + } + + HandledScreens.Provider screenFactory = HandledScreens.getProvider(type); + + if (screenFactory != null) { + MinecraftClient client = MinecraftClient.getInstance(); + PlayerEntity player = client.player; + + Screen screen = screenFactory.create( + ((ExtendedScreenHandlerType<?>) type).create(syncId, player.inventory, buf), + player.inventory, + title + ); + + player.currentScreenHandler = ((ScreenHandlerProvider<?>) screen).getScreenHandler(); + client.openScreen(screen); + } else { + LOGGER.warn("Screen not registered for screen handler {}!", typeId); + } + } +} diff --git a/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/mixin/screenhandler/ServerPlayerEntityMixin.java b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/mixin/screenhandler/ServerPlayerEntityMixin.java new file mode 100644 index 000000000..adcc34e2c --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/mixin/screenhandler/ServerPlayerEntityMixin.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.screenhandler; + +import java.util.OptionalInt; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import net.minecraft.network.Packet; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; +import net.fabricmc.fabric.impl.screenhandler.ExtendedScreenHandlerType; +import net.fabricmc.fabric.impl.screenhandler.Networking; + +@Mixin(ServerPlayerEntity.class) +public class ServerPlayerEntityMixin { + @Shadow + private int screenHandlerSyncId; + + @Unique + private final ThreadLocal<ScreenHandler> fabric_openedScreenHandler = new ThreadLocal<>(); + + @Inject(method = "openHandledScreen(Lnet/minecraft/screen/NamedScreenHandlerFactory;)Ljava/util/OptionalInt;", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V"), locals = LocalCapture.CAPTURE_FAILHARD) + private void fabric_storeOpenedScreenHandler(NamedScreenHandlerFactory factory, CallbackInfoReturnable<OptionalInt> info, ScreenHandler handler) { + if (factory instanceof ExtendedScreenHandlerFactory) { + fabric_openedScreenHandler.set(handler); + } else if (handler.getType() instanceof ExtendedScreenHandlerType<?>) { + Identifier id = Registry.SCREEN_HANDLER.getId(handler.getType()); + throw new IllegalArgumentException("[Fabric] Extended screen handler " + id + " must be opened with an ExtendedScreenHandlerFactory!"); + } + } + + @Redirect(method = "openHandledScreen(Lnet/minecraft/screen/NamedScreenHandlerFactory;)Ljava/util/OptionalInt;", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V")) + private void fabric_replaceVanillaScreenPacket(ServerPlayNetworkHandler networkHandler, Packet<?> packet, NamedScreenHandlerFactory factory) { + if (factory instanceof ExtendedScreenHandlerFactory) { + ScreenHandler handler = fabric_openedScreenHandler.get(); + + if (handler.getType() instanceof ExtendedScreenHandlerType<?>) { + Networking.sendOpenPacket((ServerPlayerEntity) (Object) this, (ExtendedScreenHandlerFactory) factory, handler, screenHandlerSyncId); + } else { + Identifier id = Registry.SCREEN_HANDLER.getId(handler.getType()); + throw new IllegalArgumentException("[Fabric] Non-extended screen handler " + id + " must not be opened with an ExtendedScreenHandlerFactory!"); + } + } else { + // Use vanilla logic for non-extended screen handlers + networkHandler.sendPacket(packet); + } + } + + @Inject(method = "openHandledScreen(Lnet/minecraft/screen/NamedScreenHandlerFactory;)Ljava/util/OptionalInt;", at = @At("RETURN")) + private void fabric_clearStoredScreenHandler(NamedScreenHandlerFactory factory, CallbackInfoReturnable<OptionalInt> info) { + fabric_openedScreenHandler.remove(); + } +} diff --git a/fabric-screen-handler-api-v1/src/main/resources/assets/fabric-screen-handler-api-v1/icon.png b/fabric-screen-handler-api-v1/src/main/resources/assets/fabric-screen-handler-api-v1/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2931efbf610873c0084debb8690902b0103d27fe GIT binary patch literal 1579 zcmbVMTWB0r7@iGm)TAXsYw<=rnU=;v=W=GRbL=!tc4Brl6GO7t2vVJ$IlDV#XU;e? z+r2ymsZdMQqAyaFLLUo;RumtE8Z@?uf_*4nP^4;o6fOFoSkN<j8Kcx&2hN<!|DEr@ zod5ryo}Zi9I&|j{!!TP5d3Ax#ARIRj(!bws|3s%--25Xx!whc=M~pe~^6d;0zuPJ< z1xwm2GKkIVCMjXQX}c87F#9H&u5K*j0F-dWauoLax87!fWh(5!lqPC!4p*&w+rx|P zxuVftHe{2X*bnwK5hbv3po6Aeb9~fP*bXnE>+o1$K?f2nE9_*b5G-l)AV)k5Qhb^- zU{V4ZnTKgnmXdpcB*Kg!W(1hvM2N&RO30x1u~eI9meGQGe@_?PDQq<eTqFpMMuTr8 zc;ZzAD9f@SN`fSD6v6o|C(xUm<L~S<sMt3=%MC2zfRIryk$Rx8)Y7gCwj0qpelJWk zU_w)O1;~q`OC6wTL^!wZ)jG;eL%=m`V<+$_7DiaNN&@0n$=^^%;y)>%q1CiV$8~M7 z?MQ_mOdqCh^a65Sv|ntwSXjV5se1;VK1|Kr8G7TQoQL&*ctt{L{fC<Gn+$Tf@L{sx z-h-B7l7_!$(;ckp0an;h&OwQT=^{*{R1(1qCuWf-cA*+Et#T`Z%AA<tq-;@w6o-;o zy8Q!6v&Pf|{a?YRfy%_Qb?UQa>lG}xPK5<gBvFpkh({Gu>k^yK3%T69N6J=>3jBqc zDNvZsrJ<Zoa}p0b=4u)$IDViz1}>-yOXI^^mWf1cmY^XST)CVzIGjvEPENowmy}ax zvJ8_(Cf#+H-dBlH53`_u-~6BVAMz|(g?jCVdBWNZ(+A}(pFV7>S3QgPiQcMaflkIC z-3Ti|VT~{au*vq0ts9O&m$p&Gl=L6+q6_m$IcVq}o~+Pl{g>1esQp4%wp~|*zk1n` zZ7T6Toc4`y88s}riCP|ZXrJ?FLz@^KTcyqLje<H^TzdE0PhK5b5x2)LE6;s)`N3ZX z2Cv?+vFqVy1|k2_cl$rw7=Ck$@N2wL$?9VEp7Gi35A3;$)g3FR_g;G8x7eAVQRC>y zu95Yz%F&S{<0~f)Iomek?+hQ%MhCu%T^zsg>C_L`1`Br`xNY&))k9yTQb$JC>)w_f zpU<A$%?N8BFlS$R^rq&-d+#&n&pq`bxOC;qliz$4TRVRI>(^tu^Q)y%W~lVz`jz;_ jF?g&s@Y=Qe&c#kW|JbvqK0Y=Rw)4XDoVqsk_>;c_`@;F@ literal 0 HcmV?d00001 diff --git a/fabric-screen-handler-api-v1/src/main/resources/fabric-screen-handler-api-v1.accesswidener b/fabric-screen-handler-api-v1/src/main/resources/fabric-screen-handler-api-v1.accesswidener new file mode 100644 index 000000000..65704847e --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/resources/fabric-screen-handler-api-v1.accesswidener @@ -0,0 +1,8 @@ +accessWidener v1 named +accessible class net/minecraft/screen/ScreenHandlerType$Factory +accessible method net/minecraft/screen/ScreenHandlerType <init> (Lnet/minecraft/screen/ScreenHandlerType$Factory;)V +extendable method net/minecraft/screen/ScreenHandlerType <init> (Lnet/minecraft/screen/ScreenHandlerType$Factory;)V + +accessible class net/minecraft/client/gui/screen/ingame/HandledScreens$Provider +accessible method net/minecraft/client/gui/screen/ingame/HandledScreens register (Lnet/minecraft/screen/ScreenHandlerType;Lnet/minecraft/client/gui/screen/ingame/HandledScreens$Provider;)V +accessible method net/minecraft/client/gui/screen/ingame/HandledScreens getProvider (Lnet/minecraft/screen/ScreenHandlerType;)Lnet/minecraft/client/gui/screen/ingame/HandledScreens$Provider; diff --git a/fabric-screen-handler-api-v1/src/main/resources/fabric-screen-handler-api-v1.mixins.json b/fabric-screen-handler-api-v1/src/main/resources/fabric-screen-handler-api-v1.mixins.json new file mode 100644 index 000000000..69e30be3d --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/resources/fabric-screen-handler-api-v1.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "package": "net.fabricmc.fabric.mixin.screenhandler", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "ServerPlayerEntityMixin" + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/fabric-screen-handler-api-v1/src/main/resources/fabric.mod.json b/fabric-screen-handler-api-v1/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..6539d01a1 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/resources/fabric.mod.json @@ -0,0 +1,31 @@ +{ + "schemaVersion": 1, + "id": "fabric-screen-handler-api-v1", + "name": "Fabric Screen Handler API (v1)", + "version": "${version}", + "environment": "*", + "license": "Apache-2.0", + "icon": "assets/fabric-screen-handler-api-v1/icon.png", + "contact": { + "homepage": "https://fabricmc.net", + "irc": "irc://irc.esper.net:6667/fabric", + "issues": "https://github.com/FabricMC/fabric/issues", + "sources": "https://github.com/FabricMC/fabric" + }, + "authors": [ + "FabricMC" + ], + "depends": { + "fabricloader": ">=0.8.0", + "fabric-api-base": "*", + "fabric-networking-v0": "*" + }, + "entrypoints": { + "client": ["net.fabricmc.fabric.impl.screenhandler.client.ClientNetworking"] + }, + "description": "Hooks and extensions for creating screen handlers.", + "mixins": [ + "fabric-screen-handler-api-v1.mixins.json" + ], + "accessWidener": "fabric-screen-handler-api-v1.accesswidener" +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/ScreenHandlerTest.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/ScreenHandlerTest.java new file mode 100644 index 000000000..c65da0e43 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/ScreenHandlerTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler; + +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemGroup; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; +import net.fabricmc.fabric.test.screenhandler.block.BoxBlock; +import net.fabricmc.fabric.test.screenhandler.block.BoxBlockEntity; +import net.fabricmc.fabric.test.screenhandler.item.BagItem; +import net.fabricmc.fabric.test.screenhandler.item.PositionedBagItem; +import net.fabricmc.fabric.test.screenhandler.screen.BagScreenHandler; +import net.fabricmc.fabric.test.screenhandler.screen.BoxScreenHandler; +import net.fabricmc.fabric.test.screenhandler.screen.PositionedBagScreenHandler; + +public class ScreenHandlerTest implements ModInitializer { + public static final String ID = "fabric-screen-handler-api-v1-testmod"; + + public static final Item BAG = new BagItem(new Item.Settings().group(ItemGroup.TOOLS).maxCount(1)); + public static final Item POSITIONED_BAG = new PositionedBagItem(new Item.Settings().group(ItemGroup.TOOLS).maxCount(1)); + public static final Block BOX = new BoxBlock(AbstractBlock.Settings.copy(Blocks.OAK_WOOD)); + public static final Item BOX_ITEM = new BlockItem(BOX, new Item.Settings().group(ItemGroup.DECORATIONS)); + public static final BlockEntityType<?> BOX_ENTITY = BlockEntityType.Builder.create(BoxBlockEntity::new, BOX).build(null); + public static final ScreenHandlerType<BagScreenHandler> BAG_SCREEN_HANDLER = ScreenHandlerRegistry.registerSimple(id("bag"), BagScreenHandler::new); + public static final ScreenHandlerType<PositionedBagScreenHandler> POSITIONED_BAG_SCREEN_HANDLER = ScreenHandlerRegistry.registerExtended(id("positioned_bag"), PositionedBagScreenHandler::new); + public static final ScreenHandlerType<BoxScreenHandler> BOX_SCREEN_HANDLER = ScreenHandlerRegistry.registerExtended(id("box"), BoxScreenHandler::new); + + public static Identifier id(String path) { + return new Identifier(ID, path); + } + + @Override + public void onInitialize() { + Registry.register(Registry.ITEM, id("bag"), BAG); + Registry.register(Registry.ITEM, id("positioned_bag"), POSITIONED_BAG); + Registry.register(Registry.BLOCK, id("box"), BOX); + Registry.register(Registry.ITEM, id("box"), BOX_ITEM); + Registry.register(Registry.BLOCK_ENTITY_TYPE, id("box"), BOX_ENTITY); + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/block/BoxBlock.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/block/BoxBlock.java new file mode 100644 index 000000000..280ef3ff5 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/block/BoxBlock.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler.block; + +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.block.BlockWithEntity; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.ItemScatterer; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockView; +import net.minecraft.world.World; + +public class BoxBlock extends BlockWithEntity { + public BoxBlock(Settings settings) { + super(settings); + } + + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + if (!world.isClient) { + NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos); + + if (screenHandlerFactory != null) { + player.openHandledScreen(screenHandlerFactory); + } + } + + return ActionResult.SUCCESS; + } + + @Override + public BlockEntity createBlockEntity(BlockView world) { + return new BoxBlockEntity(); + } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.MODEL; + } + + @Override + public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { + if (state.getBlock() != newState.getBlock()) { + BlockEntity be = world.getBlockEntity(pos); + + if (be instanceof Inventory) { + ItemScatterer.spawn(world, pos, (Inventory) be); + world.updateComparators(pos, this); + } + + super.onStateReplaced(state, world, pos, newState, moved); + } + } + + @Override + public int getComparatorOutput(BlockState state, World world, BlockPos pos) { + return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos)); + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/block/BoxBlockEntity.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/block/BoxBlockEntity.java new file mode 100644 index 000000000..2cab02d23 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/block/BoxBlockEntity.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler.block; + +import net.minecraft.block.entity.LootableContainerBlockEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.collection.DefaultedList; + +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; +import net.fabricmc.fabric.test.screenhandler.ScreenHandlerTest; +import net.fabricmc.fabric.test.screenhandler.screen.BoxScreenHandler; + +public class BoxBlockEntity extends LootableContainerBlockEntity implements ExtendedScreenHandlerFactory { + private DefaultedList<ItemStack> items = DefaultedList.ofSize(size(), ItemStack.EMPTY); + + public BoxBlockEntity() { + super(ScreenHandlerTest.BOX_ENTITY); + } + + @Override + protected DefaultedList<ItemStack> getInvStackList() { + return items; + } + + @Override + protected void setInvStackList(DefaultedList<ItemStack> list) { + this.items = list; + } + + @Override + protected Text getContainerName() { + return new TranslatableText(getCachedState().getBlock().getTranslationKey()); + } + + @Override + protected ScreenHandler createScreenHandler(int syncId, PlayerInventory playerInventory) { + return new BoxScreenHandler(syncId, playerInventory, this); + } + + @Override + public int size() { + return 3 * 3; + } + + @Override + public void writeScreenOpeningData(ServerPlayerEntity player, PacketByteBuf buf) { + buf.writeBlockPos(pos); + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/client/ClientScreenHandlerTest.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/client/ClientScreenHandlerTest.java new file mode 100644 index 000000000..6edce1eaa --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/client/ClientScreenHandlerTest.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler.client; + +import net.minecraft.client.gui.screen.ingame.Generic3x3ContainerScreen; + +import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry; +import net.fabricmc.fabric.test.screenhandler.ScreenHandlerTest; +import net.fabricmc.fabric.test.screenhandler.screen.BoxScreenHandler; +import net.fabricmc.fabric.test.screenhandler.screen.PositionedBagScreenHandler; +import net.fabricmc.api.ClientModInitializer; + +public class ClientScreenHandlerTest implements ClientModInitializer { + @Override + public void onInitializeClient() { + ScreenRegistry.register(ScreenHandlerTest.BAG_SCREEN_HANDLER, Generic3x3ContainerScreen::new); + ScreenRegistry.<PositionedBagScreenHandler, PositionedScreen<PositionedBagScreenHandler>>register( + ScreenHandlerTest.POSITIONED_BAG_SCREEN_HANDLER, + PositionedScreen::new + ); + ScreenRegistry.<BoxScreenHandler, PositionedScreen<BoxScreenHandler>>register( + ScreenHandlerTest.BOX_SCREEN_HANDLER, + PositionedScreen::new + ); + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/client/PositionedScreen.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/client/PositionedScreen.java new file mode 100644 index 000000000..631479061 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/client/PositionedScreen.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler.client; + +import com.mojang.blaze3d.systems.RenderSystem; + +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; + +import net.fabricmc.fabric.test.screenhandler.screen.PositionedScreenHandler; + +public class PositionedScreen<T extends ScreenHandler & PositionedScreenHandler> extends HandledScreen<T> { + private static final Identifier TEXTURE = new Identifier("minecraft", "textures/gui/container/dispenser.png"); + + public PositionedScreen(T handler, PlayerInventory inventory, Text title) { + super(handler, inventory, title); + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + renderBackground(matrices); + super.render(matrices, mouseX, mouseY, delta); + drawMouseoverTooltip(matrices, mouseX, mouseY); + } + + @Override + protected void drawForeground(MatrixStack matrices, int mouseX, int mouseY) { + BlockPos pos = handler.getPos(); + Text usedTitle = pos != null ? new LiteralText("(" + pos.toShortString() + ")") : title; + textRenderer.draw(matrices, usedTitle, (float) (backgroundWidth / 2 - textRenderer.getWidth(usedTitle) / 2), 6.0F, 0x404040); + textRenderer.draw(matrices, playerInventory.getDisplayName(), 8.0F, backgroundHeight - 96 + 2, 0x404040); + } + + @Override + protected void drawBackground(MatrixStack matrices, float delta, int mouseX, int mouseY) { + RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + client.getTextureManager().bindTexture(TEXTURE); + int x = (width - backgroundWidth) / 2; + int y = (height - backgroundHeight) / 2; + drawTexture(matrices, x, y, 0, 0, backgroundWidth, backgroundHeight); + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/BagInventory.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/BagInventory.java new file mode 100644 index 000000000..aec664e09 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/BagInventory.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler.item; + +import net.minecraft.inventory.Inventories; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.collection.DefaultedList; + +final class BagInventory implements ImplementedInventory { + private final ItemStack stack; + private final DefaultedList<ItemStack> items = DefaultedList.ofSize(9, ItemStack.EMPTY); + + BagInventory(ItemStack stack) { + this.stack = stack; + CompoundTag tag = stack.getSubTag("Items"); + + if (tag != null) { + Inventories.fromTag(tag, items); + } + } + + @Override + public DefaultedList<ItemStack> getItems() { + return items; + } + + @Override + public void markDirty() { + CompoundTag tag = stack.getOrCreateSubTag("Items"); + Inventories.toTag(tag, items); + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/BagItem.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/BagItem.java new file mode 100644 index 000000000..fd5b78208 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/BagItem.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler.item; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.SimpleNamedScreenHandlerFactory; +import net.minecraft.util.Hand; +import net.minecraft.util.TypedActionResult; +import net.minecraft.world.World; + +import net.fabricmc.fabric.test.screenhandler.screen.BagScreenHandler; + +public class BagItem extends Item { + public BagItem(Settings settings) { + super(settings); + } + + @Override + public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) { + ItemStack stack = user.getStackInHand(hand); + user.openHandledScreen(createScreenHandlerFactory(stack)); + return TypedActionResult.success(stack); + } + + private NamedScreenHandlerFactory createScreenHandlerFactory(ItemStack stack) { + return new SimpleNamedScreenHandlerFactory((syncId, inventory, player) -> { + return new BagScreenHandler(syncId, inventory, new BagInventory(stack)); + }, stack.getName()); + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/ImplementedInventory.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/ImplementedInventory.java new file mode 100644 index 000000000..a84ce895d --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/ImplementedInventory.java @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler.item; + +import java.util.List; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventories; +import net.minecraft.inventory.Inventory; +import net.minecraft.inventory.SidedInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.math.Direction; + +/** + * A simple {@code SidedInventory} implementation with only default methods + an item list getter. + * + * <h2>Reading and writing to tags</h2> + * Use {@link Inventories#fromTag(CompoundTag, DefaultedList)} and {@link Inventories#toTag(CompoundTag, DefaultedList)} + * on {@linkplain #getItems() the item list}. + * + * @author Juuz + */ +@FunctionalInterface +public interface ImplementedInventory extends SidedInventory { + /** + * Gets the item list of this inventory. + * Must return the same instance every time it's called. + * + * @return the item list + */ + DefaultedList<ItemStack> getItems(); + + // Creation + + /** + * Creates an inventory from the item list. + * + * @param items the item list + * @return a new inventory + */ + static ImplementedInventory of(DefaultedList<ItemStack> items) { + return () -> items; + } + + /** + * Creates a new inventory with the size. + * + * @param size the inventory size + * @return a new inventory + */ + static ImplementedInventory ofSize(int size) { + return of(DefaultedList.ofSize(size, ItemStack.EMPTY)); + } + + // SidedInventory + + /** + * Gets the available slots to automation on the side. + * + * <p>The default implementation returns an array of all slots. + * + * @param side the side + * @return the available slots + */ + @Override + default int[] getAvailableSlots(Direction side) { + int[] result = new int[getItems().size()]; + + for (int i = 0; i < result.length; i++) { + result[i] = i; + } + + return result; + } + + /** + * Returns true if the stack can be inserted in the slot at the side. + * + * <p>The default implementation returns true. + * + * @param slot the slot + * @param stack the stack + * @param side the side + * @return true if the stack can be inserted + */ + @Override + default boolean canInsert(int slot, ItemStack stack, Direction side) { + return true; + } + + /** + * Returns true if the stack can be extracted from the slot at the side. + * + * <p>The default implementation returns true. + * + * @param slot the slot + * @param stack the stack + * @param side the side + * @return true if the stack can be extracted + */ + @Override + default boolean canExtract(int slot, ItemStack stack, Direction side) { + return true; + } + + // Inventory + + /** + * Returns the inventory size. + * + * <p>The default implementation returns the size of {@link #getItems()}. + * + * @return the inventory size + */ + @Override + default int size() { + return getItems().size(); + } + + /** + * @return true if this inventory has only empty stacks, false otherwise + */ + @Override + default boolean isEmpty() { + for (int i = 0; i < size(); i++) { + ItemStack stack = getStack(i); + + if (!stack.isEmpty()) { + return false; + } + } + + return true; + } + + /** + * Gets the item in the slot. + * + * @param slot the slot + * @return the item in the slot + */ + @Override + default ItemStack getStack(int slot) { + return getItems().get(slot); + } + + /** + * Takes a stack of the size from the slot. + * + * <p>(default implementation) If there are less items in the slot than what are requested, + * takes all items in that slot. + * + * @param slot the slot + * @param count the item count + * @return a stack + */ + @Override + default ItemStack removeStack(int slot, int count) { + ItemStack result = Inventories.splitStack(getItems(), slot, count); + + if (!result.isEmpty()) { + markDirty(); + } + + return result; + } + + /** + * Removes the current stack in the {@code slot} and returns it. + * + * <p>The default implementation uses {@link Inventories#removeStack(List, int)} + * + * @param slot the slot + * @return the removed stack + */ + @Override + default ItemStack removeStack(int slot) { + return Inventories.removeStack(getItems(), slot); + } + + /** + * Replaces the current stack in the {@code slot} with the provided stack. + * + * <p>If the stack is too big for this inventory ({@link Inventory#getMaxCountPerStack()} ()}), + * it gets resized to this inventory's maximum amount. + * + * @param slot the slot + * @param stack the stack + */ + @Override + default void setStack(int slot, ItemStack stack) { + getItems().set(slot, stack); + + if (stack.getCount() > getMaxCountPerStack()) { + stack.setCount(getMaxCountPerStack()); + } + } + + /** + * Clears {@linkplain #getItems() the item list}}. + */ + @Override + default void clear() { + getItems().clear(); + } + + @Override + default void markDirty() { + // Override if you want behavior. + } + + @Override + default boolean canPlayerUse(PlayerEntity player) { + return true; + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/PositionedBagItem.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/PositionedBagItem.java new file mode 100644 index 000000000..13373b385 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/item/PositionedBagItem.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler.item; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUsageContext; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.TypedActionResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; +import net.fabricmc.fabric.test.screenhandler.screen.PositionedBagScreenHandler; + +public class PositionedBagItem extends BagItem { + public PositionedBagItem(Settings settings) { + super(settings); + } + + @Override + public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) { + ItemStack stack = user.getStackInHand(hand); + user.openHandledScreen(createScreenHandlerFactory(stack, null)); + return TypedActionResult.success(stack); + } + + @Override + public ActionResult useOnBlock(ItemUsageContext context) { + PlayerEntity user = context.getPlayer(); + ItemStack stack = user.getStackInHand(context.getHand()); + BlockPos pos = context.getBlockPos(); + user.openHandledScreen(createScreenHandlerFactory(stack, pos)); + return ActionResult.SUCCESS; + } + + private ExtendedScreenHandlerFactory createScreenHandlerFactory(ItemStack stack, BlockPos pos) { + return new ExtendedScreenHandlerFactory() { + @Override + public ScreenHandler createMenu(int syncId, PlayerInventory inventory, PlayerEntity player) { + return new PositionedBagScreenHandler(syncId, inventory, new BagInventory(stack), pos); + } + + @Override + public Text getDisplayName() { + return stack.getName(); + } + + @Override + public void writeScreenOpeningData(ServerPlayerEntity player, PacketByteBuf buf) { + buf.writeBoolean(pos != null); + buf.writeBlockPos(pos != null ? pos : BlockPos.ORIGIN); + } + }; + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/BagScreenHandler.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/BagScreenHandler.java new file mode 100644 index 000000000..a1eac6781 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/BagScreenHandler.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler.screen; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.Inventory; +import net.minecraft.inventory.SimpleInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.Generic3x3ContainerScreenHandler; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.screen.slot.SlotActionType; + +import net.fabricmc.fabric.test.screenhandler.ScreenHandlerTest; +import net.fabricmc.fabric.test.screenhandler.item.BagItem; + +public class BagScreenHandler extends Generic3x3ContainerScreenHandler { + private final ScreenHandlerType<?> type; + + public BagScreenHandler(int syncId, PlayerInventory playerInventory) { + this(syncId, playerInventory, new SimpleInventory(9)); + } + + public BagScreenHandler(int syncId, PlayerInventory playerInventory, Inventory inventory) { + this(ScreenHandlerTest.BAG_SCREEN_HANDLER, syncId, playerInventory, inventory); + } + + protected BagScreenHandler(ScreenHandlerType<?> type, int syncId, PlayerInventory playerInventory, Inventory inventory) { + super(syncId, playerInventory, inventory); + this.type = type; + } + + @Override + public ScreenHandlerType<?> getType() { + return type; + } + + @Override + public ItemStack onSlotClick(int slotId, int clickData, SlotActionType actionType, PlayerEntity playerEntity) { + if (slotId >= 0) { // slotId < 0 are used for networking internals + ItemStack stack = getSlot(slotId).getStack(); + + if (stack.getItem() instanceof BagItem) { + // Prevent moving bags around + return stack; + } + } + + return super.onSlotClick(slotId, clickData, actionType, playerEntity); + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/BoxScreenHandler.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/BoxScreenHandler.java new file mode 100644 index 000000000..6d3dc7e13 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/BoxScreenHandler.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler.screen; + +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.Inventory; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.Generic3x3ContainerScreenHandler; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.util.math.BlockPos; + +import net.fabricmc.fabric.test.screenhandler.ScreenHandlerTest; + +public class BoxScreenHandler extends Generic3x3ContainerScreenHandler implements PositionedScreenHandler { + private final BlockPos pos; + + public BoxScreenHandler(int syncId, PlayerInventory playerInventory, PacketByteBuf buf) { + super(syncId, playerInventory); + this.pos = buf.readBlockPos(); + } + + public BoxScreenHandler(int syncId, PlayerInventory playerInventory, Inventory inventory) { + super(syncId, playerInventory, inventory); + this.pos = BlockPos.ORIGIN; + } + + @Override + public BlockPos getPos() { + return pos; + } + + @Override + public ScreenHandlerType<?> getType() { + return ScreenHandlerTest.BOX_SCREEN_HANDLER; + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/PositionedBagScreenHandler.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/PositionedBagScreenHandler.java new file mode 100644 index 000000000..2c7102f94 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/PositionedBagScreenHandler.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler.screen; + +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.Inventory; +import net.minecraft.inventory.SimpleInventory; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.util.math.BlockPos; + +import net.fabricmc.fabric.test.screenhandler.ScreenHandlerTest; + +public class PositionedBagScreenHandler extends BagScreenHandler implements PositionedScreenHandler { + private final BlockPos pos; + + public PositionedBagScreenHandler(int syncId, PlayerInventory playerInventory, PacketByteBuf buf) { + this(syncId, playerInventory, new SimpleInventory(9), readOptionalPos(buf)); + } + + private static BlockPos readOptionalPos(PacketByteBuf buf) { + boolean hasPos = buf.readBoolean(); + BlockPos pos = buf.readBlockPos(); + return hasPos ? pos : null; + } + + public PositionedBagScreenHandler(int syncId, PlayerInventory playerInventory, Inventory inventory, BlockPos pos) { + super(ScreenHandlerTest.POSITIONED_BAG_SCREEN_HANDLER, syncId, playerInventory, inventory); + this.pos = pos; + } + + @Override + public BlockPos getPos() { + return pos; + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/PositionedScreenHandler.java b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/PositionedScreenHandler.java new file mode 100644 index 000000000..9432db94a --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/java/net/fabricmc/fabric/test/screenhandler/screen/PositionedScreenHandler.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.screenhandler.screen; + +import net.minecraft.util.math.BlockPos; + +public interface PositionedScreenHandler { + BlockPos getPos(); +} diff --git a/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/blockstates/box.json b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/blockstates/box.json new file mode 100644 index 000000000..861b9b4f8 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/blockstates/box.json @@ -0,0 +1,5 @@ +{ + "variants": { + "": { "model": "fabric-screen-handler-api-v1-testmod:block/box" } + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/lang/en_us.json b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/lang/en_us.json new file mode 100644 index 000000000..f74eb07c3 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/lang/en_us.json @@ -0,0 +1,5 @@ +{ + "block.fabric-screen-handler-api-v1-testmod.box": "Box", + "item.fabric-screen-handler-api-v1-testmod.bag": "Bag", + "item.fabric-screen-handler-api-v1-testmod.positioned_bag": "Positioned Bag" +} diff --git a/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/block/box.json b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/block/box.json new file mode 100644 index 000000000..7307a9c37 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/block/box.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "fabric-screen-handler-api-v1-testmod:block/box" + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/item/bag.json b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/item/bag.json new file mode 100644 index 000000000..e9479a5ec --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/item/bag.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "fabric-screen-handler-api-v1-testmod:item/bag" + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/item/box.json b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/item/box.json new file mode 100644 index 000000000..ff03794e4 --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/item/box.json @@ -0,0 +1,3 @@ +{ + "parent": "fabric-screen-handler-api-v1-testmod:block/box" +} diff --git a/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/item/positioned_bag.json b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/item/positioned_bag.json new file mode 100644 index 000000000..2b7938cbd --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/models/item/positioned_bag.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "fabric-screen-handler-api-v1-testmod:item/positioned_bag" + } +} diff --git a/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/textures/block/box.png b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/textures/block/box.png new file mode 100644 index 0000000000000000000000000000000000000000..b57b82765819e20ba8d615522c4a1247f6ba1859 GIT binary patch literal 616 zcmV-u0+;=XP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0004mX+uL$Nkc;* zaB^>EX>4Tx04R}tkv&MmKpe$iKcpfR5i>|}$WWau6curlDi*;)X)CnqU~=gfG%+M8 zE{=k0!NHHks)LKOt`4q(Aou~|<mja6A|?JWDYS_3;J6>}?mh0_0sdx<sb(+^sG4PD zk_j<iSP?_72tvRh;)qDh)Kl4o96ZO@J$!t<i}5V)bAOJ0rD!t1Clb#x-LQz)iKjO$ zo%24iz$%hLd`>)W&;^Mfxh}i>#<}dUpJxh2E;C0g5R2t5mb;i$43&6_II5@`<@@t4 zE1b7DtF=07-;=*ET-27cT&FpLBo>iE8X{!WQAG_FVzg?cn8?t6!oweN{AqH@<f?*^ zV;&n&Avu2VKlt6PS(==1lfnt0=f$=^MuE^S&}!KB_pxoaPJqBOaHVzp8%<#5lk`SM ziyi?3+rY(jN0aw}%N=0&NtX=CkpeXRr4sOdM&DEbhHinrRkyeHK29Hi9CfvH0~{Oz zV`a)-^LTe}cW?imY4`U7sgrWO0G?El00006VoOIv0PX<p0Pc!u@Du<5010qNS#tmY zE+YT{E+YYWr9XB6000McNliru<OCEEG6r%Dtv>(&02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{002NqL_t(I%VV6L>F}R{OmOG<M+PQJG(Ug;m4O9WfE4ij z{Z|GC1_tt700W~2j2bXF3}8Xd7-YGC63q+@3=9AqJR1{`WoKsq0000<MNUMnLSTYw C`1=b0 literal 0 HcmV?d00001 diff --git a/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/textures/item/bag.png b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/textures/item/bag.png new file mode 100644 index 0000000000000000000000000000000000000000..1a474f87a2c7f36e59fa4a2bf4cc9c9c18c9fe34 GIT binary patch literal 837 zcmV-L1G@Z)P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0004mX+uL$Nkc;* zaB^>EX>4Tx04R}tkv&MmKpe$iQ>CI62Ro=ZWT;Lph>AE$6^me@v=v%)FuC*#nlvOS zE{=k0!NHHks)LKOt`4q(Aou~|<mja6A|?JWDYS_3;J6>}?mh0_0Yam~RI_UWP&La) z#baVNw<-o+;m0ug5J5m<rk+SIX5cx#?&0I>U6f~epZjz4D|wRvK9P8i>4rtTK|Hf* z>74h8L#!kz#OK5jgDyz?$aUG}H_k<e1)do)GO2mu5V2V7V7Y@?$xw->iNlJjQNECM zS>e3JS*_Gq>z@3D!MwJT<~q$$#Ib|~k`N)IhB7L!5T#Wk#YBqsV;=qy$DbsZOs+B* zITlcb3d!+<|H1EW&BD~An-q)z-7mKNF$M&7fo9#dzmILZc>?&Kfh(=;uQq_$Ptxmc zEqnwFYy%h9ZB5<-E_Z;TCtWfmNAlAY3I*W(jJ_!c4Bi60Yi@6?eVjf38R}~J1~@nb z#*37_?(y!P&ffk#)9UXBYgBTi5QZ(M00006VoOIv0Nwz&02c5cV7>qV010qNS#tmY zE+YT{E+YYWr9XB6000McNliru<O3NCFEafu7ySSL02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00A9IL_t(I%hi&<N&`U<#($R~F&B|EBDTJRji60X#A^h7 zgEZIJ`waHhzQGk<W5h<V^&KRL|9Z)VTZgq+Z!bCTLcq#_E%uw8Z@&3<;NM3uce{98 zuIhZdfdG(UV(Imu+lA>AjDdFBB_|W~>NIFpP>{r_)j<TRKY$<)cj)C&uy}--cp7ck zwbd413gHU$ciwB?wrUj&6T9{K!TR%<&DSygmpA0>#x6x5!^G<0G32=eR3XpNy#pjp z?Lq>HQ>)Pli1^tFL!Z|{<V>#fK;qQu?ml!nuB(VUg^~WDAonA0XsI9!U2!41S_p2e z3SJUqS=n)xtRRFEGp7C<y@3_UUXciLdp);I&6{Y9Q<7z6(wJYH_~-Zr<Na%FrhzwJ P00000NkvXXu0mjf<yCps literal 0 HcmV?d00001 diff --git a/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/textures/item/positioned_bag.png b/fabric-screen-handler-api-v1/src/testmod/resources/assets/fabric-screen-handler-api-v1-testmod/textures/item/positioned_bag.png new file mode 100644 index 0000000000000000000000000000000000000000..542e1607fb0461fb097de35790c833d935eb95cd GIT binary patch literal 2064 zcmV+r2=DiaP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV000E$dQ@0+Qek%> zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|aw&f@e{AU%t1SA0x%fSri^bTtI9SnB9Id68= zXPI*i1|bCsN%nR9um2ABA6!g{U5IKar{r;k95NRS%<rqLJNdBg=fU5Dck}L9U`z>m z*^idae8)UPp3i(edJ5*_8%4RFh3ox7If~ehf!pFSB(x3qb`+JPNcdO|`}sPSQ#O5j zgtO0&v%cJbpPRQJ$|)w&fO}xCnli@5J}CUw;@Zf0?u*y0=>4<1MH!g53yEKM-Y8}N z3Vwn+ON1Or#yFy%^R&@APzDGX=i^)UKVILVcW>bz+TYRojOd&B!?wFwNPHIL154@Y zznrIdEBZj|;_i**WRK-{^N`oKM|L-T^EXDbG5S7T2?<9|=TP@i)(CRf^w!#y(9|b~ zAT$hS%V>tQsEDQJtH01HWnxe{C{Uw9gZk<#RX_~fS<y3B$Fe33WMr<BP6@NoU<J)h z45U|tgkY8*EVRt#Wv-I>=6oZFGC>)l=l^f+Rl%`xg2>zBE8yZ8bwJ?>^v@1rV1&kT zYFrM!+sAA2Dqt`!HyaLE{N=WaE7Gsvl0~#YFrwc{OxlhDxCo{rz>t6epGYDlAW~)} zf+GzC6+mYRe1QRqksCmA5J?~hISkv_qqIah@}5R9l;DtjNfg{55kXc65%HtJ5JM$O z3^B$OHCoKEBuO*FQqnZ5YEjXkQIo2g)2zkBf<;TFW|pmF&Vs5NGx9N8&bbsAEzn%B zyFj3ni!Zst6|Z#ZWmk4rsR*AMYOJYhwVG>b+@v9oTWZ>@<yJa%gi;SZ_SCgo&%F$U z+K>@O9BHT<Hu5MBYlqfP?GIR^!x}H9rl3BoVOI54L9?91$r%{qKp<Sf8W=-hPtLqi z2t1jaocYYiipT&NCpnEKV_-0J;yCEx?l9-L{4=~cwZ$9%UFO`R?nUN4^Y#^MZN8rC zVr-}3bgCC*AJ)4Swld$A-}dfz0<ZS}D*97JBlS7p3v@~GYmC>_E4}+c0FjlJg;qzS z@G~s;d0`}4nsOdKgeycs(jc^X4k#E(=vhy)_oV2D+jDpct_>*2aSbAJw<EOYn5B>K zJ2$!C35>Muo8VR6^FC`&QjLyCS{NKaphV1}x2{Ldq(!M|KP6<=1NhtC{Z8ORuPw<M zYDXcuO1w7B;>hZDlaVZB5np*-#$F#WNPUTa_i~`jcxZN?7Oy=NnPs@5gcWfQfty@- z_vUd{zjcU^`vnU3kpvZpzOdx%Z$LV}s6`FmM+Zs0`A(a|3fk99z+aZV6jb6bjJcx} zF9x&?i|!mKzSdK(dUjX;4wCCPvA@E7X9eo*32gF**c_gayYV9kcIdexElbsN3~k;1 z3>3u;%5}{_c5x5E&Z*^b%P&W5oI>9iLiX<xgb!N0XEscHgQnLqM7Mg1?6hmquov)6 zkke<MJ(hHP$nqEPZq^=mKF7?pZ%&%mG9%@L#b`c!TWUYligQ8~0Hy6Uz<c0)jM5Fy zO?;nR{K*wRMB+J;`<~=Gx4O5tAk)|R;{ff6yLJjn4O@onj!nt7>q@ba0{)Pk%pO_} zYWI3cyZr5LV~$Hx3ALsZN1*GT#QGlD^|eE%&%Z)5jk!N6v_JI!j3OPwHT=7F{{!@g z?58iNo8tfg0fcEoLr_UWLm+T+Z)Rz1WdHzpoPCi!NW(xJ#a~lJk%~w=s5oS(P8N!a zI7$_ZV4<`XT6HkF^b49aBq=VAf@{ISkHxBki?gl{u7V)=0pjH7r060g{x2!Ci1FaK zAMfrx?%n}Hqrz0PD+;KZWu)RUF`HWzdtTwkFa{AtP-3Q@NH1pKIlk`U<Lh07XL+Cd zbMz~DlL0=Fc#i3YMZ7^gvuWv^_lZNSBq_w_#1jTxkob}7vdeFriw+AsGh}2^^TZ)y zvDm?K2eXo)5>FF{6;-2rA?vcjd5g1Jsj=2Q`3nPiZ6(chnxlwg2?-=2LPiZ`RA3=O zt44~66z#`6{3DJ(NiLaOWiWCqpb8a|;|KqP-`$#psYy2}5CghjZ2Myj=-CCDb=&?v zw(aH#;C}|Lw6?$60A@c)ueY`E5iqa~TwJ#`c@MbU0fwG*$&eh$Pg5uqfcG={rW_Ew z1^U+9-dg)OeE>4l)$$E+a0rYSDSO@H-MyW?{d=a>-w&cPa=Lfw10(<d00v@9M??Ss z00000`9r&Z00009a7bBm001r{001r{0eGc9b^rhX2XskIMF->q84)uAEHPZF0000P zbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAV*0}P*;Ht7XSbN_DMuRR5;7kk}+<=KoCXW zu7hxdA|x#3C?G@;iAzvYSfb=G6s|~-k{i&{AaM#>8d5vL>`;s?udxl0Qsq~>vj5Ec zvjhKLrgGcNf9INgwG;qY#X@MHYvIR1Ch(H~mI^FCO*=uMBo-zSIMKT`aQKGB+B}Zn z>9~EDx1J@t!fO}$<CA$l13$(zf=f=&F|cnYu#M&q&wNGCqk%?ySRlze2b9@EujwSx z28|JtSQriz*NK{goWNH=B~D2YS~VBgPU^F{NUdO5Aaz>ZiDGv=bmt8dbT=Abp%~yj uazSJb?9P>CYTv|6G*;@$ZyB{s{IhPMcvCBc18A}U0000<MNUMnLSTa3bIfP} literal 0 HcmV?d00001 diff --git a/fabric-screen-handler-api-v1/src/testmod/resources/data/fabric-screen-handler-api-v1-testmod/loot_tables/blocks/box.json b/fabric-screen-handler-api-v1/src/testmod/resources/data/fabric-screen-handler-api-v1-testmod/loot_tables/blocks/box.json new file mode 100644 index 000000000..f8a3e07dd --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/resources/data/fabric-screen-handler-api-v1-testmod/loot_tables/blocks/box.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "fabric-screen-handler-api-v1-testmod:box" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} diff --git a/fabric-screen-handler-api-v1/src/testmod/resources/fabric.mod.json b/fabric-screen-handler-api-v1/src/testmod/resources/fabric.mod.json new file mode 100644 index 000000000..f3d6f8bad --- /dev/null +++ b/fabric-screen-handler-api-v1/src/testmod/resources/fabric.mod.json @@ -0,0 +1,20 @@ +{ + "schemaVersion": 1, + "id": "fabric-screen-handler-api-v1-testmod", + "name": "Fabric Screen Handler API (v1) Test Mod", + "version": "1.0.0", + "environment": "*", + "license": "Apache-2.0", + "depends": { + "fabric-resource-loader-v0": "*", + "fabric-screen-handler-api-v1": "*" + }, + "entrypoints": { + "main": [ + "net.fabricmc.fabric.test.screenhandler.ScreenHandlerTest" + ], + "client": [ + "net.fabricmc.fabric.test.screenhandler.client.ClientScreenHandlerTest" + ] + } +} diff --git a/settings.gradle b/settings.gradle index b6faf41d5..4dcd34a31 100644 --- a/settings.gradle +++ b/settings.gradle @@ -44,6 +44,7 @@ include 'fabric-rendering-v1' include 'fabric-rendering-data-attachment-v1' include 'fabric-rendering-fluids-v1' include 'fabric-resource-loader-v0' +include 'fabric-screen-handler-api-v1' include 'fabric-tag-extensions-v0' include 'fabric-textures-v0' include 'fabric-tool-attribute-api-v1'