Skip to content

Commit de3a5b4

Browse files
committed
Release
1 parent fc8ed14 commit de3a5b4

15 files changed

+1527
-1433
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_modules
22
.cache
33
dist
4+
build

package-lock.json

+1,366-1,378
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+8-8
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@
3535
},
3636
"homepage": "https://github.com/Apisium/PureLauncherOfficialPlugins#readme",
3737
"dependencies": {
38-
"@xmcl/task": "^2.1.2",
39-
"@xmcl/text-component": "^2.1.0",
38+
"@xmcl/task": "^2.1.4",
39+
"@xmcl/text-component": "^2.1.1",
4040
"cloudscraper": "^4.6.0",
41-
"commander": "^4.1.1",
41+
"commander": "^5.0.0",
4242
"crc": "^3.8.0",
4343
"crc32-stream": "^3.0.1",
4444
"filenamify": "^4.1.0",
@@ -62,16 +62,16 @@
6262
"@babel/core": "^7.8.7",
6363
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
6464
"@types/fs-extra": "^8.1.0",
65-
"@types/node": "^13.9.0",
65+
"@types/node": "^13.9.1",
6666
"@types/react": "^16.9.23",
6767
"@types/react-router-dom": "^5.1.3",
6868
"@typescript-eslint/eslint-plugin": "^2.23.0",
6969
"@typescript-eslint/parser": "^2.23.0",
70-
"@xmcl/core": "^2.0.4",
71-
"@xmcl/installer": "^2.4.0",
72-
"@xmcl/unzip": "^1.1.1",
70+
"@xmcl/core": "^2.0.7",
71+
"@xmcl/installer": "^2.6.0",
72+
"@xmcl/unzip": "^1.1.3",
7373
"babel-plugin-module-resolver": "^4.0.0",
74-
"electron": "^8.1.0",
74+
"electron": "^8.1.1",
7575
"eslint": "^6.8.0",
7676
"eslint-config-standard": "^14.1.0",
7777
"eslint-plugin-import": "^2.20.1",

packages/AuthlibInjector/AuthlibInjectorAuthenticator.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ fs.ensureDirSync(ROOT_PATH)
1010

1111
export interface AuthlibInjectorProfile extends Authenticator.Profile {
1212
url: string
13-
serverName?: string
13+
manifest?: { meta?: { serverName?: string } }
1414
displayUrl: string
1515
}
1616

@@ -46,8 +46,8 @@ const logo = require('./logo.png')
4646
export const AUTHLIB_INJECTOR = 'AuthlibInjector'
4747
@registerAuthenticator({
4848
name: AUTHLIB_INJECTOR,
49-
title: (_: any, p: AuthlibInjectorProfile) => 'Authlib Injector' + (p ? p.serverName
50-
? ` (${p.serverName} - ${p.displayUrl})` : ` (${p.displayUrl})` : ''),
49+
title: (_: any, p: AuthlibInjectorProfile) => 'Authlib Injector' + (p ? p?.manifest?.meta?.serverName
50+
? ` (${p.manifest.meta.serverName} - ${p.displayUrl})` : ` (${p.displayUrl})` : ''),
5151
logo: join(__dirname, logo),
5252
fields: [
5353
{
@@ -108,7 +108,7 @@ export default class AuthlibInjectorAuthenticator extends Auth {
108108
accessToken: json.accessToken,
109109
username: p.name,
110110
displayUrl: options.url,
111-
serverName: (await getJson(url).catch(console.error))?.meta?.serverName,
111+
manifest: await getJson(url).catch(console.error),
112112
skinUrl: await this.getSkin(url, p.id, p.name)
113113
}
114114
await fs.writeJson(DATABASE_PATH, this.db)

packages/AuthlibInjector/index.ts

+35-12
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
11
/* eslint-disable object-curly-newline, @typescript-eslint/explicit-function-return-type */
22
import AuthlibInjectorAuthenticator, { AUTHLIB_INJECTOR, AuthlibInjectorProfile } from './AuthlibInjectorAuthenticator'
33
import { join } from 'path'
4-
import { version } from './package.json'
54
import { LaunchOption } from '@xmcl/core'
6-
import { Plugin, plugin, event, pluginMaster, profilesStore, fs, constants,
7-
download, getJson, $ as $0, openLoginDialog } from '@plugin'
5+
import { id, version, author } from './package.json'
6+
import { Plugin, plugin, event, pluginMaster, profilesStore, fs, constants, types,
7+
download, getJson, $ as $0, openLoginDialog, openConfirmDialog } from '@plugin'
88
import $ from './langs'
99

1010
const JAR_PATH = join(constants.APP_PATH, 'authlib-injector/authlib-injector.jar')
1111
const JSON_URL = 'https://bmclapi2.bangbang93.com/mirrors/authlib-injector/artifact/latest.json'
1212

13+
type YggdrasilVersion = types.ResourceVersion & { yggdrasilUrl?: string }
14+
1315
@plugin({
16+
id,
17+
author,
1418
version,
15-
author: 'Shirasawa',
1619
title: () => 'Authlib-Injector',
17-
description: () => $.description,
18-
id: '@PureLauncher/multi-instances'
20+
description: () => $.description
1921
})
2022
export default class AuthlibInjector extends Plugin {
23+
private instance = new AuthlibInjectorAuthenticator()
2124
constructor () {
2225
super()
23-
pluginMaster.registerAuthenticator(AUTHLIB_INJECTOR, this, new AuthlibInjectorAuthenticator())
26+
pluginMaster.registerAuthenticator(AUTHLIB_INJECTOR, this, this.instance)
2427
}
2528

2629
@event()
@@ -47,12 +50,25 @@ export default class AuthlibInjector extends Plugin {
4750
}
4851

4952
@event()
50-
public preLaunch (_: string, option: LaunchOption) {
51-
const profile = profilesStore.getCurrentProfile()
53+
public async launchPostUpdate (_: string, profile: AuthlibInjectorProfile, json?: YggdrasilVersion) {
54+
if (!json?.yggdrasilUrl) return
55+
if (profile.type === AUTHLIB_INJECTOR && profile.url === json.yggdrasilUrl) return
56+
if (this.instance.getAllProfiles().some(it => it.url === json.yggdrasilUrl)) {
57+
openConfirmDialog({ text: $.notSelectedProfile })
58+
} else if (await openConfirmDialog({ text: $.noExistsProfile, cancelButton: true })) {
59+
openLoginDialog(AUTHLIB_INJECTOR, { url: json.yggdrasilUrl })
60+
}
61+
throw new Error($.incorrectAccount)
62+
}
63+
64+
@event()
65+
public preLaunch (_: string, option: LaunchOption, profile: AuthlibInjectorProfile) {
5266
if (profile?.type !== AUTHLIB_INJECTOR) return
53-
const server = (profile as AuthlibInjectorProfile).url
54-
// option.extraJVMArgs.push('-Dauthlibinjector.side=client', '-Dauthlibinjector.yggdrasil.prefetched=' + btoa(server))
55-
option.yggdrasilAgent = { jar: JAR_PATH, server }
67+
option.yggdrasilAgent = {
68+
jar: JAR_PATH,
69+
server: profile.url,
70+
prefetched: profile.manifest ? btoa(JSON.stringify(profile.manifest)) : undefined
71+
}
5672
}
5773

5874
@event()
@@ -61,4 +77,11 @@ export default class AuthlibInjector extends Plugin {
6177
if (!data.startsWith('authlib-injector:yggdrasil-server:') || !(data = data.slice(34))) return
6278
openLoginDialog(AUTHLIB_INJECTOR, { url: decodeURIComponent(data) })
6379
}
80+
81+
@event()
82+
public protocolInstallResource (r: YggdrasilVersion) {
83+
if (!r || !types.isVersion(r) || !r.yggdrasilUrl || typeof r.yggdrasilUrl !== 'string') return
84+
if (this.instance.getAllProfiles().some(it => it.url === r.yggdrasilUrl)) return
85+
openLoginDialog(AUTHLIB_INJECTOR, { url: r.yggdrasilUrl })
86+
}
6487
}

packages/AuthlibInjector/langs.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ export const zhCN = {
55
redirect: '重定向次数过多!',
66
downloadFailed: '下载失败!',
77
description: 'Authlib-Injector 登陆插件.',
8-
withoutProfile: '你还没有在网页中选择角色!'
8+
withoutProfile: '你还没有在网页中选择角色!',
9+
incorrectAccount: '错误的账户',
10+
notSelectedProfile: '检测到该版本应使用 AuthlibInjector 进行登陆, 但你没有选择正确的账户, 请选择后再尝试重新启动!',
11+
noExistsProfile: '检测到该版本应使用 AuthlibInjector 进行登陆, 但并没有找到合适的账号, 点击确定按钮可以进行登陆.'
912
}
1013

1114
export default locates<typeof zhCN>({
@@ -15,6 +18,9 @@ export default locates<typeof zhCN>({
1518
downloadFailed: 'Download failed!',
1619
redirect: 'Redirect too many times!',
1720
description: 'Authlib-Injector plugin.',
18-
withoutProfile: "You haven't selected a profile on the web yet"
21+
incorrectAccount: 'Incorrect account',
22+
withoutProfile: "You haven't selected a profile on the web yet",
23+
notSelectedProfile: 'It is detected that this version should use AuthlibInjector to login, but you have not selected the correct account, please select and relaunch!',
24+
noExistsProfile: 'It is detected that this version should use AuthlibInjector to login, but no suitable account has been found. Click OK to login.'
1925
}
2026
})

packages/AuthlibInjector/package.json

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,14 @@
77
"license": "MIT",
88
"devDependencies": {
99
"@babel/core": "^7.8.4"
10-
}
10+
},
11+
12+
"type": "Plugin",
13+
"id": "@PureLauncher/authlib-injector",
14+
"title": "AuthlibInjector",
15+
"description": "A plugin that allows you to run multiple game instances.",
16+
"url": "https://dl.pl.apisium.cn/resources/plugins/authlib-injector/files/351a0d895a1d68d8eab2cf41438a2f8f9c2a54f3.asar",
17+
"hash": "351a0d895a1d68d8eab2cf41438a2f8f9c2a54f3",
18+
"website": "https://pl.apisium.cn",
19+
"updateUrl": "https://dl.pl.apisium.cn/resources/plugins/authlib-injectorpackage.json"
1120
}

packages/CurseForge/package.json

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,14 @@
77
"license": "MIT",
88
"devDependencies": {
99
"@babel/core": "^7.8.4"
10-
}
10+
},
11+
12+
"type": "Plugin",
13+
"id": "@PureLauncher/curseforge",
14+
"title": "CurseForge",
15+
"description": "The installer of CurseForge resources.",
16+
"url": "https://dl.pl.apisium.cn/resources/plugins/curseforge/files/7477a2641aa225c0206f63a36e1774dc3f643522.asar",
17+
"hash": "7477a2641aa225c0206f63a36e1774dc3f643522",
18+
"website": "https://pl.apisium.cn",
19+
"updateUrl": "https://dl.pl.apisium.cn/resources/plugins/curseforge/package.json"
1120
}

packages/MCBot/index.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable no-unused-expressions, no-sequences, object-curly-newline */
2-
import { version } from './package.json'
2+
import { version, id, author } from './package.json'
33
import { React, Plugin, plugin, event, history, pluginMaster, LiveRoute, fs,
44
constants, $ as $0, openConfirmDialog, notice } from '@plugin'
55
import { join } from 'path'
@@ -23,11 +23,11 @@ const renderDom = (info: ReturnType<typeof render>, elm: HTMLElement) => {
2323
}
2424

2525
@plugin({
26+
id,
27+
author,
2628
version,
27-
author: 'Shirasawa',
2829
title: () => 'MCBot',
29-
description: () => $.description,
30-
id: '@PureLauncher/mc-bot'
30+
description: () => $.description
3131
})
3232
export default class MCBot extends Plugin {
3333
public config = {}

packages/MCBot/package.json

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,14 @@
77
"license": "MIT",
88
"devDependencies": {
99
"@babel/core": "^7.8.4"
10-
}
10+
},
11+
12+
"type": "Plugin",
13+
"id": "@PureLauncher/mc-bot",
14+
"title": "MCBot",
15+
"description": "This plugin allows you to create a bot that can chat and record in game.",
16+
"url": "https://dl.pl.apisium.cn/resources/plugins/mcbot/files/f7a9d89f731c5f422aa7b7b6f8957ac3153e149f.asar",
17+
"hash": "f7a9d89f731c5f422aa7b7b6f8957ac3153e149f",
18+
"website": "https://pl.apisium.cn",
19+
"updateUrl": "https://dl.pl.apisium.cn/resources/plugins/mcbot/package.json"
1120
}

packages/MultiInstances/Page.tsx

+33-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable @typescript-eslint/explicit-function-return-type, object-curly-newline */
2-
import { React, Reqwq, ProfilesStore, pluginMaster, $ as $0, xmcl, openConfirmDialog,
3-
version as launcherBrand, constants, notice, Avatar, getVersionTypeText } from '@plugin'
2+
import { React, Reqwq, ProfilesStore, pluginMaster, $ as $0, xmcl, openConfirmDialog, getSuitableMemory, fs,
3+
version as launcherBrand, constants, notice, Avatar, getVersionTypeText, resolveJavaPath } from '@plugin'
44
import { join } from 'path'
55
import $ from './langs'
66

@@ -54,7 +54,7 @@ const MultiInstances: React.FC = () => {
5454
<div style={css[1]}>
5555
<span style={css[2]}>{$.account}: </span>
5656
<select style={css[3]} onChange={e => setAccount(e.target.value)} value={account}>
57-
{accounts.map(it => <option value={it.key} key={it.key}>{it.username}</option>)}
57+
{accounts.map(it => <option value={it.key} key={it.key}>{it.username} ({it.type})</option>)}
5858
</select>
5959
</div>
6060
<div style={css[1]}>
@@ -90,25 +90,48 @@ const MultiInstances: React.FC = () => {
9090
}
9191
}
9292
try {
93-
const versionId = await ps.resolveVersion(version)
93+
const v = { version }
94+
await pluginMaster.emitSync('launchResolveVersion', v)
95+
await pluginMaster.emitSync('launchPostResolvedVersion', v)
96+
97+
await pluginMaster.emit('launchPreUpdate', v.version)
98+
await pluginMaster.emit('launchPostUpdate', v.version)
99+
100+
const versionId = await ps.resolveVersion(v.version)
101+
await ps.checkModsDirectoryOfVersion(versionId,
102+
(await fs.readJson(constants.RESOURCES_VERSIONS_INDEX_PATH, { throws: false }) || { })[version])
103+
await pluginMaster.emit('launchEnsureFiles', versionId)
104+
105+
const versionDir = join(constants.VERSIONS_PATH, versionId)
106+
const javaPath = await resolveJavaPath(ps.extraJson.javaPath)
107+
const json = (await fs.readJson(constants.RESOURCES_VERSIONS_INDEX_PATH, { throws: false }) || { })[versionId]
94108
const option: import('@xmcl/core').LaunchOption & { prechecks: import('@xmcl/core').LaunchPrecheck[] } = {
95-
resourcePath: constants.GAME_ROOT,
96-
prechecks: ps.extraJson.noChecker ? [] : undefined,
97109
launcherBrand,
110+
minMemory: 512,
98111
properties: {},
99112
userType: 'mojang',
100113
version: versionId,
101-
gamePath: constants.GAME_ROOT,
102114
launcherName: 'pure-launcher',
103115
accessToken: a.accessToken || '',
104116
versionType: getVersionTypeText(),
117+
resourcePath: constants.GAME_ROOT,
118+
extraExecOption: { detached: true },
105119
javaPath: ps.extraJson.javaPath || 'javaw',
106120
gameProfile: { id: a.uuid, name: a.username },
121+
prechecks: ps.extraJson.noChecker ? [] : undefined,
107122
extraJVMArgs: (ps.extraJson.javaArgs || '').split(' '),
108-
extraExecOption: { detached: true }
123+
maxMemory: getSuitableMemory(!!JSON.parse(localStorage.getItem('javaArches') || '{}')[javaPath]),
124+
gamePath: json?.isolation || (await fs.readJson(join(versionDir, versionId + '.json'),
125+
{ throws: false }))?.isolation ? versionDir : constants.GAME_ROOT
109126
}
110-
await pluginMaster.emitSync('preLaunch', versionId, option)
111-
await launch(option)
127+
await pluginMaster.emitSync('preLaunch', versionId, option, a)
128+
const p = (await launch(option))
129+
.on('error', e => {
130+
console.error(e)
131+
notice({ content: $.launchFailed + ': ' + e.message, error: true })
132+
})
133+
.on('exit', code => code && notice({ content: $.launchFailed + ': ' + code, error: true }))
134+
await pluginMaster.emit('postLaunch', p, versionId, option)
112135
notice({ content: $.launched })
113136
} catch (e) {
114137
console.error(e)

packages/MultiInstances/index.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import { version } from './package.json'
1+
import { id, version, author } from './package.json'
22
import { Plugin, plugin, event, pluginMaster, React, LiveRoute, history } from '@plugin'
33
import $ from './langs'
44
import page from './Page'
55

66
@plugin({
7+
id,
8+
author,
79
version,
8-
author: 'Shirasawa',
910
title: () => $.title,
10-
description: () => $.description,
11-
id: '@PureLauncher/multi-instances'
11+
description: () => $.description
1212
})
1313
export default class MultiInstances extends Plugin {
1414
constructor () {

packages/MultiInstances/package.json

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,14 @@
77
"license": "MIT",
88
"devDependencies": {
99
"@babel/core": "^7.8.4"
10-
}
10+
},
11+
12+
"type": "Plugin",
13+
"id": "@PureLauncher/multi-instances",
14+
"title": "MultiInstances",
15+
"description": "A plugin that allows you to run multiple game instances.",
16+
"url": "https://dl.pl.apisium.cn/resources/plugins/multi-instances/files/351a0d895a1d68d8eab2cf41438a2f8f9c2a54f3.asar",
17+
"hash": "351a0d895a1d68d8eab2cf41438a2f8f9c2a54f3",
18+
"website": "https://pl.apisium.cn",
19+
"updateUrl": "https://dl.pl.apisium.cn/resources/plugins/multi-instances/package.json"
1120
}

packages/Skins/index.tsx

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
/* eslint-disable no-unused-expressions, no-sequences */
22
import { join } from 'path'
3-
import { version } from './package.json'
3+
import { remote } from 'electron'
4+
import { version, id, author } from './package.json'
45
import { React, Plugin, plugin, event, history, pluginMaster, ReactRouter, fs, constants } from '@plugin'
56
import Page from './Page'
67
import $ from './langs'
78

89
@plugin({
10+
id,
11+
author,
912
version,
10-
author: 'Shirasawa',
1113
title: () => $.title,
12-
description: () => $.description,
13-
id: '@PureLauncher/skins'
14+
description: () => $.description
1415
})
1516
export default class Skins extends Plugin {
1617
public cssPath = join(constants.APP_PATH, 'custom-skin.css')
@@ -19,8 +20,15 @@ export default class Skins extends Plugin {
1920

2021
constructor () {
2122
super()
22-
this.element.type = 'text/css'
23-
document.body.appendChild(this.element)
23+
let dark = remote.nativeTheme.shouldUseDarkColors
24+
document.body.classList.add(dark ? 'dark-theme' : 'light-theme')
25+
remote.nativeTheme.on('updated', () => {
26+
if (dark === remote.nativeTheme.shouldUseDarkColors) return
27+
dark = !dark
28+
document.body.classList.remove('dark-theme', 'light-theme')
29+
document.body.classList.add(dark ? 'dark-theme' : 'light-theme')
30+
})
31+
document.body.append(this.element)
2432
pluginMaster.addExtensionsButton({
2533
key: 'skins',
2634
title: () => $.title,

0 commit comments

Comments
 (0)