Compare commits
10 Commits
Author | SHA1 | Date |
---|---|---|
Daniel Scalzi | eb683f89ec | |
Daniel Scalzi | ae0e9e227d | |
Daniel Scalzi | dc15bbfde8 | |
Daniel Scalzi | 0d23f5c45b | |
Kamesuta | fc4823a01f | |
Daniel Scalzi | 95eebc18a7 | |
Daniel Scalzi | d03ff90f78 | |
Daniel Scalzi | 258cd0d421 | |
Daniel Scalzi | f65eb2f2d6 | |
jebibot | fb1cb7b415 |
|
@ -20,7 +20,7 @@ jobs:
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 20
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v4
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017-2022 Daniel D. Scalzi
|
Copyright (c) 2017-2024 Daniel D. Scalzi
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -84,7 +84,7 @@ This section details the setup of a basic developmentment environment.
|
||||||
|
|
||||||
**System Requirements**
|
**System Requirements**
|
||||||
|
|
||||||
* [Node.js][nodejs] v18
|
* [Node.js][nodejs] v20
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -12,12 +12,122 @@
|
||||||
const ConfigManager = require('./configmanager')
|
const ConfigManager = require('./configmanager')
|
||||||
const { LoggerUtil } = require('helios-core')
|
const { LoggerUtil } = require('helios-core')
|
||||||
const { RestResponseStatus } = require('helios-core/common')
|
const { RestResponseStatus } = require('helios-core/common')
|
||||||
const { MojangRestAPI, mojangErrorDisplayable, MojangErrorCode } = require('helios-core/mojang')
|
const { MojangRestAPI, MojangErrorCode } = require('helios-core/mojang')
|
||||||
const { MicrosoftAuth, microsoftErrorDisplayable, MicrosoftErrorCode } = require('helios-core/microsoft')
|
const { MicrosoftAuth, MicrosoftErrorCode } = require('helios-core/microsoft')
|
||||||
const { AZURE_CLIENT_ID } = require('./ipcconstants')
|
const { AZURE_CLIENT_ID } = require('./ipcconstants')
|
||||||
|
const Lang = require('./langloader')
|
||||||
|
|
||||||
const log = LoggerUtil.getLogger('AuthManager')
|
const log = LoggerUtil.getLogger('AuthManager')
|
||||||
|
|
||||||
|
// Error messages
|
||||||
|
|
||||||
|
function microsoftErrorDisplayable(errorCode) {
|
||||||
|
switch (errorCode) {
|
||||||
|
case MicrosoftErrorCode.NO_PROFILE:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.microsoft.error.noProfileTitle'),
|
||||||
|
desc: Lang.queryJS('auth.microsoft.error.noProfileDesc')
|
||||||
|
}
|
||||||
|
case MicrosoftErrorCode.NO_XBOX_ACCOUNT:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.microsoft.error.noXboxAccountTitle'),
|
||||||
|
desc: Lang.queryJS('auth.microsoft.error.noXboxAccountDesc')
|
||||||
|
}
|
||||||
|
case MicrosoftErrorCode.XBL_BANNED:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.microsoft.error.xblBannedTitle'),
|
||||||
|
desc: Lang.queryJS('auth.microsoft.error.xblBannedDesc')
|
||||||
|
}
|
||||||
|
case MicrosoftErrorCode.UNDER_18:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.microsoft.error.under18Title'),
|
||||||
|
desc: Lang.queryJS('auth.microsoft.error.under18Desc')
|
||||||
|
}
|
||||||
|
case MicrosoftErrorCode.UNKNOWN:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.microsoft.error.unknownTitle'),
|
||||||
|
desc: Lang.queryJS('auth.microsoft.error.unknownDesc')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mojangErrorDisplayable(errorCode) {
|
||||||
|
switch(errorCode) {
|
||||||
|
case MojangErrorCode.ERROR_METHOD_NOT_ALLOWED:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.methodNotAllowedTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.methodNotAllowedDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.ERROR_NOT_FOUND:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.notFoundTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.notFoundDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.ERROR_USER_MIGRATED:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.accountMigratedTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.accountMigratedDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.ERROR_INVALID_CREDENTIALS:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.invalidCredentialsTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.invalidCredentialsDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.ERROR_RATELIMIT:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.tooManyAttemptsTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.tooManyAttemptsDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.ERROR_INVALID_TOKEN:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.invalidTokenTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.invalidTokenDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.ERROR_ACCESS_TOKEN_HAS_PROFILE:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.tokenHasProfileTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.tokenHasProfileDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.ERROR_CREDENTIALS_MISSING:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.credentialsMissingTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.credentialsMissingDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.ERROR_INVALID_SALT_VERSION:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.invalidSaltVersionTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.invalidSaltVersionDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.ERROR_UNSUPPORTED_MEDIA_TYPE:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.unsupportedMediaTypeTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.unsupportedMediaTypeDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.ERROR_GONE:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.accountGoneTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.accountGoneDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.ERROR_UNREACHABLE:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.unreachableTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.unreachableDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.ERROR_NOT_PAID:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.gameNotPurchasedTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.gameNotPurchasedDesc')
|
||||||
|
}
|
||||||
|
case MojangErrorCode.UNKNOWN:
|
||||||
|
return {
|
||||||
|
title: Lang.queryJS('auth.mojang.error.unknownErrorTitle'),
|
||||||
|
desc: Lang.queryJS('auth.mojang.error.unknownErrorDesc')
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown error code: ${errorCode}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,14 +12,23 @@ 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, versionData, forgeData, authUser, launcherVersion){
|
constructor(distroServer, vanillaManifest, modManifest, 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.versionData = versionData
|
this.vanillaManifest = vanillaManifest
|
||||||
this.forgeData = forgeData
|
this.modManifest = modManifest
|
||||||
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+
|
||||||
|
@ -28,6 +37,7 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,9 +50,12 @@ 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){
|
||||||
|
@ -166,7 +179,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){
|
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader || type === Type.FabricMod){
|
||||||
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)){
|
||||||
|
@ -178,7 +191,7 @@ class ProcessBuilder {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(type === Type.ForgeMod){
|
if(type === Type.ForgeMod || type === Type.FabricMod){
|
||||||
fMods.push(mdl)
|
fMods.push(mdl)
|
||||||
} else {
|
} else {
|
||||||
lMods.push(mdl)
|
lMods.push(mdl)
|
||||||
|
@ -194,7 +207,7 @@ class ProcessBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
_lteMinorVersion(version) {
|
_lteMinorVersion(version) {
|
||||||
return Number(this.forgeData.id.split('-')[0].split('.')[1]) <= Number(version)
|
return Number(this.modManifest.id.split('-')[0].split('.')[1]) <= Number(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -206,7 +219,7 @@ class ProcessBuilder {
|
||||||
if(this._lteMinorVersion(9)) {
|
if(this._lteMinorVersion(9)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const ver = this.forgeData.id.split('-')[2]
|
const ver = this.modManifest.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++){
|
||||||
|
@ -282,18 +295,21 @@ class ProcessBuilder {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the mod argument list for forge 1.13
|
* Construct the mod argument list for forge 1.13 and Fabric
|
||||||
*
|
*
|
||||||
* @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 mod.getExtensionlessMavenIdentifier()
|
return this.usingFabricLoader ? mod.getPath() : 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 [
|
return this.usingFabricLoader ? [
|
||||||
|
'--fabric.addMods',
|
||||||
|
`@${this.forgeModListFile}`
|
||||||
|
] : [
|
||||||
'--fml.mavenRoots',
|
'--fml.mavenRoots',
|
||||||
path.join('..', '..', 'common', 'modstore'),
|
path.join('..', '..', 'common', 'modstore'),
|
||||||
'--fml.modLists',
|
'--fml.modLists',
|
||||||
|
@ -361,7 +377,7 @@ class ProcessBuilder {
|
||||||
args.push('-Djava.library.path=' + tempNativePath)
|
args.push('-Djava.library.path=' + tempNativePath)
|
||||||
|
|
||||||
// Main Java Class
|
// Main Java Class
|
||||||
args.push(this.forgeData.mainClass)
|
args.push(this.modManifest.mainClass)
|
||||||
|
|
||||||
// Forge Arguments
|
// Forge Arguments
|
||||||
args = args.concat(this._resolveForgeArgs())
|
args = args.concat(this._resolveForgeArgs())
|
||||||
|
@ -384,17 +400,17 @@ class ProcessBuilder {
|
||||||
const argDiscovery = /\${*(.*)}/
|
const argDiscovery = /\${*(.*)}/
|
||||||
|
|
||||||
// JVM Arguments First
|
// JVM Arguments First
|
||||||
let args = this.versionData.arguments.jvm
|
let args = this.vanillaManifest.arguments.jvm
|
||||||
|
|
||||||
// Debug securejarhandler
|
// Debug securejarhandler
|
||||||
// args.push('-Dbsl.debug=true')
|
// args.push('-Dbsl.debug=true')
|
||||||
|
|
||||||
if(this.forgeData.arguments.jvm != null) {
|
if(this.modManifest.arguments.jvm != null) {
|
||||||
for(const argStr of this.forgeData.arguments.jvm) {
|
for(const argStr of this.modManifest.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.forgeData.id)
|
.replaceAll('${version_name}', this.modManifest.id)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -411,10 +427,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.forgeData.mainClass)
|
args.push(this.modManifest.mainClass)
|
||||||
|
|
||||||
// Vanilla Arguments
|
// Vanilla Arguments
|
||||||
args = args.concat(this.versionData.arguments.game)
|
args = args.concat(this.vanillaManifest.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){
|
||||||
|
@ -471,7 +487,7 @@ class ProcessBuilder {
|
||||||
val = this.authUser.displayName.trim()
|
val = this.authUser.displayName.trim()
|
||||||
break
|
break
|
||||||
case 'version_name':
|
case 'version_name':
|
||||||
//val = versionData.id
|
//val = vanillaManifest.id
|
||||||
val = this.server.rawServer.id
|
val = this.server.rawServer.id
|
||||||
break
|
break
|
||||||
case 'game_directory':
|
case 'game_directory':
|
||||||
|
@ -481,7 +497,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.versionData.assets
|
val = this.vanillaManifest.assets
|
||||||
break
|
break
|
||||||
case 'auth_uuid':
|
case 'auth_uuid':
|
||||||
val = this.authUser.uuid.trim()
|
val = this.authUser.uuid.trim()
|
||||||
|
@ -493,7 +509,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.versionData.type
|
val = this.vanillaManifest.type
|
||||||
break
|
break
|
||||||
case 'resolution_width':
|
case 'resolution_width':
|
||||||
val = ConfigManager.getGameWidth()
|
val = ConfigManager.getGameWidth()
|
||||||
|
@ -522,25 +538,11 @@ class ProcessBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Autoconnect
|
// Autoconnect
|
||||||
let isAutoconnectBroken
|
this._processAutoConnectArg(args)
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Forge Specific Arguments
|
// Forge Specific Arguments
|
||||||
args = args.concat(this.forgeData.arguments.game)
|
args = args.concat(this.modManifest.arguments.game)
|
||||||
|
|
||||||
// Filter null values
|
// Filter null values
|
||||||
args = args.filter(arg => {
|
args = args.filter(arg => {
|
||||||
|
@ -556,7 +558,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.forgeData.minecraftArguments.split(' ')
|
const mcArgs = this.modManifest.minecraftArguments.split(' ')
|
||||||
const argDiscovery = /\${*(.*)}/
|
const argDiscovery = /\${*(.*)}/
|
||||||
|
|
||||||
// Replace the declared variables with their proper values.
|
// Replace the declared variables with their proper values.
|
||||||
|
@ -569,7 +571,7 @@ class ProcessBuilder {
|
||||||
val = this.authUser.displayName.trim()
|
val = this.authUser.displayName.trim()
|
||||||
break
|
break
|
||||||
case 'version_name':
|
case 'version_name':
|
||||||
//val = versionData.id
|
//val = vanillaManifest.id
|
||||||
val = this.server.rawServer.id
|
val = this.server.rawServer.id
|
||||||
break
|
break
|
||||||
case 'game_directory':
|
case 'game_directory':
|
||||||
|
@ -579,7 +581,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.versionData.assets
|
val = this.vanillaManifest.assets
|
||||||
break
|
break
|
||||||
case 'auth_uuid':
|
case 'auth_uuid':
|
||||||
val = this.authUser.uuid.trim()
|
val = this.authUser.uuid.trim()
|
||||||
|
@ -594,7 +596,7 @@ class ProcessBuilder {
|
||||||
val = '{}'
|
val = '{}'
|
||||||
break
|
break
|
||||||
case 'version_type':
|
case 'version_type':
|
||||||
val = this.versionData.type
|
val = this.vanillaManifest.type
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if(val != null){
|
if(val != null){
|
||||||
|
@ -669,10 +671,10 @@ class ProcessBuilder {
|
||||||
classpathArg(mods, tempNativePath){
|
classpathArg(mods, tempNativePath){
|
||||||
let cpArgs = []
|
let cpArgs = []
|
||||||
|
|
||||||
if(!mcVersionAtLeast('1.17', this.server.rawServer.minecraftVersion)) {
|
if(!mcVersionAtLeast('1.17', this.server.rawServer.minecraftVersion) || this.usingFabricLoader) {
|
||||||
// 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.versionData.id
|
const version = this.vanillaManifest.id
|
||||||
cpArgs.push(path.join(this.commonDir, 'versions', version, version + '.jar'))
|
cpArgs.push(path.join(this.commonDir, 'versions', version, version + '.jar'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,7 +713,7 @@ class ProcessBuilder {
|
||||||
const nativesRegex = /.+:natives-([^-]+)(?:-(.+))?/
|
const nativesRegex = /.+:natives-([^-]+)(?:-(.+))?/
|
||||||
const libs = {}
|
const libs = {}
|
||||||
|
|
||||||
const libArr = this.versionData.libraries
|
const libArr = this.vanillaManifest.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]
|
||||||
|
@ -830,10 +832,10 @@ class ProcessBuilder {
|
||||||
const mdls = this.server.modules
|
const mdls = this.server.modules
|
||||||
let libs = {}
|
let libs = {}
|
||||||
|
|
||||||
// Locate Forge/Libraries
|
// Locate Forge/Fabric/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.Library){
|
if(type === Type.ForgeHosted || type === Type.Fabric || 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)
|
||||||
|
@ -887,24 +889,6 @@ 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
|
|
@ -442,7 +442,7 @@ let hasRPC = false
|
||||||
// Joined server regex
|
// Joined server regex
|
||||||
// Change this if your server uses something different.
|
// Change this if your server uses something different.
|
||||||
const GAME_JOINED_REGEX = /\[.+\]: Sound engine started/
|
const GAME_JOINED_REGEX = /\[.+\]: Sound engine started/
|
||||||
const GAME_LAUNCH_REGEX = /^\[.+\]: (?:MinecraftForge .+ Initialized|ModLauncher .+ starting: .+)$/
|
const GAME_LAUNCH_REGEX = /^\[.+\]: (?:MinecraftForge .+ Initialized|ModLauncher .+ starting: .+|Loading Minecraft .+ with Fabric Loader .+)$/
|
||||||
const MIN_LINGER = 5000
|
const MIN_LINGER = 5000
|
||||||
|
|
||||||
async function dlAsync(login = true) {
|
async function dlAsync(login = true) {
|
||||||
|
@ -548,13 +548,13 @@ async function dlAsync(login = true) {
|
||||||
serv.rawServer.id
|
serv.rawServer.id
|
||||||
)
|
)
|
||||||
|
|
||||||
const forgeData = await distributionIndexProcessor.loadForgeVersionJson(serv)
|
const modLoaderData = await distributionIndexProcessor.loadModLoaderVersionJson(serv)
|
||||||
const versionData = await mojangIndexProcessor.getVersionJson()
|
const versionData = await mojangIndexProcessor.getVersionJson()
|
||||||
|
|
||||||
if(login) {
|
if(login) {
|
||||||
const authUser = ConfigManager.getSelectedAccount()
|
const authUser = ConfigManager.getSelectedAccount()
|
||||||
loggerLaunchSuite.info(`Sending selected account (${authUser.displayName}) to ProcessBuilder.`)
|
loggerLaunchSuite.info(`Sending selected account (${authUser.displayName}) to ProcessBuilder.`)
|
||||||
let pb = new ProcessBuilder(serv, versionData, forgeData, authUser, remote.app.getVersion())
|
let pb = new ProcessBuilder(serv, versionData, modLoaderData, authUser, remote.app.getVersion())
|
||||||
setLaunchDetails(Lang.queryJS('landing.dlAsync.launchingGame'))
|
setLaunchDetails(Lang.queryJS('landing.dlAsync.launchingGame'))
|
||||||
|
|
||||||
// const SERVER_JOINED_REGEX = /\[.+\]: \[CHAT\] [a-zA-Z0-9_]{1,16} joined the game/
|
// const SERVER_JOINED_REGEX = /\[.+\]: \[CHAT\] [a-zA-Z0-9_]{1,16} joined the game/
|
||||||
|
|
|
@ -736,7 +736,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){
|
if(mdl.rawModule.type === Type.ForgeMod || mdl.rawModule.type === Type.LiteMod || mdl.rawModule.type === Type.LiteLoader || mdl.rawModule.type === Type.FabricMod){
|
||||||
|
|
||||||
if(mdl.getRequired().value){
|
if(mdl.getRequired().value){
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,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){
|
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader || type === Type.FabricMod){
|
||||||
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 +198,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){
|
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader || type === Type.FabricMod){
|
||||||
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 +253,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){
|
if(type === Type.ForgeMod || type === Type.LiteMod || type === Type.LiteLoader || type === Type.FabricMod){
|
||||||
// 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)
|
||||||
|
|
|
@ -279,6 +279,11 @@ latestVersionTitle = "You Are Running the Latest Version"
|
||||||
checkForUpdatesButton = "Check for Updates"
|
checkForUpdatesButton = "Check for Updates"
|
||||||
checkingForUpdatesButton = "Checking for Updates.."
|
checkingForUpdatesButton = "Checking for Updates.."
|
||||||
|
|
||||||
|
[js.settings.msftLogin]
|
||||||
|
errorTitle = "Microsoft Login Failed"
|
||||||
|
errorMessage = "We were unable to authenticate your Microsoft account. Please try again."
|
||||||
|
okButton = "OK"
|
||||||
|
|
||||||
[js.uibinder.startup]
|
[js.uibinder.startup]
|
||||||
fatalErrorTitle = "Fatal Error: Unable to Load Distribution Index"
|
fatalErrorTitle = "Fatal Error: Unable to Load Distribution Index"
|
||||||
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."
|
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."
|
||||||
|
@ -295,3 +300,45 @@ selectAnotherAccountButton = "Select Another Account"
|
||||||
checkingForUpdateButton = "Checking for Updates..."
|
checkingForUpdateButton = "Checking for Updates..."
|
||||||
installNowButton = "Install Now"
|
installNowButton = "Install Now"
|
||||||
checkForUpdatesButton = "Check for Updates"
|
checkForUpdatesButton = "Check for Updates"
|
||||||
|
|
||||||
|
[js.auth.microsoft.error]
|
||||||
|
noProfileTitle = "Error During Login:<br>Profile Not Set Up"
|
||||||
|
noProfileDesc = "Your Microsoft account does not yet have a Minecraft profile set up. If you have recently purchased the game or redeemed it through Xbox Game Pass, you have to set up your profile on <a href=\"https://minecraft.net/\">Minecraft.net</a>.<br><br>If you have not yet purchased the game, you can also do that on <a href=\"https://minecraft.net/\">Minecraft.net</a>."
|
||||||
|
noXboxAccountTitle = "Error During Login:<br>No Xbox Account"
|
||||||
|
noXboxAccountDesc = "Your Microsoft account has no Xbox account associated with it."
|
||||||
|
xblBannedTitle = "Error During Login:<br>Xbox Live Unavailable"
|
||||||
|
xblBannedDesc = "Your Microsoft account is from a country where Xbox Live is not available or banned."
|
||||||
|
under18Title = "Error During Login:<br>Parental Approval Required"
|
||||||
|
under18Desc = "Accounts for users under the age of 18 must be added to a Family by an adult."
|
||||||
|
unknownTitle = "Unknown Error During Login"
|
||||||
|
unknownDesc = "An unknown error has occurred. Please see the console for details."
|
||||||
|
|
||||||
|
[js.auth.mojang.error]
|
||||||
|
methodNotAllowedTitle = "Internal Error:<br>Method Not Allowed"
|
||||||
|
methodNotAllowedDesc = "Method not allowed. Please report this error."
|
||||||
|
notFoundTitle = "Internal Error:<br>Not Found"
|
||||||
|
notFoundDesc = "The authentication endpoint was not found. Please report this issue."
|
||||||
|
accountMigratedTitle = "Error During Login:<br>Account Migrated"
|
||||||
|
accountMigratedDesc = "You've attempted to login with a migrated account. Try again using the account email as the username."
|
||||||
|
invalidCredentialsTitle = "Error During Login:<br>Invalid Credentials"
|
||||||
|
invalidCredentialsDesc = "The email or password you've entered is incorrect. Please try again."
|
||||||
|
tooManyAttemptsTitle = "Error During Login:<br>Too Many Attempts"
|
||||||
|
tooManyAttemptsDesc = "There have been too many login attempts with this account recently. Please try again later."
|
||||||
|
invalidTokenTitle = "Error During Login:<br>Invalid Token"
|
||||||
|
invalidTokenDesc = "The provided access token is invalid."
|
||||||
|
tokenHasProfileTitle = "Error During Login:<br>Token Has Profile"
|
||||||
|
tokenHasProfileDesc = "Access token already has a profile assigned. Selecting profiles is not implemented yet."
|
||||||
|
credentialsMissingTitle = "Error During Login:<br>Credentials Missing"
|
||||||
|
credentialsMissingDesc = "Username/password was not submitted or password is less than 3 characters."
|
||||||
|
invalidSaltVersionTitle = "Error During Login:<br>Invalid Salt Version"
|
||||||
|
invalidSaltVersionDesc = "Invalid salt version."
|
||||||
|
unsupportedMediaTypeTitle = "Internal Error:<br>Unsupported Media Type"
|
||||||
|
unsupportedMediaTypeDesc = "Unsupported media type. Please report this error."
|
||||||
|
accountGoneTitle = "Error During Login:<br>Account Migrated"
|
||||||
|
accountGoneDesc = "Account has been migrated to a Microsoft account. Please log in with Microsoft."
|
||||||
|
unreachableTitle = "Error During Login:<br>Unreachable"
|
||||||
|
unreachableDesc = "Unable to reach the authentication servers. Ensure that they are online and you are connected to the internet."
|
||||||
|
gameNotPurchasedTitle = "Error During Login:<br>Game Not Purchased"
|
||||||
|
gameNotPurchasedDesc = "The account you are trying to login with has not purchased a copy of Minecraft. You may purchase a copy on <a href=\"https://minecraft.net/\">Minecraft.net</a>"
|
||||||
|
unknownErrorTitle = "Unknown Error During Login"
|
||||||
|
unknownErrorDesc = "An unknown error has occurred. Please see the console for details."
|
||||||
|
|
|
@ -360,10 +360,12 @@ 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.
|
||||||
|
@ -408,7 +410,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 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.
|
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.
|
||||||
|
|
||||||
Ex.
|
Ex.
|
||||||
|
|
||||||
|
@ -443,6 +445,40 @@ 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.
|
||||||
|
|
|
@ -2,7 +2,7 @@ appId: 'helioslauncher'
|
||||||
productName: 'Helios Launcher'
|
productName: 'Helios Launcher'
|
||||||
artifactName: '${productName}-setup-${version}.${ext}'
|
artifactName: '${productName}-setup-${version}.${ext}'
|
||||||
|
|
||||||
copyright: 'Copyright © 2018-2022 Daniel Scalzi'
|
copyright: 'Copyright © 2018-2024 Daniel Scalzi'
|
||||||
|
|
||||||
asar: true
|
asar: true
|
||||||
compression: 'maximum'
|
compression: 'maximum'
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "helioslauncher",
|
"name": "helioslauncher",
|
||||||
"version": "2.0.6",
|
"version": "2.2.1",
|
||||||
"productName": "Helios Launcher",
|
"productName": "Helios Launcher",
|
||||||
"description": "Modded Minecraft Launcher",
|
"description": "Modded Minecraft Launcher",
|
||||||
"author": "Daniel Scalzi (https://github.com/dscalzi/)",
|
"author": "Daniel Scalzi (https://github.com/dscalzi/)",
|
||||||
|
@ -20,29 +20,29 @@
|
||||||
"lint": "eslint --config .eslintrc.json ."
|
"lint": "eslint --config .eslintrc.json ."
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "18.x.x"
|
"node": "20.x.x"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron/remote": "^2.1.0",
|
"@electron/remote": "^2.1.2",
|
||||||
"adm-zip": "^0.5.9",
|
"adm-zip": "^0.5.12",
|
||||||
"discord-rpc-patch": "^4.0.1",
|
"discord-rpc-patch": "^4.0.1",
|
||||||
"ejs": "^3.1.9",
|
"ejs": "^3.1.10",
|
||||||
"ejs-electron": "^2.1.1",
|
"ejs-electron": "^3.0.0",
|
||||||
"electron-updater": "^6.1.7",
|
"electron-updater": "^6.1.8",
|
||||||
"fs-extra": "^11.1.1",
|
"fs-extra": "^11.1.1",
|
||||||
"github-syntax-dark": "^0.5.0",
|
"github-syntax-dark": "^0.5.0",
|
||||||
"got": "^11.8.5",
|
"got": "^11.8.5",
|
||||||
"helios-core": "~2.0.6",
|
"helios-core": "~2.2.1",
|
||||||
"helios-distribution-types": "^1.2.0",
|
"helios-distribution-types": "^1.3.0",
|
||||||
"jquery": "^3.7.1",
|
"jquery": "^3.7.1",
|
||||||
"lodash.merge": "^4.6.2",
|
"lodash.merge": "^4.6.2",
|
||||||
"semver": "^7.5.4",
|
"semver": "^7.6.0",
|
||||||
"toml": "^3.0.0"
|
"toml": "^3.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"electron": "^27.1.2",
|
"electron": "^30.0.1",
|
||||||
"electron-builder": "^24.9.1",
|
"electron-builder": "^24.13.3",
|
||||||
"eslint": "^8.54.0"
|
"eslint": "^8.57.0"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
Loading…
Reference in New Issue