Implement achievements properly

This commit is contained in:
Melledy
2025-11-29 00:29:04 -08:00
parent 898e8dd43f
commit f53bdaba32
44 changed files with 818 additions and 115 deletions
+2 -2
View File
@@ -15,9 +15,10 @@ For any extra support, questions, or discussions, check out our [Discord](https:
- Battle pass
- Gacha
- Friend system (sending energy not implemented)
- Shop (using only in-game currency)
- Shop (only in-game currency supported)
- Commissions
- Heartlink
- Achievements (not all of them are scripted properly)
- Monoliths (completeable but many other features missing)
- Bounty Trials
- Menance Arena
@@ -26,7 +27,6 @@ For any extra support, questions, or discussions, check out our [Discord](https:
- Boss Blitz
### Not implemented
- Achievements
- Events
# Running the server and client
@@ -10,6 +10,7 @@ import org.reflections.Reflections;
import emu.nebula.util.JsonUtils;
import emu.nebula.util.Utils;
import emu.nebula.Nebula;
import emu.nebula.game.achievement.AchievementHelper;
public class ResourceLoader {
private static boolean loaded = false;
@@ -22,6 +23,9 @@ public class ResourceLoader {
// Load
loadResources();
// Add hardcoded achievements params
AchievementHelper.fixParams();
// Done
loaded = true;
Nebula.getLogger().info("Resource loading complete");
@@ -2,7 +2,8 @@ package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import emu.nebula.game.achievement.AchievementHelper;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import lombok.Getter;
@Getter
@@ -18,9 +19,32 @@ public class AchievementDef extends BaseDef {
private int Tid1;
private int Qty1;
// Custom params
private transient int param1 = -1;
private transient int param2 = -1;
@Override
public int getId() {
return Id;
}
public void setParams(int param1, int param2) {
this.param1 = param1;
this.param2 = param2;
}
public boolean hasParam1() {
return this.param1 >= 0;
}
public boolean hasParam2() {
return this.param2 >= 0;
}
@Override
public void onLoad() {
// Add to cached achievement list
var list = AchievementHelper.getCache().computeIfAbsent(this.CompleteCond, i -> new ObjectArrayList<>());
list.add(this);
}
}
@@ -10,6 +10,8 @@ import lombok.Getter;
@ResourceType(name = "StarTower.json")
public class StarTowerDef extends BaseDef {
private int Id;
private int GroupId;
private int Difficulty;
private int[] FloorNum;
private transient int maxFloors;
@@ -0,0 +1,159 @@
package emu.nebula.game.achievement;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import lombok.Getter;
public enum AchievementCondition {
AchievementSpecific (1),
AchievementTotal (2),
BattleTotal (3),
CharacterAcquire (5),
CharacterAcquireQuantityRarityAndAdvancement (6),
CharacterAdvanceTotal (7),
CharacterSkillUpTotal (8),
CharacterSkillWithSpecificUpTotal (9),
CharacterSpecific (10),
CharacterUpLevel (11),
CharacterUpTotal (12),
CharacterWithSpecificAdvance (13),
CharacterWithSpecificAffinity (14),
CharacterWithSpecificUpLevel (15),
CharactersWithSpecificLevelAndQuantity (16),
CharactersWithSpecificNumberLevelAndAttributes (17),
CharactersWithSpecificPlot (18),
CharactersWithSpecificQuantityAdvancementCountAndAttribute (19),
CharactersWithSpecificQuantityAndRarity (20),
CharactersWithSpecificQuantityRarityAndAdvancement (21),
CharactersWithSpecificQuantityRarityAndLevel (22),
ChatTotal (23),
DailyInstanceClearSpecificDifficultyAndTotal (24),
DailyInstanceClearSpecificTypeAndTotal (25),
DailyInstanceClearTotal (26),
DateSpecific (27),
DiscAcquire (28),
DiscAcquireSpecificQuantityAndRarity (29),
DiscAcquireQuantityLevelAndRarity (30),
DiscAcquireQuantityPhaseAndRarity (31),
DiscAcquireQuantityStarAndRarity (32),
DiscLimitBreakTotal (33),
DiscPromoteTotal (34),
DiscStrengthenTotal (35),
DiscWithSpecificQuantityLevelAndRarity (36),
DiscWithSpecificQuantityPhaseAndRarity (37),
DiscWithSpecificQuantityStarAndRarity (38),
GachaCharacterNotSSRTotal (40),
GachaCharacterTenModeSSRTotal (41),
GachaCharacterTotal (42),
GachaTenModeAcquireQuantityAndRarityItems (43),
GachaTotal (44),
GiftGiveTotal (45),
InfinityTowerClearSpecificFloor (46),
InfinityTowerClearTotal (47),
ItemsAdd (48),
ItemsDeplete (49),
ItemsProductTotal (50),
LoginTotal (51),
QuestTravelerDuelChallengeTotal (52),
QuestTourGuideSpecific (53),
QuestTravelerDuelSpecific (54),
QuestWithSpecificType (55),
RegionBossClearSpecificFullStarWithBossIdAndDifficulty (56),
RegionBossClearSpecificLevelWithDifficultyAndTotal (57),
RegionBossClearSpecificTotal (58),
RegionBossClearTotal (59),
SkillsWithSpecificQuantityAndLevel (60),
SkinAcquire (61),
StageClearSpecificStars (62),
StoryClear (63),
TravelerDuelChallengeSpecificBoosLevelWithDifficultyAndTotal (64),
TravelerDuelClearBossTotal (65),
TravelerDuelClearSpecificBossIdAndDifficulty (66),
TravelerDuelChallengeClearSpecificBossLevelAndAffix (67),
TravelerDuelClearSpecificBossLevelWithDifficultyAndTotal (68),
TravelerDuelClearSpecificBossTotal (69),
TravelerDuelChallengeRankUploadTotal (70),
WorldClassSpecific (71),
RegionBossClearSpecificTypeWithTotal (72),
CharactersWithSpecificDatingCount (73),
CharactersDatingTotal (74),
VampireSurvivorScoreTotal (75),
VampireSurvivorSpecificLevelWithSpecificScore (76),
VampireSurvivorPassedSpecificLevel (77),
CharacterParticipateTowerNumber (78),
CharacterAllSkillReachSpecificLevel (79),
TravelerDuelPlayTotal (80),
VampireClearTotal (81),
VampireWithSpecificClearTotal (82),
AgentFinishTotal (83),
AgentWithSpecificFinishTotal (84),
ActivityMiningEnterLayer (86),
ActivityMiningDestroyGrid (87),
BossRushTotalStars (88),
InfinityTowerClearSpecificDifficultyAndTotal (89),
SkillInstanceClearTotal (90),
VampireSurvivorSpecificPassedLevel (91),
WeekBoosClearSpecificDifficultyAndTotal (92),
NpcAffinityWithSpecificLevel (93),
CharacterPassedWithSpecificTowerAndCount (94),
JointDrillScoreTotal (95),
CharGemInstanceClearTotal (104),
DailyShopReceiveShopTotal (105),
AgentApplyTotal (106),
DiscSpecific (114),
ClientReport (200),
TowerBattleTimes (501),
TowerBossChallengeSpecificHighRewardWithTotal (502),
TowerBuildSpecificCharacter (503),
TowerBuildSpecificScoreWithTotal (504),
TowerClearSpecificCharacterTypeWithTotal (505),
TowerClearSpecificGroupIdAndDifficulty (506),
TowerClearSpecificLevelWithDifficultyAndTotal (507),
TowerClearTotal (508),
TowerEnterRoom (509),
TowerEventTimes (511),
TowerFateTimes (512),
TowerItemsGet (513),
TowerSpecificDifficultyShopBuyTimes (514),
TowerGrowthSpecificNote (515),
TowerClearSpecificLevelWithDifficultyAndTotalHistory (516),
TowerBookWithSpecificEvent (517),
TowerBookWithSpecificFateCard (518),
TowerBookWithSpecificPotential (520),
TowerBuildSpecificDifficultyAndScoreWithTotal (521),
TowerSpecificDifficultyStrengthenMachineTotal (522),
TowerSpecificDifficultyKillBossTotal (524),
TowerBookSpecificCharWithPotentialTotal (525),
TowerBuildSpecificCharSpecificScoreWithTotal (526),
TowerGrowthWithSpecificNote (527),
TowerSpecificFateCardReRollTotal (528),
TowerSpecificPotentialReRollTotal (529),
TowerSpecificShopReRollTotal (530),
TowerSpecificNoteActivateTotal (531),
TowerSpecificNoteLevelTotal (532),
TowerSpecificPotentialBonusTotal (533),
TowerSpecificPotentialLuckyTotal (534),
TowerSpecificShopBuyDiscountTotal (535),
TowerSpecificSecondarySkillActivateTotal (536),
TowerSpecificGetExtraNoteLvTotal (537),
TowerSweepTimes (539),
TowerSweepTotal (540);
@Getter
private final int value;
private final static Int2ObjectMap<AchievementCondition> map = new Int2ObjectOpenHashMap<>();
static {
for (AchievementCondition type : AchievementCondition.values()) {
map.put(type.getValue(), type);
}
}
private AchievementCondition(int value) {
this.value = value;
}
public static AchievementCondition getByValue(int value) {
return map.get(value);
}
}
@@ -0,0 +1,36 @@
package emu.nebula.game.achievement;
import java.util.List;
import emu.nebula.data.GameData;
import emu.nebula.data.resources.AchievementDef;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import lombok.Getter;
// Because achievements in the data files do not have params, we will hardcode them here
public class AchievementHelper {
// Achievement cache
@Getter
private static Int2ObjectMap<List<AchievementDef>> cache = new Int2ObjectOpenHashMap<>();
public static List<AchievementDef> getAchievementsByCondition(AchievementCondition condition) {
return cache.get(condition.getValue());
}
// Fix params
public static void fixParams() {
addParam(78, -1, 2);
addParam(79, -1, 4);
addParam(498, -1, 1);
}
private static void addParam(int achievementId, int param1, int param2) {
var data = GameData.getAchievementDataTable().get(achievementId);
if (data == null) return;
data.setParams(param1, param2);
}
}
@@ -0,0 +1,222 @@
package emu.nebula.game.achievement;
import java.util.HashMap;
import java.util.Map;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import emu.nebula.Nebula;
import emu.nebula.data.GameData;
import emu.nebula.data.resources.AchievementDef;
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.game.player.PlayerManager;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.Public.Achievements;
import emu.nebula.proto.Public.Events;
import lombok.Getter;
import lombok.Setter;
import us.hebi.quickbuf.RepeatedInt;
@Getter
@Entity(value = "achievements", useDiscriminator = false)
public class AchievementManager extends PlayerManager implements GameDatabaseObject {
@Id
private int uid;
// Achievement data
private Map<Integer, GameAchievement> achievements;
@Setter
private transient boolean queueSave;
@Deprecated // Morphia only
public AchievementManager() {
}
public AchievementManager(Player player) {
super(player);
this.uid = player.getUid();
this.achievements = new HashMap<>();
this.save();
}
/**
* Returns true if there are any unclaimed achievements
*/
public synchronized boolean hasNewAchievements() {
for (var achievement : this.getAchievements().values()) {
if (achievement.isClaimable()) {
return true;
}
}
return false;
}
public synchronized GameAchievement getAchievement(AchievementDef data) {
// Try and get achievement normally
var achievement = this.getAchievements().get(data.getId());
// Create achievement if it doesnt exist
if (achievement == null) {
achievement = new GameAchievement(data);
this.getAchievements().put(achievement.getId(), achievement);
}
return achievement;
}
public synchronized void handleClientEvents(Events events) {
// Parse events
for (var event : events.getList()) {
// Check id
if (event.getId() != 200) {
continue;
}
// Sanity check
if (event.getData().length() < 2) {
continue;
}
// Get achievement id and progress
int id = event.getData().get(1);
int progress = event.getData().get(0);
if (progress <= 0) {
continue;
}
// Get achievement data
var data = GameData.getAchievementDataTable().get(id);
if (data == null) continue;
// Make sure achivement can be completed by the client
if (data.getCompleteCond() != AchievementCondition.ClientReport.getValue()) {
continue;
}
// Get achievement
var achievement = this.getAchievement(data);
// Update achievement
boolean changed = achievement.trigger(true, progress, 0, 0);
// Only save/update on client if achievement was changed
if (changed) {
// Sync
this.syncAchievement(achievement);
// Set save flag
this.queueSave = true;
}
}
}
public synchronized void trigger(AchievementCondition condition, int progress, int param1, int param2) {
// Sanity check
if (progress <= 0) {
return;
}
// Get achievements to trigger
var triggerList = AchievementHelper.getAchievementsByCondition(condition);
if (triggerList == null) {
return;
}
// Check what type of achievement condition this is
boolean isTotal = condition.name().endsWith("Total");
// Parse achievements
for (var data : triggerList) {
// Get achievement
var achievement = this.getAchievement(data);
// Update achievement
boolean changed = achievement.trigger(isTotal, progress, param1, param2);
// Only save/update on client if achievement was changed
if (changed) {
// Sync
this.syncAchievement(achievement);
// Set save flag
this.queueSave = true;
}
}
}
/**
* Update this achievement on the player client
*/
private void syncAchievement(GameAchievement achievement) {
if (!getPlayer().hasSession()) {
return;
}
getPlayer().addNextPackage(
NetMsgId.achievement_change_notify,
achievement.toProto()
);
}
public synchronized PlayerChangeInfo recvRewards(RepeatedInt ids) {
// Sanity check
if (ids.length() <= 0) {
return null;
}
// Init variables
var rewards = new ItemParamMap();
// Claim achievements
for (int id : ids) {
// Get achievement
var achievement = this.getAchievements().get(id);
if (achievement == null) continue;
// Check if we can claim this achievement
if (achievement.isClaimable()) {
// Claim
achievement.setClaimed(true);
// Add rewards
rewards.add(achievement.getData().getTid1(), achievement.getData().getQty1());
// Save
this.queueSave = true;
}
}
// Success
return this.getPlayer().getInventory().addItems(rewards);
}
// Proto
public synchronized Achievements toProto() {
var proto = Achievements.newInstance();
for (var achievement : this.getAchievements().values()) {
proto.addList(achievement.toProto());
}
return proto;
}
// Database
@Override
public void save() {
Nebula.getGameDatabase().save(this);
this.queueSave = false;
}
}
@@ -0,0 +1,122 @@
package emu.nebula.game.achievement;
import dev.morphia.annotations.Entity;
import emu.nebula.Nebula;
import emu.nebula.data.GameData;
import emu.nebula.data.resources.AchievementDef;
import emu.nebula.proto.Public.Achievement;
import emu.nebula.proto.Public.QuestProgress;
import lombok.Getter;
@Getter
@Entity(useDiscriminator = false)
public class GameAchievement {
private int id;
private int curProgress;
private long completed;
private boolean claimed;
private transient AchievementDef data;
@Deprecated // Morphia only
public GameAchievement() {
}
public GameAchievement(AchievementDef data) {
this.id = data.getId();
this.data = data;
}
public AchievementDef getData() {
if (this.data == null) {
this.data = GameData.getAchievementDataTable().get(this.getId());
}
return this.data;
}
public int getMaxProgress() {
return this.getData().getAimNumShow();
}
public boolean isComplete() {
return this.completed > 0;
}
public boolean isClaimable() {
return !this.isClaimed() && this.isComplete();
}
public void setClaimed(boolean claimed) {
this.claimed = claimed;
}
public int getStatus() {
if (this.isClaimed()) {
return 2;
} else if (this.isComplete()) {
return 1;
}
return 0;
}
/**
* Returns true if achievement was updated
*/
public boolean trigger(boolean isTotal, int progress, int param1, int param2) {
// Sanity check
if (this.isComplete()) {
return false;
}
// Check param conditions
var data = this.getData();
if (data == null) return false;
if (data.hasParam1() && data.getParam1() != param1) {
return false;
}
if (data.hasParam2() && data.getParam2() != param2) {
return false;
}
// Set previous progress
int prevProgress = this.curProgress;
// Update progress
if (isTotal) {
this.curProgress += progress;
} else {
this.curProgress = progress;
}
// Check if completed
if (this.getCurProgress() >= this.getMaxProgress()) {
this.curProgress = this.getMaxProgress();
this.completed = Nebula.getCurrentTime();
return true;
}
// Check if progress was changed
return prevProgress != this.curProgress;
}
// Proto
public Achievement toProto() {
var progress = QuestProgress.newInstance()
.setCur(this.getCurProgress())
.setMax(this.getMaxProgress());
var proto = Achievement.newInstance()
.setId(this.getId())
.setCompleted(this.getCompleted())
.setStatus(this.getStatus())
.addProgress(progress);
return proto;
}
}
@@ -8,11 +8,12 @@ import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import emu.nebula.data.GameData;
import emu.nebula.database.GameDatabaseObject;
import emu.nebula.game.achievement.AchievementCondition;
import emu.nebula.game.character.GameCharacter;
import emu.nebula.game.player.Player;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.game.player.PlayerManager;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import lombok.Getter;
import us.hebi.quickbuf.RepeatedInt;
@@ -84,7 +85,7 @@ public class AgentManager extends PlayerManager implements GameDatabaseObject {
this.getAgents().put(agent.getId(), agent);
// Quest
this.getPlayer().triggerQuest(QuestCondType.AgentApplyTotal, 1);
this.getPlayer().triggerQuest(QuestCondition.AgentApplyTotal, 1);
// Success
return agent;
@@ -182,8 +183,9 @@ public class AgentManager extends PlayerManager implements GameDatabaseObject {
// Save to database
this.save();
// Quest
this.getPlayer().triggerQuest(QuestCondType.AgentFinishTotal, list.size());
// Quest + Achievements
getPlayer().triggerQuest(QuestCondition.AgentFinishTotal, list.size());
getPlayer().triggerAchievement(AchievementCondition.AgentWithSpecificFinishTotal, list.size());
// Success
return change.setSuccess(true);
@@ -16,7 +16,7 @@ import emu.nebula.game.inventory.ItemParamMap;
import emu.nebula.game.player.Player;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.game.quest.GameQuest;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.game.quest.QuestType;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.BattlePassInfoOuterClass.BattlePassInfo;
@@ -123,7 +123,7 @@ public class BattlePass implements GameDatabaseObject {
this.save();
}
public synchronized void trigger(QuestCondType condition, int progress, int param) {
public synchronized void trigger(QuestCondition condition, int progress, int param) {
for (var quest : getQuests().values()) {
// Try to trigger quest
boolean result = quest.trigger(condition, progress, param);
@@ -6,7 +6,9 @@ import java.util.Map;
import dev.morphia.annotations.Entity;
import emu.nebula.Nebula;
import emu.nebula.data.resources.ChatDef;
import emu.nebula.game.achievement.AchievementCondition;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.Public.Contacts;
import emu.nebula.proto.Public.UI32;
@@ -125,6 +127,9 @@ public class CharacterContact {
);
}
// Trigger quest/achievement
this.getCharacter().getPlayer().triggerAchievement(AchievementCondition.ChatTotal, 1);
// Success
return change.setSuccess(true);
}
@@ -18,10 +18,11 @@ import emu.nebula.data.GameData;
import emu.nebula.data.resources.CharacterDef;
import emu.nebula.data.resources.TalentGroupDef;
import emu.nebula.database.GameDatabaseObject;
import emu.nebula.game.achievement.AchievementCondition;
import emu.nebula.game.inventory.ItemParamMap;
import emu.nebula.game.player.Player;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.Notify.Skin;
import emu.nebula.proto.Notify.SkinChange;
@@ -186,7 +187,7 @@ public class GameCharacter implements GameDatabaseObject {
// Check if we leveled up
if (this.level > oldLevel) {
// Trigger quest
this.getPlayer().triggerQuest(QuestCondType.CharacterUpTotal, this.level - oldLevel);
this.getPlayer().triggerQuest(QuestCondition.CharacterUpTotal, this.level - oldLevel);
}
// Save to database
@@ -459,8 +460,9 @@ public class GameCharacter implements GameDatabaseObject {
// Add affinity exp
this.addAffinityExp(exp);
// Trigger quest
this.getPlayer().triggerQuest(QuestCondType.GiftGiveTotal, count);
// Trigger quest/achievement
this.getPlayer().triggerQuest(QuestCondition.GiftGiveTotal, count);
this.getPlayer().triggerAchievement(AchievementCondition.GiftGiveTotal, count);
// Remove items
var change = this.getPlayer().getInventory().removeItems(items);
@@ -14,7 +14,7 @@ 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.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.proto.Public.Disc;
import emu.nebula.proto.PublicStarTower.StarTowerDisc;
@@ -145,7 +145,7 @@ public class GameDisc implements GameDatabaseObject {
// Check if we leveled up
if (this.level > oldLevel) {
// Trigger quest
this.getPlayer().triggerQuest(QuestCondType.DiscStrengthenTotal, this.level - oldLevel);
this.getPlayer().triggerQuest(QuestCondition.DiscStrengthenTotal, this.level - oldLevel);
}
// Save to database
@@ -1,10 +1,11 @@
package emu.nebula.game.dating;
import emu.nebula.data.GameData;
import emu.nebula.game.achievement.AchievementCondition;
import emu.nebula.game.character.GameCharacter;
import emu.nebula.game.player.Player;
import emu.nebula.game.player.PlayerManager;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import lombok.Getter;
@Getter
@@ -26,8 +27,9 @@ public class DatingManager extends PlayerManager {
// Set landmark + character
this.game = new DatingGame(character, data);
// Trigger quest
this.getPlayer().triggerQuest(QuestCondType.CharactersDatingTotal, 1);
// Trigger quest/achievement
this.getPlayer().triggerQuest(QuestCondition.CharactersDatingTotal, 1);
this.getPlayer().triggerAchievement(AchievementCondition.CharactersDatingTotal, 1);
// Success
return this.game;
@@ -3,6 +3,7 @@ package emu.nebula.game.gacha;
import emu.nebula.data.GameData;
import emu.nebula.game.GameContext;
import emu.nebula.game.GameContextModule;
import emu.nebula.game.achievement.AchievementCondition;
import emu.nebula.game.inventory.ItemAcquireMap;
import emu.nebula.game.inventory.ItemParamMap;
import emu.nebula.game.inventory.ItemType;
@@ -164,6 +165,9 @@ public class GachaModule extends GameContextModule {
var log = new GachaHistoryLog(data.getGachaType(), results);
player.getGachaManager().addGachaHistory(log);
// Trigger achievements
player.triggerAchievement(AchievementCondition.GachaTotal, amount);
// Complete
return new GachaResult(info, change, results);
}
@@ -8,7 +8,7 @@ import emu.nebula.game.player.Player;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.game.player.PlayerManager;
import emu.nebula.game.player.PlayerProgress;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import lombok.Getter;
@@ -35,7 +35,7 @@ public class InstanceManager extends PlayerManager {
return this.getPlayer().getProgress();
}
public PlayerChangeInfo settleInstance(InstanceData data, QuestCondType questCondition, Int2IntMap log, String logName, int star) {
public PlayerChangeInfo settleInstance(InstanceData data, QuestCondition questCondition, Int2IntMap log, String logName, int star) {
// Calculate settle data
var settleData = new InstanceSettleData();
@@ -64,7 +64,7 @@ public class InstanceManager extends PlayerManager {
// Quest triggers
this.getPlayer().triggerQuest(questCondition, 1);
this.getPlayer().triggerQuest(QuestCondType.BattleTotal, 1);
this.getPlayer().triggerQuest(QuestCondition.BattleTotal, 1);
}
// Set extra data
@@ -74,7 +74,7 @@ public class InstanceManager extends PlayerManager {
return change.setSuccess(true);
}
public PlayerChangeInfo sweepInstance(InstanceData data, QuestCondType questCondition, Int2IntMap log, int rewardType, int count) {
public PlayerChangeInfo sweepInstance(InstanceData data, QuestCondition questCondition, Int2IntMap log, int rewardType, int count) {
// Sanity check count
if (count <= 0) {
return null;
@@ -132,7 +132,7 @@ public class InstanceManager extends PlayerManager {
// Quest triggers
this.getPlayer().triggerQuest(questCondition, count);
this.getPlayer().triggerQuest(QuestCondType.BattleTotal, count);
this.getPlayer().triggerQuest(QuestCondition.BattleTotal, count);
// Success
return change.setSuccess(true);
@@ -11,7 +11,7 @@ import emu.nebula.data.resources.MallShopDef;
import emu.nebula.data.resources.ResidentGoodsDef;
import emu.nebula.database.GameDatabaseObject;
import emu.nebula.game.player.PlayerManager;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.Notify.Skin;
import emu.nebula.proto.Public.Honor;
@@ -464,9 +464,9 @@ public class Inventory extends PlayerManager implements GameDatabaseObject {
// Trigger quest
if (amount > 0) {
this.getPlayer().triggerQuest(QuestCondType.ItemsAdd, amount, id);
this.getPlayer().triggerQuest(QuestCondition.ItemsAdd, amount, id);
} else {
this.getPlayer().triggerQuest(QuestCondType.ItemsDeplete, Math.abs(amount), id);
this.getPlayer().triggerQuest(QuestCondition.ItemsDeplete, Math.abs(amount), id);
}
//
@@ -12,6 +12,8 @@ import emu.nebula.Nebula;
import emu.nebula.data.GameData;
import emu.nebula.database.GameDatabaseObject;
import emu.nebula.game.account.Account;
import emu.nebula.game.achievement.AchievementCondition;
import emu.nebula.game.achievement.AchievementManager;
import emu.nebula.game.agent.AgentManager;
import emu.nebula.game.battlepass.BattlePassManager;
import emu.nebula.game.character.CharacterStorage;
@@ -23,7 +25,7 @@ import emu.nebula.game.infinitytower.InfinityTowerManager;
import emu.nebula.game.instance.InstanceManager;
import emu.nebula.game.inventory.Inventory;
import emu.nebula.game.mail.Mailbox;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.game.quest.QuestManager;
import emu.nebula.game.scoreboss.ScoreBossManager;
import emu.nebula.game.story.StoryManager;
@@ -104,6 +106,7 @@ public class Player implements GameDatabaseObject {
private transient PlayerProgress progress;
private transient StoryManager storyManager;
private transient QuestManager questManager;
private transient AchievementManager achievementManager;
private transient AgentManager agentManager;
// Extra
@@ -204,8 +207,14 @@ public class Player implements GameDatabaseObject {
}
public void setLevel(int level) {
// Set player world class (level)
this.level = level;
// Save to database
Nebula.getGameDatabase().update(this, this.getUid(), "level", this.level);
// Trigger achievement
this.triggerAchievement(AchievementCondition.WorldClassSpecific, this.getLevel());
}
public void setExp(int exp) {
@@ -491,6 +500,7 @@ public class Player implements GameDatabaseObject {
// Save level rewards if we changed it
if (oldLevel != this.getLevel()) {
// Update level rewards
this.getQuestManager().saveLevelRewards();
this.addNextPackage(
@@ -498,6 +508,9 @@ public class Player implements GameDatabaseObject {
WorldClassRewardState.newInstance()
.setFlag(getQuestManager().getLevelRewards().toBigEndianByteArray())
);
// Trigger achievement
this.triggerAchievement(AchievementCondition.WorldClassSpecific, this.getLevel());
}
// Calculate changes
@@ -550,7 +563,7 @@ public class Player implements GameDatabaseObject {
change = modifyEnergy(-amount, change);
// Trigger quest
this.triggerQuest(QuestCondType.EnergyDeplete, amount);
this.triggerQuest(QuestCondition.EnergyDeplete, amount);
// Complete
return change;
@@ -601,6 +614,10 @@ public class Player implements GameDatabaseObject {
// Reset dailies
this.resetDailies(hasWeekChanged);
// Trigger quest/achievement login
this.triggerQuest(QuestCondition.LoginTotal, 1);
this.triggerAchievement(AchievementCondition.LoginTotal, 1);
// Update last epoch day
this.lastEpochDay = Nebula.getGameContext().getEpochDays();
Nebula.getGameDatabase().update(this, this.getUid(), "lastEpochDay", this.lastEpochDay);
@@ -612,17 +629,25 @@ public class Player implements GameDatabaseObject {
this.getBattlePassManager().getBattlePass().resetDailyQuests(resetWeekly);
}
// Trigger quests
// Trigger quests + achievements
public void triggerQuest(QuestCondType condition, int progress) {
public void triggerQuest(QuestCondition condition, int progress) {
this.triggerQuest(condition, progress, 0);
}
public void triggerQuest(QuestCondType condition, int progress, int param) {
public void triggerQuest(QuestCondition condition, int progress, int param) {
this.getQuestManager().trigger(condition, progress, param);
this.getBattlePassManager().getBattlePass().trigger(condition, progress, param);
}
public void triggerAchievement(AchievementCondition condition, int progress) {
this.getAchievementManager().trigger(condition, progress, 0, 0);
}
public void triggerAchievement(AchievementCondition condition, int progress, int param1, int param2) {
this.getAchievementManager().trigger(condition, progress, param1, param2);
}
// Login
private <T extends PlayerManager> T loadManagerFromDatabase(Class<T> cls) {
@@ -664,6 +689,7 @@ public class Player implements GameDatabaseObject {
this.gachaManager = this.loadManagerFromDatabase(GachaManager.class);
this.storyManager = this.loadManagerFromDatabase(StoryManager.class);
this.questManager = this.loadManagerFromDatabase(QuestManager.class);
this.achievementManager = this.loadManagerFromDatabase(AchievementManager.class);
this.agentManager = this.loadManagerFromDatabase(AgentManager.class);
// Database fixes
@@ -680,9 +706,6 @@ public class Player implements GameDatabaseObject {
// See if we need to reset dailies
this.checkResetDailies();
// Trigger quest login
this.triggerQuest(QuestCondType.LoginTotal, 1);
// Update last login time
this.lastLogin = System.currentTimeMillis();
Nebula.getGameDatabase().update(this, this.getUid(), "lastLogin", this.getLastLogin());
@@ -698,6 +721,18 @@ public class Player implements GameDatabaseObject {
this.getNextPackages().add(new NetMsgPacket(msgId, proto));
}
// Misc
/**
* Called AFTER a response is sent to the client
*/
public void afterResponse() {
// Check if we need save achievements
if (this.getAchievementManager().isQueueSave()) {
this.getAchievementManager().save();
}
}
// Proto
public PlayerInfo toProto() {
@@ -785,9 +820,11 @@ public class Player implements GameDatabaseObject {
state.getMutableBattlePass()
.setState(1);
state.getMutableAchievement()
.setNew(this.getAchievementManager().hasNewAchievements());
state.getMutableFriendEnergy();
state.getMutableMallPackage();
state.getMutableAchievement();
state.getMutableTravelerDuelQuest()
.setType(QuestType.TravelerDuel);
state.getMutableTravelerDuelChallengeQuest()
@@ -55,7 +55,7 @@ public class GameQuest {
return 0;
}
public boolean trigger(QuestCondType condition, int progress, int param) {
public boolean trigger(QuestCondition condition, int progress, int param) {
// Sanity check
if (this.isComplete()) {
return false;
@@ -4,7 +4,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import lombok.Getter;
public enum QuestCondType {
public enum QuestCondition {
BattleTotal (3),
BattlesTotalWithPartner (4),
CharacterAcquireQuantityRarityAndAdvancement (6),
@@ -126,19 +126,19 @@ public enum QuestCondType {
@Getter
private final int value;
private final static Int2ObjectMap<QuestCondType> map = new Int2ObjectOpenHashMap<>();
private final static Int2ObjectMap<QuestCondition> map = new Int2ObjectOpenHashMap<>();
static {
for (QuestCondType type : QuestCondType.values()) {
for (QuestCondition type : QuestCondition.values()) {
map.put(type.getValue(), type);
}
}
private QuestCondType(int value) {
private QuestCondition(int value) {
this.value = value;
}
public static QuestCondType getByValue(int value) {
public static QuestCondition getByValue(int value) {
return map.get(value);
}
}
@@ -11,19 +11,20 @@ public class QuestHelper {
@Getter
private static final Int2ObjectMap<QuestParams> battlePassQuestParams = new Int2ObjectOpenHashMap<>();
// Put params here
static {
battlePassQuestParams.put(1001, new QuestParams(QuestCondType.LoginTotal, 1));
battlePassQuestParams.put(1002, new QuestParams(QuestCondType.EnergyDeplete, 160));
battlePassQuestParams.put(1003, new QuestParams(QuestCondType.BattleTotal, 6));
battlePassQuestParams.put(1004, new QuestParams(QuestCondType.QuestWithSpecificType, 5, QuestType.Daily));
battlePassQuestParams.put(2001, new QuestParams(QuestCondType.TowerEnterFloor, 1));
battlePassQuestParams.put(2002, new QuestParams(QuestCondType.WeekBoosClearSpecificDifficultyAndTotal, 3));
battlePassQuestParams.put(2003, new QuestParams(QuestCondType.BattleTotal, 20));
battlePassQuestParams.put(2004, new QuestParams(QuestCondType.LoginTotal, 5));
battlePassQuestParams.put(2005, new QuestParams(QuestCondType.AgentFinishTotal, 3));
battlePassQuestParams.put(2006, new QuestParams(QuestCondType.ItemsDeplete, 100000, 1));
battlePassQuestParams.put(2007, new QuestParams(QuestCondType.GiftGiveTotal, 5));
battlePassQuestParams.put(2008, new QuestParams(QuestCondType.EnergyDeplete, 1200));
battlePassQuestParams.put(1001, new QuestParams(QuestCondition.LoginTotal, 1));
battlePassQuestParams.put(1002, new QuestParams(QuestCondition.EnergyDeplete, 160));
battlePassQuestParams.put(1003, new QuestParams(QuestCondition.BattleTotal, 6));
battlePassQuestParams.put(1004, new QuestParams(QuestCondition.QuestWithSpecificType, 5, QuestType.Daily));
battlePassQuestParams.put(2001, new QuestParams(QuestCondition.TowerEnterFloor, 1));
battlePassQuestParams.put(2002, new QuestParams(QuestCondition.WeekBoosClearSpecificDifficultyAndTotal, 3));
battlePassQuestParams.put(2003, new QuestParams(QuestCondition.BattleTotal, 20));
battlePassQuestParams.put(2004, new QuestParams(QuestCondition.LoginTotal, 5));
battlePassQuestParams.put(2005, new QuestParams(QuestCondition.AgentFinishTotal, 3));
battlePassQuestParams.put(2006, new QuestParams(QuestCondition.ItemsDeplete, 100000, 1));
battlePassQuestParams.put(2007, new QuestParams(QuestCondition.GiftGiveTotal, 5));
battlePassQuestParams.put(2008, new QuestParams(QuestCondition.EnergyDeplete, 1200));
}
@Getter
@@ -40,7 +41,7 @@ public class QuestHelper {
this(cond, new int[] {param});
}
public QuestParams(QuestCondType cond, int... params) {
public QuestParams(QuestCondition cond, int... params) {
this(cond.getValue(), params);
}
}
@@ -114,7 +114,7 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
this.save();
}
public synchronized void trigger(QuestCondType condition, int progress, int param) {
public synchronized void trigger(QuestCondition condition, int progress, int param) {
for (var quest : getQuests().values()) {
// Try to trigger quest
boolean result = quest.trigger(condition, progress, param);
@@ -194,7 +194,7 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
}
// Trigger quest
this.getPlayer().triggerQuest(QuestCondType.QuestWithSpecificType, claimList.size(), QuestType.Daily);
this.getPlayer().triggerQuest(QuestCondition.QuestWithSpecificType, claimList.size(), QuestType.Daily);
// Success
return change.setSuccess(true);
@@ -305,7 +305,7 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
Nebula.getGameDatabase().update(this, this.getUid(), "hasDailyReward", this.hasDailyReward);
// Trigger quest
this.getPlayer().triggerQuest(QuestCondType.DailyShopReceiveShopTotal, 1);
this.getPlayer().triggerQuest(QuestCondition.DailyShopReceiveShopTotal, 1);
// Success
return change.setSuccess(true);
@@ -6,7 +6,6 @@ import java.util.List;
import dev.morphia.annotations.Entity;
import emu.nebula.GameConstants;
import emu.nebula.Nebula;
import emu.nebula.data.GameData;
import emu.nebula.data.resources.PotentialDef;
import emu.nebula.data.resources.StarTowerDef;
@@ -552,6 +551,8 @@ public class StarTowerGame {
this.addRandomSubNoteSkills(subNoteSkills, change);
}
// Handle client events for achievements
getPlayer().getAchievementManager().handleClientEvents(proto.getVictory().getEvents());
} else {
// Handle defeat
// TODO
@@ -563,6 +564,7 @@ public class StarTowerGame {
// Set change
rsp.setChange(change.toProto());
// Return response for the player
return rsp;
}
@@ -742,7 +744,7 @@ public class StarTowerGame {
public StarTowerInteractResp settle(StarTowerInteractResp rsp) {
// End game
this.getManager().endGame();
this.getManager().endGame(true);
// Settle info
var settle = rsp.getMutableSettle()
@@ -3,11 +3,12 @@ package emu.nebula.game.tower;
import emu.nebula.Nebula;
import emu.nebula.data.GameData;
import emu.nebula.data.resources.StarTowerGrowthNodeDef;
import emu.nebula.game.achievement.AchievementCondition;
import emu.nebula.game.player.Player;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.game.player.PlayerManager;
import emu.nebula.game.player.PlayerProgress;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.proto.StarTowerApply.StarTowerApplyReq;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
@@ -207,24 +208,44 @@ public class StarTowerManager extends PlayerManager {
this.game = new StarTowerGame(this, data, formation, req);
// Trigger quest
this.getPlayer().triggerQuest(QuestCondType.TowerEnterFloor, 1);
this.getPlayer().triggerQuest(QuestCondition.TowerEnterFloor, 1);
// Success
return change.setExtraData(this.game);
}
public StarTowerGame endGame() {
public StarTowerGame endGame(boolean victory) {
// Cache instance
var game = this.game;
if (game != null) {
if (game == null) {
return null;
}
// Set last build
this.lastBuild = game.getBuild();
// Clear instance
this.game = null;
// Handle victory events
if (victory) {
// Trigger achievements
this.getPlayer().triggerAchievement(
AchievementCondition.TowerClearSpecificGroupIdAndDifficulty,
1,
game.getData().getGroupId(),
game.getData().getDifficulty()
);
this.getPlayer().triggerAchievement(
AchievementCondition.TowerClearSpecificLevelWithDifficultyAndTotal,
1,
game.getData().getId(),
game.getData().getDifficulty()
);
}
// Clear game instance
this.game = null;
// Return game
return game;
}
@@ -5,6 +5,7 @@ import java.util.List;
import emu.nebula.Nebula;
import emu.nebula.data.GameData;
import emu.nebula.game.achievement.AchievementCondition;
import emu.nebula.game.player.Player;
import emu.nebula.game.player.PlayerManager;
import emu.nebula.game.player.PlayerProgress;
@@ -173,6 +174,9 @@ public class VampireSurvivorManager extends PlayerManager {
// Clear game
this.game = null;
// Trigger achievement
getPlayer().triggerAchievement(AchievementCondition.VampireWithSpecificClearTotal, 1);
}
private void updateSavedCards() {
@@ -249,4 +249,15 @@ public class GameSession {
return proto;
}
// Misc network
/**
* Called AFTER a response is sent to the client
*/
public void afterResponse() {
if (this.getPlayer() != null) {
this.getPlayer().afterResponse();
}
}
}
@@ -2,11 +2,7 @@ package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.Public.Achievement;
import emu.nebula.proto.Public.Achievements;
import emu.nebula.proto.Public.QuestProgress;
import emu.nebula.net.HandlerId;
import emu.nebula.data.GameData;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.achievement_info_req)
@@ -15,21 +11,7 @@ public class HandlerAchievementInfoReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Build response
var rsp = Achievements.newInstance();
for (var data : GameData.getAchievementDataTable()) {
var progress = QuestProgress.newInstance()
.setCur(data.getAimNumShow())
.setMax(data.getAimNumShow());
var info = Achievement.newInstance()
.setId(data.getId())
.setStatus(2)
.setCompleted(session.getPlayer().getCreateTime())
.addProgress(progress);
rsp.addList(info);
}
var rsp = session.getPlayer().getAchievementManager().toProto();
// Encode and send
return session.encodeMsg(NetMsgId.achievement_info_succeed_ack, rsp);
@@ -0,0 +1,28 @@
package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.AchievementRewardReceive.AchievementRewardReq;
import emu.nebula.net.HandlerId;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.achievement_reward_receive_req)
public class HandlerAchievementRewardReceiveReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Parse request
var req = AchievementRewardReq.parseFrom(message);
// Claim rewards
var change = session.getPlayer().getAchievementManager().recvRewards(req.getIds());
if (change == null) {
return session.encodeMsg(NetMsgId.achievement_reward_receive_failed_ack);
}
// Encode and send
return session.encodeMsg(NetMsgId.achievement_reward_receive_succeed_ack, change.toProto());
}
}
@@ -7,7 +7,7 @@ import emu.nebula.proto.CharGemInstanceSettle.CharGemInstanceSettleResp;
import emu.nebula.net.HandlerId;
import emu.nebula.data.GameData;
import emu.nebula.game.instance.InstanceSettleData;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.char_gem_instance_settle_req)
@@ -30,7 +30,7 @@ public class HandlerCharGemInstanceSettleReq extends NetHandler {
// Settle instance
var changes = player.getInstanceManager().settleInstance(
data,
QuestCondType.CharGemInstanceClearTotal,
QuestCondition.CharGemInstanceClearTotal,
player.getProgress().getCharGemLog(),
"charGemLog",
req.getStar()
@@ -38,6 +38,9 @@ public class HandlerCharGemInstanceSettleReq extends NetHandler {
var settleData = (InstanceSettleData) changes.getExtraData();
// Handle client events for achievements
session.getPlayer().getAchievementManager().handleClientEvents(req.getEvents());
// Create response
var rsp = CharGemInstanceSettleResp.newInstance()
.setExp(settleData.getExp())
@@ -11,7 +11,7 @@ import java.util.List;
import emu.nebula.data.GameData;
import emu.nebula.game.inventory.ItemParamMap;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.char_gem_instance_sweep_req)
@@ -31,7 +31,7 @@ public class HandlerCharGemInstanceSweepReq extends NetHandler {
// Sweep
var change = session.getPlayer().getInstanceManager().sweepInstance(
data,
QuestCondType.CharGemInstanceClearTotal,
QuestCondition.CharGemInstanceClearTotal,
session.getPlayer().getProgress().getCharGemLog(),
0,
req.getTimes()
@@ -4,7 +4,7 @@ import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.Public.Nil;
import emu.nebula.net.HandlerId;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.client_event_report_req)
@@ -13,7 +13,7 @@ public class HandlerClientEventReportReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Interact
session.getPlayer().triggerQuest(QuestCondType.ClientReport, 1, 1005);
session.getPlayer().triggerQuest(QuestCondition.ClientReport, 1, 1005);
// Encode response
return session.encodeMsg(NetMsgId.client_event_report_succeed_ack, Nil.newInstance());
@@ -11,7 +11,7 @@ import java.util.List;
import emu.nebula.data.GameData;
import emu.nebula.game.inventory.ItemParamMap;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.daily_instance_raid_req)
@@ -36,7 +36,7 @@ public class HandlerDailyInstanceRaidReq extends NetHandler {
// Sweep
var change = session.getPlayer().getInstanceManager().sweepInstance(
data,
QuestCondType.DailyInstanceClearTotal,
QuestCondition.DailyInstanceClearTotal,
session.getPlayer().getProgress().getDailyInstanceLog(),
req.getRewardType(),
req.getTimes()
@@ -7,7 +7,7 @@ import emu.nebula.proto.DailyInstanceSettle.DailyInstanceSettleResp;
import emu.nebula.net.HandlerId;
import emu.nebula.data.GameData;
import emu.nebula.game.instance.InstanceSettleData;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.daily_instance_settle_req)
@@ -30,7 +30,7 @@ public class HandlerDailyInstanceSettleReq extends NetHandler {
// Settle instance
var changes = player.getInstanceManager().settleInstance(
data,
QuestCondType.DailyInstanceClearTotal,
QuestCondition.DailyInstanceClearTotal,
player.getProgress().getDailyInstanceLog(),
"dailyInstanceLog",
req.getStar()
@@ -38,6 +38,9 @@ public class HandlerDailyInstanceSettleReq extends NetHandler {
var settleData = (InstanceSettleData) changes.getExtraData();
// Handle client events for achievements
session.getPlayer().getAchievementManager().handleClientEvents(req.getEvents());
// Create response
var rsp = DailyInstanceSettleResp.newInstance()
.setExp(settleData.getExp())
@@ -32,6 +32,9 @@ public class HandlerInfinityTowerSettleReq extends NetHandler {
nextLevel = 0;
}
// Handle client events for achievements
session.getPlayer().getAchievementManager().handleClientEvents(req.getEvents());
// Build response
var rsp = InfinityTowerSettleResp.newInstance()
.setNextLevelId(nextLevel)
@@ -7,7 +7,7 @@ import emu.nebula.proto.RegionBossLevelSettle.RegionBossLevelSettleResp;
import emu.nebula.net.HandlerId;
import emu.nebula.data.GameData;
import emu.nebula.game.instance.InstanceSettleData;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.region_boss_level_settle_req)
@@ -30,7 +30,7 @@ public class HandlerRegionBossLevelSettleReq extends NetHandler {
// Settle instance
var changes = player.getInstanceManager().settleInstance(
data,
QuestCondType.RegionBossClearTotal,
QuestCondition.RegionBossClearTotal,
player.getProgress().getRegionBossLog(),
"regionBossLog",
req.getStar()
@@ -38,6 +38,9 @@ public class HandlerRegionBossLevelSettleReq extends NetHandler {
var settleData = (InstanceSettleData) changes.getExtraData();
// Handle client events for achievements
session.getPlayer().getAchievementManager().handleClientEvents(req.getEvents());
// Create response
var rsp = RegionBossLevelSettleResp.newInstance()
.setExp(settleData.getExp())
@@ -11,7 +11,7 @@ import java.util.List;
import emu.nebula.data.GameData;
import emu.nebula.game.inventory.ItemParamMap;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.region_boss_level_sweep_req)
@@ -31,7 +31,7 @@ public class HandlerRegionBossLevelSweepReq extends NetHandler {
// Sweep
var change = session.getPlayer().getInstanceManager().sweepInstance(
data,
QuestCondType.RegionBossClearTotal,
QuestCondition.RegionBossClearTotal,
session.getPlayer().getProgress().getRegionBossLog(),
0,
req.getTimes()
@@ -22,6 +22,9 @@ public class HandlerScoreBossSettleReq extends NetHandler {
return session.encodeMsg(NetMsgId.score_boss_settle_failed_ack);
}
// Handle client events for achievements
session.getPlayer().getAchievementManager().handleClientEvents(req.getEvents());
// Build response
var rsp = ScoreBossSettleResp.newInstance();
@@ -7,7 +7,7 @@ import emu.nebula.proto.SkillInstanceSettle.SkillInstanceSettleResp;
import emu.nebula.net.HandlerId;
import emu.nebula.data.GameData;
import emu.nebula.game.instance.InstanceSettleData;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.skill_instance_settle_req)
@@ -30,7 +30,7 @@ public class HandlerSkillInstanceSettleReq extends NetHandler {
// Settle instance
var changes = player.getInstanceManager().settleInstance(
data,
QuestCondType.SkillInstanceClearTotal,
QuestCondition.SkillInstanceClearTotal,
player.getProgress().getSkillInstanceLog(),
"skillInstanceLog",
req.getStar()
@@ -38,6 +38,9 @@ public class HandlerSkillInstanceSettleReq extends NetHandler {
var settleData = (InstanceSettleData) changes.getExtraData();
// Handle client events for achievements
session.getPlayer().getAchievementManager().handleClientEvents(req.getEvents());
// Create response
var rsp = SkillInstanceSettleResp.newInstance()
.setExp(settleData.getExp())
@@ -11,7 +11,7 @@ import java.util.List;
import emu.nebula.data.GameData;
import emu.nebula.game.inventory.ItemParamMap;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.skill_instance_sweep_req)
@@ -31,7 +31,7 @@ public class HandlerSkillInstanceSweepReq extends NetHandler {
// Sweep
var change = session.getPlayer().getInstanceManager().sweepInstance(
data,
QuestCondType.SkillInstanceClearTotal,
QuestCondition.SkillInstanceClearTotal,
session.getPlayer().getProgress().getSkillInstanceLog(),
0,
req.getTimes()
@@ -11,7 +11,7 @@ public class HandlerStarTowerGiveUpReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
var game = session.getPlayer().getStarTowerManager().endGame();
var game = session.getPlayer().getStarTowerManager().endGame(false);
if (game == null) {
return session.encodeMsg(NetMsgId.star_tower_give_up_failed_ack);
@@ -19,10 +19,10 @@ public class HandlerStarTowerGiveUpReq extends NetHandler {
// Build response
var rsp = StarTowerGiveUpResp.newInstance()
.setBuild(game.getBuild().toProto())
.setFloor(game.getFloor());
rsp.getMutableChange();
rsp.setBuild(game.getBuild().toProto());
return session.encodeMsg(NetMsgId.star_tower_give_up_succeed_ack, rsp);
}
@@ -24,6 +24,9 @@ public class HandlerVampireSurvivorAreaChangeReq extends NetHandler {
// Calculate score for area
game.settleArea(req.getTime(), req.getKillCount().toArray());
// Handle client events for achievements
session.getPlayer().getAchievementManager().handleClientEvents(req.getEvents());
// Encode and send
return session.encodeMsg(NetMsgId.vampire_survivor_area_change_succeed_ack);
}
@@ -32,6 +32,9 @@ public class HandlerVampireSurvivorSettleReq extends NetHandler {
// Settle game
session.getPlayer().getVampireSurvivorManager().settle(victory, score);
// Handle client events for achievements
session.getPlayer().getAchievementManager().handleClientEvents(req.getEvents());
// Build response
var rsp = VampireSurvivorSettleResp.newInstance();
@@ -7,7 +7,7 @@ import emu.nebula.proto.WeekBossSettle.WeekBossSettleReq;
import emu.nebula.net.HandlerId;
import emu.nebula.data.GameData;
import emu.nebula.game.instance.InstanceSettleData;
import emu.nebula.game.quest.QuestCondType;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.week_boss_settle_req)
@@ -30,7 +30,7 @@ public class HandlerWeekBossSettleReq extends NetHandler {
// Settle instance
var changes = player.getInstanceManager().settleInstance(
data,
QuestCondType.WeekBoosClearSpecificDifficultyAndTotal,
QuestCondition.WeekBoosClearSpecificDifficultyAndTotal,
player.getProgress().getWeekBossLog(),
"weekBossLog",
req.getResult() ? 1 : 0
@@ -38,6 +38,9 @@ public class HandlerWeekBossSettleReq extends NetHandler {
var settleData = (InstanceSettleData) changes.getExtraData();
// Handle client events for achievements
session.getPlayer().getAchievementManager().handleClientEvents(req.getEvents());
// Create response
var rsp = WeekBossLevelSettleResp.newInstance()
.setFirst(settleData.isFirst())
@@ -162,7 +162,13 @@ public class AgentZoneHandler implements Handler {
ctx.status(200);
ctx.result(result);
// Clear header
ctx.res().setHeader("Content-Type", null);
// Handle post response events
if (session != null) {
session.afterResponse();
}
}
}