diff --git a/.github/scripts/gen-uninstall-check.py b/.github/scripts/gen-uninstall-check.py index d2e152a..888e8a5 100644 --- a/.github/scripts/gen-uninstall-check.py +++ b/.github/scripts/gen-uninstall-check.py @@ -18,8 +18,8 @@ repo, dest = sys.argv[1], sys.argv[2] -# 121/ holds the overlay of the newest pack format, both are scanned -folders = [os.path.join(repo, "data", "timber", "function"), os.path.join(repo, "121", "data", "timber", "function")] +# 101/ holds the overlay of the older pack formats, both are scanned +folders = [os.path.join(repo, "data", "timber", "function"), os.path.join(repo, "101", "data", "timber", "function")] uninstall_text = "" objectives, schedules, storage_keys = set(), set(), set() for folder in folders: diff --git a/.github/workflows/latest.yml b/.github/workflows/latest.yml index f55952f..d67d772 100644 --- a/.github/workflows/latest.yml +++ b/.github/workflows/latest.yml @@ -66,7 +66,7 @@ jobs: if: steps.setup.outputs.ready == 'true' run: | mkdir -p world/datapacks/timber world/datapacks/timber_test - cp -r data pack.mcmeta 121 world/datapacks/timber/ + cp -r data pack.mcmeta 101 world/datapacks/timber/ cp -r tests/. world/datapacks/timber_test/ # the uninstall test checks the scoreboards the code of the datapack creates, without this step it fails diff --git a/.github/workflows/publish-modrinth.yml b/.github/workflows/publish-modrinth.yml index 32c0250..f53313e 100644 --- a/.github/workflows/publish-modrinth.yml +++ b/.github/workflows/publish-modrinth.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v4 - name: Build the datapack zip - run: git archive --format=zip -o "Timber-${{ github.event.release.tag_name }}.zip" HEAD -- data 121 pack.mcmeta pack.png LICENSE README.md + run: git archive --format=zip -o "Timber-${{ github.event.release.tag_name }}.zip" HEAD -- data 101 pack.mcmeta pack.png LICENSE README.md - name: Attach the zip to the GitHub release env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f5d971b..9dd09d0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,9 +11,10 @@ jobs: runs-on: ubuntu-latest strategy: fail-fast: false + # the newest supported version (data/) plus the oldest version of each overlay range in pack.mcmeta matrix: include: - - minecraft: "26.1.2" + - minecraft: "26.1" java: "25" - minecraft: "26.3" java: "25" @@ -31,7 +32,7 @@ jobs: - name: Install datapacks run: | mkdir -p world/datapacks/timber world/datapacks/timber_test - cp -r data pack.mcmeta 121 world/datapacks/timber/ + cp -r data pack.mcmeta 101 world/datapacks/timber/ cp -r tests/. world/datapacks/timber_test/ # the uninstall test checks the scoreboards the code of the datapack creates, so a forgotten one can't slip through diff --git a/101/data/minecraft/loot_table/blocks/mushroom_stem.json b/101/data/minecraft/loot_table/blocks/mushroom_stem.json new file mode 100644 index 0000000..ffc9b6b --- /dev/null +++ b/101/data/minecraft/loot_table/blocks/mushroom_stem.json @@ -0,0 +1,62 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:mushroom_stem" + } + ], + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "predicates": { + "minecraft:enchantments": [ + { + "enchantments": "minecraft:silk_touch" + } + ] + } + } + } + ] + }, + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:knowledge_book", + "functions": [ + { + "function": "minecraft:set_custom_data", + "tag": "{Tags:[\"timber_location\"]}" + } + ], + "conditions": [ + { + "condition": "minecraft:any_of", + "terms": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "items": "#timber:axes" + } + }, + { + "condition": "minecraft:match_tool", + "predicate": { + "items": "#minecraft:axes" + } + } + ] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/101/data/timber/advancement/axes/found.json b/101/data/timber/advancement/axes/found.json new file mode 100644 index 0000000..cc9a3c9 --- /dev/null +++ b/101/data/timber/advancement/axes/found.json @@ -0,0 +1,294 @@ +{ + "criteria": { + "axe_in_hotbar": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "player": [ + { + "condition": "minecraft:any_of", + "terms": [ + { + "condition": "minecraft:all_of", + "terms": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.0": { + "items": "#minecraft:axes" + } + } + } + }, + { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.0": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "condition": "minecraft:all_of", + "terms": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.1": { + "items": "#minecraft:axes" + } + } + } + }, + { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.1": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "condition": "minecraft:all_of", + "terms": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.2": { + "items": "#minecraft:axes" + } + } + } + }, + { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.2": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "condition": "minecraft:all_of", + "terms": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.3": { + "items": "#minecraft:axes" + } + } + } + }, + { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.3": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "condition": "minecraft:all_of", + "terms": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.4": { + "items": "#minecraft:axes" + } + } + } + }, + { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.4": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "condition": "minecraft:all_of", + "terms": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.5": { + "items": "#minecraft:axes" + } + } + } + }, + { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.5": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "condition": "minecraft:all_of", + "terms": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.6": { + "items": "#minecraft:axes" + } + } + } + }, + { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.6": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "condition": "minecraft:all_of", + "terms": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.7": { + "items": "#minecraft:axes" + } + } + } + }, + { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.7": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "condition": "minecraft:all_of", + "terms": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.8": { + "items": "#minecraft:axes" + } + } + } + }, + { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "slots": { + "hotbar.8": { + "items": "#timber:axes" + } + } + } + } + } + ] + } + ] + } + ], + "items": [ + { + "items": "#minecraft:axes" + } + ] + } + } + }, + "rewards": { + "function": "timber:axes/auto/found" + } +} diff --git a/121/data/timber/function/autoplant/plant.mcfunction b/101/data/timber/function/autoplant/plant.mcfunction similarity index 92% rename from 121/data/timber/function/autoplant/plant.mcfunction rename to 101/data/timber/function/autoplant/plant.mcfunction index 0380e9f..fb72d66 100644 --- a/121/data/timber/function/autoplant/plant.mcfunction +++ b/101/data/timber/function/autoplant/plant.mcfunction @@ -13,8 +13,8 @@ execute if block ~ ~ ~ minecraft:farmland[moisture=6] run summon marker ~ ~ ~ {T execute if block ~ ~ ~ minecraft:farmland[moisture=7] run summon marker ~ ~ ~ {Tags:["timber_farmland","timber_moisture_7","global.ignore"]} execute if block ~ ~ ~ minecraft:farmland run schedule function timber:autoplant/farmland_fix 3t execute if block ~ ~ ~ minecraft:farmland run setblock ~ ~ ~ minecraft:dirt -summon minecraft:falling_block ~ ~0.125 ~ {BlockState:"minecraft:barrier",Time:1,DropItem:0b,Tags:["timber_item_to_block"]} -execute positioned ~ ~0.125 ~ run data modify entity @e[type=minecraft:falling_block,tag=timber_item_to_block,distance=...1,sort=arbitrary,limit=1] BlockState set from entity @s Item.id +summon minecraft:falling_block ~ ~0.125 ~ {BlockState:{Name:"minecraft:barrier"},Time:1,DropItem:0b,Tags:["timber_item_to_block"]} +execute positioned ~ ~0.125 ~ run data modify entity @e[type=minecraft:falling_block,tag=timber_item_to_block,distance=...1,sort=arbitrary,limit=1] BlockState.Name set from entity @s Item.id # on stacks -1 execute store result score @s timber run data get entity @s Item.count diff --git a/121/data/timber/predicate/block/cap.json b/101/data/timber/predicate/block/cap.json similarity index 68% rename from 121/data/timber/predicate/block/cap.json rename to 101/data/timber/predicate/block/cap.json index fb9867d..807ada7 100644 --- a/121/data/timber/predicate/block/cap.json +++ b/101/data/timber/predicate/block/cap.json @@ -1,8 +1,8 @@ { - "type": "minecraft:any_of", + "condition": "minecraft:any_of", "terms": [ { - "type": "minecraft:location_check", + "condition": "minecraft:location_check", "predicate": { "block": { "blocks": "#minecraft:wart_blocks" @@ -10,7 +10,7 @@ } }, { - "type": "minecraft:location_check", + "condition": "minecraft:location_check", "predicate": { "block": { "blocks": "minecraft:shroomlight" @@ -18,7 +18,7 @@ } }, { - "type": "minecraft:location_check", + "condition": "minecraft:location_check", "predicate": { "block": { "blocks": "minecraft:brown_mushroom_block" @@ -26,7 +26,7 @@ } }, { - "type": "minecraft:location_check", + "condition": "minecraft:location_check", "predicate": { "block": { "blocks": "minecraft:red_mushroom_block" @@ -34,4 +34,4 @@ } } ] -} +} \ No newline at end of file diff --git a/121/data/timber/predicate/block/leaf.json b/101/data/timber/predicate/block/leaf.json similarity index 72% rename from 121/data/timber/predicate/block/leaf.json rename to 101/data/timber/predicate/block/leaf.json index 33e0408..69effa4 100644 --- a/121/data/timber/predicate/block/leaf.json +++ b/101/data/timber/predicate/block/leaf.json @@ -1,8 +1,8 @@ { - "type": "minecraft:any_of", + "condition": "minecraft:any_of", "terms": [ { - "type": "minecraft:location_check", + "condition": "minecraft:location_check", "predicate": { "block": { "blocks": "#minecraft:leaves", @@ -13,10 +13,10 @@ } }, { - "type": "minecraft:all_of", + "condition": "minecraft:all_of", "terms": [ { - "type": "minecraft:location_check", + "condition": "minecraft:location_check", "predicate": { "block": { "blocks": "#minecraft:leaves" @@ -24,7 +24,7 @@ } }, { - "type": "minecraft:entity_scores", + "condition": "minecraft:entity_scores", "entity": "this", "scores": { "timber_persistent": { @@ -35,7 +35,7 @@ ] }, { - "type": "minecraft:location_check", + "condition": "minecraft:location_check", "predicate": { "block": { "blocks": "minecraft:mangrove_propagule", diff --git a/121/data/timber/predicate/block/log.json b/101/data/timber/predicate/block/log.json similarity index 65% rename from 121/data/timber/predicate/block/log.json rename to 101/data/timber/predicate/block/log.json index 5ce9666..3b960aa 100644 --- a/121/data/timber/predicate/block/log.json +++ b/101/data/timber/predicate/block/log.json @@ -1,5 +1,5 @@ { - "type": "minecraft:location_check", + "condition": "minecraft:location_check", "predicate": { "block": { "blocks": "#minecraft:logs" diff --git a/121/data/timber/predicate/block/stem.json b/101/data/timber/predicate/block/stem.json similarity index 65% rename from 121/data/timber/predicate/block/stem.json rename to 101/data/timber/predicate/block/stem.json index 4f22e0d..591f3db 100644 --- a/121/data/timber/predicate/block/stem.json +++ b/101/data/timber/predicate/block/stem.json @@ -1,8 +1,8 @@ { - "type": "minecraft:any_of", + "condition": "minecraft:any_of", "terms": [ { - "type": "minecraft:location_check", + "condition": "minecraft:location_check", "predicate": { "block": { "blocks": "#minecraft:logs" @@ -10,7 +10,7 @@ } }, { - "type": "minecraft:location_check", + "condition": "minecraft:location_check", "predicate": { "block": { "blocks": "minecraft:mushroom_stem" @@ -18,4 +18,4 @@ } } ] -} +} \ No newline at end of file diff --git a/121/data/timber/predicate/item/log.json b/101/data/timber/predicate/item/log.json similarity index 73% rename from 121/data/timber/predicate/item/log.json rename to 101/data/timber/predicate/item/log.json index dee4b89..7fea675 100644 --- a/121/data/timber/predicate/item/log.json +++ b/101/data/timber/predicate/item/log.json @@ -1,5 +1,5 @@ { - "type": "minecraft:entity_properties", + "condition": "minecraft:entity_properties", "entity": "this", "predicate": { "equipment": { @@ -8,4 +8,4 @@ } } } -} +} \ No newline at end of file diff --git a/121/data/timber/predicate/item/root.json b/101/data/timber/predicate/item/root.json similarity index 74% rename from 121/data/timber/predicate/item/root.json rename to 101/data/timber/predicate/item/root.json index b4c236d..f746554 100644 --- a/121/data/timber/predicate/item/root.json +++ b/101/data/timber/predicate/item/root.json @@ -1,5 +1,5 @@ { - "type": "minecraft:entity_properties", + "condition": "minecraft:entity_properties", "entity": "this", "predicate": { "equipment": { @@ -8,4 +8,4 @@ } } } -} +} \ No newline at end of file diff --git a/121/data/timber/predicate/item/sapling.json b/101/data/timber/predicate/item/sapling.json similarity index 74% rename from 121/data/timber/predicate/item/sapling.json rename to 101/data/timber/predicate/item/sapling.json index 88e2bf9..31bd5c7 100644 --- a/121/data/timber/predicate/item/sapling.json +++ b/101/data/timber/predicate/item/sapling.json @@ -1,5 +1,5 @@ { - "type": "minecraft:entity_properties", + "condition": "minecraft:entity_properties", "entity": "this", "predicate": { "equipment": { @@ -8,4 +8,4 @@ } } } -} +} \ No newline at end of file diff --git a/121/data/timber/predicate/item/stem.json b/101/data/timber/predicate/item/stem.json similarity index 79% rename from 121/data/timber/predicate/item/stem.json rename to 101/data/timber/predicate/item/stem.json index a820b2c..43b5e29 100644 --- a/121/data/timber/predicate/item/stem.json +++ b/101/data/timber/predicate/item/stem.json @@ -1,8 +1,8 @@ { - "type": "minecraft:any_of", + "condition": "minecraft:any_of", "terms": [ { - "type": "minecraft:entity_properties", + "condition": "minecraft:entity_properties", "entity": "this", "predicate": { "equipment": { @@ -13,7 +13,7 @@ } }, { - "type": "minecraft:entity_properties", + "condition": "minecraft:entity_properties", "entity": "this", "predicate": { "equipment": { @@ -24,7 +24,7 @@ } }, { - "type": "minecraft:entity_properties", + "condition": "minecraft:entity_properties", "entity": "this", "predicate": { "equipment": { @@ -42,4 +42,4 @@ } } ] -} +} \ No newline at end of file diff --git a/101/data/timber/predicate/random_chance/0.25.json b/101/data/timber/predicate/random_chance/0.25.json new file mode 100644 index 0000000..9740f91 --- /dev/null +++ b/101/data/timber/predicate/random_chance/0.25.json @@ -0,0 +1,4 @@ +{ + "condition": "minecraft:random_chance", + "chance": 0.25 + } \ No newline at end of file diff --git a/101/data/timber/predicate/random_chance/0.333.json b/101/data/timber/predicate/random_chance/0.333.json new file mode 100644 index 0000000..52e5ecf --- /dev/null +++ b/101/data/timber/predicate/random_chance/0.333.json @@ -0,0 +1,4 @@ +{ + "condition": "minecraft:random_chance", + "chance": 0.333 + } \ No newline at end of file diff --git a/101/data/timber/predicate/random_chance/0.5.json b/101/data/timber/predicate/random_chance/0.5.json new file mode 100644 index 0000000..66c2b14 --- /dev/null +++ b/101/data/timber/predicate/random_chance/0.5.json @@ -0,0 +1,4 @@ +{ + "condition": "minecraft:random_chance", + "chance": 0.5 + } \ No newline at end of file diff --git a/101/data/timber/predicate/sneaking.json b/101/data/timber/predicate/sneaking.json new file mode 100644 index 0000000..a41c89c --- /dev/null +++ b/101/data/timber/predicate/sneaking.json @@ -0,0 +1,9 @@ +{ + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "flags": { + "is_sneaking": true + } + } +} \ No newline at end of file diff --git a/121/data/minecraft/loot_table/blocks/mushroom_stem.json b/121/data/minecraft/loot_table/blocks/mushroom_stem.json deleted file mode 100644 index fa0265a..0000000 --- a/121/data/minecraft/loot_table/blocks/mushroom_stem.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "type": "minecraft:block", - "pools": [ - { - "rolls": 1, - "entries": [ - { - "type": "minecraft:item", - "name": "minecraft:mushroom_stem" - } - ], - "condition": { - "type": "minecraft:match_tool", - "predicate": { - "predicates": { - "minecraft:enchantments": [ - { - "enchantments": "minecraft:silk_touch" - } - ] - } - } - } - }, - { - "rolls": 1, - "entries": [ - { - "type": "minecraft:item", - "name": "minecraft:knowledge_book", - "modifier": { - "type": "minecraft:set_custom_data", - "tag": "{Tags:[\"timber_location\"]}" - }, - "condition": { - "type": "minecraft:match_tool", - "predicate": { - "items": "#timber:axes" - } - } - } - ] - } - ] -} diff --git a/121/data/timber/predicate/random_chance/0.25.json b/121/data/timber/predicate/random_chance/0.25.json deleted file mode 100644 index c4155b5..0000000 --- a/121/data/timber/predicate/random_chance/0.25.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:random_chance", - "chance": 0.25 -} diff --git a/121/data/timber/predicate/random_chance/0.333.json b/121/data/timber/predicate/random_chance/0.333.json deleted file mode 100644 index 79001a1..0000000 --- a/121/data/timber/predicate/random_chance/0.333.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:random_chance", - "chance": 0.333 -} diff --git a/121/data/timber/predicate/random_chance/0.5.json b/121/data/timber/predicate/random_chance/0.5.json deleted file mode 100644 index 62d7fd5..0000000 --- a/121/data/timber/predicate/random_chance/0.5.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "minecraft:random_chance", - "chance": 0.5 -} diff --git a/121/data/timber/predicate/sneaking.json b/121/data/timber/predicate/sneaking.json deleted file mode 100644 index ab3659c..0000000 --- a/121/data/timber/predicate/sneaking.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "type": "minecraft:entity_properties", - "entity": "this", - "predicate": { - "flags": { - "is_sneaking": true - } - } -} diff --git a/CHANGELOG.md b/CHANGELOG.md index 09296c7..027954d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,6 @@ Release notes live on the [GitHub Releases page](https://github.com/Moggla/Timbe ## Releasing -1. If the supported MC versions changed: bump `pack.mcmeta` (`min_format`/`max_format`), match `.github/mc-version-range.txt` to it, and update the `matrix` in `.github/workflows/test.yml` to test the new version. [Pack format](https://minecraft.wiki/w/Pack_format) lists which MC version has which format number. -2. Update the version string in `data/timber/dialog/help.json` and in `data/timber/function/settings/open/menu.mcfunction` (the Settings dialog body). +1. If the supported MC versions changed: bump `pack.mcmeta` (`min_format`/`max_format`), match `.github/mc-version-range.txt` to it, and update the `matrix` in `.github/workflows/test.yml`: the newest version plus the oldest version of each overlay range. A new format goes into `data/`, the old files move into an overlay (see `CLAUDE.md`). [Pack format](https://minecraft.wiki/w/Pack_format) lists which MC version has which format number. +2. Update the version string in `data/timber/dialog/help.json` (pause menu) and `data/timber/function/settings/open/help.mcfunction` (the same help dialog, opened by commands). 3. Tag the commit `vX.Y.Z` and publish it as a GitHub Release, using "Generate release notes" for the body; that triggers the Modrinth upload and attaches the datapack zip to the release automatically. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..71e7710 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,10 @@ +# Notes for Claude + +## Pack formats and overlays +- `data/` is always written in the format of the newest supported Minecraft version (`max_format` in `pack.mcmeta`). +- Older versions get an overlay, never the other way round. The overlay folder is named after its lowest pack format (`101/` for 26.1) and listed in `pack.mcmeta` under `overlays.entries`. +- A file whose JSON differs between formats (predicates, loot tables, advancements, some commands) lives in `data/` in the new format and in the overlay in the old one. +- Adding support for a new version: bring `data/` to the new format, move the old versions of the changed files into an overlay for the older formats. +- Dropping an old version: delete its overlay folder and its entry in `pack.mcmeta`. +- Scripts and workflows that copy or scan the overlay folder by name: `.github/workflows/test.yml`, `.github/workflows/latest.yml`, `.github/workflows/publish-modrinth.yml`, `.github/scripts/gen-uninstall-check.py`. +- The `matrix` of `.github/workflows/test.yml` holds the newest supported version (for `data/`) and the oldest version of each overlay range (the functions in `data/` are shared by all versions, a command that only newer versions know breaks the oldest). A new overlay needs its own entry. A JSON error in one format breaks the whole registry of that version only. diff --git a/README.md b/README.md index c683bf5..db33617 100644 --- a/README.md +++ b/README.md @@ -3,21 +3,23 @@ [![Test](https://github.com/Moggla/Timber-Datapack/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/Moggla/Timber-Datapack/actions/workflows/test.yml) [![Latest Minecraft](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2FMoggla/Timber-Datapack%2Fbadges%2Flatest.json)](https://github.com/Moggla/Timber-Datapack/actions/workflows/latest.yml) [![Last check](https://img.shields.io/github/last-commit/Moggla/Timber-Datapack/badges?path=latest.json&label=last%20check)](https://github.com/Moggla/Timber-Datapack/actions/workflows/latest.yml) -This is a really useful addition for those who don't want to spend expensive time on gathering resources! After installing, the Timber Datapack allows you to instantly chop down a tree just by breaking one log with any axe. +Break one log with any axe and the whole tree comes down. No more chopping log by log! Optionally, you can adjust everything as you wish. # Under the Hood Features - Chops only trees¹ - Works with every type of log² -- Supports custom trees³ +- Works with every axe³ +- Supports custom trees⁴ - Leaves drop normal loot - Takes account of any enchantment - Many options for customization ¹ Trees are defined as logs with naturally generated leaves within 2 blocks of the trunk. ² Logs in the tag #minecraft:logs. -³ All kind of custom trees like from **BiomesO'Plenty**, **The Biome Overhaul**, **Terrestria and Traverse**. +³ Axes in the tag #minecraft:axes, also those of mods. +⁴ Custom trees of mods and datapacks, e.g. **BiomesO'Plenty**, **The Biome Overhaul**, **Terrestria and Traverse**. # Preview @@ -25,10 +27,10 @@ Optionally, you can adjust everything as you wish. > [!NOTE] -> Enable the option `Chop Fungi` +> Fungi need the setting `Chop Fungi` # Settings -To get descriptions and settings for this datapack use: +Open the Timber menu from the pause menu (Esc) or run: ``` /function timber:help @@ -46,20 +48,20 @@ To get descriptions and settings for this datapack use:
-Every player can individually turn the datapack ON or OFF by using: - -``` -/trigger TimberToggle -``` - ![help](.github/resources/help.png) ![settings1](.github/resources/settings1.png) ![settings2](.github/resources/settings2.png) # Advanced Manual +
+ +Click to reveal
+ ## Add Custom Axes -To add the axe of a mod (for example the emeraldaxe of supertools) run one command: +Axes of mods in the item tag `#minecraft:axes` work by themselves: Timber adds one as soon as it is in the hotbar, with the durability of the item. It gets its own button in the settings menu, where it can be turned off. + +To add an axe that is not in that tag, or to give one another durability or label, run one command (for example for the emeraldaxe of supertools): ``` function timber:api/add_axe {item:"supertools:emeraldaxe", durability:500, label:"Emerald Axe"} @@ -69,11 +71,6 @@ function timber:api/add_axe {item:"supertools:emeraldaxe", durability:500, label - `label` is the name of its button in the settings menu. The button appears by itself. ## For Other Datapacks - -
- -Click to reveal
- Timber has an API, so that your datapack can work together with it without changing any file of Timber (an update of Timber doesn't remove your changes). Everything below goes into a datapack of your own, with its own `pack.mcmeta`. Replace `mypack` with the namespace of your datapack. ### Register Axes When Timber Loads @@ -93,7 +90,7 @@ function timber:api/add_axe {item:"supertools:emeraldaxe", durability:500, label } ``` -Also add the axe to the item tag `timber:axes`, it is used for the loot of mushroom stems: +If the axe is not in `#minecraft:axes`, also add it to the item tag `timber:axes`, it is used for the loot of mushroom stems: `data/timber/tags/item/axes.json` ```json @@ -106,6 +103,7 @@ Also add the axe to the item tag `timber:axes`, it is used for the loot of mushr Good to know: - Timber registers its vanilla axes with the same command (`data/timber/function/axes/init.mcfunction`). If you register one of them again, your values replace the vanilla ones. +- An axe you register is never replaced by the automatic detection. An axe that was found automatically is replaced by your values. - Timber only sees the damage of an axe. A modded axe with its own way of breaking may stay in the hand for a few more logs, that is not a problem. ### React to Broken Blocks @@ -145,7 +143,7 @@ If something doesn't work, enable the output log (Minecraft Launcher → Setting - Finished! Enjoy! > [!NOTE] -> It does not work in creative mode! +> Doesn't work in Creative mode (Minecraft doesn't count it as using the axe). # Server Compatibility Other Minecraft servers, unlike Vanilla or Realm, often do not fully support Datapacks. diff --git a/data/minecraft/loot_table/blocks/mushroom_stem.json b/data/minecraft/loot_table/blocks/mushroom_stem.json index 734f4a6..6860267 100644 --- a/data/minecraft/loot_table/blocks/mushroom_stem.json +++ b/data/minecraft/loot_table/blocks/mushroom_stem.json @@ -9,20 +9,18 @@ "name": "minecraft:mushroom_stem" } ], - "conditions": [ - { - "condition": "minecraft:match_tool", - "predicate": { - "predicates": { - "minecraft:enchantments": [ - { - "enchantments": "minecraft:silk_touch" - } - ] - } + "condition": { + "type": "minecraft:match_tool", + "predicate": { + "predicates": { + "minecraft:enchantments": [ + { + "enchantments": "minecraft:silk_touch" + } + ] } } - ] + } }, { "rolls": 1, @@ -30,22 +28,29 @@ { "type": "minecraft:item", "name": "minecraft:knowledge_book", - "functions": [ - { - "function": "minecraft:set_custom_data", - "tag": "{Tags:[\"timber_location\"]}" - } - ], - "conditions": [ - { - "condition": "minecraft:match_tool", - "predicate": { - "items": "#timber:axes" + "modifier": { + "type": "minecraft:set_custom_data", + "tag": "{Tags:[\"timber_location\"]}" + }, + "condition": { + "type": "minecraft:any_of", + "terms": [ + { + "type": "minecraft:match_tool", + "predicate": { + "items": "#timber:axes" + } + }, + { + "type": "minecraft:match_tool", + "predicate": { + "items": "#minecraft:axes" + } } - } - ] + ] + } } ] } ] -} \ No newline at end of file +} diff --git a/data/timber/advancement/axes/found.json b/data/timber/advancement/axes/found.json new file mode 100644 index 0000000..d6daf78 --- /dev/null +++ b/data/timber/advancement/axes/found.json @@ -0,0 +1,292 @@ +{ + "criteria": { + "axe_in_hotbar": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "player": { + "type": "minecraft:any_of", + "terms": [ + { + "type": "minecraft:all_of", + "terms": [ + { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.0": { + "items": "#minecraft:axes" + } + } + } + }, + { + "type": "minecraft:inverted", + "term": { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.0": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "type": "minecraft:all_of", + "terms": [ + { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.1": { + "items": "#minecraft:axes" + } + } + } + }, + { + "type": "minecraft:inverted", + "term": { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.1": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "type": "minecraft:all_of", + "terms": [ + { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.2": { + "items": "#minecraft:axes" + } + } + } + }, + { + "type": "minecraft:inverted", + "term": { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.2": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "type": "minecraft:all_of", + "terms": [ + { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.3": { + "items": "#minecraft:axes" + } + } + } + }, + { + "type": "minecraft:inverted", + "term": { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.3": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "type": "minecraft:all_of", + "terms": [ + { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.4": { + "items": "#minecraft:axes" + } + } + } + }, + { + "type": "minecraft:inverted", + "term": { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.4": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "type": "minecraft:all_of", + "terms": [ + { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.5": { + "items": "#minecraft:axes" + } + } + } + }, + { + "type": "minecraft:inverted", + "term": { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.5": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "type": "minecraft:all_of", + "terms": [ + { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.6": { + "items": "#minecraft:axes" + } + } + } + }, + { + "type": "minecraft:inverted", + "term": { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.6": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "type": "minecraft:all_of", + "terms": [ + { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.7": { + "items": "#minecraft:axes" + } + } + } + }, + { + "type": "minecraft:inverted", + "term": { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.7": { + "items": "#timber:axes" + } + } + } + } + } + ] + }, + { + "type": "minecraft:all_of", + "terms": [ + { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.8": { + "items": "#minecraft:axes" + } + } + } + }, + { + "type": "minecraft:inverted", + "term": { + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "minecraft:slots": { + "hotbar.8": { + "items": "#timber:axes" + } + } + } + } + } + ] + } + ] + }, + "items": [ + { + "items": "#minecraft:axes" + } + ] + } + } + }, + "rewards": { + "function": "timber:axes/auto/found" + } +} diff --git a/data/timber/function/autoplant/plant.mcfunction b/data/timber/function/autoplant/plant.mcfunction index fb72d66..0380e9f 100644 --- a/data/timber/function/autoplant/plant.mcfunction +++ b/data/timber/function/autoplant/plant.mcfunction @@ -13,8 +13,8 @@ execute if block ~ ~ ~ minecraft:farmland[moisture=6] run summon marker ~ ~ ~ {T execute if block ~ ~ ~ minecraft:farmland[moisture=7] run summon marker ~ ~ ~ {Tags:["timber_farmland","timber_moisture_7","global.ignore"]} execute if block ~ ~ ~ minecraft:farmland run schedule function timber:autoplant/farmland_fix 3t execute if block ~ ~ ~ minecraft:farmland run setblock ~ ~ ~ minecraft:dirt -summon minecraft:falling_block ~ ~0.125 ~ {BlockState:{Name:"minecraft:barrier"},Time:1,DropItem:0b,Tags:["timber_item_to_block"]} -execute positioned ~ ~0.125 ~ run data modify entity @e[type=minecraft:falling_block,tag=timber_item_to_block,distance=...1,sort=arbitrary,limit=1] BlockState.Name set from entity @s Item.id +summon minecraft:falling_block ~ ~0.125 ~ {BlockState:"minecraft:barrier",Time:1,DropItem:0b,Tags:["timber_item_to_block"]} +execute positioned ~ ~0.125 ~ run data modify entity @e[type=minecraft:falling_block,tag=timber_item_to_block,distance=...1,sort=arbitrary,limit=1] BlockState set from entity @s Item.id # on stacks -1 execute store result score @s timber run data get entity @s Item.count diff --git a/data/timber/function/axes/auto/add.mcfunction b/data/timber/function/axes/auto/add.mcfunction new file mode 100644 index 0000000..480221c --- /dev/null +++ b/data/timber/function/axes/auto/add.mcfunction @@ -0,0 +1,13 @@ +# Registers the axe in the hotbar slot with the max durability of the item. It is not in the NBT of the item when it is the default +# of the item, but the item predicate damage~{durability:...} sees how much the item can still take: max = that + the damage. +# An item without durability never breaks. +$execute store result score #auto_damage timber run data get entity @s Inventory[{Slot:$(slot)b}].components."minecraft:damage" +scoreboard players set #auto_max timber 2147483647 +$execute if items entity @s hotbar.$(slot) *[damage~{durability:{min:0}}] run function timber:axes/auto/durability +data modify storage timber:axes build set value {} +data modify storage timber:axes build.item set from storage timber:axes auto.item +execute store result storage timber:axes build.durability int 1 run scoreboard players get #auto_max timber +data modify storage timber:axes build.label set from storage timber:axes auto.item +# found by itself: the settings menu shows the name of the item (translation key item.namespace.name) +data modify storage timber:axes build.auto set value 1b +function timber:axes/register diff --git a/data/timber/function/axes/auto/check.mcfunction b/data/timber/function/axes/auto/check.mcfunction new file mode 100644 index 0000000..e832a40 --- /dev/null +++ b/data/timber/function/axes/auto/check.mcfunction @@ -0,0 +1,3 @@ +# an axe that is in the list already (found before, or added with timber:api/add_axe) keeps its values +$execute if data storage timber:axes list[{item:"$(item)"}] run return 0 +function timber:axes/auto/add with storage timber:axes auto diff --git a/data/timber/function/axes/auto/durability.mcfunction b/data/timber/function/axes/auto/durability.mcfunction new file mode 100644 index 0000000..51d518d --- /dev/null +++ b/data/timber/function/axes/auto/durability.mcfunction @@ -0,0 +1,7 @@ +# binary search for the durability the item has left: the highest value that damage~{durability:{min:value}} still matches +scoreboard players set #auto_lo timber 0 +scoreboard players set #auto_hi timber 1048576 +scoreboard players set #auto_two timber 2 +function timber:axes/auto/search +scoreboard players operation #auto_max timber = #auto_lo timber +scoreboard players operation #auto_max timber += #auto_damage timber diff --git a/data/timber/function/axes/auto/found.mcfunction b/data/timber/function/axes/auto/found.mcfunction new file mode 100644 index 0000000..dbc3e32 --- /dev/null +++ b/data/timber/function/axes/auto/found.mcfunction @@ -0,0 +1,15 @@ +# Reward of the advancement timber:axes/found: an axe changed in the inventory while an axe of #minecraft:axes that is not in +# #timber:axes is in the hotbar (the axe of a mod). The ones that are not in the list yet get registered, so they chop without +# timber:api/add_axe. Only the hotbar is checked: an axe has to be in it to be used, moving it there changes the inventory. +advancement revoke @s only timber:axes/found +# after timber:uninstall the list is gone, nothing is registered any more +execute unless data storage timber:axes list run return 0 +execute if items entity @s hotbar.0 #minecraft:axes unless items entity @s hotbar.0 #timber:axes run function timber:axes/auto/slot {slot:0} +execute if items entity @s hotbar.1 #minecraft:axes unless items entity @s hotbar.1 #timber:axes run function timber:axes/auto/slot {slot:1} +execute if items entity @s hotbar.2 #minecraft:axes unless items entity @s hotbar.2 #timber:axes run function timber:axes/auto/slot {slot:2} +execute if items entity @s hotbar.3 #minecraft:axes unless items entity @s hotbar.3 #timber:axes run function timber:axes/auto/slot {slot:3} +execute if items entity @s hotbar.4 #minecraft:axes unless items entity @s hotbar.4 #timber:axes run function timber:axes/auto/slot {slot:4} +execute if items entity @s hotbar.5 #minecraft:axes unless items entity @s hotbar.5 #timber:axes run function timber:axes/auto/slot {slot:5} +execute if items entity @s hotbar.6 #minecraft:axes unless items entity @s hotbar.6 #timber:axes run function timber:axes/auto/slot {slot:6} +execute if items entity @s hotbar.7 #minecraft:axes unless items entity @s hotbar.7 #timber:axes run function timber:axes/auto/slot {slot:7} +execute if items entity @s hotbar.8 #minecraft:axes unless items entity @s hotbar.8 #timber:axes run function timber:axes/auto/slot {slot:8} diff --git a/data/timber/function/axes/auto/key.mcfunction b/data/timber/function/axes/auto/key.mcfunction new file mode 100644 index 0000000..c12c00b --- /dev/null +++ b/data/timber/function/axes/auto/key.mcfunction @@ -0,0 +1 @@ +$data modify storage timber:axes entry.key set value "item.$(ns).$(path)" diff --git a/data/timber/function/axes/auto/probe.mcfunction b/data/timber/function/axes/auto/probe.mcfunction new file mode 100644 index 0000000..3c9ae06 --- /dev/null +++ b/data/timber/function/axes/auto/probe.mcfunction @@ -0,0 +1 @@ +$execute store success score #auto_ok timber if items entity @s hotbar.$(slot) *[damage~{durability:{min:$(mid)}}] diff --git a/data/timber/function/axes/auto/search.mcfunction b/data/timber/function/axes/auto/search.mcfunction new file mode 100644 index 0000000..711e9fb --- /dev/null +++ b/data/timber/function/axes/auto/search.mcfunction @@ -0,0 +1,12 @@ +execute if score #auto_lo timber >= #auto_hi timber run return 0 +# mid = (lo + hi + 1) / 2 +scoreboard players operation #auto_mid timber = #auto_lo timber +scoreboard players operation #auto_mid timber += #auto_hi timber +scoreboard players add #auto_mid timber 1 +scoreboard players operation #auto_mid timber /= #auto_two timber +execute store result storage timber:axes auto.mid int 1 run scoreboard players get #auto_mid timber +function timber:axes/auto/probe with storage timber:axes auto +execute if score #auto_ok timber matches 1 run scoreboard players operation #auto_lo timber = #auto_mid timber +execute if score #auto_ok timber matches 0 run scoreboard players operation #auto_hi timber = #auto_mid timber +execute if score #auto_ok timber matches 0 run scoreboard players remove #auto_hi timber 1 +function timber:axes/auto/search diff --git a/data/timber/function/axes/auto/slot.mcfunction b/data/timber/function/axes/auto/slot.mcfunction new file mode 100644 index 0000000..d79d51a --- /dev/null +++ b/data/timber/function/axes/auto/slot.mcfunction @@ -0,0 +1,5 @@ +# the item id of the axe in the hotbar slot (the Slot of the Inventory has the same number) +$data modify storage timber:axes auto set value {slot:$(slot)} +$data modify storage timber:axes auto.item set from entity @s Inventory[{Slot:$(slot)b}].id +function timber:axes/auto/check with storage timber:axes auto +data remove storage timber:axes auto diff --git a/data/timber/function/axes/create.mcfunction b/data/timber/function/axes/create.mcfunction index a8623c3..651042e 100644 --- a/data/timber/function/axes/create.mcfunction +++ b/data/timber/function/axes/create.mcfunction @@ -17,6 +17,8 @@ data modify storage timber:axes entry.durability set from storage timber:axes bu data modify storage timber:axes entry.label set from storage timber:axes build.label data modify storage timber:axes entry.obj set from storage timber:axes build.obj data modify storage timber:axes entry.holder set from storage timber:axes build.holder +# an axe that timber:axes/auto found: the settings menu shows the name of the item +execute if data storage timber:axes build{auto:1b} run function timber:axes/auto/key with storage timber:axes build # custom axes (added outside of a load, for example typed in chat) survive the next load; timber:axes/init registers the vanilla # axes and the ones of the function tag itself at every load, so those don't need to execute if score #axes_loading timber matches 1 run data modify storage timber:axes entry.custom set value 0b diff --git a/data/timber/function/axes/uninstall.mcfunction b/data/timber/function/axes/uninstall.mcfunction index fb851de..ae23a08 100644 --- a/data/timber/function/axes/uninstall.mcfunction +++ b/data/timber/function/axes/uninstall.mcfunction @@ -8,3 +8,4 @@ data remove storage timber:axes build data remove storage timber:axes entry data remove storage timber:axes pick data remove storage timber:axes wear +data remove storage timber:axes auto diff --git a/data/timber/function/settings/open/help.mcfunction b/data/timber/function/settings/open/help.mcfunction index 2c3ee5f..0cd2a6e 100644 --- a/data/timber/function/settings/open/help.mcfunction +++ b/data/timber/function/settings/open/help.mcfunction @@ -1,5 +1,6 @@ # opens the help dialog; the last button shows whether Timber is on or off for the player -data modify storage timber:settings dialog set value {"type":"minecraft:multi_action","title":"Timber Datapack","external_title":"Timber","body":{"type":"minecraft:plain_message","contents":["",{"text":"The Timber Datapack allows you to instantly chop down a tree just by breaking one log with any axe."},"\n\n",{"text":"By default, sneaking while breaking will not chop the tree."},"\n\n",{"text":"Every player can use "},{"text":"/trigger TimberToggle","color":"blue","click_event":{"action":"suggest_command","command":"/trigger TimberToggle"}},{"text":" or the button below to individually turn the datapack on or off."}],"width":300},"inputs":[],"can_close_with_escape":true,"pause":false,"actions":[{"label":"Check for New Updates","action":{"type":"minecraft:open_url","url":"https://github.com/Moggla/Timber-Datapack/releases"}},{"label":"Settings","tooltip":{"text":"Requires the tag timber_admin.","color":"gray"},"action":{"type":"minecraft:run_command","command":"trigger TimberToggle set 2"}}],"after_action":"none","exit_action":{"label":{"translate":"gui.back"},"action":{"type":"minecraft:run_command","command":"trigger TimberToggle set 4"}}} +# the same dialog as data/timber/dialog/help.json (the one of the pause menu), keep both the same +data modify storage timber:settings dialog set value {"type":"minecraft:multi_action","title":"Timber Datapack","external_title":"Timber","body":{"type":"minecraft:plain_message","contents":["",{"text":"Version v8.0.0","color":"#724E21"},"\n\n",{"text":"The Timber Datapack allows you to instantly chop down a tree just by breaking one log with any axe."},"\n\n",{"text":"By default, sneaking while breaking will not chop the tree."},"\n\n",{"text":"Every player can use "},{"text":"/trigger TimberToggle","color":"blue","click_event":{"action":"suggest_command","command":"/trigger TimberToggle"}},{"text":" or the button below to individually turn the datapack on or off."}],"width":300},"inputs":[],"can_close_with_escape":true,"pause":false,"actions":[{"label":"Check for New Updates","action":{"type":"minecraft:open_url","url":"https://github.com/Moggla/Timber-Datapack/releases"}},{"label":"Settings","tooltip":{"text":"Requires the tag timber_admin.","color":"gray"},"action":{"type":"minecraft:run_command","command":"trigger TimberToggle set 2"}}],"after_action":"none","exit_action":{"label":{"translate":"gui.back"},"action":{"type":"minecraft:run_command","command":"trigger TimberToggle set 4"}}} execute unless score @s timber_disabled matches 1.. run data modify storage timber:settings dialog.actions append value {"label":{"translate":"options.generic_value","with":[{"text":"Timber"},{"translate":"options.on","color":"green"}]},"tooltip":"Turns the datapack on or off for you only.","action":{"type":"minecraft:run_command","command":"trigger TimberToggle set 3"}} execute if score @s timber_disabled matches 1.. run data modify storage timber:settings dialog.actions append value {"label":{"translate":"options.generic_value","with":[{"text":"Timber"},{"translate":"options.off","color":"red"}]},"tooltip":"Turns the datapack on or off for you only.","action":{"type":"minecraft:run_command","command":"trigger TimberToggle set 3"}} function timber:settings/show with storage timber:settings diff --git a/data/timber/function/settings/open/menu.mcfunction b/data/timber/function/settings/open/menu.mcfunction index 38cd58d..c5fff46 100644 --- a/data/timber/function/settings/open/menu.mcfunction +++ b/data/timber/function/settings/open/menu.mcfunction @@ -1,6 +1,6 @@ # opens the "Settings" settings page with the current values # only reachable for admins -data modify storage timber:settings dialog set value {"type":"minecraft:multi_action","title":"Timber Settings","external_title":"Timber Settings","body":{"type":"minecraft:plain_message","contents":["",{"text":"Version v8.0.0","color":"#724E21"},"\n\n",{"text":"Changes are saved for the whole server."}],"width":300},"inputs":[],"can_close_with_escape":true,"pause":false,"after_action":"none","columns":2,"actions":[],"exit_action":{"label":{"translate":"gui.back"},"width":150,"action":{"type":"minecraft:run_command","command":"trigger TimberSettings set 98"}}} +data modify storage timber:settings dialog set value {"type":"minecraft:multi_action","title":"Timber Settings","external_title":"Timber Settings","body":{"type":"minecraft:plain_message","contents":["",{"text":"Changes are saved for the whole server."}],"width":300},"inputs":[],"can_close_with_escape":true,"pause":false,"after_action":"none","columns":2,"actions":[],"exit_action":{"label":{"translate":"gui.back"},"width":150,"action":{"type":"minecraft:run_command","command":"trigger TimberSettings set 98"}}} execute if score standing timber matches 1 run data modify storage timber:settings dialog.actions append value {"label":{"translate":"options.generic_value","with":[{"text":"Works When Standing"},{"translate":"options.on","color":"green"}]},"width":150,"action":{"type":"minecraft:run_command","command":"trigger TimberSettings set 100"}} execute unless score standing timber matches 1 run data modify storage timber:settings dialog.actions append value {"label":{"translate":"options.generic_value","with":[{"text":"Works When Standing"},{"translate":"options.off","color":"red"}]},"width":150,"action":{"type":"minecraft:run_command","command":"trigger TimberSettings set 100"}} execute if score sneaking timber matches 1 run data modify storage timber:settings dialog.actions append value {"label":{"translate":"options.generic_value","with":[{"text":"Works When Sneaking"},{"translate":"options.on","color":"green"}]},"width":150,"action":{"type":"minecraft:run_command","command":"trigger TimberSettings set 101"}} diff --git a/data/timber/function/settings/open/tools_button_key.mcfunction b/data/timber/function/settings/open/tools_button_key.mcfunction new file mode 100644 index 0000000..1bd7c32 --- /dev/null +++ b/data/timber/function/settings/open/tools_button_key.mcfunction @@ -0,0 +1,3 @@ +# the button of an axe that was found by itself (timber:axes/auto): the name of the item, the item id when it has no translation +$execute if score $(holder) timber matches 1 run data modify storage timber:settings dialog.actions append value {"label":{"translate":"options.generic_value","with":[["Enable ",{"translate":"$(key)","fallback":"$(label)"}],{"translate":"options.on","color":"green"}]},"width":150,"action":{"type":"minecraft:run_command","command":"trigger TimberSettings set $(code)"}} +$execute unless score $(holder) timber matches 1 run data modify storage timber:settings dialog.actions append value {"label":{"translate":"options.generic_value","with":[["Enable ",{"translate":"$(key)","fallback":"$(label)"}],{"translate":"options.off","color":"red"}]},"width":150,"action":{"type":"minecraft:run_command","command":"trigger TimberSettings set $(code)"}} diff --git a/data/timber/function/settings/open/tools_next.mcfunction b/data/timber/function/settings/open/tools_next.mcfunction index 216fc4e..e07167a 100644 --- a/data/timber/function/settings/open/tools_next.mcfunction +++ b/data/timber/function/settings/open/tools_next.mcfunction @@ -1,6 +1,7 @@ execute unless data storage timber:axes queue[0] run return 0 execute store result storage timber:axes queue[0].code int 1 run scoreboard players get #axe_code timber -function timber:settings/open/tools_button with storage timber:axes queue[0] +execute unless data storage timber:axes queue[0].key run function timber:settings/open/tools_button with storage timber:axes queue[0] +execute if data storage timber:axes queue[0].key run function timber:settings/open/tools_button_key with storage timber:axes queue[0] scoreboard players add #axe_code timber 1 data remove storage timber:axes queue[0] function timber:settings/open/tools_next diff --git a/data/timber/predicate/block/cap.json b/data/timber/predicate/block/cap.json index 807ada7..fb9867d 100644 --- a/data/timber/predicate/block/cap.json +++ b/data/timber/predicate/block/cap.json @@ -1,8 +1,8 @@ { - "condition": "minecraft:any_of", + "type": "minecraft:any_of", "terms": [ { - "condition": "minecraft:location_check", + "type": "minecraft:location_check", "predicate": { "block": { "blocks": "#minecraft:wart_blocks" @@ -10,7 +10,7 @@ } }, { - "condition": "minecraft:location_check", + "type": "minecraft:location_check", "predicate": { "block": { "blocks": "minecraft:shroomlight" @@ -18,7 +18,7 @@ } }, { - "condition": "minecraft:location_check", + "type": "minecraft:location_check", "predicate": { "block": { "blocks": "minecraft:brown_mushroom_block" @@ -26,7 +26,7 @@ } }, { - "condition": "minecraft:location_check", + "type": "minecraft:location_check", "predicate": { "block": { "blocks": "minecraft:red_mushroom_block" @@ -34,4 +34,4 @@ } } ] -} \ No newline at end of file +} diff --git a/data/timber/predicate/block/leaf.json b/data/timber/predicate/block/leaf.json index 69effa4..33e0408 100644 --- a/data/timber/predicate/block/leaf.json +++ b/data/timber/predicate/block/leaf.json @@ -1,8 +1,8 @@ { - "condition": "minecraft:any_of", + "type": "minecraft:any_of", "terms": [ { - "condition": "minecraft:location_check", + "type": "minecraft:location_check", "predicate": { "block": { "blocks": "#minecraft:leaves", @@ -13,10 +13,10 @@ } }, { - "condition": "minecraft:all_of", + "type": "minecraft:all_of", "terms": [ { - "condition": "minecraft:location_check", + "type": "minecraft:location_check", "predicate": { "block": { "blocks": "#minecraft:leaves" @@ -24,7 +24,7 @@ } }, { - "condition": "minecraft:entity_scores", + "type": "minecraft:entity_scores", "entity": "this", "scores": { "timber_persistent": { @@ -35,7 +35,7 @@ ] }, { - "condition": "minecraft:location_check", + "type": "minecraft:location_check", "predicate": { "block": { "blocks": "minecraft:mangrove_propagule", diff --git a/data/timber/predicate/block/log.json b/data/timber/predicate/block/log.json index 3b960aa..5ce9666 100644 --- a/data/timber/predicate/block/log.json +++ b/data/timber/predicate/block/log.json @@ -1,5 +1,5 @@ { - "condition": "minecraft:location_check", + "type": "minecraft:location_check", "predicate": { "block": { "blocks": "#minecraft:logs" diff --git a/data/timber/predicate/block/stem.json b/data/timber/predicate/block/stem.json index 591f3db..4f22e0d 100644 --- a/data/timber/predicate/block/stem.json +++ b/data/timber/predicate/block/stem.json @@ -1,8 +1,8 @@ { - "condition": "minecraft:any_of", + "type": "minecraft:any_of", "terms": [ { - "condition": "minecraft:location_check", + "type": "minecraft:location_check", "predicate": { "block": { "blocks": "#minecraft:logs" @@ -10,7 +10,7 @@ } }, { - "condition": "minecraft:location_check", + "type": "minecraft:location_check", "predicate": { "block": { "blocks": "minecraft:mushroom_stem" @@ -18,4 +18,4 @@ } } ] -} \ No newline at end of file +} diff --git a/data/timber/predicate/item/log.json b/data/timber/predicate/item/log.json index 7fea675..dee4b89 100644 --- a/data/timber/predicate/item/log.json +++ b/data/timber/predicate/item/log.json @@ -1,5 +1,5 @@ { - "condition": "minecraft:entity_properties", + "type": "minecraft:entity_properties", "entity": "this", "predicate": { "equipment": { @@ -8,4 +8,4 @@ } } } -} \ No newline at end of file +} diff --git a/data/timber/predicate/item/root.json b/data/timber/predicate/item/root.json index f746554..b4c236d 100644 --- a/data/timber/predicate/item/root.json +++ b/data/timber/predicate/item/root.json @@ -1,5 +1,5 @@ { - "condition": "minecraft:entity_properties", + "type": "minecraft:entity_properties", "entity": "this", "predicate": { "equipment": { @@ -8,4 +8,4 @@ } } } -} \ No newline at end of file +} diff --git a/data/timber/predicate/item/sapling.json b/data/timber/predicate/item/sapling.json index 31bd5c7..88e2bf9 100644 --- a/data/timber/predicate/item/sapling.json +++ b/data/timber/predicate/item/sapling.json @@ -1,5 +1,5 @@ { - "condition": "minecraft:entity_properties", + "type": "minecraft:entity_properties", "entity": "this", "predicate": { "equipment": { @@ -8,4 +8,4 @@ } } } -} \ No newline at end of file +} diff --git a/data/timber/predicate/item/stem.json b/data/timber/predicate/item/stem.json index 43b5e29..a820b2c 100644 --- a/data/timber/predicate/item/stem.json +++ b/data/timber/predicate/item/stem.json @@ -1,8 +1,8 @@ { - "condition": "minecraft:any_of", + "type": "minecraft:any_of", "terms": [ { - "condition": "minecraft:entity_properties", + "type": "minecraft:entity_properties", "entity": "this", "predicate": { "equipment": { @@ -13,7 +13,7 @@ } }, { - "condition": "minecraft:entity_properties", + "type": "minecraft:entity_properties", "entity": "this", "predicate": { "equipment": { @@ -24,7 +24,7 @@ } }, { - "condition": "minecraft:entity_properties", + "type": "minecraft:entity_properties", "entity": "this", "predicate": { "equipment": { @@ -42,4 +42,4 @@ } } ] -} \ No newline at end of file +} diff --git a/data/timber/predicate/random_chance/0.25.json b/data/timber/predicate/random_chance/0.25.json index 9740f91..c4155b5 100644 --- a/data/timber/predicate/random_chance/0.25.json +++ b/data/timber/predicate/random_chance/0.25.json @@ -1,4 +1,4 @@ { - "condition": "minecraft:random_chance", - "chance": 0.25 - } \ No newline at end of file + "type": "minecraft:random_chance", + "chance": 0.25 +} diff --git a/data/timber/predicate/random_chance/0.333.json b/data/timber/predicate/random_chance/0.333.json index 52e5ecf..79001a1 100644 --- a/data/timber/predicate/random_chance/0.333.json +++ b/data/timber/predicate/random_chance/0.333.json @@ -1,4 +1,4 @@ { - "condition": "minecraft:random_chance", - "chance": 0.333 - } \ No newline at end of file + "type": "minecraft:random_chance", + "chance": 0.333 +} diff --git a/data/timber/predicate/random_chance/0.5.json b/data/timber/predicate/random_chance/0.5.json index 66c2b14..62d7fd5 100644 --- a/data/timber/predicate/random_chance/0.5.json +++ b/data/timber/predicate/random_chance/0.5.json @@ -1,4 +1,4 @@ { - "condition": "minecraft:random_chance", - "chance": 0.5 - } \ No newline at end of file + "type": "minecraft:random_chance", + "chance": 0.5 +} diff --git a/data/timber/predicate/sneaking.json b/data/timber/predicate/sneaking.json index a41c89c..ab3659c 100644 --- a/data/timber/predicate/sneaking.json +++ b/data/timber/predicate/sneaking.json @@ -1,9 +1,9 @@ { - "condition": "minecraft:entity_properties", - "entity": "this", - "predicate": { - "flags": { - "is_sneaking": true - } + "type": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "flags": { + "is_sneaking": true } -} \ No newline at end of file + } +} diff --git a/pack.mcmeta b/pack.mcmeta index c9f3a12..73dd93e 100644 --- a/pack.mcmeta +++ b/pack.mcmeta @@ -7,7 +7,7 @@ }, "overlays": { "entries": [ - {"directory": "121", "min_format": 121, "max_format": 121} + {"directory": "101", "min_format": 101, "max_format": 120} ] } } diff --git a/tests/data/minecraft/tags/item/axes.json b/tests/data/minecraft/tags/item/axes.json new file mode 100644 index 0000000..a6a1a29 --- /dev/null +++ b/tests/data/minecraft/tags/item/axes.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:blaze_rod", + "minecraft:breeze_rod" + ] +} diff --git a/tests/data/timber_test/function/env/axes_auto_setup.mcfunction b/tests/data/timber_test/function/env/axes_auto_setup.mcfunction new file mode 100644 index 0000000..4640846 --- /dev/null +++ b/tests/data/timber_test/function/env/axes_auto_setup.mcfunction @@ -0,0 +1,2 @@ +#> Setting for the test of this environment +#> The test lets the datapack find axes that nobody registered (the blaze rod and the breeze rod are in #minecraft:axes) diff --git a/tests/data/timber_test/function/env/axes_auto_teardown.mcfunction b/tests/data/timber_test/function/env/axes_auto_teardown.mcfunction new file mode 100644 index 0000000..3896ca8 --- /dev/null +++ b/tests/data/timber_test/function/env/axes_auto_teardown.mcfunction @@ -0,0 +1,4 @@ +#> Back to the default +#> A found axe survives timber:axes/init like a custom one: uninstall clears the registry, init rebuilds it the way a load does +function timber:axes/uninstall +function timber:axes/init diff --git a/tests/data/timber_test/test/axes_auto_found_axe_chops_a_tree.mcfunction b/tests/data/timber_test/test/axes_auto_found_axe_chops_a_tree.mcfunction new file mode 100644 index 0000000..afdddbc --- /dev/null +++ b/tests/data/timber_test/test/axes_auto_found_axe_chops_a_tree.mcfunction @@ -0,0 +1,43 @@ +#> An axe of #minecraft:axes that nobody registered is found when it is in the hotbar, with the durability of the item, and chops a tree +# @environment timber_test:axes_auto +# @template timber_test:arena +# @timeout 400 +# @skyaccess true + +function timber_test:platform +function timber_test:tree {feature:"minecraft:oak"} +assert block ~20 ~ ~20 #minecraft:logs + +await delay 1s +scoreboard objectives add timber_test dummy +function timber_test:count_d7 {test:"axes_auto_found_axe_chops_a_tree"} +function timber_test:player {name:"auto_axe_t",axe:"minecraft:iron_axe"} + +# a vanilla axe is known already: the list stays at the 7 vanilla axes and the stick of the tests +await delay 5t +execute store result score #auto_n timber_test run data get storage timber:axes list +assert score #auto_n timber_test matches 8 + +# the blaze rod and the breeze rod are in #minecraft:axes (test datapack), nobody registered them. +# The blaze rod can take 40 and has taken 5 already, the breeze rod has no durability. +item replace entity @e[type=minecraft:player,name=auto_axe_t,limit=1] weapon.mainhand with minecraft:blaze_rod[minecraft:max_damage=40,minecraft:damage=5,minecraft:max_stack_size=1,minecraft:tool={rules:[{blocks:"#minecraft:logs",speed:6,correct_for_drops:true}],default_mining_speed:1,damage_per_block:1}] +item replace entity @e[type=minecraft:player,name=auto_axe_t,limit=1] hotbar.1 with minecraft:breeze_rod +await data storage timber:axes list[{item:"minecraft:blaze_rod"}] +await data storage timber:axes list[{item:"minecraft:breeze_rod"}] +assert data storage timber:axes list[{item:"minecraft:blaze_rod",durability:40,key:"item.minecraft.blaze_rod",custom:1b}] +assert data storage timber:axes list[{item:"minecraft:breeze_rod",durability:2147483647}] +execute store result score #auto_n timber_test run data get storage timber:axes list +assert score #auto_n timber_test matches 10 + +function timber_test:mine {name:"auto_axe_t"} + +# wait until the datapack has had its chance to act +# (await doesn't work inside a called function, so this block is repeated in every test) +# 1. the base log is gone: the dummy hit the tree +# 2. five ticks pass: the datapack reacts to the mined block in the next tick or two +# 3. no marker is left in the arena +await not block ~20 ~ ~20 #minecraft:logs +await delay 5t +await not entity @e[type=minecraft:marker,dx=39,dy=39,dz=39] + +function timber_test:assert_no_tree {test:"axes_auto_found_axe_chops_a_tree"} diff --git a/tests/data/timber_test/test_environment/axes_auto.json b/tests/data/timber_test/test_environment/axes_auto.json new file mode 100644 index 0000000..6cfc2fb --- /dev/null +++ b/tests/data/timber_test/test_environment/axes_auto.json @@ -0,0 +1,5 @@ +{ + "type": "minecraft:function", + "setup": "timber_test:env/axes_auto_setup", + "teardown": "timber_test:env/axes_auto_teardown" +}