Add files via upload
This commit is contained in:
parent
d84b162867
commit
6c0e851f2b
@ -1,73 +1,73 @@
|
|||||||
let target = require('./assetguard')[process.argv[2]]
|
let target = require('./assetguard')[process.argv[2]]
|
||||||
if(target == null){
|
if(target == null){
|
||||||
process.send({context: 'error', data: null, error: 'Invalid class name'})
|
process.send({context: 'error', data: null, error: 'Invalid class name'})
|
||||||
console.error('Invalid class name passed to argv[2], cannot continue.')
|
console.error('Invalid class name passed to argv[2], cannot continue.')
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
let tracker = new target(...(process.argv.splice(3)))
|
let tracker = new target(...(process.argv.splice(3)))
|
||||||
|
|
||||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
|
||||||
|
|
||||||
//const tracker = new AssetGuard(process.argv[2], process.argv[3])
|
//const tracker = new AssetGuard(process.argv[2], process.argv[3])
|
||||||
console.log('AssetExec Started')
|
console.log('AssetExec Started')
|
||||||
|
|
||||||
// Temporary for debug purposes.
|
// Temporary for debug purposes.
|
||||||
process.on('unhandledRejection', r => console.log(r))
|
process.on('unhandledRejection', r => console.log(r))
|
||||||
|
|
||||||
let percent = 0
|
let percent = 0
|
||||||
function assignListeners(){
|
function assignListeners(){
|
||||||
tracker.on('validate', (data) => {
|
tracker.on('validate', (data) => {
|
||||||
process.send({context: 'validate', data})
|
process.send({context: 'validate', data})
|
||||||
})
|
})
|
||||||
tracker.on('progress', (data, acc, total) => {
|
tracker.on('progress', (data, acc, total) => {
|
||||||
const currPercent = parseInt((acc/total) * 100)
|
const currPercent = parseInt((acc/total) * 100)
|
||||||
if (currPercent !== percent) {
|
if (currPercent !== percent) {
|
||||||
percent = currPercent
|
percent = currPercent
|
||||||
process.send({context: 'progress', data, value: acc, total, percent})
|
process.send({context: 'progress', data, value: acc, total, percent})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
tracker.on('complete', (data, ...args) => {
|
tracker.on('complete', (data, ...args) => {
|
||||||
process.send({context: 'complete', data, args})
|
process.send({context: 'complete', data, args})
|
||||||
})
|
})
|
||||||
tracker.on('error', (data, error) => {
|
tracker.on('error', (data, error) => {
|
||||||
process.send({context: 'error', data, error})
|
process.send({context: 'error', data, error})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
assignListeners()
|
assignListeners()
|
||||||
|
|
||||||
process.on('message', (msg) => {
|
process.on('message', (msg) => {
|
||||||
if(msg.task === 'execute'){
|
if(msg.task === 'execute'){
|
||||||
const func = msg.function
|
const func = msg.function
|
||||||
let nS = tracker[func] // Nonstatic context
|
let nS = tracker[func] // Nonstatic context
|
||||||
let iS = target[func] // Static context
|
let iS = target[func] // Static context
|
||||||
if(typeof nS === 'function' || typeof iS === 'function'){
|
if(typeof nS === 'function' || typeof iS === 'function'){
|
||||||
const f = typeof nS === 'function' ? nS : iS
|
const f = typeof nS === 'function' ? nS : iS
|
||||||
const res = f.apply(f === nS ? tracker : null, msg.argsArr)
|
const res = f.apply(f === nS ? tracker : null, msg.argsArr)
|
||||||
if(res instanceof Promise){
|
if(res instanceof Promise){
|
||||||
res.then((v) => {
|
res.then((v) => {
|
||||||
process.send({result: v, context: func})
|
process.send({result: v, context: func})
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
process.send({result: err.message || err, context: func})
|
process.send({result: err.message || err, context: func})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
process.send({result: res, context: func})
|
process.send({result: res, context: func})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
process.send({context: 'error', data: null, error: `Function ${func} not found on ${process.argv[2]}`})
|
process.send({context: 'error', data: null, error: `Function ${func} not found on ${process.argv[2]}`})
|
||||||
}
|
}
|
||||||
} else if(msg.task === 'changeContext'){
|
} else if(msg.task === 'changeContext'){
|
||||||
target = require('./assetguard')[msg.class]
|
target = require('./assetguard')[msg.class]
|
||||||
if(target == null){
|
if(target == null){
|
||||||
process.send({context: 'error', data: null, error: `Invalid class ${msg.class}`})
|
process.send({context: 'error', data: null, error: `Invalid class ${msg.class}`})
|
||||||
} else {
|
} else {
|
||||||
tracker = new target(...(msg.args))
|
tracker = new target(...(msg.args))
|
||||||
assignListeners()
|
assignListeners()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
process.on('disconnect', () => {
|
process.on('disconnect', () => {
|
||||||
console.log('AssetExec Disconnected')
|
console.log('AssetExec Disconnected')
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
})
|
})
|
File diff suppressed because it is too large
Load Diff
@ -1,99 +1,99 @@
|
|||||||
/**
|
/**
|
||||||
* AuthManager
|
* AuthManager
|
||||||
*
|
*
|
||||||
* This module aims to abstract login procedures. Results from Mojang's REST api
|
* This module aims to abstract login procedures. Results from Mojang's REST api
|
||||||
* are retrieved through our Mojang module. These results are processed and stored,
|
* are retrieved through our Mojang module. These results are processed and stored,
|
||||||
* if applicable, in the config using the ConfigManager. All login procedures should
|
* if applicable, in the config using the ConfigManager. All login procedures should
|
||||||
* be made through this module.
|
* be made through this module.
|
||||||
*
|
*
|
||||||
* @module authmanager
|
* @module authmanager
|
||||||
*/
|
*/
|
||||||
// Requirements
|
// Requirements
|
||||||
const ConfigManager = require('./configmanager')
|
const ConfigManager = require('./configmanager')
|
||||||
const LoggerUtil = require('./loggerutil')
|
const LoggerUtil = require('./loggerutil')
|
||||||
const Mojang = require('./mojang')
|
const Mojang = require('./mojang')
|
||||||
const logger = LoggerUtil('%c[AuthManager]', 'color: #a02d2a; font-weight: bold')
|
const logger = LoggerUtil('%c[AuthManager]', 'color: #a02d2a; font-weight: bold')
|
||||||
const loggerSuccess = LoggerUtil('%c[AuthManager]', 'color: #209b07; font-weight: bold')
|
const loggerSuccess = LoggerUtil('%c[AuthManager]', 'color: #209b07; font-weight: bold')
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an account. This will authenticate the given credentials with Mojang's
|
* Add an account. This will authenticate the given credentials with Mojang's
|
||||||
* authserver. The resultant data will be stored as an auth account in the
|
* authserver. The resultant data will be stored as an auth account in the
|
||||||
* configuration database.
|
* configuration database.
|
||||||
*
|
*
|
||||||
* @param {string} username The account username (email if migrated).
|
* @param {string} username The account username (email if migrated).
|
||||||
* @param {string} password The account password.
|
* @param {string} password The account password.
|
||||||
* @returns {Promise.<Object>} Promise which resolves the resolved authenticated account object.
|
* @returns {Promise.<Object>} Promise which resolves the resolved authenticated account object.
|
||||||
*/
|
*/
|
||||||
exports.addAccount = async function(username, password){
|
exports.addAccount = async function(username, password){
|
||||||
try {
|
try {
|
||||||
const session = await Mojang.authenticate(username, password, ConfigManager.getClientToken())
|
const session = await Mojang.authenticate(username, password, ConfigManager.getClientToken())
|
||||||
if(session.selectedProfile != null){
|
if(session.selectedProfile != null){
|
||||||
const ret = ConfigManager.addAuthAccount(session.selectedProfile.id, session.accessToken, username, session.selectedProfile.name)
|
const ret = ConfigManager.addAuthAccount(session.selectedProfile.id, session.accessToken, username, session.selectedProfile.name)
|
||||||
if(ConfigManager.getClientToken() == null){
|
if(ConfigManager.getClientToken() == null){
|
||||||
ConfigManager.setClientToken(session.clientToken)
|
ConfigManager.setClientToken(session.clientToken)
|
||||||
}
|
}
|
||||||
ConfigManager.save()
|
ConfigManager.save()
|
||||||
return ret
|
return ret
|
||||||
} else {
|
} else {
|
||||||
throw new Error('NotPaidAccount')
|
throw new Error('NotPaidAccount')
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err){
|
} catch (err){
|
||||||
return Promise.reject(err)
|
return Promise.reject(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove an account. This will invalidate the access token associated
|
* Remove an account. This will invalidate the access token associated
|
||||||
* with the account and then remove it from the database.
|
* with the account and then remove it from the database.
|
||||||
*
|
*
|
||||||
* @param {string} uuid The UUID of the account to be removed.
|
* @param {string} uuid The UUID of the account to be removed.
|
||||||
* @returns {Promise.<void>} Promise which resolves to void when the action is complete.
|
* @returns {Promise.<void>} Promise which resolves to void when the action is complete.
|
||||||
*/
|
*/
|
||||||
exports.removeAccount = async function(uuid){
|
exports.removeAccount = async function(uuid){
|
||||||
try {
|
try {
|
||||||
const authAcc = ConfigManager.getAuthAccount(uuid)
|
const authAcc = ConfigManager.getAuthAccount(uuid)
|
||||||
await Mojang.invalidate(authAcc.accessToken, ConfigManager.getClientToken())
|
await Mojang.invalidate(authAcc.accessToken, ConfigManager.getClientToken())
|
||||||
ConfigManager.removeAuthAccount(uuid)
|
ConfigManager.removeAuthAccount(uuid)
|
||||||
ConfigManager.save()
|
ConfigManager.save()
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
} catch (err){
|
} catch (err){
|
||||||
return Promise.reject(err)
|
return Promise.reject(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the selected account with Mojang's authserver. If the account is not valid,
|
* Validate the selected account with Mojang's authserver. If the account is not valid,
|
||||||
* we will attempt to refresh the access token and update that value. If that fails, a
|
* we will attempt to refresh the access token and update that value. If that fails, a
|
||||||
* new login will be required.
|
* new login will be required.
|
||||||
*
|
*
|
||||||
* **Function is WIP**
|
* **Function is WIP**
|
||||||
*
|
*
|
||||||
* @returns {Promise.<boolean>} Promise which resolves to true if the access token is valid,
|
* @returns {Promise.<boolean>} Promise which resolves to true if the access token is valid,
|
||||||
* otherwise false.
|
* otherwise false.
|
||||||
*/
|
*/
|
||||||
exports.validateSelected = async function(){
|
exports.validateSelected = async function(){
|
||||||
const current = ConfigManager.getSelectedAccount()
|
const current = ConfigManager.getSelectedAccount()
|
||||||
const isValid = await Mojang.validate(current.accessToken, ConfigManager.getClientToken())
|
const isValid = await Mojang.validate(current.accessToken, ConfigManager.getClientToken())
|
||||||
if(!isValid){
|
if(!isValid){
|
||||||
try {
|
try {
|
||||||
const session = await Mojang.refresh(current.accessToken, ConfigManager.getClientToken())
|
const session = await Mojang.refresh(current.accessToken, ConfigManager.getClientToken())
|
||||||
ConfigManager.updateAuthAccount(current.uuid, session.accessToken)
|
ConfigManager.updateAuthAccount(current.uuid, session.accessToken)
|
||||||
ConfigManager.save()
|
ConfigManager.save()
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
logger.debug('Error while validating selected profile:', err)
|
logger.debug('Error while validating selected profile:', err)
|
||||||
if(err && err.error === 'ForbiddenOperationException'){
|
if(err && err.error === 'ForbiddenOperationException'){
|
||||||
// What do we do?
|
// What do we do?
|
||||||
}
|
}
|
||||||
logger.log('Account access token is invalid.')
|
logger.log('Account access token is invalid.')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
loggerSuccess.log('Account access token validated.')
|
loggerSuccess.log('Account access token validated.')
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
loggerSuccess.log('Account access token validated.')
|
loggerSuccess.log('Account access token validated.')
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1,48 +1,48 @@
|
|||||||
// Work in progress
|
// Work in progress
|
||||||
const logger = require('./loggerutil')('%c[DiscordWrapper]', 'color: #7289da; font-weight: bold')
|
const logger = require('./loggerutil')('%c[DiscordWrapper]', 'color: #7289da; font-weight: bold')
|
||||||
|
|
||||||
const {Client} = require('discord-rpc')
|
const {Client} = require('discord-rpc')
|
||||||
|
|
||||||
let client
|
let client
|
||||||
let activity
|
let activity
|
||||||
|
|
||||||
exports.initRPC = function(genSettings, servSettings, initialDetails = 'Waiting for Client..'){
|
exports.initRPC = function(genSettings, servSettings, initialDetails = 'Waiting for Client..'){
|
||||||
client = new Client({ transport: 'ipc' })
|
client = new Client({ transport: 'ipc' })
|
||||||
|
|
||||||
activity = {
|
activity = {
|
||||||
details: initialDetails,
|
details: initialDetails,
|
||||||
state: 'Server: ' + servSettings.shortId,
|
state: 'Server: ' + servSettings.shortId,
|
||||||
largeImageKey: servSettings.largeImageKey,
|
largeImageKey: servSettings.largeImageKey,
|
||||||
largeImageText: servSettings.largeImageText,
|
largeImageText: servSettings.largeImageText,
|
||||||
smallImageKey: genSettings.smallImageKey,
|
smallImageKey: genSettings.smallImageKey,
|
||||||
smallImageText: genSettings.smallImageText,
|
smallImageText: genSettings.smallImageText,
|
||||||
startTimestamp: new Date().getTime(),
|
startTimestamp: new Date().getTime(),
|
||||||
instance: false
|
instance: false
|
||||||
}
|
}
|
||||||
|
|
||||||
client.on('ready', () => {
|
client.on('ready', () => {
|
||||||
logger.log('Discord RPC Connected')
|
logger.log('Discord RPC Connected')
|
||||||
client.setActivity(activity)
|
client.setActivity(activity)
|
||||||
})
|
})
|
||||||
|
|
||||||
client.login({clientId: genSettings.clientId}).catch(error => {
|
client.login({clientId: genSettings.clientId}).catch(error => {
|
||||||
if(error.message.includes('ENOENT')) {
|
if(error.message.includes('ENOENT')) {
|
||||||
logger.log('Unable to initialize Discord Rich Presence, no client detected.')
|
logger.log('Unable to initialize Discord Rich Presence, no client detected.')
|
||||||
} else {
|
} else {
|
||||||
logger.log('Unable to initialize Discord Rich Presence: ' + error.message, error)
|
logger.log('Unable to initialize Discord Rich Presence: ' + error.message, error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.updateDetails = function(details){
|
exports.updateDetails = function(details){
|
||||||
activity.details = details
|
activity.details = details
|
||||||
client.setActivity(activity)
|
client.setActivity(activity)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.shutdownRPC = function(){
|
exports.shutdownRPC = function(){
|
||||||
if(!client) return
|
if(!client) return
|
||||||
client.clearActivity()
|
client.clearActivity()
|
||||||
client.destroy()
|
client.destroy()
|
||||||
client = null
|
client = null
|
||||||
activity = null
|
activity = null
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1,232 +1,232 @@
|
|||||||
const fs = require('fs-extra')
|
const fs = require('fs-extra')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const { shell } = require('electron')
|
const { shell } = require('electron')
|
||||||
|
|
||||||
// Group #1: File Name (without .disabled, if any)
|
// Group #1: File Name (without .disabled, if any)
|
||||||
// Group #2: File Extension (jar, zip, or litemod)
|
// Group #2: File Extension (jar, zip, or litemod)
|
||||||
// Group #3: If it is disabled (if string 'disabled' is present)
|
// Group #3: If it is disabled (if string 'disabled' is present)
|
||||||
const MOD_REGEX = /^(.+(jar|zip|litemod))(?:\.(disabled))?$/
|
const MOD_REGEX = /^(.+(jar|zip|litemod))(?:\.(disabled))?$/
|
||||||
const DISABLED_EXT = '.disabled'
|
const DISABLED_EXT = '.disabled'
|
||||||
|
|
||||||
const SHADER_REGEX = /^(.+)\.zip$/
|
const SHADER_REGEX = /^(.+)\.zip$/
|
||||||
const SHADER_OPTION = /shaderPack=(.+)/
|
const SHADER_OPTION = /shaderPack=(.+)/
|
||||||
const SHADER_DIR = 'shaderpacks'
|
const SHADER_DIR = 'shaderpacks'
|
||||||
const SHADER_CONFIG = 'optionsshaders.txt'
|
const SHADER_CONFIG = 'optionsshaders.txt'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate that the given directory exists. If not, it is
|
* Validate that the given directory exists. If not, it is
|
||||||
* created.
|
* created.
|
||||||
*
|
*
|
||||||
* @param {string} modsDir The path to the mods directory.
|
* @param {string} modsDir The path to the mods directory.
|
||||||
*/
|
*/
|
||||||
exports.validateDir = function(dir) {
|
exports.validateDir = function(dir) {
|
||||||
fs.ensureDirSync(dir)
|
fs.ensureDirSync(dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan for drop-in mods in both the mods folder and version
|
* Scan for drop-in mods in both the mods folder and version
|
||||||
* safe mods folder.
|
* safe mods folder.
|
||||||
*
|
*
|
||||||
* @param {string} modsDir The path to the mods directory.
|
* @param {string} modsDir The path to the mods directory.
|
||||||
* @param {string} version The minecraft version of the server configuration.
|
* @param {string} version The minecraft version of the server configuration.
|
||||||
*
|
*
|
||||||
* @returns {{fullName: string, name: string, ext: string, disabled: boolean}[]}
|
* @returns {{fullName: string, name: string, ext: string, disabled: boolean}[]}
|
||||||
* An array of objects storing metadata about each discovered mod.
|
* An array of objects storing metadata about each discovered mod.
|
||||||
*/
|
*/
|
||||||
exports.scanForDropinMods = function(modsDir, version) {
|
exports.scanForDropinMods = function(modsDir, version) {
|
||||||
const modsDiscovered = []
|
const modsDiscovered = []
|
||||||
if(fs.existsSync(modsDir)){
|
if(fs.existsSync(modsDir)){
|
||||||
let modCandidates = fs.readdirSync(modsDir)
|
let modCandidates = fs.readdirSync(modsDir)
|
||||||
let verCandidates = []
|
let verCandidates = []
|
||||||
const versionDir = path.join(modsDir, version)
|
const versionDir = path.join(modsDir, version)
|
||||||
if(fs.existsSync(versionDir)){
|
if(fs.existsSync(versionDir)){
|
||||||
verCandidates = fs.readdirSync(versionDir)
|
verCandidates = fs.readdirSync(versionDir)
|
||||||
}
|
}
|
||||||
for(let file of modCandidates){
|
for(let file of modCandidates){
|
||||||
const match = MOD_REGEX.exec(file)
|
const match = MOD_REGEX.exec(file)
|
||||||
if(match != null){
|
if(match != null){
|
||||||
modsDiscovered.push({
|
modsDiscovered.push({
|
||||||
fullName: match[0],
|
fullName: match[0],
|
||||||
name: match[1],
|
name: match[1],
|
||||||
ext: match[2],
|
ext: match[2],
|
||||||
disabled: match[3] != null
|
disabled: match[3] != null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(let file of verCandidates){
|
for(let file of verCandidates){
|
||||||
const match = MOD_REGEX.exec(file)
|
const match = MOD_REGEX.exec(file)
|
||||||
if(match != null){
|
if(match != null){
|
||||||
modsDiscovered.push({
|
modsDiscovered.push({
|
||||||
fullName: path.join(version, match[0]),
|
fullName: path.join(version, match[0]),
|
||||||
name: match[1],
|
name: match[1],
|
||||||
ext: match[2],
|
ext: match[2],
|
||||||
disabled: match[3] != null
|
disabled: match[3] != null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return modsDiscovered
|
return modsDiscovered
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add dropin mods.
|
* Add dropin mods.
|
||||||
*
|
*
|
||||||
* @param {FileList} files The files to add.
|
* @param {FileList} files The files to add.
|
||||||
* @param {string} modsDir The path to the mods directory.
|
* @param {string} modsDir The path to the mods directory.
|
||||||
*/
|
*/
|
||||||
exports.addDropinMods = function(files, modsdir) {
|
exports.addDropinMods = function(files, modsdir) {
|
||||||
|
|
||||||
exports.validateDir(modsdir)
|
exports.validateDir(modsdir)
|
||||||
|
|
||||||
for(let f of files) {
|
for(let f of files) {
|
||||||
if(MOD_REGEX.exec(f.name) != null) {
|
if(MOD_REGEX.exec(f.name) != null) {
|
||||||
fs.moveSync(f.path, path.join(modsdir, f.name))
|
fs.moveSync(f.path, path.join(modsdir, f.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a drop-in mod from the file system.
|
* Delete a drop-in mod from the file system.
|
||||||
*
|
*
|
||||||
* @param {string} modsDir The path to the mods directory.
|
* @param {string} modsDir The path to the mods directory.
|
||||||
* @param {string} fullName The fullName of the discovered mod to delete.
|
* @param {string} fullName The fullName of the discovered mod to delete.
|
||||||
*
|
*
|
||||||
* @returns {boolean} True if the mod was deleted, otherwise false.
|
* @returns {boolean} True if the mod was deleted, otherwise false.
|
||||||
*/
|
*/
|
||||||
exports.deleteDropinMod = function(modsDir, fullName){
|
exports.deleteDropinMod = function(modsDir, fullName){
|
||||||
const res = shell.moveItemToTrash(path.join(modsDir, fullName))
|
const res = shell.moveItemToTrash(path.join(modsDir, fullName))
|
||||||
if(!res){
|
if(!res){
|
||||||
shell.beep()
|
shell.beep()
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle a discovered mod on or off. This is achieved by either
|
* Toggle a discovered mod on or off. This is achieved by either
|
||||||
* adding or disabling the .disabled extension to the local file.
|
* adding or disabling the .disabled extension to the local file.
|
||||||
*
|
*
|
||||||
* @param {string} modsDir The path to the mods directory.
|
* @param {string} modsDir The path to the mods directory.
|
||||||
* @param {string} fullName The fullName of the discovered mod to toggle.
|
* @param {string} fullName The fullName of the discovered mod to toggle.
|
||||||
* @param {boolean} enable Whether to toggle on or off the mod.
|
* @param {boolean} enable Whether to toggle on or off the mod.
|
||||||
*
|
*
|
||||||
* @returns {Promise.<void>} A promise which resolves when the mod has
|
* @returns {Promise.<void>} A promise which resolves when the mod has
|
||||||
* been toggled. If an IO error occurs the promise will be rejected.
|
* been toggled. If an IO error occurs the promise will be rejected.
|
||||||
*/
|
*/
|
||||||
exports.toggleDropinMod = function(modsDir, fullName, enable){
|
exports.toggleDropinMod = function(modsDir, fullName, enable){
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const oldPath = path.join(modsDir, fullName)
|
const oldPath = path.join(modsDir, fullName)
|
||||||
const newPath = path.join(modsDir, enable ? fullName.substring(0, fullName.indexOf(DISABLED_EXT)) : fullName + DISABLED_EXT)
|
const newPath = path.join(modsDir, enable ? fullName.substring(0, fullName.indexOf(DISABLED_EXT)) : fullName + DISABLED_EXT)
|
||||||
|
|
||||||
fs.rename(oldPath, newPath, (err) => {
|
fs.rename(oldPath, newPath, (err) => {
|
||||||
if(err){
|
if(err){
|
||||||
reject(err)
|
reject(err)
|
||||||
} else {
|
} else {
|
||||||
resolve()
|
resolve()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a drop-in mod is enabled.
|
* Check if a drop-in mod is enabled.
|
||||||
*
|
*
|
||||||
* @param {string} fullName The fullName of the discovered mod to toggle.
|
* @param {string} fullName The fullName of the discovered mod to toggle.
|
||||||
* @returns {boolean} True if the mod is enabled, otherwise false.
|
* @returns {boolean} True if the mod is enabled, otherwise false.
|
||||||
*/
|
*/
|
||||||
exports.isDropinModEnabled = function(fullName){
|
exports.isDropinModEnabled = function(fullName){
|
||||||
return !fullName.endsWith(DISABLED_EXT)
|
return !fullName.endsWith(DISABLED_EXT)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan for shaderpacks inside the shaderpacks folder.
|
* Scan for shaderpacks inside the shaderpacks folder.
|
||||||
*
|
*
|
||||||
* @param {string} instanceDir The path to the server instance directory.
|
* @param {string} instanceDir The path to the server instance directory.
|
||||||
*
|
*
|
||||||
* @returns {{fullName: string, name: string}[]}
|
* @returns {{fullName: string, name: string}[]}
|
||||||
* An array of objects storing metadata about each discovered shaderpack.
|
* An array of objects storing metadata about each discovered shaderpack.
|
||||||
*/
|
*/
|
||||||
exports.scanForShaderpacks = function(instanceDir){
|
exports.scanForShaderpacks = function(instanceDir){
|
||||||
const shaderDir = path.join(instanceDir, SHADER_DIR)
|
const shaderDir = path.join(instanceDir, SHADER_DIR)
|
||||||
const packsDiscovered = [{
|
const packsDiscovered = [{
|
||||||
fullName: 'OFF',
|
fullName: 'OFF',
|
||||||
name: 'Off (Default)'
|
name: 'Off (Default)'
|
||||||
}]
|
}]
|
||||||
if(fs.existsSync(shaderDir)){
|
if(fs.existsSync(shaderDir)){
|
||||||
let modCandidates = fs.readdirSync(shaderDir)
|
let modCandidates = fs.readdirSync(shaderDir)
|
||||||
for(let file of modCandidates){
|
for(let file of modCandidates){
|
||||||
const match = SHADER_REGEX.exec(file)
|
const match = SHADER_REGEX.exec(file)
|
||||||
if(match != null){
|
if(match != null){
|
||||||
packsDiscovered.push({
|
packsDiscovered.push({
|
||||||
fullName: match[0],
|
fullName: match[0],
|
||||||
name: match[1]
|
name: match[1]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return packsDiscovered
|
return packsDiscovered
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the optionsshaders.txt file to locate the current
|
* Read the optionsshaders.txt file to locate the current
|
||||||
* enabled pack. If the file does not exist, OFF is returned.
|
* enabled pack. If the file does not exist, OFF is returned.
|
||||||
*
|
*
|
||||||
* @param {string} instanceDir The path to the server instance directory.
|
* @param {string} instanceDir The path to the server instance directory.
|
||||||
*
|
*
|
||||||
* @returns {string} The file name of the enabled shaderpack.
|
* @returns {string} The file name of the enabled shaderpack.
|
||||||
*/
|
*/
|
||||||
exports.getEnabledShaderpack = function(instanceDir){
|
exports.getEnabledShaderpack = function(instanceDir){
|
||||||
exports.validateDir(instanceDir)
|
exports.validateDir(instanceDir)
|
||||||
|
|
||||||
const optionsShaders = path.join(instanceDir, SHADER_CONFIG)
|
const optionsShaders = path.join(instanceDir, SHADER_CONFIG)
|
||||||
if(fs.existsSync(optionsShaders)){
|
if(fs.existsSync(optionsShaders)){
|
||||||
const buf = fs.readFileSync(optionsShaders, {encoding: 'utf-8'})
|
const buf = fs.readFileSync(optionsShaders, {encoding: 'utf-8'})
|
||||||
const match = SHADER_OPTION.exec(buf)
|
const match = SHADER_OPTION.exec(buf)
|
||||||
if(match != null){
|
if(match != null){
|
||||||
return match[1]
|
return match[1]
|
||||||
} else {
|
} else {
|
||||||
console.warn('WARNING: Shaderpack regex failed.')
|
console.warn('WARNING: Shaderpack regex failed.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 'OFF'
|
return 'OFF'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the enabled shaderpack.
|
* Set the enabled shaderpack.
|
||||||
*
|
*
|
||||||
* @param {string} instanceDir The path to the server instance directory.
|
* @param {string} instanceDir The path to the server instance directory.
|
||||||
* @param {string} pack the file name of the shaderpack.
|
* @param {string} pack the file name of the shaderpack.
|
||||||
*/
|
*/
|
||||||
exports.setEnabledShaderpack = function(instanceDir, pack){
|
exports.setEnabledShaderpack = function(instanceDir, pack){
|
||||||
exports.validateDir(instanceDir)
|
exports.validateDir(instanceDir)
|
||||||
|
|
||||||
const optionsShaders = path.join(instanceDir, SHADER_CONFIG)
|
const optionsShaders = path.join(instanceDir, SHADER_CONFIG)
|
||||||
let buf
|
let buf
|
||||||
if(fs.existsSync(optionsShaders)){
|
if(fs.existsSync(optionsShaders)){
|
||||||
buf = fs.readFileSync(optionsShaders, {encoding: 'utf-8'})
|
buf = fs.readFileSync(optionsShaders, {encoding: 'utf-8'})
|
||||||
buf = buf.replace(SHADER_OPTION, `shaderPack=${pack}`)
|
buf = buf.replace(SHADER_OPTION, `shaderPack=${pack}`)
|
||||||
} else {
|
} else {
|
||||||
buf = `shaderPack=${pack}`
|
buf = `shaderPack=${pack}`
|
||||||
}
|
}
|
||||||
fs.writeFileSync(optionsShaders, buf, {encoding: 'utf-8'})
|
fs.writeFileSync(optionsShaders, buf, {encoding: 'utf-8'})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add shaderpacks.
|
* Add shaderpacks.
|
||||||
*
|
*
|
||||||
* @param {FileList} files The files to add.
|
* @param {FileList} files The files to add.
|
||||||
* @param {string} instanceDir The path to the server instance directory.
|
* @param {string} instanceDir The path to the server instance directory.
|
||||||
*/
|
*/
|
||||||
exports.addShaderpacks = function(files, instanceDir) {
|
exports.addShaderpacks = function(files, instanceDir) {
|
||||||
|
|
||||||
const p = path.join(instanceDir, SHADER_DIR)
|
const p = path.join(instanceDir, SHADER_DIR)
|
||||||
|
|
||||||
exports.validateDir(p)
|
exports.validateDir(p)
|
||||||
|
|
||||||
for(let f of files) {
|
for(let f of files) {
|
||||||
if(SHADER_REGEX.exec(f.name) != null) {
|
if(SHADER_REGEX.exec(f.name) != null) {
|
||||||
fs.moveSync(f.path, path.join(p, f.name))
|
fs.moveSync(f.path, path.join(p, f.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
const getFromEnv = parseInt(process.env.ELECTRON_IS_DEV, 10) === 1
|
const getFromEnv = parseInt(process.env.ELECTRON_IS_DEV, 10) === 1
|
||||||
const isEnvSet = 'ELECTRON_IS_DEV' in process.env
|
const isEnvSet = 'ELECTRON_IS_DEV' in process.env
|
||||||
|
|
||||||
module.exports = isEnvSet ? getFromEnv : (process.defaultApp || /node_modules[\\/]electron[\\/]/.test(process.execPath))
|
module.exports = isEnvSet ? getFromEnv : (process.defaultApp || /node_modules[\\/]electron[\\/]/.test(process.execPath))
|
@ -1,21 +1,21 @@
|
|||||||
const fs = require('fs-extra')
|
const fs = require('fs-extra')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
let lang
|
let lang
|
||||||
|
|
||||||
exports.loadLanguage = function(id){
|
exports.loadLanguage = function(id){
|
||||||
lang = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'lang', `${id}.json`))) || {}
|
lang = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'lang', `${id}.json`))) || {}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.query = function(id){
|
exports.query = function(id){
|
||||||
let query = id.split('.')
|
let query = id.split('.')
|
||||||
let res = lang
|
let res = lang
|
||||||
for(let q of query){
|
for(let q of query){
|
||||||
res = res[q]
|
res = res[q]
|
||||||
}
|
}
|
||||||
return res === lang ? {} : res
|
return res === lang ? {} : res
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.queryJS = function(id){
|
exports.queryJS = function(id){
|
||||||
return exports.query(`js.${id}`)
|
return exports.query(`js.${id}`)
|
||||||
}
|
}
|
@ -1,32 +1,32 @@
|
|||||||
class LoggerUtil {
|
class LoggerUtil {
|
||||||
|
|
||||||
constructor(prefix, style){
|
constructor(prefix, style){
|
||||||
this.prefix = prefix
|
this.prefix = prefix
|
||||||
this.style = style
|
this.style = style
|
||||||
}
|
}
|
||||||
|
|
||||||
log(){
|
log(){
|
||||||
console.log.apply(null, [this.prefix, this.style, ...arguments])
|
console.log.apply(null, [this.prefix, this.style, ...arguments])
|
||||||
}
|
}
|
||||||
|
|
||||||
info(){
|
info(){
|
||||||
console.info.apply(null, [this.prefix, this.style, ...arguments])
|
console.info.apply(null, [this.prefix, this.style, ...arguments])
|
||||||
}
|
}
|
||||||
|
|
||||||
warn(){
|
warn(){
|
||||||
console.warn.apply(null, [this.prefix, this.style, ...arguments])
|
console.warn.apply(null, [this.prefix, this.style, ...arguments])
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(){
|
debug(){
|
||||||
console.debug.apply(null, [this.prefix, this.style, ...arguments])
|
console.debug.apply(null, [this.prefix, this.style, ...arguments])
|
||||||
}
|
}
|
||||||
|
|
||||||
error(){
|
error(){
|
||||||
console.error.apply(null, [this.prefix, this.style, ...arguments])
|
console.error.apply(null, [this.prefix, this.style, ...arguments])
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function (prefix, style){
|
module.exports = function (prefix, style){
|
||||||
return new LoggerUtil(prefix, style)
|
return new LoggerUtil(prefix, style)
|
||||||
}
|
}
|
@ -1,271 +1,271 @@
|
|||||||
/**
|
/**
|
||||||
* Mojang
|
* Mojang
|
||||||
*
|
*
|
||||||
* This module serves as a minimal wrapper for Mojang's REST api.
|
* This module serves as a minimal wrapper for Mojang's REST api.
|
||||||
*
|
*
|
||||||
* @module mojang
|
* @module mojang
|
||||||
*/
|
*/
|
||||||
// Requirements
|
// Requirements
|
||||||
const request = require('request')
|
const request = require('request')
|
||||||
const logger = require('./loggerutil')('%c[Mojang]', 'color: #a02d2a; font-weight: bold')
|
const logger = require('./loggerutil')('%c[Mojang]', 'color: #a02d2a; font-weight: bold')
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const minecraftAgent = {
|
const minecraftAgent = {
|
||||||
name: 'Minecraft',
|
name: 'Minecraft',
|
||||||
version: 1
|
version: 1
|
||||||
}
|
}
|
||||||
const authpath = 'https://authserver.mojang.com'
|
const authpath = 'https://authserver.mojang.com'
|
||||||
const statuses = [
|
const statuses = [
|
||||||
{
|
{
|
||||||
service: 'sessionserver.mojang.com',
|
service: 'sessionserver.mojang.com',
|
||||||
status: 'grey',
|
status: 'grey',
|
||||||
name: 'Multiplayer Session Service',
|
name: 'Multiplayer Session Service',
|
||||||
essential: true
|
essential: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
service: 'authserver.mojang.com',
|
service: 'authserver.mojang.com',
|
||||||
status: 'grey',
|
status: 'grey',
|
||||||
name: 'Authentication Service',
|
name: 'Authentication Service',
|
||||||
essential: true
|
essential: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
service: 'textures.minecraft.net',
|
service: 'textures.minecraft.net',
|
||||||
status: 'grey',
|
status: 'grey',
|
||||||
name: 'Minecraft Skins',
|
name: 'Minecraft Skins',
|
||||||
essential: false
|
essential: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
service: 'api.mojang.com',
|
service: 'api.mojang.com',
|
||||||
status: 'grey',
|
status: 'grey',
|
||||||
name: 'Public API',
|
name: 'Public API',
|
||||||
essential: false
|
essential: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
service: 'minecraft.net',
|
service: 'minecraft.net',
|
||||||
status: 'grey',
|
status: 'grey',
|
||||||
name: 'Minecraft.net',
|
name: 'Minecraft.net',
|
||||||
essential: false
|
essential: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
service: 'account.mojang.com',
|
service: 'account.mojang.com',
|
||||||
status: 'grey',
|
status: 'grey',
|
||||||
name: 'Mojang Accounts Website',
|
name: 'Mojang Accounts Website',
|
||||||
essential: false
|
essential: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a Mojang status color to a hex value. Valid statuses
|
* Converts a Mojang status color to a hex value. Valid statuses
|
||||||
* are 'green', 'yellow', 'red', and 'grey'. Grey is a custom status
|
* are 'green', 'yellow', 'red', and 'grey'. Grey is a custom status
|
||||||
* to our project which represents an unknown status.
|
* to our project which represents an unknown status.
|
||||||
*
|
*
|
||||||
* @param {string} status A valid status code.
|
* @param {string} status A valid status code.
|
||||||
* @returns {string} The hex color of the status code.
|
* @returns {string} The hex color of the status code.
|
||||||
*/
|
*/
|
||||||
exports.statusToHex = function(status){
|
exports.statusToHex = function(status){
|
||||||
switch(status.toLowerCase()){
|
switch(status.toLowerCase()){
|
||||||
case 'green':
|
case 'green':
|
||||||
return '#a5c325'
|
return '#a5c325'
|
||||||
case 'yellow':
|
case 'yellow':
|
||||||
return '#eac918'
|
return '#eac918'
|
||||||
case 'red':
|
case 'red':
|
||||||
return '#c32625'
|
return '#c32625'
|
||||||
case 'grey':
|
case 'grey':
|
||||||
default:
|
default:
|
||||||
return '#848484'
|
return '#848484'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the status of Mojang's services.
|
* Retrieves the status of Mojang's services.
|
||||||
* The response is condensed into a single object. Each service is
|
* The response is condensed into a single object. Each service is
|
||||||
* a key, where the value is an object containing a status and name
|
* a key, where the value is an object containing a status and name
|
||||||
* property.
|
* property.
|
||||||
*
|
*
|
||||||
* @see http://wiki.vg/Mojang_API#API_Status
|
* @see http://wiki.vg/Mojang_API#API_Status
|
||||||
*/
|
*/
|
||||||
exports.status = function(){
|
exports.status = function(){
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
request.get('https://status.mojang.com/check',
|
request.get('https://status.mojang.com/check',
|
||||||
{
|
{
|
||||||
json: true,
|
json: true,
|
||||||
timeout: 2500
|
timeout: 2500
|
||||||
},
|
},
|
||||||
function(error, response, body){
|
function(error, response, body){
|
||||||
|
|
||||||
if(error || response.statusCode !== 200){
|
if(error || response.statusCode !== 200){
|
||||||
logger.warn('Unable to retrieve Mojang status.')
|
logger.warn('Unable to retrieve Mojang status.')
|
||||||
logger.debug('Error while retrieving Mojang statuses:', error)
|
logger.debug('Error while retrieving Mojang statuses:', error)
|
||||||
//reject(error || response.statusCode)
|
//reject(error || response.statusCode)
|
||||||
for(let i=0; i<statuses.length; i++){
|
for(let i=0; i<statuses.length; i++){
|
||||||
statuses[i].status = 'grey'
|
statuses[i].status = 'grey'
|
||||||
}
|
}
|
||||||
resolve(statuses)
|
resolve(statuses)
|
||||||
} else {
|
} else {
|
||||||
for(let i=0; i<body.length; i++){
|
for(let i=0; i<body.length; i++){
|
||||||
const key = Object.keys(body[i])[0]
|
const key = Object.keys(body[i])[0]
|
||||||
inner:
|
inner:
|
||||||
for(let j=0; j<statuses.length; j++){
|
for(let j=0; j<statuses.length; j++){
|
||||||
if(statuses[j].service === key) {
|
if(statuses[j].service === key) {
|
||||||
statuses[j].status = body[i][key]
|
statuses[j].status = body[i][key]
|
||||||
break inner
|
break inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resolve(statuses)
|
resolve(statuses)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticate a user with their Mojang credentials.
|
* Authenticate a user with their Mojang credentials.
|
||||||
*
|
*
|
||||||
* @param {string} username The user's username, this is often an email.
|
* @param {string} username The user's username, this is often an email.
|
||||||
* @param {string} password The user's password.
|
* @param {string} password The user's password.
|
||||||
* @param {string} clientToken The launcher's Client Token.
|
* @param {string} clientToken The launcher's Client Token.
|
||||||
* @param {boolean} requestUser Optional. Adds user object to the reponse.
|
* @param {boolean} requestUser Optional. Adds user object to the reponse.
|
||||||
* @param {Object} agent Optional. Provided by default. Adds user info to the response.
|
* @param {Object} agent Optional. Provided by default. Adds user info to the response.
|
||||||
*
|
*
|
||||||
* @see http://wiki.vg/Authentication#Authenticate
|
* @see http://wiki.vg/Authentication#Authenticate
|
||||||
*/
|
*/
|
||||||
exports.authenticate = function(username, password, clientToken, requestUser = true, agent = minecraftAgent){
|
exports.authenticate = function(username, password, clientToken, requestUser = true, agent = minecraftAgent){
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
agent,
|
agent,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
requestUser
|
requestUser
|
||||||
}
|
}
|
||||||
if(clientToken != null){
|
if(clientToken != null){
|
||||||
body.clientToken = clientToken
|
body.clientToken = clientToken
|
||||||
}
|
}
|
||||||
|
|
||||||
request.post(authpath + '/authenticate',
|
request.post(authpath + '/authenticate',
|
||||||
{
|
{
|
||||||
json: true,
|
json: true,
|
||||||
body
|
body
|
||||||
},
|
},
|
||||||
function(error, response, body){
|
function(error, response, body){
|
||||||
if(error){
|
if(error){
|
||||||
logger.error('Error during authentication.', error)
|
logger.error('Error during authentication.', error)
|
||||||
reject(error)
|
reject(error)
|
||||||
} else {
|
} else {
|
||||||
if(response.statusCode === 200){
|
if(response.statusCode === 200){
|
||||||
resolve(body)
|
resolve(body)
|
||||||
} else {
|
} else {
|
||||||
reject(body || {code: 'ENOTFOUND'})
|
reject(body || {code: 'ENOTFOUND'})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate an access token. This should always be done before launching.
|
* Validate an access token. This should always be done before launching.
|
||||||
* The client token should match the one used to create the access token.
|
* The client token should match the one used to create the access token.
|
||||||
*
|
*
|
||||||
* @param {string} accessToken The access token to validate.
|
* @param {string} accessToken The access token to validate.
|
||||||
* @param {string} clientToken The launcher's client token.
|
* @param {string} clientToken The launcher's client token.
|
||||||
*
|
*
|
||||||
* @see http://wiki.vg/Authentication#Validate
|
* @see http://wiki.vg/Authentication#Validate
|
||||||
*/
|
*/
|
||||||
exports.validate = function(accessToken, clientToken){
|
exports.validate = function(accessToken, clientToken){
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
request.post(authpath + '/validate',
|
request.post(authpath + '/validate',
|
||||||
{
|
{
|
||||||
json: true,
|
json: true,
|
||||||
body: {
|
body: {
|
||||||
accessToken,
|
accessToken,
|
||||||
clientToken
|
clientToken
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
function(error, response, body){
|
function(error, response, body){
|
||||||
if(error){
|
if(error){
|
||||||
logger.error('Error during validation.', error)
|
logger.error('Error during validation.', error)
|
||||||
reject(error)
|
reject(error)
|
||||||
} else {
|
} else {
|
||||||
if(response.statusCode === 403){
|
if(response.statusCode === 403){
|
||||||
resolve(false)
|
resolve(false)
|
||||||
} else {
|
} else {
|
||||||
// 204 if valid
|
// 204 if valid
|
||||||
resolve(true)
|
resolve(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalidates an access token. The clientToken must match the
|
* Invalidates an access token. The clientToken must match the
|
||||||
* token used to create the provided accessToken.
|
* token used to create the provided accessToken.
|
||||||
*
|
*
|
||||||
* @param {string} accessToken The access token to invalidate.
|
* @param {string} accessToken The access token to invalidate.
|
||||||
* @param {string} clientToken The launcher's client token.
|
* @param {string} clientToken The launcher's client token.
|
||||||
*
|
*
|
||||||
* @see http://wiki.vg/Authentication#Invalidate
|
* @see http://wiki.vg/Authentication#Invalidate
|
||||||
*/
|
*/
|
||||||
exports.invalidate = function(accessToken, clientToken){
|
exports.invalidate = function(accessToken, clientToken){
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
request.post(authpath + '/invalidate',
|
request.post(authpath + '/invalidate',
|
||||||
{
|
{
|
||||||
json: true,
|
json: true,
|
||||||
body: {
|
body: {
|
||||||
accessToken,
|
accessToken,
|
||||||
clientToken
|
clientToken
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
function(error, response, body){
|
function(error, response, body){
|
||||||
if(error){
|
if(error){
|
||||||
logger.error('Error during invalidation.', error)
|
logger.error('Error during invalidation.', error)
|
||||||
reject(error)
|
reject(error)
|
||||||
} else {
|
} else {
|
||||||
if(response.statusCode === 204){
|
if(response.statusCode === 204){
|
||||||
resolve()
|
resolve()
|
||||||
} else {
|
} else {
|
||||||
reject(body)
|
reject(body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh a user's authentication. This should be used to keep a user logged
|
* Refresh a user's authentication. This should be used to keep a user logged
|
||||||
* in without asking them for their credentials again. A new access token will
|
* in without asking them for their credentials again. A new access token will
|
||||||
* be generated using a recent invalid access token. See Wiki for more info.
|
* be generated using a recent invalid access token. See Wiki for more info.
|
||||||
*
|
*
|
||||||
* @param {string} accessToken The old access token.
|
* @param {string} accessToken The old access token.
|
||||||
* @param {string} clientToken The launcher's client token.
|
* @param {string} clientToken The launcher's client token.
|
||||||
* @param {boolean} requestUser Optional. Adds user object to the reponse.
|
* @param {boolean} requestUser Optional. Adds user object to the reponse.
|
||||||
*
|
*
|
||||||
* @see http://wiki.vg/Authentication#Refresh
|
* @see http://wiki.vg/Authentication#Refresh
|
||||||
*/
|
*/
|
||||||
exports.refresh = function(accessToken, clientToken, requestUser = true){
|
exports.refresh = function(accessToken, clientToken, requestUser = true){
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
request.post(authpath + '/refresh',
|
request.post(authpath + '/refresh',
|
||||||
{
|
{
|
||||||
json: true,
|
json: true,
|
||||||
body: {
|
body: {
|
||||||
accessToken,
|
accessToken,
|
||||||
clientToken,
|
clientToken,
|
||||||
requestUser
|
requestUser
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
function(error, response, body){
|
function(error, response, body){
|
||||||
if(error){
|
if(error){
|
||||||
logger.error('Error during refresh.', error)
|
logger.error('Error during refresh.', error)
|
||||||
reject(error)
|
reject(error)
|
||||||
} else {
|
} else {
|
||||||
if(response.statusCode === 200){
|
if(response.statusCode === 200){
|
||||||
resolve(body)
|
resolve(body)
|
||||||
} else {
|
} else {
|
||||||
reject(body)
|
reject(body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
@ -1,69 +1,69 @@
|
|||||||
const {ipcRenderer} = require('electron')
|
const {ipcRenderer} = require('electron')
|
||||||
const fs = require('fs-extra')
|
const fs = require('fs-extra')
|
||||||
const os = require('os')
|
const os = require('os')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
const ConfigManager = require('./configmanager')
|
const ConfigManager = require('./configmanager')
|
||||||
const DistroManager = require('./distromanager')
|
const DistroManager = require('./distromanager')
|
||||||
const LangLoader = require('./langloader')
|
const LangLoader = require('./langloader')
|
||||||
const logger = require('./loggerutil')('%c[Preloader]', 'color: #a02d2a; font-weight: bold')
|
const logger = require('./loggerutil')('%c[Preloader]', 'color: #a02d2a; font-weight: bold')
|
||||||
|
|
||||||
logger.log('Loading..')
|
logger.log('Loading..')
|
||||||
|
|
||||||
// Load ConfigManager
|
// Load ConfigManager
|
||||||
ConfigManager.load()
|
ConfigManager.load()
|
||||||
|
|
||||||
// Load Strings
|
// Load Strings
|
||||||
LangLoader.loadLanguage('en_US')
|
LangLoader.loadLanguage('en_US')
|
||||||
|
|
||||||
function onDistroLoad(data){
|
function onDistroLoad(data){
|
||||||
if(data != null){
|
if(data != null){
|
||||||
|
|
||||||
// Resolve the selected server if its value has yet to be set.
|
// Resolve the selected server if its value has yet to be set.
|
||||||
if(ConfigManager.getSelectedServer() == null || data.getServer(ConfigManager.getSelectedServer()) == null){
|
if(ConfigManager.getSelectedServer() == null || data.getServer(ConfigManager.getSelectedServer()) == null){
|
||||||
logger.log('Determining default selected server..')
|
logger.log('Determining default selected server..')
|
||||||
ConfigManager.setSelectedServer(data.getMainServer().getID())
|
ConfigManager.setSelectedServer(data.getMainServer().getID())
|
||||||
ConfigManager.save()
|
ConfigManager.save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ipcRenderer.send('distributionIndexDone', data != null)
|
ipcRenderer.send('distributionIndexDone', data != null)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure Distribution is downloaded and cached.
|
// Ensure Distribution is downloaded and cached.
|
||||||
DistroManager.pullRemote().then((data) => {
|
DistroManager.pullRemote().then((data) => {
|
||||||
logger.log('Loaded distribution index.')
|
logger.log('Loaded distribution index.')
|
||||||
|
|
||||||
onDistroLoad(data)
|
onDistroLoad(data)
|
||||||
|
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
logger.log('Failed to load distribution index.')
|
logger.log('Failed to load distribution index.')
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
|
|
||||||
logger.log('Attempting to load an older version of the distribution index.')
|
logger.log('Attempting to load an older version of the distribution index.')
|
||||||
// Try getting a local copy, better than nothing.
|
// Try getting a local copy, better than nothing.
|
||||||
DistroManager.pullLocal().then((data) => {
|
DistroManager.pullLocal().then((data) => {
|
||||||
logger.log('Successfully loaded an older version of the distribution index.')
|
logger.log('Successfully loaded an older version of the distribution index.')
|
||||||
|
|
||||||
onDistroLoad(data)
|
onDistroLoad(data)
|
||||||
|
|
||||||
|
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
|
|
||||||
logger.log('Failed to load an older version of the distribution index.')
|
logger.log('Failed to load an older version of the distribution index.')
|
||||||
logger.log('Application cannot run.')
|
logger.log('Application cannot run.')
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
|
|
||||||
onDistroLoad(null)
|
onDistroLoad(null)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Clean up temp dir incase previous launches ended unexpectedly.
|
// Clean up temp dir incase previous launches ended unexpectedly.
|
||||||
fs.remove(path.join(os.tmpdir(), ConfigManager.getTempNativeFolder()), (err) => {
|
fs.remove(path.join(os.tmpdir(), ConfigManager.getTempNativeFolder()), (err) => {
|
||||||
if(err){
|
if(err){
|
||||||
logger.warn('Error while cleaning natives directory', err)
|
logger.warn('Error while cleaning natives directory', err)
|
||||||
} else {
|
} else {
|
||||||
logger.log('Cleaned natives directory.')
|
logger.log('Cleaned natives directory.')
|
||||||
}
|
}
|
||||||
})
|
})
|
@ -317,7 +317,7 @@ class ProcessBuilder {
|
|||||||
|
|
||||||
// Java Arguments
|
// Java Arguments
|
||||||
if(process.platform === 'darwin'){
|
if(process.platform === 'darwin'){
|
||||||
args.push('-Xdock:name=HeliosLauncher')
|
args.push('-Xdock:name=NemesisMCLauncher')
|
||||||
args.push('-Xdock:icon=' + path.join(__dirname, '..', 'images', 'minecraft.icns'))
|
args.push('-Xdock:icon=' + path.join(__dirname, '..', 'images', 'minecraft.icns'))
|
||||||
}
|
}
|
||||||
args.push('-Xmx' + ConfigManager.getMaxRAM())
|
args.push('-Xmx' + ConfigManager.getMaxRAM())
|
||||||
@ -355,7 +355,7 @@ class ProcessBuilder {
|
|||||||
|
|
||||||
// Java Arguments
|
// Java Arguments
|
||||||
if(process.platform === 'darwin'){
|
if(process.platform === 'darwin'){
|
||||||
args.push('-Xdock:name=HeliosLauncher')
|
args.push('-Xdock:name=NemesisMCLauncher')
|
||||||
args.push('-Xdock:icon=' + path.join(__dirname, '..', 'images', 'minecraft.icns'))
|
args.push('-Xdock:icon=' + path.join(__dirname, '..', 'images', 'minecraft.icns'))
|
||||||
}
|
}
|
||||||
args.push('-Xmx' + ConfigManager.getMaxRAM())
|
args.push('-Xmx' + ConfigManager.getMaxRAM())
|
||||||
@ -457,7 +457,7 @@ class ProcessBuilder {
|
|||||||
val = args[i].replace(argDiscovery, tempNativePath)
|
val = args[i].replace(argDiscovery, tempNativePath)
|
||||||
break
|
break
|
||||||
case 'launcher_name':
|
case 'launcher_name':
|
||||||
val = args[i].replace(argDiscovery, 'Helios-Launcher')
|
val = args[i].replace(argDiscovery, 'NemesisMC-Launcher')
|
||||||
break
|
break
|
||||||
case 'launcher_version':
|
case 'launcher_version':
|
||||||
val = args[i].replace(argDiscovery, this.launcherVersion)
|
val = args[i].replace(argDiscovery, this.launcherVersion)
|
||||||
|
@ -1,65 +1,65 @@
|
|||||||
const net = require('net')
|
const net = require('net')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the status of a minecraft server.
|
* Retrieves the status of a minecraft server.
|
||||||
*
|
*
|
||||||
* @param {string} address The server address.
|
* @param {string} address The server address.
|
||||||
* @param {number} port Optional. The port of the server. Defaults to 25565.
|
* @param {number} port Optional. The port of the server. Defaults to 25565.
|
||||||
* @returns {Promise.<Object>} A promise which resolves to an object containing
|
* @returns {Promise.<Object>} A promise which resolves to an object containing
|
||||||
* status information.
|
* status information.
|
||||||
*/
|
*/
|
||||||
exports.getStatus = function(address, port = 25565){
|
exports.getStatus = function(address, port = 25565){
|
||||||
|
|
||||||
if(port == null || port == ''){
|
if(port == null || port == ''){
|
||||||
port = 25565
|
port = 25565
|
||||||
}
|
}
|
||||||
if(typeof port === 'string'){
|
if(typeof port === 'string'){
|
||||||
port = parseInt(port)
|
port = parseInt(port)
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const socket = net.connect(port, address, () => {
|
const socket = net.connect(port, address, () => {
|
||||||
let buff = Buffer.from([0xFE, 0x01])
|
let buff = Buffer.from([0xFE, 0x01])
|
||||||
socket.write(buff)
|
socket.write(buff)
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.setTimeout(2500, () => {
|
socket.setTimeout(2500, () => {
|
||||||
socket.end()
|
socket.end()
|
||||||
reject({
|
reject({
|
||||||
code: 'ETIMEDOUT',
|
code: 'ETIMEDOUT',
|
||||||
errno: 'ETIMEDOUT',
|
errno: 'ETIMEDOUT',
|
||||||
address,
|
address,
|
||||||
port
|
port
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.on('data', (data) => {
|
socket.on('data', (data) => {
|
||||||
if(data != null && data != ''){
|
if(data != null && data != ''){
|
||||||
let server_info = data.toString().split('\x00\x00\x00')
|
let server_info = data.toString().split('\x00\x00\x00')
|
||||||
const NUM_FIELDS = 6
|
const NUM_FIELDS = 6
|
||||||
if(server_info != null && server_info.length >= NUM_FIELDS){
|
if(server_info != null && server_info.length >= NUM_FIELDS){
|
||||||
resolve({
|
resolve({
|
||||||
online: true,
|
online: true,
|
||||||
version: server_info[2].replace(/\u0000/g, ''),
|
version: server_info[2].replace(/\u0000/g, ''),
|
||||||
motd: server_info[3].replace(/\u0000/g, ''),
|
motd: server_info[3].replace(/\u0000/g, ''),
|
||||||
onlinePlayers: server_info[4].replace(/\u0000/g, ''),
|
onlinePlayers: server_info[4].replace(/\u0000/g, ''),
|
||||||
maxPlayers: server_info[5].replace(/\u0000/g,'')
|
maxPlayers: server_info[5].replace(/\u0000/g,'')
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
resolve({
|
resolve({
|
||||||
online: false
|
online: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
socket.end()
|
socket.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.on('error', (err) => {
|
socket.on('error', (err) => {
|
||||||
socket.destroy()
|
socket.destroy()
|
||||||
reject(err)
|
reject(err)
|
||||||
// ENOTFOUND = Unable to resolve.
|
// ENOTFOUND = Unable to resolve.
|
||||||
// ECONNREFUSED = Unable to connect to port.
|
// ECONNREFUSED = Unable to connect to port.
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user