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/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java index c4d433430503e844121f1917c6caf05823af0a34..7df24be46e4471ae0ddad5cded5eef4937fd37a3 100644 --- a/src/main/java/net/minecraft/server/EntityHuman.java +++ b/src/main/java/net/minecraft/server/EntityHuman.java @@ -35,7 +35,7 @@ public abstract class EntityHuman extends EntityLiving { private static final Map b = ImmutableMap.builder().put(EntityPose.STANDING, EntityHuman.bp).put(EntityPose.SLEEPING, EntityHuman.ap).put(EntityPose.FALL_FLYING, EntitySize.b(0.6F, 0.6F)).put(EntityPose.SWIMMING, EntitySize.b(0.6F, 0.6F)).put(EntityPose.SPIN_ATTACK, EntitySize.b(0.6F, 0.6F)).put(EntityPose.CROUCHING, EntitySize.b(0.6F, 1.5F)).put(EntityPose.DYING, EntitySize.c(0.2F, 0.2F)).build(); private static final DataWatcherObject c = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.c); private static final DataWatcherObject d = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.b); - protected static final DataWatcherObject bq = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); + protected static final DataWatcherObject bq = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); public static DataWatcherObject getSkinPartsWatcher() { return bq; } // Paper - OBFHELPER protected static final DataWatcherObject br = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); protected static final DataWatcherObject bs = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.p); protected static final DataWatcherObject bt = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.p); diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java index 49fe2d1a0376e5aa8a5ec00d010e6c834633e7b7..64e00275edf38739fe6e2d79dbcb93243e765678 100644 --- a/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java @@ -2,6 +2,7 @@ package net.minecraft.server; import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent; import com.google.common.collect.Lists; +import com.destroystokyo.paper.event.player.PlayerClientOptionsChangeEvent; // Paper import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Either; import io.netty.util.concurrent.Future; @@ -59,7 +60,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public int lastSentExp = -99999999; public int invulnerableTicks = 60; private EnumChatVisibility ch; - private boolean ci = true; + private boolean ci = true; public boolean hasChatColorsEnabled() { return this.ci; } // Paper - OBFHELPER private long cj = SystemUtils.getMonotonicMillis(); private Entity spectatedEntity; public boolean worldChangeInvuln; @@ -1573,6 +1574,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public void a(PacketPlayInSettings packetplayinsettings) { + new PlayerClientOptionsChangeEvent(getBukkitEntity(), packetplayinsettings.getLocale(), packetplayinsettings.viewDistance, com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(packetplayinsettings.getChatVisibility().name()), packetplayinsettings.hasChatColorsEnabled(), new com.destroystokyo.paper.PaperSkinParts(packetplayinsettings.getSkinParts()), packetplayinsettings.getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT).callEvent(); // Paper - settings event // CraftBukkit start if (getMainHand() != packetplayinsettings.getMainHand()) { PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT); diff --git a/src/main/java/net/minecraft/server/PacketPlayInSettings.java b/src/main/java/net/minecraft/server/PacketPlayInSettings.java index 8faebf9efed7c3529b151fddf8246e8c77a8b693..4da637138190c9b749d986ac32dddc051931d58f 100644 --- a/src/main/java/net/minecraft/server/PacketPlayInSettings.java +++ b/src/main/java/net/minecraft/server/PacketPlayInSettings.java @@ -37,18 +37,22 @@ public class PacketPlayInSettings implements Packet { packetlistenerplayin.a(this); } + public String getLocale() { return b(); } // Paper - OBFHELPER public String b() { return this.a; } + public EnumChatVisibility getChatVisibility() { return d(); } // Paper - OBFHELPER public EnumChatVisibility d() { return this.c; } + public boolean hasChatColorsEnabled() { return e(); } // Paper - OBFHELPER public boolean e() { return this.d; } + public int getSkinParts() { return f(); } // Paper - OBFHELPER public int f() { return this.e; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 6672feaf5198b89969796185a2fc110308678eb0..dcbda5b35ab4d44e6b1d6c34bb8763a7dd08e629 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1,5 +1,8 @@ package org.bukkit.craftbukkit.entity; +import com.destroystokyo.paper.ClientOption.ChatVisibility; +import com.destroystokyo.paper.PaperSkinParts; +import com.destroystokyo.paper.ClientOption; import com.destroystokyo.paper.Title; import com.destroystokyo.paper.profile.CraftPlayerProfile; import com.destroystokyo.paper.profile.PlayerProfile; @@ -36,6 +39,7 @@ import net.minecraft.server.BlockPosition; import net.minecraft.server.ChatComponentText; import net.minecraft.server.Container; import net.minecraft.server.Entity; +import net.minecraft.server.EntityHuman; import net.minecraft.server.EntityLiving; import net.minecraft.server.EntityPlayer; import net.minecraft.server.EnumChatFormat; @@ -1969,6 +1973,24 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public void setViewDistance(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(ClientOption type) { + if(ClientOption.SKIN_PARTS.equals(type)) { + return type.getType().cast(new PaperSkinParts(getHandle().getDataWatcher().get(EntityHuman.getSkinPartsWatcher()))); + } else if(ClientOption.CHAT_COLORS_ENABLED.equals(type)) { + return type.getType().cast(getHandle().hasChatColorsEnabled()); + } else if(ClientOption.CHAT_VISIBILITY.equals(type)) { + return type.getType().cast(getHandle().getChatFlags() == null ? ChatVisibility.UNKNOWN : ChatVisibility.valueOf(getHandle().getChatFlags().name())); + } else if(ClientOption.LOCALE.equals(type)) { + return type.getType().cast(getLocale()); + } else if(ClientOption.MAIN_HAND.equals(type)) { + return type.getType().cast(getMainHand()); + } else if(ClientOption.VIEW_DISTANCE.equals(type)) { + return type.getType().cast(getClientViewDistance()); + } + throw new RuntimeException("Unknown settings type"); + } // Paper end // Spigot start