Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concurrency fix #665

Merged
merged 2 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/main/java/gui/GuiMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -473,4 +473,8 @@ public RegionImageHandler getRegionHandler() {
public void setChunkState(Coordinate2D coords, ChunkImageState state) {
regionHandler.setChunkState(coords, state);
}

public Bounds getBounds() {
return bounds;
}
}
2 changes: 1 addition & 1 deletion src/main/java/gui/ZoomBehaviour.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

public interface ZoomBehaviour {
double initialBlocksPerPixel = 1.0;
double maxBlocksPerPixel = 64;
double maxBlocksPerPixel = 256;
double minBlocksPerPixel = 1.0 / 16.0;

double zoomInMultiplier = 2;
Expand Down
11 changes: 6 additions & 5 deletions src/main/java/gui/images/RegionImage.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ public RegionImage(Path path, Coordinate2D coords) {
}

private RegionImage(WritableImage image, Path path, Coordinate2D coords) {
this.coordinates = coords;
this.currentSize = MIN_SIZE;
this.targetSize = MIN_SIZE;
this.path = path;

this.image = image;
this.buffer = new byte[16 * 16 * 4];
this.saved = true;
this.coordinates = coords;

chunkOverlay = new WritableImage(Region.REGION_SIZE, Region.REGION_SIZE);

Expand Down Expand Up @@ -94,7 +94,7 @@ public static RegionImage of(Path directoryPath, Coordinate2D coordinate) {
WritableImage image = loadFromFile(directoryPath, coordinate, MIN_SIZE);

return new RegionImage(image, directoryPath, coordinate);
} catch (IOException e) {
} catch (Exception e) {
return new RegionImage(directoryPath, coordinate);
}
}
Expand Down Expand Up @@ -201,8 +201,8 @@ public Image getImage() {
}

public void drawChunk(Coordinate2D local, Image chunkImage) {
lastUpdated = System.currentTimeMillis();
saved = false;
this.lastUpdated = System.currentTimeMillis();
this.saved = false;

if (targetSize < SIZE || currentSize < SIZE) {
targetSize = SIZE;
Expand Down Expand Up @@ -233,7 +233,6 @@ public void save() throws IOException {
if (saved) {
return;
}
saved = true;

File f = getFile(path, NORMAL_PREFIX, coordinates);
BufferedImage img = SwingFXUtils.fromFXImage(image, null);
Expand All @@ -242,6 +241,8 @@ public void save() throws IOException {
img = resize(img, MIN_SIZE);
f = getFile(path, SMALL_PREFIX, coordinates);
ImageIO.write(img, "png", f);

saved = true;
}

public static File getFile(Path p, String prefix, Coordinate2D coords) {
Expand Down
65 changes: 17 additions & 48 deletions src/main/java/gui/images/RegionImageHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ public void drawChunk(CoordinateDim2D coordinate, Map<ImageMode, Image> imageMap
}

Coordinate2D region = coordinate.chunkToRegion();
RegionImages images = regions.computeIfAbsent(region, (coordinate2D -> loadRegion(region)));
RegionImages images = regions.computeIfAbsent(region,
coordinate2D -> RegionImages.loadRegion(activeDimension, region)
);

Coordinate2D local = coordinate.toRegionLocal();

Expand Down Expand Up @@ -116,16 +118,6 @@ public void markChunkSaved(CoordinateDim2D coordinate) {
setChunkState(coordinate, ChunkImageState.SAVED);
}

private RegionImages loadRegion(Coordinate2D coordinate) {
return RegionImages.of(activeDimension, coordinate);
}

private void allowResample(Map<Coordinate2D, RegionImages> regions, Dimension activeDimension) {
regions.forEach((coordinate, image) -> {
attempt(() -> image.allowResample());
});
}

private void save(Map<Coordinate2D, RegionImages> regions, Dimension dim) {
// if shutdown is called, wait for saving to complete
if (isSaving) {
Expand All @@ -151,32 +143,24 @@ public void save() {
save(this.regions, this.activeDimension);
}

public void allowResample() {
allowResample(this.regions, this.activeDimension);
}

private void unload() {
this.regions = new ConcurrentHashMap<>();
}

/**
* Searches for all region files in a directory to load them in.
*/
private void load() {
Map<Coordinate2D, RegionImages> regionMap = regions;

private void loadFromFile() {
new Thread(() -> attemptQuiet(() -> {
for (ImageMode mode : ImageMode.values()) {
Files.walk(dimensionPath(this.activeDimension, mode), 1)
.limit(3200)
.forEach(image -> attempt(() -> load(regionMap, mode, image)));
}
// walk one of the modes, check for the others if we find one
Files.walk(dimensionPath(this.activeDimension, ImageMode.NORMAL), 1)
.limit(32000)
.forEach(image -> attempt(() -> loadFromFile(regions, this.activeDimension, image)));
})).start();
}

private void load(Map<Coordinate2D, RegionImages> regionMap, ImageMode mode, Path image) {
if (!image.toString().toLowerCase().endsWith("png") || image.getFileName().startsWith(
SMALL_PREFIX)) {
private static void loadFromFile(Map<Coordinate2D, RegionImages> regions, Dimension dim, Path image) {
if (!image.toString().toLowerCase().endsWith("png") || image.getFileName().startsWith(SMALL_PREFIX)) {
return;
}

Expand All @@ -186,8 +170,7 @@ private void load(Map<Coordinate2D, RegionImages> regionMap, ImageMode mode, Pat
int z = Integer.parseInt(parts[2]);
Coordinate2D regionCoordinate = new Coordinate2D(x, z);

Path p = image.getParent();
regionMap.computeIfAbsent(regionCoordinate, k -> new RegionImages(p, regionCoordinate)).set(mode, p);
regions.computeIfAbsent(regionCoordinate, coord -> RegionImages.loadRegion(dim, coord));
}

public void setDimension(Dimension dimension) {
Expand All @@ -201,7 +184,7 @@ public void setDimension(Dimension dimension) {
}

this.activeDimension = dimension;
load();
loadFromFile();
}

static Path dimensionPath(Dimension dim) {
Expand Down Expand Up @@ -286,26 +269,19 @@ public void resetRegion(Coordinate2D region) {
}

class RegionImages {
Coordinate2D coordinate;
RegionImage normal;
RegionImage caves;
final RegionImage normal;
final RegionImage caves;

public RegionImages(RegionImage normal, RegionImage caves) {
public RegionImages(Coordinate2D coordinate, RegionImage normal, RegionImage caves) {
this.normal = normal;
this.caves = caves;
}

public RegionImages(Path p, Coordinate2D coordinate2D) {
normal = new RegionImage(p, coordinate2D);
caves = new RegionImage(p, coordinate2D);
coordinate = coordinate2D;
}

public static RegionImages of(Dimension dimension, Coordinate2D coordinate) {
public static RegionImages loadRegion(Dimension dimension, Coordinate2D coordinate) {
RegionImage normal = RegionImage.of(RegionImageHandler.dimensionPath(dimension, ImageMode.NORMAL), coordinate);
RegionImage caves = RegionImage.of(RegionImageHandler.dimensionPath(dimension, ImageMode.CAVES), coordinate);

return new RegionImages(normal, caves);
return new RegionImages(coordinate, normal, caves);
}

public RegionImage getImage(ImageMode mode) {
Expand All @@ -327,13 +303,6 @@ public void save() throws IOException {
caves.save();
}

public void set(ImageMode mode, Path image) {
switch (mode) {
case NORMAL -> normal = RegionImage.of(image, coordinate);
case CAVES -> caves = RegionImage.of(image, coordinate);
};
}

public boolean updateSize(boolean isVisible, ImageMode mode, double blocksPerPixel) {
boolean shouldResize = caves.setTargetSize(isVisible && mode == ImageMode.CAVES, blocksPerPixel);
shouldResize |= normal.setTargetSize(isVisible && mode == ImageMode.NORMAL, blocksPerPixel);
Expand Down
Loading