Tutorial Custom Mob Spawners

Discussion in 'Resources' started by Machine Maker, Jul 16, 2017.

?

Would you like to see an API for mob spawners?

  1. Yes

    7 vote(s)
    100.0%
  2. No

    0 vote(s)
    0.0%
Thread Status:
Not open for further replies.
  1. Offline

    Machine Maker

    Custom Mob Spawners
    by: X1machinemaker1X

    I spent a long while trying to figure out how to create monsters spawners in minecraft that had entities inside that had armor and/or items in their hands. I could not find a tutorial anywhere so I decided to create on after I figured out how. Note that this tutorial does involve NMS (Net Minecraft Server) and so will break if you change minecraft versions unless you use different classes for different versions (just google for a tutorial on that). So, to begin, figure out what you want your mob to be, what you want it to hold, and what you want it to wear. For this tutorial, I will keep it pretty straight forward.

    Mob Type: Zombie
    Main Hand: Diamond Sword (Sharpness III)
    Off Hand: (nothing)
    Helmet: Leather
    Chestplate: Gold
    Leggings: (nothing)
    Boots: Iron

    Ok, so step one is to get the TileEntityMobSpawner object. Now, this can be done several ways, but here is what I think is the simplest. This assumes you already have a mob spawner in your world and have the location.
    Variables:
    • spawner: This is the TileEntityMobSpawner variable that holds the tile entity.
    • world: This is the world where the mob spawner is located/
    • loc: This is the location of the mob spawner
    • blockPos: This is the Block Position object we need for the next line of code.
    Code:
    BlockPosition blockPos = new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
    
    TileEntityMobSpawner spawner = ((CraftWorld) world).getHandle().getTileEntity(blockPos);
    Now we have the spawner object. Next step is to get something called an NBT Tag from it. NBT data is what tells tile entities what they are. And we're gonna change some of them to get the custom mob spawner!
    Code:
    NBTTagCompound spawnerTag = spawner.d();
    At this point, you're probably wondering what that d() method does and why it's just a d. The d() method gets the current NBTTagCompound from the spawner. The reason Mojang made it a d, is so that it's more difficult to tell what each method does. There is an a(), b(), c(), d(), and a whole bunch more methods that are just letters. On to the next step!

    So each tile entity in minecraft has its own set of "tags" which are basically pieces of information stored in the object. Each tile entity also has different names for those tags. A list of a mob spawners "tags" can be found here. We are gonna focus on just a few tags but this tutorial can easily be applied to all the tags which allow you to have some pretty cool customization options.

    The tags we need to change are "SpawnData", which holds information on the mob and the mobs NBT data, "SpawnRange", which is the spawn radius of the mobs, and "MaxNearbyEntities", which is how many entities must be in the spawn range for the spawner to stop spawning mobs. The second two tags are easier to change so we'll start there.

    Code:
    spawnerTag.setShort("SpawnRange", (short) 20);
    This simple line of code will change the "SpawnRange" tag to 20 blocks. Now a quick note, you must set the range to a short, so remember to cast the integer to a short. (A short is just another java object for a smaller number).

    Code:
    spawnerTag.setShort("MaxNearbyEntities", (short) 100);
    This line sets the "MaxNearbyEntities" to 100 (default is 6) so you can spawn a bunch more mobs.

    Now on to the slightly more complicated part.
    Step 1: Create two new NBTTabLists
    Code:
    NBTTagList handList = new NBTTagList();
    NBTTagList armorList = new NBTTagList();
    Based on the names, I think you can guess what will go in those lists. BTW, an NBTTagList is a list of NBT tags.

    Step 2: Create each hand NBT tag
    Code:
    NBTTagCompound mainHand = new NBTTagCompound();
    NBTTagCompound offHand = new NBTTagCompound();
    Now we have to blank NBT tags. We need to set them to the items we wanted the zombie to hold. Lets create the diamond sword.
    Code:
    mainHand.setString("id", "minecraft:diamond_sword");
    mainHand.setShort("Count", (short) 1);
    The "id" tag is the item type you want the hand to hold. The "Count" tag is how many of the item you want there to be. But wait a second, we wanted to enchant the diamond sword. So we'll need to create another list of NBT tags to hold the enchants. Even though we are only adding one enchant, you must create the list anyway.

    Code:
    NBTTagList enchantments = new NBTTagList();
    NBTTagCompound sharpness3 = new NBTTagCompound();
    sharpness3.setShort("id", (short) 16);
    sharpness3.setShort("lvl", (short) 3); 
    enchantments.add(sharpness3);
    We just made a new enchantment nbt taglist and added sharpness (id:16) level 3 (lvl:3) to that taglist. A full list of enchantment ids can be found here. Now we will add the NBTTagList to the sword using the "tag" tag.

    Code:
    NBTTagCompound ench = new NBTTagCompound();
    each.set("ench", enchantments);
    mainHand.set("tag", ench);
    handList.add(mainHand);
    The set(String, NBTBase) method takes an NBT tag and sets it to the string Tag. This allows you to store tags inside of other tags. Then we add the finished mainHand tag to the handList and we're done with the mainHand. This process can easily be replicated for the offhand, but for simplicities sake, we will have nothing in the off hand. Just add a blank NBTTagCompound object to the handList because the handList list is expecting two tags, one for each hand, so we'll just give it a blank one and we're done with the hands!

    Code:
    handList.add(offHand);
    Step 3: Create the armor item NBT tags
    Code:
    NBTTagCompound helmet = new NBTTagCompound();
    NBTTagCompound chestplate = new NBTTagCompound();
    NBTTagCompound leggings = new NBTTagCompound();
    NBTTagCompound boots = new NBTTagCompound();
    We need to create 4 more NBTTagCompound objects, one for each armor slot, even if we aren't gonna put an item there. Since you know how to do this already, I will show all the code for adding the items below.

    Code:
    helmet.setString("id", "minecraft:leather_helmet");
    helmet.setShort("Count", (short) 1);
    chestplate.setString("id", "minecraft:golden_chestplate");
    chestplate.setShort("Count", (short) 1);
    //we're leaving the leg slot empty
    boots.setString("id", "minecraft:iron_boots");
    boots.setShort("Count", (short) 1);
    armorList.add(boots);
    armorList.add(leggings);
    armorList.add(chestplate);
    armorList.add(helmet);
    They must be added in that order!

    Step 4: Create and set the "SpawnData" tag
    Ok, so now we have our complete armorList and handList. Now we need to set the "HandItems" and "ArmorItems" to the "SpawnData" tag, I mentioned earlier. Let's create the "SpawnData" tag.

    Code:
    NBTTagCompound spawnData = new NBTTagCompound();
    spawnData.setString("id", "minecraft_zombie"); //sets the spawner to a zombie
    spawnData.set("HandItems", handList);
    spawnData.set("ArmorItems", armorList);
    spawnerTag.set("SpawnData", spawnData);
    We now have our fully setup spawnerTag!

    Step 5: Set the spawner's NBT data

    Code:
    spawner.a(spawnerTag);
    This is really simple. We have to use one of the weirdly named methods, but there it is! We set the spawner's NBT data to our custom NBT tags. This tutorial is only the start to what you can do with mob spawners. They can spawn items, or multiple different mobs at once, and so much more! I encourage you to play around and see what you can come up with. Also, if you think I should make an API for making custom mob spawners, vote in the poll at the top of the post.

    Congratulations!
    [​IMG]
    Here is a picture of what the spawner should look like

    [​IMG]
    And here is the mob that spawns!


    Full Code
    Code:
    BlockPosition blockPos = new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getZ());
    TileEntityMobSpawner spawner = (TileEntityMobSpawner) ((CraftWorld) p.getWorld()).getHandle().getTileEntity(blockPos);
    NBTTagCompound spawnerTag = spawner.d();
    spawnerTag.setShort("SpawnRange", (short) 20);
    spawnerTag.setShort("MaxNearbyEntities", (short) 100);
    NBTTagList handList = new NBTTagList();
    NBTTagList armorList = new NBTTagList();
    NBTTagCompound mainHand = new NBTTagCompound();
    NBTTagCompound offHand = new NBTTagCompound();
    mainHand.setString("id", "minecraft:diamond_sword");
    mainHand.setShort("Count", (short) 1);
    NBTTagList enchantments = new NBTTagList();
    NBTTagCompound sharpness3 = new NBTTagCompound();
    sharpness3.setShort("id", (short) 16);
    sharpness3.setShort("lvl", (short) 3); 
    enchantments.add(sharpness3);
    NBTTagCompound ench = new NBTTagCompound();
    ench.set("ench", enchantments);
    mainHand.set("tag", ench);
    handList.add(mainHand);
    handList.add(offHand);
    NBTTagCompound helmet = new NBTTagCompound();
    NBTTagCompound chestplate = new NBTTagCompound();
    NBTTagCompound leggings = new NBTTagCompound();
    NBTTagCompound boots = new NBTTagCompound();
    helmet.setString("id", "minecraft:leather_helmet");
    helmet.setShort("Count", (short) 1);
    chestplate.setString("id", "minecraft:golden_chestplate");
    chestplate.setShort("Count", (short) 1);
    //we're leaving the leg slot empty
    boots.setString("id", "minecraft:iron_boots");
    boots.setShort("Count", (short) 1);
    armorList.add(boots);
    armorList.add(leggings);
    armorList.add(chestplate);
    armorList.add(helmet);
    NBTTagCompound spawnData = new NBTTagCompound();
    spawnData.setString("id", "zombie"); //sets the spawner to a zombie
    spawnData.set("HandItems", handList);
    spawnData.set("ArmorItems", armorList);
    spawnerTag.set("SpawnData", spawnData);
    spawner.a(spawnerTag);
    Thanks for Reading!!
     
  2. Offline

    Zombie_Striker

    @X1machinemaker1X
    Great tutorial. I don't think there have been any tutorials on this topic before.

    Do create an API or Util; It's better to have something that is not version dependent.
     
  3. Offline

    plisov

    This is really amazing! How would you add a saddle to a horse? I've changed the spawner to be a horse I just don't know how to add a saddle to the horse.
     
  4. @plisov
    Easiest way is to just add this line (before setting the spawnData):
    Code:java
    1. spawnData.set("SaddleItem", new ItemStack(Items.SADDLE).save(new NBTTagCompound()));
    It simply creates a new NMS ItemStack and saves the NBT. It's a whole lot easier than manually replicating each of the NBT tags, like was with the zombie armour above.

    Also, in the latest version, the method to load the NBT data onto the spawner has been changed from 'a' to 'load', so the last line should be:
    Code:java
    1. spawner.load(spawnerTag);
    Instead of:
    Code:java
    1. spawner.a(spawnerTag);
     
  5. Offline

    plisov

    Ahh thanks. Is there a way to have this work in 1.8? I noticed that .d in
    NBTTagCompound spawnerTag = spawner.d();
    is unknown.
     
  6. @plisov
    Yeah, the method name is probably different. I don't have a 1.8 jar setup to poke around in atm, but you should be able to find a method that saves all of the spawners properties into an NBTTagCompound.
     
  7. How would i add armor and weapons with a custom name and custom lore?
    Could anyone please provide an example?
     
Thread Status:
Not open for further replies.

Share This Page