Implement infinite arena

This commit is contained in:
Melledy
2025-11-09 07:22:21 -08:00
parent 7d5fef1020
commit 3f7b0d366d
7 changed files with 259 additions and 0 deletions

View File

@@ -80,6 +80,9 @@ public class GameData {
@Getter private static DataTable<PotentialDef> PotentialDataTable = new DataTable<>();
@Getter private static DataTable<SubNoteSkillPromoteGroupDef> SubNoteSkillPromoteGroupDataTable = new DataTable<>();
// Infinity Tower
@Getter private static DataTable<InfinityTowerLevelDef> InfinityTowerLevelDataTable = new DataTable<>();
// Vampire survivor
@Getter private static DataTable<VampireSurvivorDef> VampireSurvivorDataTable = new DataTable<>();
@Getter private static DataTable<FateCardDef> FateCardDataTable = new DataTable<>();

View File

@@ -0,0 +1,72 @@
package emu.nebula.data.resources;
import java.util.ArrayList;
import java.util.List;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import emu.nebula.game.instance.InstanceRewardParam;
import emu.nebula.game.inventory.ItemParamMap;
import emu.nebula.util.JsonUtils;
import lombok.Getter;
@Getter
@ResourceType(name = "InfinityTowerLevel.json")
public class InfinityTowerLevelDef extends BaseDef {
private int Id;
private String BaseAwardPreview;
private transient List<InstanceRewardParam> rewards;
@Override
public int getId() {
return Id;
}
public int getEnergyConsume() {
return 0;
}
public ItemParamMap generateRewards() {
var map = new ItemParamMap();
for (var param : this.getRewards()) {
map.add(param.getId(), param.getRandomCount());
}
return map;
}
@Override
public void onLoad() {
// Init reward lists
this.rewards = new ArrayList<>();
// Parse rewards
var awards = JsonUtils.decodeList(this.BaseAwardPreview, int[].class);
if (awards == null) {
return;
}
for (int[] award : awards) {
int itemId = award[0];
int min = award[1];
int max = award.length >= 4 ? award[2] : min;
boolean isFirst = award[award.length - 1] == 1;
if (min == -1) {
min = 0;
max = 1;
}
var reward = new InstanceRewardParam(itemId, min, max);
if (isFirst) {
} else {
this.rewards.add(reward);
}
}
}
}

View File

@@ -0,0 +1,82 @@
package emu.nebula.game.infinitytower;
import dev.morphia.annotations.Id;
import emu.nebula.data.GameData;
import emu.nebula.game.player.Player;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.game.player.PlayerManager;
import lombok.Getter;
@Getter
public class InfinityTowerManager extends PlayerManager {
@Id
private int uid;
private transient int levelId;
private transient long buildId;
@Deprecated // Morphia only
public InfinityTowerManager() {
}
public InfinityTowerManager(Player player) {
super(player);
this.uid = player.getUid();
//this.save();
}
public int getBountyLevel() {
return 1;
}
public boolean apply(int levelId, long buildId) {
// Verify level data
var data = GameData.getInfinityTowerLevelDataTable().get(levelId);
if (data == null) {
return false;
}
// Set level id
this.levelId = levelId;
// Set build id
if (buildId >= 0) {
this.buildId = buildId;
}
// Success
return true;
}
public PlayerChangeInfo settle(int value) {
// Verify level data
var data = GameData.getInfinityTowerLevelDataTable().get(this.getLevelId());
if (data == null) {
return null;
}
// Init change info
var change = new PlayerChangeInfo();
// TODO
if (value != 1) {
return change;
}
// Calculate rewards
var rewards = data.generateRewards();
// Add items
this.getPlayer().getInventory().addItems(rewards, change);
// Set in change info
change.setExtraData(rewards);
// Success
return change.setSuccess(true);
}
}

View File

@@ -14,6 +14,7 @@ import emu.nebula.game.account.Account;
import emu.nebula.game.character.CharacterStorage;
import emu.nebula.game.formation.FormationManager;
import emu.nebula.game.gacha.GachaManager;
import emu.nebula.game.infinitytower.InfinityTowerManager;
import emu.nebula.game.instance.InstanceManager;
import emu.nebula.game.inventory.Inventory;
import emu.nebula.game.mail.Mailbox;
@@ -71,6 +72,7 @@ public class Player implements GameDatabaseObject {
// Managers
private final transient CharacterStorage characters;
private final transient GachaManager gachaManager;
private final transient InfinityTowerManager infinityTowerManager;
private final transient VampireSurvivorManager vampireSurvivorManager;
private final transient ScoreBossManager scoreBossManager;
@@ -91,6 +93,7 @@ public class Player implements GameDatabaseObject {
// Init player managers
this.characters = new CharacterStorage(this);
this.gachaManager = new GachaManager(this);
this.infinityTowerManager = new InfinityTowerManager(this);
this.vampireSurvivorManager = new VampireSurvivorManager(this);
this.scoreBossManager = new ScoreBossManager(this);

View File

@@ -0,0 +1,28 @@
package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.InfinityTowerApply.InfinityTowerApplyReq;
import emu.nebula.net.HandlerId;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.infinity_tower_apply_req)
public class HandlerInfinityTowerApplyReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Template hanlder
var req = InfinityTowerApplyReq.parseFrom(message);
// Apply
boolean success = session.getPlayer().getInfinityTowerManager().apply(req.getLevelId(), req.getBuildId());
if (!success) {
return session.encodeMsg(NetMsgId.infinity_tower_apply_failed_ack);
}
// Encode and send
return session.encodeMsg(NetMsgId.infinity_tower_apply_succeed_ack);
}
}

View File

@@ -0,0 +1,22 @@
package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.InfinityTowerInfo.InfinityTowerInfoResp;
import emu.nebula.net.HandlerId;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.infinity_tower_info_req)
public class HandlerInfinityTowerInfoReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Build response
var rsp = InfinityTowerInfoResp.newInstance()
.setBountyLevel(0);
// Encode and send
return session.encodeMsg(NetMsgId.infinity_tower_info_succeed_ack, rsp);
}
}

View File

@@ -0,0 +1,49 @@
package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.InfinityTowerSettle.InfinityTowerSettleReq;
import emu.nebula.proto.InfinityTowerSettle.InfinityTowerSettleResp;
import emu.nebula.net.HandlerId;
import emu.nebula.game.inventory.ItemParamMap;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.infinity_tower_settle_req)
public class HandlerInfinityTowerSettleReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Parse request
var req = InfinityTowerSettleReq.parseFrom(message);
// Settle
var manager = session.getPlayer().getInfinityTowerManager();
var change = manager.settle(req.getValue());
if (change == null) {
return session.encodeMsg(NetMsgId.infinity_tower_settle_failed_ack);
}
// Get next level
int nextLevel = manager.getLevelId() + 1;
// Try to apply for next level
if (!manager.apply(nextLevel, -1)) {
nextLevel = 0;
}
// Build response
var rsp = InfinityTowerSettleResp.newInstance()
.setNextLevelId(nextLevel)
.setBountyLevel(manager.getBountyLevel())
.setChange(change.toProto());
if (change.getExtraData() != null && change.getExtraData() instanceof ItemParamMap rewards) {
rewards.toItemTemplateStream().forEach(rsp::addShow);
}
// Encode and send
return session.encodeMsg(NetMsgId.infinity_tower_settle_succeed_ack, rsp);
}
}