From 1a17fa6129df31593e91b2cb41c12698849306d5 Mon Sep 17 00:00:00 2001 From: William Bradford Larcombe Date: Mon, 19 Jul 2021 19:54:42 +0000 Subject: [PATCH] Fix FakePlayers having null `connection` and add FakePlayer test mod (#7733) --- .../common/util/FakePlayer.java | 77 ++++++++++++++++++- .../debug/misc/FakePlayerTest.java | 69 +++++++++++++++++ src/test/resources/META-INF/mods.toml | 2 + 3 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 src/test/java/net/minecraftforge/debug/misc/FakePlayerTest.java diff --git a/src/main/java/net/minecraftforge/common/util/FakePlayer.java b/src/main/java/net/minecraftforge/common/util/FakePlayer.java index bd481f2641..21373757a2 100644 --- a/src/main/java/net/minecraftforge/common/util/FakePlayer.java +++ b/src/main/java/net/minecraftforge/common/util/FakePlayer.java @@ -20,13 +20,21 @@ package net.minecraftforge.common.util; import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.authlib.GameProfile; -import net.minecraft.entity.Entity; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; + import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.network.play.client.CClientSettingsPacket; +import net.minecraft.network.IPacket; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.PacketDirection; +import net.minecraft.network.play.ServerPlayNetHandler; +import net.minecraft.network.play.client.*; +import net.minecraft.network.play.server.SPlayerPositionLookPacket; import net.minecraft.server.MinecraftServer; import net.minecraft.server.management.PlayerInteractionManager; import net.minecraft.stats.Stat; @@ -37,6 +45,7 @@ import net.minecraft.util.text.ITextComponent; import net.minecraft.world.server.ServerWorld; import net.minecraftforge.fml.server.ServerLifecycleHooks; +import java.util.Set; import java.util.UUID; //Preliminary, simple Fake Player class @@ -45,6 +54,7 @@ public class FakePlayer extends ServerPlayerEntity public FakePlayer(ServerWorld world, GameProfile name) { super(world.getServer(), world, name, new PlayerInteractionManager(world)); + this.connection = new FakePlayerNetHandler(world.getServer(), this); } @Override public Vector3d position(){ return new Vector3d(0, 0, 0); } @@ -59,4 +69,67 @@ public class FakePlayer extends ServerPlayerEntity @Override public void tick(){ return; } @Override public void updateOptions(CClientSettingsPacket pkt){ return; } @Override @Nullable public MinecraftServer getServer() { return ServerLifecycleHooks.getCurrentServer(); } + + @ParametersAreNonnullByDefault + private static class FakePlayerNetHandler extends ServerPlayNetHandler { + private static final NetworkManager DUMMY_NETWORK_MANAGER = new NetworkManager(PacketDirection.CLIENTBOUND); + + public FakePlayerNetHandler(MinecraftServer server, ServerPlayerEntity player) { + super(server, DUMMY_NETWORK_MANAGER, player); + } + + @Override public void tick() { } + @Override public void resetPosition() { } + @Override public void disconnect(ITextComponent message) { } + @Override public void handlePlayerInput(CInputPacket packet) { } + @Override public void handleMoveVehicle(CMoveVehiclePacket packet) { } + @Override public void handleAcceptTeleportPacket(CConfirmTeleportPacket packet) { } + @Override public void handleRecipeBookSeenRecipePacket(CMarkRecipeSeenPacket packet) { } + @Override public void handleRecipeBookChangeSettingsPacket(CUpdateRecipeBookStatusPacket packet) { } + @Override public void handleSeenAdvancements(CSeenAdvancementsPacket packet) { } + @Override public void handleCustomCommandSuggestions(CTabCompletePacket packet) { } + @Override public void handleSetCommandBlock(CUpdateCommandBlockPacket packet) { } + @Override public void handleSetCommandMinecart(CUpdateMinecartCommandBlockPacket packet) { } + @Override public void handlePickItem(CPickItemPacket packet) { } + @Override public void handleRenameItem(CRenameItemPacket packet) { } + @Override public void handleSetBeaconPacket(CUpdateBeaconPacket packet) { } + @Override public void handleSetStructureBlock(CUpdateStructureBlockPacket packet) { } + @Override public void handleSetJigsawBlock(CUpdateJigsawBlockPacket packet) { } + @Override public void handleJigsawGenerate(CJigsawBlockGeneratePacket packet) { } + @Override public void handleSelectTrade(CSelectTradePacket packet) { } + @Override public void handleEditBook(CEditBookPacket packet) { } + @Override public void handleEntityTagQuery(CQueryEntityNBTPacket packet) { } + @Override public void handleBlockEntityTagQuery(CQueryTileEntityNBTPacket packet) { } + @Override public void handleMovePlayer(CPlayerPacket packet) { } + @Override public void teleport(double x, double y, double z, float yaw, float pitch) { } + @Override public void teleport(double x, double y, double z, float yaw, float pitch, Set flags) { } + @Override public void handlePlayerAction(CPlayerDiggingPacket packet) { } + @Override public void handleUseItemOn(CPlayerTryUseItemOnBlockPacket packet) { } + @Override public void handleUseItem(CPlayerTryUseItemPacket packet) { } + @Override public void handleTeleportToEntityPacket(CSpectatePacket packet) { } + @Override public void handleResourcePackResponse(CResourcePackStatusPacket packet) { } + @Override public void handlePaddleBoat(CSteerBoatPacket packet) { } + @Override public void onDisconnect(ITextComponent message) { } + @Override public void send(IPacket packet) { } + @Override public void send(IPacket packet, @Nullable GenericFutureListener> p_211148_2_) { } + @Override public void handleSetCarriedItem(CHeldItemChangePacket packet) { } + @Override public void handleChat(CChatMessagePacket packet) { } + @Override public void handleAnimate(CAnimateHandPacket packet) { } + @Override public void handlePlayerCommand(CEntityActionPacket packet) { } + @Override public void handleInteract(CUseEntityPacket packet) { } + @Override public void handleClientCommand(CClientStatusPacket packet) { } + @Override public void handleContainerClose(CCloseWindowPacket packet) { } + @Override public void handleContainerClick(CClickWindowPacket packet) { } + @Override public void handlePlaceRecipe(CPlaceRecipePacket packet) { } + @Override public void handleContainerButtonClick(CEnchantItemPacket packet) { } + @Override public void handleSetCreativeModeSlot(CCreativeInventoryActionPacket packet) { } + @Override public void handleContainerAck(CConfirmTransactionPacket packet) { } + @Override public void handleSignUpdate(CUpdateSignPacket packet) { } + @Override public void handleKeepAlive(CKeepAlivePacket packet) { } + @Override public void handlePlayerAbilities(CPlayerAbilitiesPacket packet) { } + @Override public void handleClientInformation(CClientSettingsPacket packet) { } + @Override public void handleCustomPayload(CCustomPayloadPacket packet) { } + @Override public void handleChangeDifficulty(CSetDifficultyPacket packet) { } + @Override public void handleLockDifficulty(CLockDifficultyPacket packet) { } + } } diff --git a/src/test/java/net/minecraftforge/debug/misc/FakePlayerTest.java b/src/test/java/net/minecraftforge/debug/misc/FakePlayerTest.java new file mode 100644 index 0000000000..87a2e18a59 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/misc/FakePlayerTest.java @@ -0,0 +1,69 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.debug.misc; + +import net.minecraft.command.Commands; +import net.minecraft.command.arguments.EntityArgument; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.Hand; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.util.FakePlayerFactory; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod("fake_player_test") +public class FakePlayerTest +{ + public static final boolean ENABLE = true; + + public FakePlayerTest() + { + if (ENABLE) + MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event) + { + event.getDispatcher().register(Commands.literal("fakeplayer") + //Tests fake player creation & interaction with other entities in world + .then(Commands.literal("attack") + .then(Commands.argument("target", EntityArgument.entity()) + .executes(context -> { + FakePlayerFactory.getMinecraft(context.getSource().getLevel()).attack(EntityArgument.getEntity(context, "target")); + return 1; + })) + ) + //Makes sure fake player does not crash when its `connection` is accessed [#7604] + .then(Commands.literal("opencontainer") + .executes(context -> { + ServerPlayerEntity fakePlayer = FakePlayerFactory.getMinecraft(context.getSource().getLevel()); + Hand hand = Hand.MAIN_HAND; + ItemStack stack = Items.WRITABLE_BOOK.getDefaultInstance(); + fakePlayer.setItemInHand(hand, stack); + fakePlayer.openItemGui(stack, hand); + return 1; + }) + )); + } +} diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index 72d8e59c1e..f05369e8e8 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -122,6 +122,8 @@ license="LGPL v2.1" modId="enum_argument_test" [[mods]] modId="entity_teleport_event_test" +[[mods]] + modId="fake_player_test" [[mods]] modId="text_linear_filtering_test" [[mods]]