Solved Minecart Spawner Data and Falling Block Data

Discussion in 'Plugin Development' started by thebiologist13, Mar 15, 2013.

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

    thebiologist13

    Hello everyone!

    I have been experimenting with the development build for Minecraft 1.5, and I am trying to get NBT tags for spawner data to set to spawner minecarts and falling blocks. So far I have basic minecarts and falling entity blocks working, however I cannot seem to set the actual spawner NBT data.

    I have tried using reflection to get the NBT, as specifed here: http://forums.bukkit.org/threads/getting-entity-nbt-data.113049/ and roughly the same for setting, with the exception of invoking "a(NBTTagCompound)" instead of "b(NBTTagCompound)".

    After I got the data, I would add the tags specified here: http://www.minecraftwiki.net/wiki/Chunk_format#Vehicles

    Finally, I would set the modified tags back to the mob. This works totally for pretty much everything (custom name tags, potion effects, tile ID/damage, etc.). No errors are thrown ever, just, nothing seems to happen in the case of spawner data.

    Any ideas about what I could be doing wrong? Or is it not implemented to do this all yet?

    Thanks! :D
    ~thebiologist13
     
  2. the spawner data may be cached inside the class of the spawner, so modifying the underlying nbt may not work
     
  3. Offline

    thebiologist13

    Ok, is there a way to change the cached NBT then? Or a way to spawn it with specific data?

    Thanks!
    ~thebiologist13
     
  4. Offline

    thebiologist13

    Any ideas anyone? I am stumped. I did find out that it's something wrong with my NBT setter though. It won't apply the NBT data to spawner minecarts or falling blocks, but it will for other entities like pigs.

    My setter:
    Code:java
    1. public void setEntityNBT(Entity e, NBTTagCompound n) {
    2. net.minecraft.server.v1_5_R1.Entity nms = ((CraftEntity) e).getHandle();
    3. Class<?> entityClass = nms.getClass();
    4. Method[] methods = entityClass.getMethods();
    5. for (Method method : methods) {
    6. if ((method.getName() == "a")
    7. && (method.getParameterTypes().length == 1)
    8. && (method.getParameterTypes()[0] == NBTTagCompound.class)) {
    9. try {
    10. method.setAccessible(true);
    11. method.invoke(nms, n);
    12. } catch (Exception ex) {
    13. ex.printStackTrace();
    14. }
    15. }
    16. }
    17. }

    One more note, I did put a debug check in, and the compound I passed into my setter has all the data it needs in it.

    Thanks in Advance!
    ~thebiologist13

    Oh my gosh I figured it out! It was sort-of cached like ferrybig said. I ended up having to use some more reflection to get it to work.

    Here is the way I set spawner minecart NBT now:
    Code:java
    1. EntityMinecartAbstract abs = ((CraftMinecart) entity).getHandle();
    2. EntityMinecartMobSpawner cart = (EntityMinecartMobSpawner) abs;
    3.  
    4. //Show custom name is a value in my plugin.
    5. if(data.showCustomName()) {
    6. abs.a(data.getName()); //Sets the name. Not even sure if it matters though...
    7. }
    8.  
    9. //The item type thing is internal to my plugin, CustomSpawners
    10. if(!data.getItemType().getType().equals(Material.AIR)) {
    11. int id = data.getItemType().getTypeId();
    12. int dur = (int) data.getItemType().getDurability();
    13. cart.a(true); //Show tile
    14. cart.k(id); //Tile ID
    15. cart.l(dur); //Tile durability
    16. }
    17.  
    18. //Spawner data is yet another thing internal to my plugin. It is a class with a ton of
    19. //data related to spawners.
    20. if(data.getSpawnerData() != null && entity instanceof SpawnerMinecart) {
    21. NBTTagCompound spawnerData = new NBTTagCompound();
    22. NBTBase[] props = nbt.getPropertyArray(data.getSpawnerData());
    23. for(NBTBase base : props) {
    24. if(base.getName().equals("id") || base.getName().equals("x") ||
    25. base.getName().equals("y") || base.getName().equals("z")) {
    26. continue;
    27. }
    28. nbtComp.set(base.getName(), base);
    29. spawnerData.set(base.getName(), base);
    30. }
    31.  
    32. try {
    33. Field theSpawner = cart.getClass().getDeclaredField("a");
    34. theSpawner.setAccessible(true);
    35. MobSpawnerAbstract spawner = (MobSpawnerAbstract) theSpawner.get(cart);
    36. spawner.a(spawnerData);
    37. } catch(Exception e) {
    38. e.printStackTrace();
    39. }
    40. }


    And for falling blocks:
    Code:java
    1. NBTTagCompound nbtComp = nbt.getEntityNBT(entity); //This gets the base nbt of the entity.
    2. EntityFallingBlock block = ((CraftFallingSand) entity).getHandle();
    3. //Now we set the TileEntityData tag to the data from my spawner class.
    4. nbtComp.setCompound("TileEntityData", nbt.getSpawnerNBT((ISpawner) data.getSpawnerData()));
    5. try {
    6. Class<?> entityClass = block.getClass();
    7. Method[] methods = entityClass.getDeclaredMethods();
    8. for (Method method : methods) {
    9. if ((method.getName() == "a")
    10. && (method.getParameterTypes().length == 1)
    11. && (method.getParameterTypes()[0] == NBTTagCompound.class)) {
    12. method.setAccessible(true);
    13. method.invoke(block, nbtComp);
    14. }
    15. }
    16. } catch(Exception e) {
    17. e.printStackTrace();
    18. }


    Yay code! :D
    ~thebiologist13

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 31, 2016
Thread Status:
Not open for further replies.

Share This Page