From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 15 May 2021 10:04:43 -0700
Subject: [PATCH] additions to PlayerGameModeChangeEvent


diff --git a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java
index 2e4fd72da147393581027fc35702d6c3fd989765..1bf4c5b36f53ef1e71d50d1a9af8e1410e5dff60 100644
--- a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java
+++ b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java
@@ -25,9 +25,13 @@ public class DefaultGameModeCommands {
         GameType gameType = minecraftServer.getForcedGameType();
         if (gameType != null) {
             for(ServerPlayer serverPlayer : minecraftServer.getPlayerList().getPlayers()) {
-                if (serverPlayer.setGameMode(gameType)) {
-                    ++i;
+                // Paper start - extend PlayerGameModeChangeEvent
+                org.bukkit.event.player.PlayerGameModeChangeEvent event = serverPlayer.setGameMode(gameType, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.empty());
+                if (event != null && event.isCancelled()) {
+                    source.sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false);
                 }
+                // Paper end
+                    ++i;
             }
         }
 
diff --git a/src/main/java/net/minecraft/server/commands/GameModeCommand.java b/src/main/java/net/minecraft/server/commands/GameModeCommand.java
index d47f3d255eddd652fedb4aa55286b756fe962995..27c0aaf123c3e945eb24e8a3892bd8ac42115733 100644
--- a/src/main/java/net/minecraft/server/commands/GameModeCommand.java
+++ b/src/main/java/net/minecraft/server/commands/GameModeCommand.java
@@ -44,9 +44,14 @@ public class GameModeCommand {
         int i = 0;
 
         for(ServerPlayer serverPlayer : targets) {
-            if (serverPlayer.setGameMode(gameMode)) {
+            // Paper start - extend PlayerGameModeChangeEvent
+            org.bukkit.event.player.PlayerGameModeChangeEvent event = serverPlayer.setGameMode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.empty());
+            if (event != null && !event.isCancelled()) {
                 logGamemodeChange(context.getSource(), serverPlayer, gameMode);
                 ++i;
+            } else if (event != null && event.cancelMessage() != null) {
+                context.getSource().sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), true);
+                // Paper end
             }
         }
 
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 5cc7edca158fed862d0dd18c6d2754de6df0ec4c..5428a5ee4097e29922d48564714998604ba07dbb 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1826,8 +1826,15 @@ public class ServerPlayer extends Player {
     }
 
     public boolean setGameMode(GameType gameMode) {
-        if (!this.gameMode.changeGameModeForPlayer(gameMode)) {
-            return false;
+        // Paper start - Add cause and nullable message to event
+        org.bukkit.event.player.PlayerGameModeChangeEvent event = this.setGameMode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null);
+        return event == null ? false : event.isCancelled();
+    }
+    public org.bukkit.event.player.PlayerGameModeChangeEvent setGameMode(GameType gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component message) {
+        org.bukkit.event.player.PlayerGameModeChangeEvent event = this.gameMode.changeGameModeForPlayer(gameMode, cause, message);
+        if (event == null || event.isCancelled()) {
+            // Paper end
+            return null;
         } else {
             this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) gameMode.getId()));
             if (gameMode == GameType.SPECTATOR) {
@@ -1839,7 +1846,7 @@ public class ServerPlayer extends Player {
 
             this.onUpdateAbilities();
             this.updateEffectVisibility();
-            return true;
+            return event; // Paper
         }
     }
 
@@ -2249,6 +2256,16 @@ public class ServerPlayer extends Player {
     }
 
     public void loadGameTypes(@Nullable CompoundTag nbt) {
+        // Paper start
+        if (this.server.getForcedGameType() != null && this.server.getForcedGameType() != ServerPlayer.readPlayerMode(nbt, "playerGameType")) {
+            if (new org.bukkit.event.player.PlayerGameModeChangeEvent(this.getBukkitEntity(), org.bukkit.GameMode.getByValue(this.server.getDefaultGameType().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) {
+                this.gameMode.setGameModeForPlayer(this.server.getForcedGameType(), GameType.DEFAULT_MODE);
+            } else {
+                this.gameMode.setGameModeForPlayer(ServerPlayer.readPlayerMode(nbt,"playerGameType"), ServerPlayer.readPlayerMode(nbt, "previousPlayerGameType"));
+            }
+            return;
+        }
+        // Paper end
         this.gameMode.setGameModeForPlayer(this.calculateGameModeForNewPlayer(ServerPlayer.readPlayerMode(nbt, "playerGameType")), ServerPlayer.readPlayerMode(nbt, "previousPlayerGameType"));
     }
 
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 645a226c2e3f6dcf1c25187d006d425038b4545d..17c313b9cb45c8158cab751ffc4e0dc3b7e1fa3c 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -73,21 +73,27 @@ public class ServerPlayerGameMode {
     }
 
     public boolean changeGameModeForPlayer(GameType gameMode) {
+        // Paper end
+        PlayerGameModeChangeEvent event = this.changeGameModeForPlayer(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null);
+        return event == null ? false : event.isCancelled();
+    }
+    public PlayerGameModeChangeEvent changeGameModeForPlayer(GameType gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component cancelMessage) {
+        // Paper end
         if (gameMode == this.gameModeForPlayer) {
-            return false;
+            return null; // Paper
         } else {
             // CraftBukkit start
-            PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(this.player.getBukkitEntity(), GameMode.getByValue(gameMode.getId()));
+            PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(this.player.getBukkitEntity(), GameMode.getByValue(gameMode.getId()), cause, cancelMessage); // Paper
             this.level.getCraftServer().getPluginManager().callEvent(event);
             if (event.isCancelled()) {
-                return false;
+                return event; // Paper
             }
             // CraftBukkit end
             this.setGameModeForPlayer(gameMode, this.previousGameModeForPlayer);
             this.player.onUpdateAbilities();
             this.player.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit
             this.level.updateSleepingPlayerList();
-            return true;
+            return event; // Paper
         }
     }
 
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 7dd27fc7a539ab0cbf06936ba4daa37ea607845d..69780a4a69048291b4898c2d0ecc57ce518ffd93 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2767,7 +2767,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
 
                     this.player = this.server.getPlayerList().respawn(this.player, false);
                     if (this.server.isHardcore()) {
-                        this.player.setGameMode(GameType.SPECTATOR);
+                        this.player.setGameMode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper
                         ((GameRules.BooleanValue) this.player.getLevel().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, this.server);
                     }
                 }
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 55c206d2bff70fd7febd5f635ea0d7a5e779a058..e225ef6eb6f061c3bdeebf824aa884611f79020e 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1472,7 +1472,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
             throw new IllegalArgumentException("Mode cannot be null");
         }
 
-        this.getHandle().setGameMode(GameType.byId(mode.getValue()));
+        this.getHandle().setGameMode(GameType.byId(mode.getValue()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.PLUGIN, null); // Paper
     }
 
     @Override
