7.4 KiB
title, type, weight
| title | type | weight |
|---|---|---|
| Snapshots | docs | 5 |
The snapshot system provides undo/redo functionality for builder tools by capturing and restoring state.
Package: com.hypixel.hytale.builtin.buildertools.snapshot
Architecture
Snapshots
├── Base
│ └── SelectionSnapshot - Snapshot interface
├── Block Snapshots
│ └── BlockSelectionSnapshot - Block selection state
├── Clipboard Snapshots
│ ├── ClipboardSnapshot - Clipboard interface
│ ├── ClipboardContentsSnapshot - Clipboard contents
│ └── ClipboardBoundsSnapshot - Selection bounds
└── Entity Snapshots
├── EntitySnapshot - Entity interface
├── EntityAddSnapshot - Track entity addition
├── EntityRemoveSnapshot - Track entity removal
└── EntityTransformSnapshot - Track transform changes
SelectionSnapshot Interface
Base interface for all snapshots:
public interface SelectionSnapshot<T extends SelectionSnapshot<?>> {
// Restore to previous state
// Returns inverse snapshot for redo
T restore(Ref<EntityStore> ref, Player player, World world,
ComponentAccessor<EntityStore> accessor);
}
How Undo/Redo Works
The snapshot pattern creates inverse operations:
- Snapshot captures current state before operation
- Operation modifies the state
- Calling
restore()reverts changes restore()returns new snapshot for redo
Block Selection Snapshots
BlockSelectionSnapshot
Captures block selection state:
public class BlockSelectionSnapshot implements SelectionSnapshot<BlockSelectionSnapshot> {
private final BlockSelection selection;
public BlockSelection getBlockSelection();
// Create copy of selection
public static BlockSelectionSnapshot copyOf(BlockSelection selection);
}
Usage
// Before modifying selection
BlockSelectionSnapshot snapshot = BlockSelectionSnapshot.copyOf(selection);
// Perform modifications...
// To undo - restore returns redo snapshot
BlockSelectionSnapshot redoSnapshot = snapshot.restore(ref, player, world, accessor);
Clipboard Snapshots
ClipboardSnapshot Interface
Extended interface for clipboard operations:
public interface ClipboardSnapshot<T extends SelectionSnapshot<?>>
extends SelectionSnapshot<T> {
T restoreClipboard(Ref<EntityStore> ref, Player player, World world,
BuilderToolsPlugin.BuilderState state,
ComponentAccessor<EntityStore> accessor);
}
ClipboardContentsSnapshot
Captures clipboard contents:
public class ClipboardContentsSnapshot implements ClipboardSnapshot<ClipboardContentsSnapshot> {
private final BlockSelection selection;
// Create copy of clipboard contents
public static ClipboardContentsSnapshot copyOf(BlockSelection selection);
}
ClipboardBoundsSnapshot
Captures selection bounds only:
public class ClipboardBoundsSnapshot implements ClipboardSnapshot<ClipboardBoundsSnapshot> {
public static final ClipboardBoundsSnapshot EMPTY;
private final Vector3i min;
private final Vector3i max;
public ClipboardBoundsSnapshot(BlockSelection selection);
public ClipboardBoundsSnapshot(Vector3i min, Vector3i max);
public Vector3i getMin();
public Vector3i getMax();
}
Entity Snapshots
EntitySnapshot Interface
Interface for entity-related snapshots:
public interface EntitySnapshot<T extends SelectionSnapshot<?>>
extends SelectionSnapshot<T> {
T restoreEntity(Player player, World world,
ComponentAccessor<EntityStore> accessor);
}
Entity snapshots handle thread safety automatically, ensuring restoration runs on the world's tick thread.
EntityAddSnapshot
Tracks entity creation (undo removes entity):
public class EntityAddSnapshot implements EntitySnapshot<EntityRemoveSnapshot> {
private final Ref<EntityStore> entityRef;
public Ref<EntityStore> getEntityRef();
// Restore removes the entity
// Returns EntityRemoveSnapshot for redo (re-add)
}
EntityRemoveSnapshot
Tracks entity removal (undo adds entity back):
public class EntityRemoveSnapshot implements EntitySnapshot<EntityAddSnapshot> {
private final Holder<EntityStore> holder;
public Holder<EntityStore> getHolder();
// Restore adds entity back
// Returns EntityAddSnapshot for redo (remove again)
}
The Holder<EntityStore> stores a complete copy of the entity and its components.
EntityTransformSnapshot
Tracks entity position and rotation:
public class EntityTransformSnapshot implements EntitySnapshot<EntityTransformSnapshot> {
private final Ref<EntityStore> ref;
private final Transform transform; // Position and rotation
private final Vector3f headRotation; // Head direction
// Stores current transform state
public EntityTransformSnapshot(Ref<EntityStore> ref,
ComponentAccessor<EntityStore> accessor);
// Restore returns snapshot of current state before restoration
}
Snapshot Pairs
Snapshots come in complementary pairs:
| Add Operation | Undo (Remove) | Redo (Add) |
|---|---|---|
EntityAddSnapshot |
Removes entity | EntityRemoveSnapshot |
EntityRemoveSnapshot |
Adds entity back | EntityAddSnapshot |
| Modification | Undo | Redo |
|---|---|---|
EntityTransformSnapshot |
Restores previous transform | Returns new snapshot |
BlockSelectionSnapshot |
Restores previous blocks | Returns new snapshot |
ClipboardContentsSnapshot |
Restores previous contents | Returns new snapshot |
ClipboardBoundsSnapshot |
Restores previous bounds | Returns new snapshot |
Edit History Integration
Snapshots integrate with the edit history system:
// History stores snapshots for each operation
// /undo command restores from history
// /redo command uses inverse snapshots
// Commands related to history:
// /undo [count]
// /redo [count]
// /clearedithistory
// /settoolhistorysize <size>
Thread Safety
Entity snapshots automatically handle world thread requirements:
// EntitySnapshot.restore() implementation
default T restore(...) {
if (!world.isInThread()) {
// Run on world tick thread
return CompletableFuture.supplyAsync(
() -> this.restoreEntity(player, world, store),
world
).join();
}
return this.restoreEntity(player, world, store);
}
API Usage
Working with Block Snapshots
// Before operation
BlockSelectionSnapshot before = BlockSelectionSnapshot.copyOf(selection);
// Perform operation that modifies blocks
// ...
// Store snapshot in history for undo
Working with Entity Snapshots
// Before adding entity
Ref<EntityStore> newEntity = world.spawnEntity(...);
EntityAddSnapshot snapshot = new EntityAddSnapshot(newEntity);
// To undo (remove the entity)
EntityRemoveSnapshot inverse = snapshot.restore(ref, player, world, accessor);
// To redo (add entity back)
EntityAddSnapshot restored = inverse.restore(ref, player, world, accessor);
Working with Transform Snapshots
// Before moving entity
EntityTransformSnapshot before = new EntityTransformSnapshot(entityRef, accessor);
// Move entity
transformComponent.setPosition(newPosition);
// To undo (restore original position)
EntityTransformSnapshot after = before.restore(player, world, accessor);