Як написати плагін
Плагін малий. Він має ім'я і одну функцію, build, яка повертає частку плагіна в маніфесті. Якщо ви можете описати бажане як «ці файли, ці змінні, ці аргументи», ви можете написати це як плагін просто у вашій конфігурації.
Форма
import { definePlugin } from '@opys/dev';
const myPlugin = (options) =>
definePlugin({
name: 'myPlugin',
async build(ctx) {
return {
artifacts: [], // файли для встановлення
vars: {}, // змінні
envs: {}, // змінні середовища для гри
launch: {}, // іменовані фрагменти командного рядка
};
},
});Кожне поле необов'язкове. Повертайте лише те, що маєте.
build отримує малий контекст:
| Поле | Що це |
|---|---|
ctx.log(scope, message) | Друкує рядок [scope] message під час збирання. |
ctx.configDir | Тека файла конфігурації. Зіставляйте відносні шляхи з нею. |
ctx.mode | Значення --mode. |
Одне правило про структуру: виклик плагіна нічого не робить.myPlugin({ … }) лише повертає { name, build }. Уся справжня робота, включаючи мережеві запити і читання файлів, відбувається всередині build. Це тримає конфігурацію дешевою для завантаження і дозволяє opys запускати всі плагіни разом.
Розібраний приклад
Цей плагін робить усього по одному: задає змінну, додає файл за URL, додає згенерований файл і пропонує аргумент JVM.
import { defineConfig, definePlugin, userDataDir } from '@opys/dev';
import { java, minecraft } from '@opys/minecraft';
// A plugin is { name, build(ctx) }. Calling welcome() does no I/O; the work
// happens in build(), which the engine runs once per `opys build`.
const welcome = (motd) =>
definePlugin({
name: 'welcome',
build(ctx) {
ctx.log('welcome', `motd is "${motd}"`);
// A generated file. It is carried in the bundle: the build names it by
// its content, so there is nothing to hash or keep track of here.
const config = new TextEncoder().encode(`motd = "${motd}"\n`);
return {
vars: { motd },
artifacts: [
{
path: '${root}/downloads/brigadier-1.3.10.jar',
source: {
url: 'https://libraries.minecraft.net/com/mojang/brigadier/1.3.10/brigadier-1.3.10.jar',
},
size: 80082,
integrity: { sha1: 'd15b53a14cf20fdcaa98f731af5dda654452c010' },
},
{ path: '${root}/config/welcome.toml', source: { bytes: config } },
],
launch: { jvmArg: '-Dwelcome.motd=${motd}' },
};
},
});
export default defineConfig({
output: 'game.opys',
plugins: [
minecraft({ version: '1.21.1' }),
java({ version: '21' }),
welcome('Hello from opys'),
],
manifest: {
command: '@minecraft.command',
args: [
'@welcome.jvmArg',
'@minecraft.jvmArgs',
'@minecraft.mainClass',
'@minecraft.gameArgs',
],
workdir: '${game_directory}',
},
run: (manifest) => ({
manifest: {
vars: {
...manifest.vars,
root: userDataDir('my-pack'),
username: 'Player',
uuid: '00000000-0000-0000-0000-000000000001',
token: '0',
},
},
}),
});Розбираємо те, що повертає build:
vars стають змінними маніфесту. Тут motd потім можна використовувати як ${motd} будь-де.
artifacts це файли. Перший це завантаження: шлях, URL і хеш, який він мусить мати. Завжди давайте хеш. Файл без нього не можна перевірити, і він ніколи не оновлюється, коли вже існує.
Другий артефакт привезений: файл, що подорожує всередині бандла. Його джерело каже, де байти просто зараз, у пам'яті ({ bytes }) або у файлі ({ file: path }). Збирання читає їх, називає за їхнім sha256 і зберігає в бандлі. Нічого хешувати самостійно.
launch пропонує іменовані фрагменти командного рядка. Оскільки плагін зветься welcome і пропонує jvmArg, конфігурація може писати '@welcome.jvmArg'. З definePlugin TypeScript теж знає це ім'я, і одрук у конфігурації підсвічується, коли ви друкуєте.
Фрагмент запуску може бути рядком, списком або обмеженим платформою:
launch: {
jvmArgs: [
'-Dfoo=bar',
{ rules: 'allow.os.osx', value: ['-XstartOnFirstThread'] },
],
},Яким має бути добрий плагін
- Вирішуйте все у
build. Маніфест ніколи не каже «найновіша версія». Дізнайтеся версію, URL і хеш під час збирання і запишіть точні відповіді. - Фіксуйте кожен файл. Якщо ніхто не публікує хеш для нього, завантажте його у
buildі хешуйте самі. - Описуйте збірку, а не власний комп'ютер.
buildпрацює на комп'ютері збирання. Домашня тека або змінна середовища, прочитана там, запікається для кожного гравця. Використовуйте змінні на зразок${root}для шляхів. - Жодних секретів у тому, що повертаєте. Бандл це zip, який отримують інші люди.
- Володейте своїми іменами. Починайте змінні з імені вашого плагіна, щоб вони не могли зіткнутися зі змінними іншого плагіна. Виберіть ім'я плагіна, яке добре читається у
'@name.group'. - Приймайте один об'єкт параметрів, як вбудовані плагіни, щоб конфігурації читалися однаково всюди.
Можливо, він вам не потрібен
Перш ніж писати плагін, перевірте, чи наявний не робить цієї роботи:
- Тека файлів:
files. - Файл за URL:
links. - Наявний плагін, що майже підходить: підправте його вивід через
.exclude()і подібні. Кожен плагін, зроблений зdefinePlugin, має ці методи, включно з вашим.