summaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/dico/parcels2/ParcelGenerator.kt
blob: 8e7a5df9b56a937b651722fe51730681d44033cb (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
package io.dico.parcels2

import io.dico.parcels2.blockvisitor.RegionTraverser
import io.dico.parcels2.blockvisitor.Worker
import io.dico.parcels2.blockvisitor.WorkerScope
import io.dico.parcels2.blockvisitor.WorktimeLimiter
import io.dico.parcels2.util.Region
import io.dico.parcels2.util.Vec2i
import io.dico.parcels2.util.get
import kotlinx.coroutines.CoroutineScope
import org.bukkit.Chunk
import org.bukkit.Location
import org.bukkit.World
import org.bukkit.block.Biome
import org.bukkit.block.Block
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(worldId: ParcelWorldId,
                                                  container: ParcelContainer,
                                                  coroutineScope: CoroutineScope,
                                                  worktimeLimiter: WorktimeLimiter): Pair<ParcelLocator, ParcelBlockManager>
}

interface ParcelBlockManager {
    val world: World
    val worktimeLimiter: WorktimeLimiter
    val parcelTraverser: RegionTraverser

    // fun getBottomBlock(parcel: ParcelId): Vec2i

    fun getHomeLocation(parcel: ParcelId): Location

    fun getRegion(parcel: ParcelId): Region

    fun getEntities(parcel: ParcelId): Collection<Entity>

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

    fun setBiome(parcel: ParcelId, biome: Biome): Worker

    fun clearParcel(parcel: ParcelId): Worker

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

inline fun ParcelBlockManager.doBlockOperation(parcel: ParcelId,
                                               traverser: RegionTraverser,
                                               crossinline operation: suspend WorkerScope.(Block) -> Unit) = worktimeLimiter.submit {
    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(parcel: ParcelId): Collection<Entity> {
        val region = getRegion(parcel)
        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)
    }

}