gistfile1.txt
· 4.0 KiB · Text
Неформатований
import fs from "fs";
import path from "path";
import { CharacterMap, Character, ClassKey, Nation, AccountMap, AccountData } from "../types";
const CHARS_PATH = path.join(__dirname, "../../data/characters.json");
const ACCOUNTS_PATH = path.join(__dirname, "../../data/accounts.json");
let _chars: CharacterMap = {};
let _accounts: AccountMap = {};
export function loadCharacters(): void {
try { _chars = JSON.parse(fs.readFileSync(CHARS_PATH, "utf8")); }
catch { _chars = {}; }
try { _accounts = JSON.parse(fs.readFileSync(ACCOUNTS_PATH, "utf8")); }
catch { _accounts = {}; }
}
function saveCharacters(): void {
fs.writeFileSync(CHARS_PATH, JSON.stringify(_chars, null, 2));
}
function saveAccounts(): void {
fs.writeFileSync(ACCOUNTS_PATH, JSON.stringify(_accounts, null, 2));
}
export function getCharacters(userKey: string): Character[] {
return _chars[userKey]?.characters ?? [];
}
export function getActiveCharacter(userKey: string): Character | null {
return getCharacters(userKey).find((c) => c.active) ?? null;
}
export function getCharacterByName(userKey: string, name: string): Character | null {
return getCharacters(userKey).find((c) => c.name.toLowerCase() === name.toLowerCase()) ?? null;
}
export function getCharacterByClass(userKey: string, cls: ClassKey): Character | null {
// Returns the active character of that class, or first found
const chars = getCharacters(userKey).filter((c) => c.class === cls);
return chars.find((c) => c.active) ?? chars[0] ?? null;
}
export function addCharacter(userKey: string, char: Omit<Character, "active">): boolean {
if (!_chars[userKey]) _chars[userKey] = { characters: [] };
const exists = _chars[userKey].characters.some((c) => c.name.toLowerCase() === char.name.toLowerCase());
if (exists) return false;
// If no active character, set this one as active
const hasActive = _chars[userKey].characters.some((c) => c.active);
_chars[userKey].characters.push({ ...char, active: !hasActive });
saveCharacters();
return true;
}
export function removeCharacter(userKey: string, name: string): boolean {
if (!_chars[userKey]) return false;
const before = _chars[userKey].characters.length;
_chars[userKey].characters = _chars[userKey].characters.filter(
(c) => c.name.toLowerCase() !== name.toLowerCase()
);
if (_chars[userKey].characters.length === before) return false;
// If we removed the active one, set the first remaining as active
if (!_chars[userKey].characters.some((c) => c.active) && _chars[userKey].characters.length > 0) {
_chars[userKey].characters[0].active = true;
}
saveCharacters();
return true;
}
export function setActiveCharacter(userKey: string, name: string): boolean {
const chars = _chars[userKey]?.characters;
if (!chars) return false;
const target = chars.find((c) => c.name.toLowerCase() === name.toLowerCase());
if (!target) return false;
chars.forEach((c) => (c.active = false));
target.active = true;
saveCharacters();
return true;
}
export function setCharacterNation(userKey: string, name: string, nation: Nation): boolean {
const char = getCharacterByName(userKey, name);
if (!char) return false;
char.nation = nation;
saveCharacters();
return true;
}
export function setCharacterStats(
userKey: string,
name: string,
stats: { atk?: number; def?: number; heal?: number }
): boolean {
const char = getCharacterByName(userKey, name);
if (!char) return false;
if (!char.stats) char.stats = {};
Object.assign(char.stats, stats);
saveCharacters();
return true;
}
// ─── Account data ─────────────────────────────────────────────────────────────
export function getAccountData(userKey: string): AccountData {
return _accounts[userKey] ?? {};
}
export function setAccountData(userKey: string, data: Partial<AccountData>): void {
if (!_accounts[userKey]) _accounts[userKey] = {};
Object.assign(_accounts[userKey], data);
saveAccounts();
}
| 1 | import fs from "fs"; |
| 2 | import path from "path"; |
| 3 | import { CharacterMap, Character, ClassKey, Nation, AccountMap, AccountData } from "../types"; |
| 4 | |
| 5 | const CHARS_PATH = path.join(__dirname, "../../data/characters.json"); |
| 6 | const ACCOUNTS_PATH = path.join(__dirname, "../../data/accounts.json"); |
| 7 | |
| 8 | let _chars: CharacterMap = {}; |
| 9 | let _accounts: AccountMap = {}; |
| 10 | |
| 11 | export function loadCharacters(): void { |
| 12 | try { _chars = JSON.parse(fs.readFileSync(CHARS_PATH, "utf8")); } |
| 13 | catch { _chars = {}; } |
| 14 | try { _accounts = JSON.parse(fs.readFileSync(ACCOUNTS_PATH, "utf8")); } |
| 15 | catch { _accounts = {}; } |
| 16 | } |
| 17 | |
| 18 | function saveCharacters(): void { |
| 19 | fs.writeFileSync(CHARS_PATH, JSON.stringify(_chars, null, 2)); |
| 20 | } |
| 21 | |
| 22 | function saveAccounts(): void { |
| 23 | fs.writeFileSync(ACCOUNTS_PATH, JSON.stringify(_accounts, null, 2)); |
| 24 | } |
| 25 | |
| 26 | export function getCharacters(userKey: string): Character[] { |
| 27 | return _chars[userKey]?.characters ?? []; |
| 28 | } |
| 29 | |
| 30 | export function getActiveCharacter(userKey: string): Character | null { |
| 31 | return getCharacters(userKey).find((c) => c.active) ?? null; |
| 32 | } |
| 33 | |
| 34 | export function getCharacterByName(userKey: string, name: string): Character | null { |
| 35 | return getCharacters(userKey).find((c) => c.name.toLowerCase() === name.toLowerCase()) ?? null; |
| 36 | } |
| 37 | |
| 38 | export function getCharacterByClass(userKey: string, cls: ClassKey): Character | null { |
| 39 | // Returns the active character of that class, or first found |
| 40 | const chars = getCharacters(userKey).filter((c) => c.class === cls); |
| 41 | return chars.find((c) => c.active) ?? chars[0] ?? null; |
| 42 | } |
| 43 | |
| 44 | export function addCharacter(userKey: string, char: Omit<Character, "active">): boolean { |
| 45 | if (!_chars[userKey]) _chars[userKey] = { characters: [] }; |
| 46 | const exists = _chars[userKey].characters.some((c) => c.name.toLowerCase() === char.name.toLowerCase()); |
| 47 | if (exists) return false; |
| 48 | // If no active character, set this one as active |
| 49 | const hasActive = _chars[userKey].characters.some((c) => c.active); |
| 50 | _chars[userKey].characters.push({ ...char, active: !hasActive }); |
| 51 | saveCharacters(); |
| 52 | return true; |
| 53 | } |
| 54 | |
| 55 | export function removeCharacter(userKey: string, name: string): boolean { |
| 56 | if (!_chars[userKey]) return false; |
| 57 | const before = _chars[userKey].characters.length; |
| 58 | _chars[userKey].characters = _chars[userKey].characters.filter( |
| 59 | (c) => c.name.toLowerCase() !== name.toLowerCase() |
| 60 | ); |
| 61 | if (_chars[userKey].characters.length === before) return false; |
| 62 | // If we removed the active one, set the first remaining as active |
| 63 | if (!_chars[userKey].characters.some((c) => c.active) && _chars[userKey].characters.length > 0) { |
| 64 | _chars[userKey].characters[0].active = true; |
| 65 | } |
| 66 | saveCharacters(); |
| 67 | return true; |
| 68 | } |
| 69 | |
| 70 | export function setActiveCharacter(userKey: string, name: string): boolean { |
| 71 | const chars = _chars[userKey]?.characters; |
| 72 | if (!chars) return false; |
| 73 | const target = chars.find((c) => c.name.toLowerCase() === name.toLowerCase()); |
| 74 | if (!target) return false; |
| 75 | chars.forEach((c) => (c.active = false)); |
| 76 | target.active = true; |
| 77 | saveCharacters(); |
| 78 | return true; |
| 79 | } |
| 80 | |
| 81 | export function setCharacterNation(userKey: string, name: string, nation: Nation): boolean { |
| 82 | const char = getCharacterByName(userKey, name); |
| 83 | if (!char) return false; |
| 84 | char.nation = nation; |
| 85 | saveCharacters(); |
| 86 | return true; |
| 87 | } |
| 88 | |
| 89 | export function setCharacterStats( |
| 90 | userKey: string, |
| 91 | name: string, |
| 92 | stats: { atk?: number; def?: number; heal?: number } |
| 93 | ): boolean { |
| 94 | const char = getCharacterByName(userKey, name); |
| 95 | if (!char) return false; |
| 96 | if (!char.stats) char.stats = {}; |
| 97 | Object.assign(char.stats, stats); |
| 98 | saveCharacters(); |
| 99 | return true; |
| 100 | } |
| 101 | |
| 102 | // ─── Account data ───────────────────────────────────────────────────────────── |
| 103 | export function getAccountData(userKey: string): AccountData { |
| 104 | return _accounts[userKey] ?? {}; |
| 105 | } |
| 106 | |
| 107 | export function setAccountData(userKey: string, data: Partial<AccountData>): void { |
| 108 | if (!_accounts[userKey]) _accounts[userKey] = {}; |
| 109 | Object.assign(_accounts[userKey], data); |
| 110 | saveAccounts(); |
| 111 | } |
| 112 |