Implement anniversary banner gacha rewards

This commit is contained in:
Melledy committed 2026-10-22 22:38:20 -07:00
1 parent a928bb40f0
commit 1b745a5cc5
7 files changed
+144 -3

No files matched your search

+4 -2
View File
@@ -49,8 +49,9 @@ public class GameData {
@Getter private static DataTable<ItemDef> ItemDataTable = new DataTable<>(); @Getter private static DataTable<ItemDef> ItemDataTable = new DataTable<>();
@Getter private static DataTable<ProductionDef> ProductionDataTable = new DataTable<>(); @Getter private static DataTable<ProductionDef> ProductionDataTable = new DataTable<>();
@Getter private static DataTable<PlayerHeadDef> PlayerHeadDataTable = new DataTable<>(); @Getter private static DataTable<PlayerHeadDef> PlayerHeadDataTable = new DataTable<>();
@Getter private static DataTable<TitleDef> titleDataTable = new DataTable<>(); @Getter private static DataTable<TitleDef> TitleDataTable = new DataTable<>();
@Getter private static DataTable<HonorDef> honorDataTable = new DataTable<>(); @Getter private static DataTable<HonorDef> HonorDataTable = new DataTable<>();
@Getter private static DataTable<DropDef> DropDataTable = new DataTable<>();
// ===== Shops ===== // ===== Shops =====
@Getter private static DataTable<MallMonthlyCardDef> MallMonthlyCardDataTable = new DataTable<>(); @Getter private static DataTable<MallMonthlyCardDef> MallMonthlyCardDataTable = new DataTable<>();
@@ -80,6 +81,7 @@ public class GameData {
@Getter private static DataTable<GachaATypeProbDef> GachaATypeProbDataTable = new DataTable<>(); @Getter private static DataTable<GachaATypeProbDef> GachaATypeProbDataTable = new DataTable<>();
@Getter private static DataTable<GachaDef> GachaDataTable = new DataTable<>(); @Getter private static DataTable<GachaDef> GachaDataTable = new DataTable<>();
@Getter private static DataTable<GachaNewbieDef> GachaNewbieDataTable = new DataTable<>(); @Getter private static DataTable<GachaNewbieDef> GachaNewbieDataTable = new DataTable<>();
@Getter private static DataTable<GachaRewardDef> GachaRewardDataTable = new DataTable<>();
@Getter private static DataTable<GachaStorageDef> GachaStorageDataTable = new DataTable<>(); @Getter private static DataTable<GachaStorageDef> GachaStorageDataTable = new DataTable<>();
@Getter private static DataTable<GachaTypeDef> GachaTypeDataTable = new DataTable<>(); @Getter private static DataTable<GachaTypeDef> GachaTypeDataTable = new DataTable<>();
@@ -0,0 +1,23 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "Drop.json")
public class DropDef extends BaseDef {
private int DropId;
private int PkgId;
@Override
public int getId() {
return DropId;
}
@Override
public void onLoad() {
}
}
@@ -1,6 +1,7 @@
package emu.nebula.data.resources; package emu.nebula.data.resources;
import emu.nebula.data.BaseDef; import emu.nebula.data.BaseDef;
import emu.nebula.data.GameData;
import emu.nebula.data.ResourceType; import emu.nebula.data.ResourceType;
import emu.nebula.util.Utils; import emu.nebula.util.Utils;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@@ -31,6 +32,14 @@ public class DropPkgDef extends BaseDef {
public static int getRandomDrop(int packageId) { public static int getRandomDrop(int packageId) {
var packageList = PACKAGES.get(packageId); var packageList = PACKAGES.get(packageId);
if (packageList == null) {
// Try and get package id from drop data
var dropData = GameData.getDropDataTable().get(packageId);
if (dropData != null) {
packageList = PACKAGES.get(dropData.getPkgId());
}
}
if (packageList == null) { if (packageList == null) {
return 0; return 0;
} }
@@ -0,0 +1,22 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "GachaReward.json")
public class GachaRewardDef extends BaseDef {
private int Id;
private int GachaId;
private int Index;
private int Num;
private int Tid;
private int Qty;
@Override
public int getId() {
return this.Id;
}
}
@@ -5,6 +5,7 @@ import dev.morphia.annotations.Entity;
import emu.nebula.data.GameData; import emu.nebula.data.GameData;
import emu.nebula.data.resources.GachaDef; import emu.nebula.data.resources.GachaDef;
import emu.nebula.proto.GachaInformation.GachaInfo; import emu.nebula.proto.GachaInformation.GachaInfo;
import emu.nebula.util.Bitset;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@@ -18,6 +19,7 @@ public class GachaBannerInfo {
private int total; private int total;
private boolean usedFirstTen; private boolean usedFirstTen;
private boolean usedGuarantee; private boolean usedGuarantee;
private Bitset rewards;
@Deprecated //Morphia only @Deprecated //Morphia only
public GachaBannerInfo() { public GachaBannerInfo() {
@@ -28,6 +30,14 @@ public class GachaBannerInfo {
this.id = data.getId(); this.id = data.getId();
} }
public Bitset getRewards() {
if (this.rewards == null) {
this.rewards = new Bitset();
}
return this.rewards;
}
public GachaBannerDraft copyForSpin() { public GachaBannerDraft copyForSpin() {
return new GachaBannerDraft(this.total, this.usedFirstTen, this.usedGuarantee); return new GachaBannerDraft(this.total, this.usedFirstTen, this.usedGuarantee);
} }
@@ -67,7 +77,8 @@ public class GachaBannerInfo {
.setAMissTimes(missTimesA) .setAMissTimes(missTimesA)
.setAupGuaranteeTimes(aupGuaranteeTimes) .setAupGuaranteeTimes(aupGuaranteeTimes)
.setReveFirstTenReward(!showFirstTenBonusHintText) .setReveFirstTenReward(!showFirstTenBonusHintText)
.setRecvGuaranteeReward(this.isUsedGuarantee()); .setRecvGuaranteeReward(this.isUsedGuarantee())
.setRewardsRecords(this.getRewards().toByteArray());
} }
public record GachaBannerDraft( public record GachaBannerDraft(
@@ -35,6 +35,7 @@ public class GachaModule extends GameContextModule {
var storage = data.getStorageData(); var storage = data.getStorageData();
var manager = player.getGachaManager(); var manager = player.getGachaManager();
synchronized (manager) { synchronized (manager) {
var info = manager.getBannerInfo(data); var info = manager.getBannerInfo(data);
var pityState = manager.getPityState(data.getStorageId()); var pityState = manager.getPityState(data.getStorageId());
@@ -55,6 +56,7 @@ public class GachaModule extends GameContextModule {
public PlayerChangeInfo recvGuarantee(Player player, int bannerId) { public PlayerChangeInfo recvGuarantee(Player player, int bannerId) {
var manager = player.getGachaManager(); var manager = player.getGachaManager();
synchronized (manager) { synchronized (manager) {
var info = manager.findBannerInfo(bannerId); var info = manager.findBannerInfo(bannerId);
if (info == null) { if (info == null) {
@@ -79,11 +81,54 @@ public class GachaModule extends GameContextModule {
} }
info.setUsedGuarantee(true); info.setUsedGuarantee(true);
// Save to database
manager.saveBanner(info); manager.saveBanner(info);
// Complete
return player.getInventory().addItem(data.getGuaranteeTid(), data.getGuaranteeQty()); return player.getInventory().addItem(data.getGuaranteeTid(), data.getGuaranteeQty());
} }
} }
public PlayerChangeInfo recvReward(Player player, int rewardId) {
// Get reward data
var rewardData = GameData.getGachaRewardDataTable().get(rewardId);
if (rewardData == null) {
return null;
}
// Get banner data
var data = GameData.getGachaDataTable().get(rewardData.getGachaId());
if (data == null || !data.isActiveAt(Nebula.getCurrentServerTime())) {
return null;
}
var manager = player.getGachaManager();
synchronized (manager) {
// Get banner info
var info = manager.getBannerInfo(data);
// Make sure the reward is unlocked
if (info.getTotal() < rewardData.getNum()) {
return null;
}
// Make sure we haven't already claimed the reward
if (info.getRewards().isSet(rewardData.getIndex())) {
return null;
}
// Set claimed
info.getRewards().setBit(rewardData.getIndex());
// Save to database
manager.saveBanner(info);
// Complete
return player.getInventory().addItem(rewardData.getTid(), rewardData.getQty());
}
}
public List<GachaNewbieInfo> listNewbieInfos(Player player) { public List<GachaNewbieInfo> listNewbieInfos(Player player) {
return this.newbieGachaModule.listInfos(player); return this.newbieGachaModule.listInfos(player);
} }
@@ -0,0 +1,29 @@
package emu.nebula.server.handlers;
import emu.nebula.Nebula;
import emu.nebula.net.GameSession;
import emu.nebula.net.HandlerId;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.Public.UI32;
@HandlerId(NetMsgId.gacha_reward_get_req)
public class HandlerGachaRewardGetReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Parse req
var req = UI32.parseFrom(message);
// Receive reward
var change = Nebula.getGameContext().getGachaModule().recvReward(session.getPlayer(), req.getValue());
if (change == null) {
return session.encodeMsg(NetMsgId.gacha_reward_get_failed_ack);
}
// Encode and send
return session.encodeMsg(NetMsgId.gacha_reward_get_succeed_ack, change.toProto());
}
}