diff --git a/.gitignore b/.gitignore
index b63da45..e21d8b4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@ build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
+run/
### IntelliJ IDEA ###
.idea/modules.xml
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 2c99fbb..12993cb 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,9 +2,9 @@ import java.io.BufferedReader
import java.io.InputStreamReader
plugins {
+ id("java")
alias(libs.plugins.runPaper)
alias(libs.plugins.paperweight) apply true
- alias(libs.plugins.kotlinJvm) apply true
alias(libs.plugins.shadow) apply true
`maven-publish`
@@ -23,13 +23,16 @@ repositories {
maven("https://repo.dmulloy2.net/repository/public/")
maven("https://jitpack.io")
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/")
+ maven("https://repo.codemc.io/repository/maven-releases/")
+ maven("https://maven.evokegames.gg/snapshots")
}
dependencies {
paperweight.paperDevBundle(libs.versions.paperApi.get())
- compileOnly(libs.ktgui)
compileOnly(libs.placeholder.api)
+ compileOnly(libs.packet.events)
+ implementation(libs.entity.lib)
}
tasks {
@@ -82,9 +85,9 @@ java {
withSourcesJar()
}
-kotlin {
- jvmToolchain(17)
-}
+//kotlin {
+// jvmToolchain(21)
+//}
sourceSets["main"].resources.srcDir("src/resources/")
diff --git a/gradle.properties b/gradle.properties
index 7dbbec3..61e8bd5 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -2,11 +2,11 @@ kotlin.code.style=official
# Project configuration
group_name = com.mattmx
-id = template
+id = nametags
version = 1.0
-plugin_name = Template
-plugin_main_class_name = TemplatePlugin
+plugin_name = NameTags
+plugin_main_class_name = NameTags
plugin_author = MattMX
include_commit_hash = true
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 9717558..15f0209 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -9,6 +9,9 @@ placeholderapi = "2.11.6"
ktgui = "2.4.2-alpha"
runPaper = "2.2.4"
+packetEvents = "2.4.0"
+entityLib = "2.4.9-SNAPSHOT"
+
[libraries]
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
@@ -16,6 +19,8 @@ kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "
paper-api = { module = "io.papermc.paper:paper-api", version.ref = "paperApi" }
placeholder-api = { module = "me.clip:placeholderapi", version.ref = "placeholderapi" }
ktgui = { module = "com.mattmx:ktgui", version.ref = "ktgui" }
+packet-events = { module = "com.github.retrooper:packetevents-spigot", version.ref = "packetEvents" }
+entity-lib = { module = "me.tofaa.entitylib:spigot", version.ref = "entityLib" }
[plugins]
diff --git a/run/plugins/packetevents-spigot-2.4.0 (3).jar b/run/plugins/packetevents-spigot-2.4.0 (3).jar
new file mode 100644
index 0000000..682254f
Binary files /dev/null and b/run/plugins/packetevents-spigot-2.4.0 (3).jar differ
diff --git a/src/main/java/com/mattmx/nametags/EventsListener.java b/src/main/java/com/mattmx/nametags/EventsListener.java
new file mode 100644
index 0000000..9f7de87
--- /dev/null
+++ b/src/main/java/com/mattmx/nametags/EventsListener.java
@@ -0,0 +1,45 @@
+package com.mattmx.nametags;
+
+import com.github.retrooper.packetevents.protocol.world.Location;
+import com.mattmx.nametags.entity.NameTagEntity;
+import io.github.retrooper.packetevents.util.SpigotConversionUtil;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerChangedWorldEvent;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.jetbrains.annotations.NotNull;
+
+public class EventsListener implements Listener {
+
+ @EventHandler
+ public void onPlayerJoin(@NotNull PlayerJoinEvent event) {
+ NameTagEntity nameTagEntity = NameTags.getInstance()
+ .getEntityManager()
+ .getOrCreateNameTagEntity(event.getPlayer());
+ }
+
+ @EventHandler
+ public void onPlayerQuit(@NotNull PlayerQuitEvent event) {
+ NameTagEntity entity = NameTags.getInstance()
+ .getEntityManager()
+ .removeEntity(event.getPlayer());
+
+ if (entity == null) return;
+
+ entity.getPassenger().despawn();
+ }
+
+ @EventHandler
+ public void onChangeWorld(@NotNull PlayerChangedWorldEvent event) {
+ NameTagEntity nameTagEntity = NameTags.getInstance()
+ .getEntityManager()
+ .getNameTagEntity(event.getPlayer());
+
+ if (nameTagEntity == null) return;
+
+ Location newLocation = SpigotConversionUtil.fromBukkitLocation(event.getPlayer().getLocation());
+
+ nameTagEntity.getPassenger().setLocation(newLocation);
+ }
+}
diff --git a/src/main/java/com/mattmx/nametags/NameTags.java b/src/main/java/com/mattmx/nametags/NameTags.java
new file mode 100644
index 0000000..f1deb5b
--- /dev/null
+++ b/src/main/java/com/mattmx/nametags/NameTags.java
@@ -0,0 +1,51 @@
+package com.mattmx.nametags;
+
+import com.github.retrooper.packetevents.PacketEvents;
+import com.mattmx.nametags.entity.NameTagEntityManager;
+import me.tofaa.entitylib.APIConfig;
+import me.tofaa.entitylib.EntityLib;
+import me.tofaa.entitylib.spigot.SpigotEntityLibPlatform;
+import org.bukkit.Bukkit;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class NameTags extends JavaPlugin {
+ private static @Nullable NameTags instance;
+
+ private NameTagEntityManager entityManager;
+ private final EventsListener eventsListener = new EventsListener();
+ private final OutgoingPacketListener packetListener = new OutgoingPacketListener(this);
+
+ @Override
+ public void onEnable() {
+ instance = this;
+ entityManager = new NameTagEntityManager();
+
+ SpigotEntityLibPlatform platform = new SpigotEntityLibPlatform(this);
+ APIConfig settings = new APIConfig(PacketEvents.getAPI())
+ .debugMode()
+ .tickTickables()
+ .trackPlatformEntities()
+ .usePlatformLogger();
+
+ EntityLib.init(platform, settings);
+
+ PacketEvents.getAPI()
+ .getEventManager()
+ .registerListener(packetListener);
+
+ Bukkit.getPluginManager().registerEvents(eventsListener, this);
+ }
+
+ public @NotNull NameTagEntityManager getEntityManager() {
+ return this.entityManager;
+ }
+
+ public static @NotNull NameTags getInstance() {
+ if (instance == null)
+ throw new RuntimeException("NameTags plugin has not initialized yet! Did you forget to depend?");
+
+ return instance;
+ }
+}
diff --git a/src/main/java/com/mattmx/nametags/OutgoingPacketListener.java b/src/main/java/com/mattmx/nametags/OutgoingPacketListener.java
new file mode 100644
index 0000000..6d13965
--- /dev/null
+++ b/src/main/java/com/mattmx/nametags/OutgoingPacketListener.java
@@ -0,0 +1,53 @@
+package com.mattmx.nametags;
+
+import com.github.retrooper.packetevents.event.PacketListenerAbstract;
+import com.github.retrooper.packetevents.event.PacketSendEvent;
+import com.github.retrooper.packetevents.protocol.packettype.PacketType;
+import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
+import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity;
+import com.mattmx.nametags.entity.NameTagEntity;
+import org.jetbrains.annotations.NotNull;
+
+public class OutgoingPacketListener extends PacketListenerAbstract {
+
+ private NameTags plugin;
+
+ public OutgoingPacketListener(NameTags plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public void onPacketSend(@NotNull PacketSendEvent event) {
+ switch (event.getPacketType()) {
+ case PacketType.Play.Server.SPAWN_ENTITY -> {
+ WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(event);
+
+ if (packet.getUUID().isEmpty()) return;
+
+ NameTagEntity nameTagEntity = plugin.getEntityManager().getNameTagEntityByUUID(packet.getUUID().get());
+
+ if (nameTagEntity == null) return;
+
+ // Add passenger and send to player (Delayed so this packet sends first)
+ event.getTasksAfterSend().add(() -> {
+ nameTagEntity.getPassenger().removeViewer(event.getUser());
+ nameTagEntity.getPassenger().addViewer(event.getUser());
+ event.getUser().sendPacket(nameTagEntity.getPassengersPacket());
+ });
+ }
+ case PacketType.Play.Server.DESTROY_ENTITIES -> {
+ WrapperPlayServerDestroyEntities packet = new WrapperPlayServerDestroyEntities(event);
+
+ for (int entityId : packet.getEntityIds()) {
+ NameTagEntity nameTagEntity = plugin.getEntityManager().getNameTagEntityById(entityId);
+
+ if (nameTagEntity == null) continue;
+
+ nameTagEntity.getPassenger().removeViewer(event.getUser());
+ }
+ }
+ default -> {
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/mattmx/nametags/entity/NameTagEntity.java b/src/main/java/com/mattmx/nametags/entity/NameTagEntity.java
new file mode 100644
index 0000000..f4a76a9
--- /dev/null
+++ b/src/main/java/com/mattmx/nametags/entity/NameTagEntity.java
@@ -0,0 +1,60 @@
+package com.mattmx.nametags.entity;
+
+import com.github.retrooper.packetevents.PacketEvents;
+import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
+import com.github.retrooper.packetevents.util.Vector3f;
+import com.github.retrooper.packetevents.wrapper.PacketWrapper;
+import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPassengers;
+import io.github.retrooper.packetevents.util.SpigotConversionUtil;
+import me.tofaa.entitylib.meta.display.AbstractDisplayMeta;
+import me.tofaa.entitylib.meta.display.TextDisplayMeta;
+import me.tofaa.entitylib.wrapper.WrapperEntity;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import org.bukkit.Color;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+public class NameTagEntity {
+ private final @NotNull Entity bukkitEntity;
+ private final @NotNull WrapperEntity passenger;
+
+ public NameTagEntity(@NotNull Entity entity) {
+ this.bukkitEntity = entity;
+ this.passenger = new WrapperEntity(EntityTypes.TEXT_DISPLAY);
+
+ applyDefaultMeta();
+ }
+
+ public void applyDefaultMeta() {
+ this.passenger.consumeEntityMeta(TextDisplayMeta.class, (meta) -> {
+ meta.setText(bukkitEntity.name());
+ meta.setTranslation(new Vector3f(0f, 0.25f, 0f));
+ meta.setBackgroundColor(Color.RED.setAlpha(50).asARGB());
+ meta.setBillboardConstraints(AbstractDisplayMeta.BillboardConstraints.CENTER);
+ });
+
+ this.passenger.spawn(SpigotConversionUtil.fromBukkitLocation(this.bukkitEntity.getLocation()));
+
+ // TODO: Send packet to player if enabled in config
+ }
+
+ public void sendPassengerPacket(Player target) {
+ PacketEvents.getAPI()
+ .getPlayerManager()
+ .sendPacket(target, getPassengersPacket());
+ }
+
+ public PacketWrapper> getPassengersPacket() {
+ return new WrapperPlayServerSetPassengers(bukkitEntity.getEntityId(), new int[]{this.passenger.getEntityId()});
+ }
+
+ public Entity getBukkitEntity() {
+ return bukkitEntity;
+ }
+
+ public WrapperEntity getPassenger() {
+ return passenger;
+ }
+}
diff --git a/src/main/java/com/mattmx/nametags/entity/NameTagEntityManager.java b/src/main/java/com/mattmx/nametags/entity/NameTagEntityManager.java
new file mode 100644
index 0000000..0100e5a
--- /dev/null
+++ b/src/main/java/com/mattmx/nametags/entity/NameTagEntityManager.java
@@ -0,0 +1,36 @@
+package com.mattmx.nametags.entity;
+
+import org.bukkit.entity.Entity;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class NameTagEntityManager {
+ private final ConcurrentHashMap entityMap = new ConcurrentHashMap<>();
+
+ public @NotNull NameTagEntity getOrCreateNameTagEntity(@NotNull Entity entity) {
+ return entityMap.computeIfAbsent(entity.getUniqueId(), (k) -> new NameTagEntity(entity));
+ }
+
+ public @Nullable NameTagEntity removeEntity(@NotNull Entity entity) {
+ return entityMap.remove(entity.getUniqueId());
+ }
+
+ public @Nullable NameTagEntity getNameTagEntity(@NotNull Entity entity) {
+ return entityMap.get(entity.getUniqueId());
+ }
+
+ public @Nullable NameTagEntity getNameTagEntityByUUID(UUID uuid) {
+ return entityMap.get(uuid);
+ }
+
+ public @Nullable NameTagEntity getNameTagEntityById(int entityId) {
+ return entityMap.values()
+ .stream()
+ .filter((e) -> e.getBukkitEntity().getEntityId() == entityId)
+ .findFirst()
+ .orElse(null);
+ }
+}
diff --git a/src/main/kotlin/com/mattmx/template/TemplatePlugin.kt b/src/main/kotlin/com/mattmx/template/TemplatePlugin.kt
deleted file mode 100644
index dc603ac..0000000
--- a/src/main/kotlin/com/mattmx/template/TemplatePlugin.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.mattmx.template
-
-import com.mattmx.ktgui.GuiManager
-import org.bukkit.plugin.java.JavaPlugin
-
-class TemplatePlugin : JavaPlugin() {
-
- override fun onEnable() {
- instance = this
- GuiManager.init(this)
- }
-
- companion object {
- private lateinit var instance: TemplatePlugin
- fun get() = instance
- }
-
-}
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 1932adb..3cb945b 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -4,9 +4,8 @@ version: ${version}
author: ${author}
api-version: 1.17
-softdepend:
- - PlaceholderAPI
- - MCKotlin-Paper
+depend:
+ - packetevents
-libraries:
- - org.jetbrains.kotlin:kotlin-stdlib:2.0.0
\ No newline at end of file
+softdepend:
+ - PlaceholderAPI
\ No newline at end of file