目标系统学习笔记

抽象模型

目标

public class Target {
    // 任务目标类型
    private TargetType targetType;

    // 任务目标值
    private TargetType targetType;

    // 任务进度值
    private int count;

    // 目标组索引
    private transient int index;

    // 获取配置信息
    private transient ITargetDefGetter defGetter;

    // 目标进度变化以后的通知接口
    private transient Consumer<Target> updateNotify;

    public Target() {

    }

    public Target() {
        this.targetType = targetType;
    }

    // 任务目标是否达到
    @JSONField(serialize = false)
    public boolean isComplete() {
        return count >= getValue();
    }


    // 进度+1
    @JSONField(serialize = false)
    public void addCount() {
        count += 1;
    }

    // 通过索引取出目标配置
    @JSONField(serialize = false)
    public TargetDef getDef() {
        return defGetter.get(index);
    }

    @JSONField(serialize = false)
    public int getValue() {
        return getDef().getValue();
    }
}

目标配置

public class TargetDef implements IResourceCheck {
    // 目标类型
    private TargetType type;
    // 目标参数
    private TargetParamContext params = new TargetParamContext();
    // 目标值
    private int value;

    @Override
    public void check() {
        type.check(this);
    }
}

目标参数全量表


public class TargetParamContext {
    // 装备物品
    private EquipStorageType storageType;
    private EquipmentPosition equipmentPosition;

    // 装备等级
    private int equipLevel;

    // 道具列表
    private List<Integer> itemList;

    //........... 后面还有很多
}

目标进度

public interface TargetProgress {
    // 正在进行
    int progress = 0;
    // 已完成
    int complete = 1;
}

目标类型 TargetType

@Desc("目标类型")
public enum TargetType implements EnumReadable {
    @Desc("等级")
    LEVEL(1),
    @Desc("杀怪")
    MONSTER_HUNT(2) {
        @Override
        protected void checkParam(TargetParamContext targetParamContext) {

        }
    },
    @Desc("进入地图")
    ENTER_SCENE(5),
    @Desc("加入公会")
    JOIN_GUILD(3),
    @Desc("获取物品")
    GAIN_CHEST(9),

    //........... 后面还有很多

    // 检测参数配置

}

目标处理器基类 BaseTargetHandler

public abstract class BaseTargetHandler {
    private static Map<TargetType, BaseTargetHandler> handlers = new HashMap<>();

    public static BaseTargetHandler getHandler(TargetType type) {
        return handlers.get(type);
    }

    @PostConstrcut
    public void init() {
        if(handlers.containsKey(getType())) {
            throw new RuntimeException(String.format("questTargetHandler type[%s]重复!"), getType());
        }
        handlers.put(getType(),this);
    }


    // 获取目标类型
    public abstract TargetType getType();

    // 更新目标进度
    protected void progress(Player player, BitConsumer<Target, TargetDef> updater) {
        try{
            List<Target> targets = player.getTargetsByType(getType());
            for(Target target : targets) {
                TargetManager.self().updateTarget(player, target, updater);
            }
        } catch(Exception e) {
            logger.error("更新目标进度异常",e)
        }
    }


    // 活人是否无效
    protected boolean checkAcitvityUnValid(TargetDef targetDef) {
        int actId = targetDef.getParams().getActivityId();
        if(actId > 0) {
            return !ActivityPlayerManager.self().checkActivityProgress();
        } else {
            return false;
        }
    }
}

目标管理器 TargetManager

创建目标,并监听目标完成状态

public Targets createTargetsAndWatch(Player player, List<TargetDef> list, ITargetDefGetter defGetter, Consumer<Target> updateNotify)  {
    if(list == null) {
        return new Targets(null);
    }
    List<Target> targetList = new ArrayList<>(list.size());
    for(TargetDef targetDef : list) {
        Target target = new Target
    }
    List<Target> targetList = new ArrayList<>(list.size());
    for(TargetDef targetDef : list) {
        Target targetList = new Target(targetDef.getType());
        targetList.add(target);
    }
    Targets targets = new Targets(targetList);
    watch(player, targets, defGetter, updateNotify);
    return targets;
}

开始监控目标进度(参数是目标组)

public void watch(Player player, Targets targets, ITargetDefGetter defGetter, Consumer<Target> updateNotify) {
    List<Target> targetList = targets.getTargets();
    if(targetList == null) {
        return;
    }
    for(int i=0; i< targetList.size(); i++) {
        Target target = targetList.get(i);
        // 标记索引
        target.setIndex(i);
        watch(player, target, defGetter, updateNotify);
    }
}

开始监控目标进度(参数是目标)

public void watch(Player player, Target target, ITargetDefGetter defGetter, Consumer<Target> updateNotify) {
    target.setDefGetter(defGetter);
    target.setUpdateNotify(updateNotify);

    player.getTargetsByType(target.getTargetType()).add(target);

    BaseTargetHandler questTargetHandler = target.getTargetType().getQuestTargetHandler();
    if(questTargetHandler == null) {
        throw new NullPointerException("not found questTargetHandler "+ target.getTargetType());
    }

    questTargetHandler.checkOnStaerWatch(target, player);

    if(target.isComplete()) {
        // 目标完成,移出目标监听
        unWatch(player, target);
    }
}

移除进度监控(目标组)

public void unWatch(Player player, Targets targets) {
    List<Target> targetList = targets.getTargets();
    if(targetList == null) {
        return;
    }
    for(Target target: targetList) {
        unWatch(player, target);
    }
}

移除进度监控(目标)

public void unWatch(Player player, Targets target) {
    player.getTargetsByType(target.getTargetType()).remove(target);
}

更新目标进度

public void updateTarget(Player player, Target target, BiConsumer<Target, TargetDef> updater) {
    TargetDef targetDef = null;
    try {
        targetDef = target.getDef();
    } catch (Exception e) {
        LOGGER.error(String.format("get targetDef error! %s -> index %d", target.getDefGetter(), target.getIndex()), e));
    }
    if(targetDef == null) {
           LOGGER.error(String.format("get targetDef null! %s -> index %d", target.getDefGetter(), target.getIndex()));
           returm;
    }
    int oldCont = target.getCount();
    updater.accept(target, targetDef);
    if(oldCount != target.getCount()) {
        // 进度发生变化
        target.getUpdateNotify().accept(target);

        if(target.isComplete()) {
            // 目标完成,移除目标监听
            unWatch(player,target);
        }
    }
}