Changelog for Bedrock Energistics Core and the Bedrock Energistics Core API package.
The add-on and the API package are now one release. As of v0.12.0 they share a single version number and ship together.
Requires Minecraft 26.30 or newer (was 26.0). The API package's peer dependencies are @minecraft/server ^2.8.0 (was ^2.5.0) and @minecraft/vanilla-data >=1.26.30 (was >=1.26.2).
This version is not compatible with earlier releases of either half. An add-on bundling an older API package will not work with this add-on, and vice versa.
Breaking Changes
Errors
- Failures caused by the calling add-on now propagate to it instead of being logged by the core pack and answered with
null. - Every API function that can throw a
PublicErrordocuments whichPublicErrorTypes it raises, including theInvalidStateraised when a function that needs the core pack is called beforeinit.
API Renames
| Before | After |
|---|---|
MachineOnStorageSetEvent |
MachineOnStorageSetEventArg |
MachineRecieveHandlerArg |
MachineReceiveHandlerArg |
RecieveHandlerResponse |
MachineReceiveHandlerRes |
MachineUpdateUiHandlerResponse |
MachineUpdateUiHandlerRes |
NetworkStatsEventArg |
MachineNetworkStatsEventArg |
IoCapabilities#acceptsType |
IoCapabilities#acceptsTypeData |
IoCapabilities#acceptsTypeWithId |
IoCapabilities#acceptsTypeId |
IoCapabilities.fromMachine |
IoCapabilities.fromBlock |
MachineNetworkStatsEventArg.networkData |
MachineNetworkStatsEventArg.allocationData |
API Signature Changes
setMachineSlotItemreturnsPromise<boolean>instead ofPromise<void>, and takesMachineSlotItemExpectOptions. It resolvesfalsewithout writing when a condition was given that the slot does not meet; a write with no conditions always resolvestrue.setMachineSlotItemthrows if the amount exceeds the item's maximum stack size, or if the item type does not exist.getMachineSlotItemthrows aPublicErrorof typeNotFoundif there is no block at the given location, including when that location's chunk is not loaded. It previously read the stored data without consulting the block; it now flushes the machine's open UI container into block storage first, so the answer is current as of the call.MachineItemStack.amountmust be a positive integer — the constructor, the property setter, andwithAmountall throw otherwise. Such a value used to be accepted but caused unpredictable behavior.MachineNetwork#queueSendno longer takes atype:queueSend(blockLocation, amount)instead ofqueueSend(blockLocation, type, amount). A network distributes exactly one storage type, which is now available asMachineNetwork#ioType.MachineNetworkStatsEventArg.allocationDatais a singleNetworkStorageTypeDatarather than a record keyed by storage type ID, for the same reason.IoCapabilities.acceptingandIoCapabilities.acceptingAnytake aNewIoCapabilitiesOptionsobject in place of theonlyAllowConduitConnectionsboolean. TheIoCapabilitiesconstructor also gained anisConduitparameter afteronlyAllowsConduitConnections.MachineUiElements.getreturns a frozen object, shared between calls, instead of a fresh mutable deep copy. Code that modified the element it returned must copy it first.RegisteredStorageType's definition — including the object returned by itstexturegetter — is copied and frozen on construction. A registered texture could previously be modified after the fact, either through the getter or through the add-on's own reference to the object it passed in.STANDARD_STORAGE_TYPE_DEFINITIONSis deeply frozen.
Behavior
- A
receivehandler can no longer accept more than it was offered. The returned amount is clamped to the offer, then re-clamped against the room left in the machine after the handler answers, since storage can change while the call is in flight; anything that no longer fits stays in the network's budget.
Standard Storage Types
StandardStorageType.LiquidAmmonia("liquid_ammonia") was removed, along with its entry inSTANDARD_STORAGE_TYPE_DEFINITIONS.StandardStorageType.LiquidExp("liquid_exp", liquid experience, categoryFluid) was added.- The standard definitions were repointed to the new per-type texture presets:
energyyellow → energy,lavared → lava,oilblack → oil,waterblue → water,ammoniaorange → ammonia,carbonred → carbon,hydrogenpink → hydrogen,nitrogenpurple → nitrogen,oxygenwhite → oxygen,steamwhite → steam.
Items, Textures and JSON UI
- UI item IDs shortened. Storage bar segment items went from
fluffyalien_energisticscore:ui_storage_bar_segment_<texture><n>tofluffyalien_energisticscore:ui_sbar_seg_<texture><n>, and progress indicator items fromui_progress_<indicator><n>toui_prog_<indicator><n>. Any pack that references these item IDs directly must be updated. - Empty slot texture moved.
textures/fluffyalien/energisticscore/ui/empty_slotwas deleted;fluffyalien_energisticscore:ui_empty_slotnow resolves totextures/fluffyalien/energisticscore/empty. - The legacy
fluffyalien_energisticscore:commonJSON UI namespace is deprecated and will be removed in a future update. It still ships and still works; usecommon_v2instead.
Added
PublicError,InternalError, andPublicErrorType. APublicErroris the caller's mistake and crosses the pack boundary so it surfaces in the add-on that caused it; anInternalErroris a bug in the library and is logged by the pack that raised it.PublicErrorTypelets an add-on branch on the kind of failure.- Atomic machine item slot operations:
takeMachineSlotItemandaddMachineSlotItem. Reading a slot, computing a new value and writing it back held a read across two round trips — many ticks — so if the player emptied the slot in that window the write put the item back while they were still holding it, duplicating it. These run the whole read-modify-write inside the core pack, so there is no window to lose.takeMachineSlotItemreturns what it removed (orundefined);addMachineSlotItemreturns how many items it added. MachineSlotItemExpectOptions, accepted bytakeMachineSlotItem,addMachineSlotItemandsetMachineSlotItemfor transforms the atomic operations don't express:expectType,expectAmount,expectMinAmountandexpectMaxAmountstate what the slot must currently hold, and the operation reports that it did not apply rather than clobbering a change made since you last looked.- Configuration file.
BP/scripts/__config.jsis excluded from the script bundle and can be edited with any text editor after installation. Every option is optional and documented in the file; a missing or wrong-typed option falls back to its default and logs a warning to the content log. The first option iscustomCommandNamespace, which sets the namespace for the add-on's custom commands (/<namespace>:becdebugmode,/<namespace>:becprintnetworks) so the add-on can be rebranded when bundled into a modpack. - New
common_v2JSON UI namespace, replacing the deprecatedcommonnamespace with a documented, fuller set of elements:screen_templateandcontent_template(a machine screen layout with the player inventory in the bottom half),container_title,container_slot_item(a slot that looks like a regular chest slot),container_slot_custom,container_slot_nobg,container_slot_nobg_noclick,container_slot_nobg_nohover, the matchingcontainer_item_*controls, andmachine_storage_bar. Every element carries documentation, published as a generated JSON UI Reference. - A dedicated storage bar texture for each standard storage type, so fluids and gases are distinguishable at a glance instead of sharing the generic color presets. Eleven new
StorageTypeTexturePresetvalues:ammonia,carbon,energy,hydrogen,lava,liquid_exp,nitrogen,oil,oxygen,steam,water. Nothing was removed — the generic color presets all still work. - Storage bar borders as separate textures, rather than being baked into each generated segment image. Added
ui/sbar_border_inset_{top,middle,bottom}andui/sbar_border_overlay_{top,middle,bottom}.common_v2.machine_storage_baruses the inset set by default, through its$border_top_texture,$border_middle_textureand$border_bottom_textureprops. The deprecatedcommon.machine_storage_baruses the same border as before. StorageTypeTextureDescription.segments(default 16), how many fill levels one slot of a bar has. A bar's resolution was fixed at 16, so a custom texture had to supply seventeen items whatever it looked like; a coarser bar now needs correspondingly fewer. Registration rejects a count that isn't a positive integer.MachineNetwork#getLatestAllocationData, so allocation statistics can be read on demand rather than only when theonNetworkAllocationCompletedevent fires. Returns the same statistics passed to that event, for the network's latest allocation.MachineNetwork#ioType, theStorageTypeDatathis network distributes.MachineNetworkStatsEventArg.network, the network that triggered the event.IoCapabilities#isConduit,IoCapabilities#acceptsTypeIdExplicit(a type accepted explicitly or viaacceptsAny, ignoring categories), andIoCapabilities#canConnectTo.NewIoCapabilitiesOptions, withonlyAllowsConduitConnectionsandisConduit.isRegistrationOpen, answering whether machines, item machines and storage types can still be registered. Registration is open from the moment scripts start running until 20 ticks afterworldLoad, then closes permanently.MACHINE_ENTITY_NO_UPDATE_UI_TAG(fluffyalien_energisticscore:no_update_ui). A machine entity carrying this tag receives no UI updates.MachineDefinitionDescription.defaultEntityNameTagandRegisteredMachine#defaultEntityNameTag, the name tag given to the machine entity when spawned. Defaults to the machine ID, which is what was always used before.initvalidation.initnow throws aPublicErrorof typeInvalidArgumentif the unique ID is empty or longer thanmcbe-addon-ipc'sMAX_ROUTER_UID_LENGTH, reporting the real range and the length given. It is also now documented thatuidis passed straight to theRouteras its own unique ID, which matters if your add-on constructs aRouterof its own — two sharing an ID receive each other's messages.isBedrockEnergisticsCoreInWorldthrows aPublicErrorof typeInvalidStateif called beforeworldLoad, rather than letting the engine's error about item types through. It works by looking for one of the core pack's items, which is whyinithas to be called afterworldLoad.- A Using the API guide, covering
init, the registration window, why reads are asynchronous, and error handling. Guides were also added or updated for UI buttons, progress indicator frame counts, custom storage bar textures, and item machine I/O.
Changed
- Allocations can now distribute unevenly. Previously a budget that did not divide evenly across the consumers in a priority group was not distributed at all. The remaining budget is now respread across the machines still to be processed on each iteration, so anything a machine does not take — because it is full, or because its
receivehandler reduced or refused the amount — rolls forward to the rest of the group instead of being lost. - Machine item slot changes are shown in the open UI as they are made, rather than up to an update interval later. For that window the container used to show an amount the machine had already changed, so a player could take items that were no longer there. The machinery that tried to reconcile the two afterwards (the changed-slot registry, the recorded pre-change values, and the merge between them) is gone, since the case it handled no longer arises.
- Item slots are synced outside the async UI render. They no longer wait on the machine's
updateUihandler, which takes several ticks to answer across the pack boundary; they are now driven synchronously on container open, on every interval tick regardless of a redraw in flight, and on container close. - Player-in-UI tracking moved to container events.
entityContainerOpenedandentityContainerClosedreplace the per-tickgetPlayers({ maxDistance: 10 })distance query that persistent entities ran on every interval tick. UI updates run every 4 ticks (was every 5). - Network performance. Machine definitions are looked up once during the allocation scan and carried through to distribution; block tags and I/O capabilities are computed once per block during network discovery instead of once per side (explicit-side machines are still evaluated per direction); and the static "find the network(s) at this location" lookups compute the block UID once instead of once per network.
- Storage bar label colors changed for three generic presets: blue
§9→§1, orange§6→§v, yellow§e→§6. The color composite source images were also redrawn, so existing bars using the generic presets look slightly different. MachineItemStack.toItemStackclamps an amount above the item's maximum stack size and logs a warning, instead of throwing.ItemMachine#getStorageis nowasync, so an invalid-object failure rejects rather than throwing synchronously, matching the other methods.ItemMachine#setStoragevalidates that it is given a non-negative integer.MachineNetwork.getAllWithdefaults to an empty list. An unexpected error in the core pack is answered withnull, which was previously dereferenced.hasCallbackreturnsfalsefor an unrecognized name on bothRegisteredMachineandRegisteredItemMachine, rather than implicitly returningundefinedto JavaScript callers.- Registering a machine or item machine fails up front if the library has not been initialized, instead of partway through with the registration half-applied.
- A destroyed machine reached during allocation logs at info instead of warning. Finding air where a registered machine was expected is a normal consequence of a machine being broken mid-allocation, so it no longer looks like a fault. Allocation log messages now name the phase they came from and render locations consistently.
- Scoreboard write failures are handled instead of propagating out of
setMachineStorage. MachineItemStackdocuments what it can and cannot carry. It holds an item's type, amount, name tag, damage, lore and enchantments and nothing else, so an item holding more than that does not survive a round trip — a shulker box with items in it comes back out empty. Restrict slots withUiItemSlotElementDefinition.allowedItems, or use a persistent entity's container if a slot has to accept any item.- Machine registry types are documented throughout, including which handlers can change what the add-on does and which events only observe.
Fixed
- Allocation could freeze permanently if a
receivehandler threw or timed out: the per-tick lock was never released. The pump now releases the lock in afinallyand discards the broken job. - A handler that throws (
receive,getIo) answers withnull, which is now guarded instead of being used as a result. onNetworkAllocationCompletednever fired for machines that don't consume the network's I/O type. Listening is independent of consuming, but the listener lookup sat behind the consumer filter, so a non-consuming observer was never registered. Non-consumers also ran outside the allocation job's cross-tick chunking.- Read-modify-write race in
distributeToGroup: the stored amount was read before thereceivehandler was called and written back after it, overwriting anything that changed in between. - Machine override was broken for any machine with a custom entity ID. The entity-attachment guard compared the stored machine ID against the new entity ID rather than the new machine ID. A stale entity ID → machine ID mapping is now cleared when an override changes the entity ID.
- Item name tags and lore containing a backslash threw "Illegal escape code" when read back. Backslashes are now escaped on serialization.
- Machine item slots ignored stack size. An amount above the item's maximum stack size threw while rendering the machine's UI — taking out the whole UI render, and the machine's contents as it broke, over one slot. Oversized amounts are now rejected when stored, and rendering clamps with a warning so anything stored before this check still renders.
MachineItemStackshared itsloreandenchantmentswith the options object it was constructed from, socloneandwithAmountproduced objects backed by the originals' arrays: mutating one changed the other, andisSimilarTothen wrongly reported them as similar. Enchantment entries are copied too, since theirlevelis writable.RegisteredStorageType.getAllIdscould permanently cache an incomplete list. It read the registration window after awaiting the response, so a call made late in that window could cache a list the core pack built while other packs were still registering. It also never included the calling pack's own registrations, so it could omit a storage type thatgetreported as existing.- Concurrent redraws of the same machine UI could race on the item slot sync, because the redraw awaits the
updateUihandler and the interval could start a second one while the first was still in flight. - A disabled storage bar ignored the element's
size, always writing four slots: a larger bar kept stale segments in the extra slots and a smaller one wrote into slots it does not own. - The
labeloption was ignored on a disabled storage bar (typeset to"_disabled"). - Custom progress indicators were off by one: passing the highest valid frame index rendered the error item instead of the last frame.
- The changed-item-slot registry grew without bound for a machine whose UI was never opened.
- Network link nodes: connecting to or destroying a node whose partner chunk is not loaded now raises a clear error or is skipped, instead of orphaning the backing entity and leaving dangling links. Duplicate connections are no longer stored — a single removal filtered out every match, which made the two directions of a link asymmetric and grew the stored property each time.
- A machine entity without an inventory component threw out of an event handler; it is now logged and skipped.
- An
ItemMachinewhose item is held by a block or entity with no inventory asserted non-null; it now raises a clear error. - A storage type texture override was reported even when nothing changed, because two add-ons registering an identical texture were compared by reference. Override diagnostics also read more clearly now.
- Interacting with a machine entity did not check that the target was still valid.
- The debug menu's set-variable form turned an invalid entry into an unhandled rejection.
- Re-registering a machine or item machine threw partway through, leaving the registration half-applied. It now overrides the previous one, and logs that it did, since an override usually means two packs claim the same ID.