Skip to content

Commit f0c93cc

Browse files
chore: implement Skyblock schematic handling, spawnpoint utils, and velocity plugin integration
1 parent 7e611dd commit f0c93cc

File tree

9 files changed

+291
-38
lines changed

9 files changed

+291
-38
lines changed

surf-event-base/surf-event-base-paper/src/main/kotlin/dev/slne/surf/event/base/paper/PaperRedisLoader.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dev.slne.surf.event.base.paper
22

3+
import dev.slne.surf.event.base.paper.redis.listener.EventServerStateChangeListener
34
import dev.slne.surf.event.base.paper.redis.listener.EventServerStateRequestListener
45
import dev.slne.surf.redis.RedisApi
56

@@ -18,6 +19,7 @@ class PaperRedisLoader {
1819

1920
private fun registerListeners() {
2021
redisApi.registerRequestHandler(EventServerStateRequestListener)
22+
redisApi.subscribeToEvents(EventServerStateChangeListener)
2123
}
2224

2325
fun disconnect() {
Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,12 @@
11
plugins {
2-
kotlin("jvm")
2+
id("dev.slne.surf.surfapi.gradle.velocity")
33
}
44

5-
group = "dev.slne.surf.event"
6-
version = "1.21.11-1.0.0-SNAPSHOT"
7-
8-
repositories {
9-
mavenCentral()
5+
velocityPluginFile {
6+
main = "dev.slne.surf.event.base.velocity.VelocityMain"
7+
authors = listOf("red")
108
}
119

1210
dependencies {
13-
testImplementation(kotlin("test"))
14-
}
15-
16-
kotlin {
17-
jvmToolchain(21)
18-
}
19-
20-
tasks.test {
21-
useJUnitPlatform()
11+
api(project(":surf-event-base:surf-event-base-api:surf-event-base-api-common"))
2212
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package dev.slne.surf.event.base.velocity
2+
3+
class VelocityMain {
4+
}
Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import dev.slne.surf.surfapi.gradle.util.registerRequired
2-
31
plugins {
42
id("dev.slne.surf.surfapi.gradle.paper-plugin")
53
}
@@ -8,23 +6,16 @@ repositories {
86
mavenCentral()
97
}
108

9+
dependencies {
10+
compileOnlyApi(libs.fawe.core)
11+
compileOnlyApi(libs.fawe.bukkit)
12+
}
13+
1114
surfPaperPluginApi {
1215
mainClass("dev.slne.surf.event.oneblock.OneblockSkyblock")
13-
// bootstrapper("dev.slne.surf.event.oneblock.BukkitBootstrap")
1416

1517
generateLibraryLoader(false)
1618
foliaSupported(false)
1719

1820
authors.add("Ammo")
19-
20-
serverDependencies {
21-
registerRequired("surf-event-base")
22-
}
23-
24-
runServer {
25-
minecraftVersion("1.21.4")
26-
27-
downloadPlugins {
28-
}
29-
}
3021
}

surf-event-events/surf-oneblock-skyblock-event/src/main/kotlin/dev/slne/surf/event/oneblock/OneblockSkyblock.kt

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package dev.slne.surf.event.oneblock
22

3+
import com.github.shynixn.mccoroutine.folia.SuspendingJavaPlugin
34
import com.github.shynixn.mccoroutine.folia.entityDispatcher
45
import com.github.shynixn.mccoroutine.folia.registerSuspendingEvents
5-
import dev.slne.surf.event.base.EventPlugin
6-
import dev.slne.surf.event.base.schematic.SchematicPaster
7-
import dev.slne.surf.event.base.world.SpawnpointUtils
8-
import dev.slne.surf.event.base.world.SpawnpointUtils.hasJoinedBefore
6+
import dev.slne.surf.event.oneblock.schematic.SchematicPaster
7+
import dev.slne.surf.event.oneblock.world.SpawnpointUtils
8+
import dev.slne.surf.event.oneblock.world.SpawnpointUtils.hasJoinedBefore
99
import dev.slne.surf.event.oneblock.world.VoidSpawnSchematic
1010
import dev.slne.surf.event.oneblock.world.VoidWorldGenerator
1111
import org.bukkit.Bukkit
@@ -20,20 +20,16 @@ import kotlin.coroutines.CoroutineContext
2020
val oneblockPlugin: OneblockSkyblock
2121
get() = JavaPlugin.getPlugin(OneblockSkyblock::class.java)
2222

23-
class OneblockSkyblock : EventPlugin(), Listener {
23+
class OneblockSkyblock : SuspendingJavaPlugin(), Listener {
2424

2525
lateinit var world: World
2626
lateinit var schematicPaster: SchematicPaster
2727

2828
override suspend fun onLoadAsync() {
29-
super.onLoadAsync()
30-
3129
schematicPaster = SchematicPaster(this)
3230
}
3331

3432
override suspend fun onEnableAsync() {
35-
super.onEnableAsync()
36-
3733
val manager = Bukkit.getPluginManager()
3834
manager.registerSuspendingEvents(this, this, eventDispatcher)
3935

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package dev.slne.surf.event.oneblock.schematic
2+
3+
class SchematicPasteException(message: String, cause: Throwable?) : Exception(message, cause)
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package dev.slne.surf.event.oneblock.schematic
2+
3+
import com.sk89q.worldedit.WorldEdit
4+
import com.sk89q.worldedit.WorldEditException
5+
import com.sk89q.worldedit.bukkit.BukkitAdapter
6+
import com.sk89q.worldedit.extent.clipboard.Clipboard
7+
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats
8+
import com.sk89q.worldedit.function.operation.Operation
9+
import com.sk89q.worldedit.function.operation.Operations
10+
import com.sk89q.worldedit.math.BlockVector3
11+
import com.sk89q.worldedit.session.ClipboardHolder
12+
import com.sk89q.worldedit.world.block.BlockType
13+
import org.bukkit.Location
14+
import org.bukkit.World
15+
import org.bukkit.plugin.java.JavaPlugin
16+
import java.io.File
17+
import java.io.FileInputStream
18+
import java.io.IOException
19+
import java.nio.file.Path
20+
import kotlin.io.path.exists
21+
22+
class SchematicPaster(private val plugin: JavaPlugin) {
23+
24+
fun canPaste(
25+
clipboard: Clipboard,
26+
pasteLocation: Location,
27+
safeList: List<BlockType>
28+
): Boolean {
29+
val adaptedWorld = BukkitAdapter.adapt(pasteLocation.world)
30+
31+
val pasteVector3 = BlockVector3.at(
32+
pasteLocation.x,
33+
pasteLocation.y,
34+
pasteLocation.z
35+
)
36+
37+
for (x in 0..<clipboard.dimensions.x()) {
38+
for (y in 0..<clipboard.dimensions.y()) {
39+
for (z in 0..<clipboard.dimensions.z()) {
40+
val relativePosition = BlockVector3.at(x, y, z)
41+
val worldPosition = pasteVector3.add(relativePosition)
42+
43+
val block = adaptedWorld.getBlock(worldPosition)
44+
45+
if (!safeList.contains(block.blockType)) {
46+
return false
47+
}
48+
49+
if (!pasteLocation.world.worldBorder.isInside(
50+
Location(
51+
pasteLocation.world,
52+
worldPosition.x().toDouble(),
53+
worldPosition.y().toDouble(),
54+
worldPosition.z().toDouble()
55+
)
56+
)
57+
) {
58+
return false
59+
}
60+
}
61+
}
62+
}
63+
64+
return true
65+
}
66+
67+
@Throws(IllegalArgumentException::class, SchematicPasteException::class)
68+
fun readSchematic(schematicName: String): Clipboard {
69+
val pluginDataFolder: Path = plugin.dataPath
70+
val schematicPath = pluginDataFolder.resolve("schematics")
71+
72+
if (!schematicPath.exists()) {
73+
schematicPath.toFile().mkdirs()
74+
}
75+
76+
val schematicFile = File(schematicPath.toFile(), schematicName)
77+
require(schematicFile.exists()) { "Schematic file does not exist." }
78+
79+
val format = ClipboardFormats.findByFile(schematicFile)
80+
requireNotNull(format) { "Schematic file is not a valid format." }
81+
82+
try {
83+
format.getReader(FileInputStream(schematicFile)).use { reader ->
84+
return reader.read()
85+
}
86+
} catch (exception: IOException) {
87+
throw SchematicPasteException("Failed to read schematic.", exception)
88+
} catch (exception: WorldEditException) {
89+
throw SchematicPasteException("Failed to read schematic.", exception)
90+
}
91+
}
92+
93+
fun pasteSchematic(world: World, clipboard: Clipboard, pasteLocation: Location) {
94+
WorldEdit.getInstance().newEditSession(BukkitAdapter.adapt(world)).use { editSession ->
95+
val operation: Operation = ClipboardHolder(clipboard)
96+
.createPaste(editSession)
97+
.to(BlockVector3.at(pasteLocation.x, pasteLocation.y, pasteLocation.z))
98+
.ignoreAirBlocks(false)
99+
.copyEntities(true)
100+
.build()
101+
102+
Operations.complete(operation)
103+
}
104+
}
105+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package dev.slne.surf.event.oneblock.world
2+
3+
import com.github.shynixn.mccoroutine.folia.SuspendingJavaPlugin
4+
import com.github.shynixn.mccoroutine.folia.entityDispatcher
5+
import com.github.shynixn.mccoroutine.folia.launch
6+
import com.jeff_media.morepersistentdatatypes.DataType
7+
import com.sk89q.worldedit.extent.clipboard.Clipboard
8+
import dev.slne.surf.event.oneblock.schematic.SchematicPasteException
9+
import dev.slne.surf.event.oneblock.schematic.SchematicPaster
10+
import dev.slne.surf.surfapi.bukkit.api.util.key
11+
import kotlinx.coroutines.future.await
12+
import kotlinx.coroutines.withContext
13+
import org.bukkit.Location
14+
import org.bukkit.World
15+
import org.bukkit.entity.Player
16+
import org.bukkit.persistence.PersistentDataContainer
17+
import java.util.function.Consumer
18+
19+
object SpawnpointUtils {
20+
21+
private val JOIN_KEY = key("joined")
22+
private val JOIN_LOCATION_KEY = key("joined_location")
23+
24+
fun Player.hasJoinedBefore() = persistentDataContainer.has(JOIN_KEY)
25+
26+
suspend fun generateSpawnpoint(
27+
player: Player,
28+
world: World,
29+
changeDataContainer: Boolean,
30+
schematicPaster: SchematicPaster,
31+
schematic: Clipboard,
32+
plugin: SuspendingJavaPlugin,
33+
generatedSpawnpoint: Consumer<Location?>? = null,
34+
) {
35+
try {
36+
val spawnable = WorldUtils.findSpawnableLocation(
37+
spawnSchematic = schematic,
38+
world = world,
39+
schematicPaster = schematicPaster,
40+
player = player,
41+
plugin = plugin
42+
)
43+
val pdc: PersistentDataContainer = player.persistentDataContainer
44+
45+
schematicPaster.pasteSchematic(world, schematic, spawnable)
46+
47+
val result = runCatching { player.teleportAsync(spawnable).await() }.getOrNull()
48+
49+
if (result == null || !result) {
50+
plugin.launch {
51+
withContext(plugin.entityDispatcher(player)) {
52+
if (changeDataContainer) {
53+
pdc.remove(JOIN_KEY)
54+
}
55+
56+
generatedSpawnpoint?.accept(null)
57+
}
58+
}
59+
60+
throw RuntimeException("Failed to teleport player to spawnpoint.")
61+
}
62+
63+
plugin.launch {
64+
withContext(plugin.entityDispatcher(player)) {
65+
if (changeDataContainer) {
66+
pdc.set(JOIN_KEY, DataType.BOOLEAN, true)
67+
pdc.set(JOIN_LOCATION_KEY, DataType.LOCATION, spawnable)
68+
}
69+
70+
player.setRespawnLocation(spawnable, true)
71+
}
72+
}
73+
74+
generatedSpawnpoint?.accept(spawnable)
75+
} catch (exception: SchematicPasteException) {
76+
throw RuntimeException(exception)
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)