diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index c4f48eeb6..1e2607ab8 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -10,11 +10,6 @@ public interface LevelContainer { public static final char VERTICAL_DATA_DELIMITER = '\t'; public static final char DATA_DELIMITER = ','; - public static final ConcurrentMap threadAddDataMap = new ConcurrentHashMap(); - public static final ConcurrentMap threadGetDataMap = new ConcurrentHashMap(); - public static final ConcurrentMap threadSingleUpdateMap = new ConcurrentHashMap(); - public static final ConcurrentMap threadVerticalUpdateMap = new ConcurrentHashMap(); - public static final ConcurrentMap threadVerticalIndexesMap = new ConcurrentHashMap(); /**With this you can add data to the level container * * @param data actual data to add in a array of long format. diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index f4b034961..4b1db5d6f 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -25,10 +25,7 @@ import java.util.concurrent.Executors; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.handlers.LodDimensionFileHandler; -import com.seibel.lod.util.DetailDistanceUtil; -import com.seibel.lod.util.LevelPosUtil; -import com.seibel.lod.util.LodThreadFactory; -import com.seibel.lod.util.LodUtil; +import com.seibel.lod.util.*; import com.seibel.lod.wrappers.MinecraftWrapper; import net.minecraft.util.math.ChunkPos; @@ -446,12 +443,7 @@ public class LodDimension LodRegion region = getRegion(regionPosX, regionPosZ); if (region == null) return false; - ; - if(!LevelContainer.threadAddDataMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadAddDataMap.get(Thread.currentThread().getName()) == null)) - { - LevelContainer.threadAddDataMap.put(Thread.currentThread().getName(), new long[10]); - } - long[] dataArray = LevelContainer.threadAddDataMap.get(Thread.currentThread().getName()); + long[] dataArray = ThreadMapUtil.getSingleAddDataArray(); dataArray[0] = lodDataPoint; boolean nodeAdded = region.addData(detailLevel, posX, posZ, dataArray, serverQuality); // only save valid LODs to disk diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java index a8c69cf32..66657b963 100644 --- a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java @@ -2,10 +2,7 @@ package com.seibel.lod.objects; import com.seibel.lod.builders.LodBuilder; import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.util.DataPointUtil; -import com.seibel.lod.util.DetailDistanceUtil; -import com.seibel.lod.util.LevelPosUtil; -import com.seibel.lod.util.LodUtil; +import com.seibel.lod.util.*; public class SingleLevelContainer implements LevelContainer { @@ -35,20 +32,16 @@ public class SingleLevelContainer implements LevelContainer data[posX][posZ] = newData; return true; } + public long[] getData(int posX, int posZ){ - - if(!LevelContainer.threadGetDataMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()) == null)) - { - LevelContainer.threadGetDataMap.put(Thread.currentThread().getName(), new long[1]); - } - long[] dataArray = LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()); - + long[] dataArray = ThreadMapUtil.getSingleGetDataArray(); posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); //Improve this using a thread map to long[] dataArray[0] = data[posX][posZ]; return dataArray; } + private long getSingleData(int posX, int posZ){ posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); @@ -66,23 +59,35 @@ public class SingleLevelContainer implements LevelContainer public SingleLevelContainer(String inputString) { - + int tempIndex; + int shift = 0; int index = 0; - int lastIndex = 0; - - - index = inputString.indexOf(DATA_DELIMITER, 0); - detailLevel = (byte) Integer.parseInt(inputString.substring(0, index)); + int digit; + char currentChar; + long newData; + currentChar = inputString.charAt(index); + digit = Character.digit(currentChar,16); + detailLevel = (byte) digit; size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); - this.data = new long[size][size]; for (int x = 0; x < size; x++) { for (int z = 0; z < size; z++) { - lastIndex = index; - index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1); - data[x][z] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16); + newData = 0; + for(tempIndex = 0; tempIndex < 16; tempIndex++) + { + currentChar = inputString.charAt(index+tempIndex); + if(currentChar == ','){ + break; + } + shift = (15-tempIndex)*4; + digit = Character.digit(currentChar,16); + newData += ((long) (digit & 0xf)) << shift; + } + newData = newData >>> (shift); + data[x][z] = newData; + index = index + tempIndex; } } } @@ -90,11 +95,7 @@ public class SingleLevelContainer implements LevelContainer public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) { //We reset the array - if(!LevelContainer.threadGetDataMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()) == null)) - { - LevelContainer.threadGetDataMap.put(Thread.currentThread().getName(), new long[4]); - } - long[] dataToMerge = LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()); + long[] dataToMerge = ThreadMapUtil.getSingleUpdateArray(); int childPosX; int childPosZ; diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java index 7a685d051..1c26730d6 100644 --- a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java @@ -1,9 +1,9 @@ package com.seibel.lod.objects; - +/* import com.seibel.lod.util.DataPointUtil; import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; -/* + public class VerticalLevelContainer implements LevelContainer { @@ -75,6 +75,33 @@ public class VerticalLevelContainer implements LevelContainer return new SingleLevelContainer((byte) (getDetailLevel() - 1)); } + public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) + { + //We reset the array + if(!LevelContainer.threadGetDataMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()) == null)) + { + LevelContainer.threadGetDataMap.put(Thread.currentThread().getName(), new long[4]); + } + long[] dataToMerge = LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()); + + int childPosX; + int childPosZ; + long data = 0; + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + for (int x = 0; x <= 1; x++) + { + for (int z = 0; z <= 1; z++) + { + childPosX = 2 * posX + x; + childPosZ = 2 * posZ + z; + dataToMerge[2*z + x] = lowerLevelContainer.getData(childPosX, childPosZ)[0]; + } + } + data = DataPointUtil.mergeSingleData(dataToMerge); + addData(data,posX,posZ); + } + public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) { long[][][] updateTemps; diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index fe0f340d2..2ca05f865 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -46,11 +46,12 @@ public class DataPointUtil public static long createDataPoint(int height, int depth, int color, int lightValue, int generationMode) { - int alpha = ColorUtil.getAlpha(color); - int red = ColorUtil.getRed(color); - int green = ColorUtil.getGreen(color); - int blue = ColorUtil.getBlue(color); - return createDataPoint(alpha, red, green, blue, height, depth, lightValue, generationMode); + return createDataPoint( + ColorUtil.getAlpha(color), + ColorUtil.getRed(color), + ColorUtil.getGreen(color), + ColorUtil.getBlue(color), + height, depth, lightValue, generationMode); } public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightValue, int generationMode) @@ -62,15 +63,15 @@ public class DataPointUtil dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT; dataPoint += (height & HEIGHT_MASK) << HEIGHT_SHIFT; dataPoint += (depth & DEPTH_MASK) << DEPTH_SHIFT; - dataPoint += (depth & LIGHT_MASK) << LIGHT_SHIFT; - dataPoint += (depth & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; + dataPoint += (lightValue & LIGHT_MASK) << LIGHT_SHIFT; + dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT; return dataPoint; } public static short getHeight(long dataPoint) { - return (short) ((dataPoint >> HEIGHT_SHIFT) & HEIGHT_MASK); + return (short) ((dataPoint >>> HEIGHT_SHIFT) & HEIGHT_MASK); } public static short getDepth(long dataPoint) @@ -81,51 +82,48 @@ public class DataPointUtil public static short getAlpha(long dataPoint) { - return (short) ((dataPoint >> ALPHA_SHIFT) & ALPHA_MASK); + return (short) ((dataPoint >>> ALPHA_SHIFT) & ALPHA_MASK); } public static short getRed(long dataPoint) { - return (short) ((dataPoint >> RED_SHIFT) & RED_MASK); + return (short) ((dataPoint >>> RED_SHIFT) & RED_MASK); } public static short getGreen(long dataPoint) { - return (short) ((dataPoint >> GREEN_SHIFT) & GREEN_MASK); + return (short) ((dataPoint >>> GREEN_SHIFT) & GREEN_MASK); } public static short getBlue(long dataPoint) { - return (short) ((dataPoint >> BLUE_SHIFT) & BLUE_MASK); + return (short) ((dataPoint >>> BLUE_SHIFT) & BLUE_MASK); } public static byte getLightValue(long dataPoint) { - return (byte) ((dataPoint >> LIGHT_SHIFT) & LIGHT_MASK); + return (byte) ((dataPoint >>> LIGHT_SHIFT) & LIGHT_MASK); } public static byte getGenerationMode(long dataPoint) { - return (byte) ((dataPoint >> GEN_TYPE_SHIFT) & GEN_TYPE_MASK); + return (byte) ((dataPoint >>> GEN_TYPE_SHIFT) & GEN_TYPE_MASK); } public static boolean isItVoid(long dataPoint) { - return (((dataPoint >> VOID_SHIFT) & VOID_MASK) == 1); + return (((dataPoint >>> VOID_SHIFT) & VOID_MASK) == 1); } public static boolean doesItExist(long dataPoint) { - return (((dataPoint >> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1); + return (((dataPoint >>> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1); } public static int getColor(long dataPoint) { - int R = (getRed(dataPoint) << 16) & 0x00FF0000; - int G = (getGreen(dataPoint) << 8) & 0x0000FF00; - int B = getBlue(dataPoint) & 0x000000FF; - return 0xFF000000 | R | G | B; + return (int) ((dataPoint >>> COLOR_SHIFT) & COLOR_MASK); } public static String toString(long dataPoint) @@ -157,7 +155,6 @@ public class DataPointUtil int tempDepth = 0; int tempLight = 0; byte tempGenMode = DistanceGenerationMode.SERVER.complexity; - long newData = 0; for(long data : dataToMerge) { if (DataPointUtil.doesItExist(data)) diff --git a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java new file mode 100644 index 000000000..b9904276a --- /dev/null +++ b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java @@ -0,0 +1,73 @@ +package com.seibel.lod.util; + +import com.seibel.lod.objects.LevelContainer; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public class ThreadMapUtil +{ + public static final ConcurrentMap threadSingleAddDataMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadSingleGetDataMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadVerticalAddDataMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadVerticalGetDataMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadSingleUpdateMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadVerticalUpdateMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadVerticalIndexesMap = new ConcurrentHashMap(); + + public static long[] getSingleAddDataArray(){ + if(!threadSingleAddDataMap.containsKey(Thread.currentThread().getName()) || (threadSingleAddDataMap.get(Thread.currentThread().getName()) == null)) + { + threadSingleAddDataMap.put(Thread.currentThread().getName(), new long[1]); + } + return threadSingleAddDataMap.get(Thread.currentThread().getName()); + } + + public static long[] getSingleGetDataArray(){ + if(!threadSingleGetDataMap.containsKey(Thread.currentThread().getName()) || (threadSingleGetDataMap.get(Thread.currentThread().getName()) == null)) + { + threadSingleGetDataMap.put(Thread.currentThread().getName(), new long[1]); + } + return threadSingleGetDataMap.get(Thread.currentThread().getName()); + } + + public static long[] getSingleUpdateArray(){ + if(!threadSingleUpdateMap.containsKey(Thread.currentThread().getName()) || (threadSingleUpdateMap.get(Thread.currentThread().getName()) == null)) + { + threadSingleUpdateMap.put(Thread.currentThread().getName(), new long[4]); + } + return threadSingleUpdateMap.get(Thread.currentThread().getName()); + } + + public static long[] addVerticalDataArray(){ + if(!threadVerticalAddDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMap.get(Thread.currentThread().getName()) == null)) + { + threadVerticalAddDataMap.put(Thread.currentThread().getName(), new long[16]); + } + return threadVerticalAddDataMap.get(Thread.currentThread().getName()); + } + + public static long[] getVerticalGetDataArray(){ + if(!threadVerticalGetDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalGetDataMap.get(Thread.currentThread().getName()) == null)) + { + threadVerticalGetDataMap.put(Thread.currentThread().getName(), new long[16]); + } + return threadVerticalGetDataMap.get(Thread.currentThread().getName()); + } + + public static long[][][] getVerticalUpdateArray(){ + if(!threadVerticalUpdateMap.containsKey(Thread.currentThread().getName()) || (threadVerticalUpdateMap.get(Thread.currentThread().getName()) == null)) + { + threadVerticalUpdateMap.put(Thread.currentThread().getName(), new long[4][4][16]); + } + return threadVerticalUpdateMap.get(Thread.currentThread().getName()); + } + + public static int[] getVerticalIndexesArray(){ + if(!threadVerticalIndexesMap.containsKey(Thread.currentThread().getName()) || (threadVerticalIndexesMap.get(Thread.currentThread().getName()) == null)) + { + threadVerticalIndexesMap.put(Thread.currentThread().getName(), new int[4]); + } + return threadVerticalIndexesMap.get(Thread.currentThread().getName()); + } +}