feat: update dependencies
This commit is contained in:
parent
1c809b3def
commit
e324a110e5
|
|
@ -1 +1 @@
|
|||
Subproject commit be85d83428eff52a749747fc495c4bda0e82d035
|
||||
Subproject commit 5535c259494adcd33e659aae9a171c3ebf16e2cf
|
||||
|
|
@ -18,15 +18,14 @@ val exposedVersion = "1.0.0-rc-4"
|
|||
|
||||
dependencies {
|
||||
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
|
||||
compileOnly("org.jetbrains.kotlin:kotlin-stdlib")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0") {
|
||||
exclude(group = "org.jetbrains.kotlin")
|
||||
}
|
||||
paperLibrary("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
|
||||
paperLibrary("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0")
|
||||
compileOnly("com.michael-bull.kotlin-result:kotlin-result:2.1.0")
|
||||
|
||||
compileOnly("net.hareworks.hcu:hcu-core")
|
||||
compileOnly("net.hareworks:kommand-lib")
|
||||
compileOnly("net.hareworks:permits-lib")
|
||||
compileOnly("net.hareworks:GhostDisplays")
|
||||
|
||||
compileOnly("net.kyori:adventure-api:4.25.0")
|
||||
compileOnly("net.kyori:adventure-text-minimessage:4.25.0")
|
||||
|
|
@ -43,9 +42,10 @@ tasks {
|
|||
}
|
||||
shadowJar {
|
||||
archiveClassifier.set("min")
|
||||
minimize()
|
||||
dependencies {
|
||||
exclude(dependency("org.jetbrains.kotlin:kotlin-stdlib"))
|
||||
minimize {
|
||||
exclude(dependency("net.hareworks:GhostDisplays"))
|
||||
exclude(dependency("net.hareworks:kommand-lib"))
|
||||
exclude(dependency("net.hareworks:permits-lib"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -61,6 +61,10 @@ paper {
|
|||
required = true
|
||||
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
|
||||
}
|
||||
register("GhostDisplays") {
|
||||
required = true
|
||||
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
|
||||
}
|
||||
}
|
||||
authors =
|
||||
listOf(
|
||||
|
|
|
|||
2
hcu-core
2
hcu-core
|
|
@ -1 +1 @@
|
|||
Subproject commit 520a378cd5c3da6321305d07cc0b402b73292add
|
||||
Subproject commit e2375c0876de9ba30be24af84d90443ea844a99b
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
rootProject.name = "faction"
|
||||
rootProject.name = "lands"
|
||||
includeBuild("hcu-core")
|
||||
includeBuild("hcu-core/kommand-lib")
|
||||
includeBuild("hcu-core/kommand-lib/permits-lib")
|
||||
|
|
|
|||
|
|
@ -58,6 +58,12 @@ class App : JavaPlugin() {
|
|||
this.playerIdService = pIdService
|
||||
this.actorIdentityService = actorService
|
||||
|
||||
// Load DisplayService (optional dependency)
|
||||
val displayService = server.servicesManager.load(net.hareworks.ghostdisplays.api.DisplayService::class.java)
|
||||
if (displayService == null) {
|
||||
logger.warning("DisplayService not found. Land name displays will not be shown.")
|
||||
}
|
||||
|
||||
// Register public API as a Bukkit service
|
||||
val landsAPI = net.hareworks.hcu.lands.api.LandsAPIImpl(service)
|
||||
server.servicesManager.register(
|
||||
|
|
@ -67,8 +73,10 @@ class App : JavaPlugin() {
|
|||
org.bukkit.plugin.ServicePriority.Normal
|
||||
)
|
||||
|
||||
// Run visualizer every 20 ticks (1 second)
|
||||
server.scheduler.runTaskTimer(this, VisualizerTask(service), 20L, 10L)
|
||||
// Run visualizer every 10 ticks (0.5 seconds)
|
||||
val visualizerTask = VisualizerTask(service, displayService)
|
||||
net.hareworks.hcu.lands.task.LandsVisualizer.setVisualizerTask(visualizerTask)
|
||||
server.scheduler.runTaskTimer(this, visualizerTask, 20L, 10L)
|
||||
|
||||
logger.info("Lands plugin initialized successfully.")
|
||||
logger.info("LandsAPI registered as a Bukkit service.")
|
||||
|
|
|
|||
|
|
@ -99,6 +99,43 @@ data class Land(
|
|||
|
||||
return totalVolume
|
||||
}
|
||||
|
||||
fun getBoundingBox(): net.hareworks.hcu.lands.index.BoundingBox {
|
||||
if (data.parts.isEmpty()) {
|
||||
return net.hareworks.hcu.lands.index.BoundingBox(0, 0, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
var minX = Int.MAX_VALUE
|
||||
var minY = Int.MAX_VALUE
|
||||
var minZ = Int.MAX_VALUE
|
||||
var maxX = Int.MIN_VALUE
|
||||
var maxY = Int.MIN_VALUE
|
||||
var maxZ = Int.MIN_VALUE
|
||||
|
||||
data.parts.forEach { shape ->
|
||||
when (shape) {
|
||||
is Shape.Cuboid -> {
|
||||
minX = minOf(minX, shape.minX())
|
||||
maxX = maxOf(maxX, shape.maxX())
|
||||
minY = minOf(minY, shape.minY())
|
||||
maxY = maxOf(maxY, shape.maxY())
|
||||
minZ = minOf(minZ, shape.minZ())
|
||||
maxZ = maxOf(maxZ, shape.maxZ())
|
||||
}
|
||||
is Shape.Cylinder -> {
|
||||
val r = (shape.radius + 0.5).toInt() + 1
|
||||
minX = minOf(minX, shape.x - r)
|
||||
maxX = maxOf(maxX, shape.x + r)
|
||||
minY = minOf(minY, shape.y - shape.bottomHeight)
|
||||
maxY = maxOf(maxY, shape.y + shape.topHeight)
|
||||
minZ = minOf(minZ, shape.z - r)
|
||||
maxZ = maxOf(maxZ, shape.z + r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return net.hareworks.hcu.lands.index.BoundingBox(minX, minY, minZ, maxX, maxY, maxZ)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
|
|
|
|||
|
|
@ -2,20 +2,32 @@ package net.hareworks.hcu.lands.task
|
|||
|
||||
import net.hareworks.hcu.lands.model.Shape
|
||||
import net.hareworks.hcu.lands.service.LandService
|
||||
import net.hareworks.ghostdisplays.api.DisplayController
|
||||
import net.hareworks.ghostdisplays.api.DisplayService
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.Color
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.Particle
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.entity.TextDisplay
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
object LandsVisualizer {
|
||||
private val enabledPlayers = mutableSetOf<UUID>()
|
||||
private var visualizerTask: VisualizerTask? = null
|
||||
|
||||
fun setVisualizerTask(task: VisualizerTask) {
|
||||
visualizerTask = task
|
||||
}
|
||||
|
||||
fun toggle(player: Player) {
|
||||
if (enabledPlayers.contains(player.uniqueId)) {
|
||||
enabledPlayers.remove(player.uniqueId)
|
||||
visualizerTask?.cleanupDisplaysForPlayer(player.uniqueId)
|
||||
player.sendMessage("Visualization disabled.")
|
||||
} else {
|
||||
enabledPlayers.add(player.uniqueId)
|
||||
|
|
@ -26,7 +38,12 @@ object LandsVisualizer {
|
|||
fun isEnabled(player: Player) = enabledPlayers.contains(player.uniqueId)
|
||||
}
|
||||
|
||||
class VisualizerTask(private val landService: LandService) : Runnable {
|
||||
class VisualizerTask(
|
||||
private val landService: LandService,
|
||||
private val displayService: DisplayService?
|
||||
) : Runnable {
|
||||
private val logger = org.bukkit.Bukkit.getLogger()
|
||||
private val displayControllers = ConcurrentHashMap<UUID, MutableMap<Int, DisplayController<TextDisplay>>>()
|
||||
override fun run() {
|
||||
Bukkit.getOnlinePlayers().forEach { p ->
|
||||
if (LandsVisualizer.isEnabled(p)) {
|
||||
|
|
@ -43,6 +60,30 @@ class VisualizerTask(private val landService: LandService) : Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
// Manage TextDisplays for land names
|
||||
if (displayService != null) {
|
||||
val activeDisplays = displayControllers.getOrPut(p.uniqueId) { mutableMapOf() }
|
||||
val nearbyLandIds = nearbyLands.map { it.id }.toSet()
|
||||
|
||||
// Update displays for nearby lands
|
||||
nearbyLands.forEach { land ->
|
||||
val controller = activeDisplays.getOrPut(land.id) {
|
||||
val newController = createDisplayForLand(p, land)
|
||||
logger.info("[LandsDisplay] Created display for land '${land.name}' (ID: ${land.id}) for player ${p.name}")
|
||||
newController
|
||||
}
|
||||
updateDisplayPosition(controller, p, land)
|
||||
}
|
||||
|
||||
// Remove displays for lands no longer nearby
|
||||
val toRemove = activeDisplays.keys.filter { it !in nearbyLandIds }
|
||||
toRemove.forEach { landId ->
|
||||
activeDisplays[landId]?.destroy()
|
||||
activeDisplays.remove(landId)
|
||||
logger.info("[LandsDisplay] Removed display for land ID $landId for player ${p.name} (out of range)")
|
||||
}
|
||||
}
|
||||
|
||||
nearbyLands.forEach { land ->
|
||||
// Verify that this is the current version of the land
|
||||
val currentLand = landService.getLand(land.id)
|
||||
|
|
@ -162,19 +203,6 @@ class VisualizerTask(private val landService: LandService) : Runnable {
|
|||
|
||||
drawLine(player, x, bottomY, z, x, topY, z, edgeColor, 0.5)
|
||||
}
|
||||
|
||||
// Draw top face outline in red (outer edges only)
|
||||
// Optimized: Calculate outline once for both faces as they share the same XZ shape
|
||||
val faceOutline = cylinder.getOptimizedFaceOutline()
|
||||
val redColor = Particle.DustOptions(Color.RED, 1.0f)
|
||||
val topFaceY = cylinder.y + cylinder.topHeight
|
||||
|
||||
drawFaceOutline(player, faceOutline, topFaceY + 1.0, redColor, cylinder)
|
||||
|
||||
// Draw bottom face outline in red (outer edges only)
|
||||
val bottomFaceY = cylinder.y - cylinder.bottomHeight
|
||||
|
||||
drawFaceOutline(player, faceOutline, bottomFaceY.toDouble(), redColor, cylinder)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -275,4 +303,90 @@ class VisualizerTask(private val landService: LandService) : Runnable {
|
|||
player.spawnParticle(Particle.DUST, x, y, z, 1, 0.0, 0.0, 0.0, dustOptions)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createDisplayForLand(player: Player, land: net.hareworks.hcu.lands.model.Land): DisplayController<TextDisplay> {
|
||||
val position = calculateFaceAttachmentPoint(player, land)
|
||||
val controller = displayService!!.createTextDisplay(position)
|
||||
controller.applyEntityUpdate { display ->
|
||||
display.text(net.kyori.adventure.text.Component.text(land.name))
|
||||
display.billboard = org.bukkit.entity.Display.Billboard.VERTICAL
|
||||
}
|
||||
controller.show(player)
|
||||
logger.info("[LandsDisplay] Display for '${land.name}' made visible to ${player.name} at ${position.blockX}, ${position.blockY}, ${position.blockZ}")
|
||||
return controller
|
||||
}
|
||||
|
||||
private fun updateDisplayPosition(controller: DisplayController<TextDisplay>, player: Player, land: net.hareworks.hcu.lands.model.Land) {
|
||||
val newPosition = calculateFaceAttachmentPoint(player, land)
|
||||
val currentLoc = controller.display.location
|
||||
|
||||
// Only update if position changed significantly (>0.5 blocks)
|
||||
if (currentLoc.distanceSquared(newPosition) > 0.25) {
|
||||
controller.applyEntityUpdate { display ->
|
||||
display.teleport(newPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateFaceAttachmentPoint(player: Player, land: net.hareworks.hcu.lands.model.Land): Location {
|
||||
val bbox = land.getBoundingBox()
|
||||
val px = player.location.x
|
||||
val py = player.location.y
|
||||
val pz = player.location.z
|
||||
|
||||
// Check if player is within XZ footprint
|
||||
val withinX = px >= bbox.minX && px <= bbox.maxX + 1.0
|
||||
val withinZ = pz >= bbox.minZ && pz <= bbox.maxZ + 1.0
|
||||
|
||||
if (withinX && withinZ) {
|
||||
// Player is above or below the land → use top/bottom face
|
||||
return if (py > bbox.maxY + 1.0) {
|
||||
// Attach to top face
|
||||
Location(
|
||||
player.world,
|
||||
px.coerceIn(bbox.minX.toDouble(), bbox.maxX + 1.0),
|
||||
bbox.maxY + 1.1,
|
||||
pz.coerceIn(bbox.minZ.toDouble(), bbox.maxZ + 1.0)
|
||||
)
|
||||
} else {
|
||||
// Attach to bottom face
|
||||
Location(
|
||||
player.world,
|
||||
px.coerceIn(bbox.minX.toDouble(), bbox.maxX + 1.0),
|
||||
bbox.minY - 0.1,
|
||||
pz.coerceIn(bbox.minZ.toDouble(), bbox.maxZ + 1.0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Player is outside XZ footprint → use nearest vertical face
|
||||
val clampedX = px.coerceIn(bbox.minX.toDouble(), bbox.maxX + 1.0)
|
||||
val clampedY = py.coerceIn(bbox.minY.toDouble(), bbox.maxY + 1.0)
|
||||
val clampedZ = pz.coerceIn(bbox.minZ.toDouble(), bbox.maxZ + 1.0)
|
||||
|
||||
// Determine which face is nearest
|
||||
val distToWest = abs(px - bbox.minX)
|
||||
val distToEast = abs(px - (bbox.maxX + 1.0))
|
||||
val distToNorth = abs(pz - bbox.minZ)
|
||||
val distToSouth = abs(pz - (bbox.maxZ + 1.0))
|
||||
|
||||
val minDist = minOf(distToWest, distToEast, distToNorth, distToSouth)
|
||||
|
||||
return when (minDist) {
|
||||
distToWest -> Location(player.world, bbox.minX - 0.1, clampedY, clampedZ)
|
||||
distToEast -> Location(player.world, bbox.maxX + 1.1, clampedY, clampedZ)
|
||||
distToNorth -> Location(player.world, clampedX, clampedY, bbox.minZ - 0.1)
|
||||
else -> Location(player.world, clampedX, clampedY, bbox.maxZ + 1.1)
|
||||
}
|
||||
}
|
||||
|
||||
fun cleanupDisplaysForPlayer(playerId: UUID) {
|
||||
val count = displayControllers[playerId]?.size ?: 0
|
||||
displayControllers[playerId]?.values?.forEach { it.destroy() }
|
||||
displayControllers.remove(playerId)
|
||||
if (count > 0) {
|
||||
val playerName = Bukkit.getPlayer(playerId)?.name ?: playerId.toString()
|
||||
logger.info("[LandsDisplay] Cleaned up $count display(s) for player $playerName")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user