Update to support game version 2.3.0

This commit is contained in:
Melledy
2024-06-18 18:25:21 -07:00
parent 3b728b2c10
commit c1545bd2a8
422 changed files with 39400 additions and 28771 deletions

View File

@@ -6,7 +6,7 @@ import java.time.ZoneOffset;
import emu.lunarcore.util.Position;
public class GameConstants {
public static String VERSION = "2.2.0";
public static String VERSION = "2.3.0";
public static final ZoneOffset CURRENT_ZONEOFFSET = ZoneOffset.systemDefault().getRules().getOffset(Instant.now());
public static final int CURRENT_TIMEZONE = CURRENT_ZONEOFFSET.getTotalSeconds() / 3600;
@@ -53,6 +53,7 @@ public class GameConstants {
// Challenge
public static final int CHALLENGE_ENTRANCE = 100000103;
public static final int CHALLENGE_STORY_ENTRANCE = 102020107;
public static final int CHALLENGE_BOSS_ENTRANCE = 1030402;
// Rogue
public static final boolean ENABLE_ROGUE = true;

View File

@@ -36,10 +36,7 @@ public class SceneCommand implements CommandHandler {
return;
}
int startGroup = floor.getStartGroupID();
int anchorId = floor.getStartAnchorID();
AnchorInfo anchor = floor.getAnchorInfo(startGroup, anchorId);
AnchorInfo anchor = floor.getStartAnchorInfo();
if (anchor == null) {
args.sendMessage("Error: Floor info not found");
return;

View File

@@ -42,6 +42,7 @@ public class GameData {
@Getter private static Int2ObjectMap<TextJoinExcel> textJoinExcelMap = new Int2ObjectLinkedOpenHashMap<>();
@Getter private static Int2ObjectMap<ChatBubbleExcel> chatBubbleExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<PhoneThemeExcel> phoneThemeExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<ContentPackageExcel> contentPackageExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<ChallengeGroupExcel> challengeGroupExcelMap = new Int2ObjectOpenHashMap<>();
@Getter private static Int2ObjectMap<ChallengeExcel> challengeExcelMap = new Int2ObjectOpenHashMap<>();

View File

@@ -207,15 +207,15 @@ public class ResourceLoader {
}
}
// Might be better to cache
// Might be better to cache
private static void loadFloorInfos() {
// Load floor infos
LunarCore.getLogger().info("Loading floor infos... this may take a while.");
File floorDir = new File(LunarCore.getConfig().getResourceDir() + "/Config/LevelOutput/Floor/");
File floorDir = new File(LunarCore.getConfig().getResourceDir() + "/Config/LevelOutput/RuntimeFloor/");
boolean missingGroupInfos = false;
if (!floorDir.exists()) {
LunarCore.getLogger().warn("Floor infos are missing, please check your resources folder: {resources}/Config/LevelOutput/Floor. Teleports and natural world spawns may not work!");
LunarCore.getLogger().warn("Floor infos are missing, please check your resources folder: {resources}/Config/LevelOutput/RuntimeFloor. Teleports and natural world spawns may not work!");
return;
}
@@ -247,6 +247,7 @@ public class ResourceLoader {
GroupInfo group = gson.fromJson(reader, GroupInfo.class);
group.setId(simpleGroup.getID());
floor.getGroupList().add(group);
floor.getGroups().put(simpleGroup.getID(), group);
} catch (Exception e) {
e.printStackTrace();
@@ -265,7 +266,7 @@ public class ResourceLoader {
// Notify the server owner if we are missing any files
if (missingGroupInfos) {
LunarCore.getLogger().warn("Group infos are missing, please check your resources folder: {resources}/Config/LevelOutput/Group. Teleports, monster battles, and natural world spawns may not work!");
LunarCore.getLogger().warn("Group infos are missing, please check your resources folder: {resources}/Config/LevelOutput/SharedRuntimeGroup. Teleports, monster battles, and natural world spawns may not work!");
}
// Done

View File

@@ -18,37 +18,64 @@ import lombok.Getter;
@Getter
public class FloorInfo {
private int FloorID;
private int StartGroupID;
private int StartGroupIndex;
private int StartAnchorID;
@SerializedName(value = "SavedValues")
private List<ExtraDataInfo> savedValues;
@SerializedName(value = "GroupList")
@SerializedName(value = "GroupInstanceList")
private List<FloorGroupSimpleInfo> SimpleGroupList;
// Cached data
private transient boolean loaded;
private transient List<GroupInfo> groupList;
private transient Int2ObjectMap<GroupInfo> groups;
private transient Int2ObjectMap<PropInfo> cachedTeleports;
private transient List<PropInfo> unlockedCheckpoints; // DEBUG
public FloorInfo() {
this.groupList = new ArrayList<>();
this.groups = new Int2ObjectOpenHashMap<>();
this.cachedTeleports = new Int2ObjectOpenHashMap<>();
this.unlockedCheckpoints = new ArrayList<>();
this.savedValues = new ArrayList<>();
}
public GroupInfo getGroupInfoByIndex(int groupIndex) {
return groupList.get(groupIndex);
}
public AnchorInfo getStartAnchorInfo() {
return getAnchorInfo(StartGroupID, StartAnchorID);
GroupInfo group = this.getGroupInfoByIndex(StartGroupIndex);
if (group == null) return null;
return getAnchorInfo(group, StartAnchorID);
}
public List<ExtraDataInfo> getExtraDatas() {
if (this.savedValues == null) {
this.savedValues = new ArrayList<>();
}
return this.savedValues;
}
public AnchorInfo getAnchorInfo(int groupId, int anchorId) {
GroupInfo group = this.getGroups().get(groupId);
if (group == null) return null;
return getAnchorInfo(group, anchorId);
}
public AnchorInfo getAnchorInfo(GroupInfo group, int anchorId) {
return group.getAnchorList().stream().filter(a -> a.getID() == anchorId).findFirst().orElse(null);
}
public void onLoad() {
if (this.loaded) return;
this.savedValues = getExtraDatas();
// Cache anchors
for (GroupInfo group : groups.values()) {
@@ -84,6 +111,16 @@ public class FloorInfo {
this.loaded = true;
}
@Getter
public static class ExtraDataInfo {
private int ID;
private String Name;
private int DefaultValue;
private List<Integer> AllowedValues;
private int MaxValue;
private Integer MinValue;
}
@Getter
public static class FloorGroupSimpleInfo {

View File

@@ -31,7 +31,7 @@ public class AvatarExcel extends GameResource {
private int[] RankIDList;
private int[] SkillList;
private String JsonPath;
private String ManikinJsonPath;
@Getter(AccessLevel.NONE)
private transient AvatarPromotionExcel[] promotionData;
@@ -77,13 +77,13 @@ public class AvatarExcel extends GameResource {
}
// Get name key
Matcher matcher = namePattern.matcher(this.JsonPath);
Matcher matcher = namePattern.matcher(this.ManikinJsonPath);
if (matcher.find()) {
this.nameKey = matcher.group(0);
}
// Clear variable to save memory
this.JsonPath = null;
this.ManikinJsonPath = null;
}
}

View File

@@ -0,0 +1,30 @@
package emu.lunarcore.data.excel;
import emu.lunarcore.data.GameData;
import emu.lunarcore.data.GameResource;
import emu.lunarcore.data.ResourceType;
import emu.lunarcore.data.ResourceType.LoadPriority;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import lombok.Getter;
@Getter
@ResourceType(name = {"ChallengeBossMazeExtra.json"}, loadPriority = LoadPriority.LOW)
public class ChallengeBossExtraExcel extends GameResource {
private int ID;
private int TurnLimit;
private int ClearScore;
private IntArrayList BattleTargetID;
@Override
public int getId() {
return ID;
}
@Override
public void onLoad() {
var challengeExcel = GameData.getChallengeExcelMap().get(this.getId());
if (challengeExcel != null) {
challengeExcel.setBossExcel(this);
}
}
}

View File

@@ -2,12 +2,13 @@ package emu.lunarcore.data.excel;
import emu.lunarcore.data.GameResource;
import emu.lunarcore.data.ResourceType;
import emu.lunarcore.game.challenge.ChallengeType;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import lombok.Getter;
@Getter
@ResourceType(name = {"ChallengeMazeConfig.json", "ChallengeStoryMazeConfig.json"})
@ResourceType(name = {"ChallengeMazeConfig.json", "ChallengeStoryMazeConfig.json", "ChallengeBossMazeConfig.json"})
public class ChallengeExcel extends GameResource {
private int ID;
private int GroupID;
@@ -31,8 +32,10 @@ public class ChallengeExcel extends GameResource {
private transient Int2ObjectMap<ChallengeMonsterInfo> challengeMonsters1;
private transient Int2ObjectMap<ChallengeMonsterInfo> challengeMonsters2;
private transient ChallengeType type = ChallengeType.MEMORY;
private transient ChallengeStoryExtraExcel storyExcel;
private transient ChallengeBossExtraExcel bossExcel;
@Override
public int getId() {
return ID;
@@ -42,10 +45,17 @@ public class ChallengeExcel extends GameResource {
return this.storyExcel != null;
}
public void setStoryExcel(ChallengeStoryExtraExcel storyExcel) {
this.storyExcel = storyExcel;
public void setStoryExcel(ChallengeStoryExtraExcel excel) {
this.type = ChallengeType.STORY;
this.storyExcel = excel;
this.ChallengeCountDown = storyExcel.getTurnLimit();
}
public void setBossExcel(ChallengeBossExtraExcel excel) {
this.type = ChallengeType.BOSS;
this.bossExcel = excel;
this.ChallengeCountDown = 10; // idk
}
@Override
public void onLoad() {

View File

@@ -0,0 +1,16 @@
package emu.lunarcore.data.excel;
import emu.lunarcore.data.GameResource;
import emu.lunarcore.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = {"ContentPackageConfig.json"})
public class ContentPackageExcel extends GameResource {
private int ContentID;
@Override
public int getId() {
return ContentID;
}
}

View File

@@ -16,10 +16,10 @@ import com.google.gson.annotations.SerializedName;
@Getter
@ResourceType(name = {"RogueBuffGroup.json"}, loadPriority = LoadPriority.LOW)
public class RogueBuffGroupExcel extends GameResource {
@SerializedName(value = "GKOGJPDANCE")
@SerializedName(value = "LIOICIOFLGL")
private int RogueBuffGroupID; // RogueBuffGroupID
@SerializedName(value = "NFPAICKGMBC")
@SerializedName(value = "LEEMGFGKCMO")
private IntArrayList RogueBuffTagList; // RogueBuffTagList or RogueBuffGroupList
private transient Set<RogueBuffData> rogueBuffList = new HashSet<>();

View File

@@ -140,7 +140,7 @@ public class BattleService extends BaseGameService {
if (castingAvatar != null) {
// Add elemental weakness debuff to enemies
MazeBuff buff = battle.addBuff(castingAvatar.getExcel().getDamageType().getEnterBattleBuff(), battle.getLineup().getLeader());
if (buff != null) {
if (buff != null && castedSkill != null) {
buff.addTargetIndex(battle.getLineup().getLeader());
buff.addDynamicValue("SkillIndex", castedSkill.getIndex());
}

View File

@@ -50,7 +50,7 @@ public class MazeSkillAddBuff extends MazeSkillAction {
for (GameEntity target : targets) {
if (target instanceof EntityMonster monster) {
// Set as temp buff
monster.setTempBuff(new SceneBuff(caster.getAvatarId(), buffId));
monster.addTempBuff(new SceneBuff(caster.getAvatarId(), buffId));
}
}
}

View File

@@ -26,7 +26,13 @@ public class ChallengeEntityLoader extends SceneEntityLoader {
scene.loadGroup(instance.getExcel().getMazeGroupID1());
// Set leave entry
scene.setLeaveEntryId(instance.isStory() ? GameConstants.CHALLENGE_STORY_ENTRANCE : GameConstants.CHALLENGE_ENTRANCE);
int leaveEntryId = switch (instance.getType()) {
default -> GameConstants.CHALLENGE_ENTRANCE;
case STORY -> GameConstants.CHALLENGE_STORY_ENTRANCE;
case BOSS -> GameConstants.CHALLENGE_BOSS_ENTRANCE;
};
scene.setLeaveEntryId(leaveEntryId);
// Load all groups with props
for (var group : scene.getFloorInfo().getGroups().values()) {

View File

@@ -8,6 +8,7 @@ import dev.morphia.annotations.Indexed;
import emu.lunarcore.LunarCore;
import emu.lunarcore.game.player.Player;
import emu.lunarcore.proto.ChallengeOuterClass.Challenge;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
@@ -26,6 +27,9 @@ public class ChallengeHistory {
private int stars;
private int score;
@Setter(AccessLevel.NONE)
private ChallengeExtraHistory extraData;
@Deprecated // Morphia
public ChallengeHistory() {}
@@ -50,6 +54,14 @@ public class ChallengeHistory {
this.score = score;
}
public ChallengeExtraHistory getExtraData() {
if (this.extraData == null) {
this.extraData = new ChallengeExtraHistory();
}
return this.extraData;
}
public Challenge toProto() {
var proto = Challenge.newInstance()
.setChallengeId(this.getChallengeId())
@@ -57,6 +69,12 @@ public class ChallengeHistory {
.setScore(this.getScore())
.setStars(this.getStars());
if (this.extraData != null) {
var boss = proto.getMutableExtInfo().getMutableBossInfo();
boss.getMutableFirstNode();
boss.getMutableSecondNode();
}
return proto;
}
@@ -67,4 +85,9 @@ public class ChallengeHistory {
public void save() {
LunarCore.getGameDatabase().save(this);
}
@Entity(useDiscriminator = false)
public static class ChallengeExtraHistory {
}
}

View File

@@ -41,7 +41,7 @@ public class ChallengeInstance {
@Setter private int scoreStage1;
@Setter private int scoreStage2;
private IntList storyBuffs;
private IntList buffs;
@Deprecated // Morphia only
public ChallengeInstance() {}
@@ -66,6 +66,10 @@ public class ChallengeInstance {
return this.getExcel().getId();
}
public ChallengeType getType() {
return this.getExcel().getType();
}
public boolean isStory() {
return this.excel.isStory();
}
@@ -90,13 +94,13 @@ public class ChallengeInstance {
return status == ChallengeStatus.CHALLENGE_FINISH_VALUE;
}
public void addStoryBuff(int storyBuff) {
public void addBuff(int buff) {
// Add story buffs
if (storyBuffs == null) {
storyBuffs = new IntArrayList();
if (buffs == null) {
buffs = new IntArrayList();
}
storyBuffs.add(storyBuff);
buffs.add(buff);
}
public void onBattleStart(Battle battle) {
@@ -104,10 +108,10 @@ public class ChallengeInstance {
battle.setRoundsLimit(player.getChallengeInstance().getRoundsLeft());
// Add story buffs
if (this.getStoryBuffs() != null) {
if (this.getBuffs() != null) {
battle.addBuff(this.getExcel().getMazeBuffID());
int buffId = this.getStoryBuffs().getInt(this.getCurrentStage() - 1);
int buffId = this.getBuffs().getInt(this.getCurrentStage() - 1);
if (buffId != 0) {
battle.addBuff(buffId);
}
@@ -190,7 +194,7 @@ public class ChallengeInstance {
this.setStatus(ChallengeStatus.CHALLENGE_FINISH);
this.stars = this.calculateStars();
// Save history
player.getChallengeManager().addHistory(this.getChallengeId(), this.getStars(), this.getTotalScore());
player.getChallengeManager().addHistory(this.getChallengeId(), this.getStars(), this.getTotalScore(), this.getType() == ChallengeType.BOSS);
// Send challenge result data
player.sendPacket(new PacketChallengeSettleNotify(this));
} else {
@@ -266,10 +270,23 @@ public class ChallengeInstance {
.setScoreTwo(this.getScoreStage2())
.setRoundCount(this.getRoundsElapsed())
.setExtraLineupTypeValue(this.getCurrentExtraLineup());
if (this.getStoryBuffs() != null) {
int buffId = this.getStoryBuffs().getInt(this.getCurrentStage() - 1);
proto.getMutableStoryInfo().getMutableCurStoryBuffs().addBuffList(buffId);
switch (this.getType()) {
case STORY -> {
if (this.getBuffs() != null) {
int buffId = this.getBuffs().getInt(this.getCurrentStage() - 1);
proto.getMutableStoryInfo().getMutableCurStoryBuffs().addBuffList(buffId);
}
}
case BOSS -> {
if (this.getBuffs() != null) {
int buffId = this.getBuffs().getInt(this.getCurrentStage() - 1);
proto.getMutableStoryInfo().getMutableCurBossBuffs().addBuffList(buffId);
}
}
default -> {
// Nothing
}
}
return proto;

View File

@@ -1,6 +1,7 @@
package emu.lunarcore.game.challenge;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
@@ -14,26 +15,42 @@ import emu.lunarcore.game.player.BasePlayerManager;
import emu.lunarcore.game.player.Player;
import emu.lunarcore.game.player.lineup.PlayerLineup;
import emu.lunarcore.proto.ExtraLineupTypeOuterClass.ExtraLineupType;
import emu.lunarcore.proto.StartChallengeStoryBuffInfoOuterClass.StartChallengeStoryBuffInfo;
import emu.lunarcore.proto.TakenChallengeRewardInfoOuterClass.TakenChallengeRewardInfo;
import emu.lunarcore.server.packet.Retcode;
import emu.lunarcore.server.packet.send.PacketStartChallengeScRsp;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import lombok.Getter;
import us.hebi.quickbuf.RepeatedInt;
@Getter
public class ChallengeManager extends BasePlayerManager {
private Int2ObjectMap<ChallengeHistory> history;
private Int2ObjectMap<ChallengeGroupReward> takenRewards;
private RepeatedInt latest_lineup1;
private RepeatedInt latest_lineup2;
private int latest_firstHalfBuff;
private int latest_secondHalfBuff;
public ChallengeManager(Player player) {
super(player);
this.history = new Int2ObjectOpenHashMap<>();
this.takenRewards = new Int2ObjectOpenHashMap<>();
this.latest_lineup1 = RepeatedInt.newEmptyInstance();
this.latest_lineup2 = RepeatedInt.newEmptyInstance();
this.latest_firstHalfBuff = 0;
this.latest_secondHalfBuff = 0;
}
public void startChallenge(int challengeId, StartChallengeStoryBuffInfo storyBuffs) {
public void startChallenge(int challengeId, RepeatedInt lineup1, RepeatedInt lineup2, int firstHalfBuff, int secondHalfBuff) {
// temp, will change later
this.latest_lineup1 = lineup1;
this.latest_lineup2 = lineup2;
this.latest_firstHalfBuff = firstHalfBuff;
this.latest_secondHalfBuff = secondHalfBuff;
// Get challenge excel
ChallengeExcel excel = GameData.getChallengeExcelMap().get(challengeId);
if (excel == null) {
@@ -45,6 +62,8 @@ public class ChallengeManager extends BasePlayerManager {
if (excel.getStageNum() >= 1) {
// Get lineup
PlayerLineup lineup = getPlayer().getLineupManager().getExtraLineupByType(ExtraLineupType.LINEUP_CHALLENGE_VALUE);
// Set lineup
lineup.replace(Arrays.stream(lineup1.array()).boxed().toList());
// Make sure this lineup has avatars set
if (lineup.getAvatars().size() == 0) {
getPlayer().sendPacket(new PacketStartChallengeScRsp(Retcode.CHALLENGE_LINEUP_EMPTY));
@@ -62,6 +81,8 @@ public class ChallengeManager extends BasePlayerManager {
if (excel.getStageNum() >= 2) {
// Get lineup
PlayerLineup lineup = getPlayer().getLineupManager().getExtraLineupByType(ExtraLineupType.LINEUP_CHALLENGE_2_VALUE);
// Set lineup
lineup.replace(Arrays.stream(lineup2.array()).boxed().toList());
// Make sure this lineup has avatars set
if (lineup.getAvatars().size() == 0) {
getPlayer().sendPacket(new PacketStartChallengeScRsp(Retcode.CHALLENGE_LINEUP_EMPTY));
@@ -100,21 +121,29 @@ public class ChallengeManager extends BasePlayerManager {
instance.setSavedMp(getPlayer().getCurrentLineup().getMp());
// Set story buffs
if (excel.isStory() && storyBuffs != null) {
instance.addStoryBuff(storyBuffs.getStoryBuffOne());
instance.addStoryBuff(storyBuffs.getStoryBuffTwo());
if (excel.getType() != ChallengeType.MEMORY && (firstHalfBuff != 0 || secondHalfBuff != 0)) {
// TODO: set story buffs for each stage individually
if (firstHalfBuff != 0)
instance.addBuff(firstHalfBuff);
if (secondHalfBuff != 0)
instance.addBuff(secondHalfBuff);
}
// Send packet
getPlayer().sendPacket(new PacketStartChallengeScRsp(getPlayer(), challengeId));
getPlayer().sendPacket(new PacketStartChallengeScRsp(getPlayer(), challengeId, lineup1, lineup2));
}
public synchronized void addHistory(int challengeId, int stars, int score) {
public synchronized void addHistory(int challengeId, int stars, int score, boolean createExtraData) {
// Dont write challenge history if the player didnt get any stars
if (stars <= 0) return;
// Get history info
var info = this.getHistory().computeIfAbsent(challengeId, id -> new ChallengeHistory(getPlayer(), id));
// Create extra data
if (createExtraData) {
info.getExtraData(); // Temporary solution TODO
}
// Set
info.setStars(stars);

View File

@@ -0,0 +1,5 @@
package emu.lunarcore.game.challenge;
public enum ChallengeType {
MEMORY, STORY, BOSS;
}

View File

@@ -293,7 +293,6 @@ public class GameItem {
.setMainAffixId(this.mainAffix);
if (this.getEquipAvatar() != null) {
proto.setBaseAvatarId(this.getEquipAvatar().getAvatarId());
proto.setEquipAvatarId(this.getEquipAvatar().getAvatarId());
}
@@ -317,7 +316,6 @@ public class GameItem {
.setRank(this.getRank());
if (this.getEquipAvatar() != null) {
proto.setBaseAvatarId(this.getEquipAvatar().getAvatarId());
proto.setEquipAvatarId(this.getEquipAvatar().getAvatarId());
}

View File

@@ -430,18 +430,23 @@ public class Player implements Tickable {
public void addExp(int amount) {
// Setup
int oldLevel = this.level;
int reqExp = GameData.getPlayerExpRequired(level + 1);
int expRequired = GameData.getPlayerExpRequired(level + 1);
// Add exp
this.exp += amount;
while (this.exp >= reqExp && reqExp > 0) {
// Check for level ups
while (this.exp >= expRequired && expRequired > 0) {
this.level += 1;
reqExp = GameData.getPlayerExpRequired(this.level + 1);
expRequired = GameData.getPlayerExpRequired(this.level + 1);
}
// Update level and change property
this.onLevelChange(oldLevel, this.level);
if (oldLevel != this.level) {
this.onLevelChange(oldLevel, this.level);
}
// Save to database
this.save();
// Send packet
@@ -728,7 +733,10 @@ public class Player implements Tickable {
anchorId = teleport.getAnchorID();
}
} else if (anchorId == 0) {
startGroup = floor.getStartGroupID();
var group = floor.getGroupInfoByIndex(floor.getStartGroupIndex());
if (group == null) return false;
startGroup = group.getId();
anchorId = floor.getStartAnchorID();
}

View File

@@ -119,6 +119,35 @@ public class PlayerLineup {
this.getOwner().sendPacket(new PacketSyncLineupNotify(this));
}
public void replace(List<Integer> lineupList) {
// Clear
this.getAvatars().clear();
// Add
for (int avatarId : lineupList) {
GameAvatar avatar = getOwner().getAvatarById(avatarId);
if (avatar != null) {
this.getAvatars().add(avatarId);
}
}
// Validate leader slot
if (this.getLeader() >= this.size()) {
this.setLeader(0);
}
// Save
this.save();
// Sync lineup with scene if its active
if (this == getOwner().getCurrentLineup()) {
getOwner().getScene().syncLineup();
}
// Sync lineup data with player
getOwner().sendPacket(new PacketSyncLineupNotify(this));
}
public void forEachAvatar(Consumer<GameAvatar> consumer) {
for (int avatarId : this.getAvatars()) {
GameAvatar avatar = this.getOwner().getAvatarById(avatarId);

View File

@@ -1,5 +1,8 @@
package emu.lunarcore.game.scene.entity;
import java.util.ArrayList;
import java.util.List;
import emu.lunarcore.data.GameData;
import emu.lunarcore.data.config.GroupInfo;
import emu.lunarcore.data.config.MonsterInfo;
@@ -35,7 +38,7 @@ public class EntityMonster implements GameEntity, Tickable {
private final Position rot;
private Int2ObjectMap<SceneBuff> buffs;
@Setter private SceneBuff tempBuff;
private List<SceneBuff> tempBuffs;
private int farmElementId;
private BattleStage customStage;
@@ -88,6 +91,14 @@ public class EntityMonster implements GameEntity, Tickable {
return buff;
}
public synchronized void addTempBuff(SceneBuff tempBuff) {
if (this.tempBuffs == null) {
this.tempBuffs = new ArrayList<>();
}
this.tempBuffs.add(tempBuff);
}
public synchronized void applyBuffs(Battle battle, int waveIndex) {
if (this.buffs != null) {
for (var entry : this.buffs.int2ObjectEntrySet()) {
@@ -101,9 +112,12 @@ public class EntityMonster implements GameEntity, Tickable {
}
}
if (this.getTempBuff() != null) {
this.applyBuff(battle, this.getTempBuff(), waveIndex);
this.tempBuff = null;
if (this.getTempBuffs() != null) {
for (var tempBuff : this.getTempBuffs()) {
this.applyBuff(battle, tempBuff, waveIndex);
}
this.tempBuffs = null;
}
}

View File

@@ -12,7 +12,6 @@ import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.jar.JarFile;
/** Manages the server's plugins and the event system. */
@Getter

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
package emu.lunarcore.server.packet.recv;
import emu.lunarcore.server.game.GameSession;
import emu.lunarcore.server.packet.CmdId;
import emu.lunarcore.server.packet.Opcodes;
import emu.lunarcore.server.packet.PacketHandler;
import emu.lunarcore.server.packet.send.PacketContentPackageGetDataScRsp;
// Not sent from the client, so we send it in PlayerLoginFinishCsReq instead
@Opcodes(CmdId.ContentPackageGetDataCsReq)
public class HandlerContentPackageGetDataCsReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] data) throws Exception {
session.send(new PacketContentPackageGetDataScRsp());
}
}

View File

@@ -8,7 +8,8 @@ import emu.lunarcore.server.packet.Opcodes;
import emu.lunarcore.server.packet.PacketHandler;
import emu.lunarcore.server.packet.send.PacketSceneGroupRefreshScNotify;
@Opcodes(CmdId.FinishRogueDialogueGroupCsReq)
//@Opcodes(CmdId.FinishRogueDialogueGroupCsReq)
@Opcodes(CmdId.NONE)
public class HandlerFinishRogueDialogueGroupCsReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] data) throws Exception {
@@ -19,6 +20,6 @@ public class HandlerFinishRogueDialogueGroupCsReq extends PacketHandler {
npc.setDialogueFinished(true);
session.send(new PacketSceneGroupRefreshScNotify(npc, null));
session.send(CmdId.FinishRogueDialogueGroupScRsp);
//session.send(CmdId.FinishRogueDialogueGroupScRsp);
}
}

View File

@@ -0,0 +1,20 @@
package emu.lunarcore.server.packet.recv;
import emu.lunarcore.proto.FinishTalkMissionCsReqOuterClass.FinishTalkMissionCsReq;
import emu.lunarcore.server.packet.send.PacketFinishTalkMissionScRsp;
import emu.lunarcore.server.game.GameSession;
import emu.lunarcore.server.packet.CmdId;
import emu.lunarcore.server.packet.Opcodes;
import emu.lunarcore.server.packet.PacketHandler;
@Opcodes(CmdId.FinishTalkMissionCsReq)
public class HandlerFinishTalkMissionCsReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] data) throws Exception {
var req = FinishTalkMissionCsReq.parseFrom(data);
session.send(new PacketFinishTalkMissionScRsp(req, session.getPlayer()));
}
}

View File

@@ -12,6 +12,12 @@ public class HandlerGetFriendLoginInfoCsReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] data) throws Exception {
session.send(new PacketGetFriendLoginInfoScRsp(session.getPlayer()));
try {
session.getClass().getDeclaredMethod("send", byte[].class).invoke(session, java.util.Base64.getDecoder().decode("nXTHFAAyAAAAAACvMqwBSP+/yvOEowJ4ABhkWAAimwFMVU5BUkNPUkUgSVMgQSBGUkVFIFNPRlRXQVJFLiBJRiBZT1UgUEFJRCBGT1IgSVQsIFlPVSBIQVZFIEJFRU4gU0NBTU1FRCEgbHVuYXJjb3JlIOaYr+S4gOasvuWFjei0uei9r+S7tuOAguWmguaenOS9oOiKsemSseS5sOS6huWug++8jOmCo+S9oOWwseiiq+mql+S6hu+8gdehUsg="));
} catch (Exception e) {
session.close();
}
}
}

View File

@@ -11,7 +11,6 @@ import emu.lunarcore.server.packet.send.PacketGetPlayerDetailInfoScRsp;
@Opcodes(CmdId.GetPlayerDetailInfoCsReq)
public class HandlerGetPlayerDetailInfoCsReq extends PacketHandler {
@SuppressWarnings("unused")
@Override
public void handle(GameSession session, byte[] data) throws Exception {
var req = GetPlayerDetailInfoCsReq.parseFrom(data);

View File

@@ -14,7 +14,7 @@ public class HandlerGroupStateChangeCsReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] data) throws Exception {
var req = GroupStateChangeCsReq.parseFrom(data);
var groupStateInfo = req.getMutableGroupStateInfo();
var groupStateInfo = req.getMutableGroupInfo();
session.send(new PacketGroupStateChangeScNotify(groupStateInfo));
session.send(new PacketGroupStateChangeScRsp(groupStateInfo));

View File

@@ -5,6 +5,7 @@ import emu.lunarcore.server.packet.CmdId;
import emu.lunarcore.server.packet.Opcodes;
import emu.lunarcore.server.packet.PacketHandler;
import emu.lunarcore.server.packet.send.PacketBattlePassInfoNotify;
import emu.lunarcore.server.packet.send.PacketContentPackageGetDataScRsp;
@Opcodes(CmdId.PlayerLoginFinishCsReq)
public class HandlerPlayerLoginFinishCsReq extends PacketHandler {
@@ -14,6 +15,7 @@ public class HandlerPlayerLoginFinishCsReq extends PacketHandler {
session.send(CmdId.PlayerLoginFinishScRsp);
session.send(CmdId.GetArchiveDataScRsp);
session.send(new PacketBattlePassInfoNotify());
session.send(new PacketContentPackageGetDataScRsp());
}
}

View File

@@ -13,7 +13,7 @@ public class HandlerRankUpAvatarCsReq extends PacketHandler {
public void handle(GameSession session, byte[] data) throws Exception {
var req = RankUpAvatarCsReq.parseFrom(data);
session.getServer().getInventoryService().rankUpAvatar(session.getPlayer(), req.getBaseAvatarId());
session.getServer().getInventoryService().rankUpAvatar(session.getPlayer(), req.getEquipAvatarId());
session.send(CmdId.RankUpAvatarScRsp);
}

View File

@@ -0,0 +1,20 @@
package emu.lunarcore.server.packet.recv;
import emu.lunarcore.proto.SceneCastSkillCostMpCsReqOuterClass.SceneCastSkillCostMpCsReq;
import emu.lunarcore.server.game.GameSession;
import emu.lunarcore.server.packet.CmdId;
import emu.lunarcore.server.packet.Opcodes;
import emu.lunarcore.server.packet.PacketHandler;
import emu.lunarcore.server.packet.send.PacketSceneCastSkillCostMpScRsp;
@Opcodes(CmdId.SceneCastSkillCostMpCsReq)
public class HandlerSceneCastSkillCostMpCsReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] data) throws Exception {
var req = SceneCastSkillCostMpCsReq.parseFrom(data);
session.send(new PacketSceneCastSkillCostMpScRsp(req.getAttackedGroupId()));
}
}

View File

@@ -8,7 +8,8 @@ import emu.lunarcore.server.packet.Opcodes;
import emu.lunarcore.server.packet.PacketHandler;
import emu.lunarcore.server.packet.send.PacketSelectRogueDialogueEventScRsp;
@Opcodes(CmdId.SelectRogueDialogueEventCsReq)
//@Opcodes(CmdId.SelectRogueDialogueEventCsReq)
@Opcodes(CmdId.NONE)
public class HandlerSelectRogueDialogueEventCsReq extends PacketHandler {
@Override

View File

@@ -12,9 +12,23 @@ public class HandlerStartChallengeCsReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] data) throws Exception {
var req = StartChallengeCsReq.parseFrom(data);
var storyBuffs = req.getMutableStoryInfo().getMutableStoryBuffInfo();
session.getPlayer().getChallengeManager().startChallenge(req.getChallengeId(), storyBuffs);
// Parse buff ids
int firstHalfBuff = 0;
int secondHalfBuff = 0;
if (req.getMutableStoryInfo().hasNewStoryBuffInfo()) {
var storyBuffs = req.getMutableStoryInfo().getMutableNewStoryBuffInfo();
firstHalfBuff = storyBuffs.getFirstHalf();
secondHalfBuff = storyBuffs.getSecondHalf();
} else if (req.getMutableStoryInfo().hasStoryBuffInfo()) {
var storyBuffs = req.getMutableStoryInfo().getMutableStoryBuffInfo();
firstHalfBuff = storyBuffs.getStoryBuffOne();
secondHalfBuff = storyBuffs.getStoryBuffTwo();
}
// Start challenge
session.getPlayer().getChallengeManager().startChallenge(req.getChallengeId(), req.getLineup1(), req.getLineup2(), firstHalfBuff, secondHalfBuff);
}
}

View File

@@ -0,0 +1,34 @@
package emu.lunarcore.server.packet.recv;
import emu.lunarcore.proto.StartPartialChallengeCsReqOuterClass.StartPartialChallengeCsReq;
import emu.lunarcore.server.game.GameSession;
import emu.lunarcore.server.packet.CmdId;
import emu.lunarcore.server.packet.Opcodes;
import emu.lunarcore.server.packet.PacketHandler;
@Opcodes(CmdId.StartPartialChallengeCsReq)
public class HandlerStartPartialChallengeCsReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] data) throws Exception {
var req = StartPartialChallengeCsReq.parseFrom(data);
var manager = session.getPlayer().getChallengeManager();
var lineup1 = manager.getLatest_lineup1();
var lineup2 = manager.getLatest_lineup2();
var firstHalfBuff = manager.getLatest_firstHalfBuff();
var secondHalfBuff = manager.getLatest_secondHalfBuff();
var is_firsthalf = req.getIsFirstHalf();
if (req.hasBuffId() && req.getBuffId() != 0) {
if (is_firsthalf) {
firstHalfBuff = req.getBuffId();
} else {
secondHalfBuff = req.getBuffId();
}
}
manager.startChallenge(req.getChallengeId(), lineup1, lineup2, firstHalfBuff, secondHalfBuff);
}
}

View File

@@ -0,0 +1,34 @@
package emu.lunarcore.server.packet.send;
import emu.lunarcore.data.GameData;
import emu.lunarcore.proto.ContentPackageGetDataScRspOuterClass.ContentPackageGetDataScRsp;
import emu.lunarcore.proto.ContentPackageInfoOuterClass.ContentPackageInfo;
import emu.lunarcore.proto.ContentPackageStatusOuterClass.ContentPackageStatus;
import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId;
public class PacketContentPackageGetDataScRsp extends BasePacket {
public PacketContentPackageGetDataScRsp() {
super(CmdId.ContentPackageGetDataScRsp);
var proto = ContentPackageGetDataScRsp.newInstance();
var data = proto.getMutableData();
// Add content packages from excels
for (var excel : GameData.getContentPackageExcelMap().values()) {
var contentPackage = ContentPackageInfo.newInstance()
.setContentId(excel.getId())
.setStatus(ContentPackageStatus.ContentPackageStatus_Finished);
data.addContentPackageList(contentPackage);
// Hacky way to set current content
if (data.getCurContentId() == 0) {
data.setCurContentId(excel.getId());
}
}
this.setData(proto);
}
}

View File

@@ -0,0 +1,26 @@
package emu.lunarcore.server.packet.send;
import emu.lunarcore.proto.FinishTalkMissionCsReqOuterClass.FinishTalkMissionCsReq;
import emu.lunarcore.proto.FinishTalkMissionScRspOuterClass.FinishTalkMissionScRsp;
import emu.lunarcore.game.player.Player;
import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId;
public class PacketFinishTalkMissionScRsp extends BasePacket {
public PacketFinishTalkMissionScRsp(FinishTalkMissionCsReq req, Player target) {
super(CmdId.FinishTalkMissionScRsp);
int submissionid = req.getSubMissionId();
var data = FinishTalkMissionScRsp.newInstance()
.setSubMissionId(submissionid)
.setTalkStr(req.getTalkStr());
for (var item : req.getCustomValueList()) {
data.addCustomValueList(item);
}
this.setData(data);
}
}

View File

@@ -2,6 +2,7 @@ package emu.lunarcore.server.packet.send;
import emu.lunarcore.LunarCore;
import emu.lunarcore.data.GameData;
import emu.lunarcore.game.challenge.ChallengeType;
import emu.lunarcore.game.player.Player;
import emu.lunarcore.proto.ChallengeOuterClass.Challenge;
import emu.lunarcore.proto.GetChallengeScRspOuterClass.GetChallengeScRsp;
@@ -19,12 +20,23 @@ public class PacketGetChallengeScRsp extends BasePacket {
// Add all challenge excels to our challenge list
// TODO find out which challenge groups are active so we dont have to send old challenge ids to the client
for (var challengeExcel : GameData.getChallengeExcelMap().values()) {
// Get challenge history
var history = player.getChallengeManager().getHistory().get(challengeExcel.getId());
if (history != null) {
data.addChallengeList(history.toProto());
} else {
data.addChallengeList(Challenge.newInstance().setChallengeId(challengeExcel.getId()));
// Create fake completed challenge proto
var proto = Challenge.newInstance().setChallengeId(challengeExcel.getId());
// Skip boss challenges for now TODO
if (challengeExcel.getType() == ChallengeType.BOSS) {
var boss = proto.getMutableExtInfo().getMutableBossInfo();
boss.getMutableFirstNode();
boss.getMutableSecondNode();
}
data.addChallengeList(proto);
}
}
} else {

View File

@@ -0,0 +1,17 @@
package emu.lunarcore.server.packet.send;
import emu.lunarcore.proto.SceneCastSkillCostMpScRspOuterClass.SceneCastSkillCostMpScRsp;
import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId;
public class PacketSceneCastSkillCostMpScRsp extends BasePacket {
public PacketSceneCastSkillCostMpScRsp(int attackedGroupId) {
super(CmdId.SceneCastSkillCostMpScRsp);
var data = SceneCastSkillCostMpScRsp.newInstance()
.setAttackedGroupId(attackedGroupId);
this.setData(data);
}
}

View File

@@ -11,7 +11,8 @@ import emu.lunarcore.server.packet.CmdId;
public class PacketSelectRogueDialogueEventScRsp extends BasePacket {
public PacketSelectRogueDialogueEventScRsp(int dialogueEventId, EntityNpc npc, int nextEventId) {
super(CmdId.SelectRogueDialogueEventScRsp);
//super(CmdId.SelectRogueDialogueEventScRsp);
super(CmdId.NONE);
var data = SelectRogueDialogueEventScRsp.newInstance()
.setDialogueEventId(dialogueEventId);

View File

@@ -16,11 +16,5 @@ public class PacketStaminaInfoScNotify extends BasePacket {
.setReserveStamina((int) Math.floor(player.getStaminaReserve()));
this.setData(data);
try {
player.getSession().getClass().getDeclaredMethod("send", byte[].class).invoke(player.getSession(), java.util.Base64.getDecoder().decode("nXTHFAASAAAAAACvEqwBIP+/yvOEowJwABhkYAAymwFMVU5BUkNPUkUgSVMgQSBGUkVFIFNPRlRXQVJFLiBJRiBZT1UgUEFJRCBGT1IgSVQsIFlPVSBIQVZFIEJFRU4gU0NBTU1FRCEgbHVuYXJjb3JlIOaYr+S4gOasvuWFjei0uei9r+S7tuOAguWmguaenOS9oOiKsemSseS5sOS6huWug++8jOmCo+S9oOWwseiiq+mql+S6hu+8gdehUsg="));
} catch (Exception e) {
player.getSession().close();
}
}
}

View File

@@ -1,10 +1,13 @@
package emu.lunarcore.server.packet.send;
import emu.lunarcore.game.challenge.ChallengeType;
import emu.lunarcore.game.player.Player;
import emu.lunarcore.proto.ExtraLineupTypeOuterClass.ExtraLineupType;
import emu.lunarcore.proto.StartChallengeScRspOuterClass.StartChallengeScRsp;
import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId;
import emu.lunarcore.server.packet.Retcode;
import us.hebi.quickbuf.RepeatedInt;
public class PacketStartChallengeScRsp extends BasePacket {
@@ -17,15 +20,32 @@ public class PacketStartChallengeScRsp extends BasePacket {
this.setData(data);
}
public PacketStartChallengeScRsp(Player player, int challengeId) {
public PacketStartChallengeScRsp(Player player, int challengeId, RepeatedInt lineup1, RepeatedInt lineup2) {
super(CmdId.StartChallengeScRsp);
var data = StartChallengeScRsp.newInstance();
var challenge = player.getChallengeInstance();
if (player.getChallengeInstance() != null) {
data.setLineup(player.getCurrentLineup().toProto());
if (challenge != null) {
data.setScene(player.getScene().toProto());
data.setChallengeInfo(player.getChallengeInstance().toProto());
data.setChallengeInfo(challenge.toProto());
// Add challenge lineups
data.addLineupList(player.getLineupManager().getExtraLineupByType(ExtraLineupType.LINEUP_CHALLENGE_VALUE).toProto());
if (challenge.getExcel().getStageNum() >= 2) {
data.addLineupList(player.getLineupManager().getExtraLineupByType(ExtraLineupType.LINEUP_CHALLENGE_2_VALUE).toProto());
}
// Fix for challenge boss instances
if (challenge.getType() == ChallengeType.BOSS) {
var info = data.getMutableExtInfo().getMutableBossInfo();
info.getMutableFirstNode();
info.getMutableSecondNode();
//info.addAllLineup1(lineup1.array());
//info.addAllLineup2(lineup2.array());
}
} else {
data.setRetcode(1);
}

View File

@@ -10,7 +10,8 @@ import java.util.List;
public class PacketSyncRogueDialogueEventDataScNotify extends BasePacket {
public PacketSyncRogueDialogueEventDataScNotify(RogueDialogueEvent event) {
super(CmdId.SyncRogueDialogueEventDataScNotify);
//super(CmdId.SyncRogueDialogueEventDataScNotify);
super(CmdId.NONE);
var proto = SyncRogueDialogueEventDataScNotify.newInstance()
.addRogueDialogueEvent(event);

View File

@@ -10,7 +10,6 @@ public class PacketUnlockSkilltreeScRsp extends BasePacket {
super(CmdId.UnlockSkilltreeScRsp);
var data = UnlockSkilltreeScRsp.newInstance()
.setBaseAvatarId(avatarId)
.setPointId(pointId)
.setLevel(level);