package me.nallar.tickthreading.minecraft;

import java.util.Map;

import me.nallar.tickthreading.Log;
import net.minecraft.world.World;

public class DeadLockDetector {
	public static String lastJob = "";
	private final Map<World, TickManager> managerMap;
	private final Thread deadlockThread;

	public DeadLockDetector(Map<World, TickManager> managerMap) {
		this.managerMap = managerMap;
		deadlockThread = new Thread(new Runnable() {
			@Override
			public void run() {
				while (checkForDeadlocks()) {
					try {
						Thread.sleep(4000);
					} catch (InterruptedException ignored) {
					}
				}
			}
		});
		deadlockThread.setDaemon(true);
		deadlockThread.setName("Deadlock Detector");
		deadlockThread.start();
	}

	public boolean checkForDeadlocks() {
		long lastRunTime = 0;
		for (TickManager tickManager : managerMap.values()) {
			lastRunTime = Math.max(lastRunTime, tickManager.lastStartTime);
		}
		if (lastRunTime == 0) {
			return true;
		}
		int deadTime = (int) (System.currentTimeMillis() - lastRunTime);
		if (deadTime > 10000) {
			StringBuilder sb = new StringBuilder();
			sb.append("The server appears to have deadlocked!")
					.append("\nTicking: ").append(lastJob).append('\n');
			Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces();
			for (Map.Entry<Thread, StackTraceElement[]> entry : traces.entrySet()) {
				Thread thread = entry.getKey();
				sb.append("Current Thread: ").append(thread.getName()).append('\n').append("    PID: ").append(thread.getId())
						.append(" | Alive: ").append(thread.isAlive()).append(" | State: ").append(thread.getState())
						.append("    Stack:").append('\n');
				for (StackTraceElement stackTraceElement : entry.getValue()) {
					sb.append("        ").append(stackTraceElement.toString()).append('\n');
				}
			}
			Log.severe(sb.toString());
			return false;
		}
		return true;
	}
}

@@ -61,16 +61,43 @@
 il.Map;%0D
+%0Aimport java.util.TreeMap;%0D
 %0A%0D%0Aimpor
@@ -1114,16 +1114,91 @@
 000) %7B%0D%0A
+%09%09%09TreeMap%3CString, Thread%3E sortedThreads = new TreeMap%3CString, Thread%3E();%0D%0A
 %09%09%09Strin
@@ -1233,16 +1233,16 @@
 der();%0D%0A
-
 %09%09%09sb.ap
@@ -1434,52 +1434,21 @@
 or (
-Map.Entry%3CThread, StackTraceElement%5B%5D%3E entry
+Thread thread
  : t
@@ -1453,20 +1453,18 @@
  traces.
+k
 e
-ntr
 ySet()) 
@@ -1474,39 +1474,109 @@
 %09%09%09%09
-Thread thread = entry.getKey();
+sortedThreads.put(thread.getName(), thread);%0D%0A%09%09%09%7D%0D%0A%09%09%09for (Thread thread : sortedThreads.values()) %7B
 %0D%0A%09%09
@@ -1884,21 +1884,27 @@
 t : 
-entry.getValu
+thread.getStackTrac
 e())

Order deadlock log by thread name