diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index 3238de22e..8f1d2ceb6 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -453,9 +453,18 @@ public class Player { } public boolean setLevel(int level) { + if (this.getLevel() == level) { + return true; + } + if (this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, level)) { + // Update world level and profile. this.updateWorldLevel(); this.updateProfile(); + + // Handle OpenState unlocks from level-up. + this.getOpenStateManager().onPlayerLevelUp(); + return true; } return false; @@ -538,7 +547,6 @@ public class Player { // Directly give player exp public void addExpDirectly(int gain) { - boolean hasLeveledUp = false; int level = getLevel(); int exp = getExp(); int reqExp = getExpRequired(level); @@ -549,10 +557,8 @@ public class Player { exp -= reqExp; level += 1; reqExp = getExpRequired(level); - hasLeveledUp = true; - } - if (hasLeveledUp) { + // Set level each time to allow level-up specific logic to run. this.setLevel(level); } diff --git a/src/main/java/emu/grasscutter/game/player/PlayerOpenStateManager.java b/src/main/java/emu/grasscutter/game/player/PlayerOpenStateManager.java index 562c81ec9..ae569106c 100644 --- a/src/main/java/emu/grasscutter/game/player/PlayerOpenStateManager.java +++ b/src/main/java/emu/grasscutter/game/player/PlayerOpenStateManager.java @@ -32,173 +32,9 @@ public class PlayerOpenStateManager { // For development. Remove entry when properly implemented // TODO - Set as boolean in OpenState - public static final Set DEV_OPEN_STATES = Set.of( - OPEN_STATE_PAIMON, - OPEN_STATE_PAIMON_NAVIGATION, - OPEN_STATE_AVATAR_PROMOTE, - OPEN_STATE_AVATAR_TALENT, - OPEN_STATE_WEAPON_PROMOTE, - OPEN_STATE_WEAPON_AWAKEN, - OPEN_STATE_QUEST_REMIND, - OPEN_STATE_GAME_GUIDE, - OPEN_STATE_COOK, - OPEN_STATE_WEAPON_UPGRADE, - OPEN_STATE_RELIQUARY_UPGRADE, - OPEN_STATE_RELIQUARY_PROMOTE, - OPEN_STATE_WEAPON_PROMOTE_GUIDE, - OPEN_STATE_WEAPON_CHANGE_GUIDE, - OPEN_STATE_PLAYER_LVUP_GUIDE, - OPEN_STATE_FRESHMAN_GUIDE, - OPEN_STATE_SKIP_FRESHMAN_GUIDE, - OPEN_STATE_GUIDE_MOVE_CAMERA, - OPEN_STATE_GUIDE_SCALE_CAMERA, - OPEN_STATE_GUIDE_KEYBOARD, - OPEN_STATE_GUIDE_MOVE, - OPEN_STATE_GUIDE_JUMP, - OPEN_STATE_GUIDE_SPRINT, - OPEN_STATE_GUIDE_MAP, - OPEN_STATE_GUIDE_ATTACK, - OPEN_STATE_GUIDE_FLY, - OPEN_STATE_GUIDE_TALENT, - OPEN_STATE_GUIDE_RELIC, - OPEN_STATE_GUIDE_RELIC_PROM, - OPEN_STATE_COMBINE, - OPEN_STATE_GACHA, - OPEN_STATE_GUIDE_GACHA, - OPEN_STATE_GUIDE_TEAM, - OPEN_STATE_GUIDE_PROUD, - OPEN_STATE_GUIDE_AVATAR_PROMOTE, - OPEN_STATE_GUIDE_ADVENTURE_CARD, - OPEN_STATE_FORGE, - OPEN_STATE_GUIDE_BAG, - OPEN_STATE_EXPEDITION, - OPEN_STATE_GUIDE_ADVENTURE_DAILYTASK, - OPEN_STATE_GUIDE_ADVENTURE_DUNGEON, - OPEN_STATE_TOWER, - OPEN_STATE_WORLD_STAMINA, - OPEN_STATE_TOWER_FIRST_ENTER, - OPEN_STATE_RESIN, - OPEN_STATE_LIMIT_REGION_FRESHMEAT, - OPEN_STATE_MULTIPLAYER, - OPEN_STATE_GUIDE_MOUSEPC, - OPEN_STATE_GUIDE_MULTIPLAYER, - OPEN_STATE_GUIDE_DUNGEONREWARD, - OPEN_STATE_GUIDE_BLOSSOM, - OPEN_STATE_AVATAR_FASHION, - OPEN_STATE_PHOTOGRAPH, - OPEN_STATE_GUIDE_KSLQUEST, - OPEN_STATE_PERSONAL_LINE, - OPEN_STATE_GUIDE_PERSONAL_LINE, - OPEN_STATE_GUIDE_APPEARANCE, - OPEN_STATE_GUIDE_PROCESS, - OPEN_STATE_GUIDE_PERSONAL_LINE_KEY, - OPEN_STATE_GUIDE_WIDGET, - OPEN_STATE_GUIDE_ACTIVITY_SKILL_ASTER, - OPEN_STATE_GUIDE_COLDCLIMATE, - OPEN_STATE_DERIVATIVE_MALL, - OPEN_STATE_GUIDE_EXITMULTIPLAYER, - OPEN_STATE_GUIDE_THEATREMACHANICUS_BUILD, - OPEN_STATE_GUIDE_THEATREMACHANICUS_REBUILD, - OPEN_STATE_GUIDE_THEATREMACHANICUS_CARD, - OPEN_STATE_GUIDE_THEATREMACHANICUS_MONSTER, - OPEN_STATE_GUIDE_THEATREMACHANICUS_MISSION_CHECK, - OPEN_STATE_GUIDE_THEATREMACHANICUS_BUILD_SELECT, - OPEN_STATE_GUIDE_THEATREMACHANICUS_CHALLENGE_START, - OPEN_STATE_GUIDE_CONVERT, - OPEN_STATE_GUIDE_THEATREMACHANICUS_MULTIPLAYER, - OPEN_STATE_GUIDE_COOP_TASK, - OPEN_STATE_GUIDE_HOMEWORLD_ADEPTIABODE, - OPEN_STATE_GUIDE_HOMEWORLD_DEPLOY, - OPEN_STATE_GUIDE_CHANNELLERSLAB_EQUIP, - OPEN_STATE_GUIDE_CHANNELLERSLAB_MP_SOLUTION, - OPEN_STATE_GUIDE_CHANNELLERSLAB_POWER, - OPEN_STATE_GUIDE_HIDEANDSEEK_SKILL, - OPEN_STATE_GUIDE_HOMEWORLD_MAPLIST, - OPEN_STATE_GUIDE_RELICRESOLVE, - OPEN_STATE_GUIDE_GGUIDE, - OPEN_STATE_GUIDE_GGUIDE_HINT, - OPEN_STATE_GUIDE_QUICK_TEAMMEMBERCHANGE, - OPEN_STATE_CITY_REPUATION_MENGDE, - OPEN_STATE_CITY_REPUATION_LIYUE, - OPEN_STATE_CITY_REPUATION_UI_HINT, - OPEN_STATE_CITY_REPUATION_INAZUMA, - OPEN_STATE_SHOP_TYPE_MALL, - OPEN_STATE_SHOP_TYPE_RECOMMANDED, - OPEN_STATE_SHOP_TYPE_GENESISCRYSTAL, - OPEN_STATE_SHOP_TYPE_GIFTPACKAGE, - OPEN_STATE_SHOP_TYPE_PAIMON, - OPEN_STATE_SHOP_TYPE_CITY, - OPEN_STATE_SHOP_TYPE_BLACKSMITH, - OPEN_STATE_SHOP_TYPE_GROCERY, - OPEN_STATE_SHOP_TYPE_FOOD, - OPEN_STATE_SHOP_TYPE_SEA_LAMP, - OPEN_STATE_SHOP_TYPE_VIRTUAL_SHOP, - OPEN_STATE_SHOP_TYPE_LIYUE_GROCERY, - OPEN_STATE_SHOP_TYPE_LIYUE_SOUVENIR, - OPEN_STATE_SHOP_TYPE_LIYUE_RESTAURANT, - OPEN_STATE_SHOP_TYPE_INAZUMA_SOUVENIR, - OPEN_STATE_SHOP_TYPE_NPC_TOMOKI, - OPEN_ADVENTURE_MANUAL, - OPEN_ADVENTURE_MANUAL_CITY_MENGDE, - OPEN_ADVENTURE_MANUAL_CITY_LIYUE, - OPEN_ADVENTURE_MANUAL_MONSTER, - OPEN_ADVENTURE_MANUAL_BOSS_DUNGEON, - OPEN_STATE_ACTIVITY_SEALAMP, - OPEN_STATE_ACTIVITY_SEALAMP_TAB2, - OPEN_STATE_ACTIVITY_SEALAMP_TAB3, - OPEN_STATE_BATTLE_PASS, - OPEN_STATE_BATTLE_PASS_ENTRY, - OPEN_STATE_ACTIVITY_CRUCIBLE, - OPEN_STATE_ACTIVITY_NEWBEEBOUNS_OPEN, - OPEN_STATE_ACTIVITY_NEWBEEBOUNS_CLOSE, - OPEN_STATE_ACTIVITY_ENTRY_OPEN, - OPEN_STATE_MENGDE_INFUSEDCRYSTAL, - OPEN_STATE_LIYUE_INFUSEDCRYSTAL, - OPEN_STATE_SNOW_MOUNTAIN_ELDER_TREE, - OPEN_STATE_MIRACLE_RING, - OPEN_STATE_COOP_LINE, - OPEN_STATE_INAZUMA_INFUSEDCRYSTAL, - OPEN_STATE_FISH, - OPEN_STATE_GUIDE_SUMO_TEAM_SKILL, - OPEN_STATE_GUIDE_FISH_RECIPE, - OPEN_STATE_HOME, - OPEN_STATE_ACTIVITY_HOMEWORLD, - OPEN_STATE_ADEPTIABODE, - OPEN_STATE_HOME_AVATAR, - OPEN_STATE_HOME_EDIT, - OPEN_STATE_HOME_EDIT_TIPS, - OPEN_STATE_RELIQUARY_DECOMPOSE, - OPEN_STATE_ACTIVITY_H5, - OPEN_STATE_ORAIONOKAMI, - OPEN_STATE_GUIDE_CHESS_MISSION_CHECK, - OPEN_STATE_GUIDE_CHESS_BUILD, - OPEN_STATE_GUIDE_CHESS_WIND_TOWER_CIRCLE, - OPEN_STATE_GUIDE_CHESS_CARD_SELECT, - OPEN_STATE_INAZUMA_MAINQUEST_FINISHED, - OPEN_STATE_PAIMON_LVINFO, - OPEN_STATE_TELEPORT_HUD, - OPEN_STATE_GUIDE_MAP_UNLOCK, - OPEN_STATE_GUIDE_PAIMON_LVINFO, - OPEN_STATE_GUIDE_AMBORTRANSPORT, - OPEN_STATE_GUIDE_FLY_SECOND, - OPEN_STATE_GUIDE_KAEYA_CLUE, - OPEN_STATE_CAPTURE_CODEX, - OPEN_STATE_ACTIVITY_FISH_OPEN, - OPEN_STATE_ACTIVITY_FISH_CLOSE, - OPEN_STATE_GUIDE_ROGUE_MAP, - OPEN_STATE_GUIDE_ROGUE_RUNE, - OPEN_STATE_GUIDE_BARTENDER_FORMULA, - OPEN_STATE_GUIDE_BARTENDER_MIX, - OPEN_STATE_GUIDE_BARTENDER_CUP, - OPEN_STATE_GUIDE_MAIL_FAVORITES, - OPEN_STATE_GUIDE_POTION_CONFIGURE, - OPEN_STATE_GUIDE_LANV2_FIREWORK, - OPEN_STATE_LOADINGTIPS_ENKANOMIYA, - OPEN_STATE_MICHIAE_CASKET, - OPEN_STATE_MAIL_COLLECT_UNLOCK_RED_POINT, - OPEN_STATE_LUMEN_STONE, - OPEN_STATE_GUIDE_CRYSTALLINK_BUFF - ); + public static final Set DEV_OPEN_STATES = Stream.of(OpenState.values()) + .filter(s -> s != OpenState.OPEN_STATE_NONE && s.getUnlockLevel() <= 1) + .collect(Collectors.toSet()); public PlayerOpenStateManager(Player player) { this.player = player; @@ -236,4 +72,10 @@ public class PlayerOpenStateManager { public void onPlayerLogin() { player.getSession().send(new PacketOpenStateUpdateNotify(this)); } + + public void onPlayerLevelUp() { + Stream.of(OpenState.values()) + .filter(s -> s.getUnlockLevel() == this.player.getLevel()) + .forEach(s -> this.setOpenState(s, 1)); + } } \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/props/OpenState.java b/src/main/java/emu/grasscutter/game/props/OpenState.java index 560edf5f2..536c57d45 100644 --- a/src/main/java/emu/grasscutter/game/props/OpenState.java +++ b/src/main/java/emu/grasscutter/game/props/OpenState.java @@ -38,16 +38,16 @@ public enum OpenState { OPEN_STATE_GUIDE_TALENT (27), OPEN_STATE_GUIDE_RELIC (28), OPEN_STATE_GUIDE_RELIC_PROM (29), - OPEN_STATE_COMBINE (30), + OPEN_STATE_COMBINE (30, 2), OPEN_STATE_GACHA (31), OPEN_STATE_GUIDE_GACHA (32), OPEN_STATE_GUIDE_TEAM (33), OPEN_STATE_GUIDE_PROUD (34), OPEN_STATE_GUIDE_AVATAR_PROMOTE (35), OPEN_STATE_GUIDE_ADVENTURE_CARD (36), - OPEN_STATE_FORGE (37), + OPEN_STATE_FORGE (37, 2), OPEN_STATE_GUIDE_BAG (38), - OPEN_STATE_EXPEDITION (39), + OPEN_STATE_EXPEDITION (39, 14), OPEN_STATE_GUIDE_ADVENTURE_DAILYTASK (40), OPEN_STATE_GUIDE_ADVENTURE_DUNGEON (41), OPEN_STATE_TOWER (42), @@ -56,15 +56,15 @@ public enum OpenState { OPEN_STATE_RESIN (45), OPEN_STATE_LIMIT_REGION_FRESHMEAT (47), OPEN_STATE_LIMIT_REGION_GLOBAL (48), - OPEN_STATE_MULTIPLAYER (49), + OPEN_STATE_MULTIPLAYER (49, 16), OPEN_STATE_GUIDE_MOUSEPC (50), OPEN_STATE_GUIDE_MULTIPLAYER (51), OPEN_STATE_GUIDE_DUNGEONREWARD (52), - OPEN_STATE_GUIDE_BLOSSOM (53), + OPEN_STATE_GUIDE_BLOSSOM (53, 8), OPEN_STATE_AVATAR_FASHION (54), OPEN_STATE_PHOTOGRAPH (55), OPEN_STATE_GUIDE_KSLQUEST (56), - OPEN_STATE_PERSONAL_LINE (57), + OPEN_STATE_PERSONAL_LINE (57, 26), OPEN_STATE_GUIDE_PERSONAL_LINE (58), OPEN_STATE_GUIDE_APPEARANCE (59), OPEN_STATE_GUIDE_PROCESS (60), @@ -102,35 +102,35 @@ public enum OpenState { OPEN_STATE_GGUIDE_MAINPAGE_ENTRY_DISAPPEAR (92), OPEN_STATE_CITY_REPUATION_MENGDE (800), OPEN_STATE_CITY_REPUATION_LIYUE (801), - OPEN_STATE_CITY_REPUATION_UI_HINT (802), + OPEN_STATE_CITY_REPUATION_UI_HINT (802, 25), OPEN_STATE_CITY_REPUATION_INAZUMA (803), OPEN_STATE_SHOP_TYPE_MALL (900), - OPEN_STATE_SHOP_TYPE_RECOMMANDED (901), - OPEN_STATE_SHOP_TYPE_GENESISCRYSTAL (902), - OPEN_STATE_SHOP_TYPE_GIFTPACKAGE (903), + OPEN_STATE_SHOP_TYPE_RECOMMANDED (901, 1), + OPEN_STATE_SHOP_TYPE_GENESISCRYSTAL (902, 1), + OPEN_STATE_SHOP_TYPE_GIFTPACKAGE (903, 1), OPEN_STATE_SHOP_TYPE_PAIMON (1001), OPEN_STATE_SHOP_TYPE_CITY (1002), OPEN_STATE_SHOP_TYPE_BLACKSMITH (1003), - OPEN_STATE_SHOP_TYPE_GROCERY (1004), - OPEN_STATE_SHOP_TYPE_FOOD (1005), - OPEN_STATE_SHOP_TYPE_SEA_LAMP (1006), + OPEN_STATE_SHOP_TYPE_GROCERY (1004, 5), + OPEN_STATE_SHOP_TYPE_FOOD (1005, 5), + OPEN_STATE_SHOP_TYPE_SEA_LAMP (1006, 13), OPEN_STATE_SHOP_TYPE_VIRTUAL_SHOP (1007), - OPEN_STATE_SHOP_TYPE_LIYUE_GROCERY (1008), + OPEN_STATE_SHOP_TYPE_LIYUE_GROCERY (1008, 5), OPEN_STATE_SHOP_TYPE_LIYUE_SOUVENIR (1009), - OPEN_STATE_SHOP_TYPE_LIYUE_RESTAURANT (1010), + OPEN_STATE_SHOP_TYPE_LIYUE_RESTAURANT (1010, 5), OPEN_STATE_SHOP_TYPE_INAZUMA_SOUVENIR (1011), OPEN_STATE_SHOP_TYPE_NPC_TOMOKI (1012), OPEN_STATE_SHOP_TYPE_INAZUMA_SOUVENIR_BLACK_BAR (1013), OPEN_ADVENTURE_MANUAL (1100), OPEN_ADVENTURE_MANUAL_CITY_MENGDE (1101), OPEN_ADVENTURE_MANUAL_CITY_LIYUE (1102), - OPEN_ADVENTURE_MANUAL_MONSTER (1103), + OPEN_ADVENTURE_MANUAL_MONSTER (1103, 8), OPEN_ADVENTURE_MANUAL_BOSS_DUNGEON (1104), OPEN_STATE_ACTIVITY_SEALAMP (1200), OPEN_STATE_ACTIVITY_SEALAMP_TAB2 (1201), OPEN_STATE_ACTIVITY_SEALAMP_TAB3 (1202), - OPEN_STATE_BATTLE_PASS (1300), - OPEN_STATE_BATTLE_PASS_ENTRY (1301), + OPEN_STATE_BATTLE_PASS (1300, 1), + OPEN_STATE_BATTLE_PASS_ENTRY (1301, 20), OPEN_STATE_ACTIVITY_CRUCIBLE (1400), OPEN_STATE_ACTIVITY_NEWBEEBOUNS_OPEN (1401), OPEN_STATE_ACTIVITY_NEWBEEBOUNS_CLOSE (1402), @@ -139,27 +139,27 @@ public enum OpenState { OPEN_STATE_LIYUE_INFUSEDCRYSTAL (1405), OPEN_STATE_SNOW_MOUNTAIN_ELDER_TREE (1406), OPEN_STATE_MIRACLE_RING (1407), - OPEN_STATE_COOP_LINE (1408), + OPEN_STATE_COOP_LINE (1408, 26), OPEN_STATE_INAZUMA_INFUSEDCRYSTAL (1409), OPEN_STATE_FISH (1410), OPEN_STATE_GUIDE_SUMO_TEAM_SKILL (1411), OPEN_STATE_GUIDE_FISH_RECIPE (1412), OPEN_STATE_HOME (1500), - OPEN_STATE_ACTIVITY_HOMEWORLD (1501), + OPEN_STATE_ACTIVITY_HOMEWORLD (1501, 28), OPEN_STATE_ADEPTIABODE (1502), OPEN_STATE_HOME_AVATAR (1503), OPEN_STATE_HOME_EDIT (1504), OPEN_STATE_HOME_EDIT_TIPS (1505), - OPEN_STATE_RELIQUARY_DECOMPOSE (1600), - OPEN_STATE_ACTIVITY_H5 (1700), + OPEN_STATE_RELIQUARY_DECOMPOSE (1600, 45), + OPEN_STATE_ACTIVITY_H5 (1700, 10), OPEN_STATE_ORAIONOKAMI (2000), OPEN_STATE_GUIDE_CHESS_MISSION_CHECK (2001), OPEN_STATE_GUIDE_CHESS_BUILD (2002), OPEN_STATE_GUIDE_CHESS_WIND_TOWER_CIRCLE (2003), OPEN_STATE_GUIDE_CHESS_CARD_SELECT (2004), OPEN_STATE_INAZUMA_MAINQUEST_FINISHED (2005), - OPEN_STATE_PAIMON_LVINFO (2100), - OPEN_STATE_TELEPORT_HUD (2101), + OPEN_STATE_PAIMON_LVINFO (2100, 7), + OPEN_STATE_TELEPORT_HUD (2101, 2), OPEN_STATE_GUIDE_MAP_UNLOCK (2102), OPEN_STATE_GUIDE_PAIMON_LVINFO (2103), OPEN_STATE_GUIDE_AMBORTRANSPORT (2104), @@ -177,7 +177,7 @@ public enum OpenState { OPEN_STATE_GUIDE_POTION_CONFIGURE (2401), OPEN_STATE_GUIDE_LANV2_FIREWORK (2402), OPEN_STATE_LOADINGTIPS_ENKANOMIYA (2403), - OPEN_STATE_MICHIAE_CASKET (2500), + OPEN_STATE_MICHIAE_CASKET (2500, 30), OPEN_STATE_MAIL_COLLECT_UNLOCK_RED_POINT (2501), OPEN_STATE_LUMEN_STONE (2600), OPEN_STATE_GUIDE_CRYSTALLINK_BUFF (2601), @@ -190,6 +190,7 @@ public enum OpenState { OPEN_ADVENTURE_MANUAL_EDUCATION (2801); private final int value; + private final int unlockLevel; private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); private static final Map stringMap = new HashMap<>(); @@ -202,11 +203,20 @@ public enum OpenState { private OpenState(int value) { this.value = value; + this.unlockLevel = -1; + } + private OpenState(int value, int unlockLevel) { + this.value = value; + this.unlockLevel = unlockLevel; } public int getValue() { return value; } + + public int getUnlockLevel() { + return this.unlockLevel; + } public static OpenState getTypeByValue(int value) { return map.getOrDefault(value, OPEN_STATE_NONE);