1.15.2 Portal Frame Detection

Discussion in 'Spigot Plugin Development' started by WhispTheFox, Jan 29, 2020.

  1. Hi guys,

    I've been working on a basic portal plugin for a while now, and while teleportation and database storage haven't been a problem, I've been struggling with frame detection. I'm trying to make portals freeform, much like with AncientGates. So far, for the frame detection, I've been drafting pseudo code on paper, but I've become confused with some of the logic. I've thought about using Block#getRelative, but I don't know how to detect when the end of a section of frame has been detected or which direction to start in.

    I'm not looking for or anything; just ideas to try because I really have no idea where to start.
     
  2. Block#getRelative() doesn't sound wrong.
    You could get the Portal-block, and check it's orientation. Then loop along the four sides while you have another portal-block until you reach a portal frame-block (obsidian). If you reach any other block, the portal has probably been put there via plugin or command.
    You could now either do that for all portal-blocks (inefficient, but easy) or you'd now loop around the "square"of the portal frame.
     
  3. That would work if I were working with nether portals. But I'm not. I'm trying to make it possible to make a portal out of any block. The material inside is, for right now, air.
     
  4. Well if you only want to detect the frame, just use a non-portal block as a start, instead of a portal-block.
    If you don't have a Directional block or an Orientable, you will have to set a certain max-length and then check for both sides. There can be three cases:
    1) The first side has the given Portal-frame block that is less than the maximum distance -> Try to detect a frame
    2) The first has no frame-block, but the second has -> Try to detect a frame
    3) Both have no frame-blocks in sight, so there is no portal -> return

    Detecting the actual frame could maybe be done something like this. But this is just something to think about, this algorithm doesn't take into account multiple blocks that do not belong to the portal but are adjacent to some other blocks. But it could probably be extended to that by putting all the blocks that might belong to the portal in a list. If the algorithm returns, you have to throw out non-fitting blocks and start the algorithm again but with a tabu-list of those non-fitting blocks. If the algorithm finally returns with an empty list, no portal was created.
    Code (Java):
    Block start;
    Location startLoc = start.getLocation();
    BlockFace startFace, newFace;
    int index = 0;
    BlockFace[] directionsDone = new BlockFace[4] {startFace, null, null, null};
    boolean portalFound = false;
    while(true) {
        for (BlockFace face: north, south, east, west, up, down; face != last) {
            start = block.getRelative(face)
            if (start.getType() == material) break;
            return false;
        }
        if (newFace != directionsDone[index]) {
            index++:
            if (index > 3) return false;
            directionsDone[index] = newFace;
            if (directionsDone contains more than two of the same faces) return false;
        } else start = newFace;
        if (start.getLocation() == startLoc) return true;
    }
     
  5. Alright, thanks. I'll give this a try.
     
  6. Probably it‘s a good idea to store the faces in a map (face, list of blocks in that face) in the first place and update the list at each face-change. If the size of the list is greater than 4, either you are done or you have to move the smallest element into a tabu-list (or completely remove it)
     
  7. Do you mean the size of the map should be no greater than four?