Android build v1.1.23
This commit is contained in:
+59
-11
@@ -51,6 +51,14 @@ function ensureRuntimeMigrations(database) {
|
||||
SET last_saved_at = COALESCE(NULLIF(last_saved_at, ''), created_at, CURRENT_TIMESTAMP)
|
||||
WHERE last_saved_at IS NULL OR last_saved_at = ''
|
||||
`).run()
|
||||
database.exec(`
|
||||
CREATE TABLE IF NOT EXISTS account_iwt2_saves (
|
||||
account_id INTEGER PRIMARY KEY REFERENCES accounts(id) ON DELETE CASCADE,
|
||||
save_json TEXT NOT NULL,
|
||||
character_level INTEGER NOT NULL DEFAULT 1,
|
||||
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`)
|
||||
}
|
||||
|
||||
function sqliteDateFromMs(value) {
|
||||
@@ -1384,6 +1392,46 @@ function importSyncSave(database, accountId, activeCharacterId, payload) {
|
||||
}
|
||||
}
|
||||
|
||||
function readIwt2SyncSave(database, accountId) {
|
||||
const row = database.prepare(`
|
||||
SELECT save_json AS saveJson
|
||||
FROM account_iwt2_saves
|
||||
WHERE account_id = ?
|
||||
`).get(accountId)
|
||||
if (!row) return { save: null }
|
||||
try {
|
||||
return { save: JSON.parse(row.saveJson) }
|
||||
} catch {
|
||||
return { save: null }
|
||||
}
|
||||
}
|
||||
|
||||
function importIwt2SyncSave(database, accountId, payload) {
|
||||
const save = payload?.save
|
||||
if (
|
||||
!save
|
||||
|| typeof save !== 'object'
|
||||
|| Number(save.version) !== 2
|
||||
|| typeof save.updatedAt !== 'number'
|
||||
|| !save.character
|
||||
|| typeof save.character !== 'object'
|
||||
|| typeof save.character.level !== 'number'
|
||||
) {
|
||||
throw new Error('The IWT2 save snapshot is invalid.')
|
||||
}
|
||||
const savedAt = sqliteDateFromMs(save.updatedAt)
|
||||
const characterLevel = clampInteger(save.character.level, 1, 1, 1000000)
|
||||
database.prepare(`
|
||||
INSERT INTO account_iwt2_saves (account_id, save_json, character_level, updated_at)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(account_id) DO UPDATE SET
|
||||
save_json = excluded.save_json,
|
||||
character_level = excluded.character_level,
|
||||
updated_at = excluded.updated_at
|
||||
`).run(accountId, JSON.stringify(save), characterLevel, savedAt)
|
||||
return readIwt2SyncSave(database, accountId)
|
||||
}
|
||||
|
||||
function itemById(database, itemId) {
|
||||
return database.prepare(`
|
||||
SELECT
|
||||
@@ -1544,11 +1592,6 @@ function rollEncounterLoot(database, characterId, encounterId, difficultyId, run
|
||||
`).get(encounterId, difficultyId)
|
||||
if (!context) throw new Error('That loot table is not available.')
|
||||
|
||||
const character = database.prepare('SELECT level FROM characters WHERE id = ?').get(characterId)
|
||||
if (character.level < context.unlockLevel) {
|
||||
throw new Error(`${context.difficultyName} unlocks at level ${context.unlockLevel}.`)
|
||||
}
|
||||
|
||||
const entries = database.prepare(`
|
||||
SELECT
|
||||
encounter_loot.drop_weight AS dropWeight,
|
||||
@@ -2249,9 +2292,6 @@ function completeDungeon(database, characterId, accountId, dungeonId, difficulty
|
||||
JOIN classes ON classes.id = characters.class_id
|
||||
WHERE characters.id = ?
|
||||
`).get(characterId)
|
||||
if (character.level < dungeon.unlockLevel) {
|
||||
throw new Error(`${dungeon.difficultyName} unlocks at level ${dungeon.unlockLevel}.`)
|
||||
}
|
||||
const maxLevel = Number(
|
||||
database.prepare("SELECT value FROM game_settings WHERE key = 'max_level'").get()?.value ?? 25,
|
||||
)
|
||||
@@ -2483,9 +2523,6 @@ function completeRoguelike(database, characterId, accountId, runMetrics) {
|
||||
FROM characters
|
||||
WHERE characters.id = ?
|
||||
`).get(characterId)
|
||||
if (character.level < dungeon.unlockLevel) {
|
||||
throw new Error(`${dungeon.difficultyName} unlocks at level ${dungeon.unlockLevel}.`)
|
||||
}
|
||||
const maxLevel = Number(
|
||||
database.prepare("SELECT value FROM game_settings WHERE key = 'max_level'").get()?.value ?? 25,
|
||||
)
|
||||
@@ -3137,6 +3174,17 @@ export async function handleApiRequest(request, response, next) {
|
||||
return
|
||||
}
|
||||
|
||||
if (request.url === '/api/iwt2/sync-save' && request.method === 'GET') {
|
||||
sendJson(response, 200, readIwt2SyncSave(database, session.accountId))
|
||||
return
|
||||
}
|
||||
|
||||
if (request.url === '/api/iwt2/sync-save' && request.method === 'PUT') {
|
||||
const payload = await readJson(request, 512 * 1024)
|
||||
sendJson(response, 200, importIwt2SyncSave(database, session.accountId, payload))
|
||||
return
|
||||
}
|
||||
|
||||
if (request.url === '/api/profile' && request.method === 'GET') {
|
||||
sendJson(response, 200, getProfile(database, session.characterId, session.accountId))
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user