Skip to content

Commit

Permalink
Implement chunk filters
Browse files Browse the repository at this point in the history
  • Loading branch information
pop4959 committed Feb 4, 2024
1 parent 62c437d commit 2a58fda
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 31 deletions.
18 changes: 8 additions & 10 deletions common/src/main/java/org/popcraft/chunky/command/TrimCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.popcraft.chunky.Chunky;
import org.popcraft.chunky.Selection;
import org.popcraft.chunky.nbt.CompoundTag;
import org.popcraft.chunky.nbt.LongTag;
import org.popcraft.chunky.nbt.Tag;
import org.popcraft.chunky.nbt.TagType;
import org.popcraft.chunky.nbt.util.ChunkFilter;
import org.popcraft.chunky.nbt.util.RegionFile;
import org.popcraft.chunky.platform.Sender;
import org.popcraft.chunky.platform.World;
Expand Down Expand Up @@ -103,7 +105,7 @@ public void execute(final Sender sender, final CommandArguments arguments) {
.filter(file -> ChunkCoordinate.fromRegionFile(file.getFileName().toString()).isPresent())
.toList();
final long totalRegions = regions.size();
for (final Path region: regions) {
for (final Path region : regions) {
if (trimTask.isCancelled()) {
break;
}
Expand All @@ -112,7 +114,7 @@ public void execute(final Sender sender, final CommandArguments arguments) {
if (!trimTask.isCancelled() && !chunky.getConfig().isSilent()) {
final long currentTime = System.currentTimeMillis();
final boolean updateIntervalElapsed = ((currentTime - updateTime.get()) / 1e3) > chunky.getConfig().getUpdateInterval();
if (updateIntervalElapsed) {
if (updateIntervalElapsed || finishedRegions.get() == totalRegions) {
sender.sendMessagePrefixed(TranslationKey.TASK_TRIM_UPDATE, selection.world().getName(), finishedRegions.get(), String.format("%.2f", 100f * finishedRegions.get() / totalRegions));
updateTime.set(currentTime);
}
Expand Down Expand Up @@ -186,7 +188,7 @@ private int trimRegion(final World world, final String regionFileName, final Sha
final Path entitiesPath = world.getEntitiesDirectory().map(region -> region.resolve(regionFileName)).orElse(null);
int marked = 0;
int deleted = 0;
final RegionFile regionData = inhabitedTimeCheck ? new RegionFile(regionPath.toFile()) : null;
final RegionFile regionData = inhabitedTimeCheck ? new RegionFile(regionPath.toFile(), ChunkFilter.of(TagType.LONG, "InhabitedTime")) : null;
try (final RandomAccessFile regionFile = new RandomAccessFile(regionPath.toFile(), "rw");
final RandomAccessFile poiFile = poiPath == null || Files.notExists(poiPath) ? null : new RandomAccessFile(poiPath.toFile(), "rw");
final RandomAccessFile entitiesFile = entitiesPath == null || Files.notExists(entitiesPath) ? null : new RandomAccessFile(entitiesPath.toFile(), "rw")) {
Expand All @@ -209,12 +211,8 @@ private int trimRegion(final World world, final String regionFileName, final Sha
}
final boolean trimInhabited = regionData == null || regionData.getChunk(offsetChunkX, offsetChunkZ)
.map(chunk -> {
final CompoundTag compoundTag = chunk.getData();
if (compoundTag == null) {
return true;
}
final LongTag inhabited = compoundTag.getLong("InhabitedTime").orElse(null);
if (inhabited == null) {
final Tag tag = chunk.getData();
if (!(tag instanceof final LongTag inhabited)) {
return true;
}
return inhabited.value() <= inhabitedTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import org.popcraft.chunky.Chunky;
import org.popcraft.chunky.Selection;
import org.popcraft.chunky.nbt.StringTag;
import org.popcraft.chunky.nbt.TagType;
import org.popcraft.chunky.nbt.util.ChunkFilter;
import org.popcraft.chunky.nbt.util.RegionFile;
import org.popcraft.chunky.util.ChunkCoordinate;
import org.popcraft.chunky.util.Hilbert;
Expand All @@ -16,6 +18,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;
Expand Down Expand Up @@ -109,14 +112,16 @@ public boolean process() {
.orElseThrow(IllegalStateException::new);
final int regionX = regionCoordinate.x();
final int regionZ = regionCoordinate.z();
final RegionFile regionFile = new RegionFile(region.toFile());
final RegionFile regionFile = new RegionFile(region.toFile(), ChunkFilter.of(TagType.STRING, "Status"));
for (final ChunkCoordinate offset : Hilbert.chunkCoordinateOffsets()) {
final ChunkCoordinate chunkCoordinate = new ChunkCoordinate((regionX << 5) + offset.x(), (regionZ << 5) + offset.z());
if (chunkCoordinate.x() < minChunkX || chunkCoordinate.x() > maxChunkX || chunkCoordinate.z() < minChunkZ || chunkCoordinate.z() > maxChunkZ) {
continue;
}
regionFile.getChunk(chunkCoordinate.x(), chunkCoordinate.z()).ifPresent(chunk -> {
final boolean generated = chunk.getData().getString("Status")
final boolean generated = Optional.ofNullable(chunk.getData())
.filter(StringTag.class::isInstance)
.map(StringTag.class::cast)
.map(StringTag::value)
.map(status -> "minecraft:full".equals(status) || "full".equals(status))
.orElse(false);
Expand Down
30 changes: 25 additions & 5 deletions nbt/src/main/java/org/popcraft/chunky/nbt/util/Chunk.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,41 @@
package org.popcraft.chunky.nbt.util;

import org.popcraft.chunky.nbt.CompoundTag;
import org.popcraft.chunky.nbt.Tag;

public final class Chunk {
private CompoundTag data;
private int x;
private int z;
private Tag data;
private long lastModified;

public Chunk(final CompoundTag data, final long lastModified) {
public Chunk(final int x, final int z, final Tag data, final long lastModified) {
this.x = x;
this.z = z;
this.data = data;
this.lastModified = lastModified;
}

public CompoundTag getData() {
public Tag getData() {
return data;
}

public void setData(CompoundTag data) {
public int getX() {
return x;
}

public void setX(int x) {
this.x = x;
}

public int getZ() {
return z;
}

public void setZ(int z) {
this.z = z;
}

public void setData(Tag data) {
this.data = data;
}

Expand Down
23 changes: 23 additions & 0 deletions nbt/src/main/java/org/popcraft/chunky/nbt/util/ChunkFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.popcraft.chunky.nbt.util;

public final class ChunkFilter {
private final byte type;
private final String name;

private ChunkFilter(final byte type, final String name) {
this.type = type;
this.name = name;
}

public static ChunkFilter of(final byte type, final String name) {
return new ChunkFilter(type, name);
}

public byte getType() {
return type;
}

public String getName() {
return name;
}
}
46 changes: 32 additions & 14 deletions nbt/src/main/java/org/popcraft/chunky/nbt/util/RegionFile.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.popcraft.chunky.nbt.util;

import org.popcraft.chunky.nbt.CompoundTag;
import org.popcraft.chunky.nbt.IntTag;
import org.popcraft.chunky.nbt.Tag;

import java.io.BufferedInputStream;
Expand All @@ -25,10 +23,32 @@ public final class RegionFile {
private final Map<ChunkPos, Chunk> chunkMap = new HashMap<>();

public RegionFile(final File file) {
this(file, null);
}

public RegionFile(final File file, final ChunkFilter filter) {
try (final RandomAccessFile region = new RandomAccessFile(file, "r")) {
if (region.length() < 4096) {
return;
}
final String regionFileName = file.getName();
if (!regionFileName.startsWith("r.")) {
return;
}
final int extension = regionFileName.indexOf(".mca");
if (extension < 2) {
return;
}
final String regionCoordinates = regionFileName.substring(2, extension);
final int separator = regionCoordinates.indexOf('.');
final int regionX;
final int regionZ;
try {
regionX = Integer.parseInt(regionCoordinates.substring(0, separator));
regionZ = Integer.parseInt(regionCoordinates.substring(separator + 1));
} catch (final NumberFormatException e) {
return;
}
final int[] offsetTable = new int[ENTRIES];
final int[] sizeTable = new int[ENTRIES];
for (int i = 0; i < ENTRIES; ++i) {
Expand Down Expand Up @@ -58,24 +78,22 @@ public RegionFile(final File file) {
final InflaterInputStream inflater = new InflaterInputStream(bytes);
final BufferedInputStream buffer = new BufferedInputStream(inflater);
final DataInputStream input = new DataInputStream(buffer)) {
if (Tag.load(input) instanceof final CompoundTag data) {
chunks.add(new Chunk(data, timestampTable[i]));
final int x = (regionX * 32) + (i % 32);
final int z = (regionZ * 32) + (i / 32);
final Tag data;
if (filter == null) {
data = Tag.load(input);
} else {
data = Tag.find(input, filter.getType(), filter.getName());
}
final Chunk chunk = new Chunk(x, z, data, timestampTable[i]);
chunks.add(chunk);
chunkMap.put(ChunkPos.of(x, z), chunk);
}
}
} catch (IOException e) {
e.printStackTrace();
}
for (final Chunk chunk : chunks) {
final CompoundTag data = chunk.getData();
final Optional<IntTag> xPos = data.getInt("xPos");
final Optional<IntTag> zPos = data.getInt("zPos");
if (xPos.isPresent() && zPos.isPresent()) {
final int x = xPos.get().value();
final int z = zPos.get().value();
chunkMap.put(ChunkPos.of(x, z), chunk);
}
}
}

public Collection<Chunk> getChunks() {
Expand Down

0 comments on commit 2a58fda

Please sign in to comment.