Skip to content

Commit

Permalink
Enhance mod loading to respect dependency declarations starting with …
Browse files Browse the repository at this point in the history
…`~` which indicates dependencies that don't affect mod loading order. Relates to issues demodude4u#37 and demodude4u#42.
  • Loading branch information
FactorioBlueprints committed Jan 3, 2023
1 parent 7165867 commit 9028a2a
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 14 deletions.
69 changes: 56 additions & 13 deletions FactorioDataWrapper/src/com/demod/factorio/ModInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,66 @@

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.json.JSONArray;
import org.json.JSONObject;

public class ModInfo {
public static final Pattern DEPENDENCY_REGEX = Pattern.compile(
"(^(?:(\\?|\\(\\?\\)|!|~) *)?(.+?)(?: *([<>=]=?) *([0-9.]+))?$)");

// https://wiki.factorio.com/Tutorial:Mod_structure#dependencies
public static enum DependencyType {
// ! for incompatibility
INCOMPATIBLE,
// ? for an optional dependency
OPTIONAL,
// (?) for a hidden optional dependency
HIDDEN_OPTIONAL,
// ~ for a dependency that does not affect load order
DOES_NOT_AFFECT_LOAD_ORDER,
// no prefix for a hard requirement for the other mod.
REQUIRED,
;

private static DependencyType fromSymbol(String symbol) {
if (symbol == null) {
return REQUIRED;
}
switch (symbol) {
case "!":
return INCOMPATIBLE;
case "?":
return OPTIONAL;
case "(?)":
return HIDDEN_OPTIONAL;
case "~":
return DOES_NOT_AFFECT_LOAD_ORDER;
default:
throw new RuntimeException("Invalid dependency symbol: " + symbol);
}
}
}

public static class Dependency {
private final boolean optional;
private final DependencyType type;
private final String name;
private final String conditional;
private final String version;

private Dependency(boolean optional, String name, String conditional, String version) {
this.optional = optional;
private Dependency(DependencyType type, String name, String conditional, String version) {
this.type = type;
this.name = name;
this.conditional = conditional;
this.version = version;
}

public DependencyType getType() {
return this.type;
}

public String getConditional() {
return conditional;
}
Expand All @@ -33,7 +75,7 @@ public String getVersion() {
}

public boolean isOptional() {
return optional;
return this.type == DependencyType.OPTIONAL || this.type == DependencyType.HIDDEN_OPTIONAL;
}
}

Expand All @@ -60,15 +102,16 @@ public ModInfo(JSONObject json) {
}
for (int i = 0; i < dependenciesJson.length(); i++) {
String depString = dependenciesJson.getString(i);
String[] depSplit = depString.split("\\s");
if (depSplit.length == 1) {
dependencies.add(new Dependency(false, depSplit[0], null, null));
} else if (depSplit.length == 2) {
dependencies.add(new Dependency(true, depSplit[1], null, null));
} else if (depSplit.length == 3) {
dependencies.add(new Dependency(false, depSplit[0], depSplit[1], depSplit[2]));
} else if (depSplit.length == 4) {
dependencies.add(new Dependency(true, depSplit[1], depSplit[2], depSplit[3]));
Matcher matcher = DEPENDENCY_REGEX.matcher(depString);
if (matcher.matches()) {
String symbol = matcher.group(2);
DependencyType type = DependencyType.fromSymbol(symbol);
String name = matcher.group(3);
String conditional = matcher.group(4);
String version = matcher.group(5);
dependencies.add(new Dependency(type, name, conditional, version));
} else {
throw new RuntimeException("Invalid dependency string: " + depString);
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion FactorioDataWrapper/src/com/demod/factorio/ModLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import org.json.JSONException;

import com.demod.factorio.ModInfo.Dependency;
import com.demod.factorio.ModInfo.DependencyType;

import com.google.common.io.ByteStreams;

public class ModLoader {
Expand Down Expand Up @@ -145,7 +147,7 @@ public List<Mod> getModsInLoadOrder() {
for (Dependency dependency : mod.getInfo().getDependencies()) {
String depName = dependency.getName();
if (getMod(depName).isPresent()) {
if (!order.contains(depName)) {
if (!order.contains(depName) && dependency.getType() != DependencyType.DOES_NOT_AFFECT_LOAD_ORDER) {
missingDep = true;
break;
}
Expand Down

0 comments on commit 9028a2a

Please sign in to comment.