mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-04 23:47:59 +01:00
hollow-cube/add-gamemodechangeevent-and-fix-game-profile (#43)
* Resolve some todos and add connection.setProfile to EncryptionResponsePacket * Add PlayerGameModeChangeEvent (cherry picked from commit1514d8ac1f
) * Add unit tests (cherry picked from commit9685e74f3b
) --------- Co-authored-by: GreatWyrm <alecmusante@gmail.com> Co-authored-by: NxDs <7994264+NxDs@users.noreply.github.com> (cherry picked from commit2c567696ac
)
This commit is contained in:
parent
6d3690a660
commit
edf7b870c7
@ -1378,8 +1378,18 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
* Changes the player {@link GameMode}
|
||||
*
|
||||
* @param gameMode the new player GameMode
|
||||
* @return true if the gamemode was changed successfully, false otherwise (cancelled by event)
|
||||
*/
|
||||
public void setGameMode(@NotNull GameMode gameMode) {
|
||||
public boolean setGameMode(@NotNull GameMode gameMode) {
|
||||
PlayerGameModeChangeEvent playerGameModeChangeEvent = new PlayerGameModeChangeEvent(this, gameMode);
|
||||
EventDispatcher.call(playerGameModeChangeEvent);
|
||||
if (playerGameModeChangeEvent.isCancelled()) {
|
||||
// Abort
|
||||
return false;
|
||||
}
|
||||
|
||||
gameMode = playerGameModeChangeEvent.getNewGameMode();
|
||||
|
||||
this.gameMode = gameMode;
|
||||
// Condition to prevent sending the packets before spawning the player
|
||||
if (isActive()) {
|
||||
@ -1411,6 +1421,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
if (isActive()) {
|
||||
refreshAbilities();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,56 @@
|
||||
package net.minestom.server.event.player;
|
||||
|
||||
import net.minestom.server.entity.GameMode;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.trait.CancellableEvent;
|
||||
import net.minestom.server.event.trait.PlayerInstanceEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when the gamemode of a player is being modified.
|
||||
*/
|
||||
public class PlayerGameModeChangeEvent implements PlayerInstanceEvent, CancellableEvent {
|
||||
|
||||
private final Player player;
|
||||
private GameMode newGameMode;
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
public PlayerGameModeChangeEvent(@NotNull Player player, @NotNull GameMode newGameMode) {
|
||||
this.player = player;
|
||||
this.newGameMode = newGameMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the target gamemode.
|
||||
*
|
||||
* @return the target gamemode
|
||||
*/
|
||||
public @NotNull GameMode getNewGameMode() {
|
||||
return newGameMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the target gamemode.
|
||||
*
|
||||
* @param newGameMode the new target gamemode
|
||||
*/
|
||||
public void setNewGameMode(@NotNull GameMode newGameMode) {
|
||||
this.newGameMode = newGameMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancelled = cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
@ -1,12 +1,15 @@
|
||||
package net.minestom.server.network.packet.client.login;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.extras.MojangAuth;
|
||||
import net.minestom.server.extras.mojangAuth.MojangCrypt;
|
||||
import net.minestom.server.network.NetworkBuffer;
|
||||
import net.minestom.server.network.packet.client.ClientPreplayPacket;
|
||||
import net.minestom.server.network.player.GameProfile;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.network.player.PlayerSocketConnection;
|
||||
import net.minestom.server.utils.async.AsyncUtils;
|
||||
@ -20,7 +23,9 @@ import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static net.minestom.server.network.NetworkBuffer.BYTE_ARRAY;
|
||||
@ -72,14 +77,22 @@ public record EncryptionResponsePacket(byte[] sharedSecret,
|
||||
client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).whenComplete((response, throwable) -> {
|
||||
if (throwable != null) {
|
||||
MinecraftServer.getExceptionManager().handleException(throwable);
|
||||
//todo disconnect with reason
|
||||
if (socketConnection.getPlayer() != null) {
|
||||
socketConnection.getPlayer().kick(Component.text("Failed to contact Mojang's Session Servers (Are they down?)"));
|
||||
} else {
|
||||
socketConnection.disconnect();
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final JsonObject gameProfile = GSON.fromJson(response.body(), JsonObject.class);
|
||||
if (gameProfile == null) {
|
||||
// Invalid response
|
||||
//todo disconnect with reason
|
||||
if (socketConnection.getPlayer() != null) {
|
||||
socketConnection.getPlayer().kick(Component.text("Failed to get data from Mojang's Session Servers (Are they down?)"));
|
||||
} else {
|
||||
socketConnection.disconnect();
|
||||
}
|
||||
return;
|
||||
}
|
||||
socketConnection.setEncryptionKey(getSecretKey());
|
||||
@ -89,6 +102,12 @@ public record EncryptionResponsePacket(byte[] sharedSecret,
|
||||
|
||||
MinecraftServer.LOGGER.info("UUID of player {} is {}", loginUsername, profileUUID);
|
||||
CONNECTION_MANAGER.startPlayState(connection, profileUUID, profileName, true);
|
||||
List<GameProfile.Property> propertyList = new ArrayList<>();
|
||||
for (JsonElement element : gameProfile.get("properties").getAsJsonArray()) {
|
||||
JsonObject object = element.getAsJsonObject();
|
||||
propertyList.add(new GameProfile.Property(object.get("name").getAsString(), object.get("value").getAsString(), object.get("signature").getAsString()));
|
||||
}
|
||||
socketConnection.UNSAFE_setProfile(new GameProfile(profileUUID, profileName, propertyList));
|
||||
} catch (Exception e) {
|
||||
MinecraftServer.getExceptionManager().handleException(e);
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
package net.minestom.server.entity.player;
|
||||
|
||||
import net.minestom.server.event.player.PlayerGameModeChangeEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.entity.damage.DamageType;
|
||||
import net.minestom.server.message.ChatMessageType;
|
||||
import net.minestom.server.network.packet.client.play.ClientSettingsPacket;
|
||||
import net.minestom.server.event.player.PlayerGameModeChangeEvent;
|
||||
import net.minestom.testing.Collector;
|
||||
import net.minestom.testing.Env;
|
||||
import net.minestom.testing.EnvTest;
|
||||
@ -27,7 +29,8 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
public class PlayerIntegrationTest {
|
||||
|
||||
/**
|
||||
* Test to see whether player abilities are updated correctly when changing gamemodes
|
||||
* Test to see whether player abilities are updated correctly and events
|
||||
* are handled properly when changing gamemode.
|
||||
*/
|
||||
@Test
|
||||
public void gamemodeTest(Env env) {
|
||||
@ -36,16 +39,38 @@ public class PlayerIntegrationTest {
|
||||
var player = connection.connect(instance, new Pos(0, 42, 0)).join();
|
||||
assertEquals(instance, player.getInstance());
|
||||
|
||||
player.setGameMode(GameMode.CREATIVE);
|
||||
assertAbilities(player, true, false, true, true);
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
assertAbilities(player, true, true, true, false);
|
||||
player.setGameMode(GameMode.CREATIVE);
|
||||
assertAbilities(player, true, true, true, true);
|
||||
player.setGameMode(GameMode.ADVENTURE);
|
||||
assertAbilities(player, false, false, false, false);
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
assertAbilities(player, false, false, false, false);
|
||||
// Abilities
|
||||
{
|
||||
player.setGameMode(GameMode.CREATIVE);
|
||||
assertAbilities(player, true, false, true, true);
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
assertAbilities(player, true, true, true, false);
|
||||
player.setGameMode(GameMode.CREATIVE);
|
||||
assertAbilities(player, true, true, true, true);
|
||||
player.setGameMode(GameMode.ADVENTURE);
|
||||
assertAbilities(player, false, false, false, false);
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
assertAbilities(player, false, false, false, false);
|
||||
}
|
||||
|
||||
var listener = env.listen(PlayerGameModeChangeEvent.class);
|
||||
// Normal change
|
||||
{
|
||||
listener.followup();
|
||||
assertTrue(player.setGameMode(GameMode.ADVENTURE));
|
||||
}
|
||||
// Change target gamemode event
|
||||
{
|
||||
listener.followup(event -> event.setNewGameMode(GameMode.SPECTATOR));
|
||||
assertTrue(player.setGameMode(GameMode.CREATIVE));
|
||||
assertEquals(GameMode.SPECTATOR, player.getGameMode());
|
||||
}
|
||||
// Cancel event
|
||||
{
|
||||
listener.followup(event -> event.setCancelled(true));
|
||||
assertFalse(player.setGameMode(GameMode.CREATIVE));
|
||||
assertEquals(GameMode.SPECTATOR, player.getGameMode());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -165,7 +190,7 @@ public class PlayerIntegrationTest {
|
||||
|
||||
assertNull(player.getDeathLocation());
|
||||
player.damage(DamageType.VOID, 30);
|
||||
|
||||
|
||||
assertNotNull(player.getDeathLocation());
|
||||
assertEquals(dimensionNamespace, player.getDeathLocation().dimension());
|
||||
assertEquals(5, player.getDeathLocation().position().x());
|
||||
|
Loading…
Reference in New Issue
Block a user