Changing a mob spawner's spawned entities

Discussion in 'Plugin Development' started by Taco, Jul 30, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    Taco

    I've been trying to work on something similar to SilkSpawners for my server, with a few variations of my own. I've been basing my method of setting the spawner's mob type off of the one used in SilkSpawners, but it appears that the setSpawnedType method isn't working properly, and I was wondering if anyone knew an efficient workaround for this. Below is my BlockPlaceEvent for reference.

    Code:java
    1. @EventHandler
    2. public void onBlockPlace(BlockPlaceEvent event)
    3. {
    4. final Block b = event.getBlock();
    5. Player p = event.getPlayer();
    6. if(b.getType() == Material.MOB_SPAWNER)
    7. {
    8. ItemStack item = p.getItemInHand();
    9. short data = (short) item.getEnchantmentLevel(Enchantment.KNOCKBACK);
    10. if(data==0)
    11. data=item.getDurability();
    12. final CraftCreatureSpawner spawner = (CraftCreatureSpawner) b.getState();
    13. final EntityType type = EntityType.fromId(data);
    14. plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
    15. public void run() {
    16. spawner.setSpawnedType(type);
    17. b.getState().update();
    18. }
    19. }, 5L);
    20. }
    21. }
     
  2. Offline

    r0306

    Taco
    Code:
    CreatureSpawner cs = (CreatureSpawner) b.getState();
    cs.setSpawnedType(EntityType.ENTITY);
     
  3. Offline

    Firefly

    I think he said:

     
  4. Offline

    r0306

    Firefly
    He's using CraftCreatureSpawner, not CreatureSpawner. :)
     
  5. Offline

    Firefly

    True that.
     
  6. Offline

    r0306

    Firefly
    Unless it's a custom spawner class that he created and it extends CreatureSpawner. I can't find anything called CraftCreatureSpawner on the JavaDocs.
     
  7. Offline

    Taco

    Hmmm... I don't see why it would make a difference, but I'll use CreatureSpawner instead to see if it yields different results.

    Seems that the method still doesn't work for the CreatureSpawner class either. I've confirmed that the data value is 100% correct, so that isn't the issue here.

    Also, r0306 the CraftCreatureSpawner is the Craftbukkit class for Creature Spawners.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 27, 2016
  8. Offline

    r0306

    Taco
    Make sure that the entitytypes aren't coming out as null. Maybe try printing a few debug lines to console.
     
  9. Offline

    Taco

    Already did that. The data and entity types are fine. I'm fairly certain it'd throw an NPE if the entitytype was null anyways.
     
  10. Offline

    r0306

    Taco
    Just to be sure, try updating the blockstate directly.
    Code:
    final BlockState state = b.getState();
    final CraftCreatureSpawner spawner = (CraftCreatureSpawner) state;
    final EntityType type = EntityType.fromId(data);
    plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
    public void run() {
    spawner.setSpawnedType(type);
    state.update();
    }
    }, 5L);
    }
     
  11. Offline

    nisovin

    The CreatureSpawner is a BlockState, you can and should call update() on it directly.

    This line:
    Code:
    b.getState().update();
    doesn't do anything. It just gets the block's current state then updates it to its current state.
     
  12. Offline

    r0306

    nisovin
    I was looking at the silkspawners source and that's what they did. :eek:
     
  13. Offline

    nisovin

  14. Offline

    r0306

    nisovin
    Oh. I didn't realize you were talking about Taco's code. Never mind.
     
  15. Offline

    nisovin

    I wasn't, I was talking about your code.
     
  16. Offline

    r0306

    nisovin
    In my code, I never retrieved the block state twice.

    Anyways, take a closer look at the source:
    Code:
    BlockState blockState = block.getState();
    CraftCreatureSpawner spawner = ((CraftCreatureSpawner)blockState);
    spawner.setSpawnedType(ct);
    blockState.update();
    I never called block.getState().update();
     
  17. Offline

    nisovin

    Oh, my bad, for some reason I thought you were the OP.
     
  18. Offline

    r0306

    nisovin
    Lol. Np. Happens to me too. :)
     
  19. Offline

    Taco

    I tried what was suggested above, and it's still not updating. When I place the spawner, I get the data variable output as 53, and when I break the placed spawner after waiting several seconds, it outputs the data as 90.
     
  20. Offline

    mushroomhostage

    I was going to say how you have to set the spawner type after the event because of where the block place event is fired.. but I see you've already done that. Strange, SilkSpawners sets the type similarity to your code, and it works..

    One difference is I use net.minecraft.TileEntityMobSpawner to set the mob ID string instead of using the Bukkit wrappers:

    https://github.com/mushroomhostage/SilkSpawners/blob/master/SilkSpawners.java#L968 - see setSpawnerEntityID

    (I do this so I can support mobs added by mods like Mo' Creatures, which do not extend Bukkit's wrappers). Not sure if this matters, I would expect your code to work too, but I know this approach works :)
     
  21. Offline

    Taco

    How do you get the mob ID String? I'm trying to follow your code, and I'm not finding that bit.
     
  22. Offline

    nisovin

    Post your updated code.
     
  23. Offline

    mushroomhostage

    I store an entity ID -> mob ID map ("ConcurrentHashMap<Short,String> eid2MobID"), populated by scanning net.minecraft.server.EntityTypes:

    https://github.com/mushroomhostage/SilkSpawners/blob/master/SilkSpawners.java#L547

    which has its own map. The entity ID is used in spawn eggs and the mob ID in mob spawners, so having this mapping makes it easy to switch between the two as needed.

    Bukkit stores yet another mapping in its own org.bukkit.entity.EntityType class (which I don't use in SilkSpawners, but it might work for your purposes) you can see here: http://jd.bukkit.org/apidocs/src-html/org/bukkit/entity/EntityType.html#line.9. Looks like fromName() and getName() could be useful (they use what is internally referred to as the "mob ID" string).
     
  24. Offline

    Taco

    My current code:

    Code:java
    1. plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
    2. public void run() {
    3. Field tileField;
    4. try {
    5. tileField = CraftCreatureSpawner.class.getDeclaredField("spawner");
    6. tileField.setAccessible(true);
    7. String mobID = type.getName();
    8. net.minecraft.server.TileEntityMobSpawner tile = (net.minecraft.server.TileEntityMobSpawner)tileField.get(spawner);
    9. tile.a(mobID);
    10. //spawner.setSpawnedType(type);
    11. //state.update();
    12. return;
    13. } catch (Exception e) {
    14. // TODO Auto-generated catch block
    15. e.printStackTrace();
    16. }
    17.  
    18. }
    19. }, 5L);


    I have not yet checked this for null variables, but I'm also not getting any errors printed to the console.
     
  25. Offline

    Slipswhitley

    Tah Dah!

    Code:
    @EventHandler
        public void onBlockPlace(BlockPlaceEvent event) {
            if(event.getBlock().getType() == Material.MOB_SPAWNER) {
                ItemStack item = event.getItemInHand();
                setSpawner(event.getBlockPlaced());
            }
        }
     
        public void setSpawner(final Block block) {
            plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
             
                public void run() {
                    BlockState blockState = block.getState();
                    CreatureSpawner spawner = ((CreatureSpawner)blockState);
                    spawner.setSpawnedType(EntityType.BLAZE));
                    blockState.update();
                }
            }, 1L);
        }
    if this needs explaining just ask
     
  26. Offline

    Taco

    Although I appreciate the contribution, this thread is quite old, and those classes that you used there may have had issue back when this thread was around. Next time, you may want to check the date on a thread before replying to see if the issue may have already been resolved or is no longer an issue.
     
  27. Offline

    Slipswhitley

    I did this for anyone who had a similar problem and is looking for a solution thank you very much :)
     
Thread Status:
Not open for further replies.

Share This Page