ChiefOfGxBxL / WC3MapTranslator

Translate war3map ⇄ json formats for WarCraft III .w3x maps
https://www.npmjs.com/package/wc3maptranslator
MIT License
73 stars 31 forks source link

ERR_OUT_OF_RANGE in W3Buffer/InfoTranslator #67

Closed Luashine closed 2 years ago

Luashine commented 2 years ago

I wanted to convert a war3map.w3i (made in v1.26) to JSON to experiment with it. I have no idea how to use the library, so I came up with this by following the included tests:

const wc3 = require('wc3maptranslator')
const fs = require('fs')

const war3infoPath = "war3map.w3i"

function readWar3MapBuffer(filename) {
    return fs.readFileSync(filename);
}

function readJsonTestFile(filename) {
    return fs.readJsonSync(filename);
}

function writeJsonTestFile(filename, json) {
    return fs.writeJsonSync(filename, json);
}

const w3infoData = readWar3MapBuffer(war3infoPath)
const translatedJson = wc3.InfoTranslator.warToJson(w3infoData).json
writeJsonTestFile("war3info.json", translatedJson)

Looks like an off-by-one error? thats hopefully not related to my code:

$ node .
node:internal/buffer:86
  throw new ERR_OUT_OF_RANGE(type || 'offset',
  ^

RangeError [ERR_OUT_OF_RANGE]: The value of "offset" is out of range. It must be >= 0 and <= 735. Received 736
    at new NodeError (node:internal/errors:377:5)
    at boundsError (node:internal/buffer:86:9)
    at Buffer.readInt32LE (node:internal/buffer:390:5)
    at W3Buffer.readInt (/home/user/node_modules/wc3maptranslator/lib/W3Buffer.js:14:34)
    at Function.warToJson (/home/user/node_modules/wc3maptranslator/lib/translators/InfoTranslator.js:346:29)
    at Object.<anonymous> (/home/user/war3-24p/w3i2json.js:32:43)
    at Module._compile (node:internal/modules/cjs/loader:1105:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Module._load (node:internal/modules/cjs/loader:827:12) {
  code: 'ERR_OUT_OF_RANGE'
}

Node.js v18.2.0

I installed the library from npm: version 4.0.0. The .w3i file is attached within zip: war3info.zip

ChiefOfGxBxL commented 2 years ago

Hi @Luashine, thanks for the details and sorry that it's not working! I'll be able to take a look this upcoming weekend.

ChiefOfGxBxL commented 2 years ago

I am able to replicate this issue with the RangeError [ERR_OUT_OF_RANGE]: The value of "offset" is out of range. It must be >= 0 and <= 735. Received 736 error.

It looks like from the .w3i file you provided, you're using a Pre-Reforged data format (version 25 instead of the latest version 31). WC3MapTranslator will be trying to translate this file as if it version 31. Because there were a number of fields added, this will mess up the parsing of older files.

You have a few options:

  1. Open the map you extracted this .w3i file from in World Editor, and then save the map. World Editor will handle the data format upgrade for you, so the .w3i will be in the latest format. Then use that file.
  2. Use an older version of WC3MapTranslator (before v4.0.0). For example, you could try downgrading to npm install --save wc3maptranslator@3.0.2, which was the most recent version to translate Info 25 files.

    V3 has different syntax for translators:

    const wc3maptranslator = new wc3.Translator()
    const translatedJson = wc3maptranslator.Info.warToJson(w3infoData).json

I think the first option is better, because WC3MapTranslator v4 saw some nice improvements to the organization of the translators and the code you'd use to import them and use them. As you can see in the code snippet above, WC3MapTranslator@3.0.2 is a little uglier and more confusing to use.

However, I was able to translate the info file:

{
  map: {
    name: 'TRIGSTR_014',
    author: 'TRIGSTR_017',
    description: 'TRIGSTR_016',
    recommendedPlayers: 'TRIGSTR_015',
    playableArea: { width: 244, height: 244 },
    mainTileType: 'V',
    flags: {
      hideMinimapInPreview: false,
      modifyAllyPriorities: false,
      isMeleeMap: false,
      maskedPartiallyVisible: true,
      fixedPlayerSetting: false,
      useCustomForces: false,
      useCustomTechtree: false,
      useCustomAbilities: false,
      useCustomUpgrades: false,
      waterWavesOnCliffShores: true,
      waterWavesOnRollingShores: true
    }
  },
  loadingScreen: { background: -1, path: '', text: '', title: '', subtitle: '' },
  prologue: { path: '', text: '', title: '', subtitle: '' },
  fog: {
    type: 0,
    startHeight: 3000,
    endHeight: 5000,
    density: 0.5,
    color: [ 0, 0, 0, 255 ]
  },
  camera: {
    bounds: [
      -15104, -15616,
       15104,  15104,
      -15104,  15104,
       15104, -15616
    ],
    complements: [ 6, 6, 4, 8 ]
  },
  players: [
    {
      name: 'TRIGSTR_001',
      startingPos: [Object],
      playerNum: 0,
      type: 1,
      race: 1
    },
    {
      name: 'TRIGSTR_002',
      startingPos: [Object],
      playerNum: 1,
      type: 1,
      race: 1
    },
    {
      name: 'TRIGSTR_003',
      startingPos: [Object],
      playerNum: 2,
      type: 2,
      race: 1
    },
    {
      name: 'TRIGSTR_004',
      startingPos: [Object],
      playerNum: 3,
      type: 2,
      race: 1
    },
    {
      name: 'TRIGSTR_005',
      startingPos: [Object],
      playerNum: 4,
      type: 2,
      race: 1
    },
    {
      name: 'TRIGSTR_006',
      startingPos: [Object],
      playerNum: 5,
      type: 2,
      race: 1
    },
    {
      name: 'TRIGSTR_007',
      startingPos: [Object],
      playerNum: 6,
      type: 2,
      race: 1
    },
    {
      name: 'TRIGSTR_008',
      startingPos: [Object],
      playerNum: 7,
      type: 2,
      race: 1
    },
    {
      name: 'TRIGSTR_009',
      startingPos: [Object],
      playerNum: 8,
      type: 2,
      race: 1
    },
    {
      name: 'TRIGSTR_010',
      startingPos: [Object],
      playerNum: 9,
      type: 2,
      race: 1
    },
    {
      name: 'TRIGSTR_011',
      startingPos: [Object],
      playerNum: 10,
      type: 2,
      race: 1
    },
    {
      name: 'TRIGSTR_012',
      startingPos: [Object],
      playerNum: 11,
      type: 2,
      race: 1
    }
  ],
  forces: [ { flags: [Object], players: -1, name: 'TRIGSTR_013' } ],
  saves: 10,
  editorVersion: 6059,
  globalWeather: '0000',
  customSoundEnvironment: '',
  customLightEnv: '0',
  water: [ 255, 255, 255, 255 ]
}

Let me know how either of these options go and if you encounter any more issues.

Luashine commented 2 years ago

Thanks for the explanation, I thought old versions to be supported. In this case I really want and need to tinker with the 1.26 file. I will find another way then or use the older version as you suggested. :+1:

ChiefOfGxBxL commented 2 years ago

Using an older version is the way to go for now.

There is #65 for adding older file versions to the translators, which I can reconsider supporting. I'll think about the level of effort to build that functionality.