You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在循环中为每个对象创建独立实例以区分同类型Challenge的完成状态

问题核心原因

你遇到的同类型Challenge状态混淆、进度不生效的核心问题出在状态存储的位置和逻辑错误,具体可以拆解为3个错误点:

  • 你把challengeHolderMap定义在for循环内部,每次遍历到新的Challenge时,上一轮循环创建的Map和Holder实例会直接被销毁,所有进度、完成状态根本没有持久保存,每次循环都是新建初始状态(进度1、未完成)的Holder,自然无法区分不同Challenge的状态。
  • 创建ChallengeHolder时进度写死为1,没有读取玩家的历史进度,也没有在触发收集行为时累加进度,逻辑上永远只能判断进度为1的情况。
  • 没有基于Challenge的唯一标识做区分,仅靠类型判断的话,同类型的不同Challenge会被判定为同一个,自然会出现完成一个就全部标记完成的问题。
修复方案

1. 先给Challenge类增加唯一标识

在你的Challenge类中新增唯一ID字段(比如自增ID或者唯一字符串ID),用来区分同类型的不同Challenge,示例:

public class Challenge {
    private String id; // 新增唯一标识,同类型的不同Challenge id不同
    private ChallengeType type;
    private int challengeCondition;
    // 其余原有字段和get/set方法
    public String getId() {
        return id;
    }
}

2. 调整ChallengeHolder缓存结构

把存储Holder的Map从循环内移到全局作用域(可以放在你的Plugin类或者ChallengeManager中作为成员变量),用双层Map结构保证每个玩家的每个Challenge对应唯一的Holder实例:

// 全局缓存定义:Key1=玩家UUID,Key2=Challenge唯一ID,Value=对应的Holder实例
private Map<UUID, Map<String, ChallengeHolder>> playerChallengeCache = new HashMap<>();

3. 重写循环逻辑

修正进度读取、更新、状态判断的逻辑:

// 先获取当前玩家的所有Challenge缓存,没有的话初始化
Map<String, ChallengeHolder> userChallengeMap = playerChallengeCache.computeIfAbsent(playerUUID, k -> new HashMap<>());

for (Challenge challenge : challengeList) {
    // 原有过滤逻辑保留
    if (plugin.getChallengeManager().canCompleteChallenge(playerUUID, challenge)
            || !plugin.getChallengeManager().isSameChallengeType(challenge, ChallengeType.COLLECT)) {
        continue;
    }

    String challengeId = challenge.getId();
    // 从缓存取当前Challenge对应的Holder,不存在则新建
    ChallengeHolder holder = userChallengeMap.computeIfAbsent(challengeId, k -> new ChallengeHolder(challenge, 0, false));
    
    // 已经完成的直接跳过
    if (holder.isCompleted()) {
        continue;
    }

    // 物品匹配判断保留
    ItemStack itemStack = new ItemStack(new ChallengeReplacer(plugin).replaceItemStack(holder.getChallenge()));
    if (!generatorItem.isSimilar(itemStack)) {
        continue;
    }

    // 匹配到对应物品,进度+1
    holder.setProgress(holder.getProgress() + 1);
    int currentProgress = holder.getProgress();
    int challengeCondition = challenge.getChallengeCondition();

    // 进度满足条件时标记完成
    if (currentProgress >= challengeCondition) {
        int challengeRemaining = plugin.getDatabaseManager().getChallengeRemaining(playerUUID, challenge);
        plugin.getChallengeManager().updateChallenge(playerUUID, challenge, (challengeRemaining - 1));
        holder.setCompleted(true);
    }
}
额外注意事项
  • 如果服务端重启后需要保留进度,需要把ChallengeHolder的进度和状态定期持久化到数据库,启动时再加载到缓存中即可。
  • 如果玩家完成Challenge后要重置进度,直接从userChallengeMap中移除对应Challenge的Key即可。

内容的提问来源于stack exchange,提问作者Ricardo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 07:15:04