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

import io.dico.dicore.command.*
import io.dico.parcels2.Parcel
import io.dico.parcels2.ParcelWorld
import io.dico.parcels2.Worlds
import io.dico.parcels2.logger
import io.dico.parcels2.util.hasAdminManage
import io.dico.parcels2.util.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.javaType
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 getParcelCommandReceiver(worlds: Worlds, 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(worlds.getParcelRequired(player, admin, owner))
        WorldScope::class -> WorldScope(worlds.getWorldRequired(player, admin))
        else -> throw InternalError("Invalid command receiver type")
    }
}

fun Worlds.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 Worlds.getParcelRequired(player: Player, admin: Boolean = false, own: Boolean = false): Parcel {
    val parcel = getWorldRequired(player, admin = admin).parcelAt(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
}