Skip to content

Commit 6de4d55

Browse files
committed
bump to 1.14.1 (mc 1.20.60+; api 1.18.0-beta)
1 parent 35fa628 commit 6de4d55

File tree

3 files changed

+96
-89
lines changed

3 files changed

+96
-89
lines changed

pack/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"name": "Debug Stick",
66
"description": "Java §dDebug Stick§r ported to Minecraft: Bedrock Edition, by §bvytdev§r\nUse §a/give @s vyt:debug_stick§r or find it in the inventory screen to obtain the item.\n\nReport bugs here: §bhttps://github.com/vytdev/debug-stick/§r\nCopyright (c) 2023-2025 Vincent Yanzee J. Tan\nLicensed under the MIT License.",
77
"uuid": "21aadfa6-e27c-400c-c596-596021852939",
8-
"version": "1.14.0",
8+
"version": "1.14.1",
99
"min_engine_version": [ 1, 21, 60 ]
1010
},
1111

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "debug-stick",
3-
"version": "1.14.0",
3+
"version": "1.14.1",
44
"description": "Debug stick for minecraft bedrock",
55
"scripts": {
66
"test": "npx tsc",

src/index.ts

Lines changed: 94 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
Block,
2020
BlockStates,
2121
ItemStack,
22+
LiquidType,
2223
world,
2324
system
2425
} from "@minecraft/server";
@@ -41,43 +42,43 @@ const DEBUG_STICK_ID = "vyt:debug_stick";
4142
// Some event listeners. Listens for entityHitBkock
4243
// and itemUseOn events, which triggers an action onto
4344
// the debug stick
44-
world.afterEvents.entityHitBlock.subscribe((ev) => {
45+
world.afterEvents.entityHitBlock.subscribe(safeCallWrapper((ev) => {
4546
if (ev.damagingEntity.typeId != "minecraft:player")
4647
return;
47-
4848
const player = getPlayerByID(ev.damagingEntity.id);
49-
49+
if (!player)
50+
return;
5051
if (!isHoldingDebugStick(player))
5152
return;
53+
changeSelectedProperty(player, ev.hitBlock);
54+
}));
5255

53-
safeCall(changeSelectedProperty, player, ev.hitBlock);
54-
});
5556

56-
world.beforeEvents.itemUseOn.subscribe((ev) => {
57+
world.beforeEvents.itemUseOn.subscribe(safeCallWrapper((ev) => {
5758
if (ev.source.typeId != "minecraft:player")
5859
return;
5960
if (ev.itemStack?.typeId != DEBUG_STICK_ID)
6061
return;
61-
6262
ev.cancel = true;
63-
6463
const player = getPlayerByID(ev.source.id);
65-
64+
if (!player)
65+
return;
6666
if (player.isSneaking)
67-
safeCall(displayBlockInfo, player, ev.block);
67+
displayBlockInfo(player, ev.block);
6868
else
69-
safeCall(updateBlockProperty, player, ev.block);
70-
});
69+
updateBlockProperty(player, ev.block);
70+
}));
71+
7172

7273
// Players should not be able to break blocks using
7374
// the debug stick in survival
7475
//
7576
// TODO: explore other alternatives
76-
world.beforeEvents.playerBreakBlock.subscribe((ev) => {
77+
world.beforeEvents.playerBreakBlock.subscribe(safeCallWrapper((ev) => {
7778
if (ev.itemStack?.typeId != DEBUG_STICK_ID)
7879
return;
7980
ev.cancel = true;
80-
})
81+
}));
8182

8283

8384
/*============================================================================*\
@@ -90,37 +91,22 @@ world.beforeEvents.playerBreakBlock.subscribe((ev) => {
9091
* @param block
9192
*/
9293
function changeSelectedProperty(player: Player, block: Block) {
93-
const permutation = block.permutation;
94-
const states = permutation.getAllStates();
94+
const states = getBlockStates(block);
9595
const names = Object.keys(states);
96-
97-
if (!names.length/* && !block.type.canBeWaterlogged*/)
96+
if (!names.length)
9897
return message(`${block.typeId} has no properties`, player);
99-
10098
let prop = getCurrentProperty(player, block.typeId);
10199
let val: BlockStateValue;
102-
103100
// Increment for the next property
104101
prop = names[names.indexOf(prop) + 1];
105102
val = states[prop];
106-
107103
// We're probably at the end of the property names
108-
// list, check if the 'waterlogged' property is
109-
// available, or just go back at the start of the list
104+
// list, cycle back from the start.
110105
if (!prop) {
111-
/*if (block.type.canBeWaterlogged) {
112-
prop = "waterlogged";
113-
val = block.isWaterlogged;
114-
}
115-
else {*/
116-
prop = names[0];
117-
val = states[prop];
118-
/*}*/
106+
prop = names[0];
107+
val = states[prop];
119108
}
120-
121-
// Update the player's selection
122109
setCurrentProperty(player, block.typeId, prop);
123-
124110
message(`selected "${prop}" (${val})`, player);
125111
}
126112

@@ -130,48 +116,22 @@ function changeSelectedProperty(player: Player, block: Block) {
130116
* @param block
131117
*/
132118
function updateBlockProperty(player: Player, block: Block) {
133-
const permutation = block.permutation;
134-
const states = permutation.getAllStates();
119+
const states = getBlockStates(block);
135120
const names = Object.keys(states);
136-
137-
if (!names.length/* && !block.type.canBeWaterlogged*/)
121+
if (!names.length)
138122
return message(`${block.typeId} has no properties`, player);
139-
140123
let prop = getCurrentProperty(player, block.typeId);
141124
let val: BlockStateValue;
142-
143125
// Ensure that the recorded block property selection
144126
// is available on the block
145-
/*if (prop == "waterlogged" ? !block.type.canBeWaterlogged : !names.includes(prop))*/
146127
if (!names.includes(prop))
147128
prop = names[0];
148-
149-
/*if (!prop && block.type.canBeWaterlogged)
150-
prop = "waterlogged";*/
151-
152-
// Update the property value
153-
/*if (prop == "waterlogged") {
154-
val = !block.isWaterlogged;
155-
system.run(() => {
156-
block.setWaterlogged(val as boolean);
157-
});
158-
}
159-
160-
else {*/
161-
const valids = BlockStates.get(prop).validValues;
162-
val = valids[valids.indexOf(states[prop]) + 1];
163-
164-
if (typeof val === "undefined")
165-
val = valids[0];
166-
167-
system.run(() => {
168-
block.setPermutation(permutation.withState(prop as keyof BlockStateSuperset, val));
169-
});
170-
/*}*/
171-
172-
// Avoid some edge cases bugs
129+
const valids = getStateValidValues(prop);
130+
val = valids[valids.indexOf(states[prop]) + 1];
131+
if (typeof val === "undefined")
132+
val = valids[0];
133+
setBlockState(block, prop, val);
173134
setCurrentProperty(player, block.typeId, prop);
174-
175135
message(`"${prop}" to ${val}`, player);
176136
}
177137

@@ -182,38 +142,24 @@ function updateBlockProperty(player: Player, block: Block) {
182142
*/
183143
function displayBlockInfo(player: Player, block: Block) {
184144
let info = "§l§b" + block.typeId + "§r";
185-
186-
// The block's coordinates
145+
// Basic info
187146
info += "\n§4" + block.x + " §a" + block.y + " §9" + block.z;
188-
189-
// Block's matter state
190147
info += "\n§7matter state§8: §e";
191-
if (block.isLiquid) info += "liquid";
148+
if (block.isLiquid) info += "liquid";
192149
else if (block.isAir) info += "gas";
193-
else info += "solid";
194-
195-
// Whether the block is impassable
150+
else info += "solid";
196151
info += "\n§7hard block§8: " + (block.isSolid ? "§ayes" : "§cno");
197-
198-
// The block's emitted/recieved redstone power
199152
info += "\n§7redstone power§8: §c" + (block.getRedstonePower() ?? 0);
200-
201153
// The block states
202-
Object.entries(block.permutation.getAllStates()).forEach(([k, v]) => {
154+
Object.entries(getBlockStates(block)).forEach(([k, v]) => {
203155
info += "\n§o§7" + k + "§r§8: ";
204156
if (typeof v == "string") info += "§e";
205157
if (typeof v == "number") info += "§3";
206158
if (typeof v == "boolean") info += "§6";
207159
info += v;
208160
});
209-
210-
// Waterlog property if available
211-
/*if (block.type.canBeWaterlogged)
212-
info += "\n§o§7waterlogged§r§8: §6" + block.isWaterlogged;*/
213-
214161
// Additional block tags
215162
block.getTags().forEach(v => info += "\n§d#" + v);
216-
217163
message(info, player);
218164
}
219165

@@ -271,6 +217,54 @@ function getPlayerByID(id: string): Player | undefined {
271217
.find(v => v.id == id);
272218
}
273219

220+
/**
221+
* Returns all the block states of a block.
222+
* @param block The block.
223+
* @returns Record<string, BlockStateValue>
224+
*/
225+
function getBlockStates(block: Block): Record<string, BlockStateValue> {
226+
const states = block.permutation.getAllStates() || {};
227+
if (block.canContainLiquid(LiquidType.Water))
228+
states["waterlogged"] = block.isWaterlogged;
229+
return states;
230+
}
231+
232+
/**
233+
* Get the valid values of a block state.
234+
* @param state The block state.
235+
* @returns BlockStateValue[]
236+
*/
237+
function getStateValidValues(state: string): BlockStateValue[] {
238+
if (state == "waterlogged")
239+
return [false, true];
240+
return BlockStates.get(state).validValues;
241+
}
242+
243+
/**
244+
* Set a block's state.
245+
* @param block The block to modify.
246+
* @param state The state property to set.
247+
* @param val The value to set.
248+
* @returns Promise
249+
*/
250+
function setBlockState(block: Block, state: string, val: BlockStateValue): Promise<undefined> {
251+
return new Promise<undefined>((res, rej) => {
252+
system.run(() => {
253+
try {
254+
if (state == "waterlogged")
255+
block.setWaterlogged(val as boolean);
256+
else
257+
block.setPermutation(block.permutation.withState(
258+
state as keyof BlockStateSuperset, val));
259+
res(undefined);
260+
}
261+
catch (e) {
262+
rej(e);
263+
}
264+
});
265+
});
266+
}
267+
274268
/**
275269
* Get the currently selected property for a block given the
276270
* interacting player
@@ -306,7 +300,7 @@ function setCurrentProperty(player: Player, block: string, val: string): void {
306300
function safeCall<A extends any[], R>(
307301
func: (...args: A) => R,
308302
...args: A
309-
): R {
303+
): R | undefined {
310304

311305
try {
312306
return func.apply({}, args);
@@ -319,9 +313,22 @@ function safeCall<A extends any[], R>(
319313

320314
msg += e;
321315

322-
if (e?.stack)
316+
if (e instanceof Error && e?.stack)
323317
msg += `\n${e.stack}`;
324318

325319
console.error(msg);
326320
}
327321
}
322+
323+
/**
324+
* Safe call wrapper function.
325+
* @param func The function to wrap
326+
* @returns A function
327+
*/
328+
function safeCallWrapper<A extends any[], R>(
329+
func: (...args: A) => R
330+
): ((...args: A) => R | undefined) {
331+
return function (...args: A): R | undefined {
332+
return safeCall(func, ...args);
333+
}
334+
}

0 commit comments

Comments
 (0)