mdx-m3-viewer
Version:
A browser WebGL model viewer. Mainly focused on models of the games Warcraft 3 and Starcraft 2.
301 lines (236 loc) • 9.26 kB
text/typescript
import BinaryStream from '../../../common/binarystream';
import Force from './force';
import Player from './player';
import RandomItemTable from './randomitemtable';
import RandomUnitTable from './randomunittable';
import TechAvailabilityChange from './techavailabilitychange';
import UpgradeAvailabilityChange from './upgradeavailabilitychange';
/**
* war3map.w3i - the general information file.
*/
export default class War3MapW3i {
version: number = 0;
saves: number = 0;
editorVersion: number = 0;
buildVersion: Uint32Array = new Uint32Array(4);
name: string = '';
author: string = '';
description: string = '';
recommendedPlayers: string = '';
cameraBounds: Float32Array = new Float32Array(8);
cameraBoundsComplements: Int32Array = new Int32Array(4);
playableSize: Int32Array = new Int32Array(2);
flags: number = 0;
tileset: string = 'A';
campaignBackground: number = 0;
loadingScreenModel: string = '';
loadingScreenText: string = '';
loadingScreenTitle: string = '';
loadingScreenSubtitle: string = '';
loadingScreen: number = 0;
prologueScreenModel: string = '';
prologueScreenText: string = '';
prologueScreenTitle: string = '';
prologueScreenSubtitle: string = '';
useTerrainFog: number = 0;
fogHeight: Float32Array = new Float32Array(2);
fogDensity: number = 0;
fogColor: Uint8Array = new Uint8Array(4);
globalWeather: number = 0;
soundEnvironment: string = '';
lightEnvironmentTileset: string = '\0';
waterVertexColor: Uint8Array = new Uint8Array(4);
scriptMode: number = 0;
graphicsMode: number = 0;
players: Player[] = [];
forces: Force[] = [];
upgradeAvailabilityChanges: UpgradeAvailabilityChange[] = [];
techAvailabilityChanges: TechAvailabilityChange[] = [];
randomUnitTables: RandomUnitTable[] = [];
randomItemTables: RandomItemTable[] = [];
unknown1: number = 0;
constructor(buffer?: ArrayBuffer) {
if (buffer) {
this.load(buffer);
}
}
load(buffer: ArrayBuffer) {
let stream = new BinaryStream(buffer);
this.version = stream.readInt32();
this.saves = stream.readInt32();
this.editorVersion = stream.readInt32();
if (this.version > 27) {
stream.readUint32Array(this.buildVersion);
}
this.name = stream.readUntilNull();
this.author = stream.readUntilNull();
this.description = stream.readUntilNull();
this.recommendedPlayers = stream.readUntilNull();
stream.readFloat32Array(this.cameraBounds);
stream.readInt32Array(this.cameraBoundsComplements);
stream.readInt32Array(this.playableSize);
this.flags = stream.readUint32();
this.tileset = stream.read(1);
this.campaignBackground = stream.readInt32();
if (this.version > 24) {
this.loadingScreenModel = stream.readUntilNull();
}
this.loadingScreenText = stream.readUntilNull();
this.loadingScreenTitle = stream.readUntilNull();
this.loadingScreenSubtitle = stream.readUntilNull();
this.loadingScreen = stream.readInt32();
if (this.version > 24) {
this.prologueScreenModel = stream.readUntilNull();
}
this.prologueScreenText = stream.readUntilNull();
this.prologueScreenTitle = stream.readUntilNull();
this.prologueScreenSubtitle = stream.readUntilNull();
if (this.version > 24) {
this.useTerrainFog = stream.readInt32();
stream.readFloat32Array(this.fogHeight);
this.fogDensity = stream.readFloat32();
stream.readUint8Array(this.fogColor);
this.globalWeather = stream.readInt32();
this.soundEnvironment = stream.readUntilNull();
this.lightEnvironmentTileset = stream.read(1, true);
stream.readUint8Array(this.waterVertexColor);
}
if (this.version > 27) {
this.scriptMode = stream.readUint32();
}
if (this.version > 30) {
this.graphicsMode = stream.readUint32();
this.unknown1 = stream.readUint32();
}
for (let i = 0, l = stream.readInt32(); i < l; i++) {
let player = new Player();
player.load(stream, this.version);
this.players[i] = player;
}
for (let i = 0, l = stream.readInt32(); i < l; i++) {
let force = new Force();
force.load(stream);
this.forces[i] = force;
}
for (let i = 0, l = stream.readInt32(); i < l; i++) {
let upgradeAvailabilityChange = new UpgradeAvailabilityChange();
upgradeAvailabilityChange.load(stream);
this.upgradeAvailabilityChanges[i] = upgradeAvailabilityChange;
}
for (let i = 0, l = stream.readInt32(); i < l; i++) {
let techAvailabilityChange = new TechAvailabilityChange();
techAvailabilityChange.load(stream);
this.techAvailabilityChanges[i] = techAvailabilityChange;
}
for (let i = 0, l = stream.readInt32(); i < l; i++) {
let randomUnitTable = new RandomUnitTable();
randomUnitTable.load(stream);
this.randomUnitTables[i] = randomUnitTable;
}
if (this.version > 24) {
for (let i = 0, l = stream.readInt32(); i < l; i++) {
let randomItemTable = new RandomItemTable();
randomItemTable.load(stream);
this.randomItemTables[i] = randomItemTable;
}
}
}
save() {
let buffer = new ArrayBuffer(this.getByteLength());
let stream = new BinaryStream(buffer);
stream.writeInt32(this.version);
stream.writeInt32(this.saves);
stream.writeInt32(this.editorVersion);
if (this.version > 27) {
stream.writeUint32Array(this.buildVersion);
}
stream.write(`${this.name}\0`);
stream.write(`${this.author}\0`);
stream.write(`${this.description}\0`);
stream.write(`${this.recommendedPlayers}\0`);
stream.writeFloat32Array(this.cameraBounds);
stream.writeInt32Array(this.cameraBoundsComplements);
stream.writeInt32Array(this.playableSize);
stream.writeUint32(this.flags);
stream.write(this.tileset);
stream.writeInt32(this.campaignBackground);
if (this.version > 24) {
stream.write(`${this.loadingScreenModel}\0`);
}
stream.write(`${this.loadingScreenText}\0`);
stream.write(`${this.loadingScreenTitle}\0`);
stream.write(`${this.loadingScreenSubtitle}\0`);
stream.writeInt32(this.loadingScreen);
if (this.version > 24) {
stream.write(`${this.prologueScreenModel}\0`);
}
stream.write(`${this.prologueScreenText}\0`);
stream.write(`${this.prologueScreenTitle}\0`);
stream.write(`${this.prologueScreenSubtitle}\0`);
if (this.version > 24) {
stream.writeInt32(this.useTerrainFog);
stream.writeFloat32Array(this.fogHeight);
stream.writeFloat32(this.fogDensity);
stream.writeUint8Array(this.fogColor);
stream.writeInt32(this.globalWeather);
stream.write(`${this.soundEnvironment}\0`);
stream.write(this.lightEnvironmentTileset);
stream.writeUint8Array(this.waterVertexColor);
}
if (this.version > 27) {
stream.writeUint32(this.scriptMode);
}
if (this.version > 30) {
stream.writeUint32(this.graphicsMode);
stream.writeUint32(this.unknown1);
}
stream.writeUint32(this.players.length);
for (let player of this.players) {
player.save(stream, this.version);
}
stream.writeUint32(this.forces.length);
for (let force of this.forces) {
force.save(stream);
}
stream.writeUint32(this.upgradeAvailabilityChanges.length);
for (let change of this.upgradeAvailabilityChanges) {
change.save(stream);
}
stream.writeUint32(this.techAvailabilityChanges.length);
for (let change of this.techAvailabilityChanges) {
change.save(stream);
}
stream.writeUint32(this.randomUnitTables.length);
for (let table of this.randomUnitTables) {
table.save(stream);
}
if (this.version > 24) {
stream.writeUint32(this.randomItemTables.length);
for (let table of this.randomItemTables) {
table.save(stream);
}
}
return buffer;
}
getByteLength() {
let size = 111 + this.name.length + this.author.length + this.description.length + this.recommendedPlayers.length + this.loadingScreenText.length + this.loadingScreenTitle.length + this.loadingScreenSubtitle.length + this.prologueScreenText.length + this.prologueScreenTitle.length + this.prologueScreenSubtitle.length;
for (let player of this.players) {
size += player.getByteLength(this.version);
}
for (let force of this.forces) {
size += force.getByteLength();
}
size += this.upgradeAvailabilityChanges.length * 16;
size += this.techAvailabilityChanges.length * 8;
for (let table of this.randomUnitTables) {
size += table.getByteLength();
}
if (this.version > 24) {
size += 36 + this.loadingScreenModel.length + this.prologueScreenModel.length + this.soundEnvironment.length;
for (let table of this.randomItemTables) {
size += table.getByteLength();
}
}
return size;
}
}