summaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/dico/parcels2/command/ParcelCommandReceivers.kt
blob: 15548b4cecbe0c06c725f84521146988d5940b3a (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
62
63
64
65
66
67
68
package io.dico.parcels2.command

import io.dico.dicore.command.CommandException
import io.dico.dicore.command.ExecutionContext
import io.dico.dicore.command.registration.reflect.ICommandReceiver
import io.dico.dicore.command.Validate
import io.dico.parcels2.*
import io.dico.parcels2.Privilege.*
import io.dico.parcels2.util.ext.hasPermAdminManage
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 RequireParcelPrivilege(val privilege: Privilege)

/*
@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(parcel.canManage(player), "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<RequireParcelPrivilege>()

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

fun ParcelProvider.getWorldRequired(player: Player, admin: Boolean = false): ParcelWorld {
    if (admin) Validate.isTrue(player.hasPermAdminManage, "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, privilege: Privilege? = null): Parcel {
    val parcel = getWorldRequired(player, admin = privilege == ADMIN).getParcelAt(player)
        ?: throw CommandException("You must be in a parcel to use that command")

    if (!player.hasPermAdminManage) {
        @Suppress("NON_EXHAUSTIVE_WHEN")
        when (privilege) {
            OWNER ->
                Validate.isTrue(parcel.isOwner(player.uuid), "You must own this parcel to use that command")
            CAN_MANAGE ->
                Validate.isTrue(parcel.canManage(player), "You must have management privileges on this parcel to use that command")
        }
    }

    return parcel
}