--- title: Snapshots type: docs weight: 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: ```java public interface SelectionSnapshot> { // Restore to previous state // Returns inverse snapshot for redo T restore(Ref ref, Player player, World world, ComponentAccessor accessor); } ``` ### How Undo/Redo Works The snapshot pattern creates inverse operations: 1. Snapshot captures current state before operation 2. Operation modifies the state 3. Calling `restore()` reverts changes 4. `restore()` returns new snapshot for redo ## Block Selection Snapshots ### BlockSelectionSnapshot Captures block selection state: ```java public class BlockSelectionSnapshot implements SelectionSnapshot { private final BlockSelection selection; public BlockSelection getBlockSelection(); // Create copy of selection public static BlockSelectionSnapshot copyOf(BlockSelection selection); } ``` ### Usage ```java // 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: ```java public interface ClipboardSnapshot> extends SelectionSnapshot { T restoreClipboard(Ref ref, Player player, World world, BuilderToolsPlugin.BuilderState state, ComponentAccessor accessor); } ``` ### ClipboardContentsSnapshot Captures clipboard contents: ```java public class ClipboardContentsSnapshot implements ClipboardSnapshot { private final BlockSelection selection; // Create copy of clipboard contents public static ClipboardContentsSnapshot copyOf(BlockSelection selection); } ``` ### ClipboardBoundsSnapshot Captures selection bounds only: ```java public class ClipboardBoundsSnapshot implements ClipboardSnapshot { 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: ```java public interface EntitySnapshot> extends SelectionSnapshot { T restoreEntity(Player player, World world, ComponentAccessor accessor); } ``` Entity snapshots handle thread safety automatically, ensuring restoration runs on the world's tick thread. ### EntityAddSnapshot Tracks entity creation (undo removes entity): ```java public class EntityAddSnapshot implements EntitySnapshot { private final Ref entityRef; public Ref getEntityRef(); // Restore removes the entity // Returns EntityRemoveSnapshot for redo (re-add) } ``` ### EntityRemoveSnapshot Tracks entity removal (undo adds entity back): ```java public class EntityRemoveSnapshot implements EntitySnapshot { private final Holder holder; public Holder getHolder(); // Restore adds entity back // Returns EntityAddSnapshot for redo (remove again) } ``` The `Holder` stores a complete copy of the entity and its components. ### EntityTransformSnapshot Tracks entity position and rotation: ```java public class EntityTransformSnapshot implements EntitySnapshot { private final Ref ref; private final Transform transform; // Position and rotation private final Vector3f headRotation; // Head direction // Stores current transform state public EntityTransformSnapshot(Ref ref, ComponentAccessor 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: ```java // 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 ``` ## Thread Safety Entity snapshots automatically handle world thread requirements: ```java // 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 ```java // Before operation BlockSelectionSnapshot before = BlockSelectionSnapshot.copyOf(selection); // Perform operation that modifies blocks // ... // Store snapshot in history for undo ``` ### Working with Entity Snapshots ```java // Before adding entity Ref 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 ```java // 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); ```