001 /* 002 * The FML Forge Mod Loader suite. Copyright (C) 2012 cpw 003 * 004 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free 005 * Software Foundation; either version 2.1 of the License, or any later version. 006 * 007 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 008 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 009 * 010 * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 011 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 012 */ 013 package cpw.mods.fml.common.toposort; 014 015 import java.util.Arrays; 016 import java.util.List; 017 import java.util.Map; 018 019 import com.google.common.collect.Lists; 020 021 import cpw.mods.fml.common.DummyModContainer; 022 import cpw.mods.fml.common.Loader; 023 import cpw.mods.fml.common.ModContainer; 024 import cpw.mods.fml.common.toposort.TopologicalSort.DirectedGraph; 025 import cpw.mods.fml.common.versioning.ArtifactVersion; 026 027 /** 028 * @author cpw 029 * 030 */ 031 public class ModSorter 032 { 033 private DirectedGraph<ModContainer> modGraph; 034 035 private ModContainer beforeAll = new DummyModContainer(); 036 private ModContainer afterAll = new DummyModContainer(); 037 private ModContainer before = new DummyModContainer(); 038 private ModContainer after = new DummyModContainer(); 039 040 private List<ModContainer> immutableMods; 041 042 public ModSorter(List<ModContainer> modList, Map<String, ModContainer> nameLookup) 043 { 044 buildGraph(modList, nameLookup); 045 } 046 047 private void buildGraph(List<ModContainer> modList, Map<String, ModContainer> nameLookup) 048 { 049 modGraph = new DirectedGraph<ModContainer>(); 050 immutableMods = Lists.newArrayList(); 051 modGraph.addNode(beforeAll); 052 modGraph.addNode(before); 053 modGraph.addNode(afterAll); 054 modGraph.addNode(after); 055 modGraph.addEdge(before, after); 056 modGraph.addEdge(beforeAll, before); 057 modGraph.addEdge(after, afterAll); 058 059 for (ModContainer mod : modList) 060 { 061 if (!mod.isImmutable()) 062 { 063 modGraph.addNode(mod); 064 } 065 else 066 { 067 immutableMods.add(mod); 068 } 069 } 070 071 for (ModContainer mod : modList) 072 { 073 if (mod.isImmutable()) 074 continue; 075 boolean preDepAdded = false; 076 boolean postDepAdded = false; 077 078 for (ArtifactVersion dep : mod.getDependencies()) 079 { 080 preDepAdded = true; 081 082 String modid = dep.getLabel(); 083 if (modid.equals("*")) 084 { 085 // We are "after" everything 086 modGraph.addEdge(mod, afterAll); 087 modGraph.addEdge(after, mod); 088 postDepAdded = true; 089 } 090 else 091 { 092 modGraph.addEdge(before, mod); 093 if (Loader.isModLoaded(modid)) { 094 modGraph.addEdge(nameLookup.get(modid), mod); 095 } 096 } 097 } 098 099 for (ArtifactVersion dep : mod.getDependants()) 100 { 101 postDepAdded = true; 102 103 String modid = dep.getLabel(); 104 if (modid.equals("*")) 105 { 106 // We are "before" everything 107 modGraph.addEdge(beforeAll, mod); 108 modGraph.addEdge(mod, before); 109 preDepAdded = true; 110 } 111 else 112 { 113 modGraph.addEdge(mod, after); 114 if (Loader.isModLoaded(modid)) { 115 modGraph.addEdge(mod, nameLookup.get(modid)); 116 } 117 } 118 } 119 120 if (!preDepAdded) 121 { 122 modGraph.addEdge(before, mod); 123 } 124 125 if (!postDepAdded) 126 { 127 modGraph.addEdge(mod, after); 128 } 129 } 130 } 131 132 public List<ModContainer> sort() 133 { 134 List<ModContainer> sortedList = TopologicalSort.topologicalSort(modGraph); 135 sortedList.removeAll(Arrays.asList(new ModContainer[] {beforeAll, before, after, afterAll})); 136 immutableMods.addAll(sortedList); 137 return immutableMods; 138 } 139 }