Allow multiple startup commands per egg (#1656)

This commit is contained in:
Boy132 2025-10-07 23:42:28 +02:00 committed by GitHub
parent a58ae874f3
commit cd965678b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 301 additions and 146 deletions

View File

@ -83,14 +83,16 @@ class CreateEgg extends CreateRecord
->rows(2) ->rows(2)
->columnSpanFull() ->columnSpanFull()
->helperText(trans('admin/egg.description_help')), ->helperText(trans('admin/egg.description_help')),
Textarea::make('startup') KeyValue::make('startup_commands')
->label(trans('admin/egg.startup')) ->label(trans('admin/egg.startup_commands'))
->rows(3) ->live()
->columnSpanFull() ->columnSpanFull()
->required() ->required()
->placeholder(implode("\n", [ ->addActionLabel(trans('admin/egg.add_startup'))
'java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}', ->keyLabel(trans('admin/egg.startup_name'))
])) ->keyPlaceholder('Default')
->valueLabel(trans('admin/egg.startup_command'))
->valuePlaceholder('java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}')
->helperText(trans('admin/egg.startup_help')), ->helperText(trans('admin/egg.startup_help')),
TagsInput::make('file_denylist') TagsInput::make('file_denylist')
->label(trans('admin/egg.file_denylist')) ->label(trans('admin/egg.file_denylist'))

View File

@ -80,11 +80,14 @@ class EditEgg extends EditRecord
->disabled() ->disabled()
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2]) ->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2])
->helperText(trans('admin/egg.author_help_edit')), ->helperText(trans('admin/egg.author_help_edit')),
Textarea::make('startup') KeyValue::make('startup_commands')
->label(trans('admin/egg.startup')) ->label(trans('admin/egg.startup_commands'))
->rows(3) ->live()
->columnSpanFull() ->columnSpanFull()
->required() ->required()
->addActionLabel(trans('admin/egg.add_startup'))
->keyLabel(trans('admin/egg.startup_name'))
->valueLabel(trans('admin/egg.startup_command'))
->helperText(trans('admin/egg.startup_help')), ->helperText(trans('admin/egg.startup_help')),
TagsInput::make('file_denylist') TagsInput::make('file_denylist')
->label(trans('admin/egg.file_denylist')) ->label(trans('admin/egg.file_denylist'))

View File

@ -328,7 +328,7 @@ class CreateServer extends CreateRecord
->live() ->live()
->afterStateUpdated(function ($state, Set $set, Get $get, $old) { ->afterStateUpdated(function ($state, Set $set, Get $get, $old) {
$egg = Egg::query()->find($state); $egg = Egg::query()->find($state);
$set('startup', $egg->startup ?? ''); $set('startup', '');
$set('image', ''); $set('image', '');
$variables = $egg->variables ?? []; $variables = $egg->variables ?? [];
@ -402,24 +402,45 @@ class CreateServer extends CreateRecord
]) ])
->inline(), ->inline(),
Textarea::make('startup') Select::make('select_startup')
->hintIcon('tabler-code')
->label(trans('admin/server.startup_cmd')) ->label(trans('admin/server.startup_cmd'))
->hidden(fn (Get $get) => $get('egg_id') === null) ->hidden(fn (Get $get) => $get('egg_id') === null)
->live()
->afterStateUpdated(fn (Set $set, $state) => $set('startup', $state))
->options(function ($state, Get $get, Set $set) {
$egg = Egg::query()->find($get('egg_id'));
$startups = $egg->startup_commands ?? [];
$currentStartup = $get('startup');
if (!$currentStartup && $startups) {
$currentStartup = collect($startups)->first();
$set('startup', $currentStartup);
$set('select_startup', $currentStartup);
}
return array_flip($startups) + ['' => 'Custom Startup'];
})
->selectablePlaceholder(false)
->columnSpanFull(),
Textarea::make('startup')
->hiddenLabel()
->hidden(fn (Get $get) => $get('egg_id') === null)
->required() ->required()
->live() ->live()
->rows(function ($state) { ->autosize()
return str($state)->explode("\n")->reduce( ->afterStateUpdated(function ($state, Get $get, Set $set) {
fn (int $carry, $line) => $carry + floor(strlen($line) / 125), $egg = Egg::query()->find($get('egg_id'));
1 $startups = $egg->startup_commands ?? [];
);
if (in_array($state, $startups)) {
$set('select_startup', $state);
} else {
$set('select_startup', '');
}
}) })
->columnSpan([ ->placeholder(trans('admin/server.startup_placeholder'))
'default' => 1, ->columnSpanFull(),
'sm' => 4,
'md' => 4,
'lg' => 6,
]),
Hidden::make('environment')->default([]), Hidden::make('environment')->default([]),

View File

@ -609,26 +609,51 @@ class EditServer extends EditRecord
1 => 'tabler-code-off', 1 => 'tabler-code-off',
]) ])
->required(), ->required(),
Hidden::make('previewing') Hidden::make('previewing')
->default(false), ->default(false),
Textarea::make('startup')
Select::make('select_startup')
->label(trans('admin/server.startup_cmd')) ->label(trans('admin/server.startup_cmd'))
->required() ->live()
->columnSpan(6) ->afterStateUpdated(function (Set $set, $state) {
->autosize() $set('startup', $state);
$set('previewing', false);
})
->options(function ($state, Get $get, Set $set) {
$egg = Egg::find($get('egg_id'));
$startups = $egg->startup_commands ?? [];
$currentStartup = $get('startup');
if (!$currentStartup && $startups) {
$currentStartup = collect($startups)->first();
$set('startup', $currentStartup);
$set('select_startup', $currentStartup);
}
return array_flip($startups) + ['' => 'Custom Startup'];
})
->selectablePlaceholder(false)
->columnSpanFull()
->hintAction(PreviewStartupAction::make('preview')), ->hintAction(PreviewStartupAction::make('preview')),
Textarea::make('defaultStartup') Textarea::make('startup')
->hintCopy() ->hiddenLabel()
->label(trans('admin/server.default_startup')) ->required()
->disabled() ->live()
->autosize() ->autosize()
->columnSpan(6) ->afterStateUpdated(function ($state, Get $get, Set $set) {
->formatStateUsing(function ($state, Get $get) { $egg = Egg::find($get('egg_id'));
$egg = Egg::query()->find($get('egg_id')); $startups = $egg->startup_commands ?? [];
return $egg->startup; if (in_array($state, $startups)) {
}), $set('select_startup', $state);
} else {
$set('select_startup', '');
}
})
->placeholder(trans('admin/server.startup_placeholder'))
->columnSpanFull(),
Repeater::make('server_variables') Repeater::make('server_variables')
->hiddenLabel() ->hiddenLabel()

View File

@ -15,19 +15,17 @@ class PreviewStartupAction extends Action
return 'preview'; return 'preview';
} }
public function getLabel(): string
{
return trans('server/startup.preview');
}
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
$this->label(fn (Get $get) => $get('previewing') ? trans('server/startup.disable_preview') : trans('server/startup.enable_preview'));
$this->action(function (Get $get, Set $set, Server $server) { $this->action(function (Get $get, Set $set, Server $server) {
$active = $get('previewing'); $previewing = !$get('previewing');
$set('previewing', !$active);
$set('startup', $active ? $server->startup : fn (Server $server, StartupCommandService $service) => $service->handle($server)); $set('previewing', $previewing);
$set('startup', !$previewing ? $server->startup : fn (Server $server, StartupCommandService $service) => $service->handle($server, $server->startup));
}); });
} }
} }

View File

@ -17,6 +17,7 @@ use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput; use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification; use Filament\Notifications\Notification;
use Filament\Schemas\Components\Section; use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Schemas\Schema; use Filament\Schemas\Schema;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
@ -35,35 +36,51 @@ class Startup extends ServerFormPage
return parent::form($schema) return parent::form($schema)
->columns([ ->columns([
'default' => 1, 'default' => 1,
'sm' => 1, 'md' => 2,
'md' => 4,
'lg' => 6,
]) ])
->components([ ->components([
Hidden::make('previewing') Hidden::make('previewing')
->default(false), ->default(false),
Textarea::make('startup') TextInput::make('custom_startup')
->label(trans('server/startup.command')) ->label(trans('server/startup.command'))
->columnSpan([ ->readOnly()
'default' => 1, ->visible(fn (Server $server) => !in_array($server->startup, $server->egg->startup_commands))
'sm' => 1, ->formatStateUsing(fn () => 'Custom Startup')
'md' => 2, ->hintAction(PreviewStartupAction::make()),
'lg' => 4, Select::make('startup_select')
]) ->label(trans('server/startup.command'))
->autosize() ->live()
->hintAction(PreviewStartupAction::make()) ->visible(fn (Server $server) => in_array($server->startup, $server->egg->startup_commands))
->readOnly(), ->disabled(fn (Server $server) => !auth()->user()->can(Permission::ACTION_STARTUP_UPDATE, $server))
->formatStateUsing(fn (Server $server) => $server->startup)
->afterStateUpdated(function ($state, Server $server, Set $set) {
$original = $server->startup;
$server->forceFill(['startup' => $state])->saveOrFail();
$set('startup', $state);
$set('previewing', false);
if ($original !== $server->startup) {
$startups = array_flip($server->egg->startup_commands);
Activity::event('server:startup.command')
->property(['old' => $startups[$original], 'new' => $startups[$state]])
->log();
}
Notification::make()
->title(trans('server/startup.notification_startup'))
->body(trans('server/startup.notification_startup_body'))
->success()
->send();
})
->options(fn (Server $server) => array_flip($server->egg->startup_commands))
->selectablePlaceholder(false)
->hintAction(PreviewStartupAction::make()),
TextInput::make('custom_image') TextInput::make('custom_image')
->label(trans('server/startup.docker_image')) ->label(trans('server/startup.docker_image'))
->readOnly() ->readOnly()
->visible(fn (Server $server) => !in_array($server->image, $server->egg->docker_images)) ->visible(fn (Server $server) => !in_array($server->image, $server->egg->docker_images))
->formatStateUsing(fn (Server $server) => $server->image) ->formatStateUsing(fn (Server $server) => $server->image),
->columnSpan([
'default' => 1,
'sm' => 1,
'md' => 2,
'lg' => 2,
]),
Select::make('image') Select::make('image')
->label(trans('server/startup.docker_image')) ->label(trans('server/startup.docker_image'))
->live() ->live()
@ -89,14 +106,12 @@ class Startup extends ServerFormPage
$images = $server->egg->docker_images; $images = $server->egg->docker_images;
return array_flip($images); return array_flip($images);
}) }),
->selectablePlaceholder(false) Textarea::make('startup')
->columnSpan([ ->hiddenLabel()
'default' => 1, ->columnSpanFull()
'sm' => 1, ->autosize()
'md' => 2, ->readOnly(),
'lg' => 2,
]),
Section::make(trans('server/startup.variables')) Section::make(trans('server/startup.variables'))
->columnSpanFull() ->columnSpanFull()
->schema([ ->schema([

View File

@ -22,8 +22,7 @@ use Illuminate\Support\Str;
* @property string $name * @property string $name
* @property string|null $description * @property string|null $description
* @property string[]|null $features * @property string[]|null $features
* @property string $docker_image -- deprecated, use $docker_images * @property array<string, string> $docker_images
* @property array<array-key, string> $docker_images
* @property string|null $update_url * @property string|null $update_url
* @property bool $force_outgoing_ip * @property bool $force_outgoing_ip
* @property string[]|null $file_denylist * @property string[]|null $file_denylist
@ -32,7 +31,7 @@ use Illuminate\Support\Str;
* @property string|null $config_logs * @property string|null $config_logs
* @property string|null $config_stop * @property string|null $config_stop
* @property int|null $config_from * @property int|null $config_from
* @property string|null $startup * @property array<string, string> $startup_commands
* @property bool $script_is_privileged * @property bool $script_is_privileged
* @property string|null $script_install * @property string|null $script_install
* @property string $script_entry * @property string $script_entry
@ -71,7 +70,7 @@ class Egg extends Model implements Validatable
/** /**
* Defines the current egg export version. * Defines the current egg export version.
*/ */
public const EXPORT_VERSION = 'PLCN_v2'; public const EXPORT_VERSION = 'PLCN_v3';
/** /**
* Fields that are not mass assignable. * Fields that are not mass assignable.
@ -90,7 +89,7 @@ class Egg extends Model implements Validatable
'config_logs', 'config_logs',
'config_stop', 'config_stop',
'config_from', 'config_from',
'startup', 'startup_commands',
'update_url', 'update_url',
'script_is_privileged', 'script_is_privileged',
'script_install', 'script_install',
@ -111,7 +110,8 @@ class Egg extends Model implements Validatable
'file_denylist.*' => ['string'], 'file_denylist.*' => ['string'],
'docker_images' => ['required', 'array', 'min:1'], 'docker_images' => ['required', 'array', 'min:1'],
'docker_images.*' => ['required', 'string'], 'docker_images.*' => ['required', 'string'],
'startup' => ['required', 'nullable', 'string'], 'startup_commands' => ['required', 'array', 'min:1'],
'startup_commands.*' => ['required', 'string', 'distinct'],
'config_from' => ['sometimes', 'bail', 'nullable', 'numeric', 'exists:eggs,id'], 'config_from' => ['sometimes', 'bail', 'nullable', 'numeric', 'exists:eggs,id'],
'config_stop' => ['required_without:config_from', 'nullable', 'string', 'max:255'], 'config_stop' => ['required_without:config_from', 'nullable', 'string', 'max:255'],
'config_startup' => ['required_without:config_from', 'nullable', 'json'], 'config_startup' => ['required_without:config_from', 'nullable', 'json'],
@ -143,6 +143,7 @@ class Egg extends Model implements Validatable
'features' => 'array', 'features' => 'array',
'docker_images' => 'array', 'docker_images' => 'array',
'file_denylist' => 'array', 'file_denylist' => 'array',
'startup_commands' => 'array',
'tags' => 'array', 'tags' => 'array',
]; ];
} }

View File

@ -5,6 +5,7 @@ namespace App\Services\Eggs;
use App\Models\Egg; use App\Models\Egg;
use App\Models\Server; use App\Models\Server;
use App\Models\ServerVariable; use App\Models\ServerVariable;
use Illuminate\Support\Arr;
class EggChangerService class EggChangerService
{ {
@ -21,8 +22,8 @@ class EggChangerService
// Change egg id, default image and startup command // Change egg id, default image and startup command
$server->forceFill([ $server->forceFill([
'egg_id' => $newEgg->id, 'egg_id' => $newEgg->id,
'image' => array_values($newEgg->docker_images)[0], 'image' => Arr::first($newEgg->docker_images),
'startup' => $newEgg->startup, 'startup' => Arr::first($newEgg->startup_commands),
])->saveOrFail(); ])->saveOrFail();
$oldVariables = []; $oldVariables = [];

View File

@ -33,7 +33,7 @@ class EggExporterService
'features' => $egg->features, 'features' => $egg->features,
'docker_images' => $egg->docker_images, 'docker_images' => $egg->docker_images,
'file_denylist' => Collection::make($egg->inherit_file_denylist)->filter(fn ($v) => !empty($v))->values(), 'file_denylist' => Collection::make($egg->inherit_file_denylist)->filter(fn ($v) => !empty($v))->values(),
'startup' => $egg->startup, 'startup_commands' => $egg->startup_commands,
'config' => [ 'config' => [
'files' => $egg->inherit_config_files, 'files' => $egg->inherit_config_files,
'startup' => $egg->inherit_config_startup, 'startup' => $egg->inherit_config_startup,

View File

@ -133,8 +133,9 @@ class EggImporterService
$version = $parsed['meta']['version'] ?? ''; $version = $parsed['meta']['version'] ?? '';
$parsed = match ($version) { $parsed = match ($version) {
'PTDL_v1' => $this->convertToV2($parsed), 'PTDL_v1' => $this->convertToV3($this->convertLegacy($parsed)),
'PTDL_v2', 'PLCN_v1', 'PLCN_v2' => $parsed, 'PTDL_v2', 'PLCN_v1', 'PLCN_v2' => $this->convertToV3($parsed),
Egg::EXPORT_VERSION => $parsed,
default => throw new InvalidFileUploadException('The file format is not recognized.'), default => throw new InvalidFileUploadException('The file format is not recognized.'),
}; };
@ -180,9 +181,9 @@ class EggImporterService
if ($forbidden->count()) { if ($forbidden->count()) {
$parsed['variables'] = $allowed->merge($updatedVariables)->all(); $parsed['variables'] = $allowed->merge($updatedVariables)->all();
if (!empty($parsed['startup'])) { foreach ($parsed['startup_commands'] ?? [] as $name => $startup) {
$pattern = '/\b(' . collect($forbidden)->map(fn ($variable) => preg_quote($variable['env_variable']))->join('|') . ')\b/'; $pattern = '/\b(' . collect($forbidden)->map(fn ($variable) => preg_quote($variable['env_variable']))->join('|') . ')\b/';
$parsed['startup'] = preg_replace($pattern, 'SERVER_$1', $parsed['startup']) ?? $parsed['startup']; $parsed['startup_commands'][$name] = preg_replace($pattern, 'SERVER_$1', $startup) ?? $startup;
} }
} }
@ -206,7 +207,7 @@ class EggImporterService
'config_startup' => json_encode(json_decode(Arr::get($parsed, 'config.startup')), JSON_PRETTY_PRINT), 'config_startup' => json_encode(json_decode(Arr::get($parsed, 'config.startup')), JSON_PRETTY_PRINT),
'config_logs' => json_encode(json_decode(Arr::get($parsed, 'config.logs')), JSON_PRETTY_PRINT), 'config_logs' => json_encode(json_decode(Arr::get($parsed, 'config.logs')), JSON_PRETTY_PRINT),
'config_stop' => Arr::get($parsed, 'config.stop'), 'config_stop' => Arr::get($parsed, 'config.stop'),
'startup' => Arr::get($parsed, 'startup'), 'startup_commands' => Arr::get($parsed, 'startup_commands'),
'script_install' => Arr::get($parsed, 'scripts.installation.script'), 'script_install' => Arr::get($parsed, 'scripts.installation.script'),
'script_entry' => Arr::get($parsed, 'scripts.installation.entrypoint'), 'script_entry' => Arr::get($parsed, 'scripts.installation.entrypoint'),
'script_container' => Arr::get($parsed, 'scripts.installation.container'), 'script_container' => Arr::get($parsed, 'scripts.installation.container'),
@ -217,7 +218,7 @@ class EggImporterService
* @param array<string, mixed> $parsed * @param array<string, mixed> $parsed
* @return array<string, mixed> * @return array<string, mixed>
*/ */
protected function convertToV2(array $parsed): array protected function convertLegacy(array $parsed): array
{ {
if (!isset($parsed['images'])) { if (!isset($parsed['images'])) {
$images = [Arr::get($parsed, 'image') ?? 'nil']; $images = [Arr::get($parsed, 'image') ?? 'nil'];
@ -234,4 +235,21 @@ class EggImporterService
return $parsed; return $parsed;
} }
/**
* @param array<string, mixed> $parsed
* @return array<string, mixed>
*/
protected function convertToV3(array $parsed): array
{
$startup = $parsed['startup'];
unset($parsed['startup']);
$parsed['startup_commands'] = [
'Default' => $startup,
];
return $parsed;
}
} }

View File

@ -61,8 +61,8 @@ class ServerCreationService
$egg = Egg::query()->findOrFail($data['egg_id']); $egg = Egg::query()->findOrFail($data['egg_id']);
// Fill missing fields from egg // Fill missing fields from egg
$data['image'] ??= collect($egg->docker_images)->first(); $data['image'] ??= Arr::first($egg->docker_images);
$data['startup'] ??= $egg->startup; $data['startup'] ??= Arr::first($egg->startup_commands);
// If a deployment object has been passed we need to get the allocation and node that the server should use. // If a deployment object has been passed we need to get the allocation and node that the server should use.
if ($deployment) { if ($deployment) {

View File

@ -9,8 +9,10 @@ class StartupCommandService
/** /**
* Generates a startup command for a given server instance. * Generates a startup command for a given server instance.
*/ */
public function handle(Server $server, bool $hideAllValues = false): string public function handle(Server $server, ?string $startup = null, bool $hideAllValues = false): string
{ {
$startup ??= $server->startup;
$find = ['{{SERVER_MEMORY}}', '{{SERVER_IP}}', '{{SERVER_PORT}}']; $find = ['{{SERVER_MEMORY}}', '{{SERVER_IP}}', '{{SERVER_PORT}}'];
$replace = [ $replace = [
(string) $server->memory, (string) $server->memory,
@ -23,6 +25,6 @@ class StartupCommandService
$replace[] = ($variable->user_viewable && !$hideAllValues) ? ($variable->server_value ?? $variable->default_value) : '[hidden]'; $replace[] = ($variable->user_viewable && !$hideAllValues) ? ($variable->server_value ?? $variable->default_value) : '[hidden]';
} }
return str_replace($find, $replace, $server->startup); return str_replace($find, $replace, $startup);
} }
} }

View File

@ -85,8 +85,8 @@ class StartupModificationService
]); ]);
// Fill missing fields from egg // Fill missing fields from egg
$data['docker_image'] = $data['docker_image'] ?? collect($egg->docker_images)->first(); $data['docker_image'] ??= Arr::first($egg->docker_images);
$data['startup'] = $data['startup'] ?? $egg->startup; $data['startup'] ??= Arr::first($egg->startup_commands);
} }
$server->fill([ $server->fill([

View File

@ -48,10 +48,7 @@ class EggTransformer extends BaseTransformer
'description' => $model->description, 'description' => $model->description,
'features' => $model->features, 'features' => $model->features,
'tags' => $model->tags, 'tags' => $model->tags,
// "docker_image" is deprecated, but left here to avoid breaking too many things at once 'docker_image' => Arr::first($model->docker_images, default: ''), // docker_images, use startup_commands
// in external software. We'll remove it down the road once things have gotten the chance
// to upgrade to using "docker_images".
'docker_image' => count($model->docker_images) > 0 ? Arr::first($model->docker_images) : '',
'docker_images' => $model->docker_images, 'docker_images' => $model->docker_images,
'config' => [ 'config' => [
'files' => $files, 'files' => $files,
@ -61,7 +58,8 @@ class EggTransformer extends BaseTransformer
'file_denylist' => $model->inherit_file_denylist, 'file_denylist' => $model->inherit_file_denylist,
'extends' => $model->config_from, 'extends' => $model->config_from,
], ],
'startup' => $model->startup, 'startup' => Arr::first($model->startup_commands, default: ''), // deprecated, use startup_commands
'startup_commands' => $model->startup_commands,
'script' => [ 'script' => [
'privileged' => $model->script_is_privileged, 'privileged' => $model->script_is_privileged,
'install' => $model->copy_script_install, 'install' => $model->copy_script_install,

View File

@ -60,7 +60,7 @@ class ServerTransformer extends BaseClientTransformer
'oom_disabled' => !$server->oom_killer, 'oom_disabled' => !$server->oom_killer,
'oom_killer' => $server->oom_killer, 'oom_killer' => $server->oom_killer,
], ],
'invocation' => $service->handle($server, !$user->can(Permission::ACTION_STARTUP_READ, $server)), 'invocation' => $service->handle($server, hideAllValues: !$user->can(Permission::ACTION_STARTUP_READ, $server)),
'docker_image' => $server->image, 'docker_image' => $server->image,
'egg_features' => $server->egg->inherit_features, 'egg_features' => $server->egg->inherit_features,
'feature_limits' => [ 'feature_limits' => [

View File

@ -30,7 +30,7 @@ class EggFactory extends Factory
'config_files' => '{}', 'config_files' => '{}',
'name' => $this->faker->name(), 'name' => $this->faker->name(),
'description' => implode(' ', $this->faker->sentences()), 'description' => implode(' ', $this->faker->sentences()),
'startup' => 'java -jar test.jar', 'startup_commands' => ['java -jar test.jar'],
]; ];
} }
} }

View File

@ -1,8 +1,8 @@
_comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL' _comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL'
meta: meta:
version: PLCN_v2 version: PLCN_v3
update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/minecraft/egg-bungeecord.yaml' update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/minecraft/egg-bungeecord.yaml'
exported_at: '2025-07-25T13:32:34+00:00' exported_at: '2025-09-05T08:54:34+00:00'
name: Bungeecord name: Bungeecord
author: panel@example.com author: panel@example.com
uuid: 9e6b409e-4028-4947-aea8-50a2c404c271 uuid: 9e6b409e-4028-4947-aea8-50a2c404c271
@ -26,7 +26,8 @@ docker_images:
'Java 11': 'ghcr.io/parkervcp/yolks:java_11' 'Java 11': 'ghcr.io/parkervcp/yolks:java_11'
'Java 8': 'ghcr.io/parkervcp/yolks:java_8' 'Java 8': 'ghcr.io/parkervcp/yolks:java_8'
file_denylist: { } file_denylist: { }
startup: 'java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}' startup_commands:
Default: 'java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}'
config: config:
files: files:
config.yml: config.yml:

View File

@ -1,8 +1,8 @@
_comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL' _comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL'
meta: meta:
version: PLCN_v2 version: PLCN_v3
update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/minecraft/egg-forge-minecraft.yaml' update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/minecraft/egg-forge-minecraft.yaml'
exported_at: '2025-08-05T21:00:17+00:00' exported_at: '2025-09-05T08:54:45+00:00'
name: 'Forge Minecraft' name: 'Forge Minecraft'
author: panel@example.com author: panel@example.com
uuid: ed072427-f209-4603-875c-f540c6dd5a65 uuid: ed072427-f209-4603-875c-f540c6dd5a65
@ -22,7 +22,8 @@ docker_images:
'Java 11': 'ghcr.io/parkervcp/yolks:java_11' 'Java 11': 'ghcr.io/parkervcp/yolks:java_11'
'Java 8': 'ghcr.io/parkervcp/yolks:java_8' 'Java 8': 'ghcr.io/parkervcp/yolks:java_8'
file_denylist: { } file_denylist: { }
startup: 'java -Xms128M -XX:MaxRAMPercentage=95.0 -Dterminal.jline=false -Dterminal.ansi=true $( [[ ! -f unix_args.txt ]] && printf %s "-jar {{SERVER_JARFILE}}" || printf %s "@unix_args.txt" )' startup_commands:
Default: 'java -Xms128M -XX:MaxRAMPercentage=95.0 -Dterminal.jline=false -Dterminal.ansi=true $( [[ ! -f unix_args.txt ]] && printf %s "-jar {{SERVER_JARFILE}}" || printf %s "@unix_args.txt" )'
config: config:
files: files:
server.properties: server.properties:

View File

@ -1,8 +1,8 @@
_comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL' _comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL'
meta: meta:
version: PLCN_v2 version: PLCN_v3
update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/minecraft/egg-paper.yaml' update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/minecraft/egg-paper.yaml'
exported_at: '2025-08-05T21:00:17+00:00' exported_at: '2025-09-05T08:54:10+00:00'
name: Paper name: Paper
author: parker@example.com author: parker@example.com
uuid: 5da37ef6-58da-4169-90a6-e683e1721247 uuid: 5da37ef6-58da-4169-90a6-e683e1721247
@ -20,7 +20,8 @@ docker_images:
'Java 11': 'ghcr.io/parkervcp/yolks:java_11' 'Java 11': 'ghcr.io/parkervcp/yolks:java_11'
'Java 8': 'ghcr.io/parkervcp/yolks:java_8' 'Java 8': 'ghcr.io/parkervcp/yolks:java_8'
file_denylist: { } file_denylist: { }
startup: 'java -Xms128M -XX:MaxRAMPercentage=95.0 -Dterminal.jline=false -Dterminal.ansi=true -jar {{SERVER_JARFILE}}' startup_commands:
Default: 'java -Xms128M -XX:MaxRAMPercentage=95.0 -Dterminal.jline=false -Dterminal.ansi=true -jar {{SERVER_JARFILE}}'
config: config:
files: files:
server.properties: server.properties:

View File

@ -1,8 +1,8 @@
_comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL' _comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL'
meta: meta:
version: PLCN_v2 version: PLCN_v3
update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/minecraft/egg-sponge--sponge-vanilla.yaml' update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/minecraft/egg-sponge.yaml'
exported_at: '2025-08-05T21:00:17+00:00' exported_at: '2025-09-12T08:38:42+00:00'
name: Sponge name: Sponge
author: panel@example.com author: panel@example.com
uuid: f0d2f88f-1ff3-42a0-b03f-ac44c5571e6d uuid: f0d2f88f-1ff3-42a0-b03f-ac44c5571e6d
@ -20,7 +20,8 @@ docker_images:
'Java 11': 'ghcr.io/parkervcp/yolks:java_11' 'Java 11': 'ghcr.io/parkervcp/yolks:java_11'
'Java 8': 'ghcr.io/parkervcp/yolks:java_8' 'Java 8': 'ghcr.io/parkervcp/yolks:java_8'
file_denylist: { } file_denylist: { }
startup: 'java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}' startup_commands:
Default: 'java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}'
config: config:
files: files:
server.properties: server.properties:

View File

@ -1,8 +1,8 @@
_comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL' _comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL'
meta: meta:
version: PLCN_v2 version: PLCN_v3
update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/minecraft/egg-vanilla-minecraft.yaml' update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/minecraft/egg-vanilla-minecraft.yaml'
exported_at: '2025-08-05T20:59:51+00:00' exported_at: '2025-09-05T08:55:10+00:00'
name: 'Vanilla Minecraft' name: 'Vanilla Minecraft'
author: panel@example.com author: panel@example.com
uuid: 9ac39f3d-0c34-4d93-8174-c52ab9e6c57b uuid: 9ac39f3d-0c34-4d93-8174-c52ab9e6c57b
@ -24,7 +24,8 @@ docker_images:
'Java 11': 'ghcr.io/parkervcp/yolks:java_11' 'Java 11': 'ghcr.io/parkervcp/yolks:java_11'
'Java 8': 'ghcr.io/parkervcp/yolks:java_8' 'Java 8': 'ghcr.io/parkervcp/yolks:java_8'
file_denylist: { } file_denylist: { }
startup: 'java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}' startup_commands:
Default: 'java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}'
config: config:
files: files:
server.properties: server.properties:

View File

@ -1,8 +1,8 @@
_comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL' _comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL'
meta: meta:
version: PLCN_v2 version: PLCN_v3
update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/rust/egg-rust.yaml' update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/rust/egg-rust.yaml'
exported_at: '2025-07-25T13:30:56+00:00' exported_at: '2025-09-05T08:56:17+00:00'
name: Rust name: Rust
author: panel@example.com author: panel@example.com
uuid: bace2dfb-209c-452a-9459-7d6f340b07ae uuid: bace2dfb-209c-452a-9459-7d6f340b07ae
@ -17,9 +17,10 @@ tags:
features: features:
- steam_disk_space - steam_disk_space
docker_images: docker_images:
'ghcr.io/parkervcp/games:rust': 'ghcr.io/parkervcp/games:rust' Rust: 'ghcr.io/parkervcp/games:rust'
file_denylist: { } file_denylist: { }
startup: './RustDedicated -batchmode +server.port {{SERVER_PORT}} +server.queryport {{QUERY_PORT}} +server.identity "rust" +rcon.port {{RCON_PORT}} +rcon.web true +server.hostname \"{{SERVER_HOSTNAME}}\" +server.level \"{{LEVEL}}\" +server.description \"{{DESCRIPTION}}\" +server.url \"{{SERVER_URL}}\" +server.headerimage \"{{SERVER_IMG}}\" +server.logoimage \"{{SERVER_LOGO}}\" +server.maxplayers {{MAX_PLAYERS}} +rcon.password \"{{RCON_PASS}}\" +server.saveinterval {{SAVEINTERVAL}} +app.port {{APP_PORT}} $( [ -z ${MAP_URL} ] && printf %s "+server.worldsize \"{{WORLD_SIZE}}\" +server.seed \"{{WORLD_SEED}}\"" || printf %s "+server.levelurl {{MAP_URL}}" ) {{ADDITIONAL_ARGS}}' startup_commands:
Default: './RustDedicated -batchmode +server.port {{SERVER_PORT}} +server.queryport {{QUERY_PORT}} +server.identity "rust" +rcon.port {{RCON_PORT}} +rcon.web true +server.hostname \"{{SERVER_HOSTNAME}}\" +server.level \"{{LEVEL}}\" +server.description \"{{DESCRIPTION}}\" +server.url \"{{SERVER_URL}}\" +server.headerimage \"{{SERVER_IMG}}\" +server.logoimage \"{{SERVER_LOGO}}\" +server.maxplayers {{MAX_PLAYERS}} +rcon.password \"{{RCON_PASS}}\" +server.saveinterval {{SAVEINTERVAL}} +app.port {{APP_PORT}} $( [ -z ${MAP_URL} ] && printf %s "+server.worldsize \"{{WORLD_SIZE}}\" +server.seed \"{{WORLD_SEED}}\"" || printf %s "+server.levelurl {{MAP_URL}}" ) {{ADDITIONAL_ARGS}}'
config: config:
files: { } files: { }
startup: startup:

View File

@ -1,8 +1,8 @@
_comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL' _comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL'
meta: meta:
version: PLCN_v2 version: PLCN_v3
update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/source-engine/egg-custom-source-engine-game.yaml' update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/source-engine/egg-custom-source-engine-game.yaml'
exported_at: '2025-07-25T13:30:23+00:00' exported_at: '2025-09-05T08:55:22+00:00'
name: 'Custom Source Engine Game' name: 'Custom Source Engine Game'
author: panel@example.com author: panel@example.com
uuid: 2a42d0c2-c0ba-4067-9a0a-9b95d77a3490 uuid: 2a42d0c2-c0ba-4067-9a0a-9b95d77a3490
@ -15,9 +15,10 @@ tags:
features: features:
- steam_disk_space - steam_disk_space
docker_images: docker_images:
'ghcr.io/parkervcp/games:source': 'ghcr.io/parkervcp/games:source' Source: 'ghcr.io/parkervcp/games:source'
file_denylist: { } file_denylist: { }
startup: './srcds_run -game {{SRCDS_GAME}} -console -port {{SERVER_PORT}} +map {{SRCDS_MAP}} +ip 0.0.0.0 -strictportbind -norestart' startup_commands:
Default: './srcds_run -game {{SRCDS_GAME}} -console -port {{SERVER_PORT}} +map {{SRCDS_MAP}} +ip 0.0.0.0 -strictportbind -norestart'
config: config:
files: { } files: { }
startup: startup:

View File

@ -1,8 +1,8 @@
_comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL' _comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL'
meta: meta:
version: PLCN_v2 version: PLCN_v3
update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/source-engine/egg-garrys-mod.yaml' update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/source-engine/egg-garrys-mod.yaml'
exported_at: '2025-07-25T13:30:30+00:00' exported_at: '2025-09-05T08:54:21+00:00'
name: 'Garrys Mod' name: 'Garrys Mod'
author: panel@example.com author: panel@example.com
uuid: 60ef81d4-30a2-4d98-ab64-f59c69e2f915 uuid: 60ef81d4-30a2-4d98-ab64-f59c69e2f915
@ -16,9 +16,10 @@ features:
- gsl_token - gsl_token
- steam_disk_space - steam_disk_space
docker_images: docker_images:
'ghcr.io/parkervcp/games:source': 'ghcr.io/parkervcp/games:source' Source: 'ghcr.io/parkervcp/games:source'
file_denylist: { } file_denylist: { }
startup: './srcds_run -game garrysmod -console -port {{SERVER_PORT}} +ip 0.0.0.0 +host_workshop_collection {{WORKSHOP_ID}} +map {{SRCDS_MAP}} +gamemode {{GAMEMODE}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}} +maxplayers {{MAX_PLAYERS}} -tickrate {{TICKRATE}} $( [ "$LUA_REFRESH" == "1" ] || printf %s ''-disableluarefresh'' )' startup_commands:
Default: './srcds_run -game garrysmod -console -port {{SERVER_PORT}} +ip 0.0.0.0 +host_workshop_collection {{WORKSHOP_ID}} +map {{SRCDS_MAP}} +gamemode {{GAMEMODE}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}} +maxplayers {{MAX_PLAYERS}} -tickrate {{TICKRATE}} $( [ "$LUA_REFRESH" == "1" ] || printf %s ''-disableluarefresh'' )'
config: config:
files: { } files: { }
startup: startup:

View File

@ -1,8 +1,8 @@
_comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL' _comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL'
meta: meta:
version: PLCN_v2 version: PLCN_v3
update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/source-engine/egg-insurgency.yaml' update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/source-engine/egg-insurgency.yaml'
exported_at: '2025-07-25T13:30:35+00:00' exported_at: '2025-09-05T08:55:34+00:00'
name: Insurgency name: Insurgency
author: panel@example.com author: panel@example.com
uuid: a5702286-655b-4069-bf1e-925c7300b61a uuid: a5702286-655b-4069-bf1e-925c7300b61a
@ -16,9 +16,10 @@ tags:
features: features:
- steam_disk_space - steam_disk_space
docker_images: docker_images:
'ghcr.io/parkervcp/games:source': 'ghcr.io/parkervcp/games:source' Source: 'ghcr.io/parkervcp/games:source'
file_denylist: { } file_denylist: { }
startup: './srcds_run -game insurgency -console -port {{SERVER_PORT}} +map {{SRCDS_MAP}} +ip 0.0.0.0 -strictportbind -norestart' startup_commands:
Default: './srcds_run -game insurgency -console -port {{SERVER_PORT}} +map {{SRCDS_MAP}} +ip 0.0.0.0 -strictportbind -norestart'
config: config:
files: { } files: { }
startup: startup:

View File

@ -1,8 +1,8 @@
_comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL' _comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL'
meta: meta:
version: PLCN_v2 version: PLCN_v3
update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/source-engine/egg-team-fortress2.yaml' update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/source-engine/egg-team-fortress2.yaml'
exported_at: '2025-07-25T13:30:44+00:00' exported_at: '2025-09-05T08:55:44+00:00'
name: 'Team Fortress 2' name: 'Team Fortress 2'
author: panel@example.com author: panel@example.com
uuid: 7f8eb681-b2c8-4bf8-b9f4-d79ff70b6e5d uuid: 7f8eb681-b2c8-4bf8-b9f4-d79ff70b6e5d
@ -16,9 +16,10 @@ features:
- gsl_token - gsl_token
- steam_disk_space - steam_disk_space
docker_images: docker_images:
'ghcr.io/parkervcp/games:source': 'ghcr.io/parkervcp/games:source' Source: 'ghcr.io/parkervcp/games:source'
file_denylist: { } file_denylist: { }
startup: './srcds_run -game tf -console -port {{SERVER_PORT}} +map {{SRCDS_MAP}} +ip 0.0.0.0 -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}}' startup_commands:
Default: './srcds_run -game tf -console -port {{SERVER_PORT}} +map {{SRCDS_MAP}} +ip 0.0.0.0 -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}}'
config: config:
files: { } files: { }
startup: startup:

View File

@ -1,8 +1,8 @@
_comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL' _comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL'
meta: meta:
version: PLCN_v2 version: PLCN_v3
update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/voice-servers/egg-mumble-server.yaml' update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/voice-servers/egg-mumble-server.yaml'
exported_at: '2025-07-25T13:30:48+00:00' exported_at: '2025-09-05T08:55:54+00:00'
name: 'Mumble Server' name: 'Mumble Server'
author: panel@example.com author: panel@example.com
uuid: 727ee758-7fb2-4979-972b-d3eba4e1e9f0 uuid: 727ee758-7fb2-4979-972b-d3eba4e1e9f0
@ -15,7 +15,8 @@ features: { }
docker_images: docker_images:
Mumble: 'ghcr.io/parkervcp/yolks:voice_mumble' Mumble: 'ghcr.io/parkervcp/yolks:voice_mumble'
file_denylist: { } file_denylist: { }
startup: 'mumble-server -fg -ini murmur.ini' startup_commands:
Default: 'mumble-server -fg -ini murmur.ini'
config: config:
files: files:
murmur.ini: murmur.ini:

View File

@ -1,8 +1,8 @@
_comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL' _comment: 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PANEL'
meta: meta:
version: PLCN_v2 version: PLCN_v3
update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/voice-servers/egg-teamspeak3-server.yaml' update_url: 'https://github.com/pelican-dev/panel/raw/main/database/Seeders/eggs/voice-servers/egg-teamspeak3-server.yaml'
exported_at: '2025-07-25T13:30:53+00:00' exported_at: '2025-09-05T08:56:06+00:00'
name: 'Teamspeak3 Server' name: 'Teamspeak3 Server'
author: panel@example.com author: panel@example.com
uuid: 983b1fac-d322-4d5f-a636-436127326b37 uuid: 983b1fac-d322-4d5f-a636-436127326b37
@ -15,7 +15,8 @@ features: { }
docker_images: docker_images:
Debian: 'ghcr.io/parkervcp/yolks:debian' Debian: 'ghcr.io/parkervcp/yolks:debian'
file_denylist: { } file_denylist: { }
startup: './ts3server default_voice_port={{SERVER_PORT}} query_port={{QUERY_PORT}} filetransfer_ip=0.0.0.0 filetransfer_port={{FILE_TRANSFER}} query_http_port={{QUERY_HTTP}} query_ssh_port={{QUERY_SSH}} query_protocols={{QUERY_PROTOCOLS_VAR}} license_accepted=1' startup_commands:
Default: './ts3server default_voice_port={{SERVER_PORT}} query_port={{QUERY_PORT}} filetransfer_ip=0.0.0.0 filetransfer_port={{FILE_TRANSFER}} query_http_port={{QUERY_HTTP}} query_ssh_port={{QUERY_SSH}} query_protocols={{QUERY_PROTOCOLS_VAR}} license_accepted=1'
config: config:
files: { } files: { }
startup: startup:

View File

@ -0,0 +1,50 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('eggs', function (Blueprint $table) {
$table->json('startup_commands')->after('startup')->nullable();
});
DB::table('eggs')->select(['id', 'startup'])->cursor()->each(function ($egg) {
DB::table('eggs')->where('id', $egg->id)->update(['startup_commands' => json_encode(['Default' => $egg->startup], JSON_UNESCAPED_SLASHES)]);
});
Schema::table('eggs', function (Blueprint $table) {
$table->dropColumn('startup');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
DB::transaction(function () {
Schema::table('eggs', function (Blueprint $table) {
$table->text('startup')->after('startup_commands');
});
DB::table('eggs')->select(['id', 'startup_commands'])->cursor()->each(function ($egg) {
DB::table('eggs')->where('id', $egg->id)->update([
'startup' => Arr::first(json_decode($egg->startup_commands, true, 512, JSON_THROW_ON_ERROR)),
]);
});
Schema::table('eggs', function (Blueprint $table) {
$table->dropColumn('startup_commands');
});
});
}
};

View File

@ -112,6 +112,7 @@ return [
'startup' => [ 'startup' => [
'edit' => 'Changed the <b>:variable</b> variable from "<b>:old</b>" to "<b>:new</b>"', 'edit' => 'Changed the <b>:variable</b> variable from "<b>:old</b>" to "<b>:new</b>"',
'image' => 'Updated the Docker Image for the server from <b>:old</b> to <b>:new</b>', 'image' => 'Updated the Docker Image for the server from <b>:old</b> to <b>:new</b>',
'command' => 'Updated the Startup Command for the server from <b>:old</b> to <b>:new</b>',
], ],
'subuser' => [ 'subuser' => [
'create' => 'Added <b>:email</b> as a subuser', 'create' => 'Added <b>:email</b> as a subuser',

View File

@ -37,8 +37,11 @@ return [
'author_help_edit' => 'The author of this version of the Egg. Uploading a new configuration from a different author will change this.', 'author_help_edit' => 'The author of this version of the Egg. Uploading a new configuration from a different author will change this.',
'description' => 'Description', 'description' => 'Description',
'description_help' => 'A description of this Egg that will be displayed throughout the Panel as needed.', 'description_help' => 'A description of this Egg that will be displayed throughout the Panel as needed.',
'startup' => 'Startup Command', 'add_startup' => 'Add Startup Command',
'startup_help' => 'The default startup command that should be used for new servers using this Egg.', 'startup_command' => 'Command',
'startup_commands' => 'Startup Commands',
'startup_name' => 'Display Name',
'startup_help' => 'The startup commands available to servers using this Egg. The first one is the default.',
'file_denylist' => 'File Denylist', 'file_denylist' => 'File Denylist',
'file_denylist_help' => 'A list of files that the end user is not allowed to edit.', 'file_denylist_help' => 'A list of files that the end user is not allowed to edit.',
'features' => 'Features', 'features' => 'Features',
@ -51,7 +54,7 @@ return [
'docker_images' => 'Docker Images', 'docker_images' => 'Docker Images',
'docker_name' => 'Image Name', 'docker_name' => 'Image Name',
'docker_uri' => 'Image URI', 'docker_uri' => 'Image URI',
'docker_help' => 'The docker images available to servers using this Egg.', 'docker_help' => 'The docker images available to servers using this Egg. The first one is the default.',
'stop_command' => 'Stop Command', 'stop_command' => 'Stop Command',
'stop_command_help' => 'The command that should be sent to server processes to stop them gracefully. If you need to send a SIGINT you should enter ^C here.', 'stop_command_help' => 'The command that should be sent to server processes to stop them gracefully. If you need to send a SIGINT you should enter ^C here.',

View File

@ -26,7 +26,9 @@ return [
'already_primary' => 'Already Primary', 'already_primary' => 'Already Primary',
'make_primary' => 'Make Primary', 'make_primary' => 'Make Primary',
'startup_cmd' => 'Startup Command', 'startup_cmd' => 'Startup Command',
'startup_name' => 'Startup Name',
'default_startup' => 'Default Startup Command', 'default_startup' => 'Default Startup Command',
'startup_placeholder' => 'Enter a custom startup command',
'variables' => 'Variables', 'variables' => 'Variables',
'resource_limits' => 'Resource Limits', 'resource_limits' => 'Resource Limits',
'cpu' => 'CPU', 'cpu' => 'CPU',

View File

@ -3,7 +3,10 @@
return [ return [
'title' => 'Startup', 'title' => 'Startup',
'command' => 'Startup Command', 'command' => 'Startup Command',
'preview' => 'Preview', 'notification_startup' => 'Startup Command Updated',
'notification_startup_body' => 'Restart the server to use the new startup command.',
'enable_preview' => 'Enable Preview',
'disable_preview' => 'Disable Preview',
'docker_image' => 'Docker Image', 'docker_image' => 'Docker Image',
'notification_docker' => 'Docker Image Updated', 'notification_docker' => 'Docker Image Updated',
'notification_docker_body' => 'Restart the server to use the new image.', 'notification_docker_body' => 'Restart the server to use the new image.',