Rewrite part 1 (doesn't work yet)

This commit is contained in:
JFronny 2021-06-10 13:10:12 +02:00
parent fa46b8b78d
commit 68a3bf2d54
No known key found for this signature in database
GPG Key ID: BEC5ACBBD4EE17E5
28 changed files with 582 additions and 448 deletions

View File

@ -4,9 +4,8 @@ repositories {
maven { url = "https://maven.terraformersmc.com/"; name = "ModMenu" }
maven { url = "https://maven.shedaniel.me/"; name = "Cloth Config" }
maven { url = "https://maven.dblsaiko.net/"; name = "Canvas" }
maven { url = 'https://server.bbkr.space/artifactory/libs-release'; name = "Required for canvas" }
maven { url = "https://minecraft.curseforge.com/api/maven"; name = "CurseForge (for canvas)" }
maven { url = 'https://server.bbkr.space/artifactory/libs-release'; name = "LibCD" }
jcenter();
}
dependencies {
@ -20,7 +19,7 @@ dependencies {
modImplementation "com.terraformersmc:modmenu:2.0.0-beta.7"
modApi("me.shedaniel.cloth:cloth-config-fabric:5.+")
modApi("me.shedaniel.cloth:cloth-config-fabric:5.0.34")
modImplementation("grondag:canvas-mc117-1.17:+") {
exclude(group: "me.shedaniel.cloth")
}

View File

@ -14,7 +14,6 @@
"viewDir"
],
"waterVertexWavy": false,
"stringTest": "this is a string",
"numTest": 15.4,
"subcategoryTest": {
"thisIsCool": true,

View File

@ -1,11 +1,9 @@
package io.gitlab.jfronny.respackopts;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import io.gitlab.jfronny.respackopts.abstractions.JfConfigCategory;
import io.gitlab.jfronny.respackopts.abstractions.JfConfigCategoryPrimary;
import io.gitlab.jfronny.respackopts.abstractions.JfConfigCategorySub;
import io.gitlab.jfronny.respackopts.data.*;
import me.shedaniel.clothconfig2.api.ConfigBuilder;
import me.shedaniel.clothconfig2.api.ConfigCategory;
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
@ -17,146 +15,71 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.*;
import net.minecraft.util.Language;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
//TODO fix enums always showing "reset"
//TODO fix booleans and enums not properly loading
public class GuiFactory {
public void buildCategory(JsonObject source, String screenId, JfConfigCategory config, ConfigEntryBuilder entryBuilder, String namePrefix) {
if (!Respackopts.boolVals.containsKey(screenId))
Respackopts.boolVals.put(screenId, new HashMap<>());
if (!Respackopts.numVals.containsKey(screenId))
Respackopts.numVals.put(screenId, new HashMap<>());
if (!Respackopts.strVals.containsKey(screenId))
Respackopts.strVals.put(screenId, new HashMap<>());
if (!Respackopts.enumKeys.containsKey(screenId))
Respackopts.enumKeys.put(screenId, new HashMap<>());
public void buildCategory(ConfigBranch source, String screenId, JfConfigCategory config, ConfigEntryBuilder entryBuilder, String namePrefix) {
String b = "respackopts.field." + screenId;
for (Map.Entry<String, JsonElement> entry : source.entrySet()) {
String n = ("".equals(namePrefix) ? "" : namePrefix + ".") + entry.getKey();
JsonElement e = entry.getValue();
if (e.isJsonPrimitive()) {
JsonPrimitive p = e.getAsJsonPrimitive();
if (p.isBoolean()) {
boolean defaultValue = p.getAsBoolean();
boolean currentValue = defaultValue;
if (Respackopts.boolVals.get(screenId).containsKey(n))
currentValue = Respackopts.boolVals.get(screenId).get(n);
else
Respackopts.boolVals.get(screenId).put(n, defaultValue);
config.addEntry(entryBuilder.startBooleanToggle(getText(n, b), currentValue)
.setDefaultValue(defaultValue)
.setSaveConsumer(v -> Respackopts.boolVals.get(screenId).put(n, v))
.setTooltipSupplier(() -> getTooltip(n, screenId))
.build());
}
else if (p.isNumber()) {
double defaultValue = p.getAsDouble();
Double currentValue = defaultValue;
if (Respackopts.numVals.get(screenId).containsKey(n))
currentValue = Respackopts.numVals.get(screenId).get(n);
else
Respackopts.numVals.get(screenId).put(n, defaultValue);
config.addEntry(entryBuilder.startDoubleField(getText(n, b), currentValue)
.setDefaultValue(defaultValue)
.setSaveConsumer(v -> Respackopts.numVals.get(screenId).put(n, v))
.setTooltipSupplier(() -> getTooltip(n, screenId))
.build());
}
else if (p.isString()) {
String defaultValue = p.getAsString();
String currentValue = defaultValue;
if (Respackopts.strVals.get(screenId).containsKey(n))
currentValue = Respackopts.strVals.get(screenId).get(n);
else
Respackopts.strVals.get(screenId).put(n, defaultValue);
config.addEntry(entryBuilder.startStrField(getText(n, b), currentValue)
.setDefaultValue(defaultValue)
.setSaveConsumer(v -> Respackopts.strVals.get(screenId).put(n, v))
.setTooltipSupplier(() -> getTooltip(n, screenId))
.build());
}
for (Map.Entry<String, Entry<?>> in : source.getEntries()) {
Entry<?> entry = in.getValue();
String n = ("".equals(namePrefix) ? "" : namePrefix + ".") + in.getKey();
if (entry instanceof ConfigBranch e) {
SubCategoryBuilder sc = entryBuilder.startSubCategory(getText(n, "respackopts.title." + screenId));
buildCategory(e, screenId, new JfConfigCategorySub(sc), entryBuilder, n);
sc.setTooltipSupplier(() -> getTooltip(n, screenId));
config.addEntry(sc.build());
}
else if (e.isJsonArray()) {
Set<String> ev = Respackopts.enumKeys.get(screenId).get(n);
Double c = Respackopts.numVals.get(screenId).get(n);
String sel = "";
String def = "";
int i = 0;
for (String s1 : ev) {
if (i == 0) def = s1;
if (c.intValue() == i) sel = s1;
i++;
}
config.addEntry(entryBuilder.startDropdownMenu(getText(n, b), (DropdownBoxEntry.SelectionTopCellElement) DropdownMenuBuilder.TopCellElementBuilder.of(sel, (s) -> s, (s) -> new LiteralText(s)), new DropdownBoxEntry.DefaultSelectionCellCreator())
.setSuggestionMode(false)
.setDefaultValue(def)
.setSelections(() -> ev.iterator())
else if (entry instanceof ConfigBooleanEntry e) {
config.addEntry(entryBuilder.startBooleanToggle(getText(n, b), e.value)
.setDefaultValue(e.defaultValue)
.setSaveConsumer(v -> {
int j = 0;
for (String s1 : ev) {
if (s1.equals(v))
Respackopts.numVals.get(screenId).put(n, (double) j);
j++;
}
/*ConfigBooleanEntry cb = (ConfigBooleanEntry)source.get(e.name);
cb.value = v;
Respackopts.LOGGER.info(cb == e);
Respackopts.LOGGER.info(cb == entry);*/
e.value = v;
})
.setTooltipSupplier(() -> getTooltip(n, screenId))
.build());
}
else if (e.isJsonNull()) {
Respackopts.logger.error("Config definition contains null, skipping that entry");
}
else if (e.isJsonObject()) {
JsonObject data = e.getAsJsonObject();
//Slider
if (data.entrySet().stream().allMatch(s -> "default".equals(s.getKey()) || "min".equals(s.getKey()) || "max".equals(s.getKey())))
{
JsonElement def = data.get("default");
JsonElement min = data.get("min");
JsonElement max = data.get("max");
if (def.isJsonPrimitive() && def.getAsJsonPrimitive().isNumber()
&& min.isJsonPrimitive() && min.getAsJsonPrimitive().isNumber()
&& max.isJsonPrimitive() && max.getAsJsonPrimitive().isNumber()) {
Double defV = def.getAsNumber().doubleValue();
Double minV = min.getAsNumber().doubleValue();
Double maxV = max.getAsNumber().doubleValue();
if (defV < minV || defV > maxV) {
Respackopts.logger.error("default value out of range");
}
else if (isWhole(defV) && isWhole(minV) && isWhole(maxV)) {
Double currentValue = defV;
if (Respackopts.numVals.get(screenId).containsKey(n))
currentValue = Respackopts.numVals.get(screenId).get(n);
else Respackopts.numVals.get(screenId).put(n, defV);
if (currentValue < minV)
currentValue = minV;
if (currentValue > maxV)
currentValue = maxV;
config.addEntry(entryBuilder.startIntSlider(getText(n, b),
currentValue.intValue(), minV.intValue(), maxV.intValue())
.setDefaultValue(defV.intValue())
.setSaveConsumer(v -> Respackopts.numVals.get(screenId).put(n, v.doubleValue()))
.setTooltipSupplier(() -> getTooltip(n, screenId))
.build());
}
else {
Respackopts.logger.error("Expected whole number in slider definition");
}
}
else {
Respackopts.logger.error("Expected numeric values in slider definition");
}
continue;
else if (entry instanceof ConfigEnumEntry e) {
String selected = "";
String def = "";
for (Map.Entry<String, Integer> en : e.values.entrySet()) {
if (en.getValue().equals(e.value))
selected = en.getKey();
if (en.getValue().equals(e.defaultValue))
def = en.getKey();
}
//Normal object
SubCategoryBuilder sc = entryBuilder.startSubCategory(getText(n, "respackopts.title." + screenId));
buildCategory(data, screenId, new JfConfigCategorySub(sc), entryBuilder, n);
sc.setTooltipSupplier(() -> getTooltip(n, screenId));
config.addEntry(sc.build());
config.addEntry(entryBuilder.startDropdownMenu(getText(n, b),
DropdownMenuBuilder.TopCellElementBuilder.of(selected, LiteralText::new),
new DropdownBoxEntry.DefaultSelectionCellCreator())
.setSuggestionMode(false)
.setDefaultValue(def)
.setSelections(() -> e.values.keySet().iterator())
.setSaveConsumer(v -> e.value = e.values.get(v))
.setTooltipSupplier(() -> getTooltip(n, screenId))
.build());
}
else {
Respackopts.logger.error("Unsupported non-primitive datatype");
else if (entry instanceof ConfigNumericEntry e) {
if (e.min != null && e.max != null) {
config.addEntry(entryBuilder.startIntSlider(getText(n, b),
e.value.intValue(), e.min.intValue(), e.max.intValue())
.setDefaultValue(e.defaultValue.intValue())
.setSaveConsumer(v -> e.value = v.doubleValue())
.setTooltipSupplier(() -> getTooltip(n, screenId))
.build());
}
else {
config.addEntry(entryBuilder.startDoubleField(getText(n, b), e.value)
.setDefaultValue(e.defaultValue)
.setSaveConsumer(v -> e.value = v)
.setTooltipSupplier(() -> getTooltip(n, screenId))
.build());
}
}
}
}
@ -172,11 +95,7 @@ public class GuiFactory {
return Optional.empty();
}
private boolean isWhole(double v) {
return v == Math.floor(v) && !Double.isInfinite(v);
}
public Screen buildGui(JsonObject source, String resourcepackid, Screen parent, Runnable onSave) {
public Screen buildGui(ConfigBranch source, String resourcepackid, Screen parent, Runnable onSave) {
try {
ConfigBuilder builder;
builder = ConfigBuilder.create()

View File

@ -1,13 +1,23 @@
package io.gitlab.jfronny.respackopts;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.gitlab.jfronny.respackopts.data.Config;
import io.gitlab.jfronny.respackopts.data.Respackmeta;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import io.gitlab.jfronny.respackopts.data.ConfigBooleanEntry;
import io.gitlab.jfronny.respackopts.data.ConfigBranch;
import io.gitlab.jfronny.respackopts.data.ConfigEnumEntry;
import io.gitlab.jfronny.respackopts.data.ConfigNumericEntry;
import io.gitlab.jfronny.respackopts.data.in.Respackmeta;
import io.gitlab.jfronny.respackopts.filters.conditions.SyntaxError;
import io.gitlab.jfronny.respackopts.gson.BooleanEntrySerializer;
import io.gitlab.jfronny.respackopts.gson.ConfigBranchSerializer;
import io.gitlab.jfronny.respackopts.gson.EnumEntrySerializer;
import io.gitlab.jfronny.respackopts.gson.NumericEntrySerializer;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.util.Identifier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -18,118 +28,72 @@ import java.util.*;
@Environment(EnvType.CLIENT)
public class Respackopts implements ClientModInitializer {
public static Map<String, Map<String, Boolean>> boolVals;
public static Map<String, Map<String, Double>> numVals;
public static Map<String, Map<String, String>> strVals;
public static Map<String, Map<String, Set<String>>> enumKeys;
public static Gson g = new Gson();
public static GuiFactory factory = new GuiFactory();
public static final Integer metaVersion = 1;
public static Map<String, Respackmeta> resPackMetas = new HashMap<>();
public static final Integer META_VERSION = 1;
public static final String ID = "respackopts";
static final Path p = FabricLoader.getInstance().getConfigDir().resolve("respackopts");
public static final Set<Runnable> saveActions = new HashSet<>();
public static final String fileExtension = ".rpo";
public static final Identifier CONF_ID = new Identifier(ID, "conf.json");
public static final Logger LOGGER = LogManager.getFormatterLogger(ID);
private static final Path CONF_DIR = FabricLoader.getInstance().getConfigDir().resolve(ID);
public static final String FILE_EXTENSION = ".rpo";
public static final Set<Runnable> SAVE_ACTIONS = new HashSet<>();
public static final Map<String, ConfigBranch> CONFIG_BRANCH = new HashMap<>();
public static final Gson GSON;
public static GuiFactory factory = new GuiFactory();
public static Map<String, Respackmeta> resPackMetas = new HashMap<>();
public static boolean forceRespackReload = false;
public static final Logger logger = LogManager.getFormatterLogger(ID);
static {
GSON = new GsonBuilder()
.registerTypeAdapter(ConfigEnumEntry.class, new EnumEntrySerializer())
.registerTypeAdapter(ConfigNumericEntry.class, new NumericEntrySerializer())
.registerTypeAdapter(ConfigBooleanEntry.class, new BooleanEntrySerializer())
.registerTypeAdapter(ConfigBranch.class, new ConfigBranchSerializer())
.setPrettyPrinting()
.create();
}
@Override
public void onInitializeClient() {
try {
Files.createDirectories(p);
Files.createDirectories(CONF_DIR);
} catch (IOException e) {
e.printStackTrace();
Respackopts.LOGGER.error(e);
}
if (boolVals == null)
boolVals = new HashMap<>();
if (numVals == null)
numVals = new HashMap<>();
if (strVals == null)
strVals = new HashMap<>();
if (enumKeys == null)
enumKeys = new HashMap<>();
if (FabricLoader.getInstance().isDevelopmentEnvironment())
saveActions.add(() -> logger.info("Save"));
SAVE_ACTIONS.add(() -> LOGGER.info("Save"));
}
public static void save() {
for (String s : resPackMetas.keySet()) {
s = resPackMetas.get(s).id;
Config cfg = new Config();
if (boolVals.containsKey(s))
{
cfg.bools = new JsonObject();
for (Map.Entry<String, Boolean> entry : boolVals.get(s).entrySet()) {
cfg.bools.addProperty(entry.getKey(), entry.getValue());
}
}
if (numVals.containsKey(s))
{
cfg.doubles = new JsonObject();
for (Map.Entry<String, Double> entry : numVals.get(s).entrySet()) {
cfg.doubles.addProperty(entry.getKey(), entry.getValue());
}
}
if (strVals.containsKey(s))
{
cfg.strings = new JsonObject();
for (Map.Entry<String, String> entry : strVals.get(s).entrySet()) {
cfg.strings.addProperty(entry.getKey(), entry.getValue());
}
}
try {
Writer writer = Files.newBufferedWriter(p.resolve(s + ".json"));
g.toJson(cfg, writer);
try (Writer writer = Files.newBufferedWriter(CONF_DIR.resolve(s + ".json"))) {
GSON.toJson(CONFIG_BRANCH.get(s), writer);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
Respackopts.LOGGER.error(e);
}
}
for (Runnable action : saveActions) {
for (Runnable action : SAVE_ACTIONS) {
action.run();
}
}
public static void load(String id) {
Path q = p.resolve(id + ".json");
Path q = CONF_DIR.resolve(id + ".json");
if (Files.exists(q)) {
try {
Reader reader = Files.newBufferedReader(q);
Config c = g.fromJson(reader, Config.class);
reader.close();
if (c.bools != null) {
boolVals.get(id).forEach((i, val) -> {
if (c.bools.has(i)
&& c.bools.get(i).isJsonPrimitive()
&& c.bools.get(i).getAsJsonPrimitive().isBoolean()) {
boolVals.get(id).put(i, c.bools.get(i).getAsBoolean());
} else if (FabricLoader.getInstance().isDevelopmentEnvironment())
Respackopts.logger.error("Could not find bool " + i + " in " + id);
});
}
if (c.doubles != null) {
numVals.get(id).forEach((i, val) -> {
if (c.doubles.has(i)
&& c.doubles.get(i).isJsonPrimitive()
&& c.doubles.get(i).getAsJsonPrimitive().isNumber()) {
numVals.get(id).put(i, c.doubles.get(i).getAsNumber().doubleValue());
} else if (FabricLoader.getInstance().isDevelopmentEnvironment())
Respackopts.logger.error("Could not find num " + i + " in " + id);
});
}
if (c.strings != null) {
strVals.get(id).forEach((i, val) -> {
if (c.strings.has(i)
&& c.strings.get(i).isJsonPrimitive()
&& c.strings.get(i).getAsJsonPrimitive().isString()) {
strVals.get(id).put(i, c.strings.get(i).getAsString());
} else if (FabricLoader.getInstance().isDevelopmentEnvironment())
Respackopts.logger.error("Could not find str " + i + " in " + id);
});
}
} catch (IOException e) {
e.printStackTrace();
try (Reader reader = Files.newBufferedReader(q)) {
ConfigBranch b = GSON.fromJson(reader, ConfigBranch.class);
if (CONFIG_BRANCH.containsKey(id))
CONFIG_BRANCH.get(id).loadValues(b, false);
else
CONFIG_BRANCH.put(id, b);
} catch (IOException | SyntaxError e) {
LOGGER.error("Failed to load " + id, e);
}
}
/*if ("lumi".equals(id)) {
LOGGER.info("w" + CONFIG_BRANCH.get(id).subClasses.get("subcategoryTest").booleanEntries.get("enableLangJokeFallback").value);
}*/
}
}

View File

@ -1,9 +0,0 @@
package io.gitlab.jfronny.respackopts.data;
import com.google.gson.JsonObject;
public class Config {
public JsonObject bools;
public JsonObject doubles;
public JsonObject strings;
}

View File

@ -0,0 +1,7 @@
package io.gitlab.jfronny.respackopts.data;
public class ConfigBooleanEntry extends Entry<Boolean> {
public ConfigBooleanEntry(boolean v) {
value = v;
}
}

View File

@ -0,0 +1,132 @@
package io.gitlab.jfronny.respackopts.data;
import io.gitlab.jfronny.respackopts.filters.conditions.SyntaxError;
import java.io.InvalidClassException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class ConfigBranch extends Entry<Object> {
private final Map<String, Entry<?>> entries = new HashMap<>();
public boolean getBoolean(String name) throws SyntaxError {
String[] sp = name.split("\\.");
if (!entries.containsKey(sp[0]))
throw new SyntaxError("Invalid path to key");
Entry<?> e = entries.get(sp[0]);
if (sp.length == 1) {
if (e instanceof ConfigBooleanEntry b)
return b.value;
throw new SyntaxError("Not a boolean");
}
if (sp.length == 2 && e instanceof ConfigEnumEntry en) {
for (Map.Entry<String, Integer> entry : en.values.entrySet()) {
if (entry.getKey().equals(sp[1]))
return entry.getValue().equals(en.value);
}
throw new SyntaxError("Could not find enum entry");
}
if (e instanceof ConfigBranch b)
return b.getBoolean(name.substring(name.indexOf('.') + 1));
throw new SyntaxError("Invalid path to key");
}
public void loadValues(ConfigBranch newBranch, boolean additionOnly) throws SyntaxError {
for (Map.Entry<String, Entry<?>> e : newBranch.entries.entrySet()) {
if (!entries.containsKey(e.getKey()))
add(e.getKey(), e.getValue());
else if (!additionOnly) {
if (e.getValue() instanceof ConfigEnumEntry ne) {
ConfigEnumEntry ol = (ConfigEnumEntry)entries.get(e.getKey());
if (ne.value != null)
ol.value = ne.value;
if (ne.values != null && !ne.values.isEmpty())
ol.values = ne.values;
}
else if (e.getValue() instanceof ConfigBooleanEntry ne) {
ConfigBooleanEntry ol = (ConfigBooleanEntry)entries.get(e.getKey());
if (ne.value != null)
ol.value = ne.value;
}
else if (e.getValue() instanceof ConfigNumericEntry ne) {
ConfigNumericEntry ol = (ConfigNumericEntry)entries.get(e.getKey());
if (ne.value != null)
ol.value = ne.value;
if (ne.min != null)
ol.min = ne.min;
if (ne.max != null)
ol.max = ne.max;
}
else if (e.getValue() instanceof ConfigBranch ne) {
ConfigBranch ol = (ConfigBranch)entries.get(e.getKey());
ol.loadValues(ne, false);
}
else {
throw new SyntaxError("Invalid type");
}
}
}
}
public <T extends Entry<T2>, T2> T add(String name, T val) {
val.name = name;
val.defaultValue = val.value;
entries.put(name, val);
return val;
}
public Entry<?> get(String key) {
return entries.get(key);
}
public boolean has(String key) {
return entries.containsKey(key);
}
public Set<Map.Entry<String, Entry<?>>> getEntries() {
return entries.entrySet();
}
public void buildShader(StringBuilder sb, String valuePrefix) throws SyntaxError {
for (Map.Entry<String, Entry<?>> e : entries.entrySet()) {
if (e.getValue() instanceof ConfigNumericEntry n) {
sb.append("\n#define ");
sb.append(valuePrefix);
sb.append(e.getKey());
sb.append(' ');
sb.append(n.value.toString());
}
else if (e.getValue() instanceof ConfigBooleanEntry n) {
if (n.value) {
sb.append("\n#define ");
sb.append(valuePrefix);
sb.append(e.getKey());
}
}
else if (e.getValue() instanceof ConfigEnumEntry n) {
sb.append("\n#define ");
sb.append(valuePrefix);
sb.append(e.getKey());
sb.append(' ');
sb.append(n.value.toString());
for (Map.Entry<String, Integer> e2 : n.values.entrySet()) {
sb.append("\n#define ");
sb.append(valuePrefix);
sb.append(e.getKey());
sb.append('_');
sb.append(e2.getKey());
sb.append(' ');
sb.append(e2.getValue().toString());
}
}
else if (e.getValue() instanceof ConfigBranch n) {
n.buildShader(sb, valuePrefix + e.getKey() + "_");
}
else {
throw new SyntaxError("Invalid type");
}
}
}
}

View File

@ -0,0 +1,12 @@
package io.gitlab.jfronny.respackopts.data;
import java.util.HashMap;
import java.util.Map;
public class ConfigEnumEntry extends Entry<Integer> {
public Map<String, Integer> values = new HashMap<>();
public ConfigEnumEntry() {
value = 0;
}
}

View File

@ -0,0 +1,10 @@
package io.gitlab.jfronny.respackopts.data;
public class ConfigNumericEntry extends Entry<Double> {
public Double min;
public Double max;
public ConfigNumericEntry() {
value = 0d;
}
}

View File

@ -0,0 +1,7 @@
package io.gitlab.jfronny.respackopts.data;
public abstract class Entry<T> {
public String name;
public T defaultValue;
public T value;
}

View File

@ -1,9 +0,0 @@
package io.gitlab.jfronny.respackopts.data;
import com.google.gson.JsonObject;
public class Respackmeta {
public JsonObject conf;
public String id;
public Integer version;
}

View File

@ -0,0 +1,8 @@
package io.gitlab.jfronny.respackopts.data.in;
import java.util.HashMap;
public class LegacyConfig {
public HashMap<String, Double> doubles = new HashMap<>();
public HashMap<String, Boolean> bools = new HashMap<>();
}

View File

@ -0,0 +1,9 @@
package io.gitlab.jfronny.respackopts.data.in;
import io.gitlab.jfronny.respackopts.data.ConfigBranch;
public class Respackmeta {
public ConfigBranch conf;
public String id;
public Integer version;
}

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.respackopts.data;
package io.gitlab.jfronny.respackopts.data.in;
import com.google.gson.JsonArray;

View File

@ -2,15 +2,15 @@ package io.gitlab.jfronny.respackopts.filters.conditions;
import com.google.gson.JsonElement;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.data.in.Respackmeta;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
public class ConditionEvaluator {
private static Set<Condition> conditions;
private static final Set<Condition> conditions;
static {
conditions = new LinkedHashSet<>();
conditions.add(new AndCondition());
@ -50,19 +50,14 @@ public class ConditionEvaluator {
if (!condition.contains(":")) {
throw new SyntaxError("You must include you resource pack ID in conditions (format: pack:some.key)");
}
AtomicBoolean found = new AtomicBoolean(false);
AtomicBoolean output = new AtomicBoolean(false);
Respackopts.resPackMetas.forEach((r, v) -> {
String sourcePack = condition.split(":")[0];
String name = condition.substring(condition.indexOf(':') + 1);
if (Objects.equals(v.id, sourcePack)) {
found.set(true);
output.set(Respackopts.boolVals.get(sourcePack).get(name));
String sourcePack = condition.split(":")[0];
String name = condition.substring(condition.indexOf(':') + 1);
for (Map.Entry<String, Respackmeta> e : Respackopts.resPackMetas.entrySet()) {
if (Objects.equals(e.getValue().id, sourcePack)) {
return Respackopts.CONFIG_BRANCH.get(sourcePack).getBoolean(name);
}
});
if (!found.get()) {
throw new SyntaxError("Could not find pack with specified ID");
}
return output.get();
throw new SyntaxError("Could not find pack with specified ID");
}
}

View File

@ -2,7 +2,7 @@ package io.gitlab.jfronny.respackopts.filters.conditions;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.abstractions.FileOpenProvider;
import io.gitlab.jfronny.respackopts.data.Rpo;
import io.gitlab.jfronny.respackopts.data.in.Rpo;
import java.io.InputStream;
import java.io.InputStreamReader;
@ -18,18 +18,18 @@ public class ResourcePackFilter {
}
public boolean fileHidden(String name) {
if (name.endsWith(Respackopts.fileExtension))
if (name.endsWith(Respackopts.FILE_EXTENSION))
return false;
if (!containsFileBase.test(name + Respackopts.fileExtension))
if (!containsFileBase.test(name + Respackopts.FILE_EXTENSION))
return false;
try (InputStream stream = openFileBase.open(name + Respackopts.fileExtension); Reader w = new InputStreamReader(stream)) {
Rpo rpo = Respackopts.g.fromJson(w, Rpo.class);
try (InputStream stream = openFileBase.open(name + Respackopts.FILE_EXTENSION); Reader w = new InputStreamReader(stream)) {
Rpo rpo = Respackopts.GSON.fromJson(w, Rpo.class);
if (rpo.conditions == null)
return false;
return !ConditionEvaluator.evaluate(rpo.conditions);
}
catch (Throwable e) {
e.printStackTrace();
Respackopts.LOGGER.error(e);
return false;
}
}

View File

@ -2,7 +2,7 @@ package io.gitlab.jfronny.respackopts.filters.fallback;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.abstractions.FileOpenProvider;
import io.gitlab.jfronny.respackopts.data.Rpo;
import io.gitlab.jfronny.respackopts.data.in.Rpo;
import net.minecraft.resource.ResourceNotFoundException;
import net.minecraft.util.Identifier;
@ -23,13 +23,13 @@ public class FallbackFilter {
}
public boolean fileVisible(String name) {
if (name.endsWith(Respackopts.fileExtension))
if (name.endsWith(Respackopts.FILE_EXTENSION))
return false;
String fbt = name + Respackopts.fileExtension;
String fbt = name + Respackopts.FILE_EXTENSION;
if (containsFileBase.test(fbt)) {
System.out.println(fbt);
try (InputStream stream = openFileBase.open(fbt); Reader w = new InputStreamReader(stream)) {
Rpo rpo = Respackopts.g.fromJson(w, Rpo.class);
Rpo rpo = Respackopts.GSON.fromJson(w, Rpo.class);
if (rpo.fallbacks != null) {
List<String> arr = rpo.fallbacks;
for (String s : arr) {
@ -39,16 +39,16 @@ public class FallbackFilter {
}
}
catch (IOException e) {
e.printStackTrace();
Respackopts.LOGGER.error(e);
}
}
return false;
}
public InputStream getReplacement(String name, ResourceNotFoundException ex) throws ResourceNotFoundException {
String fbt = name + Respackopts.fileExtension;
String fbt = name + Respackopts.FILE_EXTENSION;
try (InputStream stream = openFileBase.open(fbt); Reader w = new InputStreamReader(stream)) {
Rpo rpo = Respackopts.g.fromJson(w, Rpo.class);
Rpo rpo = Respackopts.GSON.fromJson(w, Rpo.class);
if (rpo.fallbacks != null) {
List<String> arr = rpo.fallbacks;
for (String s : arr) {
@ -58,7 +58,7 @@ public class FallbackFilter {
}
}
catch (IOException e) {
e.printStackTrace();
Respackopts.LOGGER.error(e);
}
throw ex;
}
@ -66,8 +66,8 @@ public class FallbackFilter {
public void addFallbackResources(Collection<Identifier> ret, String namespace) {
for (Identifier identifier : ret) {
String path = identifier.getPath();
if (path.endsWith(Respackopts.fileExtension)) {
String expectedTarget = path.substring(0, path.length() - Respackopts.fileExtension.length());
if (path.endsWith(Respackopts.FILE_EXTENSION)) {
String expectedTarget = path.substring(0, path.length() - Respackopts.FILE_EXTENSION.length());
System.out.println(expectedTarget);
if (ret.stream().noneMatch(s -> s.getPath().equals(expectedTarget)) && fileVisible(expectedTarget)) {
ret.add(new Identifier(namespace, expectedTarget));

View File

@ -0,0 +1,18 @@
package io.gitlab.jfronny.respackopts.gson;
import com.google.gson.*;
import io.gitlab.jfronny.respackopts.data.ConfigBooleanEntry;
import java.lang.reflect.Type;
public class BooleanEntrySerializer implements JsonSerializer<ConfigBooleanEntry>, JsonDeserializer<ConfigBooleanEntry> {
@Override
public ConfigBooleanEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return new ConfigBooleanEntry(json.getAsBoolean());
}
@Override
public JsonElement serialize(ConfigBooleanEntry src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.value);
}
}

View File

@ -0,0 +1,54 @@
package io.gitlab.jfronny.respackopts.gson;
import com.google.gson.*;
import io.gitlab.jfronny.respackopts.data.*;
import java.lang.reflect.Type;
import java.util.Map;
public class ConfigBranchSerializer implements JsonSerializer<ConfigBranch>, JsonDeserializer<ConfigBranch> {
@Override
public JsonElement serialize(ConfigBranch src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject o = new JsonObject();
for (Map.Entry<String, Entry<?>> entry : src.getEntries()) {
o.add(entry.getKey(), context.serialize(entry.getValue()));
}
return o;
}
@Override
public ConfigBranch deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (!json.isJsonObject())
throw new JsonSyntaxException("ConfigBranch is not an object");
JsonObject o = json.getAsJsonObject();
if (o.entrySet().stream().allMatch(s -> "bools".equals(s.getKey()) || "doubles".equals(s.getKey()) || "strings".equals(s.getKey()))) {
return LegacyConfigDeserializer.deserialize(json, context);
}
ConfigBranch cbNew = new ConfigBranch();
for (Map.Entry<String, JsonElement> e : o.entrySet()) {
JsonElement j = e.getValue();
String s = e.getKey();
if (NumericEntrySerializer.isSlider(j))
cbNew.add(s, context.deserialize(j, ConfigNumericEntry.class));
else if (j.isJsonPrimitive()) {
JsonPrimitive p = j.getAsJsonPrimitive();
if (p.isBoolean())
cbNew.add(s, new ConfigBooleanEntry(p.getAsBoolean()));
else if (p.isNumber()) {
//TODO identify saved enum values - use string?
cbNew.add(s, context.deserialize(j, ConfigNumericEntry.class));
} else if (p.isString())
throw new JsonSyntaxException("String primitives are not currently supported");
}
else if (j.isJsonArray())
cbNew.add(s, context.deserialize(j, ConfigEnumEntry.class));
else if (j.isJsonObject())
cbNew.add(s, context.deserialize(j, ConfigBranch.class));
else if (j.isJsonNull())
throw new JsonSyntaxException("Unexpected json null");
else
throw new JsonSyntaxException("Unexpected json object type");
}
return cbNew;
}
}

View File

@ -0,0 +1,43 @@
package io.gitlab.jfronny.respackopts.gson;
import com.google.gson.*;
import io.gitlab.jfronny.respackopts.data.ConfigEnumEntry;
import java.lang.reflect.Type;
import java.util.HashMap;
public class EnumEntrySerializer implements JsonSerializer<ConfigEnumEntry>, JsonDeserializer<ConfigEnumEntry> {
@Override
public JsonElement serialize(ConfigEnumEntry src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.value == null ? 0 : src.value);
}
@Override
public ConfigEnumEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
ConfigEnumEntry result = new ConfigEnumEntry();
if (json.isJsonPrimitive()) {
JsonPrimitive jp = json.getAsJsonPrimitive();
if (jp.isNumber()) {
result.value = jp.getAsInt();
return result;
}
else
throw new JsonSyntaxException("Expected primitive numeric key for enum");
}
else if (json.isJsonArray()) {
result.values = new HashMap<>();
int i = 0;
for (JsonElement e : json.getAsJsonArray()) {
if (e.isJsonPrimitive() && e.getAsJsonPrimitive().isString()) {
result.values.put(e.getAsString(), i);
}
else
throw new JsonSyntaxException("Expected string entry in enum");
i++;
}
return result;
}
else
throw new JsonSyntaxException("Expected primitive numeric key for enum");
}
}

View File

@ -0,0 +1,49 @@
package io.gitlab.jfronny.respackopts.gson;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import io.gitlab.jfronny.respackopts.data.ConfigBooleanEntry;
import io.gitlab.jfronny.respackopts.data.ConfigBranch;
import io.gitlab.jfronny.respackopts.data.ConfigNumericEntry;
import io.gitlab.jfronny.respackopts.data.Entry;
import io.gitlab.jfronny.respackopts.data.in.LegacyConfig;
import java.util.Map;
public class LegacyConfigDeserializer {
public static ConfigBranch deserialize(JsonElement json, JsonDeserializationContext context) throws JsonParseException {
ConfigBranch cb = new ConfigBranch();
LegacyConfig lc = context.deserialize(json, LegacyConfig.class);
for (Map.Entry<String, Boolean> e : lc.bools.entrySet()) {
ConfigBooleanEntry c = new ConfigBooleanEntry(e.getValue());
int i = e.getKey().lastIndexOf('.');
if (i == -1)
cb.add(e.getKey(), c);
else {
cb = getBranch(e.getKey().substring(0, i), cb);
String n = e.getKey().substring(i + 1);
cb.add(n, c);
}
}
for (Map.Entry<String, Double> e : lc.doubles.entrySet()) {
ConfigNumericEntry ne = new ConfigNumericEntry();
ne.value = e.getValue();
int i = e.getKey().lastIndexOf('.');
if (i == -1)
cb.add(e.getKey(), ne);
else
getBranch(e.getKey().substring(0, i), cb).add(e.getKey().substring(i + 1), ne);
}
return cb;
}
private static ConfigBranch getBranch(String name, ConfigBranch base) {
int i = name.indexOf('.');
String keyNext = i == -1 ? name : name.substring(0, i);
if (!base.has(keyNext))
base.add(keyNext, new ConfigBranch());
ConfigBranch c = (ConfigBranch)base.get(keyNext);
return i == -1 ? c : getBranch(name.substring(i + 1), c);
}
}

View File

@ -0,0 +1,54 @@
package io.gitlab.jfronny.respackopts.gson;
import com.google.gson.*;
import io.gitlab.jfronny.respackopts.data.ConfigNumericEntry;
import java.lang.reflect.Type;
public class NumericEntrySerializer implements JsonSerializer<ConfigNumericEntry>, JsonDeserializer<ConfigNumericEntry> {
@Override
public JsonElement serialize(ConfigNumericEntry src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.value);
}
@Override
public ConfigNumericEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
ConfigNumericEntry result = new ConfigNumericEntry();
if (json.isJsonPrimitive() && json.getAsJsonPrimitive().isNumber()) {
result.value = json.getAsDouble();
return result;
}
else if (isSlider(json)) {
JsonObject o = json.getAsJsonObject();
JsonElement def = o.get("default");
JsonElement min = o.get("min");
JsonElement max = o.get("max");
if (def.isJsonPrimitive() && def.getAsJsonPrimitive().isNumber()
&& min.isJsonPrimitive() && min.getAsJsonPrimitive().isNumber()
&& max.isJsonPrimitive() && max.getAsJsonPrimitive().isNumber()) {
double defV = def.getAsNumber().doubleValue();
double minV = min.getAsNumber().doubleValue();
double maxV = max.getAsNumber().doubleValue();
if (defV < minV || defV > maxV) {
throw new JsonSyntaxException("Default value out of range in slider definition");
}
if (isWhole(defV) && isWhole(minV) && isWhole(maxV)) {
result.value = defV;
result.min = minV;
result.max = maxV;
return result;
}
throw new JsonSyntaxException("Expected whole number in slider definition");
}
throw new JsonSyntaxException("Expected numeric values in slider definition");
}
throw new JsonSyntaxException("Could not deserialize numeric entry");
}
public static boolean isSlider(JsonElement element) {
return element.isJsonObject() && element.getAsJsonObject().entrySet().stream().allMatch(s -> "default".equals(s.getKey()) || "min".equals(s.getKey()) || "max".equals(s.getKey()));
}
private boolean isWhole(double v) {
return v == Math.floor(v) && !Double.isInfinite(v);
}
}

View File

@ -3,9 +3,11 @@ package io.gitlab.jfronny.respackopts.integration;
import grondag.frex.FrexInitializer;
import grondag.frex.api.config.ShaderConfig;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.data.ConfigBranch;
import io.gitlab.jfronny.respackopts.filters.conditions.SyntaxError;
import net.minecraft.util.Identifier;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.Map;
public class FrexCompat implements FrexInitializer {
boolean initial = true;
@ -13,53 +15,25 @@ public class FrexCompat implements FrexInitializer {
public void onInitalizeFrex() {
ShaderConfig.registerShaderConfigSupplier(new Identifier(Respackopts.ID, "config_supplier"), () -> {
StringBuilder sb = new StringBuilder();
Respackopts.numVals.forEach((s, v) -> v.forEach((s1, v1) -> {
sb.append("\n");
sb.append("#define ");
sb.append(s.replace('.', '_'));
sb.append("_");
sb.append(s1.replace('.', '_'));
sb.append(" ");
String tmp = v1.toString();
if (tmp.endsWith(".0"))
tmp = tmp.substring(0, tmp.length() - 2);
sb.append(tmp);
}));
Respackopts.boolVals.forEach((s, v) -> v.forEach((s1, v1) -> {
if (v1) {
sb.append("\n");
sb.append("#define ");
sb.append(s.replace('.', '_'));
sb.append("_");
sb.append(s1.replace('.', '_'));
for (Map.Entry<String, ConfigBranch> e : Respackopts.CONFIG_BRANCH.entrySet()) {
try {
e.getValue().buildShader(sb, e.getKey() + "_");
} catch (SyntaxError syntaxError) {
Respackopts.LOGGER.error(syntaxError);
}
}));
Respackopts.enumKeys.forEach((s, v) -> v.forEach((s1, v1) -> {
AtomicInteger i = new AtomicInteger(0);
v1.forEach((s2) -> {
sb.append("\n");
sb.append("#define ");
sb.append(s.replace('.', '_'));
sb.append("_");
sb.append(s1.replace('.', '_'));
sb.append("_");
sb.append(s2.replace('.', '_'));
sb.append(" ");
sb.append(i.getAndIncrement());
});
}));
}
sb.append("\n#define respackopts_loaded");
return sb.toString();
});
Respackopts.logger.info("enabled frex/canvas support");
Respackopts.saveActions.add(() -> {
Respackopts.LOGGER.info("enabled frex/canvas support");
Respackopts.SAVE_ACTIONS.add(() -> {
try {
if (!initial)
ShaderConfig.invalidateShaderConfig();
initial = false;
}
catch (Throwable e) {
e.printStackTrace();
Respackopts.LOGGER.error(e);
}
});
}

View File

@ -9,7 +9,6 @@ import me.shedaniel.clothconfig2.api.ConfigCategory;
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.FatalErrorScreen;
import net.minecraft.text.LiteralText;
import net.minecraft.text.TranslatableText;
import java.util.concurrent.atomic.AtomicBoolean;

View File

@ -2,7 +2,7 @@ package io.gitlab.jfronny.respackopts.mixin;
import com.mojang.blaze3d.systems.RenderSystem;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.data.Respackmeta;
import io.gitlab.jfronny.respackopts.data.in.Respackmeta;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.gui.screen.pack.PackListWidget;
@ -25,7 +25,7 @@ public abstract class ResourcePackEntryMixin extends AlwaysSelectedEntryListWidg
@Shadow protected abstract boolean isSelectable();
@Shadow @Final private ResourcePackOrganizer.Pack pack;
boolean respackopts$selected;
boolean rpo$selected;
@Inject(at = @At("TAIL"), method = "render(Lnet/minecraft/client/util/math/MatrixStack;IIIIIIIZF)V")
private void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta, CallbackInfo info) {
@ -34,8 +34,8 @@ public abstract class ResourcePackEntryMixin extends AlwaysSelectedEntryListWidg
int d = mouseX - x;
d = widget.getRowWidth() - d;
int e = mouseY - y;
respackopts$selected = d <= 32 && d >= 12 && e <= entryHeight / 2 + 10 && e >= entryHeight / 2 - 10;
respackopts$renderButton(matrices, respackopts$selected, new Identifier("modmenu", "textures/gui/configure_button.png"), x + entryWidth - 30, y + entryHeight / 2 - 10, 20, 20, 0, 0, 32, 64);
rpo$selected = d <= 32 && d >= 12 && e <= entryHeight / 2 + 10 && e >= entryHeight / 2 - 10;
rpo$renderButton(matrices, rpo$selected, new Identifier("modmenu", "textures/gui/configure_button.png"), x + entryWidth - 30, y + entryHeight / 2 - 10);
}
}
@ -44,7 +44,7 @@ public abstract class ResourcePackEntryMixin extends AlwaysSelectedEntryListWidg
if (!info.getReturnValue()) {
if (this.isSelectable()) {
String k = pack.getDisplayName().asString();
if (Respackopts.resPackMetas.containsKey(k) && respackopts$selected) {
if (Respackopts.resPackMetas.containsKey(k) && rpo$selected) {
info.setReturnValue(true);
Respackmeta meta = Respackopts.resPackMetas.get(k);
MinecraftClient c = MinecraftClient.getInstance();
@ -54,16 +54,11 @@ public abstract class ResourcePackEntryMixin extends AlwaysSelectedEntryListWidg
}
}
private void respackopts$renderButton(MatrixStack matrices, boolean hovered, Identifier texture, int x, int y, int width, int height, int u, int v, int uWidth, int vHeight) {
private void rpo$renderButton(MatrixStack matrices, boolean hovered, Identifier texture, int x, int y) {
RenderSystem.setShaderColor(1, 1, 1, 1f);
RenderSystem.setShaderTexture(0, texture);
RenderSystem.disableDepthTest();
int adjustedV = v;
if (hovered) {
adjustedV += height;
}
DrawableHelper.drawTexture(matrices, x, y, u, adjustedV, width, height, uWidth, vHeight);
DrawableHelper.drawTexture(matrices, x, y, 0, hovered ? 20 : 0, 20, 20, 32, 64);
RenderSystem.enableDepthTest();
}
}

View File

@ -2,11 +2,11 @@ package io.gitlab.jfronny.respackopts.mixin;
import com.google.gson.*;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.data.Respackmeta;
import io.gitlab.jfronny.respackopts.data.ConfigBranch;
import io.gitlab.jfronny.respackopts.data.in.Respackmeta;
import net.minecraft.resource.ResourcePackManager;
import net.minecraft.resource.ResourcePackProfile;
import net.minecraft.resource.ResourceType;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@ -16,7 +16,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
@ -27,126 +26,32 @@ public class ResourcePackManagerMixin {
@Inject(at = @At("TAIL"), method = "scanPacks()V")
private void scanPacks(CallbackInfo info) {
profiles.forEach((s, v) -> {
if (respackopts$hasMetadata(v, "conf.json")) {
if (rpo$hasMetadata(v)) {
try {
Respackmeta conf = Respackopts.g.fromJson(respackopts$readMetadata(v, "conf.json", Respackopts.g), Respackmeta.class);
if (!Respackopts.metaVersion.equals(conf.version)) {
Respackopts.logger.error(s + " was not loaded as it specifies a different respackopts version than is installed");
Respackmeta conf = Respackopts.GSON.fromJson(rpo$readMetadata(v, Respackopts.GSON), Respackmeta.class);
if (!Respackopts.META_VERSION.equals(conf.version)) {
Respackopts.LOGGER.error(s + " was not loaded as it specifies a different respackopts version than is installed");
return;
}
if (!Respackopts.boolVals.containsKey(conf.id))
Respackopts.boolVals.put(conf.id, new HashMap<>());
if (!Respackopts.numVals.containsKey(conf.id))
Respackopts.numVals.put(conf.id, new HashMap<>());
if (!Respackopts.strVals.containsKey(conf.id))
Respackopts.strVals.put(conf.id, new HashMap<>());
if (!Respackopts.enumKeys.containsKey(conf.id))
Respackopts.enumKeys.put(conf.id, new HashMap<>());
if (!Respackopts.CONFIG_BRANCH.containsKey(conf.id))
Respackopts.CONFIG_BRANCH.put(conf.id, conf.conf);
else
Respackopts.CONFIG_BRANCH.get(conf.id).loadValues(conf.conf, true);
Respackopts.resPackMetas.put(v.getDisplayName().asString(), conf);
respackopts$registerFields(conf.conf, conf.id, "");
Respackopts.load(conf.id);
} catch (Throwable e) {
e.printStackTrace();
Respackopts.LOGGER.error(e);
}
}
});
}
private void respackopts$registerFields(JsonObject data, String id, String keyPrefix) {
//Slider
if (data.entrySet().stream().allMatch(s -> "default".equals(s.getKey()) || "min".equals(s.getKey()) || "max".equals(s.getKey())))
{
JsonElement def = data.get("default");
JsonElement min = data.get("min");
JsonElement max = data.get("max");
if (def.isJsonPrimitive() && def.getAsJsonPrimitive().isNumber()
&& min.isJsonPrimitive() && min.getAsJsonPrimitive().isNumber()
&& max.isJsonPrimitive() && max.getAsJsonPrimitive().isNumber()) {
double defV = def.getAsNumber().doubleValue();
double minV = min.getAsNumber().doubleValue();
double maxV = max.getAsNumber().doubleValue();
if (defV < minV || defV > maxV) {
Respackopts.logger.error("Default value out of range in slider definition " + id);
}
else if (respackopts$isWhole(defV) && respackopts$isWhole(minV) && respackopts$isWhole(maxV)) {
Respackopts.numVals.get(id).put(keyPrefix, defV);
}
else {
Respackopts.logger.error("Expected whole number in slider definition " + id);
}
}
else {
Respackopts.logger.error("Expected numeric values in slider definition " + id);
}
return;
}
//Normal object
for (Map.Entry<String, JsonElement> entry : data.entrySet()) {
String n = ("".equals(keyPrefix) ? "" : keyPrefix + ".") + entry.getKey();
JsonElement e = entry.getValue();
if (e.isJsonPrimitive()) {
JsonPrimitive p = e.getAsJsonPrimitive();
if (p.isBoolean()) {
if (!Respackopts.boolVals.get(id).containsKey(n))
Respackopts.boolVals.get(id).put(n, p.getAsBoolean());
}
else if (p.isNumber()) {
if (!Respackopts.numVals.get(id).containsKey(n))
Respackopts.numVals.get(id).put(n, p.getAsDouble());
}
else if (p.isString()) {
if (!Respackopts.strVals.get(id).containsKey(n))
Respackopts.strVals.get(id).put(n, p.getAsString());
}
}
else if (e.isJsonArray()) {
JsonArray a = e.getAsJsonArray();
for (JsonElement element : a) {
if (!element.isJsonPrimitive()) {
Respackopts.logger.error("Unsupported non-primitive datatype in enum definition");
continue;
}
if (!Respackopts.enumKeys.get(id).containsKey(n)) {
Respackopts.enumKeys.get(id).put(n, new LinkedHashSet<>());
}
JsonPrimitive p = element.getAsJsonPrimitive();
if (!p.isString()) {
Respackopts.logger.error("Unsupported non-string enum key");
continue;
}
String b = p.getAsString();
if (b.contains(":") || b.contains(".") || b.contains("_")) {
Respackopts.logger.error(b + " contains invalid characters");
continue;
}
Respackopts.enumKeys.get(id).get(n).add(b);
}
if (!Respackopts.numVals.get(id).containsKey(n)) {
Respackopts.numVals.get(id).put(n, 0d);
}
}
else if (e.isJsonNull()) {
Respackopts.logger.error("Config definition contains null, skipping that entry");
}
else if (e.isJsonObject()) {
respackopts$registerFields(e.getAsJsonObject(), id, n);
}
else {
Respackopts.logger.error("Unsupported non-primitive datatype");
}
}
private boolean rpo$hasMetadata(ResourcePackProfile v) {
return v.createResourcePack().contains(ResourceType.CLIENT_RESOURCES, Respackopts.CONF_ID);
}
private boolean respackopts$isWhole(double v) {
return v == Math.floor(v) && !Double.isInfinite(v);
}
private boolean respackopts$hasMetadata(ResourcePackProfile v, String fname) {
return v.createResourcePack().contains(ResourceType.CLIENT_RESOURCES, new Identifier(Respackopts.ID, fname));
}
private JsonObject respackopts$readMetadata(ResourcePackProfile v, String fname, Gson g) throws IOException {
InputStream is = v.createResourcePack().open(ResourceType.CLIENT_RESOURCES, new Identifier(Respackopts.ID, fname));
private JsonObject rpo$readMetadata(ResourcePackProfile v, Gson g) throws IOException {
InputStream is = v.createResourcePack().open(ResourceType.CLIENT_RESOURCES, Respackopts.CONF_ID);
ByteArrayOutputStream bais = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;

View File

@ -28,20 +28,20 @@ public abstract class DirectoryResourcePackMixin extends AbstractFileResourcePac
@Shadow protected abstract InputStream openFile(String name) throws IOException;
FilterProvider filter = new FilterProvider(this::containsFile, this::openFile);
FilterProvider rpo$filter = new FilterProvider(this::containsFile, this::openFile);
@Inject(at = @At("HEAD"), method = "openFile(Ljava/lang/String;)Ljava/io/InputStream;", cancellable = true)
protected void openFile(String name, CallbackInfoReturnable<InputStream> info) throws IOException {
filter.openFile(name, base, info);
rpo$filter.openFile(name, base, info);
}
@Inject(at = @At("TAIL"), method = "containsFile(Ljava/lang/String;)Z", cancellable = true)
protected void containsFile(String name, CallbackInfoReturnable<Boolean> info) {
filter.containsFile(name, info);
rpo$filter.containsFile(name, info);
}
@Inject(at = @At("TAIL"), method = "findResources(Lnet/minecraft/resource/ResourceType;Ljava/lang/String;Ljava/lang/String;ILjava/util/function/Predicate;)Ljava/util/Collection;")
private void findResources(ResourceType type, String namespace, String prefix, int maxDepth, Predicate<String> pathFilter, CallbackInfoReturnable<Collection<Identifier>> info) {
filter.findResources(type, namespace, prefix, maxDepth, pathFilter, info);
rpo$filter.findResources(type, namespace, prefix, maxDepth, pathFilter, info);
}
}

View File

@ -28,20 +28,20 @@ public abstract class ZipResourcePackMixin extends AbstractFileResourcePack {
@Shadow protected abstract InputStream openFile(String name) throws IOException;
FilterProvider filter = new FilterProvider(this::containsFile, this::openFile);
FilterProvider rpo$filter = new FilterProvider(this::containsFile, this::openFile);
@Inject(at = @At("HEAD"), method = "openFile(Ljava/lang/String;)Ljava/io/InputStream;", cancellable = true)
protected void openFile(String name, CallbackInfoReturnable<InputStream> info) throws IOException {
filter.openFile(name, base, info);
rpo$filter.openFile(name, base, info);
}
@Inject(at = @At("TAIL"), method = "containsFile(Ljava/lang/String;)Z", cancellable = true)
protected void containsFile(String name, CallbackInfoReturnable<Boolean> info) {
filter.containsFile(name, info);
rpo$filter.containsFile(name, info);
}
@Inject(at = @At("TAIL"), method = "findResources(Lnet/minecraft/resource/ResourceType;Ljava/lang/String;Ljava/lang/String;ILjava/util/function/Predicate;)Ljava/util/Collection;")
private void findResources(ResourceType type, String namespace, String prefix, int maxDepth, Predicate<String> pathFilter, CallbackInfoReturnable<Collection<Identifier>> info) {
filter.findResources(type, namespace, prefix, maxDepth, pathFilter, info);
rpo$filter.findResources(type, namespace, prefix, maxDepth, pathFilter, info);
}
}