Rewrite part 1 (doesn't work yet)
This commit is contained in:
parent
fa46b8b78d
commit
68a3bf2d54
@ -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")
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
"viewDir"
|
||||
],
|
||||
"waterVertexWavy": false,
|
||||
"stringTest": "this is a string",
|
||||
"numTest": 15.4,
|
||||
"subcategoryTest": {
|
||||
"thisIsCool": true,
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package io.gitlab.jfronny.respackopts.data;
|
||||
|
||||
public class ConfigBooleanEntry extends Entry<Boolean> {
|
||||
public ConfigBooleanEntry(boolean v) {
|
||||
value = v;
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package io.gitlab.jfronny.respackopts.data;
|
||||
|
||||
public abstract class Entry<T> {
|
||||
public String name;
|
||||
public T defaultValue;
|
||||
public T value;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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<>();
|
||||
}
|
@ -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;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package io.gitlab.jfronny.respackopts.data;
|
||||
package io.gitlab.jfronny.respackopts.data.in;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user