diff options
Diffstat (limited to 'src/main/kotlin/io/dico/parcels2/ParcelWorld.kt')
-rw-r--r-- | src/main/kotlin/io/dico/parcels2/ParcelWorld.kt | 242 |
1 files changed, 49 insertions, 193 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt b/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt index 9a50b31..16f108f 100644 --- a/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt +++ b/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt @@ -1,230 +1,86 @@ package io.dico.parcels2 -import io.dico.parcels2.storage.SerializableParcel -import io.dico.parcels2.storage.SerializableWorld import io.dico.parcels2.storage.Storage import io.dico.parcels2.util.Vec2i -import io.dico.parcels2.util.doAwait import io.dico.parcels2.util.floor -import kotlinx.coroutines.experimental.launch -import org.bukkit.Bukkit import org.bukkit.Location import org.bukkit.World -import org.bukkit.WorldCreator import org.bukkit.block.Block import org.bukkit.entity.Entity -import org.bukkit.entity.Player -import java.util.* -import kotlin.coroutines.experimental.buildIterator -import kotlin.coroutines.experimental.buildSequence -import kotlin.reflect.jvm.javaMethod -import kotlin.reflect.jvm.kotlinFunction +import java.util.UUID -class Worlds(val plugin: ParcelsPlugin) { - val worlds: Map<String, ParcelWorld> get() = _worlds - private val _worlds: MutableMap<String, ParcelWorld> = HashMap() +interface ParcelProvider { + val worlds: Map<String, ParcelWorld> + + fun getWorldById(id: ParcelWorldId): ParcelWorld? + + fun getParcelById(id: ParcelId): Parcel? - fun getWorld(name: String): ParcelWorld? = _worlds[name] + fun getWorld(name: String): ParcelWorld? fun getWorld(world: World): ParcelWorld? = getWorld(world.name) - fun getParcelAt(block: Block): Parcel? = getParcelAt(block.world, block.x, block.z) + fun getWorld(block: Block): ParcelWorld? = getWorld(block.world) + + fun getWorld(loc: Location): ParcelWorld? = getWorld(loc.world) - fun getParcelAt(player: Player): Parcel? = getParcelAt(player.location) + fun getWorld(entity: Entity): ParcelWorld? = getWorld(entity.location) - fun getParcelAt(location: Location): Parcel? = getParcelAt(location.world, location.x.floor(), location.z.floor()) + fun getParcelAt(worldName: String, x: Int, z: Int): Parcel? = getWorld(worldName)?.locator?.getParcelAt(x, z) fun getParcelAt(world: World, x: Int, z: Int): Parcel? = getParcelAt(world.name, x, z) - fun getParcelAt(world: String, x: Int, z: Int): Parcel? { - with(getWorld(world) ?: return null) { - return generator.parcelAt(x, z) - } - } - - init { - val function = ::loadWorlds - function.javaMethod!!.kotlinFunction - } - - operator fun SerializableParcel.invoke(): Parcel? { - return world()?.parcelByID(pos) - } - - operator fun SerializableWorld.invoke(): ParcelWorld? { - return world?.let { getWorld(it) } - } - - fun loadWorlds(options: Options) { - for ((worldName, worldOptions) in options.worlds.entries) { - val world: ParcelWorld - try { - - world = ParcelWorld( - worldName, - worldOptions, - worldOptions.generator.getGenerator(this, worldName), - plugin.storage) - - } catch (ex: Exception) { - ex.printStackTrace() - continue - } - - _worlds.put(worldName, world) - - if (Bukkit.getWorld(worldName) == null) { - plugin.doAwait { - cond = { - try { - // server.getDefaultGameMode() throws an error before any worlds are initialized. - // createWorld() below calls that method. - // Plugin needs to load on STARTUP for generators to be registered correctly. - // Means we need to await the initial worlds getting loaded. - - plugin.server.defaultGameMode; true - } catch (ex: Throwable) { - false - } - } - - onSuccess = { - val bworld = WorldCreator(worldName).generator(world.generator).createWorld() - val spawn = world.generator.getFixedSpawnLocation(bworld, null) - bworld.setSpawnLocation(spawn.x.floor(), spawn.y.floor(), spawn.z.floor()) - } - } - } - - } - - } + fun getParcelAt(world: World, vec: Vec2i): Parcel? = getParcelAt(world, vec.x, vec.z) + + fun getParcelAt(loc: Location): Parcel? = getParcelAt(loc.world, loc.x.floor(), loc.z.floor()) + + fun getParcelAt(entity: Entity): Parcel? = getParcelAt(entity.location) + + fun getParcelAt(block: Block): Parcel? = getParcelAt(block.world, block.x, block.z) + + fun getWorldGenerator(worldName: String): ParcelGenerator? + + fun loadWorlds() } -interface ParcelProvider { +interface ParcelLocator { + val world: World - fun parcelAt(x: Int, z: Int): Parcel? + fun getParcelIdAt(x: Int, z: Int): ParcelId? - fun parcelAt(vec: Vec2i): Parcel? = parcelAt(vec.x, vec.z) + fun getParcelAt(x: Int, z: Int): Parcel? - fun parcelAt(loc: Location): Parcel? = parcelAt(loc.x.floor(), loc.z.floor()) + fun getParcelAt(vec: Vec2i): Parcel? = getParcelAt(vec.x, vec.z) - fun parcelAt(entity: Entity): Parcel? = parcelAt(entity.location) + fun getParcelAt(loc: Location): Parcel? = getParcelAt(loc.x.floor(), loc.z.floor()).takeIf { loc.world == world } - fun parcelAt(block: Block): Parcel? = parcelAt(block.x, block.z) -} + fun getParcelAt(entity: Entity): Parcel? = getParcelAt(entity.location).takeIf { entity.world == world } -class ParcelWorld constructor(val name: String, - val options: WorldOptions, - val generator: ParcelGenerator, - val storage: Storage) : ParcelProvider by generator, ParcelContainer { - val world: World by lazy { - Bukkit.getWorld(name) ?: throw NullPointerException("World $name does not appear to be loaded") - } - val container: ParcelContainer = DefaultParcelContainer(this, storage) - - override fun parcelByID(x: Int, z: Int): Parcel? { - return container.parcelByID(x, z) - } - - override fun nextEmptyParcel(): Parcel? { - return container.nextEmptyParcel() - } - - fun parcelByID(id: Vec2i): Parcel? = parcelByID(id.x, id.z) - - fun enforceOptionsIfApplicable() { - val world = world - val options = options - if (options.dayTime) { - world.setGameRuleValue("doDaylightCycle", "false") - world.setTime(6000) - } - - if (options.noWeather) { - world.setStorm(false) - world.setThundering(false) - world.weatherDuration = Integer.MAX_VALUE - } - - world.setGameRuleValue("doTileDrops", "${options.doTileDrops}") - } + fun getParcelAt(block: Block): Parcel? = getParcelAt(block.x, block.z).takeIf { block.world == world } } +typealias ParcelContainerFactory = (ParcelWorld) -> ParcelContainer + interface ParcelContainer { - fun parcelByID(x: Int, z: Int): Parcel? + fun getParcelById(x: Int, z: Int): Parcel? + + fun getParcelById(id: Vec2i): Parcel? = getParcelById(id.x, id.z) fun nextEmptyParcel(): Parcel? } -typealias ParcelContainerFactory = (ParcelWorld) -> ParcelContainer - -class DefaultParcelContainer(private val world: ParcelWorld, - private val storage: Storage) : ParcelContainer { - private var parcels: Array<Array<Parcel>> - - init { - parcels = initArray(world.options.axisLimit, world) - } - - fun resizeIfSizeChanged() { - if (parcels.size / 2 != world.options.axisLimit) { - resize(world.options.axisLimit) - } - } - - fun resize(axisLimit: Int) { - parcels = initArray(axisLimit, world, this) - } - - fun initArray(axisLimit: Int, world: ParcelWorld, cur: DefaultParcelContainer? = null): Array<Array<Parcel>> { - val arraySize = 2 * axisLimit + 1 - return Array(arraySize) { - val x = it - axisLimit - Array(arraySize) { - val z = it - axisLimit - cur?.parcelByID(x, z) ?: Parcel(world, Vec2i(x, z)) - } - } - } - - override fun parcelByID(x: Int, z: Int): Parcel? { - return parcels.getOrNull(x + world.options.axisLimit)?.getOrNull(z + world.options.axisLimit) - } - - override fun nextEmptyParcel(): Parcel? { - return walkInCircle().find { it.owner == null } - } - - private fun walkInCircle(): Iterable<Parcel> = Iterable { - buildIterator { - val center = world.options.axisLimit - for (radius in 0..center) { - var x = center - radius; var z = center - radius - repeat(radius * 2) { yield(parcels[x++][z]) } - repeat(radius * 2) { yield(parcels[x][z++]) } - repeat(radius * 2) { yield(parcels[x--][z]) } - repeat(radius * 2) { yield(parcels[x][z--]) } - } - } - } - - fun allParcels(): Sequence<Parcel> = buildSequence { - for (array in parcels) { - yieldAll(array.iterator()) - } - } - - fun loadAllData() { - val channel = storage.readParcelData(allParcels(), 100) - launch(storage.asyncDispatcher) { - for ((parcel, data) in channel) { - data?.let { parcel.copyDataIgnoringDatabase(it) } - } - } - } - -}
\ No newline at end of file +interface ParcelWorld : ParcelLocator, ParcelContainer, ParcelBlockManager { + val id: ParcelWorldId + val name: String + val uid: UUID? + val options: WorldOptions + val generator: ParcelGenerator + val storage: Storage + val container: ParcelContainer + val locator: ParcelLocator + val blockManager: ParcelBlockManager + val globalAddedData: GlobalAddedDataManager +} |