mirror of
https://github.com/Melledy/Nebula.git
synced 2025-12-22 09:14:35 +01:00
Initial Commit
This commit is contained in:
283
src/main/java/emu/nebula/game/character/Character.java
Normal file
283
src/main/java/emu/nebula/game/character/Character.java
Normal file
@@ -0,0 +1,283 @@
|
||||
package emu.nebula.game.character;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import dev.morphia.annotations.Id;
|
||||
import dev.morphia.annotations.Indexed;
|
||||
|
||||
import emu.nebula.GameConstants;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.data.resources.CharacterDef;
|
||||
import emu.nebula.database.GameDatabaseObject;
|
||||
import emu.nebula.game.inventory.ItemParamMap;
|
||||
import emu.nebula.game.player.Player;
|
||||
import emu.nebula.game.player.PlayerChangeInfo;
|
||||
import emu.nebula.proto.Public.Char;
|
||||
import emu.nebula.proto.Public.CharGemPreset;
|
||||
import emu.nebula.proto.Public.CharGemSlot;
|
||||
import emu.nebula.proto.PublicStarTower.StarTowerChar;
|
||||
import emu.nebula.proto.PublicStarTower.StarTowerCharGem;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Entity(value = "characters", useDiscriminator = false)
|
||||
public class Character implements GameDatabaseObject {
|
||||
@Id
|
||||
private ObjectId uid;
|
||||
@Indexed
|
||||
private int playerUid;
|
||||
|
||||
private transient CharacterDef data;
|
||||
private transient Player player;
|
||||
|
||||
private int charId;
|
||||
private int advance;
|
||||
private int level;
|
||||
private int exp;
|
||||
private int skin;
|
||||
private int[] skills;
|
||||
private byte[] talents;
|
||||
|
||||
private long createTime;
|
||||
|
||||
@Deprecated // Morphia only!
|
||||
public Character() {
|
||||
|
||||
}
|
||||
|
||||
public Character(Player player, int charId) {
|
||||
this(player, GameData.getCharacterDataTable().get(charId));
|
||||
}
|
||||
|
||||
public Character(Player player, CharacterDef data) {
|
||||
this.player = player;
|
||||
this.playerUid = player.getUid();
|
||||
this.charId = data.getId();
|
||||
this.data = data;
|
||||
this.level = 1;
|
||||
this.skin = data.getDefaultSkinId();
|
||||
this.skills = new int[] {1, 1, 1, 1, 1};
|
||||
this.talents = new byte[8];
|
||||
this.createTime = Nebula.getCurrentTime();
|
||||
}
|
||||
|
||||
public void setPlayer(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public void setData(CharacterDef data) {
|
||||
if (this.data == null && data.getId() == this.getCharId()) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxGainableExp() {
|
||||
if (this.getLevel() >= this.getMaxLevel()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int maxLevel = this.getMaxLevel();
|
||||
int max = 0;
|
||||
|
||||
for (int i = this.getLevel() + 1; i <= maxLevel; i++) {
|
||||
var data = GameData.getCharacterUpgradeDataTable().get(i);
|
||||
|
||||
if (data != null) {
|
||||
max += data.getExp();
|
||||
}
|
||||
}
|
||||
|
||||
return Math.max(max - this.getExp(), 0);
|
||||
}
|
||||
|
||||
public int getMaxExp() {
|
||||
if (this.getLevel() >= this.getMaxLevel()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var data = GameData.getCharacterUpgradeDataTable().get(this.level + 1);
|
||||
return data != null ? data.getExp() : 0;
|
||||
}
|
||||
|
||||
public int getMaxLevel() {
|
||||
return 10 + (this.getAdvance() * 10);
|
||||
}
|
||||
|
||||
public void addExp(int amount) {
|
||||
// Setup
|
||||
int expRequired = this.getMaxExp();
|
||||
|
||||
// Add exp
|
||||
this.exp += amount;
|
||||
|
||||
// Check for level ups
|
||||
while (this.exp >= expRequired && expRequired > 0) {
|
||||
this.level += 1;
|
||||
this.exp -= expRequired;
|
||||
|
||||
expRequired = this.getMaxExp();
|
||||
}
|
||||
|
||||
// Clamp exp
|
||||
if (this.getLevel() >= this.getMaxLevel()) {
|
||||
this.exp = 0;
|
||||
}
|
||||
|
||||
// Save to database
|
||||
this.save();
|
||||
}
|
||||
|
||||
// Handlers
|
||||
|
||||
public PlayerChangeInfo upgrade(ItemParamMap params) {
|
||||
// Calculate exp gained
|
||||
int exp = 0;
|
||||
|
||||
// Check if item is an exp item
|
||||
for (var entry : params.getEntrySet()) {
|
||||
var data = GameData.getCharItemExpDataTable().get(entry.getIntKey());
|
||||
if (data == null) return null;
|
||||
|
||||
exp += data.getExpValue() * entry.getIntValue();
|
||||
}
|
||||
|
||||
// Clamp exp gain
|
||||
exp = Math.min(this.getMaxGainableExp(), exp);
|
||||
|
||||
// Calculate gold required
|
||||
params.add(GameConstants.GOLD_ITEM_ID, (int) Math.ceil(exp * 0.15D));
|
||||
|
||||
// Verify that the player has the items
|
||||
if (!this.getPlayer().getInventory().verifyItems(params)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Remove items
|
||||
var changes = this.getPlayer().getInventory().removeItems(params, null);
|
||||
|
||||
// Add exp
|
||||
this.addExp(exp);
|
||||
|
||||
// Success
|
||||
return changes.setSuccess(true);
|
||||
}
|
||||
|
||||
public PlayerChangeInfo advance() {
|
||||
// TODO check player level to make sure they can advance this character
|
||||
|
||||
// Get advance data
|
||||
int advanceId = (this.getData().getAdvanceGroup() * 100) + (this.advance + 1);
|
||||
var data = GameData.getCharacterAdvanceDataTable().get(advanceId);
|
||||
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Verify that the player has the items
|
||||
if (!this.getPlayer().getInventory().verifyItems(data.getMaterials())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Remove items
|
||||
var changes = this.getPlayer().getInventory().removeItems(data.getMaterials(), null);
|
||||
|
||||
// Add advance level
|
||||
this.advance++;
|
||||
|
||||
// Save to database
|
||||
this.save();
|
||||
|
||||
// Success
|
||||
return changes.setSuccess(true);
|
||||
}
|
||||
|
||||
public PlayerChangeInfo upgradeSkill(int index) {
|
||||
// TODO check player level to make sure they can advance this character
|
||||
|
||||
// Sanity check
|
||||
if (index < 0 || index >= this.skills.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get advance data
|
||||
int upgradeId = (this.getData().getSkillsUpgradeGroup(index) * 100) + (this.skills[index] + 1);
|
||||
var data = GameData.getCharacterSkillUpgradeDataTable().get(upgradeId);
|
||||
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Verify that the player has the items
|
||||
if (!this.getPlayer().getInventory().verifyItems(data.getMaterials())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Remove items
|
||||
var changes = this.getPlayer().getInventory().removeItems(data.getMaterials(), null);
|
||||
|
||||
// Add skill level
|
||||
this.skills[index]++;
|
||||
|
||||
// Save to database
|
||||
this.save();
|
||||
|
||||
// Success
|
||||
return changes.setSuccess(true);
|
||||
}
|
||||
|
||||
// Proto
|
||||
|
||||
public Char toProto() {
|
||||
var proto = Char.newInstance()
|
||||
.setTid(this.getCharId())
|
||||
.setLevel(this.getLevel())
|
||||
.setSkin(this.getSkin())
|
||||
.setAdvance(this.getAdvance())
|
||||
.setTalentNodes(this.getTalents())
|
||||
.addAllSkillLvs(this.getSkills())
|
||||
.setCreateTime(this.getCreateTime());
|
||||
|
||||
var gemPresets = proto.getMutableCharGemPresets()
|
||||
.getMutableCharGemPresets();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
var preset = CharGemPreset.newInstance()
|
||||
.addAllSlotGem(-1, -1, -1);
|
||||
|
||||
gemPresets.add(preset);
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
var slot = CharGemSlot.newInstance()
|
||||
.setId(i);
|
||||
|
||||
proto.addCharGemSlots(slot);
|
||||
}
|
||||
|
||||
proto.getMutableAffinityQuests();
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
public StarTowerChar toStarTowerProto() {
|
||||
var proto = StarTowerChar.newInstance()
|
||||
.setId(this.getCharId())
|
||||
.setAdvance(this.getAdvance())
|
||||
.setLevel(this.getLevel())
|
||||
.setTalentNodes(this.getTalents())
|
||||
.addAllSkillLvs(this.getSkills());
|
||||
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
var slot = StarTowerCharGem.newInstance()
|
||||
.setSlotId(i)
|
||||
.addAllAttributes(new int[] {0, 0, 0, 0});
|
||||
|
||||
proto.addGems(slot);
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
151
src/main/java/emu/nebula/game/character/CharacterStorage.java
Normal file
151
src/main/java/emu/nebula/game/character/CharacterStorage.java
Normal file
@@ -0,0 +1,151 @@
|
||||
package emu.nebula.game.character;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.data.resources.CharacterDef;
|
||||
import emu.nebula.data.resources.DiscDef;
|
||||
import emu.nebula.game.player.PlayerManager;
|
||||
import emu.nebula.game.player.Player;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class CharacterStorage extends PlayerManager {
|
||||
private final Int2ObjectMap<Character> characters;
|
||||
private final Int2ObjectMap<GameDisc> discs;
|
||||
|
||||
public CharacterStorage(Player player) {
|
||||
super(player);
|
||||
|
||||
this.characters = new Int2ObjectOpenHashMap<>();
|
||||
this.discs = new Int2ObjectOpenHashMap<>();
|
||||
}
|
||||
|
||||
// Characters
|
||||
|
||||
public Character getCharacterById(int id) {
|
||||
if (id <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.characters.get(id);
|
||||
}
|
||||
|
||||
public boolean hasCharacter(int id) {
|
||||
return this.characters.containsKey(id);
|
||||
}
|
||||
|
||||
public Character addCharacter(int charId) {
|
||||
// Sanity check to make sure we dont have this character already
|
||||
if (this.hasCharacter(charId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.addCharacter(GameData.getCharacterDataTable().get(charId));
|
||||
}
|
||||
|
||||
private Character addCharacter(CharacterDef data) {
|
||||
// Sanity check to make sure we dont have this character already
|
||||
if (this.hasCharacter(data.getId())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create character
|
||||
var character = new Character(this.getPlayer(), data);
|
||||
|
||||
// Save to database
|
||||
character.save();
|
||||
|
||||
// Add to characters
|
||||
this.characters.put(character.getCharId(), character);
|
||||
return character;
|
||||
}
|
||||
|
||||
public Collection<Character> getCharacterCollection() {
|
||||
return this.getCharacters().values();
|
||||
}
|
||||
|
||||
// Discs
|
||||
|
||||
public GameDisc getDiscById(int id) {
|
||||
if (id <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.discs.get(id);
|
||||
}
|
||||
|
||||
public boolean hasDisc(int id) {
|
||||
return this.discs.containsKey(id);
|
||||
}
|
||||
|
||||
public GameDisc addDisc(int discId) {
|
||||
// Sanity check to make sure we dont have this character already
|
||||
if (this.hasDisc(discId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.addDisc(GameData.getDiscDataTable().get(discId));
|
||||
}
|
||||
|
||||
private GameDisc addDisc(DiscDef data) {
|
||||
// Sanity check to make sure we dont have this character already
|
||||
if (this.hasDisc(data.getId())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create disc
|
||||
var disc = new GameDisc(this.getPlayer(), data);
|
||||
|
||||
// Save to database
|
||||
disc.save();
|
||||
|
||||
// Add to discs
|
||||
this.discs.put(disc.getDiscId(), disc);
|
||||
return disc;
|
||||
}
|
||||
|
||||
public Collection<GameDisc> getDiscCollection() {
|
||||
return this.getDiscs().values();
|
||||
}
|
||||
|
||||
|
||||
// Database
|
||||
|
||||
public void loadFromDatabase() {
|
||||
var db = Nebula.getGameDatabase();
|
||||
|
||||
db.getObjects(Character.class, "playerUid", getPlayerUid()).forEach(character -> {
|
||||
// Get data
|
||||
var data = GameData.getCharacterDataTable().get(character.getCharId());
|
||||
|
||||
// Validate
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
character.setPlayer(this.getPlayer());
|
||||
character.setData(data);
|
||||
|
||||
// Add to characters
|
||||
this.characters.put(character.getCharId(), character);
|
||||
});
|
||||
|
||||
|
||||
|
||||
db.getObjects(GameDisc.class, "playerUid", getPlayerUid()).forEach(disc -> {
|
||||
// Get data
|
||||
var data = GameData.getDiscDataTable().get(disc.getDiscId());
|
||||
if (data == null) return;
|
||||
|
||||
disc.setPlayer(this.getPlayer());
|
||||
disc.setData(data);
|
||||
|
||||
// Add
|
||||
this.discs.put(disc.getDiscId(), disc);
|
||||
});
|
||||
}
|
||||
}
|
||||
216
src/main/java/emu/nebula/game/character/GameDisc.java
Normal file
216
src/main/java/emu/nebula/game/character/GameDisc.java
Normal file
@@ -0,0 +1,216 @@
|
||||
package emu.nebula.game.character;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import dev.morphia.annotations.Id;
|
||||
import dev.morphia.annotations.Indexed;
|
||||
import emu.nebula.GameConstants;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.data.resources.DiscDef;
|
||||
import emu.nebula.database.GameDatabaseObject;
|
||||
import emu.nebula.game.inventory.ItemParamMap;
|
||||
import emu.nebula.game.player.Player;
|
||||
import emu.nebula.game.player.PlayerChangeInfo;
|
||||
import emu.nebula.proto.Public.Disc;
|
||||
import emu.nebula.proto.PublicStarTower.StarTowerDisc;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Entity(value = "discs", useDiscriminator = false)
|
||||
public class GameDisc implements GameDatabaseObject {
|
||||
@Id
|
||||
private ObjectId uid;
|
||||
@Indexed
|
||||
private int playerUid;
|
||||
|
||||
private transient DiscDef data;
|
||||
private transient Player player;
|
||||
|
||||
private int discId;
|
||||
private int level;
|
||||
private int exp;
|
||||
private int phase;
|
||||
private int star;
|
||||
|
||||
private long createTime;
|
||||
|
||||
@Deprecated // Morphia only!
|
||||
public GameDisc() {
|
||||
|
||||
}
|
||||
|
||||
public GameDisc(Player player, int discId) {
|
||||
this(player, GameData.getDiscDataTable().get(discId));
|
||||
}
|
||||
|
||||
public GameDisc(Player player, DiscDef data) {
|
||||
this.player = player;
|
||||
this.playerUid = player.getUid();
|
||||
this.data = data;
|
||||
this.discId = data.getId();
|
||||
this.level = 1;
|
||||
this.createTime = Nebula.getCurrentTime();
|
||||
}
|
||||
|
||||
public void setPlayer(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public void setData(DiscDef data) {
|
||||
if (this.data == null && data.getId() == this.getDiscId()) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxGainableExp() {
|
||||
if (this.getLevel() >= this.getMaxLevel()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int maxLevel = this.getMaxLevel();
|
||||
int max = 0;
|
||||
|
||||
for (int i = this.getLevel() + 1; i <= maxLevel; i++) {
|
||||
int dataId = (this.getData().getStrengthenGroupId() * 1000) + i;
|
||||
var data = GameData.getDiscStrengthenDataTable().get(dataId);
|
||||
|
||||
if (data != null) {
|
||||
max += data.getExp();
|
||||
}
|
||||
}
|
||||
|
||||
return Math.max(max - this.getExp(), 0);
|
||||
}
|
||||
|
||||
public int getMaxExp() {
|
||||
if (this.getLevel() >= this.getMaxLevel()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dataId = (this.getData().getStrengthenGroupId() * 1000) + (this.level + 1);
|
||||
var data = GameData.getDiscStrengthenDataTable().get(dataId);
|
||||
return data != null ? data.getExp() : 0;
|
||||
}
|
||||
|
||||
public int getMaxLevel() {
|
||||
return 10 + (this.getPhase() * 10);
|
||||
}
|
||||
|
||||
public void addExp(int amount) {
|
||||
// Setup
|
||||
int expRequired = this.getMaxExp();
|
||||
|
||||
// Add exp
|
||||
this.exp += amount;
|
||||
|
||||
// Check for level ups
|
||||
while (this.exp >= expRequired && expRequired > 0) {
|
||||
this.level += 1;
|
||||
this.exp -= expRequired;
|
||||
|
||||
expRequired = this.getMaxExp();
|
||||
}
|
||||
|
||||
// Clamp exp
|
||||
if (this.getLevel() >= this.getMaxLevel()) {
|
||||
this.exp = 0;
|
||||
}
|
||||
|
||||
// Save to database
|
||||
this.save();
|
||||
}
|
||||
|
||||
// Handlers
|
||||
|
||||
public PlayerChangeInfo upgrade(ItemParamMap params) {
|
||||
// Calculate exp gained
|
||||
int exp = 0;
|
||||
|
||||
// Check if item is an exp item
|
||||
for (var entry : params.getEntrySet()) {
|
||||
var data = GameData.getDiscItemExpDataTable().get(entry.getIntKey());
|
||||
if (data == null) return null;
|
||||
|
||||
exp += data.getExp() * entry.getIntValue();
|
||||
}
|
||||
|
||||
// Clamp exp gain
|
||||
exp = Math.min(this.getMaxGainableExp(), exp);
|
||||
|
||||
// Calculate gold required
|
||||
params.add(GameConstants.GOLD_ITEM_ID, (int) Math.ceil(exp * 0.25D));
|
||||
|
||||
// Verify that the player has the items
|
||||
if (!this.getPlayer().getInventory().verifyItems(params)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create change info
|
||||
var changes = new PlayerChangeInfo();
|
||||
|
||||
// Remove items
|
||||
this.getPlayer().getInventory().removeItems(params, changes);
|
||||
|
||||
// Add exp
|
||||
this.addExp(exp);
|
||||
|
||||
// Success
|
||||
return changes.setSuccess(true);
|
||||
}
|
||||
|
||||
public PlayerChangeInfo promote() {
|
||||
// TODO check player level to make sure they can advance this disc
|
||||
|
||||
// Get promote data
|
||||
int phaseId = (this.getData().getPromoteGroupId() * 1000) + (this.phase + 1);
|
||||
var data = GameData.getDiscPromoteDataTable().get(phaseId);
|
||||
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Verify that the player has the items
|
||||
if (!this.getPlayer().getInventory().verifyItems(data.getMaterials())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Remove items
|
||||
var changes = this.getPlayer().getInventory().removeItems(data.getMaterials(), null);
|
||||
|
||||
// Add phase level
|
||||
this.phase++;
|
||||
|
||||
// Save to database
|
||||
this.save();
|
||||
|
||||
// Success
|
||||
return changes.setSuccess(true);
|
||||
}
|
||||
|
||||
// Proto
|
||||
|
||||
public Disc toProto() {
|
||||
var proto = Disc.newInstance()
|
||||
.setId(this.getDiscId())
|
||||
.setLevel(this.getLevel())
|
||||
.setExp(this.getExp())
|
||||
.setPhase(this.getPhase())
|
||||
.setStar(this.getStar())
|
||||
.setCreateTime(this.getCreateTime());
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
public StarTowerDisc toStarTowerProto() {
|
||||
var proto = StarTowerDisc.newInstance()
|
||||
.setId(this.getDiscId())
|
||||
.setLevel(this.getLevel())
|
||||
.setPhase(this.getPhase())
|
||||
.setStar(this.getStar());
|
||||
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user