用户:
Nomen查看: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
Nomen经测试,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
评论