@@ -506,6 +524,12 @@
+
+
+
+
diff --git a/launcher/launcher/src/resources/ui/launcher.js b/launcher/launcher/src/resources/ui/launcher.js
index 3c92dfb..999d188 100644
--- a/launcher/launcher/src/resources/ui/launcher.js
+++ b/launcher/launcher/src/resources/ui/launcher.js
@@ -163,9 +163,19 @@ const LOCALES = {
'admin.newsCreated': 'News published!',
'admin.newsDeleted': 'News deleted',
'admin.newsEmpty': 'No news',
+ 'admin.packs': 'Packs',
+ 'admin.packsList': 'Pack Management',
+ 'admin.packsEmpty': 'No packs',
+ 'admin.packsToggle': 'Toggle',
+ 'admin.packsDisabled': 'Disabled',
+ 'admin.packsEnabled': 'Enabled',
+ 'admin.packsStatus': 'Status',
'admin.delete': 'Delete',
'admin.loading': 'Loading...',
'admin.error': 'Error',
+ 'install.preset.label': 'Preset (optional)',
+ 'install.preset.default': 'Default',
+ 'pack.disabled': 'Disabled',
},
ru: {
'nav.packs': 'Сборки', 'nav.news': 'Новости', 'nav.settings': 'Настройки',
@@ -329,9 +339,19 @@ const LOCALES = {
'admin.newsCreated': 'Новость опубликована!',
'admin.newsDeleted': 'Новость удалена',
'admin.newsEmpty': 'Нет новостей',
+ 'admin.packs': 'Сборки',
+ 'admin.packsList': 'Управление сборками',
+ 'admin.packsEmpty': 'Нет сборок',
+ 'admin.packsToggle': 'Переключить',
+ 'admin.packsDisabled': 'Отключена',
+ 'admin.packsEnabled': 'Включена',
+ 'admin.packsStatus': 'Статус',
'admin.delete': 'Удалить',
'admin.loading': 'Загрузка...',
'admin.error': 'Ошибка',
+ 'install.preset.label': 'Пресет (опционально)',
+ 'install.preset.default': 'Стандартный',
+ 'pack.disabled': 'Отключена',
}
};
@@ -570,6 +590,10 @@ class ZernMCLauncher {
const r = await this.req('/packs');
if (r.success && r.data) {
this.state.serverPacks = r.data;
+ this.state.serverPacksMap = {};
+ r.data.forEach(function(p) {
+ app.state.serverPacksMap[p.name] = p;
+ });
}
}
@@ -584,6 +608,7 @@ class ZernMCLauncher {
});
document.getElementById('add-pack-btn').addEventListener('click', () => this.showInstallModal());
+ document.getElementById('add-server-pack-btn').addEventListener('click', () => this.showInstallModal());
document.getElementById('close-modal-btn').addEventListener('click', () => this.hideInstallModal());
document.querySelectorAll('.modal-tab').forEach(t => {
t.addEventListener('click', () => this.switchInstallTab(t.dataset.tab));
@@ -673,6 +698,10 @@ class ZernMCLauncher {
if (!this.state.instances) return;
for (const inst of this.state.instances) {
if (!inst.isServerPack) continue;
+ // Skip disabled packs
+ if (this.state.serverPacksMap && this.state.serverPacksMap[inst.name] && this.state.serverPacksMap[inst.name].disabled) {
+ continue;
+ }
const r = await this.req('/check-updates?name=' + encodeURIComponent(inst.name));
if (r.success && r.data) {
this.state.updateMap[inst.name] = r.data.hasUpdate;
@@ -682,6 +711,10 @@ class ZernMCLauncher {
async checkUpdateForPack(inst) {
if (!inst || !inst.isServerPack) return;
+ // Skip disabled packs
+ if (this.state.serverPacksMap && this.state.serverPacksMap[inst.name] && this.state.serverPacksMap[inst.name].disabled) {
+ return;
+ }
const r = await this.req('/check-updates?name=' + encodeURIComponent(inst.name));
if (r.success && r.data) {
if (!this.state.updateMap) this.state.updateMap = {};
@@ -706,9 +739,11 @@ class ZernMCLauncher {
this.state.instances.forEach(inst => {
const isZern = inst.isServerPack || inst.category === 'zernmc';
const targetList = isZern ? serverList : localList;
+ const isDisabled = this.state.serverPacksMap && this.state.serverPacksMap[inst.name] && this.state.serverPacksMap[inst.name].disabled;
const el = document.createElement('div');
- el.className = 'pack-entry' + (this.state.selectedPack && this.state.selectedPack.name === inst.name ? ' selected' : '');
+ el.className = 'pack-entry' + (this.state.selectedPack && this.state.selectedPack.name === inst.name ? ' selected' : '') + (isDisabled ? ' disabled' : '');
+ if (isDisabled) el.setAttribute('data-disabled-text', t('pack.disabled'));
const hasUpd = this.hasUpdate(inst);
el.innerHTML = `
@@ -716,14 +751,16 @@ class ZernMCLauncher {
? '
'
: '
'
}
- ${hasUpd ? '
' : ''}
+ ${hasUpd && !isDisabled ? '
' : ''}
-
${this.esc(inst.name)}${hasUpd ? ' ' + t('pack.update') + '' : ''}
+
${this.esc(inst.name)}${hasUpd && !isDisabled ? ' ' + t('pack.update') + '' : ''}
${inst.version || '?'}${inst.loaderType && inst.loaderType !== 'vanilla' ? ' \u00b7 ' + inst.loaderType : ''}
`;
- el.addEventListener('click', () => this.selectPack(inst));
+ if (!isDisabled) {
+ el.addEventListener('click', () => this.selectPack(inst));
+ }
targetList.appendChild(el);
});
@@ -965,6 +1002,7 @@ class ZernMCLauncher {
if (tab === 'users') this.adminClearUser();
if (tab === 'passes') this.adminLoadPasses();
if (tab === 'news') this.adminLoadNewsList();
+ if (tab === 'packs') this.adminLoadPacks();
}
// --- Clients ---
@@ -1229,6 +1267,48 @@ class ZernMCLauncher {
}
}
+ // --- Packs ---
+ async adminLoadPacks() {
+ var el = document.getElementById('admin-packs-list');
+ if (!el) return;
+ el.innerHTML = '