diff --git a/common/src/main/java/com/adamcalculator/dynamicpack/Mod.java b/common/src/main/java/com/adamcalculator/dynamicpack/Mod.java index 0352979..c5f3d38 100644 --- a/common/src/main/java/com/adamcalculator/dynamicpack/Mod.java +++ b/common/src/main/java/com/adamcalculator/dynamicpack/Mod.java @@ -117,9 +117,13 @@ public static void debugNetwork() { if (isRelease()) return; try { - Thread.sleep(13); + Thread.sleep(200); } catch (InterruptedException e) { throw new RuntimeException(e); } } + + public static boolean isDebugLogs() { + return false; + } } diff --git a/common/src/main/java/com/adamcalculator/dynamicpack/pack/Pack.java b/common/src/main/java/com/adamcalculator/dynamicpack/pack/Pack.java index fd770bf..e9b3fa2 100644 --- a/common/src/main/java/com/adamcalculator/dynamicpack/pack/Pack.java +++ b/common/src/main/java/com/adamcalculator/dynamicpack/pack/Pack.java @@ -11,6 +11,9 @@ import java.io.File; import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; public class Pack { public static final String UNKNOWN_PACK_MCMETA = """ @@ -30,6 +33,8 @@ public class Pack { private boolean isSyncing = false; private final String remoteTypeStr; private Exception latestException; + private final List> destroyListeners = new ArrayList<>(); + private boolean destroyed = false; public Pack(File location, JSONObject json) { @@ -190,9 +195,30 @@ public Exception getLatestException() { public void saveReScanData(Pack oldestPack) { if (oldestPack == null) return; + oldestPack.markAsDestroyed(this); if (this.latestException == null) { this.latestException = oldestPack.latestException; } } + + public void addDestroyListener(Consumer runnable) { + destroyListeners.add(runnable); + } + + public void removeDestroyListener(Consumer runnable) { + destroyListeners.remove(runnable); + } + + private void markAsDestroyed(Pack heirPack) { + for (Consumer runnable : destroyListeners.toArray(new Consumer[0])) { + runnable.accept(heirPack); + } + destroyListeners.clear(); + this.destroyed = true; + } + + public boolean isDestroyed() { + return destroyed; + } } diff --git a/common/src/main/java/com/adamcalculator/dynamicpack/sync/SyncingTask.java b/common/src/main/java/com/adamcalculator/dynamicpack/sync/SyncingTask.java index cad5ca2..7e26f41 100644 --- a/common/src/main/java/com/adamcalculator/dynamicpack/sync/SyncingTask.java +++ b/common/src/main/java/com/adamcalculator/dynamicpack/sync/SyncingTask.java @@ -13,6 +13,9 @@ */ public class SyncingTask implements Runnable { public static boolean isSyncing = false; + public static String syncingLog1 = ""; + public static String syncingLog2 = ""; + public static String syncingLog3 = ""; private final boolean manually; // skip checkUpdateAvailable(). private boolean reloadRequired = false; @@ -30,6 +33,7 @@ public void run() { } isSyncing = true; Out.println("SyncTask started!"); + log("Syncing started..."); onSyncStart(); DynamicPackModBase.INSTANCE.rescanPacks(); DynamicPackModBase.INSTANCE.rescanPacksBlocked = true; @@ -38,8 +42,10 @@ public void run() { try { pack.sync(createSyncProgressForPack(pack), manually); onPackDoneSuccess(pack); + log(pack.getName() + " success"); } catch (Exception e) { Out.error("Pack error: " + pack.getName(), e); + log(pack.getName() + " error: " + e); onPackError(pack, e); } } @@ -47,6 +53,7 @@ public void run() { onSyncDone(reloadRequired); Out.println("SyncTask ended!"); isSyncing = false; + clearLog(); } public void onPackDoneSuccess(Pack pack) {} @@ -78,6 +85,7 @@ private void _packLog(String s) { @Override public void start() { + log("Sync started " + pack.getName()); _packLog("Sync started."); } @@ -101,20 +109,25 @@ public void done(boolean reloadRequired) { @Override public void textLog(String s) { _packLog("[textLog] " + s); + log(s); } @Override public void downloading(String name, float percentage) { if (cachedDownloading == null) { cachedDownloading = new StateDownloading(name); + log("Downloading " + name); } else { - cachedDownloading.setName(name); + if (!cachedDownloading.getName().equals(name)) { + cachedDownloading.setName(name); + log("Downloading " + name); + } } if (percentage == 100f) { setState(new StateDownloadDone()); return; } - + syncingLog3 = "Downloading " + name + " " + (Math.round(percentage * 100f) / 100f) + "%"; cachedDownloading.setPercentage(Math.round(percentage * 10f) / 10f); setState(cachedDownloading); } @@ -125,4 +138,17 @@ public void stateChanged(SyncProgressState state) { } }; } + + private void log(String s) { + Out.debug("log: " + s); + syncingLog1 = syncingLog2; + syncingLog2 = syncingLog3; + syncingLog3 = s; + } + + private void clearLog() { + syncingLog3 = ""; + syncingLog2 = ""; + syncingLog1 = ""; + } } diff --git a/common/src/main/java/com/adamcalculator/dynamicpack/util/Out.java b/common/src/main/java/com/adamcalculator/dynamicpack/util/Out.java index 60c912a..34e8c46 100644 --- a/common/src/main/java/com/adamcalculator/dynamicpack/util/Out.java +++ b/common/src/main/java/com/adamcalculator/dynamicpack/util/Out.java @@ -1,50 +1,41 @@ package com.adamcalculator.dynamicpack.util; +import com.adamcalculator.dynamicpack.Mod; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; - public class Out { public static final Logger LOGGER = LoggerFactory.getLogger("dynamicpack"); public static boolean ENABLE = true; public static boolean USE_SOUT = false; + public static final String PREFIX = "[DynamicPack] "; public static void println(Object o) { if (!ENABLE) return; if (USE_SOUT) { - System.out.println(o); + System.out.println(PREFIX + o); return; } - LOGGER.info(o + ""); + LOGGER.info(PREFIX + o); } public static void error(String s, Exception e) { if (!ENABLE) return; if (USE_SOUT) { - System.err.println(s); + System.err.println(PREFIX + s); e.printStackTrace(); return; } - LOGGER.error(s, e); - } - - public static void downloading(String url, File file) { - if (!ENABLE) return; - if (USE_SOUT) { - System.out.println(file.getName() + " downloading from " + url); - return; - } - LOGGER.warn("Downloading " + file.getName() + " from " + url); + LOGGER.error(PREFIX + s, e); } public static void warn(String s) { if (!ENABLE) return; if (USE_SOUT) { - System.out.println("WARN: " + s); + System.out.println(PREFIX + "WARN: " + s); return; } - LOGGER.warn(s); + LOGGER.warn(PREFIX + s); } /** @@ -52,19 +43,21 @@ public static void warn(String s) { */ public static void securityWarning(String s) { if (USE_SOUT) { - System.out.println("[dynamicpack] " + s); + System.out.println("[DynamicPack] " + s); return; } try { - LOGGER.warn(s); + LOGGER.warn("[DynamicPack] " + s); } catch (Exception ignored) { - System.out.println("[dynamicpack] " + s); + System.out.println("[DynamicPack] " + s); } } public static void debug(String s) { - println("DEBUG: " + s); + if (Mod.isDebugLogs()) { + println("DEBUG: " + s); + } } /** @@ -72,10 +65,10 @@ public static void debug(String s) { */ public static void securityStackTrace() { if (USE_SOUT) { - System.out.println("[dynamicpack] Stacktrace"); + System.out.println("[DynamicPack] Stacktrace"); new Throwable("StackTrace printer").printStackTrace(); return; } - LOGGER.error("No error. This is stacktrace printer", new Throwable("StackTrace printer")); + LOGGER.error("[DynamicPack] No error. This is stacktrace printer", new Throwable("StackTrace printer")); } } diff --git a/src/client/java/com/adamcalculator/dynamicpack/DynamicPackScreen.java b/src/client/java/com/adamcalculator/dynamicpack/DynamicPackScreen.java index 52e0c10..12bf7a5 100644 --- a/src/client/java/com/adamcalculator/dynamicpack/DynamicPackScreen.java +++ b/src/client/java/com/adamcalculator/dynamicpack/DynamicPackScreen.java @@ -1,23 +1,26 @@ package com.adamcalculator.dynamicpack; +import com.adamcalculator.dynamicpack.include.modmenu.util.DrawingUtil; import com.adamcalculator.dynamicpack.pack.Pack; import com.adamcalculator.dynamicpack.sync.SyncingTask; -import com.terraformersmc.modmenu.util.DrawingUtil; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.screen.ScreenTexts; +import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import java.util.Date; +import java.util.function.Consumer; public class DynamicPackScreen extends Screen { private final Screen parent; - private final Pack pack; - private final Text screenDescText; + private Pack pack; + private final MutableText screenDescText; private ButtonWidget syncButton; + private final Consumer destroyListener = this::setPack; public DynamicPackScreen(Screen parent, Pack pack) { super(Text.literal(pack.getName()).formatted(Formatting.BOLD)); @@ -25,6 +28,15 @@ public DynamicPackScreen(Screen parent, Pack pack) { this.client = MinecraftClient.getInstance(); this.parent = parent; this.screenDescText = Text.translatable("dynamicpack.screen.pack.description"); + setPack(pack); + } + + private void setPack(Pack pack) { + if (this.pack != null) { + this.pack.removeDestroyListener(destroyListener); + } + this.pack = pack; + pack.addDestroyListener(destroyListener); } @Override @@ -39,6 +51,13 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { if (pack.getLatestException() != null) { DrawingUtil.drawWrappedString(context, Text.translatable("dynamicpack.screen.pack.latestException", pack.getLatestException().getMessage()).asTruncatedString(9999), 20, 78 + h, 500, 99, 0xff2222); + h+=10; + } + + if (SyncingTask.isSyncing) { + DrawingUtil.drawWrappedString(context, SyncingTask.syncingLog1, 20, 78+30 + h, 500, 99, 0xCCCCCC); + DrawingUtil.drawWrappedString(context, SyncingTask.syncingLog2, 20, 78+30+20 + h, 500, 99, 0xCCCCCC); + DrawingUtil.drawWrappedString(context, SyncingTask.syncingLog3, 20, 78+30+40 + h, 500, 99, 0xCCCCCC); } super.render(context, mouseX, mouseY, delta); @@ -48,10 +67,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { protected void init() { addDrawableChild(syncButton = Compat.createButton( Text.translatable("dynamicpack.screen.pack.manually_sync"), - () -> { - DynamicPackModBase.INSTANCE.startManuallySync(); - close(); - }, + () -> DynamicPackModBase.INSTANCE.startManuallySync(), 100, 20, width - 120, 10 )); @@ -61,5 +77,6 @@ protected void init() { @Override public void close() { this.client.setScreen(parent); + pack.removeDestroyListener(destroyListener); } } diff --git a/src/client/java/com/adamcalculator/dynamicpack/PackMixinHelper.java b/src/client/java/com/adamcalculator/dynamicpack/PackMixinHelper.java index a5c5ed1..55a78c1 100644 --- a/src/client/java/com/adamcalculator/dynamicpack/PackMixinHelper.java +++ b/src/client/java/com/adamcalculator/dynamicpack/PackMixinHelper.java @@ -1,7 +1,6 @@ package com.adamcalculator.dynamicpack; import com.adamcalculator.dynamicpack.pack.Pack; -import com.adamcalculator.dynamicpack.sync.SyncingTask; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.pack.PackListWidget; @@ -16,7 +15,7 @@ public class PackMixinHelper { public static void renderResourcePackEntry(Object resourcePackEntryMixin, DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta, CallbackInfo ci) { PackListWidget.ResourcePackEntry entry = (PackListWidget.ResourcePackEntry) resourcePackEntryMixin; Pack pack = DynamicPackModBase.INSTANCE.getDynamicPackByMinecraftName(entry.getName()); - if (pack != null && !SyncingTask.isSyncing) { + if (pack != null) { int i = mouseX - x; int j = mouseY - y; context.drawTexture(pack.getLatestException() != null ? BUTTON_WARNING_TEXTURE : BUTTON_TEXTURE, x + 174, y+16, 0.0F, ((i >= 174 && j >= 16 && hovered) ? 16f : 0f), 16, 16, 16, 32); @@ -26,7 +25,7 @@ public static void renderResourcePackEntry(Object resourcePackEntryMixin, DrawCo public static void mouseClicked(Object resourcePackEntryMixin, PackListWidget widget, double mouseX, double mouseY, int button, CallbackInfoReturnable cir) { PackListWidget.ResourcePackEntry entry = (PackListWidget.ResourcePackEntry) resourcePackEntryMixin; Pack pack = DynamicPackModBase.INSTANCE.getDynamicPackByMinecraftName(entry.getName()); - if (pack != null && !SyncingTask.isSyncing) { + if (pack != null) { double d = mouseX - (double)widget.getRowLeft(); double e = mouseY - (double)widget.getRowTop(widget.children().indexOf(entry)); diff --git a/src/client/java/com/adamcalculator/dynamicpack/include/modmenu/util/DrawingUtil.java b/src/client/java/com/adamcalculator/dynamicpack/include/modmenu/util/DrawingUtil.java new file mode 100644 index 0000000..6435a6f --- /dev/null +++ b/src/client/java/com/adamcalculator/dynamicpack/include/modmenu/util/DrawingUtil.java @@ -0,0 +1,84 @@ +/* +LICENSE: MIT +FILE FROM ModMenu PROJECT +Modrinth: https://modrinth.com/mod/modmenu +GitHub: https://github.com/TerraformersMC/ModMenu + +Big thanks for all ModMenu contributors! + */ + +package com.adamcalculator.dynamicpack.include.modmenu.util; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.terraformersmc.modmenu.config.ModMenuConfig; +import com.terraformersmc.modmenu.util.mod.Mod; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.OrderedText; +import net.minecraft.text.StringVisitable; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.Language; +import net.minecraft.util.math.MathHelper; + +import java.util.List; +import java.util.Random; + + +@Environment(EnvType.CLIENT) +public class DrawingUtil { + private static final MinecraftClient CLIENT = MinecraftClient.getInstance(); + + public static void drawRandomVersionBackground(Mod mod, DrawContext DrawContext, int x, int y, int width, int height) { + int seed = mod.getName().hashCode() + mod.getVersion().hashCode(); + Random random = new Random(seed); + int color = 0xFF000000 | MathHelper.hsvToRgb(random.nextFloat(1f), random.nextFloat(0.7f, 0.8f), 0.9f); + if (!ModMenuConfig.RANDOM_JAVA_COLORS.getValue()) { + color = 0xFFDD5656; + } + RenderSystem.setShaderColor(1f, 1f, 1f, 1f); + DrawContext.fill(x, y, x + width, y + height, color); + } + + public static void drawWrappedString(DrawContext DrawContext, String string, int x, int y, int wrapWidth, int lines, int color) { + while (string != null && string.endsWith("\n")) { + string = string.substring(0, string.length() - 1); + } + List strings = CLIENT.textRenderer.getTextHandler().wrapLines(Text.literal(string), wrapWidth, Style.EMPTY); + for (int i = 0; i < strings.size(); i++) { + if (i >= lines) { + break; + } + StringVisitable renderable = strings.get(i); + if (i == lines - 1 && strings.size() > lines) { + renderable = StringVisitable.concat(strings.get(i), StringVisitable.plain("...")); + } + OrderedText line = Language.getInstance().reorder(renderable); + int x1 = x; + if (CLIENT.textRenderer.isRightToLeft()) { + int width = CLIENT.textRenderer.getWidth(line); + x1 += (float) (wrapWidth - width); + } + DrawContext.drawText(CLIENT.textRenderer, line, x1, y + i * CLIENT.textRenderer.fontHeight, color, false); + } + } + + public static void drawBadge(DrawContext DrawContext, int x, int y, int tagWidth, OrderedText text, int outlineColor, int fillColor, int textColor) { + DrawContext.fill(x + 1, y - 1, x + tagWidth, y, outlineColor); + DrawContext.fill(x, y, x + 1, y + CLIENT.textRenderer.fontHeight, outlineColor); + DrawContext.fill(x + 1, y + 1 + CLIENT.textRenderer.fontHeight - 1, x + tagWidth, y + CLIENT.textRenderer.fontHeight + 1, outlineColor); + DrawContext.fill( x + tagWidth, y, x + tagWidth + 1, y + CLIENT.textRenderer.fontHeight, outlineColor); + DrawContext.fill( x + 1, y, x + tagWidth, y + CLIENT.textRenderer.fontHeight, fillColor); + DrawContext.drawText(CLIENT.textRenderer, text, (int) (x + 1 + (tagWidth - CLIENT.textRenderer.getWidth(text)) / (float) 2), y + 1, textColor, false); + } + + /** + * @author AdamCalculator + * no part of oroginal ModMenu file + */ + public static void runAtUI(Runnable o) { + MinecraftClient.getInstance().executeSync(o); + } +}