Prevent a Block type from TNT damage. (Simple)

Discussion in 'Archived: Plugin Requests' started by RustyDagger, Feb 6, 2012.

  1. Offline

    RustyDagger

    So currently on my server we use factions so there is a fair bit of Tnt cannons going around for raiding bases and what not the issue I have noticed is that there is currently no block in the game that can be moved with pistons and still protect from TNT.

    So The idea for this plugin was created from that need to fill the gap.

    Ideally the block type should be changeable from a config and even setting a list of block types in the config. this leaves server owners like my self in control and the plugin my dynamic. meaning useful to more people.

    personally i would use Gold blocks as it makes protection come at a high cost just like farming Obsidian because it comes at the cost of time. and the block is largely unused as it is a non cheating based server.

    NB: if this could be done with an existing plugin let me know please. I Just starting to wonder if WorldGuard could do it.
     
  2. Offline

    JayEffKay

    I'll try this, seems fun to make.

    edit:
    Not as easy as I hoped. I see no way to actually stop a specific block from destruction caused by an explosion. I do see a possibility to quickly rebuild the block and cancel its droppings, so I'll try and do that. But maybe another dev might know a better method.
     
  3. Offline

    RustyDagger

    JayEffKay you should tag people when you reply

    Thanks for having a go let me know if it works out cheer's :D
     
  4. Offline

    Zarius

    Try something like this:

    Code:
        @Override
        public void onEntityExplode(EntityExplodeEvent event) {
            if (event.isCancelled()) return;
     
            List<Block> blockListCopy = new ArrayList<Block>();
            blockListCopy.addAll(event.blockList());
            for (Block block : blockListCopy) {
                if (block.getType() == Material.GOLD_BLOCK) event.blockList().remove(block);
            }
                 
    
    The tricky part is that this will only stop gold blocks from being destroyed - not stop blocks behind the gold block from blowing up. I guess you could save the location of each gold block and do some maths to try and work out which blocks are behind them then remove those blocks too.
     
  5. Offline

    romobomo

    Zarius
    JayEffKay

    Why not instead cancel the event, and then call BlockBreak on the NOT included blocks in the blocklist?
     
  6. Offline

    Zarius

    romobomo

    Why would we do that? Seems slower than removing the protected blocks from the blocklist. As mentioned above the tricky bit is the maths to work out which blocks are "behind" the gold blocks - not sure how you'd work out where the TNT hit either... perhaps you could use "event.getEntity().getLocation().getDirection();"
     
  7. Offline

    romobomo

    Zarius

    Oh sorry, I read the guy before you're post. I didn't look at your code, though either way would work about the same speed, honestly. As for the math, if you use the cancel first method, you can just get the location of the TNT entity at the time of the explosion, iterate around it in an oooh i dunno 5x5x5 area (dunno off the top of my head the size of a tnt explosion), and call BlockDestroy for each block in that area that is both in the blocklist and NOT behind a "protected" block.
     
  8. Offline

    Zarius

    romobomo

    Explosions could be variable size depending on the entity - and TNT explosions could vary depending on local plugins, best to deal with the blocks within the event - again the trick is determining which direction is "behind" the protected block (the TNT could be coming in from below, straight into, above, angled to the side, etc)
     
  9. Offline

    romobomo

    Zarius

    Hence the iterator (or a nested for loop) AROUND the explosion area. If the block at the iterated location is not within the blocklist or is MATERIAL.AIR (ID 0), then continue;, otherwise check if the block is a protected block. if it is, set a protectedFound TRUE flag for the next iterations beyond that (already having eliminated non effected blocks), and continue; through that iteration. If it is NOT, destroy the block and check the next iteration. This would be a lot easier (and I'd wager faster) than determining physics... in which you'll STILL need to iterate as you're only determining a straight line vector, not a boxed vector.
     
  10. Offline

    desht

    Hmm, an interesting problem (protecting blocks behind the "shield" blocks, that is - just protecting blocks is trivial, as Zarius already showed with that example event handler).

    I can see two possibilities:

    1. Simple, but not very efficient: for each block, run a block iterator from the explosion's centre to the block. If you encounter a "shield" block along the way, remove the block from the event's destroyed list.

    2. More complex (but hopefully more efficient?) :
    • Consider the explosion area as a sphere. Every block in the area can have its (x,y,z) Cartesian co-ordinates converted to polar co-ordinates with the explosion's centre as the origin (basically a latitude, longitude and distance from centre - see http://electron9.phys.utk.edu/vectors/3dcoordinates.htm for conversion formulae)
    • Divide the surface of your sphere into subdivisions, based on latitude & longitude - the number of subdivisions would really depend on the radius of the sphere for best results. Implement a method that returns a unique ID for each subdivision that a block falls in.
    • For each "shield" block, build a Map<Integer,Integer> which maps a subdivision ID to the distance of the closest shield block in that subdivision to the center of the explosion. Also remove it from the destroyed list, of course.
    • For each other block, if there's a "shield" block in that subdivision closer to the centre than itself (which we can now look up via the Map above), remove it from the destroyed list.
    Calculating the optimal subdivision resolution would take a little consideration, but I'd say it's doable. Would be interesting to see if method 2 really is more efficient...
     
  11. Offline

    romobomo

    desht
    Zarius

    I wouldn't bother with converting to spherical coordinates, we're working in cuboids... there's only 22 directions we need to check (8 corners, 8 edges, 6 faces), as opposed to a whole sphere. Also, Java's Sin and Cos are RIDDIC-slow. Here's an example that will work... it may look heavy, but I assure you, it will likely run quickly.... it can easily be shrunk (line wise) by building a hashmap or method construct to hold the directions and looping through that with a single for loop (instead of 22)... but this is what's happening happening now matter how you pretty it up, might as well keep it as such. I havn't tested it, so it may need some slight tweaking, and can probably be made even more efficient. You can also swap to your method of removing from the block list instead of canceling the event before destroying, but I stick to my prefered method :p... Up to you... anyway, give it a whirl, should work...

    The following code checks 10 blocks out in each direction for a "protected ID block". It ignores air blocks/non-effected blocks, destroys non protected blocks, until it hits a "protected ID block", at which time it breaks from the loop and tries the next direction. Meaning that the protected block and all after it will not be affected.

    Code to follow:

    Code:java
    1.  
    2. List<Block> blocklist; // get this from the event
    3. HashSet<Integer> protIDs; // from a config file possibly?
    4. Location loc; //location of explosion
    5. Location loc2 = loc; //copy that location to work with
    6.  
    7. // first handle the block AT the explosion...
    8. if(!blocklist.contains(loc.getBlock()))
    9. loc.getBlock().breakNaturally();
    10.  
    11. // y+
    12. for(int i = 1; i <= 10; i++) {
    13. loc2.setY(loc.getY()+i);
    14. if(!blocklist.contains(loc2.getBlock()))
    15. continue;
    16. if(loc2.getBlock().getTypeId() == 0)
    17. continue;
    18. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    19. loc2.getBlock().breakNaturally();
    20. } else {
    21. break;
    22. }
    23. }
    24. loc2 = loc;
    25. // y+, x+
    26. for(int i = 1; i <= 10; i++) {
    27. loc2.setY(loc.getY()+i);
    28. loc2.setX(loc.getX()+i);
    29. if(!blocklist.contains(loc2.getBlock()))
    30. continue;
    31. if(loc2.getBlock().getTypeId() == 0)
    32. continue;
    33. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    34. loc2.getBlock().breakNaturally();
    35. } else {
    36. break;
    37. }
    38. }
    39. loc2 = loc;
    40. // y+, x+, z+
    41. for(int i = 1; i <= 10; i++) {
    42. loc2.setY(loc.getY()+i);
    43. loc2.setX(loc.getX()+i);
    44. loc2.setZ(loc.getZ()+i);
    45. if(!blocklist.contains(loc2.getBlock()))
    46. continue;
    47. if(loc2.getBlock().getTypeId() == 0)
    48. continue;
    49. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    50. loc2.getBlock().breakNaturally();
    51. } else {
    52. break;
    53. }
    54. }
    55. loc2 = loc;
    56. // y+, z+
    57. for(int i = 1; i <= 10; i++) {
    58. loc2.setY(loc.getY()+i);
    59. loc2.setZ(loc.getZ()+i);
    60. if(!blocklist.contains(loc2.getBlock()))
    61. continue;
    62. if(loc2.getBlock().getTypeId() == 0)
    63. continue;
    64. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    65. loc2.getBlock().breakNaturally();
    66. } else {
    67. break;
    68. }
    69. }
    70. loc2 = loc;
    71. // y+, z+, x-
    72. for(int i = 1; i <= 10; i++) {
    73. loc2.setY(loc.getY()+i);
    74. loc2.setX(loc.getX()-i);
    75. loc2.setZ(loc.getZ()+i);
    76. if(!blocklist.contains(loc2.getBlock()))
    77. continue;
    78. if(loc2.getBlock().getTypeId() == 0)
    79. continue;
    80. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    81. loc2.getBlock().breakNaturally();
    82. } else {
    83. break;
    84. }
    85. }
    86. loc2 = loc;
    87. // y+, x-
    88. for(int i = 1; i <= 10; i++) {
    89. loc2.setY(loc.getY()+i);
    90. loc2.setX(loc.getX()-i);
    91. if(!blocklist.contains(loc2.getBlock()))
    92. continue;
    93. if(loc2.getBlock().getTypeId() == 0)
    94. continue;
    95. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    96. loc2.getBlock().breakNaturally();
    97. } else {
    98. break;
    99. }
    100. }
    101. loc2 = loc;
    102. // y+, x-, z-
    103. for(int i = 1; i <= 10; i++) {
    104. loc2.setY(loc.getY()+i);
    105. loc2.setX(loc.getX()-i);
    106. loc2.setZ(loc.getZ()-i);
    107. if(!blocklist.contains(loc2.getBlock()))
    108. continue;
    109. if(loc2.getBlock().getTypeId() == 0)
    110. continue;
    111. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    112. loc2.getBlock().breakNaturally();
    113. } else {
    114. break;
    115. }
    116. }
    117. loc2 = loc;
    118. // y+, z-
    119. for(int i = 1; i <= 10; i++) {
    120. loc2.setY(loc.getY()+i);
    121. loc2.setZ(loc.getZ()-i);
    122. if(!blocklist.contains(loc2.getBlock()))
    123. continue;
    124. if(loc2.getBlock().getTypeId() == 0)
    125. continue;
    126. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    127. loc2.getBlock().breakNaturally();
    128. } else {
    129. break;
    130. }
    131. }
    132. loc2 = loc;
    133. // y+, z-, x+
    134. for(int i = 1; i <= 10; i++) {
    135. loc2.setY(loc.getY()+i);
    136. loc2.setX(loc.getX()+i);
    137. loc2.setZ(loc.getZ()-i);
    138. if(!blocklist.contains(loc2.getBlock()))
    139. continue;
    140. if(loc2.getBlock().getTypeId() == 0)
    141. continue;
    142. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    143. loc2.getBlock().breakNaturally();
    144. } else {
    145. break;
    146. }
    147. }
    148. loc2 = loc;
    149. // x+
    150. for(int i = 1; i <= 10; i++) {
    151. loc2.setX(loc.getX()+i);
    152. if(!blocklist.contains(loc2.getBlock()))
    153. continue;
    154. if(loc2.getBlock().getTypeId() == 0)
    155. continue;
    156. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    157. loc2.getBlock().breakNaturally();
    158. } else {
    159. break;
    160. }
    161. }
    162. loc2 = loc;
    163. // x-
    164. for(int i = 1; i <= 10; i++) {
    165. loc2.setX(loc.getX()-i);
    166. if(!blocklist.contains(loc2.getBlock()))
    167. continue;
    168. if(loc2.getBlock().getTypeId() == 0)
    169. continue;
    170. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    171. loc2.getBlock().breakNaturally();
    172. } else {
    173. break;
    174. }
    175. }
    176. loc2 = loc;
    177. // z+
    178. for(int i = 1; i <= 10; i++) {
    179. loc2.setZ(loc.getZ()+i);
    180. if(!blocklist.contains(loc2.getBlock()))
    181. continue;
    182. if(loc2.getBlock().getTypeId() == 0)
    183. continue;
    184. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    185. loc2.getBlock().breakNaturally();
    186. } else {
    187. break;
    188. }
    189. }
    190. loc2 = loc;
    191. // z-
    192. for(int i = 1; i <= 10; i++) {
    193. loc2.setZ(loc.getZ()-i);
    194. if(!blocklist.contains(loc2.getBlock()))
    195. continue;
    196. if(loc2.getBlock().getTypeId() == 0)
    197. continue;
    198. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    199. loc2.getBlock().breakNaturally();
    200. } else {
    201. break;
    202. }
    203. }
    204. loc2 = loc;
    205. // y-
    206. for(int i = 1; i <= 10; i++) {
    207. loc2.setY(loc.getY()-i);
    208. if(!blocklist.contains(loc2.getBlock()))
    209. continue;
    210. if(loc2.getBlock().getTypeId() == 0)
    211. continue;
    212. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    213. loc2.getBlock().breakNaturally();
    214. } else {
    215. break;
    216. }
    217. }
    218. loc2 = loc;
    219. // y-, x+
    220. for(int i = 1; i <= 10; i++) {
    221. loc2.setY(loc.getY()-i);
    222. loc2.setX(loc.getX()+i);
    223. if(!blocklist.contains(loc2.getBlock()))
    224. continue;
    225. if(loc2.getBlock().getTypeId() == 0)
    226. continue;
    227. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    228. loc2.getBlock().breakNaturally();
    229. } else {
    230. break;
    231. }
    232. }
    233. loc2 = loc;
    234. // y-, x+, z+
    235. for(int i = 1; i <= 10; i++) {
    236. loc2.setY(loc.getY()-i);
    237. loc2.setX(loc.getX()+i);
    238. loc2.setZ(loc.getZ()+i);
    239. if(!blocklist.contains(loc2.getBlock()))
    240. continue;
    241. if(loc2.getBlock().getTypeId() == 0)
    242. continue;
    243. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    244. loc2.getBlock().breakNaturally();
    245. } else {
    246. break;
    247. }
    248. }
    249. loc2 = loc;
    250. // y-, z+
    251. for(int i = 1; i <= 10; i++) {
    252. loc2.setY(loc.getY()-i);
    253. loc2.setZ(loc.getZ()+i);
    254. if(!blocklist.contains(loc2.getBlock()))
    255. continue;
    256. if(loc2.getBlock().getTypeId() == 0)
    257. continue;
    258. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    259. loc2.getBlock().breakNaturally();
    260. } else {
    261. break;
    262. }
    263. }
    264. loc2 = loc;
    265. // y-, z+, x-
    266. for(int i = 1; i <= 10; i++) {
    267. loc2.setY(loc.getY()-i);
    268. loc2.setX(loc.getX()-i);
    269. loc2.setZ(loc.getZ()+i);
    270. if(!blocklist.contains(loc2.getBlock()))
    271. continue;
    272. if(loc2.getBlock().getTypeId() == 0)
    273. continue;
    274. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    275. loc2.getBlock().breakNaturally();
    276. } else {
    277. break;
    278. }
    279. }
    280. loc2 = loc;
    281. // y-, x-
    282. for(int i = 1; i <= 10; i++) {
    283. loc2.setY(loc.getY()-i);
    284. loc2.setX(loc.getX()-i);
    285. if(!blocklist.contains(loc2.getBlock()))
    286. continue;
    287. if(loc2.getBlock().getTypeId() == 0)
    288. continue;
    289. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    290. loc2.getBlock().breakNaturally();
    291. } else {
    292. break;
    293. }
    294. }
    295. loc2 = loc;
    296. // y-, x-, z-
    297. for(int i = 1; i <= 10; i++) {
    298. loc2.setY(loc.getY()-i);
    299. loc2.setX(loc.getX()-i);
    300. loc2.setZ(loc.getZ()-i);
    301. if(!blocklist.contains(loc2.getBlock()))
    302. continue;
    303. if(loc2.getBlock().getTypeId() == 0)
    304. continue;
    305. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    306. loc2.getBlock().breakNaturally();
    307. } else {
    308. break;
    309. }
    310. }
    311. loc2 = loc;
    312. // y-, z-
    313. for(int i = 1; i <= 10; i++) {
    314. loc2.setY(loc.getY()-i);
    315. loc2.setZ(loc.getZ()-i);
    316. if(!blocklist.contains(loc2.getBlock()))
    317. continue;
    318. if(loc2.getBlock().getTypeId() == 0)
    319. continue;
    320. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    321. loc2.getBlock().breakNaturally();
    322. } else {
    323. break;
    324. }
    325. }
    326. loc2 = loc;
    327. // y-, z-, x+
    328. for(int i = 1; i <= 10; i++) {
    329. loc2.setY(loc.getY()-i);
    330. loc2.setX(loc.getX()+i);
    331. loc2.setZ(loc.getZ()-i);
    332. if(!blocklist.contains(loc2.getBlock()))
    333. continue;
    334. if(loc2.getBlock().getTypeId() == 0)
    335. continue;
    336. if(!protIDs.contains(loc2.getBlock().getTypeId())) {
    337. loc2.getBlock().breakNaturally();
    338. } else {
    339. break;
    340. }
    341. }
    342.  


    Sorry for any typo's, I pounded that out pretty fast... also, if you want to speed up each loop, you can predefine your iterator (int i = 1; imax = 10, then for(i; i<imax; i++))

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

    JayEffKay

    RustyDagger
    No problem, I'll do that. There's also a 'watch thread' button, maybe you can use that next time as well ;)

    Anyway, although others suggest also protecting blocks behind the tnt-free blocks, we don't even know what you want. So in that case the method Zarius suggested seems to be enough (and I've been building a whole 'repairing'-plugin for nothing, except teh learn :p). Anyway, here's the thing in a nice package, with source and credits to Zarius.
    Might publish it properly later.

    Do let me know if you do want blocks behind protected, I could use my previous code to temporary change the blocks into Obsidian, not sure if that's a good idea, but willing to test :p

    edit(3):
    romobomo
    If I understand it right, your method involves canceling the explosion event. But wouldn't that also cancel other physical effects that we want when building a TnT-cannon?
     

    Attached Files:

  13. Offline

    RustyDagger

    JayEffKay Protecting blocks behind the Said gold blocks would be nice however its not 100% needed because we can just make the doors to our vaults more away from what we are protecting. the only down side to that might be our buttons or levers getting destroyed. I intended it to be used with a lot of obsid around it any way. as a vault door.

    another option for me would be just allowing obsidian to be moved with pistons :/
     
  14. Offline

    Zarius

    RustyDagger

    OtherDrops should be able to do the basic protection (ie. just stopping the gold blocks themselves, not protecting behind) now in the most recent version - 2.3-beta4. Example config:

    Code:
      GOLD_BLOCK:
        - action: BLOCK_BREAK
          tool: EXPLOSION  # or just EXPLOSION_TNT if you don't want to protect against creepers
          drop: DENY
    
     
  15. Offline

    foxwillow

    so a block's blast resistance can't just be altered?

    this was a question i had that seems to fit in well here. if a gold block just had obby's blast resistance, wouldnt that be easiest?
     
  16. Offline

    RustyDagger

    Zarius I think I might just do that Seems simple enough. Now back to fixing combattag arrg...
     
  17. Offline

    Zarius

    Doesn't seem to be any way to do this easily yet (I did a quick Bukkit & Google search - people asking how to do it but no definitive answers).

    You could also kinda "fake" a blast resistance in OtherDrops using this config:

    Code:
      GOLD_BLOCK:
        - action: BLOCK_BREAK
          tool: EXPLOSION  # or just EXPLOSION_TNT if you don't want to protect against creepers
          drop: DENY
          chance: 99.5%  # this would let 1 in 200 blocks actually get destroyed
    
    Although it's not dependant on explosion "strength" at all.

    Let me know if there are any problems with my solution - I should be able to fix OtherDrops pretty quickly if there are any problems.
     
  18. Offline

    RustyDagger

    Zarius yup will do will open a ticket if i run into any thing not acting as I think it should :D

    About to but the new bukkit RB on new CombatTag then otherdrops :D Config seems nice btw well laid out and iv seen a lot of bad configs in my time :D
     

Share This Page