mirror of
https://github.com/Melledy/Nebula.git
synced 2025-12-14 21:34:52 +01:00
Implement vampire survivor records
This commit is contained in:
@@ -8,6 +8,8 @@ import lombok.Getter;
|
|||||||
@ResourceType(name = "VampireSurvivor.json")
|
@ResourceType(name = "VampireSurvivor.json")
|
||||||
public class VampireSurvivorDef extends BaseDef {
|
public class VampireSurvivorDef extends BaseDef {
|
||||||
private int Id;
|
private int Id;
|
||||||
|
private int Mode;
|
||||||
|
private int NeedWorldClass;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getId() {
|
public int getId() {
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
package emu.nebula.game.player;
|
package emu.nebula.game.player;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import dev.morphia.annotations.Entity;
|
import dev.morphia.annotations.Entity;
|
||||||
import dev.morphia.annotations.Id;
|
import dev.morphia.annotations.Id;
|
||||||
import emu.nebula.Nebula;
|
import emu.nebula.Nebula;
|
||||||
import emu.nebula.data.GameData;
|
import emu.nebula.data.GameData;
|
||||||
import emu.nebula.database.GameDatabaseObject;
|
import emu.nebula.database.GameDatabaseObject;
|
||||||
|
import emu.nebula.game.vampire.VampireSurvivorLog;
|
||||||
import emu.nebula.proto.PlayerData.PlayerInfo;
|
import emu.nebula.proto.PlayerData.PlayerInfo;
|
||||||
import emu.nebula.proto.Public.CharGemInstance;
|
import emu.nebula.proto.Public.CharGemInstance;
|
||||||
import emu.nebula.proto.Public.DailyInstance;
|
import emu.nebula.proto.Public.DailyInstance;
|
||||||
@@ -12,6 +16,7 @@ import emu.nebula.proto.Public.RegionBossLevel;
|
|||||||
import emu.nebula.proto.Public.SkillInstance;
|
import emu.nebula.proto.Public.SkillInstance;
|
||||||
import emu.nebula.proto.Public.VampireSurvivorLevel;
|
import emu.nebula.proto.Public.VampireSurvivorLevel;
|
||||||
import emu.nebula.proto.Public.WeekBossLevel;
|
import emu.nebula.proto.Public.WeekBossLevel;
|
||||||
|
import emu.nebula.util.Bitset;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||||
@@ -38,6 +43,9 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject
|
|||||||
private Int2IntMap infinityArenaLog;
|
private Int2IntMap infinityArenaLog;
|
||||||
|
|
||||||
// Vampire Survivors TODO
|
// Vampire Survivors TODO
|
||||||
|
private Map<Integer, VampireSurvivorLog> vampireLog;
|
||||||
|
private Bitset vampireTalents;
|
||||||
|
private IntSet vampireCards;
|
||||||
|
|
||||||
@Deprecated // Morphia only
|
@Deprecated // Morphia only
|
||||||
public PlayerProgress() {
|
public PlayerProgress() {
|
||||||
@@ -62,6 +70,9 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject
|
|||||||
this.infinityArenaLog = new Int2IntOpenHashMap();
|
this.infinityArenaLog = new Int2IntOpenHashMap();
|
||||||
|
|
||||||
// Vampire Survivor
|
// Vampire Survivor
|
||||||
|
this.vampireLog = new HashMap<>();
|
||||||
|
this.vampireTalents = new Bitset();
|
||||||
|
this.vampireCards = new IntOpenHashSet();
|
||||||
|
|
||||||
// Save to database
|
// Save to database
|
||||||
this.save();
|
this.save();
|
||||||
@@ -180,18 +191,31 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject
|
|||||||
proto.addWeekBossLevels(p);
|
proto.addWeekBossLevels(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force unlock all vampire survivor records
|
// Vampire survivors
|
||||||
var vsProto = proto.getMutableVampireSurvivorRecord();
|
var vsProto = proto.getMutableVampireSurvivorRecord();
|
||||||
|
|
||||||
vsProto.getMutableSeason();
|
vsProto.getMutableSeason();
|
||||||
|
|
||||||
for (var vsData : GameData.getVampireSurvivorDataTable()) {
|
if (unlockAll) {
|
||||||
var level = VampireSurvivorLevel.newInstance()
|
// Force unlock all vampire survivor records if we dont have the records
|
||||||
.setId(vsData.getId())
|
for (var vsData : GameData.getVampireSurvivorDataTable()) {
|
||||||
.setScore(0)
|
// Get existing record
|
||||||
.setPassed(true);
|
var log = this.getVampireLog().get(vsData.getId());
|
||||||
|
|
||||||
vsProto.addRecords(level);
|
if (log == null) {
|
||||||
|
var level = VampireSurvivorLevel.newInstance()
|
||||||
|
.setId(vsData.getId())
|
||||||
|
.setScore(0)
|
||||||
|
.setPassed(true);
|
||||||
|
|
||||||
|
vsProto.addRecords(level);
|
||||||
|
} else {
|
||||||
|
vsProto.addRecords(log.toProto());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var log : this.getVampireLog().values()) {
|
||||||
|
vsProto.addRecords(log.toProto());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ public class StarTowerManager extends PlayerManager {
|
|||||||
public StarTowerBuild getBuildById(long id) {
|
public StarTowerBuild getBuildById(long id) {
|
||||||
return this.getBuilds().get(id);
|
return this.getBuilds().get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasBuild(long id) {
|
||||||
|
return this.getBuilds().containsKey(id);
|
||||||
|
}
|
||||||
|
|
||||||
public StarTowerGame apply(StarTowerApplyReq req) {
|
public StarTowerGame apply(StarTowerApplyReq req) {
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import lombok.Getter;
|
|||||||
public class VampireSurvivorGame {
|
public class VampireSurvivorGame {
|
||||||
private final VampireSurvivorManager manager;
|
private final VampireSurvivorManager manager;
|
||||||
private final VampireSurvivorDef data;
|
private final VampireSurvivorDef data;
|
||||||
|
private long[] builds;
|
||||||
|
|
||||||
private IntSet cards;
|
private IntSet cards;
|
||||||
|
|
||||||
@@ -22,9 +23,10 @@ public class VampireSurvivorGame {
|
|||||||
private int rewardLevel;
|
private int rewardLevel;
|
||||||
private IntList rewards;
|
private IntList rewards;
|
||||||
|
|
||||||
public VampireSurvivorGame(VampireSurvivorManager manager, VampireSurvivorDef data) {
|
public VampireSurvivorGame(VampireSurvivorManager manager, VampireSurvivorDef data, long[] builds) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
this.builds = builds;
|
||||||
|
|
||||||
this.cards = new IntOpenHashSet();
|
this.cards = new IntOpenHashSet();
|
||||||
this.rewards = new IntArrayList();
|
this.rewards = new IntArrayList();
|
||||||
@@ -32,6 +34,10 @@ public class VampireSurvivorGame {
|
|||||||
this.calcRewards();
|
this.calcRewards();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return this.getData().getId();
|
||||||
|
}
|
||||||
|
|
||||||
private WeightedList<Integer> getRandom() {
|
private WeightedList<Integer> getRandom() {
|
||||||
var random = new WeightedList<Integer>();
|
var random = new WeightedList<Integer>();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package emu.nebula.game.vampire;
|
||||||
|
|
||||||
|
import dev.morphia.annotations.Entity;
|
||||||
|
import emu.nebula.proto.Public.VampireSurvivorLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Entity(useDiscriminator = false)
|
||||||
|
public class VampireSurvivorLog {
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
@Setter private int score;
|
||||||
|
@Setter private boolean passed;
|
||||||
|
@Setter private long[] builds;
|
||||||
|
|
||||||
|
@Deprecated // Morphia only
|
||||||
|
public VampireSurvivorLog() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public VampireSurvivorLog(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proto
|
||||||
|
|
||||||
|
public VampireSurvivorLevel toProto() {
|
||||||
|
var proto = VampireSurvivorLevel.newInstance()
|
||||||
|
.setId(this.getId())
|
||||||
|
.setScore(this.getScore())
|
||||||
|
.setPassed(this.isPassed());
|
||||||
|
|
||||||
|
if (this.builds != null) {
|
||||||
|
for (long buildId : this.builds) {
|
||||||
|
proto.addBuildIds(buildId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return proto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,35 +1,100 @@
|
|||||||
package emu.nebula.game.vampire;
|
package emu.nebula.game.vampire;
|
||||||
|
|
||||||
|
import emu.nebula.Nebula;
|
||||||
import emu.nebula.data.GameData;
|
import emu.nebula.data.GameData;
|
||||||
import emu.nebula.game.player.Player;
|
import emu.nebula.game.player.Player;
|
||||||
import emu.nebula.game.player.PlayerManager;
|
import emu.nebula.game.player.PlayerManager;
|
||||||
|
import emu.nebula.game.player.PlayerProgress;
|
||||||
|
import emu.nebula.util.Bitset;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import us.hebi.quickbuf.RepeatedLong;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class VampireSurvivorManager extends PlayerManager {
|
public class VampireSurvivorManager extends PlayerManager {
|
||||||
// Game
|
// Game
|
||||||
private transient VampireSurvivorGame game;
|
private VampireSurvivorGame game;
|
||||||
|
|
||||||
public VampireSurvivorManager(Player player) {
|
public VampireSurvivorManager(Player player) {
|
||||||
super(player);
|
super(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public VampireSurvivorGame apply(int levelId) {
|
public PlayerProgress getProgress() {
|
||||||
|
return this.getPlayer().getProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bitset getTalents() {
|
||||||
|
return this.getProgress().getVampireTalents();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTalentPoints() {
|
||||||
|
return this.getProgress().getVampireCards().size() * 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VampireSurvivorGame apply(int levelId, RepeatedLong builds) {
|
||||||
// Get data
|
// Get data
|
||||||
var data = GameData.getVampireSurvivorDataTable().get(levelId);
|
var data = GameData.getVampireSurvivorDataTable().get(levelId);
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check player level (world class)
|
||||||
|
if (this.getPlayer().getLevel() < data.getNeedWorldClass()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check builds
|
||||||
|
if (builds.length() != data.getMode()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure our builds exist
|
||||||
|
for (long buildId : builds) {
|
||||||
|
boolean hasBuild = this.getPlayer().getStarTowerManager().hasBuild(buildId);
|
||||||
|
if (hasBuild == false) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create game
|
// Create game
|
||||||
this.game = new VampireSurvivorGame(this, data);
|
this.game = new VampireSurvivorGame(this, data, builds.toArray());
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
return this.game;
|
return this.game;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void settle(boolean isWin, int score) {
|
public void settle(boolean isWin, int score) {
|
||||||
|
// Sanity check
|
||||||
|
if (this.game == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if we didn't win
|
||||||
|
if (!isWin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get log from database
|
||||||
|
var log = this.getProgress().getVampireLog().computeIfAbsent(
|
||||||
|
game.getId(),
|
||||||
|
id -> new VampireSurvivorLog(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if we should update score
|
||||||
|
if (score >= log.getScore() || !log.isPassed()) {
|
||||||
|
// Set record info
|
||||||
|
log.setPassed(isWin);
|
||||||
|
log.setScore(score);
|
||||||
|
log.setBuilds(game.getBuilds());
|
||||||
|
|
||||||
|
// Save record to database if we set any data
|
||||||
|
Nebula.getGameDatabase().update(
|
||||||
|
this.getProgress(),
|
||||||
|
this.getPlayerUid(),
|
||||||
|
"vampireLog." + game.getId(),
|
||||||
|
log
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Clear game
|
// Clear game
|
||||||
this.game = null;
|
this.game = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class HandlerVampireSurvivorApplyReq extends NetHandler {
|
|||||||
var req = VampireSurvivorApplyReq.parseFrom(message);
|
var req = VampireSurvivorApplyReq.parseFrom(message);
|
||||||
|
|
||||||
// Apply
|
// Apply
|
||||||
var game = session.getPlayer().getVampireSurvivorManager().apply(req.getId());
|
var game = session.getPlayer().getVampireSurvivorManager().apply(req.getId(), req.getBuildIds());
|
||||||
|
|
||||||
if (game == null) {
|
if (game == null) {
|
||||||
return session.encodeMsg(NetMsgId.vampire_survivor_apply_failed_ack);
|
return session.encodeMsg(NetMsgId.vampire_survivor_apply_failed_ack);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class HandlerVampireSurvivorSettleReq extends NetHandler {
|
|||||||
|
|
||||||
// Calculate victory + score
|
// Calculate victory + score
|
||||||
boolean victory = !req.getDefeat();
|
boolean victory = !req.getDefeat();
|
||||||
int score = 0;
|
int score = 1;
|
||||||
|
|
||||||
// Settle
|
// Settle
|
||||||
session.getPlayer().getVampireSurvivorManager().settle(victory, score);
|
session.getPlayer().getVampireSurvivorManager().settle(victory, score);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import emu.nebula.net.NetHandler;
|
|||||||
import emu.nebula.net.NetMsgId;
|
import emu.nebula.net.NetMsgId;
|
||||||
import emu.nebula.proto.VampireTalentDetail.VampireTalentDetailResp;
|
import emu.nebula.proto.VampireTalentDetail.VampireTalentDetailResp;
|
||||||
import emu.nebula.net.HandlerId;
|
import emu.nebula.net.HandlerId;
|
||||||
|
|
||||||
import emu.nebula.net.GameSession;
|
import emu.nebula.net.GameSession;
|
||||||
|
|
||||||
@HandlerId(NetMsgId.vampire_talent_detail_req)
|
@HandlerId(NetMsgId.vampire_talent_detail_req)
|
||||||
@@ -11,9 +12,13 @@ public class HandlerVampireTalentDetailReq extends NetHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||||
|
// Get vampire surv manager
|
||||||
|
var manager = session.getPlayer().getVampireSurvivorManager();
|
||||||
|
|
||||||
// Build response
|
// Build response
|
||||||
var rsp = VampireTalentDetailResp.newInstance()
|
var rsp = VampireTalentDetailResp.newInstance()
|
||||||
.setNodes(new byte[8]);
|
.setNodes(manager.getTalents().toByteArray())
|
||||||
|
.setActiveCount(manager.getTalentPoints());
|
||||||
|
|
||||||
// Encode and send
|
// Encode and send
|
||||||
return session.encodeMsg(NetMsgId.vampire_talent_detail_succeed_ack, rsp);
|
return session.encodeMsg(NetMsgId.vampire_talent_detail_succeed_ack, rsp);
|
||||||
|
|||||||
Reference in New Issue
Block a user