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

import io.dico.dicore.command.CommandException
import io.dico.dicore.command.ExecutionContext
import io.dico.dicore.command.ICommandReceiver
import io.dico.dicore.command.Validate
import io.dico.parcels2.Parcel
import io.dico.parcels2.ParcelProvider
import io.dico.parcels2.ParcelWorld
import io.dico.parcels2.util.ext.hasAdminManage
import io.dico.parcels2.util.ext.uuid
import org.bukkit.entity.Player
import java.lang.reflect.Method
import kotlin.reflect.full.extensionReceiverParameter
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.jvm.jvmErasure
import kotlin.reflect.jvm.kotlinFunction

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class ParcelRequire(val admin: Boolean = false, val owner: Boolean = false)

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class SuspensionTimeout(val millis: Int)

open class WorldScope(val world: ParcelWorld) : ICommandReceiver
open class ParcelScope(val parcel: Parcel) : WorldScope(parcel.world) {
    fun checkCanManage(player: Player, action: String) = Validate.isTrue(player.hasAdminManage || parcel.isOwner(player.uuid),
        "You must own this parcel to $action")
}

fun getParcelCommandReceiver(parcelProvider: ParcelProvider, context: ExecutionContext, method: Method, cmdName: String): ICommandReceiver {
    val player = context.sender as Player
    val function = method.kotlinFunction!!
    val receiverType = function.extensionReceiverParameter!!.type
    val require = function.findAnnotation<ParcelRequire>()
    val admin = require?.admin == true
    val owner = require?.owner == true

    return when (receiverType.jvmErasure) {
        ParcelScope::class -> ParcelScope(parcelProvider.getParcelRequired(player, admin, owner))
        WorldScope::class -> WorldScope(parcelProvider.getWorldRequired(player, admin))
        else -> throw InternalError("Invalid command receiver type")
    }
}

fun ParcelProvider.getWorldRequired(player: Player, admin: Boolean = false): ParcelWorld {
    if (admin) Validate.isTrue(player.hasAdminManage, "You must have admin rights to use that command")
    return getWorld(player.world)
        ?: throw CommandException("You must be in a parcel world to use that command")
}

fun ParcelProvider.getParcelRequired(player: Player, admin: Boolean = false, own: Boolean = false): Parcel {
    val parcel = getWorldRequired(player, admin = admin).getParcelAt(player)
        ?: throw CommandException("You must be in a parcel to use that command")
    if (own) Validate.isTrue(parcel.isOwner(player.uuid) || player.hasAdminManage,
        "You must own this parcel to use that command")
    return parcel
}