From b9e3380f6ca97ac29d912875e100c009d4543859 Mon Sep 17 00:00:00 2001 From: SysAdmin Date: Mon, 27 Apr 2026 21:59:27 +0100 Subject: [PATCH] feat(camping): three-tier ore detector with private-chest faraday cage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New basic/improved/advanced detectors (8/16/32 block range). Aim and right-click to ping the nearest ore on the view ray; pitch-coded sound and action-bar text show distance and ore type. Any ore within 4 blocks of a silverlabs:private_chest is hidden — chests act as faraday cages so claimed bases stay private from neighbours' detectors. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../items/ore_detector_advanced.json | 17 +++ .../items/ore_detector_basic.json | 17 +++ .../items/ore_detector_improved.json | 17 +++ .../recipes/ore_detector_advanced.json | 27 +++++ .../recipes/ore_detector_basic.json | 36 ++++++ .../recipes/ore_detector_improved.json | 28 +++++ .../camping_supplies_BP/scripts/main.js | 110 ++++++++++++++++++ .../camping_supplies_RP/texts/en_US.lang | 3 + .../textures/item_texture.json | 9 ++ .../textures/items/ore_detector_advanced.png | Bin 0 -> 228 bytes .../textures/items/ore_detector_basic.png | Bin 0 -> 227 bytes .../textures/items/ore_detector_improved.png | Bin 0 -> 227 bytes 12 files changed, 264 insertions(+) create mode 100644 camping-supplies-addon/camping_supplies_BP/items/ore_detector_advanced.json create mode 100644 camping-supplies-addon/camping_supplies_BP/items/ore_detector_basic.json create mode 100644 camping-supplies-addon/camping_supplies_BP/items/ore_detector_improved.json create mode 100644 camping-supplies-addon/camping_supplies_BP/recipes/ore_detector_advanced.json create mode 100644 camping-supplies-addon/camping_supplies_BP/recipes/ore_detector_basic.json create mode 100644 camping-supplies-addon/camping_supplies_BP/recipes/ore_detector_improved.json create mode 100644 camping-supplies-addon/camping_supplies_RP/textures/items/ore_detector_advanced.png create mode 100644 camping-supplies-addon/camping_supplies_RP/textures/items/ore_detector_basic.png create mode 100644 camping-supplies-addon/camping_supplies_RP/textures/items/ore_detector_improved.png diff --git a/camping-supplies-addon/camping_supplies_BP/items/ore_detector_advanced.json b/camping-supplies-addon/camping_supplies_BP/items/ore_detector_advanced.json new file mode 100644 index 0000000..8517575 --- /dev/null +++ b/camping-supplies-addon/camping_supplies_BP/items/ore_detector_advanced.json @@ -0,0 +1,17 @@ +{ + "format_version": "1.21.0", + "minecraft:item": { + "description": { + "identifier": "silverlabs:ore_detector_advanced", + "menu_category": { + "category": "equipment", + "group": "itemGroup.name.miscellaneous" + } + }, + "components": { + "minecraft:max_stack_size": 1, + "minecraft:icon": "ore_detector_advanced", + "minecraft:hand_equipped": true + } + } +} diff --git a/camping-supplies-addon/camping_supplies_BP/items/ore_detector_basic.json b/camping-supplies-addon/camping_supplies_BP/items/ore_detector_basic.json new file mode 100644 index 0000000..1135e68 --- /dev/null +++ b/camping-supplies-addon/camping_supplies_BP/items/ore_detector_basic.json @@ -0,0 +1,17 @@ +{ + "format_version": "1.21.0", + "minecraft:item": { + "description": { + "identifier": "silverlabs:ore_detector_basic", + "menu_category": { + "category": "equipment", + "group": "itemGroup.name.miscellaneous" + } + }, + "components": { + "minecraft:max_stack_size": 1, + "minecraft:icon": "ore_detector_basic", + "minecraft:hand_equipped": true + } + } +} diff --git a/camping-supplies-addon/camping_supplies_BP/items/ore_detector_improved.json b/camping-supplies-addon/camping_supplies_BP/items/ore_detector_improved.json new file mode 100644 index 0000000..b502595 --- /dev/null +++ b/camping-supplies-addon/camping_supplies_BP/items/ore_detector_improved.json @@ -0,0 +1,17 @@ +{ + "format_version": "1.21.0", + "minecraft:item": { + "description": { + "identifier": "silverlabs:ore_detector_improved", + "menu_category": { + "category": "equipment", + "group": "itemGroup.name.miscellaneous" + } + }, + "components": { + "minecraft:max_stack_size": 1, + "minecraft:icon": "ore_detector_improved", + "minecraft:hand_equipped": true + } + } +} diff --git a/camping-supplies-addon/camping_supplies_BP/recipes/ore_detector_advanced.json b/camping-supplies-addon/camping_supplies_BP/recipes/ore_detector_advanced.json new file mode 100644 index 0000000..55e31fc --- /dev/null +++ b/camping-supplies-addon/camping_supplies_BP/recipes/ore_detector_advanced.json @@ -0,0 +1,27 @@ +{ + "format_version": "1.21.0", + "minecraft:recipe_shapeless": { + "description": { + "identifier": "silverlabs:ore_detector_advanced_recipe" + }, + "tags": [ + "crafting_table" + ], + "unlock": [ + { + "item": "silverlabs:ore_detector_improved" + } + ], + "ingredients": [ + { "item": "silverlabs:ore_detector_improved" }, + { "item": "minecraft:gold_ingot" }, + { "item": "minecraft:gold_ingot" }, + { "item": "minecraft:amethyst_shard" }, + { "item": "minecraft:amethyst_shard" } + ], + "result": { + "item": "silverlabs:ore_detector_advanced", + "count": 1 + } + } +} diff --git a/camping-supplies-addon/camping_supplies_BP/recipes/ore_detector_basic.json b/camping-supplies-addon/camping_supplies_BP/recipes/ore_detector_basic.json new file mode 100644 index 0000000..58d9a35 --- /dev/null +++ b/camping-supplies-addon/camping_supplies_BP/recipes/ore_detector_basic.json @@ -0,0 +1,36 @@ +{ + "format_version": "1.21.0", + "minecraft:recipe_shaped": { + "description": { + "identifier": "silverlabs:ore_detector_basic_recipe" + }, + "tags": [ + "crafting_table" + ], + "unlock": [ + { + "item": "minecraft:redstone" + } + ], + "pattern": [ + " R ", + "CSC", + " C " + ], + "key": { + "R": { + "item": "minecraft:redstone" + }, + "C": { + "item": "minecraft:cobblestone" + }, + "S": { + "item": "minecraft:stick" + } + }, + "result": { + "item": "silverlabs:ore_detector_basic", + "count": 1 + } + } +} diff --git a/camping-supplies-addon/camping_supplies_BP/recipes/ore_detector_improved.json b/camping-supplies-addon/camping_supplies_BP/recipes/ore_detector_improved.json new file mode 100644 index 0000000..5ca65b3 --- /dev/null +++ b/camping-supplies-addon/camping_supplies_BP/recipes/ore_detector_improved.json @@ -0,0 +1,28 @@ +{ + "format_version": "1.21.0", + "minecraft:recipe_shapeless": { + "description": { + "identifier": "silverlabs:ore_detector_improved_recipe" + }, + "tags": [ + "crafting_table" + ], + "unlock": [ + { + "item": "silverlabs:ore_detector_basic" + } + ], + "ingredients": [ + { "item": "silverlabs:ore_detector_basic" }, + { "item": "minecraft:iron_ingot" }, + { "item": "minecraft:iron_ingot" }, + { "item": "minecraft:iron_ingot" }, + { "item": "minecraft:iron_ingot" }, + { "item": "minecraft:redstone" } + ], + "result": { + "item": "silverlabs:ore_detector_improved", + "count": 1 + } + } +} diff --git a/camping-supplies-addon/camping_supplies_BP/scripts/main.js b/camping-supplies-addon/camping_supplies_BP/scripts/main.js index 288d78d..54f7d73 100644 --- a/camping-supplies-addon/camping_supplies_BP/scripts/main.js +++ b/camping-supplies-addon/camping_supplies_BP/scripts/main.js @@ -703,6 +703,116 @@ function dismantleHammockAt(loc, dimId, player) { if (player) player.sendMessage("§7[Camping] Hammock taken down."); } +// ─── Ore Detector ─────────────────────────────────────────── +// Three tiered items share one scan handler. Tier → max scan range. +// Faraday: any ore within 4 blocks of a silverlabs:private_chest is hidden +// (mirrors the source DetectOre faraday-cage mechanic, but built into private chests). +const DETECTOR_RANGES = { + "silverlabs:ore_detector_basic": 8, + "silverlabs:ore_detector_improved": 16, + "silverlabs:ore_detector_advanced": 32, +}; +const PRIVATE_CHEST_ID = "silverlabs:private_chest"; +const FARADAY_RADIUS = 4; // 9³ cube around each ore candidate + +const ORE_IDS = new Set([ + "minecraft:coal_ore", "minecraft:deepslate_coal_ore", + "minecraft:iron_ore", "minecraft:deepslate_iron_ore", + "minecraft:copper_ore", "minecraft:deepslate_copper_ore", + "minecraft:gold_ore", "minecraft:deepslate_gold_ore", "minecraft:nether_gold_ore", + "minecraft:redstone_ore", "minecraft:deepslate_redstone_ore", + "minecraft:lit_redstone_ore", "minecraft:lit_deepslate_redstone_ore", + "minecraft:lapis_ore", "minecraft:deepslate_lapis_ore", + "minecraft:emerald_ore", "minecraft:deepslate_emerald_ore", + "minecraft:diamond_ore", "minecraft:deepslate_diamond_ore", + "minecraft:nether_quartz_ore", + "minecraft:ancient_debris", +]); + +function prettyOreName(typeId) { + const bare = typeId.replace(/^minecraft:/, "") + .replace(/^lit_/, "") + .replace(/^deepslate_/, "Deepslate ") + .replace(/^nether_/, "Nether "); + return bare.split("_").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" "); +} + +function isPrivateChestNearby(dim, cx, cy, cz) { + for (let dx = -FARADAY_RADIUS; dx <= FARADAY_RADIUS; dx++) { + for (let dy = -FARADAY_RADIUS; dy <= FARADAY_RADIUS; dy++) { + for (let dz = -FARADAY_RADIUS; dz <= FARADAY_RADIUS; dz++) { + const b = dim.getBlock({ x: cx + dx, y: cy + dy, z: cz + dz }); + if (b && b.typeId === PRIVATE_CHEST_ID) return true; + } + } + } + return false; +} + +function runOreScan(player, range) { + const dim = player.dimension; + const head = player.getHeadLocation(); + const dir = player.getViewDirection(); + + // Walk integer-block steps along the view ray. Resolution 0.5 blocks + // catches ores the cardinal-aligned steps would skip on diagonals. + const stepCount = Math.floor(range * 2); + const seen = new Set(); + let foundOre = null; + let foundDist = 0; + + for (let i = 1; i <= stepCount; i++) { + const t = i * 0.5; + const px = head.x + dir.x * t; + const py = head.y + dir.y * t; + const pz = head.z + dir.z * t; + const bx = Math.floor(px); + const by = Math.floor(py); + const bz = Math.floor(pz); + const key = `${bx},${by},${bz}`; + if (seen.has(key)) continue; + seen.add(key); + + let block; + try { block = dim.getBlock({ x: bx, y: by, z: bz }); } catch (_) { continue; } + if (!block) continue; + + if (ORE_IDS.has(block.typeId)) { + if (isPrivateChestNearby(dim, bx, by, bz)) continue; // faraday + foundOre = block.typeId; + foundDist = t; + break; + } + } + + if (foundOre) { + const distRounded = Math.round(foundDist * 10) / 10; + const pitch = Math.max(0.8, Math.min(2.0, 2.0 - (foundDist / range))); + try { + player.playSound("random.orb", { pitch, volume: 0.7 }); + } catch (_) {} + try { + player.onScreenDisplay.setActionBar(`§a● §f${prettyOreName(foundOre)} §7at §b${distRounded}m`); + } catch (_) {} + } else { + try { + player.playSound("note.bass", { pitch: 0.7, volume: 0.5 }); + } catch (_) {} + try { + player.onScreenDisplay.setActionBar(`§7○ No ores within §f${range}m`); + } catch (_) {} + } +} + +world.afterEvents.itemUse.subscribe((event) => { + const player = event.source; + const stack = event.itemStack; + if (!stack || !player) return; + const range = DETECTOR_RANGES[stack.typeId]; + if (!range) return; + system.run(() => runOreScan(player, range)); +}); + // ─── Boot ─────────────────────────────────────────────────── system.run(() => { loadState(); diff --git a/camping-supplies-addon/camping_supplies_RP/texts/en_US.lang b/camping-supplies-addon/camping_supplies_RP/texts/en_US.lang index 63dfe57..b2a5ac4 100644 --- a/camping-supplies-addon/camping_supplies_RP/texts/en_US.lang +++ b/camping-supplies-addon/camping_supplies_RP/texts/en_US.lang @@ -1,4 +1,7 @@ item.silverlabs:tent.name=Tent item.silverlabs:hammock.name=Hammock +item.silverlabs:ore_detector_basic.name=Ore Detector +item.silverlabs:ore_detector_improved.name=Ore Detector (Improved) +item.silverlabs:ore_detector_advanced.name=Ore Detector (Advanced) tile.silverlabs:tent_canvas.name=Tent Canvas tile.silverlabs:hammock_cloth.name=Hammock Cloth diff --git a/camping-supplies-addon/camping_supplies_RP/textures/item_texture.json b/camping-supplies-addon/camping_supplies_RP/textures/item_texture.json index 2a790b9..6d7a0d7 100644 --- a/camping-supplies-addon/camping_supplies_RP/textures/item_texture.json +++ b/camping-supplies-addon/camping_supplies_RP/textures/item_texture.json @@ -7,6 +7,15 @@ }, "hammock_item": { "textures": "textures/items/hammock" + }, + "ore_detector_basic": { + "textures": "textures/items/ore_detector_basic" + }, + "ore_detector_improved": { + "textures": "textures/items/ore_detector_improved" + }, + "ore_detector_advanced": { + "textures": "textures/items/ore_detector_advanced" } } } diff --git a/camping-supplies-addon/camping_supplies_RP/textures/items/ore_detector_advanced.png b/camping-supplies-addon/camping_supplies_RP/textures/items/ore_detector_advanced.png new file mode 100644 index 0000000000000000000000000000000000000000..f7e014a1f27d2fe4794e56624d69145e890197db GIT binary patch literal 228 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`t36#DLn`JZCmdjYCn5QFe{#wf z`T0^!3HSF2SMVk*I#H4(aiBwQ!lX&<*H5bZ&r8`+^HU{8p4-e-+HB3S%!VaPWVqy4 zGxC5yrLf^qwWrA(f;`RUfeS01a!M&|;@MsDlqp+ILdc)I$ztaD0e0szImS+W2C literal 0 HcmV?d00001 diff --git a/camping-supplies-addon/camping_supplies_RP/textures/items/ore_detector_basic.png b/camping-supplies-addon/camping_supplies_RP/textures/items/ore_detector_basic.png new file mode 100644 index 0000000000000000000000000000000000000000..a2d500addf63fe3c805fd6788d494742feaedbd6 GIT binary patch literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`t2|vCLn`JZCmdjYCn5QFe{#wf z`T0^!3HSF2SMVk*I#H4(aiBwQ!lX&<*H5bZ&r8`+^HU{8p4-e-+HB3S%!VaPWVqy4 zGx7j|RArw;lDXR3;{wVOY@&gI6;C;(E^N$^jH{dzci>sfqS%C#lye&%9LZT@Vs${O zw_ncoQ0C*$&(CwZgUHT8+cI$jAb9a=*8lXsZ7;j-#}sL7Gd6g@!JISeV`nf6L#@1} VXUlZmPe4~Qc)I$ztaD0e0synlSYH4D literal 0 HcmV?d00001 diff --git a/camping-supplies-addon/camping_supplies_RP/textures/items/ore_detector_improved.png b/camping-supplies-addon/camping_supplies_RP/textures/items/ore_detector_improved.png new file mode 100644 index 0000000000000000000000000000000000000000..7ca7730291b5d030709eff0195386e23cde9aabd GIT binary patch literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`t2|vCLn`JZCmdjYCn5QFe{#wf z`T0^!3HSF2SMVk*I#H4(aiBwQ!lX&<*H5bZ&r8`+^HU{8p4-e-+HB3S%!VaPWVqy4 zGx7idHq zfMCb<#N`(m!}M+H{pNg@l-Qu6!UhDfv7i61xo^Py-h8@@mr_!~frqR)vp#kPvoP$G WFnBOMfqN>@)eN4lelF{r5}E*+3{x`z literal 0 HcmV?d00001