Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sisilicon
GitHub Repository: sisilicon/worldedit-be
Path: blob/master/src/editor/modules/selection.ts
1784 views
1
import { EditorModule } from "./base";
2
import { Player, system } from "@minecraft/server";
3
import { IPlayerUISession, SelectionContainerVolume, SelectionManager } from "@minecraft/server-editor";
4
import { DefaultSelection, setSelectionClass } from "@modules/selection";
5
import { Vector } from "@notbeer-api";
6
import { VolumeShape } from "editor/shapes/volume";
7
import { shapeToBlockVolume } from "editor/util";
8
import { getSession } from "server/sessions";
9
10
const selections = new WeakMap<Player, SelectionManager>();
11
const ignoreSelectionUpdates = new WeakMap<Player, number>();
12
13
function ignoreSelectionUpdate(player: Player) {
14
if (ignoreSelectionUpdates.has(player)) system.clearRun(ignoreSelectionUpdates.get(player));
15
ignoreSelectionUpdates.set(
16
player,
17
system.runTimeout(() => ignoreSelectionUpdates.delete(player), 2)
18
);
19
}
20
21
class EditorSelection extends DefaultSelection {
22
private volumeUpdator = shapeToBlockVolume();
23
24
public updateVolumeShape() {
25
this.set(0, Vector.ZERO);
26
this.set(1, Vector.ZERO);
27
this.shape = [new VolumeShape(this.volume.get()), Vector.ZERO];
28
}
29
30
protected updateShape() {
31
super.updateShape();
32
33
if (this.mode === "volume") return;
34
35
const [shape, location] = this.getShape() ?? [undefined, undefined];
36
this.volumeUpdator.update(shape, (volume) => {
37
if (!volume) {
38
this.volume.clear();
39
} else {
40
volume.translate(location);
41
this.volume.set(volume);
42
}
43
ignoreSelectionUpdate(this.player);
44
});
45
}
46
47
private get volume(): SelectionContainerVolume {
48
return selections.get(this.player)?.volume;
49
}
50
}
51
setSelectionClass(EditorSelection);
52
53
export class SelectionModule extends EditorModule {
54
constructor(session: IPlayerUISession) {
55
super(session);
56
const selection = this.session.extensionContext.selectionManager;
57
selections.set(this.player, selection);
58
59
this.session.extensionContext.afterEvents.SelectionChange.subscribe(() => {
60
if (ignoreSelectionUpdates.has(this.player)) return;
61
62
const worldEditSelection = getSession(this.player).selection as EditorSelection;
63
if (selection.volume.isEmpty) {
64
worldEditSelection.clear();
65
} else if (selection.volume.volumeCount === 1) {
66
if (!worldEditSelection.isCuboid) worldEditSelection.mode = "cuboid";
67
const { min, max } = selection.volume.getBoundingBox();
68
worldEditSelection.set(0, Vector.from(min));
69
worldEditSelection.set(1, Vector.from(max));
70
} else {
71
if (worldEditSelection.mode !== "volume") {
72
worldEditSelection.mode = "volume";
73
worldEditSelection.updateVolumeShape();
74
}
75
}
76
});
77
}
78
79
teardown() {
80
selections.delete(this.player);
81
}
82
}
83
84