a
This commit is contained in:
parent
d163ceb291
commit
f6d7412744
94 changed files with 3836 additions and 1226 deletions
|
|
@ -317,8 +317,10 @@
|
|||
(worldRef.items || []).forEach((item, index) => {
|
||||
const row = Array.isArray(itemRows[index]) ? itemRows[index] : [];
|
||||
item._achievementPlayerPlaced = Boolean(row[0]);
|
||||
item._achievementPlayerPlacedCounted = item._achievementPlayerPlaced;
|
||||
item._achievementPlacedAt = row[1] != null && Number.isFinite(Number(row[1])) ? Number(row[1]) : null;
|
||||
});
|
||||
worldRef.achievementPlayerPlacedActiveCount = (worldRef.items || []).reduce((count, item) => count + (item && !item.dead && item._achievementPlayerPlaced ? 1 : 0), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -434,12 +436,25 @@
|
|||
const owner = tarinaiIndex.get(item.ownerId) ?? -1;
|
||||
const carried = item.carriedById ? (tarinaiIndex.get(item.carriedById) ?? -1) : -1;
|
||||
const consumed = item.singleUseConsumedById ? (tarinaiIndex.get(item.singleUseConsumedById) ?? -1) : -1;
|
||||
return [q(item.hp, 10), q(item.maxHp, 10), owner, carried, item.singleUsePending ? 1 : 0, consumed, q(item.createdAt, 10)];
|
||||
const base = [q(item.hp, 10), q(item.maxHp, 10), owner, carried, item.singleUsePending ? 1 : 0, consumed, q(item.createdAt, 10)];
|
||||
if (type === "grave") return base.concat([
|
||||
String(item.memorialFamilyKey || ""),
|
||||
String(item.memorialName || ""),
|
||||
String(item.memorialType || ""),
|
||||
String(item.memorialDeathReason || ""),
|
||||
q(item.memorialDeathTime, 10, -1),
|
||||
String(item.memorialBuilderFamilyKey || ""),
|
||||
JSON.stringify(Array.isArray(item.memorialEligibleFamilyKeys) ? item.memorialEligibleFamilyKeys : []),
|
||||
item.memorialFavorite ? 1 : 0,
|
||||
item.memorialTarinaiKing ? 1 : 0,
|
||||
item.memorialZunchiSlave ? 1 : 0,
|
||||
]);
|
||||
return base;
|
||||
}
|
||||
if (type === "grass") return [q(item.growth, 100), q(item.health, 100), q(item.fertilityBoost, 100), item.manualGrass || item.placedByPlayer ? 1 : 0];
|
||||
if (type === "zunchi") return [enumIndex(STAGE_IDS, item.stage || "fresh"), q(item.freshness, 100), q(item.fertility, 100)];
|
||||
if (type === "signboard") return [item.text || ""];
|
||||
if (type === "robot_cleaner") return [Math.max(0, Math.min(0x3f, Number(item.robotCleanerMask ?? 3) | 0)), item.robotCleanerHighSpeed ? 1 : 0];
|
||||
if (type === "robot_cleaner") return [Math.max(0, Math.min(0x7f, Number(item.robotCleanerMask ?? 3) | 0)), item.robotCleanerHighSpeed ? 1 : 0];
|
||||
if (type === "circuit_board") return [JSON.stringify(global.TarinaiCircuitBoardSystem?.serializeConfig?.(item) || item.circuitConfig || {})];
|
||||
if (global.TarinaiPhysicsBodySystem.isPhysicsType(type)) {
|
||||
const packed = global.TarinaiPhysicsBodySystem.compactItemExtra(item, tarinaiIndex, itemIndex);
|
||||
|
|
@ -482,9 +497,32 @@
|
|||
}
|
||||
function compactItem(item, index, tarinaiIndex = new Map(), itemIndex = new Map()) {
|
||||
const typeId = itemTypeIndex(item?.type || "", -1);
|
||||
if (typeId < 0 || item?.type === "trace") return null;
|
||||
if (typeId < 0) return null;
|
||||
return [typeId, q(item?.x, 1), q(item?.y, 1), q(item?.amount ?? item?.hp, 10), itemExtra(item, tarinaiIndex, itemIndex)];
|
||||
}
|
||||
function compactResidue(residue) {
|
||||
if (!residue || residue.dead || Number(residue.amount || 0) <= 0) return null;
|
||||
const typeCode = residue.type === "splat" ? 1 : (residue.type === "trace" ? 0 : -1);
|
||||
if (typeCode < 0) return null;
|
||||
return [
|
||||
typeCode,
|
||||
q(residue.x, 1),
|
||||
q(residue.y, 1),
|
||||
q(residue.amount, 10),
|
||||
q(residue.r, 10, typeCode === 1 ? 260 : 160),
|
||||
q(residue.seed, 100, 0),
|
||||
];
|
||||
}
|
||||
function restoreResidueRow(worldRef, row) {
|
||||
if (!worldRef || !Array.isArray(row)) return null;
|
||||
const type = Number(row[0]) === 1 ? "splat" : "trace";
|
||||
return worldRef.addResidue?.(type, u(row[1], 1), u(row[2], 1), {
|
||||
amount: u(row[3], 10, type === "splat" ? 260 : 220),
|
||||
r: u(row[4], 10, type === "splat" ? 26 : 16),
|
||||
seed: u(row[5], 100, 0),
|
||||
reason: "restore-residue",
|
||||
}) || null;
|
||||
}
|
||||
function applyItemExtra(item, extra, tarinaiList = [], itemList = []) {
|
||||
const type = item.type || "";
|
||||
if (global.TarinaiPhysicsBodySystem.applyCompactExtra(item, extra, tarinaiList, itemList)) return;
|
||||
|
|
@ -504,6 +542,19 @@
|
|||
if (type === "plushie") {
|
||||
item.onHead = Boolean(item.carriedById);
|
||||
}
|
||||
if (type === "grave") {
|
||||
item.memorialFamilyKey = String(extra[7] || "");
|
||||
item.memorialName = String(extra[8] || "");
|
||||
item.memorialType = String(extra[9] || "");
|
||||
item.memorialDeathReason = String(extra[10] || "");
|
||||
item.memorialDeathTime = Number(extra[11]) >= 0 ? u(extra[11], 10, null) : null;
|
||||
item.memorialBuilderFamilyKey = String(extra[12] || "");
|
||||
try { item.memorialEligibleFamilyKeys = JSON.parse(String(extra[13] || "[]")); } catch (_) { item.memorialEligibleFamilyKeys = []; }
|
||||
if (!Array.isArray(item.memorialEligibleFamilyKeys)) item.memorialEligibleFamilyKeys = [];
|
||||
item.memorialFavorite = Boolean(extra[14]);
|
||||
item.memorialTarinaiKing = Boolean(extra[15]);
|
||||
item.memorialZunchiSlave = Boolean(extra[16]);
|
||||
}
|
||||
const def = global.StructureRegistry?.get?.(type);
|
||||
if (def) {
|
||||
item.label = def.label;
|
||||
|
|
@ -521,7 +572,7 @@
|
|||
item.text = String(extra[0] || "");
|
||||
} else if (type === "robot_cleaner") {
|
||||
const mask = Number(extra[0]);
|
||||
item.robotCleanerMask = Number.isFinite(mask) ? Math.max(0, Math.min(0x3f, mask | 0)) : (global.TarinaiItemDynamicToolSystem?.robotCleanerDefaultMask?.() ?? 3);
|
||||
item.robotCleanerMask = Number.isFinite(mask) ? Math.max(0, Math.min(0x7f, mask | 0)) : (global.TarinaiItemDynamicToolSystem?.robotCleanerDefaultMask?.() ?? 3);
|
||||
item.robotCleanerHighSpeed = Boolean(extra[1]);
|
||||
item.robotCleanerSpeed = global.TarinaiItemDynamicToolSystem?.robotCleanerEffectiveSpeed?.(item) ?? (item.robotCleanerHighSpeed ? 120 : 60);
|
||||
item.robotCleanerTargetId = "";
|
||||
|
|
@ -598,7 +649,7 @@
|
|||
tarinaiLive.forEach((t, i) => { if (t.id) tarinaiIndex.set(t.id, i); if (t.familyKey) familyIndex.set(t.familyKey, i); });
|
||||
const itemRecords = [];
|
||||
for (const it of (worldRef.items || [])) {
|
||||
if (!it || it.dead || it.type === "trace") continue;
|
||||
if (!it || it.dead || it.type === "trace" || it.type === "splat") continue;
|
||||
const typeId = itemTypeIndex(it.type || "", -1);
|
||||
if (typeId < 0) continue;
|
||||
itemRecords.push({ item: it, sortTypeId: typeId, sortX: q(it.x, 1), sortY: q(it.y, 1) });
|
||||
|
|
@ -606,6 +657,12 @@
|
|||
itemRecords.sort((a, b) => (a.sortTypeId || 0) - (b.sortTypeId || 0) || mortonKeyXY(a.sortX, a.sortY) - mortonKeyXY(b.sortX, b.sortY) || String(a.item?.id || "").localeCompare(String(b.item?.id || "")));
|
||||
const itemIndex = new Map();
|
||||
itemRecords.forEach((rec, i) => { if (rec.item?.id) itemIndex.set(rec.item.id, i); });
|
||||
const residueRows = (worldRef.residues || [])
|
||||
.filter(residue => residue && !residue.dead && Number(residue.amount || 0) > 0)
|
||||
.slice()
|
||||
.sort((a, b) => String(a.type || "").localeCompare(String(b.type || "")) || mortonKeyXY(a.x, a.y) - mortonKeyXY(b.x, b.y))
|
||||
.map(compactResidue)
|
||||
.filter(Boolean);
|
||||
const itemRows = itemRecords.map((rec, i) => compactItem(rec.item, i, tarinaiIndex, itemIndex)).filter(Boolean);
|
||||
return {
|
||||
v: SNAPSHOT_VERSION,
|
||||
|
|
@ -614,6 +671,7 @@
|
|||
w: compactWorld(worldRef),
|
||||
t: tarinaiLive.map((t, i) => compactTarinai(t, i, familyIndex, tarinaiIndex, itemIndex)),
|
||||
i: itemRows,
|
||||
r: residueRows,
|
||||
g: compactAchievementMetadata(worldRef, tarinaiLive, itemRecords, options),
|
||||
};
|
||||
}
|
||||
|
|
@ -674,6 +732,7 @@
|
|||
applyItemExtra(item, item.__savedExtra || [], worldRef.tarinai, worldRef.items);
|
||||
delete item.__savedExtra;
|
||||
}
|
||||
for (const row of (Array.isArray(snapshot.r) ? snapshot.r : [])) restoreResidueRow(worldRef, row);
|
||||
for (const t of worldRef.tarinai) {
|
||||
if (Number.isInteger(t.__savedPinIdx) && t.__savedPinIdx >= 0) t.stuckPushpinId = worldRef.items[t.__savedPinIdx]?.id || null;
|
||||
if (Number.isInteger(t.__savedNestIdx) && t.__savedNestIdx >= 0) t.insideNestBoxId = worldRef.items[t.__savedNestIdx]?.id || null;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue