Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c1e2c6d8b5 | |||
| f7b041f86f | |||
| 05bd70a9fe | |||
| bb5c7e6e21 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -7,8 +7,8 @@ android {
|
||||
applicationId "com.warren.iwanttoheal"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 65
|
||||
versionName "1.0.45"
|
||||
versionCode 69
|
||||
versionName "1.0.50"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
||||
+72
-36
@@ -532,42 +532,78 @@ INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (10
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1007, 583001, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1008, 583001, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1009, 583001, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1101, 683002, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1102, 683002, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1103, 683002, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1104, 783002, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1105, 783002, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1106, 783002, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1107, 883002, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1108, 883002, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1109, 883002, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1201, 983003, 15);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1202, 983003, 15);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1203, 983003, 15);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1204, 1083003, 15);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1205, 1083003, 15);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1206, 1083003, 15);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1207, 1183003, 15);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1208, 1183003, 15);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1209, 1183003, 15);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1301, 1283004, 20);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1302, 1283004, 20);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1303, 1283004, 20);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1304, 1383004, 20);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1305, 1383004, 20);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1306, 1383004, 20);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1307, 1483004, 20);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1308, 1483004, 20);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1309, 1483004, 20);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1401, 1583005, 25);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1402, 1583005, 25);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1403, 1583005, 25);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1404, 1683005, 25);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1405, 1683005, 25);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1406, 1683005, 25);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1407, 1783005, 25);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1408, 1783005, 25);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1409, 1783005, 25);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1101, 383002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1101, 683002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1102, 383002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1102, 683002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1103, 383002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1103, 683002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1104, 483002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1104, 783002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1105, 483002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1105, 783002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1106, 483002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1106, 783002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1107, 583002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1107, 883002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1108, 583002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1108, 883002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1109, 583002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1109, 883002, 5);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1201, 683003, 7);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1201, 983003, 8);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1202, 683003, 7);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1202, 983003, 8);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1203, 683003, 7);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1203, 983003, 8);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1204, 783003, 7);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1204, 1083003, 8);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1205, 783003, 7);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1205, 1083003, 8);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1206, 783003, 7);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1206, 1083003, 8);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1207, 883003, 7);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1207, 1183003, 8);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1208, 883003, 7);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1208, 1183003, 8);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1209, 883003, 7);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1209, 1183003, 8);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1301, 983004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1301, 1283004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1302, 983004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1302, 1283004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1303, 983004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1303, 1283004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1304, 1083004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1304, 1383004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1305, 1083004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1305, 1383004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1306, 1083004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1306, 1383004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1307, 1183004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1307, 1483004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1308, 1183004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1308, 1483004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1309, 1183004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1309, 1483004, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1401, 1283005, 12);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1401, 1583005, 13);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1402, 1283005, 12);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1402, 1583005, 13);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1403, 1283005, 12);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1403, 1583005, 13);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1404, 1383005, 12);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1404, 1683005, 13);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1405, 1383005, 12);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1405, 1683005, 13);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1406, 1383005, 12);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1406, 1683005, 13);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1407, 1483005, 12);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1407, 1783005, 13);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1408, 1483005, 12);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1408, 1783005, 13);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1409, 1483005, 12);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (1409, 1783005, 13);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (2001, 2283101, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (2002, 2283101, 10);
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity) VALUES (2003, 2283101, 10);
|
||||
|
||||
+15
@@ -1908,6 +1908,21 @@ JOIN coin_sources
|
||||
ON coin_sources.encounter_id = crafting_recipes.source_encounter_id
|
||||
AND coin_sources.difficulty_id = crafting_recipes.difficulty_id;
|
||||
|
||||
DELETE FROM crafting_recipe_components
|
||||
WHERE recipe_id IN (1101, 1102, 1103);
|
||||
|
||||
INSERT INTO crafting_recipe_components (recipe_id, item_id, quantity)
|
||||
SELECT recipe_id, items.id, quantity
|
||||
FROM (
|
||||
SELECT 1101 AS recipe_id, 'tigrex-boss-coin-diff-2-ilvl-10' AS item_slug, 5 AS quantity
|
||||
UNION ALL SELECT 1101, 'bulldrome-boss-coin-diff-2-ilvl-10', 5
|
||||
UNION ALL SELECT 1102, 'tigrex-boss-coin-diff-2-ilvl-10', 5
|
||||
UNION ALL SELECT 1102, 'bulldrome-boss-coin-diff-2-ilvl-10', 5
|
||||
UNION ALL SELECT 1103, 'tigrex-boss-coin-diff-2-ilvl-10', 5
|
||||
UNION ALL SELECT 1103, 'bulldrome-boss-coin-diff-2-ilvl-10', 5
|
||||
) AS requirements
|
||||
JOIN items ON items.slug = requirements.item_slug;
|
||||
|
||||
DELETE FROM gear_upgrade_paths;
|
||||
|
||||
INSERT INTO gear_upgrade_paths (from_item_id, to_item_id)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { readFileSync, writeFileSync } from 'node:fs'
|
||||
import { DatabaseSync } from 'node:sqlite'
|
||||
import { catalogPayload } from '../server/catalog.mjs'
|
||||
import { getProfile } from '../server/game-api.mjs'
|
||||
|
||||
const database = new DatabaseSync(':memory:')
|
||||
@@ -7,10 +8,14 @@ const database = new DatabaseSync(':memory:')
|
||||
try {
|
||||
database.exec(readFileSync('db/schema.sql', 'utf8'))
|
||||
database.exec(readFileSync('db/seed.sql', 'utf8'))
|
||||
const profile = getProfile(database, 1)
|
||||
const catalog = catalogPayload(getProfile(database, 1))
|
||||
writeFileSync(
|
||||
'src/offline-starter-profile.json',
|
||||
`${JSON.stringify(profile, null, 2)}\n`,
|
||||
`${JSON.stringify(catalog.profile, null, 2)}\n`,
|
||||
)
|
||||
writeFileSync(
|
||||
'src/offline-catalog-meta.ts',
|
||||
`export const bundledCatalogHash = '${catalog.hash}'\n`,
|
||||
)
|
||||
console.log('Offline starter profile exported from SQLite.')
|
||||
} finally {
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import { createHash } from 'node:crypto'
|
||||
|
||||
function normalizeRecipe(recipe) {
|
||||
return {
|
||||
...recipe,
|
||||
components: recipe.components.map((component) => ({
|
||||
...component,
|
||||
owned: 0,
|
||||
})),
|
||||
canCraft: false,
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeDungeon(dungeon) {
|
||||
return {
|
||||
...dungeon,
|
||||
completionCount: 0,
|
||||
leaderboard: [],
|
||||
leaderboards: {
|
||||
part_1: [],
|
||||
part_2: [],
|
||||
part_3: [],
|
||||
full_run: [],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeCatalogProfile(profile) {
|
||||
return {
|
||||
...profile,
|
||||
character: {
|
||||
...profile.character,
|
||||
id: 1,
|
||||
name: 'Mira',
|
||||
level: 1,
|
||||
experience: 0,
|
||||
talentPoints: 1,
|
||||
currentLevelExperience: 0,
|
||||
nextLevelExperience: 100,
|
||||
},
|
||||
abilitySlots: profile.abilitySlots,
|
||||
allocatedTalentPoints: 0,
|
||||
inventory: [],
|
||||
completedDungeonParts: 0,
|
||||
completedRaidPhases: 0,
|
||||
gearStats: {
|
||||
averageItemLevel: 0,
|
||||
healingPower: 0,
|
||||
maxResourceBonus: 0,
|
||||
},
|
||||
setBonuses: profile.setBonuses.map((bonus) => ({
|
||||
...bonus,
|
||||
equippedPieces: 0,
|
||||
active: false,
|
||||
})),
|
||||
craftingRecipes: profile.craftingRecipes.map(normalizeRecipe),
|
||||
dungeons: profile.dungeons.map(normalizeDungeon),
|
||||
}
|
||||
}
|
||||
|
||||
export function catalogHash(profile) {
|
||||
return createHash('sha256')
|
||||
.update(JSON.stringify(profile))
|
||||
.digest('hex')
|
||||
}
|
||||
|
||||
export function catalogPayload(profile) {
|
||||
const normalized = normalizeCatalogProfile(profile)
|
||||
return {
|
||||
version: 1,
|
||||
hash: catalogHash(normalized),
|
||||
profile: normalized,
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import { isIP } from 'node:net'
|
||||
import { extname, resolve, sep } from 'node:path'
|
||||
import { DatabaseSync } from 'node:sqlite'
|
||||
import { catalogPayload } from './catalog.mjs'
|
||||
|
||||
const databasePath = fileURLToPath(new URL('../data/game.db', import.meta.url))
|
||||
const bossImageDirectory = fileURLToPath(new URL('../data/uploads/bosses/', import.meta.url))
|
||||
@@ -2696,6 +2697,11 @@ export async function handleApiRequest(request, response, next) {
|
||||
return
|
||||
}
|
||||
|
||||
if (request.url === '/api/catalog' && request.method === 'GET') {
|
||||
sendJson(response, 200, catalogPayload(getProfile(database, 1)))
|
||||
return
|
||||
}
|
||||
|
||||
const session = requireSession(database, request)
|
||||
|
||||
if (request.url === '/api/profile/sync-save' && request.method === 'GET') {
|
||||
|
||||
+66
-3
@@ -1,4 +1,5 @@
|
||||
import starterProfile from './offline-starter-profile.json'
|
||||
import { bundledCatalogHash } from './offline-catalog-meta'
|
||||
import type {
|
||||
Account,
|
||||
AuthSession,
|
||||
@@ -82,6 +83,12 @@ type OnlineCache = {
|
||||
dirty: boolean
|
||||
}
|
||||
|
||||
type CatalogCache = {
|
||||
version: 1
|
||||
hash: string
|
||||
profile: CharacterProfile
|
||||
}
|
||||
|
||||
export type CloudSyncStatus = {
|
||||
available: boolean
|
||||
dirty: boolean
|
||||
@@ -102,6 +109,8 @@ type LocalSaveStore = {
|
||||
const modeKey = 'chronicle.repositoryMode'
|
||||
const offlineSaveKey = 'chronicle.offlineSave.v1'
|
||||
const onlineCacheKey = 'chronicle.onlineCache.v1'
|
||||
const catalogCacheKey = 'chronicle.catalog.v1'
|
||||
const catalogBundleKey = 'chronicle.catalog.bundleHash.v1'
|
||||
const authTokenKey = 'chronicle.authToken.v1'
|
||||
const offlineAccount = { id: -1, username: 'Offline' }
|
||||
const ABILITY_SLOT_COUNT = 6
|
||||
@@ -281,8 +290,42 @@ function clearOnlineCache() {
|
||||
localStorage.removeItem(onlineCacheKey)
|
||||
}
|
||||
|
||||
function bundledCatalog(): CatalogCache {
|
||||
return {
|
||||
version: 1,
|
||||
hash: bundledCatalogHash,
|
||||
profile: starterProfile as CharacterProfile,
|
||||
}
|
||||
}
|
||||
|
||||
function readCatalogCache(): CatalogCache | null {
|
||||
if (localStorage.getItem(catalogBundleKey) !== bundledCatalogHash) {
|
||||
localStorage.removeItem(catalogCacheKey)
|
||||
localStorage.setItem(catalogBundleKey, bundledCatalogHash)
|
||||
return null
|
||||
}
|
||||
const serialized = localStorage.getItem(catalogCacheKey)
|
||||
if (!serialized) return null
|
||||
try {
|
||||
const raw = JSON.parse(serialized) as CatalogCache
|
||||
if (raw.version !== 1 || typeof raw.hash !== 'string' || !raw.profile) return null
|
||||
return raw
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function writeCatalogCache(cache: CatalogCache) {
|
||||
localStorage.setItem(catalogBundleKey, bundledCatalogHash)
|
||||
localStorage.setItem(catalogCacheKey, JSON.stringify(cache))
|
||||
}
|
||||
|
||||
function activeCatalog(): CatalogCache {
|
||||
return readCatalogCache() ?? bundledCatalog()
|
||||
}
|
||||
|
||||
function buildProfile(save: OfflineSave): CharacterProfile {
|
||||
const static_ = clone(starterProfile) as CharacterProfile
|
||||
const static_ = clone(activeCatalog().profile)
|
||||
const cd = save.characters[save.activeClassId]
|
||||
const gameClass = static_.classes.find((c) => c.id === save.activeClassId)!
|
||||
|
||||
@@ -657,6 +700,23 @@ function isNetworkError(reason: unknown): reason is NetworkError {
|
||||
return reason instanceof Error && Boolean((reason as NetworkError).network)
|
||||
}
|
||||
|
||||
async function loadServerCatalog(): Promise<CatalogCache> {
|
||||
return requestJson('/api/catalog')
|
||||
}
|
||||
|
||||
async function refreshCatalogFromServer(): Promise<CatalogCache | null> {
|
||||
try {
|
||||
const catalog = await loadServerCatalog()
|
||||
if (catalog.version !== 1 || !catalog.hash || !catalog.profile) return null
|
||||
if (catalog.hash !== activeCatalog().hash || !readCatalogCache()) {
|
||||
writeCatalogCache(catalog)
|
||||
}
|
||||
return catalog
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function cachedOnlineSession(): AuthSession | null {
|
||||
const cache = readOnlineCache()
|
||||
if (!cache) return null
|
||||
@@ -698,6 +758,7 @@ async function pushServerSyncSave(save: OfflineSave): Promise<{ profile: Charact
|
||||
async function finalizeOnlineSession(session: AuthSession): Promise<AuthSession> {
|
||||
const cache = readOnlineCache()
|
||||
if (session.token) writeAuthToken(session.token)
|
||||
await refreshCatalogFromServer()
|
||||
if (!session.account || !session.profile) {
|
||||
if (session.account && cache?.account.id === session.account.id) {
|
||||
return {
|
||||
@@ -848,7 +909,7 @@ const serverRepository: GameRepository = {
|
||||
}
|
||||
|
||||
function emptyCharacterData(classId: number): CharacterData {
|
||||
const static_ = clone(starterProfile) as CharacterProfile
|
||||
const static_ = clone(activeCatalog().profile)
|
||||
const gc = static_.classes.find((c) => c.id === classId)!
|
||||
const talentRanks: Record<string, number> = {}
|
||||
for (const t of gc.talents) talentRanks[String(t.id)] = 0
|
||||
@@ -1544,7 +1605,9 @@ export async function syncCloudSave(): Promise<CharacterProfile> {
|
||||
if (!cache) {
|
||||
throw new Error('No signed-in save is available for cloud sync.')
|
||||
}
|
||||
await refreshCatalogFromServer()
|
||||
const synced = await pushServerSyncSave(cache.save)
|
||||
await refreshCatalogFromServer()
|
||||
writeOnlineCache({
|
||||
version: 1,
|
||||
account: cache.account,
|
||||
@@ -1552,7 +1615,7 @@ export async function syncCloudSave(): Promise<CharacterProfile> {
|
||||
dirty: false,
|
||||
})
|
||||
writeMode('online')
|
||||
return synced.profile
|
||||
return buildProfile(synced.save)
|
||||
}
|
||||
|
||||
export function selectOnlineMode() {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export const bundledCatalogHash = '07506c52bab428c439f09a9b82e39e6eff2b243fb972d664da48852059bcd937'
|
||||
@@ -1437,6 +1437,22 @@
|
||||
"setName": null
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"item": {
|
||||
"id": 383002,
|
||||
"slug": "bulldrome-boss-coin-diff-2-ilvl-10",
|
||||
"name": "Green Bulldrome Coin",
|
||||
"slot": "component",
|
||||
"rarity": "uncommon",
|
||||
"itemLevel": 10,
|
||||
"healingPower": 0,
|
||||
"maxResourceBonus": 0,
|
||||
"glyph": "$",
|
||||
"description": "A boss coin from Bulldrome used for item level 10 crafting."
|
||||
},
|
||||
"quantity": 5,
|
||||
"owned": 0
|
||||
},
|
||||
{
|
||||
"item": {
|
||||
"id": 683002,
|
||||
@@ -1450,7 +1466,7 @@
|
||||
"glyph": "$",
|
||||
"description": "A boss coin from Tigrex used for item level 10 crafting."
|
||||
},
|
||||
"quantity": 10,
|
||||
"quantity": 5,
|
||||
"owned": 0
|
||||
}
|
||||
],
|
||||
@@ -1477,6 +1493,22 @@
|
||||
"setName": null
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"item": {
|
||||
"id": 383002,
|
||||
"slug": "bulldrome-boss-coin-diff-2-ilvl-10",
|
||||
"name": "Green Bulldrome Coin",
|
||||
"slot": "component",
|
||||
"rarity": "uncommon",
|
||||
"itemLevel": 10,
|
||||
"healingPower": 0,
|
||||
"maxResourceBonus": 0,
|
||||
"glyph": "$",
|
||||
"description": "A boss coin from Bulldrome used for item level 10 crafting."
|
||||
},
|
||||
"quantity": 5,
|
||||
"owned": 0
|
||||
},
|
||||
{
|
||||
"item": {
|
||||
"id": 683002,
|
||||
@@ -1490,7 +1522,7 @@
|
||||
"glyph": "$",
|
||||
"description": "A boss coin from Tigrex used for item level 10 crafting."
|
||||
},
|
||||
"quantity": 10,
|
||||
"quantity": 5,
|
||||
"owned": 0
|
||||
}
|
||||
],
|
||||
@@ -1517,6 +1549,22 @@
|
||||
"setName": null
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"item": {
|
||||
"id": 383002,
|
||||
"slug": "bulldrome-boss-coin-diff-2-ilvl-10",
|
||||
"name": "Green Bulldrome Coin",
|
||||
"slot": "component",
|
||||
"rarity": "uncommon",
|
||||
"itemLevel": 10,
|
||||
"healingPower": 0,
|
||||
"maxResourceBonus": 0,
|
||||
"glyph": "$",
|
||||
"description": "A boss coin from Bulldrome used for item level 10 crafting."
|
||||
},
|
||||
"quantity": 5,
|
||||
"owned": 0
|
||||
},
|
||||
{
|
||||
"item": {
|
||||
"id": 683002,
|
||||
@@ -1530,7 +1578,7 @@
|
||||
"glyph": "$",
|
||||
"description": "A boss coin from Tigrex used for item level 10 crafting."
|
||||
},
|
||||
"quantity": 10,
|
||||
"quantity": 5,
|
||||
"owned": 0
|
||||
}
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user