Initial Commit

This commit is contained in:
Melledy
2025-10-27 02:02:26 -07:00
commit f58951fe2a
378 changed files with 315914 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
package emu.nebula.data;
public abstract class BaseDef implements Comparable<BaseDef> {
public abstract int getId();
public void onLoad() {
}
@Override
public int compareTo(BaseDef o) {
return this.getId() - o.getId();
}
}

View File

@@ -0,0 +1,89 @@
package emu.nebula.data;
import java.util.Iterator;
import java.util.stream.Stream;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntCollection;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.ObjectCollection;
import it.unimi.dsi.fastutil.objects.ObjectSet;
public class DataTable<T> implements Iterable<T> {
private Int2ObjectMap<T> map;
public DataTable() {
this.map = new Int2ObjectOpenHashMap<>();
}
@SuppressWarnings("unchecked")
public void add(Object res) {
if (res instanceof BaseDef r) {
this.map.put(r.getId(), (T) res);
}
}
public int size() {
return this.map.size();
}
// Wrapper functions
/**
* Wrapper for {@link it.unimi.dsi.fastutil.ints.Int2ObjectMap.get}
*/
public T get(int id) {
return this.map.get(id);
}
/**
* Wrapper for {@link it.unimi.dsi.fastutil.ints.Int2ObjectMap.containsKey}
*/
public boolean containsKey(int id) {
return this.map.containsKey(id);
}
/**
* Wrapper for {@link it.unimi.dsi.fastutil.ints.Int2ObjectMap.keySet}
*/
public IntSet keySet() {
return this.map.keySet();
}
/**
* Wrapper for {@link it.unimi.dsi.fastutil.ints.Int2ObjectMap.values}
*/
public ObjectCollection<T> values() {
return this.map.values();
}
/**
* Wrapper for {@link it.unimi.dsi.fastutil.ints.Int2ObjectMap.int2ObjectEntrySet}
*/
public ObjectSet<Int2ObjectMap.Entry<T>> int2ObjectEntrySet() {
return this.map.int2ObjectEntrySet();
}
// Iterable/Streamable
@Override
public Iterator<T> iterator() {
return this.values().iterator();
}
public Stream<T> stream() {
return this.values().stream();
}
// Custom
public IntCollection getIds() {
return this.map.keySet();
}
public IntCollection getAllIds() {
return this.getIds();
}
}

View File

@@ -0,0 +1,45 @@
package emu.nebula.data;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import emu.nebula.data.resources.*;
import lombok.Getter;
@SuppressWarnings("unused")
public class GameData {
@Getter private static DataTable<CharacterDef> CharacterDataTable = new DataTable<>();
@Getter private static DataTable<CharacterAdvanceDef> CharacterAdvanceDataTable = new DataTable<>();
@Getter private static DataTable<CharacterSkillUpgradeDef> CharacterSkillUpgradeDataTable = new DataTable<>();
@Getter private static DataTable<CharacterUpgradeDef> CharacterUpgradeDataTable = new DataTable<>();
@Getter private static DataTable<CharItemExpDef> CharItemExpDataTable = new DataTable<>();
@Getter private static DataTable<DiscDef> DiscDataTable = new DataTable<>();
@Getter private static DataTable<DiscStrengthenDef> DiscStrengthenDataTable = new DataTable<>();
@Getter private static DataTable<DiscItemExpDef> DiscItemExpDataTable = new DataTable<>();
@Getter private static DataTable<DiscPromoteDef> DiscPromoteDataTable = new DataTable<>();
@Getter private static DataTable<DiscPromoteLimitDef> DiscPromoteLimitDataTable = new DataTable<>();
@Getter private static DataTable<ItemDef> ItemDataTable = new DataTable<>();
@Getter private static DataTable<MallMonthlyCardDef> MallMonthlyCardDataTable = new DataTable<>();
@Getter private static DataTable<MallPackageDef> MallPackageDataTable = new DataTable<>();
@Getter private static DataTable<MallShopDef> MallShopDataTable = new DataTable<>();
@Getter private static DataTable<MallGemDef> MallGemDataTable = new DataTable<>();
@Getter private static DataTable<WorldClassDef> WorldClassDataTable = new DataTable<>();
@Getter private static DataTable<GuideGroupDef> GuideGroupDataTable = new DataTable<>();
@Getter private static DataTable<StarTowerDef> StarTowerDataTable = new DataTable<>();
@Getter private static DataTable<PotentialDef> PotentialDataTable = new DataTable<>();
}

View File

@@ -0,0 +1,121 @@
package emu.nebula.data;
import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Collectors;
import org.reflections.Reflections;
import emu.nebula.util.JsonUtils;
import emu.nebula.util.Utils;
import emu.nebula.Nebula;
public class ResourceLoader {
private static boolean loaded = false;
// Load all resources
public static void loadAll() {
// Make sure we don't load more than once
if (loaded) return;
// Load
loadResources();
// Done
loaded = true;
Nebula.getLogger().info("Resource loading complete");
}
public static void loadResources() {
// Get resource classes and sort
List<Class<?>> classes = new Reflections(ResourceLoader.class.getPackage().getName())
.getTypesAnnotatedWith(ResourceType.class)
.stream()
.collect(Collectors.toList());
classes.sort((a, b) -> b.getAnnotation(ResourceType.class).loadPriority().value() - a.getAnnotation(ResourceType.class).loadPriority().value());
// Load resource
for (Class<?> def : classes) {
loadFromResource(def);
}
}
public static void loadFromResource(Class<?> resourceClass) {
// Load to map
DataTable<?> table = getTableForResource(GameData.class, resourceClass);
ResourceType type = resourceClass.getAnnotation(ResourceType.class);
// Sanity check
if (type == null) {
return;
}
int count = 0;
try {
var json = JsonUtils.loadToMap(Nebula.getConfig().resourceDir + "/bin/" + type.name(), String.class, resourceClass);
for (Object o : json.values()) {
BaseDef res = (BaseDef) o;
if (res == null) {
continue;
}
res.onLoad();
count++;
if (table != null) {
table.add(o);
}
}
} catch (Exception e) {
e.printStackTrace();
Nebula.getLogger().error("Error loading resource file: " + type.name(), e);
}
Nebula.getLogger().info("Loaded " + count + " " + resourceClass.getSimpleName() + "s.");
}
// Utility
@SuppressWarnings("unchecked")
private static <T> DataTable<T> getTableForResource(Class<?> dataClass, Class<T> resourceClass) {
// Init
DataTable<T> table = null;
Field field = null;
// Parse out "Def" in the resource name
String simpleName = resourceClass.getSimpleName();
if (simpleName.endsWith("Def")) {
simpleName = simpleName.substring(0, simpleName.length() - 3) + "Data";
}
// Get table
try {
field = dataClass.getDeclaredField(simpleName + "Table");
} catch (Exception e) {
try {
field = dataClass.getDeclaredField(Utils.lowerCaseFirstChar(simpleName) + "Table");
} catch (Exception ex) {
}
}
if (field != null) {
try {
field.setAccessible(true);
table = (DataTable<T>) field.get(null);
} catch (Exception e) {
} finally {
field.setAccessible(false);
}
}
return table;
}
}

View File

@@ -0,0 +1,33 @@
package emu.nebula.data;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface ResourceType {
/** Names of the file that this Resource loads from */
String name();
/**
* Load priority - dictates which order to load this resource, with "highest"
* being loaded first
*/
LoadPriority loadPriority() default LoadPriority.NORMAL;
Class<?> keyType() default int.class;
public enum LoadPriority {
HIGHEST(4), HIGH(3), NORMAL(2), LOW(1), LOWEST(0);
private final int value;
LoadPriority(int value) {
this.value = value;
}
public int value() {
return value;
}
}
}

View File

@@ -0,0 +1,17 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "CharItemExp.json")
public class CharItemExpDef extends BaseDef {
private int ItemId;
private int ExpValue;
@Override
public int getId() {
return ItemId;
}
}

View File

@@ -0,0 +1,55 @@
package emu.nebula.data.resources;
import emu.nebula.GameConstants;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import emu.nebula.data.ResourceType.LoadPriority;
import emu.nebula.game.inventory.ItemParamMap;
import lombok.Getter;
@Getter
@ResourceType(name = "CharacterAdvance.json", loadPriority = LoadPriority.LOW)
public class CharacterAdvanceDef extends BaseDef {
private int Id;
private int Group;
private int AdvanceLvl;
private int Tid1;
private int Qty1;
private int Tid2;
private int Qty2;
private int Tid3;
private int Qty3;
private int Tid4;
private int Qty4;
private int GoldQty;
private transient ItemParamMap materials;
@Override
public int getId() {
return Id;
}
@Override
public void onLoad() {
this.materials = new ItemParamMap();
if (this.Tid1 > 0) {
this.materials.add(this.Tid1, this.Qty1);
}
if (this.Tid2 > 0) {
this.materials.add(this.Tid2, this.Qty2);
}
if (this.Tid3 > 0) {
this.materials.add(this.Tid3, this.Qty3);
}
if (this.Tid4 > 0) {
this.materials.add(this.Tid4, this.Qty4);
}
if (this.GoldQty > 0) {
this.materials.add(GameConstants.GOLD_ITEM_ID, this.GoldQty);
}
}
}

View File

@@ -0,0 +1,32 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "Character.json")
public class CharacterDef extends BaseDef {
private int Id;
private String Name;
private boolean Available;
private int Grade;
private int DefaultSkinId;
private int AdvanceSkinId;
private int AdvanceGroup;
private int[] SkillsUpgradeGroup;
@Override
public int getId() {
return Id;
}
public int getSkillsUpgradeGroup(int index) {
if (index < 0 || index >= this.SkillsUpgradeGroup.length) {
return -1;
}
return this.SkillsUpgradeGroup[index];
}
}

View File

@@ -0,0 +1,57 @@
package emu.nebula.data.resources;
import emu.nebula.GameConstants;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import emu.nebula.data.ResourceType.LoadPriority;
import emu.nebula.game.inventory.ItemParamMap;
import lombok.Getter;
@Getter
@ResourceType(name = "CharacterSkillUpgrade.json", loadPriority = LoadPriority.LOW)
public class CharacterSkillUpgradeDef extends BaseDef {
private int Group;
private int AdvanceNum;
private int Tid1;
private int Qty1;
private int Tid2;
private int Qty2;
private int Tid3;
private int Qty3;
private int Tid4;
private int Qty4;
private int GoldQty;
private transient int upgradeId;
private transient ItemParamMap materials;
@Override
public int getId() {
return upgradeId;
}
@Override
public void onLoad() {
this.materials = new ItemParamMap();
if (this.Tid1 > 0) {
this.materials.add(this.Tid1, this.Qty1);
}
if (this.Tid2 > 0) {
this.materials.add(this.Tid2, this.Qty2);
}
if (this.Tid3 > 0) {
this.materials.add(this.Tid3, this.Qty3);
}
if (this.Tid4 > 0) {
this.materials.add(this.Tid4, this.Qty4);
}
if (this.GoldQty > 0) {
this.materials.add(GameConstants.GOLD_ITEM_ID, this.GoldQty);
}
this.upgradeId = (this.Group * 100) + this.AdvanceNum;
}
}

View File

@@ -0,0 +1,17 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "CharacterUpgrade.json")
public class CharacterUpgradeDef extends BaseDef {
private int Level;
private int Exp;
@Override
public int getId() {
return Level;
}
}

View File

@@ -0,0 +1,24 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "Disc.json")
public class DiscDef extends BaseDef {
private int Id;
private int StrengthenGroupId;
private int PromoteGroupId;
private int TransformItemId;
@Override
public int getId() {
return Id;
}
@Override
public void onLoad() {
}
}

View File

@@ -0,0 +1,17 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "DiscItemExp.json")
public class DiscItemExpDef extends BaseDef {
private int ItemId;
private int Exp;
@Override
public int getId() {
return ItemId;
}
}

View File

@@ -0,0 +1,50 @@
package emu.nebula.data.resources;
import emu.nebula.GameConstants;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import emu.nebula.data.ResourceType.LoadPriority;
import emu.nebula.game.inventory.ItemParamMap;
import lombok.Getter;
@Getter
@ResourceType(name = "DiscPromote.json", loadPriority = LoadPriority.LOW)
public class DiscPromoteDef extends BaseDef {
private int Id;
private int Group;
private int AdvanceLvl;
private int ItemId1;
private int Num1;
private int ItemId2;
private int Num2;
private int ItemId3;
private int Num3;
private int ExpenseGold;
private transient ItemParamMap materials;
@Override
public int getId() {
return Id;
}
@Override
public void onLoad() {
this.materials = new ItemParamMap();
if (this.ItemId1 > 0 && this.Num1 > 0) {
this.materials.add(this.ItemId1, this.Num1);
}
if (this.ItemId2 > 0 && this.Num2 > 0) {
this.materials.add(this.ItemId2, this.Num2);
}
if (this.ItemId3 > 0 && this.Num3 > 0) {
this.materials.add(this.ItemId3, this.Num3);
}
if (this.ExpenseGold > 0) {
this.materials.add(GameConstants.GOLD_ITEM_ID, this.ExpenseGold);
}
}
}

View File

@@ -0,0 +1,20 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "DiscPromoteLimit.json")
public class DiscPromoteLimitDef extends BaseDef {
private int Id;
private int Rarity;
private int Phase;
private int MaxLevel;
private int WorldClassLimit;
@Override
public int getId() {
return Id;
}
}

View File

@@ -0,0 +1,18 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "DiscStrengthen.json")
public class DiscStrengthenDef extends BaseDef {
private int Id;
private int Exp;
@Override
public int getId() {
return Id;
}
}

View File

@@ -0,0 +1,17 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "GuideGroup.json")
public class GuideGroupDef extends BaseDef {
private int Id;
private boolean IsActive;
@Override
public int getId() {
return Id;
}
}

View File

@@ -0,0 +1,32 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import emu.nebula.game.inventory.ItemSubType;
import emu.nebula.game.inventory.ItemType;
import lombok.Getter;
@Getter
@ResourceType(name = "Item.json")
public class ItemDef extends BaseDef {
private int Id;
private String Title;
private int Type;
private int Stype;
private int Rarity;
private boolean Stack;
private transient ItemType itemType;
private transient ItemSubType itemSubType;
@Override
public int getId() {
return Id;
}
@Override
public void onLoad() {
this.itemType = ItemType.getByValue(this.Type);
this.itemSubType = ItemSubType.getByValue(this.Stype);
}
}

View File

@@ -0,0 +1,23 @@
package emu.nebula.data.resources;
import com.google.gson.annotations.SerializedName;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "MallGem.json")
public class MallGemDef extends BaseDef {
@SerializedName("Id")
private String IdString;
private int Stock;
private int ItemId;
private int CurrencyItemId;
private int ItemQty;
@Override
public int getId() {
return IdString.hashCode();
}
}

View File

@@ -0,0 +1,23 @@
package emu.nebula.data.resources;
import com.google.gson.annotations.SerializedName;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "MallMonthlyCard.json")
public class MallMonthlyCardDef extends BaseDef {
@SerializedName("Id")
private String IdString;
private int MonthlyCardId;
private int Price;
private int BaseItemId;
private int BaseItemQty;
@Override
public int getId() {
return IdString.hashCode();
}
}

View File

@@ -0,0 +1,23 @@
package emu.nebula.data.resources;
import com.google.gson.annotations.SerializedName;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "MallPackage.json")
public class MallPackageDef extends BaseDef {
@SerializedName("Id")
private String IdString;
private int Stock;
private int CurrencyType;
private int CurrencyItemId;
private int CurrencyItemQty;
@Override
public int getId() {
return IdString.hashCode();
}
}

View File

@@ -0,0 +1,23 @@
package emu.nebula.data.resources;
import com.google.gson.annotations.SerializedName;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "MallShop.json")
public class MallShopDef extends BaseDef {
@SerializedName("Id")
private String IdString;
private int Stock;
private int ItemId;
private int CurrencyItemId;
private int ItemQty;
@Override
public int getId() {
return IdString.hashCode();
}
}

View File

@@ -0,0 +1,19 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "Potential.json")
public class PotentialDef extends BaseDef {
private int Id;
private int CharId;
private int Build;
private int MaxLevel;
@Override
public int getId() {
return Id;
}
}

View File

@@ -0,0 +1,17 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "StarTower.json")
public class StarTowerDef extends BaseDef {
private int Id;
private int[] FloorNum;
@Override
public int getId() {
return Id;
}
}

View File

@@ -0,0 +1,18 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "WorldClass.json")
public class WorldClassDef extends BaseDef {
private int Id;
private int Exp;
private String Reward;
@Override
public int getId() {
return Id;
}
}