Commit 1c4d263d authored by AnimeGitB's avatar AnimeGitB
Browse files

Add Data TSJ loading, replace and update Banners

parent 35962542
...@@ -5,6 +5,8 @@ import emu.grasscutter.server.http.handlers.GachaHandler; ...@@ -5,6 +5,8 @@ import emu.grasscutter.server.http.handlers.GachaHandler;
import emu.grasscutter.tools.Tools; import emu.grasscutter.tools.Tools;
import emu.grasscutter.utils.FileUtils; import emu.grasscutter.utils.FileUtils;
import emu.grasscutter.utils.JsonUtils; import emu.grasscutter.utils.JsonUtils;
import emu.grasscutter.utils.TsvUtils;
import lombok.val;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
...@@ -88,6 +90,17 @@ public class DataLoader { ...@@ -88,6 +90,17 @@ public class DataLoader {
} }
} }
public static <T> List<T> loadTableToList(String resourcePath, Class<T> classType) throws IOException {
val path = FileUtils.getDataPathTsjJsonTsv(resourcePath);
Grasscutter.getLogger().info("Loading data table from: "+path);
return switch (FileUtils.getFileExtension(path)) {
case "json" -> JsonUtils.loadToList(path, classType);
case "tsj" -> TsvUtils.loadTsjToListSetField(path, classType);
case "tsv" -> TsvUtils.loadTsvToListSetField(path, classType);
default -> null;
};
}
public static void checkAllFiles() { public static void checkAllFiles() {
try { try {
List<Path> filenames = FileUtils.getPathsFromResource("/defaults/data/"); List<Path> filenames = FileUtils.getPathsFromResource("/defaults/data/");
......
...@@ -152,8 +152,8 @@ public class ResourceLoader { ...@@ -152,8 +152,8 @@ public class ResourceLoader {
protected static <T> void loadFromResource(Class<T> c, Path filename, Int2ObjectMap map) throws Exception { protected static <T> void loadFromResource(Class<T> c, Path filename, Int2ObjectMap map) throws Exception {
val results = switch (FileUtils.getFileExtension(filename)) { val results = switch (FileUtils.getFileExtension(filename)) {
case "json" -> JsonUtils.loadToList(filename, c); case "json" -> JsonUtils.loadToList(filename, c);
case "tsj" -> TsvUtils.loadTsjToListSetField(c, filename); case "tsj" -> TsvUtils.loadTsjToListSetField(filename, c);
case "tsv" -> TsvUtils.loadTsvToListSetField(c, filename); case "tsv" -> TsvUtils.loadTsvToListSetField(filename, c);
default -> null; default -> null;
}; };
if (results == null) return; if (results == null) return;
......
...@@ -27,7 +27,7 @@ public class GachaBanner { ...@@ -27,7 +27,7 @@ public class GachaBanner {
private int[] rateUpItems4 = {}; private int[] rateUpItems4 = {};
private int[] rateUpItems5 = {}; private int[] rateUpItems5 = {};
@Getter private int[] fallbackItems3 = {11301, 11302, 11306, 12301, 12302, 12305, 13303, 14301, 14302, 14304, 15301, 15302, 15304}; @Getter private int[] fallbackItems3 = {11301, 11302, 11306, 12301, 12302, 12305, 13303, 14301, 14302, 14304, 15301, 15302, 15304};
@Getter private int[] fallbackItems4Pool1 = {1014, 1020, 1023, 1024, 1025, 1027, 1031, 1032, 1034, 1036, 1039, 1043, 1044, 1045, 1048, 1053, 1055, 1056, 1064}; @Getter private int[] fallbackItems4Pool1 = {1014, 1020, 1023, 1024, 1025, 1027, 1031, 1032, 1034, 1036, 1039, 1043, 1044, 1045, 1048, 1053, 1055, 1056, 1059, 1064, 1065, 1067, 1068, 1072};
@Getter private int[] fallbackItems4Pool2 = {11401, 11402, 11403, 11405, 12401, 12402, 12403, 12405, 13401, 13407, 14401, 14402, 14403, 14409, 15401, 15402, 15403, 15405}; @Getter private int[] fallbackItems4Pool2 = {11401, 11402, 11403, 11405, 12401, 12402, 12403, 12405, 13401, 13407, 14401, 14402, 14403, 14409, 15401, 15402, 15403, 15405};
@Getter private int[] fallbackItems5Pool1 = {1003, 1016, 1042, 1035, 1041}; @Getter private int[] fallbackItems5Pool1 = {1003, 1016, 1042, 1035, 1041};
@Getter private int[] fallbackItems5Pool2 = {11501, 11502, 12501, 12502, 13502, 13505, 14501, 14502, 15501, 15502}; @Getter private int[] fallbackItems5Pool2 = {11501, 11502, 12501, 12502, 13502, 13505, 14501, 14502, 15501, 15502};
......
...@@ -70,7 +70,7 @@ public class GachaSystem extends BaseGameSystem { ...@@ -70,7 +70,7 @@ public class GachaSystem extends BaseGameSystem {
public synchronized void load() { public synchronized void load() {
getGachaBanners().clear(); getGachaBanners().clear();
try { try {
List<GachaBanner> banners = DataLoader.loadList("Banners.json", GachaBanner.class); List<GachaBanner> banners = DataLoader.loadTableToList("Banners", GachaBanner.class);
if (banners.size() > 0) { if (banners.size() > 0) {
for (GachaBanner banner : banners) { for (GachaBanner banner : banners) {
banner.onLoad(); banner.onLoad();
......
...@@ -88,6 +88,19 @@ public final class FileUtils { ...@@ -88,6 +88,19 @@ public final class FileUtils {
: Path.of(scripts); : Path.of(scripts);
}; };
private static final String[] TSJ_JSON_TSV = {"tsj", "json", "tsv"};
private static final Path[] DATA_PATHS = {DATA_USER_PATH, DATA_DEFAULT_PATH};
public static Path getDataPathTsjJsonTsv(String filename) {
val name = getFilenameWithoutExtension(filename);
for (val data_path : DATA_PATHS) {
for (val ext : TSJ_JSON_TSV) {
val path = data_path.resolve(name + "." + ext);
if (Files.exists(path)) return path;
}
}
return DATA_USER_PATH.resolve(name + ".tsj"); // Maybe they want to write to a new file
}
public static Path getDataPath(String path) { public static Path getDataPath(String path) {
Path userPath = DATA_USER_PATH.resolve(path); Path userPath = DATA_USER_PATH.resolve(path);
if (Files.exists(userPath)) return userPath; if (Files.exists(userPath)) return userPath;
...@@ -121,13 +134,11 @@ public final class FileUtils { ...@@ -121,13 +134,11 @@ public final class FileUtils {
// If none exist, return the TSJ path, in case it wants to create a file // If none exist, return the TSJ path, in case it wants to create a file
public static Path getTsjJsonTsv(Path root, String filename) { public static Path getTsjJsonTsv(Path root, String filename) {
val name = getFilenameWithoutExtension(filename); val name = getFilenameWithoutExtension(filename);
val tsj = root.resolve(name + ".tsj"); for (val ext : TSJ_JSON_TSV) {
if (Files.exists(tsj)) return tsj; val path = root.resolve(name + "." + ext);
val json = root.resolve(name + ".json"); if (Files.exists(path)) return path;
if (Files.exists(json)) return json; }
val tsv = root.resolve(name + ".tsv"); return root.resolve(name + ".tsj");
if (Files.exists(tsv)) return tsv;
return tsj;
} }
public static Path getScriptPath(String path) { public static Path getScriptPath(String path) {
......
...@@ -402,7 +402,7 @@ public class TsvUtils { ...@@ -402,7 +402,7 @@ public class TsvUtils {
// Arrays are represented as arrayName.0, arrayName.1, etc. columns. // Arrays are represented as arrayName.0, arrayName.1, etc. columns.
// Maps/POJOs are represented as objName.fieldOneName, objName.fieldTwoName, etc. columns. // Maps/POJOs are represented as objName.fieldOneName, objName.fieldTwoName, etc. columns.
// This is currently about 25x as slow as TSJ and Gson parsers, likely due to the tree spam. // This is currently about 25x as slow as TSJ and Gson parsers, likely due to the tree spam.
public static <T> List<T> loadTsvToListSetField(Class<T> classType, Path filename) { public static <T> List<T> loadTsvToListSetField(Path filename, Class<T> classType) {
try (val fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { try (val fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) {
// val fieldMap = getClassFieldMap(classType); // val fieldMap = getClassFieldMap(classType);
// val constructor = classType.getDeclaredConstructor(); // val constructor = classType.getDeclaredConstructor();
...@@ -453,7 +453,7 @@ public class TsvUtils { ...@@ -453,7 +453,7 @@ public class TsvUtils {
// This uses a hybrid format where columns can hold JSON-encoded values. // This uses a hybrid format where columns can hold JSON-encoded values.
// I'll term it TSJ (tab-separated JSON) for now, it has convenient properties. // I'll term it TSJ (tab-separated JSON) for now, it has convenient properties.
public static <T> List<T> loadTsjToListSetField(Class<T> classType, Path filename) { public static <T> List<T> loadTsjToListSetField(Path filename, Class<T> classType) {
try (val fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) { try (val fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) {
val fieldMap = getClassFieldMap(classType); val fieldMap = getClassFieldMap(classType);
val constructor = classType.getDeclaredConstructor(); val constructor = classType.getDeclaredConstructor();
......
[
{
"comment": "Beginner's Banner. Do not change for no reason.",
"gachaType": 100,
"scheduleId": 803,
"bannerType": "EVENT",
"prefabPath": "GachaShowPanel_A016",
"titlePath": "UI_GACHA_SHOW_PANEL_A016_TITLE",
"costItemId": 224,
"costItemAmount10": 8,
"gachaTimesLimit": 20,
"beginTime": 0,
"endTime": 1924992000,
"sortId": 9999,
"rateUpItems5": [],
"rateUpItems4": [1034]
},
{
"comment": "Standard",
"gachaType": 200,
"scheduleId": 893,
"bannerType": "STANDARD",
"prefabPath": "GachaShowPanel_A022",
"titlePath": "UI_GACHA_SHOW_PANEL_A022_TITLE",
"costItemId": 224,
"beginTime": 0,
"endTime": 1924992000,
"sortId": 1000,
"fallbackItems4Pool1": [1006, 1014, 1015, 1020, 1021, 1023, 1024, 1025, 1027, 1031, 1032, 1034, 1036, 1039, 1043, 1044, 1045, 1048, 1053, 1055, 1056, 1064],
"weights5": [[1,75], [73,150], [90,10000]]
},
{
"comment": "Character Event Banner 1",
"gachaType": 301,
"scheduleId": 903,
"bannerType": "EVENT",
"prefabPath": "GachaShowPanel_A103",
"titlePath": "UI_GACHA_SHOW_PANEL_A081_TITLE",
"costItemId": 223,
"beginTime": 0,
"endTime": 1924992000,
"sortId": 9998,
"rateUpItems4": [1032, 1020, 1034],
"rateUpItems5": [1073],
"fallbackItems5Pool2": [],
"weights5": [[1,80], [73,80], [90,10000]]
},
{
"comment": "Character Event Banner 2",
"gachaType": 400,
"scheduleId": 923,
"bannerType": "EVENT",
"prefabPath": "GachaShowPanel_A104",
"titlePath": "UI_GACHA_SHOW_PANEL_A049_TITLE",
"costItemId": 223,
"beginTime": 0,
"endTime": 1924992000,
"sortId": 9998,
"rateUpItems4": [1032, 1020, 1034],
"rateUpItems5": [1049],
"fallbackItems5Pool2": [],
"weights5": [[1,80], [73,80], [90,10000]]
},
{
"comment": "Weapon Event Banner",
"gachaType": 302,
"scheduleId": 913,
"bannerType": "WEAPON",
"prefabPath": "GachaShowPanel_A105",
"titlePath": "UI_GACHA_SHOW_PANEL_A021_TITLE",
"costItemId": 223,
"beginTime": 0,
"endTime": 1924992000,
"sortId": 9997,
"rateUpItems4":[15405, 11402, 13407, 14402, 12403],
"rateUpItems5": [14511, 15509],
"fallbackItems5Pool1": [],
"weights4": [[1,600], [7,600], [8,6600], [10,12600]],
"weights5": [[1,100], [62,100], [73,7800], [80,10000]],
"eventChance4": 75,
"eventChance5": 75
}
]
comment gachaType scheduleId bannerType prefabPath titlePath costItemId beginTime endTime sortId rateUpItems5 rateUpItems4 weights5 weights4 fallbackItems5Pool2 fallbackItems5Pool1 fallbackItems4Pool1 eventChance4 eventChance5 costItemAmount10 gachaTimesLimit
Beginner's Banner. Do not change for no reason. 100 803 EVENT GachaShowPanel_A016 UI_GACHA_SHOW_PANEL_A016_TITLE 224 1924992000 9999 [1034] 8 20
Standard 200 893 STANDARD GachaShowPanel_A022 UI_GACHA_SHOW_PANEL_A022_TITLE 224 1924992000 1000 [[1, 75], [73, 150], [90, 10000]] [1006, 1014, 1015, 1020, 1021, 1023, 1024, 1025, 1027, 1031, 1032, 1034, 1036, 1039, 1043, 1044, 1045, 1048, 1053, 1055, 1056, 1059, 1064, 1065, 1067, 1068, 1072]
Character Event Banner 1 301 903 EVENT GachaShowPanel_A106 UI_GACHA_SHOW_PANEL_A071_TITLE 223 1924992000 9998 [1058] [1050, 1059, 1074] [[1, 80], [73, 80], [90, 10000]] []
Character Event Banner 2 400 923 EVENT GachaShowPanel_A107 UI_GACHA_SHOW_PANEL_A037_TITLE 223 1924992000 9998 [1033] [1050, 1059, 1074] [[1, 80], [73, 80], [90, 10000]] []
Weapon Event Banner 302 913 WEAPON GachaShowPanel_A108 UI_GACHA_SHOW_PANEL_A021_TITLE 223 1924992000 9997 [14509, 15507] [11401, 12402, 13401, 14401, 15402] [[1, 100], [62, 100], [73, 7800], [80, 10000]] [[1, 600], [7, 600], [8, 6600], [10, 12600]] [] 75 75
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment