猫史档案馆


整活)NomenItemStack:快捷管理物品栈/背包,具有堆叠上限和全map操作

用户:NomenNomen查看:1 回复:6 评论:1 创建时间:2023-07-14T04:52:15


这里是没有开场白的Nomen,最近在帮忙整地图的时候发现背包太难写了,由于我这个人很懒,所以我就顺手写了一个背包全操作,包括自定义堆叠上线(参考mc的物品栈),增加自定义物品之类的,同时还支持enough-是否有足够物品,全部map方法,以及自带迭代器,entries,keys,foreach之类的

(碎碎念:其实物品栈不是栈)

NomenItemStack@1.0.0

/**
 * @typedef {object} NomenItemStackItem
 * @property {string | number} id 相同id的物品可以堆叠,依靠id查找
 * @property {number} num 数量
 * @property {boolean} canStack 是否能堆叠
 */
/**
 * @typedef {object} NomenItemStackConfig
 * @property {number | undefined} maxItem
 */


class NomenItemStack {
    /**
     * @param {NomenItemStackItem[] | undefined} is 
     * @param {NomenItemStackConfig | undefined} config
     */
    constructor(is, config) {
        if (!is) is = [];
        if (!config) config = {};
        this.IS=this.parse(is) || [];
        this.maxItem = config.maxItem || 喵;
    }

    /**@param {NomenItemStackItem|string} is  */
    parse(is) {
        function check(l) {
            if (Array.isArray(l)) {
                return l.filter(v => v.id !== undefined);
            };
            return null;
        }
        if (typeof is == "string") {
            try {
                return check(JSON.parse(is))
            } catch {
                return null;
            }
        };
        return check(is);
    }

    /**@param {NomenItemStackItem} item  */
    add(item,_skip) {
        if (item.canStack !== undefined && !item.canStack) {
            for (let i = 0; i < item.num; i++) {
                this.IS.push({ ...item, num: 1 });
            }
            return;
        }
        if (this.IS.filter(v => v.id == item.id).length && _skip !== true) {
            let l = item.num, r = this.IS.filter(v => v.id == item.id);
            for (let i = 0; i < r.length; i++) {
                if (l <= 0) return;
                if (r[i].num + l > this.maxItem) {
                    l -= this.maxItem - r[i].num;
                    r[i].num += this.maxItem - r[i].num;
                } else {
                    l = 0;
                    r[i].num += l;
                    return;
                }
            };
            this,this.add({...item,num:l},true)
        } else {
            if (item.num > this.maxItem) {
                let r = (item.num - (item.num % this.maxItem)) / this.maxItem;
                for (let i = 0; i < r; i++) {
                    this.IS.push({
                        ...item,
                        num: this.maxItem
                    });
                };
                if (item.num % this.maxItem) {
                    this.IS.push({
                        ...item,
                        num: item.num % this.maxItem
                    });
                }
            }
            else {
                this.IS.push({
                    ...item,
                    num: item.num
                });
            }

        }
    }

    num(id) {
        if (!this.get(id).length) return false;
        return this.IS
            .filter(v => v.id == id)
            .map(v => v.num)
            .filter(v => typeof v == "number")
            .reduce((a, b) => a + b, 0);
    }

    enough(id, num) {
        if (!this.get(id).length) return false;
        return this.num(id) >= num;
    }

    remove(id, num) {
        if (!this.enough(id, num)) return false;
        let l = num, r = this.get(id), td = [];
        for (let d of r) {
            if (d.num > l) {
                d.num -= l;
                this.IS = this.IS.filter(v => v.num > 0)
                return true;
            } else {
                l -= d.num;
                d.num = 0;
                if (l == 0) {
                    this.IS = this.IS.filter(v => v.num > 0)
                    return true;
                }
            }
        }
    }

    has(id) {
        return !!this.IS.filter(v => v.id == id).length;
    }
    get(id) {
        return this.IS.filter(v => v.id == id);
    }
    entries() {
        return [Object.keys(this._gen()), Object.values(this._gen())];
    }
    forEach(c) {
        return this.IS.forEach(c);
    }
    delete(id) {
        this.IS = this.IS.filter(v => v.id != id);
    }
    keys() {
        return Object.keys(this._gen())
    }
    values() {
        return Object.values(this._gen())
    }
    clear() {
        this.IS = [];
    }
    _gen() {
        let output = {};
        this.IS.forEach(v => {
            if (output[v.id]) {
                output[v.id] += v.num;
            } else {
                output[v.id] = v;
            }
        });
        return output;
    }
}

示例代码:

let nis = new NomenItemStack([/* 这里是一个数组,可以是一些初始化内容 ?NomenItemStackItem[]*/],{
    maxItem: 16
});
nis.add({
    id:"awa",
    num:34
});
// 添加32个物品awa,id必须是足以标识这个物品的,可以是string或number或symbol

nis.remove("awa",5);
// 移除5个awa

nis.enough("awa",33);
// 物品栈内是否有足够的awa

nis.delete("awa");
// 删除所有的awa

nis.has("awa");
// 是否有awa

// ...以及全部支持的map操作,还有迭代器例如forEach, keys, values, entries


回复

上一页1 页 / 共 1下一页
NomenNomen

照例沙发

点赞0


评论


NomenNomen

经测试,add方法存在问题,请修改为如下函数:

/**@param {NomenItemStackItem} item  */
    add(item, _skip) {
        if (item.canStack !== undefined && !item.canStack) {
            for (let i = 0; i < item.num; i++) {
                this.IS.push({ ...item, num: 1 });
            }
            return;
        }
        if (this.IS.filter(v => v.id == item.id).length && _skip !== true) {
            let l = item.num, r = this.IS.filter(v => v.id == item.id);
            for (let i = 0; i < r.length; i++) {
                if (l <= 0) return;
                if (r[i].num + l > this.maxItem) {
                    l -= this.maxItem - r[i].num;
                    r[i].num += this.maxItem - r[i].num;
                } else {
                    r[i].num += l;
                    l = 0;
                    return;
                }
            };
            this, this.add({ ...item, num: l }, true)
        } else {
            if (item.num > this.maxItem) {
                let r = (item.num - (item.num % this.maxItem)) / this.maxItem;
                for (let i = 0; i < r; i++) {
                    this.IS.push({
                        ...item,
                        num: this.maxItem
                    });
                };
                if (item.num % this.maxItem) {
                    this.IS.push({
                        ...item,
                        num: item.num % this.maxItem
                    });
                }
            }
            else {
                this.IS.push({
                    ...item,
                    num: item.num
                });
            }

        }
    }

或前往Box3Tools仓库更新至NomenItemStack 1.0.1

github.com/helloyork/Box3-Tools/tree/main/src/%E6%95%B0%E6%8D%AE%E5%A4%84%E7%90%86%E5%B7%A5%E5%85%B7/NomenItemStack

点赞0


评论


烟魂烟魂

继续帮你优化布局。。。

点赞0


评论


烟魂烟魂

不对啊。。。

不是有网站吗?

 

点赞0


评论


小屑鹿小屑鹿

👀

点赞0


评论


囧仙_official囧仙_official

直接自己写吧(汗)

点赞0


评论