From 1f6558e8fb240364d2de812f585e8d0f96faf18c Mon Sep 17 00:00:00 2001 From: Juuxel <6596629+Juuxel@users.noreply.github.com> Date: Sun, 10 Apr 2022 18:26:54 +0300 Subject: [PATCH] Expose extended screen handler type creation in SH API (#2104) * Expose extended screen handler type creation in SH API * Update SHAPI test mod to use non-deprecated API --- .../v1/ExtendedScreenHandlerFactory.java | 3 +- .../v1/ExtendedScreenHandlerType.java | 119 ++++++++++++++++++ .../v1/ScreenHandlerRegistry.java | 36 +++--- .../api/screenhandler/v1/package-info.java | 25 +++- .../ExtendedScreenHandlerType.java | 46 ------- .../client/ClientNetworking.java | 2 +- .../ServerPlayerEntityMixin.java | 2 +- .../test/screenhandler/ScreenHandlerTest.java | 11 +- .../client/ClientScreenHandlerTest.java | 8 +- 9 files changed, 175 insertions(+), 77 deletions(-) create mode 100644 fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ExtendedScreenHandlerType.java delete mode 100644 fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/ExtendedScreenHandlerType.java 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 index e1fb76878..4ffb7cbc2 100644 --- 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 @@ -22,8 +22,9 @@ import net.minecraft.server.network.ServerPlayerEntity; /** * An extension of {@code NamedScreenHandlerFactory} that can write additional data to a screen opening packet. + * This is used for {@linkplain ExtendedScreenHandlerType extended screen handlers}. * - * @see ScreenHandlerRegistry#registerExtended(net.minecraft.util.Identifier, ScreenHandlerRegistry.ExtendedClientHandlerFactory) + * @see ExtendedScreenHandlerType usage examples */ public interface ExtendedScreenHandlerFactory extends NamedScreenHandlerFactory { /** diff --git a/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ExtendedScreenHandlerType.java b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ExtendedScreenHandlerType.java new file mode 100644 index 000000000..2f4032b1c --- /dev/null +++ b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ExtendedScreenHandlerType.java @@ -0,0 +1,119 @@ +/* + * 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 java.util.Objects; + +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.ScreenHandlerType; + +/** + * A {@link ScreenHandlerType} for an extended screen handler that + * synchronizes additional data to the client when it is opened. + * + * <p>Extended screen handlers can be opened using + * {@link net.minecraft.entity.player.PlayerEntity#openHandledScreen(NamedScreenHandlerFactory) + * PlayerEntity.openHandledScreen} with an + * {@link ExtendedScreenHandlerFactory}. + * + * <h2>Example</h2> + * <pre> + * {@code + * // Creating and registering the type + * public static final ExtendedScreenHandlerType<OvenScreenHandler> OVEN = + * new ExtendedScreenHandlerType((syncId, inventory, buf) -> ...); + * Registry.register(Registry.SCREEN_HANDLER, new Identifier(...), OVEN); + * + * // Note: remember to also register the screen using vanilla's HandledScreens! + * + * // Screen handler class + * public class OvenScreenHandler extends ScreenHandler { + * public OvenScreenHandler(int syncId) { + * super(MyScreenHandlers.OVEN, syncId); + * } + * } + * + * // Opening the extended screen handler + * var factory = new ExtendedScreenHandlerFactory() { + * ... + * }; + * player.openHandlerScreen(factory); // only works on ServerPlayerEntity instances + * } + * </pre> + * + * @param <T> the type of screen handler created by this type + */ +public class ExtendedScreenHandlerType<T extends ScreenHandler> extends ScreenHandlerType<T> { + private final ExtendedFactory<T> factory; + + /** + * Constructs an extended screen handler type. + * + * @param factory the screen handler factory used for {@link #create(int, PlayerInventory, PacketByteBuf)} + */ + public ExtendedScreenHandlerType(ExtendedFactory<T> factory) { + super(null); + this.factory = Objects.requireNonNull(factory, "screen handler factory cannot be null"); + } + + /** + * @throws UnsupportedOperationException always; use {@link #create(int, PlayerInventory, PacketByteBuf)} + * @deprecated Use {@link #create(int, PlayerInventory, PacketByteBuf)} instead. + */ + @Deprecated + @Override + public final T create(int syncId, PlayerInventory inventory) { + throw new UnsupportedOperationException("Use ExtendedScreenHandlerType.create(int, PlayerInventory, PacketByteBuf)!"); + } + + /** + * Creates a new screen handler using the extra opening data. + * + * @param syncId the sync ID + * @param inventory the player inventory + * @param buf the buffer containing the synced opening data + * @return the created screen handler + */ + public T create(int syncId, PlayerInventory inventory, PacketByteBuf buf) { + return factory.create(syncId, inventory, buf); + } + + /** + * A factory for creating screen handler instances from + * additional opening data. + * This is primarily used on the client, but can be called on the + * server too. + * + * @param <T> the type of screen handlers created + * @see #create(int, PlayerInventory, PacketByteBuf) + */ + @FunctionalInterface + public interface ExtendedFactory<T extends ScreenHandler> { + /** + * Creates a new 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 + */ + 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/ScreenHandlerRegistry.java b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/screenhandler/v1/ScreenHandlerRegistry.java index 8e7c226c6..6b723a990 100644 --- 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 @@ -17,16 +17,11 @@ 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}. * @@ -66,7 +61,14 @@ import net.fabricmc.fabric.impl.screenhandler.ExtendedScreenHandlerType; * </pre> * * @see net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry registering screens for screen handlers + * @deprecated Replaced by <ul> + * <li>Creating simple screen handler types directly with {@link ScreenHandlerType} + * using an access widener in Fabric Transitive Access Wideners (v1)</li> + * <li>Creating extended screen handler types with {@link ExtendedScreenHandlerType}</li> + * <li>Registering using {@link Registry#SCREEN_HANDLER} directly</li> + * </ul> */ +@Deprecated public final class ScreenHandlerRegistry { private ScreenHandlerRegistry() { } @@ -98,14 +100,18 @@ public final class ScreenHandlerRegistry { * @param factory the client-sided screen handler factory * @param <T> the screen handler type * @return the created type object + * @deprecated Replaced with creating an {@link ExtendedScreenHandlerType} manually and registering it + * in the vanilla registry. */ + @Deprecated 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. + * A factory for screen handler instances. + * This is typically used on the client but is also available on the server. * * @param <T> the screen handler type * @deprecated Replaced by access widener for {@link ScreenHandlerType.Factory} in Fabric Transitive Access Wideners (v1). @@ -119,27 +125,19 @@ public final class ScreenHandlerRegistry { * @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 + * A factory for screen handler instances * with additional screen opening data. + * This is typically used on the client but is also available on the server. * * @param <T> the screen handler type * @see ExtendedScreenHandlerFactory + * @deprecated Replaced with {@link ExtendedScreenHandlerType.ExtendedFactory}. */ - 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); + @Deprecated + public interface ExtendedClientHandlerFactory<T extends ScreenHandler> extends ExtendedScreenHandlerType.ExtendedFactory<T> { } } 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 index 3d1ff2e3d..3e523eeb6 100644 --- 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 @@ -15,6 +15,29 @@ */ /** - * The Fabric screen handler API for creating screen handlers. + * The Fabric screen handler API for creating screen handlers and screen handler types. + * + * <p>Screen handlers types are used to synchronize {@linkplain net.minecraft.screen.ScreenHandler screen handlers} + * between the server and the client. Their main job is to create screen handler instances on 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. + * You can create simple screen handlers using vanilla's {@link net.minecraft.screen.ScreenHandlerType}. + * + * <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. + * You can create extended screen handlers using + * {@link net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType}. + * + * <h2>Opening screen handlers</h2> + * Screen handlers can be opened using + * {@link net.minecraft.entity.player.PlayerEntity#openHandledScreen(net.minecraft.screen.NamedScreenHandlerFactory)}. + * Note that calling it on the logical client does nothing. To open an extended screen handler, the factory passed in + * should be an {@link net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory}. */ 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 deleted file mode 100644 index 951338f03..000000000 --- a/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/ExtendedScreenHandlerType.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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/client/ClientNetworking.java b/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler/client/ClientNetworking.java index 953fa80bc..039c8952c 100644 --- 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 @@ -34,7 +34,7 @@ import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.impl.screenhandler.ExtendedScreenHandlerType; +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType; import net.fabricmc.fabric.impl.screenhandler.Networking; @Environment(EnvType.CLIENT) 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 index adcc34e2c..b4eb4795e 100644 --- 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 @@ -36,7 +36,7 @@ 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.api.screenhandler.v1.ExtendedScreenHandlerType; import net.fabricmc.fabric.impl.screenhandler.Networking; @Mixin(ServerPlayerEntity.class) 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 index 2a5967c3b..ad5769f75 100644 --- 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 @@ -28,7 +28,7 @@ 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.api.screenhandler.v1.ExtendedScreenHandlerType; import net.fabricmc.fabric.test.screenhandler.block.BoxBlock; import net.fabricmc.fabric.test.screenhandler.block.BoxBlockEntity; import net.fabricmc.fabric.test.screenhandler.item.BagItem; @@ -46,9 +46,9 @@ public class ScreenHandlerTest implements ModInitializer { 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<BoxBlockEntity> BOX_ENTITY = FabricBlockEntityTypeBuilder.create(BoxBlockEntity::new, BOX).build(); - 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 final ScreenHandlerType<BagScreenHandler> BAG_SCREEN_HANDLER = new ScreenHandlerType<>(BagScreenHandler::new); + public static final ScreenHandlerType<PositionedBagScreenHandler> POSITIONED_BAG_SCREEN_HANDLER = new ExtendedScreenHandlerType<>(PositionedBagScreenHandler::new); + public static final ScreenHandlerType<BoxScreenHandler> BOX_SCREEN_HANDLER = new ExtendedScreenHandlerType<>(BoxScreenHandler::new); public static Identifier id(String path) { return new Identifier(ID, path); @@ -61,5 +61,8 @@ public class ScreenHandlerTest implements ModInitializer { 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); + Registry.register(Registry.SCREEN_HANDLER, id("bag"), BAG_SCREEN_HANDLER); + Registry.register(Registry.SCREEN_HANDLER, id("positioned_bag"), POSITIONED_BAG_SCREEN_HANDLER); + Registry.register(Registry.SCREEN_HANDLER, id("box"), BOX_SCREEN_HANDLER); } } 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 index 934978d4b..f5bd4e468 100644 --- 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 @@ -17,16 +17,16 @@ package net.fabricmc.fabric.test.screenhandler.client; import net.minecraft.client.gui.screen.ingame.Generic3x3ContainerScreen; +import net.minecraft.client.gui.screen.ingame.HandledScreens; -import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry; import net.fabricmc.fabric.test.screenhandler.ScreenHandlerTest; import net.fabricmc.api.ClientModInitializer; public class ClientScreenHandlerTest implements ClientModInitializer { @Override public void onInitializeClient() { - ScreenRegistry.register(ScreenHandlerTest.BAG_SCREEN_HANDLER, Generic3x3ContainerScreen::new); - ScreenRegistry.register(ScreenHandlerTest.POSITIONED_BAG_SCREEN_HANDLER, PositionedScreen::new); - ScreenRegistry.register(ScreenHandlerTest.BOX_SCREEN_HANDLER, PositionedScreen::new); + HandledScreens.register(ScreenHandlerTest.BAG_SCREEN_HANDLER, Generic3x3ContainerScreen::new); + HandledScreens.register(ScreenHandlerTest.POSITIONED_BAG_SCREEN_HANDLER, PositionedScreen::new); + HandledScreens.register(ScreenHandlerTest.BOX_SCREEN_HANDLER, PositionedScreen::new); } }