Skip to content

成就插件 (AchievementAPI)

本API允许其他插件动态地注册成就,或主动为用户解锁成就。

1. 获取API实例

首先,在你的插件主类的 __init__ 方法中,通过 shared_services 获取API实例。强烈建议使用异步等待函数来确保获取成功。

python
import asyncio
from ..common.services import shared_services
# ...

class YourOtherPlugin(Star):
    def __init__(self, context: Context, config: AstrBotConfig):
        super().__init__(context)
        self.achievement_api = None
        asyncio.create_task(self.initialize_apis())

    async def initialize_apis(self):
        self.achievement_api = await self.wait_for_api("achievement_api")
        if self.achievement_api:
            logger.info("成功连接到成就系统API。")
        else:
            logger.warning("未能连接到成就系统API,相关功能将受限。")
    
    async def wait_for_api(self, api_name: str, timeout: int = 30):
        # ... (通用API等待函数的实现) ...

2. API 方法详解

async def register_achievement(...) -> (bool, str)

在插件启动或特定时机,向成就系统动态注册一个新成就。

  • 参数:

    • owner_plugin (str): 你的插件名称,如 "shop_plugin"
    • ach_id (str): 成就的全局唯一ID,如 "shop_first_legendary_item"
    • title (str): 成就的显示名称,如 "传说中的工匠"
    • description (str): 成就的描述,如 "第一次购买了传说品质的物品。"
    • icon_path (str): 成就图标的绝对路径相对于AstrBot根目录的路径
    • rarity (str): 稀有度,依次递增为 rarity_list = ['common', 'rare', 'epic', 'legendary', 'mythic', 'miracle', 'flawless']
    • reward_coins (int): (可选) 奖励的金币数量,默认为 0
    • check_func (Callable): (可选) 一个异步检查函数,用于被动检查。如果你的成就只需要主动解锁,此项可为 None
    • "unique":(可选)是否为唯一成就,该成就被首次解锁后不再可被触发。
    • hidden (bool): (可选) 是否为隐藏成就,默认为 False。隐藏成就只有在解锁后才对用户可见。
  • 返回: (bool, str) - 一个元组,(是否成功, 附带信息)

  • 示例:

    python
    # 在你的插件的某个初始化逻辑里
    if self.achievement_api:
        success, message = await self.achievement_api.register_achievement(
            owner_plugin="my_shop_plugin",
            ach_id="buy_sword",
            title="剑术大师",
            description="在商店购买了第一把剑。",
            icon_path="data/plugins/my_shop_plugin/assets/sword_icon.png",
            rarity="rare",
            reward_coins=200
        )
        if success:
            logger.info("自定义商店成就注册成功!")
        else:
            logger.error(f"商店成就注册失败: {message}")

async def unlock_achievement(user_id: str, achievement_id: str, event: Optional[AstrMessageEvent] = None) -> bool

当你的插件内部逻辑判断用户达成了某个条件时,调用此方法为用户立即解锁一个成就。

  • 参数:

    • user_id (str): 目标用户的ID。
    • achievement_id (str): 要解锁的成就的ID。
    • event (Optional[AstrMessageEvent]): 非常重要
      • 如果你传入了当前事件的 event 对象,插件会自动为用户发送解锁通知(合并转发消息)。
      • 如果你不传入 (或传入 None),插件将静默解锁,只记录数据和发放奖励,不发送任何通知。
  • 返回: bool - True 表示成功解锁, False 表示用户之前已解锁或成就ID不存在。

  • 示例 (在你的某个指令处理器中):

    python
    # 假设这是一个购买物品的指令
    @filter.command("buy")
    async def buy_item(self, event: AstrMessageEvent, item_name: str):
        # ... 购买逻辑 ...
        
        # 假设用户购买了“圣剑”,我们想立即为他解锁成就
        if item_name == "圣剑" and self.achievement_api:
            user_id = event.get_sender_id()
            
            # 调用API,传入event对象以发送通知
            was_unlocked = await self.achievement_api.unlock_achievement(
                user_id=user_id,
                achievement_id="buy_sword",
                event=event 
            )
            
            if was_unlocked:
                logger.info(f"用户 {user_id} 通过主动调用API解锁了成就 buy_sword。")