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

import io.dico.parcels2.blockvisitor.*
import io.dico.parcels2.util.math.Region
import io.dico.parcels2.util.math.Vec2i
import io.dico.parcels2.util.math.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,
                                                  jobDispatcher: JobDispatcher): Pair<ParcelLocator, ParcelBlockManager>
}

interface ParcelBlockManager {
    val world: World
    val jobDispatcher: JobDispatcher
    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): Job

    fun clearParcel(parcel: ParcelId): Job

    fun swapParcels(parcel1: ParcelId, parcel2: ParcelId): Job

    fun submitBlockVisitor(vararg parcelIds: ParcelId, task: JobFunction): Job

    /**
     * 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 JobScope.(Block) -> Unit) = submitBlockVisitor(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(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)
    }

}