2018-12-01 13:20:42 +00:00
|
|
|
const fs = require('fs-extra')
|
2018-08-07 08:16:15 +00: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-11-20 10:19:59 +00:00
|
|
|
/**
|
|
|
|
* Validate that the given mods directory exists. If not,
|
|
|
|
* it is created.
|
|
|
|
*
|
|
|
|
* @param {string} modsDir The path to the mods directory.
|
|
|
|
*/
|
|
|
|
exports.validateModsDir = function(modsDir) {
|
2018-12-01 13:20:42 +00:00
|
|
|
fs.ensureDirSync(modsDir)
|
2018-11-20 10:19:59 +00:00
|
|
|
}
|
|
|
|
|
2018-08-07 08:16:15 +00: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 08:41:26 +00:00
|
|
|
for(let file of modCandidates){
|
2018-08-07 08:16:15 +00: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 08:41:26 +00:00
|
|
|
for(let file of verCandidates){
|
2018-08-07 08:16:15 +00: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 13:20:42 +00: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-01 15:06:23 +00:00
|
|
|
exports.validateModsDir(modsdir)
|
|
|
|
|
2018-12-01 13:20:42 +00: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 08:16:15 +00: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 08:41:26 +00: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 08:16:15 +00:00
|
|
|
exports.isDropinModEnabled = function(fullName){
|
|
|
|
return !fullName.endsWith(DISABLED_EXT)
|
|
|
|
}
|