Skip to content
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
20 changes: 11 additions & 9 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {
}

group = "fr.sukikui.biomemap"
version = "0.1.4"
version = "0.1.5"

def minecraftVersion = '26.1.2'
def paperApiVersion = "${minecraftVersion}.build.65-stable"
Expand Down Expand Up @@ -62,15 +62,17 @@ test {
}

processResources {
def resourceProperties = [
NAME: rootProject.name,
VERSION: project.version.toString(),
PACKAGE: rootProject.group.toString(),
AUTHOR: "Sukikui",
DESCRIPTION: "Lightweight PaperMC plugin exporting dominant biomes from a selected area to JSON",
API_VERSION: minecraftVersion
]
inputs.properties(resourceProperties)
filesMatching("**/plugin.yml") {
expand(
NAME: rootProject.name,
VERSION: version,
PACKAGE: rootProject.group.toString(),
AUTHOR: "Sukikui",
DESCRIPTION: "Lightweight PaperMC plugin exporting dominant biomes from a selected area to JSON",
API_VERSION: minecraftVersion
)
expand(resourceProperties)
}
}

Expand Down
31 changes: 16 additions & 15 deletions src/main/java/fr/sukikui/biomemap/command/BiomeMapCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import fr.sukikui.biomemap.export.AsyncBiomeExportTask;
import fr.sukikui.biomemap.export.BiomeExporter;
import fr.sukikui.biomemap.util.GridMath;
import fr.sukikui.biomemap.util.ProgressFormatter;
import java.io.File;
import java.nio.file.Path;
Expand Down Expand Up @@ -31,8 +32,7 @@
@SuppressFBWarnings("EI_EXPOSE_REP2")
public final class BiomeMapCommand implements CommandExecutor, TabCompleter {

private static final int CHUNK_SIZE = 16;
private static final int MIN_CELL_SIZE = 8;
private static final int MIN_CELL_SIZE = 4;
private static final String CHAT_PREFIX = "§8[§b§lBiomeMap§8] §r";
private static final int PLAYER_STATUS_MAP_MAX_WIDTH = 28;
private static final int PLAYER_STATUS_MAP_MAX_HEIGHT = 10;
Expand Down Expand Up @@ -173,14 +173,11 @@ public boolean onCommand(CommandSender sender, Command command, String label, St

long totalCells = (long) width * height;
long totalChunks;
if (cellSize >= CHUNK_SIZE) {
int chunksPerCell = Math.max(1, cellSize / CHUNK_SIZE);
totalChunks = totalCells * (long) chunksPerCell * chunksPerCell;
} else {
int cellsPerChunk = CHUNK_SIZE / cellSize;
int chunkColumns = Math.max(1, (width + cellsPerChunk - 1) / cellsPerChunk);
int chunkRows = Math.max(1, (height + cellsPerChunk - 1) / cellsPerChunk);
totalChunks = (long) chunkColumns * chunkRows;
try {
totalChunks = GridMath.countChunksForGrid(originX, originZ, width, height, cellSize);
} catch (IllegalArgumentException ex) {
sendError(sender, "Selection is too large to export.");
return true;
}
notifyInfo(
sender,
Expand Down Expand Up @@ -268,7 +265,7 @@ public List<String> onTabComplete(
}
return Collections.emptyList();
} else if (args.length >= 6) {
return List.of("8", "16", "32", "64", "128", "256", "preview");
return List.of("4", "8", "16", "32", "64", "128", "256", "preview");
}
return Collections.emptyList();
}
Expand Down Expand Up @@ -410,14 +407,18 @@ private int alignCellSize(int requestedSize) {
if (requestedSize <= MIN_CELL_SIZE) {
return MIN_CELL_SIZE;
}
if (requestedSize < CHUNK_SIZE) {
return CHUNK_SIZE;
if (requestedSize < GridMath.CHUNK_SIZE) {
int alignedSize = MIN_CELL_SIZE;
while (alignedSize < GridMath.CHUNK_SIZE && requestedSize > alignedSize) {
alignedSize *= 2;
}
return alignedSize;
}
int remainder = requestedSize % CHUNK_SIZE;
int remainder = requestedSize % GridMath.CHUNK_SIZE;
if (remainder == 0) {
return requestedSize;
}
return requestedSize + (CHUNK_SIZE - remainder);
return requestedSize + (GridMath.CHUNK_SIZE - remainder);
}

private void notifyInfo(CommandSender sender, String senderMessage, String logMessage) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import fr.sukikui.biomemap.export.BiomeExporter.BiomeCell;
import fr.sukikui.biomemap.export.BiomeExporter.BiomeMapExport;
import fr.sukikui.biomemap.export.BiomeExporter.Point;
import fr.sukikui.biomemap.util.GridMath;
import fr.sukikui.biomemap.util.ProgressFormatter;
import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -42,7 +43,7 @@
@SuppressFBWarnings("EI_EXPOSE_REP2")
public final class AsyncBiomeExportTask extends BukkitRunnable {

private static final int CHUNK_SIZE = 16;
private static final int CHUNK_SIZE = GridMath.CHUNK_SIZE;
private static final String CHAT_PREFIX = "§8[§b§lBiomeMap§8] §r";
private static final long FIRST_PROGRESS_HEARTBEAT_MS = TimeUnit.SECONDS.toMillis(10);
private static final long PROGRESS_HEARTBEAT_MS = TimeUnit.MINUTES.toMillis(5);
Expand Down Expand Up @@ -149,15 +150,10 @@ public AsyncBiomeExportTask(
this.subChunkSampling = cellSize < CHUNK_SIZE;
this.chunksPerCell = subChunkSampling ? 1 : Math.max(1, cellSize / CHUNK_SIZE);
this.cellsPerChunk = subChunkSampling ? Math.max(1, CHUNK_SIZE / cellSize) : 1;
if (subChunkSampling) {
this.chunkColumns = Math.max(1, (width + cellsPerChunk - 1) / cellsPerChunk);
this.chunkRows = Math.max(1, (height + cellsPerChunk - 1) / cellsPerChunk);
} else {
this.chunkColumns = width * chunksPerCell;
this.chunkRows = height * chunksPerCell;
}
this.chunkStartX = Math.floorDiv(originX, CHUNK_SIZE);
this.chunkStartZ = Math.floorDiv(originZ, CHUNK_SIZE);
this.chunkColumns = GridMath.countChunksForCells(originX, width, cellSize);
this.chunkRows = GridMath.countChunksForCells(originZ, height, cellSize);
this.chunkStartX = GridMath.chunkStart(originX);
this.chunkStartZ = GridMath.chunkStart(originZ);
this.chunkBiomes = new String[chunkColumns * chunkRows];
this.totalChunks = chunkBiomes.length;
this.chunkCompletedMap = new boolean[chunkBiomes.length];
Expand Down
47 changes: 47 additions & 0 deletions src/main/java/fr/sukikui/biomemap/util/GridMath.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package fr.sukikui.biomemap.util;

/**
* Shared grid/chunk calculations for biome exports.
*/
public final class GridMath {

public static final int CHUNK_SIZE = 16;

private GridMath() {
}

/**
* Counts how many chunks are touched by a cell axis.
*/
public static int countChunksForCells(int origin, int cellCount, int cellSize) {
if (cellCount <= 0 || cellSize <= 0) {
throw new IllegalArgumentException("Cell count and size must be positive");
}

long minChunk = Math.floorDiv((long) origin, CHUNK_SIZE);
long maxBlock = (long) origin + ((long) cellCount * cellSize) - 1L;
long maxChunk = Math.floorDiv(maxBlock, CHUNK_SIZE);
long span = maxChunk - minChunk + 1L;
if (span > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Selection spans too many chunks");
}
return Math.max(1, (int) span);
}

/**
* Counts how many chunks are touched by a cell grid.
*/
public static long countChunksForGrid(
int originX, int originZ, int width, int height, int cellSize) {
long columns = countChunksForCells(originX, width, cellSize);
long rows = countChunksForCells(originZ, height, cellSize);
return columns * rows;
}

/**
* Returns the chunk coordinate containing the provided block coordinate.
*/
public static int chunkStart(int origin) {
return Math.floorDiv(origin, CHUNK_SIZE);
}
}
33 changes: 33 additions & 0 deletions src/test/java/fr/sukikui/biomemap/util/GridMathTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package fr.sukikui.biomemap.util;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import org.junit.jupiter.api.Test;

class GridMathTest {

@Test
void countsAlignedSubChunkCellsInsideOneChunk() {
assertEquals(1, GridMath.countChunksForCells(0, 4, 4));
assertEquals(1, GridMath.countChunksForCells(0, 2, 8));
}

@Test
void countsOffsetSubChunkCellsCrossingChunkBoundary() {
assertEquals(2, GridMath.countChunksForCells(8, 2, 8));
assertEquals(2, GridMath.countChunksForCells(12, 3, 4));
}

@Test
void countsLargeCellsAcrossMultipleChunks() {
assertEquals(4, GridMath.countChunksForCells(0, 2, 32));
assertEquals(6, GridMath.countChunksForCells(-32, 3, 32));
}

@Test
void rejectsInvalidCellGrid() {
assertThrows(IllegalArgumentException.class, () -> GridMath.countChunksForCells(0, 0, 4));
assertThrows(IllegalArgumentException.class, () -> GridMath.countChunksForCells(0, 1, 0));
}
}
Loading