Skip to content

RFC: World Transactional API #2407

Open
@gabizou

Description

The basics

We enforce a transaction based system onto Minecraft, but we struggle to do so for plugins who want to go to a further level of "I want to know if the full set of changes succeeded"

Backstory

In Sponge, we implemented a transaction recording system for blocks/entities changes in the game to enable plugins better control over all sorts of side effects. The implementation of the system is powered by what most in the community know as the PhaseTracker. This handy bit of code isn't small, nor is it easy to break down into usable portions outside of the game. As the crude explanation, it's a series of hooks to push and pop labeled states of the game onto a stack, which determine with added context, what to populate in a Cause for every event thrown during that state.

Some current half-steps

We do enable plugin developers to operate on a near full transaction-like system by providing VolumeStream as an API, which does a pretty good job at keeping the full breadth of bulk changes in one fell swoop. We also have the one-offs change methods (setBlock, etc)

Goals

This API should expose a closed loop of bulk changes:

  • Block changes with BlockChangeFlag understanding
  • Single series of events being called (up to one ChangeBlock.All and up to one SpawnEntityEvent for spawns, etc.)
  • Validator callback to accept or cancel the entire transaction based on the results of above events (if anything was cancelled, can selectively ignore those cancelled changes, or cancel the entire transaction)
  • Offer a StackFrame to enable adding additional Cause/Context information for the events named above

Non-goals

This API looks like a transaction library, but by no means is it meant to fully expose the PhaseTracker as an API, nor states, nor anything under the hood. Similarly, we do not want to treat this as a SQL-like system.

Examples

Quite simply, I could see this as:

final boolean appliedSuccessfully = world.transact((CauseStackManager.StackFrame frame, ServerWorld serverWorld, Verifier verifier) -> { 
  // Do changes
  verifier.verifyBlocks((BlockTransaction transaction) -> transaction.isCancelled());
  verifier.verifyEntities((//...));
});

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions