Thread: [REVISED] Advanced Region System

Page 1 of 3 123 LastLast
Results 1 to 10 of 30
  1. #1 [REVISED] Advanced Region System 
    Banned

    Join Date
    Jul 2008
    Age
    26
    Posts
    5,826
    Thanks given
    1,301
    Thanks received
    197
    Rep Power
    0
    NOTE: THIS CODE IS UNTESTED AS OF NOW. REPORT ANY BUGS.

    Heres my final version of my Regioning System. If you want an explanation, please go to the previous thread:
    [Only registered and activated users can see links. ]
    - The ONLY operations you have to deal with when using this Region System are add, remove, move, and getTileContents.
    - This Class uses Generics, so you can instantate a RegionSystem<Entity>, RegionSystem<MapObject> or whatever you want to, to make it fit your needs.
    - It handles automatic allocation and deallocation of regions when not in use.
    - It allows you to set your own size arguments for region and map width/height/depth.
    - To access a tiles contents, an unmodifiable ListIterator<TileContent> is returned, giving you the most flexability possible.

    Heres the code:
    Code:
    import java.util.LinkedList;
    import java.util.ListIterator;
    
    /**
     * Handles splitting the map up into
     * lazily initialized regions to combine
     * the speed of a Tile system with the
     * memory efficiency of the standard method.
     * This unlike my old system completely separates
     * internal code from the end user, and allows
     * multiple region instances and sizes within a
     * single server.
     * @author Colby
     */
    @SuppressWarnings({"unchecked", "rawtypes", "serial"})
    public class RegionSystem<TileContent> {
    
        /**
         * Creates a RegionSystem with default sizes.
         */
        public RegionSystem() {
            this(1024 * 16, 1024 * 16, 4, 16, 16);
        }
    
        /**
         * Creates a RegionSystem with custom sizes.
         * @param worldAbsWidth
         * @param worldAbsHeight
         * @param worldAbsDepth
         * @param regionAbsWidth
         * @param regionAbsHeight
         */
        public RegionSystem(int worldAbsWidth, int worldAbsHeight, int worldAbsDepth, int regionAbsWidth, int regionAbsHeight) {
            this.regions = new Region[worldAbsWidth / regionAbsWidth][worldAbsHeight / regionAbsHeight][worldAbsDepth];
            this.worldAbsWidth = worldAbsWidth;
            this.worldAbsHeight = worldAbsHeight;
            this.worldAbsDepth = worldAbsDepth;
            this.regionAbsWidth = regionAbsWidth;
            this.regionAbsHeight = regionAbsHeight;
        }
        //World sizes
        public final int worldAbsWidth;
        public final int worldAbsHeight;
        public final int worldAbsDepth;
        public final int regionAbsWidth;
        public final int regionAbsHeight;
        //Actual regions
        private final Region[][][] regions;
    
        /**
         * Gets the contents at the specified X/Y/Z location.
         * @param absX The X coordinate.
         * @param absY The Y coordinate.
         * @param absZ The Z coordinate.
         * @return An UNMODIFYABLE ListIterator with the contents of
         * the requested tile, or null if the parent region is not initialized.
         */
        public ListIterator<TileContent> getTileContents(int absX, int absY, int absZ) {
            int regX = absX / regionAbsWidth, regY = absY / regionAbsHeight;
            Region region = regions[regX][regY][absZ];
            if (region != null) {
                return region.tiles[absX & regionAbsWidth - 1][absY & regionAbsHeight - 1].contents.listIterator();
            }
            return null;
        }
    
        /**
         * Adds a TileContent to the specified X/Y/Z.
         * @param content The TileContent to add.
         * @param absX The X coordinate.
         * @param absY The Y coordinate.
         * @param absZ The Z coordinate.
         * @return If the operation was successful.
         */
        public boolean add(TileContent content, int absX, int absY, int absZ) {
            int regX = absX / regionAbsWidth, regY = absY / regionAbsHeight;
            Region region = regions[regX][regY][absZ];
            if (region == null) {
                region = (regions[regX][regY][absZ] = new Region(regX, regY, absZ));
            }
            return region.add(content, absX, absY);
        }
    
        /**
         * Removes the specified TileContent only
         * from the specified X/Y/Z.
         * @param content The TileContent to remove.
         * @param absX The X coordinate.
         * @param absY The Y Coordinate.
         * @param absZ The Z coordinate.
         * @return If the operation was successful.
         */
        public boolean remove(TileContent content, int absX, int absY, int absZ) {
            int regX = absX / regionAbsWidth, regY = absY / regionAbsHeight;
            Region region = regions[regX][regY][absZ];
            if (region != null) {
                return region.remove(content, absX, absY);
            }
            return false;
        }
    
        /**
         * Attempts to move the specified TileContent.
         * @param content The TileContent to move.
         * @param fx The old X coordinate.
         * @param fy The old Y coordinate.
         * @param fz The old Z coordinate.
         * @param tox The new X coordinate.
         * @param toy The new Y coordinate.
         * @param toz The new Z coordinate.
         * @return If the add operation was successful.
         */
        public boolean move(TileContent content, int fx, int fy, int fz, int tox, int toy, int toz) {
            remove(content, fx, fy, fz);
            return add(content, tox, toy, toz);
        }
    
        private class Region<TileContent> {
    
            public Region(int regX, int regY, int regZ) {
                this.regX = regX;
                this.regY = regY;
                this.regZ = regZ;
            }
            private final Tile[][] tiles = new Tile[regionAbsWidth][regionAbsHeight];
            private final int regX, regY, regZ;
            private long activeTiles = 0L;
    
            {
                for (int x = regionAbsWidth, y; --x != -1;) {
                    for (y = regionAbsHeight; --y != -1;) {
                        tiles[x][y] = new Tile();
                    }
                }
            }
    
            private boolean add(TileContent content, int absX, int absY) {
                Tile tile = tiles[absX % regionAbsWidth][absY % regionAbsHeight];
                if (tile.contents.isEmpty()) {
                    ++activeTiles;
                }
                return tile.contents.add(content);
            }
    
            private boolean remove(TileContent content, int absX, int absY) {
                Tile tile = tiles[absX % regionAbsWidth][absY % regionAbsHeight];
                if (tile.contents.remove(content)) {
                    if (tile.contents.isEmpty()) {
                        if (--activeTiles < 1) {
                            regions[regX][regY][regZ] = null;
                        }
                    }
                    return true;
                }
                return false;
            }
        }
    
        private class Tile<TileContent> {
    
            private TileContents contents = new TileContents();
        }
    
        private class TileContents extends LinkedList {
    
            @Override
            public ListIterator listIterator() {
                return new ListIterator<TileContent>() {
    
                    private ListIterator<TileContent> parent = TileContents.super.listIterator();
    
                    @Override
                    public boolean hasNext() {
                        return parent.hasNext();
                    }
    
                    @Override
                    public TileContent next() {
                        return parent.next();
                    }
    
                    @Override
                    public boolean hasPrevious() {
                        return parent.hasPrevious();
                    }
    
                    @Override
                    public TileContent previous() {
                        return parent.previous();
                    }
    
                    @Override
                    public int nextIndex() {
                        return parent.nextIndex();
                    }
    
                    @Override
                    public int previousIndex() {
                        return parent.previousIndex();
                    }
    
                    @Override
                    public void add(TileContent o) {
                        throw new UnsupportedOperationException();
                    }
    
                    @Override
                    public void set(TileContent t) {
                        throw new UnsupportedOperationException();
                    }
    
                    @Override
                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        }
    }
    Reply With Quote  
     


  2. #2  
    Banned

    Join Date
    Sep 2007
    Posts
    1,838
    Thanks given
    22
    Thanks received
    21
    Rep Power
    0
    - It allows you to set your own size arguments for region and map width/height/depth.
    good job
    Reply With Quote  
     

  3. #3  
    Member

    Join Date
    May 2008
    Posts
    1,288
    Thanks given
    50
    Thanks received
    92
    Rep Power
    0
    Will test verryy soon.
    edit: see below.
    Reply With Quote  
     

  4. #4  
    Banned

    Join Date
    Jul 2008
    Age
    26
    Posts
    5,826
    Thanks given
    1,301
    Thanks received
    197
    Rep Power
    0
    114 views 2 replies lol. Nobody understand what this is even for.
    Reply With Quote  
     

  5. #5  
    Member

    Join Date
    May 2008
    Posts
    1,288
    Thanks given
    50
    Thanks received
    92
    Rep Power
    0
    Code:
        public boolean remove(TileContent content, int absX, int absY, int absZ) {
            Region region = getRegion(absX, absY, absZ);
            if (region != null) {
                return region.remove(content, absX, absY);
            }
            return false;
        }
    Should be:
    Code:
        public boolean remove(TileContent content, int absX, int absY, int absZ) {
            Region region = getRegion(absX, absY, absZ);
            if (region != null) {
                return region.remove(content, region.toLocalX(absX), region.toLocalY(absY));
            }
            return false;
        }
    p.s. got it working, not sure if i did the looping correctly though. Example for the looping plox?
    This is what I tried: (excuse my retarded-ness if its completely wrong - it does work tho)
    Code:
    	for(int x = -regionSystem.regionAbsWidth; x < regionSystem.regionAbsWidth; x++){
    	    for(int y = -regionSystem.regionAbsHeight; y < regionSystem.regionAbsHeight; y++){
    		ListIterator<Player> tileContents = regionSystem.getTileContents(plr.absX + x, plr.absY + y, plr.heightLevel);
    		if(tileContents == null){
    		    continue;
    		}
    		for(; tileContents.hasNext();){
    		    Player otherPlayer = tileContents.next();
    		    // Player updating stoofz.
    		}
    	    }
    	}
    edit:
    looking at your other thread my loop looks right, other than the "x < width/y < height" should be "x <= width/y <= height" thnx.
    Reply With Quote  
     

  6. #6  
    damnant quod non intellegunt

    Mr Chainsaw's Avatar
    Join Date
    Sep 2006
    Age
    27
    Posts
    4,058
    Thanks given
    827
    Thanks received
    1,277
    Rep Power
    4664
    Sexy! Thanks for releasing this. Much love and thanks .
    [Only registered and activated users can see links. ]

    Reply With Quote  
     

  7. #7  
    Registered Member Akeid's Avatar
    Join Date
    May 2009
    Posts
    911
    Thanks given
    22
    Thanks received
    15
    Rep Power
    37
    lol this is to advanced for this community lol
    [Only registered and activated users can see links. ]
    [Only registered and activated users can see links. ]
    MSN: [email protected]
    Reply With Quote  
     

  8. Thankful user:


  9. #8  
    Banned
    Join Date
    Feb 2008
    Posts
    384
    Thanks given
    30
    Thanks received
    26
    Rep Power
    0
    so RegionSystem creates the regions then Region allows you to control what is in each region for updating purposes? Nice..
    Reply With Quote  
     

  10. #9  
    Registered Member
    .Dan's Avatar
    Join Date
    Sep 2008
    Age
    25
    Posts
    873
    Thanks given
    54
    Thanks received
    115
    Rep Power
    494
    [troll]this(1024 * 16, 1024 * 16, 4, 16, 16); should be: this(16384, 16384, 4, 16, 16); cuz it iz faster!!![/troll]

    Nice to see some good snippets here, nice job, Colby.
    Reply With Quote  
     

  11. #10  
    Banned

    Join Date
    Jul 2008
    Age
    26
    Posts
    5,826
    Thanks given
    1,301
    Thanks received
    197
    Rep Power
    0
    Quote Originally Posted by Clifton View Post
    Code:
        public boolean remove(TileContent content, int absX, int absY, int absZ) {
            Region region = getRegion(absX, absY, absZ);
            if (region != null) {
                return region.remove(content, absX, absY);
            }
            return false;
        }
    Should be:
    Code:
        public boolean remove(TileContent content, int absX, int absY, int absZ) {
            Region region = getRegion(absX, absY, absZ);
            if (region != null) {
                return region.remove(content, region.toLocalX(absX), region.toLocalY(absY));
            }
            return false;
        }
    p.s. got it working, not sure if i did the looping correctly though. Example for the looping plox?
    This is what I tried: (excuse my retarded-ness if its completely wrong - it does work tho)
    Code:
    	for(int x = -regionSystem.regionAbsWidth; x < regionSystem.regionAbsWidth; x++){
    	    for(int y = -regionSystem.regionAbsHeight; y < regionSystem.regionAbsHeight; y++){
    		ListIterator<Player> tileContents = regionSystem.getTileContents(plr.absX + x, plr.absY + y, plr.heightLevel);
    		if(tileContents == null){
    		    continue;
    		}
    		for(; tileContents.hasNext();){
    		    Player otherPlayer = tileContents.next();
    		    // Player updating stoofz.
    		}
    	    }
    	}
    edit:
    looking at your other thread my loop looks right, other than the "x < width/y < height" should be "x <= width/y <= height" thnx.
    I realized that today Gimmie a sec and I'll post the optimized and updated version.
    Reply With Quote  
     

Page 1 of 3 123 LastLast

Thread Information
Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)


User Tag List

Posting Permissions
  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •