add WrappedNumberFormat

This commit is contained in:
vytskalt 2024-03-02 17:23:09 +02:00
parent 7aa5f3b47f
commit 8df7ed8ce8
6 changed files with 234 additions and 4 deletions

View File

@ -895,6 +895,17 @@ public abstract class AbstractStructure {
return getOptionals(BukkitConverters.getWrappedTeamParametersConverter());
}
/**
* Retrieve a read/write structure for the NumberFormat class in 1.20.4+.
* @return A modifier for NumberFormat fields.
*/
public StructureModifier<WrappedNumberFormat> getNumberFormats() {
return structureModifier.withType(
MinecraftReflection.getNumberFormatClass().orElse(null),
BukkitConverters.getWrappedNumberFormatConverter());
}
/**
* Retrieve a read/write structure for the MinecraftKey class.
* @return A modifier for MinecraftKey fields.

View File

@ -1037,6 +1037,42 @@ public final class MinecraftReflection {
return getMinecraftClass("network.chat.ChatModifier", "ChatModifier");
}
/**
* Retrieve the NMS NumberFormat class.
*
* @return The NumberFormat class.
*/
public static Optional<Class<?>> getNumberFormatClass() {
return getOptionalNMS("network.chat.numbers.NumberFormat");
}
/**
* Retrieve the NMS BlankFormat class.
*
* @return The FixedFormat class.
*/
public static Optional<Class<?>> getBlankFormatClass() {
return getOptionalNMS("network.chat.numbers.BlankFormat");
}
/**
* Retrieve the NMS FixedFormat class.
*
* @return The FixedFormat class.
*/
public static Optional<Class<?>> getFixedFormatClass() {
return getOptionalNMS("network.chat.numbers.FixedFormat");
}
/**
* Retrieve the NMS StyledFormat class.
*
* @return The StyledFormat class.
*/
public static Optional<Class<?>> getStyledFormatClass() {
return getOptionalNMS("network.chat.numbers.StyledFormat");
}
/**
* Retrieve the Gson class used by Minecraft.
*

View File

@ -644,6 +644,10 @@ public class BukkitConverters {
return ignoreNull(handle(WrappedTeamParameters::getHandle, WrappedTeamParameters::new, WrappedTeamParameters.class));
}
public static EquivalentConverter<WrappedNumberFormat> getWrappedNumberFormatConverter() {
return ignoreNull(handle(WrappedNumberFormat::getHandle, WrappedNumberFormat::fromHandle, WrappedNumberFormat.class));
}
public static EquivalentConverter<PacketContainer> getPacketContainerConverter() {
return ignoreNull(handle(PacketContainer::getHandle, PacketContainer::fromPacket, PacketContainer.class));
}

View File

@ -46,10 +46,6 @@ public class WrappedComponentStyle extends AbstractWrapper {
}
}
public static WrappedComponentStyle fromHandle(Object handle) {
return new WrappedComponentStyle(handle);
}
public static WrappedComponentStyle fromJson(JsonObject json) {
Object handle;
if (CODEC != null) {

View File

@ -0,0 +1,133 @@
package com.comphenix.protocol.wrappers;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
import com.comphenix.protocol.utility.MinecraftReflection;
import org.jetbrains.annotations.NotNull;
/**
* A wrapper around the NumberFormat NMS classes.
*
* @author vytskalt
* @since 1.20.4
*/
@SuppressWarnings("OptionalGetWithoutIsPresent")
public class WrappedNumberFormat extends AbstractWrapper {
private static final IllegalStateException UNSUPPORTED = new IllegalStateException("NumberFormat classes don't exist on this server version");
private static final Object BLANK;
private static final ConstructorAccessor FIXED_CONSTRUCTOR, STYLED_CONSTRUCTOR;
static {
if (!isSupported()) {
BLANK = null;
FIXED_CONSTRUCTOR = null;
STYLED_CONSTRUCTOR = null;
} else {
Class<?> blankClass = MinecraftReflection.getBlankFormatClass().get();
FuzzyReflection fuzzyBlank = FuzzyReflection.fromClass(blankClass, true);
BLANK = Accessors.getFieldAccessor(fuzzyBlank.getFieldByType("INSTANCE", blankClass)).get(null);
FIXED_CONSTRUCTOR = Accessors.getConstructorAccessor(
MinecraftReflection.getFixedFormatClass().get(),
MinecraftReflection.getIChatBaseComponentClass()
);
STYLED_CONSTRUCTOR = Accessors.getConstructorAccessor(
MinecraftReflection.getStyledFormatClass().get(),
MinecraftReflection.getComponentStyleClass()
);
}
}
/**
* @return Whether the NumberFormat classes exist on the current server version
*/
public static boolean isSupported() {
return MinecraftReflection.getNumberFormatClass().isPresent();
}
public static WrappedNumberFormat fromHandle(Object handle) {
if (!isSupported()) {
throw UNSUPPORTED;
}
if (MinecraftReflection.getBlankFormatClass().get().isInstance(handle)) {
return new Blank(handle);
} else if (MinecraftReflection.getFixedFormatClass().get().isInstance(handle)) {
return new Fixed(handle);
} else if (MinecraftReflection.getStyledFormatClass().get().isInstance(handle)) {
return new Styled(handle);
} else {
throw new IllegalArgumentException("handle is not a NumberFormat instance, but " + handle.getClass());
}
}
public static Blank blank() {
if (!isSupported()) {
throw UNSUPPORTED;
}
return new Blank(WrappedNumberFormat.BLANK);
}
public static Fixed fixed(@NotNull WrappedChatComponent content) {
if (!isSupported()) {
throw UNSUPPORTED;
}
Object handle = FIXED_CONSTRUCTOR.invoke(content.getHandle());
return new Fixed(handle);
}
public static Styled styled(@NotNull WrappedComponentStyle style) {
if (!isSupported()) {
throw UNSUPPORTED;
}
Object handle = STYLED_CONSTRUCTOR.invoke(style.getHandle());
return new Styled(handle);
}
private WrappedNumberFormat(Class<?> handleType) {
super(handleType);
}
public static class Blank extends WrappedNumberFormat {
private Blank(Object handle) {
super(MinecraftReflection.getBlankFormatClass().get());
setHandle(handle);
}
}
public static class Fixed extends WrappedNumberFormat {
private final StructureModifier<Object> modifier;
private Fixed(Object handle) {
super(MinecraftReflection.getFixedFormatClass().get());
setHandle(handle);
this.modifier = new StructureModifier<>(handle.getClass()).withTarget(handle);
}
public WrappedChatComponent getContent() {
Object handle = modifier.withType(MinecraftReflection.getIChatBaseComponentClass()).read(0);
return WrappedChatComponent.fromHandle(handle);
}
}
public static class Styled extends WrappedNumberFormat {
private final StructureModifier<Object> modifier;
private Styled(Object handle) {
super(MinecraftReflection.getStyledFormatClass().get());
setHandle(handle);
this.modifier = new StructureModifier<>(handle.getClass()).withTarget(handle);
}
public WrappedComponentStyle getStyle() {
Object handle = modifier.withType(MinecraftReflection.getComponentStyleClass()).read(0);
return new WrappedComponentStyle(handle);
}
}
}

View File

@ -0,0 +1,50 @@
package com.comphenix.protocol.wrappers;
import com.comphenix.protocol.BukkitInitialization;
import net.minecraft.EnumChatFormat;
import net.minecraft.network.chat.ChatModifier;
import net.minecraft.network.chat.IChatBaseComponent;
import net.minecraft.network.chat.numbers.BlankFormat;
import net.minecraft.network.chat.numbers.FixedFormat;
import net.minecraft.network.chat.numbers.StyledFormat;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
public class WrappedNumberFormatTest {
@BeforeAll
static void initializeBukkit() {
BukkitInitialization.initializeAll();
}
@Test
void testBlankFormat() {
assertInstanceOf(WrappedNumberFormat.Blank.class, WrappedNumberFormat.fromHandle(BlankFormat.a));
assertEquals(BlankFormat.a, WrappedNumberFormat.blank().getHandle());
}
@Test
void testFixedFormat() {
IChatBaseComponent content = IChatBaseComponent.a("Fixed");
WrappedNumberFormat wrappedHandle = WrappedNumberFormat.fromHandle(new FixedFormat(content));
assertInstanceOf(WrappedNumberFormat.Fixed.class, wrappedHandle);
assertEquals(content, ((WrappedNumberFormat.Fixed) wrappedHandle).getContent().getHandle());
WrappedNumberFormat.Fixed wrapped = WrappedNumberFormat.fixed(WrappedChatComponent.fromHandle(content));
assertEquals(content, wrapped.getContent().getHandle());
}
@Test
void testStyledFormat() {
ChatModifier style = ChatModifier.a.b(EnumChatFormat.g);
WrappedNumberFormat wrappedHandle = WrappedNumberFormat.fromHandle(new StyledFormat(style));
assertInstanceOf(WrappedNumberFormat.Styled.class, wrappedHandle);
assertEquals(style, ((WrappedNumberFormat.Styled) wrappedHandle).getStyle().getHandle());
WrappedNumberFormat.Styled newWrapper = WrappedNumberFormat.styled(new WrappedComponentStyle(style));
assertEquals(style, newWrapper.getStyle().getHandle());
}
}