Can somebody figure out a better solution for this?

Discussion in 'Plugin Development' started by blablubbabc, Aug 17, 2013.

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

    blablubbabc

    Hey,
    I am currently trying to detect if a newly placed block very likely blocks a hallway (making it impossible to walk through that hallway there).

    I say "very likely" because I only (try to) analyize the surrounding blocks to decide if this could be a hallway, which could be blocked by the newly placed block (in my case a flower pot). It also doesn't take possibilities in account, which allows the player to climb over that "block construction" which it considers being a hallway.

    So, here is what I currently have. The question is, if somebody can think of a better, more elegant way to do this, maybe even taking other conditions additionally into account..

    Code:java
    1. private boolean blocksHallway(Block block) {
    2. if (block.getRelative(BlockFace.UP).getType() == Material.AIR) {
    3. boolean roofed = isRoofed(block);
    4.  
    5. Block northB = block.getRelative(BlockFace.NORTH);
    6. Block southB = block.getRelative(BlockFace.SOUTH);
    7. Block westB = block.getRelative(BlockFace.WEST);
    8. Block eastB = block.getRelative(BlockFace.EAST);
    9.  
    10. boolean north = isWall(northB);
    11. boolean south = isWall(southB);
    12. boolean west = isWall(westB);
    13. boolean east = isWall(eastB);
    14.  
    15. boolean northRoofed = isRoofed(northB);
    16. boolean southRoofed = isRoofed(southB);
    17. boolean westRoofed = isRoofed(westB);
    18. boolean eastRoofed = isRoofed(eastB);
    19.  
    20. // | H | | X |
    21. // X o X H o H
    22. // | H | | X |
    23. if (west && east && !north && !south && (roofed || northRoofed || southRoofed)) return true;
    24. if (north && south && !west && !east && (roofed || westRoofed || eastRoofed)) return true;
    25.  
    26. Block northWestB = block.getRelative(BlockFace.NORTH_WEST);
    27. Block southEastB = block.getRelative(BlockFace.SOUTH_EAST);
    28. Block northEastB = block.getRelative(BlockFace.NORTH_EAST);
    29. Block southWestB = block.getRelative(BlockFace.SOUTH_WEST);
    30.  
    31. boolean northWest = isWall(northWestB);
    32. boolean southEast = isWall(southEastB);
    33. boolean northEast = isWall(northEastB);
    34. boolean southWest = isWall(southWestB);
    35.  
    36. /*boolean northWestRoofed = isRoofed(northWestB);
    37.   boolean southEastRoofed = isRoofed(southEastB);
    38.   boolean northEastRoofed = isRoofed(northEastB);
    39.   boolean southWestRoofed = isRoofed(southWestB);*/
    40.  
    41. // X H X X h | | h | | h X
    42. // h o h H o h h o h h o H
    43. // | h | X h | X H X | h X
    44. if (northWest) {
    45. if (northEast && !north) {
    46. if (roofed || northRoofed) {
    47. if (!west || !east || !south) return true;
    48. }
    49. if (!west && westRoofed && (east || eastRoofed) && (south || southRoofed)) return true;
    50. if (!east && eastRoofed && (west || westRoofed) && (south || southRoofed)) return true;
    51. if (!south && southRoofed && (west || westRoofed) && (east || eastRoofed)) return true;
    52. }
    53. if (southWest && !west) {
    54. if (roofed || westRoofed) {
    55. if (!north || !east || !south) return true;
    56. }
    57. if (!north && northRoofed && (east || eastRoofed) && (south || southRoofed)) return true;
    58. if (!east && eastRoofed && (north || northRoofed) && (south || southRoofed)) return true;
    59. if (!south && southRoofed && (north || northRoofed) && (east || eastRoofed)) return true;
    60. }
    61. }
    62. if (southEast) {
    63. if (southWest && !south) {
    64. if (roofed || southRoofed) {
    65. if (!north || !east || !west) return true;
    66. }
    67. if (!north && northRoofed && (east || eastRoofed) && (west || westRoofed)) return true;
    68. if (!east && eastRoofed && (north || northRoofed) && (west || westRoofed)) return true;
    69. if (!west && westRoofed && (north || northRoofed) && (east || eastRoofed)) return true;
    70. }
    71. if (northEast && !east) {
    72. if (roofed || eastRoofed) {
    73. if (!west || !north || !south) return true;
    74. }
    75. if (!north && northRoofed && (south || southRoofed) && (west || westRoofed)) return true;
    76. if (!south && southRoofed && (north || northRoofed) && (west || westRoofed)) return true;
    77. if (!west && westRoofed && (north || northRoofed) && (south || southRoofed)) return true;
    78. }
    79. }
    80.  
    81. // X H | | h |
    82. // h o X h o X
    83. // | h | X H |
    84. if (east) {
    85. if (northWest && !north) {
    86. if (roofed || northRoofed) {
    87. if (!south || !west) return true;
    88. }
    89. if (!south && southRoofed && (west || westRoofed)) return true;
    90. if (!west && westRoofed && (south || southRoofed)) return true;
    91. }
    92. if (southWest && !south) {
    93. if (roofed || southRoofed) {
    94. if (!north || !west) return true;
    95. }
    96. if (!north && northRoofed && (west || westRoofed)) return true;
    97. if (!west && westRoofed && (north || northRoofed)) return true;
    98. }
    99. }
    100.  
    101. // | X | | X |
    102. // h o H H o h
    103. // | h X X h |
    104. if (north) {
    105. if (southEast && !east) {
    106. if (roofed || eastRoofed) {
    107. if (!south || !west) return true;
    108. }
    109. if (!south && southRoofed && (west || westRoofed)) return true;
    110. if (!west && westRoofed && (south || southRoofed)) return true;
    111. }
    112. if (southWest && !west) {
    113. if (roofed || westRoofed) {
    114. if (!south || !east) return true;
    115. }
    116. if (!south && southRoofed && (east || eastRoofed)) return true;
    117. if (!east && eastRoofed && (south || southRoofed)) return true;
    118. }
    119. }
    120.  
    121. // | h | | H X
    122. // X o h X o h
    123. // | H X | h |
    124. if (west) {
    125. if (southEast && !south) {
    126. if (roofed || southRoofed) {
    127. if (!east || !north) return true;
    128. }
    129. if (!east && eastRoofed && (north || northRoofed)) return true;
    130. if (!north && northRoofed && (east || eastRoofed)) return true;
    131. }
    132. if (northEast && !north) {
    133. if (roofed || northRoofed) {
    134. if (!south || !east) return true;
    135. }
    136. if (!east && eastRoofed && (south || southRoofed)) return true;
    137. if (!south && southRoofed && (east || eastRoofed)) return true;
    138. }
    139. }
    140.  
    141. // | h X X h |
    142. // h o H H o h
    143. // | X | | X |
    144. if (south) {
    145. if (northEast && !east) {
    146. if (roofed || eastRoofed) {
    147. if (!north || !west) return true;
    148. }
    149. if (!west && westRoofed && (north || northRoofed)) return true;
    150. if (!north && northRoofed && (west || westRoofed)) return true;
    151. }
    152. if (northWest && !west) {
    153. if (roofed || westRoofed) {
    154. if (!north || !east) return true;
    155. }
    156. if (!east && eastRoofed && (north || northRoofed)) return true;
    157. if (!north && northRoofed && (east || eastRoofed)) return true;
    158. }
    159. }
    160.  
    161. // X | | | | X
    162. // | o | | o |
    163. // | | X X | |
    164. if (northWest && southEast && ((roofed && !(west && south) && !(north && east)) || (westRoofed && southRoofed && !(west && south)) || (northRoofed && eastRoofed && !(north && east)))) return true;
    165. if (northEast && southWest && ((roofed && !(west && north) && !(south && east)) || (westRoofed && northRoofed && !(west && north)) || (southRoofed && eastRoofed && !(east && south)))) return true;
    166.  
    167. }
    168. return false;
    169. }
    170.  
    171. private boolean isWall(Block bottom) {
    172. Block top = bottom.getRelative(BlockFace.UP);
    173. return bottom.getType() != Material.AIR || top.getType() != Material.AIR;
    174. }
    175.  
    176. private boolean isRoofed(Block bottom) {
    177. Block top = bottom.getRelative(BlockFace.UP, 2);
    178. return top.getType() != Material.AIR;
    179. }
     
  2. Offline

    blablubbabc

    Nobody got an better idea, or an idea how to improve this? :-(
     
  3. Offline

    Saposhiente

    Better is to only check one block at a time instead of loading them all at the beginning. So you first check whether the block above it is solid (if yes, it's not a hallway), then check the block above that (if that's not solid, you're not blocking anything), then check the blocks 1 above and 1 horizontal to it (if 2 opposites are solid, you're blocking a straight hallway; if 2 diagonally adjacent ones are solid, you might be blocking a corner, check the opposite corner block; if more or less than 2 are solid you're not in a hallway)
    This particular algorithm won't detect if you're blocking the outside of the entrance to a hallway, but I'm sure you can figure out how to extend it.
     
  4. Offline

    blablubbabc

    Hah! Someone is finally taking the chance.
    I already tried to only load the blocks and do the checks needed. If you take a look at my first condition I use all the blocks loaded above there..

    There are cases, there the placed block is blocking a hallway, even though the 2 blocks above are both air.
    Example: X -> Wall ; H -> Air / No Wall / walkable; O -> the placed block; R -> no wall (2 blocks of air) but the block above that is not air -> it is "roofed"
    X R X
    H O H
    H H H

    Could you be more precise? Do you mean the block in the north or the block "upwards" the block placed?
    Maybe you can even try and write an algorithm for that, I guess that will probably be easier, than trying to explain this with words :) Let's see if you can find one, which checks for at least the same hallway-conditions like mine, but is more effizient / smaller / etc.

    Yes, it does only check the blocks around (currently). I want it to be a quick check, because it might be called quite often. It doesn't have to be 100 % correct, but more like "very likly correct" ( I don't want to waste to much processing on this check).
    If you have an idea to make it more precise with as less processing power as possible, let me know!

    This one works pretty well currently. I just wanted to see if someone has an idea to improve this by reducing the amount of checks it needs to do or by adding funcionality to it, or maybe even solve this kind of problem (detecting blocking of hallways) with a complet other attempt.
     
  5. Offline

    Saposhiente

    You gave the example of a clay pot, I assumed that there could only be solid blocks underneath it. Your algorithm looks like it's a bit inefficient, but not in obvious ways if the objective is certainty. One thing you certainly need to do is update isWall to not treat torches & etc as walls.
     
  6. Offline

    jayfella

    I have information to contribute.

    Firstly, if a block is actually blocking, e.g. a torch or flower or something like that.

    org.​bukkit.​Material
    public boolean isSolid()
    Check if the material is a block and solid (cannot be passed through by a player)

    Returns:
    True if this material is a block and solid


    Secondly, somewhat trivial, but a "block" has a .isEmpty() method, so no need to compare the material to air.

    org.​bukkit.​block.​Block
    public boolean isEmpty()
    Checks if this block is empty.
    A block is considered empty when getType() returns Material.AIR.


    Returns:
    true if this block is empty
     
    blablubbabc likes this.
  7. Offline

    blablubbabc

    There are only solid blocks underneath it. The picture above shows the situation from above, looking from the sky down on to the blocks. Hope that clarifies the picture :)
    jayfella
    Oh yeah. Can't believe that I forgot something obvious like that, thanks!
     
Thread Status:
Not open for further replies.

Share This Page