Source responsible for spawn PrimedTNT

Discussion in 'Spigot Plugin Development' started by WAS, Apr 19, 2017.

  1. WAS

    WAS

    Moar TNT Trivia.

    So last week I found a topic which refers to the source where bukkit/mc spawns PrimedTNT. However, for the life of me I can't find it either in the stash by searching files one by one or from google again. Does someone know which file it might be contained in? Been driving me nuts. I can't seem to figure out all the mechanics needed for redstone interaction with TNT (to simulate vanilla/api) so I was hoping to maybe just override the source method and inject my metadata which will handle all causalities.
     
  2. Do you mean where it is spawned in the NMS code? If so, look in BlockTNT. I'm pretty sure it'll spawn it there.
     
  3. WAS

    WAS

    Oh man thanks! I sure hope thats it. I'm not familiar with NMS at all. :\

    So I can't seem to get a relevant source file for 1.11 (not sure how to decompile and do that myself yet haven't looked). Only 1.8 and 1.7.10 but I don't see any reference to the spawn method like I had thought I had seen before.

    Upade: But I dooo see this. Is this what I am looking for? If so great. Now I'm wondering how to import and override it. :p going to do some searching.

    Code (Java):
        public void wasExploded(World world, int i, int j, int k) {
            if (!world.isStatic) {
                EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) ((float) i + 0.5F), (double) ((float) j + 0.5F), (double) ((float) k + 0.5F));
                entitytntprimed.fuseTicks = world.random.nextInt(entitytntprimed.fuseTicks / 4) + entitytntprimed.fuseTicks / 8;
                world.addEntity(entitytntprimed);
            }
        }
     
    #3 WAS, Apr 19, 2017
    Last edited: Apr 19, 2017
  4. The line that spawns it is the world.addEntity(entitytntprimed); as before that, the entity is created but doesn't exist anywhere.

    And although others might say it's not the best, I've found the "Eclipse Class Decomiler" addon you can get in the eclipse marketplace to be very good. Doesn't require you to do anything fancy; just every time you open a .class file, it shows some code instead of "javadocs cannot be found".

    Overriding methods isn't that simple, either. As far as I know, it requires ASM which is a highly complex and slow library. I know some Core Forge Mods use it, but there is nothing like that in Spigot. Because it's also manipulating entire classes at runtime (I think), it's even slower than reflection - so it should be avoided unless it's absolutely necessary. Now I don't have any experience in it myself, so that might not be 100% accurate. But the short answer is that it can't really be done lol. Sorry to burst your bubble :p

    One thing to look into is if an event is fired when the tnt entity itself is spawned (which is, when it's primed). Although it'd be kinda messy, you could check for surrounding redstone circuits that activated it if the block existed there. Maybe have a look into that?
     
  5. WAS

    WAS

    Not sure how extending it and overriding is hard? And how does everyone else do it. They certainly aren't reinventing the wheel in listeners which would be much slower Lol There is literally a plethora of NMS based TNT plugins.

    This is what I got so far, just trying to figure out how to register the class and actually override, as it does nothing so far

    Code (Java):
    public class TNTPrimeSpawn_v1_11_R1 extends BlockTNT {
       
       private BlastRadius plugin;
       private TNTLocationManager TNTManager;
       private TNTEffectsManager TNTEffects;
       
       private Logger logger;
       
      public static final BlockStateBoolean EXPLODE = BlockStateBoolean.of("explode");
       
       public TNTPrimeSpawn_v1_11_R1() {
         super();
         plugin = BlastRadius.getBlastRadiusInstance();
         TNTManager = plugin.getTNTLocationManager();
         TNTEffects = plugin.getTNTEffectsManager();
         logger = plugin.getLogger();
       }
       
       @Override
       public void wasExploded(World world, BlockPosition blockposition, Explosion explosion) {
         if ( ! ( world.isClientSide ) ) {
           Location location = new Location((org.bukkit.World) world, blockposition.getX(), blockposition.getY(), blockposition.getZ());
           if ( OnCommand.toggleDebug != null && OnCommand.toggleDebug ) {
             logger.info("Creating Primed TNT at: "+location.getX()+", "+location.getY()+", "+location.getZ()+ " ...");
           }
           EntityTNTPrimed tnt = new EntityTNTPrimed(world, (double) ((float) blockposition.getX() + 0.5F), (double) blockposition.getY(), (double) ((float) blockposition.getZ() + 0.5F), explosion.getSource());
           tnt.setFuseTicks(world.random.nextInt(tnt.getFuseTicks() / 4) + tnt.getFuseTicks() / 8);
           if ( TNTManager.containsRelativeLocation(location) ) {
             String type = TNTManager.getRelativeType(location);
             Map<String, Object> effect = TNTEffects.getEffect(type);
             tnt.setFuseTicks((int) effect.get("fuseTicks"));
             ((TNTPrimed)tnt).setYield(((TNTPrimed)tnt).getYield() * (float) effect.get("yieldMultiplier"));
             ((TNTPrimed)tnt).setMetadata("tntType", new FixedMetadataValue(((JavaPlugin)plugin), type));
             if ( OnCommand.toggleDebug != null && OnCommand.toggleDebug ) {
               logger.info("Created Primed TNT with Effect Type: "+type);
             }
           }
           world.addEntity(tnt);
         }
       }
       
       @Override
       public void a(World world, BlockPosition blockposition, IBlockData iblockdata, EntityLiving entityliving) {
         if ( ! ( world.isClientSide ) ) {
           if ( ((Boolean)iblockdata.get(BlockTNT.EXPLODE)).booleanValue() ) {
             Location location = new Location((org.bukkit.World) world, blockposition.getX(), blockposition.getY(), blockposition.getZ());
             if ( OnCommand.toggleDebug != null && OnCommand.toggleDebug ) {
               logger.info("Creating Primed TNT at: "+location.getX()+", "+location.getY()+", "+location.getZ()+ " ...");
             }
             EntityTNTPrimed tnt = new EntityTNTPrimed(world, (double) ((float) blockposition.getX() + 0.5F), (double) blockposition.getY(), (double) ((float) blockposition.getZ() + 0.5F), entityliving);
             tnt.setFuseTicks(world.random.nextInt(tnt.getFuseTicks() / 4) + tnt.getFuseTicks() / 8);
             if ( TNTManager.containsRelativeLocation(location) ) {
               String type = TNTManager.getRelativeType(location);
               Map<String, Object> effect = TNTEffects.getEffect(type);
               tnt.setFuseTicks((int) effect.get("fuseTicks"));
               ((TNTPrimed)tnt).setYield(((TNTPrimed)tnt).getYield() * (float) effect.get("yieldMultiplier"));
               ((TNTPrimed)tnt).setMetadata("tntType", new FixedMetadataValue(((JavaPlugin)plugin), type));
               if ( OnCommand.toggleDebug != null && OnCommand.toggleDebug ) {
                 logger.info("Created Primed TNT with Effect Type: "+type);
               }
             }
             world.addEntity(tnt);
           }
         }
       }

    }
     
    #5 WAS, Apr 19, 2017
    Last edited: Apr 19, 2017
  6. Ah, my bad. I misinterpreted what you were trying to do. Thought you were wanting to override the method in the NMS. Didn't even think that you meant via extending it lol

    I'm not too sure how that will play out, though. You may have to re-register the block as well. I'm also not sure if doing block.setType(Materjal.TNT) in bukkit will break it, since it may reference the old TNT type.
     
  7. WAS

    WAS

    Sorry, where are you seeing block.setType()? This is spawning primed TNT. I'm trying to inject said primed TNT with it's MetaData to be handled by the Spigot API. It is crucial to get the metadata set at this point to catch it before it moves out of location which than wouldn't register it's correct type which is the case using spigot api methods.

    The problem is my overrides are actually not firing with any primed TNT spawning, as if BlockTNT is not responsible for most of this behavior, or the Overrides are not taking. I tried debugging the constructor and the class is being initiated. Beyond all that I have no idea what's going on or why it wouldn't work. So I'm back to the old buggy ass relative location checking.

    Perhaps NMS is not actually utilizing the extension. To my understanding reading online, a extended class would load in chain after it's super.