From f375683bcd326d907c265dc7412a5f52b131c00e Mon Sep 17 00:00:00 2001 From: LexManos Date: Thu, 12 Nov 2026 13:13:43 -0800 Subject: [PATCH] Fix Mod Sorting reporting incorrect cycles when sorting fails. Closes #10942 Co-authored-by: ZZZank <47418975+ZZZank@users.noreply.github.com> --- .../StronglyConnectedComponentDetector.java | 54 +++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/toposort/StronglyConnectedComponentDetector.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/toposort/StronglyConnectedComponentDetector.java index f70535b93e..ec3b57188e 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/toposort/StronglyConnectedComponentDetector.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/toposort/StronglyConnectedComponentDetector.java @@ -22,15 +22,18 @@ import java.util.Set; * *

This detector evaluates the graph lazily and won't reflect the modifications in the * graph after initial evaluation. + * + *

Implementation based on Wikipedia Psudocode */ public class StronglyConnectedComponentDetector { private final Graph graph; private final Map ids = new HashMap<>(); private T[] elements; - private int[] dfn; - private int[] low; + private int[] indexes; + private int[] lowlinks; private int[] stack; private int top; + private int index; private BitSet onStack; private Set> components; @@ -58,48 +61,43 @@ public class StronglyConnectedComponentDetector { } final int n = nodes.size(); - dfn = new int[n]; - low = new int[n]; + indexes = new int[n]; + lowlinks = new int[n]; stack = new int[n]; onStack = new BitSet(n); top = -1; + index = 1; for (int i = 0; i < n; i++) { - if (dfn[i] == 0) { - dfs(i, 1); - } + if (indexes[i] == 0) + dfs(i); } } - private void dfs(int now, int depth) { - dfn[now] = depth; - low[now] = depth; - top++; - stack[top] = now; + private void dfs(int now) { + indexes[now] = lowlinks[now] = index++; + stack[++top] = now; onStack.set(now); + for (T each : graph.successors(elements[now])) { int to = ids.get(each); - if (dfn[to] != 0) { - if (low[now] > dfn[to]) { - low[now] = dfn[to]; - } - } else { - dfs(to, depth + 1); - if (low[now] > low[to]) { - low[now] = low[to]; - } + if (indexes[to] == 0) { // 0 is unvisited + dfs(to); + if (lowlinks[now] > lowlinks[to]) + lowlinks[now] = lowlinks[to]; + } else if (onStack.get(to)) { + if (lowlinks[now] > indexes[to]) + lowlinks[now] = indexes[to]; } } - if (dfn[now] == low[now]) { + if (indexes[now] == lowlinks[now]) { Set component = new HashSet<>(); while (top >= 0) { - final int t = stack[top]; - component.add(elements[t]); - onStack.clear(t); - top--; - if (t == now) { + final int w = stack[top--]; + onStack.clear(w); + component.add(elements[w]); + if (w == now) break; - } } components.add(component); }