Skip to content

Commit c00a4c4

Browse files
author
Eric Blackman
committed
feat: add quick fill clipboard foundation
1 parent 6b3e108 commit c00a4c4

11 files changed

Lines changed: 1969 additions & 63 deletions
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { QuickFillContainerPolicy } from "./QuickFillContainerPolicy";
2+
3+
export class QuickFillClipboard {
4+
static WildcardAll = 'all';
5+
6+
constructor({
7+
shape,
8+
slots = [],
9+
wildcardMask = []
10+
} = {}) {
11+
this.shape = shape;
12+
this.slots = slots;
13+
this.wildcardMask = wildcardMask;
14+
}
15+
16+
static createDefault() {
17+
return new QuickFillClipboard({
18+
shape: QuickFillContainerPolicy.AdaptiveShape,
19+
wildcardMask: this.WildcardAll
20+
});
21+
}
22+
23+
static copy(block, container) {
24+
if (!block || !container)
25+
return;
26+
27+
const shape = QuickFillContainerPolicy.getShape(
28+
block,
29+
container
30+
);
31+
32+
if (!shape)
33+
return;
34+
35+
const slots = [];
36+
37+
for (let slot = 0; slot < container.size; slot++) {
38+
const itemStack = container.getItem(slot);
39+
40+
slots.push(itemStack?.clone());
41+
}
42+
43+
return new QuickFillClipboard({
44+
shape,
45+
slots,
46+
wildcardMask: new Array(container.size).fill(false)
47+
});
48+
}
49+
50+
isCompatibleWith(block, container) {
51+
const targetShape = QuickFillContainerPolicy.getShape(
52+
block,
53+
container
54+
);
55+
56+
return QuickFillContainerPolicy.isCompatible(
57+
this.shape,
58+
targetShape
59+
);
60+
}
61+
62+
isWildcard(slot) {
63+
if (this.wildcardMask === QuickFillClipboard.WildcardAll)
64+
return true;
65+
66+
return this.wildcardMask[slot] === true;
67+
}
68+
69+
resolveSlot(slot, heldItem) {
70+
if (this.isWildcard(slot))
71+
return heldItem?.clone();
72+
73+
return this.slots[slot]?.clone();
74+
}
75+
76+
getSlotCount(container) {
77+
if (this.shape === QuickFillContainerPolicy.AdaptiveShape)
78+
return container?.size ?? 0;
79+
80+
return this.slots.length;
81+
}
82+
83+
hasWildcards() {
84+
if (this.wildcardMask === QuickFillClipboard.WildcardAll)
85+
return true;
86+
87+
return this.wildcardMask.some(Boolean);
88+
}
89+
90+
clone() {
91+
return new QuickFillClipboard({
92+
shape: this.shape,
93+
slots: this.slots.map(itemStack => itemStack?.clone()),
94+
wildcardMask:
95+
this.wildcardMask === QuickFillClipboard.WildcardAll
96+
? QuickFillClipboard.WildcardAll
97+
: [...this.wildcardMask]
98+
});
99+
}
100+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { GameMode } from "@minecraft/server";
2+
import { QuickFillClipboard } from "./QuickFillClipboard";
3+
import { QuickFillClipboardExecutor } from "./QuickFillClipboardExecutor";
4+
import { QuickFillClipboardStore } from "./QuickFillClipboardStore";
5+
6+
export class QuickFillClipboardController {
7+
static get(player) {
8+
return QuickFillClipboardStore.get(player);
9+
}
10+
11+
static copy(player, block) {
12+
const blockInv =
13+
block.getComponent('inventory')?.container;
14+
15+
if (!blockInv)
16+
return;
17+
18+
const clipboard = QuickFillClipboard.copy(
19+
block,
20+
blockInv
21+
);
22+
23+
if (!clipboard)
24+
return;
25+
26+
QuickFillClipboardStore.set(
27+
player,
28+
clipboard
29+
);
30+
31+
player.onScreenDisplay.setActionBar(
32+
`§7Quick Fill: copied §a${blockInv.size}§7-slot clipboard.`
33+
);
34+
}
35+
36+
static apply(player, block, clipboard, isSneaking) {
37+
const playerInv =
38+
player.getComponent('inventory')?.container;
39+
40+
const blockInv =
41+
block.getComponent('inventory')?.container;
42+
43+
if (!playerInv || !blockInv)
44+
return;
45+
46+
const result = this.execute(
47+
player,
48+
block,
49+
playerInv,
50+
blockInv,
51+
clipboard,
52+
isSneaking
53+
);
54+
55+
this.sendFeedback(
56+
player,
57+
result,
58+
isSneaking
59+
);
60+
}
61+
62+
static execute(
63+
player,
64+
block,
65+
playerInv,
66+
blockInv,
67+
clipboard,
68+
isSneaking
69+
) {
70+
if (isSneaking) {
71+
return QuickFillClipboardExecutor.remove(
72+
playerInv,
73+
block,
74+
blockInv,
75+
clipboard
76+
);
77+
}
78+
79+
if (player.getGameMode() === GameMode.Creative) {
80+
return QuickFillClipboardExecutor.applyCreative(
81+
block,
82+
blockInv,
83+
clipboard
84+
);
85+
}
86+
87+
return QuickFillClipboardExecutor.applySurvival(
88+
playerInv,
89+
block,
90+
blockInv,
91+
clipboard
92+
);
93+
}
94+
static deactivate(player) {
95+
if (!QuickFillClipboardStore.has(player))
96+
return false;
97+
98+
QuickFillClipboardStore.clear(player);
99+
player.onScreenDisplay.setActionBar("Quick Fill clipboard deactivated.");
100+
return true;
101+
}
102+
static sendFeedback(player, result, isRemoving) {
103+
if (result?.incompatible) {
104+
player.onScreenDisplay.setActionBar(
105+
'§cQuick Fill: incompatible container.'
106+
);
107+
return;
108+
}
109+
110+
if (result?.insufficient) {
111+
player.onScreenDisplay.setActionBar(
112+
'§cQuick Fill: insufficient resources.'
113+
);
114+
return;
115+
}
116+
117+
if (!result?.changedSlots)
118+
return;
119+
120+
const action = isRemoving
121+
? 'removed'
122+
: 'applied';
123+
124+
player.onScreenDisplay.setActionBar(
125+
`§7Quick Fill: ${action} clipboard (§a${result.changedSlots}§7 slots).`
126+
);
127+
}
128+
}

0 commit comments

Comments
 (0)