diff --git a/InvUI/pom.xml b/InvUI/pom.xml index 6702b69..e0e4360 100644 --- a/InvUI/pom.xml +++ b/InvUI/pom.xml @@ -7,7 +7,7 @@ de.studiocode.invui InvUI-Parent - 0.4-SNAPSHOT + 0.5-SNAPSHOT ../pom.xml @@ -40,47 +40,52 @@ de.studiocode.invui IA - 0.4-SNAPSHOT + 0.5-SNAPSHOT de.studiocode.invui IA-R1 - 0.4-SNAPSHOT + 0.5-SNAPSHOT de.studiocode.invui IA-R2 - 0.4-SNAPSHOT + 0.5-SNAPSHOT de.studiocode.invui IA-R3 - 0.4-SNAPSHOT + 0.5-SNAPSHOT de.studiocode.invui IA-R4 - 0.4-SNAPSHOT + 0.5-SNAPSHOT de.studiocode.invui IA-R5 - 0.4-SNAPSHOT + 0.5-SNAPSHOT de.studiocode.invui IA-R6 - 0.4-SNAPSHOT + 0.5-SNAPSHOT de.studiocode.invui IA-R7 - 0.4-SNAPSHOT + 0.5-SNAPSHOT de.studiocode.invui IA-R8 - 0.4-SNAPSHOT + 0.5-SNAPSHOT + + + de.studiocode.invui + IA-R9 + 0.5-SNAPSHOT diff --git a/InventoryAccess/IA-R1/pom.xml b/InventoryAccess/IA-R1/pom.xml index 5fde265..a7bdfbb 100644 --- a/InventoryAccess/IA-R1/pom.xml +++ b/InventoryAccess/IA-R1/pom.xml @@ -5,7 +5,7 @@ de.studiocode.invui InvUI-Parent - 0.4-SNAPSHOT + 0.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/InventoryAccess/IA-R2/pom.xml b/InventoryAccess/IA-R2/pom.xml index 6010950..2236af5 100644 --- a/InventoryAccess/IA-R2/pom.xml +++ b/InventoryAccess/IA-R2/pom.xml @@ -5,7 +5,7 @@ de.studiocode.invui InvUI-Parent - 0.4-SNAPSHOT + 0.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/InventoryAccess/IA-R3/pom.xml b/InventoryAccess/IA-R3/pom.xml index 05afd9e..20b4830 100644 --- a/InventoryAccess/IA-R3/pom.xml +++ b/InventoryAccess/IA-R3/pom.xml @@ -5,7 +5,7 @@ de.studiocode.invui InvUI-Parent - 0.4-SNAPSHOT + 0.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/InventoryAccess/IA-R4/pom.xml b/InventoryAccess/IA-R4/pom.xml index 54e0f2e..ff03a5b 100644 --- a/InventoryAccess/IA-R4/pom.xml +++ b/InventoryAccess/IA-R4/pom.xml @@ -5,7 +5,7 @@ de.studiocode.invui InvUI-Parent - 0.4-SNAPSHOT + 0.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/InventoryAccess/IA-R5/pom.xml b/InventoryAccess/IA-R5/pom.xml index 08d1e4b..aba9c10 100644 --- a/InventoryAccess/IA-R5/pom.xml +++ b/InventoryAccess/IA-R5/pom.xml @@ -5,7 +5,7 @@ de.studiocode.invui InvUI-Parent - 0.4-SNAPSHOT + 0.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/InventoryAccess/IA-R6/pom.xml b/InventoryAccess/IA-R6/pom.xml index cb73950..42697a8 100644 --- a/InventoryAccess/IA-R6/pom.xml +++ b/InventoryAccess/IA-R6/pom.xml @@ -5,7 +5,7 @@ de.studiocode.invui InvUI-Parent - 0.4-SNAPSHOT + 0.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/InventoryAccess/IA-R7/pom.xml b/InventoryAccess/IA-R7/pom.xml index ef599d4..dd45ffb 100644 --- a/InventoryAccess/IA-R7/pom.xml +++ b/InventoryAccess/IA-R7/pom.xml @@ -5,7 +5,7 @@ de.studiocode.invui InvUI-Parent - 0.4-SNAPSHOT + 0.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/InventoryAccess/IA-R8/pom.xml b/InventoryAccess/IA-R8/pom.xml index 563c8da..27e02a8 100644 --- a/InventoryAccess/IA-R8/pom.xml +++ b/InventoryAccess/IA-R8/pom.xml @@ -5,7 +5,7 @@ de.studiocode.invui InvUI-Parent - 0.4-SNAPSHOT + 0.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/InventoryAccess/IA-R9/pom.xml b/InventoryAccess/IA-R9/pom.xml new file mode 100644 index 0000000..1c73897 --- /dev/null +++ b/InventoryAccess/IA-R9/pom.xml @@ -0,0 +1,177 @@ + + + + de.studiocode.invui + InvUI-Parent + 0.5-SNAPSHOT + ../../pom.xml + + 4.0.0 + + IA-R9 + + + 17 + 17 + 1.18.2-R0.1-SNAPSHOT + + + + + org.spigotmc + spigot + ${spigot.version} + remapped-mojang + provided + + + de.studiocode.invui + IA + ${project.parent.version} + + + + + + + xyz.xenondevs + string-remapper-maven-plugin + 0.1-SNAPSHOT + + + + remap-spigot + + remap + + + spigot + string-remapper-sources/spigot + org.spigotmc:minecraft-server:txt:maps-mojang:${spigot.version} + + org.spigotmc:minecraft-server:csrg:maps-spigot:${spigot.version} + org.spigotmc:minecraft-server:csrg:maps-spigot-members:${spigot.version} + + + + + + remap-mojang + + remap + + + mojang + string-remapper-sources/mojang + org.spigotmc:minecraft-server:txt:maps-mojang:${spigot.version} + + org.spigotmc:minecraft-server:csrg:maps-spigot:${spigot.version} + org.spigotmc:minecraft-server:csrg:maps-spigot-members:${spigot.version} + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + + default-compile + none + + + compile-spigot + + compile + + + ${project.build.directory}/string-remapper-sources/spigot + ${project.build.directory}/classes/spigot + + + + compile-mojang + + compile + + + ${project.build.directory}/string-remapper-sources/mojang + ${project.build.directory}/classes/mojang + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.2 + + + default-jar + none + + + spigot + + jar + + + ${project.build.directory}/classes/spigot + + + + mojang + + jar + + + ${project.build.directory}/classes/mojang + remapped-mojang + + + + + + + net.md-5 + specialsource-maven-plugin + 1.2.2 + + + package + + remap + + remap-obf + + org.spigotmc:minecraft-server:${spigot.version}:txt:maps-mojang + true + org.spigotmc:spigot:${spigot.version}:jar:remapped-mojang + false + ${project.artifactId}-${project.version}-remapped-obf + + + + package + + remap + + remap-spigot + + ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar + org.spigotmc:minecraft-server:${spigot.version}:csrg:maps-spigot + org.spigotmc:spigot:${spigot.version}:jar:remapped-obf + + + + + + + + \ No newline at end of file diff --git a/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/inventory/AnvilInventoryImpl.java b/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/inventory/AnvilInventoryImpl.java new file mode 100644 index 0000000..fa75304 --- /dev/null +++ b/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/inventory/AnvilInventoryImpl.java @@ -0,0 +1,189 @@ +package de.studiocode.inventoryaccess.r9.inventory; + +import de.studiocode.inventoryaccess.abstraction.inventory.AnvilInventory; +import de.studiocode.inventoryaccess.r9.util.InventoryUtilsImpl; +import net.md_5.bungee.api.chat.BaseComponent; +import net.minecraft.core.BlockPos; +import net.minecraft.core.NonNullList; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket; +import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; +import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.AnvilMenu; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.ItemStack; +import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_18_R2.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventoryView; +import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; +import org.bukkit.event.inventory.PrepareAnvilEvent; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Consumer; + +public class AnvilInventoryImpl extends AnvilMenu implements AnvilInventory { + + private final Component title; + private final Consumer renameHandler; + private final CraftInventoryView view; + private final ServerPlayer player; + + private String text; + private boolean open; + + public AnvilInventoryImpl(org.bukkit.entity.Player player, @NotNull BaseComponent[] title, Consumer renameHandler) { + this(((CraftPlayer) player).getHandle(), InventoryUtilsImpl.createNMSComponent(title), renameHandler); + } + + public AnvilInventoryImpl(ServerPlayer player, Component title, Consumer renameHandler) { + super(player.nextContainerCounter(), player.getInventory(), + ContainerLevelAccess.create(player.level, new BlockPos(0, 0, 0))); + + this.title = title; + this.renameHandler = renameHandler; + this.player = player; + + CraftInventoryAnvil inventory = new CraftInventoryAnvil(access.getLocation(), + inputSlots, resultSlots, this); + this.view = new CraftInventoryView(player.getBukkitEntity(), inventory, this); + } + + public void open() { + open = true; + + // call the InventoryOpenEvent + CraftEventFactory.callInventoryOpenEvent(player, this); + + // set active container + player.containerMenu = this; + + // send open packet + player.connection.send(new ClientboundOpenScreenPacket(containerId, MenuType.ANVIL, title)); + + // send initial items + NonNullList itemsList = NonNullList.of(ItemStack.EMPTY, getItem(0), getItem(1), getItem(2)); + player.connection.send(new ClientboundContainerSetContentPacket(getActiveWindowId(player), incrementStateId(), itemsList, ItemStack.EMPTY)); + + // init menu + player.initMenu(this); + } + + public void sendItem(int slot) { + player.connection.send(new ClientboundContainerSetSlotPacket(getActiveWindowId(player), slot, incrementStateId(), getItem(slot))); + } + + public void setItem(int slot, ItemStack item) { + if (slot < 2) inputSlots.setItem(slot, item); + else resultSlots.setItem(0, item); + + if (open) sendItem(slot); + } + + private ItemStack getItem(int slot) { + if (slot < 2) return inputSlots.getItem(slot); + else return resultSlots.getItem(0); + } + + private int getActiveWindowId(ServerPlayer player) { + AbstractContainerMenu container = player.containerMenu; + return container == null ? -1 : container.containerId; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack itemStack) { + setItem(slot, CraftItemStack.asNMSCopy(itemStack)); + } + + @Override + public @NotNull Inventory getBukkitInventory() { + return view.getTopInventory(); + } + + @Override + public String getRenameText() { + return text; + } + + @Override + public boolean isOpen() { + return open; + } + + // --- AnvilMenu --- + + @Override + public CraftInventoryView getBukkitView() { + return view; + } + + /** + * Called every tick to see if the {@link Player} can still use that container. + * (Used to for checking the distance between the {@link Player} and the container + * and closing the window when the distance gets too big.) + * + * @param player The {@link Player} + * @return If the {@link Player} can still use that container + */ + @Override + public boolean stillValid(Player player) { + return true; + } + + /** + * Called when the rename text gets changed. + * + * @param s The new rename text + */ + @Override + public void setItemName(String s) { + // save rename text + text = s; + + // call the rename handler + if (renameHandler != null) renameHandler.accept(s); + + // the client expects the item to change to it's new name and removes it from the inventory, so it needs to be sent again + sendItem(2); + } + + /** + * Called when the container is closed to give the items back. + * + * @param player The {@link Player} that closed this container + */ + @Override + public void removed(Player player) { + open = false; + } + + + /** + * Called when the container gets closed to put items back into a players + * inventory or drop them in the world. + * + * @param player The {@link Player} that closed this container + * @param container The container + */ + @Override + protected void clearContainer(Player player, Container container) { + open = false; + } + + /** + * Called when both items in the {@link AnvilMenu#inputSlots} were set to create + * the resulting product, calculate the level cost and call the {@link PrepareAnvilEvent}. + */ + @Override + public void createResult() { + // empty + } + + +} diff --git a/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/inventory/CartographyInventoryImpl.java b/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/inventory/CartographyInventoryImpl.java new file mode 100644 index 0000000..5cf79b3 --- /dev/null +++ b/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/inventory/CartographyInventoryImpl.java @@ -0,0 +1,138 @@ +package de.studiocode.inventoryaccess.r9.inventory; + +import de.studiocode.inventoryaccess.abstraction.inventory.CartographyInventory; +import de.studiocode.inventoryaccess.r9.util.InventoryUtilsImpl; +import de.studiocode.inventoryaccess.util.ReflectionUtils; +import net.md_5.bungee.api.chat.BaseComponent; +import net.minecraft.core.BlockPos; +import net.minecraft.core.NonNullList; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket; +import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; +import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.*; +import net.minecraft.world.item.ItemStack; +import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_18_R2.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventoryCartography; +import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventoryView; +import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; + +public class CartographyInventoryImpl extends CartographyTableMenu implements CartographyInventory { + + private static final Field RESULT_CONTAINER_FIELD = ReflectionUtils.getField( + CartographyTableMenu.class, + true, + "SRF(net.minecraft.world.inventory.CartographyTableMenu resultContainer)" + ); + + private final ResultContainer resultContainer = ReflectionUtils.getFieldValue(RESULT_CONTAINER_FIELD, this); + private final Component title; + private final CraftInventoryView view; + private final ServerPlayer player; + + private boolean open; + + public CartographyInventoryImpl(Player player, @NotNull BaseComponent[] title) { + this(((CraftPlayer) player).getHandle(), InventoryUtilsImpl.createNMSComponent(title)); + } + + public CartographyInventoryImpl(ServerPlayer player, Component title) { + super(player.nextContainerCounter(), player.getInventory(), ContainerLevelAccess.create(player.level, new BlockPos(0, 0, 0))); + + this.player = player; + this.title = title; + CraftInventoryCartography inventory = new CraftInventoryCartography(container, resultContainer); + view = new CraftInventoryView(player.getBukkitEntity(), inventory, this); + } + + public void open() { + open = true; + + // call the InventoryOpenEvent + CraftEventFactory.callInventoryOpenEvent(player, this); + + // set active container + player.containerMenu = this; + + // send open packet + player.connection.send(new ClientboundOpenScreenPacket(containerId, MenuType.CARTOGRAPHY_TABLE, title)); + + // send initial items + NonNullList itemsList = NonNullList.of(ItemStack.EMPTY, getItem(0), getItem(1), getItem(2)); + player.connection.send(new ClientboundContainerSetContentPacket(InventoryUtilsImpl.getActiveWindowId(player), incrementStateId(), itemsList, ItemStack.EMPTY)); + + // init menu + player.initMenu(this); + } + + @Override + public boolean isOpen() { + return open; + } + + public void sendItem(int slot) { + player.connection.send(new ClientboundContainerSetSlotPacket(InventoryUtilsImpl.getActiveWindowId(player), slot, incrementStateId(), getItem(slot))); + } + + public void setItem(int slot, ItemStack item) { + if (slot < 2) container.setItem(slot, item); + else resultContainer.setItem(0, item); + + if (open) sendItem(slot); + } + + private ItemStack getItem(int slot) { + if (slot < 2) return container.getItem(slot); + else return resultContainer.getItem(0); + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack itemStack) { + setItem(slot, CraftItemStack.asNMSCopy(itemStack)); + } + + @Override + public Inventory getBukkitInventory() { + return view.getTopInventory(); + } + + // --- CartographyTableMenu --- + + @Override + public CraftInventoryView getBukkitView() { + return view; + } + + @Override + public void slotsChanged(Container container) { + } + + @Override + public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player entityhuman, int i) { + return ItemStack.EMPTY; + } + + @Override + public boolean canTakeItemForPickAll(ItemStack itemstack, Slot slot) { + return true; + } + + @Override + public boolean stillValid(net.minecraft.world.entity.player.Player entityhuman) { + return true; + } + + @Override + protected void clearContainer(net.minecraft.world.entity.player.Player entityhuman, Container container) { + // empty + } + +} diff --git a/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/util/InventoryUtilsImpl.java b/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/util/InventoryUtilsImpl.java new file mode 100644 index 0000000..10cba44 --- /dev/null +++ b/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/util/InventoryUtilsImpl.java @@ -0,0 +1,75 @@ +package de.studiocode.inventoryaccess.r9.util; + +import de.studiocode.inventoryaccess.abstraction.util.InventoryUtils; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.chat.ComponentSerializer; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.MenuType; +import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_18_R2.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftContainer; +import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventory; +import org.bukkit.craftbukkit.v1_18_R2.util.CraftChatMessage; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; + +public class InventoryUtilsImpl implements InventoryUtils { + + public static Component createNMSComponent(BaseComponent[] components) { + if (components == null) return null; + + String json = ComponentSerializer.toString(components); + return CraftChatMessage.fromJSON(json); + } + + public static int getActiveWindowId(ServerPlayer player) { + AbstractContainerMenu container = player.containerMenu; + return container == null ? -1 : container.containerId; + } + + @Override + public void openCustomInventory(@NotNull Player player, @NotNull Inventory inventory) { + openCustomInventory(player, inventory, null); + } + + @Override + public void openCustomInventory(@NotNull Player player, @NotNull Inventory inventory, @NotNull BaseComponent[] title) { + ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); + MenuType menuType = CraftContainer.getNotchInventoryType(inventory); + + if (serverPlayer.connection != null) { + AbstractContainerMenu menu = new CraftContainer(inventory, serverPlayer, serverPlayer.nextContainerCounter()); + menu = CraftEventFactory.callInventoryOpenEvent(serverPlayer, menu); + if (menu != null) { + Container container = ((CraftInventory) inventory).getInventory(); + Component titleComponent; + if (title == null) { + if (container instanceof MenuProvider) + titleComponent = ((MenuProvider) container).getDisplayName(); + else titleComponent = CraftChatMessage.fromString(menu.getBukkitView().getTitle())[0]; + } else titleComponent = createNMSComponent(title); + + menu.checkReachable = false; + serverPlayer.connection.send(new ClientboundOpenScreenPacket(menu.containerId, menuType, titleComponent)); + serverPlayer.containerMenu = menu; + serverPlayer.initMenu(menu); + } + } + + } + + @Override + public void updateOpenInventoryTitle(@NotNull Player player, @NotNull BaseComponent[] title) { + ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); + AbstractContainerMenu menu = serverPlayer.containerMenu; + serverPlayer.connection.send(new ClientboundOpenScreenPacket(menu.containerId, menu.getType(), createNMSComponent(title))); + serverPlayer.initMenu(menu); + } + +} diff --git a/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/util/ItemUtilsImpl.java b/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/util/ItemUtilsImpl.java new file mode 100644 index 0000000..e153004 --- /dev/null +++ b/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/util/ItemUtilsImpl.java @@ -0,0 +1,92 @@ +package de.studiocode.inventoryaccess.r9.util; + +import de.studiocode.inventoryaccess.abstraction.util.ItemUtils; +import de.studiocode.inventoryaccess.util.ReflectionRegistry; +import de.studiocode.inventoryaccess.util.ReflectionUtils; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.chat.ComponentSerializer; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.item.ItemStack; +import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; + +import java.io.*; +import java.util.List; +import java.util.stream.Collectors; + +public class ItemUtilsImpl implements ItemUtils { + + @Override + public byte[] serializeItemStack(org.bukkit.inventory.@NotNull ItemStack itemStack, boolean compressed) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + serializeItemStack(itemStack, out, compressed); + return out.toByteArray(); + } + + @Override + public void serializeItemStack(org.bukkit.inventory.@NotNull ItemStack itemStack, @NotNull OutputStream outputStream, boolean compressed) { + try { + ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); + CompoundTag nbt = nmsStack.save(new CompoundTag()); + + if (compressed) { + NbtIo.writeCompressed(nbt, outputStream); + } else { + DataOutputStream dataOut = new DataOutputStream(outputStream); + NbtIo.write(nbt, dataOut); + } + + outputStream.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public org.bukkit.inventory.ItemStack deserializeItemStack(byte[] data, boolean compressed) { + ByteArrayInputStream in = new ByteArrayInputStream(data); + return deserializeItemStack(in, compressed); + } + + @Override + public org.bukkit.inventory.ItemStack deserializeItemStack(@NotNull InputStream inputStream, boolean compressed) { + try { + CompoundTag nbt; + if (compressed) { + nbt = NbtIo.readCompressed(inputStream); + } else { + DataInputStream dataIn = new DataInputStream(inputStream); + nbt = NbtIo.read(dataIn); + } + + ItemStack itemStack = ItemStack.of(nbt); + + return CraftItemStack.asCraftMirror(itemStack); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + @Override + public void setDisplayName(@NotNull ItemMeta itemMeta, BaseComponent[] name) { + ReflectionUtils.setFieldValue( + ReflectionRegistry.CB_CRAFT_META_ITEM_DISPLAY_NAME_FIELD, + itemMeta, + ComponentSerializer.toString(name) + ); + } + + @Override + public void setLore(@NotNull ItemMeta itemMeta, @NotNull List<@NotNull BaseComponent[]> lore) { + ReflectionUtils.setFieldValue( + ReflectionRegistry.CB_CRAFT_META_ITEM_LORE_FIELD, + itemMeta, + lore.stream().map(ComponentSerializer::toString).collect(Collectors.toList()) + ); + } + +} \ No newline at end of file diff --git a/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/util/PlayerUtilsImpl.java b/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/util/PlayerUtilsImpl.java new file mode 100644 index 0000000..d9d7c11 --- /dev/null +++ b/InventoryAccess/IA-R9/src/main/java/de/studiocode/inventoryaccess/r9/util/PlayerUtilsImpl.java @@ -0,0 +1,98 @@ +package de.studiocode.inventoryaccess.r9.util; + +import de.studiocode.inventoryaccess.abstraction.util.PlayerUtils; +import de.studiocode.inventoryaccess.map.MapIcon; +import de.studiocode.inventoryaccess.map.MapPatch; +import de.studiocode.inventoryaccess.util.DataUtils; +import de.studiocode.inventoryaccess.util.ReflectionUtils; +import net.md_5.bungee.api.chat.BaseComponent; +import net.minecraft.network.protocol.game.ClientboundMapItemDataPacket; +import net.minecraft.network.protocol.game.ClientboundResourcePackPacket; +import net.minecraft.server.PlayerAdvancements; +import net.minecraft.server.ServerAdvancementManager; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.saveddata.maps.MapDecoration; +import net.minecraft.world.level.saveddata.maps.MapItemSavedData; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_18_R2.CraftServer; +import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class PlayerUtilsImpl implements PlayerUtils { + + private static final Method REGISTER_LISTENERS_METHOD = ReflectionUtils.getMethod( + PlayerAdvancements.class, + true, + "SRM(net.minecraft.server.PlayerAdvancements registerListeners)", + ServerAdvancementManager.class + ); + + @Override + public void stopAdvancementListening(@NotNull Player player) { + stopAdvancementListening(((CraftPlayer) player).getHandle()); + } + + @Override + public void stopAdvancementListening(@NotNull Object player) { + ((ServerPlayer) player).getAdvancements().stopListening(); + } + + @Override + public void startAdvancementListening(@NotNull Player player) { + startAdvancementListening(((CraftPlayer) player).getHandle()); + } + + @Override + public void startAdvancementListening(@NotNull Object player) { + PlayerAdvancements advancements = ((ServerPlayer) player).getAdvancements(); + ServerAdvancementManager manager = ((CraftServer) Bukkit.getServer()).getServer().getAdvancements(); + ReflectionUtils.invokeMethod(REGISTER_LISTENERS_METHOD, advancements, manager); + } + + @Override + public void sendMapUpdate(@NotNull Player player, int mapId, byte scale, boolean locked, @Nullable MapPatch mapPatch, @Nullable List icons) { + List decorations = icons != null ? icons.stream().map(this::toMapDecoration).collect(Collectors.toCollection(ArrayList::new)) : null; + MapItemSavedData.MapPatch patch = toMapPatch(mapPatch); + ClientboundMapItemDataPacket packet = new ClientboundMapItemDataPacket(mapId, scale, locked, decorations, patch); + ((CraftPlayer) player).getHandle().connection.send(packet); + } + + private MapDecoration toMapDecoration(MapIcon icon) { + return new MapDecoration( + MapDecoration.Type.byIcon(icon.getType().getId()), + icon.getX(), icon.getY(), + icon.getRot(), + icon.getComponents() != null ? InventoryUtilsImpl.createNMSComponent(icon.getComponents()) : null + ); + } + + private MapItemSavedData.MapPatch toMapPatch(MapPatch patch) { + if (patch == null) return null; + + return new MapItemSavedData.MapPatch( + patch.getStartX(), patch.getStartY(), + patch.getWidth(), patch.getHeight(), + patch.getColors() + ); + } + + @Override + public void sendResourcePack(@NotNull Player player, @NotNull String url, byte[] hash, @Nullable BaseComponent[] prompt, boolean force) { + var serverPlayer = ((CraftPlayer) player).getHandle(); + var packet = new ClientboundResourcePackPacket( + url, + DataUtils.toHexadecimalString(hash), + force, + InventoryUtilsImpl.createNMSComponent(prompt) + ); + serverPlayer.connection.connection.send(packet); + } + +} diff --git a/InventoryAccess/IA/pom.xml b/InventoryAccess/IA/pom.xml index f3ad2dd..e819491 100644 --- a/InventoryAccess/IA/pom.xml +++ b/InventoryAccess/IA/pom.xml @@ -5,7 +5,7 @@ de.studiocode.invui InvUI-Parent - 0.4-SNAPSHOT + 0.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/InventoryAccess/IA/src/main/java/de/studiocode/inventoryaccess/version/InventoryAccessRevision.java b/InventoryAccess/IA/src/main/java/de/studiocode/inventoryaccess/version/InventoryAccessRevision.java index d346bf8..a22de7b 100644 --- a/InventoryAccess/IA/src/main/java/de/studiocode/inventoryaccess/version/InventoryAccessRevision.java +++ b/InventoryAccess/IA/src/main/java/de/studiocode/inventoryaccess/version/InventoryAccessRevision.java @@ -5,6 +5,7 @@ import de.studiocode.inventoryaccess.util.VersionUtils; public enum InventoryAccessRevision { // this order is required + R9("r9", "1.18.2"), R8("r8", "1.18.0"), R7("r7", "1.17.1"), R6("r6", "1.17.0"), diff --git a/ResourcePack/pom.xml b/ResourcePack/pom.xml index 88f2aeb..cf36411 100644 --- a/ResourcePack/pom.xml +++ b/ResourcePack/pom.xml @@ -5,7 +5,7 @@ InvUI-Parent de.studiocode.invui - 0.4-SNAPSHOT + 0.5-SNAPSHOT 4.0.0 @@ -33,7 +33,7 @@ de.studiocode.invui InvUI - 0.4-SNAPSHOT + 0.5-SNAPSHOT fr.xephi diff --git a/pom.xml b/pom.xml index cd0d914..8dd959e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ de.studiocode.invui InvUI-Parent - 0.4-SNAPSHOT + 0.5-SNAPSHOT pom @@ -49,6 +49,7 @@ InventoryAccess/IA-R6 InventoryAccess/IA-R7 InventoryAccess/IA-R8 + InventoryAccess/IA-R9 InventoryAccess/IA InvUI ResourcePack