Newer
Older
ultramine_private_regions / src / main / java / org / ultramine / regions / RegionMap.java
@vlad20012 vlad20012 on 29 Mar 2016 3 KB Initial commit
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;
	}
}