complete rewrite

This commit is contained in:
Oth3r 2024-07-11 13:43:54 -05:00
commit 1316686d85
24 changed files with 1808 additions and 871 deletions

View file

@ -1,256 +0,0 @@
package one.oth3r.sit.file;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import net.fabricmc.loader.api.FabricLoader;
import one.oth3r.sit.LangReader;
import one.oth3r.sit.Sit;
import one.oth3r.sit.SitClient;
import one.oth3r.sit.Utl.*;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class Config {
public static String lang = defaults.lang;
public static boolean keepActive = defaults.keepActive;
public static boolean sitWhileSeated = defaults.sitWhileSeated;
public static boolean stairsOn = defaults.stairsOn;
public static boolean slabsOn = defaults.slabsOn;
public static boolean carpetsOn = defaults.carpetsOn;
public static boolean fullBlocksOn = defaults.fullBlocksOn;
public static boolean customOn = defaults.customOn;
public static List<String> customBlocks = defaults.customBlocks;
public enum HandRequirement {
empty,
restrictive,
none;
public static HandRequirement get(String s) {
try {
return HandRequirement.valueOf(s);
} catch (IllegalArgumentException e) {
return empty;
}
}
}
public static HandRequirement mainReq = defaults.mainReq;
public static boolean mainBlock = defaults.mainBlock;
public static boolean mainFood = defaults.mainFood;
public static boolean mainUsable = defaults.mainUsable;
public static List<String> mainWhitelist = defaults.mainWhitelist;
public static List<String> mainBlacklist = defaults.mainBlacklist;
public static HandRequirement offReq = defaults.offReq;
public static boolean offBlock = defaults.offBlock;
public static boolean offFood = defaults.offFood;
public static boolean offUsable = defaults.offUsable;
public static List<String> offWhitelist = defaults.offWhitelist;
public static List<String> offBlacklist = defaults.offBlacklist;
public static File configFile() {
return new File(FabricLoader.getInstance().getConfigDir().toFile()+"/Sit!.properties");
}
public static void load() {
if (!configFile().exists() || !configFile().canRead()) {
save();
load();
return;
}
try (FileInputStream fileStream = new FileInputStream(configFile())) {
Properties properties = new Properties();
properties.load(fileStream);
String ver = (String) properties.computeIfAbsent("version", a -> String.valueOf(defaults.version));
// if the old version system (v1.0) remove "v"
if (ver.contains("v")) ver = ver.substring(1);
loadVersion(properties,Double.parseDouble(ver));
LangReader.loadLanguageFile();
save();
} catch (Exception e) {
//read fail
e.printStackTrace();
save();
}
}
public static ArrayList<String> validateCustomBlocks(ArrayList<String> fix) {
ArrayList<String> out = new ArrayList<>();
for (String entry : fix) {
String[] split = entry.split("\\|");
// skip if not the right size
if (split.length < 3 || split.length > 4) continue;
// keep going if that block exists
// if (Registries.BLOCK.stream().anyMatch(match -> Registries.BLOCK.getId(match).toString().equals(split[0]))) {}
// if the other entries aren't correct, skip
if (!Num.isFloat(split[1]) || !Num.isInt(split[2])) continue;
// add if everything is a okay
out.add(entry);
}
return out;
}
public static void loadVersion(Properties properties, double version) {
try {
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
Type listType = new TypeToken<ArrayList<String>>() {}.getType();
lang = (String) properties.computeIfAbsent("lang", a -> defaults.lang);
//CONFIG
keepActive = Boolean.parseBoolean((String) properties.computeIfAbsent("keep-active", a -> String.valueOf(defaults.keepActive)));
sitWhileSeated = Boolean.parseBoolean((String) properties.computeIfAbsent("sit-while-seated", a -> String.valueOf(defaults.sitWhileSeated)));
stairsOn = Boolean.parseBoolean((String) properties.computeIfAbsent("stairs", a -> String.valueOf(defaults.stairsOn)));
slabsOn = Boolean.parseBoolean((String) properties.computeIfAbsent("slabs", a -> String.valueOf(defaults.slabsOn)));
carpetsOn = Boolean.parseBoolean((String) properties.computeIfAbsent("carpets", a -> String.valueOf(defaults.carpetsOn)));
fullBlocksOn = Boolean.parseBoolean((String) properties.computeIfAbsent("full-blocks", a -> String.valueOf(defaults.fullBlocksOn)));
customOn = Boolean.parseBoolean((String) properties.computeIfAbsent("custom", a -> String.valueOf(defaults.customOn)));
try {
customBlocks = validateCustomBlocks(new Gson().fromJson((String)
properties.computeIfAbsent("custom-blocks", a -> gson.toJson(defaults.customBlocks)), listType));
} catch (JsonSyntaxException ignore) {}
mainReq = HandRequirement.get((String) properties.computeIfAbsent("hand.main.requirement", a -> String.valueOf(defaults.mainReq)));
mainBlock = Boolean.parseBoolean((String) properties.computeIfAbsent("hand.main.block", a -> String.valueOf(defaults.mainBlock)));
mainFood = Boolean.parseBoolean((String) properties.computeIfAbsent("hand.main.food", a -> String.valueOf(defaults.mainFood)));
mainUsable = Boolean.parseBoolean((String) properties.computeIfAbsent("hand.main.usable", a -> String.valueOf(defaults.mainUsable)));
try {
mainWhitelist = new Gson().fromJson((String)
properties.computeIfAbsent("hand.main.whitelist", a -> gson.toJson(defaults.mainWhitelist)), listType);
} catch (JsonSyntaxException ignore) {}
try {
mainBlacklist = new Gson().fromJson((String)
properties.computeIfAbsent("hand.main.blacklist", a -> gson.toJson(defaults.mainBlacklist)), listType);
} catch (JsonSyntaxException ignore) {}
offReq = HandRequirement.get((String) properties.computeIfAbsent("hand.off.requirement", a -> String.valueOf(defaults.offReq)));
offBlock = Boolean.parseBoolean((String) properties.computeIfAbsent("hand.off.block", a -> String.valueOf(defaults.offBlock)));
offFood = Boolean.parseBoolean((String) properties.computeIfAbsent("hand.off.food", a -> String.valueOf(defaults.offFood)));
offUsable = Boolean.parseBoolean((String) properties.computeIfAbsent("hand.off.usable", a -> String.valueOf(defaults.offUsable)));
offWhitelist = new Gson().fromJson((String)
properties.computeIfAbsent("hand.off.whitelist", a -> gson.toJson(defaults.offWhitelist)), listType);
offBlacklist = new Gson().fromJson((String)
properties.computeIfAbsent("hand.off.blacklist", a -> gson.toJson(defaults.offBlacklist)), listType);
if (version == 1.0) {
mainReq = HandRequirement.get((String) properties.computeIfAbsent("main-hand-requirement", a -> String.valueOf(defaults.mainReq)));
mainBlock = Boolean.parseBoolean((String) properties.computeIfAbsent("main-hand-block", a -> String.valueOf(defaults.mainBlock)));
mainFood = Boolean.parseBoolean((String) properties.computeIfAbsent("main-hand-food", a -> String.valueOf(defaults.mainFood)));
mainUsable = Boolean.parseBoolean((String) properties.computeIfAbsent("main-hand-usable", a -> String.valueOf(defaults.mainUsable)));
try {
mainWhitelist = new Gson().fromJson((String)
properties.computeIfAbsent("main-hand-whitelist", a -> gson.toJson(defaults.mainWhitelist)), listType);
} catch (JsonSyntaxException ignore) {}
try {
mainBlacklist = new Gson().fromJson((String)
properties.computeIfAbsent("main-hand-blacklist", a -> gson.toJson(defaults.mainBlacklist)), listType);
} catch (JsonSyntaxException ignore) {}
offReq = HandRequirement.get((String) properties.computeIfAbsent("off-hand-requirement", a -> String.valueOf(defaults.offReq)));
offBlock = Boolean.parseBoolean((String) properties.computeIfAbsent("off-hand-block", a -> String.valueOf(defaults.offBlock)));
offFood = Boolean.parseBoolean((String) properties.computeIfAbsent("off-hand-food", a -> String.valueOf(defaults.offFood)));
offUsable = Boolean.parseBoolean((String) properties.computeIfAbsent("off-hand-usable", a -> String.valueOf(defaults.offUsable)));
try {
offWhitelist = new Gson().fromJson((String)
properties.computeIfAbsent("off-hand-whitelist", a -> gson.toJson(defaults.offWhitelist)), listType);
} catch (JsonSyntaxException ignore) {}
try {
offBlacklist = new Gson().fromJson((String)
properties.computeIfAbsent("off-hand-blacklist", a -> gson.toJson(defaults.offBlacklist)), listType);
} catch (JsonSyntaxException ignore) {}
}
} catch (Exception e) {
Sit.LOGGER.info("ERROR LOADING CONFIG - PLEASE REPORT WITH THE ERROR LOG");
e.printStackTrace();
}
}
public static String lang(String key, Object... args) {
return Utl.lang("config."+key, args).getString();
}
public static void save() {
try (var file = Files.newBufferedWriter(configFile().toPath(), StandardCharsets.UTF_8)) {
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
file.write("# Sit! Config\n");
file.write("\nversion="+defaults.version);
file.write("\n# all available languages: en_us, ru_ru, es_es");
file.write("\nlang=" + lang);
file.write("\n\n# "+lang("general.keep_active.description"));
file.write("\nkeep-active=" + keepActive);
file.write("\n# "+lang("general.sit_while_seated.description"));
file.write("\nsit-while-seated=" + sitWhileSeated);
file.write("\n# "+lang("general.sittable.description"));
file.write("\nstairs=" + stairsOn);
file.write("\nslabs=" + slabsOn);
file.write("\ncarpets=" + carpetsOn);
file.write("\nfull-blocks=" + fullBlocksOn);
file.write("\ncustom=" + customOn);
file.write("\n# "+ Utl.lang("config."+
"general.sittable_blocks.description")
.append("\n# ").append(lang("example",Utl.Assets.CUSTOM_BLOCKS))
.append("\n# ").append(lang("general.sittable_blocks.description.2"))
.append("\n# ").append(lang("general.sittable_blocks.description.3"))
.append("\n# ").append(lang("general.sittable_blocks.description.4"))
.append("\n# ").append(lang("general.sittable_blocks.description.5"))
.append("\n# ").append(lang("general.sittable_blocks.description.6")).getString());
file.write("\ncustom-blocks="+gson.toJson(customBlocks));
file.write("\n\n# "+lang("hand"));
file.write("\n# "+ Utl.lang("config."+
"hand.requirement.description")
.append("\n# ").append(lang("hand.requirement.description.2",HandRequirement.empty))
.append("\n# ").append(lang("hand.requirement.description.3",HandRequirement.restrictive))
.append("\n# ").append(lang("hand.requirement.description.4",HandRequirement.none)).getString());
file.write("\n# "+lang("hand.requirement.options",Utl.Assets.REQUIREMENT_OPTIONS));
file.write("\nhand.main.requirement=" + mainReq);
file.write("\n#");
file.write("\nhand.off.requirement=" + offReq);
file.write("\n\n# "+lang("hand.restriction"));
file.write("\n# "+lang("hand.restriction.description"));
file.write("\nhand.main.block=" + mainBlock);
file.write("\nhand.main.food=" + mainFood);
file.write("\nhand.main.usable=" + mainUsable);
file.write("\n#");
file.write("\nhand.off.block=" + offBlock);
file.write("\nhand.off.food=" + offFood);
file.write("\nhand.off.usable=" + offUsable);
file.write("\n\n# "+lang("hand.restriction.list"));
file.write("\n# "+lang("hand.restriction.list.description"));
file.write("\n# "+lang("example",Utl.Assets.LIST));
file.write("\nhand.main.whitelist="+gson.toJson(mainWhitelist));
file.write("\nhand.main.blacklist="+gson.toJson(mainBlacklist));
file.write("\n#");
file.write("\nhand.off.whitelist="+gson.toJson(offWhitelist));
file.write("\nhand.off.blacklist="+gson.toJson(offBlacklist));
// send packets to update the settings on the server
SitClient.sendSettingsPackets();
} catch (Exception e) {
e.printStackTrace();
}
}
public static class defaults {
public static double version = 1.1;
public static String lang = "en_us";
public static boolean keepActive = true;
public static boolean sitWhileSeated = true;
public static boolean stairsOn = true;
public static boolean slabsOn = true;
public static boolean carpetsOn = true;
public static boolean fullBlocksOn = false;
public static boolean customOn = false;
public static List<String> customBlocks = List.of("minecraft:campfire|.46|1|lit=false","minecraft:soul_campfire|.46|1|lit=false,waterlogged=false");
public static HandRequirement mainReq = HandRequirement.empty;
public static boolean mainBlock = false;
public static boolean mainFood = false;
public static boolean mainUsable = false;
public static List<String> mainWhitelist = new ArrayList<>();
public static List<String> mainBlacklist = new ArrayList<>();
public static HandRequirement offReq = HandRequirement.restrictive;
public static boolean offBlock = true;
public static boolean offFood = false;
public static boolean offUsable = true;
public static List<String> offWhitelist = List.of("minecraft:torch","minecraft:soul_torch","minecraft:redstone_torch");
public static List<String> offBlacklist = new ArrayList<>();
}
}

View file

@ -0,0 +1,92 @@
package one.oth3r.sit.file;
import com.google.gson.annotations.SerializedName;
import net.minecraft.block.BlockState;
import net.minecraft.registry.Registries;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Identifier;
import one.oth3r.sit.utl.Utl;
import java.util.ArrayList;
public class CustomBlock {
@SerializedName("block-ids")
private ArrayList<String> blockIds = new ArrayList<>();
@SerializedName("block-tags")
private ArrayList<String> blockTags = new ArrayList<>();
@SerializedName("blockstates")
private ArrayList<String> blockStates = new ArrayList<>();
@SerializedName("sittingHeight")
private Double sittingHeight = 0.5;
public CustomBlock() {}
public CustomBlock(ArrayList<String> blockIds, ArrayList<String> blockTags, ArrayList<String> blockStates, Double sittingHeight) {
this.blockIds = blockIds;
this.blockTags = blockTags;
this.blockStates = blockStates;
this.sittingHeight = sittingHeight;
}
public ArrayList<String> getBlockIds() {
return blockIds;
}
public ArrayList<String> getBlockTags() {
return blockTags;
}
public ArrayList<String> getBlockStates() {
return blockStates;
}
public Double getSittingHeight() {
return sittingHeight;
}
/**
* checks if the blockstate matches the CustomBlock params
* @param blockState the blockState to check
* @return if the blockstate is allowed by the CustomBlock rules
*/
public boolean isValid(BlockState blockState) {
boolean blockType = checkBlockType(blockState);
if (!blockType) return false;
// now check if the state is one of the acceptable states
for (String state : blockStates) {
// if there is a NOT (!) blockstate, and it is contained in the block, return false
if (state.startsWith("!") && blockState.toString().contains(state.substring(1))) return false;
// else check if the blockstate matches, if not return false
else if (!blockState.toString().contains(state)) return false;
}
// if here, all passes have passed
return true;
}
/**
* returns if the block is the correct type or not
* @param blockState the blockstate to check
* @return if the type of block is matching the CustomBlock rules (e.g. if it is wood, ect.)
*/
private boolean checkBlockType(BlockState blockState) {
// for all the entered blocks
for (String id : blockIds) {
// if there is a match for the NOT(!) blocks, return false immediately
if (id.startsWith("!") && id.substring(1).equals(Utl.getBlockID(blockState))) return false;
// if there is a match for the block, return true immediately
if (id.equalsIgnoreCase(Utl.getBlockID(blockState))) return true;
}
// for all the entered tags
for (String tag : blockTags) {
// substring to remove # and if needed, !
// if there is a math for the NOT(!) tag, return false
if (tag.startsWith("!") && blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.of(tag.substring(2))))) return false;
// if there is a match, return true
if (blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.of(tag.substring(1))))) return true;
}
return false;
}
}

View file

@ -0,0 +1,102 @@
package one.oth3r.sit.file;
import net.minecraft.entity.decoration.DisplayEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import java.util.HashMap;
public class Data {
/**
* Sit! config file
*/
private static ServerConfig serverConfig = new ServerConfig();
public static ServerConfig getServerConfig() {
return new ServerConfig(serverConfig);
}
public static void setServerConfig(ServerConfig newServerConfig) {
serverConfig = new ServerConfig(newServerConfig);
}
/**
* The default hand config for all new players
*/
private static HandConfig handConfig = new HandConfig();
public static HandConfig getHandConfig() {
return new HandConfig(handConfig);
}
public static void setHandConfig(HandConfig newHandConfig) {
handConfig = new HandConfig(newHandConfig);
}
/**
* the hand config stored per player on the server
*/
private static final HashMap<ServerPlayerEntity, HandConfig> playerSettings = new HashMap<>();
public static void clearPlayerSettings() {
playerSettings.clear();
}
public static void setPlayerSetting(ServerPlayerEntity player, HandConfig config) {
playerSettings.put(player, config);
}
public static void removePlayerSetting(ServerPlayerEntity player) {
playerSettings.remove(player);
}
public static HandConfig getPlayerSetting(ServerPlayerEntity player) {
return playerSettings.getOrDefault(player,handConfig);
}
/**
* a list of every Sit! entity in the server, bound to the player
*/
private static final HashMap<ServerPlayerEntity, DisplayEntity.TextDisplayEntity> sitEntities = new HashMap<>();
public static void addSitEntity(ServerPlayerEntity player, DisplayEntity.TextDisplayEntity entity) {
sitEntities.put(player, entity);
}
public static void removeSitEntity(DisplayEntity.TextDisplayEntity entity) {
sitEntities.values().remove(entity);
}
public static DisplayEntity.TextDisplayEntity getSitEntity(ServerPlayerEntity player) {
return sitEntities.get(player);
}
public static HashMap<ServerPlayerEntity, DisplayEntity.TextDisplayEntity> getSitEntities() {
return new HashMap<>(sitEntities);
}
/**
* a list of players who just joined, to check if they are mounted to a Sit! entity
*/
private static final HashMap<ServerPlayerEntity, Integer> checkPlayers = new HashMap<>();
public static void setCheckPlayer(ServerPlayerEntity player, Integer time) {
checkPlayers.put(player, time);
}
public static void removeCheckPlayer(ServerPlayerEntity player) {
checkPlayers.remove(player);
}
public static HashMap<ServerPlayerEntity, Integer> getCheckPlayers() {
return new HashMap<>(checkPlayers);
}
/**
* loads all config files to memory
* @param tryLegacy try to load the legacy file, usually only used on server startup
*/
public static void loadFiles(boolean tryLegacy) {
ServerConfig.load(tryLegacy);
HandConfig.load();
}
}

View file

@ -0,0 +1,97 @@
package one.oth3r.sit.file;
import com.google.gson.annotations.SerializedName;
import net.minecraft.util.Hand;
import one.oth3r.sit.Sit;
import one.oth3r.sit.utl.Utl;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
public class HandConfig {
@SerializedName("version")
private Double version = 1.0;
@SerializedName("hand-sitting")
private boolean handSitting = true;
@SerializedName("main-hand")
private HandSetting mainHand = new HandSetting(HandSetting.SittingRequirement.EMPTY, new HandSetting.Filter());
@SerializedName("off-hand")
private HandSetting offHand = new HandSetting(HandSetting.SittingRequirement.FILTER,
new HandSetting.Filter(false,true,false,new ArrayList<>(),new ArrayList<>())); // todo fill out some fox examples sake
public HandConfig() {}
public HandConfig(double version, boolean handSitting, HandSetting mainHand, HandSetting offHand) {
this.version = version;
this.handSitting = handSitting;
this.mainHand = mainHand;
this.offHand = offHand;
}
public HandConfig(HandConfig handConfig) {
this.version = handConfig.version;
this.handSitting = handConfig.handSitting;
this.mainHand = handConfig.mainHand;
this.offHand = handConfig.offHand;
}
public Double getVersion() {
return version;
}
public boolean canSitWithHand() {
return handSitting;
}
public HandSetting getHand(Hand handType) {
return handType.equals(Hand.MAIN_HAND) ? mainHand : offHand;
}
public HandSetting getMainHand() {
return mainHand;
}
public HandSetting getOffHand() {
return offHand;
}
public static File getFile() {
return new File(Sit.CONFIG_DIR+"hand-config.json");
}
/**
* loads the Config file to Data
*/
public static void load() {
File file = getFile();
if (!file.exists()) save();
// try reading the file
try (BufferedReader reader = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
Updater.HandConfigFile.run(reader);
} catch (Exception e) {
Sit.LOGGER.error(String.format("ERROR LOADING '%s`: %s", file.getName(),e.getMessage()));
}
// save after loading
save();
}
/**
* saves Data.config to config.json
*/
public static void save() {
if (!getFile().exists()) {
Sit.LOGGER.info(String.format("Creating new `%s`", getFile().getName()));
}
try (BufferedWriter writer = Files.newBufferedWriter(getFile().toPath(), StandardCharsets.UTF_8)) {
writer.write(Utl.getGson().toJson(Data.getHandConfig()));
} catch (Exception e) {
Sit.LOGGER.error(String.format("ERROR SAVING '%s`: %s", getFile().getName(), e.getMessage()));
}
}
}

View file

@ -0,0 +1,79 @@
package one.oth3r.sit.file;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
public class HandSetting {
public boolean mainBlock;
@SerializedName("requirement")
private SittingRequirement sittingRequirement = SittingRequirement.NONE;
@SerializedName("filter")
private Filter filter = new Filter();
public HandSetting() {}
public HandSetting(SittingRequirement sittingRequirement, Filter filter) {
this.sittingRequirement = sittingRequirement;
this.filter = filter;
}
public SittingRequirement getSittingRequirement() {
return sittingRequirement;
}
public Filter getFilter() {
return filter;
}
public enum SittingRequirement {
NONE,
FILTER,
EMPTY
}
public static class Filter {
@SerializedName("block")
private boolean block = false;
@SerializedName("food")
private boolean food = false;
@SerializedName("usable")
private boolean usable = false;
@SerializedName("custom-items")
private ArrayList<String> customItems = new ArrayList<>();
@SerializedName("custom-tags")
private ArrayList<String> customTags = new ArrayList<>();
public Filter() {}
public Filter(boolean block, boolean food, boolean usable, ArrayList<String> customItems, ArrayList<String> customTags) {
this.block = block;
this.food = food;
this.usable = usable;
this.customItems = customItems;
this.customTags = customTags;
}
public boolean isBlock() {
return block;
}
public boolean isFood() {
return food;
}
public boolean isUsable() {
return usable;
}
public ArrayList<String> getCustomItems() {
return customItems;
}
public ArrayList<String> getCustomTags() {
return customTags;
}
}
}

View file

@ -0,0 +1,107 @@
package one.oth3r.sit.file;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import one.oth3r.sit.Sit;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LangReader {
private static final Map<String, String> languageMap = new HashMap<>();
private final String translationKey;
private final Object[] placeholders;
public LangReader(String translationKey, Object... placeholders) {
this.translationKey = translationKey;
this.placeholders = placeholders;
}
public MutableText getTxT() {
String translated = getLanguageValue(translationKey);
if (placeholders != null && placeholders.length > 0) {
//removed all double \\ and replaces with \
translated = translated.replaceAll("\\\\\\\\", "\\\\");
String regex = "%\\d*\\$?[dfs]";
Matcher anyMatch = Pattern.compile(regex).matcher(translated);
Matcher endMatch = Pattern.compile(regex+"$").matcher(translated);
//Arraylist with all the %(#$)[dfs]
ArrayList<String> matches = new ArrayList<>();
while (anyMatch.find()) {
String match = anyMatch.group();
matches.add(match);
}
//SPLITS the text at each regex and remove the regex
String[] parts = translated.split(regex);
//if the last element of the array ends with regex, remove it and add an empty string to the end of the array
if (endMatch.find()) {
String[] newParts = Arrays.copyOf(parts, parts.length + 1);
newParts[parts.length] = "";
parts = newParts;
}
//if there are placeholders specified, and the split is more than 1, it will replace %(dfs) with the placeholder objects
if (parts.length > 1) {
MutableText txt = Text.empty();
int i = 0;
for (String match : matches) {
int get = i;
//if the match is numbered, change GET to the number it wants
if (match.contains("$")) {
match = match.substring(1,match.indexOf('$'));
get = Integer.parseInt(match)-1;
}
if (parts.length != i) txt.append(parts[i]);
//convert the obj into txt
Object obj = placeholders[get];
if (obj instanceof Text) txt.append((Text) obj);
else txt.append(String.valueOf(obj));
i++;
}
if (parts.length != i) txt.append(parts[i]);
return txt;
}
}
return Text.empty().append(translated);
}
public static LangReader of(String translationKey, Object... placeholders) {
return new LangReader(translationKey, placeholders);
}
public static void loadLanguageFile() {
ClassLoader classLoader = Sit.class.getClassLoader();
try {
InputStream inputStream = classLoader.getResourceAsStream("assets/sit/lang/"+ Data.getServerConfig().getLang() +".json");
// if the input stream is null, the language file wasn't found
if (inputStream == null) {
// try loading the default language file
inputStream = classLoader.getResourceAsStream("assets/sit/lang/"+ new ServerConfig().getLang() +".json");
//todo error message and reset back to EN_US
}
// if the input stream is still null, throw an exception
if (inputStream == null) throw new IllegalArgumentException("UNABLE TO LOAD THE LANGUAGE FILE.");
Type type = new TypeToken<Map<String, String>>(){}.getType();
Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
languageMap.putAll(new Gson().fromJson(reader, type));
// close the input stream
inputStream.close();
} catch (Exception e) {
Sit.LOGGER.error(e.getMessage());
}
}
public static String getLanguageValue(String key) {
return languageMap.getOrDefault(key, key);
}
}

View file

@ -0,0 +1,177 @@
package one.oth3r.sit.file;
import com.google.gson.annotations.SerializedName;
import one.oth3r.sit.Sit;
import one.oth3r.sit.utl.Utl;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
public class ServerConfig {
@SerializedName("version")
private Double version = 2.0;
@SerializedName("lang")
private String lang = "en_us";
@SerializedName("keep-active")
private Boolean keepActive = true;
@SerializedName("sit-while-seated")
private Boolean sitWhileSeated = false;
@SerializedName("preset-blocks")
private PresetBlocks presetBlocks = new PresetBlocks();
@SerializedName("custom-enabled")
private Boolean customEnabled = false;
@SerializedName("custom-blocks")
private ArrayList<CustomBlock> customBlocks = new ArrayList<>();
@SerializedName("blacklisted-blocks")
private ArrayList<String> blacklistedBlocks = new ArrayList<>();
public ServerConfig() {}
public ServerConfig(ServerConfig serverConfig) {
this.version = serverConfig.version;
this.lang = serverConfig.lang;
this.keepActive = serverConfig.keepActive;
this.sitWhileSeated = serverConfig.sitWhileSeated;
this.presetBlocks = serverConfig.presetBlocks;
this.customEnabled = serverConfig.customEnabled;
this.customBlocks = serverConfig.customBlocks;
this.blacklistedBlocks = serverConfig.blacklistedBlocks;
}
public ServerConfig(Double version, String lang, boolean keepActive, boolean sitWhileSeated, PresetBlocks presetBlocks, boolean customEnabled, ArrayList<CustomBlock> customBlocks, ArrayList<String> blacklistedBlocks) {
this.version = version;
this.lang = lang;
this.keepActive = keepActive;
this.sitWhileSeated = sitWhileSeated;
this.presetBlocks = presetBlocks;
this.customEnabled = customEnabled;
this.customBlocks = customBlocks;
this.blacklistedBlocks = blacklistedBlocks;
}
public Double getVersion() {
return version;
}
public String getLang() {
return lang;
}
public boolean isKeepActive() {
return keepActive;
}
public boolean isSitWhileSeated() {
return sitWhileSeated;
}
public PresetBlocks getPresetBlocks() {
return presetBlocks;
}
public Boolean isCustomEnabled() {
return customEnabled;
}
public ArrayList<CustomBlock> getCustomBlocks() {
return customBlocks;
}
public ArrayList<String> getBlacklistedBlocks() {
return blacklistedBlocks;
}
public static class PresetBlocks {
@SerializedName("stairs")
private boolean stairs = true;
@SerializedName("slabs")
private boolean slabs = true;
@SerializedName("carpets")
private boolean carpets = true;
@SerializedName("full-blocks")
private boolean fullBlocks = false;
public PresetBlocks() {}
public PresetBlocks(boolean stairs, boolean slabs, boolean carpets, boolean fullBlocks) {
this.stairs = stairs;
this.slabs = slabs;
this.carpets = carpets;
this.fullBlocks = fullBlocks;
}
public boolean isStairs() {
return stairs;
}
public boolean isSlabs() {
return slabs;
}
public boolean isCarpets() {
return carpets;
}
public boolean isFullBlocks() {
return fullBlocks;
}
}
public static File getFile() {
return new File(Sit.CONFIG_DIR+"server-config.json");
}
/**
* loads the directionhud Config file to Data.config
*/
public static void load(boolean tryLegacy) {
File file = getFile();
if (!file.exists()) {
// try to make the config directory
try {
Files.createDirectories(Paths.get(Sit.CONFIG_DIR));
} catch (Exception e) {
Sit.LOGGER.error("Failed to create config directory. Canceling all config loading...");
return;
}
// if loading from legacy, try checking the old config directory for the file
if (tryLegacy && Updater.ServerConfigFile.Legacy.getLegacyFile().exists()) {
Sit.LOGGER.info("Updating Sit!.properties to sit!/config.json");
Updater.ServerConfigFile.Legacy.run();
}
save();
}
try (BufferedReader reader = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
Updater.ServerConfigFile.run(reader);
} catch (Exception e) {
Sit.LOGGER.error(String.format("ERROR LOADING '%s`: %s", file.getName(),e.getMessage()));
}
// save after loading
save();
}
/**
* saves Data.config to config.json
*/
public static void save() {
if (!getFile().exists()) {
Sit.LOGGER.info(String.format("Creating new `%s`", getFile().getName()));
}
try (BufferedWriter writer = Files.newBufferedWriter(getFile().toPath(), StandardCharsets.UTF_8)) {
writer.write(Utl.getGson().toJson(Data.getServerConfig()));
} catch (Exception e) {
Sit.LOGGER.info(String.format("ERROR SAVING '%s`: %s", getFile().getName(), e.getMessage()));
}
}
}

View file

@ -0,0 +1,288 @@
package one.oth3r.sit.file;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import net.minecraft.util.Hand;
import one.oth3r.sit.Sit;
import one.oth3r.sit.utl.Utl;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.util.*;
public class Updater {
public static class HandConfigFile {
/**
* runs the updater from the file reader and sets the loaded settings when finished
* @param reader the file reader
* @throws NullPointerException if the file is null
*/
public static void run(BufferedReader reader)
throws NullPointerException {
// try to read the json
HandConfig handConfig;
try {
handConfig = Utl.getGson().fromJson(reader, HandConfig.class);
} catch (Exception e) {
throw new NullPointerException();
}
// throw null if the fileData is null or version is null
if (handConfig == null) throw new NullPointerException();
// get the file version
Double version = handConfig.getVersion();
// if there's no version, throw
if (version == null) throw new NullPointerException();
// update the config (using the non-null version)
handConfig = update(handConfig);
// set the config in the mod data
Data.setHandConfig(handConfig);
}
/**
* updates the file
*/
public static HandConfig update(HandConfig old) {
HandConfig serverConfig = new HandConfig(old);
return serverConfig;
}
}
public static class ServerConfigFile {
public static final double VERSION = 1.0;
/**
* runs the updater from the file reader and sets the loaded settings when finished
* @param reader the file reader
* @throws NullPointerException if the file is null
*/
public static void run(BufferedReader reader)
throws NullPointerException {
// try to read the json
ServerConfig serverConfig;
try {
serverConfig = Utl.getGson().fromJson(reader, ServerConfig.class);
} catch (Exception e) {
throw new NullPointerException();
}
// throw null if the fileData is null or version is null
if (serverConfig == null) throw new NullPointerException();
// get the file version
Double version = serverConfig.getVersion();
// if there's no version, throw
if (version == null) throw new NullPointerException();
// update the config (using the non-null version)
serverConfig = update(serverConfig);
System.out.println("updated");
System.out.println(serverConfig.getBlacklistedBlocks());
// set the config in the mod data
Data.setServerConfig(serverConfig);
}
/**
* updates the file
*/
public static ServerConfig update(ServerConfig old) {
ServerConfig serverConfig = new ServerConfig(old);
return serverConfig;
}
public static class Legacy {
/**
* gets the legacy file, from the old directory for fabric, and the same one for spigot
*/
public static File getLegacyFile() {
// strip the new directory
return new File(Sit.CONFIG_DIR.substring(0,Sit.CONFIG_DIR.length()-5)+"Sit!.properties");
}
/**
* updates the old Sit!.properties to config.json
*/
public static void run() {
// shouldn't happen, only call if the file exists
File file = getLegacyFile();
if (!file.exists()) return;
// update to the new system
try (FileInputStream fileStream = new FileInputStream(file)) {
Properties properties = new Properties();
properties.load(fileStream);
String ver = (String) properties.computeIfAbsent("version", a -> String.valueOf(VERSION));
// if the old version system (v1.0) remove "v"
if (ver.contains("v")) ver = ver.substring(1);
loadVersion(properties,Double.parseDouble(ver));
} catch (Exception e) {
Sit.LOGGER.error("Error loading legacy config file: {}", e.getMessage());
}
// delete the old file
try {
Files.delete(file.toPath());
Sit.LOGGER.info("Deleted " + file.getName());
} catch (Exception e) {
Sit.LOGGER.error("Failed to delete the old Sit! config.");
}
}
/**
* gets a list of custom blocks from the legacy way of entering custom sit blocks
*/
private static ArrayList<CustomBlock> getCustomBlocks(ArrayList<String> fix) {
//eg. minecraft:campfire|.46|1|lit=false
ArrayList<CustomBlock> out = new ArrayList<>();
for (String entry : fix) {
String[] split = entry.split("\\|");
// skip if not the right size
if (split.length < 3 || split.length > 4) continue;
// if the other entries aren't correct, skip
if (!Utl.Num.isNum(split[2])) continue;
// make the block states list if possible
ArrayList<String> blockstates = new ArrayList<>();
// if there are blockstates
if (split.length == 4) {
blockstates.addAll(Arrays.asList(split[3].split(",")));
}
// add if everything is A-OK
out.add(new CustomBlock(
new ArrayList<>(Arrays.asList(split[0])),
new ArrayList<>(),blockstates,Double.parseDouble(split[1])));
}
return out;
}
private static ArrayList<String> getFilterList(ArrayList<String> whitelist, ArrayList<String> blacklist) {
ArrayList<String> out = new ArrayList<>(whitelist);
// add a ! in front of every entry of the blacklist
out.addAll(blacklist.stream().map(e -> "!"+e).toList());
return out;
}
public static void loadVersion(Properties properties, double version) {
try {
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
Type listType = new TypeToken<ArrayList<String>>() {}.getType();
ServerConfig defaultConfig = new ServerConfig();
// load the latest config
ServerConfig serverConfig = new ServerConfig(
2.0,
(String) properties.computeIfAbsent("lang", a -> defaultConfig.getLang()),
Boolean.parseBoolean((String) properties.computeIfAbsent("keep-active", a -> String.valueOf(defaultConfig.isKeepActive()))),
Boolean.parseBoolean((String) properties.computeIfAbsent("sit-while-seated", a -> String.valueOf(defaultConfig.isSitWhileSeated()))),
new ServerConfig.PresetBlocks(
Boolean.parseBoolean((String) properties.computeIfAbsent("stairs", a -> String.valueOf(defaultConfig.getPresetBlocks().isStairs()))),
Boolean.parseBoolean((String) properties.computeIfAbsent("slabs", a -> String.valueOf(defaultConfig.getPresetBlocks().isSlabs()))),
Boolean.parseBoolean((String) properties.computeIfAbsent("carpets", a -> String.valueOf(defaultConfig.getPresetBlocks().isCarpets()))),
Boolean.parseBoolean((String) properties.computeIfAbsent("full-blocks", a -> String.valueOf(defaultConfig.getPresetBlocks().isFullBlocks())))
),
Boolean.parseBoolean((String) properties.computeIfAbsent("custom", a -> String.valueOf(defaultConfig.isCustomEnabled()))),
getCustomBlocks(new Gson().fromJson((String)
properties.computeIfAbsent("custom-blocks", a -> "[]"), listType)),
new ArrayList<>()
);
HandConfig defaultHandConfig = new HandConfig();
HandConfig handConfig = null;
try {
handConfig = new HandConfig(
1.0, Boolean.parseBoolean((String) properties.computeIfAbsent("hand.sitting", a -> String.valueOf(defaultHandConfig.canSitWithHand()))),
new HandSetting(
Utl.Enum.get(properties.computeIfAbsent("hand.main.requirement", a -> String.valueOf(defaultHandConfig.getHand(Hand.MAIN_HAND).getSittingRequirement())),HandSetting.SittingRequirement.class,HandSetting.SittingRequirement.FILTER),
new HandSetting.Filter(
Boolean.parseBoolean((String) properties.computeIfAbsent("hand.main.block", a -> String.valueOf(defaultHandConfig.getHand(Hand.MAIN_HAND).getFilter().isBlock()))),
Boolean.parseBoolean((String) properties.computeIfAbsent("hand.main.food", a -> String.valueOf(defaultHandConfig.getHand(Hand.MAIN_HAND).getFilter().isFood()))),
Boolean.parseBoolean((String) properties.computeIfAbsent("hand.main.usable", a -> String.valueOf(defaultHandConfig.getHand(Hand.MAIN_HAND).getFilter().isUsable()))),
getFilterList(
new Gson().fromJson((String) properties.computeIfAbsent("hand.main.whitelist", a -> "[]"), listType),
new Gson().fromJson((String) properties.computeIfAbsent("hand.main.blacklist", a -> "[]"), listType)
),
new ArrayList<>()
)
),
new HandSetting(
Utl.Enum.get(properties.computeIfAbsent("hand.off.requirement", a -> String.valueOf(defaultHandConfig.getHand(Hand.OFF_HAND).getSittingRequirement())),HandSetting.SittingRequirement.class,HandSetting.SittingRequirement.FILTER),
new HandSetting.Filter(
Boolean.parseBoolean((String) properties.computeIfAbsent("hand.off.block", a -> String.valueOf(defaultHandConfig.getHand(Hand.OFF_HAND).getFilter().isBlock()))),
Boolean.parseBoolean((String) properties.computeIfAbsent("hand.off.food", a -> String.valueOf(defaultHandConfig.getHand(Hand.OFF_HAND).getFilter().isFood()))),
Boolean.parseBoolean((String) properties.computeIfAbsent("hand.off.usable", a -> String.valueOf(defaultHandConfig.getHand(Hand.OFF_HAND).getFilter().isUsable()))),
getFilterList(
new Gson().fromJson((String) properties.computeIfAbsent("hand.off.whitelist", a -> "[]"), listType),
new Gson().fromJson((String) properties.computeIfAbsent("hand.off.blacklist", a -> "[]"), listType)
),
new ArrayList<>()
)
)
);
} catch (JsonSyntaxException ignored) {}
// load an older version
if (version == 1.0) {
try {
handConfig = new HandConfig(
1.0, defaultHandConfig.canSitWithHand(),
new HandSetting(
Utl.Enum.get(properties.computeIfAbsent("main-hand-requirement", a -> String.valueOf(defaultHandConfig.getHand(Hand.MAIN_HAND).getSittingRequirement())),HandSetting.SittingRequirement.class,HandSetting.SittingRequirement.FILTER),
new HandSetting.Filter(
Boolean.parseBoolean((String) properties.computeIfAbsent("main-hand-block", a -> String.valueOf(defaultHandConfig.getHand(Hand.MAIN_HAND).getFilter().isBlock()))),
Boolean.parseBoolean((String) properties.computeIfAbsent("main-hand-food", a -> String.valueOf(defaultHandConfig.getHand(Hand.MAIN_HAND).getFilter().isFood()))),
Boolean.parseBoolean((String) properties.computeIfAbsent("main-hand-usable", a -> String.valueOf(defaultHandConfig.getHand(Hand.MAIN_HAND).getFilter().isUsable()))),
getFilterList(
new Gson().fromJson((String) properties.computeIfAbsent("main-hand-whitelist", a -> "[]"), listType),
new Gson().fromJson((String) properties.computeIfAbsent("main-hand-blacklist", a -> "[]"), listType)
),
new ArrayList<>()
)
),
new HandSetting(
Utl.Enum.get(properties.computeIfAbsent("off-hand-requirement", a -> String.valueOf(defaultHandConfig.getHand(Hand.OFF_HAND).getSittingRequirement())),HandSetting.SittingRequirement.class,HandSetting.SittingRequirement.FILTER),
new HandSetting.Filter(
Boolean.parseBoolean((String) properties.computeIfAbsent("off-hand-block", a -> String.valueOf(defaultHandConfig.getHand(Hand.OFF_HAND).getFilter().isBlock()))),
Boolean.parseBoolean((String) properties.computeIfAbsent("off-hand-food", a -> String.valueOf(defaultHandConfig.getHand(Hand.OFF_HAND).getFilter().isFood()))),
Boolean.parseBoolean((String) properties.computeIfAbsent("off-hand-usable", a -> String.valueOf(defaultHandConfig.getHand(Hand.OFF_HAND).getFilter().isUsable()))),
getFilterList(
new Gson().fromJson((String) properties.computeIfAbsent("off-hand-whitelist", a -> "[]"), listType),
new Gson().fromJson((String) properties.computeIfAbsent("off-hand-blacklist", a -> "[]"), listType)
),
new ArrayList<>()
)
)
);
} catch (JsonSyntaxException ignored) {}
}
Data.setServerConfig(serverConfig);
Data.setHandConfig(handConfig);
ServerConfig.save();
HandConfig.save();
} catch (Exception e) {
Sit.LOGGER.error("Error loading legacy config: {}", e.getMessage());
}
}
}
}
}