Skip to content

Commit

Permalink
1.20.4
Browse files Browse the repository at this point in the history
  • Loading branch information
NatanLifshitz committed Feb 5, 2024
1 parent 06fdf43 commit b74d457
Show file tree
Hide file tree
Showing 19 changed files with 340 additions and 270 deletions.
2 changes: 1 addition & 1 deletion TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ To test in production, build the test Fabric/Forge mod and add them alongside NE
` - Verify:
- The game crashes.
- The crash screen appears.
- No mods are blamed.
- "Not Enough Crashes Test Mod" is blamed.
- In the terminal, no information is repeated.
- Verify in the **Log**, **TXT File**, and **Get Link Site**:
- No information is repeated.
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
alias libs.plugins.architectury.loom apply false
alias libs.plugins.loom.quiltflower apply false
// alias libs.plugins.loom.quiltflower apply false
alias libs.plugins.minotaur apply false
alias libs.plugins.architectury.plugin
alias libs.plugins.cursegradle
Expand All @@ -16,7 +16,7 @@ subprojects {
apply plugin: 'maven-publish'
apply plugin: 'com.matthewprenger.cursegradle'
// apply plugin: "com.modrinth.minotaur"
apply plugin: "io.github.juuxel.loom-quiltflower"
// apply plugin: "io.github.juuxel.loom-quiltflower"

dependencies {
minecraft libs.minecraft
Expand Down
10 changes: 10 additions & 0 deletions common/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
plugins {
id 'org.jetbrains.kotlin.jvm'
}
dependencies {
// We depend on fabric loader here to use the fabric @Environment annotations
// Do NOT use other classes from fabric loader
modImplementation libs.fabric.loader
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}

configurations {
Expand All @@ -15,3 +19,9 @@ artifacts {
architectury {
common("fabric","forge")
}
repositories {
mavenCentral()
}
kotlin {
jvmToolchain(17)
}
414 changes: 199 additions & 215 deletions common/src/main/java/fudge/notenoughcrashes/config/MidnightConfig.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fudge.notenoughcrashes.gui;

import fudge.notenoughcrashes.config.NecConfig;
import fudge.notenoughcrashes.mixinhandlers.InGameCatcher;
import fudge.notenoughcrashes.utils.NecLocalization;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
Expand All @@ -27,7 +28,10 @@ public void init() {
super.init();
ButtonWidget mainMenuButton = ButtonWidget.builder(
NecLocalization.translatedText("gui.toTitle"),
button -> MinecraftClient.getInstance().setScreen(new TitleScreen())
button -> {
InGameCatcher.crashScreenActive = true;
MinecraftClient.getInstance().setScreen(new TitleScreen());
}
)
.dimensions(width / 2 - 155, height / 4 + 120 + 12, 150, 20)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,7 @@ private void handleLegacyLinkClick(ButtonWidget buttonWidget) {
if (uploadedCrashLink == null) {
uploadedCrashLink = LegacyCrashLogUpload.upload(report.asString());
}
MinecraftClient.getInstance().setScreen(new ConfirmLinkScreen(b -> {
if (b) {
Util.getOperatingSystem().open(uploadedCrashLink);
}

MinecraftClient.getInstance().setScreen(construct(report));
}, uploadedCrashLink, true));
Util.getOperatingSystem().open(uploadedCrashLink);
} catch (Throwable e) {
NotEnoughCrashes.getLogger().error("Exception when crash menu button clicked:", e);
buttonWidget.setMessage(NecLocalization.translatedText("notenoughcrashes.gui.failed"));
Expand Down Expand Up @@ -139,7 +133,8 @@ public void init() {
addDrawableChild(
ButtonWidget.builder(
NecLocalization.translatedText("notenoughcrashes.gui.getLink")
.copy().setStyle(Style.EMPTY.withColor(GRAY))
// No longer grayed out because Crashy is not working ATM
// .copy().setStyle(Style.EMPTY.withColor(GRAY))
, this::handleLegacyLinkClick)
.dimensions(width / 2 - 155 + 160, height / 4 + 144 + 12, 150, 20)
.build()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package fudge.notenoughcrashes.mixinhandlers;

import fudge.notenoughcrashes.config.NecConfig;
import fudge.notenoughcrashes.NotEnoughCrashes;
import fudge.notenoughcrashes.StateManager;
import fudge.notenoughcrashes.config.NecConfig;
import fudge.notenoughcrashes.gui.CrashScreen;
import fudge.notenoughcrashes.patches.MinecraftClientAccess;
import fudge.notenoughcrashes.stacktrace.CrashUtils;
Expand All @@ -24,14 +24,15 @@ public class InGameCatcher {

private static int clientCrashCount = 0;
private static int serverCrashCount = 0;
public static boolean crashScreenActive = false;

public static void handleClientCrash(CrashReport report) {
clientCrashCount++;
addInfoToCrash(report);

resetStates();
boolean reported = report.getCause() instanceof CrashException;
LOGGER.fatal(reported ? "Reported" : "Unreported" + " exception thrown!", report.getCause());
// boolean reported = report.getCause() instanceof CrashException;
// LOGGER.fatal(reported ? "Reported" : "Unreported" + " exception thrown!", report.getCause());
displayCrashScreen(report, clientCrashCount, true);
// Continue game loop
getClient().run();
Expand Down Expand Up @@ -66,6 +67,9 @@ private static void resetCriticalGameState() {
}
client.player = null;
client.world = null;

var server = client.getServer();
if (server != null) server.stop(true);
}

private static void resetModState() {
Expand All @@ -90,6 +94,7 @@ public static void addInfoToCrash(CrashReport report) {
}

private static void displayCrashScreen(CrashReport report, int crashCount, boolean clientCrash) {
crashScreenActive = true;
try {
if (EntryPointCatcher.crashedDuringStartup()) {
throw new IllegalStateException("Could not initialize startup crash screen");
Expand All @@ -107,9 +112,10 @@ private static void displayCrashScreen(CrashReport report, int crashCount, boole
// Display the crash screen
getClient().setScreen(new CrashScreen(report));
} catch (Throwable t) {
crashScreenActive = false;
// The crash screen has crashed. Report it normally instead.
LOGGER.error("An uncaught exception occured while displaying the crash screen, making normal report instead", t);
MinecraftClient.printCrashReport(report);
getClient().printCrashReport(report);
System.exit(report.getFile() != null ? -1 : -2);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package fudge.notenoughcrashes.mixins.client;

import fudge.notenoughcrashes.mixinhandlers.InGameCatcher;
import net.minecraft.client.Keyboard;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(Keyboard.class)
public class MixinKeyboard {
/**
* pollDebugCrash() keeps crashing the game when we display the crash screen, infinitely times over,
* so we need to stop it from crashing after it has done its job just once.
*/
@Inject(method = "pollDebugCrash()V", at = @At("HEAD"), cancellable = true)
public void pollDebugCrashDontCrashInfinitely(CallbackInfo ci) {
if (InGameCatcher.crashScreenActive) ci.cancel();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package fudge.notenoughcrashes.mixins.client;

import fudge.notenoughcrashes.NotEnoughCrashes;
import fudge.notenoughcrashes.gui.InitErrorScreen;
import fudge.notenoughcrashes.mixinhandlers.EntryPointCatcher;
import fudge.notenoughcrashes.mixinhandlers.InGameCatcher;
import fudge.notenoughcrashes.patches.MinecraftClientAccess;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.crash.CrashReport;
import net.minecraft.util.profiler.Recorder;
import net.minecraft.util.thread.ReentrantThreadExecutor;
Expand All @@ -20,6 +22,7 @@

import java.util.Queue;
import java.util.function.Supplier;
//TODO: infinite repeating crashes in different cases, need to go over the crash cases and solve them one by one.


@Mixin(MinecraftClient.class)
Expand All @@ -36,7 +39,7 @@ public abstract class MixinMinecraftClient extends ReentrantThreadExecutor<Runna
private Recorder recorder;

@Shadow
public static void printCrashReport(CrashReport report) {
public void printCrashReport(CrashReport report) {
}

@Override
Expand All @@ -53,13 +56,27 @@ public MixinMinecraftClient(String string_1) {
super(string_1);
}

/**
* If the game has crashed, we set the screen to the init crash screen, but then Minecraft sets the screen back
* to the title screen. We want to prevent that, to keep the screen to be the InitCrashScreen
*/
@Inject(method = "setScreen(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At("HEAD"), cancellable = true)
private void setScreenDontResetCrashScreen(Screen screen, CallbackInfo ci) {
if (EntryPointCatcher.crashedDuringStartup() && !(screen instanceof InitErrorScreen)) ci.cancel();
}

@Inject(method = "run()V", at = @At("HEAD"))
private void beforeRun(CallbackInfo ci) {
if (EntryPointCatcher.crashedDuringStartup()) EntryPointCatcher.displayInitErrorScreen();
}

@Inject(method = "run()V", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;crashReportSupplier:Ljava/util/function/Supplier;"))
private void onRunLoop(CallbackInfo ci) {
// @Inject(method = "run()V", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;crashReportSupplier:Ljava/util/function/Supplier;"))
// private void onRunLoop(CallbackInfo ci) {
//
// }

@Inject(method = "printCrashReport()V", at = @At("HEAD"))
private void onCheckGameCrashed(CallbackInfo ci) {
if (!NotEnoughCrashes.enableGameloopCatching()) return;

if (this.crashReportSupplier != null) {
Expand All @@ -73,7 +90,7 @@ private void onRunLoop(CallbackInfo ci) {


// Can't capture arg in inject so captured here
@ModifyArg(method = "run()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;printCrashReport(Lnet/minecraft/util/crash/CrashReport;)V", ordinal = 1))
@ModifyArg(method = "run()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;printCrashReport(Lnet/minecraft/util/crash/CrashReport;)V", ordinal = 0))
private CrashReport atTheEndOfFirstCatchBeforePrintingCrashReport(CrashReport report) {
if (!NotEnoughCrashes.enableGameloopCatching()) return report;

Expand All @@ -84,7 +101,7 @@ private CrashReport atTheEndOfFirstCatchBeforePrintingCrashReport(CrashReport re
}

// Can't capture arg in inject so captured here
@ModifyArg(method = "run()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;printCrashReport(Lnet/minecraft/util/crash/CrashReport;)V", ordinal = 2))
@ModifyArg(method = "run()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;printCrashReport(Lnet/minecraft/util/crash/CrashReport;)V", ordinal = 1))
private CrashReport atTheEndOfSecondCatchBeforePrintingCrashReport(CrashReport report) {
if (!NotEnoughCrashes.enableGameloopCatching()) return report;

Expand All @@ -94,11 +111,11 @@ private CrashReport atTheEndOfSecondCatchBeforePrintingCrashReport(CrashReport r
return report;
}

// Prevent calling printCrashReport which is not needed
@Inject(method = "run()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;printCrashReport(Lnet/minecraft/util/crash/CrashReport;)V"), cancellable = true)
private void cancelRunLoopAfterCrash(CallbackInfo ci) {
if (NotEnoughCrashes.enableGameloopCatching()) ci.cancel();
}
// // Prevent calling printCrashReport which is not needed
// @Inject(method = "run()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;printCrashReport(Lnet/minecraft/util/crash/CrashReport;)V"), cancellable = true)
// private void cancelRunLoopAfterCrash(CallbackInfo ci) {
// if (NotEnoughCrashes.enableGameloopCatching()) ci.cancel();
// }

@Inject(method = "cleanUpAfterCrash()V", at = @At("HEAD"))
private void beforeCleanUpAfterCrash(CallbackInfo info) {
Expand All @@ -108,18 +125,16 @@ private void beforeCleanUpAfterCrash(CallbackInfo info) {
}
//String levelName, LevelStorage.Session session, ResourcePackManager dataPackManager, SaveLoader saveLoader

/**
* Prevent the integrated server from exiting in the case it crashed
*/
@Redirect(method = "startIntegratedServer(" +
"Ljava/lang/String;Lnet/minecraft/world/level/storage/LevelStorage$Session;" +
"Lnet/minecraft/resource/ResourcePackManager;" +
"Lnet/minecraft/server/SaveLoader;" +
")V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;printCrashReport(Lnet/minecraft/util/crash/CrashReport;)V"))
private void redirectPrintCrashReport(CrashReport report) {
if (!NotEnoughCrashes.enableGameloopCatching()) printCrashReport(report);
}
//TODO: test this: maybe we don't need this mixin anymore?

// /**
// * Prevent the integrated server from exiting in the case it crashed
// */
// @Redirect(method = "startIntegratedServer(Lnet/minecraft/world/level/storage/LevelStorage$Session;Lnet/minecraft/resource/ResourcePackManager;Lnet/minecraft/server/SaveLoader;Z)V",
// at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;printCrashReport(Lnet/minecraft/util/crash/CrashReport;)V"))
// private void redirectPrintCrashReport(CrashReport report) {
// if (!NotEnoughCrashes.enableGameloopCatching()) printCrashReport(report);
// }

/**
* Forge only: Prevent the integrated server from exiting in the case it crashed in another case
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fudge.notenoughcrashes.mixins.client;

import net.minecraft.server.MinecraftServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
//
///**
// * Mixin to stop the integrated server from ticking when the game has crashed
// */
//@Mixin(MinecraftServer.class)
//public class MixinMinecraftServer {
// @Inject(method = "Lnet/minecraft/server/MinecraftServer;shouldKeepTicking()Z", at = @At("HEAD"), cancellable = true)
// public void shouldKeepTickingStopTickOnCrash() {
//
// }
//}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ private static String localizeCustom(String translationKey, String languageCode)
}

public static Text translatedText(String translationKey) {
if (useCustomLocalization) return Text.of(localize(translationKey));
if (useCustomLocalization && translationKey.startsWith(NotEnoughCrashes.MOD_ID)) return Text.of(localize(translationKey));
else return Text.translatable(translationKey);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"notenoughcrashes.gui.getLink": "Show crash log (old)",
"notenoughcrashes.gui.uploadToCrashy": "Show crash log",
"notenoughcrashes.gui.getLink": "Show crash log",
"notenoughcrashes.gui.uploadToCrashy": "Upload to Crashy",
"notenoughcrashes.gui.loadingCrashyUpload": "Uploading...",
"notenoughcrashes.gui.failed": "[Failed, Report to NEC]",
"notenoughcrashes.gui.keepPlaying": "Keep playing",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions common/src/main/resources/notenoughcrashes.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
],
"client": [
"client.MixinBufferBuilder",
"client.MixinKeyboard",
"client.MixinMinecraftClient",
"client.MixinMinecraftServerClientOnly"
]
Expand Down
4 changes: 2 additions & 2 deletions fabric/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ dependencies {
// For config modmenu integration.
modCompileOnly("com.terraformersmc:modmenu:6.2.2")
modCompileOnly "maven.modrinth:iris:1.6.1+1.19.2"
modRuntimeOnly("com.terraformersmc:modmenu:7.1.0")
modRuntimeOnly libs.modmenu

// Uncomment to add the test mod at runtime
// runtimeOnly project(path: ":TestFabricMod", configuration: "namedElements")
runtimeOnly project(path: ":TestFabricMod", configuration: "namedElements")

common(project(path: ":common", configuration: "namedElements")) { transitive false }
shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -63,11 +64,22 @@ public boolean isDevelopmentEnvironment() {
return FabricLoader.getInstance().isDevelopmentEnvironment();
}

private Path getResourcesDirectory() {
Path fabricPath = NotEnoughCrashes.getMetadata().rootPath();
if (isDevelopmentEnvironment()) {
// Replace \ with / for it to work on all platforms
// The assets are usually in the common build folder in dev and not in the fabric builder folder, so we use the common one instead.
return Paths.get(fabricPath.toString().replace("\\", "/").replace("/fabric/build", "/common/build"));
} else {
return fabricPath;
}
}

@Override
@Nullable
public InputStream getResource(Path relativePath) {
// Don't resolve the root path directly with a normal Path, they are incompatible because the root path is often in a Zip FS
Path path = NotEnoughCrashes.getMetadata().rootPath().resolve(relativePath.toString());
Path path = getResourcesDirectory().resolve(relativePath.toString());
if (!Files.exists(path)) return null;
else {
try {
Expand Down
Loading

0 comments on commit b74d457

Please sign in to comment.