From 7729e6b6137baff68d944698838ec411ab4c4b28 Mon Sep 17 00:00:00 2001 From: acrylic-style Date: Thu, 2 Nov 2023 12:30:48 +0900 Subject: [PATCH] feat: support 1.20.2 --- .../loreeditor/api/util/ReflectionUtil.java | 7 +- .../loreeditor/common/util/Reflected.java | 2 +- plugin/build.gradle.kts | 1 + settings.gradle.kts | 1 + v1_20/build.gradle.kts | 10 ++ .../v1_20/chat/ChatModifierImpl.java | 30 ++++++ .../loreeditor/v1_20/chat/ComponentImpl.java | 58 +++++++++++ .../loreeditor/v1_20/entity/CraftPlayer.java | 21 ++++ .../loreeditor/v1_20/entity/EntityPlayer.java | 22 +++++ .../v1_20/item/CraftItemStackImpl.java | 27 ++++++ .../loreeditor/v1_20/item/ItemStackImpl.java | 51 ++++++++++ .../v1_20/item/tag/CompoundTagImpl.java | 95 +++++++++++++++++++ .../v1_20/item/tag/ListTagImpl.java | 44 +++++++++ .../v1_20/item/tag/StringTagImpl.java | 26 +++++ .../loreeditor/v1_20/item/tag/TagImpl.java | 66 +++++++++++++ .../IServerCommonPacketListenerImpl.java | 12 +++ .../v1_20/network/NetworkManager.java | 11 +++ .../ServerCommonPacketListenerImpl.java | 21 ++++ .../packet/ClientboundSetSlotImpl.java | 32 +++++++ .../packet/ClientboundWindowItemsImpl.java | 38 ++++++++ .../ServerboundClickContainerSlotImpl.java | 29 ++++++ .../ServerboundSetCreativeSlotImpl.java | 27 ++++++ .../v1_20/util/ChannelUtilImpl.java | 57 +++++++++++ 23 files changed, 686 insertions(+), 2 deletions(-) create mode 100644 v1_20/build.gradle.kts create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/chat/ChatModifierImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/chat/ComponentImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/entity/CraftPlayer.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/entity/EntityPlayer.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/CraftItemStackImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/ItemStackImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/CompoundTagImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/ListTagImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/StringTagImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/TagImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/IServerCommonPacketListenerImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/NetworkManager.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/ServerCommonPacketListenerImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ClientboundSetSlotImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ClientboundWindowItemsImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ServerboundClickContainerSlotImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ServerboundSetCreativeSlotImpl.java create mode 100644 v1_20/src/main/java/net/azisaba/loreeditor/v1_20/util/ChannelUtilImpl.java diff --git a/api/src/main/java/net/azisaba/loreeditor/api/util/ReflectionUtil.java b/api/src/main/java/net/azisaba/loreeditor/api/util/ReflectionUtil.java index 98e4440..cbc094e 100644 --- a/api/src/main/java/net/azisaba/loreeditor/api/util/ReflectionUtil.java +++ b/api/src/main/java/net/azisaba/loreeditor/api/util/ReflectionUtil.java @@ -21,6 +21,11 @@ public static boolean isModernNMS() { } public static @NotNull String getServerImplVersion() { + switch (Bukkit.getBukkitVersion()) { + case "1.20.1-R0.1-SNAPSHOT": + case "1.20.2-R0.1-SNAPSHOT": + return "v1_20"; + } return Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; } @@ -38,7 +43,7 @@ public static boolean isModernNMS() { public static @NotNull Class getOBCClass(@NotNull String name) { try { - return Class.forName("org.bukkit.craftbukkit." + getServerImplVersion() + "." + name); + return Class.forName(Bukkit.getServer().getClass().getPackage().getName() + "." + name); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } diff --git a/common/src/main/java/net/azisaba/loreeditor/common/util/Reflected.java b/common/src/main/java/net/azisaba/loreeditor/common/util/Reflected.java index 9543b05..30c8442 100644 --- a/common/src/main/java/net/azisaba/loreeditor/common/util/Reflected.java +++ b/common/src/main/java/net/azisaba/loreeditor/common/util/Reflected.java @@ -3,6 +3,6 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Target; -@Target(ElementType.METHOD) +@Target({ElementType.METHOD, ElementType.TYPE}) public @interface Reflected { } diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index b316958..77fbe4a 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -2,6 +2,7 @@ dependencies { api(project(":common")) api(project(":v1_15_R1")) api(project(":v1_19_R3")) + api(project(":v1_20")) } tasks { diff --git a/settings.gradle.kts b/settings.gradle.kts index b2afab5..a6c1ada 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,3 +4,4 @@ include("plugin") include("common") include("v1_15_R1") include("v1_19_R3") +include("v1_20") diff --git a/v1_20/build.gradle.kts b/v1_20/build.gradle.kts new file mode 100644 index 0000000..baeafc7 --- /dev/null +++ b/v1_20/build.gradle.kts @@ -0,0 +1,10 @@ +repositories { + mavenLocal() +} + +java.toolchain.languageVersion.set(JavaLanguageVersion.of(17)) + +dependencies { + compileOnly(project(":common")) + compileOnly("org.spigotmc:spigot:1.20.2-R0.1-SNAPSHOT") +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/chat/ChatModifierImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/chat/ChatModifierImpl.java new file mode 100644 index 0000000..d8be1f5 --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/chat/ChatModifierImpl.java @@ -0,0 +1,30 @@ +package net.azisaba.loreeditor.v1_20.chat; + +import net.azisaba.loreeditor.common.chat.ChatModifier; +import net.azisaba.loreeditor.common.util.Reflected; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public record ChatModifierImpl(net.minecraft.network.chat.ChatModifier handle) implements ChatModifier { + public ChatModifierImpl { + Objects.requireNonNull(handle, "handle"); + } + + @Contract(value = "_ -> new", pure = true) + @Reflected + public static @NotNull ChatModifierImpl getInstance(@NotNull Object handle) { + return new ChatModifierImpl((net.minecraft.network.chat.ChatModifier) handle); + } + + @Override + public @NotNull net.minecraft.network.chat.ChatModifier handle() { + return handle; + } + + @Override + public @NotNull ChatModifier setItalic(boolean italic) { + return getInstance(handle.b(italic)); // setItalic + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/chat/ComponentImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/chat/ComponentImpl.java new file mode 100644 index 0000000..8f2f33c --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/chat/ComponentImpl.java @@ -0,0 +1,58 @@ +package net.azisaba.loreeditor.v1_20.chat; + +import net.azisaba.loreeditor.common.chat.ChatModifier; +import net.azisaba.loreeditor.common.chat.Component; +import net.azisaba.loreeditor.common.util.Reflected; +import net.minecraft.network.chat.IChatBaseComponent; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Objects; +import java.util.function.UnaryOperator; + +@Reflected +public record ComponentImpl(IChatBaseComponent handle) implements Component { + public ComponentImpl(@Nullable IChatBaseComponent handle) { + this.handle = handle; + } + + @Contract(value = "_ -> new", pure = true) + @Reflected + public static @NotNull ComponentImpl getInstance(@Nullable Object component) { + return new ComponentImpl((IChatBaseComponent) component); + } + + @Override + public @NotNull IChatBaseComponent handle() { + return Objects.requireNonNull(handle, "cannot reference handle in static context"); + } + + @Override + public @Nullable Component deserialize(@NotNull String input) { + return getInstance(IChatBaseComponent.ChatSerializer.a(input)); // deserialize + } + + @Override + public @NotNull String serialize(@NotNull Component component) { + return IChatBaseComponent.ChatSerializer.a(((ComponentImpl) component).handle()); // serialize + } + + @Override + public @NotNull List getSiblings() { + return handle().c(); // getSiblings + } + + @Override + public void addSiblingText(@NotNull String text) { + handle().a(IChatBaseComponent.ChatSerializer.a(text)); // addSibling + } + + @Override + public @NotNull Component modifyStyle(@NotNull UnaryOperator action) { + ChatModifier cm = new ChatModifierImpl(handle().a()); // getChatModifier + net.minecraft.network.chat.ChatModifier newChatModifier = ((ChatModifierImpl) action.apply(cm)).handle(); + return getInstance(handle().a(newChatModifier)); // setChatModifier + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/entity/CraftPlayer.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/entity/CraftPlayer.java new file mode 100644 index 0000000..eab936d --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/entity/CraftPlayer.java @@ -0,0 +1,21 @@ +package net.azisaba.loreeditor.v1_20.entity; + +import net.azisaba.loreeditor.api.util.ReflectionUtil; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import xyz.acrylicstyle.util.reflector.CastTo; +import xyz.acrylicstyle.util.reflector.Reflector; +import xyz.acrylicstyle.util.reflector.ReflectorHandler; + +import java.util.Objects; + +public interface CraftPlayer { + static @NotNull CraftPlayer getInstance(@NotNull Player player) { + return Reflector.newReflector(null, CraftPlayer.class, + new ReflectorHandler(ReflectionUtil.getOBCClass("entity.CraftPlayer"), Objects.requireNonNull(player, "player"))); + } + + @NotNull + @CastTo(EntityPlayer.class) + EntityPlayer getHandle(); +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/entity/EntityPlayer.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/entity/EntityPlayer.java new file mode 100644 index 0000000..c67207c --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/entity/EntityPlayer.java @@ -0,0 +1,22 @@ +package net.azisaba.loreeditor.v1_20.entity; + +import net.azisaba.loreeditor.api.util.ReflectionUtil; +import net.azisaba.loreeditor.v1_20.network.ServerCommonPacketListenerImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import xyz.acrylicstyle.util.reflector.CastTo; +import xyz.acrylicstyle.util.reflector.FieldGetter; +import xyz.acrylicstyle.util.reflector.Reflector; +import xyz.acrylicstyle.util.reflector.ReflectorHandler; + +public interface EntityPlayer { + static @NotNull EntityPlayer getInstance(@Nullable Object o) { + return Reflector.newReflector(null, EntityPlayer.class, + new ReflectorHandler(ReflectionUtil.getNMSClass("net.minecraft.server.level.EntityPlayer"), o)); + } + + @NotNull + @CastTo(value = ServerCommonPacketListenerImpl.class, createInstance = true) + @FieldGetter("c") + ServerCommonPacketListenerImpl getPlayerConnection(); +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/CraftItemStackImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/CraftItemStackImpl.java new file mode 100644 index 0000000..b94ee90 --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/CraftItemStackImpl.java @@ -0,0 +1,27 @@ +package net.azisaba.loreeditor.v1_20.item; + +import net.azisaba.loreeditor.api.item.CraftItemStack; +import net.azisaba.loreeditor.api.item.ItemStack; +import net.azisaba.loreeditor.common.util.Reflected; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class CraftItemStackImpl implements CraftItemStack { + @Contract(value = "_ -> new", pure = true) + @Reflected + public static @NotNull CraftItemStackImpl getInstance(@Nullable Object item) { + return new CraftItemStackImpl(); + } + + @Override + public @Nullable ItemStack asNMSCopy(org.bukkit.inventory.@Nullable ItemStack item) { + return new ItemStackImpl(org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack.asNMSCopy(item)); + } + + @NotNull + @Override + public org.bukkit.inventory.ItemStack asCraftMirror(@NotNull ItemStack item) { + return org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack.asCraftMirror(((ItemStackImpl) item).handle()); + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/ItemStackImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/ItemStackImpl.java new file mode 100644 index 0000000..cd9b20d --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/ItemStackImpl.java @@ -0,0 +1,51 @@ +package net.azisaba.loreeditor.v1_20.item; + +import net.azisaba.loreeditor.api.item.ItemStack; +import net.azisaba.loreeditor.api.item.tag.CompoundTag; +import net.azisaba.loreeditor.common.util.Reflected; +import net.azisaba.loreeditor.v1_20.item.tag.CompoundTagImpl; +import net.minecraft.nbt.NBTTagCompound; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +public record ItemStackImpl(net.minecraft.world.item.ItemStack handle) implements ItemStack { + public ItemStackImpl(net.minecraft.world.item.ItemStack handle) { + this.handle = Objects.requireNonNull(handle, "handle"); + } + + @Override + public @NotNull net.minecraft.world.item.ItemStack handle() { + return handle; + } + + @Contract("_ -> new") + @Reflected + public static @NotNull ItemStackImpl getInstance(@NotNull Object item) { + Objects.requireNonNull(item, "item"); + return new ItemStackImpl((net.minecraft.world.item.ItemStack) item); + } + + @Override + public @NotNull CompoundTag getOrCreateTag() { + return new CompoundTagImpl(handle.w()); // getOrCreateTag + } + + @Override + public @Nullable CompoundTag getTag() { + NBTTagCompound handle = this.handle.v(); // getTag + return handle == null ? null : new CompoundTagImpl(handle); + } + + @Override + public void setTag(@Nullable CompoundTag tag) { + handle.c(tag == null ? null : ((CompoundTagImpl) tag).getHandle()); // setTag + } + + @Override + public int getCount() { + return handle.K(); // getCount (probably) + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/CompoundTagImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/CompoundTagImpl.java new file mode 100644 index 0000000..784ed43 --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/CompoundTagImpl.java @@ -0,0 +1,95 @@ +package net.azisaba.loreeditor.v1_20.item.tag; + +import net.azisaba.loreeditor.api.item.tag.CompoundTag; +import net.azisaba.loreeditor.api.item.tag.ListTag; +import net.azisaba.loreeditor.api.item.tag.Tag; +import net.azisaba.loreeditor.common.util.Reflected; +import net.minecraft.nbt.NBTTagCompound; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class CompoundTagImpl extends TagImpl implements CompoundTag { + public CompoundTagImpl(@NotNull NBTTagCompound handle) { + super(handle); + } + + @Contract("_ -> new") + @Reflected + public static @NotNull CompoundTagImpl getInstance(@Nullable Object tag) { + if (tag == null) { + return new CompoundTagImpl(new NBTTagCompound()); + } + return new CompoundTagImpl((NBTTagCompound) tag); + } + + @Override + public @NotNull CompoundTag constructor() { + return new CompoundTagImpl(new NBTTagCompound()); + } + + @Override + public int size() { + return getHandle().f(); // size + } + + @Override + public boolean hasKeyOfType(@NotNull String key, int type) { + return getHandle().b(key, type); // hasKeyOfType + } + + @Override + public void remove(@NotNull String key) { + getHandle().r(key); // remove + } + + @Override + public boolean getBoolean(@NotNull String key) { + return getHandle().q(key); // getBoolean + } + + @Override + public int getInt(@NotNull String key) { + return getHandle().h(key); // getInt + } + + @Override + public @NotNull String getString(@NotNull String key) { + return getHandle().l(key); // getString + } + + @Override + public @NotNull CompoundTag getCompound(@NotNull String key) { + return new CompoundTagImpl(getHandle().p(key)); // getCompound + } + + @Override + public @NotNull ListTag getList(@NotNull String key, int type) { + return new ListTagImpl(getHandle().c(key, type)); // getList + } + + @Override + public void setString(@NotNull String key, @NotNull String value) { + getHandle().a(key, value); // setString + } + + @Override + public void setBoolean(@NotNull String key, boolean value) { + getHandle().a(key, value); // setBoolean + } + + @Override + public void setInt(@NotNull String key, int value) { + getHandle().a(key, value); // setInt + } + + @Override + public void set(@NotNull String key, @NotNull Tag value) { + getHandle().a(key, ((TagImpl) value).getHandle()); // set + } + + @Override + public @Nullable Tag get(@NotNull String key) { + return TagImpl.toTag(getHandle().c(key)); // get + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/ListTagImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/ListTagImpl.java new file mode 100644 index 0000000..57e6a4d --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/ListTagImpl.java @@ -0,0 +1,44 @@ +package net.azisaba.loreeditor.v1_20.item.tag; + +import net.azisaba.loreeditor.api.item.tag.ListTag; +import net.azisaba.loreeditor.api.item.tag.Tag; +import net.azisaba.loreeditor.common.util.Reflected; +import net.minecraft.nbt.NBTTagList; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ListTagImpl extends TagImpl implements ListTag { + public ListTagImpl(NBTTagList handle) { + super(handle); + } + + @Contract("_ -> new") + @Reflected + public static @NotNull ListTagImpl getInstance(@Nullable Object tag) { + if (tag == null) { + return new ListTagImpl(new NBTTagList()); + } + return new ListTagImpl((NBTTagList) tag); + } + + @Override + public @NotNull ListTag constructor() { + return new ListTagImpl(new NBTTagList()); + } + + @Override + public int size() { + return getHandle().size(); + } + + @Override + public @NotNull Tag removeAt(int index) { + return TagImpl.toTag(getHandle().remove(index)); + } + + @Override + public void add(int index, @NotNull Tag tag) { + getHandle().add(index, ((TagImpl) tag).getHandle()); + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/StringTagImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/StringTagImpl.java new file mode 100644 index 0000000..c92dba3 --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/StringTagImpl.java @@ -0,0 +1,26 @@ +package net.azisaba.loreeditor.v1_20.item.tag; + +import net.azisaba.loreeditor.api.item.tag.StringTag; +import net.minecraft.nbt.NBTTagString; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class StringTagImpl extends TagImpl implements StringTag { + public StringTagImpl(@NotNull NBTTagString handle) { + super(handle); + } + + @Contract("_ -> new") + public static @NotNull StringTagImpl getInstance(@Nullable Object handle) { + if (handle == null) { + return new StringTagImpl(NBTTagString.a("")); + } + return new StringTagImpl((NBTTagString) handle); + } + + @Override + public @NotNull StringTag valueOf(@NotNull String text) { + return getInstance(NBTTagString.a(text)); + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/TagImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/TagImpl.java new file mode 100644 index 0000000..a9c9963 --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/item/tag/TagImpl.java @@ -0,0 +1,66 @@ +package net.azisaba.loreeditor.v1_20.item.tag; + +import net.azisaba.loreeditor.api.item.tag.Tag; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +public class TagImpl implements Tag { + private final T handle; + + public TagImpl(@NotNull T handle) { + this.handle = Objects.requireNonNull(handle, "handle"); + } + + public @NotNull T getHandle() { + return Objects.requireNonNull(handle); + } + + @Contract("null -> null; !null -> !null") + public static Tag toTag(@Nullable NBTBase handle) { + if (handle == null) { + return null; + } else if (handle instanceof NBTTagCompound) { + return new CompoundTagImpl((NBTTagCompound) handle); + } else if (handle instanceof NBTTagList) { + return new ListTagImpl((NBTTagList) handle); + } else if (handle instanceof NBTTagString) { + return new StringTagImpl((NBTTagString) handle); + } else { + return new TagImpl<>(handle); + } + } + + @Override + public @NotNull String asString() { + return handle.r_(); // asString + } + + @Override + public String toString() { + return handle.toString(); + } + + @Override + public int hashCode() { + return handle.hashCode(); + } + + @Contract(value = "null -> false", pure = true) + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Tag) && !(obj instanceof NBTBase)) { + return false; + } + if (obj instanceof Tag) { + obj = ((TagImpl) obj).getHandle(); + } + return handle.equals(obj); + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/IServerCommonPacketListenerImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/IServerCommonPacketListenerImpl.java new file mode 100644 index 0000000..4ec34c1 --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/IServerCommonPacketListenerImpl.java @@ -0,0 +1,12 @@ +package net.azisaba.loreeditor.v1_20.network; + +import org.jetbrains.annotations.NotNull; +import xyz.acrylicstyle.util.reflector.CastTo; +import xyz.acrylicstyle.util.reflector.FieldGetter; + +public interface IServerCommonPacketListenerImpl { + @NotNull + @CastTo(NetworkManager.class) + @FieldGetter(value = "c") + NetworkManager getNetworkManager(); +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/NetworkManager.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/NetworkManager.java new file mode 100644 index 0000000..d95925e --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/NetworkManager.java @@ -0,0 +1,11 @@ +package net.azisaba.loreeditor.v1_20.network; + +import io.netty.channel.Channel; +import org.jetbrains.annotations.NotNull; +import xyz.acrylicstyle.util.reflector.FieldGetter; + +public interface NetworkManager { + @NotNull + @FieldGetter("n") + Channel getChannel(); +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/ServerCommonPacketListenerImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/ServerCommonPacketListenerImpl.java new file mode 100644 index 0000000..a91191b --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/ServerCommonPacketListenerImpl.java @@ -0,0 +1,21 @@ +package net.azisaba.loreeditor.v1_20.network; + +import net.azisaba.loreeditor.api.util.ReflectionUtil; +import org.jetbrains.annotations.NotNull; +import xyz.acrylicstyle.util.reflector.CastTo; +import xyz.acrylicstyle.util.reflector.FieldGetter; +import xyz.acrylicstyle.util.reflector.Reflector; +import xyz.acrylicstyle.util.reflector.ReflectorHandler; + +public class ServerCommonPacketListenerImpl { + private final IServerCommonPacketListenerImpl reflector; + + public ServerCommonPacketListenerImpl(Object o) { + this.reflector = Reflector.newReflector(null, IServerCommonPacketListenerImpl.class, + new ReflectorHandler(ReflectionUtil.getNMSClass("net.minecraft.server.network.ServerCommonPacketListenerImpl"), o)); + } + + public @NotNull NetworkManager getNetworkManager() { + return reflector.getNetworkManager(); + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ClientboundSetSlotImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ClientboundSetSlotImpl.java new file mode 100644 index 0000000..d1df6ea --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ClientboundSetSlotImpl.java @@ -0,0 +1,32 @@ +package net.azisaba.loreeditor.v1_20.network.packet; + +import net.azisaba.loreeditor.api.item.ItemStack; +import net.azisaba.loreeditor.api.util.ReflectionUtil; +import net.azisaba.loreeditor.common.network.packet.ClientboundSetSlot; +import net.azisaba.loreeditor.v1_20.item.ItemStackImpl; +import net.minecraft.network.protocol.game.PacketPlayOutSetSlot; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ClientboundSetSlotImpl implements ClientboundSetSlot { + private final PacketPlayOutSetSlot handle; + + public ClientboundSetSlotImpl(PacketPlayOutSetSlot handle) { + this.handle = handle; + } + + @Contract(value = "_ -> new", pure = true) + public static @NotNull ClientboundSetSlotImpl getInstance(@NotNull Object handle) { + return new ClientboundSetSlotImpl((PacketPlayOutSetSlot) handle); + } + + public @NotNull PacketPlayOutSetSlot getHandle() { + return handle; + } + + @Override + public @Nullable ItemStack getItem() { + return ItemStackImpl.getInstance(ReflectionUtil.getField(handle, "f")); + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ClientboundWindowItemsImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ClientboundWindowItemsImpl.java new file mode 100644 index 0000000..181d5f4 --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ClientboundWindowItemsImpl.java @@ -0,0 +1,38 @@ +package net.azisaba.loreeditor.v1_20.network.packet; + +import net.azisaba.loreeditor.api.item.ItemStack; +import net.azisaba.loreeditor.api.util.ReflectionUtil; +import net.azisaba.loreeditor.common.network.packet.ClientboundWindowItems; +import net.azisaba.loreeditor.v1_20.item.ItemStackImpl; +import net.minecraft.network.protocol.game.PacketPlayOutWindowItems; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class ClientboundWindowItemsImpl implements ClientboundWindowItems { + private final PacketPlayOutWindowItems handle; + + public ClientboundWindowItemsImpl(@NotNull PacketPlayOutWindowItems handle) { + this.handle = handle; + } + + @Contract(value = "_ -> new", pure = true) + public static @NotNull ClientboundWindowItemsImpl getInstance(Object handle) { + return new ClientboundWindowItemsImpl((PacketPlayOutWindowItems) handle); + } + + public @NotNull PacketPlayOutWindowItems getHandle() { + return handle; + } + + @Override + public @NotNull List getItems() { + List items = new ArrayList<>(); + for (Object o : ((List) ReflectionUtil.getField(getHandle(), "c"))) { + items.add(ItemStackImpl.getInstance(o)); + } + return items; + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ServerboundClickContainerSlotImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ServerboundClickContainerSlotImpl.java new file mode 100644 index 0000000..778501a --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ServerboundClickContainerSlotImpl.java @@ -0,0 +1,29 @@ +package net.azisaba.loreeditor.v1_20.network.packet; + +import net.azisaba.loreeditor.api.item.ItemStack; +import net.azisaba.loreeditor.common.network.packet.ServerboundClickContainerSlot; +import net.azisaba.loreeditor.v1_20.item.ItemStackImpl; +import net.minecraft.network.protocol.game.PacketPlayInWindowClick; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +public class ServerboundClickContainerSlotImpl implements ServerboundClickContainerSlot { + private final PacketPlayInWindowClick handle; + + public ServerboundClickContainerSlotImpl(@NotNull PacketPlayInWindowClick handle) { + this.handle = Objects.requireNonNull(handle, "handle"); + } + + @Contract(value = "_ -> new", pure = true) + public static @NotNull ServerboundClickContainerSlotImpl getInstance(@NotNull Object handle) { + return new ServerboundClickContainerSlotImpl((PacketPlayInWindowClick) handle); + } + + @Override + public @Nullable ItemStack getItem() { + return ItemStackImpl.getInstance(handle.f()); + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ServerboundSetCreativeSlotImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ServerboundSetCreativeSlotImpl.java new file mode 100644 index 0000000..cc45858 --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/network/packet/ServerboundSetCreativeSlotImpl.java @@ -0,0 +1,27 @@ +package net.azisaba.loreeditor.v1_20.network.packet; + +import net.azisaba.loreeditor.api.item.ItemStack; +import net.azisaba.loreeditor.common.network.packet.ServerboundSetCreativeSlot; +import net.azisaba.loreeditor.v1_20.item.ItemStackImpl; +import net.minecraft.network.protocol.game.PacketPlayInSetCreativeSlot; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ServerboundSetCreativeSlotImpl implements ServerboundSetCreativeSlot { + private final PacketPlayInSetCreativeSlot handle; + + public ServerboundSetCreativeSlotImpl(PacketPlayInSetCreativeSlot handle) { + this.handle = handle; + } + + @Contract(value = "_ -> new", pure = true) + public static @NotNull ServerboundSetCreativeSlotImpl getInstance(Object handle) { + return new ServerboundSetCreativeSlotImpl((PacketPlayInSetCreativeSlot) handle); + } + + @Override + public @Nullable ItemStack getItem() { + return ItemStackImpl.getInstance(handle.d()); + } +} diff --git a/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/util/ChannelUtilImpl.java b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/util/ChannelUtilImpl.java new file mode 100644 index 0000000..bb5ed09 --- /dev/null +++ b/v1_20/src/main/java/net/azisaba/loreeditor/v1_20/util/ChannelUtilImpl.java @@ -0,0 +1,57 @@ +package net.azisaba.loreeditor.v1_20.util; + +import io.netty.channel.ChannelPipeline; +import net.azisaba.loreeditor.common.network.PacketPreHandler; +import net.azisaba.loreeditor.common.util.ChannelUtil; +import net.azisaba.loreeditor.v1_20.entity.CraftPlayer; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; + +import java.util.NoSuchElementException; + +public class ChannelUtilImpl implements ChannelUtil { + @Override + public void inject(@NotNull Plugin plugin, @NotNull Player player) { + try { + CraftPlayer.getInstance(player) + .getHandle() + .getPlayerConnection() + .getNetworkManager() + .getChannel() + .pipeline() + .addBefore("packet_handler", "loreeditor", new PacketPreHandler(plugin, player)); + plugin.getLogger().info("Injected packet handler for " + player.getName()); + } catch (NoSuchElementException e) { + Bukkit.getScheduler().runTaskLater(plugin, () -> { + if (!player.isOnline()) return; + try { + CraftPlayer.getInstance(player) + .getHandle() + .getPlayerConnection() + .getNetworkManager() + .getChannel() + .pipeline() + .addBefore("packet_handler", "loreeditor", new PacketPreHandler(plugin, player)); + plugin.getLogger().info("Injected packet handler for " + player.getName()); + } catch (NoSuchElementException ignore) { + plugin.getLogger().warning("Failed to inject packet handler to " + player.getName()); + } + }, 10); + } + } + + @Override + public void eject(@NotNull Player player) { + try { + ChannelPipeline pipeline = CraftPlayer.getInstance(player) + .getHandle() + .getPlayerConnection() + .getNetworkManager() + .getChannel() + .pipeline(); + if (pipeline.get("loreeditor") != null) pipeline.remove("loreeditor"); + } catch (RuntimeException ignore) {} + } +}