502 lines
11 KiB
JavaScript
502 lines
11 KiB
JavaScript
// 通用库存操作模块 (items, tals, equips)
|
||
const { getOrCreaterUser } = require('./auth');
|
||
|
||
const user_db_name = "cocos_users";
|
||
|
||
// 支持的数据类型
|
||
const SUPPORTED_TYPES = ['items', 'tals', 'equips'];
|
||
|
||
/**
|
||
* 验证数据类型
|
||
* @param {string} dataType 数据类型
|
||
* @returns {boolean} 是否有效
|
||
*/
|
||
function validateDataType(dataType) {
|
||
return SUPPORTED_TYPES.includes(dataType);
|
||
}
|
||
|
||
/**
|
||
* 获取库存数据
|
||
* @param {Object} db 数据库实例
|
||
* @param {string} openid 用户openid
|
||
* @param {string} dataType 数据类型 ('items', 'tals', 'equips')
|
||
* @returns {Object} 操作结果
|
||
*/
|
||
async function getInventory(db, openid, dataType) {
|
||
try {
|
||
if (!validateDataType(dataType)) {
|
||
return {
|
||
code: -3,
|
||
msg: `Invalid data type: ${dataType}`
|
||
};
|
||
}
|
||
|
||
let user = await getOrCreaterUser(db, openid);
|
||
if (!user) {
|
||
return {
|
||
code: -4,
|
||
msg: "User not found"
|
||
};
|
||
}
|
||
|
||
return {
|
||
code: 200,
|
||
data: user[dataType],
|
||
msg: `${dataType} retrieved successfully`
|
||
};
|
||
} catch (error) {
|
||
console.error(`Get ${dataType} error:`, error);
|
||
return {
|
||
code: -5,
|
||
msg: `Get ${dataType} error: ${error.message}`
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取单个物品数据
|
||
* @param {Object} db 数据库实例
|
||
* @param {string} openid 用户openid
|
||
* @param {string} dataType 数据类型
|
||
* @param {number} itemId 物品ID
|
||
* @returns {Object} 操作结果
|
||
*/
|
||
async function getInventoryItem(db, openid, dataType, itemId) {
|
||
try {
|
||
if (!validateDataType(dataType)) {
|
||
return {
|
||
code: -3,
|
||
msg: `Invalid data type: ${dataType}`
|
||
};
|
||
}
|
||
|
||
let user = await getOrCreaterUser(db, openid);
|
||
if (!user) {
|
||
return {
|
||
code: -4,
|
||
msg: "User not found"
|
||
};
|
||
}
|
||
|
||
const itemCount = user[dataType][itemId];
|
||
if (itemCount === undefined) {
|
||
return {
|
||
code: -6,
|
||
msg: `${dataType.slice(0, -1)} ${itemId} not found`
|
||
};
|
||
}
|
||
|
||
return {
|
||
code: 200,
|
||
data: {
|
||
item_id: itemId,
|
||
count: itemCount
|
||
},
|
||
msg: `${dataType.slice(0, -1)} ${itemId} retrieved successfully`
|
||
};
|
||
} catch (error) {
|
||
console.error(`Get ${dataType} item error:`, error);
|
||
return {
|
||
code: -5,
|
||
msg: `Get ${dataType} item error: ${error.message}`
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 添加物品
|
||
* @param {Object} db 数据库实例
|
||
* @param {string} openid 用户openid
|
||
* @param {string} dataType 数据类型
|
||
* @param {number} itemId 物品ID
|
||
* @param {number} count 添加数量
|
||
* @returns {Object} 操作结果
|
||
*/
|
||
async function addInventoryItem(db, openid, dataType, itemId, count) {
|
||
try {
|
||
if (!validateDataType(dataType)) {
|
||
return {
|
||
code: -3,
|
||
msg: `Invalid data type: ${dataType}`
|
||
};
|
||
}
|
||
|
||
const _ = db.command;
|
||
let user = await getOrCreaterUser(db, openid);
|
||
if (!user) {
|
||
return {
|
||
code: -4,
|
||
msg: "User not found"
|
||
};
|
||
}
|
||
|
||
if (typeof count !== 'number' || count < 0) {
|
||
return {
|
||
code: -3,
|
||
msg: "Count must be a non-negative number"
|
||
};
|
||
}
|
||
|
||
const currentCount = user[dataType][itemId] || 0;
|
||
const newCount = currentCount + count;
|
||
|
||
let updateRes = await db.collection(user_db_name).doc(user._id).update({
|
||
data: {
|
||
[`${dataType}.${itemId}`]: _.set(newCount),
|
||
last_save_time: _.set(Date.now())
|
||
}
|
||
});
|
||
|
||
if (updateRes?.stats?.updated >= 1) {
|
||
return {
|
||
code: 200,
|
||
data: {
|
||
item_id: itemId,
|
||
old_count: currentCount,
|
||
new_count: newCount,
|
||
added: count
|
||
},
|
||
msg: `${dataType.slice(0, -1)} ${itemId} added successfully`
|
||
};
|
||
} else {
|
||
return {
|
||
code: -1,
|
||
msg: `Add ${dataType.slice(0, -1)} fail`
|
||
};
|
||
}
|
||
} catch (error) {
|
||
console.error(`Add ${dataType} item error:`, error);
|
||
return {
|
||
code: -5,
|
||
msg: `Add ${dataType} item error: ${error.message}`
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 消耗物品
|
||
* @param {Object} db 数据库实例
|
||
* @param {string} openid 用户openid
|
||
* @param {string} dataType 数据类型
|
||
* @param {number} itemId 物品ID
|
||
* @param {number} count 消耗数量
|
||
* @returns {Object} 操作结果
|
||
*/
|
||
async function consumeInventoryItem(db, openid, dataType, itemId, count) {
|
||
try {
|
||
if (!validateDataType(dataType)) {
|
||
return {
|
||
code: -3,
|
||
msg: `Invalid data type: ${dataType}`
|
||
};
|
||
}
|
||
|
||
let user = await getOrCreaterUser(db, openid);
|
||
if (!user) {
|
||
return {
|
||
code: -4,
|
||
msg: "User not found"
|
||
};
|
||
}
|
||
|
||
if (typeof count !== 'number' || count < 0) {
|
||
return {
|
||
code: -3,
|
||
msg: "Count must be a non-negative number"
|
||
};
|
||
}
|
||
|
||
const currentCount = user[dataType][itemId] || 0;
|
||
if (currentCount < count) {
|
||
return {
|
||
code: -6,
|
||
msg: `Insufficient ${dataType.slice(0, -1)} ${itemId}, current: ${currentCount}, required: ${count}`
|
||
};
|
||
}
|
||
|
||
return await addInventoryItem(db, openid, dataType, itemId, -count);
|
||
} catch (error) {
|
||
console.error(`Consume ${dataType} item error:`, error);
|
||
return {
|
||
code: -5,
|
||
msg: `Consume ${dataType} item error: ${error.message}`
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 设置物品数量
|
||
* @param {Object} db 数据库实例
|
||
* @param {string} openid 用户openid
|
||
* @param {string} dataType 数据类型
|
||
* @param {number} itemId 物品ID
|
||
* @param {number} count 新的数量
|
||
* @returns {Object} 操作结果
|
||
*/
|
||
async function setInventoryItem(db, openid, dataType, itemId, count) {
|
||
try {
|
||
if (!validateDataType(dataType)) {
|
||
return {
|
||
code: -3,
|
||
msg: `Invalid data type: ${dataType}`
|
||
};
|
||
}
|
||
|
||
const _ = db.command;
|
||
let user = await getOrCreaterUser(db, openid);
|
||
if (!user) {
|
||
return {
|
||
code: -4,
|
||
msg: "User not found"
|
||
};
|
||
}
|
||
|
||
if (typeof count !== 'number' || count < 0) {
|
||
return {
|
||
code: -3,
|
||
msg: "Count must be a non-negative number"
|
||
};
|
||
}
|
||
|
||
const oldCount = user[dataType][itemId] || 0;
|
||
|
||
let updateRes = await db.collection(user_db_name).doc(user._id).update({
|
||
data: {
|
||
[`${dataType}.${itemId}`]: _.set(count),
|
||
last_save_time: _.set(Date.now())
|
||
}
|
||
});
|
||
|
||
if (updateRes?.stats?.updated >= 1) {
|
||
return {
|
||
code: 200,
|
||
data: {
|
||
item_id: itemId,
|
||
old_count: oldCount,
|
||
new_count: count
|
||
},
|
||
msg: `${dataType.slice(0, -1)} ${itemId} set successfully`
|
||
};
|
||
} else {
|
||
return {
|
||
code: -1,
|
||
msg: `Set ${dataType.slice(0, -1)} fail`
|
||
};
|
||
}
|
||
} catch (error) {
|
||
console.error(`Set ${dataType} item error:`, error);
|
||
return {
|
||
code: -5,
|
||
msg: `Set ${dataType} item error: ${error.message}`
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 批量更新库存
|
||
* @param {Object} db 数据库实例
|
||
* @param {string} openid 用户openid
|
||
* @param {string} dataType 数据类型
|
||
* @param {Object} updateData 更新数据对象
|
||
* @param {boolean} merge 是否合并更新(默认true)
|
||
* @returns {Object} 操作结果
|
||
*/
|
||
async function updateInventory(db, openid, dataType, updateData, merge = true) {
|
||
try {
|
||
if (!validateDataType(dataType)) {
|
||
return {
|
||
code: -3,
|
||
msg: `Invalid data type: ${dataType}`
|
||
};
|
||
}
|
||
|
||
const _ = db.command;
|
||
let user = await getOrCreaterUser(db, openid);
|
||
if (!user) {
|
||
return {
|
||
code: -4,
|
||
msg: "User not found"
|
||
};
|
||
}
|
||
|
||
// 验证更新数据
|
||
if (!updateData || typeof updateData !== 'object') {
|
||
return {
|
||
code: -3,
|
||
msg: "Invalid update data format"
|
||
};
|
||
}
|
||
|
||
// 验证所有值都是非负数
|
||
for (const itemId in updateData) {
|
||
const count = updateData[itemId];
|
||
if (typeof count !== 'number' || count < 0) {
|
||
return {
|
||
code: -3,
|
||
msg: `Invalid count for item ${itemId}: ${count}`
|
||
};
|
||
}
|
||
}
|
||
|
||
let newData;
|
||
if (merge) {
|
||
// 合并更新
|
||
newData = { ...user[dataType], ...updateData };
|
||
} else {
|
||
// 完全替换
|
||
newData = updateData;
|
||
}
|
||
|
||
let updateRes = await db.collection(user_db_name).doc(user._id).update({
|
||
data: {
|
||
[dataType]: _.set(newData),
|
||
last_save_time: _.set(Date.now())
|
||
}
|
||
});
|
||
|
||
if (updateRes?.stats?.updated >= 1) {
|
||
return {
|
||
code: 200,
|
||
data: newData,
|
||
msg: `${dataType} updated successfully`
|
||
};
|
||
} else {
|
||
return {
|
||
code: -1,
|
||
msg: `Update ${dataType} fail`
|
||
};
|
||
}
|
||
} catch (error) {
|
||
console.error(`Update ${dataType} error:`, error);
|
||
return {
|
||
code: -5,
|
||
msg: `Update ${dataType} error: ${error.message}`
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 重置库存数据
|
||
* @param {Object} db 数据库实例
|
||
* @param {string} openid 用户openid
|
||
* @param {string} dataType 数据类型
|
||
* @returns {Object} 操作结果
|
||
*/
|
||
async function resetInventory(db, openid, dataType) {
|
||
try {
|
||
if (!validateDataType(dataType)) {
|
||
return {
|
||
code: -3,
|
||
msg: `Invalid data type: ${dataType}`
|
||
};
|
||
}
|
||
|
||
const _ = db.command;
|
||
const { getNewUserInitData } = require('../user_init_data');
|
||
let user = await getOrCreaterUser(db, openid);
|
||
if (!user) {
|
||
return {
|
||
code: -4,
|
||
msg: "User not found"
|
||
};
|
||
}
|
||
|
||
const defaultData = getNewUserInitData();
|
||
|
||
let resetRes = await db.collection(user_db_name).doc(user._id).update({
|
||
data: {
|
||
[dataType]: _.set(defaultData[dataType]),
|
||
last_save_time: _.set(Date.now()),
|
||
reset_time: _.set(Date.now())
|
||
}
|
||
});
|
||
|
||
if (resetRes?.stats?.updated >= 1) {
|
||
return {
|
||
code: 200,
|
||
data: defaultData[dataType],
|
||
msg: `${dataType} reset successfully`
|
||
};
|
||
} else {
|
||
return {
|
||
code: -1,
|
||
msg: `Reset ${dataType} fail`
|
||
};
|
||
}
|
||
} catch (error) {
|
||
console.error(`Reset ${dataType} error:`, error);
|
||
return {
|
||
code: -5,
|
||
msg: `Reset ${dataType} error: ${error.message}`
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取拥有的物品列表(数量大于0的)
|
||
* @param {Object} db 数据库实例
|
||
* @param {string} openid 用户openid
|
||
* @param {string} dataType 数据类型
|
||
* @returns {Object} 操作结果
|
||
*/
|
||
async function getOwnedItems(db, openid, dataType) {
|
||
try {
|
||
if (!validateDataType(dataType)) {
|
||
return {
|
||
code: -3,
|
||
msg: `Invalid data type: ${dataType}`
|
||
};
|
||
}
|
||
|
||
let user = await getOrCreaterUser(db, openid);
|
||
if (!user) {
|
||
return {
|
||
code: -4,
|
||
msg: "User not found"
|
||
};
|
||
}
|
||
|
||
const ownedItems = [];
|
||
for (const itemId in user[dataType]) {
|
||
const count = user[dataType][itemId];
|
||
if (count > 0) {
|
||
ownedItems.push({
|
||
item_id: parseInt(itemId),
|
||
count: count
|
||
});
|
||
}
|
||
}
|
||
|
||
return {
|
||
code: 200,
|
||
data: {
|
||
owned_items: ownedItems,
|
||
total_types: ownedItems.length
|
||
},
|
||
msg: `Owned ${dataType} retrieved successfully`
|
||
};
|
||
} catch (error) {
|
||
console.error(`Get owned ${dataType} error:`, error);
|
||
return {
|
||
code: -5,
|
||
msg: `Get owned ${dataType} error: ${error.message}`
|
||
};
|
||
}
|
||
}
|
||
|
||
module.exports = {
|
||
getInventory,
|
||
getInventoryItem,
|
||
addInventoryItem,
|
||
consumeInventoryItem,
|
||
setInventoryItem,
|
||
updateInventory,
|
||
resetInventory,
|
||
getOwnedItems,
|
||
SUPPORTED_TYPES
|
||
};
|
||
|
||
|
||
|
||
|