UNPKG

sc4

Version:

A command line utility for automating SimCity 4 modding tasks & modifying savegames

228 lines (227 loc) 6.99 kB
// # region-view-file.js import semver from 'semver'; import Stream from './stream.js'; import { FileType } from './enums.js'; import { kFileType } from './symbols.js'; import Unknown from './unknown.js'; import WriteBuffer from './write-buffer.js'; // # RegionView export default class RegionView { static [kFileType] = FileType.RegionView; version = '1.13'; x = 0; z = 0; xSize = 0; zSize = 0; population; rating = 0; starCount = 0; tutorial = false; guid = 0x00000000; mode = 'god'; name = ''; formerName = ''; mayorName = ''; description = ''; defaultMayor = 'Jonas Sparks'; currentInfo = []; maxInfo = []; limits = []; unknownFloats = []; neighbourConnections = []; u = new Unknown() .float(0) .repeat(5, u => u.dword(0x00000000)) .repeat(5, u => u.dword(0x00000000)) .dword(0xffffffff) .array() .dword() .float(0) .dword() .float(0) .array() .array() .array() .array(); // ## parse(buff) // Partially read in. This stuff is pretty much read-only for now, no // need to fully parse it yet. parse(buff) { this.u = new Unknown(); let rs = new Stream(buff); const unknown = this.u.reader(rs); this.version = rs.version(2); this.x = rs.dword(); this.z = rs.dword(); this.xSize = rs.dword(); this.zSize = rs.dword(); this.population = { residential: rs.dword(), commercial: rs.dword(), industrial: rs.dword(), }; if (semver.gt(`${this.version}.0`, '1.9.0')) { unknown.float(); } if (semver.gt(`${this.version}.0`, '1.10.0')) { this.rating = rs.byte(); } this.starCount = rs.byte(); this.tutorial = rs.bool(); this.guid = rs.dword(); unknown.repeat(5, u => u.dword()); this.mode = rs.byte() === 1 ? 'mayor' : 'god'; this.name = rs.string(); this.formerName = rs.string(); this.mayorName = rs.string(); this.description = rs.string(); this.defaultMayor = rs.string(); unknown.repeat(5, u => u.dword(0x00000000)); unknown.dword(0xffffffff); this.currentInfo = rs.array(() => { let occupantGroup = rs.dword(); let population = rs.dword(); return { occupantGroup, population }; }); this.maxInfo = rs.array(() => { let occupantGroup = rs.dword(); let population = rs.dword(); return { occupantGroup, population }; }); this.limits = rs.array(() => { let occupantGroup = rs.dword(); let population = rs.dword(); return { occupantGroup, population }; }); this.unknownFloats = rs.array(() => rs.float()); this.neighbourConnections = rs.array(() => { return new NeighbourConnection().parse(rs); }); unknown.array(unknown => { unknown.dword(); unknown.dword(); unknown.bytes(5); }); unknown.dword(); unknown.float(); unknown.dword(); unknown.float(); unknown.array(unknown => { unknown.dword(); unknown.repeat(5, unknown => { unknown.dword(); unknown.float(); }); }); unknown.array(unknown => unknown.bytes(76)); unknown.array(unknown => unknown.bytes(76)); unknown.array(unknown => { unknown.dword(); unknown.array(unknown => { unknown.float(); unknown.float(); unknown.float(); }); }); rs.assert(); } toBuffer() { let ws = new WriteBuffer(); let unknown = this.u.writer(ws); ws.version(this.version); ws.dword(this.x); ws.dword(this.z); ws.dword(this.xSize); ws.dword(this.zSize); ws.dword(this.population.residential); ws.dword(this.population.commercial); ws.dword(this.population.industrial); if (semver.gt(`${this.version}.0`, '1.9.0')) { unknown.float(); } if (semver.gt(`${this.version}.0`, '1.10.0')) { ws.byte(this.rating); } ws.byte(this.starCount); ws.bool(this.tutorial); ws.dword(this.guid); unknown.repeat(5, u => u.dword()); ws.byte(this.mode === 'mayor' ? 1 : 0); ws.string(this.name); ws.string(this.formerName); ws.string(this.mayorName); ws.string(this.description); ws.string(this.defaultMayor); unknown.repeat(5, u => u.dword()); unknown.dword(); ws.array(this.currentInfo, info => { ws.dword(info.occupantGroup); ws.dword(info.population); }); ws.array(this.maxInfo, info => { ws.dword(info.occupantGroup); ws.dword(info.population); }); ws.array(this.limits, info => { ws.dword(info.occupantGroup); ws.dword(info.population); }); ws.array(this.unknownFloats, ws.float); ws.array(this.neighbourConnections); unknown.array(unknown => { unknown.dword(); unknown.dword(); unknown.bytes(); }); unknown.dword(); unknown.float(); unknown.dword(); unknown.float(); unknown.array(unknown => { unknown.dword(); unknown.repeat(5, unknown => { unknown.dword(); unknown.float(); }); }); unknown.array(unknown => unknown.bytes()); unknown.array(unknown => unknown.bytes()); unknown.array(unknown => { unknown.dword(); unknown.array(unknown => { unknown.float(); unknown.float(); unknown.float(); }); }); return ws.toUint8Array(); } } class NeighbourConnection { version = '1'; type = 0x00000000; connection = [0x00000000, 0x00000000]; destination = [0x00000000, 0x00000000]; byte = 0x00; sgprops = []; propertyVersion = 2; parse(rs) { this.version = rs.version(1); this.type = rs.dword(); this.connection = [rs.dword(), rs.dword()]; this.destination = [rs.dword(), rs.dword()]; this.byte = rs.byte(); this.propertyVersion = rs.word(); this.sgprops = rs.sgprops(); return this; } write(ws) { ws.version(this.version); ws.dword(this.type); ws.tuple(this.connection, ws.dword); ws.tuple(this.destination, ws.dword); ws.byte(this.byte); ws.word(this.propertyVersion); ws.array(this.sgprops); } }