Revert "Merge branch 'master' of github.com:dscalzi/HeliosLauncher into dscalzi-master"
This reverts commit 6c7196ad2cf86e0289cc8ca9e3d4f1ea3ad0dd9a, reversing changes made to 3d3055560f06ad47d6c5d3663254852cce1bb9fb.
This commit is contained in:
parent
2643830278
commit
b23c9d0317
@ -5,17 +5,15 @@ const logger = LoggerUtil.getLogger('DiscordWrapper')
|
|||||||
|
|
||||||
const { Client } = require('discord-rpc-patch')
|
const { Client } = require('discord-rpc-patch')
|
||||||
|
|
||||||
const Lang = require('./langloader')
|
|
||||||
|
|
||||||
let client
|
let client
|
||||||
let activity
|
let activity
|
||||||
|
|
||||||
exports.initRPC = function(genSettings, servSettings, initialDetails = Lang.queryJS('discord.waiting')){
|
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: Lang.queryJS('discord.state', {shortId: servSettings.shortId}),
|
state: 'Server: ' + servSettings.shortId,
|
||||||
largeImageKey: servSettings.largeImageKey,
|
largeImageKey: servSettings.largeImageKey,
|
||||||
largeImageText: servSettings.largeImageText,
|
largeImageText: servSettings.largeImageText,
|
||||||
smallImageKey: genSettings.smallImageKey,
|
smallImageKey: genSettings.smallImageKey,
|
||||||
|
@ -1,27 +1,19 @@
|
|||||||
const fs = require('fs-extra')
|
const fs = require('fs-extra')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const toml = require('toml')
|
|
||||||
const merge = require('lodash.merge')
|
|
||||||
|
|
||||||
let lang
|
let lang
|
||||||
|
|
||||||
exports.loadLanguage = function(id){
|
exports.loadLanguage = function(id){
|
||||||
lang = merge(lang || {}, toml.parse(fs.readFileSync(path.join(__dirname, '..', 'lang', `${id}.toml`))) || {})
|
lang = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'lang', `${id}.json`))) || {}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.query = function(id, placeHolders){
|
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]
|
||||||
}
|
}
|
||||||
let text = res === lang ? '' : res
|
return res === lang ? {} : res
|
||||||
if (placeHolders) {
|
|
||||||
Object.entries(placeHolders).forEach(([key, value]) => {
|
|
||||||
text = text.replace(`{${key}}`, value)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return text
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.queryJS = function(id, placeHolders){
|
exports.queryJS = function(id, placeHolders){
|
||||||
|
@ -12,23 +12,14 @@ const ConfigManager = require('./configmanager')
|
|||||||
|
|
||||||
const logger = LoggerUtil.getLogger('ProcessBuilder')
|
const logger = LoggerUtil.getLogger('ProcessBuilder')
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only forge and fabric are top level mod loaders.
|
|
||||||
*
|
|
||||||
* Forge 1.13+ launch logic is similar to fabrics, for now using usingFabricLoader flag to
|
|
||||||
* change minor details when needed.
|
|
||||||
*
|
|
||||||
* Rewrite of this module may be needed in the future.
|
|
||||||
*/
|
|
||||||
class ProcessBuilder {
|
class ProcessBuilder {
|
||||||
|
|
||||||
constructor(distroServer, vanillaManifest, modManifest, authUser, launcherVersion){
|
constructor(distroServer, versionData, forgeData, authUser, launcherVersion){
|
||||||
this.gameDir = path.join(ConfigManager.getInstanceDirectory(), distroServer.rawServer.id)
|
this.gameDir = path.join(ConfigManager.getInstanceDirectory(), distroServer.rawServer.id)
|
||||||
this.commonDir = ConfigManager.getCommonDirectory()
|
this.commonDir = ConfigManager.getCommonDirectory()
|
||||||
this.server = distroServer
|
this.server = distroServer
|
||||||
this.vanillaManifest = vanillaManifest
|
this.versionData = versionData
|
||||||
this.modManifest = modManifest
|
this.forgeData = forgeData
|
||||||
this.authUser = authUser
|
this.authUser = authUser
|
||||||
this.launcherVersion = launcherVersion
|
this.launcherVersion = launcherVersion
|
||||||
this.forgeModListFile = path.join(this.gameDir, 'forgeMods.list') // 1.13+
|
this.forgeModListFile = path.join(this.gameDir, 'forgeMods.list') // 1.13+
|
||||||
@ -37,7 +28,6 @@ class ProcessBuilder {
|
|||||||
this.libPath = path.join(this.commonDir, 'libraries')
|
this.libPath = path.join(this.commonDir, 'libraries')
|
||||||
|
|
||||||
this.usingLiteLoader = false
|
this.usingLiteLoader = false
|
||||||
this.usingFabricLoader = false
|
|
||||||
this.llPath = null
|
this.llPath = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,12 +40,9 @@ class ProcessBuilder {
|
|||||||
process.throwDeprecation = true
|
process.throwDeprecation = true
|
||||||
this.setupLiteLoader()
|
this.setupLiteLoader()
|
||||||
logger.info('Using liteloader:', this.usingLiteLoader)
|
logger.info('Using liteloader:', this.usingLiteLoader)
|
||||||
this.usingFabricLoader = this.server.modules.some(mdl => mdl.rawModule.type === Type.Fabric)
|
|
||||||
logger.info('Using fabric loader:', this.usingFabricLoader)
|
|
||||||
const modObj = this.resolveModConfiguration(ConfigManager.getModConfiguration(this.server.rawServer.id).mods, this.server.modules)
|
const modObj = this.resolveModConfiguration(ConfigManager.getModConfiguration(this.server.rawServer.id).mods, this.server.modules)
|
||||||
|
|
||||||
// Mod list below 1.13
|
// Mod list below 1.13
|
||||||
// Fabric only supports 1.14+
|
|
||||||
if(!mcVersionAtLeast('1.13', this.server.rawServer.minecraftVersion)){
|
if(!mcVersionAtLeast('1.13', this.server.rawServer.minecraftVersion)){
|
||||||
this.constructJSONModList('forge', modObj.fMods, true)
|
this.constructJSONModList('forge', modObj.fMods, true)
|
||||||
if(this.usingLiteLoader){
|
if(this.usingLiteLoader){
|
||||||
@ -179,7 +166,7 @@ class ProcessBuilder {
|
|||||||
|
|
||||||
for(let mdl of mdls){
|
for(let mdl of mdls){
|
||||||
const type = mdl.rawModule.type
|
const type = mdl.rawModule.type
|
||||||
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader || type === Type.FabricMod){
|
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader){
|
||||||
const o = !mdl.getRequired().value
|
const o = !mdl.getRequired().value
|
||||||
const e = ProcessBuilder.isModEnabled(modCfg[mdl.getVersionlessMavenIdentifier()], mdl.getRequired())
|
const e = ProcessBuilder.isModEnabled(modCfg[mdl.getVersionlessMavenIdentifier()], mdl.getRequired())
|
||||||
if(!o || (o && e)){
|
if(!o || (o && e)){
|
||||||
@ -191,7 +178,7 @@ class ProcessBuilder {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(type === Type.ForgeMod || type === Type.FabricMod){
|
if(type === Type.ForgeMod){
|
||||||
fMods.push(mdl)
|
fMods.push(mdl)
|
||||||
} else {
|
} else {
|
||||||
lMods.push(mdl)
|
lMods.push(mdl)
|
||||||
@ -207,7 +194,7 @@ class ProcessBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_lteMinorVersion(version) {
|
_lteMinorVersion(version) {
|
||||||
return Number(this.modManifest.id.split('-')[0].split('.')[1]) <= Number(version)
|
return Number(this.forgeData.id.split('-')[0].split('.')[1]) <= Number(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -219,7 +206,7 @@ class ProcessBuilder {
|
|||||||
if(this._lteMinorVersion(9)) {
|
if(this._lteMinorVersion(9)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const ver = this.modManifest.id.split('-')[2]
|
const ver = this.forgeData.id.split('-')[2]
|
||||||
const pts = ver.split('.')
|
const pts = ver.split('.')
|
||||||
const min = [14, 23, 3, 2655]
|
const min = [14, 23, 3, 2655]
|
||||||
for(let i=0; i<pts.length; i++){
|
for(let i=0; i<pts.length; i++){
|
||||||
@ -295,21 +282,18 @@ class ProcessBuilder {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the mod argument list for forge 1.13 and Fabric
|
* Construct the mod argument list for forge 1.13
|
||||||
*
|
*
|
||||||
* @param {Array.<Object>} mods An array of mods to add to the mod list.
|
* @param {Array.<Object>} mods An array of mods to add to the mod list.
|
||||||
*/
|
*/
|
||||||
constructModList(mods) {
|
constructModList(mods) {
|
||||||
const writeBuffer = mods.map(mod => {
|
const writeBuffer = mods.map(mod => {
|
||||||
return this.usingFabricLoader ? mod.getPath() : mod.getExtensionlessMavenIdentifier()
|
return mod.getExtensionlessMavenIdentifier()
|
||||||
}).join('\n')
|
}).join('\n')
|
||||||
|
|
||||||
if(writeBuffer) {
|
if(writeBuffer) {
|
||||||
fs.writeFileSync(this.forgeModListFile, writeBuffer, 'UTF-8')
|
fs.writeFileSync(this.forgeModListFile, writeBuffer, 'UTF-8')
|
||||||
return this.usingFabricLoader ? [
|
return [
|
||||||
'--fabric.addMods',
|
|
||||||
`@${this.forgeModListFile}`
|
|
||||||
] : [
|
|
||||||
'--fml.mavenRoots',
|
'--fml.mavenRoots',
|
||||||
path.join('..', '..', 'common', 'modstore'),
|
path.join('..', '..', 'common', 'modstore'),
|
||||||
'--fml.modLists',
|
'--fml.modLists',
|
||||||
@ -323,17 +307,12 @@ class ProcessBuilder {
|
|||||||
|
|
||||||
_processAutoConnectArg(args){
|
_processAutoConnectArg(args){
|
||||||
if(ConfigManager.getAutoConnect() && this.server.rawServer.autoconnect){
|
if(ConfigManager.getAutoConnect() && this.server.rawServer.autoconnect){
|
||||||
if(mcVersionAtLeast('1.20', this.server.rawServer.minecraftVersion)){
|
|
||||||
args.push('--quickPlayMultiplayer')
|
|
||||||
args.push(`${this.server.hostname}:${this.server.port}`)
|
|
||||||
} else {
|
|
||||||
args.push('--server')
|
args.push('--server')
|
||||||
args.push(this.server.hostname)
|
args.push(this.server.hostname)
|
||||||
args.push('--port')
|
args.push('--port')
|
||||||
args.push(this.server.port)
|
args.push(this.server.port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the argument array that will be passed to the JVM process.
|
* Construct the argument array that will be passed to the JVM process.
|
||||||
@ -377,7 +356,7 @@ class ProcessBuilder {
|
|||||||
args.push('-Djava.library.path=' + tempNativePath)
|
args.push('-Djava.library.path=' + tempNativePath)
|
||||||
|
|
||||||
// Main Java Class
|
// Main Java Class
|
||||||
args.push(this.modManifest.mainClass)
|
args.push(this.forgeData.mainClass)
|
||||||
|
|
||||||
// Forge Arguments
|
// Forge Arguments
|
||||||
args = args.concat(this._resolveForgeArgs())
|
args = args.concat(this._resolveForgeArgs())
|
||||||
@ -400,17 +379,17 @@ class ProcessBuilder {
|
|||||||
const argDiscovery = /\${*(.*)}/
|
const argDiscovery = /\${*(.*)}/
|
||||||
|
|
||||||
// JVM Arguments First
|
// JVM Arguments First
|
||||||
let args = this.vanillaManifest.arguments.jvm
|
let args = this.versionData.arguments.jvm
|
||||||
|
|
||||||
// Debug securejarhandler
|
// Debug securejarhandler
|
||||||
// args.push('-Dbsl.debug=true')
|
// args.push('-Dbsl.debug=true')
|
||||||
|
|
||||||
if(this.modManifest.arguments.jvm != null) {
|
if(this.forgeData.arguments.jvm != null) {
|
||||||
for(const argStr of this.modManifest.arguments.jvm) {
|
for(const argStr of this.forgeData.arguments.jvm) {
|
||||||
args.push(argStr
|
args.push(argStr
|
||||||
.replaceAll('${library_directory}', this.libPath)
|
.replaceAll('${library_directory}', this.libPath)
|
||||||
.replaceAll('${classpath_separator}', ProcessBuilder.getClasspathSeparator())
|
.replaceAll('${classpath_separator}', ProcessBuilder.getClasspathSeparator())
|
||||||
.replaceAll('${version_name}', this.modManifest.id)
|
.replaceAll('${version_name}', this.forgeData.id)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -427,10 +406,10 @@ class ProcessBuilder {
|
|||||||
args = args.concat(ConfigManager.getJVMOptions(this.server.rawServer.id))
|
args = args.concat(ConfigManager.getJVMOptions(this.server.rawServer.id))
|
||||||
|
|
||||||
// Main Java Class
|
// Main Java Class
|
||||||
args.push(this.modManifest.mainClass)
|
args.push(this.forgeData.mainClass)
|
||||||
|
|
||||||
// Vanilla Arguments
|
// Vanilla Arguments
|
||||||
args = args.concat(this.vanillaManifest.arguments.game)
|
args = args.concat(this.versionData.arguments.game)
|
||||||
|
|
||||||
for(let i=0; i<args.length; i++){
|
for(let i=0; i<args.length; i++){
|
||||||
if(typeof args[i] === 'object' && args[i].rules != null){
|
if(typeof args[i] === 'object' && args[i].rules != null){
|
||||||
@ -487,7 +466,7 @@ class ProcessBuilder {
|
|||||||
val = this.authUser.displayName.trim()
|
val = this.authUser.displayName.trim()
|
||||||
break
|
break
|
||||||
case 'version_name':
|
case 'version_name':
|
||||||
//val = vanillaManifest.id
|
//val = versionData.id
|
||||||
val = this.server.rawServer.id
|
val = this.server.rawServer.id
|
||||||
break
|
break
|
||||||
case 'game_directory':
|
case 'game_directory':
|
||||||
@ -497,7 +476,7 @@ class ProcessBuilder {
|
|||||||
val = path.join(this.commonDir, 'assets')
|
val = path.join(this.commonDir, 'assets')
|
||||||
break
|
break
|
||||||
case 'assets_index_name':
|
case 'assets_index_name':
|
||||||
val = this.vanillaManifest.assets
|
val = this.versionData.assets
|
||||||
break
|
break
|
||||||
case 'auth_uuid':
|
case 'auth_uuid':
|
||||||
val = this.authUser.uuid.trim()
|
val = this.authUser.uuid.trim()
|
||||||
@ -509,7 +488,7 @@ class ProcessBuilder {
|
|||||||
val = this.authUser.type === 'microsoft' ? 'msa' : 'mojang'
|
val = this.authUser.type === 'microsoft' ? 'msa' : 'mojang'
|
||||||
break
|
break
|
||||||
case 'version_type':
|
case 'version_type':
|
||||||
val = this.vanillaManifest.type
|
val = this.versionData.type
|
||||||
break
|
break
|
||||||
case 'resolution_width':
|
case 'resolution_width':
|
||||||
val = ConfigManager.getGameWidth()
|
val = ConfigManager.getGameWidth()
|
||||||
@ -538,11 +517,25 @@ class ProcessBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Autoconnect
|
// Autoconnect
|
||||||
|
let isAutoconnectBroken
|
||||||
|
try {
|
||||||
|
isAutoconnectBroken = ProcessBuilder.isAutoconnectBroken(this.forgeData.id.split('-')[2])
|
||||||
|
} catch(err) {
|
||||||
|
logger.error(err)
|
||||||
|
logger.error('Forge version format changed.. assuming autoconnect works.')
|
||||||
|
logger.debug('Forge version:', this.forgeData.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isAutoconnectBroken) {
|
||||||
|
logger.error('Server autoconnect disabled on Forge 1.15.2 for builds earlier than 31.2.15 due to OpenGL Stack Overflow issue.')
|
||||||
|
logger.error('Please upgrade your Forge version to at least 31.2.15!')
|
||||||
|
} else {
|
||||||
this._processAutoConnectArg(args)
|
this._processAutoConnectArg(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Forge Specific Arguments
|
// Forge Specific Arguments
|
||||||
args = args.concat(this.modManifest.arguments.game)
|
args = args.concat(this.forgeData.arguments.game)
|
||||||
|
|
||||||
// Filter null values
|
// Filter null values
|
||||||
args = args.filter(arg => {
|
args = args.filter(arg => {
|
||||||
@ -558,7 +551,7 @@ class ProcessBuilder {
|
|||||||
* @returns {Array.<string>} An array containing the arguments required by forge.
|
* @returns {Array.<string>} An array containing the arguments required by forge.
|
||||||
*/
|
*/
|
||||||
_resolveForgeArgs(){
|
_resolveForgeArgs(){
|
||||||
const mcArgs = this.modManifest.minecraftArguments.split(' ')
|
const mcArgs = this.forgeData.minecraftArguments.split(' ')
|
||||||
const argDiscovery = /\${*(.*)}/
|
const argDiscovery = /\${*(.*)}/
|
||||||
|
|
||||||
// Replace the declared variables with their proper values.
|
// Replace the declared variables with their proper values.
|
||||||
@ -571,7 +564,7 @@ class ProcessBuilder {
|
|||||||
val = this.authUser.displayName.trim()
|
val = this.authUser.displayName.trim()
|
||||||
break
|
break
|
||||||
case 'version_name':
|
case 'version_name':
|
||||||
//val = vanillaManifest.id
|
//val = versionData.id
|
||||||
val = this.server.rawServer.id
|
val = this.server.rawServer.id
|
||||||
break
|
break
|
||||||
case 'game_directory':
|
case 'game_directory':
|
||||||
@ -581,7 +574,7 @@ class ProcessBuilder {
|
|||||||
val = path.join(this.commonDir, 'assets')
|
val = path.join(this.commonDir, 'assets')
|
||||||
break
|
break
|
||||||
case 'assets_index_name':
|
case 'assets_index_name':
|
||||||
val = this.vanillaManifest.assets
|
val = this.versionData.assets
|
||||||
break
|
break
|
||||||
case 'auth_uuid':
|
case 'auth_uuid':
|
||||||
val = this.authUser.uuid.trim()
|
val = this.authUser.uuid.trim()
|
||||||
@ -596,7 +589,7 @@ class ProcessBuilder {
|
|||||||
val = '{}'
|
val = '{}'
|
||||||
break
|
break
|
||||||
case 'version_type':
|
case 'version_type':
|
||||||
val = this.vanillaManifest.type
|
val = this.versionData.type
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if(val != null){
|
if(val != null){
|
||||||
@ -671,10 +664,10 @@ class ProcessBuilder {
|
|||||||
classpathArg(mods, tempNativePath){
|
classpathArg(mods, tempNativePath){
|
||||||
let cpArgs = []
|
let cpArgs = []
|
||||||
|
|
||||||
if(!mcVersionAtLeast('1.17', this.server.rawServer.minecraftVersion) || this.usingFabricLoader) {
|
if(!mcVersionAtLeast('1.17', this.server.rawServer.minecraftVersion)) {
|
||||||
// Add the version.jar to the classpath.
|
// Add the version.jar to the classpath.
|
||||||
// Must not be added to the classpath for Forge 1.17+.
|
// Must not be added to the classpath for Forge 1.17+.
|
||||||
const version = this.vanillaManifest.id
|
const version = this.versionData.id
|
||||||
cpArgs.push(path.join(this.commonDir, 'versions', version, version + '.jar'))
|
cpArgs.push(path.join(this.commonDir, 'versions', version, version + '.jar'))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,7 +706,7 @@ class ProcessBuilder {
|
|||||||
const nativesRegex = /.+:natives-([^-]+)(?:-(.+))?/
|
const nativesRegex = /.+:natives-([^-]+)(?:-(.+))?/
|
||||||
const libs = {}
|
const libs = {}
|
||||||
|
|
||||||
const libArr = this.vanillaManifest.libraries
|
const libArr = this.versionData.libraries
|
||||||
fs.ensureDirSync(tempNativePath)
|
fs.ensureDirSync(tempNativePath)
|
||||||
for(let i=0; i<libArr.length; i++){
|
for(let i=0; i<libArr.length; i++){
|
||||||
const lib = libArr[i]
|
const lib = libArr[i]
|
||||||
@ -832,10 +825,10 @@ class ProcessBuilder {
|
|||||||
const mdls = this.server.modules
|
const mdls = this.server.modules
|
||||||
let libs = {}
|
let libs = {}
|
||||||
|
|
||||||
// Locate Forge/Fabric/Libraries
|
// Locate Forge/Libraries
|
||||||
for(let mdl of mdls){
|
for(let mdl of mdls){
|
||||||
const type = mdl.rawModule.type
|
const type = mdl.rawModule.type
|
||||||
if(type === Type.ForgeHosted || type === Type.Fabric || type === Type.Library){
|
if(type === Type.ForgeHosted || type === Type.Library){
|
||||||
libs[mdl.getVersionlessMavenIdentifier()] = mdl.getPath()
|
libs[mdl.getVersionlessMavenIdentifier()] = mdl.getPath()
|
||||||
if(mdl.subModules.length > 0){
|
if(mdl.subModules.length > 0){
|
||||||
const res = this._resolveModuleLibraries(mdl)
|
const res = this._resolveModuleLibraries(mdl)
|
||||||
@ -889,6 +882,24 @@ class ProcessBuilder {
|
|||||||
return libs
|
return libs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static isAutoconnectBroken(forgeVersion) {
|
||||||
|
|
||||||
|
const minWorking = [31, 2, 15]
|
||||||
|
const verSplit = forgeVersion.split('.').map(v => Number(v))
|
||||||
|
|
||||||
|
if(verSplit[0] === 31) {
|
||||||
|
for(let i=0; i<minWorking.length; i++) {
|
||||||
|
if(verSplit[i] > minWorking[i]) {
|
||||||
|
return false
|
||||||
|
} else if(verSplit[i] < minWorking[i]) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ProcessBuilder
|
module.exports = ProcessBuilder
|
@ -220,7 +220,10 @@ loginButton.addEventListener('click', () => {
|
|||||||
} else {
|
} else {
|
||||||
// Uh oh.
|
// Uh oh.
|
||||||
msftLoginLogger.error('Unhandled error during login.', displayableError)
|
msftLoginLogger.error('Unhandled error during login.', displayableError)
|
||||||
actualDisplayableError = Lang.queryJS('login.error.unknown')
|
actualDisplayableError = {
|
||||||
|
title: 'Unknown Error During Login',
|
||||||
|
desc: 'An unknown error has occurred. Please see the console for details.'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setOverlayContent(actualDisplayableError.title, actualDisplayableError.desc, Lang.queryJS('login.tryAgain'))
|
setOverlayContent(actualDisplayableError.title, actualDisplayableError.desc, Lang.queryJS('login.tryAgain'))
|
||||||
|
@ -130,7 +130,7 @@ async function toggleServerSelection(toggleState){
|
|||||||
* @param {string} acknowledge Acknowledge button text.
|
* @param {string} acknowledge Acknowledge button text.
|
||||||
* @param {string} dismiss Dismiss button text.
|
* @param {string} dismiss Dismiss button text.
|
||||||
*/
|
*/
|
||||||
function setOverlayContent(title, description, acknowledge, dismiss = Lang.queryJS('overlay.dismiss')){
|
function setOverlayContent(title, description, acknowledge, dismiss = 'Dismiss'){
|
||||||
document.getElementById('overlayTitle').innerHTML = title
|
document.getElementById('overlayTitle').innerHTML = title
|
||||||
document.getElementById('overlayDesc').innerHTML = description
|
document.getElementById('overlayDesc').innerHTML = description
|
||||||
document.getElementById('overlayAcknowledge').innerHTML = acknowledge
|
document.getElementById('overlayAcknowledge').innerHTML = acknowledge
|
||||||
@ -289,7 +289,7 @@ async function populateServerListings(){
|
|||||||
<path class="cls-1" d="M100.93,65.54C89,62,68.18,55.65,63.54,52.13c2.7-5.23,18.8-19.2,28-27.55C81.36,31.74,63.74,43.87,58.09,45.3c-2.41-5.37-3.61-26.52-4.37-39-.77,12.46-2,33.64-4.36,39-5.7-1.46-23.3-13.57-33.49-20.72,9.26,8.37,25.39,22.36,28,27.55C39.21,55.68,18.47,62,6.52,65.55c12.32-2,33.63-6.06,39.34-4.9-.16,5.87-8.41,26.16-13.11,37.69,6.1-10.89,16.52-30.16,21-33.9,4.5,3.79,14.93,23.09,21,34C70,86.84,61.73,66.48,61.59,60.65,67.36,59.49,88.64,63.52,100.93,65.54Z"/>
|
<path class="cls-1" d="M100.93,65.54C89,62,68.18,55.65,63.54,52.13c2.7-5.23,18.8-19.2,28-27.55C81.36,31.74,63.74,43.87,58.09,45.3c-2.41-5.37-3.61-26.52-4.37-39-.77,12.46-2,33.64-4.36,39-5.7-1.46-23.3-13.57-33.49-20.72,9.26,8.37,25.39,22.36,28,27.55C39.21,55.68,18.47,62,6.52,65.55c12.32-2,33.63-6.06,39.34-4.9-.16,5.87-8.41,26.16-13.11,37.69,6.1-10.89,16.52-30.16,21-33.9,4.5,3.79,14.93,23.09,21,34C70,86.84,61.73,66.48,61.59,60.65,67.36,59.49,88.64,63.52,100.93,65.54Z"/>
|
||||||
<circle class="cls-2" cx="53.73" cy="53.9" r="38"/>
|
<circle class="cls-2" cx="53.73" cy="53.9" r="38"/>
|
||||||
</svg>
|
</svg>
|
||||||
<span class="serverListingStarTooltip">${Lang.queryJS('settings.serverListing.mainServer')}</span>
|
<span class="serverListingStarTooltip">Main Server</span>
|
||||||
</div>` : ''}
|
</div>` : ''}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -59,8 +59,8 @@ function bindFileSelectors(){
|
|||||||
|
|
||||||
if(isJavaExecSel && process.platform === 'win32') {
|
if(isJavaExecSel && process.platform === 'win32') {
|
||||||
options.filters = [
|
options.filters = [
|
||||||
{ name: Lang.queryJS('settings.fileSelectors.executables'), extensions: ['exe'] },
|
{ name: 'Executables', extensions: ['exe'] },
|
||||||
{ name: Lang.queryJS('settings.fileSelectors.allFiles'), extensions: ['*'] }
|
{ name: 'All Files', extensions: ['*'] }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,9 +374,9 @@ ipcRenderer.on(MSFT_OPCODE.REPLY_LOGIN, (_, ...arguments_) => {
|
|||||||
|
|
||||||
// Unexpected error.
|
// Unexpected error.
|
||||||
setOverlayContent(
|
setOverlayContent(
|
||||||
Lang.queryJS('settings.msftLogin.errorTitle'),
|
'Something Went Wrong',
|
||||||
Lang.queryJS('settings.msftLogin.errorMessage'),
|
'Microsoft authentication failed. Please try again.',
|
||||||
Lang.queryJS('settings.msftLogin.okButton')
|
'OK'
|
||||||
)
|
)
|
||||||
setOverlayHandler(() => {
|
setOverlayHandler(() => {
|
||||||
toggleOverlay(false)
|
toggleOverlay(false)
|
||||||
@ -401,7 +401,7 @@ ipcRenderer.on(MSFT_OPCODE.REPLY_LOGIN, (_, ...arguments_) => {
|
|||||||
setOverlayContent(
|
setOverlayContent(
|
||||||
error,
|
error,
|
||||||
errorDesc,
|
errorDesc,
|
||||||
Lang.queryJS('settings.msftLogin.okButton')
|
'OK'
|
||||||
)
|
)
|
||||||
setOverlayHandler(() => {
|
setOverlayHandler(() => {
|
||||||
toggleOverlay(false)
|
toggleOverlay(false)
|
||||||
@ -429,7 +429,10 @@ ipcRenderer.on(MSFT_OPCODE.REPLY_LOGIN, (_, ...arguments_) => {
|
|||||||
} else {
|
} else {
|
||||||
// Uh oh.
|
// Uh oh.
|
||||||
msftLoginLogger.error('Unhandled error during login.', displayableError)
|
msftLoginLogger.error('Unhandled error during login.', displayableError)
|
||||||
actualDisplayableError = Lang.queryJS('login.error.unknown')
|
actualDisplayableError = {
|
||||||
|
title: 'Unknown Error During Login',
|
||||||
|
desc: 'An unknown error has occurred. Please see the console for details.'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switchView(getCurrentView(), viewOnClose, 500, 500, () => {
|
switchView(getCurrentView(), viewOnClose, 500, 500, () => {
|
||||||
@ -458,11 +461,11 @@ function bindAuthAccountSelect(){
|
|||||||
for(let i=0; i<selectBtns.length; i++){
|
for(let i=0; i<selectBtns.length; i++){
|
||||||
if(selectBtns[i].hasAttribute('selected')){
|
if(selectBtns[i].hasAttribute('selected')){
|
||||||
selectBtns[i].removeAttribute('selected')
|
selectBtns[i].removeAttribute('selected')
|
||||||
selectBtns[i].innerHTML = Lang.queryJS('settings.authAccountSelect.selectButton')
|
selectBtns[i].innerHTML = 'Select Account'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val.setAttribute('selected', '')
|
val.setAttribute('selected', '')
|
||||||
val.innerHTML = Lang.queryJS('settings.authAccountSelect.selectedButton')
|
val.innerHTML = 'Selected Account ✔'
|
||||||
setSelectedAccount(val.closest('.settingsAuthAccount').getAttribute('uuid'))
|
setSelectedAccount(val.closest('.settingsAuthAccount').getAttribute('uuid'))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -480,10 +483,10 @@ function bindAuthAccountLogOut(){
|
|||||||
if(Object.keys(ConfigManager.getAuthAccounts()).length === 1){
|
if(Object.keys(ConfigManager.getAuthAccounts()).length === 1){
|
||||||
isLastAccount = true
|
isLastAccount = true
|
||||||
setOverlayContent(
|
setOverlayContent(
|
||||||
Lang.queryJS('settings.authAccountLogout.lastAccountWarningTitle'),
|
'Warning<br>This is Your Last Account',
|
||||||
Lang.queryJS('settings.authAccountLogout.lastAccountWarningMessage'),
|
'In order to use the launcher you must be logged into at least one account. You will need to login again after.<br><br>Are you sure you want to log out?',
|
||||||
Lang.queryJS('settings.authAccountLogout.confirmButton'),
|
'I\'m Sure',
|
||||||
Lang.queryJS('settings.authAccountLogout.cancelButton')
|
'Cancel'
|
||||||
)
|
)
|
||||||
setOverlayHandler(() => {
|
setOverlayHandler(() => {
|
||||||
processLogOut(val, isLastAccount)
|
processLogOut(val, isLastAccount)
|
||||||
@ -552,9 +555,9 @@ ipcRenderer.on(MSFT_OPCODE.REPLY_LOGOUT, (_, ...arguments_) => {
|
|||||||
|
|
||||||
// Unexpected error.
|
// Unexpected error.
|
||||||
setOverlayContent(
|
setOverlayContent(
|
||||||
Lang.queryJS('settings.msftLogout.errorTitle'),
|
'Something Went Wrong',
|
||||||
Lang.queryJS('settings.msftLogout.errorMessage'),
|
'Microsoft logout failed. Please try again.',
|
||||||
Lang.queryJS('settings.msftLogout.okButton')
|
'OK'
|
||||||
)
|
)
|
||||||
setOverlayHandler(() => {
|
setOverlayHandler(() => {
|
||||||
toggleOverlay(false)
|
toggleOverlay(false)
|
||||||
@ -608,12 +611,12 @@ function refreshAuthAccountSelected(uuid){
|
|||||||
const selBtn = val.getElementsByClassName('settingsAuthAccountSelect')[0]
|
const selBtn = val.getElementsByClassName('settingsAuthAccountSelect')[0]
|
||||||
if(uuid === val.getAttribute('uuid')){
|
if(uuid === val.getAttribute('uuid')){
|
||||||
selBtn.setAttribute('selected', '')
|
selBtn.setAttribute('selected', '')
|
||||||
selBtn.innerHTML = Lang.queryJS('settings.authAccountSelect.selectedButton')
|
selBtn.innerHTML = 'Selected Account ✔'
|
||||||
} else {
|
} else {
|
||||||
if(selBtn.hasAttribute('selected')){
|
if(selBtn.hasAttribute('selected')){
|
||||||
selBtn.removeAttribute('selected')
|
selBtn.removeAttribute('selected')
|
||||||
}
|
}
|
||||||
selBtn.innerHTML = Lang.queryJS('settings.authAccountSelect.selectButton')
|
selBtn.innerHTML = 'Select Account'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -645,18 +648,18 @@ function populateAuthAccounts(){
|
|||||||
<div class="settingsAuthAccountRight">
|
<div class="settingsAuthAccountRight">
|
||||||
<div class="settingsAuthAccountDetails">
|
<div class="settingsAuthAccountDetails">
|
||||||
<div class="settingsAuthAccountDetailPane">
|
<div class="settingsAuthAccountDetailPane">
|
||||||
<div class="settingsAuthAccountDetailTitle">${Lang.queryJS('settings.authAccountPopulate.username')}</div>
|
<div class="settingsAuthAccountDetailTitle">Username</div>
|
||||||
<div class="settingsAuthAccountDetailValue">${acc.displayName}</div>
|
<div class="settingsAuthAccountDetailValue">${acc.displayName}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="settingsAuthAccountDetailPane">
|
<div class="settingsAuthAccountDetailPane">
|
||||||
<div class="settingsAuthAccountDetailTitle">${Lang.queryJS('settings.authAccountPopulate.uuid')}</div>
|
<div class="settingsAuthAccountDetailTitle">UUID</div>
|
||||||
<div class="settingsAuthAccountDetailValue">${acc.uuid}</div>
|
<div class="settingsAuthAccountDetailValue">${acc.uuid}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="settingsAuthAccountActions">
|
<div class="settingsAuthAccountActions">
|
||||||
<button class="settingsAuthAccountSelect" ${selectedUUID === acc.uuid ? 'selected>' + Lang.queryJS('settings.authAccountPopulate.selectedAccount') : '>' + Lang.queryJS('settings.authAccountPopulate.selectAccount')}</button>
|
<button class="settingsAuthAccountSelect" ${selectedUUID === acc.uuid ? 'selected>Selected Account ✔' : '>Select Account'}</button>
|
||||||
<div class="settingsAuthAccountWrapper">
|
<div class="settingsAuthAccountWrapper">
|
||||||
<button class="settingsAuthAccountLogOut">${Lang.queryJS('settings.authAccountPopulate.logout')}</button>
|
<button class="settingsAuthAccountLogOut">Log Out</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -736,7 +739,7 @@ function parseModulesForUI(mdls, submodules, servConf){
|
|||||||
|
|
||||||
for(const mdl of mdls){
|
for(const mdl of mdls){
|
||||||
|
|
||||||
if(mdl.rawModule.type === Type.ForgeMod || mdl.rawModule.type === Type.LiteMod || mdl.rawModule.type === Type.LiteLoader || mdl.rawModule.type === Type.FabricMod){
|
if(mdl.rawModule.type === Type.ForgeMod || mdl.rawModule.type === Type.LiteMod || mdl.rawModule.type === Type.LiteLoader){
|
||||||
|
|
||||||
if(mdl.getRequired().value){
|
if(mdl.getRequired().value){
|
||||||
|
|
||||||
@ -870,7 +873,7 @@ async function resolveDropinModsForUI(){
|
|||||||
<div class="settingsModDetails">
|
<div class="settingsModDetails">
|
||||||
<span class="settingsModName">${dropin.name}</span>
|
<span class="settingsModName">${dropin.name}</span>
|
||||||
<div class="settingsDropinRemoveWrapper">
|
<div class="settingsDropinRemoveWrapper">
|
||||||
<button class="settingsDropinRemoveButton" remmod="${dropin.fullName}">${Lang.queryJS('settings.dropinMods.removeButton')}</button>
|
<button class="settingsDropinRemoveButton" remmod="${dropin.fullName}">Remove</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -898,9 +901,9 @@ function bindDropinModsRemoveButton(){
|
|||||||
document.getElementById(fullName).remove()
|
document.getElementById(fullName).remove()
|
||||||
} else {
|
} else {
|
||||||
setOverlayContent(
|
setOverlayContent(
|
||||||
Lang.queryJS('settings.dropinMods.deleteFailedTitle', { fullName }),
|
`Failed to Delete<br>Drop-in Mod ${fullName}`,
|
||||||
Lang.queryJS('settings.dropinMods.deleteFailedMessage'),
|
'Make sure the file is not in use and try again.',
|
||||||
Lang.queryJS('settings.dropinMods.okButton')
|
'Okay'
|
||||||
)
|
)
|
||||||
setOverlayHandler(null)
|
setOverlayHandler(null)
|
||||||
toggleOverlay(true)
|
toggleOverlay(true)
|
||||||
@ -953,9 +956,9 @@ function saveDropinModConfiguration(){
|
|||||||
DropinModUtil.toggleDropinMod(CACHE_SETTINGS_MODS_DIR, dropin.fullName, dropinUIEnabled).catch(err => {
|
DropinModUtil.toggleDropinMod(CACHE_SETTINGS_MODS_DIR, dropin.fullName, dropinUIEnabled).catch(err => {
|
||||||
if(!isOverlayVisible()){
|
if(!isOverlayVisible()){
|
||||||
setOverlayContent(
|
setOverlayContent(
|
||||||
Lang.queryJS('settings.dropinMods.failedToggleTitle'),
|
'Failed to Toggle<br>One or More Drop-in Mods',
|
||||||
err.message,
|
err.message,
|
||||||
Lang.queryJS('settings.dropinMods.okButton')
|
'Okay'
|
||||||
)
|
)
|
||||||
setOverlayHandler(null)
|
setOverlayHandler(null)
|
||||||
toggleOverlay(true)
|
toggleOverlay(true)
|
||||||
@ -1090,7 +1093,7 @@ async function loadSelectedServerOnModsTab(){
|
|||||||
<path class="cls-1" d="M100.93,65.54C89,62,68.18,55.65,63.54,52.13c2.7-5.23,18.8-19.2,28-27.55C81.36,31.74,63.74,43.87,58.09,45.3c-2.41-5.37-3.61-26.52-4.37-39-.77,12.46-2,33.64-4.36,39-5.7-1.46-23.3-13.57-33.49-20.72,9.26,8.37,25.39,22.36,28,27.55C39.21,55.68,18.47,62,6.52,65.55c12.32-2,33.63-6.06,39.34-4.9-.16,5.87-8.41,26.16-13.11,37.69,6.1-10.89,16.52-30.16,21-33.9,4.5,3.79,14.93,23.09,21,34C70,86.84,61.73,66.48,61.59,60.65,67.36,59.49,88.64,63.52,100.93,65.54Z"/>
|
<path class="cls-1" d="M100.93,65.54C89,62,68.18,55.65,63.54,52.13c2.7-5.23,18.8-19.2,28-27.55C81.36,31.74,63.74,43.87,58.09,45.3c-2.41-5.37-3.61-26.52-4.37-39-.77,12.46-2,33.64-4.36,39-5.7-1.46-23.3-13.57-33.49-20.72,9.26,8.37,25.39,22.36,28,27.55C39.21,55.68,18.47,62,6.52,65.55c12.32-2,33.63-6.06,39.34-4.9-.16,5.87-8.41,26.16-13.11,37.69,6.1-10.89,16.52-30.16,21-33.9,4.5,3.79,14.93,23.09,21,34C70,86.84,61.73,66.48,61.59,60.65,67.36,59.49,88.64,63.52,100.93,65.54Z"/>
|
||||||
<circle class="cls-2" cx="53.73" cy="53.9" r="38"/>
|
<circle class="cls-2" cx="53.73" cy="53.9" r="38"/>
|
||||||
</svg>
|
</svg>
|
||||||
<span class="serverListingStarTooltip">${Lang.queryJS('settings.serverListing.mainServer')}</span>
|
<span class="serverListingStarTooltip">Main Server</span>
|
||||||
</div>` : ''}
|
</div>` : ''}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1341,19 +1344,19 @@ async function populateJavaExecDetails(execPath){
|
|||||||
const details = await validateSelectedJvm(ensureJavaDirIsRoot(execPath), server.effectiveJavaOptions.supported)
|
const details = await validateSelectedJvm(ensureJavaDirIsRoot(execPath), server.effectiveJavaOptions.supported)
|
||||||
|
|
||||||
if(details != null) {
|
if(details != null) {
|
||||||
settingsJavaExecDetails.innerHTML = Lang.queryJS('settings.java.selectedJava', { version: details.semverStr, vendor: details.vendor })
|
settingsJavaExecDetails.innerHTML = `Selected: Java ${details.semverStr} (${details.vendor})`
|
||||||
} else {
|
} else {
|
||||||
settingsJavaExecDetails.innerHTML = Lang.queryJS('settings.java.invalidSelection')
|
settingsJavaExecDetails.innerHTML = 'Invalid Selection'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateJavaReqDesc(server) {
|
function populateJavaReqDesc(server) {
|
||||||
settingsJavaReqDesc.innerHTML = Lang.queryJS('settings.java.requiresJava', { major: server.effectiveJavaOptions.suggestedMajor })
|
settingsJavaReqDesc.innerHTML = `Requires Java ${server.effectiveJavaOptions.suggestedMajor} x64.`
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateJvmOptsLink(server) {
|
function populateJvmOptsLink(server) {
|
||||||
const major = server.effectiveJavaOptions.suggestedMajor
|
const major = server.effectiveJavaOptions.suggestedMajor
|
||||||
settingsJvmOptsLink.innerHTML = Lang.queryJS('settings.java.availableOptions', { major: major })
|
settingsJvmOptsLink.innerHTML = `Available Options for Java ${major} (HotSpot VM)`
|
||||||
if(major >= 12) {
|
if(major >= 12) {
|
||||||
settingsJvmOptsLink.href = `https://docs.oracle.com/en/java/javase/${major}/docs/specs/man/java.html#extra-options-for-java`
|
settingsJvmOptsLink.href = `https://docs.oracle.com/en/java/javase/${major}/docs/specs/man/java.html#extra-options-for-java`
|
||||||
}
|
}
|
||||||
@ -1430,11 +1433,11 @@ function isPrerelease(version){
|
|||||||
function populateVersionInformation(version, valueElement, titleElement, checkElement){
|
function populateVersionInformation(version, valueElement, titleElement, checkElement){
|
||||||
valueElement.innerHTML = version
|
valueElement.innerHTML = version
|
||||||
if(isPrerelease(version)){
|
if(isPrerelease(version)){
|
||||||
titleElement.innerHTML = Lang.queryJS('settings.about.preReleaseTitle')
|
titleElement.innerHTML = 'Pre-release'
|
||||||
titleElement.style.color = '#ff886d'
|
titleElement.style.color = '#ff886d'
|
||||||
checkElement.style.background = '#ff886d'
|
checkElement.style.background = '#ff886d'
|
||||||
} else {
|
} else {
|
||||||
titleElement.innerHTML = Lang.queryJS('settings.about.stableReleaseTitle')
|
titleElement.innerHTML = 'Stable Release'
|
||||||
titleElement.style.color = null
|
titleElement.style.color = null
|
||||||
checkElement.style.background = null
|
checkElement.style.background = null
|
||||||
}
|
}
|
||||||
@ -1473,7 +1476,7 @@ function populateReleaseNotes(){
|
|||||||
},
|
},
|
||||||
timeout: 2500
|
timeout: 2500
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
settingsAboutChangelogText.innerHTML = Lang.queryJS('settings.about.releaseNotesFailed')
|
settingsAboutChangelogText.innerHTML = 'Failed to load release notes.'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1521,27 +1524,27 @@ function settingsUpdateButtonStatus(text, disabled = false, handler = null){
|
|||||||
*/
|
*/
|
||||||
function populateSettingsUpdateInformation(data){
|
function populateSettingsUpdateInformation(data){
|
||||||
if(data != null){
|
if(data != null){
|
||||||
settingsUpdateTitle.innerHTML = isPrerelease(data.version) ? Lang.queryJS('settings.updates.newPreReleaseTitle') : Lang.queryJS('settings.updates.newReleaseTitle')
|
settingsUpdateTitle.innerHTML = `New ${isPrerelease(data.version) ? 'Pre-release' : 'Release'} Available`
|
||||||
settingsUpdateChangelogCont.style.display = null
|
settingsUpdateChangelogCont.style.display = null
|
||||||
settingsUpdateChangelogTitle.innerHTML = data.releaseName
|
settingsUpdateChangelogTitle.innerHTML = data.releaseName
|
||||||
settingsUpdateChangelogText.innerHTML = data.releaseNotes
|
settingsUpdateChangelogText.innerHTML = data.releaseNotes
|
||||||
populateVersionInformation(data.version, settingsUpdateVersionValue, settingsUpdateVersionTitle, settingsUpdateVersionCheck)
|
populateVersionInformation(data.version, settingsUpdateVersionValue, settingsUpdateVersionTitle, settingsUpdateVersionCheck)
|
||||||
|
|
||||||
if(process.platform === 'darwin'){
|
if(process.platform === 'darwin'){
|
||||||
settingsUpdateButtonStatus(Lang.queryJS('settings.updates.downloadButton'), false, () => {
|
settingsUpdateButtonStatus('Download from GitHub<span style="font-size: 10px;color: gray;text-shadow: none !important;">Close the launcher and run the dmg to update.</span>', false, () => {
|
||||||
shell.openExternal(data.darwindownload)
|
shell.openExternal(data.darwindownload)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
settingsUpdateButtonStatus(Lang.queryJS('settings.updates.downloadingButton'), true)
|
settingsUpdateButtonStatus('Downloading..', true)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
settingsUpdateTitle.innerHTML = Lang.queryJS('settings.updates.latestVersionTitle')
|
settingsUpdateTitle.innerHTML = 'You Are Running the Latest Version'
|
||||||
settingsUpdateChangelogCont.style.display = 'none'
|
settingsUpdateChangelogCont.style.display = 'none'
|
||||||
populateVersionInformation(remote.app.getVersion(), settingsUpdateVersionValue, settingsUpdateVersionTitle, settingsUpdateVersionCheck)
|
populateVersionInformation(remote.app.getVersion(), settingsUpdateVersionValue, settingsUpdateVersionTitle, settingsUpdateVersionCheck)
|
||||||
settingsUpdateButtonStatus(Lang.queryJS('settings.updates.checkForUpdatesButton'), false, () => {
|
settingsUpdateButtonStatus('Check for Updates', false, () => {
|
||||||
if(!isDev){
|
if(!isDev){
|
||||||
ipcRenderer.send('autoUpdateAction', 'checkForUpdate')
|
ipcRenderer.send('autoUpdateAction', 'checkForUpdate')
|
||||||
settingsUpdateButtonStatus(Lang.queryJS('settings.updates.checkingForUpdatesButton'), true)
|
settingsUpdateButtonStatus('Checking for Updates..', true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ const { Type } = require('helios-distribution-types')
|
|||||||
const AuthManager = require('./assets/js/authmanager')
|
const AuthManager = require('./assets/js/authmanager')
|
||||||
const ConfigManager = require('./assets/js/configmanager')
|
const ConfigManager = require('./assets/js/configmanager')
|
||||||
const { DistroAPI } = require('./assets/js/distromanager')
|
const { DistroAPI } = require('./assets/js/distromanager')
|
||||||
|
const Lang = require('./assets/js/langloader')
|
||||||
|
|
||||||
let rscShouldLoad = false
|
let rscShouldLoad = false
|
||||||
let fatalStartupError = false
|
let fatalStartupError = false
|
||||||
@ -114,9 +115,9 @@ function showFatalStartupError(){
|
|||||||
$('#loadingContainer').fadeOut(250, () => {
|
$('#loadingContainer').fadeOut(250, () => {
|
||||||
document.getElementById('overlayContainer').style.background = 'none'
|
document.getElementById('overlayContainer').style.background = 'none'
|
||||||
setOverlayContent(
|
setOverlayContent(
|
||||||
Lang.queryJS('uibinder.startup.fatalErrorTitle'),
|
'Fatal Error: Unable to Load Distribution Index',
|
||||||
Lang.queryJS('uibinder.startup.fatalErrorMessage'),
|
'A connection could not be established to our servers to download the distribution index. No local copies were available to load. <br><br>The distribution index is an essential file which provides the latest server information. The launcher is unable to start without it. Ensure you are connected to the internet and relaunch the application.',
|
||||||
Lang.queryJS('uibinder.startup.closeButton')
|
'Close'
|
||||||
)
|
)
|
||||||
setOverlayHandler(() => {
|
setOverlayHandler(() => {
|
||||||
const window = remote.getCurrentWindow()
|
const window = remote.getCurrentWindow()
|
||||||
@ -163,7 +164,7 @@ function syncModConfigurations(data){
|
|||||||
for(let mdl of mdls){
|
for(let mdl of mdls){
|
||||||
const type = mdl.rawModule.type
|
const type = mdl.rawModule.type
|
||||||
|
|
||||||
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader || type === Type.FabricMod){
|
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader){
|
||||||
if(!mdl.getRequired().value){
|
if(!mdl.getRequired().value){
|
||||||
const mdlID = mdl.getVersionlessMavenIdentifier()
|
const mdlID = mdl.getVersionlessMavenIdentifier()
|
||||||
if(modsOld[mdlID] == null){
|
if(modsOld[mdlID] == null){
|
||||||
@ -198,7 +199,7 @@ function syncModConfigurations(data){
|
|||||||
|
|
||||||
for(let mdl of mdls){
|
for(let mdl of mdls){
|
||||||
const type = mdl.rawModule.type
|
const type = mdl.rawModule.type
|
||||||
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader || type === Type.FabricMod){
|
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader){
|
||||||
if(!mdl.getRequired().value){
|
if(!mdl.getRequired().value){
|
||||||
mods[mdl.getVersionlessMavenIdentifier()] = scanOptionalSubModules(mdl.subModules, mdl)
|
mods[mdl.getVersionlessMavenIdentifier()] = scanOptionalSubModules(mdl.subModules, mdl)
|
||||||
} else {
|
} else {
|
||||||
@ -253,7 +254,7 @@ function scanOptionalSubModules(mdls, origin){
|
|||||||
for(let mdl of mdls){
|
for(let mdl of mdls){
|
||||||
const type = mdl.rawModule.type
|
const type = mdl.rawModule.type
|
||||||
// Optional types.
|
// Optional types.
|
||||||
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader || type === Type.FabricMod){
|
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader){
|
||||||
// It is optional.
|
// It is optional.
|
||||||
if(!mdl.getRequired().value){
|
if(!mdl.getRequired().value){
|
||||||
mods[mdl.getVersionlessMavenIdentifier()] = scanOptionalSubModules(mdl.subModules, mdl)
|
mods[mdl.getVersionlessMavenIdentifier()] = scanOptionalSubModules(mdl.subModules, mdl)
|
||||||
@ -332,12 +333,10 @@ async function validateSelectedAccount(){
|
|||||||
ConfigManager.save()
|
ConfigManager.save()
|
||||||
const accLen = Object.keys(ConfigManager.getAuthAccounts()).length
|
const accLen = Object.keys(ConfigManager.getAuthAccounts()).length
|
||||||
setOverlayContent(
|
setOverlayContent(
|
||||||
Lang.queryJS('uibinder.validateAccount.failedMessageTitle'),
|
'Failed to Refresh Login',
|
||||||
accLen > 0
|
`We were unable to refresh the login for <strong>${selectedAcc.displayName}</strong>. Please ${accLen > 0 ? 'select another account or ' : ''} login again.`,
|
||||||
? Lang.queryJS('uibinder.validateAccount.failedMessage', { 'account': selectedAcc.displayName })
|
'Login',
|
||||||
: Lang.queryJS('uibinder.validateAccount.failedMessageSelectAnotherAccount', { 'account': selectedAcc.displayName }),
|
'Select Another Account'
|
||||||
Lang.queryJS('uibinder.validateAccount.loginButton'),
|
|
||||||
Lang.queryJS('uibinder.validateAccount.selectAnotherAccountButton')
|
|
||||||
)
|
)
|
||||||
setOverlayHandler(() => {
|
setOverlayHandler(() => {
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ const {ipcRenderer, shell, webFrame} = require('electron')
|
|||||||
const remote = require('@electron/remote')
|
const remote = require('@electron/remote')
|
||||||
const isDev = require('./assets/js/isdev')
|
const isDev = require('./assets/js/isdev')
|
||||||
const { LoggerUtil } = require('helios-core')
|
const { LoggerUtil } = require('helios-core')
|
||||||
const Lang = require('./assets/js/langloader')
|
|
||||||
|
|
||||||
const loggerUICore = LoggerUtil.getLogger('UICore')
|
const loggerUICore = LoggerUtil.getLogger('UICore')
|
||||||
const loggerAutoUpdater = LoggerUtil.getLogger('AutoUpdater')
|
const loggerAutoUpdater = LoggerUtil.getLogger('AutoUpdater')
|
||||||
@ -43,7 +42,7 @@ if(!isDev){
|
|||||||
switch(arg){
|
switch(arg){
|
||||||
case 'checking-for-update':
|
case 'checking-for-update':
|
||||||
loggerAutoUpdater.info('Checking for update..')
|
loggerAutoUpdater.info('Checking for update..')
|
||||||
settingsUpdateButtonStatus(Lang.queryJS('uicore.autoUpdate.checkingForUpdateButton'), true)
|
settingsUpdateButtonStatus('Checking for Updates..', true)
|
||||||
break
|
break
|
||||||
case 'update-available':
|
case 'update-available':
|
||||||
loggerAutoUpdater.info('New update available', info.version)
|
loggerAutoUpdater.info('New update available', info.version)
|
||||||
@ -57,7 +56,7 @@ if(!isDev){
|
|||||||
break
|
break
|
||||||
case 'update-downloaded':
|
case 'update-downloaded':
|
||||||
loggerAutoUpdater.info('Update ' + info.version + ' ready to be installed.')
|
loggerAutoUpdater.info('Update ' + info.version + ' ready to be installed.')
|
||||||
settingsUpdateButtonStatus(Lang.queryJS('uicore.autoUpdate.installNowButton'), false, () => {
|
settingsUpdateButtonStatus('Install Now', false, () => {
|
||||||
if(!isDev){
|
if(!isDev){
|
||||||
ipcRenderer.send('autoUpdateAction', 'installUpdateNow')
|
ipcRenderer.send('autoUpdateAction', 'installUpdateNow')
|
||||||
}
|
}
|
||||||
@ -66,7 +65,7 @@ if(!isDev){
|
|||||||
break
|
break
|
||||||
case 'update-not-available':
|
case 'update-not-available':
|
||||||
loggerAutoUpdater.info('No new update found.')
|
loggerAutoUpdater.info('No new update found.')
|
||||||
settingsUpdateButtonStatus(Lang.queryJS('uicore.autoUpdate.checkForUpdatesButton'))
|
settingsUpdateButtonStatus('Check for Updates')
|
||||||
break
|
break
|
||||||
case 'ready':
|
case 'ready':
|
||||||
updateCheckListener = setInterval(() => {
|
updateCheckListener = setInterval(() => {
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
# Custom Language File for Launcher Customizer
|
|
||||||
|
|
||||||
[ejs.app]
|
|
||||||
title = "Helios Launcher"
|
|
||||||
|
|
||||||
[ejs.landing]
|
|
||||||
mediaGitHubURL = "https://github.com/dscalzi/HeliosLauncher"
|
|
||||||
mediaTwitterURL = "#"
|
|
||||||
mediaInstagramURL = "#"
|
|
||||||
mediaYouTubeURL = "#"
|
|
||||||
mediaDiscordURL = "https://discord.gg/zNWUXdt"
|
|
||||||
|
|
||||||
[ejs.settings]
|
|
||||||
sourceGithubLink = "https://github.com/dscalZi/HeliosLauncher"
|
|
||||||
supportLink = "https://github.com/dscalZi/HeliosLauncher/issues"
|
|
||||||
|
|
||||||
[ejs.welcome]
|
|
||||||
welcomeHeader = "WELCOME TO WESTEROSCRAFT"
|
|
||||||
welcomeDescription = "Our mission is to recreate the universe imagined by author George RR Martin in his fantasy series, A Song of Ice and Fire. Through the collaborative effort of thousands of community members, we have sought to create Westeros as accurately and precisely as possible within Minecraft. The world we are creating is yours to explore. Journey from Dorne to Castle Black, and if you aren’t afraid, beyond the Wall itself, but best not delay. As the words of House Stark ominously warn: Winter is Coming."
|
|
||||||
welcomeDescCTA = "You are just a few clicks away from Westeros."
|
|
49
app/assets/lang/en_US.json
Normal file
49
app/assets/lang/en_US.json
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"html": {
|
||||||
|
"avatarOverlay": "Edit"
|
||||||
|
},
|
||||||
|
"js": {
|
||||||
|
"login": {
|
||||||
|
"error": {
|
||||||
|
"invalidValue": "* Invalid Value",
|
||||||
|
"requiredValue": "* Required",
|
||||||
|
"userMigrated": {
|
||||||
|
"title": "Error During Login:<br>Invalid Credentials",
|
||||||
|
"desc": "You've attempted to login with a migrated account. Try again using the account email as the username."
|
||||||
|
},
|
||||||
|
"invalidCredentials": {
|
||||||
|
"title": "Error During Login:<br>Invalid Credentials",
|
||||||
|
"desc": "The email or password you've entered is incorrect. Please try again."
|
||||||
|
},
|
||||||
|
"rateLimit": {
|
||||||
|
"title": "Error During Login:<br>Too Many Attempts",
|
||||||
|
"desc": "There have been too many login attempts with this account recently. Please try again later."
|
||||||
|
},
|
||||||
|
"noInternet": {
|
||||||
|
"title": "Error During Login:<br>No Internet Connection",
|
||||||
|
"desc": "You must be connected to the internet in order to login. Please connect and try again."
|
||||||
|
},
|
||||||
|
"authDown": {
|
||||||
|
"title": "Error During Login:<br>Authentication Server Offline",
|
||||||
|
"desc": "Mojang's authentication server is currently offline or unreachable. Please wait a bit and try again. You can check the status of the server on <a href=\"https://help.mojang.com/\">Mojang's help portal</a>."
|
||||||
|
},
|
||||||
|
"notPaid": {
|
||||||
|
"title": "Error During Login:<br>Game Not Purchased",
|
||||||
|
"desc": "The account you are trying to login with has not purchased a copy of Minecraft.<br>You may purchase a copy on <a href=\"https://minecraft.net/\">Minecraft.net</a>"
|
||||||
|
},
|
||||||
|
"unknown": {
|
||||||
|
"title": "Error During Login:<br>Unknown Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"login": "LOGIN",
|
||||||
|
"loggingIn": "LOGGING IN",
|
||||||
|
"success": "SUCCESS",
|
||||||
|
"tryAgain": "Try Again"
|
||||||
|
},
|
||||||
|
"landing": {
|
||||||
|
"launch": {
|
||||||
|
"pleaseWait": "Please wait.."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
<div id="loginOptionsContainer" style="display: none;">
|
<div id="loginOptionsContainer" style="display: none;">
|
||||||
<div id="loginOptionsContent">
|
<div id="loginOptionsContent">
|
||||||
<div class="loginOptionsMainContent">
|
<div class="loginOptionsMainContent">
|
||||||
<h2><%- lang('loginOptions.loginOptionsTitle') %></h2>
|
<h2>Login Options</h2>
|
||||||
<div class="loginOptionActions">
|
<div class="loginOptionActions">
|
||||||
<div class="loginOptionButtonContainer">
|
<div class="loginOptionButtonContainer">
|
||||||
<button id="loginOptionMicrosoft" class="loginOptionButton">
|
<button id="loginOptionMicrosoft" class="loginOptionButton">
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<path fill="#05a6f0" d="M1 12h10v10H1z" />
|
<path fill="#05a6f0" d="M1 12h10v10H1z" />
|
||||||
<path fill="#ffba08" d="M12 12h10v10H12z" />
|
<path fill="#ffba08" d="M12 12h10v10H12z" />
|
||||||
</svg>
|
</svg>
|
||||||
<span><%- lang('loginOptions.loginWithMicrosoft') %></span>
|
<span>Login with Microsoft</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="loginOptionButtonContainer">
|
<div class="loginOptionButtonContainer">
|
||||||
@ -21,12 +21,12 @@
|
|||||||
<path d="M2.598.022h7.07L9.665 7c-.003 1.334-1.113 2.46-2.402 2.654H0V2.542C.134 1.2 1.3.195 2.598.022z" fill="#db2331" />
|
<path d="M2.598.022h7.07L9.665 7c-.003 1.334-1.113 2.46-2.402 2.654H0V2.542C.134 1.2 1.3.195 2.598.022z" fill="#db2331" />
|
||||||
<path d="M1.54 2.844c.314-.76 1.31-.46 1.954-.528.785-.083 1.503.272 2.1.758l.164-.9c.327.345.587.756.964 1.052.28.254.655-.342.86-.013.42.864.408 1.86.54 2.795l-.788-.373C6.9 4.17 5.126 3.052 3.656 3.685c-1.294.592-1.156 2.65.06 3.255 1.354.703 2.953.51 4.405.292-.07.42-.34.87-.834.816l-4.95.002c-.5.055-.886-.413-.838-.89l.04-4.315z" fill="#fff" />
|
<path d="M1.54 2.844c.314-.76 1.31-.46 1.954-.528.785-.083 1.503.272 2.1.758l.164-.9c.327.345.587.756.964 1.052.28.254.655-.342.86-.013.42.864.408 1.86.54 2.795l-.788-.373C6.9 4.17 5.126 3.052 3.656 3.685c-1.294.592-1.156 2.65.06 3.255 1.354.703 2.953.51 4.405.292-.07.42-.34.87-.834.816l-4.95.002c-.5.055-.886-.413-.838-.89l.04-4.315z" fill="#fff" />
|
||||||
</svg>
|
</svg>
|
||||||
<span><%- lang('loginOptions.loginWithMojang') %></span>
|
<span>Login with Mojang</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="loginOptionCancelContainer" style="display: none;">
|
<div id="loginOptionCancelContainer" style="display: none;">
|
||||||
<button id="loginOptionCancelButton"><%- lang('loginOptions.cancelButton') %></button>
|
<button id="loginOptionCancelButton">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
<div id="overlayContainer" style="display: none;">
|
<div id="overlayContainer" style="display: none;">
|
||||||
<div id="serverSelectContent" style="display: none;">
|
<div id="serverSelectContent" style="display: none;">
|
||||||
<span id="serverSelectHeader"><%- lang('overlay.serverSelectHeader') %></span>
|
<span id="serverSelectHeader">Available Servers</span>
|
||||||
<div id="serverSelectList">
|
<div id="serverSelectList">
|
||||||
<div id="serverSelectListScrollable">
|
<div id="serverSelectListScrollable">
|
||||||
<!-- Server listings populated here. -->
|
<!-- Server listings populated here. -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="serverSelectActions">
|
<div id="serverSelectActions">
|
||||||
<button id="serverSelectConfirm" class="overlayKeybindEnter" type="submit"><%- lang('overlay.serverSelectConfirm') %></button>
|
<button id="serverSelectConfirm" class="overlayKeybindEnter" type="submit">Select</button>
|
||||||
<div id="serverSelectCancelWrapper">
|
<div id="serverSelectCancelWrapper">
|
||||||
<button id="serverSelectCancel" class="overlayKeybindEsc"><%- lang('overlay.serverSelectCancel') %></button>
|
<button id="serverSelectCancel" class="overlayKeybindEsc">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="accountSelectContent" style="display: none;">
|
<div id="accountSelectContent" style="display: none;">
|
||||||
<span id="accountSelectHeader"><%- lang('overlay.accountSelectHeader') %></span>
|
<span id="accountSelectHeader">Select an Account</span>
|
||||||
<div id="accountSelectList">
|
<div id="accountSelectList">
|
||||||
<div id="accountSelectListScrollable">
|
<div id="accountSelectListScrollable">
|
||||||
<!-- Accounts populated here. -->
|
<!-- Accounts populated here. -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="accountSelectActions">
|
<div id="accountSelectActions">
|
||||||
<button id="accountSelectConfirm" class="overlayKeybindEnter" type="submit"><%- lang('overlay.accountSelectConfirm') %></button>
|
<button id="accountSelectConfirm" class="overlayKeybindEnter" type="submit">Select</button>
|
||||||
<div id="accountSelectCancelWrapper">
|
<div id="accountSelectCancelWrapper">
|
||||||
<button id="accountSelectCancel" class="overlayKeybindEsc"><%- lang('overlay.accountSelectCancel') %></button>
|
<button id="accountSelectCancel" class="overlayKeybindEsc">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div id="waitingContent">
|
<div id="waitingContent">
|
||||||
<div class="waitingSpinner"></div>
|
<div class="waitingSpinner"></div>
|
||||||
<div id="waitingTextContainer">
|
<div id="waitingTextContainer">
|
||||||
<h2><%- lang('waiting.waitingText') %></h2>
|
<h2>Waiting for Microsoft..</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -5,13 +5,13 @@
|
|||||||
</div>-->
|
</div>-->
|
||||||
<div id="welcomeContent">
|
<div id="welcomeContent">
|
||||||
<img id="welcomeImageSeal" src="assets/images/SealCircle.png"/>
|
<img id="welcomeImageSeal" src="assets/images/SealCircle.png"/>
|
||||||
<span id="welcomeHeader"><%- lang('welcome.welcomeHeader') %></span>
|
<span id="welcomeHeader">WELCOME TO WESTEROSCRAFT</span>
|
||||||
<span id="welcomeDescription"><%- lang('welcome.welcomeDescription') %></span>
|
<span id="welcomeDescription">Our mission is to recreate the universe imagined by author George RR Martin in his fantasy series, A Song of Ice and Fire. Through the collaborative effort of thousands of community members, we have sought to create Westeros as accurately and precisely as possible within Minecraft. The world we are creating is yours to explore. Journey from Dorne to Castle Black, and if you aren’t afraid, beyond the Wall itself, but best not delay. As the words of House Stark ominously warn: Winter is Coming.</span>
|
||||||
<br>
|
<br>
|
||||||
<span id="welcomeDescCTA"><%- lang('welcome.welcomeDescCTA') %></span>
|
<span id="welcomeDescCTA">You are just a few clicks away from Westeros.</span>
|
||||||
<button id="welcomeButton">
|
<button id="welcomeButton">
|
||||||
<div id="welcomeButtonContent">
|
<div id="welcomeButtonContent">
|
||||||
<%- lang('welcome.continueButton') %>
|
CONTINUE
|
||||||
<svg id="welcomeSVG" viewBox="0 0 24.87 13.97">
|
<svg id="welcomeSVG" viewBox="0 0 24.87 13.97">
|
||||||
<defs>
|
<defs>
|
||||||
<style>.arrowLine{fill:none;stroke:#FFF;stroke-width:2px;transition: 0.25s ease;}</style>
|
<style>.arrowLine{fill:none;stroke:#FFF;stroke-width:2px;transition: 0.25s ease;}</style>
|
||||||
|
@ -360,12 +360,10 @@ The resolved/provided paths are appended to a base path depending on the module'
|
|||||||
| Type | Path |
|
| Type | Path |
|
||||||
| ---- | ---- |
|
| ---- | ---- |
|
||||||
| `ForgeHosted` | ({`commonDirectory`}/libraries/{`path` OR resolved}) |
|
| `ForgeHosted` | ({`commonDirectory`}/libraries/{`path` OR resolved}) |
|
||||||
| `Fabric` | ({`commonDirectory`}/libraries/{`path` OR resolved}) |
|
|
||||||
| `LiteLoader` | ({`commonDirectory`}/libraries/{`path` OR resolved}) |
|
| `LiteLoader` | ({`commonDirectory`}/libraries/{`path` OR resolved}) |
|
||||||
| `Library` | ({`commonDirectory`}/libraries/{`path` OR resolved}) |
|
| `Library` | ({`commonDirectory`}/libraries/{`path` OR resolved}) |
|
||||||
| `ForgeMod` | ({`commonDirectory`}/modstore/{`path` OR resolved}) |
|
| `ForgeMod` | ({`commonDirectory`}/modstore/{`path` OR resolved}) |
|
||||||
| `LiteMod` | ({`commonDirectory`}/modstore/{`path` OR resolved}) |
|
| `LiteMod` | ({`commonDirectory`}/modstore/{`path` OR resolved}) |
|
||||||
| `FabricMod` | ({`commonDirectory`}/mods/fabric/{`path` OR resolved}) |
|
|
||||||
| `File` | ({`instanceDirectory`}/{`Server.id`}/{`path` OR resolved}) |
|
| `File` | ({`instanceDirectory`}/{`Server.id`}/{`path` OR resolved}) |
|
||||||
|
|
||||||
The `commonDirectory` and `instanceDirectory` values are stored in the launcher's config.json.
|
The `commonDirectory` and `instanceDirectory` values are stored in the launcher's config.json.
|
||||||
@ -410,7 +408,7 @@ If the module is enabled by default. Has no effect unless `Required.value` is fa
|
|||||||
|
|
||||||
### ForgeHosted
|
### ForgeHosted
|
||||||
|
|
||||||
The module type `ForgeHosted` represents forge itself. Currently, the launcher only supports modded servers, as vanilla servers can be connected to via the mojang launcher. The `Hosted` part is key, this means that the forge module must declare its required libraries as submodules.
|
The module type `ForgeHosted` represents forge itself. Currently, the launcher only supports forge servers, as vanilla servers can be connected to via the mojang launcher. The `Hosted` part is key, this means that the forge module must declare its required libraries as submodules.
|
||||||
|
|
||||||
Ex.
|
Ex.
|
||||||
|
|
||||||
@ -445,40 +443,6 @@ There were plans to add a `Forge` type, in which the required libraries would be
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Fabric
|
|
||||||
|
|
||||||
The module type `Fabric` represents the fabric mod loader. Currently, the launcher only supports modded servers, as vanilla servers can be connected to via the mojang launcher.
|
|
||||||
|
|
||||||
Ex.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "net.fabricmc:fabric-loader:0.15.0",
|
|
||||||
"name": "Fabric (fabric-loader)",
|
|
||||||
"type": "Fabric",
|
|
||||||
"artifact": {
|
|
||||||
"size": 1196222,
|
|
||||||
"MD5": "a43d5a142246801343b6cedef1c102c4",
|
|
||||||
"url": "http://localhost:8080/repo/lib/net/fabricmc/fabric-loader/0.15.0/fabric-loader-0.15.0.jar"
|
|
||||||
},
|
|
||||||
"subModules": [
|
|
||||||
{
|
|
||||||
"id": "1.20.1-fabric-0.15.0",
|
|
||||||
"name": "Fabric (version.json)",
|
|
||||||
"type": "VersionManifest",
|
|
||||||
"artifact": {
|
|
||||||
"size": 2847,
|
|
||||||
"MD5": "69a2bd43452325ba1bc882fa0904e054",
|
|
||||||
"url": "http://localhost:8080/repo/versions/1.20.1-fabric-0.15.0/1.20.1-fabric-0.15.0.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Fabric works similarly to Forge 1.13+.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### LiteLoader
|
### LiteLoader
|
||||||
|
|
||||||
The module type `LiteLoader` represents liteloader. It is handled as a library and added to the classpath at runtime. Special launch conditions are executed when liteloader is present and enabled. This module can be optional and toggled similarly to `ForgeMod` and `Litemod` modules.
|
The module type `LiteLoader` represents liteloader. It is handled as a library and added to the classpath at runtime. Special launch conditions are executed when liteloader is present and enabled. This module can be optional and toggled similarly to `ForgeMod` and `Litemod` modules.
|
||||||
|
14
index.js
14
index.js
@ -11,10 +11,6 @@ const path = require('path')
|
|||||||
const semver = require('semver')
|
const semver = require('semver')
|
||||||
const { pathToFileURL } = require('url')
|
const { pathToFileURL } = require('url')
|
||||||
const { AZURE_CLIENT_ID, MSFT_OPCODE, MSFT_REPLY_TYPE, MSFT_ERROR, SHELL_OPCODE } = require('./app/assets/js/ipcconstants')
|
const { AZURE_CLIENT_ID, MSFT_OPCODE, MSFT_REPLY_TYPE, MSFT_ERROR, SHELL_OPCODE } = require('./app/assets/js/ipcconstants')
|
||||||
const LangLoader = require('./app/assets/js/langloader')
|
|
||||||
|
|
||||||
// Setup Lang
|
|
||||||
LangLoader.setupLanguage()
|
|
||||||
|
|
||||||
// Setup auto updater.
|
// Setup auto updater.
|
||||||
function initAutoUpdater(event, data) {
|
function initAutoUpdater(event, data) {
|
||||||
@ -125,7 +121,7 @@ ipcMain.on(MSFT_OPCODE.OPEN_LOGIN, (ipcEvent, ...arguments_) => {
|
|||||||
msftAuthViewSuccess = arguments_[0]
|
msftAuthViewSuccess = arguments_[0]
|
||||||
msftAuthViewOnClose = arguments_[1]
|
msftAuthViewOnClose = arguments_[1]
|
||||||
msftAuthWindow = new BrowserWindow({
|
msftAuthWindow = new BrowserWindow({
|
||||||
title: LangLoader.queryJS('index.microsoftLoginTitle'),
|
title: 'Microsoft Login',
|
||||||
backgroundColor: '#222222',
|
backgroundColor: '#222222',
|
||||||
width: 520,
|
width: 520,
|
||||||
height: 600,
|
height: 600,
|
||||||
@ -178,7 +174,7 @@ ipcMain.on(MSFT_OPCODE.OPEN_LOGOUT, (ipcEvent, uuid, isLastAccount) => {
|
|||||||
msftLogoutSuccess = false
|
msftLogoutSuccess = false
|
||||||
msftLogoutSuccessSent = false
|
msftLogoutSuccessSent = false
|
||||||
msftLogoutWindow = new BrowserWindow({
|
msftLogoutWindow = new BrowserWindow({
|
||||||
title: LangLoader.queryJS('index.microsoftLogoutTitle'),
|
title: 'Microsoft Logout',
|
||||||
backgroundColor: '#222222',
|
backgroundColor: '#222222',
|
||||||
width: 520,
|
width: 520,
|
||||||
height: 600,
|
height: 600,
|
||||||
@ -240,11 +236,7 @@ function createWindow() {
|
|||||||
})
|
})
|
||||||
remoteMain.enable(win.webContents)
|
remoteMain.enable(win.webContents)
|
||||||
|
|
||||||
const data = {
|
ejse.data('bkid', Math.floor((Math.random() * fs.readdirSync(path.join(__dirname, 'app', 'assets', 'images', 'backgrounds')).length)))
|
||||||
bkid: Math.floor((Math.random() * fs.readdirSync(path.join(__dirname, 'app', 'assets', 'images', 'backgrounds')).length)),
|
|
||||||
lang: (str, placeHolders) => LangLoader.queryEJS(str, placeHolders)
|
|
||||||
}
|
|
||||||
Object.entries(data).forEach(([key, val]) => ejse.data(key, val))
|
|
||||||
|
|
||||||
win.loadURL(pathToFileURL(path.join(__dirname, 'app', 'app.ejs')).toString())
|
win.loadURL(pathToFileURL(path.join(__dirname, 'app', 'app.ejs')).toString())
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user