Configuration and packaged resources
Put default configuration and other server-side files in your project’s
resources/ directory. Bedriox exposes them through the plugin-bound data
capability and keeps editable copies under plugin_data/<PluginName>/.
These resources are files for the server and plugin. They are not Minecraft client resource packs.
Start with a packaged default
For a project named TownTools, a basic layout looks like this:
TownTools/
├── plugin.json
├── resources/
│ ├── config.yml
│ └── messages.yml
└── src/
└── Main.php
The simplest way to open the conventional config.yml is:
$config = $this->context()->data()->config();
If plugin_data/TownTools/config.yml does not exist and the plugin packages
resources/config.yml, config() copies that default first. If neither file
exists, Bedriox creates an empty configuration map.
Use saveResource() when you want to install a particular packaged file
explicitly:
$data = $this->context()->data();
$installed = $data->saveResource('messages.yml');
$this->logger()->debug(
$installed ? 'Installed the default messages file.' : 'Kept the existing messages file.',
);
The first call returns true when it copies the resource. Later calls return
false because the administrator’s existing file is preserved. Do not pass
replace: true on every startup; that would deliberately replace their edits.
Read typed settings
Configuration keys use dots to walk through nested maps. Given:
join:
enabled: true
message: "{player} joined the server"
rewards:
amount: 3
multiplier: 1.5
items:
- minecraft:bread
- minecraft:torch
read each setting with the type the file is expected to contain:
$config = $this->context()->data()->config();
$enabled = $config->getBool('join.enabled', true);
$message = $config->getString('join.message', '{player} joined the server');
$amount = $config->getInt('rewards.amount', 1);
$multiplier = $config->getFloat('rewards.multiplier', 1.0);
$items = $config->getList('rewards.items', []);
Defaults apply when a key is missing. Typed getters do not silently coerce a
wrong value: the string "true" is not a boolean, and asking for it with
getBool() throws PluginDataException. This makes an invalid administrator
edit visible instead of quietly changing plugin behavior.
The complete reading surface is:
has($key)checks whether a key exists, even when its value isnull.get($key, $default)returns a value without asserting its type.getString(),getInt(),getFloat(), andgetBool()enforce scalar types.getList()requires an indexed list.getMap()requires a string-keyed map.all()returns the complete in-memory configuration map.
Prefer a typed getter whenever the expected shape is known. Treat configuration as untrusted input and still validate application-specific rules such as ranges, identifier formats, list length, and allowed choices.
Save changes
set() and remove() change the in-memory map. Call save() to write the
complete updated configuration atomically:
$config = $this->context()->data()->config();
$config->set('join.enabled', false);
$config->set('rewards.items', ['minecraft:apple', 'minecraft:bread']);
$config->remove('legacy-setting');
$config->save();
Use dot-separated keys with set() too. A key cannot cross through a scalar;
for example, setting join.message.text fails when join.message is already a
string.
Reload administrator edits
A Configuration object keeps an in-memory snapshot. If an administrator edits
the file while the server is running, reload it before reading the new values:
$config = $this->context()->data()->config();
$config->reload();
$enabled = $config->getBool('join.enabled', true);
Reload before a read-modify-save operation when an external edit may have
happened, otherwise save() writes the plugin’s current in-memory map.
Use more than one configuration file
Bedriox accepts YAML, YML, and JSON configuration files:
$data = $this->context()->data();
$main = $data->config();
$messages = $data->config('messages.yml');
$storage = $data->config('storage.json');
Each file must decode to a string-keyed root map. Configuration sizes and
structures are bounded, invalid UTF-8 and unsupported PHP values are rejected,
and malformed YAML or JSON throws PluginDataException.
Read or copy other resources
Resources may be nested below resources/:
$data = $this->context()->data();
if ($data->hasResource('language/en_US.yml')) {
$contents = $data->readResource('language/en_US.yml');
$this->logger()->debug('Loaded the packaged English message catalog.');
}
$copiedFiles = $data->saveResources();
$this->logger()->debug("Installed {$copiedFiles} missing resource file(s).");
readResource() reads the packaged, read-only copy as a string; it does not
read the administrator’s data-directory copy. saveResources() attempts every
packaged resource and returns the number newly copied. By default it preserves
every existing file.
path() returns this plugin’s data-directory root for a custom bounded format
that config() does not support. Build paths only from names controlled by the
plugin, never directly from player input, and keep all data inside that root.
Handle invalid configuration clearly
Configuration and resource failures use PluginDataException. Required
configuration can fail plugin enablement rather than leaving partially
registered behavior running:
use Bedriox\Api\Plugin\Data\PluginDataException;
try {
$config = $this->context()->data()->config();
$maximumHomes = $config->getInt('homes.maximum', 3);
if ($maximumHomes < 0 || $maximumHomes > 100) {
throw new PluginDataException('homes.maximum must be between 0 and 100.');
}
} catch (PluginDataException $failure) {
$this->logger()->error('TownTools configuration is invalid: ' . $failure->getMessage());
throw $failure;
}
Never log an entire configuration file: it may contain credentials or other private administrator values. Packaged defaults committed to a plugin repository must not contain secrets.
The source-derived section below shows the exact configuration currently used by ExamplePlugin.
ExamplePlugin’s real configuration
The generator reads these examples from the exact ExamplePlugin revision used for this documentation. They are not hand-copied snippets.
Open resources/config.yml · Open src/Main.php
join:
enabled: true
message: "{player} joined this Bedriox server"Install the packaged default
$this->context()->data()->saveResource('config.yml');Read it in a listener
#[\Bedriox\Api\Event\EventHandler]
public function onJoin(\Bedriox\Api\Event\Player\PlayerJoinEvent $event): void
{
$config = $this->context()->data()->config();
if (!$config->getBool('join.enabled', true)) {
$event->setJoinMessage(null);
return;
}
$event->setJoinMessage(\Bedriox\Api\TextFormat::YELLOW . str_replace('{player}', $event->player->name, $config->getString('join.message', '{player} joined the server')) . \Bedriox\Api\TextFormat::RESET);
}PluginData, Configuration, and PluginDataException for every method and signature.