Hey all! I've been working on recreating the Silk Spawner plugin with vanilla functions. I've already been getting help from several people in a discord server, but I've come to you all for help.
I'm stuck on being able to mine a spawner and summon one in item form that has the block's nbt data. I'm looking for a way to target the block that the player is looking at. That way, when it is a spawner block, I can use the data command to add it's spawning data to a mob spawner entity that I drop. Does anybody have a good way to do this? If not, I have other ideas about how I can implement this.
I'll probably keep this post updated with what I'm doing before I release it. But again, help is appreciated!
Seems doable, but it is kind of limit (depend on how many spawn data you want to copy).
First, you need scoreboard minecraft.broken:minecraft.mob_spawner to detemine if the player actually broke the spawner.
Then, you need to create a block tag in your data pack which it contain a list of block that tell which block the ray should pass. (air,sign,wall_sign,lever,torch,#minecraft:water,#minecraft:buttons,etc.)
Now, here is the main part.
#either in a function or command block, where you need player to run repeatedly
execute as @s at @s positioned ~ ~1.62 ~ run function namespace:ray
#ray
execute if entity @s[distance=..6] if block ~ ~ ~ minecraft:mob_spawner run function namespace:getspawnertype
execute if entity @s[distance=..6] if block ~ ~ ~ #namespace:pass positioned ^ ^ ^0.1 run function namespace:ray
#getspawnertype
execute if block ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:pig"}} run tag @s add spawner_pig
execute if block ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:cow"}} run tag @s add spawner_cow
execute if block ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:zombie"}} run tag @s add spawner_zombie
execute if block ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:spider"}} run tag @s add spawner_spider
...
Once the player have a score of 1 in minecraft.broken:minecraft.mob_spawner, give them the correspond spawner, then remove the score and tag.
Seems doable, but it is kind of limit (depend on how many spawn data you want to copy).
First, you need scoreboard minecraft.broken:minecraft.mob_spawner to detemine if the player actually broke the spawner.
Then, you need to create a block tag in your data pack which it contain a list of block that tell which block the ray should pass. (air,sign,wall_sign,lever,torch,#minecraft:water,#minecraft:buttons,etc.)
Now, here is the main part.
#either in a function or command block, where you need player to run repeatedly
execute as @s at @s positioned ~ ~1.62 ~ run function namespace:ray
#ray
execute if entity @s[distance=..6] if block ~ ~ ~ minecraft:mob_spawner run function namespace:getspawnertype
execute if entity @s[distance=..6] if block ~ ~ ~ #minecraft:pass positioned ^ ^ ^0.1 run function namespace:ray
#getspawnertype
execute if block ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:pig"}} run tag @s add spawner_pig
execute if block ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:cow"}} run tag @s add spawner_cow
execute if block ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:zombie"}} run tag @s add spawner_zombie
execute if block ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:spider"}} run tag @s add spawner_spider
...
Once the player have a score of 1 in minecraft.broken:minecraft.mob_spawner, give them the correspond spawner, then remove the score and tag.
I appreciate your insight!
Can you give me some quick info about setting up that tag? I have not tested all of that code yet, but merely put it into my data pack.
Also, anywhere that you have "namespace" can that be replaced with my datapack's folder name?
Not quite right...See those two commands in #ray function?
The first cmd check if there is a spawner in current location.
If there is, record the data.
If not, run the next cmd.
Then the second cmd is just to move your current location foward if the current location is the block listed under #pass, and it will keep moving foward until either there is a solid block or out of the range of 6.
...emmm, I guess you are right. We don't really need the #pass here, since the range of 6 is a small distance. So you can change the second cmd in #ray from "if block ~ ~ ~ #namespace:pass" to "unless block ~ ~ ~ minecraft:mob_spawner". But keep in mind that using #pass can reduce some unnessary raycasting.
Hey all! I've been working on recreating the Silk Spawner plugin with vanilla functions. I've already been getting help from several people in a discord server, but I've come to you all for help.
I'm stuck on being able to mine a spawner and summon one in item form that has the block's nbt data. I'm looking for a way to target the block that the player is looking at. That way, when it is a spawner block, I can use the data command to add it's spawning data to a mob spawner entity that I drop. Does anybody have a good way to do this? If not, I have other ideas about how I can implement this.
I'll probably keep this post updated with what I'm doing before I release it. But again, help is appreciated!
Join this cool Datapack Discord server! https://discord.gg/XQg5wNt
Wrote a bunch, then the website was refresh...
Seems doable, but it is kind of limit (depend on how many spawn data you want to copy).
First, you need scoreboard minecraft.broken:minecraft.mob_spawner to detemine if the player actually broke the spawner.
Then, you need to create a block tag in your data pack which it contain a list of block that tell which block the ray should pass. (air,sign,wall_sign,lever,torch,#minecraft:water,#minecraft:buttons,etc.)
Now, here is the main part.
#either in a function or command block, where you need player to run repeatedly
execute as @s at @s positioned ~ ~1.62 ~ run function namespace:ray
#ray
execute if entity @s[distance=..6] if block ~ ~ ~ minecraft:mob_spawner run function namespace:getspawnertype
execute if entity @s[distance=..6] if block ~ ~ ~ #namespace:pass positioned ^ ^ ^0.1 run function namespace:ray
#getspawnertype
execute if block ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:pig"}} run tag @s add spawner_pig
execute if block ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:cow"}} run tag @s add spawner_cow
execute if block ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:zombie"}} run tag @s add spawner_zombie
execute if block ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:spider"}} run tag @s add spawner_spider
...
Once the player have a score of 1 in minecraft.broken:minecraft.mob_spawner, give them the correspond spawner, then remove the score and tag.
I appreciate your insight!
Can you give me some quick info about setting up that tag? I have not tested all of that code yet, but merely put it into my data pack.
Also, anywhere that you have "namespace" can that be replaced with my datapack's folder name?
Join this cool Datapack Discord server! https://discord.gg/XQg5wNt
datapacks\UIN\data\uin\tags\blocks\pass.json is where I would place my pass.json.
UIN is the name of my datapacks, and uin is the namespace.
If the namespace of your datapack is namespace, then you write function namespace:pass
Since my namespace is uin, so I would write function uin:pass instead.
And here is how the pass.json file would looks like. (Just a example)
Notice that this block tag json also contain another group of block tag(flower_pots, buttons)
See also https://minecraft.gamepedia.com/Tag
Thanks for that! So the tag then has every block/block set that is NOT what I want to target, IE a mob_spawner?
Join this cool Datapack Discord server! https://discord.gg/XQg5wNt
Not quite right...See those two commands in #ray function?
The first cmd check if there is a spawner in current location.
If there is, record the data.
If not, run the next cmd.
Then the second cmd is just to move your current location foward if the current location is the block listed under #pass, and it will keep moving foward until either there is a solid block or out of the range of 6.
...emmm, I guess you are right. We don't really need the #pass here, since the range of 6 is a small distance. So you can change the second cmd in #ray from "if block ~ ~ ~ #namespace:pass" to "unless block ~ ~ ~ minecraft:mob_spawner". But keep in mind that using #pass can reduce some unnessary raycasting.
Got everything working! Few problems though:
After one spawn, spawners turn into pig spawners
spawners are always pig spawners when placed in survival mode.
Join this cool Datapack Discord server! https://discord.gg/XQg5wNt
emmm...Sorry I forgot that you need to setblock to make spawner work..
Then you might have to change a little bit.
Instead of giving them the spawner, give them a custom spawn egg that spawn a mob with custom nbt or tag.
Then run sth like this,
/execute at @e[tag=hey] run setblock ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:armor_stand"}}
/kill @e[tag=hey]
The problem is it might replace the previous block when placing on buttons, torch, sign, water, carpets...
All you have to do is this lol
/execute at @e[tag=hey] if block ~ ~ ~ air run setblock ~ ~ ~ minecraft:mob_spawner{SpawnData:{id:"minecraft:armor_stand"}}
/kill @e[tag=hey]
That will do...It is up to him which one to use, he could add more predicate like below...
unless block ~ ~ ~ air positioned ~1 ~ ~ if block ~ ~ ~ air run...
unless block ~ ~ ~ air positioned ~ ~ ~1 if block ~ ~ ~ air run...
unless block ~ ~ ~ air positioned ~-1 ~ ~ if block ~ ~ ~ air run...
...
or just teleport that spawned entity to nearest air block, before the setblock cmd.
If he use only if block air ~ ~ ~ run, what if there isn't a air block there? Then his spawn egg would be wasted.