Solved Check for oxygen leaks in a room

Discussion in 'Spigot Plugin Development' started by TSEngineer, Jun 13, 2018.

Thread Status:
Not open for further replies.
  1. How to check for oxygen leaks in a room using any position inside

    Oxygen leak
    2018-06-13_23.37.14.png Oxygen leak 2018-06-13_23.38.08.png
    No oxygen leak[​IMG]
  2. First, you would have to define what a room is, in a rather performant way. Let's say there are also other structures around your first example, why would the hole not just be there to connect these rooms?
    Second, you would have to check every block in your room, if their adjacent tiles are either another room block, or a wall block. If adjacent block is not a room or wall block, you would have a leak.

    This is not an easy task. What are you trying to do?
  3. NathanWolf


    You'll probably want to use a recursive algorithm of some kind, but first you will need to clarify what you mean by a room. (Looks like I got ninja'd here)

    Maybe "open to the air"? So recursively iterate through all air blocks, preferring to traverse upward if possible, and if you reach an air block at y=255 then you have a leak?

    Or maybe define the max size of a room... ?

    I mean it's not a simple problem, what if you have a huge underground cave system that goes on for thousands of blocks... ?
  4. You can't detect this based off of any single given block inside of the area.
  5. Ooooo, an interesting idea! I'm assuming this is for some sort of space station/space exploration plugin?
    You're going to have to make multi-block structures.
    make a list of Materials of what you consider to be air-sealing blocks (or you could go the other way around and make a list of Materials that don't keep air sealed, whichever is easier for you) then I'd probably use a block place event, check to make sure your world is, in fact, a "space" world. Then make sure the placed block is one of the "safe" materials.
    Now's the tricky bit. you'll have to loop through all six directions of adjacent blocks to our placed block (this will not account for if you allow no corners on your build). Once you have "run out" of exterior blocks, divide the INTERIOR of these blocks into cubes and loop through those. If at any point your interior blocks don't touch other interior blocks OR your exterior blocks from before, you have a leak (Obviously, this would be an absolutely huge performance hit. You may want to look into a dependency on Async World Edit or World Guard). This performance hit is immediately decreased if you store these lists as an Object, however. Then, you simply have to check if when a block is broken, if it is part of the exterior of any of your custom Objects. If so, DO NOT delete the object, instead have another list of "breaches." Then you can check if a placed block is in one of the Objects' breaches first, and repair the already existing structure and avoid having to re-loop every time.
    Because you are not editing the world in anyway from the plugin, you might be able to make this work Async with a little bit of magic, but I wouldn't count on that.
    • Creative Creative x 2
  6. Why shouldn't it be possible? Just because it's not a simple problem doesn't mean it's impossible. There are of course limitations, but this is not impossible.
    • Agree Agree x 2
  7. I poorly worded my comment; yes, it's possible, though not using normal API methods, which is what I assumed OP was going for (a simple solution to a complex problem).
    • Agree Agree x 2
  8. NathanWolf


    This doesn't really have anything to do with API vs non-API, this can totally be done using only API methods. There is nothing more here than checking block types.

    I think the main difficulty here is a design one, there is no real clear definition of a "room". I mean you could be in a room with a hole but that room is inside an enclosed room, or maybe that room has a hole but is inside a giant space station which is enclosed... it's just not a simple problem to define, though if it were defined well I think the solution would not actually be that complicated. It's basically just a form of flood fill.
  9. One more example:
    No oxygen leak
  10. I just mean it can't be done with ex: 1 or 2 checks and a method, not that the Spigot API is incapable of doing it..
  11. Just about everything is more complex than a couple of if statements.

    On topic, however, most of the answers you're going to receive here will be 90% subjective. You're much more likely to find more on something like this outside of these Minecraft centered forums (I suggest looking around game development forums and the like), due to how few things do this reliably and successfully.

    My personal suggestion is about the same as what others have suggested- "fill" outwards until you reach either a predetermined limit or have run out of places to travel. A HashSet would give you constant time comparisons on already evaluated blocks, disregard evaluated BlockFaces, etc. Figuring out how to do this asynchronously would help you immensely and cut down on the lag.
    • Agree Agree x 2
  12. I would recommend building a system that keeps track of stored areas by storing the min and max corners for areas with 'oxygen'. When a block is broken or 'moved' (in the case of physics and pistons), do a check for that area and make sure there are no air blocks that are not stored (you're checking if there is any areas that are not stored by the system, and as such, don't have oxygen). If a block like that exists, there is a leak, and you should remove the surrounding areas that do have oxygen.

    Then, whenever you add oxygen, or need to calculate adding oxygen to an area, try to do flood fills for small areas and see if the distance between the checked block and the 'center' is greater than 50 (which would be less performance heavy check than actually finding paths that go up to 255, though this will mean large rooms will not be supported).
  13. Praya


    you can use this method:
    - create an empty block list
    - get horizontal block and vertical block from your location
    - check if the block is air, and then put to the list
    - loop again the block from the list. if the block already used to check blocks around remove from list.

    ◻️◻️◻️◻️◻️ > ◻️◻️◻️◻️◻️ > ◻️◻️◼️◻️◻️
    ◻️◻️◻️◻️◻️ > ◻️◻️◼️◻️◻️ > ◻️◼️◼️◼️◻️
    ◻️◻️◼️◻️◻️ > ◻️◼️◼️◼️◻️ > ◼️◼️◼️◼️◼️
    ◻️◻️◻️◻️◻️ > ◻️◻️◼️◻️◻️ > ◻️◼️◼️◼️◻️
    ◻️◻️◻️◻️◻️ > ◻️◻️◻️◻️◻️ > ◻️◻️◼️◻️◻️

    this method only check block air that not yet checked, it is better than loop around block for this situation
    • Winner Winner x 5
  14. If he does do this, he would make sure this is a limit to either the maximum distance it will check for, or the maximum amount of blocks it can check before stopping. If not, doing this could crash the server if it does have a leak.
  15. Praya


  16. Praya


    I just check my code based on what I said above.
    here is the result


    so, the overall is good.
    the first picture is when I flying in air, why it take 4000 milis because there are no solid block that causing there are many blocks to check (88451 blocks).
    but when we check inside a room or cave etc. it only need 44 milis with total blocks check reach more than 10.000.

    so the conclusion is, better to add more check based on total blocks
    • Winner Winner x 1
  17. If you added a check at specific Y check air up to 255 you would reduce your first screenshot from 88k blocks checked down to < 255.
    • Like Like x 1
  18. @TSEngineer , Just a little idea:
    - Select a center block, get block light level. If it is lower than the specified value, there is no leakage.
  19. Praya


    thanks for making this thread, because the question now I got some idea plugin to make by using code like this
Thread Status:
Not open for further replies.