Skip to content

Commit

Permalink
Revert hash calculation and fix buffer overflow
Browse files Browse the repository at this point in the history
  • Loading branch information
Johann Bernhardt committed Dec 19, 2021
1 parent 76ad902 commit 5c1b5af
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 43 deletions.
7 changes: 2 additions & 5 deletions src/main/java/com/sinthoras/visualprospecting/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,8 @@ public static int coordChunkToBlock(int chunkCoord) {
return chunkCoord < 0 ? -((-chunkCoord) << 4) : chunkCoord << 4;
}

public static int chunkCoordsToKey(int chunkX, int chunkZ) {
// Compare net.minecraft.world.ChunkCoordIntPair.hashCode()
int i = 1664525 * chunkX + 1013904223;
int j = 1664525 * (chunkZ ^ -559038737) + 1013904223;
return i ^ j;
public static long chunkCoordsToKey(int chunkX, int chunkZ) {
return (((long)chunkX) << 32) | (chunkZ & 0xffffffffL);
}

public static int mapToCenterOreChunkCoord(final int chunkCoord) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.sinthoras.visualprospecting.Utils;
import com.sinthoras.visualprospecting.database.veintypes.VeinType;
import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;

Expand All @@ -18,31 +19,28 @@ public enum UpdateResult {
New
}

private final Map<Integer, OreVeinPosition> oreChunks = new HashMap<>();
private final Map<Integer, UndergroundFluidPosition> undergroundFluids = new HashMap<>();
private final Set<Integer> changedOrNewOreChunks = new HashSet<>();
private final Set<Integer> changedOrNewUndergroundFluids = new HashSet<>();
private boolean oreChunksNeedsSaving = false;
private boolean undergroundFluidsNeedsSaving = false;
private final Map<ChunkCoordIntPair, OreVeinPosition> oreChunks = new HashMap<>();
private final Map<ChunkCoordIntPair, UndergroundFluidPosition> undergroundFluids = new HashMap<>();
private final Set<ChunkCoordIntPair> changedOrNewOreChunks = new HashSet<>();
private final Set<ChunkCoordIntPair> changedOrNewUndergroundFluids = new HashSet<>();
public final int dimensionId;

public DimensionCache(int dimensionId) {
this.dimensionId = dimensionId;
}

public ByteBuffer saveOreChunks() {
if(oreChunksNeedsSaving) {
final ByteBuffer byteBuffer = ByteBuffer.allocate(changedOrNewOreChunks.size() * (Long.BYTES + Short.BYTES));
for (OreVeinPosition oreVeinPosition : oreChunks.values()) {
if(changedOrNewOreChunks.isEmpty() == false) {
final ByteBuffer byteBuffer = ByteBuffer.allocate(changedOrNewOreChunks.size() * (2 * Integer.BYTES + Short.BYTES));
changedOrNewOreChunks.stream().map(oreChunks::get).forEach(oreVeinPosition -> {
byteBuffer.putInt(oreVeinPosition.chunkX);
byteBuffer.putInt(oreVeinPosition.chunkZ);
short veinTypeId = VeinTypeCaching.getVeinTypeId(oreVeinPosition.veinType);
if(oreVeinPosition.isDepleted()) {
veinTypeId |= 0x8000;
}
byteBuffer.putShort(veinTypeId);
}
oreChunksNeedsSaving = false;
});
changedOrNewOreChunks.clear();
byteBuffer.flip();
return byteBuffer;
Expand All @@ -51,19 +49,18 @@ public ByteBuffer saveOreChunks() {
}

public ByteBuffer saveUndergroundFluids() {
if(undergroundFluidsNeedsSaving) {
if(changedOrNewUndergroundFluids.isEmpty() == false) {
final ByteBuffer byteBuffer = ByteBuffer.allocate(changedOrNewUndergroundFluids.size() * (Long.BYTES + Integer.BYTES * (1 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ)));
for (UndergroundFluidPosition undergroundFluid : undergroundFluids.values()) {
byteBuffer.putInt(undergroundFluid.chunkX);
byteBuffer.putInt(undergroundFluid.chunkZ);
byteBuffer.putInt(undergroundFluid.fluid.getID());
changedOrNewUndergroundFluids.stream().map(undergroundFluids::get).forEach(undergroundFluidPosition -> {
byteBuffer.putInt(undergroundFluidPosition.chunkX);
byteBuffer.putInt(undergroundFluidPosition.chunkZ);
byteBuffer.putInt(undergroundFluidPosition.fluid.getID());
for(int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) {
for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) {
byteBuffer.putInt(undergroundFluid.chunks[offsetChunkX][offsetChunkZ]);
byteBuffer.putInt(undergroundFluidPosition.chunks[offsetChunkX][offsetChunkZ]);
}
}
}
undergroundFluidsNeedsSaving = false;
});
changedOrNewUndergroundFluids.clear();
byteBuffer.flip();
return byteBuffer;
Expand Down Expand Up @@ -98,65 +95,60 @@ public void loadCache(ByteBuffer oreChunksBuffer, ByteBuffer undergroundFluidsBu
}
}

private int getOreVeinKey(int chunkX, int chunkZ) {
return Utils.chunkCoordsToKey(Utils.mapToCenterOreChunkCoord(chunkX), Utils.mapToCenterOreChunkCoord(chunkZ));
private ChunkCoordIntPair getOreVeinKey(int chunkX, int chunkZ) {
return new ChunkCoordIntPair(Utils.mapToCenterOreChunkCoord(chunkX), Utils.mapToCenterOreChunkCoord(chunkZ));
}

public UpdateResult putOreVein(final OreVeinPosition oreVeinPosition) {
final int key = getOreVeinKey(oreVeinPosition.chunkX, oreVeinPosition.chunkZ);
final ChunkCoordIntPair key = getOreVeinKey(oreVeinPosition.chunkX, oreVeinPosition.chunkZ);
if(oreChunks.containsKey(key) == false) {
oreChunks.put(key, oreVeinPosition);
changedOrNewOreChunks.add(key);
oreChunksNeedsSaving = true;
return UpdateResult.New;
}
final OreVeinPosition storedOreVeinPosition = oreChunks.get(key);
if(storedOreVeinPosition.veinType != oreVeinPosition.veinType) {
oreChunks.put(key, oreVeinPosition.joinDepletedState(storedOreVeinPosition));
changedOrNewOreChunks.add(key);
oreChunksNeedsSaving = true;
return UpdateResult.New;
}
return UpdateResult.AlreadyKnown;
}

public void toggleOreVein(int chunkX, int chunkZ) {
final int key = getOreVeinKey(chunkX, chunkZ);
final ChunkCoordIntPair key = getOreVeinKey(chunkX, chunkZ);
if(oreChunks.containsKey(key)) {
oreChunks.get(key).toggleDepleted();
changedOrNewOreChunks.add(key);
}
changedOrNewOreChunks.add(key);
oreChunksNeedsSaving = true;
}

public OreVeinPosition getOreVein(int chunkX, int chunkZ) {
final int key = getOreVeinKey(chunkX, chunkZ);
final ChunkCoordIntPair key = getOreVeinKey(chunkX, chunkZ);
return oreChunks.getOrDefault(key, new OreVeinPosition(dimensionId, chunkX, chunkZ, VeinType.NO_VEIN, true));
}

private int getUndergroundFluidKey(int chunkX, int chunkZ) {
return Utils.chunkCoordsToKey(Utils.mapToCornerUndergroundFluidChunkCoord(chunkX), Utils.mapToCornerUndergroundFluidChunkCoord(chunkZ));
private ChunkCoordIntPair getUndergroundFluidKey(int chunkX, int chunkZ) {
return new ChunkCoordIntPair(Utils.mapToCornerUndergroundFluidChunkCoord(chunkX), Utils.mapToCornerUndergroundFluidChunkCoord(chunkZ));
}

public UpdateResult putUndergroundFluid(final UndergroundFluidPosition undergroundFluid) {
final int key = getUndergroundFluidKey(undergroundFluid.chunkX, undergroundFluid.chunkZ);
final ChunkCoordIntPair key = getUndergroundFluidKey(undergroundFluid.chunkX, undergroundFluid.chunkZ);
if(undergroundFluids.containsKey(key) == false) {
changedOrNewUndergroundFluids.add(key);
undergroundFluids.put(key, undergroundFluid);
undergroundFluidsNeedsSaving = true;
return UpdateResult.New;
}
else if(undergroundFluids.get(key).equals(undergroundFluid) == false) {
changedOrNewUndergroundFluids.add(key);
undergroundFluids.put(key, undergroundFluid);
undergroundFluidsNeedsSaving = true;
return UpdateResult.Updated;
}
return UpdateResult.AlreadyKnown;
}

public UndergroundFluidPosition getUndergroundFluid(int chunkX, int chunkZ) {
final int key = getUndergroundFluidKey(chunkX, chunkZ);
final ChunkCoordIntPair key = getUndergroundFluidKey(chunkX, chunkZ);
return undergroundFluids.getOrDefault(key, UndergroundFluidPosition.getNotProspected(dimensionId, chunkX, chunkZ));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void processMinecraftChunk(final NBTCompound chunkRoot) {
}
}

public void cleanUpWithNeighbors(final Map<Integer, Integer> veinChunkY) {
public void cleanUpWithNeighbors(final Map<Long, Integer> veinChunkY) {
final OreVeinPosition[] neighbors = new OreVeinPosition[] {
ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ + 3),
ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ + 3),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
public class DimensionAnalysis {

public final int dimensionId;
private final Map<Integer, DetailedChunkAnalysis> chunksForSecondIdentificationPass = new ConcurrentHashMap<>();

public DimensionAnalysis(int dimensionId) {
this.dimensionId = dimensionId;
Expand All @@ -29,16 +28,17 @@ private interface IChunkHandler {
void processChunk(NBTCompound root, int chunkX, int chunkZ);
}


public void processMinecraftWorld(MinecraftWorld world) throws IOException {
final Map<Integer, Integer> veinBlockY = new ConcurrentHashMap<>();
final Map<Long, Integer> veinBlockY = new ConcurrentHashMap<>();
final List<File> regionFiles = world.getAllRegionFiles(dimensionId);
final long dimensionSizeMB = regionFiles.stream().mapToLong(File::length).sum() >> 20;

if (dimensionSizeMB <= Config.maxDimensionSizeMBForFastScanning) {
AnalysisProgressTracker.announceFastDimension(dimensionId);
AnalysisProgressTracker.setNumberOfRegionFiles(regionFiles.size());

final Map<Long, DetailedChunkAnalysis> chunksForSecondIdentificationPass = new ConcurrentHashMap<>();

regionFiles.parallelStream().forEach(regionFile -> {
executeForEachGeneratedOreChunk(regionFile, (root, chunkX, chunkZ) -> {
final ChunkAnalysis chunk = new ChunkAnalysis();
Expand Down

0 comments on commit 5c1b5af

Please sign in to comment.