Last active
March 17, 2022 04:26
-
-
Save wallabyway/b83d84e4d2449faf83ad3cbd04aea6ac to your computer and use it in GitHub Desktop.
Run "Tag Equipment To Room". Take a fragmentlist.pack file and list of room dbids, and output a list of object dbids, tagged with room dbids
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
// INSTALL: | |
// run the following commands: | |
// > npm install node-fetch fs-extra aabb-3d | |
// download a rme-advanced/FragmentList.pack file using https://gist.github.com/wallabyway/51a7bf50f5fe2ec19657278494fcd076 | |
// RUNNING: | |
// Run this command, and add a comma list of roomIDs, like this: | |
// > node tagEquipmentToRoom.js [{dbid:9011},{dbid:9261},{dbid:9132}] | |
// RESULT: | |
// this will output a list of object DBIDs tagged with roomIds, like this... | |
// [{roomdbid:9011, equip:[13779,13394,13217]}, {roomdbid:9261, equip:[422,456]}, ... | |
// Dependencies | |
// AABB library: https://gist.github.com/yomotsu/d845f21e2e1eb49f647f | |
*/ | |
const zlib = require('zlib'); | |
const fs = require('fs-extra'); | |
const { read } = require('fs'); | |
var aabb = require('aabb-3d'); | |
class PackFileReader { | |
constructor(buff) { | |
if (buff[0] === 31 && buff[1] === 139) { | |
this.buff = zlib.gunzipSync(buff); | |
} else { | |
this.buff = buff; | |
} | |
this.stream = new InputStream(this.buff); | |
const len = this.stream.getInt32(); | |
this.type = this.stream.getString(len); | |
this.version = this.stream.getInt32(); | |
this.parseContents(); | |
} | |
zipBuffer() { | |
return zlib.gzipSync(this.buff); | |
} | |
parseContents() { | |
// Get offsets to TOC and type sets from the end of the file | |
const originalOffset = this.stream.offset; | |
this.stream.seek(this.stream.length - 8); | |
const entriesOffset = this.stream.getUint32(); | |
const typesOffset = this.stream.getUint32(); | |
// Populate entries | |
this.entries = []; // offsets to individual entries in the pack file | |
this.stream.seek(entriesOffset); | |
const entriesCount = this.stream.getVarint(); | |
for (let i = 0; i < entriesCount; i++) { | |
this.entries.push(this.stream.getUint32()); | |
} | |
// Populate type sets | |
this.types = []; // types of all entries in the pack file | |
this.stream.seek(typesOffset); | |
const typesCount = this.stream.getVarint(); | |
for (let i = 0; i < typesCount; i++) { | |
this.types.push({ | |
_class: this.getString(), | |
_type: this.getString(), | |
version: this.stream.getVarint() | |
}); | |
} | |
// Restore offset | |
this.stream.seek(originalOffset); | |
} | |
numEntries() { | |
return this.entries.length; | |
} | |
seekEntry(i) { | |
if (i >= this.numEntries()) { | |
return null; | |
} | |
// Read the type index and populate the entry data | |
this.stream.seek(this.entries[i]); | |
const type = this.stream.getUint32(); | |
if (type >= this.types.length) { | |
return null; | |
} | |
return this.types[type]; | |
} | |
getString() { | |
return this.stream.getString(this.stream.getVarint()); | |
} | |
} | |
class InputStream { | |
constructor(buffer) { | |
this.buffer = buffer; | |
this.offset = 0; | |
this.length = buffer.length; | |
} | |
seek(offset) { | |
this.offset = offset; | |
} | |
setUint8(value) { | |
this.buffer.writeUInt8(value, this.offset); | |
} | |
getUint8() { | |
const val = this.buffer.readUInt8(this.offset); | |
this.offset += 1; | |
return val; | |
} | |
getUint32() { | |
const val = this.buffer.readUInt32LE(this.offset); | |
this.offset += 4; | |
return val; | |
} | |
getInt32() { | |
const val = this.buffer.readInt32LE(this.offset); | |
this.offset += 4; | |
return val; | |
} | |
getFloat32() { | |
const val = this.buffer.readFloatLE(this.offset); | |
this.offset += 4; | |
return val; | |
} | |
getVarint() { | |
let byte, val = 0, shift = 0; | |
do { | |
byte = this.buffer[this.offset++]; | |
val |= (byte & 0x7f) << shift; | |
shift += 7; | |
} while (byte & 0x80); | |
return val; | |
} | |
getString(len) { | |
const val = this.buffer.toString('utf8', this.offset, this.offset + len); | |
this.offset += len; | |
return val; | |
} | |
} | |
let dbidtoFrag = []; | |
class FragmentReader extends PackFileReader { | |
constructor(buff, configs) { | |
super(buff); | |
this.parseFragments(); | |
} | |
parseFragments() { | |
const entries = this.numEntries(); | |
this.fragments = []; | |
for (let i = 0; i < entries; i++) { | |
const entryType = this.seekEntry(i); | |
console.assert(entryType); | |
console.assert(entryType.version > 4); | |
const fragment = { | |
visible: true, | |
materialID: -1, | |
geometryID: -1, | |
dbID: -1, | |
bbox: [0, 0, 0, 0, 0, 0], | |
glMatrix: null, | |
}; | |
// Flags | |
const flags = this.stream.getUint8(); | |
fragment.visible = (flags & 0x01) !== 0; | |
// Material | |
fragment.materialID = this.stream.getVarint(); | |
// Geometry | |
fragment.geometryID = this.stream.getVarint(); | |
// Transform | |
fragment.xformType = this.stream.getUint8(); | |
// Bounding box | |
for (let i = 0; i < 6; i++) { | |
fragment.bbox[i] = this.stream.getFloat32(); | |
} | |
fragment.aabb = aabb([fragment.bbox[0], fragment.bbox[1], fragment.bbox[2]], [fragment.bbox[3]-fragment.bbox[0], fragment.bbox[4]-fragment.bbox[1], fragment.bbox[5]-fragment.bbox[2]]) | |
// Database ID | |
fragment.dbID = this.stream.getVarint(); | |
dbidtoFrag[fragment.dbID] = fragment; | |
this.fragments.push(fragment); | |
} | |
} | |
} | |
function tagEquipment(uri, rooms) { | |
const reader = new FragmentReader(fs.readFileSync(uri)); | |
reader.fragments.map( frag => { | |
rooms.map( room => { | |
const roomAABB = dbidtoFrag[room.dbid].aabb; | |
if (frag.aabb.intersects(roomAABB)) | |
(room.equip.indexOf(frag.dbID) === -1) && room.equip.push(frag.dbID); | |
}) | |
}); | |
console.log(rooms); | |
} | |
const rooms = [{dbid:9531, equip:[]},{dbid:9532, equip:[]},{dbid:12438, equip:[]}]; | |
tagEquipment("rme-advanced/FragmentList.pack", rooms); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment