Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
javaVersion=25
mcVersion=26.2
group=dev.slne.surf.api
version=3.40.0
version=3.41.0
relocationPrefix=dev.slne.surf.api.libs
snapshot=false
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ interface NmsProvider {
fun createNmsBridge(): InternalNmsBridge
fun createCommonBridge(): SurfPaperNmsCommonBridge
fun createEntityBridge(): SurfPaperNmsEntityBridge
fun createPortalBridge(): SurfPaperNmsPortalBridge
fun createPlayerBridge(): SurfPaperNmsPlayerBridge
fun createItemBridge(): SurfPaperNmsItemBridge
fun createNbtBridge(): SurfPaperNmsNbtBridge
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class V1_21_11NmsProvider(override val plugin: JavaPlugin) : NmsProvider {
override fun createEntityBridge(): SurfPaperNmsEntityBridge =
V1_21_11SurfPaperNmsEntityBridgeImpl()

override fun createPortalBridge(): SurfPaperNmsPortalBridge = V1_21_11SurfPaperNmsPortalBridgeImpl()

override fun createPlayerBridge(): SurfPaperNmsPlayerBridge = V1_21_11SurfPaperNmsPlayerBridgeImpl()
override fun createItemBridge(): SurfPaperNmsItemBridge = V1_21_11SurfPaperNmsItemBridgeImpl()
override fun createNbtBridge(): SurfPaperNmsNbtBridge = V1_21_11SurfPaperNmsNbtBridgeImpl()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges

import ca.spottedleaf.moonrise.common.util.TickThread
import dev.slne.surf.api.paper.nms.NmsUseWithCaution
import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsPortalBridge
import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import org.bukkit.Location
import org.bukkit.World
import kotlin.jvm.optionals.getOrNull

@NmsUseWithCaution
@Suppress("ClassName")
class V1_21_11SurfPaperNmsPortalBridgeImpl : SurfPaperNmsPortalBridge {

override fun findNearestNetherPortal(
world: World,
x: Int,
y: Int,
z: Int,
searchRadius: Int,
minX: Int,
minZ: Int,
maxXExclusive: Int,
maxZExclusive: Int,
): Location? {
val level = world.toNms()
TickThread.ensureTickThread(level, x shr 4, z shr 4, "Cannot search for portals asynchronously")

val found = level.portalForcer
.findClosestPortalPosition(BlockPos(x, y, z), level.worldBorder, searchRadius)
.getOrNull() ?: return null

if (found.x !in minX..<maxXExclusive || found.z !in minZ..<maxZExclusive) {
return null
}

return Location(world, found.x + 0.5, found.y.toDouble(), found.z + 0.5)
}

override fun createNetherPortal(
world: World,
x: Int,
y: Int,
z: Int,
axisX: Boolean,
creationRadius: Int,
): Location? {
val level = world.toNms()
TickThread.ensureTickThread(level, x shr 4, z shr 4, "Cannot create portals asynchronously")

val axis = if (axisX) Direction.Axis.X else Direction.Axis.Z
val rectangle = level.portalForcer
.createPortal(BlockPos(x, y, z), axis, null, creationRadius)
.getOrNull() ?: return null

val corner = rectangle.minCorner
val width = rectangle.axis1Size

return Location(
world,
corner.x + if (axisX) width / 2.0 else 0.5,
corner.y.toDouble(),
corner.z + if (axisX) 0.5 else width / 2.0,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class V26_1NmsProvider(override val plugin: JavaPlugin) : NmsProvider {
V26_1SurfPaperNmsCommonBridgeImpl()

override fun createEntityBridge(): SurfPaperNmsEntityBridge = V26_1SurfPaperNmsEntityBridgeImpl()
override fun createPortalBridge(): SurfPaperNmsPortalBridge = V26_1SurfPaperNmsPortalBridgeImpl()
override fun createPlayerBridge(): SurfPaperNmsPlayerBridge = V26_1SurfPaperNmsPlayerBridgeImpl()
override fun createItemBridge(): SurfPaperNmsItemBridge = V26_1SurfPaperNmsItemBridgeImpl()
override fun createNbtBridge(): SurfPaperNmsNbtBridge = V26_1SurfPaperNmsNbtBridgeImpl()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package dev.slne.surf.api.paper.server.nms.v26_1.bridges

import ca.spottedleaf.moonrise.common.util.TickThread
import dev.slne.surf.api.paper.nms.NmsUseWithCaution
import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsPortalBridge
import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import org.bukkit.Location
import org.bukkit.World
import kotlin.jvm.optionals.getOrNull

@NmsUseWithCaution
@Suppress("ClassName")
class V26_1SurfPaperNmsPortalBridgeImpl : SurfPaperNmsPortalBridge {

override fun findNearestNetherPortal(
world: World,
x: Int,
y: Int,
z: Int,
searchRadius: Int,
minX: Int,
minZ: Int,
maxXExclusive: Int,
maxZExclusive: Int,
): Location? {
val level = world.toNms()
TickThread.ensureTickThread(level, x shr 4, z shr 4, "Cannot search for portals asynchronously")

val found = level.portalForcer
.findClosestPortalPosition(BlockPos(x, y, z), level.worldBorder, searchRadius)
.getOrNull() ?: return null

if (found.x !in minX..<maxXExclusive || found.z !in minZ..<maxZExclusive) {
return null
}

return Location(world, found.x + 0.5, found.y.toDouble(), found.z + 0.5)
}

override fun createNetherPortal(
world: World,
x: Int,
y: Int,
z: Int,
axisX: Boolean,
creationRadius: Int,
): Location? {
val level = world.toNms()
TickThread.ensureTickThread(level, x shr 4, z shr 4, "Cannot create portals asynchronously")

val axis = if (axisX) Direction.Axis.X else Direction.Axis.Z
val rectangle = level.portalForcer
.createPortal(BlockPos(x, y, z), axis, null, creationRadius)
.getOrNull() ?: return null

val corner = rectangle.minCorner
val width = rectangle.axis1Size

return Location(
world,
corner.x + if (axisX) width / 2.0 else 0.5,
corner.y.toDouble(),
corner.z + if (axisX) 0.5 else width / 2.0,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class V26_2NmsProvider(override val plugin: JavaPlugin) : NmsProvider {
V26_2SurfPaperNmsCommonBridgeImpl()

override fun createEntityBridge(): SurfPaperNmsEntityBridge = V26_2SurfPaperNmsEntityBridgeImpl()
override fun createPortalBridge(): SurfPaperNmsPortalBridge = V26_2SurfPaperNmsPortalBridgeImpl()
override fun createPlayerBridge(): SurfPaperNmsPlayerBridge = V26_2SurfPaperNmsPlayerBridgeImpl()
override fun createItemBridge(): SurfPaperNmsItemBridge = V26_2SurfPaperNmsItemBridgeImpl()
override fun createNbtBridge(): SurfPaperNmsNbtBridge = V26_2SurfPaperNmsNbtBridgeImpl()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package dev.slne.surf.api.paper.server.nms.v26_2.bridges

import ca.spottedleaf.moonrise.common.util.TickThread
import dev.slne.surf.api.paper.nms.NmsUseWithCaution
import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsPortalBridge
import dev.slne.surf.api.paper.server.nms.v26_2.extensions.toNms
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import org.bukkit.Location
import org.bukkit.World
import kotlin.jvm.optionals.getOrNull

@NmsUseWithCaution
@Suppress("ClassName")
class V26_2SurfPaperNmsPortalBridgeImpl : SurfPaperNmsPortalBridge {

override fun findNearestNetherPortal(
world: World,
x: Int,
y: Int,
z: Int,
searchRadius: Int,
minX: Int,
minZ: Int,
maxXExclusive: Int,
maxZExclusive: Int,
): Location? {
val level = world.toNms()
TickThread.ensureTickThread(level, x shr 4, z shr 4, "Cannot search for portals asynchronously")

val found = level.portalForcer
.findClosestPortalPosition(BlockPos(x, y, z), level.worldBorder, searchRadius)
.getOrNull() ?: return null

if (found.x !in minX..<maxXExclusive || found.z !in minZ..<maxZExclusive) {
return null
}

return Location(world, found.x + 0.5, found.y.toDouble(), found.z + 0.5)
}

override fun createNetherPortal(
world: World,
x: Int,
y: Int,
z: Int,
axisX: Boolean,
creationRadius: Int,
): Location? {
val level = world.toNms()
TickThread.ensureTickThread(level, x shr 4, z shr 4, "Cannot create portals asynchronously")

val axis = if (axisX) Direction.Axis.X else Direction.Axis.Z
val rectangle = level.portalForcer
.createPortal(BlockPos(x, y, z), axis, null, creationRadius)
.getOrNull() ?: return null

val corner = rectangle.minCorner
val width = rectangle.axis1Size

return Location(
world,
corner.x + if (axisX) width / 2.0 else 0.5,
corner.y.toDouble(),
corner.z + if (axisX) 0.5 else width / 2.0,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package dev.slne.surf.api.paper.server.proxy

import com.google.auto.service.AutoService
import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader
import dev.slne.surf.api.paper.nms.NmsUseWithCaution
import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsPortalBridge
import dev.slne.surf.api.paper.nms.common.NmsProvider

@NmsUseWithCaution
@AutoService(SurfPaperNmsPortalBridge::class)
class SurfPaperNmsPortalBridgeProxy :
SurfPaperNmsPortalBridge by NmsProvider.current.createPortalBridge() {
init { checkInstantiationByServiceLoader() }
}
12 changes: 12 additions & 0 deletions surf-api-paper/surf-api-paper/api/surf-api-paper.api
Original file line number Diff line number Diff line change
Expand Up @@ -1872,6 +1872,18 @@ public final class dev/slne/surf/api/paper/nms/bridges/SurfPaperNmsPlayerBridge$
public fun toString ()Ljava/lang/String;
}

public abstract interface class dev/slne/surf/api/paper/nms/bridges/SurfPaperNmsPortalBridge {
public static final field Companion Ldev/slne/surf/api/paper/nms/bridges/SurfPaperNmsPortalBridge$Companion;
public abstract fun createNetherPortal (Lorg/bukkit/World;IIIZI)Lorg/bukkit/Location;
public abstract fun findNearestNetherPortal (Lorg/bukkit/World;IIIIIIII)Lorg/bukkit/Location;
}

public final class dev/slne/surf/api/paper/nms/bridges/SurfPaperNmsPortalBridge$Companion : dev/slne/surf/api/paper/nms/bridges/SurfPaperNmsPortalBridge {
public fun createNetherPortal (Lorg/bukkit/World;IIIZI)Lorg/bukkit/Location;
public fun findNearestNetherPortal (Lorg/bukkit/World;IIIIIIII)Lorg/bukkit/Location;
public final fun getINSTANCE ()Ldev/slne/surf/api/paper/nms/bridges/SurfPaperNmsPortalBridge;
}

public abstract interface class dev/slne/surf/api/paper/nms/bridges/SurfPaperNmsStatsBridge {
public static final field Companion Ldev/slne/surf/api/paper/nms/bridges/SurfPaperNmsStatsBridge$Companion;
public abstract fun getPlayerStatsAsJson (Lorg/bukkit/entity/Player;)Ljava/lang/String;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package dev.slne.surf.api.paper.nms.bridges

import dev.slne.surf.api.core.util.requiredService
import dev.slne.surf.api.paper.nms.NmsUseWithCaution
import org.bukkit.Location
import org.bukkit.World

@NmsUseWithCaution
interface SurfPaperNmsPortalBridge {

/**
* Finds the nether portal block closest to the given position using the vanilla exit portal
* search (the server's point-of-interest lookup, as run for every regular portal travel).
*
* The result is additionally required to lie within the half-open XZ box
* ([minX]..&lt;[maxXExclusive], [minZ]..&lt;[maxZExclusive]); a closest portal outside the box
* yields `null`. Pass [Int.MIN_VALUE]/[Int.MAX_VALUE] to accept any position.
*
* Must be called from the thread owning the region around the position.
*
* @param searchRadius the horizontal search radius in blocks
* @return the center of the closest portal block, or `null` when none exists or the closest
* one lies outside the box
*/
fun findNearestNetherPortal(
world: World,
x: Int,
y: Int,
z: Int,
searchRadius: Int,
minX: Int,
minZ: Int,
maxXExclusive: Int,
maxZExclusive: Int,
): Location?

/**
* Creates a nether portal near the given position using the vanilla placement algorithm.
*
* A suitable spot is searched within [creationRadius] blocks; when none exists the portal is
* force-created at the position with a small obsidian platform. The
* server fires [org.bukkit.event.world.PortalCreateEvent] with reason `NETHER_PAIR` as part
* of the creation.
*
* Must be called from the thread owning the region around the position.
*
* @param axisX whether the portal is oriented along the X axis
* @return a spawn location centered inside the created portal, or `null` when the creation
* failed or its event was cancelled
*/
fun createNetherPortal(
world: World,
x: Int,
y: Int,
z: Int,
axisX: Boolean,
creationRadius: Int,
): Location?

companion object : SurfPaperNmsPortalBridge by bridge {
val INSTANCE get() = bridge
}
}

@OptIn(NmsUseWithCaution::class)
private val bridge = requiredService<SurfPaperNmsPortalBridge>()