aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0342-Implement-Player-Client-Options-API.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/0342-Implement-Player-Client-Options-API.patch')
-rw-r--r--patches/server/0342-Implement-Player-Client-Options-API.patch194
1 files changed, 194 insertions, 0 deletions
diff --git a/patches/server/0342-Implement-Player-Client-Options-API.patch b/patches/server/0342-Implement-Player-Client-Options-API.patch
new file mode 100644
index 0000000000..6470ba2e4a
--- /dev/null
+++ b/patches/server/0342-Implement-Player-Client-Options-API.patch
@@ -0,0 +1,194 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MiniDigger <[email protected]>
+Date: Mon, 20 Jan 2020 21:38:15 +0100
+Subject: [PATCH] Implement Player Client Options API
+
+== AT ==
+public net.minecraft.world.entity.player.Player DATA_PLAYER_MODE_CUSTOMISATION
+
+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 2d31cd0924ad44534418ec084507c19f49d95f24..15df50a36138f29ae278cf1f1f531ad949f4a93e 100644
+--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
+@@ -358,7 +358,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
+ this.stats = server.getPlayerList().getPlayerStats(this);
+ this.advancements = server.getPlayerList().getPlayerAdvancements(this);
+ // this.moveTo(this.adjustSpawnLocation(world, world.getSharedSpawnPos()).getBottomCenter(), 0.0F, 0.0F); // Paper - Don't move existing players to world spawn
+- this.updateOptions(clientOptions);
++ this.updateOptionsNoEvents(clientOptions); // Paper - don't call options events on login
+ this.object = null;
+
+ // CraftBukkit start
+@@ -2146,7 +2146,23 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
+ }
+ }
+
++ // Paper start - Client option API
++ private java.util.Map<com.destroystokyo.paper.ClientOption<?>, ?> getClientOptionMap(String locale, int viewDistance, com.destroystokyo.paper.ClientOption.ChatVisibility chatVisibility, boolean chatColors, com.destroystokyo.paper.PaperSkinParts skinParts, org.bukkit.inventory.MainHand mainHand, boolean allowsServerListing, boolean textFilteringEnabled) {
++ java.util.Map<com.destroystokyo.paper.ClientOption<?>, Object> map = new java.util.HashMap<>();
++ map.put(com.destroystokyo.paper.ClientOption.LOCALE, locale);
++ map.put(com.destroystokyo.paper.ClientOption.VIEW_DISTANCE, viewDistance);
++ map.put(com.destroystokyo.paper.ClientOption.CHAT_VISIBILITY, chatVisibility);
++ map.put(com.destroystokyo.paper.ClientOption.CHAT_COLORS_ENABLED, chatColors);
++ map.put(com.destroystokyo.paper.ClientOption.SKIN_PARTS, skinParts);
++ map.put(com.destroystokyo.paper.ClientOption.MAIN_HAND, mainHand);
++ map.put(com.destroystokyo.paper.ClientOption.ALLOW_SERVER_LISTINGS, allowsServerListing);
++ map.put(com.destroystokyo.paper.ClientOption.TEXT_FILTERING_ENABLED, textFilteringEnabled);
++ return map;
++ }
++ // Paper end
++
+ public void updateOptions(ClientInformation clientOptions) {
++ new com.destroystokyo.paper.event.player.PlayerClientOptionsChangeEvent(getBukkitEntity(), getClientOptionMap(clientOptions.language(), clientOptions.viewDistance(), com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(clientOptions.chatVisibility().name()), clientOptions.chatColors(), new com.destroystokyo.paper.PaperSkinParts(clientOptions.modelCustomisation()), clientOptions.mainHand() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT, clientOptions.allowsListing(), clientOptions.textFilteringEnabled())).callEvent(); // Paper - settings event
+ // CraftBukkit start
+ if (this.getMainArm() != clientOptions.mainHand()) {
+ PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(this.getBukkitEntity(), this.getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT);
+@@ -2157,6 +2173,11 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
+ this.server.server.getPluginManager().callEvent(event);
+ }
+ // CraftBukkit end
++ // Paper start - don't call options events on login
++ this.updateOptionsNoEvents(clientOptions);
++ }
++ public void updateOptionsNoEvents(ClientInformation clientOptions) {
++ // Paper end
+ this.language = clientOptions.language();
+ this.adventure$locale = java.util.Objects.requireNonNullElse(net.kyori.adventure.translation.Translator.parseLocale(this.language), java.util.Locale.US); // Paper
+ this.requestedViewDistance = clientOptions.viewDistance();
+diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+index 80a9a4df9b1114f932badd847238c7a0a1a00941..a0835efca3bef35c434b716ceccd05c801d2f240 100644
+--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+@@ -653,6 +653,28 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message);
+ }
+ }
++
++ @Override
++ public <T> T getClientOption(com.destroystokyo.paper.ClientOption<T> type) {
++ if (com.destroystokyo.paper.ClientOption.SKIN_PARTS == 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 == type) {
++ return type.getType().cast(getHandle().canChatInColor());
++ } else if (com.destroystokyo.paper.ClientOption.CHAT_VISIBILITY == 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 == type) {
++ return type.getType().cast(getLocale());
++ } else if (com.destroystokyo.paper.ClientOption.MAIN_HAND == type) {
++ return type.getType().cast(getMainHand());
++ } else if (com.destroystokyo.paper.ClientOption.VIEW_DISTANCE == type) {
++ return type.getType().cast(getClientViewDistance());
++ } else if (com.destroystokyo.paper.ClientOption.ALLOW_SERVER_LISTINGS == type) {
++ return type.getType().cast(getHandle().allowsListing());
++ } else if (com.destroystokyo.paper.ClientOption.TEXT_FILTERING_ENABLED == type) {
++ return type.getType().cast(getHandle().isTextFilteringEnabled());
++ }
++ 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..7f8b6462d2a1bbd39a870d2543bebc135f7eb45b
+--- /dev/null
++++ b/src/test/java/io/papermc/paper/world/TranslationKeyTest.java
+@@ -0,0 +1,18 @@
++package io.papermc.paper.world;
++
++import com.destroystokyo.paper.ClientOption;
++import net.minecraft.world.entity.player.ChatVisiblity;
++import org.bukkit.Difficulty;
++import org.junit.jupiter.api.Assertions;
++import org.junit.jupiter.api.Test;
++
++public class TranslationKeyTest {
++
++ @Test
++ public void testChatVisibilityKeys() {
++ for (ClientOption.ChatVisibility chatVisibility : ClientOption.ChatVisibility.values()) {
++ if (chatVisibility == ClientOption.ChatVisibility.UNKNOWN) continue;
++ Assertions.assertEquals(ChatVisiblity.valueOf(chatVisibility.name()).getKey(), chatVisibility.translationKey(), chatVisibility + "'s translation key doesn't match");
++ }
++ }
++}