> getTickContainers();
+
+ /**
+ * Adds a TickContainer to the API. Automatically starts ticking it.
+ * @param tickContainer the TickContainer to add.
+ */
+ void addTickContainer(@NotNull TickContainer, T> tickContainer);
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/Platform.java b/api/src/main/java/me/tofaa/entitylib/Platform.java
new file mode 100644
index 0000000..caa366a
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/Platform.java
@@ -0,0 +1,53 @@
+package me.tofaa.entitylib;
+
+import me.tofaa.entitylib.event.EntityLibEvent;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.function.Consumer;
+import java.util.logging.Logger;
+
+/**
+ * A generic representation of a platform that EntityLib is running on.
+ * @param The platform handle, for Spigot this would be a JavaPlugin. etc etc.
+ */
+public interface Platform
{
+
+
+ /**
+ * @return the logger EntityLib uses internally.
+ */
+ @NotNull Logger getLogger();
+
+ /**
+ * Sends an event to the platform. Platform implementations should handle the event accordingly.
+ * @param event the event to send.
+ */
+ void sendEvent(EntityLibEvent event);
+
+ /**
+ * Registers a listener for the given event class, the handle will be called when the event is sent.
+ * @param eventClass the event class to listen for.
+ * @param handle the handle to call when the event is sent.
+ * @param the event type.
+ */
+ void registerListener(Class eventClass, Consumer handle);
+
+ /**
+ * Sets up the API for the platform. This method should be called automatically by the platform. Don't call it yourself.
+ * @param settings
+ */
+ void setupApi(@NotNull APISettings settings);
+
+ /**
+ * @return The API instance.
+ */
+ EntityLibAPI, ?> getAPI();
+
+ /**
+ * @return the platforms name.
+ */
+ String getName();
+
+ @NotNull P getHandle();
+
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/WorldWrapper.java b/api/src/main/java/me/tofaa/entitylib/WorldWrapper.java
new file mode 100644
index 0000000..1cfdb45
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/WorldWrapper.java
@@ -0,0 +1,19 @@
+package me.tofaa.entitylib;
+
+import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
+import com.github.retrooper.packetevents.resources.ResourceLocation;
+
+/**
+ * Represents a platform specific world.
+ * These are not needed at all times, and should exclusively be used when an Entity needs to be
+ * aware of its surroundings.
+ * @param The platform specific World type.
+ */
+public interface WorldWrapper {
+
+ ResourceLocation getPacketEventsWorld();
+
+ WrappedBlockState getBlock(int x, int y, int z);
+
+ W getHandle();
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/event/EntityLibEvent.java b/api/src/main/java/me/tofaa/entitylib/event/EntityLibEvent.java
new file mode 100644
index 0000000..8f3e66c
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/event/EntityLibEvent.java
@@ -0,0 +1,13 @@
+package me.tofaa.entitylib.event;
+
+public interface EntityLibEvent {
+
+ boolean isCancelled();
+
+ void setCancelled(boolean cancelled);
+
+ default boolean isAsync() {
+ return false;
+ }
+
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/event/UserReceiveMetaUpdateEvent.java b/api/src/main/java/me/tofaa/entitylib/event/UserReceiveMetaUpdateEvent.java
new file mode 100644
index 0000000..40df9cd
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/event/UserReceiveMetaUpdateEvent.java
@@ -0,0 +1,29 @@
+package me.tofaa.entitylib.event;
+
+import com.github.retrooper.packetevents.protocol.player.User;
+import me.tofaa.entitylib.meta.EntityMeta;
+
+public final class UserReceiveMetaUpdateEvent implements EntityLibEvent {
+
+ private final User user;
+ private boolean cancelled;
+ private EntityMeta meta;
+
+ public UserReceiveMetaUpdateEvent(User user) {
+ this.user = user;
+ }
+
+ public User getUser() {
+ return user;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+
+ @Override
+ public void setCancelled(boolean cancelled) {
+
+ }
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/extras/InvalidVersionException.java b/api/src/main/java/me/tofaa/entitylib/extras/InvalidVersionException.java
new file mode 100644
index 0000000..a6d0964
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/extras/InvalidVersionException.java
@@ -0,0 +1,23 @@
+package me.tofaa.entitylib.extras;
+
+public class InvalidVersionException extends RuntimeException {
+
+ public InvalidVersionException() {
+ }
+
+ public InvalidVersionException(String message) {
+ super(message);
+ }
+
+ public InvalidVersionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public InvalidVersionException(Throwable cause) {
+ super(cause);
+ }
+
+ public InvalidVersionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/meta/EntityMeta.java b/api/src/main/java/me/tofaa/entitylib/meta/EntityMeta.java
new file mode 100644
index 0000000..bab0c11
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/meta/EntityMeta.java
@@ -0,0 +1,221 @@
+package me.tofaa.entitylib.meta;
+
+import com.github.retrooper.packetevents.manager.server.ServerVersion;
+import com.github.retrooper.packetevents.manager.server.VersionComparison;
+import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
+import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
+import com.github.retrooper.packetevents.protocol.entity.data.EntityMetadataProvider;
+import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
+import com.github.retrooper.packetevents.protocol.player.ClientVersion;
+import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
+import me.tofaa.entitylib.EntityLib;
+import me.tofaa.entitylib.extras.InvalidVersionException;
+import net.kyori.adventure.text.Component;
+
+import java.util.List;
+
+public class EntityMeta implements EntityMetadataProvider {
+
+ public static final byte OFFSET = 0;
+ public static final byte MAX_OFFSET = OFFSET + 8;
+
+ private final static byte ON_FIRE_BIT = 0x01;
+ private final static byte CROUCHING_BIT = 0x02;
+ private final static byte SPRINTING_BIT = 0x08;
+ private final static byte SWIMMING_BIT = 0x10;
+ private final static byte INVISIBLE_BIT = 0x20;
+ private final static byte HAS_GLOWING_EFFECT_BIT = 0x40;
+ private final static byte FLYING_WITH_ELYTRA_BIT = (byte) 0x80;
+
+ protected final int entityId;
+ protected final Metadata metadata;
+
+ public EntityMeta(int entityId, Metadata metadata) {
+ this.entityId = entityId;
+ this.metadata = metadata;
+ }
+
+ public boolean isOnFire() {
+ return getMaskBit(OFFSET, ON_FIRE_BIT);
+ }
+
+ public void setOnFire(boolean value) {
+ setMaskBit(OFFSET, ON_FIRE_BIT, value);
+ }
+
+ public boolean isSneaking() {
+ return getMaskBit(OFFSET, CROUCHING_BIT);
+ }
+
+ public void setSneaking(boolean value) {
+ setMaskBit(OFFSET, CROUCHING_BIT, value);
+ }
+
+ public boolean isSprinting() {
+ return getMaskBit(OFFSET, SPRINTING_BIT);
+ }
+
+ public void setSprinting(boolean value) {
+ setMaskBit(OFFSET, SPRINTING_BIT, value);
+ }
+
+ public boolean isInvisible() {
+ return getMaskBit(OFFSET, INVISIBLE_BIT);
+ }
+
+ public void setInvisible(boolean value) {
+ setMaskBit(OFFSET, INVISIBLE_BIT, value);
+ }
+
+ public short getAirTicks() {
+ return this.metadata.getIndex((byte) 1, (short) 300);
+ }
+
+ public void setAirTicks(short value) {
+ this.metadata.setIndex((byte) 1, EntityDataTypes.SHORT, value);
+ }
+
+ public Component getCustomName() {
+ return this.metadata.getIndex(offset(OFFSET, 2), null);
+ }
+
+ public void setCustomName(Component value) {
+ this.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.ADV_COMPONENT, value);
+ }
+
+ public boolean isCustomNameVisible() {
+ return this.metadata.getIndex(offset(OFFSET, 3), false);
+ }
+
+ public void setCustomNameVisible(boolean value) {
+ this.metadata.setIndex(offset(OFFSET, 3), EntityDataTypes.BOOLEAN, value);
+ }
+
+ public boolean hasGlowingEffect() {
+ return getMaskBit(OFFSET, HAS_GLOWING_EFFECT_BIT);
+ }
+
+ public boolean isSwimming() {
+ return getMaskBit(OFFSET, SWIMMING_BIT);
+ }
+
+ public void setSwimming(boolean value) {
+ setMaskBit(OFFSET, SWIMMING_BIT, value);
+ }
+
+ public void setHasGlowingEffect(boolean value) {
+ setMaskBit(OFFSET, HAS_GLOWING_EFFECT_BIT, value);
+ }
+
+ public boolean isFlyingWithElytra() {
+ return getMaskBit(OFFSET, FLYING_WITH_ELYTRA_BIT);
+ }
+
+ public void setFlyingWithElytra(boolean value) {
+ setMaskBit(OFFSET, FLYING_WITH_ELYTRA_BIT, value);
+ }
+
+ public boolean isSilent() {
+ return this.metadata.getIndex((byte) 4, false);
+ }
+
+ public void setSilent(boolean value) {
+ this.metadata.setIndex((byte) 4, EntityDataTypes.BOOLEAN, value);
+ }
+
+ public boolean isHasNoGravity() {
+ return this.metadata.getIndex(offset(OFFSET, 5), true);
+ }
+
+ public void setHasNoGravity(boolean value) {
+ this.metadata.setIndex(offset(OFFSET, 5), EntityDataTypes.BOOLEAN, value);
+ }
+
+ public EntityPose getPose() {
+ return this.metadata.getIndex(offset(OFFSET, 6), EntityPose.STANDING);
+ }
+
+ public void setPose(EntityPose value) {
+ this.metadata.setIndex(offset(OFFSET, 6), EntityDataTypes.ENTITY_POSE, value);
+ }
+
+ public int getTicksFrozenInPowderedSnow() {
+ return this.metadata.getIndex(offset(OFFSET, 7), 0);
+ }
+
+ public void setTicksFrozenInPowderedSnow(int value) {
+ this.metadata.setIndex(offset(OFFSET, 7), EntityDataTypes.INT, value);
+ }
+
+ public WrapperPlayServerEntityMetadata createPacket() {
+ return metadata.createPacket();
+ }
+
+ protected static void isVersionOlder(ServerVersion version) {
+ if (!EntityLib.getApi().getPacketEvents().getServerManager().getVersion().is(VersionComparison.OLDER_THAN, version)) {
+ throw new InvalidVersionException("This method is only available for versions older than " + version.name() + ".");
+ }
+ }
+
+ protected static void isVersionNewer(ServerVersion version) {
+ if (!EntityLib.getApi().getPacketEvents().getServerManager().getVersion().is(VersionComparison.NEWER_THAN, version)) {
+ throw new InvalidVersionException("This method is only available for versions newer than " + version.name() + ".");
+ }
+ }
+
+ protected static boolean isVersion(ServerVersion version, VersionComparison comparison) {
+ return EntityLib.getApi().getPacketEvents().getServerManager().getVersion().is(comparison, version);
+ }
+
+ protected static boolean isVersion(ServerVersion version) {
+ return EntityLib.getApi().getPacketEvents().getServerManager().getVersion().is(VersionComparison.EQUALS, version);
+ }
+
+ /**
+ * Annoying java 8 not letting me do OFFSET + amount in the method call so this is a workaround
+ * @param value the value to offset
+ * @param amount the amount to offset by
+ * @return the offset value
+ */
+ protected static byte offset(byte value, int amount) {
+ return (byte) (value + amount);
+ }
+
+ protected byte getMask(byte index) {
+ return this.metadata.getIndex(index, (byte) 0);
+ }
+
+ protected void setMask(byte index, byte mask) {
+ this.metadata.setIndex(index, EntityDataTypes.BYTE, mask);
+ }
+
+ protected boolean getMaskBit(byte index, byte bit) {
+ return (getMask(index) & bit) == bit;
+ }
+
+ protected void setMaskBit(int index, byte bit, boolean value) {
+ byte mask = getMask((byte)index);
+ boolean currentValue = (mask & bit) == bit;
+ if (currentValue == value) {
+ return;
+ }
+ if (value) {
+ mask |= bit;
+ } else {
+ mask &= (byte) ~bit;
+ }
+ setMask((byte)index, mask);
+ }
+
+ @Override
+ public List entityData(ClientVersion clientVersion) {
+ return metadata.getEntries(); // TODO: Atm this is useless cause of the way the api works. Might change in the future
+ }
+
+ @Override
+ public List entityData() {
+ return metadata.getEntries();
+ }
+
+
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/meta/Metadata.java b/api/src/main/java/me/tofaa/entitylib/meta/Metadata.java
new file mode 100644
index 0000000..cc4c681
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/meta/Metadata.java
@@ -0,0 +1,45 @@
+package me.tofaa.entitylib.meta;
+
+import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
+import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
+import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
+import me.tofaa.entitylib.EntityLib;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@SuppressWarnings("unchecked")
+public class Metadata {
+
+ private final Map metadataMap = new ConcurrentHashMap<>();
+ private final int entityId;
+
+ public Metadata(int entityId) {
+ this.entityId = entityId;
+ }
+
+ public T getIndex(byte index, @Nullable T defaultValue) {
+ EntityData entityData = metadataMap.get(index);
+ if (entityData == null) return defaultValue;
+ if (entityData.getValue() == null) return defaultValue;
+ return (T) entityData.getValue();
+ }
+
+ public void setIndex(byte index, @NotNull EntityDataType dataType, T value) {
+ EntityData data = new EntityData(index, dataType, value);
+ this.metadataMap.put(index, data);
+ }
+
+ @NotNull List getEntries() {
+ return new ArrayList<>(metadataMap.values());
+ }
+
+ public WrapperPlayServerEntityMetadata createPacket() {
+ return new WrapperPlayServerEntityMetadata(entityId, getEntries());
+ }
+
+}
\ No newline at end of file
diff --git a/api/src/main/java/me/tofaa/entitylib/tick/TickContainer.java b/api/src/main/java/me/tofaa/entitylib/tick/TickContainer.java
new file mode 100644
index 0000000..f1b856f
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/tick/TickContainer.java
@@ -0,0 +1,72 @@
+package me.tofaa.entitylib.tick;
+
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Represents a storage/container for {@link Tickable}s.
+ * @param The type of {@link Tickable} to store.
+ * @param If a platform enforces a specific method of ticking, this type represents the handler for that method.
+ */
+public abstract class TickContainer {
+
+ private final Set tickables = new HashSet<>();
+ private H handle;
+
+ /**
+ * @return The {@link Tickable}s stored in this container. This collection is immutable
+ */
+ public @NotNull Collection getTickables() {
+ return Collections.unmodifiableCollection(tickables);
+ }
+
+ /**
+ * Adds a {@link Tickable} to this container.
+ * @param tickable The {@link Tickable} to add.
+ * @return {@code true} if the {@link Tickable} was added, {@code false} otherwise.
+ */
+ public boolean addTickable(@NotNull T tickable) {
+ return tickables.add(tickable);
+ }
+
+ /**
+ * Removes a {@link Tickable} from this container.
+ * @param tickable The {@link Tickable} to remove.
+ * @return {@code true} if the {@link Tickable} was removed, {@code false} otherwise.
+ */
+ public boolean removeTickable(T tickable) {
+ return tickables.remove(tickable);
+ }
+
+ /**
+ * Ticks all {@link Tickable}s in this container, this method can be overriden to provide a custom implementation.
+ * @param time The current time in milliseconds, incase the {@link Tickable} needs to know the current time.
+ */
+ public void tick(long time) {
+ for (T tickable : tickables) {
+ tickable.tick(time);
+ }
+ }
+
+ /**
+ * @return The handler for this container.
+ */
+ public @NotNull H getHandle() {
+ return handle;
+ }
+
+ /**
+ * Sets the handler for this container. This method is only used internally.
+ * @param handle The handler to set.
+ */
+ @ApiStatus.Internal
+ public void setHandle(@NotNull H handle) {
+ this.handle = handle;
+ }
+
+}
diff --git a/api/src/main/java/me/tofaa/entitylib/tick/Tickable.java b/api/src/main/java/me/tofaa/entitylib/tick/Tickable.java
new file mode 100644
index 0000000..11dd41b
--- /dev/null
+++ b/api/src/main/java/me/tofaa/entitylib/tick/Tickable.java
@@ -0,0 +1,7 @@
+package me.tofaa.entitylib.tick;
+
+public interface Tickable {
+
+ void tick(long time);
+
+}
diff --git a/build.gradle b/build.gradle
index 1958f2c..555b4ab 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,6 +5,12 @@ plugins {
allprojects {
+ project.ext.adventureVersion = '4.15.0'
+ project.ext.adventureDependencies=["net.kyori:adventure-api:${adventureVersion}",
+ "net.kyori:adventure-text-serializer-gson:${adventureVersion}",
+ "net.kyori:adventure-text-serializer-legacy:${adventureVersion}",
+ "net.kyori:adventure-nbt:${adventureVersion}"]
+
apply plugin: 'java'
group = 'me.tofaa.entitylib'
diff --git a/platforms/spigot/build.gradle b/platforms/spigot/build.gradle
new file mode 100644
index 0000000..90169d6
--- /dev/null
+++ b/platforms/spigot/build.gradle
@@ -0,0 +1,15 @@
+plugins {
+ id 'java'
+}
+
+group = 'me.tofaa.entitylib'
+version = '1.0-SNAPSHOT'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation(project(":api"))
+ implementation('org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT')
+}
diff --git a/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibAPI.java b/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibAPI.java
new file mode 100644
index 0000000..5f2222e
--- /dev/null
+++ b/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibAPI.java
@@ -0,0 +1,98 @@
+package me.tofaa.entitylib.spigot;
+
+import com.github.retrooper.packetevents.PacketEventsAPI;
+import me.tofaa.entitylib.APISettings;
+import me.tofaa.entitylib.EntityLibAPI;
+import me.tofaa.entitylib.tick.TickContainer;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+import org.bukkit.scheduler.BukkitTask;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.logging.Level;
+
+public class SpigotEntityLibAPI implements EntityLibAPI {
+
+ private final SpigotEntityLibPlatform platform;
+ private final PacketEventsAPI> packetEvents;
+ private final APISettings settings;
+ private Collection> tickContainers;
+
+ SpigotEntityLibAPI(SpigotEntityLibPlatform platform, APISettings settings) {
+ this.platform = platform;
+ this.packetEvents = settings.getPacketEvents();
+ this.settings = settings;
+ }
+
+ @Override
+ public void onLoad() {
+ this.tickContainers = settings.shouldTickTickables() ? new HashSet<>() : Collections.EMPTY_SET;
+ }
+
+ @Override
+ public void onEnable() {
+
+ }
+
+ @NotNull @Override
+ public APISettings getSettings() {
+ return settings;
+ }
+
+ @Override
+ public void setupTickingContainers() {
+ if (!getSettings().shouldTickTickables()) {
+ if (getSettings().isDebugMode()) {
+ platform.getLogger().log(Level.CONFIG, "Skipping ticking containers as it is disabled in the settings.");
+ }
+ return;
+ }
+
+ if (getSettings().isDebugMode()) {
+ platform.getLogger().log(Level.CONFIG, "Setting up ticking containers...");
+ }
+ if (tickContainers.isEmpty()) {
+ if (getSettings().isDebugMode()) {
+ platform.getLogger().log(Level.CONFIG, "No tick containers found.");
+ }
+ return;
+ }
+
+ if (getSettings().isDebugMode()) {
+ platform.getLogger().log(Level.CONFIG, "Found " + tickContainers.size() + " tick containers.");
+ }
+
+ tickContainers.forEach(this::registerNewTickContainer);
+ }
+
+ @Override
+ public PacketEventsAPI> getPacketEvents() {
+ return packetEvents;
+ }
+
+ @Override
+ public Collection> getTickContainers() {
+ return tickContainers;
+ }
+
+ @Override
+ public void addTickContainer(@NotNull TickContainer, BukkitTask> tickContainer) {
+ tickContainers.add(tickContainer);
+ registerNewTickContainer(tickContainer);
+ }
+
+ public void registerNewTickContainer(TickContainer, BukkitTask> tickContainer) {
+
+ if (getSettings().isDebugMode()) {
+ platform.getLogger().log(Level.CONFIG, "Registering new tick container...");
+ }
+ getTickContainers().add(tickContainer);
+ BukkitTask task = Bukkit.getScheduler().runTaskTimerAsynchronously(platform.getHandle(), () -> tickContainer.tick(System.currentTimeMillis()), 1L, 1L);
+ tickContainer.setHandle(task);
+ }
+
+
+}
diff --git a/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java b/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java
new file mode 100644
index 0000000..c719df0
--- /dev/null
+++ b/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java
@@ -0,0 +1,65 @@
+package me.tofaa.entitylib.spigot;
+
+import me.tofaa.entitylib.APISettings;
+import me.tofaa.entitylib.EntityLibAPI;
+import me.tofaa.entitylib.Platform;
+import me.tofaa.entitylib.event.EntityLibEvent;
+import me.tofaa.entitylib.tick.TickContainer;
+import org.bukkit.Bukkit;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.scheduler.BukkitTask;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.function.Consumer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class SpigotEntityLibPlatform implements Platform {
+
+ private final JavaPlugin plugin;
+ private SpigotEntityLibAPI api;
+ private Logger logger;
+
+ public SpigotEntityLibPlatform(@NotNull JavaPlugin plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public void setupApi(@NotNull APISettings settings) {
+ this.logger = settings.shouldUsePlatformLogger() ? plugin.getLogger() : Logger.getLogger("EntityLib");
+ this.api = new SpigotEntityLibAPI(this, settings);
+ this.api.onLoad();
+ this.api.onEnable();
+ }
+
+ @Override
+ public @NotNull Logger getLogger() {
+ return logger;
+ }
+
+ @Override
+ public void sendEvent(EntityLibEvent event) {
+
+ }
+
+ @Override
+ public void registerListener(Class eventClass, Consumer handle) {
+
+ }
+
+ @Override
+ public EntityLibAPI getAPI() {
+ return api;
+ }
+
+ @Override
+ public @NotNull JavaPlugin getHandle() {
+ return plugin;
+ }
+
+ @Override
+ public String getName() {
+ return "Spigot";
+ }
+}
diff --git a/settings.gradle b/settings.gradle
index 81e87e9..5426790 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,4 +1,6 @@
rootProject.name = 'EntityLib'
include 'test-plugin'
include 'api'
+include 'platforms:spigot'
+findProject(':platforms:spigot')?.name = 'spigot'
diff --git a/src/main/java/me/tofaa/entitylib/meta/Metadata.java b/src/main/java/me/tofaa/entitylib/meta/Metadata.java
index 8dd0d57..bcb0f7f 100644
--- a/src/main/java/me/tofaa/entitylib/meta/Metadata.java
+++ b/src/main/java/me/tofaa/entitylib/meta/Metadata.java
@@ -9,7 +9,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;