Skip to content

Commit

Permalink
Experimental | 重构触发器&物品动作
Browse files Browse the repository at this point in the history
  • Loading branch information
TheFloodDragon committed Aug 13, 2024
1 parent 1632fcc commit 85db481
Show file tree
Hide file tree
Showing 19 changed files with 276 additions and 358 deletions.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package cn.fd.ratziel.module.item.api.trigger

import cn.fd.ratziel.function.ArgumentContext

/**
* TriggerAction - 由触发器触发的动作
*
* @author TheFloodDragon
* @since 2024/8/13 13:39
*/
interface TriggerAction {

/**
* 执行动作
* @param trigger 触发此动作的触发器
* @param context 动作参数
*/
fun execute(trigger: TriggerType, context: ArgumentContext)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cn.fd.ratziel.module.item.api.trigger

/**
* TriggerType - 触发器
*
* @author TheFloodDragon
* @since 2024/8/13 13:38
*/
interface TriggerType {

/**
* 触发器名称
*/
val names: Array<out String>

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import cn.fd.ratziel.module.item.nms.RefItemStack
import cn.fd.ratziel.module.item.util.handle
import cn.fd.ratziel.module.item.util.read
import org.bukkit.inventory.ItemStack
import taboolib.platform.util.isAir

/**
* RatzielItem
Expand Down Expand Up @@ -63,6 +64,7 @@ open class RatzielItem : NeoItem {
*/
@JvmStatic
fun of(itemStack: ItemStack): RatzielItem? {
if (itemStack.isAir()) return null
val itemData = RefItemStack(itemStack).getData() ?: return null
return of(itemData)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package cn.fd.ratziel.module.item.impl.action

import cn.fd.ratziel.core.Identifier
import cn.fd.ratziel.function.ArgumentContext
import cn.fd.ratziel.module.item.api.trigger.TriggerType
import cn.fd.ratziel.module.item.impl.service.NativeServiceRegistry
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArraySet

/**
* ActionManager
*
* @author TheFloodDragon
* @since 2024/7/3 15:20
*/
object ActionManager {

/**
* 物品触发器注册表
*/
val triggers: MutableSet<TriggerType> = CopyOnWriteArraySet(Triggers.entries)

/**
* 物品唯一标识符 - 触发器表 (存有物品触发器和物品动作)
*/
val actionMap: MutableMap<Identifier, TriggerMap> = ConcurrentHashMap()

init {
// 注册服务
NativeServiceRegistry.register(TriggerMap::class.java, { actionMap[it] }, { i, m -> actionMap[i] = m })
}

/**
* 触发指定物品的指定触发器, 并执行物品动作
*/
@JvmStatic
fun trigger(identifier: Identifier, trigger: TriggerType, context: ArgumentContext) {
// 获取物品动作 (无动作时返回)
val action = actionMap[identifier]?.get(trigger) ?: return
// 执行物品动作
action.execute(trigger, context)
}

/**
* 匹配 [TriggerMap]
*/
@JvmStatic
fun matchTrigger(name: String): TriggerType? = triggers.firstOrNull { it.names.contains(name) }

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cn.fd.ratziel.module.item.impl.feature.action
package cn.fd.ratziel.module.item.impl.action

import cn.fd.ratziel.core.serialization.getBy
import cn.fd.ratziel.core.serialization.toBasic
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package cn.fd.ratziel.module.item.impl.action

import cn.fd.ratziel.function.ArgumentContext
import cn.fd.ratziel.module.item.api.trigger.TriggerAction
import cn.fd.ratziel.module.item.api.trigger.TriggerType
import cn.fd.ratziel.script.api.EvaluableScript
import cn.fd.ratziel.script.api.ScriptEnvironment
import cn.fd.ratziel.script.impl.SimpleScriptEnv

/**
* ScriptedAction
*
* @author TheFloodDragon
* @since 2024/7/3 15:32
*/
open class ScriptedAction(
/**
* 可执行脚本
*/
val script: EvaluableScript,
) : TriggerAction {

override fun execute(trigger: TriggerType, context: ArgumentContext) {
script.evaluate(context.popOr(ScriptEnvironment::class.java, SimpleScriptEnv()))
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
@file:Suppress("unused")

package cn.fd.ratziel.module.item.impl.action

import cn.fd.ratziel.module.item.impl.RatzielItem
import cn.fd.ratziel.script.impl.SimpleScriptEnv
import org.bukkit.entity.Player
import org.bukkit.event.block.Action.*
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerItemBreakEvent
import org.bukkit.event.player.PlayerItemDamageEvent
import taboolib.common.platform.event.SubscribeEvent
import taboolib.platform.util.attacker

/**
* TriggerListener
*
* @author TheFloodDragon
* @since 2024/8/13 14:35
*/
object TriggerListener {

@SubscribeEvent
fun onAttack(event: EntityDamageByEntityEvent) {
// 获取攻击者
val attacker = event.attacker
// 判断是否是玩家, 物品是否是本插件物品
if (attacker !is Player) return
// 获取攻击时的物品
val item = attacker.inventory.itemInMainHand
val neoItem = RatzielItem.of(item) ?: return
// 触发触发器 (参数: 事件(EntityDamageByEntityEvent), 攻击者(Player), ItemStack, RatzielItem)
Triggers.ATTACK.trigger(neoItem.id) {
set("event", event)
set("attacker", attacker)
set("item", item)
set("neoItem", neoItem)
}
}

@SubscribeEvent(ignoreCancelled = true)
fun onBreak(event: PlayerItemBreakEvent) {
// 获取损坏时的物品
val item = event.brokenItem
val neoItem = RatzielItem.of(item) ?: return
// 触发触发器
Triggers.BREAK.trigger(neoItem.id) {
set("event", event)
set("player", event.player)
set("item", item)
set("neoItem", neoItem)
}
}

@SubscribeEvent
fun onDamage(event: PlayerItemDamageEvent) {
// 获取攻击时的物品
val item = event.item
val neoItem = RatzielItem.of(item) ?: return
// 触发触发器
Triggers.DAMAGED.trigger(neoItem.id) {
set("event", event)
set("player", event.player)
set("damage", event.damage)
set("item", event.item)
set("neoItem", neoItem)
}
}

/**
* 当玩家与空气或方块发生交互时
* 触发事件及脚本
*/
@SubscribeEvent
fun onInteract(event: PlayerInteractEvent) {
// 获取交互时的物品
val item = event.item ?: return
val neoItem = RatzielItem.of(item) ?: return
// 环境
val env = SimpleScriptEnv().apply {
set("event", event)
set("item", item)
set("neoItem", neoItem)
}
// 触发触发器
when (event.action) {
LEFT_CLICK_AIR -> Triggers.INTERACT_LEFT_CLICK_AIR.trigger(neoItem.id, env)
LEFT_CLICK_BLOCK -> Triggers.INTERACT_LEFT_CLICK_BLOCK.trigger(neoItem.id, env)
RIGHT_CLICK_AIR -> Triggers.INTERACT_RIGHT_CLICK_AIR.trigger(neoItem.id, env)
RIGHT_CLICK_BLOCK -> Triggers.INTERACT_RIGHT_CLICK_BLOCK.trigger(neoItem.id, env)
else -> {}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cn.fd.ratziel.module.item.impl.action

import cn.fd.ratziel.module.item.api.trigger.TriggerAction
import cn.fd.ratziel.module.item.api.trigger.TriggerType
import java.util.concurrent.ConcurrentHashMap

/**
* TriggerMap
*
* @author TheFloodDragon
* @since 2024/8/13 14:01
*/
open class TriggerMap(
protected open val map: MutableMap<TriggerType, TriggerAction> = ConcurrentHashMap(),
) : MutableMap<TriggerType, TriggerAction> by map
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package cn.fd.ratziel.module.item.impl.action

import cn.fd.ratziel.core.Identifier
import cn.fd.ratziel.function.ArgumentContext
import cn.fd.ratziel.function.SimpleArgumentContext
import cn.fd.ratziel.module.item.api.trigger.TriggerType
import cn.fd.ratziel.script.api.ScriptEnvironment
import cn.fd.ratziel.script.impl.SimpleScriptEnv

/**
* Triggers
*
* @author TheFloodDragon
* @since 2024/8/13 14:29
*/
enum class Triggers(
override vararg val names: String,
val parent: TriggerType? = null
) : TriggerType {

// 攻击
ATTACK("onAttack", "onAtk", "attack", "atk"),

// 被损坏
BREAK("onBreak", "break"),

// 耐久损伤
DAMAGED("onDamaged","damaged", "onDamage", "damage"),

// 交互
INTERACT_LEFT_CLICK("onLeft", "left", "onLeftClick", "leftClick"),
INTERACT_RIGHT_CLICK("onLeft", "left", "onLeftClick", "leftClick"),
INTERACT_LEFT_CLICK_AIR("onLeftClickedAir", "left-air", "left-click-air", parent = INTERACT_LEFT_CLICK),
INTERACT_LEFT_CLICK_BLOCK("onLeftClickedBlock", "left-block", "left-click-block", parent = INTERACT_LEFT_CLICK),
INTERACT_RIGHT_CLICK_AIR("onRightClickedAir", "right-air", "right-click-air", parent = INTERACT_RIGHT_CLICK),
INTERACT_RIGHT_CLICK_BLOCK("onRightClickedBlock", "right-block", "right-click-block", parent = INTERACT_RIGHT_CLICK);

fun trigger(identifier: Identifier, context: ArgumentContext) {
// Trigger myself
ActionManager.trigger(identifier, this, context)
// Trigger parent
if (parent != null) ActionManager.trigger(identifier, parent, context)
}

fun trigger(identifier: Identifier, environment: ScriptEnvironment) = trigger(identifier, SimpleArgumentContext(environment))

fun trigger(identifier: Identifier, envAction: ScriptEnvironment.() -> Unit) = trigger(identifier, SimpleScriptEnv().also { envAction(it) })

}
Loading

0 comments on commit 85db481

Please sign in to comment.