Block Generation Machine is an experimental ore generator plugin for Axolotl-PM. Its plugin manifest names the runtime plugin OreGenerator.
The plugin packages the released NhanAZ BlockData library through DevTools. The source passes PHPStan at maximum level against both the declared API minimum and the newer revision pinned in CI. An isolated Axolotl-PM 5.49.1 test verified first-join delivery, reconnect persistence, placement and configured block regeneration. These checks do not establish compatibility with every 5.x release, configuration, or production world. Stable artifacts are published through GitHub Releases.
The manifest declares plugin API 5.0.0. The PHAR from CI run 38389853376 loaded and enabled using the Axolotl-PM 5.0.0 source revision; the isolated server exited 0 after normal shutdown. The PHP 8.4.24 test printed deprecation notices from the older server's Symfony filesystem code and World::useBreak(); no OreGenerator error was logged. Connected gameplay checks above used Axolotl-PM 5.49.1 only. These results do not establish support for intermediate 5.x releases or gameplay on 5.0.0. Keep production worlds and plugin data separate from migration tests.
- Give a configured generator item only when a player joins for the first time.
- Store generator metadata in the stonecutter item's custom block data and at its placed block position.
- Choose an ore from the configured weights and regenerate it after the configured delay when a generated block is broken. Skip regeneration if the generator or its original metadata is gone before the delay ends.
- Play optional sounds for invalid placement and new resources.
The data migration has been checked with a synthetic legacy LevelDB database and an isolated server restart. Synthetic server events also covered placement, breaking, and regeneration. A separate event fixture checks that a pending regeneration skips a removed generator or replaced metadata.
A connected first join delivered the configured item. After a server restart, saved player data and a returning headless client's inventory packet each contained one generator with the expected name and count. When that client placed the item, its inventory slot emptied, the client received updates for the placed stonecutter and the cobblestone above it, and the plugin stored generator metadata at the placed position. The same client then broke the cobblestone; block updates showed air followed by the configured stone while the generator metadata remained stored.
In a separate isolated session, the client broke the resource and then the generator before a ten-second regeneration delay ended. It received air updates for both positions and no later ore update during the observed interval. This verifies the tested level 1 paths, not every ore weight, world, or player interaction.
In another isolated session, a connected player placed a level 2 generator item. The world then contained a stonecutter and its initial cobblestone, while storage retained the item's owner, level, and durability. A separate connected-player check used the same verified plugin PHAR with a disposable level 2 generator record. Its test configuration assigned all valid ore weight to diamond_block. After the recorded owner broke the existing cobblestone, the client received an air update followed by a resource update, and the server confirmed a diamond block above the intact generator. The level 2 owner and metadata remained stored. These checks cover one level 2 placement and one configured regeneration path; they do not measure weighted distribution or validate other configurations.
With ownerMode: true, placement and breaking of the machine or its resource require the recorded owner; ownerMode: false permits shared use. A missing or invalid owner mode is treated as protected. Source fixtures cover these decisions. On an isolated server with ownerMode: true, a connected non-owner could neither place an owner-marked generator item nor break an existing generator or its resource; the owner could break both blocks.
In a separate shared-mode session, a connected non-owner broke the resource and machine; the dropped generator item kept its recorded owner, level, and durability metadata. The non-owner then placed an item bearing the original owner's metadata; the machine and resource appeared, and the stored metadata retained that owner. These connected checks cover the tested level 1 configuration, not every world or player interaction. The durability value is stored but wear is not enforced.
The defaults in resources/config.yml define firstJoin.amount, firstJoin.level, customName, defaultBlock, sound switches, and oreGenerators.level_* ore weights and delays. Setting firstJoin.amount to 0 disables the first-join grant. delayTime is a positive whole number of seconds. Invalid values skip regeneration and produce a warning. There are no commands or permissions in plugin.yml.
Ore weights must be positive whole numbers. Decimal integer strings within range are accepted. Noninteger and nonpositive entries are ignored. If a level has no valid weights, or a weight or their sum exceeds the integer range, no ore is selected. Check each configured level before enabling the experimental generator.
Generator item metadata uses a legacy string such as isOreGenerator:true owner:NhanAZ level:1 durability:1000. The parser treats malformed values and an explicit false flag as non-generators. It also accepts spaces in a player's name.
The original Cosmoverse BlockData virion stores NBT values. The NhanAZ BlockData library stores JSON values. Both use the same per-world LevelDB path and block key pattern, so opening the old database directly with the new library could overwrite records.
The plugin keeps the old blockdata/<world> database and writes new records to blockdata-json/<world>. When a generator position is first read, it decodes the old NBT record and saves its metadata in the new database. A deletion marker in the new database prevents an old record from reappearing after the generator is broken. The plugin code never calls write or delete on the old database. Keep a backup of plugin data before upgrading a production world. The tested migration used only a synthetic database, not a copy of a production world.
The PHAR contains the project GPL-3.0 license and the BlockData virion LGPL notice. The old Cosmoverse virion is not bundled. The legacy migration reader was added in NhanAZ-authored commits and reads existing records without including Cosmoverse source code in the plugin or its artifact.
The focused PHP fixtures can run without a server.
php tests/parser-data.php
php tests/first-join.php
php tests/weighted-ore-selector.php
php tests/default-block.php
php tests/legacy-storage.php virions/BlockData/vendor/autoload.php
php tests/owner-placement.php
php tests/generator-removal.phpThe legacy storage fixture needs the released BlockData checkout and its Composer dependencies. The workflow checks these fixtures, PHPStan max, and a DevTools PHAR build, then uploads the verified PHAR as a temporary CI artifact. The isolated server probe verified exact NBT decoding, JSON persistence, deletion markers, restart behavior, retention of the old record, and synthetic placement and break events. A separate connected-player probe verified first-join delivery, inventory restoration, placement, item consumption, and one cobblestone break and stone regeneration using the CI PHAR. The block runtime IDs were resolved against the pinned server's canonical palette, and the generator's LevelDB metadata was read after the test.
This repository contains the GNU GPL version 3 license. Preserve notices for any dependency used in a future build. For project support, visit NhanAZ Discord.