diff --git a/NmsProvider - 1.21.R1/.classpath b/NmsProvider - 1.21.R1/.classpath
new file mode 100644
index 00000000..fa968cc5
--- /dev/null
+++ b/NmsProvider - 1.21.R1/.classpath
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NmsProvider - 1.21.R1/src/me/devtec/theapi/bukkit/nms/v1_21_R1.java b/NmsProvider - 1.21.R1/src/me/devtec/theapi/bukkit/nms/v1_21_R1.java
new file mode 100644
index 00000000..1907ca5d
--- /dev/null
+++ b/NmsProvider - 1.21.R1/src/me/devtec/theapi/bukkit/nms/v1_21_R1.java
@@ -0,0 +1,1759 @@
+package me.devtec.theapi.bukkit.nms;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import java.util.UUID;
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
+
+import javax.imageio.ImageIO;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Chunk;
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.block.BlockState;
+import org.bukkit.craftbukkit.v1_21_R1.CraftChunk;
+import org.bukkit.craftbukkit.v1_21_R1.CraftWorld;
+import org.bukkit.craftbukkit.v1_21_R1.block.data.CraftBlockData;
+import org.bukkit.craftbukkit.v1_21_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_21_R1.entity.CraftLivingEntity;
+import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftContainer;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.v1_21_R1.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 com.google.common.base.Preconditions;
+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.ClickEvent;
+import me.devtec.shared.components.Component;
+import me.devtec.shared.components.ComponentAPI;
+import me.devtec.shared.components.ComponentEntity;
+import me.devtec.shared.components.ComponentItem;
+import me.devtec.shared.components.HoverEvent;
+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.PropertyHandler;
+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.EnumChatFormat;
+import net.minecraft.commands.CommandBuildContext;
+import net.minecraft.commands.CommandDispatcher;
+import net.minecraft.core.BlockPosition;
+import net.minecraft.core.component.DataComponents;
+import net.minecraft.core.particles.Particle;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.data.registries.VanillaRegistries;
+import net.minecraft.nbt.MojangsonParser;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.network.chat.ChatClickable;
+import net.minecraft.network.chat.ChatClickable.EnumClickAction;
+import net.minecraft.network.chat.ChatHexColor;
+import net.minecraft.network.chat.ChatHoverable;
+import net.minecraft.network.chat.ChatHoverable.EnumHoverAction;
+import net.minecraft.network.chat.ChatModifier;
+import net.minecraft.network.chat.IChatBaseComponent;
+import net.minecraft.network.chat.IChatMutableComponent;
+import net.minecraft.network.protocol.common.ClientboundResourcePackPushPacket;
+import net.minecraft.network.protocol.game.ClientboundClearTitlesPacket;
+import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
+import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
+import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket.a;
+import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket;
+import net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket;
+import net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket;
+import net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket;
+import net.minecraft.network.protocol.game.ClientboundSystemChatPacket;
+import net.minecraft.network.protocol.game.PacketPlayInWindowClick;
+import net.minecraft.network.protocol.game.PacketPlayOutBlockChange;
+import net.minecraft.network.protocol.game.PacketPlayOutCloseWindow;
+import net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy;
+import net.minecraft.network.protocol.game.PacketPlayOutEntityHeadRotation;
+import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata;
+import net.minecraft.network.protocol.game.PacketPlayOutExperience;
+import net.minecraft.network.protocol.game.PacketPlayOutHeldItemSlot;
+import net.minecraft.network.protocol.game.PacketPlayOutOpenWindow;
+import net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter;
+import net.minecraft.network.protocol.game.PacketPlayOutPosition;
+import net.minecraft.network.protocol.game.PacketPlayOutRespawn;
+import net.minecraft.network.protocol.game.PacketPlayOutScoreboardDisplayObjective;
+import net.minecraft.network.protocol.game.PacketPlayOutScoreboardObjective;
+import net.minecraft.network.protocol.game.PacketPlayOutScoreboardScore;
+import net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam;
+import net.minecraft.network.protocol.game.PacketPlayOutSetSlot;
+import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity;
+import net.minecraft.network.protocol.status.PacketStatusOutServerInfo;
+import net.minecraft.network.protocol.status.ServerPing;
+import net.minecraft.network.protocol.status.ServerPing.ServerData;
+import net.minecraft.network.protocol.status.ServerPing.ServerPingPlayerSample;
+import net.minecraft.resources.MinecraftKey;
+import net.minecraft.resources.ResourceKey;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.ScoreboardServer;
+import net.minecraft.server.level.EntityPlayer;
+import net.minecraft.server.level.WorldServer;
+import net.minecraft.server.network.PlayerConnection;
+import net.minecraft.server.network.ServerCommonPacketListenerImpl;
+import net.minecraft.world.entity.EntityLiving;
+import net.minecraft.world.entity.EntityTypes;
+import net.minecraft.world.entity.player.EntityHuman;
+import net.minecraft.world.entity.player.PlayerInventory;
+import net.minecraft.world.inventory.ClickAction;
+import net.minecraft.world.inventory.Container;
+import net.minecraft.world.inventory.ContainerAccess;
+import net.minecraft.world.inventory.ContainerAnvil;
+import net.minecraft.world.inventory.Containers;
+import net.minecraft.world.inventory.InventoryClickType;
+import net.minecraft.world.inventory.Slot;
+import net.minecraft.world.item.Item;
+import net.minecraft.world.item.component.CustomData;
+import net.minecraft.world.level.EnumGamemode;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.BlockFalling;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.block.ITileEntity;
+import net.minecraft.world.level.block.entity.TileEntity;
+import net.minecraft.world.level.block.state.BlockStateList;
+import net.minecraft.world.level.block.state.IBlockData;
+import net.minecraft.world.level.block.state.IBlockDataHolder;
+import net.minecraft.world.level.block.state.properties.IBlockState;
+import net.minecraft.world.level.chunk.Chunk.EnumTileEntityState;
+import net.minecraft.world.level.chunk.ChunkSection;
+import net.minecraft.world.level.chunk.status.ChunkStatus;
+import net.minecraft.world.scores.DisplaySlot;
+import net.minecraft.world.scores.ScoreboardObjective;
+import net.minecraft.world.scores.criteria.IScoreboardCriteria.EnumScoreboardHealthDisplay;
+
+public class v1_21_R1 implements NmsProvider {
+ private static final MinecraftServer server = MinecraftServer.getServer();
+ private static final IChatBaseComponent empty = IChatBaseComponent.b("");
+ private static final CommandBuildContext dispatcher = CommandDispatcher.a(VanillaRegistries.a());
+
+ @Override
+ public Collection extends Player> 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.n);
+ }
+
+ @Override
+ public int getEntityId(Object entity) {
+ return ((net.minecraft.world.entity.Entity) entity).an();
+ }
+
+ @Override
+ public Object getScoreboardAction(Action type) {
+ return type == Action.CHANGE ? ScoreboardServer.Action.a : ScoreboardServer.Action.b;
+ }
+
+ @Override
+ public Object getEnumScoreboardHealthDisplay(DisplayType type) {
+ return type == DisplayType.INTEGER ? EnumScoreboardHealthDisplay.a : EnumScoreboardHealthDisplay.b;
+ }
+
+ @Override
+ public Object getNBT(ItemStack itemStack) {
+ net.minecraft.world.item.ItemStack item = (net.minecraft.world.item.ItemStack) asNMSItem(itemStack);
+ if (item.e())
+ return new NBTTagCompound();
+ CustomData data = item.a(DataComponents.b);
+ if (data != null)
+ return data.c();
+ return null;
+ }
+
+ @Override
+ public Object parseNBT(String json) {
+ if (json == null)
+ return new NBTTagCompound();
+ try {
+ return MojangsonParser.a(json);
+ } catch (Exception e) {
+ return new NBTTagCompound();
+ }
+ }
+
+ @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.b(DataComponents.b, CustomData.a((NBTTagCompound) nbt));
+ return asBukkitItem(item);
+ }
+
+ @Override
+ public Object asNMSItem(ItemStack stack) {
+ if (stack == null)
+ return net.minecraft.world.item.ItemStack.l;
+ return CraftItemStack.asNMSCopy(stack);
+ }
+
+ @Override
+ public ItemStack asBukkitItem(Object stack) {
+ return CraftItemStack.asBukkitCopy(stack == null ? net.minecraft.world.item.ItemStack.l : (net.minecraft.world.item.ItemStack) stack);
+ }
+
+ @Override
+ public int getContainerId(Object container) {
+ return ((Container) container).j;
+ }
+
+ @Override
+ public Object packetResourcePackSend(String url, String hash, boolean requireRP, Component prompt) {
+ return new ClientboundResourcePackPushPacket(UUID.randomUUID(), url, hash, requireRP,
+ prompt == null ? null : prompt == null ? Optional.empty() : Optional.of((IChatBaseComponent) this.toIChatBaseComponent(prompt)));
+ }
+
+ @Override
+ public Object packetSetSlot(int container, int slot, int changeId, Object itemStack) {
+ return new PacketPlayOutSetSlot(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 PacketPlayOutEntityMetadata(entityId, ((net.minecraft.network.syncher.DataWatcher) dataWatcher).c());
+ }
+
+ @Override
+ public Object packetEntityDestroy(int... ids) {
+ return new PacketPlayOutEntityDestroy(ids);
+ }
+
+ @Override
+ public Object packetSpawnEntity(Object entity, int id) {
+ BlockPosition pos = new BlockPosition(((net.minecraft.world.entity.Entity) entity).ds(), ((net.minecraft.world.entity.Entity) entity).dy(), ((net.minecraft.world.entity.Entity) entity).du());
+ return new PacketPlayOutSpawnEntity((net.minecraft.world.entity.Entity) entity, id, pos);
+ }
+
+ @Override
+ public Object packetNamedEntitySpawn(Object player) {
+ BlockPosition pos = new BlockPosition(((EntityHuman) player).ds(), ((EntityHuman) player).dy(), ((EntityHuman) player).du());
+ return new PacketPlayOutSpawnEntity((EntityHuman) player, 0, pos);
+ }
+
+ @Override
+ public Object packetSpawnEntityLiving(Object entityLiving) {
+ BlockPosition pos = new BlockPosition(((EntityLiving) entityLiving).ds(), ((EntityLiving) entityLiving).dy(), ((EntityLiving) entityLiving).du());
+ return new PacketPlayOutSpawnEntity((EntityLiving) entityLiving, 0, pos);
+ }
+
+ @Override
+ public Object packetPlayerListHeaderFooter(Component header, Component footer) {
+ return new PacketPlayOutPlayerListHeaderFooter((IChatBaseComponent) this.toIChatBaseComponent(header), (IChatBaseComponent) this.toIChatBaseComponent(footer));
+ }
+
+ @Override
+ public Object packetBlockChange(int x, int y, int z, Object iblockdata, int data) {
+ return new PacketPlayOutBlockChange(new BlockPosition(x, y, z), iblockdata == null ? Blocks.a.o() : (IBlockData) iblockdata);
+ }
+
+ @Override
+ public Object packetScoreboardObjective() {
+ return Ref.newUnsafeInstance(PacketPlayOutScoreboardObjective.class);
+ }
+
+ @Override
+ public Object packetScoreboardDisplayObjective(int id, Object scoreboardObjective) {
+ return new PacketPlayOutScoreboardDisplayObjective(DisplaySlot.values()[id], scoreboardObjective == null ? null : (ScoreboardObjective) scoreboardObjective);
+ }
+
+ @Override
+ public Object packetScoreboardTeam() {
+ return Ref.newUnsafeInstance(PacketPlayOutScoreboardTeam.class);
+ }
+
+ @Override
+ public Object packetScoreboardScore(Action action, String player, String line, int score) {
+ return new PacketPlayOutScoreboardScore(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((IChatBaseComponent) this.toIChatBaseComponent(text));
+ case TITLE:
+ return new ClientboundSetTitleTextPacket((IChatBaseComponent) this.toIChatBaseComponent(text));
+ case SUBTITLE:
+ return new ClientboundSetSubtitleTextPacket((IChatBaseComponent) 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((IChatBaseComponent) chatBase, false);
+ }
+
+ @Override
+ public Object packetChat(ChatType type, Component text, UUID uuid) {
+ return new ClientboundSystemChatPacket((IChatBaseComponent) this.toIChatBaseComponent(text), false);
+ }
+
+ @Override
+ public void postToMainThread(Runnable runnable) {
+ v1_21_R1.server.execute(runnable);
+ }
+
+ @Override
+ public Object getMinecraftServer() {
+ return v1_21_R1.server;
+ }
+
+ @Override
+ public Thread getServerThread() {
+ return v1_21_R1.server.aj;
+ }
+
+ @Override
+ public double[] getServerTPS() {
+ return v1_21_R1.server.recentTps;
+ }
+
+ private IChatBaseComponent convert(Component c) {
+ if (c instanceof ComponentItem || c instanceof ComponentEntity)
+ return IChatBaseComponent.ChatSerializer.a(Json.writer().simpleWrite(c.toJsonMap()), dispatcher);
+ IChatMutableComponent current = IChatBaseComponent.b(c.getText());
+ ChatModifier modif = current.a();
+ if (c.getColor() != null && !c.getColor().isEmpty())
+ if (c.getColor().startsWith("#"))
+ modif = modif.a(ChatHexColor.a(Integer.decode(c.getColor())));
+ else
+ modif = modif.a(EnumChatFormat.a(c.colorToChar()));
+ if (c.getClickEvent() != null)
+ modif = modif.a(new ChatClickable(EnumClickAction.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();
+ IChatBaseComponent component = compoundTag.getName() == null ? null : (IChatBaseComponent) toIChatBaseComponent(compoundTag.getName());
+ EntityTypes> entityType = BuiltInRegistries.f.a(MinecraftKey.a(compoundTag.getType()));
+ modif = modif.a(new ChatHoverable(EnumHoverAction.c, new ChatHoverable.b(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) {
+ NBTTagCompound nbt = (NBTTagCompound) parseNBT(compoundTag.getNbt());
+ if (!nbt.e().contains("id"))
+ nbt.a("id", BuiltInRegistries.g.b(CraftMagicNumbers.getItem(XMaterial.matchXMaterial(compoundTag.getId()).orElse(XMaterial.AIR).parseMaterial())).toString());
+ if (!nbt.e().contains("count"))
+ nbt.a("count", compoundTag.getCount());
+ stack = net.minecraft.world.item.ItemStack.a(CommandDispatcher.a(VanillaRegistries.a()), nbt);
+ }
+ modif = modif.a(new ChatHoverable(EnumHoverAction.b, new ChatHoverable.c(stack)));
+ } catch (Exception commandSyntaxException) {
+ }
+ break;
+ default:
+ modif = modif.a(new ChatHoverable(EnumHoverAction.a, (IChatBaseComponent) this.toIChatBaseComponent(c.getHoverEvent().getValue())));
+ break;
+ }
+ modif = modif.a(c.isBold());
+ modif = modif.b(c.isItalic());
+ modif = modif.e(c.isObfuscated());
+ modif = modif.c(c.isUnderlined());
+ modif = modif.d(c.isStrikethrough());
+ current.b(modif);
+ return current;
+ }
+
+ @Override
+ public Object[] toIChatBaseComponents(List components) {
+ List chat = new ArrayList<>();
+ chat.add(IChatBaseComponent.b(""));
+ 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 IChatBaseComponent[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 IChatBaseComponent[] { empty };
+ if (co instanceof ComponentItem || co instanceof ComponentEntity)
+ return new IChatBaseComponent[] { IChatBaseComponent.ChatSerializer.a(Json.writer().simpleWrite(co.toJsonMap()), dispatcher) };
+ List chat = new ArrayList<>();
+ chat.add(IChatBaseComponent.b(""));
+ 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 IChatBaseComponent[0]);
+ }
+
+ @Override
+ public Object toIChatBaseComponent(Component co) {
+ if (co == null)
+ return empty;
+ if (co instanceof ComponentItem || co instanceof ComponentEntity)
+ return IChatBaseComponent.ChatSerializer.a(Json.writer().simpleWrite(co.toJsonMap()), dispatcher);
+ IChatMutableComponent main = IChatBaseComponent.b("");
+ 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.c().addAll(chat);
+ return main.c().isEmpty() ? empty : main;
+ }
+
+ @Override
+ public Object toIChatBaseComponent(List cc) {
+ IChatMutableComponent main = IChatBaseComponent.b("");
+ for (Component c : cc)
+ main.c().add((IChatBaseComponent) this.toIChatBaseComponent(c));
+ return main.c().isEmpty() ? empty : main;
+ }
+
+ @Override
+ public Object chatBase(String json) {
+ return IChatBaseComponent.ChatSerializer.a(json, dispatcher);
+ }
+
+ @Override
+ public Component fromIChatBaseComponent(Object componentObject) {
+ if (componentObject == null)
+ return Component.EMPTY_COMPONENT;
+ IChatBaseComponent component = (IChatBaseComponent) componentObject;
+ Object result = Ref.invoke(component.b(), "b");
+ Component comp = new Component(result == null ? "" : (String) result);
+ ChatModifier modif = component.a();
+ if (modif.a() != null)
+ comp.setColor(modif.a().b());
+
+ if (modif.h() != null)
+ comp.setClickEvent(new ClickEvent(ClickEvent.Action.valueOf(modif.h().a().name()), modif.h().b()));
+
+ if (modif.i() != null)
+ switch (HoverEvent.Action.valueOf(modif.i().a().c().toUpperCase())) {
+ case SHOW_ENTITY: {
+ net.minecraft.network.chat.ChatHoverable.b hover = modif.i().a(EnumHoverAction.c);
+ ComponentEntity compEntity = new ComponentEntity(hover.b.toString(), hover.c);
+ if (hover.d.isPresent())
+ compEntity.setName(fromIChatBaseComponent(hover.d.get()));
+ comp.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ENTITY, compEntity));
+ break;
+ }
+ case SHOW_ITEM: {
+ net.minecraft.network.chat.ChatHoverable.c hover = modif.i().a(EnumHoverAction.b);
+ ComponentItem compEntity = new ComponentItem(CraftMagicNumbers.getMaterial(hover.a().g()).name(), hover.a().H());
+ if (hover.a().a() != null)
+ compEntity.setNbt(hover.a().a(CommandDispatcher.a(VanillaRegistries.a())).toString());
+ comp.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, compEntity));
+ break;
+ }
+ default:
+ IChatBaseComponent hover = modif.i().a(EnumHoverAction.a);
+ comp.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, fromIChatBaseComponent(hover)));
+ break;
+ }
+ comp.setBold(modif.b());
+ comp.setItalic(modif.c());
+ comp.setObfuscated(modif.d());
+ comp.setUnderlined(modif.e());
+ comp.setStrikethrough(modif.f());
+
+ if (!component.c().isEmpty()) {
+ List extra = new ArrayList<>();
+ for (IChatBaseComponent base : component.c())
+ extra.add(fromIChatBaseComponent(base));
+ comp.setExtra(extra);
+ }
+ return comp;
+ }
+
+ @Override
+ public BlockDataStorage toMaterial(Object blockOrIBlockData) {
+ if (blockOrIBlockData instanceof Block) {
+ IBlockData data = ((Block) blockOrIBlockData).o();
+ return new BlockDataStorage(CraftMagicNumbers.getMaterial(data.b()), (byte) 0, asString(data));
+ }
+ if (blockOrIBlockData instanceof IBlockData) {
+ IBlockData data = (IBlockData) blockOrIBlockData;
+ return new BlockDataStorage(CraftMagicNumbers.getMaterial(data.b()), (byte) 0, asString(data));
+ }
+ return new BlockDataStorage(Material.AIR);
+ }
+
+ private String asString(IBlockData data) {
+ StringBuilder stateString = new StringBuilder();
+ if (!data.C().isEmpty()) {
+ stateString.append('[');
+ stateString.append(data.C().entrySet().stream().map(IBlockDataHolder.a).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.a.o();
+ 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.a;
+ Block block = CraftMagicNumbers.getBlock(material.getType());
+ return readArgument(block, material).b();
+ }
+
+ private IBlockData readArgument(Block block, BlockDataStorage material) {
+ IBlockData ib = block.o();
+ return writeData(ib, ib.b().l(), material.getData());
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private static IBlockData writeData(IBlockData ib, BlockStateList 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 == ',') {
+ IBlockState ibj = blockStateList.a(key);
+ if (ibj != null) {
+ Optional optional = ibj.b(value);
+ if (optional.isPresent())
+ ib = ib.a(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) {
+ IBlockState ibj = blockStateList.a(key);
+ if (ibj != null) {
+ Optional optional = ibj.b(value);
+ if (optional.isPresent())
+ ib = ib.a(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.w());
+ }
+
+ @Override
+ public Object getChunk(World world, int x, int z) {
+ return ((CraftChunk) world.getChunkAt(x, z)).getHandle(ChunkStatus.n);
+ }
+
+ @Override
+ public void setBlock(Object objChunk, int x, int y, int z, Object IblockData, int data) {
+ net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) objChunk;
+ WorldServer world = chunk.r;
+ int highY = chunk.e(y);
+ if (highY < 0)
+ return;
+ ChunkSection sc = chunk.b(highY);
+ if (sc == null)
+ return;
+ BlockPosition pos = new BlockPosition(x, y, z);
+
+ IBlockData iblock = IblockData == null ? Blocks.a.o() : (IBlockData) IblockData;
+
+ boolean onlyModifyState = iblock.b() instanceof ITileEntity;
+
+ // REMOVE TILE ENTITY IF NOT SAME TYPE
+ TileEntity ent = chunk.k.get(pos);
+ if (ent != null) {
+ boolean shouldSkip = true;
+ if (!onlyModifyState)
+ shouldSkip = false;
+ else if (onlyModifyState && !ent.r().a(iblock)) {
+ shouldSkip = false;
+ onlyModifyState = false;
+ }
+ if (!shouldSkip)
+ chunk.d(pos);
+ }
+
+ IBlockData old = sc.a(x & 15, y & 15, z & 15, iblock, false);
+
+ // ADD TILE ENTITY
+ if (iblock.b() instanceof ITileEntity && !onlyModifyState) {
+ ent = ((ITileEntity) iblock.b()).a(pos, iblock);
+ chunk.k.put(pos, ent);
+ ent.a(chunk.r);
+ Object packet = ent.az_();
+ BukkitLoader.getPacketHandler().send(chunk.r.getWorld().getPlayers(), packet);
+ }
+
+ // MARK CHUNK TO SAVE
+ chunk.a(true);
+
+ // POI
+ if (!world.preventPoiUpdated)
+ world.a(pos, old, iblock);
+ }
+
+ @Override
+ public void updatePhysics(Object objChunk, int x, int y, int z, Object iblockdata) {
+ net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) objChunk;
+
+ BlockPosition blockPos = new BlockPosition(x, y, z);
+
+ doPhysicsAround(chunk.r, blockPos, ((IBlockData) iblockdata).b());
+ }
+
+ private void doPhysicsAround(WorldServer world, BlockPosition blockposition, Block block) {
+ doPhysics(world, blockposition.h(), block, blockposition); // west
+ doPhysics(world, blockposition.i(), block, blockposition); // east
+ doPhysics(world, blockposition.e(), block, blockposition); // down
+ doPhysics(world, blockposition.d(), block, blockposition); // up
+ doPhysics(world, blockposition.f(), block, blockposition); // north
+ doPhysics(world, blockposition.g(), block, blockposition); // south
+ }
+
+ private static final Method callPhysics = Ref.method(BlockFalling.class, "b", IBlockData.class, net.minecraft.world.level.World.class, BlockPosition.class, IBlockData.class, boolean.class);
+
+ private void doPhysics(WorldServer world, BlockPosition blockposition, Block block, BlockPosition blockposition1) {
+ IBlockData state = world.a_(blockposition);
+ state.a(world, blockposition, block, blockposition1, false);
+ if (state.b() instanceof BlockFalling)
+ Ref.invoke(state.b(), callPhysics, state, world, blockposition, block.o(), false);
+ }
+
+ @Override
+ public void updateLightAt(Object objChunk, int x, int y, int z) {
+ net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) objChunk;
+ chunk.r.l().a().a(new BlockPosition(x, y, z));
+ }
+
+ @Override
+ public Object getBlock(Object objChunk, int x, int y, int z) {
+ net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) objChunk;
+ int highY = chunk.e(y);
+ if (highY < 0)
+ return Blocks.a.o();
+ ChunkSection sc = chunk.b(highY);
+ if (sc == null)
+ return Blocks.a.o();
+ return sc.h().a(x & 15, y & 15, z & 15);
+ }
+
+ @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) {
+ net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) objChunk;
+ return chunk.a(new BlockPosition(x, y, z), EnumTileEntityState.a).a(dispatcher).toString();
+ }
+
+ @Override
+ public void setNBTToTile(Object objChunk, int x, int y, int z, String nbt) {
+ net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) objChunk;
+ TileEntity ent = chunk.a(new BlockPosition(x, y, z), EnumTileEntityState.a);
+ NBTTagCompound parsedNbt = (NBTTagCompound) parseNBT(nbt);
+ parsedNbt.a("x", x);
+ parsedNbt.a("y", y);
+ parsedNbt.a("z", z);
+ ent.a(parsedNbt);
+ Object packet = ent.az_();
+ BukkitLoader.getPacketHandler().send(chunk.r.getWorld().getPlayers(), packet);
+ }
+
+ @Override
+ public boolean isTileEntity(Object objChunk, int x, int y, int z) {
+ net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) objChunk;
+ return chunk.a(new BlockPosition(x, y, z), EnumTileEntityState.a) != null;
+ }
+
+ @Override
+ public int getCombinedId(Object IblockDataOrBlock) {
+ return Block.i((IBlockData) IblockDataOrBlock);
+ }
+
+ @Override
+ public Object blockPosition(int blockX, int blockY, int blockZ) {
+ return new BlockPosition(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((net.minecraft.world.level.chunk.Chunk) nmsChunk);
+ }
+
+ @Override
+ public int getPing(Player player) {
+ return ((PlayerConnection) getPlayerConnection(player)).k();
+ }
+
+ @Override
+ public Object getPlayerConnection(Player player) {
+ return ((EntityPlayer) getPlayer(player)).c;
+ }
+
+ private static Field networkManagerField = Ref.field(ServerCommonPacketListenerImpl.class, NetworkManager.class);
+
+ @Override
+ public Object getConnectionNetwork(Object playercon) {
+ return Ref.get(playercon, networkManagerField);
+ }
+
+ @Override
+ public Object getNetworkChannel(Object network) {
+ return ((NetworkManager) network).n;
+ }
+
+ @Override
+ public Object packetOpenWindow(int id, String legacy, int size, Component title) {
+ Containers> windowType = Containers.a;
+ switch (size) {
+ case 0: {
+ windowType = Containers.i;
+ break;
+ }
+ case 18: {
+ windowType = Containers.b;
+ break;
+ }
+ case 27: {
+ windowType = Containers.c;
+ break;
+ }
+ case 36: {
+ windowType = Containers.d;
+ break;
+ }
+ case 45: {
+ windowType = Containers.e;
+ break;
+ }
+ case 54: {
+ windowType = Containers.f;
+ break;
+ }
+ }
+ return new PacketPlayOutOpenWindow(id, windowType, (IChatBaseComponent) this.toIChatBaseComponent(title));
+ }
+
+ @Override
+ public void closeGUI(Player player, Object container, boolean closePacket) {
+ if (closePacket)
+ BukkitLoader.getPacketHandler().send(player, new PacketPlayOutCloseWindow(BukkitLoader.getNmsProvider().getContainerId(container)));
+ EntityPlayer nmsPlayer = (EntityPlayer) getPlayer(player);
+ nmsPlayer.cd = nmsPlayer.cc;
+ ((Container) container).transferTo(nmsPlayer.cd, (CraftPlayer) player);
+ }
+
+ @Override
+ public void setSlot(Object container, int slot, Object item) {
+ ((Container) container).b(slot, (net.minecraft.world.item.ItemStack) item);
+ }
+
+ @Override
+ public void setGUITitle(Player player, Object container, String legacy, int size, Component title) {
+ int id = ((Container) container).j;
+ BukkitLoader.getPacketHandler().send(player, packetOpenWindow(id, legacy, size, title));
+ net.minecraft.world.item.ItemStack carried = ((Container) container).g();
+ if (!carried.e())
+ BukkitLoader.getPacketHandler().send(player, new PacketPlayOutSetSlot(id, getContainerStateId(container), -1, carried));
+ int slot = 0;
+ for (net.minecraft.world.item.ItemStack item : ((Container) container).c()) {
+ if (slot == size)
+ break;
+ if (!item.e())
+ BukkitLoader.getPacketHandler().send(player, new PacketPlayOutSetSlot(id, getContainerStateId(container), slot, item));
+ ++slot;
+ }
+ }
+
+ @Override
+ public void openGUI(Player player, Object container, String legacy, int size, Component title) {
+ EntityPlayer nmsPlayer = ((CraftPlayer) player).getHandle();
+ int id = ((Container) container).j;
+ BukkitLoader.getPacketHandler().send(player, packetOpenWindow(id, legacy, size, title));
+ nmsPlayer.cd.transferTo((Container) container, (CraftPlayer) player);
+ nmsPlayer.cd = (Container) container;
+ postToMainThread(() -> nmsPlayer.a((Container) container));
+ ((Container) 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) {
+ ContainerAnvil container = new ContainerAnvil(((CraftPlayer) player).getHandle().nextContainerCounter(), ((CraftPlayer) player).getHandle().fY(), new ContainerAccess() {
+
+ @Override
+ public Optional a(BiFunction getter) {
+ return Optional.empty();
+ }
+
+ @Override
+ public Location getLocation() {
+ return null;
+ }
+ });
+ postToMainThread(() -> {
+ int slot = 0;
+ for (ItemStack stack : inv.getContents())
+ container.b(slot++).d((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 : ((Container) container).b(slot).g();
+ }
+
+ @Override
+ public String getAnvilRenameText(Object anvil) {
+ return ((ContainerAnvil) anvil).v;
+ }
+
+ 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) {
+ PacketPlayInWindowClick packet = (PacketPlayInWindowClick) provPacket;
+ int slot = packet.e();
+
+ Object container = gui.getContainer(player);
+ if (container == null)
+ return false;
+
+ int id = packet.b();
+ int mouseClick = packet.f();
+ InventoryClickType type = packet.i();
+ Container c = (Container) container;
+
+ if (slot < -1 && slot != -999)
+ return true;
+
+ EntityHuman nPlayer = ((CraftPlayer) player).getHandle();
+
+ ItemStack newItem;
+ ItemStack oldItem;
+ switch (type) {
+ case a: // PICKUP
+ oldItem = asBukkitItem(getSlotItem(container, slot));
+ newItem = asBukkitItem(c.g());
+ if (slot > 0 && mouseClick != 0) {
+ if (c.g().e()) { // 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 b: // QUICK_MOVE
+ newItem = asBukkitItem(c.g());
+ oldItem = asBukkitItem(getSlotItem(container, slot));
+ break;
+ case c:// SWAP
+ newItem = asBukkitItem(nPlayer.fY().a(mouseClick));
+ oldItem = asBukkitItem(getSlotItem(container, slot));
+ break;
+ case d:// CLONE
+ newItem = asBukkitItem(getSlotItem(container, slot));
+ oldItem = asBukkitItem(getSlotItem(container, slot));
+ break;
+ case e:// THROW
+ if (c.g().e() && slot >= 0) {
+ Slot slot3 = c.b(slot);
+ newItem = asBukkitItem(slot3.g());
+ if (mouseClick != 0 || newItem.getAmount() - 1 <= 0)
+ newItem = new ItemStack(Material.AIR);
+ else
+ newItem.setAmount(newItem.getAmount() - 1);
+ } else
+ newItem = asBukkitItem(c.g());
+ oldItem = asBukkitItem(getSlotItem(container, slot));
+ break;
+ case f:// QUICK_CRAFT
+ newItem = asBukkitItem(c.g());
+ oldItem = slot <= -1 ? new ItemStack(Material.AIR) : asBukkitItem(getSlotItem(container, slot));
+ break;
+ case g:// PICKUP_ALL
+ newItem = asBukkitItem(c.g());
+ oldItem = asBukkitItem(getSlotItem(container, slot));
+ break;
+ default:
+ newItem = slot <= -1 ? new ItemStack(Material.AIR) : asBukkitItem(packet.f());
+ oldItem = slot <= -1 ? new ItemStack(Material.AIR) : asBukkitItem(packet.f());
+ 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 == InventoryClickType.f ? 1 : type == InventoryClickType.b ? 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.j();
+ BukkitLoader.getPacketHandler().send(player, packetSetSlot(-1, -1, statusId, c.g()));
+ switch (type) {
+ case d:
+ break;
+ case c:
+ case b:
+ case g:
+ c.b();
+ break;
+ default:
+ BukkitLoader.getPacketHandler().send(player, packetSetSlot(id, slot, statusId, c.b(slot).g()));
+ break;
+ }
+ return true;
+ }
+
+ private void processEvent(Container c, InventoryClickType type, HolderGUI gui, Player player, int slot, int gameSlot, ItemStack newItem, ItemStack oldItem, PacketPlayInWindowClick packet,
+ int mouseClick, ClickType clickType, EntityHuman nPlayer) {
+ c.h();
+ switch (type) {
+ case b: {
+ 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.b(2).a(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.fY().a(modif.getKey(), (net.minecraft.world.item.ItemStack) asNMSItem(modif.getValue()));
+ if (remaining == 0) {
+ c.b(gameSlot).d((net.minecraft.world.item.ItemStack) asNMSItem(null));
+ if (interactWithResultSlot) {
+ c.b(0).d((net.minecraft.world.item.ItemStack) asNMSItem(null));
+ c.b(1).d((net.minecraft.world.item.ItemStack) asNMSItem(null));
+ }
+ } else {
+ newItem.setAmount(remaining);
+ c.b(gameSlot).d((net.minecraft.world.item.ItemStack) asNMSItem(newItem));
+ }
+ } else {
+ for (Entry modif : modified.entrySet())
+ c.b(modif.getKey()).d((net.minecraft.world.item.ItemStack) asNMSItem(modif.getValue())); // Visual & Nms side
+ // Plugin & Bukkit side
+ gui.getInventory().setStorageContents(contents);
+ if (remaining == 0)
+ nPlayer.fY().a(gameSlot, (net.minecraft.world.item.ItemStack) asNMSItem(null));
+ else {
+ newItem.setAmount(remaining);
+ nPlayer.fY().a(gameSlot, (net.minecraft.world.item.ItemStack) asNMSItem(newItem));
+ }
+ }
+ c.i();
+ return;
+ }
+ default:
+ processClick(gui, gui.getNotInterableSlots(player), c, slot, mouseClick, type, nPlayer);
+ break;
+ }
+ postToMainThread(() -> {
+ if (type != InventoryClickType.f && (c.a().equals(Containers.i) || c.a().equals(Containers.v)))
+ c.b();
+ for (final it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry entry : Int2ObjectMaps.fastIterable(packet.h()))
+ c.b(entry.getIntKey(), entry.getValue());
+ c.a(packet.g());
+ c.i();
+ if (packet.j() != c.j())
+ c.e();
+ else
+ c.d();
+ });
+ }
+
+ private Method addAmount = Ref.method(Slot.class, "b", int.class);
+ private Method checkItem = Ref.method(Container.class, "a", EntityHuman.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, Container container, int slotIndex, int button, InventoryClickType actionType, EntityHuman player) {
+ if (actionType == InventoryClickType.f)
+ 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 == InventoryClickType.a && (button == 0 || button == 1)) {
+ ClickAction clickaction = button == 0 ? ClickAction.a : ClickAction.b;
+ if (slotIndex == -999) {
+ if (!container.g().e())
+ if (clickaction == ClickAction.a) {
+ net.minecraft.world.item.ItemStack carried = container.g();
+ container.b(net.minecraft.world.item.ItemStack.l);
+ postToMainThread(() -> player.a(carried, true));
+ } else
+ postToMainThread(() -> player.a(container.g().a(1), true));
+ } else {
+ if (slotIndex < 0)
+ return;
+ Slot slot = container.b(slotIndex);
+ net.minecraft.world.item.ItemStack itemstack = slot.g();
+ net.minecraft.world.item.ItemStack itemstack4 = container.g();
+ player.a(itemstack4, slot.g(), clickaction);
+ if (!(boolean) Ref.invoke(container, checkItem, player, clickaction, slot, itemstack, itemstack4))
+ if (itemstack.e()) {
+ if (!itemstack4.e()) {
+ int i2 = clickaction == ClickAction.a ? itemstack4.H() : 1;
+ net.minecraft.world.item.ItemStack stack = slot.b(itemstack4, i2);
+ container.b(stack);
+ }
+ } else if (slot.a(player))
+ if (itemstack4.e()) {
+ int i2 = clickaction == ClickAction.a ? itemstack.H() : (itemstack.H() + 1) / 2;
+ Optional optional = slot.a(i2, 2147483647, player);
+ optional.ifPresent(i -> {
+ container.b(i);
+ slot.a(player, i);
+ });
+ } else if (slot.a(itemstack4)) {
+ if (net.minecraft.world.item.ItemStack.c(itemstack, itemstack4)) {
+ int i2 = clickaction == ClickAction.a ? itemstack4.H() : 1;
+ net.minecraft.world.item.ItemStack stack = slot.b(itemstack4, i2);
+ container.b(stack);
+ } else if (itemstack4.H() <= slot.a_(itemstack4)) {
+ container.b(itemstack);
+ slot.d(itemstack4);
+ }
+ } else if (net.minecraft.world.item.ItemStack.c(itemstack, itemstack4)) {
+ Optional optional2 = slot.a(itemstack.H(), itemstack4.j() - itemstack4.H(), player);
+ optional2.ifPresent(i -> {
+ itemstack.g(i.H());
+ slot.a(player, i);
+ });
+ }
+ slot.b();
+ if (player instanceof EntityPlayer && slot.a() != 64) {
+ BukkitLoader.getPacketHandler().send((Player) player.getBukkitEntity(), BukkitLoader.getNmsProvider().packetSetSlot(j, slot.d, container.k(), slot.g()));
+ if (container.getBukkitView().getType() == InventoryType.WORKBENCH || container.getBukkitView().getType() == InventoryType.CRAFTING)
+ BukkitLoader.getPacketHandler().send((Player) player.getBukkitEntity(), BukkitLoader.getNmsProvider().packetSetSlot(j, 0, container.k(), container.b(0).g()));
+ }
+ }
+ } else if (actionType == InventoryClickType.c) {
+ if (slotIndex < 0)
+ return;
+ PlayerInventory playerinventory = player.fY();
+ Slot slot3 = container.b(slotIndex);
+ net.minecraft.world.item.ItemStack itemstack2 = playerinventory.a(button);
+ net.minecraft.world.item.ItemStack itemstack = slot3.g();
+ if (!itemstack2.e() || !itemstack.e())
+ if (itemstack2.e()) {
+ if (slot3.a(player)) {
+ playerinventory.a(button, itemstack);
+ Ref.invoke(slot3, addAmount, itemstack.H());
+ slot3.d(net.minecraft.world.item.ItemStack.l);
+ slot3.a(player, itemstack);
+ }
+ } else if (itemstack.e()) {
+ if (slot3.a(itemstack2)) {
+ int j2 = slot3.a_(itemstack2);
+ if (itemstack2.H() > j2)
+ slot3.d(itemstack2.a(j2));
+ else {
+ playerinventory.a(button, net.minecraft.world.item.ItemStack.l);
+ slot3.d(itemstack2);
+ }
+ }
+ } else if (slot3.a(player) && slot3.a(itemstack2)) {
+ int j2 = slot3.a_(itemstack2);
+ if (itemstack2.H() > j2) {
+ slot3.d(itemstack2.a(j2));
+ slot3.a(player, itemstack);
+ if (!playerinventory.f(itemstack))
+ postToMainThread(() -> player.a(itemstack, true));
+ } else {
+ playerinventory.a(button, itemstack);
+ slot3.d(itemstack2);
+ slot3.a(player, itemstack);
+ }
+ }
+ } else if (actionType == InventoryClickType.d && player.fZ().d && container.g().e() && slotIndex >= 0) {
+ Slot slot3 = container.b(slotIndex);
+ if (slot3.h()) {
+ net.minecraft.world.item.ItemStack itemstack2 = slot3.g();
+ container.b(itemstack2.c(itemstack2.j()));
+ }
+ } else if (actionType == InventoryClickType.e && container.g().e() && slotIndex >= 0) {
+ Slot slot3 = container.b(slotIndex);
+ int m = button == 0 ? 1 : slot3.g().H();
+ net.minecraft.world.item.ItemStack itemstack = slot3.b(m, 2147483647, player);
+ postToMainThread(() -> player.a(itemstack, true));
+ } else if (actionType == InventoryClickType.g && slotIndex >= 0) {
+ final Slot slot3 = container.i.get(slotIndex);
+ final net.minecraft.world.item.ItemStack itemstack2 = container.g();
+ if (!itemstack2.e() && (!slot3.h() || !slot3.a(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.i.size() - 1;
+ final int j2 = button == 0 ? 1 : -1;
+ for (int i2 = 0; i2 < 2; ++i2)
+ for (int slot = l; slot >= 0 && slot < container.i.size() && itemstack2.H() < itemstack2.j(); slot += j2) {
+ final Slot slot4 = container.i.get(slot);
+ if (slot4.h() && Container.a(slot4, itemstack2, true) && slot4.a(player) && container.a(itemstack2, slot4)) {
+ final net.minecraft.world.item.ItemStack itemstack5 = slot4.g();
+ if (i2 != 0 || itemstack5.H() != itemstack5.j()) {
+ if (slot < gui.size() && ignoreSlots.contains(slot)) {
+ corruptedSlots.add(slot);
+ continue;
+ }
+ final net.minecraft.world.item.ItemStack itemstack6 = slot4.b(itemstack5.H(), itemstack2.j() - itemstack2.H(), player);
+ itemstack2.g(itemstack6.H());
+ int gameSlot = slot > gui.size() - 1 ? InventoryUtils.convertToPlayerInvSlot(slot - gui.size()) : slot;
+ if (slot < gui.size())
+ modifiedSlots.put(gameSlot, asBukkitItem(slot4.g()));
+ else
+ modifiedSlotsPlayerInv.put(gameSlot, asBukkitItem(slot4.g()));
+ }
+ }
+ }
+ 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(Container.class, "u"), containerV = Ref.field(Container.class, "v"), containerT = Ref.field(Container.class, "t");
+
+ @SuppressWarnings("unchecked")
+ private void processDragMove(HolderGUI gui, Container container, EntityHuman 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.g().e()) {
+ mod.clear();
+ u = 0;
+ } else
+ switch (u) {
+ case 0: {
+ int t = c(mouseClick);
+ Ref.set(container, containerT, t);
+ if (Container.a(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.b(slot);
+ final net.minecraft.world.item.ItemStack itemstack = container.g();
+ if (Container.a(bslot, itemstack, true) && bslot.a(itemstack) && (t == 2 || itemstack.H() > mod.size()) && container.b(bslot))
+ mod.add(bslot);
+ break;
+ }
+ case 2:
+ if (!mod.isEmpty()) {
+ final net.minecraft.world.item.ItemStack itemstack2 = container.g().s();
+ if (itemstack2.e()) {
+ mod.clear();
+ Ref.set(container, containerU, 0);
+ return;
+ }
+ int t = (int) Ref.get(container, containerT);
+ int l = container.g().H();
+ final Map draggedSlots = new HashMap<>();
+ for (Slot slot2 : mod) {
+ final net.minecraft.world.item.ItemStack itemstack3 = container.g();
+ if (slot2 != null && Container.a(slot2, itemstack3, true) && slot2.a(itemstack3) && (t == 2 || itemstack3.H() >= mod.size()) && container.b(slot2)) {
+ final int j1 = slot2.h() ? slot2.g().H() : 0;
+ final int k1 = Math.min(itemstack2.j(), slot2.a_(itemstack2));
+ final int l2 = Math.min(Container.a(mod, t, itemstack2) + j1, k1);
+ l -= l2 - j1;
+ draggedSlots.put(slot2.d, itemstack2.c(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.b(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.g() != null)
+ container.b();
+ }
+ 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;
+ PacketStatusOutServerInfo status = (PacketStatusOutServerInfo) container.getPacket();
+ ServerPing ping = status.b();
+
+ List gameProfiles = new ArrayList<>();
+ for (GameProfile profile : ping.b().get().c())
+ gameProfiles.add(fromGameProfile(profile));
+
+ IChatBaseComponent motd = IChatBaseComponent.a("");
+ Optional players = Optional.empty();
+ Optional onlineCount = Optional.empty();
+ Optional serverIcon = Optional.empty();
+ boolean enforceSecureProfile = ping.e();
+
+ String favicon = "server-icon.png";
+ ServerListPingEvent event = new ServerListPingEvent(getOnlinePlayers().size(), Bukkit.getMaxPlayers(), gameProfiles, Bukkit.getMotd(), favicon,
+ ((InetSocketAddress) ((Channel) channel).remoteAddress()).getAddress(), ping.c().get().b(), ping.c().get().c());
+ EventManager.call(event);
+ if (event.isCancelled()) {
+ container.setCancelled(true);
+ return true;
+ }
+ ServerPingPlayerSample playerSample = new ServerPingPlayerSample(event.getMaxPlayers(), event.getOnlinePlayers(), new ArrayList<>());
+ if (event.getSlots() != null)
+ for (GameProfileHandler s : event.getSlots())
+ playerSample.c().add(new GameProfile(s.getUUID(), s.getUsername()));
+ players = Optional.of(playerSample);
+
+ if (event.getMotd() != null)
+ motd = (IChatBaseComponent) this.toIChatBaseComponent(ComponentAPI.fromString(event.getMotd()));
+ if (event.getVersion() != null)
+ onlineCount = Optional.of(new ServerData(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()));
+ Preconditions.checkState(var1.getWidth() == 64, "Must be 64 pixels wide");
+ Preconditions.checkState(var1.getHeight() == 64, "Must be 64 pixels high");
+ ByteArrayOutputStream var2 = new ByteArrayOutputStream();
+ ImageIO.write(var1, "PNG", var2);
+ serverIcon = Optional.of(new ServerPing.a(var2.toByteArray()));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ } else
+ serverIcon = ping.d();
+ container.setPacket(new PacketStatusOutServerInfo(new ServerPing(motd, players, onlineCount, 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().f(new NBTTagCompound());
+ }
+
+ @Override
+ public Object setString(Object nbt, String path, String value) {
+ ((NBTTagCompound) nbt).a(path, value);
+ return nbt;
+ }
+
+ @Override
+ public Object setInteger(Object nbt, String path, int value) {
+ ((NBTTagCompound) nbt).a(path, value);
+ return nbt;
+ }
+
+ @Override
+ public Object setDouble(Object nbt, String path, double value) {
+ ((NBTTagCompound) nbt).a(path, value);
+ return nbt;
+ }
+
+ @Override
+ public Object setLong(Object nbt, String path, long value) {
+ ((NBTTagCompound) nbt).a(path, value);
+ return nbt;
+ }
+
+ @Override
+ public Object setShort(Object nbt, String path, short value) {
+ ((NBTTagCompound) nbt).a(path, value);
+ return nbt;
+ }
+
+ @Override
+ public Object setFloat(Object nbt, String path, float value) {
+ ((NBTTagCompound) nbt).a(path, value);
+ return nbt;
+ }
+
+ @Override
+ public Object setBoolean(Object nbt, String path, boolean value) {
+ ((NBTTagCompound) nbt).a(path, value);
+ return nbt;
+ }
+
+ @Override
+ public Object setIntArray(Object nbt, String path, int[] value) {
+ ((NBTTagCompound) nbt).a(path, value);
+ return nbt;
+ }
+
+ @Override
+ public Object setByteArray(Object nbt, String path, byte[] value) {
+ ((NBTTagCompound) nbt).a(path, value);
+ return nbt;
+ }
+
+ @Override
+ public Object setNBTBase(Object nbt, String path, Object value) {
+ ((NBTTagCompound) nbt).a(path, (NBTBase) value);
+ return nbt;
+ }
+
+ @Override
+ public String getString(Object nbt, String path) {
+ return ((NBTTagCompound) nbt).l(path);
+ }
+
+ @Override
+ public int getInteger(Object nbt, String path) {
+ return ((NBTTagCompound) nbt).h(path);
+ }
+
+ @Override
+ public double getDouble(Object nbt, String path) {
+ return ((NBTTagCompound) nbt).i(path);
+ }
+
+ @Override
+ public long getLong(Object nbt, String path) {
+ return ((NBTTagCompound) nbt).i(path);
+ }
+
+ @Override
+ public short getShort(Object nbt, String path) {
+ return ((NBTTagCompound) nbt).g(path);
+ }
+
+ @Override
+ public float getFloat(Object nbt, String path) {
+ return ((NBTTagCompound) nbt).j(path);
+ }
+
+ @Override
+ public boolean getBoolean(Object nbt, String path) {
+ return ((NBTTagCompound) nbt).e(path);
+ }
+
+ @Override
+ public int[] getIntArray(Object nbt, String path) {
+ return ((NBTTagCompound) nbt).n(path);
+ }
+
+ @Override
+ public byte[] getByteArray(Object nbt, String path) {
+ return ((NBTTagCompound) nbt).m(path);
+ }
+
+ @Override
+ public Object getNBTBase(Object nbt, String path) {
+ return ((NBTTagCompound) nbt).c(path);
+ }
+
+ @Override
+ public Set getKeys(Object nbt) {
+ return ((NBTTagCompound) nbt).e();
+ }
+
+ @Override
+ public boolean hasKey(Object nbt, String path) {
+ return ((NBTTagCompound) nbt).e(path);
+ }
+
+ @Override
+ public void removeKey(Object nbt, String path) {
+ ((NBTTagCompound) nbt).r(path);
+ }
+
+ @Override
+ public Object setByte(Object nbt, String path, byte value) {
+ ((NBTTagCompound) nbt).a(path, value);
+ return nbt;
+ }
+
+ @Override
+ public byte getByte(Object nbt, String path) {
+ return ((NBTTagCompound) nbt).f(path);
+ }
+
+ @Override
+ public Object getDataWatcher(Entity entity) {
+ return ((CraftEntity) entity).getHandle().ar();
+ }
+
+ @Override
+ public Object getDataWatcher(Object entity) {
+ return ((net.minecraft.world.entity.Entity) entity).ar();
+ }
+
+ @Override
+ public int incrementStateId(Object container) {
+ return ((Container) container).k();
+ }
+
+ @Override
+ public Object packetEntityHeadRotation(Entity entity) {
+ return new PacketPlayOutEntityHeadRotation((net.minecraft.world.entity.Entity) getEntity(entity), (byte) (entity.getLocation().getYaw() * 256F / 360F));
+ }
+
+ @Override
+ public Object packetHeldItemSlot(int slot) {
+ return new PacketPlayOutHeldItemSlot(slot);
+ }
+
+ @Override
+ public Object packetExp(float exp, int total, int toNextLevel) {
+ return new PacketPlayOutExperience(exp, total, toNextLevel);
+ }
+
+ @Override
+ public Object packetPlayerInfo(PlayerInfoType type, Player player) {
+ a action = null;
+ switch (type) {
+ case ADD_PLAYER:
+ action = a.a;
+ break;
+ case REMOVE_PLAYER:
+ return new ClientboundPlayerInfoRemovePacket(Arrays.asList(player.getUniqueId()));
+ case UPDATE_DISPLAY_NAME:
+ action = a.f;
+ break;
+ case UPDATE_GAME_MODE:
+ action = a.c;
+ break;
+ case UPDATE_LATENCY:
+ action = a.e;
+ break;
+ }
+ return new ClientboundPlayerInfoUpdatePacket(action, (EntityPlayer) getPlayer(player));
+ }
+
+ static Field setField, listField;
+ static Constructor> clientboundConstructor;
+
+ static {
+ setField = Ref.field(ClientboundPlayerInfoUpdatePacket.class, "b");
+ listField = Ref.field(ClientboundPlayerInfoUpdatePacket.class, "c");
+ }
+
+ @Override
+ public Object packetPlayerInfo(PlayerInfoType type, GameProfileHandler gameProfile, int latency, GameMode gameMode, Component playerName) {
+ a action = null;
+ switch (type) {
+ case ADD_PLAYER:
+ action = a.a;
+ break;
+ case REMOVE_PLAYER:
+ return new ClientboundPlayerInfoRemovePacket(Arrays.asList(gameProfile.getUUID()));
+ case UPDATE_DISPLAY_NAME:
+ action = a.f;
+ break;
+ case UPDATE_GAME_MODE:
+ action = a.c;
+ break;
+ case UPDATE_LATENCY:
+ action = a.e;
+ break;
+ }
+ EnumSet set = EnumSet.of(action);
+ List list = Arrays.asList(new ClientboundPlayerInfoUpdatePacket.b(gameProfile.getUUID(), (GameProfile) toGameProfile(gameProfile), true, latency,
+ gameMode == null ? EnumGamemode.a : EnumGamemode.a(gameMode.name().toLowerCase()),
+ (IChatBaseComponent) (playerName == null ? toIChatBaseComponent(new Component(gameProfile.getUsername())) : toIChatBaseComponent(playerName)), null));
+ ClientboundPlayerInfoUpdatePacket packet = (ClientboundPlayerInfoUpdatePacket) Ref.newUnsafeInstance(ClientboundPlayerInfoUpdatePacket.class);
+ Ref.set(packet, setField, set);
+ Ref.set(packet, listField, list);
+ return packet;
+ }
+
+ @Override
+ public Object packetPosition(double x, double y, double z, float yaw, float pitch) {
+ return new PacketPlayOutPosition(x, y, z, yaw, pitch, Collections.emptySet(), 0);
+ }
+
+ @Override
+ public Object packetRespawn(Player player) {
+ EntityPlayer entityPlayer = (EntityPlayer) getPlayer(player);
+
+ return new PacketPlayOutRespawn(entityPlayer.b(entityPlayer.A()), (byte) 1);
+ }
+
+ @Override
+ public String getProviderName() {
+ return "1_21_R1 (1.21)";
+ }
+
+ @Override
+ public int getContainerStateId(Object container) {
+ return ((Container) container).j();
+ }
+
+ @Override
+ public void loadParticles() {
+ for (Entry>, Particle>> s : BuiltInRegistries.i.h())
+ me.devtec.theapi.bukkit.game.particles.Particle.identifier.put(s.getKey().a().a(), 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 ((EntityPlayer) nmsPlayer).fX();
+ }
+
+}
diff --git a/NmsProvider - 1.21.R1/v1_21_R1.jar b/NmsProvider - 1.21.R1/v1_21_R1.jar
new file mode 100644
index 00000000..d6160362
Binary files /dev/null and b/NmsProvider - 1.21.R1/v1_21_R1.jar differ
diff --git a/NmsProvider - 1.21/.classpath b/NmsProvider - 1.21/.classpath
new file mode 100644
index 00000000..6693843a
--- /dev/null
+++ b/NmsProvider - 1.21/.classpath
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NmsProvider - 1.21/src/me/devtec/theapi/bukkit/nms/v1_21.java b/NmsProvider - 1.21/src/me/devtec/theapi/bukkit/nms/v1_21.java
new file mode 100644
index 00000000..983dcf8b
--- /dev/null
+++ b/NmsProvider - 1.21/src/me/devtec/theapi/bukkit/nms/v1_21.java
@@ -0,0 +1,1746 @@
+package me.devtec.theapi.bukkit.nms;
+
+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.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import java.util.UUID;
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
+
+import javax.imageio.ImageIO;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Chunk;
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.World;
+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 com.google.common.base.Preconditions;
+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.ClickEvent;
+import me.devtec.shared.components.Component;
+import me.devtec.shared.components.ComponentAPI;
+import me.devtec.shared.components.ComponentEntity;
+import me.devtec.shared.components.ComponentItem;
+import me.devtec.shared.components.HoverEvent;
+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.PropertyHandler;
+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.ClientboundAddEntityPacket;
+import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
+import net.minecraft.network.protocol.game.ClientboundClearTitlesPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerClosePacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
+import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
+import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
+import net.minecraft.network.protocol.game.ClientboundRespawnPacket;
+import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket;
+import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket;
+import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket;
+import net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket;
+import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
+import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket;
+import net.minecraft.network.protocol.game.ClientboundSetObjectivePacket;
+import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket;
+import net.minecraft.network.protocol.game.ClientboundSetScorePacket;
+import net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket;
+import net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket;
+import net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket;
+import net.minecraft.network.protocol.game.ClientboundSystemChatPacket;
+import net.minecraft.network.protocol.game.ClientboundTabListPacket;
+import net.minecraft.network.protocol.game.ServerboundContainerClickPacket;
+import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
+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.AbstractContainerMenu;
+import net.minecraft.world.inventory.AnvilMenu;
+import net.minecraft.world.inventory.ClickAction;
+import net.minecraft.world.inventory.ContainerLevelAccess;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.inventory.Slot;
+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;
+
+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 extends Player> 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 ? null : 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);
+ }
+
+ @Override
+ public Object packetNamedEntitySpawn(Object player) {
+ return new ClientboundAddEntityPacket((net.minecraft.world.entity.player.Player) player);
+ }
+
+ @Override
+ public Object packetSpawnEntityLiving(Object entityLiving) {
+ return new ClientboundAddEntityPacket((net.minecraft.world.entity.LivingEntity) entityLiving);
+ }
+
+ @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(new ResourceLocation(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()));
+ Preconditions.checkState(var1.getWidth() == 64, "Must be 64 pixels wide");
+ Preconditions.checkState(var1.getHeight() == 64, "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.20.6";
+ }
+
+ @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/NmsProvider - 1.21/v1_21.jar b/NmsProvider - 1.21/v1_21.jar
new file mode 100644
index 00000000..9fcefca5
Binary files /dev/null and b/NmsProvider - 1.21/v1_21.jar differ