UNPKG

mdx-m3-viewer

Version:

A browser WebGL model viewer. Mainly focused on models of the games Warcraft 3 and Starcraft 2.

202 lines (157 loc) 5.02 kB
import IniFile from '../../ini/file'; /** * A standard object mapping strings to function signatures and an optional Jass name. */ type FunctionObject = { [key: string]: { args: string[], scriptName: string | null } }; /** * Trigger data needed to load a WTG file. */ export default class TriggerData { types: StringObject = {}; functions: FunctionObject[] = [{}, {}, {}, {}]; presets: StringObject = {}; externalTypes: StringObject = {}; externalFunctions: FunctionObject[] = [{}, {}, {}, {}]; externalPresets: StringObject = {}; addTriggerData(buffer: string, isExternal: boolean) { let types = this.types; let functions = this.functions; let presets = this.presets; if (isExternal) { types = this.externalTypes; functions = this.externalFunctions; presets = this.externalPresets; } let triggerData = new IniFile(); triggerData.load(buffer); let section = triggerData.getSection('TriggerTypes'); if (section) { this.addTriggerTypes(types, section); } section = triggerData.getSection('TriggerEvents'); if (section) { this.addTriggerDataFunctions(functions[0], section, 1); } section = triggerData.getSection('TriggerConditions'); if (section) { this.addTriggerDataFunctions(functions[1], section, 1); } section = triggerData.getSection('TriggerActions'); if (section) { this.addTriggerDataFunctions(functions[2], section, 1); } section = triggerData.getSection('TriggerCalls'); if (section) { this.addTriggerDataFunctions(functions[3], section, 3); } section = triggerData.getSection('TriggerParams'); if (section) { this.addTriggerDataPresets(presets, section); } } addTriggerTypes(types: StringObject, section: Map<string, string>) { for (let [key, value] of section) { let tokens = value.split(','); types[key] = tokens[4] || ''; } } addTriggerDataFunctions(functions: FunctionObject, section: Map<string, string>, skipped: number) { for (let [key, value] of section) { // We don't care about metadata lines. if (key[0] !== '_') { let tokens = value.split(',').slice(skipped); let args = []; // Can be used by actions to make aliases. let scriptName = section.get(`_${key}_scriptname`) || null; for (let argument of tokens) { // We don't care about constants. if (Number.isNaN(parseFloat(argument)) && argument !== 'nothing' && argument !== '') { args.push(argument); } } functions[key] = { args, scriptName }; } } } addTriggerDataPresets(presets: StringObject, section: Map<string, string>) { for (let [key, value] of section) { let tokens = value.split(','); // Note that the operators are enclosed by "" for some reason. // Note that string literals are enclosed by backticks. presets[key] = tokens[2].replace(/"/g, '').replace(/`/g, '"'); } } /** * Given a type, return its base type. * * Returns the given type if its not a child type. */ getBaseType(type: string) { type = type.toLowerCase(); let base = this.types[type]; if (base === undefined) { base = this.externalTypes[type]; } // Same as !base, but be explicit to be clearer. if (base === '' || base === undefined) { return type; } return base; } isBaseFunction(type: number, name: string) { name = name.toLowerCase(); if (this.functions[type][name]) { return true; } return false; } /** * Gets the signature of the given function. */ getFunction(type: number, name: string) { name = name.toLowerCase(); let args = this.functions[type][name]; if (!args) { args = this.externalFunctions[type][name]; } return args; } /** * Get the type of a function given its name. * Returns -1 if the function isn't recognized. */ getFunctionType(name: string) { name = name.toLowerCase(); let functions = this.functions; for (let i = 0; i < 4; i++) { if (functions[i][name]) { return i; } } return -1; } /** * Gets a preset value. */ getPreset(name: string) { name = name.toLowerCase(); let preset = this.presets[name]; if (preset === undefined) { preset = this.externalPresets[name]; } return preset; } /** * Is the given preset a custom or standard one? */ isCustomPreset(name: string) { name = name.toLowerCase(); if (this.presets[name] !== undefined) { return false; } if (this.externalPresets[name] !== undefined) { return true; } throw new Error(`Failed to find a preset: ${name}`); } }