feat(gvg): 矿场

This commit is contained in:
luying
2023-02-17 10:58:05 +08:00
parent b2b9404684
commit d805c19847
9 changed files with 483 additions and 64 deletions
+1
View File
@@ -1077,6 +1077,7 @@ export enum ITEM_CHANGE_REASON {
PLANT = 164, // 种田
PLANT_ROLLBACK = 165, // 种田的时候田已经被抢了回滚
HARVEST = 166, // 收获
MINE_END = 165, // 挖矿
}
export enum TA_EVENT {
+10
View File
@@ -317,6 +317,16 @@ export const STATUS = {
GVG_TECH_NOT_QUEUE: { code: 21311, simStr: '该科技不在解锁队列中' },
GVG_BATTLE_FEAT_NOT_ENOUGH: { code: 21312, simStr: '战功不足' },
GVG_CANNOT_HARVEST: { code: 21313, simStr: '暂不可收获' },
GVG_FIELD_NOT_FOUND: { code: 21314, simStr: '未找到该田' },
GVG_FIELD_HAS_LOCKED: { code: 21315, simStr: '该田已被其他人锁定' },
GVG_MINE_HAS_LOCKED: { code: 21316, simStr: '全联军挖矿次数达上限或挖矿位置被他人抢先' },
GVG_MINERAL_COUNT_OVER: { code: 21317, simStr: '上传铁矿含量超过配置上限' },
GVG_MINE_HAS_OVER: { code: 21318, simStr: '挖矿超时,已被他人抢先' },
GVG_MINE_SCOOP_OVER: { code: 21319, simStr: '挖矿量超过道具耐久' },
GVG_FORESTRY_HAS_OVER: { code: 21320, simStr: '伐木超时,已被他人抢先' },
GVG_ITEM_CANNOT_USE: { code: 21321, simStr: '此处不可使用这个道具' },
GVG_FORESTRY_HAS_HARVEST: { code: 21322, simStr: '本次伐木已结算过' },
GVG_MINE_HAS_HARVEST: { code: 21323, simStr: '本次挖矿已结算过' },
// 通用 30000 - 30099
DIC_DATA_NOT_FOUND: { code: 30000, simStr: '数据表未找到' },
+47 -9
View File
@@ -1,3 +1,5 @@
// 每个农庄/每个田一条记录,这个田被其他人用了之后会覆盖
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
import { getFutureTime, nowSeconds } from '../pubUtils/timeUtil';
@@ -25,23 +27,32 @@ export default class GVGLeagueFarm extends BaseModel {
fieldId: number; // 农庄id
@prop({ required: true })
unlockTime: number; // 解锁时间,打开界面时预锁定一批填,种下去之后锁定时间延长到收获时间
unlockTime: number; // 解锁时间,农场:打开界面时预锁定一批填,种下去之后锁定时间延长到收获时间,林场&矿场:开始小游戏时锁定时间
@prop({ required: true })
lockRoleId: string; // 锁定的人
@prop({ required: true })
harvestTime: number; // 收获时间,种植下去后将时间更新,收获之后设为0
harvestTime: number; // 收获时间,农庄:种植下去后将时间更新,收获之后设为0,林场&矿场:小游戏结束时更新
@prop({ required: true })
seedType: number; // 实际种的种子类型
seedType: number; // 仅农庄使用,实际种的种子类型
@prop({ required: true })
addType: number; // 种子加成
addType: number; // 仅农庄使用,种子加成
@prop({ required: true })
batchCode: string; // 批量号
@prop({ required: true })
itemId: number; // 仅矿山使用,使用的铲子id
@prop({ required: true })
output: number; // 产量,农庄:种下去时可以预估产量,林场&矿场:小游戏结束时根据结果更新
@prop({ required: true })
outputStr: string; // 产量计算公式
public static async findByType(configId: number, leagueCode: string, type: number) {
const result: GVGLeagueFarmType[] = await GVGLeagueFarmModel.find({ configId, leagueCode, type }).select('-_id').lean();
return result;
@@ -57,12 +68,16 @@ export default class GVGLeagueFarm extends BaseModel {
return result;
}
public static async findPlantedByFarmId(configId: number, leagueCode: string, farmId: number) {
const result: GVGLeagueFarmType[] = await GVGLeagueFarmModel.find({ configId, leagueCode, farmId, unlockTime: { $gte: nowSeconds() }, harvestTime: { $gte: nowSeconds() }}).select('-_id').lean();
return result;
}
public static async findByFieldIds(configId: number, leagueCode: string, farmId: number, fieldIds: number[]) {
const result: GVGLeagueFarmType[] = await GVGLeagueFarmModel.find({ configId, leagueCode, farmId, fieldId: { $in: fieldIds } }).select('-_id').lean();
return result;
}
/**
* 首次打开页面时锁定田
* @param configId
@@ -76,7 +91,7 @@ export default class GVGLeagueFarm extends BaseModel {
return { updateOne: { filter: { configId, leagueCode, farmId, fieldId }, update: { $setOnInsert: { unlockTime: 0, harvestTime: 0, seedType: 0, addType: 0 } }, upsert: true} }
}));
const result = await GVGLeagueFarmModel.bulkWrite(lands.map(({ fieldId, addType }) => {
return { updateOne: { filter: { configId, leagueCode, farmId, fieldId, unlockTime: { $lt: nowSeconds() } }, update: { $set: { addType, unlockTime: nowSeconds() + GVG.GVG_FARM_LOCK_TIME, lockRoleId: roleId } } } }
return { updateOne: { filter: { configId, leagueCode, farmId, fieldId, $or:[{ unlockTime: { $lt: nowSeconds() }}, {lockRoleId: roleId} ] }, update: { $set: { addType, unlockTime: nowSeconds() + GVG.GVG_FARM_LOCK_TIME, lockRoleId: roleId } } } }
}));
return result;
}
@@ -86,10 +101,10 @@ export default class GVGLeagueFarm extends BaseModel {
return result;
}
public static async plant(configId: number, leagueCode: string, farmId: number, fields: { fieldId: number, seedType: number, time: number }[], roleId: string) {
public static async plant(configId: number, leagueCode: string, farmId: number, fields: { fieldId: number, seedType: number, time: number, output: number, outputStr: string }[], roleId: string) {
const batchCode = genCode(10);
const result = await GVGLeagueFarmModel.bulkWrite(fields.map(({ fieldId, seedType, time }) => {
return { updateOne: { filter: { configId, leagueCode, farmId, fieldId, lockRoleId: roleId }, update: { $set: { seedType, unlockTime: getFutureTime(), harvestTime: nowSeconds() + time, batchCode }} } }
const result = await GVGLeagueFarmModel.bulkWrite(fields.map(({ fieldId, seedType, time, output, outputStr }) => {
return { updateOne: { filter: { configId, leagueCode, farmId, fieldId, lockRoleId: roleId }, update: { $set: { seedType, unlockTime: getFutureTime(), harvestTime: nowSeconds() + time, batchCode, output, outputStr }} } }
}));
if(result.modifiedCount == 0) return [];
const fieldResult: GVGLeagueFarmType[] = await GVGLeagueFarmModel.find({ batchCode }).sort({ fieldId: 1 }).select('-_id -createdAt -updatedAt -__v -configId -leagueCode').lean();
@@ -116,6 +131,29 @@ export default class GVGLeagueFarm extends BaseModel {
public static async releaseLock(configId: number, leagueCode: string, farmId: number, roleId: string) {
await GVGLeagueFarmModel.updateMany({ configId, leagueCode, farmId, lockRoleId: roleId }, { $set: { unlockTime: 0, lockRoleId: '' } });
}
public static async lockMineOrForestry(configId: number, leagueCode: string, farmId: number, type: number, roleId: string, fieldId: number, itemId: number) {
// 先创建
await GVGLeagueFarmModel.findOneAndUpdate({ configId, leagueCode, farmId, fieldId }, { $setOnInsert: { unlockTime: 0, itemId: 0, type } }, { upsert: true });
const result: GVGLeagueFarmType = await GVGLeagueFarmModel.findOneAndUpdate(
{ configId, leagueCode, farmId, fieldId, $or:[{ unlockTime: { $lt: nowSeconds() } }, {lockRoleId: roleId}] },
{ $set: { unlockTime: nowSeconds() + GVG.GVG_FARM_LOCK_TIME, lockRoleId: roleId, itemId } },
{ new: true }).lean();
return result;
}
public static async findByField(configId: number, leagueCode: string, farmId: number, fieldId: number) {
const result: GVGLeagueFarmType = await GVGLeagueFarmModel.findOne({ configId, leagueCode, farmId, fieldId }).lean();
return result;
}
public static async mineOrForestryEnd(configId: number, leagueCode: string, farmId: number, roleId: string, fieldId: number, output: number, outputStr: string) {
const result: GVGLeagueFarmType = await GVGLeagueFarmModel.findOneAndUpdate(
{ configId, leagueCode, farmId, fieldId, lockRoleId: roleId,unlockTime: { $gte: nowSeconds() } },
{ $set: { output, outputStr, unlockTime: getFutureTime(), harvestTime: nowSeconds() } },
{ new: true }).lean();
return result;
}
}
export const GVGLeagueFarmModel = getModelForClass(GVGLeagueFarm);
+72
View File
@@ -0,0 +1,72 @@
// 仅记录农场农田的记录,因为一块田可以反复被不同人种植、收获,不像矿场林场就是固定次数
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, } from '@typegoose/typegoose';
import { GVGLeagueFarmType } from './GVGLeagueFarm';
@index({ leagueCode: 1, configId: 1, farmId: 1, fieldId: 1 })
export default class GVGLeagueFarmRec extends BaseModel {
@prop({ required: true })
leagueCode: string; // 联军唯一code
@prop({ required: true })
configId: number;
@prop({ required: true })
farmId: number; // 农庄id
@prop({ required: true })
type: number; // 农庄类型
@prop({ required: true })
fieldId: number; // 农庄id
@prop({ required: true })
startRoleId: string; // 种田玩家/开始游戏玩家
@prop({ required: true })
startTime: Date; // 种值时间/开始时间
@prop({ required: false })
addType: number; // 种子加成
@prop({ required: false })
seedType: number; // 实际种的种子类型
@prop({ required: false })
itemId: number; // 实际种的种子类型
@prop({ required: false })
endRoleId: string; // 收获玩家/结束游戏玩家
@prop({ required: false })
endTime: Date; // 收获时间/结束时间
@prop({ required: false })
output: number; // 产量
@prop({ required: false })
outputStr: number; // 产量计算公式
public static async insertRecs(params: GVGLeagueFarmType[]) {
let insertParams = params.map(field => {
return { ...field, startRoleId: field.lockRoleId, startTime: new Date() }
})
await GVGLeagueFarmRecModel.insertMany(insertParams);
}
public static async updateRecs(params: GVGLeagueFarmType[], roleId: string) {
if(params.length == 0) return;
let { configId, leagueCode, farmId } = params[0];
let fieldIds = params.map(cur => cur.fieldId);
await GVGLeagueFarmRecModel.updateMany({ configId, leagueCode, farmId, fieldId: { $in: fieldIds } }, { $set: { endRoleId: roleId, endTime: new Date() } });
}
}
export const GVGLeagueFarmRecModel = getModelForClass(GVGLeagueFarmRec);
export interface GVGLeagueFarmRecType extends Pick<DocumentType<GVGLeagueFarmRec>, keyof GVGLeagueFarmRec> {
id: number;
};
export type GVGLeagueFarmRecUpdate = Partial<GVGLeagueFarmRecType>; // 将所有字段变成可选项
+2 -4
View File
@@ -42,16 +42,14 @@ export default class GVGUserItem extends BaseModel {
public static async decreaseItem(configId: number, leagueCode: string, roleId: string, items: RewardInter[]) {
const result = await GVGUserItemModel.bulkWrite(items.map(({ id, count }) => {
let filter = { configId, leagueCode, roleId, id, count: { $gte: count }, expireTime: { $gte: nowSeconds() } }
console.log('#### filter', filter, )
return { updateOne: { filter, update: { $inc: { count: -1 * count } } } }
}));
console.log(result.matchedCount, items.length)
return result.matchedCount == items.length;
}
public static async findByItem(configId: number, leagueCode: string, roleId: string, id: number) {
const result: GVGUserItemType = await GVGUserItemModel.findOne({ configId, leagueCode, roleId, id }).select('count').lean();
return result;
public static async checkItemCnt(configId: number, leagueCode: string, roleId: string, id: number, count: number) {
return await GVGUserItemModel.exists({ configId, leagueCode, roleId, id, count: { $gte: count } });
}
}
+6 -3
View File
@@ -90,6 +90,7 @@ export class GVGMainData {
setLeague(league: GVGLeagueType, serverNames: any) {
if(!league) return;
this.hasLeague = true;
this.leagueCode = league.leagueCode;
let leader = <RoleType>league.leader;
this.leader = new LeagueLeaderInfo(leader, serverNames);
this.name = league.name;
@@ -338,9 +339,11 @@ export class LeagueFarmMember {
this.count = fields.length;
this.harvestTime = Math.min(...fields.map(cur => cur.harvestTime))||0;
this.canHelp = !!fields.find(cur => cur.harvestTime < nowSeconds());
this.output = fields.reduce((pre, cur) => (pre + cur.output||0), 0);
}
setOutput(output: number) {
this.output = output;
setByMines(mines: GVGLeagueFarmType[]) {
this.count = mines.length;
this.output = mines.reduce((pre, cur) => (pre + cur.output||0), 0);
}
}
+2 -1
View File
@@ -385,7 +385,8 @@ export const GVG = {
GVG_ARMY_LEAGUE_TIME: 3, // GVG开启军团等级开启限制
GVG_ROLE_TYPE: '1&贤臣|2&猛将', // GVG中职能选择
GVG_SP_FIELD_ADD: 0.2,
GVG_FARM_LOCK_TIME: 180,
GVG_FIELD_TYPE_RATIO: '1&10|2&20|3&10',
GVG_SP_FIELD_RATIO: '30&60',
GVG_FARM_LOCK_TIME: 180,
GVG_MINE_LOCK_TIME: 180,
};