output = new NbtList<>(NbtType.getById(list.getElementType()));
+ for (Tag base : list) {
+ output.add(fromMinecraftTag(base));
+ }
+ return output;
+ }
+
+ @Override
+ public CompoundTag toMinecraftCompound(NbtCompound compound) {
+ NbtCompound compoundTag = compound;
+ CompoundTag targetCompound = new CompoundTag();
+ for (String key : compoundTag.getKeys()) {
+ targetCompound.put(key, toMinecraftTag(compoundTag.get(key)));
+ }
+ return targetCompound;
+ }
+
+ @Override
+ public NbtCompound fromMinecraftCompound(Object raw) {
+ if (!(raw instanceof CompoundTag)) {
+ return null;
+ }
+ CompoundTag compoundTag = (CompoundTag) raw;
+ NbtCompound targetCompound = new NbtCompound();
+ for (String key : compoundTag.getAllKeys()) {
+ targetCompound.set(key, fromMinecraftTag(compoundTag.get(key)));
+ }
+ return targetCompound;
+ }
+
+ @Override
+ public org.bukkit.inventory.ItemStack itemFromCompound(NbtCompound compound) {
+ return CraftItemStack.asBukkitCopy(ItemStack.of(toMinecraftCompound(compound)));
+ }
+
+ @Override
+ public NbtCompound itemToCompound(org.bukkit.inventory.ItemStack itemStack) {
+ return fromMinecraftCompound(CraftItemStack.asNMSCopy(itemStack).save(new CompoundTag()));
+ }
+
+ @Override
+ public WrappedContext createContext(IDataAdapterContext context) {
+ return new BukkitContext1_18_R2(context);
+ }
+
+ @Override
+ public WrapType
wrap(IDataType
dataType) {
+ return new BukkitType1_18_R2<>(dataType);
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/EntityProvider1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/EntityProvider1_18_R2.java
new file mode 100644
index 0000000..deca66f
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/EntityProvider1_18_R2.java
@@ -0,0 +1,47 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2;
+
+import java.util.EnumMap;
+import java.util.function.Function;
+
+import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
+
+import net.minecraft.world.level.Level;
+import net.sourcewriters.minecraft.vcompat.provider.EntityProvider;
+import net.sourcewriters.minecraft.vcompat.provider.entity.NmsEntity;
+import net.sourcewriters.minecraft.vcompat.provider.entity.NmsEntityType;
+import net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.utils.EntityConstructors1_18_R2;
+
+public class EntityProvider1_18_R2 extends EntityProvider {
+
+ private final EnumMap> entityMap = new EnumMap<>(NmsEntityType.class);
+
+ protected EntityProvider1_18_R2(VersionControl1_18_R2 versionControl) {
+ super(versionControl);
+ }
+
+ @SuppressWarnings("unchecked")
+ private final Function searchConstructor(NmsEntityType type) {
+ try {
+ return (Function) EntityConstructors1_18_R2.class.getField(type.name()).get(null);
+ } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException ignore) {
+ return null;
+ }
+ }
+
+ private final Function getConstructor(NmsEntityType type) {
+ return entityMap.computeIfAbsent(type, (key -> searchConstructor(key)));
+ }
+
+ @Override
+ public NmsEntity createEntity(org.bukkit.World world, NmsEntityType type) {
+ if (!(world instanceof CraftWorld)) {
+ return null;
+ }
+ Function function;
+ if ((function = getConstructor(type)) == null) {
+ return null;
+ }
+ return function.apply(((CraftWorld) world).getHandle());
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/PlayerProvider1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/PlayerProvider1_18_R2.java
new file mode 100644
index 0000000..89807a5
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/PlayerProvider1_18_R2.java
@@ -0,0 +1,20 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2;
+
+import org.bukkit.entity.Player;
+
+import net.sourcewriters.minecraft.vcompat.provider.PlayerProvider;
+import net.sourcewriters.minecraft.vcompat.provider.entity.NmsPlayer;
+import net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.entity.Player1_18_R2;
+
+public class PlayerProvider1_18_R2 extends PlayerProvider {
+
+ protected PlayerProvider1_18_R2(VersionControl1_18_R2 versionControl) {
+ super(versionControl);
+ }
+
+ @Override
+ protected NmsPlayer createPlayer(Player player) {
+ return new Player1_18_R2(player);
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/TextureProvider1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/TextureProvider1_18_R2.java
new file mode 100644
index 0000000..615c2fc
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/TextureProvider1_18_R2.java
@@ -0,0 +1,111 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2;
+
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockState;
+import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlockEntityState;
+import org.bukkit.craftbukkit.v1_18_R2.block.CraftSkull;
+import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.inventory.meta.SkullMeta;
+
+import com.mojang.authlib.GameProfile;
+
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.NbtUtils;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.level.block.entity.SkullBlockEntity;
+import net.sourcewriters.minecraft.vcompat.provider.TextureProvider;
+import net.sourcewriters.minecraft.vcompat.provider.lookup.ClassLookupProvider;
+import net.sourcewriters.minecraft.vcompat.provider.lookup.handle.ClassLookup;
+
+public class TextureProvider1_18_R2 extends TextureProvider {
+
+ private final ClassLookup craftEntityStateRef;
+ private final ClassLookup craftItemStackRef;
+ private final ClassLookup craftMetaSkullRef;
+
+ protected TextureProvider1_18_R2(VersionControl1_18_R2 versionControl) {
+ super(versionControl);
+ ClassLookupProvider provider = versionControl.getLookupProvider();
+ craftEntityStateRef = provider.createLookup("CraftBlockEntityState", CraftBlockEntityState.class).searchField("tileEntity",
+ "tileEntity");
+ craftItemStackRef = provider.createLookup("CraftItemStack", CraftItemStack.class).searchField("handle", "handle");
+ craftMetaSkullRef = provider.createCBLookup("CraftMetaSkull", "inventory.CraftMetaSkull")
+ .searchField("serialized", "serializedProfile").searchField("profile", "profile");
+
+ }
+
+ @Override
+ public GameProfile profileFromBlock(Block block) {
+ BlockState state = block.getState();
+ if (!(state instanceof CraftSkull)) {
+ return null;
+ }
+ SkullBlockEntity entitySkull = (SkullBlockEntity) craftEntityStateRef.getFieldValue(state, "tileEntity");
+ return entitySkull.owner;
+ }
+
+ @Override
+ public GameProfile profileFromItem(org.bukkit.inventory.ItemStack itemStack) {
+ if (!(itemStack.getItemMeta() instanceof SkullMeta)) {
+ return null;
+ }
+ SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
+ GameProfile profile = (GameProfile) craftMetaSkullRef.getFieldValue(meta, "profile");
+ if (profile == null) {
+ CompoundTag compound = (CompoundTag) craftMetaSkullRef.getFieldValue(meta, "serialized");
+ if (compound == null) {
+ ItemStack stack = null;
+ if (itemStack instanceof CraftItemStack) {
+ stack = (ItemStack) craftItemStackRef.getFieldValue(itemStack, "handle");
+ }
+ if (stack == null) {
+ stack = CraftItemStack.asNMSCopy(itemStack);
+ }
+ CompoundTag stackTag = stack.getOrCreateTag();
+ if (stackTag.contains("SkullOwner", 10)) {
+ compound = stackTag.getCompound("SkullOwner");
+ } else if (stackTag.contains("SkullProfile", 10)) {
+ compound = stackTag.getCompound("SkullProfile");
+ }
+ }
+ if (compound == null) {
+ return null;
+ }
+ profile = NbtUtils.readGameProfile(compound);
+ }
+ return profile;
+ }
+
+ @Override
+ public org.bukkit.inventory.ItemStack getItem(GameProfile profile) {
+ org.bukkit.inventory.ItemStack craftStack = CraftItemStack.asCraftCopy(new org.bukkit.inventory.ItemStack(Material.PLAYER_HEAD));
+ applyItem(craftStack, profile);
+ return craftStack;
+ }
+
+ @Override
+ public boolean applyItem(org.bukkit.inventory.ItemStack itemStack, GameProfile profile) {
+ ItemMeta meta = itemStack.getItemMeta();
+ if (!(meta instanceof SkullMeta)) {
+ return false;
+ }
+ SkullMeta skullMeta = (SkullMeta) meta;
+ craftMetaSkullRef.setFieldValue(meta, "profile", profile);
+ itemStack.setItemMeta(skullMeta);
+ return true;
+ }
+
+ @Override
+ public boolean applyBlock(Block block, GameProfile profile) {
+ BlockState state = block.getState();
+ if (!(state instanceof CraftSkull)) {
+ return false;
+ }
+ SkullBlockEntity entitySkull = (SkullBlockEntity) craftEntityStateRef.getFieldValue(state, "tileEntity");
+ entitySkull.setOwner(profile);
+ return true;
+ }
+
+}
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/ToolProvider1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/ToolProvider1_18_R2.java
new file mode 100644
index 0000000..f3a471e
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/ToolProvider1_18_R2.java
@@ -0,0 +1,33 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2;
+
+import net.sourcewriters.minecraft.vcompat.provider.ToolProvider;
+import net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.tools.BlockTools1_18_R2;
+import net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.tools.ServerTools1_18_R2;
+import net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.tools.SkinTools1_18_R2;
+
+public class ToolProvider1_18_R2 extends ToolProvider {
+
+ private final BlockTools1_18_R2 blockTools = new BlockTools1_18_R2();
+ private final SkinTools1_18_R2 skinTools = new SkinTools1_18_R2();
+ private final ServerTools1_18_R2 serverTools = new ServerTools1_18_R2();
+
+ protected ToolProvider1_18_R2(VersionControl1_18_R2 versionControl) {
+ super(versionControl);
+ }
+
+ @Override
+ public SkinTools1_18_R2 getSkinTools() {
+ return skinTools;
+ }
+
+ @Override
+ public ServerTools1_18_R2 getServerTools() {
+ return serverTools;
+ }
+
+ @Override
+ public BlockTools1_18_R2 getBlockTools() {
+ return blockTools;
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/VersionControl1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/VersionControl1_18_R2.java
new file mode 100644
index 0000000..eb4a231
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/VersionControl1_18_R2.java
@@ -0,0 +1,55 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2;
+
+import net.sourcewriters.minecraft.vcompat.provider.VersionControl;
+import net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data.hook.BukkitContainerAdapterHook1_18_R2;
+
+public class VersionControl1_18_R2 extends VersionControl {
+
+ public static VersionControl1_18_R2 INSTANCE;
+
+ public static VersionControl1_18_R2 init() {
+ return INSTANCE != null ? INSTANCE : (INSTANCE = new VersionControl1_18_R2());
+ }
+
+ private final ToolProvider1_18_R2 toolProvider = new ToolProvider1_18_R2(this);
+ private final TextureProvider1_18_R2 textureProvider = new TextureProvider1_18_R2(this);
+ private final EntityProvider1_18_R2 entityProvider = new EntityProvider1_18_R2(this);
+ private final PlayerProvider1_18_R2 playerProvider = new PlayerProvider1_18_R2(this);
+ private final BukkitConversion1_18_R2 bukkitConversion = new BukkitConversion1_18_R2(this);
+
+ private VersionControl1_18_R2() {
+ BukkitContainerAdapterHook1_18_R2.hookEntity();
+ }
+
+ @Override
+ public ToolProvider1_18_R2 getToolProvider() {
+ return toolProvider;
+ }
+
+ @Override
+ public EntityProvider1_18_R2 getEntityProvider() {
+ return entityProvider;
+ }
+
+ @Override
+ public PlayerProvider1_18_R2 getPlayerProvider() {
+ return playerProvider;
+ }
+
+ @Override
+ public TextureProvider1_18_R2 getTextureProvider() {
+ return textureProvider;
+ }
+
+ @Override
+ public BukkitConversion1_18_R2 getBukkitConversion() {
+ return bukkitConversion;
+ }
+
+ @Override
+ public void shutdown() {
+ dataProvider.getDefaultDistributor().shutdown();
+ BukkitContainerAdapterHook1_18_R2.unhookAll();
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/BukkitContainer1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/BukkitContainer1_18_R2.java
new file mode 100644
index 0000000..7858cab
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/BukkitContainer1_18_R2.java
@@ -0,0 +1,160 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data;
+
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.bukkit.NamespacedKey;
+import org.bukkit.persistence.PersistentDataAdapterContext;
+import org.bukkit.persistence.PersistentDataContainer;
+import org.bukkit.persistence.PersistentDataType;
+
+import net.sourcewriters.minecraft.vcompat.data.api.IDataContainer;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrapType;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrappedContainer;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrappedKey;
+import net.sourcewriters.minecraft.vcompat.provider.data.wrap.SyntaxKey;
+
+public final class BukkitContainer1_18_R2 extends WrappedContainer implements PersistentDataContainer {
+
+ private final IDataContainer container;
+
+ public BukkitContainer1_18_R2(IDataContainer container) {
+ this.container = container;
+ }
+
+ @Override
+ public IDataContainer getHandle() {
+ return container;
+ }
+
+ @Override
+ public IDataContainer getAsSyntaxContainer() {
+ return container;
+ }
+
+ /*
+ *
+ */
+
+ @Override
+ public boolean has(NamespacedKey key, PersistentDataType type) {
+ return has(new BukkitKey1_18_R2(key), WrappedType1_18_R2.wrap(type));
+ }
+
+ @Override
+ public Z get(NamespacedKey key, PersistentDataType type) {
+ return get(new BukkitKey1_18_R2(key), WrappedType1_18_R2.wrap(type));
+ }
+
+ @Override
+ public Z getOrDefault(NamespacedKey key, PersistentDataType type, Z value) {
+ return Optional.ofNullable(get(key, type)).orElse(value);
+ }
+
+ @Override
+ public void set(NamespacedKey key, PersistentDataType type, Z value) {
+ set(new BukkitKey1_18_R2(key), value, WrappedType1_18_R2.wrap(type));
+ }
+
+ @Override
+ public void remove(NamespacedKey key) {
+ remove(new BukkitKey1_18_R2(key));
+ }
+
+ @Override
+ public Set getKeys() {
+ return Arrays.stream(container.getKeys()).map(SyntaxKey::new).map(BukkitKey1_18_R2::asBukkit).collect(Collectors.toSet());
+ }
+
+ @Override
+ public PersistentDataAdapterContext getAdapterContext() {
+ return getWrapContext();
+ }
+
+ /*
+ *
+ */
+
+ @Override
+ public BukkitContext1_18_R2 getWrapContext() {
+ return new BukkitContext1_18_R2(container.getContext());
+ }
+
+ @Override
+ public boolean has(String key) {
+ return has(wrappedKey(key));
+ }
+
+ @Override
+ public boolean has(WrappedKey> key) {
+ return container.has(key.getNamespacedKey());
+ }
+
+ @Override
+ public boolean has(String key, WrapType
type) {
+ return has(wrappedKey(key), type);
+ }
+
+ @Override
+ public
boolean has(WrappedKey> key, WrapType
type) {
+ return container.has(key.getNamespacedKey(), type.syntaxType());
+ }
+
+ @Override
+ public Object get(String key) {
+ return get(wrappedKey(key));
+ }
+
+ @Override
+ public Object get(WrappedKey> key) {
+ return container.get(key.getNamespacedKey());
+ }
+
+ @Override
+ public
C get(String key, WrapType
type) {
+ return get(wrappedKey(key), type);
+ }
+
+ @Override
+ public
C get(WrappedKey> key, WrapType
type) {
+ return container.get(key.getNamespacedKey(), type.syntaxType());
+ }
+
+ @Override
+ public void set(String key, B value, WrapType, B> type) {
+ set(wrappedKey(key), value, type);
+ }
+
+ @Override
+ public void set(WrappedKey> key, B value, WrapType, B> type) {
+ container.set(key.getNamespacedKey(), value, type.syntaxType());
+ }
+
+ @Override
+ public boolean remove(String key) {
+ return false;
+ }
+
+ @Override
+ public boolean remove(WrappedKey> key) {
+ return container.remove(key.getNamespacedKey());
+ }
+
+ @Override
+ public Set keySet() {
+ return container.getKeyspaces();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return container.isEmpty();
+ }
+
+ @Override
+ public int size() {
+ return container.size();
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/BukkitContext1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/BukkitContext1_18_R2.java
new file mode 100644
index 0000000..587c25d
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/BukkitContext1_18_R2.java
@@ -0,0 +1,38 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data;
+
+import org.bukkit.persistence.PersistentDataAdapterContext;
+import org.bukkit.persistence.PersistentDataContainer;
+
+import net.sourcewriters.minecraft.vcompat.data.api.IDataAdapterContext;
+import net.sourcewriters.minecraft.vcompat.data.api.IDataContainer;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrappedContext;
+
+public final class BukkitContext1_18_R2 extends WrappedContext implements PersistentDataAdapterContext {
+
+ private final IDataAdapterContext context;
+
+ public BukkitContext1_18_R2(IDataAdapterContext context) {
+ this.context = context;
+ }
+
+ @Override
+ public IDataAdapterContext getHandle() {
+ return context;
+ }
+
+ @Override
+ public PersistentDataContainer newPersistentDataContainer() {
+ return newWrapContainer();
+ }
+
+ @Override
+ public IDataContainer newContainer() {
+ return context.newContainer();
+ }
+
+ @Override
+ public BukkitContainer1_18_R2 newWrapContainer() {
+ return new BukkitContainer1_18_R2(context.newContainer());
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/BukkitKey1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/BukkitKey1_18_R2.java
new file mode 100644
index 0000000..17b7445
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/BukkitKey1_18_R2.java
@@ -0,0 +1,52 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data;
+
+import org.bukkit.NamespacedKey;
+import org.bukkit.plugin.Plugin;
+
+import net.sourcewriters.minecraft.vcompat.provider.data.WrappedKey;
+
+public final class BukkitKey1_18_R2 extends WrappedKey {
+
+ private final NamespacedKey key;
+
+ public BukkitKey1_18_R2(Plugin plugin, String key) {
+ this.key = new NamespacedKey(plugin, key);
+ }
+
+ @SuppressWarnings("deprecation")
+ public BukkitKey1_18_R2(String name, String key) {
+ this.key = new NamespacedKey(name, key);
+ }
+
+ public BukkitKey1_18_R2(NamespacedKey key) {
+ this.key = key;
+ }
+
+ @Override
+ public NamespacedKey getHandle() {
+ return key;
+ }
+
+ @Override
+ public String getName() {
+ return key.getNamespace();
+ }
+
+ @Override
+ public String getKey() {
+ return key.getKey();
+ }
+
+ @Override
+ public String toString() {
+ return key.toString();
+ }
+
+ public static NamespacedKey asBukkit(WrappedKey> key) {
+ if (key.getHandle() instanceof NamespacedKey) {
+ return (NamespacedKey) key.getHandle();
+ }
+ return new BukkitKey1_18_R2(key.getName(), key.getKey()).getHandle();
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/BukkitType1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/BukkitType1_18_R2.java
new file mode 100644
index 0000000..668faf3
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/BukkitType1_18_R2.java
@@ -0,0 +1,68 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data;
+
+import org.bukkit.persistence.PersistentDataAdapterContext;
+import org.bukkit.persistence.PersistentDataType;
+
+import net.sourcewriters.minecraft.vcompat.data.api.IDataType;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrappedContext;
+
+public class BukkitType1_18_R2 extends WrappedType1_18_R2, P0, P1, C0, C1>
+ implements PersistentDataType {
+
+ private final IDataType type;
+
+ public BukkitType1_18_R2(IDataType type) {
+ super(type.getPrimitive(), type.getComplex());
+ this.type = type;
+ }
+
+ @Override
+ public IDataType getHandle() {
+ return type;
+ }
+
+ @Override
+ public Class getPrimitiveOriginal() {
+ return type.getPrimitive();
+ }
+
+ @Override
+ public Class getComplexOriginal() {
+ return type.getComplex();
+ }
+
+ /*
+ *
+ */
+
+ @Override
+ public Class getComplexType() {
+ return complexType;
+ }
+
+ @Override
+ public Class getPrimitiveType() {
+ return primitiveType;
+ }
+
+ @Override
+ public P0 toPrimitive(C0 complex, PersistentDataAdapterContext context) {
+ return wrapToPrimitive(complex, new SyntaxContext1_18_R2(context));
+ }
+
+ @Override
+ public C0 fromPrimitive(P0 primitive, PersistentDataAdapterContext context) {
+ return wrapToComplex(primitive, new SyntaxContext1_18_R2(context));
+ }
+
+ @Override
+ public P0 wrapToPrimitive(C0 complex, WrappedContext> context) {
+ return toPrimitiveWrapped(type.toPrimitive(context, toComplexOriginal(complex)));
+ }
+
+ @Override
+ public C0 wrapToComplex(P0 primitive, WrappedContext> context) {
+ return toComplexWrapped(type.fromPrimitive(context, toPrimitiveOriginal(primitive)));
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/SimpleBukkitType1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/SimpleBukkitType1_18_R2.java
new file mode 100644
index 0000000..3be22b9
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/SimpleBukkitType1_18_R2.java
@@ -0,0 +1,36 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data;
+
+import org.bukkit.persistence.PersistentDataAdapterContext;
+import org.bukkit.persistence.PersistentDataType;
+
+import net.sourcewriters.minecraft.vcompat.provider.data.WrapType;
+
+public class SimpleBukkitType1_18_R2 implements PersistentDataType
{
+
+ private final WrapType
type;
+
+ public SimpleBukkitType1_18_R2(WrapType
type) {
+ this.type = type;
+ }
+
+ @Override
+ public Class getComplexType() {
+ return type.getComplexWrapped();
+ }
+
+ @Override
+ public Class getPrimitiveType() {
+ return type.getPrimitiveWrapped();
+ }
+
+ @Override
+ public P toPrimitive(C complex, PersistentDataAdapterContext context) {
+ return type.wrapToPrimitive(complex, new SyntaxContext1_18_R2(context));
+ }
+
+ @Override
+ public C fromPrimitive(P primitive, PersistentDataAdapterContext context) {
+ return type.wrapToComplex(primitive, new SyntaxContext1_18_R2(context));
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/SyntaxContainer1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/SyntaxContainer1_18_R2.java
new file mode 100644
index 0000000..1a62af3
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/SyntaxContainer1_18_R2.java
@@ -0,0 +1,191 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.bukkit.persistence.PersistentDataContainer;
+
+import net.sourcewriters.minecraft.vcompat.VersionCompatProvider;
+import net.sourcewriters.minecraft.vcompat.data.api.IDataAdapterContext;
+import net.sourcewriters.minecraft.vcompat.data.api.IDataAdapterRegistry;
+import net.sourcewriters.minecraft.vcompat.data.api.IDataContainer;
+import net.sourcewriters.minecraft.vcompat.data.api.IDataType;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrapType;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrappedContainer;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrappedKey;
+import net.sourcewriters.minecraft.vcompat.provider.data.wrap.SyntaxKey;
+import net.sourcewriters.minecraft.vcompat.shaded.syntaxapi.utils.key.IKey;
+
+public final class SyntaxContainer1_18_R2 extends WrappedContainer implements IDataContainer {
+
+ private final PersistentDataContainer container;
+
+ public SyntaxContainer1_18_R2(PersistentDataContainer container) {
+ this.container = container;
+ }
+
+ @Override
+ public PersistentDataContainer getHandle() {
+ return container;
+ }
+
+ @Override
+ public IDataContainer getAsSyntaxContainer() {
+ return new SyntaxContainer1_18_R2(container);
+ }
+
+ @Override
+ public IDataAdapterRegistry> getRegistry() {
+ return VersionCompatProvider.get().getControl().getDataProvider().getRegistry();
+ }
+
+ /*
+ *
+ */
+
+ @Override
+ public boolean has(IKey key) {
+ throw new UnsupportedOperationException("Can't be used with PersistentDataContainer of Bukkit");
+ }
+
+ @Override
+ public boolean has(String key, IDataType, ?> type) {
+ return has(syntaxKey(key), type);
+ }
+
+ @Override
+ public boolean has(IKey key, IDataType, ?> type) {
+ return has(new SyntaxKey(key), WrappedType1_18_R2.wrap(type));
+ }
+
+ @Override
+ public C get(String key, IDataType, C> type) {
+ return get(syntaxKey(key), type);
+ }
+
+ @Override
+ public C get(IKey key, IDataType, C> type) {
+ return get(new SyntaxKey(key), WrappedType1_18_R2.wrap(type));
+ }
+
+ @Override
+ public Object get(String key) {
+ throw new UnsupportedOperationException("Can't be used with PersistentDataContainer of Bukkit");
+ }
+
+ @Override
+ public Object get(IKey key) {
+ throw new UnsupportedOperationException("Can't be used with PersistentDataContainer of Bukkit");
+ }
+
+ @Override
+ public void set(String key, E value, IDataType type) {
+ set(wrappedKey(key), value, WrappedType1_18_R2.wrap(type));
+ }
+
+ @Override
+ public void set(IKey key, E value, IDataType type) {
+ set(new SyntaxKey(key), value, WrappedType1_18_R2.wrap(type));
+ }
+
+ @Override
+ public boolean remove(String key) {
+ return remove(wrappedKey(key));
+ }
+
+ @Override
+ public boolean remove(IKey key) {
+ return remove(new SyntaxKey(key));
+ }
+
+ @Override
+ public IKey[] getKeys() {
+ return container.getKeys().stream().map(BukkitKey1_18_R2::new).map(WrappedKey::getNamespacedKey).toArray(IKey[]::new);
+ }
+
+ @Override
+ public Set getKeyspaces() {
+ return container.getKeys().stream().map(org.bukkit.NamespacedKey::toString).collect(Collectors.toSet());
+ }
+
+ @Override
+ public IDataAdapterContext getContext() {
+ return getWrapContext();
+ }
+
+ /*
+ *
+ */
+
+ @Override
+ public SyntaxContext1_18_R2 getWrapContext() {
+ return new SyntaxContext1_18_R2(container.getAdapterContext());
+ }
+
+ @Override
+ public boolean has(String key) {
+ throw new UnsupportedOperationException("Can't be used with PersistentDataContainer of Bukkit");
+ }
+
+ @Override
+ public boolean has(WrappedKey> key) {
+ throw new UnsupportedOperationException("Can't be used with PersistentDataContainer of Bukkit");
+ }
+
+ @Override
+ public boolean has(String key, WrapType
type) {
+ return has(wrappedKey(key), type);
+ }
+
+ @Override
+ public
boolean has(WrappedKey> key, WrapType
type) {
+ return container.has(BukkitKey1_18_R2.asBukkit(key), new SimpleBukkitType1_18_R2<>(type));
+ }
+
+ @Override
+ public Object get(WrappedKey> key) {
+ throw new UnsupportedOperationException("Can't be used with PersistentDataContainer of Bukkit");
+ }
+
+ @Override
+ public
C get(String key, WrapType
type) {
+ return get(wrappedKey(key), type);
+ }
+
+ @Override
+ public
C get(WrappedKey> key, WrapType
type) {
+ return container.get(BukkitKey1_18_R2.asBukkit(key), new SimpleBukkitType1_18_R2<>(type));
+ }
+
+ @Override
+ public void set(String key, B value, WrapType, B> type) {
+ set(wrappedKey(key), value, type);
+ }
+
+ @Override
+ public void set(WrappedKey> key, B value, WrapType, B> type) {
+ container.set(BukkitKey1_18_R2.asBukkit(key), new SimpleBukkitType1_18_R2<>(type), value);
+ }
+
+ @Override
+ public boolean remove(WrappedKey> key) {
+ container.remove(BukkitKey1_18_R2.asBukkit(key));
+ return true; // Will always return true as we don't know if it contained it
+ }
+
+ @Override
+ public Set keySet() {
+ return getKeyspaces();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return container.isEmpty();
+ }
+
+ @Override
+ public int size() {
+ return container.getKeys().size();
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/SyntaxContext1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/SyntaxContext1_18_R2.java
new file mode 100644
index 0000000..745479b
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/SyntaxContext1_18_R2.java
@@ -0,0 +1,37 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data;
+
+import org.bukkit.persistence.PersistentDataAdapterContext;
+import org.bukkit.persistence.PersistentDataContainer;
+
+import net.sourcewriters.minecraft.vcompat.data.api.IDataContainer;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrappedContext;
+
+public final class SyntaxContext1_18_R2 extends WrappedContext implements PersistentDataAdapterContext {
+
+ private final PersistentDataAdapterContext context;
+
+ public SyntaxContext1_18_R2(PersistentDataAdapterContext context) {
+ this.context = context;
+ }
+
+ @Override
+ public PersistentDataAdapterContext getHandle() {
+ return context;
+ }
+
+ @Override
+ public PersistentDataContainer newPersistentDataContainer() {
+ return context.newPersistentDataContainer();
+ }
+
+ @Override
+ public IDataContainer newContainer() {
+ return newWrapContainer();
+ }
+
+ @Override
+ public SyntaxContainer1_18_R2 newWrapContainer() {
+ return new SyntaxContainer1_18_R2(context.newPersistentDataContainer());
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/SyntaxType1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/SyntaxType1_18_R2.java
new file mode 100644
index 0000000..aa4db9e
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/SyntaxType1_18_R2.java
@@ -0,0 +1,75 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data;
+
+import org.bukkit.persistence.PersistentDataAdapterContext;
+import org.bukkit.persistence.PersistentDataType;
+
+import net.sourcewriters.minecraft.vcompat.data.api.IDataAdapterContext;
+import net.sourcewriters.minecraft.vcompat.data.api.IDataType;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrappedContext;
+
+public class SyntaxType1_18_R2 extends WrappedType1_18_R2, P0, P1, C0, C1>
+ implements IDataType {
+
+ private final PersistentDataType type;
+
+ public SyntaxType1_18_R2(PersistentDataType type) {
+ super(type.getPrimitiveType(), type.getComplexType());
+ this.type = type;
+ }
+
+ @Override
+ public PersistentDataType getHandle() {
+ return type;
+ }
+
+ @Override
+ public Class getPrimitiveOriginal() {
+ return type.getPrimitiveType();
+ }
+
+ @Override
+ public Class getComplexOriginal() {
+ return type.getComplexType();
+ }
+
+ /*
+ *
+ */
+
+ @Override
+ public Class getComplex() {
+ return complexType;
+ }
+
+ @Override
+ public Class getPrimitive() {
+ return primitiveType;
+ }
+
+ @Override
+ public P0 toPrimitive(IDataAdapterContext context, C0 complex) {
+ return wrapToPrimitive(complex, new BukkitContext1_18_R2(context));
+ }
+
+ @Override
+ public C0 fromPrimitive(IDataAdapterContext context, P0 primitive) {
+ return wrapToComplex(primitive, new BukkitContext1_18_R2(context));
+ }
+
+ @Override
+ public P0 wrapToPrimitive(C0 complex, WrappedContext> context) {
+ if (!(context instanceof PersistentDataAdapterContext)) {
+ return null;
+ }
+ return toPrimitiveWrapped(type.toPrimitive(toComplexOriginal(complex), (PersistentDataAdapterContext) context));
+ }
+
+ @Override
+ public C0 wrapToComplex(P0 primitive, WrappedContext> context) {
+ if (!(context instanceof PersistentDataAdapterContext)) {
+ return null;
+ }
+ return toComplexWrapped(type.fromPrimitive(toPrimitiveOriginal(primitive), (PersistentDataAdapterContext) context));
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/WrappedType1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/WrappedType1_18_R2.java
new file mode 100644
index 0000000..3549f45
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/WrappedType1_18_R2.java
@@ -0,0 +1,149 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data;
+
+import java.util.Arrays;
+
+import org.bukkit.persistence.PersistentDataContainer;
+import org.bukkit.persistence.PersistentDataType;
+
+import net.sourcewriters.minecraft.vcompat.data.api.IDataContainer;
+import net.sourcewriters.minecraft.vcompat.data.api.IDataType;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrapType;
+
+public abstract class WrappedType1_18_R2 implements WrapType {
+
+ protected final Class primitiveType;
+ protected final Class complexType;
+
+ private final int primitiveWrap;
+ private final int complexWrap;
+
+ @SuppressWarnings("unchecked")
+ protected WrappedType1_18_R2(Class primitive, Class complex) {
+ this.primitiveWrap = WrappedType1_18_R2.internalState(primitive);
+ this.complexWrap = WrappedType1_18_R2.internalState(complex);
+ this.primitiveType = (Class) WrappedType1_18_R2.internalWrap(primitive, primitiveWrap);
+ this.complexType = (Class) WrappedType1_18_R2.internalWrap(complex, complexWrap);
+ }
+
+ public abstract H getHandle();
+
+ public Class getPrimitiveWrapped() {
+ return primitiveType;
+ }
+
+ public Class getComplexWrapped() {
+ return complexType;
+ }
+
+ public abstract Class getPrimitiveOriginal();
+
+ public abstract Class getComplexOriginal();
+
+ @SuppressWarnings("unchecked")
+ public P0 toPrimitiveWrapped(P1 primitive) {
+ switch (primitiveWrap) {
+ case 1:
+ return (P0) new SyntaxContainer1_18_R2((PersistentDataContainer) primitive);
+ case 2:
+ return (P0) Arrays.stream((PersistentDataContainer[]) primitive).map(SyntaxContainer1_18_R2::new)
+ .toArray(SyntaxContainer1_18_R2[]::new);
+ case 3:
+ return (P0) new BukkitContainer1_18_R2((IDataContainer) primitive);
+ case 4:
+ return (P0) Arrays.stream((IDataContainer[]) primitive).map(BukkitContainer1_18_R2::new)
+ .toArray(BukkitContainer1_18_R2[]::new);
+ default:
+ return (P0) primitive;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public C0 toComplexWrapped(C1 complex) {
+ switch (complexWrap) {
+ case 1:
+ return (C0) new SyntaxContainer1_18_R2((PersistentDataContainer) complex);
+ case 2:
+ return (C0) Arrays.stream((PersistentDataContainer[]) complex).map(SyntaxContainer1_18_R2::new).toArray(SyntaxContainer1_18_R2[]::new);
+ case 3:
+ return (C0) new BukkitContainer1_18_R2((IDataContainer) complex);
+ case 4:
+ return (C0) Arrays.stream((IDataContainer[]) complex).map(BukkitContainer1_18_R2::new).toArray(BukkitContainer1_18_R2[]::new);
+ default:
+ return (C0) complex;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public P1 toPrimitiveOriginal(P0 primitive) {
+ switch (primitiveWrap) {
+ case 1:
+ return (P1) new BukkitContainer1_18_R2((IDataContainer) primitive);
+ case 2:
+ return (P1) Arrays.stream((IDataContainer[]) primitive).map(BukkitContainer1_18_R2::new)
+ .toArray(BukkitContainer1_18_R2[]::new);
+ case 3:
+ return (P1) new SyntaxContainer1_18_R2((PersistentDataContainer) primitive);
+ case 4:
+ return (P1) Arrays.stream((PersistentDataContainer[]) primitive).map(SyntaxContainer1_18_R2::new)
+ .toArray(SyntaxContainer1_18_R2[]::new);
+ default:
+ return (P1) primitive;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public C1 toComplexOriginal(C0 complex) {
+ switch (complexWrap) {
+ case 1:
+ return (C1) new BukkitContainer1_18_R2((IDataContainer) complex);
+ case 2:
+ return (C1) Arrays.stream((IDataContainer[]) complex).map(BukkitContainer1_18_R2::new).toArray(BukkitContainer1_18_R2[]::new);
+ case 3:
+ return (C1) new SyntaxContainer1_18_R2((PersistentDataContainer) complex);
+ case 4:
+ return (C1) Arrays.stream((PersistentDataContainer[]) complex).map(SyntaxContainer1_18_R2::new).toArray(SyntaxContainer1_18_R2[]::new);
+ default:
+ return (C1) complex;
+ }
+ }
+
+ protected static Class> internalWrap(Class> clazz, int state) {
+ switch (state) {
+ case 1:
+ return SyntaxContainer1_18_R2.class;
+ case 2:
+ return SyntaxContainer1_18_R2[].class;
+ case 3:
+ return BukkitContainer1_18_R2.class;
+ case 4:
+ return BukkitContainer1_18_R2[].class;
+ default:
+ return clazz;
+ }
+ }
+
+ protected static int internalState(Class> clazz) {
+ if (clazz.isAssignableFrom(PersistentDataContainer.class)) {
+ return 1;
+ }
+ if (clazz.isAssignableFrom(PersistentDataContainer[].class)) {
+ return 2;
+ }
+ if (clazz.isAssignableFrom(IDataContainer.class)) {
+ return 3;
+ }
+ if (clazz.isAssignableFrom(IDataContainer[].class)) {
+ return 4;
+ }
+ return 0;
+ }
+
+ public static BukkitType1_18_R2 wrap(IDataType type) {
+ return new BukkitType1_18_R2<>(type);
+ }
+
+ public static SyntaxType1_18_R2 wrap(PersistentDataType type) {
+ return new SyntaxType1_18_R2<>(type);
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/hook/BukkitContainerAdapterHook1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/hook/BukkitContainerAdapterHook1_18_R2.java
new file mode 100644
index 0000000..b641a89
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/data/hook/BukkitContainerAdapterHook1_18_R2.java
@@ -0,0 +1,137 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data.hook;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+
+import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_18_R2.persistence.CraftPersistentDataContainer;
+import org.bukkit.craftbukkit.v1_18_R2.persistence.CraftPersistentDataTypeRegistry;
+import org.bukkit.persistence.PersistentDataContainer;
+
+import net.minecraft.nbt.CompoundTag;
+import net.sourcewriters.minecraft.vcompat.VersionCompatProvider;
+import net.sourcewriters.minecraft.vcompat.data.api.IDataContainer;
+import net.sourcewriters.minecraft.vcompat.data.nbt.NbtContainer;
+import net.sourcewriters.minecraft.vcompat.provider.VersionControl;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrappedContainer;
+import net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data.BukkitContainer1_18_R2;
+import net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data.SyntaxContainer1_18_R2;
+import net.sourcewriters.minecraft.vcompat.provider.lookup.ClassLookupProvider;
+import net.sourcewriters.minecraft.vcompat.provider.lookup.handle.ClassLookup;
+import net.sourcewriters.minecraft.vcompat.shaded.syntaxapi.nbt.NbtCompound;
+
+@SuppressWarnings({
+ "rawtypes",
+ "unchecked"
+})
+public final class BukkitContainerAdapterHook1_18_R2 {
+
+ private static final BukkitContainerAdapterHook1_18_R2 HOOK = new BukkitContainerAdapterHook1_18_R2();
+
+ private final ClassLookup registryRef;
+ private final ClassLookup entityRef;
+
+ private BukkitContainerAdapterHook1_18_R2() {
+ ClassLookupProvider provider = VersionCompatProvider.get().getLookupProvider();
+ registryRef = provider.createLookup("CraftPersistentDataTypeRegistry", CraftPersistentDataTypeRegistry.class)
+ .searchMethod("create", "createAdapter", Class.class, Class.class, Function.class, Function.class)
+ .searchField("adapters", "adapters").searchField("function", "CREATE_ADAPTER");
+ entityRef = provider.createLookup("CraftEntity", CraftEntity.class).searchField("registry", "DATA_TYPE_REGISTRY");
+ }
+
+ private final HashMap map = new HashMap<>();
+
+ private CraftPersistentDataTypeRegistry getEntityRegistry() {
+ return (CraftPersistentDataTypeRegistry) entityRef.getFieldValue("registry");
+ }
+
+ private void uninjectAll() {
+ for (CraftPersistentDataTypeRegistry registry : map.keySet()) {
+ Map adapters = (Map) registryRef.getFieldValue(registry, "adapters");
+ adapters.remove(BukkitContainer1_18_R2.class);
+ adapters.remove(SyntaxContainer1_18_R2.class);
+ registryRef.setFieldValue(registry, "function", map.get(registry));
+ }
+ map.clear();
+ }
+
+ private void inject(CraftPersistentDataTypeRegistry registry) {
+ if (map.containsKey(registry)) {
+ return;
+ }
+ map.put(registry, (Function) registryRef.getFieldValue(registry, "function"));
+ Function function = clazz -> createAdapter(registry, registryRef.getMethod("create").getReturnType(), (Class) clazz);
+ registryRef.setFieldValue(registry, "function", function);
+ }
+
+ private E createAdapter(CraftPersistentDataTypeRegistry registry, Class adapterType, Class type) {
+ if (Objects.equals(BukkitContainer1_18_R2.class, type)) {
+ return (E) buildAdapter(registry, BukkitContainer1_18_R2.class, tag -> fromPrimitiveSyntax(tag));
+ }
+ if (Objects.equals(SyntaxContainer1_18_R2.class, type)) {
+ return (E) buildAdapter(registry, SyntaxContainer1_18_R2.class, tag -> fromPrimitiveBukkit(registry, tag));
+ }
+ return (E) map.get(registry).apply(type);
+ }
+
+ private Object buildAdapter(Object handle, Class type, Function function) {
+ return registryRef.run(handle, "create", type, CompoundTag.class, (Function) input -> toPrimitive(input), function);
+ }
+
+ private CompoundTag toPrimitive(WrappedContainer input) {
+ Object handle = findFinalContainer(input).getHandle();
+ if (handle instanceof PersistentDataContainer) {
+ if (handle instanceof CraftPersistentDataContainer) {
+ return ((CraftPersistentDataContainer) handle).toTagCompound();
+ }
+ throw new IllegalArgumentException(
+ "Expected 'CraftPersistentDataContainer' got '" + handle.getClass().getSimpleName() + " instead'!");
+ }
+ if (handle instanceof IDataContainer) {
+ if (handle instanceof NbtContainer) {
+ return (CompoundTag) VersionCompatProvider.get().getControl().getBukkitConversion()
+ .toMinecraftCompound(((NbtContainer) handle).asNbt());
+ }
+ throw new IllegalArgumentException(
+ "Expected 'CraftPersistentDataContainer' got '" + handle.getClass().getSimpleName() + " instead'!");
+ }
+ throw new IllegalArgumentException("Unknown WrappedContainer implementation!");
+ }
+
+ private BukkitContainer1_18_R2 fromPrimitiveSyntax(CompoundTag data) {
+ VersionControl control = VersionCompatProvider.get().getControl();
+ NbtContainer container = new NbtContainer(control.getDataProvider().getRegistry());
+ NbtCompound compound = control.getBukkitConversion().fromMinecraftCompound(data);
+ container.fromNbt(compound);
+ return new BukkitContainer1_18_R2(container);
+ }
+
+ private SyntaxContainer1_18_R2 fromPrimitiveBukkit(CraftPersistentDataTypeRegistry registry, CompoundTag data) {
+ CraftPersistentDataContainer container = new CraftPersistentDataContainer(registry);
+ container.putAll(data);
+ return new SyntaxContainer1_18_R2(container);
+ }
+
+ private WrappedContainer findFinalContainer(WrappedContainer container) {
+ WrappedContainer output = container;
+ while (output.getHandle() instanceof WrappedContainer) {
+ output = (WrappedContainer) output.getHandle();
+ }
+ return output;
+ }
+
+ public static void unhookAll() {
+ HOOK.uninjectAll();
+ }
+
+ public static void hookEntity() {
+ HOOK.inject(HOOK.getEntityRegistry());
+ }
+
+ public static void hook(CraftPersistentDataTypeRegistry registry) {
+ HOOK.inject(registry);
+ }
+
+}
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/entity/ArmorStand1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/entity/ArmorStand1_18_R2.java
new file mode 100644
index 0000000..7ffc251
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/entity/ArmorStand1_18_R2.java
@@ -0,0 +1,24 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.entity;
+
+import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.entity.decoration.ArmorStand;
+import net.minecraft.world.level.Level;
+import net.sourcewriters.minecraft.vcompat.provider.entity.NmsArmorStand;
+
+public class ArmorStand1_18_R2 extends EntityLiving1_18_R2 implements NmsArmorStand {
+
+ public ArmorStand1_18_R2(Level world) {
+ super(new ArmorStand(EntityType.ARMOR_STAND, world));
+ }
+
+ @Override
+ public void setSmall(boolean small) {
+ handle.setSmall(small);
+ }
+
+ @Override
+ public boolean isSmall() {
+ return handle.isSmall();
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/entity/Entity1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/entity/Entity1_18_R2.java
new file mode 100644
index 0000000..feed4cb
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/entity/Entity1_18_R2.java
@@ -0,0 +1,215 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.entity;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
+import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_18_R2.util.CraftChatMessage;
+import org.bukkit.entity.Player;
+
+import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
+import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
+import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
+import net.minecraft.server.network.ServerGamePacketListenerImpl;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.phys.AABB;
+import net.minecraft.world.phys.Vec3;
+import net.sourcewriters.minecraft.vcompat.provider.entity.NmsEntity;
+import net.sourcewriters.minecraft.vcompat.provider.utils.NmsBoundingBox;
+
+public abstract class Entity1_18_R2 implements NmsEntity {
+
+ protected final E handle;
+
+ protected final List visible = Collections.synchronizedList(new ArrayList<>());
+
+ public Entity1_18_R2(E handle) {
+ this.handle = handle;
+ }
+
+ @Override
+ public final E getHandle() {
+ return handle;
+ }
+
+ @Override
+ public int getId() {
+ return handle.getId();
+ }
+
+ @Override
+ public UUID getUniqueId() {
+ return handle.getUUID();
+ }
+
+ @Override
+ public NmsBoundingBox getBoundingBox() {
+ AABB box = handle.getBoundingBox();
+ return new NmsBoundingBox(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ);
+ }
+
+ @Override
+ public void setCustomName(String name) {
+ handle.setCustomName(CraftChatMessage.fromStringOrNull(name));
+ updateVisibility();
+ }
+
+ @Override
+ public String getCustomName() {
+ return CraftChatMessage.fromComponent(handle.getCustomName());
+ }
+
+ @Override
+ public void setGravity(boolean gravity) {
+ handle.setNoGravity(!gravity);
+ }
+
+ @Override
+ public boolean hasGravity() {
+ return !handle.isNoGravity();
+ }
+
+ @Override
+ public void setCustomNameVisible(boolean visible) {
+ handle.setCustomNameVisible(visible);
+ }
+
+ @Override
+ public boolean isCustomNameVisible() {
+ return handle.isCustomNameVisible();
+ }
+
+ @Override
+ public void setInvisible(boolean invisible) {
+ handle.setInvisible(invisible);
+ }
+
+ @Override
+ public boolean isInvisible() {
+ return handle.isInvisible();
+ }
+
+ @Override
+ public boolean isInteractable() {
+ return handle.isPushable();
+ }
+
+ @Override
+ public boolean isCollidable() {
+ return handle.canBeCollidedWith();
+ }
+
+ @Override
+ public void setInvulnerable(boolean invulnerable) {
+ handle.setInvulnerable(invulnerable);
+ }
+
+ @Override
+ public boolean isInvulnerable() {
+ return handle.isInvulnerable();
+ }
+
+ @Override
+ public void setLocation(Location location) {
+ handle.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
+ if (location.getWorld() == null || handle.getCommandSenderWorld().getWorld() == location.getWorld()) {
+ updateVisibility();
+ return;
+ }
+ handle.level = ((CraftWorld) location.getWorld()).getHandle();
+ updateVisibility();
+ }
+
+ @Override
+ public Location getLocation() {
+ Vec3 vector = handle.position();
+ return new Location(handle.getCommandSenderWorld().getWorld(), vector.x, vector.y, vector.z);
+ }
+
+ @Override
+ public void updateVisibility() {
+ if (visible.isEmpty()) {
+ return;
+ }
+ Player[] players;
+ synchronized (visible) {
+ players = visible.stream().map(Bukkit::getOfflinePlayer).filter(OfflinePlayer::isOnline).map(OfflinePlayer::getPlayer)
+ .toArray(Player[]::new);
+ }
+ hide(players);
+ show(players);
+ }
+
+ @Override
+ public boolean isShown(Player player) {
+ synchronized (visible) {
+ return visible.contains(player.getUniqueId());
+ }
+ }
+
+ @Override
+ public void hide(Player... players) {
+ if (players.length == 0) {
+ return;
+ }
+ ClientboundRemoveEntitiesPacket packet = new ClientboundRemoveEntitiesPacket(handle.getId());
+ for (Player player : players) {
+ if (!isShown(player)) {
+ continue;
+ }
+ ((CraftPlayer) player).getHandle().connection.send(packet);
+ synchronized (visible) {
+ visible.remove(player.getUniqueId());
+ }
+ }
+ }
+
+ @Override
+ public void show(Player... players) {
+ if (players.length == 0) {
+ return;
+ }
+ ClientboundAddEntityPacket packet = new ClientboundAddEntityPacket(handle);
+ ClientboundSetEntityDataPacket metadataPacket = new ClientboundSetEntityDataPacket(handle.getId(), handle.getEntityData(), true);
+ ServerGamePacketListenerImpl connection;
+ for (Player player : players) {
+ if (isShown(player)) {
+ continue;
+ }
+ connection = ((CraftPlayer) player).getHandle().connection;
+ connection.send(packet);
+ connection.send(metadataPacket);
+ synchronized (visible) {
+ visible.add(player.getUniqueId());
+ }
+ }
+ }
+
+ @Override
+ public UUID[] getVisible() {
+ synchronized (visible) {
+ return visible.toArray(new UUID[0]);
+ }
+ }
+
+ @Override
+ public Player[] getVisibleAsPlayer() {
+ synchronized (visible) {
+ return visible.stream().map(Bukkit::getOfflinePlayer).filter(OfflinePlayer::isOnline).map(OfflinePlayer::getPlayer)
+ .toArray(Player[]::new);
+ }
+ }
+
+ @Override
+ public void kill() {
+ hide(getVisibleAsPlayer());
+ handle.kill();
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/entity/EntityLiving1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/entity/EntityLiving1_18_R2.java
new file mode 100644
index 0000000..93c7060
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/entity/EntityLiving1_18_R2.java
@@ -0,0 +1,17 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.entity;
+
+import net.minecraft.world.entity.LivingEntity;
+import net.sourcewriters.minecraft.vcompat.provider.entity.NmsEntityLiving;
+
+public abstract class EntityLiving1_18_R2 extends Entity1_18_R2 implements NmsEntityLiving {
+
+ public EntityLiving1_18_R2(E handle) {
+ super(handle);
+ }
+
+ @Override
+ public void setCollidable(boolean collidable) {
+ handle.collides = collidable;
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/entity/Player1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/entity/Player1_18_R2.java
new file mode 100644
index 0000000..e1d9383
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/entity/Player1_18_R2.java
@@ -0,0 +1,293 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.entity;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_18_R2.util.CraftChatMessage;
+import org.bukkit.entity.Player;
+
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.properties.Property;
+import com.mojang.authlib.properties.PropertyMap;
+import com.mojang.datafixers.util.Pair;
+
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundAddPlayerPacket;
+import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
+import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket;
+import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket;
+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.ClientboundSetEntityDataPacket;
+import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket;
+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.ClientboundTabListPacket;
+import net.minecraft.network.protocol.game.ServerboundClientCommandPacket;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerGamePacketListenerImpl;
+import net.minecraft.util.Mth;
+import net.minecraft.world.entity.EquipmentSlot;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.level.biome.BiomeManager;
+import net.sourcewriters.minecraft.vcompat.VersionCompatProvider;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrapType;
+import net.sourcewriters.minecraft.vcompat.provider.data.WrappedContainer;
+import net.sourcewriters.minecraft.vcompat.provider.data.type.SkinDataType;
+import net.sourcewriters.minecraft.vcompat.provider.entity.NmsPlayer;
+import net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.data.SyntaxContainer1_18_R2;
+import net.sourcewriters.minecraft.vcompat.util.bukkit.Players;
+import net.sourcewriters.minecraft.vcompat.util.minecraft.MojangProfileServer;
+import net.sourcewriters.minecraft.vcompat.util.minecraft.Skin;
+import net.sourcewriters.minecraft.vcompat.util.thread.PostAsync;
+
+public class Player1_18_R2 extends EntityLiving1_18_R2 implements NmsPlayer {
+
+ private String realName;
+ private Skin realSkin;
+
+ private final WrappedContainer dataAdapter;
+
+ public Player1_18_R2(Player player) {
+ super(((CraftPlayer) player).getHandle());
+ dataAdapter = new SyntaxContainer1_18_R2(getBukkitPlayer().getPersistentDataContainer());
+ update(false);
+ }
+
+ @Override
+ public CraftPlayer getBukkitPlayer() {
+ return handle.getBukkitEntity();
+ }
+
+ @Override
+ public WrappedContainer getDataAdapter() {
+ return dataAdapter;
+ }
+
+ @Override
+ public void setSkin(Skin skin) {
+ if (skin == null) {
+ return;
+ }
+ dataAdapter.set("skin", skin, SkinDataType.WRAPPED_INSTANCE);
+ }
+
+ @Override
+ public Skin getSkin() {
+ return dataAdapter.getOrDefault("skin", SkinDataType.WRAPPED_INSTANCE, realSkin);
+ }
+
+ @Override
+ public Skin getRealSkin() {
+ return realSkin;
+ }
+
+ @Override
+ public void setName(String name) {
+ if (getName().equals(name)) {
+ return;
+ }
+ if (name == null) {
+ dataAdapter.remove("name");
+ return;
+ }
+ dataAdapter.set("name", name, WrapType.STRING);
+ }
+
+ @Override
+ public String getName() {
+ return dataAdapter.getOrDefault("name", WrapType.STRING, realName);
+ }
+
+ @Override
+ public String getRealName() {
+ return realName;
+ }
+
+ @Override
+ public void setPlayerListHeader(String text) {
+ setPlayerListHeaderAndFooter(text, getPlayerListFooter());
+ }
+
+ @Override
+ public String getPlayerListHeader() {
+ return dataAdapter.getOrDefault("header", WrapType.STRING, "");
+ }
+
+ @Override
+ public void setPlayerListFooter(String text) {
+ setPlayerListHeaderAndFooter(getPlayerListHeader(), text);
+ }
+
+ @Override
+ public String getPlayerListFooter() {
+ return dataAdapter.getOrDefault("footer", WrapType.STRING, "");
+ }
+
+ @Override
+ public int getPing() {
+ return handle.latency;
+ }
+
+ @Override
+ public void setPlayerListHeaderAndFooter(String header, String footer) {
+ dataAdapter.set("header", header, WrapType.STRING);
+ dataAdapter.set("footer", footer, WrapType.STRING);
+ sendPlayerListInfo(header, footer);
+ }
+
+ private final void sendPlayerListInfo(String header, String footer) {
+ if (handle.hasDisconnected()) {
+ return;
+ }
+
+ Component headerComponent = header.isEmpty() ? null : CraftChatMessage.fromStringOrNull(header, true);
+ Component footerComponent = footer.isEmpty() ? null : CraftChatMessage.fromStringOrNull(footer, true);
+
+ handle.connection.send(new ClientboundTabListPacket(headerComponent, footerComponent));
+ }
+
+ @Override
+ public void setTitleTimes(int fadeIn, int stay, int fadeOut) {
+ if (handle.hasDisconnected()) {
+ return;
+ }
+ handle.connection.send(new ClientboundSetTitlesAnimationPacket(fadeIn, stay, fadeOut));
+ }
+
+ @Override
+ public void sendSubtitle(String text) {
+ if (handle.hasDisconnected()) {
+ return;
+ }
+ handle.connection.send(new ClientboundSetSubtitleTextPacket(CraftChatMessage.fromStringOrNull(text)));
+ }
+
+ @Override
+ public void sendTitle(String text) {
+ if (handle.hasDisconnected()) {
+ return;
+ }
+ handle.connection.send(new ClientboundSetTitleTextPacket(CraftChatMessage.fromStringOrNull(text)));
+ }
+
+ @Override
+ public void sendActionBar(String text) {
+ if (handle.hasDisconnected()) {
+ return;
+ }
+ handle.connection.send(new ClientboundSetActionBarTextPacket(CraftChatMessage.fromStringOrNull(text)));
+ }
+
+ @Override
+ public void fakeRespawn() {
+ if (handle.hasDisconnected()) {
+ return;
+ }
+ ClientboundPlayerInfoPacket remInfoPacket = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.REMOVE_PLAYER,
+ handle);
+ ClientboundPlayerInfoPacket addInfoPacket = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, handle);
+
+ ClientboundRemoveEntitiesPacket destroyPacket = new ClientboundRemoveEntitiesPacket(handle.getId());
+ ClientboundAddPlayerPacket spawnPacket = new ClientboundAddPlayerPacket(handle);
+ ClientboundRotateHeadPacket rotationPacket = new ClientboundRotateHeadPacket(handle,
+ (byte) Mth.floor(handle.getYHeadRot() * 256F / 360F));
+
+ ArrayList> list = new ArrayList<>();
+ for (EquipmentSlot slot : EquipmentSlot.values()) {
+ list.add(Pair.of(slot, handle.getItemBySlot(slot)));
+ }
+ ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(handle.getId(), list);
+
+ Player self = getBukkitPlayer();
+ Player[] players = Players.getOnlineWithout(getUniqueId());
+ for (Player player : players) {
+ if (!player.canSee(self)) {
+ continue;
+ }
+ ServerGamePacketListenerImpl connection = ((CraftPlayer) player).getHandle().connection;
+ connection.send(remInfoPacket);
+ connection.send(addInfoPacket);
+ connection.send(destroyPacket);
+ connection.send(spawnPacket);
+ connection.send(rotationPacket);
+ connection.send(equipmentPacket);
+ }
+
+ ServerLevel world = (ServerLevel) handle.level;
+
+ ClientboundRespawnPacket respawnPacket = new ClientboundRespawnPacket(world.dimensionTypeRegistration(), world.dimension(),
+ BiomeManager.obfuscateSeed(world.getSeed()), handle.gameMode.getGameModeForPlayer(),
+ handle.gameMode.getPreviousGameModeForPlayer(), world.isDebug(), world.isFlat(), true);
+ ClientboundPlayerPositionPacket positionPacket = new ClientboundPlayerPositionPacket(handle.getX(), handle.getY(), handle.getZ(),
+ handle.xRotO, handle.yRotO, Collections.emptySet(), 0, false);
+ ClientboundSetCarriedItemPacket itemPacket = new ClientboundSetCarriedItemPacket(handle.getInventory().selected);
+ ClientboundEntityEventPacket statusPacket = new ClientboundEntityEventPacket(handle, (byte) 28);
+ ClientboundSetEntityDataPacket metadataPacket = new ClientboundSetEntityDataPacket(handle.getId(), handle.getEntityData(), true);
+
+ ServerGamePacketListenerImpl connection = handle.connection;
+ connection.send(remInfoPacket);
+ connection.send(addInfoPacket);
+ connection.send(respawnPacket);
+ connection.send(positionPacket);
+ connection.send(itemPacket);
+ connection.send(statusPacket);
+ connection.send(metadataPacket);
+
+ handle.onUpdateAbilities();
+ handle.resetSentInfo();
+ handle.inventoryMenu.broadcastChanges();
+ handle.inventoryMenu.sendAllDataToRemote();
+ if (handle.containerMenu != handle.inventoryMenu) {
+ handle.containerMenu.broadcastChanges();
+ handle.containerMenu.sendAllDataToRemote();
+ }
+ self.recalculatePermissions();
+ }
+
+ @Override
+ public void respawn() {
+ if (handle.connection.isDisconnected()) {
+ return;
+ }
+ handle.connection.send(new ServerboundClientCommandPacket(ServerboundClientCommandPacket.Action.PERFORM_RESPAWN));
+ }
+
+ @Override
+ public void update() {
+ update(true);
+ }
+
+ private final void update(boolean flag) {
+ PostAsync.forcePost(() -> {
+ realName = MojangProfileServer.getName(getUniqueId());
+ realSkin = MojangProfileServer.getSkin(realName, getUniqueId());
+ });
+ if (flag) {
+ GameProfile profile = handle.getGameProfile();
+
+ Skin skin = getSkin();
+ if (skin != null) {
+ PropertyMap properties = profile.getProperties();
+ properties.removeAll("textures");
+ properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
+ }
+
+ String name = getName();
+ if (name != null) {
+ VersionCompatProvider.get().getLookupProvider().getLookup("mjGameProfile").setFieldValue(profile, "name", name);
+ }
+
+ if (!(name == null && skin == null)) {
+ fakeRespawn();
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/tools/BlockTools1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/tools/BlockTools1_18_R2.java
new file mode 100644
index 0000000..27529e3
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/tools/BlockTools1_18_R2.java
@@ -0,0 +1,47 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.tools;
+
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockState;
+import org.bukkit.craftbukkit.v1_18_R2.block.CraftSkull;
+
+import com.mojang.authlib.properties.Property;
+import com.mojang.authlib.properties.PropertyMap;
+
+import net.minecraft.world.level.block.entity.SkullBlockEntity;
+import net.sourcewriters.minecraft.vcompat.VersionCompatProvider;
+import net.sourcewriters.minecraft.vcompat.provider.lookup.handle.ClassLookup;
+import net.sourcewriters.minecraft.vcompat.provider.tools.BlockTools;
+import net.sourcewriters.minecraft.vcompat.util.constants.MinecraftConstants;
+
+public class BlockTools1_18_R2 extends BlockTools {
+
+ private final ClassLookup craftEntityStateRef;
+
+ public BlockTools1_18_R2() {
+ craftEntityStateRef = VersionCompatProvider.get().getLookupProvider().createLookup("CraftSkull", CraftSkull.class)
+ .searchField("tileEntity", "tileEntity");
+ }
+
+ @Override
+ public void setHeadTexture(Block block, String texture) {
+ BlockState state = block.getState();
+ if (!(state instanceof CraftSkull)) {
+ return;
+ }
+ SkullBlockEntity entitySkull = (SkullBlockEntity) craftEntityStateRef.getFieldValue(state, "tileEntity");
+ PropertyMap map = entitySkull.owner.getProperties();
+ map.removeAll("textures");
+ map.put("textures", new Property("textures", MinecraftConstants.TEXTURE_SIGNATURE, texture));
+ }
+
+ @Override
+ public String getHeadTexture(Block block) {
+ BlockState state = block.getState();
+ if (!(state instanceof CraftSkull)) {
+ return null;
+ }
+ SkullBlockEntity entitySkull = (SkullBlockEntity) craftEntityStateRef.getFieldValue(state, "tileEntity");
+ return entitySkull.owner.getProperties().get("textures").iterator().next().getValue();
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/tools/ServerTools1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/tools/ServerTools1_18_R2.java
new file mode 100644
index 0000000..4ca1572
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/tools/ServerTools1_18_R2.java
@@ -0,0 +1,26 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.tools;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
+
+import net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.wrapper.ConsoleReaderWrapper1_18_R2;
+import net.sourcewriters.minecraft.vcompat.provider.tools.ServerTools;
+
+public class ServerTools1_18_R2 extends ServerTools {
+
+ @Override
+ public void setMotd(String text) {
+ ((CraftServer) Bukkit.getServer()).getServer().setMotd(text);
+ }
+
+ @Override
+ public String getMotd() {
+ return ((CraftServer) Bukkit.getServer()).getServer().getMotd();
+ }
+
+ @Override
+ public ConsoleReaderWrapper1_18_R2 getConsole() {
+ return ConsoleReaderWrapper1_18_R2.INSTANCE;
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/tools/SkinTools1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/tools/SkinTools1_18_R2.java
new file mode 100644
index 0000000..958f62b
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/tools/SkinTools1_18_R2.java
@@ -0,0 +1,16 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.tools;
+
+import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+
+import net.sourcewriters.minecraft.vcompat.provider.tools.SkinTools;
+import net.sourcewriters.minecraft.vcompat.util.minecraft.Skin;
+
+public class SkinTools1_18_R2 extends SkinTools {
+
+ @Override
+ public Skin skinFromPlayer(Player player) {
+ return skinFromGameProfile(((CraftPlayer) player).getHandle().getGameProfile());
+ }
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/utils/EntityConstructors1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/utils/EntityConstructors1_18_R2.java
new file mode 100644
index 0000000..3c94769
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/utils/EntityConstructors1_18_R2.java
@@ -0,0 +1,12 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.utils;
+
+import java.util.function.Function;
+
+import net.minecraft.world.level.Level;
+import net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.entity.ArmorStand1_18_R2;
+
+public abstract class EntityConstructors1_18_R2 {
+
+ public static final Function ARMOR_STAND = (world -> new ArmorStand1_18_R2(world));
+
+}
\ No newline at end of file
diff --git a/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/wrapper/ConsoleReaderWrapper1_18_R2.java b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/wrapper/ConsoleReaderWrapper1_18_R2.java
new file mode 100644
index 0000000..aa47908
--- /dev/null
+++ b/vcompat-1_18_R2/src/main/java/net/sourcewriters/minecraft/vcompat/provider/impl/v1_18_R2/wrapper/ConsoleReaderWrapper1_18_R2.java
@@ -0,0 +1,51 @@
+package net.sourcewriters.minecraft.vcompat.provider.impl.v1_18_R2.wrapper;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.bukkit.Bukkit;
+
+import net.sourcewriters.minecraft.vcompat.provider.wrapper.ConsoleReaderWrapper;
+
+import org.bukkit.craftbukkit.Main;
+import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
+
+import jline.console.ConsoleReader;
+
+public final class ConsoleReaderWrapper1_18_R2 extends ConsoleReaderWrapper {
+
+ public static final ConsoleReaderWrapper1_18_R2 INSTANCE = new ConsoleReaderWrapper1_18_R2();
+
+ private final ConsoleReader reader;
+
+ @SuppressWarnings("resource")
+ private ConsoleReaderWrapper1_18_R2() {
+ this.reader = ((CraftServer) Bukkit.getServer()).getServer().reader;
+ }
+
+ @Override
+ public Writer getOutput() {
+ return reader.getOutput();
+ }
+
+ @Override
+ public boolean isAnsiSupported() {
+ return reader.getTerminal().isAnsiSupported();
+ }
+
+ @Override
+ public void flush() throws IOException {
+ reader.flush();
+ }
+
+ @Override
+ public void drawLine() throws IOException {
+ reader.drawLine();
+ }
+
+ @Override
+ public boolean isJLineSupported() {
+ return Main.useJline;
+ }
+
+}
diff --git a/vcompat-api/pom.xml b/vcompat-api/pom.xml
index 92ac765..919032c 100644
--- a/vcompat-api/pom.xml
+++ b/vcompat-api/pom.xml
@@ -3,7 +3,7 @@
net.sourcewriters.minecraft
vcompat-parent
- 3.0.2
+ 3.0.3
vcompat-api
diff --git a/vcompat-core/pom.xml b/vcompat-core/pom.xml
index 6dce272..fa949f3 100644
--- a/vcompat-core/pom.xml
+++ b/vcompat-core/pom.xml
@@ -1,81 +1,86 @@
- 4.0.0
-
- net.sourcewriters.minecraft
- vcompat-parent
- 3.0.2
-
- vcompat
+ 4.0.0
+
+ net.sourcewriters.minecraft
+ vcompat-parent
+ 3.0.3
+
+ vcompat
-
+
-
+
-
- net.sourcewriters.minecraft
- vcompat-api
- ${project.parent.version}
-
+
+ net.sourcewriters.minecraft
+ vcompat-api
+ ${project.parent.version}
+
-
+
-
- net.sourcewriters.minecraft
- vcompat-legacy
- ${project.parent.version}
-
-
- net.sourcewriters.minecraft
- vcompat-1_17_R1
- ${project.parent.version}
-
-
- net.sourcewriters.minecraft
- vcompat-1_18_R1
- ${project.parent.version}
-
-
+
+ net.sourcewriters.minecraft
+ vcompat-legacy
+ ${project.parent.version}
+
+
+ net.sourcewriters.minecraft
+ vcompat-1_17_R1
+ ${project.parent.version}
+
+
+ net.sourcewriters.minecraft
+ vcompat-1_18_R1
+ ${project.parent.version}
+
+
+ net.sourcewriters.minecraft
+ vcompat-1_18_R2
+ ${project.parent.version}
+
+
-
-
-
- maven-shade-plugin
- 3.2.4
-
-
- package
-
- shade
-
-
-
-
-
-
- *:*
-
- META-INF/*.SF
- META-INF/*.DSA
- META-INF/*.RSA
-
-
-
-
-
- com.syntaxphoenix.syntaxapi
- net.sourcewriters.minecraft.vcompat.shaded.syntaxapi
-
-
-
-
-
- org.apache.maven.plugins
- maven-deploy-plugin
- 3.0.0-M2
-
- false
-
-
-
-
+
+
+
+ maven-shade-plugin
+ 3.2.4
+
+
+ package
+
+ shade
+
+
+
+
+
+
+ *:*
+
+ META-INF/*.SF
+ META-INF/*.DSA
+ META-INF/*.RSA
+
+
+
+
+
+ com.syntaxphoenix.syntaxapi
+ net.sourcewriters.minecraft.vcompat.shaded.syntaxapi
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+ 3.0.0-M2
+
+ false
+
+
+
+
\ No newline at end of file
diff --git a/vcompat-legacy/pom.xml b/vcompat-legacy/pom.xml
index f29cd21..4963ec7 100644
--- a/vcompat-legacy/pom.xml
+++ b/vcompat-legacy/pom.xml
@@ -3,7 +3,7 @@
net.sourcewriters.minecraft
vcompat-parent
- 3.0.2
+ 3.0.3
vcompat-legacy