Added progress Screen for DataFixer
This commit is contained in:
parent
11926ac63c
commit
d1ef3b5807
5 changed files with 138 additions and 61 deletions
|
@ -13,7 +13,7 @@ import net.minecraft.nbt.NbtIo;
|
|||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.ProgressListener;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.chunk.storage.RegionFile;
|
||||
import net.minecraft.world.level.storage.LevelResource;
|
||||
|
@ -23,7 +23,9 @@ import org.jetbrains.annotations.NotNull;
|
|||
import ru.bclib.BCLib;
|
||||
import ru.bclib.api.WorldDataAPI;
|
||||
import ru.bclib.config.Configs;
|
||||
import ru.bclib.gui.screens.AtomicProgressListener;
|
||||
import ru.bclib.gui.screens.ConfirmFixScreen;
|
||||
import ru.bclib.gui.screens.ProgressScreen;
|
||||
import ru.bclib.util.Logger;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
|
@ -32,6 +34,8 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
@ -150,41 +154,76 @@ public class DataFixerAPI {
|
|||
}
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
private static AtomicProgressListener showProgressScreen(){
|
||||
ProgressScreen ps = new ProgressScreen(Minecraft.getInstance().screen, new TranslatableComponent("title.bclib.datafixer.progress"), new TranslatableComponent("message.bclib.datafixer.progress"));
|
||||
Minecraft.getInstance().setScreen(ps);
|
||||
return ps;
|
||||
}
|
||||
|
||||
private static boolean fixData(File dir, String levelID, boolean showUI, Consumer<Boolean> onResume) {
|
||||
MigrationProfile profile = loadProfileIfNeeded(dir);
|
||||
|
||||
Consumer<Boolean> runFixes = (applyFixes) -> {
|
||||
BiConsumer<Boolean, Boolean> runFixes = (createBackup, applyFixes) -> {
|
||||
final AtomicProgressListener progress;
|
||||
if (applyFixes) {
|
||||
runDataFixes(dir, profile, new ProgressListener() {
|
||||
if (showUI) {
|
||||
progress = showProgressScreen();
|
||||
} else {
|
||||
progress = new AtomicProgressListener() {
|
||||
private long timeStamp = Util.getMillis();
|
||||
private AtomicInteger counter = new AtomicInteger(0);
|
||||
|
||||
public void progressStartNoAbort(Component component) {
|
||||
}
|
||||
|
||||
public void progressStart(Component component) {
|
||||
}
|
||||
|
||||
public void progressStagePercentage(int i) {
|
||||
@Override
|
||||
public void incAtomic(int maxProgress) {
|
||||
int percentage = (100 * counter.incrementAndGet()) / maxProgress;
|
||||
if (Util.getMillis() - this.timeStamp >= 1000L) {
|
||||
this.timeStamp = Util.getMillis();
|
||||
BCLib.LOGGER.info((String) "Patching... {}%", (Object) i);
|
||||
BCLib.LOGGER.info((String) "Patching... {}%", percentage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetAtomic() {
|
||||
counter = new AtomicInteger(0);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
public void progressStage(Component component) {
|
||||
BCLib.LOGGER.info((String) "Patcher Stage... {}%", component.getString());
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
} else {
|
||||
//System.out.println("NO FIXES");
|
||||
progress = null;
|
||||
}
|
||||
|
||||
//UI is asynchronous, so we need to send the callback now
|
||||
Runnable runner = () -> {
|
||||
if (createBackup) {
|
||||
EditWorldScreen.makeBackupAndShowToast(Minecraft.getInstance().getLevelSource(), levelID);
|
||||
}
|
||||
|
||||
if (applyFixes) {
|
||||
runDataFixes(dir, profile, progress);
|
||||
}
|
||||
};
|
||||
|
||||
if (showUI) {
|
||||
Thread fixerThread = new Thread(() -> {
|
||||
runner.run();
|
||||
|
||||
Minecraft.getInstance().execute(() -> {
|
||||
if (profile != null && showUI) {
|
||||
onResume.accept(applyFixes);
|
||||
}
|
||||
});
|
||||
});
|
||||
fixerThread.start();
|
||||
} else {
|
||||
runner.run();
|
||||
}
|
||||
};
|
||||
|
||||
//we have some migrations
|
||||
|
@ -195,7 +234,7 @@ public class DataFixerAPI {
|
|||
return true;
|
||||
} else {
|
||||
BCLib.LOGGER.warning("Applying Fixes on Level");
|
||||
runFixes.accept(true);
|
||||
runFixes.accept(false, true);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -208,6 +247,8 @@ public class DataFixerAPI {
|
|||
}
|
||||
|
||||
MigrationProfile profile = getMigrationProfile();
|
||||
//TODO: Remove on Production
|
||||
if (!BCLib.isDevEnvironment())
|
||||
profile.runPrePatches(levelBaseDir);
|
||||
|
||||
if (!profile.hasAnyFixes()) {
|
||||
|
@ -226,46 +267,53 @@ public class DataFixerAPI {
|
|||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
static void showBackupWarning(String levelID, Consumer<Boolean> whenFinished){
|
||||
Minecraft.getInstance().setScreen(new ConfirmFixScreen((Screen) null, (createBackup, applyFixes) -> {
|
||||
if (createBackup) {
|
||||
EditWorldScreen.makeBackupAndShowToast(Minecraft.getInstance().getLevelSource(), levelID);
|
||||
static void showBackupWarning(String levelID, BiConsumer<Boolean, Boolean> whenFinished){
|
||||
Minecraft.getInstance().setScreen(new ConfirmFixScreen((Screen) null, whenFinished::accept));
|
||||
}
|
||||
|
||||
Minecraft.getInstance().setScreen((Screen)null);
|
||||
whenFinished.accept(applyFixes);
|
||||
}));
|
||||
}
|
||||
|
||||
private static void runDataFixes(File dir, MigrationProfile profile, ProgressListener progress) {
|
||||
private static void runDataFixes(File dir, MigrationProfile profile, AtomicProgressListener progress) {
|
||||
State state = new State();
|
||||
progress.resetAtomic();
|
||||
|
||||
List<File> regions = getAllRegions(dir, null);
|
||||
progress.progressStagePercentage(0);
|
||||
int[] count = {0};
|
||||
regions.parallelStream().forEach((file) -> {
|
||||
fixRegion(profile, state, file);
|
||||
count[0]++;
|
||||
progress.progressStagePercentage((100 * count[0])/regions.size());
|
||||
});
|
||||
progress.stop();
|
||||
|
||||
progress.progressStage(new TranslatableComponent("message.bclib.datafixer.progress.reading"));
|
||||
List<File> players = getAllPlayers(dir);
|
||||
players.parallelStream().forEach((file) -> fixPlayer(profile, state, file));
|
||||
List<File> regions = getAllRegions(dir, null);
|
||||
final int maxProgress = players.size()+regions.size()+4;
|
||||
progress.incAtomic(maxProgress);
|
||||
|
||||
progress.progressStage(new TranslatableComponent("message.bclib.datafixer.progress.players"));
|
||||
players.parallelStream().forEach((file) -> {
|
||||
fixPlayer(profile, state, file);
|
||||
progress.incAtomic(maxProgress);
|
||||
});
|
||||
|
||||
progress.progressStage(new TranslatableComponent("message.bclib.datafixer.progress.level"));
|
||||
fixLevel(profile, state, dir);
|
||||
progress.incAtomic(maxProgress);
|
||||
|
||||
progress.progressStage(new TranslatableComponent("message.bclib.datafixer.progress.worlddata"));
|
||||
try {
|
||||
profile.patchWorldData();
|
||||
} catch (PatchDidiFailException e){
|
||||
state.didFail = true;
|
||||
BCLib.LOGGER.error(e.getMessage());
|
||||
}
|
||||
progress.incAtomic(maxProgress);
|
||||
|
||||
progress.progressStage(new TranslatableComponent("message.bclib.datafixer.progress.regions"));
|
||||
regions.parallelStream().forEach((file) -> {
|
||||
fixRegion(profile, state, file);
|
||||
progress.incAtomic(maxProgress);
|
||||
});
|
||||
|
||||
if (!state.didFail) {
|
||||
progress.progressStage(new TranslatableComponent("message.bclib.datafixer.progress.saving"));
|
||||
profile.markApplied();
|
||||
WorldDataAPI.saveFile(BCLib.MOD_ID);
|
||||
}
|
||||
progress.incAtomic(maxProgress);
|
||||
|
||||
progress.stop();
|
||||
}
|
||||
|
||||
private static void fixLevel(MigrationProfile profile, State state, File levelBaseDir) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ru.bclib.api.datafixer;
|
||||
|
||||
import net.fabricmc.loom.util.ModUtils;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
|
@ -123,7 +124,7 @@ public class MigrationProfile {
|
|||
|
||||
final public void markApplied() {
|
||||
for (String modID : mods) {
|
||||
DataFixerAPI.LOGGER.info("Updating Patch-Level for '{}' from {} to {}", modID, currentPatchLevel(modID), Patch.maxPatchLevel(modID));
|
||||
DataFixerAPI.LOGGER.info("Updating Patch-Level for '{}' from {} to {}", modID, ModUtil.convertModVersion(currentPatchLevel(modID)), ModUtil.convertModVersion(Patch.maxPatchLevel(modID)));
|
||||
config.putString(modID, Patch.maxPatchVersion(modID));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package ru.bclib.gui.screens;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public interface AtomicProgressListener {
|
||||
public void incAtomic(int maxProgress);
|
||||
public void resetAtomic();
|
||||
public void stop();
|
||||
public void progressStage(Component component);
|
||||
}
|
|
@ -25,6 +25,8 @@ import ru.bclib.gui.gridlayout.GridScreen;
|
|||
import ru.bclib.gui.gridlayout.GridStringCell;
|
||||
import ru.bclib.gui.gridlayout.GridTransform;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class ProgressLogoRender extends GridCustomRenderCell {
|
||||
public static final int SIZE = 64;
|
||||
public static final int LOGO_SIZE = 512;
|
||||
|
@ -95,19 +97,36 @@ class ProgressLogoRender extends GridCustomRenderCell {
|
|||
}
|
||||
}
|
||||
|
||||
public class ProgressScreen extends GridScreen implements ProgressListener {
|
||||
public class ProgressScreen extends GridScreen implements ProgressListener, AtomicProgressListener {
|
||||
|
||||
static final ResourceLocation BCLIB_LOGO_PIXELATED_LOCATION = new ResourceLocation(BCLib.MOD_ID, "iconpixelated.png");
|
||||
public ProgressScreen(@Nullable Screen parent, Component title, Component description) {
|
||||
super(parent, title, 20, false);
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
|
||||
Component description;
|
||||
private Component stageComponent;
|
||||
private GridMessageCell stage;
|
||||
private GridStringCell progress;
|
||||
private ProgressLogoRender progressImage;
|
||||
private int currentProgress = 0;
|
||||
private AtomicInteger atomicCounter;
|
||||
|
||||
@Override
|
||||
public void incAtomic(int maxProgress) {
|
||||
if (atomicCounter!=null) {
|
||||
progressStagePercentage((100*atomicCounter.incrementAndGet())/maxProgress);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetAtomic() {
|
||||
progressStagePercentage(0);
|
||||
atomicCounter = new AtomicInteger(0);
|
||||
}
|
||||
|
||||
public boolean shouldCloseOnEsc() {
|
||||
return false;
|
||||
}
|
||||
|
@ -165,7 +184,6 @@ public class ProgressScreen extends GridScreen implements ProgressListener {
|
|||
if (i!=currentProgress) {
|
||||
currentProgress = i;
|
||||
if (progressImage!=null) progressImage.percentage = currentProgress / 100.0f;
|
||||
BCLib.LOGGER.info(" -> progress: " + i + "%");
|
||||
if (progress!=null) progress.setText(getProgressComponent());
|
||||
}
|
||||
}
|
||||
|
@ -174,13 +192,4 @@ public class ProgressScreen extends GridScreen implements ProgressListener {
|
|||
public void stop() {
|
||||
|
||||
}
|
||||
|
||||
double time = 0;
|
||||
@Override
|
||||
public void render(PoseStack poseStack, int i, int j, float f) {
|
||||
//time += 0.05;
|
||||
//progressStagePercentage(((int)time)%100);
|
||||
//progressStagePercentage(1);
|
||||
super.render(poseStack, i, j, f);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,5 +33,14 @@
|
|||
"title.bclib.syncfiles.modlist": "Mod Information",
|
||||
"message.bclib.syncfiles.modlist": "The following shows the state of your installed installed Mods.\n\nAll Mods that do not exist locally, or have a different version will on the Server will be synchronized.",
|
||||
"title.bclib.modmissmatch": "Mod Version Conflict",
|
||||
"message.bclib.modmissmatch": "Some Mods on this client do not match the version of Mods on the Server.\n\nMismatching Mods can result in odd game behavior or crashes. Please make sue that you use the same mods as the server."
|
||||
"message.bclib.modmissmatch": "Some Mods on this client do not match the version of Mods on the Server.\n\nMismatching Mods can result in odd game behavior or crashes. Please make sue that you use the same mods as the server.",
|
||||
|
||||
"message.bclib.datafixer.progress.reading": "Reading Data",
|
||||
"message.bclib.datafixer.progress.players": "Fixing Players",
|
||||
"message.bclib.datafixer.progress.level": "Applying Patches to level.dat",
|
||||
"message.bclib.datafixer.progress.worlddata": "Patching Custom World-Data",
|
||||
"message.bclib.datafixer.progress.regions": "Repairing all Regions",
|
||||
"message.bclib.datafixer.progress.saving": "Saving Patch State",
|
||||
"title.bclib.datafixer.progress": "Fixing World",
|
||||
"message.bclib.datafixer.progress": "Applying all Patches to your World."
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue