Skip to content

Commit

Permalink
Remove old crafting loop in favor of Pack Format 38 crafting, update …
Browse files Browse the repository at this point in the history
…nbt matching syntax, update readme, fix that magnets on spectators still work
  • Loading branch information
budak7273 committed Jul 27, 2024
1 parent 2fce60e commit 747840f
Show file tree
Hide file tree
Showing 17 changed files with 141 additions and 189 deletions.
53 changes: 28 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,42 @@
# Magnet

Survival-friendly datapack for Minecraft that adds an item magnet which attracts items to the wielder in a small radius.

## Download [here](https://github.com/budak7273/magnet/releases), put zip in your save's datapacks folder, then run `/reload` to install.
## Download [here](https://github.com/budak7273/magnet/releases), put zip in your save's datapacks folder, then run `/reload` to install

![Magnet item tooltip](https://i.imgur.com/84YWGfQ.png)
Players will receive a message in the chat upon unlocking the recipe
(obtaining an iron ingot) informing them of its existence.

Craft chainmail leggings using a custom recipe to obtain a magnet.
Craft a magnet (enhanced Chainmail Leggings) in your local Crafting Table or Crafter.

![Magnet crafting recipe](https://i.imgur.com/Rf1a2TE.png)
![Magnet crafting recipe](https://i.imgur.com/dc2A8DY.png)

## Features
* Lag friendly!
* Configurable!
* Run `/function magnet:toggle_options_pane` to see options.

* Brings items to you!
* Break blocks over a void without fear of dropping items off the edge.
* Configurable!
* Run `/function magnet:toggle_options_pane` to see options. Read the section below for more details.
* Lag friendly!
* Survival friendly
* Custom crafting recipe provides a method of obtaining magnets in a survival playthrough
* Nearby item entities play a quiet sound to help you locate them (configurable)
* Works for multiple players at once
* Multiplayer compatible
* Wear a magnet as pants!
* Both functional _and_ stylish.
* Mobs can also use magnets (configurable)
* Make a magnet powered mobfarm! Use mobs (or armor stands) wearing magnets to gather items to a hopper and save on hoppers
* Mobs with magnets can attract and equip your gear if you die. (disabled by default) Don't die near a mob with a magnet.
* Armor stands can use magnets (configurable, on by default)
* Make a magnet powered mobfarm! Use armor stands wearing magnets to gather items to a central hopper.
* Mobs can also use magnets (configurable, off by default)
* Mobs with magnets can attract and possibly equip dropped gear. Don't die near a mob with a magnet.
* Particles are displayed when an item is brought to a magnet user (configurable)
* Works on Spigot/Paper/Etc.
* Works on Fabric/Paper/etc. servers

## Commands

* `/function magnet:toggle_options_pane`
* Toggles the options pane to show/hide the current config settings.
* `/function magnet:give_magnet`
* Gives yourself a magnet if you don't want to craft one.
* Gives you a magnet's crafting ingredients for testing.
* `/function magnet:magnetize_item`
* Manually teleport an item entity within range to you as if you were holding a magnet.
* `/function magnet:default_configs`
Expand All @@ -46,38 +51,36 @@ Craft chainmail leggings using a custom recipe to obtain a magnet.
* Display the total crafted magnets stats scoreboard in the sidebar

## Config Options

Use `/scoreboard players set optionNameHere m_options valueHere` to set values

* `m_mob_interval` (Default 20) - The number of ticks between magnets working for mobs. 20 ticks in one second.
* `m_player_interval` (Default 5) - The number of ticks between magnets working for players. 20 ticks in one second.
* `armorStand` (Default 1) - If magnets work when equipped on armor stands.
* `armorStand` (Default 1) - If magnets work when equipped on armor stands (leggings slot).
* `playerHands` (Default 1) - If magnets work when in the player's main or offhand
* `playerEquip` (Default 1) - If magnets work when in the player's legs slot.
* `particlesOnHolder` (Default 1) - If particles should be spawned on the magnet user when an item is attracted.
* `particlesOnItem` (Default 1) - If particles should be spawned at the old location of the item when an item is attracted.
* `playItemSound` (Default 1) - If items should play a sound when within 10 blocks of a magnet user.
* `enabledActionbarText` (Default 1) - If having a magnet equipped should display text in your action bar.
* `allMobs_Laggy` (Default 0) - If magnets work for every mob than can equip armor. This can be quite laggy to enable.
* `allMobs_Laggy` (Default 0) - If magnets work for every mob than can equip armor. It will function when the item is in the leggings slot (ex. Zombies) or primary hand slot (ex. Fox) This can be quite laggy to enable.

## Further Details

* I tried to document exactly how everything works via comments in the function files. Feel free to contact me with any questions.
* Regular chainmail leggings are unaffected and can be used normally.
* Avoid crafting a magnet while you have chainmail leggings in your inventory. A shortcoming of my method of detecting the crafting means that they will lose their data.
* Teleports items to you in a 5 block radius.
* Only one item entity at a time is teleported on purpose, so you can't 'carry' multiple stacks of item entities with you as you move like you can with many modded magnets.
* Makes all items in a 10 block radius play a quiet sound (from the "player" sound category) to help you find them.
* Makes all items in a 10 block radius play a quiet sound (in the "player" sound category) to help you find them.
* Plays a quieter, pitch shifted version of the Experience Bottle Thrown sound, if you have captions enabled.
* More item entities causes the sounds to stack and get louder.
* Any mob that can wear a magnet in its legs slot will have the magnet effect applied on equip. Tested with zombies, skeletons, zombie pigmen, and villagers. Would probably work for foxes as well.
* When `allMobs_Laggy` is enabled, any mob wearing a magnet in its legs slot or primary hand slot will have the magnet effect applied. Tested with zombies, skeletons, zombie pigmen, foxes, and villagers.

## Credit
* I based my crafting system off of the one that SethBling uses in his [Water Mill datapack](https://www.youtube.com/watch?v=hG-KOFf5GbM).
* If you are looking to create a custom crafting recipe that produces an item with NBT data, I strongly suggest that you look at the comments I wrote in my functions. SethBling didn't leave any explanatory comments in his function files, and his process was difficult to follow at first.
* I used an [online generator](https://advancements.thedestruc7i0n.ca/) to produce the advancement used to grant the recipes.

* I used an [online tellraw generator](https://minecraft.tools/en/tellraw.php) to produce tellraw commands - those are a pain.
* Multiple stackoverflow, reddit, and minecraft forums posts explaining command behavior and nitpicky syntax were read in the process of squashing bugs.

## Known Bugs
* Because Minecraft advancements are buggy, trading with a villager for Chainmail Leggings counts as crafting them using the custom recipe.
* If you need regular chainmail leggings, either drop them out of the villager window, or craft 2 magnets together and directly drop the product out of the crafting window, then wait for 5 seconds (you should see a message in chat when it's safe to pick them up)

## Planned features (Eventually™)

* Offer a resource pack to clients that retextures the magnet item.
8 changes: 0 additions & 8 deletions data/magnet/function/crafting_dropped_item_error.mcfunction

This file was deleted.

4 changes: 2 additions & 2 deletions data/magnet/function/debug_list_holders.mcfunction
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#execute as @e[type=!minecraft:player,nbt={ArmorItems:[{}, {tag: {isMagnet:1b}}, {}, {}]}, sort=random] at @s run say I am holding a magnet.

# Make entities glow
effect give @e[type=!minecraft:player,nbt={ArmorItems:[{}, {tag: {isMagnet:1b}}, {}, {}]}] minecraft:glowing 30 0 true
effect give @e[type=!minecraft:player,nbt={ArmorItems: [{}, {components:{"minecraft:custom_data": {isMagnet: 1b}} }, {}, {}]}] minecraft:glowing 30 0 true

# Command that lists them all + helper text
tellraw @s ["",{"text":"Loaded entities holding magnets:\n","bold":true,"color":"yellow"},{"text":" ["},{"selector":"@e[type=!minecraft:player,nbt={ArmorItems:[{}, {tag: {isMagnet:1b}}, {}, {}]}]"},{"text":"]\n\nThey have all been given glowing for 30 seconds.\nTo teleport to one of them hover over them in the list to get their UUID, then type: "},{"text":"/tp <uuid>","color":"yellow","clickEvent":{"action":"suggest_command","value":"/tp UUID"},"hoverEvent":{"action":"show_text","contents":"Suggest command"}},{"text":"\nYou should probably copy-paste them in from your log file.\n\nAlternatively, you can select them for commands via:\n"},{"text":"@e[type=!minecraft:player,nbt={ArmorItems:[{}, {tag: {isMagnet:1b}}, {}, {}]}]","color":"yellow","clickEvent":{"action":"copy_to_clipboard","value":"@e[type=!minecraft:player,nbt={ArmorItems:[{}, {tag: {isMagnet:1b}}, {}, {}]}]"},"hoverEvent":{"action":"show_text","contents":"Click to Copy"}}]
tellraw @s ["",{"text":"Loaded mobs holding magnets:\n","bold":true,"color":"yellow"},{"text":"Legs: ["},{"selector":"@e[type=!minecraft:player,nbt={ArmorItems: [{}, {components:{'minecraft:custom_data': {isMagnet: 1b}} }, {}, {}]}]"},{"text":"]\nHandheld: ["},{"selector":"@e[type=!minecraft:player,nbt={HandItems: [{components:{'minecraft:custom_data': {isMagnet: 1b}}}]}]"},{"text":"]\n\nThey have all been given glowing for 30 seconds.\nUse this to teleport to one: "},{"text":"[Click to suggest legs command]","color":"yellow","clickEvent":{"action":"suggest_command","value":"/tp @e[type=!minecraft:player,nbt={ArmorItems: [{}, {components:{'minecraft:custom_data': {isMagnet: 1b}} }, {}, {}]}, limit=1]"},"hoverEvent":{"action":"show_text","contents":"Suggest command"}},{"text":" "},{"text":"[Click to suggest handheld command]","color":"yellow","clickEvent":{"action":"suggest_command","value":"/tp @e[type=!minecraft:player,nbt={HandItems: [{components:{'minecraft:custom_data': {isMagnet: 1b}}}]}, limit=1]"},"hoverEvent":{"action":"show_text","contents":"Suggest command"}},{"text":"\nYou can select them for commands via:\n"},{"text":"@e[type=!minecraft:player,nbt={ArmorItems: [{}, {components:{'minecraft:custom_data': {isMagnet: 1b}} }, {}, {}]}]","color":"yellow","clickEvent":{"action":"copy_to_clipboard","value":"@e[type=!minecraft:player,nbt={ArmorItems: [{}, {components:{'minecraft:custom_data': {isMagnet: 1b}} }, {}, {}]}]"},"hoverEvent":{"action":"show_text","contents":"Click to Copy"}}]
10 changes: 6 additions & 4 deletions data/magnet/function/give_magnet.mcfunction
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Gives the caller one properly formatted magnet item. The cause of the actual magnetism is the {isMagnet:1b} tag.
give @s minecraft:chainmail_leggings{isMagnet:1b, display:{Lore:["{\"text\":\" \"}", "{\"text\":\"When in main hand:\",\"color\":\"gray\",\"italic\":false}", "{\"text\":\"When in offhand:\",\"color\":\"gray\",\"italic\":false}", "{\"text\":\"When on legs:\",\"color\":\"gray\",\"italic\":false}", "{\"text\":\" 5 Block Item Magnetism\",\"color\":\"dark_green\",\"italic\":false}","{\"text\":\" 10 Block Item Sense\",\"color\":\"dark_green\",\"italic\":false}", "{\"text\":\"Works when equipped by mobs.\",\"color\":\"gray\"}"], Name:"{\"text\":\"Magnet\",\"italic\":false,\"color\":\"yellow\"}"}, HideFlags: 63, Unbreakable:1,Enchantments:[{id:"minecraft:invalid_enchantment_for_glimmer",lvl:1}]} 1
execute as @s at @s run playsound minecraft:block.anvil.use voice @s ~ ~ ~ 0.25 1.5

# Play a sound
execute as @s at @s run playsound minecraft:block.anvil.use voice @s ~ ~ ~ 0.25 1.5
give @s minecraft:iron_ingot 5
give @s minecraft:red_dye 1
give @s minecraft:blue_dye 1

tell @s Ingredients required to craft a magnet given.
9 changes: 0 additions & 9 deletions data/magnet/function/init.mcfunction
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
# Print load message
tellraw @a ["",{"text":"\u2714","color":"dark_green"},{"text":" Magnet datapack loaded.\nGet some iron and go craft a "},{"text":"Magnet","color":"yellow"},{"text":".\nMore info "},{"text":"here","underlined":true,"clickEvent":{"action":"open_url","value":"http://bit.ly/MagnetDatapack"}},{"text":".\nTo configure the datapack, click "}, {"text":"[here]","color":"yellow","clickEvent":{"action":"run_command","value":"/function magnet:toggle_options_pane"},"hoverEvent":{"action":"show_text","contents":"Toggle options pane"}},{"text":"\nor type: "},{"text":"/function magnet:toggle_options_pane","color":"yellow","clickEvent":{"action":"suggest_command","value":"/function magnet:toggle_options_pane"},"hoverEvent":{"action":"show_text","contents":"Click to suggest"}},{"text":"\n "}]

# Set up scoreboard values for tracking crafting of chainmail leggings
scoreboard objectives add m_craft_leggings minecraft.crafted:minecraft.chainmail_leggings
scoreboard objectives add m_count_magnets dummy
scoreboard objectives add m_count_reg_legs dummy

# Fun crafted magnets counter
scoreboard objectives add m_total_crafted_magnets dummy "Magnets Crafted"

# Set up scoreboard values for timed magnetization and internal settings
scoreboard objectives add m_internals dummy "Magnet Internal"

Expand Down Expand Up @@ -45,4 +37,3 @@ scoreboard players operation optionsOpen m_internals *= optionsOpen m_internals

# If setup never ran, run setup script
execute if score ranSetup m_internals matches 0 run function magnet:default_configs

3 changes: 3 additions & 0 deletions data/magnet/function/magnetize_item.mcfunction
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ execute if score enabledActionbarText m_options matches 1 run title @s actionbar
# Particles on item
execute if score particlesOnItem m_options matches 1 run execute as @e[limit=1,sort=nearest,distance=0..5,type=minecraft:item] at @s if entity @e[distance=0..5, type=item] run particle minecraft:reverse_portal ~ ~.25 ~ 0 0 0 0.1 3 normal

# TODO figure out how to dynamically select this particle's destination
# /particle minecraft:vibration{destination:{type:"block", pos:[0,0,0]}, arrival_in_ticks:100}

# Teleport nearest item entity to the function's caller
tp @e[limit=1,sort=nearest,distance=0..5,type=minecraft:item] @s
# Move 1 block towards the holder's feet (broken)
Expand Down
7 changes: 5 additions & 2 deletions data/magnet/function/on_mob_interval.mcfunction
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ scoreboard players set m_timer_mob m_internals 0
#Random sort so that mobs 'fight' for items and if multiple have magnets they are more likely to suck up gear that others don't need

# Detect magnet in armor stands' leggings armor slot. Exclude if all mobs is on
execute unless score allMobs_Laggy m_options matches 1 if score armorStand m_options matches 1 run execute as @e[type=minecraft:armor_stand, nbt={ArmorItems:[{}, {tag: {isMagnet:1b}}, {}, {}]}, sort=random] at @s run function magnet:magnetize_item
execute unless score allMobs_Laggy m_options matches 1 if score armorStand m_options matches 1 run execute as @e[type=minecraft:armor_stand, sort=random, nbt={ArmorItems: [{}, {components:{"minecraft:custom_data": {isMagnet: 1b}} }, {}, {}]}] at @s run function magnet:magnetize_item

# Detect magnet in any mobs' leggings armor slot.
execute if score allMobs_Laggy m_options matches 1 run execute as @e[type=!minecraft:player,nbt={ArmorItems:[{}, {tag: {isMagnet:1b}}, {}, {}]}, sort=random] at @s run function magnet:magnetize_item
execute if score allMobs_Laggy m_options matches 1 run execute as @e[type=!minecraft:player,nbt={ArmorItems: [{}, {components:{"minecraft:custom_data": {isMagnet: 1b}} }, {}, {}]}, sort=random] at @s run function magnet:magnetize_item

# Detect magnet in any mobs' hand slot (ex. Foxes).
execute if score allMobs_Laggy m_options matches 1 run execute as @e[type=!minecraft:player,nbt={HandItems: [{components:{"minecraft:custom_data": {isMagnet: 1b}}}]}, sort=random] at @s run function magnet:magnetize_item
7 changes: 3 additions & 4 deletions data/magnet/function/on_player_interval.mcfunction
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
scoreboard players set m_timer_player m_internals 0

# Detect magnet held in player main hand
execute if score playerHands m_options matches 1 run execute as @a[nbt={SelectedItem:{tag: {isMagnet:1b}}}] at @s run function magnet:magnetize_item
execute if score playerHands m_options matches 1 run execute as @a[gamemode=!spectator, nbt={SelectedItem:{components: {"minecraft:custom_data": {isMagnet: 1b}}}}] at @s run function magnet:magnetize_item
# Detect magnet equipped in player offhand
execute if score playerHands m_options matches 1 run execute as @a[nbt={Inventory:[{Slot: -106b, tag: {isMagnet:1b}}]}] at @s run function magnet:magnetize_item

execute if score playerHands m_options matches 1 run execute as @a[gamemode=!spectator, nbt={Inventory:[{Slot: -106b, components: {"minecraft:custom_data": {isMagnet: 1b}}}]}] at @s run function magnet:magnetize_item
# Detect magnet equipped in player leggings slot
execute if score playerEquip m_options matches 1 run execute as @a[nbt={Inventory:[{Slot: 101b, tag: {isMagnet:1b}}]}] at @s run function magnet:magnetize_item
execute if score playerEquip m_options matches 1 run execute as @a[gamemode=!spectator, nbt={Inventory:[{Slot: 101b, components: {"minecraft:custom_data": {isMagnet: 1b}}}]}] at @s run function magnet:magnetize_item
5 changes: 1 addition & 4 deletions data/magnet/function/tick.mcfunction
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# Detect players that have crafted at least one pair of leggings and deal with that
execute as @a[scores={m_craft_leggings=1..}] if score @s m_craft_leggings matches 1.. run function magnet:while001_crafted_legs

# Increment global timers by 1
scoreboard players add m_timer_player m_internals 1
scoreboard players add m_timer_mob m_internals 1
Expand All @@ -9,4 +6,4 @@ scoreboard players add m_timer_mob m_internals 1
execute if score m_timer_player m_internals >= m_player_interval m_options run function magnet:on_player_interval

# If mob timer exceeds m_mob_interval, set it back to zero
execute if score m_timer_mob m_internals >= m_player_interval m_options run function magnet:on_mob_interval
execute if score m_timer_mob m_internals >= m_player_interval m_options run function magnet:on_mob_interval
8 changes: 1 addition & 7 deletions data/magnet/function/uninstall.mcfunction
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@

advancement revoke @a only magnet:root

scoreboard objectives remove m_internals
scoreboard objectives remove m_options
scoreboard objectives remove m_total_crafted_magnets

scoreboard objectives remove m_count_magnets
scoreboard objectives remove m_count_reg_legs
scoreboard objectives remove m_craft_leggings

team remove magnet_internal
team remove magnet_option
team remove magnet_option
29 changes: 0 additions & 29 deletions data/magnet/function/while001_crafted_legs.mcfunction

This file was deleted.

Loading

0 comments on commit 747840f

Please sign in to comment.