Skip to content

Commit

Permalink
it renders the map again.
Browse files Browse the repository at this point in the history
  • Loading branch information
Querz committed Jan 21, 2021
1 parent c950e74 commit c09541c
Show file tree
Hide file tree
Showing 19 changed files with 383 additions and 258 deletions.
10 changes: 10 additions & 0 deletions src/main/java/net/querz/mcaselector/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,16 @@ public static void setWorldDir(File worldDir) {
cacheDir = new File(baseCacheDir, worldUUID.toString().replace("-", ""));
}

public static void setWorldDirs(File regionDir, File poiDir, File entitiesDir) {
Config.worldDirs = new WorldDirectories(regionDir, poiDir, entitiesDir);
setWorldDir(regionDir);
}

public static void setWorldDirs(WorldDirectories dirs) {
Config.worldDirs = dirs;
setWorldDir(dirs.getRegion());
}

public static File getCacheDirForWorldUUID(UUID world, int zoomLevel) {
return new File(baseCacheDir, world.toString().replace("-", "") + "/" + zoomLevel);
}
Expand Down
45 changes: 27 additions & 18 deletions src/main/java/net/querz/mcaselector/headless/ParamExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import net.querz.mcaselector.io.ChunkFilterSelector;
import net.querz.mcaselector.io.ChunkImporter;
import net.querz.mcaselector.io.FieldChanger;
import net.querz.mcaselector.io.RegionDirectories;
import net.querz.mcaselector.io.SelectionData;
import net.querz.mcaselector.io.SelectionDeleter;
import net.querz.mcaselector.io.SelectionExporter;
Expand Down Expand Up @@ -53,15 +54,17 @@ public Future<Boolean> parseAndRun() {
pi.registerDependencies("headless", null, new ActionKey("mode", null));
pi.registerDependencies("mode", null, new ActionKey("headless", null));
pi.registerRestrictions("mode", "select", "export", "import", "delete", "change", "cache");
pi.registerDependencies("mode", null, new ActionKey("world", null)); // every mode param needs a world dir
pi.registerDependencies("mode", null, new ActionKey("region", null)); // every mode param needs a region dir
pi.registerDependencies("mode", "select", new ActionKey("output", null), new ActionKey("query", null));
pi.registerDependencies("mode", "export", new ActionKey("output", null));
pi.registerDependencies("mode", "import", new ActionKey("input", null));
pi.registerDependencies("mode", "export", new ActionKey("output-region", null), new ActionKey("output-poi", null), new ActionKey("output-entities", null), new ActionKey("region", null), new ActionKey("poi", null), new ActionKey("entities", null));
pi.registerDependencies("mode", "import", new ActionKey("input-region", null), new ActionKey("input-poi", null), new ActionKey("input-entities", null));
pi.registerDependencies("mode", "change", new ActionKey("query", null));
pi.registerDependencies("mode", "cache", new ActionKey("output", null));
pi.registerDependencies("world", null, new ActionKey("mode", null)); // world param needs mode param
pi.registerSoftDependencies("output", null, new ActionKey("mode", "select"), new ActionKey("mode", "export"), new ActionKey("mode", "cache"));
pi.registerSoftDependencies("input", null, new ActionKey("mode", "export"), new ActionKey("mode", "import"), new ActionKey("mode", "delete"), new ActionKey("mode", "change"));
pi.registerDependencies("region", null, new ActionKey("mode", null)); // region param needs mode param
pi.registerDependencies("poi", null, new ActionKey("mode", null));
pi.registerDependencies("entities", null, new ActionKey("mode", null));
pi.registerSoftDependencies("output", null, new ActionKey("mode", "select"), new ActionKey("mode", "cache"));
pi.registerSoftDependencies("input", null, new ActionKey("mode", "delete"), new ActionKey("mode", "change"));
pi.registerSoftDependencies("query", null, new ActionKey("mode", "select"), new ActionKey("mode", "export"), new ActionKey("mode", "delete"), new ActionKey("mode", "change"));
pi.registerSoftDependencies("radius", null, new ActionKey("mode", "select"));
pi.registerDependencies("force", null, new ActionKey("mode", "change"));
Expand Down Expand Up @@ -129,9 +132,9 @@ private static void runModeCache(Map<String, String> params, FutureTask<Boolean>
throw new IOException("no JavaFX installation found");
}

File world = parseDirectory(params.get("world"));
checkDirectoryForFiles(world, FileHelper.MCA_FILE_PATTERN);
Config.setWorldDir(world);
File region = parseDirectory(params.get("region"));
checkDirectoryForFiles(region, FileHelper.MCA_FILE_PATTERN);
Config.setWorldDir(region);

File output = parseDirectory(params.get("output"));
createDirectoryIfNotExists(output);
Expand All @@ -149,9 +152,9 @@ private static void runModeCache(Map<String, String> params, FutureTask<Boolean>
}

private static void runModeChange(Map<String, String> params, FutureTask<Boolean> future) throws IOException {
File world = parseDirectory(params.get("world"));
checkDirectoryForFiles(world, FileHelper.MCA_FILE_PATTERN);
Config.setWorldDir(world);
File region = parseDirectory(params.get("world"));
checkDirectoryForFiles(region, FileHelper.MCA_FILE_PATTERN);
Config.setWorldDir(region);

List<Field<?>> fields = new ChangeParser(params.get("query")).parse();

Expand All @@ -164,7 +167,7 @@ private static void runModeChange(Map<String, String> params, FutureTask<Boolean
ConsoleProgress progress = new ConsoleProgress();
progress.onDone(future);

FieldChanger.changeNBTFields(fields, force, selection, progress);
FieldChanger.changeNBTFields(fields, force, selection, progress, true);
}


Expand Down Expand Up @@ -230,12 +233,18 @@ private static void runModeImport(Map<String, String> params, FutureTask<Boolean
ConsoleProgress progress = new ConsoleProgress();
progress.onDone(future);

DataProperty<Map<Point2i, File>> tempFiles = new DataProperty<>();
ChunkImporter.importChunks(input, progress, true, overwrite, null, selection, ranges, new Point2i(offsetX, offsetZ), tempFiles);
DataProperty<Map<Point2i, RegionDirectories>> tempFiles = new DataProperty<>();
ChunkImporter.importChunks(null, progress, true, overwrite, null, selection, ranges, new Point2i(offsetX, offsetZ), tempFiles);
if (tempFiles.get() != null) {
for (File tempFile : tempFiles.get().values()) {
if (!tempFile.delete()) {
Debug.errorf("failed to delete temp file %s", tempFile);
for (RegionDirectories tempFile : tempFiles.get().values()) {
if (!tempFile.getRegion().delete()) {
Debug.errorf("failed to delete temp file %s", tempFile.getRegion());
}
if (!tempFile.getPoi().delete()) {
Debug.errorf("failed to delete temp file %s", tempFile.getPoi());
}
if (!tempFile.getEntities().delete()) {
Debug.errorf("failed to delete temp file %s", tempFile.getEntities());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ private MCADeleteFilterProcessJob(RegionDirectories dirs, byte[] regionData, byt

@Override
public void execute() {
//load MCAFile
try {
// parse raw data
Region region = Region.loadRegion(getRegionDirectories(), getRegionData(), getPoiData(), getEntitiesData());
Expand Down
106 changes: 49 additions & 57 deletions src/main/java/net/querz/mcaselector/io/FieldChanger.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import net.querz.mcaselector.Config;
import net.querz.mcaselector.changer.Field;
import net.querz.mcaselector.debug.Debug;
import net.querz.mcaselector.io.mca.Region;
import net.querz.mcaselector.point.Point2i;
import net.querz.mcaselector.progress.Progress;
import net.querz.mcaselector.progress.Timer;
import net.querz.mcaselector.text.Translation;

import java.io.File;
import java.io.RandomAccessFile;
import java.nio.file.Files;
Expand All @@ -19,21 +22,27 @@ public class FieldChanger {

private FieldChanger() {}

public static void changeNBTFields(List<Field<?>> fields, boolean force, SelectionData selection, Progress progressChannel) {
File[] files = Config.getWorldDir().listFiles((d, n) -> n.matches(FileHelper.MCA_FILE_PATTERN));
if (files == null || files.length == 0) {
public static void changeNBTFields(List<Field<?>> fields, boolean force, SelectionData selection, Progress progressChannel, boolean headless) {
WorldDirectories wd = Config.getWorldDirs();
RegionDirectories[] rd = wd.listRegions();
if (rd == null || rd.length == 0) {
if (headless) {
progressChannel.done("no files");
} else {
progressChannel.done(Translation.DIALOG_PROGRESS_NO_FILES.toString());
}
return;
}

MCAFilePipe.clearQueues();

Map<Point2i, Set<Point2i>> sel = SelectionHelper.getTrueSelection(selection);

progressChannel.setMax(files.length);
progressChannel.updateProgress(files[0].getName(), 0);
progressChannel.setMax(rd.length);
progressChannel.updateProgress(rd[0].getLocationAsFileName(), 0);

for (File file : files) {
MCAFilePipe.addJob(new MCAFieldChangeLoadJob(file, fields, force, sel, progressChannel));
for (RegionDirectories r : rd) {
MCAFilePipe.addJob(new MCAFieldChangeLoadJob(r, fields, force, sel, progressChannel));
}
}

Expand All @@ -44,8 +53,8 @@ public static class MCAFieldChangeLoadJob extends LoadDataJob {
private final boolean force;
private final Map<Point2i, Set<Point2i>> selection;

private MCAFieldChangeLoadJob(File file, List<Field<?>> fields, boolean force, Map<Point2i, Set<Point2i>> selection, Progress progressChannel) {
super(file);
private MCAFieldChangeLoadJob(RegionDirectories dirs, List<Field<?>> fields, boolean force, Map<Point2i, Set<Point2i>> selection, Progress progressChannel) {
super(dirs);
this.fields = fields;
this.force = force;
this.selection = selection;
Expand All @@ -56,25 +65,24 @@ private MCAFieldChangeLoadJob(File file, List<Field<?>> fields, boolean force, M
public void execute() {
Set<Point2i> chunks = null;
if (selection != null) {
Matcher m = FileHelper.REGION_GROUP_PATTERN.matcher(getFile().getName());
if (m.find()) {
int regionX = Integer.parseInt(m.group("regionX"));
int regionZ = Integer.parseInt(m.group("regionZ"));
Point2i location = new Point2i(regionX, regionZ);
if (!selection.containsKey(location)) {
Debug.dumpf("will not apply nbt changes to %s", getFile().getName());
progressChannel.incrementProgress(getFile().getName());
return;
}
chunks = selection.get(location);
Point2i location = getRegionDirectories().getLocation();
if (!selection.containsKey(location)) {
Debug.dumpf("will not apply nbt changes to %s", getRegionDirectories().getLocationAsFileName());
progressChannel.incrementProgress(getRegionDirectories().getLocationAsFileName());
return;
}
chunks = selection.get(location);
}
byte[] data = load();
if (data != null) {
MCAFilePipe.executeProcessData(new MCAFieldChangeProcessJob(getFile(), data, fields, force, chunks, progressChannel));

byte[] regionData = loadRegion();
byte[] poiData = loadPOI();
byte[] entitiesData = loadEntities();

if (regionData == null && poiData == null && entitiesData == null) {
Debug.errorf("failed to load any data from %s", getRegionDirectories().getLocationAsFileName());
progressChannel.incrementProgress(getRegionDirectories().getLocationAsFileName());
} else {
Debug.errorf("error loading mca file %s", getFile().getName());
progressChannel.incrementProgress(getFile().getName() + ": error");
MCAFilePipe.executeProcessData(new MCAFieldChangeProcessJob(getRegionDirectories(), regionData, poiData, entitiesData, fields, force, chunks, progressChannel));
}
}
}
Expand All @@ -86,8 +94,8 @@ public static class MCAFieldChangeProcessJob extends ProcessDataJob {
private final boolean force;
private final Set<Point2i> selection;

private MCAFieldChangeProcessJob(File file, byte[] data, List<Field<?>> fields, boolean force, Set<Point2i> selection, Progress progressChannel) {
super(file, data);
private MCAFieldChangeProcessJob(RegionDirectories dirs, byte[] regionData, byte[] poiData, byte[] entitiesData, List<Field<?>> fields, boolean force, Set<Point2i> selection, Progress progressChannel) {
super(dirs, regionData, poiData, entitiesData);
this.fields = fields;
this.force = force;
this.selection = selection;
Expand All @@ -97,54 +105,38 @@ private MCAFieldChangeProcessJob(File file, byte[] data, List<Field<?>> fields,
@Override
public void execute() {
//load MCAFile
Timer t = new Timer();
try {
MCAFile mca = MCAFile.readAll(getFile(), new ByteArrayPointer(getData()));
mca.applyFieldChanges(fields, force, selection);
Debug.dumpf("took %s to apply field changes to %s", t, getFile().getName());
MCAFilePipe.executeSaveData(new MCAFieldChangeSaveJob(getFile(), mca, progressChannel));
Region region = Region.loadRegion(getRegionDirectories(), getRegionData(), getPoiData(), getEntitiesData());

region.applyFieldChanges(fields, force, selection);

MCAFilePipe.executeSaveData(new MCAFieldChangeSaveJob(getRegionDirectories(), region, progressChannel));
} catch (Exception ex) {
progressChannel.incrementProgress(getFile().getName());
Debug.errorf("error changing fields in %s", getFile().getName());
progressChannel.incrementProgress(getRegionDirectories().getLocationAsFileName());
Debug.errorf("error changing fields in %s", getRegionDirectories().getLocationAsFileName());
}
}
}

public static class MCAFieldChangeSaveJob extends SaveDataJob<MCAFile> {
public static class MCAFieldChangeSaveJob extends SaveDataJob<Region> {

private final Progress progressChannel;

private MCAFieldChangeSaveJob(File file, MCAFile data, Progress progressChannel) {
super(file, data);
private MCAFieldChangeSaveJob(RegionDirectories file, Region region, Progress progressChannel) {
super(file, region);
this.progressChannel = progressChannel;
}

@Override
public void execute() {
Timer t = new Timer();
try {
File tmpFile = File.createTempFile(getFile().getName(), null, null);

boolean empty;

try (RandomAccessFile raf = new RandomAccessFile(tmpFile, "rw")) {
empty = !getData().saveAll(raf);
}

if (empty) {
if (getFile().delete()) {
Debug.dumpf("deleted empty region file %s", getFile().getAbsolutePath());
} else {
Debug.dumpf("could not delete empty region file %s", getFile().getAbsolutePath());
}
} else {
Files.move(tmpFile.toPath(), getFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
}
getData().saveWithTempFiles();
} catch (Exception ex) {
Debug.dumpException("failed to save changed chunks in " + getFile().getName(), ex);
Debug.dumpException("failed to save changed fields for " + getRegionDirectories().getLocationAsFileName(), ex);
}
progressChannel.incrementProgress(getFile().getName());
Debug.dumpf("took %s to save data to %s", t, getFile().getName());
progressChannel.incrementProgress(getRegionDirectories().getLocationAsFileName());
Debug.dumpf("took %s to save data for %s", t, getRegionDirectories().getLocationAsFileName());
}
}
}
10 changes: 10 additions & 0 deletions src/main/java/net/querz/mcaselector/io/FileHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,16 @@ public static File createEntitiesMCAFilePath(Point2i r) {
return new File(Config.getWorldDirs().getEntities(), createMCAFileName(r));
}

public static WorldDirectories validateWorldDirectories(File dir) {
File region = new File(dir, "region");
File poi = new File(dir, "poi");
File entities = new File(dir, "entities");
if (!region.exists() || !poi.exists() || !entities.exists()) {
return null;
}
return new WorldDirectories(region, poi, entities);
}

public static RegionDirectories createRegionDirectories(Point2i r) {
File region = createRegionMCAFilePath(r);
File poi = createPoiMCAFilePath(r);
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/net/querz/mcaselector/io/MCAFilePipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ static void refillDataLoadExecutorQueue() {
&& saveDataExecutor.getQueue().size() < Config.getMaxLoadedFiles()) {
LoadDataJob job = waitingForLoad.poll();
if (job != null) {
Debug.dumpf("refilling data load executor queue with %s", job.getFile().getAbsolutePath());
Debug.dumpf("refilling data load executor queue with %s", job.getRegionDirectories().getLocationAsFileName());
loadDataExecutor.execute(job);
}
}
Expand All @@ -75,10 +75,10 @@ static void refillDataLoadExecutorQueue() {
public static void addJob(LoadDataJob job) {
if (processDataExecutor.getQueue().size() + loadDataExecutor.getQueue().size() > Config.getMaxLoadedFiles()
|| saveDataExecutor.getQueue().size() > Config.getMaxLoadedFiles()) {
Debug.dumpf("adding LoadDataJob %s for %s to wait queue", job.getClass().getSimpleName(), job.getFile().getName());
Debug.dumpf("adding LoadDataJob %s for %s to wait queue", job.getClass().getSimpleName(), job.getRegionDirectories().getLocationAsFileName());
waitingForLoad.offer(job);
} else {
Debug.dumpf("adding LoadDataJob %s for %s to executor queue", job.getClass().getSimpleName(), job.getFile().getName());
Debug.dumpf("adding LoadDataJob %s for %s to executor queue", job.getClass().getSimpleName(), job.getRegionDirectories().getLocationAsFileName());
loadDataExecutor.execute(job);
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/net/querz/mcaselector/io/RegionDirectories.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ public String getLocationAsFileName() {
return locationAsFileName;
}

public static RegionDirectories fromWorldDirectories(WorldDirectories wd, Point2i location) {
String fileName = FileHelper.createMCAFileName(location);
return new RegionDirectories(
location,
new File(wd.getRegion(), fileName),
new File(wd.getPoi(), fileName),
new File(wd.getEntities(), fileName)
);
}

@Override
public String toString() {
return "<region=" + region + ", poi=" + poi + ", entities=" + entities + ">";
Expand Down
Loading

0 comments on commit c09541c

Please sign in to comment.