Article Categories
- Baldur's Gate 3
- Diablo
- Elder Scrolls
- General
- Hogwarts Legacy
- League of Legends
- Minecraft
- Pokemon Go
- Sims 4
- StarCraft
- Steam Platform
- Xbox Game Console
More Articles
Whats wrong with this custom blocks loot table? Its supposed to choose drop by testing for silk touch, but non-enchanted pick drops both options
I have a custom block that is supposed to be only obtainable using a Silk Touch pickaxe. If mined with a pickaxe without Silk Touch, it should drop end stone instead, and if mined with the wrong tool, it should drop nothing.
Instead, it drops the correct loot only when a Silk Touch pickaxe is used. When a regular pickaxe is used, it drops both itself and an end stone block; when mined with the wrong tool, the same thing happens.
From the official documentation, "Applying a condition to a pool allows you execute the entire pool based on the conditions defined." In my custom block's loot table, each pool has its own (mutually exclusive) condition, so I'm not sure what's causing multiple drops (which would imply matching both or possibly all 3 conditions, which should be impossible).
Here is the loot table .json file:.
{.
"pools": [.
// Give rhizome block if mined using a Silk Touch pickaxe.
{.
"condition": "query.equipped_item_any_tag('slot.weapon.mainhand', 'minecraft:is_pickaxe') && query.has_silk_touch",.
"rolls": 1,.
"entries": [.
{.
"type": "item",.
"name": "end:rhizome".
}.
].
},.
// Give end stone if mined with a pickaxe without Silk Touch.
{.
"condition": "query.equipped_item_any_tag('slot.weapon.mainhand', 'minecraft:is_pickaxe') && !query.has_silk_touch",.
"rolls": 1,.
"entries": [.
{.
"type": "item",.
"name": "minecraft:end_stone".
}.
].
},.
// Drop nothing if mined with anything other than a pickaxe.
{.
"condition": "!query.equipped_item_any_tag('slot.weapon.mainhand', 'minecraft:is_pickaxe')",.
"rolls": 1,.
"entries": [.
{.
"type": "empty".
}.
].
}.
].
}.
Rearranging the three pools does not change the result. So, it doesn't matter whether the "has silk touch" condition comes first or third: it's still the only one that works as intended.
I also tested swapping out the condition strings with condition arrays of the following form:.
"conditions": [.
{.
"condition": "same molang queries here".
}.
].
but the same problem was still happening.
Question from user Quack E. Duck at gaming.stackexchange.com.
Answer:
Here is a different way of accomplishing the same thing, without using conditions in the loot table:.
Loot table for the block: (set to a single, empty entry).
{.
"pools": [.
// A placeholder; the actual drop will be determined in main.js.
{.
"rolls": 1,.
"entries": [.
{.
"type": "empty".
}.
].
}.
].
}.
Script file (main.js; uses @minecraft/server version 1.10.0-beta): -- This is where we'll test for use of silk touch pickaxe vs. unenchanted pickaxe vs. no pickaxe.
import { world, system, ItemStack, ItemComponentTypes } from "@minecraft/server".
// For use inside the .playerBreakBlock event listener, for getting the broken block's former coordinates.
// Properties will be player names (type String); values will be Block objects.
var lastBlockHitByPlayer = {};.
world.afterEvents.entityHitBlock.subscribe(event => {.
// Keep a record of the last block the player hit.
if (event.damagingEntity.typeId === "minecraft:player") {.
lastBlockHitByPlayer[event.damagingEntity.name] = event.hitBlock;.
}.
});.
world.afterEvents.playerBreakBlock.subscribe(event => {.
if (event.brokenBlockPermutation.type.id === "end:rhizome") {.
const stack = event.itemStackAfterBreak;.
const player = event.player;.
// Block will drop rhizome if mined with a silk touch pickaxe (this happens automatically).
if (stack !== undefined && stack.typeId.includes("_pickaxe") && !stack.getComponent(ItemComponentTypes.Enchantable).hasEnchantment("silk_touch")) {.
// Drop regular end stone if the block is mined with a non-silk-touch pickaxe.
(async () => {.
// For .playerBreakBlock, there's no direct way to access the block's coordinates (because it isn't there anymore?). Instead, the coordinates.
// of the block that has just been broken should be the same as those of the most recent block which the player hit (since hitting the block - left click - is a prerequisite to breaking it).
await player.dimension.spawnItem(new ItemStack("minecraft:end_stone"), {x: lastBlockHitByPlayer[player.name].x, y: lastBlockHitByPlayer[player.name].y, z: lastBlockHitByPlayer[player.name].z});.
})();.
} // Otherwise, drop nothing.
}.
});.
With this method, the custom block drops the correct loot for each case.
Answer from user Quack E. Duck at gaming.stackexchange.com.
I have a custom block that is supposed to be only obtainable using a Silk Touch pickaxe. If mined with a pickaxe without Silk Touch, it should drop end stone instead, and if mined with the wrong tool, it should drop nothing.
Instead, it drops the correct loot only when a Silk Touch pickaxe is used. When a regular pickaxe is used, it drops both itself and an end stone block; when mined with the wrong tool, the same thing happens.
From the official documentation, "Applying a condition to a pool allows you execute the entire pool based on the conditions defined." In my custom block's loot table, each pool has its own (mutually exclusive) condition, so I'm not sure what's causing multiple drops (which would imply matching both or possibly all 3 conditions, which should be impossible).
Here is the loot table .json file:.
{.
"pools": [.
// Give rhizome block if mined using a Silk Touch pickaxe.
{.
"condition": "query.equipped_item_any_tag('slot.weapon.mainhand', 'minecraft:is_pickaxe') && query.has_silk_touch",.
"rolls": 1,.
"entries": [.
{.
"type": "item",.
"name": "end:rhizome".
}.
].
},.
// Give end stone if mined with a pickaxe without Silk Touch.
{.
"condition": "query.equipped_item_any_tag('slot.weapon.mainhand', 'minecraft:is_pickaxe') && !query.has_silk_touch",.
"rolls": 1,.
"entries": [.
{.
"type": "item",.
"name": "minecraft:end_stone".
}.
].
},.
// Drop nothing if mined with anything other than a pickaxe.
{.
"condition": "!query.equipped_item_any_tag('slot.weapon.mainhand', 'minecraft:is_pickaxe')",.
"rolls": 1,.
"entries": [.
{.
"type": "empty".
}.
].
}.
].
}.
Rearranging the three pools does not change the result. So, it doesn't matter whether the "has silk touch" condition comes first or third: it's still the only one that works as intended.
I also tested swapping out the condition strings with condition arrays of the following form:.
"conditions": [.
{.
"condition": "same molang queries here".
}.
].
but the same problem was still happening.
Question from user Quack E. Duck at gaming.stackexchange.com.
Answer:
Here is a different way of accomplishing the same thing, without using conditions in the loot table:.
Loot table for the block: (set to a single, empty entry).
{.
"pools": [.
// A placeholder; the actual drop will be determined in main.js.
{.
"rolls": 1,.
"entries": [.
{.
"type": "empty".
}.
].
}.
].
}.
Script file (main.js; uses @minecraft/server version 1.10.0-beta): -- This is where we'll test for use of silk touch pickaxe vs. unenchanted pickaxe vs. no pickaxe.
import { world, system, ItemStack, ItemComponentTypes } from "@minecraft/server".
// For use inside the .playerBreakBlock event listener, for getting the broken block's former coordinates.
// Properties will be player names (type String); values will be Block objects.
var lastBlockHitByPlayer = {};.
world.afterEvents.entityHitBlock.subscribe(event => {.
// Keep a record of the last block the player hit.
if (event.damagingEntity.typeId === "minecraft:player") {.
lastBlockHitByPlayer[event.damagingEntity.name] = event.hitBlock;.
}.
});.
world.afterEvents.playerBreakBlock.subscribe(event => {.
if (event.brokenBlockPermutation.type.id === "end:rhizome") {.
const stack = event.itemStackAfterBreak;.
const player = event.player;.
// Block will drop rhizome if mined with a silk touch pickaxe (this happens automatically).
if (stack !== undefined && stack.typeId.includes("_pickaxe") && !stack.getComponent(ItemComponentTypes.Enchantable).hasEnchantment("silk_touch")) {.
// Drop regular end stone if the block is mined with a non-silk-touch pickaxe.
(async () => {.
// For .playerBreakBlock, there's no direct way to access the block's coordinates (because it isn't there anymore?). Instead, the coordinates.
// of the block that has just been broken should be the same as those of the most recent block which the player hit (since hitting the block - left click - is a prerequisite to breaking it).
await player.dimension.spawnItem(new ItemStack("minecraft:end_stone"), {x: lastBlockHitByPlayer[player.name].x, y: lastBlockHitByPlayer[player.name].y, z: lastBlockHitByPlayer[player.name].z});.
})();.
} // Otherwise, drop nothing.
}.
});.
With this method, the custom block drops the correct loot for each case.
Answer from user Quack E. Duck at gaming.stackexchange.com.
How to create a free items server in Terraria?
Anyone know where the last Hogwarts side mission is?
Which is your favorite season at Hogwarts?
Should I turn in sebastion in Hogwarts Legacy?
Can I use N.E.I. every time i play?
Is there a way to easily spot unopened chests in Genshin Impact?
Neds Island weapon slots and backpack SDU in DLC