diff options
Diffstat (limited to 'src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt')
-rw-r--r-- | src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt | 90 |
1 files changed, 47 insertions, 43 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt index cbab80a..abf7d40 100644 --- a/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt +++ b/src/main/kotlin/io/dico/parcels2/command/ParcelTarget.kt @@ -5,20 +5,23 @@ import io.dico.dicore.command.parameter.Parameter import io.dico.dicore.command.parameter.type.ParameterConfig import io.dico.dicore.command.parameter.type.ParameterType import io.dico.parcels2.* +import io.dico.parcels2.storage.Storage import io.dico.parcels2.util.Vec2i -import io.dico.parcels2.util.floor -import kotlinx.coroutines.experimental.Deferred +import io.dico.parcels2.util.ext.floor +import kotlinx.coroutines.CoroutineStart.* +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.async import org.bukkit.command.CommandSender import org.bukkit.entity.Player -sealed class ParcelTarget(val world: ParcelWorld, val isDefault: Boolean) { +sealed class ParcelTarget(val world: ParcelWorld, val parsedKind: Int, val isDefault: Boolean) { - abstract suspend fun ParcelsPlugin.getParcelSuspend(): Parcel? + abstract suspend fun getParcelSuspend(storage: Storage): Parcel? - fun ParcelsPlugin.getParcelDeferred(): Deferred<Parcel?> = functionHelper.deferUndispatchedOnMainThread { getParcelSuspend() } + fun ParcelsPlugin.getParcelDeferred(): Deferred<Parcel?> = async(start = UNDISPATCHED) { getParcelSuspend(storage) } - class ByID(world: ParcelWorld, val id: Vec2i?, isDefault: Boolean) : ParcelTarget(world, isDefault) { - override suspend fun ParcelsPlugin.getParcelSuspend(): Parcel? = getParcel() + class ByID(world: ParcelWorld, val id: Vec2i?, parsedKind: Int, isDefault: Boolean) : ParcelTarget(world, parsedKind, isDefault) { + override suspend fun getParcelSuspend(storage: Storage): Parcel? = getParcel() fun getParcel() = id?.let { world.getParcelById(it) } val isPath: Boolean get() = id == null } @@ -26,46 +29,40 @@ sealed class ParcelTarget(val world: ParcelWorld, val isDefault: Boolean) { class ByOwner(world: ParcelWorld, owner: PlayerProfile, val index: Int, + parsedKind: Int, isDefault: Boolean, - val onResolveFailure: (() -> Unit)? = null) : ParcelTarget(world, isDefault) { + val onResolveFailure: (() -> Unit)? = null) : ParcelTarget(world, parsedKind, isDefault) { init { if (index < 0) throw IllegalArgumentException("Invalid parcel home index: $index") } var owner = owner; private set - override suspend fun ParcelsPlugin.getParcelSuspend(): Parcel? { - onResolveFailure?.let { onFail -> - val owner = owner - if (owner is PlayerProfile.Unresolved) { - val new = owner.tryResolveSuspendedly(storage) - if (new == null) { - onFail() - return@let - } - this@ByOwner.owner = new - } + suspend fun resolveOwner(storage: Storage): Boolean { + val owner = owner + if (owner is PlayerProfile.Unresolved) { + this.owner = owner.tryResolveSuspendedly(storage) ?: if (parsedKind and OWNER_FAKE != 0) PlayerProfile.Fake(owner.name) + else run { onResolveFailure?.invoke(); return false } } + return true + } + + override suspend fun getParcelSuspend(storage: Storage): Parcel? { + onResolveFailure?.let { resolveOwner(storage) } val ownedParcelsSerialized = storage.getOwnedParcels(owner).await() val ownedParcels = ownedParcelsSerialized - .map { parcelProvider.getParcelById(it) } - .filter { it != null && world == it.world && owner == it.owner } + .filter { it.worldId.equals(world.id) } + .map { world.getParcelById(it.x, it.z) } return ownedParcels.getOrNull(index) } } - annotation class Kind(val kind: Int) - - companion object Config : ParameterConfig<Kind, Int>(Kind::class.java) { - override fun toParameterInfo(annotation: Kind): Int { - return annotation.kind - } - + companion object { const val ID = 1 // ID const val OWNER_REAL = 2 // an owner backed by a UUID - const val OWNER_FAKE = 3 // an owner not backed by a UUID + const val OWNER_FAKE = 4 // an owner not backed by a UUID const val OWNER = OWNER_REAL or OWNER_FAKE // any owner const val ANY = ID or OWNER_REAL or OWNER_FAKE // any @@ -73,11 +70,18 @@ sealed class ParcelTarget(val world: ParcelWorld, val isDefault: Boolean) { const val DEFAULT_KIND = REAL - const val PREFER_OWNED_FOR_DEFAULT = 4 // if the kind can be ID and OWNER_REAL, prefer OWNER_REAL for default + const val PREFER_OWNED_FOR_DEFAULT = 8 // if the kind can be ID and OWNER_REAL, prefer OWNER_REAL for default // instead of parcel that the player is in } - class PType(val parcelProvider: ParcelProvider) : ParameterType<ParcelTarget, Int>(ParcelTarget::class.java, ParcelTarget.Config) { + annotation class Kind(val kind: Int) + private object Config : ParameterConfig<Kind, Int>(Kind::class.java) { + override fun toParameterInfo(annotation: Kind): Int { + return annotation.kind + } + } + + class PType(val parcelProvider: ParcelProvider) : ParameterType<ParcelTarget, Int>(ParcelTarget::class.java, Config) { override fun parse(parameter: Parameter<ParcelTarget, Int>, sender: CommandSender, buffer: ArgumentBuffer): ParcelTarget { var input = buffer.next() @@ -95,12 +99,12 @@ sealed class ParcelTarget(val world: ParcelWorld, val isDefault: Boolean) { val kind = parameter.paramInfo ?: DEFAULT_KIND if (input.contains(',')) { if (kind and ID == 0) invalidInput(parameter, "You must specify a parcel by OWNER, that is, an owner and index") - return ByID(world, getId(parameter, input), false) + return ByID(world, getId(parameter, input), kind, false) } if (kind and OWNER == 0) invalidInput(parameter, "You must specify a parcel by ID, that is, the x and z component separated by a comma") val (owner, index) = getHomeIndex(parameter, kind, sender, input) - return ByOwner(world, owner, index, false, onResolveFailure = { invalidInput(parameter, "The player $input does not exist") }) + return ByOwner(world, owner, index, kind, false, onResolveFailure = { invalidInput(parameter, "The player $input does not exist") }) } private fun getId(parameter: Parameter<*, *>, input: String): Vec2i { @@ -116,15 +120,18 @@ sealed class ParcelTarget(val world: ParcelWorld, val isDefault: Boolean) { private fun getHomeIndex(parameter: Parameter<*, *>, kind: Int, sender: CommandSender, input: String): Pair<PlayerProfile, Int> { val splitIdx = input.indexOf(':') val ownerString: String - val indexString: String + val index: Int? if (splitIdx == -1) { // just the index. - ownerString = "" - indexString = input + index = input.toIntOrNull() + ownerString = if (index == null) input else "" } else { ownerString = input.substring(0, splitIdx) - indexString = input.substring(splitIdx + 1) + + val indexString = input.substring(splitIdx + 1) + index = indexString.toIntOrNull() + ?: invalidInput(parameter, "The home index must be an integer, $indexString is not an integer") } val owner = if (ownerString.isEmpty()) @@ -132,10 +139,7 @@ sealed class ParcelTarget(val world: ParcelWorld, val isDefault: Boolean) { else PlayerProfile.byName(ownerString, allowReal = kind and OWNER_REAL != 0, allowFake = kind and OWNER_FAKE != 0) - val index = if (indexString.isEmpty()) 0 else indexString.toIntOrNull() - ?: invalidInput(parameter, "The home index must be an integer, $indexString is not an integer") - - return owner to index + return owner to (index ?: 0) } private fun requirePlayer(sender: CommandSender, parameter: Parameter<*, *>, objName: String): Player { @@ -156,10 +160,10 @@ sealed class ParcelTarget(val world: ParcelWorld, val isDefault: Boolean) { val world = parcelProvider.getWorld(player.world) ?: invalidInput(parameter, "You must be in a parcel world to omit the parcel") if (useLocation) { val id = player.location.let { world.getParcelIdAt(it.x.floor(), it.z.floor())?.pos } - return ByID(world, id, true) + return ByID(world, id, kind, true) } - return ByOwner(world, PlayerProfile(player), 0, true) + return ByOwner(world, PlayerProfile(player), 0, kind, true) } } |