diff --git a/patches/minecraft/net/minecraft/client/network/play/NetworkPlayerInfo.java.patch b/patches/minecraft/net/minecraft/client/network/play/NetworkPlayerInfo.java.patch new file mode 100644 index 0000000000..5f5e5c6686 --- /dev/null +++ b/patches/minecraft/net/minecraft/client/network/play/NetworkPlayerInfo.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/client/network/play/NetworkPlayerInfo.java ++++ b/net/minecraft/client/network/play/NetworkPlayerInfo.java +@@ -50,6 +50,7 @@ + } + + protected void func_178839_a(GameType p_178839_1_) { ++ net.minecraftforge.client.ForgeHooksClient.onClientChangeGameMode(this, this.field_178866_b, p_178839_1_); + this.field_178866_b = p_178839_1_; + } + diff --git a/patches/minecraft/net/minecraft/entity/player/ServerPlayerEntity.java.patch b/patches/minecraft/net/minecraft/entity/player/ServerPlayerEntity.java.patch index f34d1abf28..2a55f3fd87 100644 --- a/patches/minecraft/net/minecraft/entity/player/ServerPlayerEntity.java.patch +++ b/patches/minecraft/net/minecraft/entity/player/ServerPlayerEntity.java.patch @@ -130,7 +130,15 @@ } protected void func_70670_a(EffectInstance p_70670_1_) { -@@ -1187,6 +1208,7 @@ +@@ -1139,6 +1160,7 @@ + } + + public void func_71033_a(GameType p_71033_1_) { ++ if (!net.minecraftforge.common.ForgeHooks.onChangeGameMode(this, this.field_71134_c.func_73081_b(), p_71033_1_)) return; + this.field_71134_c.func_73076_a(p_71033_1_); + this.field_71135_a.func_147359_a(new SChangeGameStatePacket(SChangeGameStatePacket.field_241767_d_, (float)p_71033_1_.func_77148_a())); + if (p_71033_1_ == GameType.SPECTATOR) { +@@ -1187,6 +1209,7 @@ this.field_71140_co = p_147100_1_.func_149520_f(); this.func_184212_Q().func_187227_b(field_184827_bp, (byte)p_147100_1_.func_149521_d()); this.func_184212_Q().func_187227_b(field_184828_bq, (byte)(p_147100_1_.func_186991_f() == HandSide.LEFT ? 0 : 1)); @@ -138,7 +146,7 @@ } public ChatVisibility func_147096_v() { -@@ -1297,14 +1319,14 @@ +@@ -1297,14 +1320,14 @@ this.func_184210_p(); if (p_200619_1_ == this.field_70170_p) { this.field_71135_a.func_147364_a(p_200619_2_, p_200619_4_, p_200619_6_, p_200619_8_, p_200619_9_); @@ -156,7 +164,7 @@ this.func_70012_b(p_200619_2_, p_200619_4_, p_200619_6_, p_200619_8_, p_200619_9_); this.func_70029_a(p_200619_1_); p_200619_1_.func_217446_a(this); -@@ -1313,6 +1335,7 @@ +@@ -1313,6 +1336,7 @@ this.field_71134_c.func_73080_a(p_200619_1_); this.field_71133_b.func_184103_al().func_72354_b(this, p_200619_1_); this.field_71133_b.func_184103_al().func_72385_f(this); @@ -164,7 +172,7 @@ } } -@@ -1335,6 +1358,7 @@ +@@ -1335,6 +1359,7 @@ } public void func_242111_a(RegistryKey p_242111_1_, @Nullable BlockPos p_242111_2_, float p_242111_3_, boolean p_242111_4_, boolean p_242111_5_) { @@ -172,7 +180,7 @@ if (p_242111_2_ != null) { boolean flag = p_242111_2_.equals(this.field_241138_cr_) && p_242111_1_.equals(this.field_241137_cq_); if (p_242111_5_ && !flag) { -@@ -1387,6 +1411,8 @@ +@@ -1387,6 +1412,8 @@ if (itementity == null) { return null; } else { @@ -181,7 +189,7 @@ this.field_70170_p.func_217376_c(itementity); ItemStack itemstack = itementity.func_92059_d(); if (p_146097_3_) { -@@ -1400,4 +1426,13 @@ +@@ -1400,4 +1427,13 @@ return itementity; } } diff --git a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java index 1b6ddaa4b6..1e9e82e1f5 100644 --- a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java +++ b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java @@ -32,6 +32,7 @@ import net.minecraft.client.gui.ClientBossInfo; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.screen.MainMenuScreen; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.network.play.NetworkPlayerInfo; import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.FogRenderer.FogType; import net.minecraft.client.renderer.color.BlockColors; @@ -72,6 +73,7 @@ import net.minecraft.util.math.vector.Vector3f; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.world.GameType; import net.minecraft.world.IBlockDisplayReader; import net.minecraftforge.client.event.*; import net.minecraftforge.client.event.sound.PlaySoundEvent; @@ -562,6 +564,15 @@ public class ForgeHooksClient return event; } + public static void onClientChangeGameMode(NetworkPlayerInfo info, GameType currentGameMode, GameType newGameMode) + { + if (currentGameMode != newGameMode) + { + ClientPlayerChangeGameModeEvent evt = new ClientPlayerChangeGameModeEvent(info, currentGameMode, newGameMode); + MinecraftForge.EVENT_BUS.post(evt); + } + } + @SuppressWarnings("deprecation") public static IBakedModel handlePerspective(IBakedModel model, ItemCameraTransforms.TransformType type, MatrixStack stack) { diff --git a/src/main/java/net/minecraftforge/client/event/ClientPlayerChangeGameModeEvent.java b/src/main/java/net/minecraftforge/client/event/ClientPlayerChangeGameModeEvent.java new file mode 100644 index 0000000000..a315f84472 --- /dev/null +++ b/src/main/java/net/minecraftforge/client/event/ClientPlayerChangeGameModeEvent.java @@ -0,0 +1,37 @@ +package net.minecraftforge.client.event; + +import net.minecraft.client.network.play.NetworkPlayerInfo; +import net.minecraft.world.GameType; +import net.minecraftforge.eventbus.api.Event; + +/** + * Fired before the client player is notified of a change in game mode from the server. + */ +public class ClientPlayerChangeGameModeEvent extends Event +{ + private final NetworkPlayerInfo info; + private final GameType currentGameMode; + private final GameType newGameMode; + + public ClientPlayerChangeGameModeEvent(NetworkPlayerInfo info, GameType currentGameMode, GameType newGameMode) + { + this.info = info; + this.currentGameMode = currentGameMode; + this.newGameMode = newGameMode; + } + + public NetworkPlayerInfo getInfo() + { + return info; + } + + public GameType getCurrentGameMode() + { + return currentGameMode; + } + + public GameType getNewGameMode() + { + return newGameMode; + } +} diff --git a/src/main/java/net/minecraftforge/common/ForgeHooks.java b/src/main/java/net/minecraftforge/common/ForgeHooks.java index 910859665e..e0dab612ef 100644 --- a/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -789,6 +789,17 @@ public class ForgeHooks MinecraftForge.EVENT_BUS.post(new PlayerInteractEvent.LeftClickEmpty(player)); } + public static boolean onChangeGameMode(PlayerEntity player, GameType currentGameMode, GameType newGameMode) + { + if (currentGameMode != newGameMode) + { + PlayerEvent.PlayerChangeGameModeEvent evt = new PlayerEvent.PlayerChangeGameModeEvent(player, currentGameMode, newGameMode); + MinecraftForge.EVENT_BUS.post(evt); + return !evt.isCanceled(); + } + return true; + } + private static ThreadLocal> lootContext = new ThreadLocal>(); private static LootTableContext getLootTableContext() { diff --git a/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java b/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java index 83db01ba95..5c6f897462 100644 --- a/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java +++ b/src/main/java/net/minecraftforge/event/entity/player/PlayerEvent.java @@ -25,6 +25,7 @@ import net.minecraft.entity.item.ItemEntity; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.util.RegistryKey; +import net.minecraft.world.GameType; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.ForgeEventFactory; @@ -510,4 +511,40 @@ public class PlayerEvent extends LivingEvent return this.toDim; } } + + /** + * Fired when the game type of a server player is changed to a different value than what it was previously. Eg Creative to Survival, not Survival to Survival. + * If the event is cancelled the game mode of the player is not changed and the value of newGameMode is ignored. + */ + @Cancelable + public static class PlayerChangeGameModeEvent extends PlayerEvent + { + private final GameType currentGameMode; + private GameType newGameMode; + + public PlayerChangeGameModeEvent(PlayerEntity player, GameType currentGameMode, GameType newGameMode) + { + super(player); + this.currentGameMode = currentGameMode; + this.newGameMode = newGameMode; + } + + public GameType getCurrentGameMode() + { + return currentGameMode; + } + + public GameType getNewGameMode() + { + return newGameMode; + } + + /** + * Sets the game mode the player will be changed to if this event is not cancelled. + */ + public void setNewGameMode(GameType newGameMode) + { + this.newGameMode = newGameMode; + } + } } diff --git a/src/test/java/net/minecraftforge/debug/entity/player/PlayerGameModeEventTest.java b/src/test/java/net/minecraftforge/debug/entity/player/PlayerGameModeEventTest.java new file mode 100644 index 0000000000..45b36eca56 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/entity/player/PlayerGameModeEventTest.java @@ -0,0 +1,53 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2020. + * + * 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.entity.player; + +import net.minecraft.world.GameType; +import net.minecraftforge.client.event.ClientPlayerChangeGameModeEvent; +import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Mod("player_game_mode_event_test") +@Mod.EventBusSubscriber() +public class PlayerGameModeEventTest +{ + private static final boolean ENABLE = false; + private static final Logger LOGGER = LogManager.getLogger(PlayerGameModeEventTest.class); + + @SubscribeEvent + public static void onPlayerChangeGameModeEvent(PlayerEvent.PlayerChangeGameModeEvent event) + { + if (!ENABLE) return; + LOGGER.info("{} changed game mode. Current GameType: {}. New Game Type: {}", event.getPlayer(), event.getCurrentGameMode(), event.getNewGameMode()); + if (event.getNewGameMode() == GameType.SURVIVAL) + event.setCanceled(true); + } + + @SubscribeEvent + public static void onClientPlayerChangeGameModeEvent(ClientPlayerChangeGameModeEvent event) + { + if (!ENABLE) return; + LOGGER.info("Client notified of changed game mode from '{}'. Current GameType: {}. New Game Type: {}", event.getInfo().getGameProfile(), event.getCurrentGameMode(), event.getNewGameMode()); + } +} diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index 0b1c0c7a75..dfbd2280c7 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -89,4 +89,6 @@ license="LGPL v2.1" [[mods]] modId="biome_loading_event_test" [[mods]] - modId="structure_spawn_list_event_test" \ No newline at end of file + modId="player_game_mode_event_test" +[[mods]] + modId="structure_spawn_list_event_test"