From 4adf3d95fde4bbd02f1b41e37e702316c23fc2c1 Mon Sep 17 00:00:00 2001 From: Straikerinos Date: Thu, 15 Aug 2024 12:09:31 +0200 Subject: [PATCH] Prevention from creating multiple unused nms classes --- .idea/misc.xml | 5 + .../me/devtec/theapi/bukkit/BukkitLoader.java | 27 +- .../src/main/java/v1_20_6.java | 14 +- NmsProvider - 1.21/build/NmsProvider.jar | Bin 37257 -> 0 bytes NmsProvider - 1.21/pom.xml | 83 - NmsProvider - 1.21/src/main/java/v1_21.java | 1694 ----------------- paper-mappings.yml | 3 + 7 files changed, 30 insertions(+), 1796 deletions(-) delete mode 100644 NmsProvider - 1.21/build/NmsProvider.jar delete mode 100644 NmsProvider - 1.21/pom.xml delete mode 100644 NmsProvider - 1.21/src/main/java/v1_21.java create mode 100644 paper-mappings.yml diff --git a/.idea/misc.xml b/.idea/misc.xml index c1f7a0b7..e08605ca 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -25,6 +25,11 @@ + diff --git a/Loader - Bukkit/src/main/java/me/devtec/theapi/bukkit/BukkitLoader.java b/Loader - Bukkit/src/main/java/me/devtec/theapi/bukkit/BukkitLoader.java index f3e00a31..7e442d2d 100644 --- a/Loader - Bukkit/src/main/java/me/devtec/theapi/bukkit/BukkitLoader.java +++ b/Loader - Bukkit/src/main/java/me/devtec/theapi/bukkit/BukkitLoader.java @@ -313,12 +313,21 @@ private void broadcastSystemInfo() { private void loadProvider(boolean canUseJavaFile) throws Exception { String serverVersion = Ref.serverVersion().replace('.', '_'); - if (!serverVersion.startsWith("v")) + if (!serverVersion.startsWith("v")) { + if(Ref.serverType()==ServerType.PAPER && (Ref.isNewerThan(20)||Ref.isNewerThan(19) && Ref.serverVersionRelease()>=6)) { + try { + Config mappings = Config.loadFromInput(new URL("https://raw.githubusercontent.com/TheDevTec/TheAPI/main/paper-mappings.yml").openStream()); + serverVersion = mappings.getString(serverVersion); + }catch(Exception noInternetConnection){ + + } + } serverVersion = 'v' + serverVersion; + } if (ToolProvider.getSystemJavaCompiler() != null && !canUseJavaFile) try { getAllJarFiles(); - checkForUpdateAndDownload(); + checkForUpdateAndDownload(serverVersion); if (new File("plugins/TheAPI/NmsProviders/" + serverVersion + ".java").exists()) { nmsProvider = (NmsProvider) new MemoryCompiler(NO_OBFUSCATED_NMS_MODE ? getClassLoader() : Bukkit.getServer().getClass().getClassLoader(), serverVersion, new File("plugins/TheAPI/NmsProviders/" + serverVersion + ".java")).buildClass().newInstance(); nmsProvider.loadParticles(); @@ -326,7 +335,7 @@ private void loadProvider(boolean canUseJavaFile) throws Exception { } catch (Exception err) { err.printStackTrace(); Bukkit.getConsoleSender().sendMessage(ColorUtils.colorize("&7> &4Error! Failed to load NmsProvider from .java file, loading from .jar.")); - checkForUpdateAndDownloadCompiled(); + checkForUpdateAndDownloadCompiled(serverVersion); if (new File("plugins/TheAPI/NmsProviders/" + serverVersion + ".jar").exists()) try (URLClassLoader cl = new URLClassLoader(new URL[]{new URL("jar:file:" + "plugins/TheAPI/NmsProviders/" + serverVersion + ".jar" + "!/")}, getClassLoader())) { Class c = cl.loadClass(serverVersion); @@ -337,7 +346,7 @@ private void loadProvider(boolean canUseJavaFile) throws Exception { } } else { // JRE - checkForUpdateAndDownloadCompiled(); + checkForUpdateAndDownloadCompiled(serverVersion); if (new File("plugins/TheAPI/NmsProviders/" + serverVersion + ".jar").exists()) try (URLClassLoader cl = new URLClassLoader(new URL[]{new URL("jar:file:" + "plugins/TheAPI/NmsProviders/" + serverVersion + ".jar" + "!/")}, getClassLoader())) { Class c = cl.loadClass(serverVersion); @@ -485,10 +494,7 @@ public void onDisable() { API.offlineCache().saveToConfig().setFile(new File("plugins/TheAPI/Cache.dat")).save("properties"); } - private void checkForUpdateAndDownloadCompiled() { - String serverVersion = Ref.serverVersion().replace('.', '_'); - if (!serverVersion.startsWith("v")) - serverVersion = 'v' + serverVersion; + private void checkForUpdateAndDownloadCompiled(String serverVersion) { try { Config gitVersion = Config.loadFromInput(new URL("https://raw.githubusercontent.com/TheDevTec/TheAPI/main/version.yml").openStream()); Config localVersion = new Config("plugins/TheAPI/version.yml"); @@ -519,10 +525,7 @@ private Version getGitVersion(Config localVersion, Config gitVersion) { return VersionUtils.getVersion(gitVersion.getString("release"), "" + release); } - private void checkForUpdateAndDownload() { - String serverVersion = Ref.serverVersion().replace('.', '_'); - if (!serverVersion.startsWith("v")) - serverVersion = 'v' + serverVersion; + private void checkForUpdateAndDownload(String serverVersion) { try { Config gitVersion = Config.loadFromInput(new URL("https://raw.githubusercontent.com/TheDevTec/TheAPI/main/version.yml").openStream()); Config localVersion = new Config("plugins/TheAPI/version.yml"); diff --git a/NmsProvider - 1.20.6/src/main/java/v1_20_6.java b/NmsProvider - 1.20.6/src/main/java/v1_20_6.java index 786cb679..d95d7b70 100644 --- a/NmsProvider - 1.20.6/src/main/java/v1_20_6.java +++ b/NmsProvider - 1.20.6/src/main/java/v1_20_6.java @@ -229,17 +229,17 @@ public Object packetEntityDestroy(int... ids) { @Override public Object packetSpawnEntity(Object entity, int id) { - return new ClientboundAddEntityPacket((net.minecraft.world.entity.Entity) entity, id); + return new ClientboundAddEntityPacket((net.minecraft.world.entity.Entity) entity, id, ((net.minecraft.world.entity.Entity) entity).blockPosition()); } @Override public Object packetNamedEntitySpawn(Object player) { - return new ClientboundAddEntityPacket((net.minecraft.world.entity.player.Player) player); + return new ClientboundAddEntityPacket((net.minecraft.world.entity.player.Player) player,0, ((net.minecraft.world.entity.Entity) player).blockPosition()); } @Override public Object packetSpawnEntityLiving(Object entityLiving) { - return new ClientboundAddEntityPacket((net.minecraft.world.entity.LivingEntity) entityLiving); + return new ClientboundAddEntityPacket((net.minecraft.world.entity.LivingEntity) entityLiving, 0, ((net.minecraft.world.entity.LivingEntity) entityLiving).blockPosition()); } @Override @@ -340,7 +340,7 @@ private net.minecraft.network.chat.Component convert(Component c) { try { ComponentEntity compoundTag = (ComponentEntity) c.getHoverEvent().getValue(); net.minecraft.network.chat.Component component = compoundTag.getName() == null ? null : (net.minecraft.network.chat.Component) toIChatBaseComponent(compoundTag.getName()); - EntityType entityType = BuiltInRegistries.ENTITY_TYPE.get(new ResourceLocation(compoundTag.getType())); + EntityType entityType = BuiltInRegistries.ENTITY_TYPE.get(ResourceLocation.tryParse(compoundTag.getType())); modif = modif.withHoverEvent(new net.minecraft.network.chat.HoverEvent(net.minecraft.network.chat.HoverEvent.Action.SHOW_ENTITY, new net.minecraft.network.chat.HoverEvent.EntityTooltipInfo(entityType, compoundTag.getId(), component))); } catch (Exception commandSyntaxException) { @@ -1402,8 +1402,8 @@ public boolean processServerListPing(String player, Object channel, Object packe BufferedImage var1; try { var1 = ImageIO.read(new File(event.getFavicon())); - Preconditions.checkState(var1.getWidth() == 64, "Must be 64 pixels wide"); - Preconditions.checkState(var1.getHeight() == 64, "Must be 64 pixels high"); + if (var1.getWidth() != 64) throw new IOException("Must be 64 pixels wide"); + if (var1.getHeight() != 64) throw new IOException("Must be 64 pixels high"); ByteArrayOutputStream var2 = new ByteArrayOutputStream(); ImageIO.write(var1, "PNG", var2); serverIcon = Optional.of(new Favicon(var2.toByteArray())); @@ -1652,7 +1652,7 @@ public Object packetRespawn(Player player) { @Override public String getProviderName() { - return "PaperMC 1.20.6"; + return "PaperMC (1.20.6) "+Bukkit.getMinecraftVersion(); } @Override diff --git a/NmsProvider - 1.21/build/NmsProvider.jar b/NmsProvider - 1.21/build/NmsProvider.jar deleted file mode 100644 index b3b7b3ed479aaf6d65531eef565520b5f747c6e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37257 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

}Hbu4+Nmjs9vw{2uV*{L;q#UIWJYk?rQ{W5bWg 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 - - 4.0.0 - - me.devtec.theapi.loaders - TheAPI - 12.9.7 - - - NmsProvider-1.21 - 12.9.7 - - - UTF-8 - - - - bytecode.space - https://repo.bytecode.space/repository/maven-public/ - - - - src/main/java - - - resources - - **/*.java - - - - - - ca.bkaw - paper-nms-maven-plugin - 1.4.4 - - - maven-compiler-plugin - 3.13.0 - - 17 - - - - org.apache.maven.plugins - maven-jar-plugin - 3.4.2 - - ${project.basedir}/build/ - NmsProvider - - - - - - - ca.bkaw - paper-nms - 1.21-SNAPSHOT - provided - - - com.google.guava - guava - 33.2.1-jre - - - org.spigotmc - spigot-api - 1.21-R0.1-SNAPSHOT - provided - - - me.devtec.theapi.loaders - Loader-Bukkit - 12.9.7 - provided - - - \ No newline at end of file diff --git a/NmsProvider - 1.21/src/main/java/v1_21.java b/NmsProvider - 1.21/src/main/java/v1_21.java deleted file mode 100644 index ac748b95..00000000 --- a/NmsProvider - 1.21/src/main/java/v1_21.java +++ /dev/null @@ -1,1694 +0,0 @@ -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; -import io.netty.channel.Channel; -import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; -import me.devtec.shared.Pair; -import me.devtec.shared.Ref; -import me.devtec.shared.components.*; -import me.devtec.shared.events.EventManager; -import me.devtec.shared.json.Json; -import me.devtec.shared.utility.ParseUtils; -import me.devtec.theapi.bukkit.BukkitLoader; -import me.devtec.theapi.bukkit.events.ServerListPingEvent; -import me.devtec.theapi.bukkit.game.BlockDataStorage; -import me.devtec.theapi.bukkit.gui.AnvilGUI; -import me.devtec.theapi.bukkit.gui.GUI.ClickType; -import me.devtec.theapi.bukkit.gui.HolderGUI; -import me.devtec.theapi.bukkit.nms.GameProfileHandler; -import me.devtec.theapi.bukkit.nms.GameProfileHandler.PropertyHandler; -import me.devtec.theapi.bukkit.nms.NBTEdit; -import me.devtec.theapi.bukkit.nms.NmsProvider; -import me.devtec.theapi.bukkit.nms.utils.InventoryUtils; -import me.devtec.theapi.bukkit.nms.utils.InventoryUtils.DestinationType; -import me.devtec.theapi.bukkit.packetlistener.PacketContainer; -import me.devtec.theapi.bukkit.xseries.XMaterial; -import net.minecraft.ChatFormatting; -import net.minecraft.commands.CommandBuildContext; -import net.minecraft.commands.Commands; -import net.minecraft.core.BlockPos; -import net.minecraft.core.component.DataComponents; -import net.minecraft.core.particles.ParticleType; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.data.registries.VanillaRegistries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; -import net.minecraft.nbt.TagParser; -import net.minecraft.network.Connection; -import net.minecraft.network.chat.HoverEvent.EntityTooltipInfo; -import net.minecraft.network.chat.HoverEvent.ItemStackInfo; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.Style; -import net.minecraft.network.chat.TextColor; -import net.minecraft.network.protocol.common.ClientboundResourcePackPushPacket; -import net.minecraft.network.protocol.game.*; -import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; -import net.minecraft.network.protocol.status.ServerStatus; -import net.minecraft.network.protocol.status.ServerStatus.Favicon; -import net.minecraft.network.protocol.status.ServerStatus.Players; -import net.minecraft.network.protocol.status.ServerStatus.Version; -import net.minecraft.network.syncher.SynchedEntityData; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerCommonPacketListenerImpl; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.inventory.*; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.component.CustomData; -import net.minecraft.world.level.GameType; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.FallingBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.StateHolder; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LevelChunk.EntityCreationType; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.chunk.status.ChunkStatus; -import net.minecraft.world.scores.DisplaySlot; -import net.minecraft.world.scores.Objective; -import net.minecraft.world.scores.criteria.ObjectiveCriteria; -import org.bukkit.*; -import org.bukkit.block.BlockState; -import org.bukkit.craftbukkit.CraftChunk; -import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.block.data.CraftBlockData; -import org.bukkit.craftbukkit.entity.CraftEntity; -import org.bukkit.craftbukkit.entity.CraftLivingEntity; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.craftbukkit.inventory.CraftContainer; -import org.bukkit.craftbukkit.inventory.CraftItemStack; -import org.bukkit.craftbukkit.util.CraftMagicNumbers; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryView; -import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.java.JavaPlugin; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.net.InetSocketAddress; -import java.util.*; -import java.util.Map.Entry; -import java.util.function.BiFunction; -import java.util.stream.Collectors; - -public class v1_21 implements NmsProvider { - private static final MinecraftServer server = MinecraftServer.getServer(); - private static final net.minecraft.network.chat.Component empty = net.minecraft.network.chat.Component.literal(""); - private static final CommandBuildContext dispatcher = Commands.createValidationContext(VanillaRegistries.createLookup()); - - @Override - public Collection getOnlinePlayers() { - return Bukkit.getOnlinePlayers(); - } - - @Override - public Object getEntity(Entity entity) { - return ((CraftEntity) entity).getHandle(); - } - - @Override - public Object getEntityLiving(LivingEntity entity) { - return ((CraftLivingEntity) entity).getHandle(); - } - - @Override - public Object getPlayer(Player player) { - return ((CraftPlayer) player).getHandle(); - } - - @Override - public Object getWorld(World world) { - return ((CraftWorld) world).getHandle(); - } - - @Override - public Object getChunk(Chunk chunk) { - return ((CraftChunk) chunk).getHandle(ChunkStatus.FULL); - } - - @Override - public int getEntityId(Object entity) { - return ((net.minecraft.world.entity.Entity) entity).getId(); - } - - @Override - public Object getScoreboardAction(Action type) { - return type == Action.CHANGE ? ClientboundSetPlayerTeamPacket.Action.ADD : ClientboundSetPlayerTeamPacket.Action.REMOVE; - } - - @Override - public Object getEnumScoreboardHealthDisplay(DisplayType type) { - return type == DisplayType.INTEGER ? ObjectiveCriteria.RenderType.INTEGER : ObjectiveCriteria.RenderType.HEARTS; - } - - @Override - public Object getNBT(ItemStack itemStack) { - net.minecraft.world.item.ItemStack item = (net.minecraft.world.item.ItemStack) asNMSItem(itemStack); - if (item.isEmpty()) - return new CompoundTag(); - CustomData data = item.get(DataComponents.CUSTOM_DATA); - if (data != null) - return data.copyTag(); - return null; - } - - @Override - public Object parseNBT(String json) { - if (json == null) - return new CompoundTag(); - try { - return TagParser.parseTag(json); - } catch (Exception e) { - return new CompoundTag(); - } - } - - @Override - public ItemStack setNBT(ItemStack stack, Object nbt) { - if (nbt instanceof NBTEdit) - nbt = ((NBTEdit) nbt).getNBT(); - net.minecraft.world.item.ItemStack item = (net.minecraft.world.item.ItemStack) asNMSItem(stack); - item.set(DataComponents.CUSTOM_DATA, CustomData.of((CompoundTag) nbt)); - return asBukkitItem(item); - } - - @Override - public Object asNMSItem(ItemStack stack) { - if (stack == null) - return net.minecraft.world.item.ItemStack.EMPTY; - return CraftItemStack.asNMSCopy(stack); - } - - @Override - public ItemStack asBukkitItem(Object stack) { - return CraftItemStack.asBukkitCopy(stack == null ? net.minecraft.world.item.ItemStack.EMPTY : (net.minecraft.world.item.ItemStack) stack); - } - - @Override - public int getContainerId(Object container) { - return ((AbstractContainerMenu) container).containerId; - } - - @Override - public Object packetResourcePackSend(String url, String hash, boolean requireRP, Component prompt) { - return new ClientboundResourcePackPushPacket(UUID.randomUUID(), url, hash, requireRP, - prompt == null ? Optional.empty() : Optional.of((net.minecraft.network.chat.Component) this.toIChatBaseComponent(prompt))); - } - - @Override - public Object packetSetSlot(int container, int slot, int changeId, Object itemStack) { - return new ClientboundContainerSetSlotPacket(container, changeId, slot, (net.minecraft.world.item.ItemStack) (itemStack == null ? asNMSItem(null) : itemStack)); - } - - @Override - public Object packetEntityMetadata(int entityId, Object dataWatcher, boolean bal) { - return new ClientboundSetEntityDataPacket(entityId, ((SynchedEntityData) dataWatcher).packAll()); - } - - @Override - public Object packetEntityDestroy(int... ids) { - return new ClientboundRemoveEntitiesPacket(ids); - } - - @Override - public Object packetSpawnEntity(Object entity, int id) { - return new ClientboundAddEntityPacket((net.minecraft.world.entity.Entity) entity, id, ((net.minecraft.world.entity.Entity) entity).blockPosition()); - } - - @Override - public Object packetNamedEntitySpawn(Object player) { - return new ClientboundAddEntityPacket((net.minecraft.world.entity.player.Player) player, 0, ((net.minecraft.world.entity.Entity) player).blockPosition()); - } - - @Override - public Object packetSpawnEntityLiving(Object entityLiving) { - return new ClientboundAddEntityPacket((net.minecraft.world.entity.LivingEntity) entityLiving, 0, ((net.minecraft.world.entity.LivingEntity) entityLiving).blockPosition()); - } - - @Override - public Object packetPlayerListHeaderFooter(Component header, Component footer) { - return new ClientboundTabListPacket((net.minecraft.network.chat.Component) toIChatBaseComponent(header), (net.minecraft.network.chat.Component) this.toIChatBaseComponent(footer)); - } - - @Override - public Object packetBlockChange(int x, int y, int z, Object iblockdata, int data) { - return new ClientboundBlockUpdatePacket(new BlockPos(x, y, z), iblockdata == null ? Blocks.AIR.defaultBlockState() : (net.minecraft.world.level.block.state.BlockState) iblockdata); - } - - @Override - public Object packetScoreboardObjective() { - return Ref.newUnsafeInstance(ClientboundSetObjectivePacket.class); - } - - @Override - public Object packetScoreboardDisplayObjective(int id, Object scoreboardObjective) { - return new ClientboundSetDisplayObjectivePacket(DisplaySlot.values()[id], scoreboardObjective == null ? null : (Objective) scoreboardObjective); - } - - @Override - public Object packetScoreboardTeam() { - return Ref.newUnsafeInstance(ClientboundSetPlayerTeamPacket.class); - } - - @Override - public Object packetScoreboardScore(Action action, String player, String line, int score) { - return new ClientboundSetScorePacket(line, player, score, Optional.ofNullable(null), Optional.ofNullable(null)); - } - - @Override - public Object packetTitle(TitleAction action, Component text, int fadeIn, int stay, int fadeOut) { - switch (action) { - case ACTIONBAR: - return new ClientboundSetActionBarTextPacket((net.minecraft.network.chat.Component) this.toIChatBaseComponent(text)); - case TITLE: - return new ClientboundSetTitleTextPacket((net.minecraft.network.chat.Component) this.toIChatBaseComponent(text)); - case SUBTITLE: - return new ClientboundSetSubtitleTextPacket((net.minecraft.network.chat.Component) this.toIChatBaseComponent(text)); - case TIMES: - return new ClientboundSetTitlesAnimationPacket(fadeIn, stay, fadeOut); - case CLEAR: - case RESET: - return new ClientboundClearTitlesPacket(true); - } - return null; - } - - @Override - public Object packetChat(ChatType type, Object chatBase, UUID uuid) { - return new ClientboundSystemChatPacket((net.minecraft.network.chat.Component) chatBase, false); - } - - @Override - public Object packetChat(ChatType type, Component text, UUID uuid) { - return new ClientboundSystemChatPacket((net.minecraft.network.chat.Component) this.toIChatBaseComponent(text), false); - } - - @Override - public void postToMainThread(Runnable runnable) { - v1_21.server.execute(runnable); - } - - @Override - public Object getMinecraftServer() { - return v1_21.server; - } - - @Override - public Thread getServerThread() { - return v1_21.server.serverThread; - } - - @SuppressWarnings("removal") - @Override - public double[] getServerTPS() { - return v1_21.server.recentTps; - } - - private net.minecraft.network.chat.Component convert(Component c) { - if (c instanceof ComponentItem || c instanceof ComponentEntity) - return net.minecraft.network.chat.Component.Serializer.fromJson(Json.writer().simpleWrite(c.toJsonMap()), dispatcher); - MutableComponent current = net.minecraft.network.chat.Component.literal(c.getText()); - Style modif = current.getStyle(); - if (c.getColor() != null && !c.getColor().isEmpty()) - if (c.getColor().startsWith("#")) - modif = modif.withColor(TextColor.fromRgb(Integer.decode(c.getColor()))); - else - modif = modif.withColor(ChatFormatting.getByCode(c.colorToChar())); - if (c.getClickEvent() != null) - modif = modif.withClickEvent( - new net.minecraft.network.chat.ClickEvent(net.minecraft.network.chat.ClickEvent.Action.valueOf(c.getClickEvent().getAction().name()), c.getClickEvent().getValue())); - if (c.getHoverEvent() != null) - switch (c.getHoverEvent().getAction()) { - case SHOW_ENTITY: - try { - ComponentEntity compoundTag = (ComponentEntity) c.getHoverEvent().getValue(); - net.minecraft.network.chat.Component component = compoundTag.getName() == null ? null : (net.minecraft.network.chat.Component) toIChatBaseComponent(compoundTag.getName()); - EntityType entityType = BuiltInRegistries.ENTITY_TYPE.get(ResourceLocation.parse(compoundTag.getType())); - modif = modif.withHoverEvent(new net.minecraft.network.chat.HoverEvent(net.minecraft.network.chat.HoverEvent.Action.SHOW_ENTITY, - new net.minecraft.network.chat.HoverEvent.EntityTooltipInfo(entityType, compoundTag.getId(), component))); - } catch (Exception commandSyntaxException) { - } - break; - case SHOW_ITEM: - try { - - ComponentItem compoundTag = (ComponentItem) c.getHoverEvent().getValue(); - net.minecraft.world.item.ItemStack stack = new net.minecraft.world.item.ItemStack( - CraftMagicNumbers.getItem(XMaterial.matchXMaterial(compoundTag.getId()).orElse(XMaterial.AIR).parseMaterial()), compoundTag.getCount()); - if (compoundTag.getNbt() != null) { - CompoundTag nbt = (CompoundTag) parseNBT(compoundTag.getNbt()); - if (!nbt.contains("id")) - nbt.putString("id", - BuiltInRegistries.ITEM.getKey(CraftMagicNumbers.getItem(XMaterial.matchXMaterial(compoundTag.getId()).orElse(XMaterial.AIR).parseMaterial())).toString()); - if (!nbt.contains("count")) - nbt.putInt("count", compoundTag.getCount()); - stack = net.minecraft.world.item.ItemStack.parseOptional(dispatcher, nbt); - } - modif = modif.withHoverEvent( - new net.minecraft.network.chat.HoverEvent(net.minecraft.network.chat.HoverEvent.Action.SHOW_ITEM, new net.minecraft.network.chat.HoverEvent.ItemStackInfo(stack))); - } catch (Exception commandSyntaxException) { - } - break; - default: - modif = modif.withHoverEvent(new net.minecraft.network.chat.HoverEvent(net.minecraft.network.chat.HoverEvent.Action.SHOW_TEXT, - (net.minecraft.network.chat.Component) this.toIChatBaseComponent(c.getHoverEvent().getValue()))); - break; - } - modif = modif.withBold(c.isBold()); - modif = modif.withItalic(c.isItalic()); - modif = modif.withObfuscated(c.isObfuscated()); - modif = modif.withUnderlined(c.isUnderlined()); - modif = modif.withStrikethrough(c.isStrikethrough()); - current.setStyle(modif); - return current; - } - - @Override - public Object[] toIChatBaseComponents(List components) { - List chat = new ArrayList<>(); - chat.add(net.minecraft.network.chat.Component.literal("")); - for (Component c : components) { - if (c.getText() == null || c.getText().isEmpty()) { - if (c.getExtra() != null) - addConverted(chat, c.getExtra()); - continue; - } - chat.add(convert(c)); - if (c.getExtra() != null) - addConverted(chat, c.getExtra()); - } - return chat.toArray(new net.minecraft.network.chat.Component[0]); - } - - private void addConverted(List chat, List extra) { - for (Component c : extra) { - if (c.getText() == null || c.getText().isEmpty()) { - if (c.getExtra() != null) - addConverted(chat, c.getExtra()); - continue; - } - chat.add(convert(c)); - if (c.getExtra() != null) - addConverted(chat, c.getExtra()); - } - } - - @Override - public Object[] toIChatBaseComponents(Component co) { - if (co == null) - return new net.minecraft.network.chat.Component[]{empty}; - if (co instanceof ComponentItem || co instanceof ComponentEntity) - return new net.minecraft.network.chat.Component[]{net.minecraft.network.chat.Component.Serializer.fromJson(Json.writer().simpleWrite(co.toJsonMap()), dispatcher)}; - List chat = new ArrayList<>(); - chat.add(net.minecraft.network.chat.Component.literal("")); - if (co.getText() != null && !co.getText().isEmpty()) - chat.add(convert(co)); - if (co.getExtra() != null) - for (Component c : co.getExtra()) { - if (c.getText() == null || c.getText().isEmpty()) { - if (c.getExtra() != null) - addConverted(chat, c.getExtra()); - continue; - } - chat.add(convert(c)); - if (c.getExtra() != null) - addConverted(chat, c.getExtra()); - } - return chat.toArray(new net.minecraft.network.chat.Component[0]); - } - - @Override - public Object toIChatBaseComponent(Component co) { - if (co == null) - return empty; - if (co instanceof ComponentItem || co instanceof ComponentEntity) - return net.minecraft.network.chat.Component.Serializer.fromJson(Json.writer().simpleWrite(co.toJsonMap()), dispatcher); - MutableComponent main = net.minecraft.network.chat.Component.literal(""); - List chat = new ArrayList<>(); - if (co.getText() != null && !co.getText().isEmpty()) - chat.add(convert(co)); - if (co.getExtra() != null) - for (Component c : co.getExtra()) { - if (c.getText() == null || c.getText().isEmpty()) { - if (c.getExtra() != null) - addConverted(chat, c.getExtra()); - continue; - } - chat.add(convert(c)); - if (c.getExtra() != null) - addConverted(chat, c.getExtra()); - } - main.getSiblings().addAll(chat); - return main.getSiblings().isEmpty() ? empty : main; - } - - @Override - public Object toIChatBaseComponent(List cc) { - MutableComponent main = net.minecraft.network.chat.Component.literal(""); - for (Component c : cc) - main.getSiblings().add((net.minecraft.network.chat.Component) this.toIChatBaseComponent(c)); - return main.getSiblings().isEmpty() ? empty : main; - } - - @Override - public Object chatBase(String json) { - return net.minecraft.network.chat.Component.Serializer.fromJson(json, dispatcher); - } - - @Override - public Component fromIChatBaseComponent(Object componentObject) { - if (componentObject == null) - return Component.EMPTY_COMPONENT; - net.minecraft.network.chat.Component component = (net.minecraft.network.chat.Component) componentObject; - Object result = Ref.invoke(component.getContents(), "text"); - Component comp = new Component(result == null ? "" : (String) result); - Style modif = component.getStyle(); - if (modif.getColor() != null) - comp.setColor(modif.getColor().serialize()); - - if (modif.getClickEvent() != null) - comp.setClickEvent(new ClickEvent(ClickEvent.Action.valueOf(modif.getClickEvent().getAction().name()), modif.getClickEvent().getValue())); - - if (modif.getHoverEvent() != null) - switch (HoverEvent.Action.valueOf(modif.getHoverEvent().getAction().getSerializedName().toUpperCase())) { - case SHOW_ENTITY: { - EntityTooltipInfo hover = modif.getHoverEvent().getValue(net.minecraft.network.chat.HoverEvent.Action.SHOW_ENTITY); - ComponentEntity compEntity = new ComponentEntity(hover.type.toString(), hover.id); - if (hover.name.isPresent()) - compEntity.setName(fromIChatBaseComponent(hover.name.get())); - comp.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ENTITY, compEntity)); - break; - } - case SHOW_ITEM: { - ItemStackInfo hover = modif.getHoverEvent().getValue(net.minecraft.network.chat.HoverEvent.Action.SHOW_ITEM); - ComponentItem compEntity = new ComponentItem(CraftMagicNumbers.getMaterial(hover.getItemStack().getItem()).name(), hover.getItemStack().getCount()); - if (hover.getItemStack().getTags() != null) - compEntity.setNbt(hover.getItemStack().save(dispatcher).toString()); - comp.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, compEntity)); - break; - } - default: - net.minecraft.network.chat.Component hover = modif.getHoverEvent().getValue(net.minecraft.network.chat.HoverEvent.Action.SHOW_TEXT); - comp.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, fromIChatBaseComponent(hover))); - break; - } - comp.setBold(modif.isBold()); - comp.setItalic(modif.isItalic()); - comp.setObfuscated(modif.isObfuscated()); - comp.setUnderlined(modif.isUnderlined()); - comp.setStrikethrough(modif.isStrikethrough()); - - if (!component.getSiblings().isEmpty()) { - List extra = new ArrayList<>(); - for (net.minecraft.network.chat.Component base : component.getSiblings()) - extra.add(fromIChatBaseComponent(base)); - comp.setExtra(extra); - } - return comp; - } - - @Override - public BlockDataStorage toMaterial(Object blockOrIBlockData) { - if (blockOrIBlockData instanceof Block) { - net.minecraft.world.level.block.state.BlockState data = ((Block) blockOrIBlockData).defaultBlockState(); - return new BlockDataStorage(CraftMagicNumbers.getMaterial(data.getBlock()), (byte) 0, asString(data)); - } - if (blockOrIBlockData instanceof net.minecraft.world.level.block.state.BlockState) { - net.minecraft.world.level.block.state.BlockState data = (net.minecraft.world.level.block.state.BlockState) blockOrIBlockData; - return new BlockDataStorage(CraftMagicNumbers.getMaterial(data.getBlock()), (byte) 0, asString(data)); - } - return new BlockDataStorage(Material.AIR); - } - - private String asString(net.minecraft.world.level.block.state.BlockState data) { - StringBuilder stateString = new StringBuilder(); - if (!data.getProperties().isEmpty()) { - stateString.append('['); - stateString.append(data.getValues().entrySet().stream().map(StateHolder.PROPERTY_ENTRY_TO_STRING_FUNCTION).collect(Collectors.joining(","))); - stateString.append(']'); - } - return stateString.toString(); - } - - @Override - public Object toIBlockData(BlockDataStorage material) { - if (material == null || material.getType() == null || material.getType() == Material.AIR) - return Blocks.AIR.defaultBlockState(); - Block block = CraftMagicNumbers.getBlock(material.getType()); - return readArgument(block, material); - } - - @Override - public Object toBlock(BlockDataStorage material) { - if (material == null || material.getType() == null || material.getType() == Material.AIR) - return Blocks.AIR; - Block block = CraftMagicNumbers.getBlock(material.getType()); - return readArgument(block, material).getBlock(); - } - - private net.minecraft.world.level.block.state.BlockState readArgument(Block block, BlockDataStorage material) { - net.minecraft.world.level.block.state.BlockState ib = block.defaultBlockState(); - return writeData(ib, ib.getBlock().getStateDefinition(), material.getData()); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - private static net.minecraft.world.level.block.state.BlockState writeData(net.minecraft.world.level.block.state.BlockState ib, StateDefinition blockStateList, String string) { - if (string == null || string.trim().isEmpty()) - return ib; - - String key = ""; - String value = ""; - int set = 0; - - for (int i = 1; i < string.length() - 1; ++i) { - char c = string.charAt(i); - if (c == ',') { - net.minecraft.world.level.block.state.properties.Property ibj = blockStateList.getProperty(key); - if (ibj != null) { - Optional optional = ibj.getValue(value); - if (optional.isPresent()) - ib = ib.setValue(ibj, (Comparable) optional.get()); - } - key = ""; - value = ""; - set = 0; - continue; - } - if (c == '=') { - set = 1; - continue; - } - if (set == 0) - key += c; - else - value += c; - } - if (set == 1) { - net.minecraft.world.level.block.state.properties.Property ibj = blockStateList.getProperty(key); - if (ibj != null) { - Optional optional = ibj.getValue(value); - if (optional.isPresent()) - ib = ib.setValue(ibj, (Comparable) optional.get()); - } - } - return ib; - } - - @Override - public ItemStack toItemStack(BlockDataStorage material) { - Item item = CraftMagicNumbers.getItem(material.getType(), ParseUtils.getShort(material.getData())); - return CraftItemStack.asBukkitCopy(item.getDefaultInstance()); - } - - @Override - public Object getChunk(World world, int x, int z) { - return ((CraftChunk) world.getChunkAt(x, z)).getHandle(ChunkStatus.FULL); - } - - @Override - public void setBlock(Object objChunk, int x, int y, int z, Object IblockData, int data) { - LevelChunk chunk = (LevelChunk) objChunk; - ServerLevel world = chunk.level; - int highY = chunk.getSectionIndex(y); - if (highY < 0) - return; - LevelChunkSection sc = chunk.getSection(highY); - if (sc == null) - return; - BlockPos pos = new BlockPos(x, y, z); - - net.minecraft.world.level.block.state.BlockState iblock = IblockData == null ? Blocks.AIR.defaultBlockState() : (net.minecraft.world.level.block.state.BlockState) IblockData; - - boolean onlyModifyState = iblock.getBlock() instanceof EntityBlock; - - // REMOVE TILE ENTITY IF NOT SAME TYPE - BlockEntity ent = chunk.blockEntities.get(pos); - if (ent != null) { - boolean shouldSkip = true; - if (!onlyModifyState) - shouldSkip = false; - else if (onlyModifyState && !ent.getType().isValid(iblock)) { - shouldSkip = false; - onlyModifyState = false; - } - if (!shouldSkip) - chunk.removeBlockEntity(pos); - } - - net.minecraft.world.level.block.state.BlockState old = sc.setBlockState(x & 15, y & 15, z & 15, iblock, false); - - // ADD TILE ENTITY - if (iblock.getBlock() instanceof EntityBlock && !onlyModifyState) { - ent = ((EntityBlock) iblock.getBlock()).newBlockEntity(pos, iblock); - chunk.blockEntities.put(pos, ent); - ent.setLevel(world); - Object packet = ent.getUpdatePacket(); - BukkitLoader.getPacketHandler().send(chunk.level.getWorld().getPlayers(), packet); - } - - // MARK CHUNK TO SAVE - chunk.setUnsaved(true); - - // POI - if (!world.preventPoiUpdated) - world.onBlockStateChange(pos, old, iblock); - } - - @Override - public void updatePhysics(Object objChunk, int x, int y, int z, Object iblockdata) { - LevelChunk chunk = (LevelChunk) objChunk; - BlockPos blockPos = new BlockPos(x, y, z); - doPhysicsAround(chunk.level, blockPos, ((net.minecraft.world.level.block.state.BlockState) iblockdata).getBlock()); - } - - private void doPhysicsAround(ServerLevel world, BlockPos BlockPos, Block block) { - doPhysics(world, BlockPos.west(), block, BlockPos); // west - doPhysics(world, BlockPos.east(), block, BlockPos); // east - doPhysics(world, BlockPos.below(), block, BlockPos); // down - doPhysics(world, BlockPos.above(), block, BlockPos); // up - doPhysics(world, BlockPos.north(), block, BlockPos); // north - doPhysics(world, BlockPos.south(), block, BlockPos); // south - } - - private static final Method callPhysics = Ref.method(FallingBlock.class, "onPlace", net.minecraft.world.level.block.state.BlockState.class, Level.class, BlockPos.class, - net.minecraft.world.level.block.state.BlockState.class, boolean.class); - - private void doPhysics(ServerLevel world, BlockPos BlockPos, Block block, BlockPos BlockPos1) { - - net.minecraft.world.level.block.state.BlockState state = world.getBlockState(BlockPos); - state.handleNeighborChanged(world, BlockPos, block, BlockPos1, false); - if (state.getBlock() instanceof FallingBlock) - Ref.invoke(state.getBlock(), callPhysics, state, world, BlockPos, block.defaultBlockState(), false); - } - - @Override - public void updateLightAt(Object objChunk, int x, int y, int z) { - LevelChunk chunk = (LevelChunk) objChunk; - chunk.level.getChunkSource().getLightEngine().checkBlock(new BlockPos(x, y, z)); - } - - @Override - public Object getBlock(Object objChunk, int x, int y, int z) { - LevelChunk chunk = (LevelChunk) objChunk; - return chunk.getBlockState(x, y, z); - } - - @Override - public byte getData(Object chunk, int x, int y, int z) { - return 0; - } - - @Override - public String getNBTOfTile(Object objChunk, int x, int y, int z) { - LevelChunk chunk = (LevelChunk) objChunk; - return chunk.getBlockEntity(new BlockPos(x, y, z), EntityCreationType.IMMEDIATE).saveWithFullMetadata(dispatcher).toString(); - } - - @Override - public void setNBTToTile(Object objChunk, int x, int y, int z, String nbt) { - LevelChunk chunk = (LevelChunk) objChunk; - BlockEntity ent = chunk.getBlockEntity(new BlockPos(x, y, z), EntityCreationType.IMMEDIATE); - CompoundTag parsedNbt = (CompoundTag) parseNBT(nbt); - parsedNbt.putInt("x", x); - parsedNbt.putInt("y", y); - parsedNbt.putInt("z", z); - ent.loadWithComponents(parsedNbt, dispatcher); - Object packet = ent.getUpdatePacket(); - BukkitLoader.getPacketHandler().send(chunk.level.getWorld().getPlayers(), packet); - } - - @Override - public boolean isTileEntity(Object objChunk, int x, int y, int z) { - LevelChunk chunk = (LevelChunk) objChunk; - return chunk.getBlockEntity(new BlockPos(x, y, z), EntityCreationType.IMMEDIATE) != null; - } - - @Override - public int getCombinedId(Object IblockDataOrBlock) { - return Block.getId((net.minecraft.world.level.block.state.BlockState) IblockDataOrBlock); - } - - @Override - public Object blockPosition(int blockX, int blockY, int blockZ) { - return new BlockPos(blockX, blockY, blockZ); - } - - @Override - public Object toIBlockData(Object data) { - return ((CraftBlockData) data).getState(); - } - - @Override - public Object toIBlockData(BlockState state) { - return CraftMagicNumbers.getBlock(state.getType(), state.getRawData()); - } - - @Override - public Chunk toBukkitChunk(Object nmsChunk) { - return new CraftChunk((LevelChunk) nmsChunk); - } - - @Override - public int getPing(Player player) { - return ((ServerGamePacketListenerImpl) getPlayerConnection(player)).latency(); - } - - @Override - public Object getPlayerConnection(Player player) { - return ((ServerPlayer) getPlayer(player)).connection; - } - - private static Field networkManagerField = Ref.field(ServerCommonPacketListenerImpl.class, Connection.class); - - @Override - public Object getConnectionNetwork(Object playercon) { - return Ref.get(playercon, networkManagerField); - } - - @Override - public Object getNetworkChannel(Object network) { - return ((Connection) network).channel; - } - - @Override - public Object packetOpenWindow(int id, String legacy, int size, Component title) { - - MenuType windowType = MenuType.GENERIC_9x1; - switch (size) { - case 0: { - windowType = MenuType.ANVIL; - break; - } - case 18: { - windowType = MenuType.GENERIC_9x2; - break; - } - case 27: { - windowType = MenuType.GENERIC_9x3; - break; - } - case 36: { - windowType = MenuType.GENERIC_9x4; - break; - } - case 45: { - windowType = MenuType.GENERIC_9x5; - break; - } - case 54: { - windowType = MenuType.GENERIC_9x6; - break; - } - } - return new ClientboundOpenScreenPacket(id, windowType, (net.minecraft.network.chat.Component) this.toIChatBaseComponent(title)); - } - - @Override - public void closeGUI(Player player, Object container, boolean closePacket) { - if (closePacket) - BukkitLoader.getPacketHandler().send(player, new ClientboundContainerClosePacket(((AbstractContainerMenu) container).containerId)); - net.minecraft.world.entity.player.Player nmsPlayer = (net.minecraft.world.entity.player.Player) getPlayer(player); - nmsPlayer.containerMenu = nmsPlayer.inventoryMenu; - ((AbstractContainerMenu) container).transferTo(nmsPlayer.containerMenu, (CraftPlayer) player); - } - - @Override - public void setSlot(Object container, int slot, Object item) { - ((AbstractContainerMenu) container).setItem(slot, ((AbstractContainerMenu) container).getStateId(), (net.minecraft.world.item.ItemStack) item); - } - - @Override - public void setGUITitle(Player player, Object container, String legacy, int size, Component title) { - int id = ((AbstractContainerMenu) container).containerId; - BukkitLoader.getPacketHandler().send(player, packetOpenWindow(id, legacy, size, title)); - net.minecraft.world.item.ItemStack carried = ((AbstractContainerMenu) container).getCarried(); - if (!carried.isEmpty()) - BukkitLoader.getPacketHandler().send(player, new ClientboundContainerSetSlotPacket(id, getContainerStateId(container), -1, carried)); - int slot = 0; - for (net.minecraft.world.item.ItemStack item : ((AbstractContainerMenu) container).getItems()) { - if (slot == size) - break; - if (!item.isEmpty()) - BukkitLoader.getPacketHandler().send(player, new ClientboundContainerSetSlotPacket(id, getContainerStateId(container), slot, item)); - ++slot; - } - } - - @Override - public void openGUI(Player player, Object container, String legacy, int size, Component title) { - ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); - int id = ((AbstractContainerMenu) container).containerId; - BukkitLoader.getPacketHandler().send(player, packetOpenWindow(id, legacy, size, title)); - nmsPlayer.containerMenu.transferTo((AbstractContainerMenu) container, (CraftPlayer) player); - nmsPlayer.containerMenu = (AbstractContainerMenu) container; - postToMainThread(() -> nmsPlayer.initMenu((AbstractContainerMenu) container)); - ((AbstractContainerMenu) container).checkReachable = false; - } - - @Override - public void openAnvilGUI(Player player, Object container, Component title) { - openGUI(player, container, "minecraft:anvil", 0, title); - } - - @Override - public Object createContainer(Inventory inv, Player player) { - if (inv.getType() == InventoryType.ANVIL) { - AnvilMenu container = new AnvilMenu(((CraftPlayer) player).getHandle().nextContainerCounter(), ((CraftPlayer) player).getHandle().getInventory(), new ContainerLevelAccess() { - - @Override - public Optional evaluate(BiFunction getter) { - return Optional.empty(); - } - - @Override - public Location getLocation() { - return null; - } - }); - postToMainThread(() -> { - int slot = 0; - for (ItemStack stack : inv.getContents()) - container.getSlot(slot++).set((net.minecraft.world.item.ItemStack) asNMSItem(stack)); - }); - container.checkReachable = false; - return container; - } - return new CraftContainer(inv, ((CraftPlayer) player).getHandle(), ((CraftPlayer) player).getHandle().nextContainerCounter()); - } - - @Override - public Object getSlotItem(Object container, int slot) { - return slot < 0 ? null : ((AbstractContainerMenu) container).getSlot(slot).getItem(); - } - - @Override - public String getAnvilRenameText(Object anvil) { - return ((AnvilMenu) anvil).itemName; - } - - public static int c(final int quickCraftData) { - return quickCraftData >> 2 & 0x3; - } - - public static int d(final int quickCraftData) { - return quickCraftData & 0x3; - } - - @Override - public boolean processInvClickPacket(Player player, HolderGUI gui, Object provPacket) { - ServerboundContainerClickPacket packet = (ServerboundContainerClickPacket) provPacket; - int slot = packet.getSlotNum(); - - Object container = gui.getContainer(player); - if (container == null) - return false; - - int id = packet.getContainerId(); - int mouseClick = packet.getButtonNum(); - net.minecraft.world.inventory.ClickType type = packet.getClickType(); - AbstractContainerMenu c = (AbstractContainerMenu) container; - - if (slot < -1 && slot != -999) - return true; - - net.minecraft.world.entity.player.Player nPlayer = ((CraftPlayer) player).getHandle(); - - ItemStack newItem; - ItemStack oldItem; - switch (type) { - case PICKUP: // PICKUP - oldItem = asBukkitItem(getSlotItem(container, slot)); - newItem = asBukkitItem(c.getCarried()); - if (slot > 0 && mouseClick != 0) { - if (c.getCarried().isEmpty()) { // pickup half - newItem = oldItem.clone(); - if (oldItem.getAmount() == 1) - newItem = new ItemStack(Material.AIR); - else - newItem.setAmount(Math.max(1, oldItem.getAmount() / 2)); - } else - // drop - if (oldItem.isSimilar(newItem) || oldItem.getType() == Material.AIR) - newItem.setAmount(oldItem.getType() == Material.AIR ? 1 : oldItem.getAmount() + 1); - } else if (slot > 0 && mouseClick == 0) // drop - if (oldItem.isSimilar(newItem)) - newItem.setAmount(Math.min(newItem.getAmount() + oldItem.getAmount(), newItem.getMaxStackSize())); - break; - case QUICK_MOVE: // QUICK_MOVE - newItem = asBukkitItem(c.getCarried()); - oldItem = asBukkitItem(getSlotItem(container, slot)); - break; - case SWAP:// SWAP - newItem = asBukkitItem(nPlayer.getInventory().getItem(mouseClick)); - oldItem = asBukkitItem(getSlotItem(container, slot)); - break; - case CLONE:// CLONE - newItem = asBukkitItem(getSlotItem(container, slot)); - oldItem = asBukkitItem(getSlotItem(container, slot)); - break; - case THROW:// THROW - if (c.getCarried().isEmpty() && slot >= 0) { - Slot slot3 = c.getSlot(slot); - newItem = asBukkitItem(slot3.getItem()); - if (mouseClick != 0 || newItem.getAmount() - 1 <= 0) - newItem = new ItemStack(Material.AIR); - else - newItem.setAmount(newItem.getAmount() - 1); - } else - newItem = asBukkitItem(c.getCarried()); - oldItem = asBukkitItem(getSlotItem(container, slot)); - break; - case QUICK_CRAFT:// QUICK_CRAFT - newItem = asBukkitItem(c.getCarried()); - oldItem = slot <= -1 ? new ItemStack(Material.AIR) : asBukkitItem(getSlotItem(container, slot)); - break; - case PICKUP_ALL:// PICKUP_ALL - newItem = asBukkitItem(c.getCarried()); - oldItem = asBukkitItem(getSlotItem(container, slot)); - break; - default: - newItem = slot <= -1 ? new ItemStack(Material.AIR) : asBukkitItem(packet.getCarriedItem()); - oldItem = slot <= -1 ? new ItemStack(Material.AIR) : asBukkitItem(packet.getCarriedItem()); - break; - } - - if (oldItem.getType() == Material.AIR && newItem.getType() == Material.AIR) - return true; - - boolean cancel = false; - int gameSlot = slot > gui.size() - 1 ? InventoryUtils.convertToPlayerInvSlot(slot - gui.size()) : slot; - - ClickType clickType = InventoryUtils.buildClick(type == net.minecraft.world.inventory.ClickType.QUICK_CRAFT ? 1 : type == net.minecraft.world.inventory.ClickType.QUICK_MOVE ? 2 : 0, - mouseClick); - if (slot > -1) { - if (!cancel) - cancel = InventoryUtils.useItem(player, gui, slot, clickType); - if (!gui.isInsertable()) - cancel = true; - - if (!cancel) - cancel = gui.onInteractItem(player, newItem, oldItem, clickType, gameSlot, slot < gui.size()); - else - gui.onInteractItem(player, newItem, oldItem, clickType, gameSlot, slot < gui.size()); - } - if (!cancel) { - if (gui instanceof AnvilGUI) { // Event - final ItemStack newItemFinal = newItem; - postToMainThread(() -> { - processEvent(c, type, gui, player, slot, gameSlot, newItemFinal, oldItem, packet, mouseClick, clickType, nPlayer); - }); - } else - processEvent(c, type, gui, player, slot, gameSlot, newItem, oldItem, packet, mouseClick, clickType, nPlayer); - return true; - } - // MOUSE - int statusId = c.getStateId(); - BukkitLoader.getPacketHandler().send(player, packetSetSlot(-1, -1, statusId, c.getCarried())); - switch (type) { - case CLONE: - break; - case SWAP: - case QUICK_MOVE: - case PICKUP_ALL: - c.sendAllDataToRemote(); - break; - default: - BukkitLoader.getPacketHandler().send(player, packetSetSlot(id, slot, statusId, c.getSlot(slot).getItem())); - break; - } - return true; - } - - private void processEvent(AbstractContainerMenu c, net.minecraft.world.inventory.ClickType type, HolderGUI gui, Player player, int slot, int gameSlot, ItemStack newItem, ItemStack oldItem, - ServerboundContainerClickPacket packet, int mouseClick, ClickType clickType, net.minecraft.world.entity.player.Player nPlayer) { - c.suppressRemoteUpdates(); - switch (type) { - case QUICK_MOVE: { - ItemStack[] contents = slot < gui.size() ? player.getInventory().getStorageContents() : gui.getInventory().getStorageContents(); - boolean interactWithResultSlot = false; - if (gui instanceof AnvilGUI && slot < gui.size() && slot == 2) - if (c.getSlot(2).allowModification(nPlayer)) - interactWithResultSlot = true; - else - return; - Pair result = slot < gui.size() - ? InventoryUtils.shift(slot, player, gui, clickType, gui instanceof AnvilGUI && slot != 2 ? DestinationType.PLAYER_FROM_ANVIL : DestinationType.PLAYER, null, contents, oldItem) - : InventoryUtils.shift(slot, player, gui, clickType, DestinationType.GUI, gui.getNotInterableSlots(player), contents, oldItem); - @SuppressWarnings("unchecked") - Map modified = (Map) result.getValue(); - int remaining = (int) result.getKey(); - - if (!modified.isEmpty()) - if (slot < gui.size()) { - for (Entry modif : modified.entrySet()) - nPlayer.getInventory().setItem(modif.getKey(), (net.minecraft.world.item.ItemStack) asNMSItem(modif.getValue())); - if (remaining == 0) { - c.getSlot(gameSlot).set((net.minecraft.world.item.ItemStack) asNMSItem(null)); - if (interactWithResultSlot) { - c.getSlot(0).set((net.minecraft.world.item.ItemStack) asNMSItem(null)); - c.getSlot(1).set((net.minecraft.world.item.ItemStack) asNMSItem(null)); - } - } else { - newItem.setAmount(remaining); - c.getSlot(gameSlot).set((net.minecraft.world.item.ItemStack) asNMSItem(newItem)); - } - } else { - for (Entry modif : modified.entrySet()) - c.getSlot(modif.getKey()).set((net.minecraft.world.item.ItemStack) asNMSItem(modif.getValue())); // Visual & Nms side - // Plugin & Bukkit side - gui.getInventory().setStorageContents(contents); - if (remaining == 0) - nPlayer.getInventory().setItem(gameSlot, (net.minecraft.world.item.ItemStack) asNMSItem(null)); - else { - newItem.setAmount(remaining); - nPlayer.getInventory().setItem(gameSlot, (net.minecraft.world.item.ItemStack) asNMSItem(newItem)); - } - } - c.resumeRemoteUpdates(); - return; - } - default: - processClick(gui, gui.getNotInterableSlots(player), c, slot, mouseClick, type, nPlayer); - break; - } - postToMainThread(() -> { - if (type != net.minecraft.world.inventory.ClickType.QUICK_CRAFT && (c.getType().equals(MenuType.ANVIL) || c.getType().equals(MenuType.SMITHING))) - c.sendAllDataToRemote(); - for (final it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry entry : Int2ObjectMaps.fastIterable(packet.getChangedSlots())) - c.setItem(entry.getIntKey(), packet.getStateId(), entry.getValue()); - c.setCarried(packet.getCarriedItem()); - c.resumeRemoteUpdates(); - if (packet.getStateId() != c.getStateId()) - c.broadcastFullState(); - else - c.broadcastChanges(); - }); - } - - private Method addAmount = Ref.method(Slot.class, "onSwapCraft", int.class); - private Method checkItem = Ref.method(AbstractContainerMenu.class, "tryItemClickBehaviourOverride", net.minecraft.world.entity.player.Player.class, ClickAction.class, Slot.class, - net.minecraft.world.item.ItemStack.class, net.minecraft.world.item.ItemStack.class); - - @SuppressWarnings("unchecked") - private void processClick(HolderGUI gui, List ignoredSlots, AbstractContainerMenu container, int slotIndex, int button, net.minecraft.world.inventory.ClickType actionType, - net.minecraft.world.entity.player.Player player) { - if (actionType == net.minecraft.world.inventory.ClickType.QUICK_CRAFT) - processDragMove(gui, container, player, slotIndex, button); - else { - int u = (int) Ref.get(container, containerU); - int j = getContainerStateId(container); - Set mod = (Set) Ref.get(container, containerV); - if (u != 0) { - Ref.set(container, containerU, u = 0); - mod.clear(); - } else if (actionType == net.minecraft.world.inventory.ClickType.PICKUP && (button == 0 || button == 1)) { - ClickAction clickaction = button == 0 ? ClickAction.PRIMARY : ClickAction.SECONDARY; - if (slotIndex == -999) { - if (!container.getCarried().isEmpty()) - if (clickaction == ClickAction.PRIMARY) { - net.minecraft.world.item.ItemStack carried = container.getCarried(); - container.setCarried(net.minecraft.world.item.ItemStack.EMPTY); - postToMainThread(() -> player.drop(carried, true)); - } else - postToMainThread(() -> player.drop(container.getCarried().split(1), true)); - } else { - if (slotIndex < 0) - return; - Slot slot = container.getSlot(slotIndex); - net.minecraft.world.item.ItemStack itemstack = slot.getItem(); - net.minecraft.world.item.ItemStack itemstack4 = container.getCarried(); - player.updateTutorialInventoryAction(itemstack4, slot.getItem(), clickaction); - if (!(boolean) Ref.invoke(container, checkItem, player, clickaction, slot, itemstack, itemstack4)) - if (itemstack.isEmpty()) { - if (!itemstack4.isEmpty()) { - int i2 = clickaction == ClickAction.PRIMARY ? itemstack4.getCount() : 1; - net.minecraft.world.item.ItemStack stack = slot.safeInsert(itemstack4, i2); - container.setCarried(stack); - } - } else if (slot.allowModification(player)) - if (itemstack4.isEmpty()) { - int i2 = clickaction == ClickAction.PRIMARY ? itemstack.getCount() : (itemstack.getCount() + 1) / 2; - Optional optional = slot.tryRemove(i2, 2147483647, player); - optional.ifPresent(i -> { - container.setCarried(i); - slot.onTake(player, i); - }); - } else if (slot.mayPlace(itemstack4)) { - if (net.minecraft.world.item.ItemStack.isSameItemSameComponents(itemstack, itemstack4)) { - int i2 = clickaction == ClickAction.PRIMARY ? itemstack4.getCount() : 1; - net.minecraft.world.item.ItemStack stack = slot.safeInsert(itemstack4, i2); - container.setCarried(stack); - } else if (itemstack4.getCount() <= slot.getMaxStackSize(itemstack4)) { - container.setCarried(itemstack); - slot.safeInsert(itemstack4); - } - } else if (net.minecraft.world.item.ItemStack.isSameItemSameComponents(itemstack, itemstack4)) { - Optional optional2 = slot.tryRemove(itemstack.getCount(), itemstack4.getMaxStackSize() - itemstack4.getCount(), player); - optional2.ifPresent(i -> { - itemstack.grow(i.getCount()); - slot.onTake(player, i); - }); - } - slot.setChanged(); - if (player instanceof net.minecraft.world.entity.player.Player && slot.getMaxStackSize() != 64) { - BukkitLoader.getPacketHandler().send((Player) player.getBukkitEntity(), - BukkitLoader.getNmsProvider().packetSetSlot(j, slot.index, container.incrementStateId(), slot.getItem())); - if (container.getBukkitView().getType() == InventoryType.WORKBENCH || container.getBukkitView().getType() == InventoryType.CRAFTING) - BukkitLoader.getPacketHandler().send((Player) player.getBukkitEntity(), - BukkitLoader.getNmsProvider().packetSetSlot(j, 0, container.incrementStateId(), container.getSlot(0).getItem())); - } - } - } else if (actionType == net.minecraft.world.inventory.ClickType.SWAP) { - if (slotIndex < 0) - return; - net.minecraft.world.entity.player.Inventory playerinventory = player.getInventory(); - Slot slot3 = container.getSlot(slotIndex); - net.minecraft.world.item.ItemStack itemstack2 = playerinventory.getItem(button); - net.minecraft.world.item.ItemStack itemstack = slot3.getItem(); - if (!itemstack2.isEmpty() || !itemstack.isEmpty()) - if (itemstack2.isEmpty()) { - if (slot3.allowModification(player)) { - playerinventory.setItem(button, itemstack); - Ref.invoke(slot3, addAmount, itemstack.getCount()); - slot3.set(net.minecraft.world.item.ItemStack.EMPTY); - slot3.onTake(player, itemstack); - } - } else if (itemstack.isEmpty()) { - if (slot3.mayPlace(itemstack2)) { - int j2 = slot3.getMaxStackSize(itemstack2); - if (itemstack2.getCount() > j2) - slot3.set(itemstack2.split(j2)); - else { - playerinventory.setItem(button, net.minecraft.world.item.ItemStack.EMPTY); - slot3.set(itemstack2); - } - } - } else if (slot3.allowModification(player) && slot3.mayPlace(itemstack2)) { - int j2 = slot3.getMaxStackSize(itemstack2); - if (itemstack2.getCount() > j2) { - slot3.set(itemstack2.split(j2)); - slot3.onTake(player, itemstack); - if (!playerinventory.add(itemstack)) - postToMainThread(() -> player.drop(itemstack, true)); - } else { - playerinventory.setItem(button, itemstack); - slot3.set(itemstack2); - slot3.onTake(player, itemstack); - } - } - } else if (actionType == net.minecraft.world.inventory.ClickType.CLONE && player.getAbilities().instabuild && container.getCarried().isEmpty() && slotIndex >= 0) { - Slot slot3 = container.getSlot(slotIndex); - if (slot3.hasItem()) { - net.minecraft.world.item.ItemStack itemstack2 = slot3.getItem(); - container.setCarried(itemstack2.copyWithCount(itemstack2.getMaxStackSize())); - } - } else if (actionType == net.minecraft.world.inventory.ClickType.THROW && container.getCarried().isEmpty() && slotIndex >= 0) { - Slot slot3 = container.getSlot(slotIndex); - int m = button == 0 ? 1 : slot3.getItem().getCount(); - net.minecraft.world.item.ItemStack itemstack = slot3.safeTake(m, 2147483647, player); - postToMainThread(() -> player.drop(itemstack, true)); - } else if (actionType == net.minecraft.world.inventory.ClickType.PICKUP_ALL && slotIndex >= 0) { - final Slot slot3 = container.slots.get(slotIndex); - final net.minecraft.world.item.ItemStack itemstack2 = container.getCarried(); - if (!itemstack2.isEmpty() && (!slot3.hasItem() || !slot3.allowModification(player))) { - List ignoreSlots = ignoredSlots == null ? Collections.emptyList() : ignoredSlots; - List corruptedSlots = ignoredSlots == null ? Collections.emptyList() : new ArrayList<>(); - Map modifiedSlots = new HashMap<>(); - Map modifiedSlotsPlayerInv = new HashMap<>(); - final int l = button == 0 ? 0 : container.slots.size() - 1; - final int j2 = button == 0 ? 1 : -1; - for (int i2 = 0; i2 < 2; ++i2) - for (int slot = l; slot >= 0 && slot < container.slots.size() && itemstack2.getCount() < itemstack2.getMaxStackSize(); slot += j2) { - final Slot slot4 = container.slots.get(slot); - if (slot4.hasItem() && AbstractContainerMenu.canItemQuickReplace(slot4, itemstack2, true) && slot4.allowModification(player) - && container.canTakeItemForPickAll(itemstack2, slot4)) { - final net.minecraft.world.item.ItemStack itemstack5 = slot4.getItem(); - if (i2 != 0 || itemstack5.getCount() != itemstack5.getMaxStackSize()) { - if (slot < gui.size() && ignoreSlots.contains(slot)) { - corruptedSlots.add(slot); - continue; - } - final net.minecraft.world.item.ItemStack itemstack6 = slot4.safeTake(itemstack5.getCount(), itemstack2.getMaxStackSize() - itemstack2.getCount(), player); - itemstack2.grow(itemstack6.getCount()); - int gameSlot = slot > gui.size() - 1 ? InventoryUtils.convertToPlayerInvSlot(slot - gui.size()) : slot; - if (slot < gui.size()) - modifiedSlots.put(gameSlot, asBukkitItem(slot4.getItem())); - else - modifiedSlotsPlayerInv.put(gameSlot, asBukkitItem(slot4.getItem())); - } - } - } - if (slotIndex < gui.size()) - modifiedSlots.put(slotIndex, new ItemStack(Material.AIR)); - else - modifiedSlotsPlayerInv.put(InventoryUtils.convertToPlayerInvSlot(slotIndex - gui.size()), new ItemStack(Material.AIR)); - if (!modifiedSlots.isEmpty() || !modifiedSlotsPlayerInv.isEmpty()) - gui.onMultipleIteract((Player) player.getBukkitEntity(), modifiedSlots, modifiedSlotsPlayerInv); - for (int s : corruptedSlots) - BukkitLoader.getPacketHandler().send((Player) player.getBukkitEntity(), BukkitLoader.getNmsProvider().packetSetSlot(BukkitLoader.getNmsProvider().getContainerId(container), s, - getContainerStateId(container), BukkitLoader.getNmsProvider().getSlotItem(container, s))); - } - } - } - } - - private Field containerU = Ref.field(AbstractContainerMenu.class, "quickcraftStatus"), containerV = Ref.field(AbstractContainerMenu.class, "quickcraftSlots"), - containerT = Ref.field(AbstractContainerMenu.class, "quickcraftType"); - - @SuppressWarnings("unchecked") - private void processDragMove(HolderGUI gui, AbstractContainerMenu container, net.minecraft.world.entity.player.Player player, int slot, int mouseClick) { - int previous = (int) Ref.get(container, containerU); - int u = d(mouseClick); - Set mod = (Set) Ref.get(container, containerV); - if ((previous != 1 || u != 2) && previous != u || container.getCarried().isEmpty()) { - mod.clear(); - u = 0; - } else - switch (u) { - case 0: { - int t = c(mouseClick); - Ref.set(container, containerT, t); - if (AbstractContainerMenu.isValidQuickcraftType(t, player)) { - u = 1; - mod.clear(); - } else { - mod.clear(); - u = 0; - } - break; - } - case 1: { - if (slot < 0) { - Ref.set(container, containerU, u); - return; // nothing - } - int t = (int) Ref.get(container, containerT); - final Slot bslot = container.getSlot(slot); - final net.minecraft.world.item.ItemStack itemstack = container.getCarried(); - if (AbstractContainerMenu.canItemQuickReplace(bslot, itemstack, true) && bslot.mayPlace(itemstack) && (t == 2 || itemstack.getCount() > mod.size()) && container.canDragTo(bslot)) - mod.add(bslot); - break; - } - case 2: - if (!mod.isEmpty()) { - final net.minecraft.world.item.ItemStack itemstack2 = container.getCarried().copy(); - if (itemstack2.isEmpty()) { - mod.clear(); - Ref.set(container, containerU, 0); - return; - } - int t = (int) Ref.get(container, containerT); - int l = container.getCarried().getCount(); - final Map draggedSlots = new HashMap<>(); - for (Slot slot2 : mod) { - final net.minecraft.world.item.ItemStack itemstack3 = container.getCarried(); - if (slot2 != null && AbstractContainerMenu.canItemQuickReplace(slot2, itemstack3, true) && slot2.mayPlace(itemstack3) && (t == 2 || itemstack3.getCount() >= mod.size()) - && container.canDragTo(slot2)) { - final int j1 = slot2.hasItem() ? slot2.getItem().getCount() : 0; - final int k1 = Math.min(itemstack2.getMaxStackSize(), slot2.getMaxStackSize(itemstack2)); - final int l2 = Math.min(AbstractContainerMenu.getQuickCraftPlaceCount(mod, t, itemstack2) + j1, k1); - l -= l2 - j1; - draggedSlots.put(slot2.index, itemstack2.copyWithCount(l2)); - } - } - final InventoryView view = container.getBukkitView(); - final org.bukkit.inventory.ItemStack newcursor = CraftItemStack.asCraftMirror(itemstack2); - newcursor.setAmount(l); - final Map guiSlots = new HashMap<>(); - final Map playerSlots = new HashMap<>(); - for (final Entry ditem : draggedSlots.entrySet()) - if (ditem.getKey() < gui.size()) - guiSlots.put(ditem.getKey(), CraftItemStack.asBukkitCopy(ditem.getValue())); - else { - int finalSlot = ditem.getKey() - gui.size(); - if (finalSlot >= 27) - finalSlot -= 27; - else - finalSlot += 9; - playerSlots.put(finalSlot, CraftItemStack.asBukkitCopy(ditem.getValue())); - } - container.setCarried(CraftItemStack.asNMSCopy(newcursor)); - if (!guiSlots.isEmpty() || !playerSlots.isEmpty()) - gui.onMultipleIteract((Player) player.getBukkitEntity(), guiSlots, playerSlots); - for (final Entry dslot : draggedSlots.entrySet()) - view.setItem(dslot.getKey(), CraftItemStack.asBukkitCopy(dslot.getValue())); - if (container.getCarried() != null) - container.sendAllDataToRemote(); - } - mod.clear(); - u = 0; - default: - mod.clear(); - u = 0; - break; - } - Ref.set(container, containerU, u); - } - - @Override - public boolean processServerListPing(String player, Object channel, Object packet) { - if (packet instanceof PacketContainer) { - PacketContainer container = (PacketContainer) packet; - ClientboundStatusResponsePacket status = (ClientboundStatusResponsePacket) container.getPacket(); - ServerStatus ping = status.status(); - List gameProfiles = new ArrayList<>(); - if (ping.players().isPresent()) - for (GameProfile profile : ping.players().get().sample()) - gameProfiles.add(fromGameProfile(profile)); - - net.minecraft.network.chat.Component motd = net.minecraft.network.chat.Component.literal(""); - Optional players = Optional.empty(); - Optional serverIcon = Optional.empty(); - Optional version = ping.version(); - boolean enforceSecureProfile = ping.enforcesSecureChat(); - - String favicon = "server-icon.png"; - ServerListPingEvent event = new ServerListPingEvent(getOnlinePlayers().size(), Bukkit.getMaxPlayers(), gameProfiles, Bukkit.getMotd(), favicon, - ((InetSocketAddress) ((Channel) channel).remoteAddress()).getAddress(), ping.version().get().name(), ping.version().get().protocol()); - EventManager.call(event); - if (event.isCancelled()) { - container.setCancelled(true); - return true; - } - Players playerSample = new Players(event.getMaxPlayers(), event.getOnlinePlayers(), new ArrayList<>()); - if (event.getSlots() != null) - for (GameProfileHandler s : event.getSlots()) - playerSample.sample().add(new GameProfile(s.getUUID(), s.getUsername())); - players = Optional.of(playerSample); - - if (event.getMotd() != null) - motd = (net.minecraft.network.chat.Component) this.toIChatBaseComponent(ComponentAPI.fromString(event.getMotd())); - if (event.getVersion() != null) - version = Optional.of(new Version(event.getVersion(), event.getProtocol())); - if (event.getFavicon() != null) - if (!event.getFavicon().equals("server-icon.png") && new File(event.getFavicon()).exists()) { - BufferedImage var1; - try { - var1 = ImageIO.read(new File(event.getFavicon())); - if (var1.getWidth() != 64) throw new IOException("Must be 64 pixels wide"); - if (var1.getHeight() != 64) throw new IOException("Must be 64 pixels high"); - ByteArrayOutputStream var2 = new ByteArrayOutputStream(); - ImageIO.write(var1, "PNG", var2); - serverIcon = Optional.of(new Favicon(var2.toByteArray())); - } catch (IOException e) { - e.printStackTrace(); - } - } else - serverIcon = ping.favicon(); - container.setPacket(new ClientboundStatusResponsePacket(new ServerStatus(motd, players, version, serverIcon, enforceSecureProfile))); - return false; - } - JavaPlugin.getPlugin(BukkitLoader.class).getLogger().warning("You are using outdated version of TheAPI, please update TheAPI to the latest version!"); - return false; - } - - @Override - public Object getNBT(Entity entity) { - return ((CraftEntity) entity).getHandle().saveWithoutId(new CompoundTag()); - } - - @Override - public Object setString(Object nbt, String path, String value) { - ((CompoundTag) nbt).putString(path, value); - return nbt; - } - - @Override - public Object setInteger(Object nbt, String path, int value) { - ((CompoundTag) nbt).putInt(path, value); - return nbt; - } - - @Override - public Object setDouble(Object nbt, String path, double value) { - ((CompoundTag) nbt).putDouble(path, value); - return nbt; - } - - @Override - public Object setLong(Object nbt, String path, long value) { - ((CompoundTag) nbt).putLong(path, value); - return nbt; - } - - @Override - public Object setShort(Object nbt, String path, short value) { - ((CompoundTag) nbt).putShort(path, value); - return nbt; - } - - @Override - public Object setFloat(Object nbt, String path, float value) { - ((CompoundTag) nbt).putFloat(path, value); - return nbt; - } - - @Override - public Object setBoolean(Object nbt, String path, boolean value) { - ((CompoundTag) nbt).putBoolean(path, value); - return nbt; - } - - @Override - public Object setIntArray(Object nbt, String path, int[] value) { - ((CompoundTag) nbt).putIntArray(path, value); - return nbt; - } - - @Override - public Object setByteArray(Object nbt, String path, byte[] value) { - ((CompoundTag) nbt).putByteArray(path, value); - return nbt; - } - - @Override - public Object setNBTBase(Object nbt, String path, Object value) { - ((CompoundTag) nbt).put(path, (Tag) value); - return nbt; - } - - @Override - public String getString(Object nbt, String path) { - return ((CompoundTag) nbt).getString(path); - } - - @Override - public int getInteger(Object nbt, String path) { - return ((CompoundTag) nbt).getInt(path); - } - - @Override - public double getDouble(Object nbt, String path) { - return ((CompoundTag) nbt).getDouble(path); - } - - @Override - public long getLong(Object nbt, String path) { - return ((CompoundTag) nbt).getLong(path); - } - - @Override - public short getShort(Object nbt, String path) { - return ((CompoundTag) nbt).getShort(path); - } - - @Override - public float getFloat(Object nbt, String path) { - return ((CompoundTag) nbt).getFloat(path); - } - - @Override - public boolean getBoolean(Object nbt, String path) { - return ((CompoundTag) nbt).getBoolean(path); - } - - @Override - public int[] getIntArray(Object nbt, String path) { - return ((CompoundTag) nbt).getIntArray(path); - } - - @Override - public byte[] getByteArray(Object nbt, String path) { - return ((CompoundTag) nbt).getByteArray(path); - } - - @Override - public Object getNBTBase(Object nbt, String path) { - return ((CompoundTag) nbt).get(path); - } - - @Override - public Set getKeys(Object nbt) { - return ((CompoundTag) nbt).getAllKeys(); - } - - @Override - public boolean hasKey(Object nbt, String path) { - return ((CompoundTag) nbt).contains(path); - } - - @Override - public void removeKey(Object nbt, String path) { - ((CompoundTag) nbt).remove(path); - } - - @Override - public Object setByte(Object nbt, String path, byte value) { - ((CompoundTag) nbt).putByte(path, value); - return nbt; - } - - @Override - public byte getByte(Object nbt, String path) { - return ((CompoundTag) nbt).getByte(path); - } - - @Override - public Object getDataWatcher(Entity entity) { - return ((CraftEntity) entity).getHandle().getEntityData(); - } - - @Override - public Object getDataWatcher(Object entity) { - return ((net.minecraft.world.entity.Entity) entity).getEntityData(); - } - - @Override - public int incrementStateId(Object container) { - return ((AbstractContainerMenu) container).incrementStateId(); - } - - @Override - public Object packetEntityHeadRotation(Entity entity) { - return new ClientboundRotateHeadPacket((net.minecraft.world.entity.Entity) getEntity(entity), (byte) (entity.getLocation().getYaw() * 256F / 360F)); - } - - @Override - public Object packetHeldItemSlot(int slot) { - return new ClientboundSetCarriedItemPacket(slot); - } - - @Override - public Object packetExp(float exp, int total, int toNextLevel) { - return new ClientboundSetExperiencePacket(exp, total, toNextLevel); - } - - @Override - public Object packetPlayerInfo(PlayerInfoType type, Player player) { - ClientboundPlayerInfoUpdatePacket.Action action = null; - switch (type) { - case ADD_PLAYER: - action = ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER; - break; - case REMOVE_PLAYER: - return new ClientboundPlayerInfoRemovePacket(Arrays.asList(player.getUniqueId())); - case UPDATE_DISPLAY_NAME: - action = ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME; - break; - case UPDATE_GAME_MODE: - action = ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE; - break; - case UPDATE_LATENCY: - action = ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY; - break; - } - return new ClientboundPlayerInfoUpdatePacket(action, (ServerPlayer) getPlayer(player)); - } - - @Override - public Object packetPlayerInfo(PlayerInfoType type, GameProfileHandler gameProfile, int latency, GameMode gameMode, Component playerName) { - ClientboundPlayerInfoUpdatePacket.Action action = null; - switch (type) { - case ADD_PLAYER: - action = ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER; - break; - case REMOVE_PLAYER: - return new ClientboundPlayerInfoRemovePacket(Arrays.asList(gameProfile.getUUID())); - case UPDATE_DISPLAY_NAME: - action = ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME; - break; - case UPDATE_GAME_MODE: - action = ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE; - break; - case UPDATE_LATENCY: - action = ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY; - break; - } - - EnumSet set = EnumSet.of(action); - List list = Arrays.asList(new ClientboundPlayerInfoUpdatePacket.Entry(gameProfile.getUUID(), (GameProfile) toGameProfile(gameProfile), true, latency, - gameMode == null ? GameType.SURVIVAL : GameType.byName(gameMode.name().toLowerCase()), - (net.minecraft.network.chat.Component) (playerName == null ? toIChatBaseComponent(new Component(gameProfile.getUsername())) : toIChatBaseComponent(playerName)), null)); - return new ClientboundPlayerInfoUpdatePacket(set, list); - } - - @Override - public Object packetPosition(double x, double y, double z, float yaw, float pitch) { - return new ServerboundMovePlayerPacket.PosRot(x, y, z, yaw, pitch, true); - } - - @Override - public Object packetRespawn(Player player) { - ServerPlayer entityPlayer = (ServerPlayer) getPlayer(player); - return new ClientboundRespawnPacket(entityPlayer.createCommonSpawnInfo(entityPlayer.serverLevel()), (byte) 1); - } - - @Override - public String getProviderName() { - return "PaperMC 1.21"; - } - - @Override - public int getContainerStateId(Object container) { - return ((AbstractContainerMenu) container).getStateId(); - } - - @Override - public void loadParticles() { - for (Entry>, ParticleType> s : BuiltInRegistries.PARTICLE_TYPE.entrySet()) - me.devtec.theapi.bukkit.game.particles.Particle.identifier.put(s.getKey().location().getPath(), s.getValue()); - } - - @Override - public Object toGameProfile(GameProfileHandler gameProfileHandler) { - - GameProfile profile = new GameProfile(gameProfileHandler.getUUID(), gameProfileHandler.getUsername()); - for (Entry entry : gameProfileHandler.getProperties().entrySet()) - profile.getProperties().put(entry.getKey(), new Property(entry.getValue().getName(), entry.getValue().getValues(), entry.getValue().getSignature())); - return profile; - } - - private Field name = Ref.field(Property.class, "name"), value = Ref.field(Property.class, "value"), signature = Ref.field(Property.class, "signature"); - - @Override - public GameProfileHandler fromGameProfile(Object gameProfile) { - GameProfile profile = (GameProfile) gameProfile; - GameProfileHandler handler = GameProfileHandler.of(profile.getName(), profile.getId()); - for (Entry entry : profile.getProperties().entries()) - handler.getProperties().put(entry.getKey(), - PropertyHandler.of((String) Ref.get(entry.getValue(), name), (String) Ref.get(entry.getValue(), value), (String) Ref.get(entry.getValue(), signature))); - return handler; - } - - @Override - public Object getGameProfile(Object nmsPlayer) { - return ((net.minecraft.world.entity.player.Player) nmsPlayer).getGameProfile(); - } - -} diff --git a/paper-mappings.yml b/paper-mappings.yml new file mode 100644 index 00000000..eb444337 --- /dev/null +++ b/paper-mappings.yml @@ -0,0 +1,3 @@ +1_20_6: 1.20.6 +1_21: 1.20.6 +1_21_1: 1.20.6 \ No newline at end of file