diff options
author | Dico <dico.karssiens@gmail.com> | 2018-09-27 07:03:02 +0100 |
---|---|---|
committer | Dico <dico.karssiens@gmail.com> | 2018-09-27 07:03:02 +0100 |
commit | 842e52bd92f0c67aa1906b899ce600ecb3b26bda (patch) | |
tree | f0e03e66ba0dfeb8d3aee58a09acd6889f5ee20e /src | |
parent | 307b7aee4af34e47139259db7049a85c682b7be2 (diff) |
Fixes n tweaks
Diffstat (limited to 'src')
33 files changed, 393 insertions, 242 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/Interactable.kt b/src/main/kotlin/io/dico/parcels2/Interactable.kt index 100e433..825be94 100644 --- a/src/main/kotlin/io/dico/parcels2/Interactable.kt +++ b/src/main/kotlin/io/dico/parcels2/Interactable.kt @@ -1,6 +1,6 @@ package io.dico.parcels2 -import io.dico.parcels2.util.ext.ceilDiv +import io.dico.parcels2.util.math.ext.ceilDiv import io.dico.parcels2.util.ext.getMaterialsWithWoodTypePrefix import org.bukkit.Material import java.util.EnumMap diff --git a/src/main/kotlin/io/dico/parcels2/Parcel.kt b/src/main/kotlin/io/dico/parcels2/Parcel.kt index 22ec0df..517b88f 100644 --- a/src/main/kotlin/io/dico/parcels2/Parcel.kt +++ b/src/main/kotlin/io/dico/parcels2/Parcel.kt @@ -1,6 +1,6 @@ package io.dico.parcels2 -import io.dico.parcels2.util.Vec2i +import io.dico.parcels2.util.math.Vec2i import org.bukkit.Location import org.joda.time.DateTime import java.util.UUID diff --git a/src/main/kotlin/io/dico/parcels2/ParcelGenerator.kt b/src/main/kotlin/io/dico/parcels2/ParcelGenerator.kt index 4e0aeb4..d45ff83 100644 --- a/src/main/kotlin/io/dico/parcels2/ParcelGenerator.kt +++ b/src/main/kotlin/io/dico/parcels2/ParcelGenerator.kt @@ -1,9 +1,9 @@ package io.dico.parcels2 import io.dico.parcels2.blockvisitor.* -import io.dico.parcels2.util.Region -import io.dico.parcels2.util.Vec2i -import io.dico.parcels2.util.get +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 @@ -37,12 +37,12 @@ abstract class ParcelGenerator : ChunkGenerator() { abstract fun makeParcelLocatorAndBlockManager(worldId: ParcelWorldId, container: ParcelContainer, coroutineScope: CoroutineScope, - workDispatcher: WorkDispatcher): Pair<ParcelLocator, ParcelBlockManager> + jobDispatcher: JobDispatcher): Pair<ParcelLocator, ParcelBlockManager> } interface ParcelBlockManager { val world: World - val workDispatcher: WorkDispatcher + val jobDispatcher: JobDispatcher val parcelTraverser: RegionTraverser // fun getBottomBlock(parcel: ParcelId): Vec2i @@ -55,13 +55,13 @@ interface ParcelBlockManager { fun setOwnerBlock(parcel: ParcelId, owner: PlayerProfile?) - fun setBiome(parcel: ParcelId, biome: Biome): Worker + fun setBiome(parcel: ParcelId, biome: Biome): Job - fun clearParcel(parcel: ParcelId): Worker + fun clearParcel(parcel: ParcelId): Job - fun swapParcels(parcel1: ParcelId, parcel2: ParcelId): Worker + fun swapParcels(parcel1: ParcelId, parcel2: ParcelId): Job - fun submitBlockVisitor(vararg parcelIds: ParcelId, task: WorkerTask): Worker + fun submitBlockVisitor(vararg parcelIds: ParcelId, task: JobFunction): Job /** * Used to update owner blocks in the corner of the parcel @@ -71,7 +71,7 @@ interface ParcelBlockManager { inline fun ParcelBlockManager.doBlockOperation(parcel: ParcelId, traverser: RegionTraverser, - crossinline operation: suspend WorkerScope.(Block) -> Unit) = submitBlockVisitor(parcel) { + crossinline operation: suspend JobScope.(Block) -> Unit) = submitBlockVisitor(parcel) { val region = getRegion(parcel) val blockCount = region.blockCount.toDouble() val blocks = traverser.traverseRegion(region) diff --git a/src/main/kotlin/io/dico/parcels2/ParcelId.kt b/src/main/kotlin/io/dico/parcels2/ParcelId.kt index 72eceb9..926fc23 100644 --- a/src/main/kotlin/io/dico/parcels2/ParcelId.kt +++ b/src/main/kotlin/io/dico/parcels2/ParcelId.kt @@ -1,6 +1,6 @@ package io.dico.parcels2 -import io.dico.parcels2.util.Vec2i +import io.dico.parcels2.util.math.Vec2i import org.bukkit.Bukkit import org.bukkit.World import java.util.UUID diff --git a/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt b/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt index 1e9dc44..87e4c68 100644 --- a/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt +++ b/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt @@ -2,8 +2,8 @@ package io.dico.parcels2 import io.dico.parcels2.options.RuntimeWorldOptions import io.dico.parcels2.storage.Storage -import io.dico.parcels2.util.Vec2i -import io.dico.parcels2.util.ext.floor +import io.dico.parcels2.util.math.Vec2i +import io.dico.parcels2.util.math.ext.floor import org.bukkit.Location import org.bukkit.World import org.bukkit.block.Block diff --git a/src/main/kotlin/io/dico/parcels2/ParcelsPlugin.kt b/src/main/kotlin/io/dico/parcels2/ParcelsPlugin.kt index 7af7468..b1bf554 100644 --- a/src/main/kotlin/io/dico/parcels2/ParcelsPlugin.kt +++ b/src/main/kotlin/io/dico/parcels2/ParcelsPlugin.kt @@ -3,8 +3,8 @@ package io.dico.parcels2 import io.dico.dicore.Registrator import io.dico.dicore.command.EOverridePolicy import io.dico.dicore.command.ICommandDispatcher -import io.dico.parcels2.blockvisitor.BukkitWorkDispatcher -import io.dico.parcels2.blockvisitor.WorkDispatcher +import io.dico.parcels2.blockvisitor.BukkitJobDispatcher +import io.dico.parcels2.blockvisitor.JobDispatcher import io.dico.parcels2.command.getParcelCommands import io.dico.parcels2.defaultimpl.GlobalPrivilegesManagerImpl import io.dico.parcels2.defaultimpl.ParcelProviderImpl @@ -44,7 +44,7 @@ class ParcelsPlugin : JavaPlugin(), CoroutineScope, PluginScheduler { override val coroutineContext: CoroutineContext = MainThreadDispatcher(this) override val plugin: Plugin get() = this - val workDispatcher: WorkDispatcher by lazy { BukkitWorkDispatcher(this, options.tickWorktime) } + val jobDispatcher: JobDispatcher by lazy { BukkitJobDispatcher(this, options.tickJobtime) } override fun onEnable() { plogger.info("Debug enabled: ${plogger.isDebugEnabled}") @@ -55,11 +55,11 @@ class ParcelsPlugin : JavaPlugin(), CoroutineScope, PluginScheduler { } override fun onDisable() { - val hasWorkers = workDispatcher.workers.isNotEmpty() + val hasWorkers = jobDispatcher.jobs.isNotEmpty() if (hasWorkers) { - plogger.warn("Parcels is attempting to complete all ${workDispatcher.workers.size} remaining jobs before shutdown...") + plogger.warn("Parcels is attempting to complete all ${jobDispatcher.jobs.size} remaining jobs before shutdown...") } - workDispatcher.completeAllTasks() + jobDispatcher.completeAllTasks() if (hasWorkers) { plogger.info("Parcels has completed the remaining jobs.") } diff --git a/src/main/kotlin/io/dico/parcels2/Privilege.kt b/src/main/kotlin/io/dico/parcels2/Privilege.kt index bc16f77..7949dbc 100644 --- a/src/main/kotlin/io/dico/parcels2/Privilege.kt +++ b/src/main/kotlin/io/dico/parcels2/Privilege.kt @@ -66,7 +66,7 @@ interface RawPrivileges { open class PrivilegesHolder(override var privilegeMap: MutablePrivilegeMap = EmptyPrivilegeMap) : RawPrivileges { private var _privilegeOfStar: Privilege = DEFAULT - override var privilegeOfStar: Privilege + override /*open*/ var privilegeOfStar: Privilege get() = _privilegeOfStar set(value) = run { _privilegeOfStar = value } @@ -94,5 +94,10 @@ open class PrivilegesHolder(override var privilegeMap: MutablePrivilegeMap = Emp return if (privilege == DEFAULT) privilegeMap.remove(key) != null else privilegeMap.put(key, privilege) != privilege } + + fun copyPrivilegesFrom(other: PrivilegesHolder) { + privilegeMap = other.privilegeMap + privilegeOfStar = other.privilegeOfStar + } } diff --git a/src/main/kotlin/io/dico/parcels2/blockvisitor/Attachables.kt b/src/main/kotlin/io/dico/parcels2/blockvisitor/Attachables.kt index f5b7ad8..8f2c565 100644 --- a/src/main/kotlin/io/dico/parcels2/blockvisitor/Attachables.kt +++ b/src/main/kotlin/io/dico/parcels2/blockvisitor/Attachables.kt @@ -1,6 +1,6 @@ package io.dico.parcels2.blockvisitor -import io.dico.parcels2.util.Vec3i +import io.dico.parcels2.util.math.Vec3i import io.dico.parcels2.util.ext.getMaterialsWithWoodTypePrefix import io.dico.parcels2.util.ext.getMaterialsWithWoolColorPrefix import org.bukkit.Material diff --git a/src/main/kotlin/io/dico/parcels2/blockvisitor/WorkDispatcher.kt b/src/main/kotlin/io/dico/parcels2/blockvisitor/JobDispatcher.kt index 7162561..702a680 100644 --- a/src/main/kotlin/io/dico/parcels2/blockvisitor/WorkDispatcher.kt +++ b/src/main/kotlin/io/dico/parcels2/blockvisitor/JobDispatcher.kt @@ -2,11 +2,11 @@ package io.dico.parcels2.blockvisitor import io.dico.parcels2.ParcelsPlugin import io.dico.parcels2.logger -import io.dico.parcels2.util.ext.clampMin +import io.dico.parcels2.util.math.ext.clampMin import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart.LAZY -import kotlinx.coroutines.Job +import kotlinx.coroutines.Job as CoroutineJob import kotlinx.coroutines.launch import org.bukkit.scheduler.BukkitTask import java.lang.System.currentTimeMillis @@ -16,21 +16,21 @@ import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.coroutines.resume -typealias WorkerTask = suspend WorkerScope.() -> Unit -typealias WorkerUpdateLister = Worker.(Double, Long) -> Unit +typealias JobFunction = suspend JobScope.() -> Unit +typealias JobUpdateLister = Job.(Double, Long) -> Unit -data class TickWorktimeOptions(var workTime: Int, var tickInterval: Int) +data class TickJobtimeOptions(var jobTime: Int, var tickInterval: Int) -interface WorkDispatcher { +interface JobDispatcher { /** * Submit a [task] that should be run synchronously, but limited such that it does not stall the server */ - fun dispatch(task: WorkerTask): Worker + fun dispatch(task: JobFunction): Job /** - * Get a list of all workers + * Get a list of all jobs */ - val workers: List<Worker> + val jobs: List<Job> /** * Attempts to complete any remaining tasks immediately, without suspension. @@ -38,27 +38,27 @@ interface WorkDispatcher { fun completeAllTasks() } -interface WorkerAndScopeMembersUnion { +interface JobAndScopeMembersUnion { /** - * The time that elapsed since this worker was dispatched, in milliseconds + * The time that elapsed since this job was dispatched, in milliseconds */ val elapsedTime: Long /** - * A value indicating the progress of this worker, in the range 0.0 <= progress <= 1.0 + * A value indicating the progress of this job, in the range 0.0 <= progress <= 1.0 * with no guarantees to its accuracy. */ val progress: Double } -interface Worker : WorkerAndScopeMembersUnion { +interface Job : JobAndScopeMembersUnion { /** - * The coroutine associated with this worker + * The coroutine associated with this job */ - val job: Job + val job: CoroutineJob /** - * true if this worker has completed + * true if this job has completed */ val isComplete: Boolean @@ -69,28 +69,28 @@ interface Worker : WorkerAndScopeMembersUnion { val completionException: Throwable? /** - * Calls the given [block] whenever the progress of this worker is updated, + * Calls the given [block] whenever the progress of this job is updated, * if [minInterval] milliseconds expired since the last call. * The first call occurs after at least [minDelay] milliseconds in a likewise manner. * Repeated invocations of this method result in an [IllegalStateException] * * if [asCompletionListener] is true, [onCompleted] is called with the same [block] */ - fun onProgressUpdate(minDelay: Int, minInterval: Int, asCompletionListener: Boolean = true, block: WorkerUpdateLister): Worker + fun onProgressUpdate(minDelay: Int, minInterval: Int, asCompletionListener: Boolean = true, block: JobUpdateLister): Job /** - * Calls the given [block] when this worker completes, with the progress value 1.0. + * Calls the given [block] when this job completes, with the progress value 1.0. * Multiple listeners may be registered to this function. */ - fun onCompleted(block: WorkerUpdateLister): Worker + fun onCompleted(block: JobUpdateLister): Job /** - * Await completion of this worker + * Await completion of this job */ suspend fun awaitCompletion() } -interface WorkerScope : WorkerAndScopeMembersUnion { +interface JobScope : JobAndScopeMembersUnion { /** * A task should call this frequently during its execution, such that the timer can suspend it when necessary. */ @@ -107,29 +107,29 @@ interface WorkerScope : WorkerAndScopeMembersUnion { fun markComplete() = setProgress(1.0) /** - * Get a [WorkerScope] that is responsible for [portion] part of the progress + * Get a [JobScope] that is responsible for [portion] part of the progress * If [portion] is negative, the remaining progress is used */ - fun delegateWork(portion: Double = -1.0): WorkerScope + fun delegateProgress(portion: Double = -1.0): JobScope } -inline fun <T> WorkerScope.delegateWork(portion: Double = -1.0, block: WorkerScope.() -> T): T { - delegateWork(portion).apply { +inline fun <T> JobScope.delegateWork(portion: Double = -1.0, block: JobScope.() -> T): T { + delegateProgress(portion).apply { val result = block() markComplete() return result } } -interface WorkerInternal : Worker, WorkerScope { +interface JobInternal : Job, JobScope { /** - * Start or resumes the execution of this worker - * and returns true if the worker completed + * Start or resumes the execution of this job + * and returns true if the job completed * * [worktime] is the maximum amount of time, in milliseconds, * that this job may run for until suspension. * - * If [worktime] is not positive, the worker will complete + * If [worktime] is not positive, the job will complete * without suspension and this method will always return true. */ fun resume(worktime: Long): Boolean @@ -137,68 +137,68 @@ interface WorkerInternal : Worker, WorkerScope { /** * An object that controls one or more jobs, ensuring that they don't stall the server too much. - * There is a configurable maxiumum amount of milliseconds that can be allocated to all workers together in each server tick + * There is a configurable maxiumum amount of milliseconds that can be allocated to all jobs together in each server tick * This object attempts to split that maximum amount of milliseconds equally between all jobs */ -class BukkitWorkDispatcher(private val plugin: ParcelsPlugin, var options: TickWorktimeOptions) : WorkDispatcher { +class BukkitJobDispatcher(private val plugin: ParcelsPlugin, var options: TickJobtimeOptions) : JobDispatcher { // The currently registered bukkit scheduler task private var bukkitTask: BukkitTask? = null - // The workers. - private val _workers = LinkedList<WorkerInternal>() - override val workers: List<Worker> = _workers + // The jobs. + private val _jobs = LinkedList<JobInternal>() + override val jobs: List<Job> = _jobs - override fun dispatch(task: WorkerTask): Worker { - val worker: WorkerInternal = WorkerImpl(plugin, task) + override fun dispatch(task: JobFunction): Job { + val job: JobInternal = JobImpl(plugin, task) if (bukkitTask == null) { - val completed = worker.resume(options.workTime.toLong()) - if (completed) return worker - bukkitTask = plugin.scheduleRepeating(0, options.tickInterval) { tickJobs() } + val completed = job.resume(options.jobTime.toLong()) + if (completed) return job + bukkitTask = plugin.scheduleRepeating(0, options.tickInterval) { tickCoroutineJobs() } } - _workers.addFirst(worker) - return worker + _jobs.addFirst(job) + return job } - private fun tickJobs() { - val workers = _workers - if (workers.isEmpty()) return + private fun tickCoroutineJobs() { + val jobs = _jobs + if (jobs.isEmpty()) return val tickStartTime = System.currentTimeMillis() - val iterator = workers.listIterator(index = 0) + val iterator = jobs.listIterator(index = 0) while (iterator.hasNext()) { val time = System.currentTimeMillis() val timeElapsed = time - tickStartTime - val timeLeft = options.workTime - timeElapsed + val timeLeft = options.jobTime - timeElapsed if (timeLeft <= 0) return - val count = workers.size - iterator.nextIndex() + val count = jobs.size - iterator.nextIndex() val timePerJob = (timeLeft + count - 1) / count - val worker = iterator.next() - val completed = worker.resume(timePerJob) + val job = iterator.next() + val completed = job.resume(timePerJob) if (completed) { iterator.remove() } } - if (workers.isEmpty()) { + if (jobs.isEmpty()) { bukkitTask?.cancel() bukkitTask = null } } override fun completeAllTasks() { - _workers.forEach { + _jobs.forEach { it.resume(-1) } - _workers.clear() + _jobs.clear() bukkitTask?.cancel() bukkitTask = null } } -private class WorkerImpl(scope: CoroutineScope, task: WorkerTask) : WorkerInternal { - override val job: Job = scope.launch(start = LAZY) { task() } +private class JobImpl(scope: CoroutineScope, task: JobFunction) : JobInternal { + override val job: CoroutineJob = scope.launch(start = LAZY) { task() } private var continuation: Continuation<Unit>? = null private var nextSuspensionTime: Long = 0L @@ -217,17 +217,17 @@ private class WorkerImpl(scope: CoroutineScope, task: WorkerTask) : WorkerIntern override var completionException: Throwable? = null; private set private var startTimeOrElapsedTime: Long = 0L // startTime before completed, elapsed time otherwise - private var onProgressUpdate: WorkerUpdateLister? = null + private var onProgressUpdate: JobUpdateLister? = null private var progressUpdateInterval: Int = 0 private var lastUpdateTime: Long = 0L - private var onCompleted: WorkerUpdateLister? = null + private var onCompleted: JobUpdateLister? = null init { job.invokeOnCompletion { exception -> // report any error that occurred completionException = exception?.also { if (it !is CancellationException) - logger.error("WorkerTask generated an exception", it) + logger.error("JobFunction generated an exception", it) } // convert to elapsed time here @@ -239,7 +239,7 @@ private class WorkerImpl(scope: CoroutineScope, task: WorkerTask) : WorkerIntern } } - override fun onProgressUpdate(minDelay: Int, minInterval: Int, asCompletionListener: Boolean, block: WorkerUpdateLister): Worker { + override fun onProgressUpdate(minDelay: Int, minInterval: Int, asCompletionListener: Boolean, block: JobUpdateLister): Job { onProgressUpdate?.let { throw IllegalStateException() } if (asCompletionListener) onCompleted(block) if (isComplete) return this @@ -250,7 +250,7 @@ private class WorkerImpl(scope: CoroutineScope, task: WorkerTask) : WorkerIntern return this } - override fun onCompleted(block: WorkerUpdateLister): Worker { + override fun onCompleted(block: JobUpdateLister): Job { if (isComplete) { block(1.0, startTimeOrElapsedTime) return this @@ -260,7 +260,7 @@ private class WorkerImpl(scope: CoroutineScope, task: WorkerTask) : WorkerIntern onCompleted = if (cur == null) { block } else { - fun Worker.(prog: Double, el: Long) { + fun Job.(prog: Double, el: Long) { cur(prog, el) block(prog, el) } @@ -315,25 +315,25 @@ private class WorkerImpl(scope: CoroutineScope, task: WorkerTask) : WorkerIntern job.join() } - private fun delegateWork(curPortion: Double, portion: Double): WorkerScope = + private fun delegateProgress(curPortion: Double, portion: Double): JobScope = DelegateScope(progress, curPortion * (if (portion < 0) 1.0 - progress else portion).clampMin(0.0)) - override fun delegateWork(portion: Double): WorkerScope = delegateWork(1.0, portion) + override fun delegateProgress(portion: Double): JobScope = delegateProgress(1.0, portion) - private inner class DelegateScope(val progressStart: Double, val portion: Double) : WorkerScope { + private inner class DelegateScope(val progressStart: Double, val portion: Double) : JobScope { override val elapsedTime: Long - get() = this@WorkerImpl.elapsedTime + get() = this@JobImpl.elapsedTime override suspend fun markSuspensionPoint() = - this@WorkerImpl.markSuspensionPoint() + this@JobImpl.markSuspensionPoint() override val progress: Double - get() = (this@WorkerImpl.progress - progressStart) / portion + get() = (this@JobImpl.progress - progressStart) / portion override fun setProgress(progress: Double) = - this@WorkerImpl.setProgress(progressStart + progress * portion) + this@JobImpl.setProgress(progressStart + progress * portion) - override fun delegateWork(portion: Double): WorkerScope = - this@WorkerImpl.delegateWork(this.portion, portion) + override fun delegateProgress(portion: Double): JobScope = + this@JobImpl.delegateProgress(this.portion, portion) } } diff --git a/src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt b/src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt index feab318..bd00407 100644 --- a/src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt +++ b/src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt @@ -1,8 +1,9 @@ package io.dico.parcels2.blockvisitor -import io.dico.parcels2.util.Region -import io.dico.parcels2.util.Vec3i -import io.dico.parcels2.util.ext.clampMax +import io.dico.parcels2.util.math.Dimension +import io.dico.parcels2.util.math.Region +import io.dico.parcels2.util.math.Vec3i +import io.dico.parcels2.util.math.ext.clampMax private typealias Scope = SequenceScope<Vec3i> @@ -54,9 +55,9 @@ sealed class RegionTraverser { val (primary, secondary, tertiary) = order.toArray() val (origin, size) = region - val maxOfPrimary = primary.extract(size) - 1 - val maxOfSecondary = secondary.extract(size) - 1 - val maxOfTertiary = tertiary.extract(size) - 1 + val maxOfPrimary = size[primary] - 1 + val maxOfSecondary = size[secondary] - 1 + val maxOfTertiary = size[tertiary] - 1 val isPrimaryIncreasing = direction.isIncreasing(primary) val isSecondaryIncreasing = direction.isIncreasing(secondary) @@ -137,24 +138,6 @@ sealed class RegionTraverser { } -enum class Dimension { - X, - Y, - Z; - - fun extract(block: Vec3i) = - when (this) { - X -> block.x - Y -> block.y - Z -> block.z - } - - companion object { - private val values = values() - operator fun get(ordinal: Int) = values[ordinal] - } -} - object TraverseOrderFactory { private fun isSwap(primary: Dimension, secondary: Dimension) = secondary.ordinal != (primary.ordinal + 1) % 3 @@ -194,15 +177,15 @@ inline class TraverseOrder(val orderNum: Int) { */ fun toArray() = arrayOf(primary, secondary, tertiary) - fun add(vec: Vec3i, dp: Int, ds: Int, dt: Int): Vec3i = + fun add(vec: Vec3i, p: Int, s: Int, t: Int): Vec3i = // optimize this, will be called lots when (orderNum) { - 0 -> vec.add(dp, ds, dt) // xyz - 1 -> vec.add(dt, dp, ds) // yzx - 2 -> vec.add(ds, dt, dp) // zxy - 3 -> vec.add(dp, dt, ds) // xzy - 4 -> vec.add(ds, dp, dt) // yxz - 5 -> vec.add(dt, ds, dp) // zyx + 0 -> vec.add(p, s, t) // xyz + 1 -> vec.add(t, p, s) // yzx + 2 -> vec.add(s, t, p) // zxy + 3 -> vec.add(p, t, s) // xzy + 4 -> vec.add(s, p, t) // yxz + 5 -> vec.add(t, s, p) // zyx else -> error("Invalid orderNum $orderNum") } } @@ -212,9 +195,9 @@ inline class TraverseDirection(val bits: Int) { fun comesFirst(current: Vec3i, block: Vec3i, dimension: Dimension): Boolean = if (isIncreasing(dimension)) - dimension.extract(block) <= dimension.extract(current) + block[dimension] <= current[dimension] else - dimension.extract(block) >= dimension.extract(current) + block[dimension] >= current[dimension] fun comesFirst(current: Vec3i, block: Vec3i) = comesFirst(current, block, Dimension.X) diff --git a/src/main/kotlin/io/dico/parcels2/blockvisitor/Schematic.kt b/src/main/kotlin/io/dico/parcels2/blockvisitor/Schematic.kt index 9f88fd9..84931b2 100644 --- a/src/main/kotlin/io/dico/parcels2/blockvisitor/Schematic.kt +++ b/src/main/kotlin/io/dico/parcels2/blockvisitor/Schematic.kt @@ -1,8 +1,8 @@ package io.dico.parcels2.blockvisitor -import io.dico.parcels2.util.Region -import io.dico.parcels2.util.Vec3i -import io.dico.parcels2.util.get +import io.dico.parcels2.util.math.Region +import io.dico.parcels2.util.math.Vec3i +import io.dico.parcels2.util.math.get import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.World @@ -24,7 +24,7 @@ class Schematic { private var isLoaded = false; private set private val traverser: RegionTraverser = RegionTraverser.upward - suspend fun WorkerScope.load(world: World, region: Region) { + suspend fun JobScope.load(world: World, region: Region) { _size = region.size val data = arrayOfNulls<BlockData>(region.blockCount).also { blockDatas = it } @@ -52,7 +52,7 @@ class Schematic { isLoaded = true } - suspend fun WorkerScope.paste(world: World, position: Vec3i) { + suspend fun JobScope.paste(world: World, position: Vec3i) { if (!isLoaded) throw IllegalStateException() val region = Region(position, _size!!) @@ -108,11 +108,11 @@ class Schematic { } } - fun getLoadTask(world: World, region: Region): WorkerTask = { + fun getLoadTask(world: World, region: Region): JobFunction = { load(world, region) } - fun getPasteTask(world: World, position: Vec3i): WorkerTask = { + fun getPasteTask(world: World, position: Vec3i): JobFunction = { paste(world, position) } diff --git a/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt b/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt index 79faf36..41f5d36 100644 --- a/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt +++ b/src/main/kotlin/io/dico/parcels2/command/AbstractParcelCommands.kt @@ -6,7 +6,7 @@ import io.dico.parcels2.ParcelsPlugin import io.dico.parcels2.PlayerProfile import io.dico.parcels2.PlayerProfile.* import io.dico.parcels2.PrivilegeKey -import io.dico.parcels2.blockvisitor.Worker +import io.dico.parcels2.blockvisitor.Job import io.dico.parcels2.util.ext.hasPermAdminManage import io.dico.parcels2.util.ext.parcelLimit import org.bukkit.entity.Player @@ -50,7 +50,7 @@ abstract class AbstractParcelCommands(val plugin: ParcelsPlugin) : ICommandRecei world.blockManager.clearParcel(parcel.id) } - protected fun Worker.reportProgressUpdates(context: ExecutionContext, action: String) { + protected fun Job.reportProgressUpdates(context: ExecutionContext, action: String) { onProgressUpdate(1000, 1000) { progress, elapsedTime -> val alt = context.getFormat(EMessageType.NUMBER) val main = context.getFormat(EMessageType.INFORMATIVE) diff --git a/src/main/kotlin/io/dico/parcels2/command/CommandsDebug.kt b/src/main/kotlin/io/dico/parcels2/command/CommandsDebug.kt index 6331b4c..c6a4d6a 100644 --- a/src/main/kotlin/io/dico/parcels2/command/CommandsDebug.kt +++ b/src/main/kotlin/io/dico/parcels2/command/CommandsDebug.kt @@ -81,14 +81,14 @@ class CommandsDebug(plugin: ParcelsPlugin) : AbstractParcelCommands(plugin) { @Cmd("jobs") fun cmdJobs(): Any? { - val workers = plugin.workDispatcher.workers + val workers = plugin.jobDispatcher.jobs println(workers.map { it.job }.joinToString(separator = "\n")) return "Task count: ${workers.size}" } @Cmd("complete_jobs") fun cmdCompleteJobs(): Any? = cmdJobs().also { - plugin.launch { plugin.workDispatcher.completeAllTasks() } + plugin.launch { plugin.jobDispatcher.completeAllTasks() } } @Cmd("message") diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt index 2852ff0..05a10bd 100644 --- a/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt +++ b/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt @@ -16,8 +16,8 @@ import io.dico.parcels2.command.ParcelTarget.TargetKind.Companion.OWNER_REAL import io.dico.parcels2.command.ParcelTarget.TargetKind.Companion.PREFER_OWNED_FOR_DEFAULT import io.dico.parcels2.command.ParcelTarget.TargetKind.Companion.REAL import io.dico.parcels2.storage.Storage -import io.dico.parcels2.util.Vec2i -import io.dico.parcels2.util.ext.floor +import io.dico.parcels2.util.math.Vec2i +import io.dico.parcels2.util.math.ext.floor import org.bukkit.command.CommandSender import org.bukkit.entity.Player diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt index 7ccb458..25d76e3 100644 --- a/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt +++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/DefaultParcelGenerator.kt @@ -3,12 +3,12 @@ package io.dico.parcels2.defaultimpl import io.dico.parcels2.* import io.dico.parcels2.blockvisitor.* import io.dico.parcels2.options.DefaultGeneratorOptions -import io.dico.parcels2.util.Region -import io.dico.parcels2.util.Vec2i -import io.dico.parcels2.util.Vec3i -import io.dico.parcels2.util.ext.even -import io.dico.parcels2.util.ext.umod -import io.dico.parcels2.util.get +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.ext.even +import io.dico.parcels2.util.math.ext.umod +import io.dico.parcels2.util.math.get import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart.UNDISPATCHED import kotlinx.coroutines.launch @@ -121,9 +121,9 @@ class DefaultParcelGenerator( worldId: ParcelWorldId, container: ParcelContainer, coroutineScope: CoroutineScope, - workDispatcher: WorkDispatcher + jobDispatcher: JobDispatcher ): Pair<ParcelLocator, ParcelBlockManager> { - return ParcelLocatorImpl(worldId, container) to ParcelBlockManagerImpl(worldId, coroutineScope, workDispatcher) + return ParcelLocatorImpl(worldId, container) to ParcelBlockManagerImpl(worldId, coroutineScope, jobDispatcher) } private inline fun <T> convertBlockLocationToId(x: Int, z: Int, mapper: (Int, Int) -> T): T? { @@ -158,7 +158,7 @@ class DefaultParcelGenerator( private inner class ParcelBlockManagerImpl( val worldId: ParcelWorldId, coroutineScope: CoroutineScope, - override val workDispatcher: WorkDispatcher + override val jobDispatcher: JobDispatcher ) : ParcelBlockManagerBase(), CoroutineScope by coroutineScope { override val world: World = this@DefaultParcelGenerator.world override val parcelTraverser: RegionTraverser = RegionTraverser.convergingTo(o.floorHeight) @@ -177,7 +177,10 @@ class DefaultParcelGenerator( override fun getRegion(parcel: ParcelId): Region { val bottom = getBottomBlock(parcel) - return Region(Vec3i(bottom.x, 0, bottom.z), Vec3i(o.parcelSize, maxHeight, o.parcelSize)) + return Region( + Vec3i(bottom.x, 0, bottom.z), + Vec3i(o.parcelSize, maxHeight, o.parcelSize) + ) } private fun getRegionConsideringWorld(parcel: ParcelId): Region { @@ -234,12 +237,12 @@ class DefaultParcelGenerator( return world.getParcelById(parcelId) } - override fun submitBlockVisitor(vararg parcelIds: ParcelId, task: WorkerTask): Worker { + override fun submitBlockVisitor(vararg parcelIds: ParcelId, task: JobFunction): Job { val parcels = parcelIds.mapNotNull { getParcel(it) } - if (parcels.isEmpty()) return workDispatcher.dispatch(task) + if (parcels.isEmpty()) return jobDispatcher.dispatch(task) if (parcels.any { it.hasBlockVisitors }) throw IllegalArgumentException("This parcel already has a block visitor") - val worker = workDispatcher.dispatch(task) + val worker = jobDispatcher.dispatch(task) for (parcel in parcels) { launch(start = UNDISPATCHED) { @@ -252,7 +255,7 @@ class DefaultParcelGenerator( return worker } - override fun setBiome(parcel: ParcelId, biome: Biome): Worker = submitBlockVisitor(parcel) { + override fun setBiome(parcel: ParcelId, biome: Biome): Job = submitBlockVisitor(parcel) { val world = world val b = getBottomBlock(parcel) val parcelSize = o.parcelSize @@ -264,7 +267,7 @@ class DefaultParcelGenerator( } } - override fun clearParcel(parcel: ParcelId): Worker = submitBlockVisitor(parcel) { + override fun clearParcel(parcel: ParcelId): Job = submitBlockVisitor(parcel) { val region = getRegion(parcel) val blocks = parcelTraverser.traverseRegion(region) val blockCount = region.blockCount.toDouble() @@ -288,7 +291,7 @@ class DefaultParcelGenerator( } } - override fun swapParcels(parcel1: ParcelId, parcel2: ParcelId): Worker = submitBlockVisitor(parcel1, parcel2) { + override fun swapParcels(parcel1: ParcelId, parcel2: ParcelId): Job = submitBlockVisitor(parcel1, parcel2) { var region1 = getRegionConsideringWorld(parcel1) var region2 = getRegionConsideringWorld(parcel2) diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelImpl.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelImpl.kt index 243ec19..65378bf 100644 --- a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelImpl.kt +++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelImpl.kt @@ -3,7 +3,7 @@ package io.dico.parcels2.defaultimpl import io.dico.dicore.Formatting import io.dico.parcels2.* import io.dico.parcels2.Privilege.* -import io.dico.parcels2.util.Vec2i +import io.dico.parcels2.util.math.Vec2i import io.dico.parcels2.util.ext.alsoIfTrue import org.bukkit.Material import org.joda.time.DateTime diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt index ff2fcd4..1edf849 100644 --- a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt +++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelProviderImpl.kt @@ -58,8 +58,10 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider { if (worldExists) Bukkit.getWorld(worldName)!! else WorldCreator(worldName).generator(generator).createWorld().also { logger.info("Creating world $worldName") } - parcelWorld = ParcelWorldImpl(bukkitWorld, generator, worldOptions.runtime, plugin.storage, - plugin.globalPrivileges, ::DefaultParcelContainer, plugin, plugin.workDispatcher) + parcelWorld = ParcelWorldImpl( + bukkitWorld, generator, worldOptions.runtime, plugin.storage, + plugin.globalPrivileges, ::DefaultParcelContainer, plugin, plugin.jobDispatcher + ) if (!worldExists) { val time = DateTime.now() @@ -95,11 +97,18 @@ class ParcelProviderImpl(val plugin: ParcelsPlugin) : ParcelProvider { logger.info("Loading all parcel data...") val channel = plugin.storage.transmitAllParcelData() - do { - val pair = channel.receiveOrNull() ?: break - val parcel = getParcelById(pair.first) ?: continue - pair.second?.let { parcel.copyDataIgnoringDatabase(it) } - } while (true) + while (true) { + val (id, data) = channel.receiveOrNull() ?: break + val parcel = getParcelById(id) ?: continue + data?.let { parcel.copyDataIgnoringDatabase(it) } + } + + val channel2 = plugin.storage.transmitAllGlobalPrivileges() + while (true) { + val (profile, data) = channel2.receiveOrNull() ?: break + val key = profile as? PrivilegeKey ?: continue + (plugin.globalPrivileges[key] as PrivilegesHolder).copyPrivilegesFrom(data) + } logger.info("Loading data completed") _dataIsLoaded = true diff --git a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelWorldImpl.kt b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelWorldImpl.kt index 24bad79..78257c3 100644 --- a/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelWorldImpl.kt +++ b/src/main/kotlin/io/dico/parcels2/defaultimpl/ParcelWorldImpl.kt @@ -3,7 +3,7 @@ package io.dico.parcels2.defaultimpl import io.dico.parcels2.* -import io.dico.parcels2.blockvisitor.WorkDispatcher +import io.dico.parcels2.blockvisitor.JobDispatcher import io.dico.parcels2.options.RuntimeWorldOptions import io.dico.parcels2.storage.Storage import kotlinx.coroutines.CoroutineScope @@ -18,7 +18,7 @@ class ParcelWorldImpl(override val world: World, override val globalPrivileges: GlobalPrivilegesManager, containerFactory: ParcelContainerFactory, coroutineScope: CoroutineScope, - workDispatcher: WorkDispatcher) + jobDispatcher: JobDispatcher) : ParcelWorld, ParcelWorldId, ParcelContainer, /* missing delegation */ @@ -39,7 +39,7 @@ class ParcelWorldImpl(override val world: World, override val blockManager: ParcelBlockManager init { - val pair = generator.makeParcelLocatorAndBlockManager(id, container, coroutineScope, workDispatcher) + val pair = generator.makeParcelLocatorAndBlockManager(id, container, coroutineScope, jobDispatcher) locator = pair.first blockManager = pair.second diff --git a/src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt b/src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt index a62f569..ff96536 100644 --- a/src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt +++ b/src/main/kotlin/io/dico/parcels2/listener/ParcelListeners.kt @@ -7,6 +7,12 @@ import io.dico.dicore.RegistratorListener import io.dico.parcels2.* import io.dico.parcels2.storage.Storage import io.dico.parcels2.util.ext.* +import io.dico.parcels2.util.math.Dimension +import io.dico.parcels2.util.math.Vec3d +import io.dico.parcels2.util.math.Vec3i +import io.dico.parcels2.util.math.ext.clampMax +import io.dico.parcels2.util.math.ext.clampMin +import org.bukkit.Location import org.bukkit.Material.* import org.bukkit.World import org.bukkit.block.Biome @@ -52,6 +58,7 @@ class ParcelListeners( return world to world.getParcelAt(block) } + /* * Prevents players from entering plots they are banned from */ @@ -59,12 +66,36 @@ class ParcelListeners( val onPlayerMoveEvent = RegistratorListener<PlayerMoveEvent> l@{ event -> val user = event.player if (user.hasPermBanBypass) return@l - val parcel = parcelProvider.getParcelAt(event.to) ?: return@l + val toLoc = event.to + val parcel = parcelProvider.getParcelAt(toLoc) ?: return@l + if (!parcel.canEnterFast(user)) { - parcelProvider.getParcelAt(event.from)?.also { - user.teleport(it.homeLocation) + val region = parcel.world.blockManager.getRegion(parcel.id) + val dimension = region.getFirstUncontainedDimensionOf(Vec3i(event.from)) + + if (dimension == null) { + user.teleport(parcel.homeLocation) user.sendParcelMessage(nopermit = true, message = "You are banned from this parcel") - } ?: run { event.to = event.from } + + } else { + val speed = getPlayerSpeed(user) + val from = Vec3d(event.from) + val to = Vec3d(toLoc).with(dimension, from[dimension]) + + var newTo = to + dimension.otherDimensions.forEach { + val delta = to[it] - from[it] + newTo = newTo.add(it, delta * 100 * if (it == Dimension.Y) 0.5 else speed) + } + + + + event.to = Location( + toLoc.world, + newTo.x, newTo.y.clampMin(0.0).clampMax(255.0), newTo.z, + toLoc.yaw, toLoc.pitch + ) + } } } @@ -607,4 +638,16 @@ class ParcelListeners( } } + + private fun getPlayerSpeed(player: Player): Double = + if (player.isFlying) { + player.flySpeed * if (player.isSprinting) 21.6 else 10.92 + } else { + player.walkSpeed * when { + player.isSprinting -> 5.612 + player.isSneaking -> 1.31 + else -> 4.317 + } / 1.5 //? + } / 20.0 + }
\ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/options/Options.kt b/src/main/kotlin/io/dico/parcels2/options/Options.kt index 79dbb46..dc80db9 100644 --- a/src/main/kotlin/io/dico/parcels2/options/Options.kt +++ b/src/main/kotlin/io/dico/parcels2/options/Options.kt @@ -1,6 +1,6 @@ package io.dico.parcels2.options -import io.dico.parcels2.blockvisitor.TickWorktimeOptions +import io.dico.parcels2.blockvisitor.TickJobtimeOptions import org.bukkit.GameMode import org.bukkit.Material import java.io.Reader @@ -11,7 +11,7 @@ class Options { var worlds: Map<String, WorldOptions> = hashMapOf() private set var storage: StorageOptions = StorageOptions() - var tickWorktime: TickWorktimeOptions = TickWorktimeOptions(20, 1) + var tickJobtime: TickJobtimeOptions = TickJobtimeOptions(20, 1) var migration = MigrationOptionsHolder() fun addWorld(name: String, diff --git a/src/main/kotlin/io/dico/parcels2/storage/Backing.kt b/src/main/kotlin/io/dico/parcels2/storage/Backing.kt index 6f71471..2e0a8ee 100644 --- a/src/main/kotlin/io/dico/parcels2/storage/Backing.kt +++ b/src/main/kotlin/io/dico/parcels2/storage/Backing.kt @@ -61,9 +61,9 @@ interface Backing { fun setParcelOptionsInteractConfig(parcel: ParcelId, config: InteractableConfiguration) - fun transmitAllGlobalAddedData(channel: SendChannel<AddedDataPair<PlayerProfile>>) + fun transmitAllGlobalPrivileges(channel: SendChannel<PrivilegePair<PlayerProfile>>) - fun readGlobalPrivileges(owner: PlayerProfile): MutablePrivilegeMap + fun readGlobalPrivileges(owner: PlayerProfile): PrivilegesHolder? fun setGlobalPrivilege(owner: PlayerProfile, player: PlayerProfile, privilege: Privilege) } diff --git a/src/main/kotlin/io/dico/parcels2/storage/Storage.kt b/src/main/kotlin/io/dico/parcels2/storage/Storage.kt index 334d010..abd9f41 100644 --- a/src/main/kotlin/io/dico/parcels2/storage/Storage.kt +++ b/src/main/kotlin/io/dico/parcels2/storage/Storage.kt @@ -14,7 +14,7 @@ import java.util.UUID import kotlin.coroutines.CoroutineContext typealias DataPair = Pair<ParcelId, ParcelData?> -typealias AddedDataPair<TAttach> = Pair<TAttach, MutablePrivilegeMap> +typealias PrivilegePair<TAttach> = Pair<TAttach, PrivilegesHolder> interface Storage { val name: String @@ -55,9 +55,9 @@ interface Storage { fun setParcelOptionsInteractConfig(parcel: ParcelId, config: InteractableConfiguration): Job - fun transmitAllGlobalAddedData(): ReceiveChannel<AddedDataPair<PlayerProfile>> + fun transmitAllGlobalPrivileges(): ReceiveChannel<PrivilegePair<PlayerProfile>> - fun readGlobalPrivileges(owner: PlayerProfile): Deferred<MutablePrivilegeMap?> + fun readGlobalPrivileges(owner: PlayerProfile): Deferred<PrivilegesHolder?> fun setGlobalPrivilege(owner: PlayerProfile, player: PlayerProfile, privilege: Privilege): Job @@ -104,9 +104,9 @@ class BackedStorage internal constructor(val b: Backing) : Storage, CoroutineSco override fun setParcelOptionsInteractConfig(parcel: ParcelId, config: InteractableConfiguration) = b.launchJob { b.setParcelOptionsInteractConfig(parcel, config) } - override fun transmitAllGlobalAddedData(): ReceiveChannel<AddedDataPair<PlayerProfile>> = b.openChannel { b.transmitAllGlobalAddedData(it) } + override fun transmitAllGlobalPrivileges(): ReceiveChannel<PrivilegePair<PlayerProfile>> = b.openChannel { b.transmitAllGlobalPrivileges(it) } - override fun readGlobalPrivileges(owner: PlayerProfile): Deferred<MutablePrivilegeMap?> = b.launchFuture { b.readGlobalPrivileges(owner) } + override fun readGlobalPrivileges(owner: PlayerProfile): Deferred<PrivilegesHolder?> = b.launchFuture { b.readGlobalPrivileges(owner) } override fun setGlobalPrivilege(owner: PlayerProfile, player: PlayerProfile, privilege: Privilege) = b.launchJob { b.setGlobalPrivilege(owner, player, privilege) } diff --git a/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt b/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt index d0b1296..e3ed21b 100644 --- a/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt +++ b/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt @@ -6,7 +6,7 @@ import com.zaxxer.hikari.HikariDataSource import io.dico.parcels2.* import io.dico.parcels2.PlayerProfile.Star.name import io.dico.parcels2.storage.* -import io.dico.parcels2.util.ext.clampMax +import io.dico.parcels2.util.math.ext.clampMax import io.dico.parcels2.util.ext.synchronized import kotlinx.coroutines.* import kotlinx.coroutines.channels.ArrayChannel @@ -193,6 +193,10 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi PrivilegesLocalT.setPrivilege(parcel, profile, privilege) } + data.privilegeOfStar.takeIf { it != Privilege.DEFAULT }?.let { privilege -> + PrivilegesLocalT.setPrivilege(parcel, PlayerProfile.Star, privilege) + } + setParcelOptionsInteractConfig(parcel, data.interactableConfig) } @@ -242,13 +246,13 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi } } - override fun transmitAllGlobalAddedData(channel: SendChannel<AddedDataPair<PlayerProfile>>) { - PrivilegesGlobalT.sendAllAddedData(channel) + override fun transmitAllGlobalPrivileges(channel: SendChannel<PrivilegePair<PlayerProfile>>) { + PrivilegesGlobalT.sendAllPrivilegesH(channel) channel.close() } - override fun readGlobalPrivileges(owner: PlayerProfile): MutablePrivilegeMap { - return PrivilegesGlobalT.readPrivileges(ProfilesT.getId(owner.toOwnerProfile()) ?: return hashMapOf()) + override fun readGlobalPrivileges(owner: PlayerProfile): PrivilegesHolder? { + return PrivilegesGlobalT.readPrivileges(ProfilesT.getId(owner.toOwnerProfile()) ?: return null) } override fun setGlobalPrivilege(owner: PlayerProfile, player: PlayerProfile, privilege: Privilege) { @@ -267,7 +271,10 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi System.arraycopy(source, 0, target, 0, source.size.clampMax(target.size)) } - privilegeMap = PrivilegesLocalT.readPrivileges(id) + val privileges = PrivilegesLocalT.readPrivileges(id) + if (privileges != null) { + copyPrivilegesFrom(privileges) + } } } diff --git a/src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt b/src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt index d22316a..6a0a41b 100644 --- a/src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt +++ b/src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt @@ -15,7 +15,7 @@ object ParcelOptionsT : Table("parcel_options") { val interact_bitmask = binary("interact_bitmask", 4) } -typealias PrivilegesSendChannel<AttachT> = SendChannel<Pair<AttachT, MutablePrivilegeMap>> +typealias PrivilegesSendChannel<AttachT> = SendChannel<Pair<AttachT, PrivilegesHolder>> sealed class PrivilegesTable<AttachT>(name: String, val idTable: IdTransactionsTable<*, AttachT>) : Table(name) { val attach_id = integer("attach_id").references(idTable.id, ReferenceOption.CASCADE) @@ -43,32 +43,32 @@ sealed class PrivilegesTable<AttachT>(name: String, val idTable: IdTransactionsT } } - fun readPrivileges(id: Int): MutablePrivilegeMap { + fun readPrivileges(id: Int): PrivilegesHolder? { val list = slice(profile_id, privilege).select { attach_id eq id } - val result = MutablePrivilegeMap() + val result = PrivilegesHolder() for (row in list) { val profile = ProfilesT.getRealItem(row[profile_id]) ?: continue - result[profile] = Privilege.getByNumber(row[privilege]) ?: continue + result.setRawStoredPrivilege(profile, Privilege.getByNumber(row[privilege]) ?: continue) } return result } - fun sendAllAddedData(channel: PrivilegesSendChannel<AttachT>) { + fun sendAllPrivilegesH(channel: PrivilegesSendChannel<AttachT>) { val iterator = selectAll().orderBy(attach_id).iterator() if (iterator.hasNext()) { val firstRow = iterator.next() var id: Int = firstRow[attach_id] var attach: AttachT? = null - var map: MutablePrivilegeMap? = null + var map: PrivilegesHolder? = null fun initAttachAndMap() { attach = idTable.getItem(id) - map = attach?.let { mutableMapOf() } + map = attach?.let { PrivilegesHolder() } } fun sendIfPresent() { - if (attach != null && map != null && map!!.isNotEmpty()) { + if (attach != null && map != null) { channel.offer(attach!! to map!!) } attach = null @@ -91,7 +91,7 @@ sealed class PrivilegesTable<AttachT>(name: String, val idTable: IdTransactionsT val profile = ProfilesT.getRealItem(row[profile_id]) ?: continue val privilege = Privilege.getByNumber(row[privilege]) ?: continue - map!![profile] = privilege + map!!.setRawStoredPrivilege(profile, privilege) } sendIfPresent() diff --git a/src/main/kotlin/io/dico/parcels2/util/Region.kt b/src/main/kotlin/io/dico/parcels2/util/Region.kt deleted file mode 100644 index 1801b4e..0000000 --- a/src/main/kotlin/io/dico/parcels2/util/Region.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.dico.parcels2.util - -data class Region(val origin: Vec3i, val size: Vec3i) { - val blockCount: Int get() = size.x * size.y * size.z - - val center: Vec3d - get() { - val x = (origin.x + size.x) / 2.0 - val y = (origin.y + size.y) / 2.0 - val z = (origin.z + size.z) / 2.0 - return Vec3d(x, y, z) - } - - fun withSize(size: Vec3i): Region { - if (size == this.size) return this - return Region(origin, size) - } -}
\ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/util/Vec2i.kt b/src/main/kotlin/io/dico/parcels2/util/Vec2i.kt deleted file mode 100644 index 62ac97f..0000000 --- a/src/main/kotlin/io/dico/parcels2/util/Vec2i.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.dico.parcels2.util - -data class Vec2i( - val x: Int, - val z: Int -) - -data class Region2i( - val bottom: Vec2i, - val top: Vec2i -)
\ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/util/ext/Misc.kt b/src/main/kotlin/io/dico/parcels2/util/ext/Misc.kt index 4df4d52..a826687 100644 --- a/src/main/kotlin/io/dico/parcels2/util/ext/Misc.kt +++ b/src/main/kotlin/io/dico/parcels2/util/ext/Misc.kt @@ -77,3 +77,8 @@ class EditLoopScope<T, U>(val _map: MutableMap<T, U>) { operator fun Formatting.plus(other: Formatting) = toString() + other operator fun Formatting.plus(other: String) = toString() + other + +inline fun <T> Pair<T, T>.forEach(block: (T) -> Unit) { + block(first) + block(second) +} diff --git a/src/main/kotlin/io/dico/parcels2/util/math/Dimension.kt b/src/main/kotlin/io/dico/parcels2/util/math/Dimension.kt new file mode 100644 index 0000000..cf67148 --- /dev/null +++ b/src/main/kotlin/io/dico/parcels2/util/math/Dimension.kt @@ -0,0 +1,19 @@ +package io.dico.parcels2.util.math + +enum class Dimension { + X, + Y, + Z; + + val otherDimensions + get() = when (this) { + X -> Y to Z + Y -> X to Z + Z -> X to Y + } + + companion object { + private val values = values() + operator fun get(ordinal: Int) = values[ordinal] + } +}
\ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/util/math/Region.kt b/src/main/kotlin/io/dico/parcels2/util/math/Region.kt new file mode 100644 index 0000000..cdbd497 --- /dev/null +++ b/src/main/kotlin/io/dico/parcels2/util/math/Region.kt @@ -0,0 +1,37 @@ +package io.dico.parcels2.util.math + +data class Region(val origin: Vec3i, val size: Vec3i) { + val blockCount: Int get() = size.x * size.y * size.z + + val center: Vec3d + get() { + val x = (origin.x + size.x) / 2.0 + val y = (origin.y + size.y) / 2.0 + val z = (origin.z + size.z) / 2.0 + return Vec3d(x, y, z) + } + + val end: Vec3i + get() = origin + size + + val max: Vec3i + get() = Vec3i(origin.x + size.x - 1, origin.y + size.y - 1, origin.z + size.z - 1) + + fun withSize(size: Vec3i): Region { + if (size == this.size) return this + return Region(origin, size) + } + + operator fun contains(loc: Vec3i): Boolean = getFirstUncontainedDimensionOf(loc) == null + + fun getFirstUncontainedDimensionOf(loc: Vec3i): Dimension? { + val max = max + return when { + loc.x !in origin.x..max.x -> Dimension.X + loc.z !in origin.z..max.z -> Dimension.Z + loc.y !in origin.y..max.y -> Dimension.Y + else -> null + } + } + +}
\ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/util/math/Vec2i.kt b/src/main/kotlin/io/dico/parcels2/util/math/Vec2i.kt new file mode 100644 index 0000000..9385535 --- /dev/null +++ b/src/main/kotlin/io/dico/parcels2/util/math/Vec2i.kt @@ -0,0 +1,6 @@ +package io.dico.parcels2.util.math + +data class Vec2i( + val x: Int, + val z: Int +) diff --git a/src/main/kotlin/io/dico/parcels2/util/math/Vec3d.kt b/src/main/kotlin/io/dico/parcels2/util/math/Vec3d.kt new file mode 100644 index 0000000..45e6216 --- /dev/null +++ b/src/main/kotlin/io/dico/parcels2/util/math/Vec3d.kt @@ -0,0 +1,54 @@ +package io.dico.parcels2.util.math + +import io.dico.parcels2.util.math.ext.floor +import org.bukkit.Location +import kotlin.math.sqrt + +data class Vec3d( + val x: Double, + val y: Double, + val z: Double +) { + constructor(loc: Location) : this(loc.x, loc.y, loc.z) + + operator fun plus(o: Vec3d) = Vec3d(x + o.x, y + o.y, z + o.z) + operator fun minus(o: Vec3i) = Vec3d(x - o.x, y - o.y, z - o.z) + infix fun addX(o: Double) = Vec3d(x + o, y, z) + infix fun addY(o: Double) = Vec3d(x, y + o, z) + infix fun addZ(o: Double) = Vec3d(x, y, z + o) + infix fun withX(o: Double) = Vec3d(o, y, z) + infix fun withY(o: Double) = Vec3d(x, o, z) + infix fun withZ(o: Double) = Vec3d(x, y, o) + fun add(ox: Double, oy: Double, oz: Double) = Vec3d(x + ox, y + oy, z + oz) + fun toVec3i() = Vec3i(x.floor(), y.floor(), z.floor()) + + fun distanceSquared(o: Vec3d): Double { + val dx = o.x - x + val dy = o.y - y + val dz = o.z - z + return dx * dx + dy * dy + dz * dz + } + + fun distance(o: Vec3d) = sqrt(distanceSquared(o)) + + operator fun get(dimension: Dimension) = + when (dimension) { + Dimension.X -> x + Dimension.Y -> y + Dimension.Z -> z + } + + fun with(dimension: Dimension, value: Double) = + when (dimension) { + Dimension.X -> withX(value) + Dimension.Y -> withY(value) + Dimension.Z -> withZ(value) + } + + fun add(dimension: Dimension, value: Double) = + when (dimension) { + Dimension.X -> addX(value) + Dimension.Y -> addY(value) + Dimension.Z -> addZ(value) + } +}
\ No newline at end of file diff --git a/src/main/kotlin/io/dico/parcels2/util/Vec3i.kt b/src/main/kotlin/io/dico/parcels2/util/math/Vec3i.kt index 8608e13..418fd0f 100644 --- a/src/main/kotlin/io/dico/parcels2/util/Vec3i.kt +++ b/src/main/kotlin/io/dico/parcels2/util/math/Vec3i.kt @@ -1,31 +1,18 @@ -package io.dico.parcels2.util +package io.dico.parcels2.util.math -import io.dico.parcels2.util.ext.clampMax +import io.dico.parcels2.util.math.ext.clampMax +import org.bukkit.Location import org.bukkit.World import org.bukkit.block.Block import org.bukkit.block.BlockFace -data class Vec3d( - val x: Double, - val y: Double, - val z: Double -) { - operator fun plus(o: Vec3d) = Vec3d(x + o.x, y + o.y, z + o.z) - operator fun minus(o: Vec3i) = Vec3d(x - o.x, y - o.y, z - o.z) - infix fun addX(o: Double) = Vec3d(x + o, y, z) - infix fun addY(o: Double) = Vec3d(x, y + o, z) - infix fun addZ(o: Double) = Vec3d(x, y, z + o) - infix fun withX(o: Double) = Vec3d(o, y, z) - infix fun withY(o: Double) = Vec3d(x, o, z) - infix fun withZ(o: Double) = Vec3d(x, y, o) - fun add(ox: Double, oy: Double, oz: Double) = Vec3d(x + ox, y + oy, z + oz) -} - data class Vec3i( val x: Int, val y: Int, val z: Int ) { + constructor(loc: Location) : this(loc.blockX, loc.blockY, loc.blockZ) + operator fun plus(o: Vec3i) = Vec3i(x + o.x, y + o.y, z + o.z) operator fun minus(o: Vec3i) = Vec3i(x - o.x, y - o.y, z - o.z) infix fun addX(o: Int) = Vec3i(x + o, y, z) @@ -38,6 +25,27 @@ data class Vec3i( fun neg() = Vec3i(-x, -y, -z) fun clampMax(o: Vec3i) = Vec3i(x.clampMax(o.x), y.clampMax(o.y), z.clampMax(o.z)) + operator fun get(dimension: Dimension) = + when (dimension) { + Dimension.X -> x + Dimension.Y -> y + Dimension.Z -> z + } + + fun with(dimension: Dimension, value: Int) = + when (dimension) { + Dimension.X -> withX(value) + Dimension.Y -> withY(value) + Dimension.Z -> withZ(value) + } + + fun add(dimension: Dimension, value: Int) = + when (dimension) { + Dimension.X -> addX(value) + Dimension.Y -> addY(value) + Dimension.Z -> addZ(value) + } + companion object { private operator fun invoke(face: BlockFace) = Vec3i(face.modX, face.modY, face.modZ) val down = Vec3i(BlockFace.DOWN) diff --git a/src/main/kotlin/io/dico/parcels2/util/ext/Math.kt b/src/main/kotlin/io/dico/parcels2/util/math/ext/Math.kt index a123bcf..1211894 100644 --- a/src/main/kotlin/io/dico/parcels2/util/ext/Math.kt +++ b/src/main/kotlin/io/dico/parcels2/util/math/ext/Math.kt @@ -1,4 +1,4 @@ -package io.dico.parcels2.util.ext +package io.dico.parcels2.util.math.ext fun Double.floor(): Int { val down = toInt() @@ -34,6 +34,7 @@ fun IntRange.clamp(min: Int, max: Int): IntRange { // the name coerceAtMost is bad fun Int.clampMax(max: Int) = coerceAtMost(max) fun Double.clampMin(min: Double) = coerceAtLeast(min) +fun Double.clampMax(max: Double) = coerceAtMost(max) // Why does this not exist? infix fun Int.ceilDiv(divisor: Int): Int { |