2018-12-01 05:20:42 -08:00
|
|
|
const fs = require('fs-extra')
|
2018-08-07 01:16:15 -07:00
|
|
|
const path = require('path')
|
|
|
|
const { shell } = require('electron')
|
|
|
|
|
|
|
|
// Group #1: File Name (without .disabled, if any)
|
|
|
|
// Group #2: File Extension (jar, zip, or litemod)
|
|
|
|
// Group #3: If it is disabled (if string 'disabled' is present)
|
|
|
|
const MOD_REGEX = /^(.+(jar|zip|litemod))(?:\.(disabled))?$/
|
|
|
|
const DISABLED_EXT = '.disabled'
|
|
|
|
|
2018-12-21 03:51:08 -08:00
|
|
|
const SHADER_REGEX = /^(.+)\.zip$/
|
|
|
|
const SHADER_OPTION = /shaderPack=(.+)/
|
2018-12-21 13:06:34 -08:00
|
|
|
const SHADER_DIR = 'shaderpacks'
|
|
|
|
const SHADER_CONFIG = 'optionsshaders.txt'
|
2018-12-21 03:51:08 -08:00
|
|
|
|
2018-11-20 02:19:59 -08:00
|
|
|
/**
|
2018-12-21 03:51:08 -08:00
|
|
|
* Validate that the given directory exists. If not, it is
|
|
|
|
* created.
|
2018-11-20 02:19:59 -08:00
|
|
|
*
|
|
|
|
* @param {string} modsDir The path to the mods directory.
|
|
|
|
*/
|
2018-12-21 03:51:08 -08:00
|
|
|
exports.validateDir = function(dir) {
|
|
|
|
fs.ensureDirSync(dir)
|
2018-11-20 02:19:59 -08:00
|
|
|
}
|
|
|
|
|
2018-08-07 01:16:15 -07:00
|
|
|
/**
|
|
|
|
* Scan for drop-in mods in both the mods folder and version
|
|
|
|
* safe mods folder.
|
|
|
|
*
|
|
|
|
* @param {string} modsDir The path to the mods directory.
|
|
|
|
* @param {string} version The minecraft version of the server configuration.
|
|
|
|
*
|
|
|
|
* @returns {{fullName: string, name: string, ext: string, disabled: boolean}[]}
|
|
|
|
* An array of objects storing metadata about each discovered mod.
|
|
|
|
*/
|
|
|
|
exports.scanForDropinMods = function(modsDir, version) {
|
|
|
|
const modsDiscovered = []
|
|
|
|
if(fs.existsSync(modsDir)){
|
|
|
|
let modCandidates = fs.readdirSync(modsDir)
|
|
|
|
let verCandidates = []
|
|
|
|
const versionDir = path.join(modsDir, version)
|
|
|
|
if(fs.existsSync(versionDir)){
|
|
|
|
verCandidates = fs.readdirSync(versionDir)
|
|
|
|
}
|
2018-08-07 01:41:26 -07:00
|
|
|
for(let file of modCandidates){
|
2018-08-07 01:16:15 -07:00
|
|
|
const match = MOD_REGEX.exec(file)
|
|
|
|
if(match != null){
|
|
|
|
modsDiscovered.push({
|
|
|
|
fullName: match[0],
|
|
|
|
name: match[1],
|
|
|
|
ext: match[2],
|
|
|
|
disabled: match[3] != null
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2018-08-07 01:41:26 -07:00
|
|
|
for(let file of verCandidates){
|
2018-08-07 01:16:15 -07:00
|
|
|
const match = MOD_REGEX.exec(file)
|
|
|
|
if(match != null){
|
|
|
|
modsDiscovered.push({
|
|
|
|
fullName: path.join(version, match[0]),
|
|
|
|
name: match[1],
|
|
|
|
ext: match[2],
|
|
|
|
disabled: match[3] != null
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return modsDiscovered
|
|
|
|
}
|
|
|
|
|
2018-12-01 05:20:42 -08:00
|
|
|
/**
|
|
|
|
* Add dropin mods.
|
|
|
|
*
|
|
|
|
* @param {FileList} files The files to add.
|
|
|
|
* @param {string} modsDir The path to the mods directory.
|
|
|
|
*/
|
|
|
|
exports.addDropinMods = function(files, modsdir) {
|
|
|
|
|
2018-12-21 03:51:08 -08:00
|
|
|
exports.validateDir(modsdir)
|
2018-12-01 07:06:23 -08:00
|
|
|
|
2018-12-01 05:20:42 -08:00
|
|
|
for(let f of files) {
|
|
|
|
if(MOD_REGEX.exec(f.name) != null) {
|
|
|
|
fs.moveSync(f.path, path.join(modsdir, f.name))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-08-07 01:16:15 -07:00
|
|
|
/**
|
|
|
|
* Delete a drop-in mod from the file system.
|
|
|
|
*
|
|
|
|
* @param {string} modsDir The path to the mods directory.
|
|
|
|
* @param {string} fullName The fullName of the discovered mod to delete.
|
|
|
|
*
|
|
|
|
* @returns {boolean} True if the mod was deleted, otherwise false.
|
|
|
|
*/
|
|
|
|
exports.deleteDropinMod = function(modsDir, fullName){
|
|
|
|
const res = shell.moveItemToTrash(path.join(modsDir, fullName))
|
|
|
|
if(!res){
|
|
|
|
shell.beep()
|
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Toggle a discovered mod on or off. This is achieved by either
|
|
|
|
* adding or disabling the .disabled extension to the local file.
|
|
|
|
*
|
|
|
|
* @param {string} modsDir The path to the mods directory.
|
|
|
|
* @param {string} fullName The fullName of the discovered mod to toggle.
|
|
|
|
* @param {boolean} enable Whether to toggle on or off the mod.
|
|
|
|
*
|
|
|
|
* @returns {Promise.<void>} A promise which resolves when the mod has
|
|
|
|
* been toggled. If an IO error occurs the promise will be rejected.
|
|
|
|
*/
|
|
|
|
exports.toggleDropinMod = function(modsDir, fullName, enable){
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const oldPath = path.join(modsDir, fullName)
|
|
|
|
const newPath = path.join(modsDir, enable ? fullName.substring(0, fullName.indexOf(DISABLED_EXT)) : fullName + DISABLED_EXT)
|
|
|
|
|
|
|
|
fs.rename(oldPath, newPath, (err) => {
|
|
|
|
if(err){
|
|
|
|
reject(err)
|
|
|
|
} else {
|
|
|
|
resolve()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-08-07 01:41:26 -07:00
|
|
|
/**
|
|
|
|
* Check if a drop-in mod is enabled.
|
|
|
|
*
|
|
|
|
* @param {string} fullName The fullName of the discovered mod to toggle.
|
|
|
|
* @returns {boolean} True if the mod is enabled, otherwise false.
|
|
|
|
*/
|
2018-08-07 01:16:15 -07:00
|
|
|
exports.isDropinModEnabled = function(fullName){
|
|
|
|
return !fullName.endsWith(DISABLED_EXT)
|
2018-12-21 03:51:08 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Scan for shaderpacks inside the shaderpacks folder.
|
|
|
|
*
|
|
|
|
* @param {string} instanceDir The path to the server instance directory.
|
|
|
|
*
|
|
|
|
* @returns {{fullName: string, name: string}[]}
|
|
|
|
* An array of objects storing metadata about each discovered shaderpack.
|
|
|
|
*/
|
|
|
|
exports.scanForShaderpacks = function(instanceDir){
|
2018-12-21 13:06:34 -08:00
|
|
|
const shaderDir = path.join(instanceDir, SHADER_DIR)
|
2018-12-21 03:51:08 -08:00
|
|
|
const packsDiscovered = [{
|
|
|
|
fullName: 'OFF',
|
2018-12-21 13:06:34 -08:00
|
|
|
name: 'Off (Default)'
|
2018-12-21 03:51:08 -08:00
|
|
|
}]
|
|
|
|
if(fs.existsSync(shaderDir)){
|
|
|
|
let modCandidates = fs.readdirSync(shaderDir)
|
|
|
|
for(let file of modCandidates){
|
|
|
|
const match = SHADER_REGEX.exec(file)
|
|
|
|
if(match != null){
|
|
|
|
packsDiscovered.push({
|
|
|
|
fullName: match[0],
|
|
|
|
name: match[1]
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return packsDiscovered
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Read the optionsshaders.txt file to locate the current
|
|
|
|
* enabled pack. If the file does not exist, OFF is returned.
|
|
|
|
*
|
|
|
|
* @param {string} instanceDir The path to the server instance directory.
|
|
|
|
*
|
|
|
|
* @returns {string} The file name of the enabled shaderpack.
|
|
|
|
*/
|
|
|
|
exports.getEnabledShaderpack = function(instanceDir){
|
|
|
|
exports.validateDir(instanceDir)
|
|
|
|
|
2018-12-21 13:06:34 -08:00
|
|
|
const optionsShaders = path.join(instanceDir, SHADER_CONFIG)
|
2018-12-21 03:51:08 -08:00
|
|
|
if(fs.existsSync(optionsShaders)){
|
|
|
|
const buf = fs.readFileSync(optionsShaders, {encoding: 'utf-8'})
|
|
|
|
const match = SHADER_OPTION.exec(buf)
|
|
|
|
if(match != null){
|
|
|
|
return match[1]
|
|
|
|
} else {
|
|
|
|
console.warn('WARNING: Shaderpack regex failed.')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 'OFF'
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the enabled shaderpack.
|
|
|
|
*
|
|
|
|
* @param {string} instanceDir The path to the server instance directory.
|
|
|
|
* @param {string} pack the file name of the shaderpack.
|
|
|
|
*/
|
|
|
|
exports.setEnabledShaderpack = function(instanceDir, pack){
|
|
|
|
exports.validateDir(instanceDir)
|
|
|
|
|
2018-12-21 13:06:34 -08:00
|
|
|
const optionsShaders = path.join(instanceDir, SHADER_CONFIG)
|
2018-12-21 03:51:08 -08:00
|
|
|
let buf
|
|
|
|
if(fs.existsSync(optionsShaders)){
|
|
|
|
buf = fs.readFileSync(optionsShaders, {encoding: 'utf-8'})
|
|
|
|
buf = buf.replace(SHADER_OPTION, `shaderPack=${pack}`)
|
|
|
|
} else {
|
|
|
|
buf = `shaderPack=${pack}`
|
|
|
|
}
|
|
|
|
fs.writeFileSync(optionsShaders, buf, {encoding: 'utf-8'})
|
|
|
|
}
|
2018-12-21 05:02:24 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Add shaderpacks.
|
|
|
|
*
|
|
|
|
* @param {FileList} files The files to add.
|
|
|
|
* @param {string} instanceDir The path to the server instance directory.
|
|
|
|
*/
|
|
|
|
exports.addShaderpacks = function(files, instanceDir) {
|
|
|
|
|
2018-12-21 13:06:34 -08:00
|
|
|
const p = path.join(instanceDir, SHADER_DIR)
|
2018-12-21 05:02:24 -08:00
|
|
|
|
|
|
|
exports.validateDir(p)
|
|
|
|
|
|
|
|
for(let f of files) {
|
|
|
|
if(SHADER_REGEX.exec(f.name) != null) {
|
|
|
|
fs.moveSync(f.path, path.join(p, f.name))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|