Merge branch 'main' of https://github.com/Crepe-Inc/CrepeSR
This commit is contained in:
commit
1f2b9f5726
@ -17,8 +17,8 @@ export default async function handle(command: Command) {
|
||||
|
||||
let count: number = 1;
|
||||
let level: number = 1;
|
||||
let rank: number = 1;
|
||||
let promotion: number = 1;
|
||||
let rank: number = 0;
|
||||
let promotion: number = 0;
|
||||
|
||||
for (let i = 2; i < command.args.length; i++) {
|
||||
const arg = command.args[i];
|
||||
@ -52,6 +52,9 @@ export default async function handle(command: Command) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Sync session.
|
||||
await player.session.sync();
|
||||
}
|
||||
|
||||
async function handleGive(player: Player, itemId: number, count:number, level: number, rank: number, promotion: number) {
|
||||
@ -96,7 +99,10 @@ async function handleGiveAll(player: Player) {
|
||||
const inventory = await player.getInventory();
|
||||
|
||||
for (const entry of ItemExcel.all()) {
|
||||
const count = entry.ItemType == "Material" ? 100 : 1;
|
||||
const count =
|
||||
(entry.ItemType == "Material") ? 1000 :
|
||||
(entry.ItemType == "Virtual") ? 10_000_000 :
|
||||
1;
|
||||
await inventory.addItem(entry.ID, count);
|
||||
}
|
||||
|
||||
|
@ -20,11 +20,9 @@ export default async function handle(command: Command) {
|
||||
|
||||
if (!planeID) return c.log("Usage: /scene <planeID>");
|
||||
|
||||
Interface.target.player.db.posData = {
|
||||
floorID: planeID.StartFloorID,
|
||||
planeID: planeID.PlaneID,
|
||||
pos: Interface.target.player.db.posData.pos
|
||||
};
|
||||
// Update scene information on player.
|
||||
Interface.target.player.db.posData.planeID = planeID!.PlaneID;
|
||||
Interface.target.player.db.posData.floorID = planeID!.StartFloorID;
|
||||
await Interface.target.player.save()
|
||||
|
||||
//ty for tamilpp25 scene
|
||||
|
@ -49,9 +49,9 @@ export default class Avatar {
|
||||
baseAvatarId: 1001,
|
||||
avatarType: AvatarType.AVATAR_FORMAL_TYPE,
|
||||
level: 1,
|
||||
exp: 1,
|
||||
promotion: 1,
|
||||
rank: 1,
|
||||
exp: 0,
|
||||
promotion: 0,
|
||||
rank: 0,
|
||||
equipmentUniqueId: 20003,
|
||||
equipRelicList: [],
|
||||
skilltreeList: [],
|
||||
@ -111,9 +111,9 @@ export default class Avatar {
|
||||
baseAvatarId: baseAvatarId,
|
||||
avatarType: AvatarType.AVATAR_FORMAL_TYPE,
|
||||
level: 1,
|
||||
exp: 1,
|
||||
promotion: 1,
|
||||
rank: 1,
|
||||
exp: 0,
|
||||
promotion: 0,
|
||||
rank: 0,
|
||||
equipmentUniqueId: 20003,
|
||||
equipRelicList: [],
|
||||
skilltreeList: [],
|
||||
|
@ -101,13 +101,24 @@ export default class Inventory {
|
||||
}
|
||||
|
||||
switch (itemData.ItemType) {
|
||||
case "Virtual": return 0; // ToDo: Handle virtual items.
|
||||
case "Virtual": return this.getVirtualItemCount(id);
|
||||
case "Material": return this.db.materials[id] ?? 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private getVirtualItemCount(id: number) : number {
|
||||
// ToDo: Figure out which virtual item ID is what.
|
||||
switch (id) {
|
||||
case 2:
|
||||
return this.player.db.basicInfo.scoin;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
Add items to the inventory.
|
||||
********************************************************************************/
|
||||
@ -151,6 +162,14 @@ export default class Inventory {
|
||||
*/
|
||||
public async addVirtualItem(id: number, count: number) {
|
||||
// ToDo: Figure out which virtual item ID is what.
|
||||
switch (id) {
|
||||
case 2:
|
||||
this.player.db.basicInfo.scoin += count;
|
||||
break;
|
||||
}
|
||||
|
||||
// Save.
|
||||
this.player.save();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,7 +43,11 @@ interface PlayerI {
|
||||
posData: {
|
||||
floorID: number;
|
||||
planeID: number;
|
||||
pos: Vector;
|
||||
pos: {
|
||||
x: number,
|
||||
y: number,
|
||||
z: number
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,7 +56,7 @@ export default class Player {
|
||||
public readonly scene: Scene;
|
||||
private inventory!: Inventory;
|
||||
|
||||
private constructor(readonly session: Session, public db: PlayerI) {
|
||||
private constructor(readonly session: Session, public readonly db: PlayerI) {
|
||||
this.uid = db._id;
|
||||
this.scene = new Scene(this);
|
||||
}
|
||||
@ -133,13 +137,13 @@ export default class Player {
|
||||
heroBasicType: HeroBasicType.BoyWarrior,
|
||||
basicInfo: {
|
||||
exp: 0,
|
||||
level: 1,
|
||||
level: 70,
|
||||
hcoin: 0,
|
||||
mcoin: 0,
|
||||
nickname: acc.name,
|
||||
scoin: 0,
|
||||
stamina: 100,
|
||||
worldLevel: 1,
|
||||
stamina: 180,
|
||||
worldLevel: 6,
|
||||
},
|
||||
lineup: {
|
||||
curIndex: 0,
|
||||
@ -155,34 +159,25 @@ export default class Player {
|
||||
}
|
||||
},
|
||||
banned: false
|
||||
} as PlayerI
|
||||
|
||||
const baseLineup = {
|
||||
avatarList: [1001],
|
||||
extraLineupType: ExtraLineupType.LINEUP_NONE,
|
||||
index: 0,
|
||||
isVirtual: false,
|
||||
leaderSlot: 0,
|
||||
mp: 100, // ?? Not sure what this is
|
||||
name: "",
|
||||
planeId: 10001
|
||||
}
|
||||
} as PlayerI;
|
||||
|
||||
const LINEUPS = 6;
|
||||
for (let i = 0; i < LINEUPS; i++) {
|
||||
const copy = {
|
||||
...baseLineup,
|
||||
const l : LineupI = {
|
||||
avatarList: [1001],
|
||||
extraLineupType: ExtraLineupType.LINEUP_NONE,
|
||||
index: i,
|
||||
name: `Team ${i}`
|
||||
isVirtual: false,
|
||||
leaderSlot: 0,
|
||||
mp: 100,
|
||||
name: `Team ${i}`,
|
||||
planeId: 10001
|
||||
};
|
||||
dataObj.lineup.lineups[i] = copy;
|
||||
dataObj.lineup.lineups[i] = l;
|
||||
}
|
||||
|
||||
const player = new Player(session, dataObj);
|
||||
|
||||
await Avatar.addAvatarToPlayer(player, 1001);
|
||||
// await Avatar.create(uid, 1001, 0);
|
||||
|
||||
|
||||
// Save to database and return.
|
||||
await db.set("players", dataObj);
|
||||
|
88
src/server/packets/AvatarExpUpCsReq.ts
Normal file
88
src/server/packets/AvatarExpUpCsReq.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import { AvatarExpUpCsReq, AvatarExpUpScRsp } from "../../data/proto/StarRail";
|
||||
import Avatar from "../../db/Avatar";
|
||||
import { PayItemData } from "../../db/Inventory";
|
||||
import AvatarExcel from "../../util/excel/AvatarExcel";
|
||||
import AvatarExpItemExcel from "../../util/excel/AvatarExpItemExcel";
|
||||
import AvatarPromotionExcel from "../../util/excel/AvatarPromotionExcel";
|
||||
import ExpTypeExcel from "../../util/excel/ExpTypeExcel";
|
||||
import Packet from "../kcp/Packet";
|
||||
import Session from "../kcp/Session";
|
||||
|
||||
export default async function handle(session: Session, packet: Packet) {
|
||||
const body = packet.body as AvatarExpUpCsReq;
|
||||
const inventory = await session.player.getInventory();
|
||||
|
||||
// Get the target avatar.
|
||||
const avatarId = body.baseAvatarId;
|
||||
const avatar = await Avatar.loadAvatarForPlayer(session.player, avatarId);
|
||||
const avatarExcelData = AvatarExcel.fromId(avatarId);
|
||||
|
||||
// Determine the next level cap based on the avatar's current promotion.
|
||||
const levelCap = AvatarPromotionExcel.fromId(`${avatarId}:${avatar.db.promotion}`).MaxLevel;
|
||||
|
||||
// Determine the EXP we get from the consumed items.
|
||||
let exp = 0;
|
||||
const costMaterialList = [];
|
||||
for (const item of body.itemCost!.itemList) {
|
||||
// Determine amount of EXP given by that item.
|
||||
// We know that the cost items given in this Req will be `PileItem`s.
|
||||
const expPerItem = AvatarExpItemExcel.fromId(item.pileItem!.itemId).Exp;
|
||||
|
||||
// Add EXP for the number of items consumed.
|
||||
exp += expPerItem * item.pileItem!.itemNum;
|
||||
|
||||
// Add material to cost.
|
||||
costMaterialList.push({ id: item.pileItem!.itemId, count: item.pileItem!.itemNum } as PayItemData);
|
||||
}
|
||||
|
||||
// Determine cost, which is always 10% of EXP, and add to the list of cost materials.
|
||||
const coinCost = exp * 0.1;
|
||||
costMaterialList.push({ id: 2, count: coinCost } as PayItemData);
|
||||
|
||||
// Try consuming materials.
|
||||
const success = await inventory.payItems(costMaterialList);
|
||||
if (!success) {
|
||||
// ToDo: Correct retcode.
|
||||
session.send(AvatarExpUpScRsp, { retcode: 1, returnItemList: [] } as AvatarExpUpScRsp);
|
||||
return;
|
||||
}
|
||||
|
||||
await inventory.save();
|
||||
|
||||
// Cost has been paid - now level up.
|
||||
let currentAvatarExp = avatar.db.exp + exp;
|
||||
let nextRequiredExp = ExpTypeExcel.fromId(`${avatarExcelData.ExpGroup}:${avatar.db.level}`).Exp;
|
||||
while (currentAvatarExp >= nextRequiredExp && avatar.db.level < levelCap) {
|
||||
// Increase level.
|
||||
avatar.db.level++;
|
||||
|
||||
// Deduct EXP necessary for this level.
|
||||
currentAvatarExp -= nextRequiredExp;
|
||||
|
||||
// Determine EXP necessary for the next level.
|
||||
nextRequiredExp = ExpTypeExcel.fromId(`${avatarExcelData.ExpGroup}:${avatar.db.level}`).Exp;
|
||||
}
|
||||
|
||||
// Calculate the character's new EXP and any excess EXP.
|
||||
let excessExp = 0;
|
||||
if (avatar.db.level == levelCap && currentAvatarExp >= nextRequiredExp) {
|
||||
avatar.db.exp = nextRequiredExp;
|
||||
excessExp = currentAvatarExp - nextRequiredExp;
|
||||
}
|
||||
else {
|
||||
avatar.db.exp = currentAvatarExp;
|
||||
}
|
||||
|
||||
// Save.
|
||||
await avatar.save();
|
||||
|
||||
// ToDo: Handle return items.
|
||||
|
||||
// Done. Sync and send response.
|
||||
await session.sync();
|
||||
|
||||
session.send(AvatarExpUpScRsp, {
|
||||
retcode: 0,
|
||||
returnItemList: []
|
||||
} as AvatarExpUpScRsp);
|
||||
}
|
@ -6,7 +6,7 @@ import Session from "../kcp/Session";
|
||||
export default async function handle(session: Session, packet: Packet) {
|
||||
const body = packet.body as DressAvatarCsReq;
|
||||
|
||||
let avatar = await Avatar.loadAvatarForPlayer(session.player, body.baseAvatarId);
|
||||
const avatar = await Avatar.loadAvatarForPlayer(session.player, body.baseAvatarId);
|
||||
|
||||
avatar.db.equipmentUniqueId = body.equipmentUniqueId;
|
||||
await avatar.save();
|
||||
|
@ -11,31 +11,6 @@ export default async function handle(session: Session, packet: Packet) {
|
||||
// Replace avatar in the player's lineup.
|
||||
const slot = body.slot ?? 0;
|
||||
session.player.db.lineup.lineups[session.player.db.lineup.curIndex].avatarList[slot] = body.baseAvatarId;
|
||||
|
||||
/*
|
||||
|
||||
let lineup = await session.player.getLineup();
|
||||
const avatarList = [];
|
||||
|
||||
// What in the fuck is the purpose of this loop supposed to be?!
|
||||
for (const avatarId in lineup) {
|
||||
const avatar = await Avatar.fromUID(session.player.db._id, Number(avatarId));
|
||||
if (avatar.length === 0) return session.c.warn(`Avatar ${body.baseAvatarId} not found`);
|
||||
if (avatar) avatarList.push(avatar[0]);
|
||||
}
|
||||
|
||||
lineup.avatarList[slot] = {
|
||||
avatarType: AvatarType.AVATAR_FORMAL_TYPE,
|
||||
hp: 10000,
|
||||
id: body.baseAvatarId,
|
||||
satiety: 100,
|
||||
slot,
|
||||
sp: 10000
|
||||
};
|
||||
if (body.extraLineupType) lineup.extraLineupType = body.extraLineupType;
|
||||
session.player.setLineup(lineup);
|
||||
*/
|
||||
|
||||
await session.player.save();
|
||||
|
||||
session.send(SyncLineupNotify, {
|
||||
|
40
src/server/packets/PromoteAvatarCsReq.ts
Normal file
40
src/server/packets/PromoteAvatarCsReq.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { PromoteAvatarCsReq, PromoteAvatarScRsp } from "../../data/proto/StarRail";
|
||||
import Avatar from "../../db/Avatar";
|
||||
import { PayItemData } from "../../db/Inventory";
|
||||
import AvatarExcel from "../../util/excel/AvatarExcel";
|
||||
import AvatarExpItemExcel from "../../util/excel/AvatarExpItemExcel";
|
||||
import AvatarPromotionExcel from "../../util/excel/AvatarPromotionExcel";
|
||||
import ExpTypeExcel from "../../util/excel/ExpTypeExcel";
|
||||
import Packet from "../kcp/Packet";
|
||||
import Session from "../kcp/Session";
|
||||
|
||||
export default async function handle(session: Session, packet: Packet) {
|
||||
const body = packet.body as PromoteAvatarCsReq;
|
||||
const inventory = await session.player.getInventory();
|
||||
|
||||
// Get the target avatar.
|
||||
const avatarId = body.baseAvatarId;
|
||||
const avatar = await Avatar.loadAvatarForPlayer(session.player, avatarId);
|
||||
const promotionExcelData = AvatarPromotionExcel.fromId(`${avatarId}:${avatar.db.promotion}`);
|
||||
|
||||
// Build list of consumed items. We take this from the excel, instead of the Req.
|
||||
const costMaterialList = promotionExcelData.PromotionCostList.map(c => { return { id: c.ItemID, count: c.ItemNum } as PayItemData });
|
||||
|
||||
// Try consuming materials.
|
||||
const success = await inventory.payItems(costMaterialList);
|
||||
if (!success) {
|
||||
// ToDo: Correct retcode.
|
||||
session.send(PromoteAvatarScRsp, { retcode: 1 } as PromoteAvatarScRsp);
|
||||
return;
|
||||
}
|
||||
|
||||
await inventory.save();
|
||||
|
||||
// Promote the avatar and save.
|
||||
avatar.db.promotion++;
|
||||
await avatar.save();
|
||||
|
||||
// Done. Sync and send response.
|
||||
await session.sync();
|
||||
session.send(PromoteAvatarScRsp, { retcode: 0 } as PromoteAvatarScRsp);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import { RankUpAvatarCsReq, RankUpAvatarScRsp } from "../../data/proto/StarRail";
|
||||
import Avatar from "../../db/Avatar";
|
||||
import { PayItemData } from "../../db/Inventory";
|
||||
import Logger from "../../util/Logger";
|
||||
import Packet from "../kcp/Packet";
|
||||
import Session from "../kcp/Session";
|
||||
@ -7,33 +8,37 @@ const c = new Logger("RankUpAvatarCsReq");
|
||||
|
||||
export default async function handle(session: Session, packet: Packet) {
|
||||
const body = packet.body as RankUpAvatarCsReq;
|
||||
const dataObj: RankUpAvatarScRsp = {
|
||||
retcode: 0
|
||||
};
|
||||
|
||||
let retcode = 0;
|
||||
if (body.costData) {
|
||||
try {
|
||||
const inv = await session.player.getInventory();
|
||||
if (!body.costData) return;
|
||||
const list = body.costData.itemList;
|
||||
const arr: Array<PayItemData> = [];
|
||||
|
||||
for (const item of body.costData.itemList) {
|
||||
if (!item.pileItem) return;
|
||||
|
||||
const succ = await inv.payItems([{
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const item = list[i];
|
||||
if (!item.pileItem) continue;
|
||||
arr.push({
|
||||
count: item.pileItem.itemNum,
|
||||
id: item.pileItem.itemId,
|
||||
}]);
|
||||
|
||||
if (!succ) {
|
||||
retcode = 1301;
|
||||
c.debug(`failed to pay item ${item.pileItem.itemId}`, item.pileItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
id: item.pileItem.itemId
|
||||
});
|
||||
}
|
||||
|
||||
if (retcode === 0) {
|
||||
if (await inv.payItems(arr)) {
|
||||
const avatar = await Avatar.loadAvatarForPlayer(session.player, body.baseAvatarId);
|
||||
avatar.db.rank = body.rank // gidra moment: ez hack
|
||||
await avatar.save();
|
||||
} else {
|
||||
dataObj.retcode = 1301;
|
||||
}
|
||||
|
||||
session.send(RankUpAvatarScRsp, { retcode });
|
||||
} catch (e) {
|
||||
c.error(e as Error);
|
||||
dataObj.retcode = 2;
|
||||
} finally {
|
||||
session.send(RankUpAvatarScRsp, dataObj);
|
||||
session.sync();
|
||||
}
|
||||
}
|
@ -23,7 +23,11 @@ export default async function handle(session: Session, packet: Packet) {
|
||||
entity.pos = motion.pos;
|
||||
if (entity instanceof ActorEntity) {
|
||||
entity.mapLayer = entityMotion.mapLayer;
|
||||
session.player.db.posData.pos = motion.pos!;
|
||||
session.player.db.posData.pos = {
|
||||
x: motion.pos.x,
|
||||
y: motion.pos.y,
|
||||
z: motion.pos.z
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,14 @@ export default async function handle(session: Session, packet: Packet) {
|
||||
rounds: 1,
|
||||
status: ChallengeStatus.CHALLENGE_DOING,
|
||||
killMonsterList: [{
|
||||
monsterId: 1001010,
|
||||
monsterId: 8013010,
|
||||
killNum: 1,
|
||||
}]
|
||||
},
|
||||
maze: {
|
||||
// ? Data from MappingInfoExcelTable
|
||||
id: 30101,
|
||||
mapEntryId: 1000,
|
||||
mapEntryId: 10001,
|
||||
floor: {
|
||||
floorId: 20121001,
|
||||
scene: {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import fs from 'fs';
|
||||
import { resolve } from 'path';
|
||||
import {resolve} from 'path';
|
||||
import Logger from './Logger';
|
||||
|
||||
const c = new Logger("Banner");
|
||||
|
||||
type Banner = {
|
||||
@ -18,15 +19,21 @@ function r(...args: string[]) {
|
||||
export default class Banners {
|
||||
public static config: Banner[];
|
||||
|
||||
public static init(){
|
||||
public static init() {
|
||||
Banners.readConfig();
|
||||
}
|
||||
|
||||
private static readConfig(){
|
||||
private static readConfig() {
|
||||
let config: Banner[];
|
||||
const defaultConfig: Banner[] = [
|
||||
{
|
||||
gachaId: 1001,
|
||||
|
||||
const defaultConfig: Banner[] = [];
|
||||
|
||||
// TODO: figure where is GachaBasicInfoConfigExcelTable. Temporary hardcode
|
||||
const bannersID = [1001, 2001, 2002, 3001, 3002, 4001]
|
||||
|
||||
for (let i = 0; i < bannersID.length; i++) {
|
||||
defaultConfig.push({
|
||||
gachaId: bannersID[i],
|
||||
detailWebview: "",
|
||||
rateUpItems4: [
|
||||
1001, 1103
|
||||
@ -35,13 +42,13 @@ export default class Banners {
|
||||
1102
|
||||
],
|
||||
costItemId: 101 // Star Rail Pass
|
||||
} as Banner
|
||||
];
|
||||
} as Banner)
|
||||
}
|
||||
|
||||
try {
|
||||
config = JSON.parse(fs.readFileSync(r('../../banners.json')).toString());
|
||||
|
||||
for(const [index, gachaBanner] of Object.entries(config)){
|
||||
for (const [index, gachaBanner] of Object.entries(config)) {
|
||||
const missing = Object.keys(defaultConfig[0]).filter(key => !gachaBanner.hasOwnProperty(key));
|
||||
if (missing.length > 0) {
|
||||
c.log(`Missing ${missing.join(', ')}, using default values.`);
|
||||
|
20
src/util/excel/AvatarExpItemExcel.ts
Normal file
20
src/util/excel/AvatarExpItemExcel.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import _AvatarExpItemConfigExcelTable from "../../data/excel/AvatarExpItemConfigExcelTable.json";
|
||||
type AvatarExpItemConfigExcelTableEntry = typeof _AvatarExpItemConfigExcelTable[keyof typeof _AvatarExpItemConfigExcelTable]
|
||||
const AvatarExpItemConfigExcelTable = _AvatarExpItemConfigExcelTable as { [key: string]: AvatarExpItemConfigExcelTableEntry };
|
||||
|
||||
export default class AvatarExpItemExcel {
|
||||
private constructor() {
|
||||
}
|
||||
|
||||
public static all() : AvatarExpItemConfigExcelTableEntry[] {
|
||||
return Object.values(AvatarExpItemConfigExcelTable);
|
||||
}
|
||||
|
||||
public static fromId(id: number) : AvatarExpItemConfigExcelTableEntry {
|
||||
return AvatarExpItemConfigExcelTable[id];
|
||||
}
|
||||
|
||||
public static fromIds(ids: number[]): AvatarExpItemConfigExcelTableEntry[] {
|
||||
return ids.map(id => AvatarExpItemExcel.fromId(id));
|
||||
}
|
||||
}
|
20
src/util/excel/AvatarPromotionExcel.ts
Normal file
20
src/util/excel/AvatarPromotionExcel.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import _AvatarPromotionExcelTable from "../../data/excel/AvatarPromotionExcelTable.json";
|
||||
type AvatarPromotionExcelTableEntry = typeof _AvatarPromotionExcelTable[keyof typeof _AvatarPromotionExcelTable]
|
||||
const AvatarPromotionExcelTable = _AvatarPromotionExcelTable as { [key: string]: AvatarPromotionExcelTableEntry };
|
||||
|
||||
export default class AvatarPromotionExcel {
|
||||
private constructor() {
|
||||
}
|
||||
|
||||
public static all() : AvatarPromotionExcelTableEntry[] {
|
||||
return Object.values(AvatarPromotionExcelTable);
|
||||
}
|
||||
|
||||
public static fromId(id: string) : AvatarPromotionExcelTableEntry {
|
||||
return AvatarPromotionExcelTable[id];
|
||||
}
|
||||
|
||||
public static fromIds(ids: string[]): AvatarPromotionExcelTableEntry[] {
|
||||
return ids.map(id => AvatarPromotionExcel.fromId(id));
|
||||
}
|
||||
}
|
20
src/util/excel/ExpTypeExcel.ts
Normal file
20
src/util/excel/ExpTypeExcel.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import _ExpTypeExcelTable from "../../data/excel/ExpTypeExcelTable.json";
|
||||
type ExpTypeExcelTableEntry = typeof _ExpTypeExcelTable[keyof typeof _ExpTypeExcelTable]
|
||||
const ExpTypeExcelTable = _ExpTypeExcelTable as { [key: string]: ExpTypeExcelTableEntry };
|
||||
|
||||
export default class ExpTypeExcel {
|
||||
private constructor() {
|
||||
}
|
||||
|
||||
public static all() : ExpTypeExcelTableEntry[] {
|
||||
return Object.values(ExpTypeExcelTable);
|
||||
}
|
||||
|
||||
public static fromId(id: string) : ExpTypeExcelTableEntry {
|
||||
return ExpTypeExcelTable[id];
|
||||
}
|
||||
|
||||
public static fromIds(ids: string[]): ExpTypeExcelTableEntry[] {
|
||||
return ids.map(id => ExpTypeExcel.fromId(id));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user