285 lines
7.4 KiB
Markdown
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);
|
|
```
|