Add WrappedTeamParameters
This commit is contained in:
parent
4c878facbe
commit
0266b25548
|
@ -877,6 +877,16 @@ public abstract class AbstractStructure {
|
|||
EnumWrappers.getRenderTypeConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a read/write structure for the ChatFormatting enum.
|
||||
* @return A modifier for ChatFormatting enum fields.
|
||||
*/
|
||||
public StructureModifier<EnumWrappers.ChatFormatting> getChatFormattings() {
|
||||
return structureModifier.withType(
|
||||
EnumWrappers.getChatFormattingClass(),
|
||||
EnumWrappers.getChatFormattingConverter());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a read/write structure for the MinecraftKey class.
|
||||
|
|
|
@ -1009,6 +1009,15 @@ public final class MinecraftReflection {
|
|||
return getMinecraftClass("world.level.block.entity.TileEntity", "world.level.block.entity.BlockEntity", "TileEntity");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the NMS team parameters class.
|
||||
*
|
||||
* @return The team parameters class.
|
||||
*/
|
||||
public static Optional<Class<?>> getTeamParametersClass() {
|
||||
return getOptionalNMS("network.protocol.game.PacketPlayOutScoreboardTeam$b");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Gson class used by Minecraft.
|
||||
*
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.comphenix.protocol.reflect.accessors.Accessors;
|
|||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameMode;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -490,6 +491,133 @@ public abstract class EnumWrappers {
|
|||
HEARTS
|
||||
}
|
||||
|
||||
public enum ChatFormatting {
|
||||
BLACK,
|
||||
DARK_BLUE,
|
||||
DARK_GREEN,
|
||||
DARK_AQUA,
|
||||
DARK_RED,
|
||||
DARK_PURPLE,
|
||||
GOLD,
|
||||
GRAY,
|
||||
DARK_GRAY,
|
||||
BLUE,
|
||||
GREEN,
|
||||
AQUA,
|
||||
RED,
|
||||
LIGHT_PURPLE,
|
||||
YELLOW,
|
||||
WHITE,
|
||||
OBFUSCATED,
|
||||
BOLD,
|
||||
STRIKETHROUGH,
|
||||
UNDERLINE,
|
||||
ITALIC,
|
||||
RESET;
|
||||
|
||||
public ChatColor toBukkit() {
|
||||
switch (this){
|
||||
case BLACK:
|
||||
return ChatColor.BLACK;
|
||||
case DARK_BLUE:
|
||||
return ChatColor.DARK_BLUE;
|
||||
case DARK_GREEN:
|
||||
return ChatColor.DARK_GREEN;
|
||||
case DARK_AQUA:
|
||||
return ChatColor.DARK_AQUA;
|
||||
case DARK_RED:
|
||||
return ChatColor.DARK_RED;
|
||||
case DARK_PURPLE:
|
||||
return ChatColor.DARK_PURPLE;
|
||||
case GOLD:
|
||||
return ChatColor.GOLD;
|
||||
case GRAY:
|
||||
return ChatColor.GRAY;
|
||||
case DARK_GRAY:
|
||||
return ChatColor.DARK_GRAY;
|
||||
case BLUE:
|
||||
return ChatColor.BLUE;
|
||||
case GREEN:
|
||||
return ChatColor.GREEN;
|
||||
case AQUA:
|
||||
return ChatColor.AQUA;
|
||||
case RED:
|
||||
return ChatColor.RED;
|
||||
case LIGHT_PURPLE:
|
||||
return ChatColor.LIGHT_PURPLE;
|
||||
case YELLOW:
|
||||
return ChatColor.YELLOW;
|
||||
case WHITE:
|
||||
return ChatColor.WHITE;
|
||||
case OBFUSCATED:
|
||||
return ChatColor.MAGIC;
|
||||
case BOLD:
|
||||
return ChatColor.BOLD;
|
||||
case STRIKETHROUGH:
|
||||
return ChatColor.STRIKETHROUGH;
|
||||
case UNDERLINE:
|
||||
return ChatColor.UNDERLINE;
|
||||
case ITALIC:
|
||||
return ChatColor.ITALIC;
|
||||
case RESET:
|
||||
return ChatColor.RESET;
|
||||
default:
|
||||
throw new IllegalStateException("Unimplemented Bukkit equivalent for " + name());
|
||||
}
|
||||
}
|
||||
|
||||
public static ChatFormatting fromBukkit(ChatColor color) {
|
||||
switch (color){
|
||||
case BLACK:
|
||||
return ChatFormatting.BLACK;
|
||||
case DARK_BLUE:
|
||||
return ChatFormatting.DARK_BLUE;
|
||||
case DARK_GREEN:
|
||||
return ChatFormatting.DARK_GREEN;
|
||||
case DARK_AQUA:
|
||||
return ChatFormatting.DARK_AQUA;
|
||||
case DARK_RED:
|
||||
return ChatFormatting.DARK_RED;
|
||||
case DARK_PURPLE:
|
||||
return ChatFormatting.DARK_PURPLE;
|
||||
case GOLD:
|
||||
return ChatFormatting.GOLD;
|
||||
case GRAY:
|
||||
return ChatFormatting.GRAY;
|
||||
case DARK_GRAY:
|
||||
return ChatFormatting.DARK_GRAY;
|
||||
case BLUE:
|
||||
return ChatFormatting.BLUE;
|
||||
case GREEN:
|
||||
return ChatFormatting.GREEN;
|
||||
case AQUA:
|
||||
return ChatFormatting.AQUA;
|
||||
case RED:
|
||||
return ChatFormatting.RED;
|
||||
case LIGHT_PURPLE:
|
||||
return ChatFormatting.LIGHT_PURPLE;
|
||||
case YELLOW:
|
||||
return ChatFormatting.YELLOW;
|
||||
case WHITE:
|
||||
return ChatFormatting.WHITE;
|
||||
case MAGIC:
|
||||
return ChatFormatting.OBFUSCATED;
|
||||
case BOLD:
|
||||
return ChatFormatting.BOLD;
|
||||
case STRIKETHROUGH:
|
||||
return ChatFormatting.STRIKETHROUGH;
|
||||
case UNDERLINE:
|
||||
return ChatFormatting.UNDERLINE;
|
||||
case ITALIC:
|
||||
return ChatFormatting.ITALIC;
|
||||
case RESET:
|
||||
return ChatFormatting.RESET;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown ChatColor " + color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> PROTOCOL_CLASS = null;
|
||||
private static Class<?> CLIENT_COMMAND_CLASS = null;
|
||||
private static Class<?> CHAT_VISIBILITY_CLASS = null;
|
||||
|
@ -513,6 +641,7 @@ public abstract class EnumWrappers {
|
|||
private static Class<?> ENTITY_POSE_CLASS = null;
|
||||
private static Class<?> DISPLAY_SLOT_CLASS = null;
|
||||
private static Class<?> RENDER_TYPE_CLASS = null;
|
||||
private static Class<?> CHAT_FORMATTING_CLASS = null;
|
||||
|
||||
private static boolean INITIALIZED = false;
|
||||
private static Map<Class<?>, EquivalentConverter<?>> FROM_NATIVE = new HashMap<>();
|
||||
|
@ -598,6 +727,7 @@ public abstract class EnumWrappers {
|
|||
ENTITY_POSE_CLASS = MinecraftReflection.getNullableNMS("world.entity.EntityPose", "world.entity.Pose", "EntityPose");
|
||||
DISPLAY_SLOT_CLASS = MinecraftReflection.getNullableNMS("world.scores.DisplaySlot");
|
||||
RENDER_TYPE_CLASS = MinecraftReflection.getNullableNMS("world.scores.criteria.IScoreboardCriteria$EnumScoreboardHealthDisplay", "IScoreboardCriteria$EnumScoreboardHealthDisplay");
|
||||
CHAT_FORMATTING_CLASS = MinecraftReflection.getNullableNMS("EnumChatFormat");
|
||||
|
||||
associate(PROTOCOL_CLASS, Protocol.class, getProtocolConverter());
|
||||
associate(CLIENT_COMMAND_CLASS, ClientCommand.class, getClientCommandConverter());
|
||||
|
@ -619,6 +749,9 @@ public abstract class EnumWrappers {
|
|||
associate(CHAT_TYPE_CLASS, ChatType.class, getChatTypeConverter());
|
||||
associate(HAND_CLASS, Hand.class, getHandConverter());
|
||||
associate(ENTITY_USE_ACTION_CLASS, EntityUseAction.class, getEntityUseActionConverter());
|
||||
associate(DISPLAY_SLOT_CLASS, DisplaySlot.class, getDisplaySlotConverter());
|
||||
associate(RENDER_TYPE_CLASS, RenderType.class, getRenderTypeConverter());
|
||||
associate(CHAT_FORMATTING_CLASS, ChatFormatting.class, getChatFormattingConverter());
|
||||
|
||||
if (ENTITY_POSE_CLASS != null) {
|
||||
associate(ENTITY_POSE_CLASS, EntityPose.class, getEntityPoseConverter());
|
||||
|
@ -780,6 +913,11 @@ public abstract class EnumWrappers {
|
|||
return RENDER_TYPE_CLASS;
|
||||
}
|
||||
|
||||
public static Class<?> getChatFormattingClass() {
|
||||
initialize();
|
||||
return CHAT_FORMATTING_CLASS;
|
||||
}
|
||||
|
||||
// Get the converters
|
||||
public static EquivalentConverter<Protocol> getProtocolConverter() {
|
||||
return new EnumConverter<>(getProtocolClass(), Protocol.class);
|
||||
|
@ -869,6 +1007,10 @@ public abstract class EnumWrappers {
|
|||
return new EnumConverter<>(getRenderTypeClass(), RenderType.class);
|
||||
}
|
||||
|
||||
public static EquivalentConverter<ChatFormatting> getChatFormattingConverter() {
|
||||
return new EnumConverter<>(getChatFormattingClass(), ChatFormatting.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.13+
|
||||
* @return {@link EnumConverter} or null (if bellow 1.13 / nms EnumPose class cannot be found)
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import com.comphenix.protocol.injector.StructureCache;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A wrapper around the team parameters NMS class.
|
||||
*
|
||||
* @author vytskalt
|
||||
* @since 1.17
|
||||
*/
|
||||
public class WrappedTeamParameters extends AbstractWrapper {
|
||||
private static Class<?> getNmsClass() {
|
||||
return MinecraftReflection.getTeamParametersClass()
|
||||
.orElseThrow(() -> new IllegalStateException("Team parameters class doesn't exist on this server version"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the team parameters class exists on the current server version
|
||||
*/
|
||||
public static boolean isSupported() {
|
||||
return MinecraftReflection.getTeamParametersClass().isPresent();
|
||||
}
|
||||
|
||||
public static Builder newBuilder() {
|
||||
return newBuilder(null);
|
||||
}
|
||||
|
||||
public static Builder newBuilder(@Nullable WrappedTeamParameters template) {
|
||||
return new Builder(template);
|
||||
}
|
||||
|
||||
private final StructureModifier<Object> modifier;
|
||||
|
||||
public WrappedTeamParameters(Object handle) {
|
||||
super(getNmsClass());
|
||||
setHandle(handle);
|
||||
this.modifier = new StructureModifier<>(getNmsClass()).withTarget(handle);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public WrappedChatComponent getDisplayName() {
|
||||
return readComponent(0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public WrappedChatComponent getPrefix() {
|
||||
return readComponent(1);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public WrappedChatComponent getSuffix() {
|
||||
return readComponent(2);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getNametagVisibility() {
|
||||
return modifier.<String>withType(String.class).read(0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getCollisionRule() {
|
||||
return modifier.<String>withType(String.class).read(1);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public EnumWrappers.ChatFormatting getColor() {
|
||||
Object handle = modifier.withType(EnumWrappers.getChatFormattingClass()).read(0);
|
||||
return EnumWrappers.getChatFormattingConverter().getSpecific(handle);
|
||||
}
|
||||
|
||||
public int getOptions() {
|
||||
return (int) modifier.withType(int.class).read(0);
|
||||
}
|
||||
|
||||
private WrappedChatComponent readComponent(int index) {
|
||||
Object handle = modifier.withType(MinecraftReflection.getIChatBaseComponentClass()).read(index);
|
||||
return WrappedChatComponent.fromHandle(handle);
|
||||
}
|
||||
|
||||
private void writeComponent(int index, WrappedChatComponent component) {
|
||||
modifier.withType(MinecraftReflection.getIChatBaseComponentClass()).write(index, component.getHandle());
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private WrappedChatComponent displayName, prefix, suffix;
|
||||
private String nametagVisibility, collisionRule;
|
||||
private EnumWrappers.ChatFormatting color;
|
||||
private int options;
|
||||
|
||||
private Builder(@Nullable WrappedTeamParameters template) {
|
||||
if (template != null) {
|
||||
this.displayName = template.getDisplayName();
|
||||
this.prefix = template.getDisplayName();
|
||||
this.suffix = template.getDisplayName();
|
||||
this.nametagVisibility = template.getNametagVisibility();
|
||||
this.collisionRule = template.getCollisionRule();
|
||||
this.color = template.getColor();
|
||||
this.options = template.getOptions();
|
||||
}
|
||||
}
|
||||
|
||||
public Builder displayName(@NotNull WrappedChatComponent displayName) {
|
||||
Preconditions.checkNotNull(displayName);
|
||||
this.displayName = displayName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder prefix(@NotNull WrappedChatComponent prefix) {
|
||||
Preconditions.checkNotNull(prefix);
|
||||
this.prefix = prefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder suffix(@NotNull WrappedChatComponent suffix) {
|
||||
Preconditions.checkNotNull(suffix);
|
||||
this.suffix = suffix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder nametagVisibility(@NotNull String nametagVisibility) {
|
||||
Preconditions.checkNotNull(nametagVisibility);
|
||||
this.nametagVisibility = nametagVisibility;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder collisionRule(@NotNull String collisionRule) {
|
||||
Preconditions.checkNotNull(collisionRule);
|
||||
this.collisionRule = collisionRule;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder color(@NotNull EnumWrappers.ChatFormatting color) {
|
||||
Preconditions.checkNotNull(color);
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder options(int options) {
|
||||
Preconditions.checkNotNull(collisionRule);
|
||||
this.options = options;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WrappedTeamParameters build() {
|
||||
Preconditions.checkNotNull(displayName, "Display name not set");
|
||||
Preconditions.checkNotNull(prefix, "Prefix not set");
|
||||
Preconditions.checkNotNull(suffix, "Suffix not set");
|
||||
Preconditions.checkNotNull(nametagVisibility, "Nametag visibility not set");
|
||||
Preconditions.checkNotNull(collisionRule, "Collision rule not set");
|
||||
Preconditions.checkNotNull(color, "Color not set");
|
||||
|
||||
// Not technically a packet, but it has a PacketDataSerializer constructor, so it works fine
|
||||
Object handle = StructureCache.newPacket(getNmsClass());
|
||||
|
||||
WrappedTeamParameters wrapped = new WrappedTeamParameters(handle);
|
||||
wrapped.writeComponent(0, displayName);
|
||||
wrapped.writeComponent(1, prefix);
|
||||
wrapped.writeComponent(2, suffix);
|
||||
wrapped.modifier.withType(String.class).write(0, nametagVisibility);
|
||||
wrapped.modifier.withType(String.class).write(1, collisionRule);
|
||||
wrapped.modifier.withType(EnumWrappers.getChatFormattingClass()).write(0, EnumWrappers.getChatFormattingConverter().getGeneric(color));
|
||||
wrapped.modifier.withType(int.class).write(0, options);
|
||||
return wrapped;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
import net.minecraft.EnumChatFormat;
|
||||
import net.minecraft.network.chat.IChatBaseComponent;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class WrappedTeamParametersTest {
|
||||
@BeforeAll
|
||||
static void initializeBukkit() {
|
||||
BukkitInitialization.initializeAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTeamParameters() {
|
||||
IChatBaseComponent displayName = IChatBaseComponent.b("display name");
|
||||
IChatBaseComponent prefix = IChatBaseComponent.b("prefix");
|
||||
IChatBaseComponent suffix = IChatBaseComponent.b("suffix");
|
||||
String nametagVisibility = "always";
|
||||
String collisionRule = "never";
|
||||
|
||||
WrappedTeamParameters wrapped = WrappedTeamParameters.newBuilder()
|
||||
.displayName(WrappedChatComponent.fromHandle(displayName))
|
||||
.prefix(WrappedChatComponent.fromHandle(prefix))
|
||||
.suffix(WrappedChatComponent.fromHandle(suffix))
|
||||
.nametagVisibility(nametagVisibility)
|
||||
.collisionRule(collisionRule)
|
||||
.color(EnumWrappers.ChatFormatting.RED)
|
||||
.options(1)
|
||||
.build();
|
||||
|
||||
assertEquals(displayName, wrapped.getDisplayName().getHandle());
|
||||
assertEquals(prefix, wrapped.getPrefix().getHandle());
|
||||
assertEquals(suffix, wrapped.getSuffix().getHandle());
|
||||
assertEquals(nametagVisibility, wrapped.getNametagVisibility());
|
||||
assertEquals(collisionRule, wrapped.getCollisionRule());
|
||||
assertEquals(EnumWrappers.ChatFormatting.RED, wrapped.getColor());
|
||||
assertEquals(1, wrapped.getOptions());
|
||||
|
||||
PacketPlayOutScoreboardTeam.b handle = (PacketPlayOutScoreboardTeam.b) wrapped.getHandle();
|
||||
assertEquals(handle.a(), displayName);
|
||||
assertEquals(handle.f(), prefix);
|
||||
assertEquals(handle.g(), suffix);
|
||||
assertEquals(handle.d(), nametagVisibility);
|
||||
assertEquals(handle.e(), collisionRule);
|
||||
assertEquals(handle.c(), EnumChatFormat.m);
|
||||
assertEquals(handle.b(), 1);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue