summaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/dico/parcels2/ParcelGenerator.kt
blob: ada6d1272bb1599fa7a70acd40dbb77b48f872bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package io.dico.parcels2

import io.dico.parcels2.blockvisitor.RegionTraverser
import io.dico.parcels2.util.math.Region
import io.dico.parcels2.util.math.Vec2i
import io.dico.parcels2.util.math.Vec3i
import io.dico.parcels2.util.math.get
import kotlinx.coroutines.CoroutineScope
import org.bukkit.Chunk
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.World
import org.bukkit.block.Biome
import org.bukkit.block.Block
import org.bukkit.block.BlockFace
import org.bukkit.entity.Entity
import org.bukkit.generator.BlockPopulator
import org.bukkit.generator.ChunkGenerator
import java.util.Random

abstract class ParcelGenerator : ChunkGenerator() {
    abstract val worldName: String

    abstract val world: World

    abstract override fun generateChunkData(world: World?, random: Random?, chunkX: Int, chunkZ: Int, biome: BiomeGrid?): ChunkData

    abstract fun populate(world: World?, random: Random?, chunk: Chunk?)

    abstract override fun getFixedSpawnLocation(world: World?, random: Random?): Location

    override fun getDefaultPopulators(world: World?): MutableList<BlockPopulator> {
        return mutableListOf(object : BlockPopulator() {
            override fun populate(world: World?, random: Random?, chunk: Chunk?) {
                this@ParcelGenerator.populate(world, random, chunk)
            }
        })
    }

    abstract fun makeParcelLocatorAndBlockManager(
        parcelProvider: ParcelProvider,
        container: ParcelContainer,
        coroutineScope: CoroutineScope,
        jobDispatcher: JobDispatcher
    ): Pair<ParcelLocator, ParcelBlockManager>
}

interface ParcelBlockManager {
    val world: World
    val jobDispatcher: JobDispatcher
    val parcelTraverser: RegionTraverser

    fun getRegionOrigin(parcel: ParcelId) = getRegion(parcel).origin.toVec2i()

    fun getHomeLocation(parcel: ParcelId): Location

    fun getRegion(parcel: ParcelId): Region

    fun getEntities(region: Region): Collection<Entity>

    fun isParcelInfoSectionLoaded(parcel: ParcelId): Boolean

    fun updateParcelInfo(parcel: ParcelId, owner: PlayerProfile?)

    fun getParcelForInfoBlockInteraction(block: Vec3i, type: Material, face: BlockFace): Parcel?

    fun setBiome(parcel: ParcelId, biome: Biome): Job?

    fun clearParcel(parcel: ParcelId): Job?

    /**
     * Used to update owner blocks in the corner of the parcel
     */
    fun getParcelsWithOwnerBlockIn(chunk: Chunk): Collection<Vec2i>
}

inline fun ParcelBlockManager.tryDoBlockOperation(
    parcelProvider: ParcelProvider,
    parcel: ParcelId,
    traverser: RegionTraverser,
    crossinline operation: suspend JobScope.(Block) -> Unit
) = parcelProvider.trySubmitBlockVisitor(Permit(), arrayOf(parcel)) {
    val region = getRegion(parcel)
    val blockCount = region.blockCount.toDouble()
    val blocks = traverser.traverseRegion(region)
    for ((index, vec) in blocks.withIndex()) {
        markSuspensionPoint()
        operation(world[vec])
        setProgress((index + 1) / blockCount)
    }
}

abstract class ParcelBlockManagerBase : ParcelBlockManager {

    override fun getEntities(region: Region): Collection<Entity> {
        val center = region.center
        val centerLoc = Location(world, center.x, center.y, center.z)
        val centerDist = (center - region.origin).add(0.2, 0.2, 0.2)
        return world.getNearbyEntities(centerLoc, centerDist.x, centerDist.y, centerDist.z)
    }

}