Skip to content

Instantly share code, notes, and snippets.

@foxfabi
Created April 24, 2021 11:49
Show Gist options
  • Save foxfabi/08b00abf683f9e7bca409df9ce86e3b0 to your computer and use it in GitHub Desktop.
Save foxfabi/08b00abf683f9e7bca409df9ce86e3b0 to your computer and use it in GitHub Desktop.
Return the CoordinateFrame (CFrame) elements extracted from a Roblox XML file (*.rbxmx) as JSON Array
/**
* Return the CoordinateFrame elements extracted
* from a Roblox XML file (*.rbxmx) as JSON Array.
*
* Models often consist of one part that is used several times
* and usually differ only in position and orientation.
* By extracting the CoordinateFrame from the model, it is now
* possible with a LUA script to clone the underlying part
* and place it dynamically at the desired location.
*
* @author Fabian Dennler <fd@fabforge.ch>
*/
const fs = require('fs')
const glob = require('glob')
const XMLExtract = require('xml-extract')
const parseString = require('xml2js').parseString
// Folder containing the rbmxm files
const folder = './srv/Models/Tree/'
// Pattern to use to identify the same model/object
const pattern = '**/Part.rbxmx'
/**
* Reads the content of the given file
* @param {string} file - the file to read
**/
const getFile = (file) => {
return new Promise((resolve, reject) => {
fs.readFile(file, 'utf8', (error, data) => {
if (error) {
reject(error)
}
resolve(data)
})
})
}
/**
* Parse the given xml, extract the CoordinateFrame
* and transform it into json format
* @param {string} data - the xml structure
**/
const parseXML = (data) => {
return new Promise((resolve, reject) => {
XMLExtract(data, 'CoordinateFrame', true, function (error, element) {
if (error) {
reject(error)
} else {
parseString(element, function (error, result) {
if (error) {
reject(error)
} else {
resolve(JSON.stringify(result))
}
})
}
})
})
}
/**
* Read the
* @param {string} data - the xml structure
**/
const parseFiles = (files) => {
return new Promise((resolve, reject) => {
const cframes = []
let count = 0
for (const file of files) {
getFile(file)
.then(data => parseXML(data)
.then(json => {
count++
cframes.push(json)
if (count === files.length) {
resolve(cframes)
}
})
.catch(err => console.error(err))
).catch(err => console.error(err))
}
})
}
/**
* Search all files matching the given pattern in the given folder
* @param {string} folder - the folder to scan
* @param {string} pattern - the pattern to use for file matching
**/
const extractFiles = function (folder, pattern) {
return new Promise((resolve, reject) => {
glob(folder + pattern, function (error, files) {
if (error) {
reject(error)
} else {
parseFiles(files)
.then(ok => {
console.log(ok)
resolve(ok)
})
.catch(err => {
console.error(err)
})
}
})
})
}
/**
* Main
* @param {string} folder - the folder to scan
* @param {string} pattern - the pattern to use for file matching
**/
extractFiles(folder, pattern)
.then(cframes => console.log(cframes))
.catch(err => console.error(err))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment