diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 228b351..6569d31 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -11,6 +11,8 @@
+
+
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 7183e2c..19904a9 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -5,15 +5,10 @@
-
+
+
-
-
-
-
-
-
-
+
@@ -66,6 +61,7 @@
@@ -73,6 +69,8 @@
+
+
@@ -318,6 +316,7 @@
+
diff --git a/code-gen/src/main/java/me/tofaa/entitylib/codegen/modern/Main.java b/code-gen/src/main/java/me/tofaa/entitylib/codegen/modern/Main.java
new file mode 100644
index 0000000..d981cea
--- /dev/null
+++ b/code-gen/src/main/java/me/tofaa/entitylib/codegen/modern/Main.java
@@ -0,0 +1,7 @@
+package me.tofaa.entitylib.codegen.modern;
+
+public final class Main {
+
+ private Main() {}
+
+}
diff --git a/kotlin/kotlin-extensions-spigot/build.gradle b/kotlin/kotlin-extensions-spigot/build.gradle
new file mode 100644
index 0000000..12d1029
--- /dev/null
+++ b/kotlin/kotlin-extensions-spigot/build.gradle
@@ -0,0 +1,13 @@
+plugins {
+ id 'org.jetbrains.kotlin.jvm' version '1.9.22'
+}
+
+dependencies {
+ compileOnly(project(":platforms:spigot"))
+ compileOnly('com.github.retrooper.packetevents:spigot:2.0.2')
+ compileOnly('org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT')
+}
+
+kotlin {
+ jvmToolchain(8)
+}
\ No newline at end of file
diff --git a/kotlin/kotlin-extensions-spigot/src/main/kotlin/me/tofaa/entitylib/kotlin/EntityExtensions.kt b/kotlin/kotlin-extensions-spigot/src/main/kotlin/me/tofaa/entitylib/kotlin/EntityExtensions.kt
new file mode 100644
index 0000000..101399a
--- /dev/null
+++ b/kotlin/kotlin-extensions-spigot/src/main/kotlin/me/tofaa/entitylib/kotlin/EntityExtensions.kt
@@ -0,0 +1,71 @@
+package me.tofaa.entitylib.kotlin
+
+import com.github.retrooper.packetevents.wrapper.PacketWrapper
+import io.github.retrooper.packetevents.util.SpigotConversionUtil
+import me.tofaa.entitylib.EntityLib
+import me.tofaa.entitylib.EntityLibAPI
+import me.tofaa.entitylib.Platform
+import me.tofaa.entitylib.spigot.SpigotEntityLibAPI
+import me.tofaa.entitylib.wrapper.WrapperEntity
+import me.tofaa.entitylib.wrapper.WrapperEntityEquipment
+import org.bukkit.Location
+import org.bukkit.entity.Entity
+import org.bukkit.inventory.ItemStack
+import org.bukkit.plugin.java.JavaPlugin
+
+fun JavaPlugin.getEntityLibApi(): EntityLibAPI {
+ return EntityLib.getApi()!!
+}
+
+fun JavaPlugin.getEntityLibPlatform(): Platform<*> {
+ return EntityLib.getPlatform()!!
+}
+
+fun WrapperEntity.asBukkitEntity(location: Location): Entity {
+ val world = location.world ?: throw IllegalArgumentException("Location world is null");
+ val entity = world.spawnEntity(location, SpigotConversionUtil.toBukkitEntityType(this.entityType));
+ // TODO: Copy entity data
+ return entity;
+}
+
+fun WrapperEntity.sendPacketToViewersAndCallback(packet: PacketWrapper<*>, callback: () -> Unit) {
+ this.sendPacketsToViewers(packet);
+ callback();
+}
+
+fun WrapperEntity.sendPacketsToViewersAndCallback(vararg packets: PacketWrapper<*>, callback: () -> Unit) {
+ this.sendPacketsToViewers(*packets);
+ callback();
+}
+
+fun Entity.asWrapperEntity(location: Location): WrapperEntity {
+ return EntityLib.getApi().cloneEntity(this, SpigotConversionUtil.fromBukkitLocation(location));
+}
+
+fun Entity.asWrapperEntity(): WrapperEntity {
+ return asWrapperEntity(this.location);
+}
+
+fun WrapperEntityEquipment.setMainHand(stack: ItemStack) {
+ this.mainHand = SpigotConversionUtil.fromBukkitItemStack(stack);
+}
+
+fun WrapperEntityEquipment.setOffHand(stack: ItemStack) {
+ this.offhand = SpigotConversionUtil.fromBukkitItemStack(stack);
+}
+
+fun WrapperEntityEquipment.setHelmet(stack: ItemStack) {
+ this.helmet = SpigotConversionUtil.fromBukkitItemStack(stack);
+}
+
+fun WrapperEntityEquipment.setChestplate(stack: ItemStack) {
+ this.chestplate = SpigotConversionUtil.fromBukkitItemStack(stack);
+}
+
+fun WrapperEntityEquipment.setLeggings(stack: ItemStack) {
+ this.leggings = SpigotConversionUtil.fromBukkitItemStack(stack);
+}
+
+fun WrapperEntityEquipment.setBoots(stack: ItemStack) {
+ this.boots = SpigotConversionUtil.fromBukkitItemStack(stack);
+}
\ No newline at end of file
diff --git a/platforms/velocity/build.gradle b/platforms/velocity/build.gradle
new file mode 100644
index 0000000..37c8f31
--- /dev/null
+++ b/platforms/velocity/build.gradle
@@ -0,0 +1,20 @@
+
+repositories {
+ maven {
+ name = 'papermc'
+ url = 'https://repo.papermc.io/repository/maven-public/'
+ }
+}
+tasks {
+ compileJava {
+ options.release.set(17)
+ }
+}
+java.toolchain.languageVersion.set(JavaLanguageVersion.of(17))
+
+
+dependencies {
+ api(project(":common"))
+ compileOnly('com.github.retrooper.packetevents:velocity:2.0.2')
+ compileOnly 'com.velocitypowered:velocity-api:3.3.0-SNAPSHOT'
+}
diff --git a/platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityEntityLibAPI.java b/platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityEntityLibAPI.java
new file mode 100644
index 0000000..866cab3
--- /dev/null
+++ b/platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityEntityLibAPI.java
@@ -0,0 +1,56 @@
+package me.tofaa.entitylib.velocity;
+
+import com.github.retrooper.packetevents.protocol.world.Location;
+import com.velocitypowered.api.proxy.ProxyServer;
+import com.velocitypowered.api.scheduler.ScheduledTask;
+import me.tofaa.entitylib.APIConfig;
+import me.tofaa.entitylib.Platform;
+import me.tofaa.entitylib.common.AbstractEntityLibAPI;
+import me.tofaa.entitylib.tick.TickContainer;
+import me.tofaa.entitylib.wrapper.WrapperEntity;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+
+public class VelocityEntityLibAPI extends AbstractEntityLibAPI {
+
+
+ public VelocityEntityLibAPI(VelocityEntityLibPlatform platform, APIConfig settings) {
+ super(platform, settings);
+ }
+
+ @Override
+ public void onLoad() {
+
+ }
+
+ @Override
+ public void onEnable() {
+
+ }
+
+ @Override
+ public void addTickContainer(@NotNull TickContainer tickContainer) {
+ if (!settings.shouldTickTickables()) {
+ if (settings.isDebugMode()) {
+ platform.getLogger().log(Level.WARNING, "Tried to add a TickContainer when ticking tickables is disabled!");
+ }
+ return;
+ }
+ tickContainers.add(tickContainer);
+ if (settings.isDebugMode()) {
+ platform.getLogger().log(Level.CONFIG, "Registering new tick container...");
+ }
+ getTickContainers().add(tickContainer);
+ Object plugin = ((VelocityEntityLibPlatform)platform).getPlugin();
+ ScheduledTask task = platform.getHandle().getScheduler().buildTask(plugin, () -> tickContainer.tick(System.currentTimeMillis())).repeat(50L, TimeUnit.MILLISECONDS).schedule();
+ tickContainer.setHandle(task);
+ }
+
+ @NotNull
+ @Override
+ public WrapperEntity cloneEntity(@NotNull Object platformEntity, @NotNull Location location) {
+ throw new UnsupportedOperationException("No support for cloning entities on Velocity");
+ }
+}
diff --git a/platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityEntityLibPlatform.java b/platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityEntityLibPlatform.java
new file mode 100644
index 0000000..252a1f8
--- /dev/null
+++ b/platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityEntityLibPlatform.java
@@ -0,0 +1,42 @@
+package me.tofaa.entitylib.velocity;
+
+import com.velocitypowered.api.proxy.ProxyServer;
+import me.tofaa.entitylib.APIConfig;
+import me.tofaa.entitylib.EntityLibAPI;
+import me.tofaa.entitylib.common.AbstractPlatform;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.logging.Logger;
+
+public class VelocityEntityLibPlatform extends AbstractPlatform {
+ private VelocityEntityLibAPI api;
+ private Object plugin;
+
+ public VelocityEntityLibPlatform(Object plugin, ProxyServer handle) {
+ super(handle);
+ this.plugin = plugin;
+ }
+
+ @Override
+ public void setupApi(@NotNull APIConfig settings) {
+ super.setupApi(settings);
+ this.logger = Logger.getLogger("EntityLib"); // Velocity does not have a logger by default.
+ this.api = new VelocityEntityLibAPI(this, settings);
+ this.api.onLoad();
+ this.api.onEnable();
+ }
+
+ public Object getPlugin() {
+ return plugin;
+ }
+
+ @Override
+ public EntityLibAPI> getAPI() {
+ return api;
+ }
+
+ @Override
+ public String getName() {
+ return "Velocity";
+ }
+}
diff --git a/settings.gradle b/settings.gradle
index 43b30b1..dde460f 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,6 @@
+plugins {
+ id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0'
+}
rootProject.name = 'EntityLib'
//include 'test-plugin'
include 'api'
@@ -8,4 +11,9 @@ include 'code-gen'
if (!Boolean.parseBoolean(System.getenv("JITPACK"))) {
include 'test-plugin'
-}
\ No newline at end of file
+}
+include 'kotlin:kotlin-extensions-spigot'
+findProject(':kotlin:kotlin-extensions-spigot')?.name = 'kotlin-extensions-spigot'
+include 'platforms:velocity'
+findProject(':platforms:velocity')?.name = 'velocity'
+