Passed
Branch dev (9bb1d9)
by Etienne
01:47
created

runOverride(CallbackInfo)   C

Complexity

Conditions 9

Size

Total Lines 76
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 51
dl 0
loc 76
rs 6.2703
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
package de.pewpewproject.lasertag.mixin;
2
3
import com.google.common.collect.Streams;
4
import com.mojang.logging.LogUtils;
5
import de.pewpewproject.lasertag.LasertagMod;
6
import net.minecraft.Bootstrap;
7
import net.minecraft.server.dedicated.DedicatedServerWatchdog;
8
import net.minecraft.util.Util;
9
import net.minecraft.util.crash.CrashReport;
10
import net.minecraft.util.crash.CrashReportSection;
11
import net.minecraft.util.registry.RegistryKey;
12
import net.minecraft.world.GameRules;
13
import org.spongepowered.asm.mixin.Mixin;
14
import org.spongepowered.asm.mixin.injection.At;
15
import org.spongepowered.asm.mixin.injection.Inject;
16
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
17
18
import java.io.File;
19
import java.lang.management.ManagementFactory;
20
import java.lang.management.ThreadInfo;
21
import java.lang.management.ThreadMXBean;
22
import java.util.Locale;
23
import java.util.stream.Collectors;
24
25
/**
26
 * Mixin into the DedicatedServerWatchdog.class to disable the watchdog during map load
27
 *
28
 * @author Étienne Muser
29
 */
30
@Mixin(DedicatedServerWatchdog.class)
31
public abstract class DedicatedServerWatchdogMixin {
32
33
    private boolean isIgnoring = false;
34
35
    @Inject(method = "run()V", at = @At("HEAD"), cancellable = true)
36
    private void runOverride(CallbackInfo ci) {
37
38
        var thisWD = ((DedicatedServerWatchdog) (Object) this);
39
40
        while (thisWD.server.isRunning()) {
41
42
            // Get the game managers
43
            var gameManager = thisWD.server.getOverworld().getServerLasertagManager();
44
            var arenaManager = gameManager.getArenaManager();
45
46
            // If map is loading, ignore
47
            if (arenaManager.isLoading()) {
48
                this.isIgnoring = true;
49
            }
50
51
            long lastServerTimeReference = ((DedicatedServerWatchdog) (Object) this).server.getTimeReference();
52
            long now = Util.getMeasuringTimeMs();
53
54
55
            long difference = now - lastServerTimeReference;
56
            if (difference > ((DedicatedServerWatchdog) (Object) this).maxTickTime) {
57
                if (!this.isIgnoring) {
58
59
                    DedicatedServerWatchdog.LOGGER.error(LogUtils.FATAL_MARKER, "A single server tick took {} seconds (should be max {})", String.format(Locale.ROOT, "%.2f", (float) difference / 1000.0F), String.format(Locale.ROOT, "%.2f", 0.05F));
60
                    DedicatedServerWatchdog.LOGGER.error(LogUtils.FATAL_MARKER, "Considering it to be crashed, server will forcibly shutdown.");
61
                    ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
62
                    ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true);
63
                    StringBuilder stringBuilder = new StringBuilder();
64
                    Error error = new Error("Watchdog");
65
                    ThreadInfo[] var11 = threadInfos;
66
                    int var12 = threadInfos.length;
67
68
                    for (int var13 = 0; var13 < var12; ++var13) {
69
                        ThreadInfo threadInfo = var11[var13];
70
                        if (threadInfo.getThreadId() == ((DedicatedServerWatchdog) (Object) this).server.getThread().getId()) {
71
                            error.setStackTrace(threadInfo.getStackTrace());
72
                        }
73
74
                        stringBuilder.append(threadInfo);
75
                        stringBuilder.append("\n");
76
                    }
77
78
                    CrashReport crashReport = new CrashReport("Watching Server", error);
79
                    ((DedicatedServerWatchdog) (Object) this).server.addSystemDetails(crashReport.getSystemDetailsSection());
80
                    CrashReportSection crashReportSection = crashReport.addElement("Thread Dump");
81
                    crashReportSection.add("Threads", stringBuilder);
82
                    CrashReportSection crashReportSection2 = crashReport.addElement("Performance stats");
83
                    crashReportSection2.add("Random tick rate", () -> ((DedicatedServerWatchdog) (Object) this).server.getSaveProperties().getGameRules().get(GameRules.RANDOM_TICK_SPEED).toString());
84
                    crashReportSection2.add("Level stats", () -> Streams.stream(((DedicatedServerWatchdog) (Object) this).server.getWorlds()).map((serverWorld) -> {
85
                        RegistryKey var10000 = serverWorld.getRegistryKey();
86
                        return "" + var10000 + ": " + serverWorld.getDebugString();
87
                    }).collect(Collectors.joining(",\n")));
88
                    Bootstrap.println("Crash report:\n" + crashReport.asString());
89
                    File file = new File(new File(((DedicatedServerWatchdog) (Object) this).server.getRunDirectory(), "crash-reports"), "crash-" + Util.getFormattedCurrentTime() + "-server.txt");
90
                    if (crashReport.writeToFile(file)) {
91
                        DedicatedServerWatchdog.LOGGER.error("This crash report has been saved to: {}", file.getAbsolutePath());
92
                    } else {
93
                        DedicatedServerWatchdog.LOGGER.error("We were unable to save this crash report to disk.");
94
                    }
95
96
                    ((DedicatedServerWatchdog) (Object) this).shutdown();
97
                } else {
98
                    // Only ignore the first time
99
                    this.isIgnoring = false;
100
                    LasertagMod.LOGGER.info("Watchdog now not ignoring anymore.");
101
                }
102
            }
103
104
            try {
105
                Thread.sleep(((DedicatedServerWatchdog) (Object) this).maxTickTime);
106
            } catch (InterruptedException ignored) {
107
            }
108
        }
109
110
        ci.cancel();
111
    }
112
}
113