mirror of
https://github.com/Melledy/Nebula.git
synced 2025-12-14 13:24:43 +01:00
Implement level rewards
This commit is contained in:
@@ -2,6 +2,7 @@ package emu.nebula.data.resources;
|
||||
|
||||
import emu.nebula.data.BaseDef;
|
||||
import emu.nebula.data.ResourceType;
|
||||
import emu.nebula.game.inventory.ItemParamMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@@ -11,8 +12,19 @@ public class WorldClassDef extends BaseDef {
|
||||
private int Exp;
|
||||
private String Reward;
|
||||
|
||||
private transient ItemParamMap rewards;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return Id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
if (this.Reward != null) {
|
||||
this.rewards = ItemParamMap.fromJsonString(this.Reward);
|
||||
} else {
|
||||
this.rewards = new ItemParamMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import emu.nebula.game.scoreboss.ScoreBossManager;
|
||||
import emu.nebula.game.story.StoryManager;
|
||||
import emu.nebula.game.tower.StarTowerManager;
|
||||
import emu.nebula.net.GameSession;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.NetMsgPacket;
|
||||
import emu.nebula.proto.PlayerData.DictionaryEntry;
|
||||
import emu.nebula.proto.PlayerData.DictionaryTab;
|
||||
@@ -32,6 +33,7 @@ import emu.nebula.proto.Public.NewbieInfo;
|
||||
import emu.nebula.proto.Public.QuestType;
|
||||
import emu.nebula.proto.Public.Story;
|
||||
import emu.nebula.proto.Public.WorldClass;
|
||||
import emu.nebula.proto.Public.WorldClassRewardState;
|
||||
import emu.nebula.proto.Public.Title;
|
||||
|
||||
import lombok.Getter;
|
||||
@@ -305,10 +307,15 @@ public class Player implements GameDatabaseObject {
|
||||
|
||||
// Check for level ups
|
||||
while (this.exp >= expRequired && expRequired > 0) {
|
||||
// Add level
|
||||
this.level += 1;
|
||||
this.exp -= expRequired;
|
||||
|
||||
// Recalculate exp required
|
||||
expRequired = this.getMaxExp();
|
||||
|
||||
// Set level reward
|
||||
this.getQuestManager().getLevelRewards().setBit(this.level);
|
||||
}
|
||||
|
||||
// Save to database
|
||||
@@ -321,6 +328,17 @@ public class Player implements GameDatabaseObject {
|
||||
this.getExp()
|
||||
);
|
||||
|
||||
// Save level rewards if we changed it
|
||||
if (oldLevel != this.getLevel()) {
|
||||
this.getQuestManager().saveLevelRewards();
|
||||
|
||||
this.addNextPackage(
|
||||
NetMsgId.world_class_reward_state_notify,
|
||||
WorldClassRewardState.newInstance()
|
||||
.setFlag(getQuestManager().getLevelRewards().toBigEndianByteArray())
|
||||
);
|
||||
}
|
||||
|
||||
// Calculate changes
|
||||
var proto = WorldClass.newInstance()
|
||||
.setAddClass(this.getLevel() - oldLevel)
|
||||
@@ -514,7 +532,6 @@ public class Player implements GameDatabaseObject {
|
||||
|
||||
state.getMutableMail();
|
||||
state.getMutableBattlePass();
|
||||
state.getMutableWorldClassReward();
|
||||
state.getMutableFriendEnergy();
|
||||
state.getMutableMallPackage();
|
||||
state.getMutableAchievement();
|
||||
@@ -571,6 +588,10 @@ public class Player implements GameDatabaseObject {
|
||||
proto.addDailyActiveIds(id);
|
||||
}
|
||||
|
||||
|
||||
state.getMutableWorldClassReward()
|
||||
.setFlag(this.getQuestManager().getLevelRewards().toBigEndianByteArray());
|
||||
|
||||
// Add dictionary tabs
|
||||
for (var dictionaryData : GameData.getDictionaryTabDataTable()) {
|
||||
var dictionaryProto = DictionaryTab.newInstance()
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package emu.nebula.game.quest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
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.WorldClassDef;
|
||||
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.util.Bitset;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
@@ -32,6 +34,9 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
|
||||
// Quests
|
||||
private Map<Integer, GameQuest> quests;
|
||||
|
||||
// Level rewards
|
||||
private Bitset levelRewards;
|
||||
|
||||
@Deprecated // Morphia only
|
||||
public QuestManager() {
|
||||
|
||||
@@ -42,12 +47,17 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
|
||||
this.uid = player.getUid();
|
||||
this.claimedActiveIds = new IntOpenHashSet();
|
||||
this.quests = new HashMap<>();
|
||||
this.levelRewards = new Bitset();
|
||||
|
||||
this.resetDailyQuests();
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
public void saveLevelRewards() {
|
||||
Nebula.getGameDatabase().update(this, this.getUid(), "levelRewards", this.levelRewards);
|
||||
}
|
||||
|
||||
public synchronized void resetDailyQuests() {
|
||||
// Reset daily quests
|
||||
for (var data : GameData.getDailyQuestDataTable()) {
|
||||
@@ -87,9 +97,9 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
|
||||
}
|
||||
}
|
||||
|
||||
public PlayerChangeInfo receiveReward(int questId) {
|
||||
public PlayerChangeInfo receiveQuestReward(int questId) {
|
||||
// Get received quests
|
||||
var claimList = new HashSet<GameQuest>();
|
||||
var claimList = new ArrayList<GameQuest>();
|
||||
|
||||
if (questId > 0) {
|
||||
// Claim specific quest
|
||||
@@ -140,7 +150,7 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
|
||||
Nebula.getGameDatabase().update(this, this.getUid(), "activity", this.getActivity());
|
||||
|
||||
// Success
|
||||
return change;
|
||||
return change.setSuccess(true);
|
||||
}
|
||||
|
||||
public PlayerChangeInfo claimActiveRewards() {
|
||||
@@ -179,7 +189,54 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
|
||||
Nebula.getGameDatabase().update(this, this.getUid(), "claimedActiveIds", this.getClaimedActiveIds());
|
||||
|
||||
// Success
|
||||
return change;
|
||||
return change.setSuccess(true);
|
||||
}
|
||||
|
||||
public PlayerChangeInfo receiveWorldClassReward(int id) {
|
||||
// Get rewards we want to claim
|
||||
var claimList = new ArrayList<WorldClassDef>();
|
||||
|
||||
if (id > 0) {
|
||||
// Claim specific level reward
|
||||
if (this.getLevelRewards().isSet(id)) {
|
||||
var data = GameData.getWorldClassDataTable().get(id);
|
||||
if (data != null) {
|
||||
claimList.add(data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Claim all
|
||||
for (var data : GameData.getWorldClassDataTable()) {
|
||||
if (this.getLevelRewards().isSet(data.getId())) {
|
||||
claimList.add(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if (claimList.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Claim
|
||||
var rewards = new ItemParamMap();
|
||||
|
||||
for (var data : claimList) {
|
||||
// Add rewards
|
||||
rewards.add(data.getRewards());
|
||||
|
||||
// Unset level rewards
|
||||
this.getLevelRewards().unsetBit(data.getId());
|
||||
}
|
||||
|
||||
// Add to inventory
|
||||
var change = this.getPlayer().getInventory().addItems(rewards);
|
||||
|
||||
// Save to db
|
||||
this.saveLevelRewards();
|
||||
|
||||
// Success
|
||||
return change.setSuccess(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.PlayerWorldClassRewardReceive.PlayerWorldClassRewardReq;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.player_world_class_reward_receive_req)
|
||||
public class HandlerPlayerWorldClassRewardReceiveReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse request
|
||||
var req = PlayerWorldClassRewardReq.parseFrom(message);
|
||||
|
||||
// Receive rewards
|
||||
var change = session.getPlayer().getQuestManager().receiveWorldClassReward(req.getClassX());
|
||||
|
||||
if (change == null) {
|
||||
return session.encodeMsg(NetMsgId.player_world_class_reward_receive_failed_ack);
|
||||
}
|
||||
|
||||
// Template
|
||||
return session.encodeMsg(NetMsgId.player_world_class_reward_receive_succeed_ack, change.toProto());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,7 +15,7 @@ public class HandlerQuestDailyRewardReceiveReq extends NetHandler {
|
||||
var req = UI32.parseFrom(message);
|
||||
|
||||
// Receive rewards
|
||||
var change = session.getPlayer().getQuestManager().receiveReward(req.getValue());
|
||||
var change = session.getPlayer().getQuestManager().receiveQuestReward(req.getValue());
|
||||
|
||||
if (change == null) {
|
||||
return session.encodeMsg(NetMsgId.quest_daily_reward_receive_failed_ack);
|
||||
|
||||
@@ -39,6 +39,19 @@ public class Bitset {
|
||||
this.data[longArrayOffset] |= (1L << bytePosition);
|
||||
}
|
||||
|
||||
public void unsetBit(int index) {
|
||||
int longArrayOffset = (int) Math.floor((index - 1) / 64D);
|
||||
int bytePosition = ((index - 1) % 64);
|
||||
|
||||
if (longArrayOffset >= this.data.length) {
|
||||
var oldData = this.data;
|
||||
this.data = new long[longArrayOffset + 1];
|
||||
System.arraycopy(oldData, 0, this.data, 0, oldData.length);
|
||||
}
|
||||
|
||||
this.data[longArrayOffset] &= (1L << bytePosition);
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
byte[] array = new byte[this.getData().length * 8];
|
||||
|
||||
@@ -53,4 +66,19 @@ public class Bitset {
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public byte[] toBigEndianByteArray() {
|
||||
byte[] array = new byte[this.getData().length * 8];
|
||||
|
||||
for (int i = 0; i < this.getData().length; i++) {
|
||||
long value = this.getData()[i];
|
||||
|
||||
for (int x = 0; x <= 7; x++) {
|
||||
array[(i * 8) + x] = (byte) (value & 0xFF);
|
||||
value >>= Byte.SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user