|
| 1 | +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| 2 | +From: MidnightTale < [email protected]> |
| 3 | +Date: Sat, 26 Jul 2025 18:08:18 +0700 |
| 4 | +Subject: [PATCH] Add more logging detail to Cycle Detection |
| 5 | + |
| 6 | + |
| 7 | +diff --git a/net/minecraft/util/Graph.java b/net/minecraft/util/Graph.java |
| 8 | +index 698420895bb556fe28518b97ec9799adda25ada4..ff1b619fa3da44cba0ada0048634e82022150d1b 100644 |
| 9 | +--- a/net/minecraft/util/Graph.java |
| 10 | ++++ b/net/minecraft/util/Graph.java |
| 11 | +@@ -9,24 +9,30 @@ public final class Graph { |
| 12 | + private Graph() { |
| 13 | + } |
| 14 | + |
| 15 | +- public static <T> boolean depthFirstSearch(Map<T, Set<T>> graph, Set<T> nonCyclicalNodes, Set<T> pathSet, Consumer<T> onNonCyclicalNodeFound, T currentNode) { |
| 16 | ++ public static <T> java.util.List<T> depthFirstSearch(Map<T, Set<T>> graph, Set<T> nonCyclicalNodes, Set<T> pathSet, Consumer<T> onNonCyclicalNodeFound, T currentNode) { |
| 17 | + if (nonCyclicalNodes.contains(currentNode)) { |
| 18 | +- return false; |
| 19 | ++ return java.util.Collections.emptyList(); |
| 20 | + } else if (pathSet.contains(currentNode)) { |
| 21 | +- return true; |
| 22 | ++ return java.util.List.of(currentNode); |
| 23 | + } else { |
| 24 | + pathSet.add(currentNode); |
| 25 | + |
| 26 | + for (T object : graph.getOrDefault(currentNode, ImmutableSet.of())) { |
| 27 | +- if (depthFirstSearch(graph, nonCyclicalNodes, pathSet, onNonCyclicalNodeFound, object)) { |
| 28 | +- return true; |
| 29 | ++ java.util.List<T> cycle = depthFirstSearch(graph, nonCyclicalNodes, pathSet, onNonCyclicalNodeFound, object); |
| 30 | ++ if (!cycle.isEmpty()) { |
| 31 | ++ if (cycle.get(0).equals(currentNode)) { |
| 32 | ++ return cycle; |
| 33 | ++ } |
| 34 | ++ java.util.List<T> ret = new java.util.ArrayList<>(cycle); |
| 35 | ++ ret.add(0, currentNode); |
| 36 | ++ return ret; |
| 37 | + } |
| 38 | + } |
| 39 | + |
| 40 | + pathSet.remove(currentNode); |
| 41 | + nonCyclicalNodes.add(currentNode); |
| 42 | + onNonCyclicalNodeFound.accept(currentNode); |
| 43 | +- return false; |
| 44 | ++ return java.util.Collections.emptyList(); |
| 45 | + } |
| 46 | + } |
| 47 | + } |
| 48 | +diff --git a/net/minecraft/world/level/biome/FeatureSorter.java b/net/minecraft/world/level/biome/FeatureSorter.java |
| 49 | +index 8b81b5e010b974a0319ef47a897814e30e1e9e63..b5cd0f2de9af9ba9830fd57f29fe0889b7663702 100644 |
| 50 | +--- a/net/minecraft/world/level/biome/FeatureSorter.java |
| 51 | ++++ b/net/minecraft/world/level/biome/FeatureSorter.java |
| 52 | +@@ -67,33 +67,29 @@ public class FeatureSorter { |
| 53 | + throw new IllegalStateException("You somehow broke the universe; DFS bork (iteration finished with non-empty in-progress vertex set"); |
| 54 | + } |
| 55 | + |
| 56 | +- if (!set1.contains(featureData) && Graph.depthFirstSearch(map1, set1, set2, list::add, featureData)) { |
| 57 | +- if (!notRecursiveFlag) { |
| 58 | +- throw new IllegalStateException("Feature order cycle found"); |
| 59 | +- } |
| 60 | +- |
| 61 | +- List<T> list2 = new ArrayList<>(featureSetSources); |
| 62 | +- |
| 63 | +- int size; |
| 64 | +- do { |
| 65 | +- size = list2.size(); |
| 66 | +- ListIterator<T> listIterator = list2.listIterator(); |
| 67 | +- |
| 68 | +- while (listIterator.hasNext()) { |
| 69 | +- T object1 = listIterator.next(); |
| 70 | +- listIterator.remove(); |
| 71 | +- |
| 72 | +- try { |
| 73 | +- buildFeaturesPerStep(list2, toFeatueSetFunction, false); |
| 74 | +- } catch (IllegalStateException var18) { |
| 75 | +- continue; |
| 76 | ++ java.util.List<FeatureData> cycle = Graph.depthFirstSearch(map1, set1, set2, list::add, featureData); |
| 77 | ++ if (!cycle.isEmpty()) { |
| 78 | ++ if (notRecursiveFlag) { |
| 79 | ++ List<T> list2 = new ArrayList<>(featureSetSources); |
| 80 | ++ int i1; |
| 81 | ++ do { |
| 82 | ++ i1 = list2.size(); |
| 83 | ++ ListIterator<T> listiterator = list2.listIterator(); |
| 84 | ++ while (listiterator.hasNext()) { |
| 85 | ++ T t0 = listiterator.next(); |
| 86 | ++ listiterator.remove(); |
| 87 | ++ try { |
| 88 | ++ buildFeaturesPerStep(list2, toFeatueSetFunction, false); |
| 89 | ++ } catch (IllegalStateException illegalstateexception) { |
| 90 | ++ continue; |
| 91 | ++ } |
| 92 | ++ listiterator.add(t0); |
| 93 | + } |
| 94 | +- |
| 95 | +- listIterator.add(object1); |
| 96 | +- } |
| 97 | +- } while (size != list2.size()); |
| 98 | +- |
| 99 | +- throw new IllegalStateException("Feature order cycle found, involved sources: " + list2); |
| 100 | ++ } while (i1 != list2.size()); |
| 101 | ++ throw new IllegalStateException("Feature order cycle found, involved sources: " + list2); |
| 102 | ++ } |
| 103 | ++ final java.util.stream.Stream<String> cycleStream = cycle.stream().map(d -> d.feature).map(net.minecraft.data.worldgen.placement.PlacementUtils::getKey).filter(java.util.Optional::isPresent).map(java.util.Optional::get).map(key -> key.location().toString()); |
| 104 | ++ throw new IllegalStateException("Feature order cycle found, cycle includes: " + cycleStream.collect(Collectors.joining(", "))); |
| 105 | + } |
| 106 | + } |
| 107 | + |
0 commit comments