Files
Documentation/content/reference/buildertools/snapshots.en.md
2026-01-20 20:33:59 +01:00

285 lines
7.4 KiB
Markdown

---
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<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:
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<BlockSelectionSnapshot> {
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<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:
```java
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:
```java
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:
```java
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):
```java
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):
```java
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:
```java
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:
```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 <size>
```
## 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<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
```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);
```