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 0000000..f7e014a Binary files /dev/null and b/camping-supplies-addon/camping_supplies_RP/textures/items/ore_detector_advanced.png differ 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 0000000..a2d500a Binary files /dev/null and b/camping-supplies-addon/camping_supplies_RP/textures/items/ore_detector_basic.png differ 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 0000000..7ca7730 Binary files /dev/null and b/camping-supplies-addon/camping_supplies_RP/textures/items/ore_detector_improved.png differ