package org.ultramine.regions; import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; import org.ultramine.server.chunk.ChunkHash; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class RegionMap { private static final int SF = 7; private final Set<IRegion> set = new HashSet<IRegion>(); private final TIntObjectMap<List<IRegion>> map = new TIntObjectHashMap<List<IRegion>>(); public void add(IRegion region) { if(!set.add(region)) return; Rectangle shape = region.getShape(); for(int x = shape.getMin().x >> SF, sx = shape.getMax().x >> SF; x <= sx; x++) { for(int z = shape.getMin().z >> SF, sz = shape.getMax().z >> SF; z <= sz; z++) { int key = ChunkHash.chunkToKey(x, z); List<IRegion> list = map.get(key); if(list == null) { list = new ArrayList<IRegion>(2); map.put(key, list); } list.add(region); } } } public void remove(IRegion region) { if(!set.remove(region)) return; Rectangle shape = region.getShape(); for(int x = shape.getMin().x >> SF, sx = shape.getMax().x >> SF; x <= sx; x++) { for(int z = shape.getMin().z >> SF, sz = shape.getMax().z >> SF; z <= sz; z++) { int key = ChunkHash.chunkToKey(x, z); List<IRegion> list = map.get(key); if(list != null) { list.remove(region); if(list.isEmpty()) map.remove(key); } } } } public void onRegionExpand(IRegion region, Rectangle expandedPart) { if(!set.contains(region)) return; for(int x = expandedPart.getMin().x >> SF, sx = expandedPart.getMax().x >> SF; x <= sx; x++) { for(int z = expandedPart.getMin().z >> SF, sz = expandedPart.getMax().z >> SF; z <= sz; z++) { int key = ChunkHash.chunkToKey(x, z); List<IRegion> list = map.get(key); if(list == null) { list = new ArrayList<IRegion>(2); map.put(key, list); } if(!list.contains(region)) list.add(region); } } } public IRegion get(BlockPos point) { return findInHierarchy(map.get(ChunkHash.chunkToKey(point.x >> SF, point.z >> SF)), point); } private IRegion findInHierarchy(List<IRegion> list, BlockPos point) { if(list == null) return null; for(IRegion region : list) { if(region.getShape().contains(point)) { IRegion region1 = findInHierarchy(region.getChildren(), point); return region1 != null ? region1 : region; } } return null; } public Set<IRegion> getInRange(Rectangle rect) { return getInRange(rect.getMin(), rect.getMax()); } public Set<IRegion> getInRange(BlockPos min, BlockPos max) { Set<IRegion> ret = new HashSet<IRegion>(); for(int x = min.x >> SF, sx = max.x >> SF; x <= sx; x++) { for(int z = min.z >> SF, sz = max.z >> SF; z <= sz; z++) { int key = ChunkHash.chunkToKey(x, z); List<IRegion> list = map.get(key); if(list != null) { for(IRegion region : list) if(RegionUtil.isIntersects(min, max, region.getShape().getMin(), region.getShape().getMax())) ret.add(region); } } } return ret; } public boolean hasInRange(Rectangle rect) { return hasInRange(rect.getMin(), rect.getMax()); } public boolean hasInRange(BlockPos min, BlockPos max) { for(int x = min.x >> SF, sx = max.x >> SF; x <= sx; x++) { for(int z = min.z >> SF, sz = max.z >> SF; z <= sz; z++) { int key = ChunkHash.chunkToKey(x, z); List<IRegion> list = map.get(key); if(list != null) { for(IRegion region : list) if(RegionUtil.isIntersects(min, max, region.getShape().getMin(), region.getShape().getMax())) return true; } } } return false; } }