Skip to content

@opys/dev ​

npm

Чим пишуть конфігурацію opys: defineConfig, плагін files, options, userDataDir і definePlugin для власного плагіна.

sh
npm install -D @opys/dev @opys/minecraft

Приклад ​

js
// opys.config.mjs
import { defineConfig, files, options, userDataDir } from '@opys/dev';
import { forge, java } from '@opys/minecraft';

export default defineConfig({
  output: 'game.opys',
  plugins: [
    forge({ version: '1.20.1' }),
    java({ version: '17' }),
    files({ from: 'mods', to: (file) => '${game_directory}/mods/' + file.rel }),
  ],
  manifest: {
    command: '@forge.command',
    args: [
      '@forge.jvmArgs',
      '-Xmx${xmx}M',
      '@forge.mainClass',
      '@forge.gameArgs',
    ],
    workdir: '${game_directory}',
  },
  options: options().slider('xmx', {
    title: 'RAM',
    unit: 'MB',
    min: 2048,
    max: 16384,
    step: 512,
    default: 4096,
  }),
  run: (manifest) => ({
    manifest: {
      vars: { ...manifest.vars, root: userDataDir('my-pack') },
    },
  }),
});

Конфігурація ​

Що приймає defineConfig: об'єкт або функцію від { mode }, яка його повертає.

ПолеЩо це
pluginsЗ чого складається збірка. Жодних двох з однаковою назвою.
manifestЯк її запустити, і все написане вручну. Див. нижче.
output?Куди opys build записує бандл, відносно конфігурації.
options?Що може налаштувати гравець. Див. Параметри.
locale?Мова, якою написані options: 'en'.
run?Викликається на комп'ютері гравця при кожному opys launch.

manifest ​

ПолеЩо це
commandПрограма для запуску: '@forge.command' або буквальне значення.
argsЇї аргументи, по порядку.
workdir?Робоча тека для запуску.
vars?Ваші власні змінні. Вони перекривають змінні плагіна.
envs?Змінні середовища для гри.
artifacts?Файли, написані вручну. Вони перекривають файли плагіна за тим самим шляхом.
cleanup?Що видалити після встановлення.

Усе під manifest копіюється в бандл. Шлях або облікові дані, які належать одному комп'ютеру, пишуть у run, ніколи сюди.

Рядок запуску ​

Рядок, що починається з @, замінюється тим, що пропонує плагін. Усе інше передається як написано.

Ви пишетеЩо означає
'@forge.jvmArgs'Група jvmArgs плагіна з назвою forge.
'-Xmx4G'Аргумент -Xmx4G.
'\\@file'Аргумент @file, для того, що справді так починається.
  • Посилання, яке нічого не називає, зупиняє збирання: '@welcome.flags': 'welcome' exposes no 'flags' (it has: flag).
  • З defineConfig неправильне посилання це також помилка типу у вашому редакторі.
  • Плагін, використаний двічі, потребує двох назв: forge({ … }).as('forge2').

run ​

js
run: (manifest) => ({ manifest: { vars: { ...manifest.vars, root: userDataDir('my-pack') } } }),

Викликається при кожному opys launch і opys install на комп'ютері, який їх виконує. Те, що повертається, замінює ці поля маніфесту. Цього немає в бандлі: лаунчер передає ті самі значення як vars.

Параметри ​

Що гравець може змінити перед запуском. Вони записуються в бандл, щоб лаунчер намалював екран налаштувань.

js
options: options()
  .slider('xmx', {
    title: 'RAM',
    unit: 'MB',
    min: 1024, max: 16384, step: 512, default: 4096,
  })
  .select('preset', { title: 'Graphics', choices: { low: 'Low', high: 'High' } })
  .feature('custom_java', {
    title: 'Custom Java',
    options: options().directory('java_home', { title: 'Java folder' }),
  }),
ВидВстановлюєПотребуєМоже мати
.slider(name, fields)зміннуmin, max, step, defaultunit
.select(name, fields)зміннуchoices, як { value: label }default
.text(name, fields)зміннуplaceholder, default
.file(name, fields)змінну
.directory(name, fields)змінну
.feature(name, fields)прапорецьdefault, options

Кожен вид також бере title, який йому потрібен, і subtitle. Без title це помилка типів, а збирання відхиляє заголовок без нього. Будь-який текст, який читає гравець, може бути перекладом, { en: 'RAM', uk: "Пам'ять" }, що мусить містити locale конфігурації. Повний опис у @opys/bundle.

files ​

Тека на вашому диску як файли збірки.

ПараметрЩо робить
fromТека відносно конфігурації.
to?Куди встановлюється кожен файл. Типово: його шлях усередині теки.
url?Звідки завантажується кожен файл. Без нього файли вбудовуються.
hash?З url: 'sha1' або 'sha256', чим фіксується кожен файл.

to і url це функції від файла:

ПолеДля mods/extra/tweaks.jar у from: 'mods'
relextra/tweaks.jar
dirextra
filenametweaks.jar
absПовний шлях на вашому диску.
sizeЙого розмір у байтах.

Файли · вбудовані ​

Без url кожен файл потрапляє в бандл.

jsonc
// files({ from: 'mods', to: (file) => '${game_directory}/mods/' + file.rel })
// у маніфесті
{
  "path": "${game_directory}/mods/a.jar",
  "source": { "blob": "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824" },
  "size": 5
}

Файли · опубліковані в іншому місці ​

З url бандл тримає лише посилання і хеш.

jsonc
// files({ from: 'mods', to: …, url: (file) => 'https://cdn.example.com/' + file.rel, hash: 'sha1' })
// у маніфесті
{
  "path": "${root}/a.jar",
  "source": { "url": "https://cdn.example.com/a.jar" },
  "size": 5,
  "integrity": { "sha1": "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d" }
}

Зміна плагіна ​

Кожен плагін має ці методи. Кожен повертає новий плагін і змінює лише його файли.

МетодЩо робить
.exclude(match)Відкидає файли, що збігаються.
.addRule(match, rules)Додає їм правила: 'allow.os.windows'.
.removeIntegrity(match)Встановлює завантаження без хешу.
.overwrite(match, 'never')Після встановлення лишає їх гравцю.
.updateFirst(match, patch)Змінює поля першого збігу.
.updateMany(match, patch)Змінює поля кожного збігу.
.as(name)Той самий плагін під іншою назвою.

match це glob-шаблон за шляхом встановлення, список glob-шаблонів або функція від файла. patch це поля для зміни або функція, яка їх повертає.

Власний плагін ​

js
import { definePlugin } from '@opys/dev';

export const welcome = ({ text }) =>
  definePlugin({
    name: 'welcome',
    build: (ctx) => ({
      artifacts: [
        {
          path: '${game_directory}/welcome.txt',
          source: { bytes: new TextEncoder().encode(text) },
        },
      ],
      vars: { greeting: text },
      launch: { flag: ['--welcome'] },
    }),
  });

build це єдиний хук. Він виконується під час збирання і повертає:

ПолеЩо це
artifacts?Файли для встановлення.
vars?Змінні, якими володіє плагін.
launch?Названі частини командного рядка, вжиті як '@welcome.flag'.
envs?Змінні середовища для гри.

source файла каже, де лежать його байти:

ДжерелоЩо цеУ бандлі
{ url }Завантаження. Додайте йому integrity.Посилання.
{ file }Файл на комп'ютері збирання.Сам файл, як блоб.
{ bytes }Uint8Array, який зробив плагін.Ці байти, як блоб.

build отримує:

ПолеЩо це
configDirКаталог конфігурації, для відносних шляхів.
mode--mode або назва команди.
loglog(scope, message), показується під час збирання.

Функції ​

ФункціяЩо робить
defineConfig(config)Повертає конфігурацію, з перевіреними посиланнями.
definePlugin(plugin)Повертає плагін, з методами вище.
files(options)Плагін для теки на диску.
options(), slider, select, …Налаштування збірки.
userDataDir(name)Тека даних користувача для name, на цьому комп'ютері.
buildManifest(config, ctx)Запускає плагіни. Повертає { manifest, blobs }.
resolveConfig(input, { mode })Викликає функційну конфігурацію, якщо вона така.
pluginOptions(example, options)Відхиляє плагін, викликаний без об'єкта параметрів.

Для плагіна завантажувача: launchGroups, carrying, withLibraryFiles і типи LoaderTemplate, LoaderGroups та ExtraLibrary.

Кожна функція ​

Кожна функція, у кожному способі використання.

js
// конфігурація, що залежить від команди: opys launch --mode dev
defineConfig(({ mode }) => ({ plugins: [/* … */], manifest: { command: 'java', args: [] } }));

// files
files({ from: 'mods' });                                              // встановлюється як a.jar, sub/b.jar
files({ from: 'mods', to: (file) => '${game_directory}/mods/' + file.rel });
files({ from: 'mods', to: (file) => '${root}/' + file.filename });    // сплощено
files({ from: 'mods', url: (file) => 'https://cdn.example.com/' + file.rel, hash: 'sha256' });
files('mods');
// кидає TypeError: плагін приймає один об'єкт параметрів

// зміна плагіна
files({ from: 'mods' }).exclude('**/*.tmp');
forge({ version: '1.20.1' }).exclude(['**/log4j-*.jar', '**/*-sources.jar']);
forge({ version: '1.20.1' }).addRule('**/*-natives-windows.jar', 'allow.os.windows');
links({ links: [url], to }).removeIntegrity('**/nightly-*.jar');
forge({ version: '1.20.1' }).updateFirst('**/guava-*.jar', { size: 2874025 });
forge({ version: '1.20.1' }).updateMany(
  (file) => 'url' in file.source,
  (file) => ({ source: { url: file.source.url.replace('maven.example.com', 'mirror.example.com') } }),
);
forge({ version: '1.20.1' }).as('forge2');                            // '@forge2.jvmArgs'

// тека даних користувача
userDataDir('my-pack');
// Linux:   ~/.local/share/my-pack   (або $XDG_DATA_HOME/my-pack)
// macOS:   ~/Library/Application Support/my-pack
// Windows: %APPDATA%\my-pack

// збирання без CLI
const config = await resolveConfig(input, { mode: 'build' });
const ctx = { configDir: process.cwd(), mode: 'build', log: (scope, message) => console.log(scope, message) };
const { manifest, blobs } = await buildManifest(config, ctx);
// manifest: { vars, artifacts, launch }   blobs: { '8f434346…': { bytes: 'aGk=' } }
await writeBundle('game.opys', manifest, blobs, { options: config.options }); // з @opys/bundle

// що зупиняє збирання
// '@welcome.flags': 'welcome' exposes no 'flags' (it has: flag)
// два плагіни названо 'welcome': перейменуйте один через `.as('…')`

Документація ​

Частина opys.