This commit is contained in:
33333-33333 2026-07-01 16:55:49 +09:00
commit c9dd7182aa
35 changed files with 478 additions and 288 deletions

View file

@ -426,6 +426,16 @@
if (SERVING_FOOD_TYPE_IDS.has(typeId)) return false;
return true;
}
function defaultStructureHp10(typeId) {
if (ITEM_TYPE_IDS[typeId] === "grass_bed") return 1000;
if (ITEM_TYPE_IDS[typeId] === "plushie") return 10;
return 10;
}
function defaultNeedsFromVitals(hunger = 0, energy = 0, sleepPressure = 0) {
const food = Math.max(0, Math.min(100, Math.round(Number(hunger) || 0)));
const sleep = Math.max(0, Math.min(100, Math.round(Math.max(Number(sleepPressure) || 0, 100 - (Number(energy) || 0)))));
return [food, sleep, 0, 0, 0, 0];
}
function writeRelationships(writer, rows = []) {
const list = Array.isArray(rows) ? rows : [];
writer.u(list.length);
@ -523,19 +533,17 @@
const defaultPersonality = seedPersonalityArray(birthSeed, flags);
const defaultTimers = [0, 0, 0, 0, 0, 0, 0, 0, 100];
let bodyMask = 0;
if (arrayHasValues(row[9], [0, 0, 0, 0, 0, 0])) bodyMask |= 1;
if (arrayHasValues(row[10], defaultPersonality)) bodyMask |= 2;
if ((row[11] || []).length) bodyMask |= 4;
if ((row[12] || []).length) bodyMask |= 8;
if (arrayHasValues(row[13], defaultTimers)) bodyMask |= 16;
if (arrayHasValues(row[14], [0, 0, 0])) bodyMask |= 32;
writeBitFields(writer, [bodyMask], [6]);
if (bodyMask & 1) writeFixedPacked(writer, row[9], 6, 6, 2);
if (bodyMask & 2) writeFixedDiffPacked(writer, defaultPersonality, row[10], 4, 8);
if (bodyMask & 4) writeIndexList(writer, row[11]);
if (bodyMask & 8) writeRelationships(writer, row[12]);
if (bodyMask & 16) writeTimers(writer, row[13]);
if (bodyMask & 32) writeModes(writer, row[14]);
if (arrayHasValues(row[10], defaultPersonality)) bodyMask |= 1;
if ((row[11] || []).length) bodyMask |= 2;
if ((row[12] || []).length) bodyMask |= 4;
if (arrayHasValues(row[13], defaultTimers)) bodyMask |= 8;
if (arrayHasValues(row[14], [0, 0, 0])) bodyMask |= 16;
writeBitFields(writer, [bodyMask], [5]);
if (bodyMask & 1) writeFixedDiffPacked(writer, defaultPersonality, row[10], 4, 8);
if (bodyMask & 2) writeIndexList(writer, row[11]);
if (bodyMask & 4) writeRelationships(writer, row[12]);
if (bodyMask & 8) writeTimers(writer, row[13]);
if (bodyMask & 16) writeModes(writer, row[14]);
let tailMask = 0;
if (pinIdx >= 0) tailMask |= 1;
if (nestIdx >= 0) tailMask |= 2;
@ -558,13 +566,13 @@
const generation = (coordState?.generation || 1) + reader.s();
if (coordState) { coordState.x = x; coordState.y = y; coordState.age = age; coordState.generation = generation; }
const [hunger, energy, sleepPressure] = readBitFields(reader, [8, 8, 8]);
const [bodyMask] = readBitFields(reader, [6]);
const needs = (bodyMask & 1) ? readFixedPacked(reader, 6, 6, 2) : [0, 0, 0, 0, 0, 0];
const current = (bodyMask & 2) ? readFixedDiffPacked(reader, seedPersonalityArray(birthSeed, flags), 4, 8) : seedPersonalityArray(birthSeed, flags);
const parents = (bodyMask & 4) ? readIndexList(reader) : [];
const relationships = (bodyMask & 8) ? readRelationships(reader) : [];
const timers = (bodyMask & 16) ? readTimers(reader) : [0, 0, 0, 0, 0, 0, 0, 0, 100];
const modes = (bodyMask & 32) ? readModes(reader) : [0, 0, 0];
const [bodyMask] = readBitFields(reader, [5]);
const needs = defaultNeedsFromVitals(hunger, energy, sleepPressure);
const current = (bodyMask & 1) ? readFixedDiffPacked(reader, seedPersonalityArray(birthSeed, flags), 4, 8) : seedPersonalityArray(birthSeed, flags);
const parents = (bodyMask & 2) ? readIndexList(reader) : [];
const relationships = (bodyMask & 4) ? readRelationships(reader) : [];
const timers = (bodyMask & 8) ? readTimers(reader) : [0, 0, 0, 0, 0, 0, 0, 0, 100];
const modes = (bodyMask & 16) ? readModes(reader) : [0, 0, 0];
const [tailMask] = readBitFields(reader, [5]);
const pinIdx = (tailMask & 1) ? reader.u() : -1;
const nestIdx = (tailMask & 2) ? reader.u() : -1;
@ -576,31 +584,41 @@
function writeItemExtra(writer, typeId, extra = []) {
if (STRUCTURE_TYPE_IDS.has(typeId)) {
writer.s(extra[0] || 0);
writer.s(extra[1] || 0);
const defaultHp = defaultStructureHp10(typeId);
const hp = toSafeInt(extra[0] || 0);
const maxHp = toSafeInt(extra[1] || 0);
let mask = 0;
if ((extra[2] ?? -1) >= 0) mask |= 1;
if ((extra[3] ?? -1) >= 0) mask |= 2;
if (extra[4]) mask |= 4;
if ((extra[5] ?? -1) >= 0) mask |= 8;
if (valuesDiffer(extra[6], 0)) mask |= 16;
writeBitFields(writer, [mask], [5]);
if (mask & 1) writer.u(extra[2]);
if (mask & 2) writer.u(extra[3]);
if (mask & 8) writer.u(extra[5]);
if (mask & 16) writer.s(extra[6] || 0);
if (valuesDiffer(hp, defaultHp)) mask |= 1;
if (valuesDiffer(maxHp, defaultHp)) mask |= 2;
if ((extra[2] ?? -1) >= 0) mask |= 4;
if ((extra[3] ?? -1) >= 0) mask |= 8;
if (extra[4]) mask |= 16;
if ((extra[5] ?? -1) >= 0) mask |= 32;
if (valuesDiffer(extra[6], 0)) mask |= 64;
writeBitFields(writer, [mask], [7]);
if (mask & 1) writer.s(hp);
if (mask & 2) writer.s(maxHp);
if (mask & 4) writer.u(extra[2]);
if (mask & 8) writer.u(extra[3]);
if (mask & 32) writer.u(extra[5]);
if (mask & 64) writer.s(extra[6] || 0);
} else if (typeId === 0) { // grass
writer.s(extra[0] || 0); writer.s(extra[1] || 0);
writer.s(extra[0] || 0);
let mask = 0;
if (valuesDiffer(extra[2], 0)) mask |= 1;
if (extra[3]) mask |= 2;
writeBitFields(writer, [mask], [2]);
if (mask & 1) writer.s(extra[2] || 0);
if (valuesDiffer(extra[1], 100)) mask |= 1;
if (valuesDiffer(extra[2], 0)) mask |= 2;
if (extra[3]) mask |= 4;
writeBitFields(writer, [mask], [3]);
if (mask & 1) writer.s(extra[1] || 0);
if (mask & 2) writer.s(extra[2] || 0);
} else if (typeId === 1) { // zunchi
writeBitFields(writer, [extra[0] || 0], [2]);
writer.s(extra[1] || 0);
if (valuesDiffer(extra[2], 0)) { writer.u(1); writer.s(extra[2] || 0); }
else writer.u(0);
let mask = 0;
if (valuesDiffer(extra[1], 100)) mask |= 1;
if (valuesDiffer(extra[2], 0)) mask |= 2;
writeBitFields(writer, [mask], [2]);
if (mask & 1) writer.s(extra[1] || 0);
if (mask & 2) writer.s(extra[2] || 0);
} else if (typeId === 22) { // signboard
writeSaveString(writer, extra[0] || "");
} else if (typeId === 6) { // duplicator
@ -643,29 +661,29 @@
}
function readItemExtra(reader, typeId) {
if (STRUCTURE_TYPE_IDS.has(typeId)) {
const hp = reader.s();
const maxHp = reader.s();
const [mask] = readBitFields(reader, [5]);
const defaultHp = defaultStructureHp10(typeId);
const [mask] = readBitFields(reader, [7]);
const hp = (mask & 1) ? reader.s() : defaultHp;
const maxHp = (mask & 2) ? reader.s() : defaultHp;
return [
hp,
maxHp,
(mask & 1) ? reader.u() : -1,
(mask & 2) ? reader.u() : -1,
(mask & 4) ? 1 : 0,
(mask & 4) ? reader.u() : -1,
(mask & 8) ? reader.u() : -1,
(mask & 16) ? reader.s() : 0,
(mask & 16) ? 1 : 0,
(mask & 32) ? reader.u() : -1,
(mask & 64) ? reader.s() : 0,
];
}
if (typeId === 0) {
const growth = reader.s();
const health = reader.s();
const [mask] = readBitFields(reader, [2]);
return [growth, health, (mask & 1) ? reader.s() : 0, (mask & 2) ? 1 : 0];
const [mask] = readBitFields(reader, [3]);
return [growth, (mask & 1) ? reader.s() : 100, (mask & 2) ? reader.s() : 0, (mask & 4) ? 1 : 0];
}
if (typeId === 1) {
const [stage] = readBitFields(reader, [2]);
const freshness = reader.s();
return [stage, freshness, reader.u() ? reader.s() : 0];
const [mask] = readBitFields(reader, [2]);
return [stage, (mask & 1) ? reader.s() : 100, (mask & 2) ? reader.s() : 0];
}
if (typeId === 22) return [readSaveString(reader)];
if (typeId === 6) return [reader.s()];