From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Mon, 20 Jan 2020 21:38:15 +0100 Subject: [PATCH] Implement Player Client Options API diff --git a/src/main/java/com/destroystokyo/paper/PaperSkinParts.java b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java new file mode 100644 index 0000000000000000000000000000000000000000..b6f4400df3d8ec7e06a996de54f8cabba57885e1 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java @@ -0,0 +1,74 @@ +package com.destroystokyo.paper; + +import com.google.common.base.Objects; + +import java.util.StringJoiner; + +public class PaperSkinParts implements SkinParts { + + private final int raw; + + public PaperSkinParts(int raw) { + this.raw = raw; + } + + public boolean hasCapeEnabled() { + return (raw & 1) == 1; + } + + public boolean hasJacketEnabled() { + return (raw >> 1 & 1) == 1; + } + + public boolean hasLeftSleeveEnabled() { + return (raw >> 2 & 1) == 1; + } + + public boolean hasRightSleeveEnabled() { + return (raw >> 3 & 1) == 1; + } + + public boolean hasLeftPantsEnabled() { + return (raw >> 4 & 1) == 1; + } + + public boolean hasRightPantsEnabled() { + return (raw >> 5 & 1) == 1; + } + + public boolean hasHatsEnabled() { + return (raw >> 6 & 1) == 1; + } + + @Override + public int getRaw() { + return raw; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PaperSkinParts that = (PaperSkinParts) o; + return raw == that.raw; + } + + @Override + public int hashCode() { + return Objects.hashCode(raw); + } + + @Override + public String toString() { + return new StringJoiner(", ", PaperSkinParts.class.getSimpleName() + "[", "]") + .add("raw=" + raw) + .add("cape=" + hasCapeEnabled()) + .add("jacket=" + hasJacketEnabled()) + .add("leftSleeve=" + hasLeftSleeveEnabled()) + .add("rightSleeve=" + hasRightSleeveEnabled()) + .add("leftPants=" + hasLeftPantsEnabled()) + .add("rightPants=" + hasRightPantsEnabled()) + .add("hats=" + hasHatsEnabled()) + .toString(); + } +} diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java index 9b3f8b6ff7a2522e74bdbc914e35d566ab9c7697..e800229c294a04581c863349119f67270da1a6ca 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1828,6 +1828,7 @@ public class ServerPlayer extends Player { public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null public java.util.Locale adventure$locale = java.util.Locale.US; // Paper public void updateOptions(ServerboundClientInformationPacket packet) { + new com.destroystokyo.paper.event.player.PlayerClientOptionsChangeEvent(getBukkitEntity(), packet.language, packet.viewDistance, com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(packet.chatVisibility().name()), packet.chatColors(), new com.destroystokyo.paper.PaperSkinParts(packet.modelCustomisation()), packet.mainHand() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT).callEvent(); // Paper - settings event // CraftBukkit start if (getMainArm() != packet.mainHand()) { PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(this.getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 42062d64b7ea55f5360c435ef1953452d439029b..0a9d519596b074fd88fc3594d673189ef2c5e3d9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -551,6 +551,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public void setSendViewDistance(int viewDistance) { throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO } + + @Override + public T getClientOption(com.destroystokyo.paper.ClientOption type) { + if(com.destroystokyo.paper.ClientOption.SKIN_PARTS.equals(type)) { + return type.getType().cast(new com.destroystokyo.paper.PaperSkinParts(getHandle().getEntityData().get(net.minecraft.world.entity.player.Player.DATA_PLAYER_MODE_CUSTOMISATION))); + } else if(com.destroystokyo.paper.ClientOption.CHAT_COLORS_ENABLED.equals(type)) { + return type.getType().cast(getHandle().canChatInColor()); + } else if(com.destroystokyo.paper.ClientOption.CHAT_VISIBILITY.equals(type)) { + return type.getType().cast(getHandle().getChatVisibility() == null ? com.destroystokyo.paper.ClientOption.ChatVisibility.UNKNOWN : com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(getHandle().getChatVisibility().name())); + } else if(com.destroystokyo.paper.ClientOption.LOCALE.equals(type)) { + return type.getType().cast(getLocale()); + } else if(com.destroystokyo.paper.ClientOption.MAIN_HAND.equals(type)) { + return type.getType().cast(getMainHand()); + } else if(com.destroystokyo.paper.ClientOption.VIEW_DISTANCE.equals(type)) { + return type.getType().cast(getClientViewDistance()); + } + throw new RuntimeException("Unknown settings type"); + } // Paper end @Override diff --git a/src/test/java/io/papermc/paper/world/TranslationKeyTest.java b/src/test/java/io/papermc/paper/world/TranslationKeyTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6cd015dc5a2e012ac827c2b2d9aa5542b0591afb --- /dev/null +++ b/src/test/java/io/papermc/paper/world/TranslationKeyTest.java @@ -0,0 +1,19 @@ +package io.papermc.paper.world; + +import com.destroystokyo.paper.ClientOption; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.world.entity.player.ChatVisiblity; +import org.bukkit.Difficulty; +import org.junit.Assert; +import org.junit.Test; + +public class TranslationKeyTest { + + @Test + public void testChatVisibilityKeys() { + for (ClientOption.ChatVisibility chatVisibility : ClientOption.ChatVisibility.values()) { + if (chatVisibility == ClientOption.ChatVisibility.UNKNOWN) continue; + Assert.assertEquals(chatVisibility + "'s translation key doesn't match", ChatVisiblity.valueOf(chatVisibility.name()).getKey(), chatVisibility.translationKey()); + } + } +}