UNPKG

@runejs/filestore

Version:

Tools for managing the RuneJS filestore.

366 lines (365 loc) 14.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ItemStore = exports.ItemConfig = void 0; const common_1 = require("@runejs/common"); const common_2 = require("@runejs/common"); /** * Contains game client need-to-know level information about a single game item. */ class ItemConfig { gameId; name = null; stackable; value = 0; members; worldOptions; widgetOptions; tradable; teamId; replacedColors; // [ originalColor, newColor ][] replacedTextures; bankNoteId; bankNoteTemplate; stackableAmounts; stackableIds; /** * 2d modelling information for this item. */ model2d = {}; /** * 3d modelling information for this item. */ model3d = { maleModels: [-1, -1, -1], maleHeadModels: [-1, -1], femaleModels: [-1, -1, -1], femaleHeadModels: [-1, -1], }; /** * Additional rendering details. */ rendering = {}; } exports.ItemConfig = ItemConfig; /** * Controls files within the Item Archive of the configuration index. */ class ItemStore { configStore; /** * The Item Archive, containing details about every game item. */ itemArchive; constructor(configStore) { this.configStore = configStore; this.itemArchive = this.configStore.getArchive('items'); } /** * Fetches the ItemConfig object for the specified item game id. * @param itemId The game id of the item to find. */ getItem(itemId) { const itemArchive = this.itemArchive; if (!itemArchive) { common_1.logger.error('Item archive not found.'); return null; } const itemFile = itemArchive.getFile(itemId) || null; if (!itemFile) { common_1.logger.error('Item file not found.'); return null; } return this.decodeItemFile(itemFile); } encodeItemFile(item) { const buffer = new common_2.ByteBuffer(5000); const putOpcode = (opcode) => { buffer.put(opcode); return buffer; }; if (item.model2d.widgetModel !== undefined) { putOpcode(1).put(item.model2d.widgetModel, 'SHORT'); } if (item.name) { putOpcode(2).putString(item.name); } putOpcode(4).put(item.model2d.zoom, 'SHORT'); putOpcode(5).put(item.model2d.rotationX, 'SHORT'); putOpcode(6).put(item.model2d.rotationY, 'SHORT'); putOpcode(7).put(item.model2d.offsetX, 'SHORT'); putOpcode(8).put(item.model2d.offsetY, 'SHORT'); if (item.stackable) { putOpcode(11); } putOpcode(12).put(item.value, 'INT'); if (item.members) { putOpcode(16); } if (item.model3d.maleModels[0] !== -1 || item.model3d.maleModelOffset !== undefined) { putOpcode(23) .put(item.model3d.maleModels[0], 'SHORT') .put(item.model3d.maleModelOffset); } if (item.model3d.maleModels[1] !== -1) { putOpcode(24).put(item.model3d.maleModels[1], 'SHORT'); } if (item.model3d.femaleModels[0] !== -1 || item.model3d.femaleModelOffset !== undefined) { putOpcode(25) .put(item.model3d.femaleModels[0], 'SHORT') .put(item.model3d.femaleModelOffset); } if (item.model3d.femaleModels[1] !== -1) { putOpcode(26).put(item.model3d.femaleModels[1], 'SHORT'); } if (item.worldOptions && item.worldOptions.length !== 0) { for (let i = 0; i < 5; i++) { if (item.worldOptions[i]) { putOpcode(30 + i).putString(item.worldOptions[i]); } } } if (item.widgetOptions && item.widgetOptions.length !== 0) { for (let i = 0; i < 5; i++) { if (item.widgetOptions[i]) { putOpcode(35 + i).putString(item.widgetOptions[i]); } } } if (item.replacedColors && item.replacedColors.length !== 0) { putOpcode(40).put(item.replacedColors.length); for (const [oldColor, newColor] of item.replacedColors) { buffer.put(oldColor, 'SHORT').put(newColor, 'SHORT'); } } if (item.replacedTextures && item.replacedTextures.length !== 0) { putOpcode(41).put(item.replacedTextures.length); for (const [oldTexture, newTexture] of item.replacedTextures) { buffer.put(oldTexture, 'SHORT').put(newTexture, 'SHORT'); } } if (item.tradable) { putOpcode(65); } if (item.model3d.maleModels[2] !== -1) { putOpcode(78).put(item.model3d.maleModels[2], 'SHORT'); } if (item.model3d.femaleModels[2] !== -1) { putOpcode(79).put(item.model3d.femaleModels[2], 'SHORT'); } if (item.model3d.maleHeadModels[0] !== -1) { putOpcode(90).put(item.model3d.maleHeadModels[0], 'SHORT'); } if (item.model3d.femaleHeadModels[0] !== -1) { putOpcode(91).put(item.model3d.femaleHeadModels[0], 'SHORT'); } putOpcode(95).put(item.model2d.rotationZ, 'SHORT'); if (item.bankNoteId) { putOpcode(97).put(item.bankNoteId, 'SHORT'); } if (item.bankNoteTemplate) { putOpcode(98).put(item.bankNoteTemplate, 'SHORT'); } if (item.stackableIds && item.stackableIds.length !== 0) { for (let i = 0; i < 10; i++) { putOpcode(100 + i) .put(item.stackableIds[i], 'SHORT') .put(item.stackableAmounts[i], 'SHORT'); } } putOpcode(110).put(item.rendering.resizeX, 'SHORT'); putOpcode(111).put(item.rendering.resizeY, 'SHORT'); putOpcode(112).put(item.rendering.resizeZ, 'SHORT'); putOpcode(113).put(item.rendering.ambient); putOpcode(114).put(item.rendering.contrast); putOpcode(115).put(item.teamId); putOpcode(0); return buffer.getSlice(0, buffer.writerIndex); } /** * Parses a raw item data file into a readable ItemConfig object. * @param itemFile The raw file-store item data. */ decodeItemFile(itemFile) { const itemConfig = new ItemConfig(); const buffer = itemFile.content; itemConfig.gameId = itemFile.fileId; let run = true; while (run) { const opcode = buffer.get('BYTE', 'UNSIGNED'); if (opcode === 0) { run = false; break; } if (opcode === 1) { itemConfig.model2d.widgetModel = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 2) { itemConfig.name = buffer.getString(); } else if (opcode === 4) { itemConfig.model2d.zoom = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 5) { itemConfig.model2d.rotationX = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 6) { itemConfig.model2d.rotationY = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 7) { itemConfig.model2d.offsetX = buffer.get('SHORT', 'UNSIGNED'); if (itemConfig.model2d.offsetX > 32767) { itemConfig.model2d.offsetX -= 65536; } } else if (opcode === 8) { itemConfig.model2d.offsetY = buffer.get('SHORT', 'UNSIGNED'); if (itemConfig.model2d.offsetY > 32767) { itemConfig.model2d.offsetY -= 65536; } } else if (opcode === 11) { itemConfig.stackable = true; } else if (opcode === 12) { itemConfig.value = buffer.get('INT'); } else if (opcode === 16) { itemConfig.members = true; } else if (opcode === 23) { itemConfig.model3d.maleModels[0] = buffer.get('SHORT', 'UNSIGNED'); itemConfig.model3d.maleModelOffset = buffer.get('BYTE', 'UNSIGNED'); } else if (opcode === 24) { itemConfig.model3d.maleModels[1] = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 25) { itemConfig.model3d.femaleModels[0] = buffer.get('SHORT', 'UNSIGNED'); itemConfig.model3d.femaleModelOffset = buffer.get('BYTE', 'UNSIGNED'); } else if (opcode === 26) { itemConfig.model3d.femaleModels[1] = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode >= 30 && opcode < 35) { if (!itemConfig.worldOptions) { itemConfig.worldOptions = new Array(5).fill(null); } itemConfig.worldOptions[opcode - 30] = buffer.getString(); if (itemConfig.worldOptions[opcode - 30] === 'Hidden' || itemConfig.worldOptions[opcode - 30] === 'hidden') { itemConfig.worldOptions[opcode - 30] = null; } } else if (opcode >= 35 && opcode < 40) { if (!itemConfig.widgetOptions) { itemConfig.widgetOptions = new Array(5).fill(null); } itemConfig.widgetOptions[opcode - 35] = buffer.getString(); if (itemConfig.widgetOptions[opcode - 35] === 'Hidden' || itemConfig.widgetOptions[opcode - 35] === 'hidden') { itemConfig.widgetOptions[opcode - 35] = null; } } else if (opcode === 40) { const colorCount = buffer.get('BYTE', 'UNSIGNED'); itemConfig.replacedColors = new Array(colorCount); itemConfig.replacedColors.fill([-1, -1]); for (let colorIndex = 0; colorIndex < colorCount; colorIndex++) { itemConfig.replacedColors[colorIndex][0] = buffer.get('SHORT', 'UNSIGNED'); itemConfig.replacedColors[colorIndex][1] = buffer.get('SHORT', 'UNSIGNED'); } } else if (opcode === 41) { const textureCount = buffer.get('BYTE', 'UNSIGNED'); itemConfig.replacedTextures = new Array(textureCount); itemConfig.replacedTextures.fill([-1, -1]); for (let textureIndex = 0; textureIndex < textureCount; textureIndex++) { itemConfig.replacedTextures[textureIndex][0] = buffer.get('SHORT', 'UNSIGNED'); itemConfig.replacedTextures[textureIndex][1] = buffer.get('SHORT', 'UNSIGNED'); } } else if (opcode === 65) { itemConfig.tradable = true; } else if (opcode === 78) { itemConfig.model3d.maleModels[2] = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 79) { itemConfig.model3d.femaleModels[2] = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 90) { itemConfig.model3d.maleHeadModels[0] = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 91) { itemConfig.model3d.femaleHeadModels[0] = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 92) { itemConfig.model3d.maleHeadModels[1] = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 93) { itemConfig.model3d.femaleHeadModels[1] = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 95) { itemConfig.model2d.rotationZ = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 97) { itemConfig.bankNoteId = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 98) { itemConfig.bankNoteTemplate = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode >= 100 && opcode < 110) { if (!itemConfig.stackableIds) { itemConfig.stackableAmounts = new Array(10); itemConfig.stackableIds = new Array(10); } itemConfig.stackableIds[opcode - 100] = buffer.get('SHORT', 'UNSIGNED'); itemConfig.stackableAmounts[opcode - 100] = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 110) { itemConfig.rendering.resizeX = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 111) { itemConfig.rendering.resizeY = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 112) { itemConfig.rendering.resizeZ = buffer.get('SHORT', 'UNSIGNED'); } else if (opcode === 113) { itemConfig.rendering.ambient = buffer.get('BYTE'); } else if (opcode === 114) { itemConfig.rendering.contrast = buffer.get('BYTE'); } else if (opcode === 115) { itemConfig.teamId = buffer.get('BYTE', 'UNSIGNED'); } } itemFile.content.readerIndex = 0; return itemConfig; } /** * Decodes every item file within the item archive and returns * the resulting ItemConfig array. */ decodeItemStore() { if (!this.itemArchive) { common_1.logger.error('Item archive not found.'); return null; } const itemCount = this.itemArchive.files.size; const itemList = new Array(itemCount); for (let itemId = 0; itemId < itemCount; itemId++) { const itemFile = this.itemArchive.getFile(itemId) || null; if (!itemFile) { common_1.logger.error('Item file not found.'); return null; } itemList[itemId] = this.decodeItemFile(itemFile); } return itemList; } } exports.ItemStore = ItemStore;