Commit 9fc8cc1c authored by Kengxxiao's avatar Kengxxiao Committed by GitHub
Browse files

Merge pull request #1 from Grasscutters/development

merge
parents 627a2f1e d1fc8c1f
...@@ -5,7 +5,7 @@ import java.util.List; ...@@ -5,7 +5,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import emu.grasscutter.data.GenshinData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.common.ItemParamData; import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.data.custom.OpenConfigEntry; import emu.grasscutter.data.custom.OpenConfigEntry;
import emu.grasscutter.data.def.AvatarPromoteData; import emu.grasscutter.data.def.AvatarPromoteData;
...@@ -15,11 +15,11 @@ import emu.grasscutter.data.def.WeaponPromoteData; ...@@ -15,11 +15,11 @@ import emu.grasscutter.data.def.WeaponPromoteData;
import emu.grasscutter.data.def.AvatarSkillDepotData.InherentProudSkillOpens; import emu.grasscutter.data.def.AvatarSkillDepotData.InherentProudSkillOpens;
import emu.grasscutter.data.def.AvatarTalentData; import emu.grasscutter.data.def.AvatarTalentData;
import emu.grasscutter.data.def.ProudSkillData; import emu.grasscutter.data.def.ProudSkillData;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.avatar.GenshinAvatar; import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.inventory.ItemType; import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.inventory.MaterialType; import emu.grasscutter.game.inventory.MaterialType;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam;
import emu.grasscutter.net.proto.MaterialInfoOuterClass.MaterialInfo; import emu.grasscutter.net.proto.MaterialInfoOuterClass.MaterialInfo;
import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServer;
...@@ -72,8 +72,8 @@ public class InventoryManager { ...@@ -72,8 +72,8 @@ public class InventoryManager {
return server; return server;
} }
public void lockEquip(GenshinPlayer player, long targetEquipGuid, boolean isLocked) { public void lockEquip(Player player, long targetEquipGuid, boolean isLocked) {
GenshinItem equip = player.getInventory().getItemByGuid(targetEquipGuid); GameItem equip = player.getInventory().getItemByGuid(targetEquipGuid);
if (equip == null || !equip.getItemData().isEquip()) { if (equip == null || !equip.getItemData().isEquip()) {
return; return;
...@@ -86,8 +86,8 @@ public class InventoryManager { ...@@ -86,8 +86,8 @@ public class InventoryManager {
player.sendPacket(new PacketSetEquipLockStateRsp(equip)); player.sendPacket(new PacketSetEquipLockStateRsp(equip));
} }
public void upgradeRelic(GenshinPlayer player, long targetGuid, List<Long> foodRelicList, List<ItemParam> list) { public void upgradeRelic(Player player, long targetGuid, List<Long> foodRelicList, List<ItemParam> list) {
GenshinItem relic = player.getInventory().getItemByGuid(targetGuid); GameItem relic = player.getInventory().getItemByGuid(targetGuid);
if (relic == null || relic.getItemType() != ItemType.ITEM_RELIQUARY) { if (relic == null || relic.getItemType() != ItemType.ITEM_RELIQUARY) {
return; return;
...@@ -98,7 +98,7 @@ public class InventoryManager { ...@@ -98,7 +98,7 @@ public class InventoryManager {
for (long guid : foodRelicList) { for (long guid : foodRelicList) {
// Add to delete queue // Add to delete queue
GenshinItem food = player.getInventory().getItemByGuid(guid); GameItem food = player.getInventory().getItemByGuid(guid);
if (food == null || !food.isDestroyable()) { if (food == null || !food.isDestroyable()) {
continue; continue;
} }
...@@ -111,7 +111,7 @@ public class InventoryManager { ...@@ -111,7 +111,7 @@ public class InventoryManager {
} }
} }
for (ItemParam itemParam : list) { for (ItemParam itemParam : list) {
GenshinItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemParam.getItemId()); GameItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemParam.getItemId());
if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_RELIQUARY_MATERIAL) { if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_RELIQUARY_MATERIAL) {
continue; continue;
} }
...@@ -139,14 +139,14 @@ public class InventoryManager { ...@@ -139,14 +139,14 @@ public class InventoryManager {
// Consume food items // Consume food items
for (long guid : foodRelicList) { for (long guid : foodRelicList) {
GenshinItem food = player.getInventory().getItemByGuid(guid); GameItem food = player.getInventory().getItemByGuid(guid);
if (food == null || !food.isDestroyable()) { if (food == null || !food.isDestroyable()) {
continue; continue;
} }
player.getInventory().removeItem(food); player.getInventory().removeItem(food);
} }
for (ItemParam itemParam : list) { for (ItemParam itemParam : list) {
GenshinItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemParam.getItemId()); GameItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemParam.getItemId());
if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_RELIQUARY_MATERIAL) { if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_RELIQUARY_MATERIAL) {
continue; continue;
} }
...@@ -169,7 +169,7 @@ public class InventoryManager { ...@@ -169,7 +169,7 @@ public class InventoryManager {
int oldLevel = level; int oldLevel = level;
int exp = relic.getExp(); int exp = relic.getExp();
int totalExp = relic.getTotalExp(); int totalExp = relic.getTotalExp();
int reqExp = GenshinData.getRelicExpRequired(relic.getItemData().getRankLevel(), level); int reqExp = GameData.getRelicExpRequired(relic.getItemData().getRankLevel(), level);
int upgrades = 0; int upgrades = 0;
List<Integer> oldAppendPropIdList = relic.getAppendPropIdList(); List<Integer> oldAppendPropIdList = relic.getAppendPropIdList();
...@@ -189,7 +189,7 @@ public class InventoryManager { ...@@ -189,7 +189,7 @@ public class InventoryManager {
upgrades += 1; upgrades += 1;
} }
// Set req exp // Set req exp
reqExp = GenshinData.getRelicExpRequired(relic.getItemData().getRankLevel(), level); reqExp = GameData.getRelicExpRequired(relic.getItemData().getRankLevel(), level);
} }
} }
...@@ -209,7 +209,7 @@ public class InventoryManager { ...@@ -209,7 +209,7 @@ public class InventoryManager {
// Avatar // Avatar
if (oldLevel != level) { if (oldLevel != level) {
GenshinAvatar avatar = relic.getEquipCharacter() > 0 ? player.getAvatars().getAvatarById(relic.getEquipCharacter()) : null; Avatar avatar = relic.getEquipCharacter() > 0 ? player.getAvatars().getAvatarById(relic.getEquipCharacter()) : null;
if (avatar != null) { if (avatar != null) {
avatar.recalcStats(); avatar.recalcStats();
} }
...@@ -220,15 +220,15 @@ public class InventoryManager { ...@@ -220,15 +220,15 @@ public class InventoryManager {
player.sendPacket(new PacketReliquaryUpgradeRsp(relic, rate, oldLevel, oldAppendPropIdList)); player.sendPacket(new PacketReliquaryUpgradeRsp(relic, rate, oldLevel, oldAppendPropIdList));
} }
public List<ItemParam> calcWeaponUpgradeReturnItems(GenshinPlayer player, long targetGuid, List<Long> foodWeaponGuidList, List<ItemParam> itemParamList) { public List<ItemParam> calcWeaponUpgradeReturnItems(Player player, long targetGuid, List<Long> foodWeaponGuidList, List<ItemParam> itemParamList) {
GenshinItem weapon = player.getInventory().getItemByGuid(targetGuid); GameItem weapon = player.getInventory().getItemByGuid(targetGuid);
// Sanity checks // Sanity checks
if (weapon == null || weapon.getItemType() != ItemType.ITEM_WEAPON) { if (weapon == null || weapon.getItemType() != ItemType.ITEM_WEAPON) {
return null; return null;
} }
WeaponPromoteData promoteData = GenshinData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel()); WeaponPromoteData promoteData = GameData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel());
if (promoteData == null) { if (promoteData == null) {
return null; return null;
} }
...@@ -236,7 +236,7 @@ public class InventoryManager { ...@@ -236,7 +236,7 @@ public class InventoryManager {
// Get exp gain // Get exp gain
int expGain = 0; int expGain = 0;
for (long guid : foodWeaponGuidList) { for (long guid : foodWeaponGuidList) {
GenshinItem food = player.getInventory().getItemByGuid(guid); GameItem food = player.getInventory().getItemByGuid(guid);
if (food == null) { if (food == null) {
continue; continue;
} }
...@@ -246,7 +246,7 @@ public class InventoryManager { ...@@ -246,7 +246,7 @@ public class InventoryManager {
} }
} }
for (ItemParam param : itemParamList) { for (ItemParam param : itemParamList) {
GenshinItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(param.getItemId()); GameItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(param.getItemId());
if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_WEAPON_EXP_STONE) { if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_WEAPON_EXP_STONE) {
continue; continue;
} }
...@@ -264,7 +264,7 @@ public class InventoryManager { ...@@ -264,7 +264,7 @@ public class InventoryManager {
int maxLevel = promoteData.getUnlockMaxLevel(); int maxLevel = promoteData.getUnlockMaxLevel();
int level = weapon.getLevel(); int level = weapon.getLevel();
int exp = weapon.getExp(); int exp = weapon.getExp();
int reqExp = GenshinData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level); int reqExp = GameData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level);
while (expGain > 0 && reqExp > 0 && level < maxLevel) { while (expGain > 0 && reqExp > 0 && level < maxLevel) {
// Do calculations // Do calculations
...@@ -277,7 +277,7 @@ public class InventoryManager { ...@@ -277,7 +277,7 @@ public class InventoryManager {
exp = 0; exp = 0;
level += 1; level += 1;
// Set req exp // Set req exp
reqExp = GenshinData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level); reqExp = GameData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level);
} }
} }
...@@ -285,15 +285,15 @@ public class InventoryManager { ...@@ -285,15 +285,15 @@ public class InventoryManager {
} }
public void upgradeWeapon(GenshinPlayer player, long targetGuid, List<Long> foodWeaponGuidList, List<ItemParam> itemParamList) { public void upgradeWeapon(Player player, long targetGuid, List<Long> foodWeaponGuidList, List<ItemParam> itemParamList) {
GenshinItem weapon = player.getInventory().getItemByGuid(targetGuid); GameItem weapon = player.getInventory().getItemByGuid(targetGuid);
// Sanity checks // Sanity checks
if (weapon == null || weapon.getItemType() != ItemType.ITEM_WEAPON) { if (weapon == null || weapon.getItemType() != ItemType.ITEM_WEAPON) {
return; return;
} }
WeaponPromoteData promoteData = GenshinData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel()); WeaponPromoteData promoteData = GameData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel());
if (promoteData == null) { if (promoteData == null) {
return; return;
} }
...@@ -302,7 +302,7 @@ public class InventoryManager { ...@@ -302,7 +302,7 @@ public class InventoryManager {
int expGain = 0, moraCost = 0; int expGain = 0, moraCost = 0;
for (long guid : foodWeaponGuidList) { for (long guid : foodWeaponGuidList) {
GenshinItem food = player.getInventory().getItemByGuid(guid); GameItem food = player.getInventory().getItemByGuid(guid);
if (food == null || !food.isDestroyable()) { if (food == null || !food.isDestroyable()) {
continue; continue;
} }
...@@ -313,7 +313,7 @@ public class InventoryManager { ...@@ -313,7 +313,7 @@ public class InventoryManager {
} }
} }
for (ItemParam param : itemParamList) { for (ItemParam param : itemParamList) {
GenshinItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(param.getItemId()); GameItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(param.getItemId());
if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_WEAPON_EXP_STONE) { if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_WEAPON_EXP_STONE) {
continue; continue;
} }
...@@ -344,14 +344,14 @@ public class InventoryManager { ...@@ -344,14 +344,14 @@ public class InventoryManager {
// Consume weapon/items used to feed // Consume weapon/items used to feed
for (long guid : foodWeaponGuidList) { for (long guid : foodWeaponGuidList) {
GenshinItem food = player.getInventory().getItemByGuid(guid); GameItem food = player.getInventory().getItemByGuid(guid);
if (food == null || !food.isDestroyable()) { if (food == null || !food.isDestroyable()) {
continue; continue;
} }
player.getInventory().removeItem(food); player.getInventory().removeItem(food);
} }
for (ItemParam param : itemParamList) { for (ItemParam param : itemParamList) {
GenshinItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(param.getItemId()); GameItem food = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(param.getItemId());
if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_WEAPON_EXP_STONE) { if (food == null || food.getItemData().getMaterialType() != MaterialType.MATERIAL_WEAPON_EXP_STONE) {
continue; continue;
} }
...@@ -365,7 +365,7 @@ public class InventoryManager { ...@@ -365,7 +365,7 @@ public class InventoryManager {
int oldLevel = level; int oldLevel = level;
int exp = weapon.getExp(); int exp = weapon.getExp();
int totalExp = weapon.getTotalExp(); int totalExp = weapon.getTotalExp();
int reqExp = GenshinData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level); int reqExp = GameData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level);
while (expGain > 0 && reqExp > 0 && level < maxLevel) { while (expGain > 0 && reqExp > 0 && level < maxLevel) {
// Do calculations // Do calculations
...@@ -379,7 +379,7 @@ public class InventoryManager { ...@@ -379,7 +379,7 @@ public class InventoryManager {
exp = 0; exp = 0;
level += 1; level += 1;
// Set req exp // Set req exp
reqExp = GenshinData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level); reqExp = GameData.getWeaponExpRequired(weapon.getItemData().getRankLevel(), level);
} }
} }
...@@ -393,7 +393,7 @@ public class InventoryManager { ...@@ -393,7 +393,7 @@ public class InventoryManager {
// Avatar // Avatar
if (oldLevel != level) { if (oldLevel != level) {
GenshinAvatar avatar = weapon.getEquipCharacter() > 0 ? player.getAvatars().getAvatarById(weapon.getEquipCharacter()) : null; Avatar avatar = weapon.getEquipCharacter() > 0 ? player.getAvatars().getAvatarById(weapon.getEquipCharacter()) : null;
if (avatar != null) { if (avatar != null) {
avatar.recalcStats(); avatar.recalcStats();
} }
...@@ -429,9 +429,9 @@ public class InventoryManager { ...@@ -429,9 +429,9 @@ public class InventoryManager {
return leftoverOreList; return leftoverOreList;
} }
public void refineWeapon(GenshinPlayer player, long targetGuid, long feedGuid) { public void refineWeapon(Player player, long targetGuid, long feedGuid) {
GenshinItem weapon = player.getInventory().getItemByGuid(targetGuid); GameItem weapon = player.getInventory().getItemByGuid(targetGuid);
GenshinItem feed = player.getInventory().getItemByGuid(feedGuid); GameItem feed = player.getInventory().getItemByGuid(feedGuid);
// Sanity checks // Sanity checks
if (weapon == null || feed == null || !feed.isDestroyable()) { if (weapon == null || feed == null || !feed.isDestroyable()) {
...@@ -478,7 +478,7 @@ public class InventoryManager { ...@@ -478,7 +478,7 @@ public class InventoryManager {
weapon.save(); weapon.save();
// Avatar // Avatar
GenshinAvatar avatar = weapon.getEquipCharacter() > 0 ? player.getAvatars().getAvatarById(weapon.getEquipCharacter()) : null; Avatar avatar = weapon.getEquipCharacter() > 0 ? player.getAvatars().getAvatarById(weapon.getEquipCharacter()) : null;
if (avatar != null) { if (avatar != null) {
avatar.recalcStats(); avatar.recalcStats();
} }
...@@ -488,16 +488,16 @@ public class InventoryManager { ...@@ -488,16 +488,16 @@ public class InventoryManager {
player.sendPacket(new PacketWeaponAwakenRsp(avatar, weapon, feed, oldRefineLevel)); player.sendPacket(new PacketWeaponAwakenRsp(avatar, weapon, feed, oldRefineLevel));
} }
public void promoteWeapon(GenshinPlayer player, long targetGuid) { public void promoteWeapon(Player player, long targetGuid) {
GenshinItem weapon = player.getInventory().getItemByGuid(targetGuid); GameItem weapon = player.getInventory().getItemByGuid(targetGuid);
if (weapon == null || weapon.getItemType() != ItemType.ITEM_WEAPON) { if (weapon == null || weapon.getItemType() != ItemType.ITEM_WEAPON) {
return; return;
} }
int nextPromoteLevel = weapon.getPromoteLevel() + 1; int nextPromoteLevel = weapon.getPromoteLevel() + 1;
WeaponPromoteData currentPromoteData = GenshinData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel()); WeaponPromoteData currentPromoteData = GameData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), weapon.getPromoteLevel());
WeaponPromoteData nextPromoteData = GenshinData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), nextPromoteLevel); WeaponPromoteData nextPromoteData = GameData.getWeaponPromoteData(weapon.getItemData().getWeaponPromoteId(), nextPromoteLevel);
if (currentPromoteData == null || nextPromoteData == null) { if (currentPromoteData == null || nextPromoteData == null) {
return; return;
} }
...@@ -509,7 +509,7 @@ public class InventoryManager { ...@@ -509,7 +509,7 @@ public class InventoryManager {
// Make sure player has promote items // Make sure player has promote items
for (ItemParamData cost : nextPromoteData.getCostItems()) { for (ItemParamData cost : nextPromoteData.getCostItems()) {
GenshinItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId());
if (feedItem == null || feedItem.getCount() < cost.getCount()) { if (feedItem == null || feedItem.getCount() < cost.getCount()) {
return; return;
} }
...@@ -524,7 +524,7 @@ public class InventoryManager { ...@@ -524,7 +524,7 @@ public class InventoryManager {
// Consume promote filler items // Consume promote filler items
for (ItemParamData cost : nextPromoteData.getCostItems()) { for (ItemParamData cost : nextPromoteData.getCostItems()) {
GenshinItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId());
player.getInventory().removeItem(feedItem, cost.getCount()); player.getInventory().removeItem(feedItem, cost.getCount());
} }
...@@ -533,7 +533,7 @@ public class InventoryManager { ...@@ -533,7 +533,7 @@ public class InventoryManager {
weapon.save(); weapon.save();
// Avatar // Avatar
GenshinAvatar avatar = weapon.getEquipCharacter() > 0 ? player.getAvatars().getAvatarById(weapon.getEquipCharacter()) : null; Avatar avatar = weapon.getEquipCharacter() > 0 ? player.getAvatars().getAvatarById(weapon.getEquipCharacter()) : null;
if (avatar != null) { if (avatar != null) {
avatar.recalcStats(); avatar.recalcStats();
} }
...@@ -543,8 +543,8 @@ public class InventoryManager { ...@@ -543,8 +543,8 @@ public class InventoryManager {
player.sendPacket(new PacketWeaponPromoteRsp(weapon, oldPromoteLevel)); player.sendPacket(new PacketWeaponPromoteRsp(weapon, oldPromoteLevel));
} }
public void promoteAvatar(GenshinPlayer player, long guid) { public void promoteAvatar(Player player, long guid) {
GenshinAvatar avatar = player.getAvatars().getAvatarByGuid(guid); Avatar avatar = player.getAvatars().getAvatarByGuid(guid);
// Sanity checks // Sanity checks
if (avatar == null) { if (avatar == null) {
...@@ -552,8 +552,8 @@ public class InventoryManager { ...@@ -552,8 +552,8 @@ public class InventoryManager {
} }
int nextPromoteLevel = avatar.getPromoteLevel() + 1; int nextPromoteLevel = avatar.getPromoteLevel() + 1;
AvatarPromoteData currentPromoteData = GenshinData.getAvatarPromoteData(avatar.getAvatarData().getAvatarPromoteId(), avatar.getPromoteLevel()); AvatarPromoteData currentPromoteData = GameData.getAvatarPromoteData(avatar.getAvatarData().getAvatarPromoteId(), avatar.getPromoteLevel());
AvatarPromoteData nextPromoteData = GenshinData.getAvatarPromoteData(avatar.getAvatarData().getAvatarPromoteId(), nextPromoteLevel); AvatarPromoteData nextPromoteData = GameData.getAvatarPromoteData(avatar.getAvatarData().getAvatarPromoteId(), nextPromoteLevel);
if (currentPromoteData == null || nextPromoteData == null) { if (currentPromoteData == null || nextPromoteData == null) {
return; return;
} }
...@@ -565,7 +565,7 @@ public class InventoryManager { ...@@ -565,7 +565,7 @@ public class InventoryManager {
// Make sure player has cost items // Make sure player has cost items
for (ItemParamData cost : nextPromoteData.getCostItems()) { for (ItemParamData cost : nextPromoteData.getCostItems()) {
GenshinItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId());
if (feedItem == null || feedItem.getCount() < cost.getCount()) { if (feedItem == null || feedItem.getCount() < cost.getCount()) {
return; return;
} }
...@@ -580,7 +580,7 @@ public class InventoryManager { ...@@ -580,7 +580,7 @@ public class InventoryManager {
// Consume promote filler items // Consume promote filler items
for (ItemParamData cost : nextPromoteData.getCostItems()) { for (ItemParamData cost : nextPromoteData.getCostItems()) {
GenshinItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId());
player.getInventory().removeItem(feedItem, cost.getCount()); player.getInventory().removeItem(feedItem, cost.getCount());
} }
...@@ -588,7 +588,7 @@ public class InventoryManager { ...@@ -588,7 +588,7 @@ public class InventoryManager {
avatar.setPromoteLevel(nextPromoteLevel); avatar.setPromoteLevel(nextPromoteLevel);
// Update proud skills // Update proud skills
AvatarSkillDepotData skillDepot = GenshinData.getAvatarSkillDepotDataMap().get(avatar.getSkillDepotId()); AvatarSkillDepotData skillDepot = GameData.getAvatarSkillDepotDataMap().get(avatar.getSkillDepotId());
if (skillDepot != null && skillDepot.getInherentProudSkillOpens() != null) { if (skillDepot != null && skillDepot.getInherentProudSkillOpens() != null) {
for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) { for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) {
...@@ -597,7 +597,7 @@ public class InventoryManager { ...@@ -597,7 +597,7 @@ public class InventoryManager {
} }
if (openData.getNeedAvatarPromoteLevel() == avatar.getPromoteLevel()) { if (openData.getNeedAvatarPromoteLevel() == avatar.getPromoteLevel()) {
int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1; int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1;
if (GenshinData.getProudSkillDataMap().containsKey(proudSkillId)) { if (GameData.getProudSkillDataMap().containsKey(proudSkillId)) {
avatar.getProudSkillList().add(proudSkillId); avatar.getProudSkillList().add(proudSkillId);
player.sendPacket(new PacketProudSkillChangeNotify(avatar)); player.sendPacket(new PacketProudSkillChangeNotify(avatar));
} }
...@@ -614,20 +614,20 @@ public class InventoryManager { ...@@ -614,20 +614,20 @@ public class InventoryManager {
avatar.save(); avatar.save();
} }
public void upgradeAvatar(GenshinPlayer player, long guid, int itemId, int count) { public void upgradeAvatar(Player player, long guid, int itemId, int count) {
GenshinAvatar avatar = player.getAvatars().getAvatarByGuid(guid); Avatar avatar = player.getAvatars().getAvatarByGuid(guid);
// Sanity checks // Sanity checks
if (avatar == null) { if (avatar == null) {
return; return;
} }
AvatarPromoteData promoteData = GenshinData.getAvatarPromoteData(avatar.getAvatarData().getAvatarPromoteId(), avatar.getPromoteLevel()); AvatarPromoteData promoteData = GameData.getAvatarPromoteData(avatar.getAvatarData().getAvatarPromoteId(), avatar.getPromoteLevel());
if (promoteData == null) { if (promoteData == null) {
return; return;
} }
GenshinItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemId); GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(itemId);
if (feedItem == null || feedItem.getItemData().getMaterialType() != MaterialType.MATERIAL_EXP_FRUIT || feedItem.getCount() < count) { if (feedItem == null || feedItem.getItemData().getMaterialType() != MaterialType.MATERIAL_EXP_FRUIT || feedItem.getCount() < count) {
return; return;
...@@ -660,8 +660,8 @@ public class InventoryManager { ...@@ -660,8 +660,8 @@ public class InventoryManager {
upgradeAvatar(player, avatar, promoteData, expGain); upgradeAvatar(player, avatar, promoteData, expGain);
} }
public void upgradeAvatar(GenshinPlayer player, GenshinAvatar avatar, int expGain) { public void upgradeAvatar(Player player, Avatar avatar, int expGain) {
AvatarPromoteData promoteData = GenshinData.getAvatarPromoteData(avatar.getAvatarData().getAvatarPromoteId(), avatar.getPromoteLevel()); AvatarPromoteData promoteData = GameData.getAvatarPromoteData(avatar.getAvatarData().getAvatarPromoteId(), avatar.getPromoteLevel());
if (promoteData == null) { if (promoteData == null) {
return; return;
} }
...@@ -669,12 +669,12 @@ public class InventoryManager { ...@@ -669,12 +669,12 @@ public class InventoryManager {
upgradeAvatar(player, avatar, promoteData, expGain); upgradeAvatar(player, avatar, promoteData, expGain);
} }
public void upgradeAvatar(GenshinPlayer player, GenshinAvatar avatar, AvatarPromoteData promoteData, int expGain) { public void upgradeAvatar(Player player, Avatar avatar, AvatarPromoteData promoteData, int expGain) {
int maxLevel = promoteData.getUnlockMaxLevel(); int maxLevel = promoteData.getUnlockMaxLevel();
int level = avatar.getLevel(); int level = avatar.getLevel();
int oldLevel = level; int oldLevel = level;
int exp = avatar.getExp(); int exp = avatar.getExp();
int reqExp = GenshinData.getAvatarLevelExpRequired(level); int reqExp = GameData.getAvatarLevelExpRequired(level);
while (expGain > 0 && reqExp > 0 && level < maxLevel) { while (expGain > 0 && reqExp > 0 && level < maxLevel) {
// Do calculations // Do calculations
...@@ -687,7 +687,7 @@ public class InventoryManager { ...@@ -687,7 +687,7 @@ public class InventoryManager {
exp = 0; exp = 0;
level += 1; level += 1;
// Set req exp // Set req exp
reqExp = GenshinData.getAvatarLevelExpRequired(level); reqExp = GameData.getAvatarLevelExpRequired(level);
} }
} }
...@@ -711,12 +711,12 @@ public class InventoryManager { ...@@ -711,12 +711,12 @@ public class InventoryManager {
player.sendPacket(new PacketAvatarUpgradeRsp(avatar, oldLevel, oldPropMap)); player.sendPacket(new PacketAvatarUpgradeRsp(avatar, oldLevel, oldPropMap));
} }
public void upgradeAvatarFetterLevel(GenshinPlayer player, GenshinAvatar avatar, int expGain) { public void upgradeAvatarFetterLevel(Player player, Avatar avatar, int expGain) {
// May work. Not test. // May work. Not test.
int maxLevel = 10; // Keep it until I think of a more "elegant" way int maxLevel = 10; // Keep it until I think of a more "elegant" way
int level = avatar.getFetterLevel(); int level = avatar.getFetterLevel();
int exp = avatar.getFetterExp(); int exp = avatar.getFetterExp();
int reqExp = GenshinData.getAvatarFetterLevelExpRequired(level); int reqExp = GameData.getAvatarFetterLevelExpRequired(level);
while (expGain > 0 && reqExp > 0 && level < maxLevel) { while (expGain > 0 && reqExp > 0 && level < maxLevel) {
int toGain = Math.min(expGain, reqExp - exp); int toGain = Math.min(expGain, reqExp - exp);
...@@ -725,7 +725,7 @@ public class InventoryManager { ...@@ -725,7 +725,7 @@ public class InventoryManager {
if (exp >= reqExp) { if (exp >= reqExp) {
exp = 0; exp = 0;
level += 1; level += 1;
reqExp = GenshinData.getAvatarFetterLevelExpRequired(level); reqExp = GameData.getAvatarFetterLevelExpRequired(level);
} }
} }
...@@ -736,9 +736,9 @@ public class InventoryManager { ...@@ -736,9 +736,9 @@ public class InventoryManager {
player.sendPacket(new PacketAvatarPropNotify(avatar)); player.sendPacket(new PacketAvatarPropNotify(avatar));
} }
public void upgradeAvatarSkill(GenshinPlayer player, long guid, int skillId) { public void upgradeAvatarSkill(Player player, long guid, int skillId) {
// Sanity checks // Sanity checks
GenshinAvatar avatar = player.getAvatars().getAvatarByGuid(guid); Avatar avatar = player.getAvatars().getAvatarByGuid(guid);
if (avatar == null) { if (avatar == null) {
return; return;
} }
...@@ -748,7 +748,7 @@ public class InventoryManager { ...@@ -748,7 +748,7 @@ public class InventoryManager {
return; return;
} }
AvatarSkillData skillData = GenshinData.getAvatarSkillDataMap().get(skillId); AvatarSkillData skillData = GameData.getAvatarSkillDataMap().get(skillId);
if (skillData == null) { if (skillData == null) {
return; return;
} }
...@@ -764,7 +764,7 @@ public class InventoryManager { ...@@ -764,7 +764,7 @@ public class InventoryManager {
} }
// Proud skill data // Proud skill data
ProudSkillData proudSkill = GenshinData.getProudSkillDataMap().get(proudSkillId); ProudSkillData proudSkill = GameData.getProudSkillDataMap().get(proudSkillId);
if (proudSkill == null) { if (proudSkill == null) {
return; return;
} }
...@@ -779,7 +779,7 @@ public class InventoryManager { ...@@ -779,7 +779,7 @@ public class InventoryManager {
if (cost.getId() == 0) { if (cost.getId() == 0) {
continue; continue;
} }
GenshinItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId());
if (feedItem == null || feedItem.getCount() < cost.getCount()) { if (feedItem == null || feedItem.getCount() < cost.getCount()) {
return; return;
} }
...@@ -797,7 +797,7 @@ public class InventoryManager { ...@@ -797,7 +797,7 @@ public class InventoryManager {
if (cost.getId() == 0) { if (cost.getId() == 0) {
continue; continue;
} }
GenshinItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId()); GameItem feedItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(cost.getId());
player.getInventory().removeItem(feedItem, cost.getCount()); player.getInventory().removeItem(feedItem, cost.getCount());
} }
...@@ -810,9 +810,9 @@ public class InventoryManager { ...@@ -810,9 +810,9 @@ public class InventoryManager {
player.sendPacket(new PacketAvatarSkillUpgradeRsp(avatar, skillId, currentLevel, nextLevel)); player.sendPacket(new PacketAvatarSkillUpgradeRsp(avatar, skillId, currentLevel, nextLevel));
} }
public void unlockAvatarConstellation(GenshinPlayer player, long guid) { public void unlockAvatarConstellation(Player player, long guid) {
// Sanity checks // Sanity checks
GenshinAvatar avatar = player.getAvatars().getAvatarByGuid(guid); Avatar avatar = player.getAvatars().getAvatarByGuid(guid);
if (avatar == null) { if (avatar == null) {
return; return;
} }
...@@ -826,13 +826,13 @@ public class InventoryManager { ...@@ -826,13 +826,13 @@ public class InventoryManager {
nextTalentId = 40 + currentTalentLevel + 1; nextTalentId = 40 + currentTalentLevel + 1;
} }
AvatarTalentData talentData = GenshinData.getAvatarTalentDataMap().get(nextTalentId); AvatarTalentData talentData = GameData.getAvatarTalentDataMap().get(nextTalentId);
if (talentData == null) { if (talentData == null) {
return; return;
} }
GenshinItem costItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(talentData.getMainCostItemId()); GameItem costItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(talentData.getMainCostItemId());
if (costItem == null || costItem.getCount() < talentData.getMainCostItemCount()) { if (costItem == null || costItem.getCount() < talentData.getMainCostItemCount()) {
return; return;
} }
...@@ -849,7 +849,7 @@ public class InventoryManager { ...@@ -849,7 +849,7 @@ public class InventoryManager {
player.sendPacket(new PacketUnlockAvatarTalentRsp(avatar, nextTalentId)); player.sendPacket(new PacketUnlockAvatarTalentRsp(avatar, nextTalentId));
// Proud skill bonus map (Extra skills) // Proud skill bonus map (Extra skills)
OpenConfigEntry entry = GenshinData.getOpenConfigEntries().get(talentData.getOpenConfig()); OpenConfigEntry entry = GameData.getOpenConfigEntries().get(talentData.getOpenConfig());
if (entry != null && entry.getExtraTalentIndex() > 0) { if (entry != null && entry.getExtraTalentIndex() > 0) {
avatar.recalcProudSkillBonusMap(); avatar.recalcProudSkillBonusMap();
player.sendPacket(new PacketProudSkillExtraLevelNotify(avatar, entry.getExtraTalentIndex())); player.sendPacket(new PacketProudSkillExtraLevelNotify(avatar, entry.getExtraTalentIndex()));
...@@ -860,7 +860,7 @@ public class InventoryManager { ...@@ -860,7 +860,7 @@ public class InventoryManager {
avatar.save(); avatar.save();
} }
public void destroyMaterial(GenshinPlayer player, List<MaterialInfo> list) { public void destroyMaterial(Player player, List<MaterialInfo> list) {
// Return materials // Return materials
Int2IntOpenHashMap returnMaterialMap = new Int2IntOpenHashMap(); Int2IntOpenHashMap returnMaterialMap = new Int2IntOpenHashMap();
...@@ -870,7 +870,7 @@ public class InventoryManager { ...@@ -870,7 +870,7 @@ public class InventoryManager {
continue; continue;
} }
GenshinItem item = player.getInventory().getItemByGuid(info.getGuid()); GameItem item = player.getInventory().getItemByGuid(info.getGuid());
if (item == null || !item.isDestroyable()) { if (item == null || !item.isDestroyable()) {
continue; continue;
} }
...@@ -890,7 +890,7 @@ public class InventoryManager { ...@@ -890,7 +890,7 @@ public class InventoryManager {
// Give back items // Give back items
if (returnMaterialMap.size() > 0) { if (returnMaterialMap.size() > 0) {
for (Int2IntMap.Entry e : returnMaterialMap.int2IntEntrySet()) { for (Int2IntMap.Entry e : returnMaterialMap.int2IntEntrySet()) {
player.getInventory().addItem(new GenshinItem(e.getIntKey(), e.getIntValue())); player.getInventory().addItem(new GameItem(e.getIntKey(), e.getIntValue()));
} }
} }
...@@ -898,9 +898,9 @@ public class InventoryManager { ...@@ -898,9 +898,9 @@ public class InventoryManager {
player.sendPacket(new PacketDestroyMaterialRsp(returnMaterialMap)); player.sendPacket(new PacketDestroyMaterialRsp(returnMaterialMap));
} }
public GenshinItem useItem(GenshinPlayer player, long targetGuid, long itemGuid, int count) { public GameItem useItem(Player player, long targetGuid, long itemGuid, int count) {
GenshinAvatar target = player.getAvatars().getAvatarByGuid(targetGuid); Avatar target = player.getAvatars().getAvatarByGuid(targetGuid);
GenshinItem useItem = player.getInventory().getItemByGuid(itemGuid); GameItem useItem = player.getInventory().getItemByGuid(itemGuid);
if (useItem == null) { if (useItem == null) {
return null; return null;
...@@ -922,6 +922,11 @@ public class InventoryManager { ...@@ -922,6 +922,11 @@ public class InventoryManager {
default: default:
break; break;
} }
if (useItem.getItemId() == 1202) {
player.rechargeMoonCard();
used = 1;
}
if (used > 0) { if (used > 0) {
player.getInventory().removeItem(useItem, used); player.getInventory().removeItem(useItem, used);
......
package emu.grasscutter.game.managers; package emu.grasscutter.game.managers;
import emu.grasscutter.game.CoopRequest; import emu.grasscutter.game.CoopRequest;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.GenshinPlayer.SceneLoadState;
import emu.grasscutter.game.props.EnterReason; import emu.grasscutter.game.props.EnterReason;
import emu.grasscutter.game.world.World;
import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType;
import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason; import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason;
import emu.grasscutter.game.World; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.player.Player.SceneLoadState;
import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass;
import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpNotify; import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpNotify;
import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpResultNotify; import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpResultNotify;
...@@ -23,10 +24,10 @@ public class MultiplayerManager { ...@@ -23,10 +24,10 @@ public class MultiplayerManager {
return server; return server;
} }
public void applyEnterMp(GenshinPlayer player, int targetUid) { public void applyEnterMp(Player player, int targetUid) {
GenshinPlayer target = getServer().getPlayerByUid(targetUid); Player target = getServer().getPlayerByUid(targetUid);
if (target == null) { if (target == null) {
player.sendPacket(new PacketPlayerApplyEnterMpResultNotify(targetUid, "", false, PlayerApplyEnterMpReason.PlayerCannotEnterMp)); player.sendPacket(new PacketPlayerApplyEnterMpResultNotify(targetUid, "", false, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.PLAYER_CANNOT_ENTER_MP));
return; return;
} }
...@@ -58,7 +59,7 @@ public class MultiplayerManager { ...@@ -58,7 +59,7 @@ public class MultiplayerManager {
target.sendPacket(new PacketPlayerApplyEnterMpNotify(player)); target.sendPacket(new PacketPlayerApplyEnterMpNotify(player));
} }
public void applyEnterMpReply(GenshinPlayer hostPlayer, int applyUid, boolean isAgreed) { public void applyEnterMpReply(Player hostPlayer, int applyUid, boolean isAgreed) {
// Checks // Checks
CoopRequest request = hostPlayer.getCoopRequests().get(applyUid); CoopRequest request = hostPlayer.getCoopRequests().get(applyUid);
if (request == null || request.isExpired()) { if (request == null || request.isExpired()) {
...@@ -66,17 +67,17 @@ public class MultiplayerManager { ...@@ -66,17 +67,17 @@ public class MultiplayerManager {
} }
// Remove now that we are handling it // Remove now that we are handling it
GenshinPlayer requester = request.getRequester(); Player requester = request.getRequester();
hostPlayer.getCoopRequests().remove(applyUid); hostPlayer.getCoopRequests().remove(applyUid);
// Sanity checks - Dont let the requesting player join if they are already in multiplayer // Sanity checks - Dont let the requesting player join if they are already in multiplayer
if (requester.getWorld().isMultiplayer()) { if (requester.getWorld().isMultiplayer()) {
request.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(hostPlayer, false, PlayerApplyEnterMpReason.PlayerCannotEnterMp)); request.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(hostPlayer, false, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.PLAYER_CANNOT_ENTER_MP));
return; return;
} }
// Response packet // Response packet
request.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(hostPlayer, isAgreed, PlayerApplyEnterMpReason.PlayerJudge)); request.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(hostPlayer, isAgreed, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.PLAYER_JUDGE));
// Declined // Declined
if (!isAgreed) { if (!isAgreed) {
...@@ -92,7 +93,7 @@ public class MultiplayerManager { ...@@ -92,7 +93,7 @@ public class MultiplayerManager {
world.addPlayer(hostPlayer); world.addPlayer(hostPlayer);
// Rejoin packet // Rejoin packet
hostPlayer.sendPacket(new PacketPlayerEnterSceneNotify(hostPlayer, hostPlayer, EnterType.EnterSelf, EnterReason.HostFromSingleToMp, hostPlayer.getScene().getId(), hostPlayer.getPos())); hostPlayer.sendPacket(new PacketPlayerEnterSceneNotify(hostPlayer, hostPlayer, EnterType.ENTER_SELF, EnterReason.HostFromSingleToMp, hostPlayer.getScene().getId(), hostPlayer.getPos()));
} }
// Set scene pos and id of requester to the host player's // Set scene pos and id of requester to the host player's
...@@ -104,17 +105,17 @@ public class MultiplayerManager { ...@@ -104,17 +105,17 @@ public class MultiplayerManager {
hostPlayer.getWorld().addPlayer(requester); hostPlayer.getWorld().addPlayer(requester);
// Packet // Packet
requester.sendPacket(new PacketPlayerEnterSceneNotify(requester, hostPlayer, EnterType.EnterOther, EnterReason.TeamJoin, hostPlayer.getScene().getId(), hostPlayer.getPos())); requester.sendPacket(new PacketPlayerEnterSceneNotify(requester, hostPlayer, EnterType.ENTER_OTHER, EnterReason.TeamJoin, hostPlayer.getScene().getId(), hostPlayer.getPos()));
} }
public boolean leaveCoop(GenshinPlayer player) { public boolean leaveCoop(Player player) {
// Make sure player's world is multiplayer // Make sure player's world is multiplayer
if (!player.getWorld().isMultiplayer()) { if (!player.getWorld().isMultiplayer()) {
return false; return false;
} }
// Make sure everyone's scene is loaded // Make sure everyone's scene is loaded
for (GenshinPlayer p : player.getWorld().getPlayers()) { for (Player p : player.getWorld().getPlayers()) {
if (p.getSceneLoadState() != SceneLoadState.LOADED) { if (p.getSceneLoadState() != SceneLoadState.LOADED) {
return false; return false;
} }
...@@ -125,19 +126,19 @@ public class MultiplayerManager { ...@@ -125,19 +126,19 @@ public class MultiplayerManager {
world.addPlayer(player); world.addPlayer(player);
// Packet // Packet
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterSelf, EnterReason.TeamBack, player.getScene().getId(), player.getPos())); player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.ENTER_SELF, EnterReason.TeamBack, player.getScene().getId(), player.getPos()));
return true; return true;
} }
public boolean kickPlayer(GenshinPlayer player, int targetUid) { public boolean kickPlayer(Player player, int targetUid) {
// Make sure player's world is multiplayer and that player is owner // Make sure player's world is multiplayer and that player is owner
if (!player.getWorld().isMultiplayer() || player.getWorld().getHost() != player) { if (!player.getWorld().isMultiplayer() || player.getWorld().getHost() != player) {
return false; return false;
} }
// Get victim and sanity checks // Get victim and sanity checks
GenshinPlayer victim = player.getServer().getPlayerByUid(targetUid); Player victim = player.getServer().getPlayerByUid(targetUid);
if (victim == null || victim == player) { if (victim == null || victim == player) {
return false; return false;
...@@ -152,7 +153,7 @@ public class MultiplayerManager { ...@@ -152,7 +153,7 @@ public class MultiplayerManager {
World world = new World(victim); World world = new World(victim);
world.addPlayer(victim); world.addPlayer(victim);
victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.EnterSelf, EnterReason.TeamKick, victim.getScene().getId(), victim.getPos())); victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.ENTER_SELF, EnterReason.TeamKick, victim.getScene().getId(), victim.getPos()));
return true; return true;
} }
} }
package emu.grasscutter.game; package emu.grasscutter.game.player;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.proto.ForwardTypeOuterClass.ForwardType; import emu.grasscutter.net.proto.ForwardTypeOuterClass.ForwardType;
public class InvokeHandler<T> { public class InvokeHandler<T> {
private final List<T> entryListForwardAll; private final List<T> entryListForwardAll;
private final List<T> entryListForwardAllExceptCur; private final List<T> entryListForwardAllExceptCur;
private final List<T> entryListForwardHost; private final List<T> entryListForwardHost;
private final Class<? extends GenshinPacket> packetClass; private final Class<? extends BasePacket> packetClass;
public InvokeHandler(Class<? extends GenshinPacket> packetClass) { public InvokeHandler(Class<? extends BasePacket> packetClass) {
this.entryListForwardAll = new ArrayList<>(); this.entryListForwardAll = new ArrayList<>();
this.entryListForwardAllExceptCur = new ArrayList<>(); this.entryListForwardAllExceptCur = new ArrayList<>();
this.entryListForwardHost = new ArrayList<>(); this.entryListForwardHost = new ArrayList<>();
...@@ -20,22 +21,15 @@ public class InvokeHandler<T> { ...@@ -20,22 +21,15 @@ public class InvokeHandler<T> {
public synchronized void addEntry(ForwardType forward, T entry) { public synchronized void addEntry(ForwardType forward, T entry) {
switch (forward) { switch (forward) {
case ForwardToAll: case FORWARD_TO_ALL -> entryListForwardAll.add(entry);
entryListForwardAll.add(entry); case FORWARD_TO_ALL_EXCEPT_CUR, FORWARD_TO_ALL_EXIST_EXCEPT_CUR -> entryListForwardAllExceptCur.add(entry);
break; case FORWARD_TO_HOST -> entryListForwardHost.add(entry);
case ForwardToAllExceptCur: default -> {
case ForwardToAllExistExceptCur: }
entryListForwardAllExceptCur.add(entry);
break;
case ForwardToHost:
entryListForwardHost.add(entry);
break;
default:
break;
} }
} }
public synchronized void update(GenshinPlayer player) { public synchronized void update(Player player) {
if (player.getWorld() == null) { if (player.getWorld() == null) {
this.entryListForwardAll.clear(); this.entryListForwardAll.clear();
this.entryListForwardAllExceptCur.clear(); this.entryListForwardAllExceptCur.clear();
...@@ -45,17 +39,17 @@ public class InvokeHandler<T> { ...@@ -45,17 +39,17 @@ public class InvokeHandler<T> {
try { try {
if (entryListForwardAll.size() > 0) { if (entryListForwardAll.size() > 0) {
GenshinPacket packet = packetClass.getDeclaredConstructor(List.class).newInstance(this.entryListForwardAll); BasePacket packet = packetClass.getDeclaredConstructor(List.class).newInstance(this.entryListForwardAll);
player.getScene().broadcastPacket(packet); player.getScene().broadcastPacket(packet);
this.entryListForwardAll.clear(); this.entryListForwardAll.clear();
} }
if (entryListForwardAllExceptCur.size() > 0) { if (entryListForwardAllExceptCur.size() > 0) {
GenshinPacket packet = packetClass.getDeclaredConstructor(List.class).newInstance(this.entryListForwardAllExceptCur); BasePacket packet = packetClass.getDeclaredConstructor(List.class).newInstance(this.entryListForwardAllExceptCur);
player.getScene().broadcastPacketToOthers(player, packet); player.getScene().broadcastPacketToOthers(player, packet);
this.entryListForwardAllExceptCur.clear(); this.entryListForwardAllExceptCur.clear();
} }
if (entryListForwardHost.size() > 0) { if (entryListForwardHost.size() > 0) {
GenshinPacket packet = packetClass.getDeclaredConstructor(List.class).newInstance(this.entryListForwardHost); BasePacket packet = packetClass.getDeclaredConstructor(List.class).newInstance(this.entryListForwardHost);
player.getWorld().getHost().sendPacket(packet); player.getWorld().getHost().sendPacket(packet);
this.entryListForwardHost.clear(); this.entryListForwardHost.clear();
} }
......
package emu.grasscutter.game; package emu.grasscutter.game.player;
import java.time.Instant;
import java.util.*;
import dev.morphia.annotations.*; import dev.morphia.annotations.*;
import emu.grasscutter.GenshinConstants; import emu.grasscutter.GameConstants;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GenshinData; import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.PlayerLevelData; import emu.grasscutter.data.def.PlayerLevelData;
import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.avatar.AvatarProfileData; import emu.grasscutter.game.avatar.AvatarProfileData;
import emu.grasscutter.game.avatar.AvatarStorage; import emu.grasscutter.game.avatar.AvatarStorage;
import emu.grasscutter.game.avatar.GenshinAvatar; import emu.grasscutter.game.Account;
import emu.grasscutter.game.CoopRequest;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.entity.EntityItem; import emu.grasscutter.game.entity.EntityItem;
import emu.grasscutter.game.entity.GenshinEntity; import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.friends.FriendsList; import emu.grasscutter.game.friends.FriendsList;
import emu.grasscutter.game.friends.PlayerProfile; import emu.grasscutter.game.friends.PlayerProfile;
import emu.grasscutter.game.gacha.PlayerGachaInfo; import emu.grasscutter.game.gacha.PlayerGachaInfo;
import emu.grasscutter.game.inventory.GenshinItem; import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.inventory.Inventory; import emu.grasscutter.game.inventory.Inventory;
import emu.grasscutter.game.player.PlayerBirthday; import emu.grasscutter.game.mail.Mail;
import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.game.world.World;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry; import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry;
import emu.grasscutter.net.proto.HeadImageOuterClass.HeadImage; import emu.grasscutter.net.proto.HeadImageOuterClass.HeadImage;
...@@ -27,20 +35,22 @@ import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; ...@@ -27,20 +35,22 @@ import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
import emu.grasscutter.net.proto.MpSettingTypeOuterClass.MpSettingType; import emu.grasscutter.net.proto.MpSettingTypeOuterClass.MpSettingType;
import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo; import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo;
import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason; import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason;
import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass;
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo; import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
import emu.grasscutter.net.proto.PlayerWorldLocationInfoOuterClass;
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
import emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo;
import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.*; import emu.grasscutter.server.packet.send.*;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.DateHelper;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.*; import java.util.*;
@Entity(value = "players", useDiscriminator = false) @Entity(value = "players", useDiscriminator = false)
public class GenshinPlayer { public class Player {
@Id private int id; @Id private int id;
@Indexed(options = @IndexOptions(unique = true)) private String accountId; @Indexed(options = @IndexOptions(unique = true)) private String accountId;
...@@ -61,7 +71,7 @@ public class GenshinPlayer { ...@@ -61,7 +71,7 @@ public class GenshinPlayer {
@Transient private long nextGuid = 0; @Transient private long nextGuid = 0;
@Transient private int peerId; @Transient private int peerId;
@Transient private World world; @Transient private World world;
@Transient private GenshinScene scene; @Transient private Scene scene;
@Transient private GameSession session; @Transient private GameSession session;
@Transient private AvatarStorage avatars; @Transient private AvatarStorage avatars;
@Transient private Inventory inventory; @Transient private Inventory inventory;
...@@ -70,16 +80,21 @@ public class GenshinPlayer { ...@@ -70,16 +80,21 @@ public class GenshinPlayer {
private TeamManager teamManager; private TeamManager teamManager;
private PlayerGachaInfo gachaInfo; private PlayerGachaInfo gachaInfo;
private PlayerProfile playerProfile; private PlayerProfile playerProfile;
private MpSettingType mpSetting = MpSettingType.MpSettingEnterAfterApply;
private boolean showAvatar; private boolean showAvatar;
private ArrayList<AvatarProfileData> shownAvatars; private ArrayList<AvatarProfileData> shownAvatars;
private Set<Integer> rewardedLevels; private Set<Integer> rewardedLevels;
private ArrayList<Mail> mail;
private int sceneId; private int sceneId;
private int regionId; private int regionId;
private int mainCharacterId; private int mainCharacterId;
private boolean godmode; private boolean godmode;
private boolean moonCard;
private Date moonCardStartTime;
private int moonCardDuration;
private Set<Date> moonCardGetTimes;
@Transient private boolean paused; @Transient private boolean paused;
@Transient private int enterSceneToken; @Transient private int enterSceneToken;
@Transient private SceneLoadState sceneState; @Transient private SceneLoadState sceneState;
...@@ -93,7 +108,7 @@ public class GenshinPlayer { ...@@ -93,7 +108,7 @@ public class GenshinPlayer {
@Deprecated @Deprecated
@SuppressWarnings({"rawtypes", "unchecked"}) // Morphia only! @SuppressWarnings({"rawtypes", "unchecked"}) // Morphia only!
public GenshinPlayer() { public Player() {
this.inventory = new Inventory(this); this.inventory = new Inventory(this);
this.avatars = new AvatarStorage(this); this.avatars = new AvatarStorage(this);
this.friendsList = new FriendsList(this); this.friendsList = new FriendsList(this);
...@@ -112,6 +127,8 @@ public class GenshinPlayer { ...@@ -112,6 +127,8 @@ public class GenshinPlayer {
this.flyCloakList = new HashSet<>(); this.flyCloakList = new HashSet<>();
this.costumeList = new HashSet<>(); this.costumeList = new HashSet<>();
this.mail = new ArrayList<>();
this.setSceneId(3); this.setSceneId(3);
this.setRegionId(1); this.setRegionId(1);
this.sceneState = SceneLoadState.NONE; this.sceneState = SceneLoadState.NONE;
...@@ -123,10 +140,11 @@ public class GenshinPlayer { ...@@ -123,10 +140,11 @@ public class GenshinPlayer {
this.birthday = new PlayerBirthday(); this.birthday = new PlayerBirthday();
this.rewardedLevels = new HashSet<>(); this.rewardedLevels = new HashSet<>();
this.moonCardGetTimes = new HashSet<>();
} }
// On player creation // On player creation
public GenshinPlayer(GameSession session) { public Player(GameSession session) {
this(); this();
this.account = session.getAccount(); this.account = session.getAccount();
this.accountId = this.getAccount().getId(); this.accountId = this.getAccount().getId();
...@@ -145,7 +163,7 @@ public class GenshinPlayer { ...@@ -145,7 +163,7 @@ public class GenshinPlayer {
this.setProperty(PlayerProperty.PROP_PLAYER_RESIN, 160); this.setProperty(PlayerProperty.PROP_PLAYER_RESIN, 160);
this.getFlyCloakList().add(140001); this.getFlyCloakList().add(140001);
this.getNameCardList().add(210001); this.getNameCardList().add(210001);
this.getPos().set(GenshinConstants.START_POSITION); this.getPos().set(GameConstants.START_POSITION);
this.getRotation().set(0, 307, 0); this.getRotation().set(0, 307, 0);
} }
...@@ -157,7 +175,7 @@ public class GenshinPlayer { ...@@ -157,7 +175,7 @@ public class GenshinPlayer {
this.id = id; this.id = id;
} }
public long getNextGenshinGuid() { public long getNextGameGuid() {
long nextId = ++this.nextGuid; long nextId = ++this.nextGuid;
return ((long) this.getUid() << 32) + nextId; return ((long) this.getUid() << 32) + nextId;
} }
...@@ -195,11 +213,11 @@ public class GenshinPlayer { ...@@ -195,11 +213,11 @@ public class GenshinPlayer {
this.world = world; this.world = world;
} }
public synchronized GenshinScene getScene() { public synchronized Scene getScene() {
return scene; return scene;
} }
public synchronized void setScene(GenshinScene scene) { public synchronized void setScene(Scene scene) {
this.scene = scene; this.scene = scene;
} }
...@@ -253,6 +271,11 @@ public class GenshinPlayer { ...@@ -253,6 +271,11 @@ public class GenshinPlayer {
public int getWorldLevel() { public int getWorldLevel() {
return this.getProperty(PlayerProperty.PROP_PLAYER_WORLD_LEVEL); return this.getProperty(PlayerProperty.PROP_PLAYER_WORLD_LEVEL);
} }
public void setWorldLevel(int level) {
this.setProperty(PlayerProperty.PROP_PLAYER_WORLD_LEVEL, level);
this.sendPacket(new PacketPlayerPropNotify(this, PlayerProperty.PROP_PLAYER_WORLD_LEVEL));
}
public int getPrimogems() { public int getPrimogems() {
return this.getProperty(PlayerProperty.PROP_PLAYER_HCOIN); return this.getProperty(PlayerProperty.PROP_PLAYER_HCOIN);
...@@ -273,7 +296,7 @@ public class GenshinPlayer { ...@@ -273,7 +296,7 @@ public class GenshinPlayer {
} }
private int getExpRequired(int level) { private int getExpRequired(int level) {
PlayerLevelData levelData = GenshinData.getPlayerLevelDataMap().get(level); PlayerLevelData levelData = GameData.getPlayerLevelDataMap().get(level);
return levelData != null ? levelData.getExp() : 0; return levelData != null ? levelData.getExp() : 0;
} }
...@@ -366,7 +389,7 @@ public class GenshinPlayer { ...@@ -366,7 +389,7 @@ public class GenshinPlayer {
} }
public MpSettingType getMpSetting() { public MpSettingType getMpSetting() {
return mpSetting; return MpSettingType.MP_SETTING_ENTER_AFTER_APPLY; // TEMP
} }
public synchronized Int2ObjectMap<CoopRequest> getCoopRequests() { public synchronized Int2ObjectMap<CoopRequest> getCoopRequests() {
...@@ -385,10 +408,6 @@ public class GenshinPlayer { ...@@ -385,10 +408,6 @@ public class GenshinPlayer {
return clientAbilityInitFinishHandler; return clientAbilityInitFinishHandler;
} }
public void setMpSetting(MpSettingType mpSetting) {
this.mpSetting = mpSetting;
}
public AvatarStorage getAvatars() { public AvatarStorage getAvatars() {
return avatars; return avatars;
} }
...@@ -485,6 +504,94 @@ public class GenshinPlayer { ...@@ -485,6 +504,94 @@ public class GenshinPlayer {
this.regionId = regionId; this.regionId = regionId;
} }
public boolean inMoonCard() {
return moonCard;
}
public void setMoonCard(boolean moonCard) {
this.moonCard = moonCard;
}
public void addMoonCardDays(int days) {
this.moonCardDuration += days;
}
public int getMoonCardDuration() {
return moonCardDuration;
}
public void setMoonCardDuration(int moonCardDuration) {
this.moonCardDuration = moonCardDuration;
}
public Date getMoonCardStartTime() {
return moonCardStartTime;
}
public void setMoonCardStartTime(Date moonCardStartTime) {
this.moonCardStartTime = moonCardStartTime;
}
public Set<Date> getMoonCardGetTimes() {
return moonCardGetTimes;
}
public void setMoonCardGetTimes(Set<Date> moonCardGetTimes) {
this.moonCardGetTimes = moonCardGetTimes;
}
public int getMoonCardRemainDays() {
Calendar remainCalendar = Calendar.getInstance();
remainCalendar.setTime(moonCardStartTime);
remainCalendar.add(Calendar.DATE, moonCardDuration);
Date theLastDay = remainCalendar.getTime();
Date now = DateHelper.onlyYearMonthDay(new Date());
return (int) ((theLastDay.getTime() - now.getTime()) / (24 * 60 * 60 * 1000)); // By copilot
}
public void rechargeMoonCard() {
LinkedList<GameItem> items = new LinkedList<GameItem>();
for (int i = 0; i < 300; i++) {
items.add(new GameItem(203));
}
inventory.addItems(items);
if (!moonCard) {
moonCard = true;
Date now = new Date();
moonCardStartTime = DateHelper.onlyYearMonthDay(now);
moonCardDuration = 30;
} else {
moonCardDuration += 30;
}
if (!moonCardGetTimes.contains(moonCardStartTime)) {
moonCardGetTimes.add(moonCardStartTime);
}
}
public void getTodayMoonCard() {
if (!moonCard) {
return;
}
Date now = DateHelper.onlyYearMonthDay(new Date());
if (moonCardGetTimes.contains(now)) {
return;
}
Date stopTime = new Date();
Calendar stopCalendar = Calendar.getInstance();
stopCalendar.setTime(stopTime);
stopCalendar.add(Calendar.DATE, moonCardDuration);
stopTime = stopCalendar.getTime();
if (now.after(stopTime)) {
moonCard = false;
return;
}
moonCardGetTimes.add(now);
addMoonCardDays(1);
GameItem item = new GameItem(201, 90);
getInventory().addItem(item, ActionReason.BlessingRedeemReward);
session.send(new PacketCardProductRewardNotify(getMoonCardRemainDays()));
}
public boolean inGodmode() { public boolean inGodmode() {
return godmode; return godmode;
} }
...@@ -501,29 +608,19 @@ public class GenshinPlayer { ...@@ -501,29 +608,19 @@ public class GenshinPlayer {
this.hasSentAvatarDataNotify = hasSentAvatarDataNotify; this.hasSentAvatarDataNotify = hasSentAvatarDataNotify;
} }
public void addAvatar(GenshinAvatar avatar) { public void addAvatar(Avatar avatar) {
boolean result = getAvatars().addAvatar(avatar); boolean result = getAvatars().addAvatar(avatar);
if (result) { if (result) {
// Add starting weapon // Add starting weapon
getAvatars().addStartingWeapon(avatar); getAvatars().addStartingWeapon(avatar);
// Try adding to team if possible
//List<EntityAvatar> currentTeam = this.getTeamManager().getCurrentTeam();
boolean addedToTeam = false;
/*
if (currentTeam.size() <= GenshinConstants.MAX_AVATARS_IN_TEAM) {
addedToTeam = currentTeam
}
*/
// Done // Done
if (hasSentAvatarDataNotify()) { if (hasSentAvatarDataNotify()) {
// Recalc stats // Recalc stats
avatar.recalcStats(); avatar.recalcStats();
// Packet // Packet
sendPacket(new PacketAvatarAddNotify(avatar, addedToTeam)); sendPacket(new PacketAvatarAddNotify(avatar, false));
} }
} else { } else {
// Failed adding avatar // Failed adding avatar
...@@ -556,7 +653,7 @@ public class GenshinPlayer { ...@@ -556,7 +653,7 @@ public class GenshinPlayer {
} }
public void dropMessage(Object message) { public void dropMessage(Object message) {
this.sendPacket(new PacketPrivateChatNotify(GenshinConstants.SERVER_CONSOLE_UID, getUid(), message.toString())); this.sendPacket(new PacketPrivateChatNotify(GameConstants.SERVER_CONSOLE_UID, getUid(), message.toString()));
} }
/** /**
...@@ -565,12 +662,53 @@ public class GenshinPlayer { ...@@ -565,12 +662,53 @@ public class GenshinPlayer {
* @param sender The sender of the message. * @param sender The sender of the message.
* @param message The message to send. * @param message The message to send.
*/ */
public void sendMessage(GenshinPlayer sender, Object message) { public void sendMessage(Player sender, Object message) {
this.sendPacket(new PacketPrivateChatNotify(sender.getUid(), this.getUid(), message.toString())); this.sendPacket(new PacketPrivateChatNotify(sender.getUid(), this.getUid(), message.toString()));
} }
// ---------------------MAIL------------------------
public List<Mail> getAllMail() { return this.mail; }
public void sendMail(Mail message) {
this.mail.add(message);
this.save();
Grasscutter.getLogger().info("Mail sent to user [" + this.getUid() + ":" + this.getNickname() + "]!");
if(this.isOnline()) {
this.sendPacket(new PacketMailChangeNotify(this, message));
} // TODO: setup a way for the mail notification to show up when someone receives mail when they were offline
}
public boolean deleteMail(int mailId) {
Mail message = getMail(mailId);
if(message != null) {
int index = getMailId(message);
message.expireTime = (int) Instant.now().getEpochSecond(); // Just set the mail as expired for now. I don't want to implement a counter specifically for an account...
this.replaceMailByIndex(index, message);
return true;
}
return false;
}
public Mail getMail(int index) { return this.mail.get(index); }
public int getMailId(Mail message) {
return this.mail.indexOf(message);
}
public boolean replaceMailByIndex(int index, Mail message) {
if(getMail(index) != null) {
this.mail.set(index, message);
this.save();
return true;
} else {
return false;
}
}
public void interactWith(int gadgetEntityId) { public void interactWith(int gadgetEntityId) {
GenshinEntity entity = getScene().getEntityById(gadgetEntityId); GameEntity entity = getScene().getEntityById(gadgetEntityId);
if (entity == null) { if (entity == null) {
return; return;
...@@ -583,12 +721,11 @@ public class GenshinPlayer { ...@@ -583,12 +721,11 @@ public class GenshinPlayer {
if (entity instanceof EntityItem) { if (entity instanceof EntityItem) {
// Pick item // Pick item
EntityItem drop = (EntityItem) entity; EntityItem drop = (EntityItem) entity;
GenshinItem item = new GenshinItem(drop.getItemData(), drop.getCount()); GameItem item = new GameItem(drop.getItemData(), drop.getCount());
// Add to inventory // Add to inventory
boolean success = getInventory().addItem(item); boolean success = getInventory().addItem(item, ActionReason.SubfieldDrop);
if (success) { if (success) {
this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.InteractPickItem)); this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_PICK_ITEM));
this.sendPacket(new PacketItemAddHintNotify(item, ActionReason.SubfieldDrop));
} }
} }
...@@ -603,7 +740,7 @@ public class GenshinPlayer { ...@@ -603,7 +740,7 @@ public class GenshinPlayer {
} }
public void sendPacket(GenshinPacket packet) { public void sendPacket(BasePacket packet) {
if (this.hasSentAvatarDataNotify) { if (this.hasSentAvatarDataNotify) {
this.getSession().send(packet); this.getSession().send(packet);
} }
...@@ -617,7 +754,7 @@ public class GenshinPlayer { ...@@ -617,7 +754,7 @@ public class GenshinPlayer {
.setMpSettingType(this.getMpSetting()) .setMpSettingType(this.getMpSetting())
.setNameCardId(this.getNameCardId()) .setNameCardId(this.getNameCardId())
.setSignature(this.getSignature()) .setSignature(this.getSignature())
.setAvatar(HeadImage.newBuilder().setAvatarId(this.getHeadImage())); .setAvatarId(HeadImage.newBuilder().setAvatarId(this.getHeadImage()).getAvatarId());
if (this.getWorld() != null) { if (this.getWorld() != null) {
onlineInfo.setCurPlayerNumInWorld(this.getWorld().getPlayers().indexOf(this) + 1); onlineInfo.setCurPlayerNumInWorld(this.getWorld().getPlayers().indexOf(this) + 1);
...@@ -652,21 +789,19 @@ public class GenshinPlayer { ...@@ -652,21 +789,19 @@ public class GenshinPlayer {
public SocialDetail.Builder getSocialDetail() { public SocialDetail.Builder getSocialDetail() {
SocialDetail.Builder social = SocialDetail.newBuilder() SocialDetail.Builder social = SocialDetail.newBuilder()
.setUid(this.getUid()) .setUid(this.getUid())
.setAvatar(HeadImage.newBuilder().setAvatarId(this.getHeadImage())) .setAvatarId(HeadImage.newBuilder().setAvatarId(this.getHeadImage()).getAvatarId())
.setNickname(this.getNickname()) .setNickname(this.getNickname())
.setSignature(this.getSignature()) .setSignature(this.getSignature())
.setLevel(this.getLevel()) .setLevel(this.getLevel())
.setBirthday(this.getBirthday().getFilledProtoWhenNotEmpty()) .setBirthday(this.getBirthday().getFilledProtoWhenNotEmpty())
.setWorldLevel(this.getWorldLevel()) .setWorldLevel(this.getWorldLevel())
.setUnk1(1)
.setUnk3(1)
.setNameCardId(this.getNameCardId()) .setNameCardId(this.getNameCardId())
.setFinishAchievementNum(0); .setFinishAchievementNum(0);
return social; return social;
} }
public WorldPlayerLocationInfo getWorldPlayerLocationInfo() { public PlayerWorldLocationInfoOuterClass.PlayerWorldLocationInfo getWorldPlayerLocationInfo() {
return WorldPlayerLocationInfo.newBuilder() return PlayerWorldLocationInfoOuterClass.PlayerWorldLocationInfo.newBuilder()
.setSceneId(this.getSceneId()) .setSceneId(this.getSceneId())
.setPlayerLoc(this.getPlayerLocationInfo()) .setPlayerLoc(this.getPlayerLocationInfo())
.build(); .build();
...@@ -691,7 +826,7 @@ public class GenshinPlayer { ...@@ -691,7 +826,7 @@ public class GenshinPlayer {
while (it.hasNext()) { while (it.hasNext()) {
CoopRequest req = it.next(); CoopRequest req = it.next();
if (req.isExpired()) { if (req.isExpired()) {
req.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(this, false, PlayerApplyEnterMpReason.SystemJudge)); req.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(this, false, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.SYSTEM_JUDGE));
it.remove(); it.remove();
} }
} }
...@@ -734,7 +869,7 @@ public class GenshinPlayer { ...@@ -734,7 +869,7 @@ public class GenshinPlayer {
// Check if player object exists in server // Check if player object exists in server
// TODO - optimize // TODO - optimize
GenshinPlayer exists = this.getServer().getPlayerByUid(getUid()); Player exists = this.getServer().getPlayerByUid(getUid());
if (exists != null) { if (exists != null) {
exists.getSession().close(); exists.getSession().close();
} }
......
package emu.grasscutter.game; package emu.grasscutter.game.player;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import dev.morphia.annotations.Entity; import dev.morphia.annotations.Entity;
import emu.grasscutter.GenshinConstants; import emu.grasscutter.GameConstants;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.avatar.GenshinAvatar; import emu.grasscutter.game.avatar.Avatar;
@Entity @Entity
public class TeamInfo { public class TeamInfo {
...@@ -34,11 +34,11 @@ public class TeamInfo { ...@@ -34,11 +34,11 @@ public class TeamInfo {
return avatars.size(); return avatars.size();
} }
public boolean contains(GenshinAvatar avatar) { public boolean contains(Avatar avatar) {
return getAvatars().contains(avatar.getAvatarId()); return getAvatars().contains(avatar.getAvatarId());
} }
public boolean addAvatar(GenshinAvatar avatar) { public boolean addAvatar(Avatar avatar) {
if (size() >= Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam || contains(avatar)) { if (size() >= Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam || contains(avatar)) {
return false; return false;
} }
......
package emu.grasscutter.game; package emu.grasscutter.game.player;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
...@@ -10,16 +10,17 @@ import java.util.Set; ...@@ -10,16 +10,17 @@ import java.util.Set;
import dev.morphia.annotations.Entity; import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Transient; import dev.morphia.annotations.Transient;
import emu.grasscutter.GenshinConstants; import emu.grasscutter.GameConstants;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.def.AvatarSkillDepotData; import emu.grasscutter.data.def.AvatarSkillDepotData;
import emu.grasscutter.game.avatar.GenshinAvatar; import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.props.ElementType; import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.game.props.EnterReason; import emu.grasscutter.game.props.EnterReason;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.game.world.World;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType;
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
...@@ -44,7 +45,7 @@ import it.unimi.dsi.fastutil.ints.IntSet; ...@@ -44,7 +45,7 @@ import it.unimi.dsi.fastutil.ints.IntSet;
@Entity @Entity
public class TeamManager { public class TeamManager {
@Transient private GenshinPlayer player; @Transient private Player player;
private Map<Integer, TeamInfo> teams; private Map<Integer, TeamInfo> teams;
private int currentTeamIndex; private int currentTeamIndex;
...@@ -65,18 +66,18 @@ public class TeamManager { ...@@ -65,18 +66,18 @@ public class TeamManager {
this.teamResonancesConfig = new IntOpenHashSet(); this.teamResonancesConfig = new IntOpenHashSet();
} }
public TeamManager(GenshinPlayer player) { public TeamManager(Player player) {
this(); this();
this.player = player; this.player = player;
this.teams = new HashMap<>(); this.teams = new HashMap<>();
this.currentTeamIndex = 1; this.currentTeamIndex = 1;
for (int i = 1; i <= GenshinConstants.MAX_TEAMS; i++) { for (int i = 1; i <= GameConstants.MAX_TEAMS; i++) {
this.teams.put(i, new TeamInfo()); this.teams.put(i, new TeamInfo());
} }
} }
public GenshinPlayer getPlayer() { public Player getPlayer() {
return player; return player;
} }
...@@ -84,7 +85,7 @@ public class TeamManager { ...@@ -84,7 +85,7 @@ public class TeamManager {
return player.getWorld(); return player.getWorld();
} }
public void setPlayer(GenshinPlayer player) { public void setPlayer(Player player) {
this.player = player; this.player = player;
} }
...@@ -207,7 +208,7 @@ public class TeamManager { ...@@ -207,7 +208,7 @@ public class TeamManager {
} }
} }
public void updateTeamEntities(GenshinPacket responsePacket) { public void updateTeamEntities(BasePacket responsePacket) {
// Sanity check - Should never happen // Sanity check - Should never happen
if (this.getCurrentTeamInfo().getAvatars().size() <= 0) { if (this.getCurrentTeamInfo().getAvatars().size() <= 0) {
return; return;
...@@ -287,9 +288,9 @@ public class TeamManager { ...@@ -287,9 +288,9 @@ public class TeamManager {
} }
// Set team data // Set team data
LinkedHashSet<GenshinAvatar> newTeam = new LinkedHashSet<>(); LinkedHashSet<Avatar> newTeam = new LinkedHashSet<>();
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
GenshinAvatar avatar = getPlayer().getAvatars().getAvatarByGuid(list.get(i)); Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(list.get(i));
if (avatar == null || newTeam.contains(avatar)) { if (avatar == null || newTeam.contains(avatar)) {
// Should never happen // Should never happen
return; return;
...@@ -299,7 +300,7 @@ public class TeamManager { ...@@ -299,7 +300,7 @@ public class TeamManager {
// Clear current team info and add avatars from our new team // Clear current team info and add avatars from our new team
teamInfo.getAvatars().clear(); teamInfo.getAvatars().clear();
for (GenshinAvatar avatar : newTeam) { for (Avatar avatar : newTeam) {
teamInfo.addAvatar(avatar); teamInfo.addAvatar(avatar);
} }
...@@ -323,9 +324,9 @@ public class TeamManager { ...@@ -323,9 +324,9 @@ public class TeamManager {
TeamInfo teamInfo = this.getMpTeam(); TeamInfo teamInfo = this.getMpTeam();
// Set team data // Set team data
LinkedHashSet<GenshinAvatar> newTeam = new LinkedHashSet<>(); LinkedHashSet<Avatar> newTeam = new LinkedHashSet<>();
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
GenshinAvatar avatar = getPlayer().getAvatars().getAvatarByGuid(list.get(i)); Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(list.get(i));
if (avatar == null || newTeam.contains(avatar)) { if (avatar == null || newTeam.contains(avatar)) {
// Should never happen // Should never happen
return; return;
...@@ -335,7 +336,7 @@ public class TeamManager { ...@@ -335,7 +336,7 @@ public class TeamManager {
// Clear current team info and add avatars from our new team // Clear current team info and add avatars from our new team
teamInfo.getAvatars().clear(); teamInfo.getAvatars().clear();
for (GenshinAvatar avatar : newTeam) { for (Avatar avatar : newTeam) {
teamInfo.addAvatar(avatar); teamInfo.addAvatar(avatar);
} }
...@@ -397,7 +398,7 @@ public class TeamManager { ...@@ -397,7 +398,7 @@ public class TeamManager {
this.setCurrentCharacterIndex(index); this.setCurrentCharacterIndex(index);
// Old entity motion state // Old entity motion state
oldEntity.setMotionState(MotionState.MotionStandby); oldEntity.setMotionState(MotionState.MOTION_STANDBY);
// Remove and Add // Remove and Add
getPlayer().getScene().replaceEntity(oldEntity, newEntity); getPlayer().getScene().replaceEntity(oldEntity, newEntity);
...@@ -437,7 +438,7 @@ public class TeamManager { ...@@ -437,7 +438,7 @@ public class TeamManager {
getPlayer().sendPacket(new PacketAvatarDieAnimationEndRsp(deadAvatar.getId(), 0)); getPlayer().sendPacket(new PacketAvatarDieAnimationEndRsp(deadAvatar.getId(), 0));
} }
public boolean reviveAvatar(GenshinAvatar avatar) { public boolean reviveAvatar(Avatar avatar) {
for (EntityAvatar entity : getActiveTeam()) { for (EntityAvatar entity : getActiveTeam()) {
if (entity.getAvatar() == avatar) { if (entity.getAvatar() == avatar) {
if (entity.isAlive()) { if (entity.isAlive()) {
...@@ -476,14 +477,14 @@ public class TeamManager { ...@@ -476,14 +477,14 @@ public class TeamManager {
} }
// Teleport player // Teleport player
getPlayer().sendPacket(new PacketPlayerEnterSceneNotify(getPlayer(), EnterType.EnterSelf, EnterReason.Revival, 3, GenshinConstants.START_POSITION)); getPlayer().sendPacket(new PacketPlayerEnterSceneNotify(getPlayer(), EnterType.ENTER_SELF, EnterReason.Revival, 3, GameConstants.START_POSITION));
// Set player position // Set player position
player.setSceneId(3); player.setSceneId(3);
player.getPos().set(GenshinConstants.START_POSITION); player.getPos().set(GameConstants.START_POSITION);
// Packets // Packets
getPlayer().sendPacket(new GenshinPacket(PacketOpcodes.WorldPlayerReviveRsp)); getPlayer().sendPacket(new BasePacket(PacketOpcodes.WorldPlayerReviveRsp));
} }
public void saveAvatars() { public void saveAvatars() {
......
package emu.grasscutter.game; package emu.grasscutter.game.world;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
...@@ -12,9 +12,9 @@ import java.util.Set; ...@@ -12,9 +12,9 @@ import java.util.Set;
import org.danilopianini.util.SpatialIndex; import org.danilopianini.util.SpatialIndex;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GenshinData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.GenshinDepot; import emu.grasscutter.data.GameDepot;
import emu.grasscutter.data.GenshinResource; import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.def.MonsterData; import emu.grasscutter.data.def.MonsterData;
import emu.grasscutter.data.def.SceneData; import emu.grasscutter.data.def.SceneData;
import emu.grasscutter.data.def.WorldLevelData; import emu.grasscutter.data.def.WorldLevelData;
...@@ -22,14 +22,15 @@ import emu.grasscutter.game.entity.EntityAvatar; ...@@ -22,14 +22,15 @@ import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.entity.EntityClientGadget; import emu.grasscutter.game.entity.EntityClientGadget;
import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.entity.EntityMonster; import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.entity.GenshinEntity; import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.player.TeamInfo;
import emu.grasscutter.game.props.ClimateType; import emu.grasscutter.game.props.ClimateType;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.LifeState; import emu.grasscutter.game.props.LifeState;
import emu.grasscutter.game.props.SceneType; import emu.grasscutter.game.props.SceneType;
import emu.grasscutter.game.world.SpawnDataEntry;
import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry; import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult;
import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
...@@ -41,11 +42,11 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; ...@@ -41,11 +42,11 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class GenshinScene { public class Scene {
private final World world; private final World world;
private final SceneData sceneData; private final SceneData sceneData;
private final List<GenshinPlayer> players; private final List<Player> players;
private final Int2ObjectMap<GenshinEntity> entities; private final Int2ObjectMap<GameEntity> entities;
private final Set<SpawnDataEntry> spawnedEntities; private final Set<SpawnDataEntry> spawnedEntities;
private final Set<SpawnDataEntry> deadSpawnedEntities; private final Set<SpawnDataEntry> deadSpawnedEntities;
...@@ -55,7 +56,7 @@ public class GenshinScene { ...@@ -55,7 +56,7 @@ public class GenshinScene {
private ClimateType climate; private ClimateType climate;
private int weather; private int weather;
public GenshinScene(World world, SceneData sceneData) { public Scene(World world, SceneData sceneData) {
this.world = world; this.world = world;
this.sceneData = sceneData; this.sceneData = sceneData;
this.players = Collections.synchronizedList(new ArrayList<>()); this.players = Collections.synchronizedList(new ArrayList<>());
...@@ -84,7 +85,7 @@ public class GenshinScene { ...@@ -84,7 +85,7 @@ public class GenshinScene {
return getSceneData().getSceneType(); return getSceneData().getSceneType();
} }
public List<GenshinPlayer> getPlayers() { public List<Player> getPlayers() {
return players; return players;
} }
...@@ -92,11 +93,11 @@ public class GenshinScene { ...@@ -92,11 +93,11 @@ public class GenshinScene {
return this.getPlayers().size(); return this.getPlayers().size();
} }
public Int2ObjectMap<GenshinEntity> getEntities() { public Int2ObjectMap<GameEntity> getEntities() {
return entities; return entities;
} }
public GenshinEntity getEntityById(int id) { public GameEntity getEntityById(int id) {
return this.entities.get(id); return this.entities.get(id);
} }
...@@ -140,11 +141,11 @@ public class GenshinScene { ...@@ -140,11 +141,11 @@ public class GenshinScene {
return deadSpawnedEntities; return deadSpawnedEntities;
} }
public boolean isInScene(GenshinEntity entity) { public boolean isInScene(GameEntity entity) {
return this.entities.containsKey(entity.getId()); return this.entities.containsKey(entity.getId());
} }
public synchronized void addPlayer(GenshinPlayer player) { public synchronized void addPlayer(Player player) {
// Check if player already in // Check if player already in
if (getPlayers().contains(player)) { if (getPlayers().contains(player)) {
return; return;
...@@ -163,7 +164,7 @@ public class GenshinScene { ...@@ -163,7 +164,7 @@ public class GenshinScene {
this.setupPlayerAvatars(player); this.setupPlayerAvatars(player);
} }
public synchronized void removePlayer(GenshinPlayer player) { public synchronized void removePlayer(Player player) {
// Remove player from scene // Remove player from scene
getPlayers().remove(player); getPlayers().remove(player);
player.setScene(null); player.setScene(null);
...@@ -182,7 +183,7 @@ public class GenshinScene { ...@@ -182,7 +183,7 @@ public class GenshinScene {
} }
} }
private void setupPlayerAvatars(GenshinPlayer player) { private void setupPlayerAvatars(Player player) {
// Clear entities from old team // Clear entities from old team
player.getTeamManager().getActiveTeam().clear(); player.getTeamManager().getActiveTeam().clear();
...@@ -199,15 +200,15 @@ public class GenshinScene { ...@@ -199,15 +200,15 @@ public class GenshinScene {
} }
} }
private void removePlayerAvatars(GenshinPlayer player) { private void removePlayerAvatars(Player player) {
Iterator<EntityAvatar> it = player.getTeamManager().getActiveTeam().iterator(); Iterator<EntityAvatar> it = player.getTeamManager().getActiveTeam().iterator();
while (it.hasNext()) { while (it.hasNext()) {
this.removeEntity(it.next(), VisionType.VisionRemove); this.removeEntity(it.next(), VisionType.VISION_REMOVE);
it.remove(); it.remove();
} }
} }
public void spawnPlayer(GenshinPlayer player) { public void spawnPlayer(Player player) {
if (this.isInScene(player.getTeamManager().getCurrentAvatarEntity())) { if (this.isInScene(player.getTeamManager().getCurrentAvatarEntity())) {
return; return;
} }
...@@ -219,33 +220,33 @@ public class GenshinScene { ...@@ -219,33 +220,33 @@ public class GenshinScene {
this.addEntity(player.getTeamManager().getCurrentAvatarEntity()); this.addEntity(player.getTeamManager().getCurrentAvatarEntity());
} }
private void addEntityDirectly(GenshinEntity entity) { private void addEntityDirectly(GameEntity entity) {
getEntities().put(entity.getId(), entity); getEntities().put(entity.getId(), entity);
} }
public synchronized void addEntity(GenshinEntity entity) { public synchronized void addEntity(GameEntity entity) {
this.addEntityDirectly(entity); this.addEntityDirectly(entity);
this.broadcastPacket(new PacketSceneEntityAppearNotify(entity)); this.broadcastPacket(new PacketSceneEntityAppearNotify(entity));
} }
public synchronized void addEntities(Collection<GenshinEntity> entities) { public synchronized void addEntities(Collection<GameEntity> entities) {
for (GenshinEntity entity : entities) { for (GameEntity entity : entities) {
this.addEntityDirectly(entity); this.addEntityDirectly(entity);
} }
this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VisionBorn)); this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_BORN));
} }
private GenshinEntity removeEntityDirectly(GenshinEntity entity) { private GameEntity removeEntityDirectly(GameEntity entity) {
return getEntities().remove(entity.getId()); return getEntities().remove(entity.getId());
} }
public void removeEntity(GenshinEntity entity) { public void removeEntity(GameEntity entity) {
this.removeEntity(entity, VisionType.VisionDie); this.removeEntity(entity, VisionType.VISION_DIE);
} }
public synchronized void removeEntity(GenshinEntity entity, VisionType visionType) { public synchronized void removeEntity(GameEntity entity, VisionType visionType) {
GenshinEntity removed = this.removeEntityDirectly(entity); GameEntity removed = this.removeEntityDirectly(entity);
if (removed != null) { if (removed != null) {
this.broadcastPacket(new PacketSceneEntityDisappearNotify(removed, visionType)); this.broadcastPacket(new PacketSceneEntityDisappearNotify(removed, visionType));
} }
...@@ -254,27 +255,27 @@ public class GenshinScene { ...@@ -254,27 +255,27 @@ public class GenshinScene {
public synchronized void replaceEntity(EntityAvatar oldEntity, EntityAvatar newEntity) { public synchronized void replaceEntity(EntityAvatar oldEntity, EntityAvatar newEntity) {
this.removeEntityDirectly(oldEntity); this.removeEntityDirectly(oldEntity);
this.addEntityDirectly(newEntity); this.addEntityDirectly(newEntity);
this.broadcastPacket(new PacketSceneEntityDisappearNotify(oldEntity, VisionType.VisionReplace)); this.broadcastPacket(new PacketSceneEntityDisappearNotify(oldEntity, VisionType.VISION_REPLACE));
this.broadcastPacket(new PacketSceneEntityAppearNotify(newEntity, VisionType.VisionReplace, oldEntity.getId())); this.broadcastPacket(new PacketSceneEntityAppearNotify(newEntity, VisionType.VISION_REPLACE, oldEntity.getId()));
} }
public void showOtherEntities(GenshinPlayer player) { public void showOtherEntities(Player player) {
List<GenshinEntity> entities = new LinkedList<>(); List<GameEntity> entities = new LinkedList<>();
GenshinEntity currentEntity = player.getTeamManager().getCurrentAvatarEntity(); GameEntity currentEntity = player.getTeamManager().getCurrentAvatarEntity();
for (GenshinEntity entity : this.getEntities().values()) { for (GameEntity entity : this.getEntities().values()) {
if (entity == currentEntity) { if (entity == currentEntity) {
continue; continue;
} }
entities.add(entity); entities.add(entity);
} }
player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VisionMeet)); player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_MEET));
} }
public void handleAttack(AttackResult result) { public void handleAttack(AttackResult result) {
//GenshinEntity attacker = getEntityById(result.getAttackerId()); //GameEntity attacker = getEntityById(result.getAttackerId());
GenshinEntity target = getEntityById(result.getDefenseId()); GameEntity target = getEntityById(result.getDefenseId());
if (target == null) { if (target == null) {
return; return;
...@@ -306,7 +307,7 @@ public class GenshinScene { ...@@ -306,7 +307,7 @@ public class GenshinScene {
} }
} }
public void killEntity(GenshinEntity target, int attackerId) { public void killEntity(GameEntity target, int attackerId) {
// Packet // Packet
this.broadcastPacket(new PacketLifeStateChangeNotify(attackerId, target, LifeState.LIFE_DEAD)); this.broadcastPacket(new PacketLifeStateChangeNotify(attackerId, target, LifeState.LIFE_DEAD));
this.removeEntity(target); this.removeEntity(target);
...@@ -321,10 +322,10 @@ public class GenshinScene { ...@@ -321,10 +322,10 @@ public class GenshinScene {
// TODO - Test // TODO - Test
public void checkSpawns() { public void checkSpawns() {
SpatialIndex<SpawnGroupEntry> list = GenshinDepot.getSpawnListById(this.getId()); SpatialIndex<SpawnGroupEntry> list = GameDepot.getSpawnListById(this.getId());
Set<SpawnDataEntry> visible = new HashSet<>(); Set<SpawnDataEntry> visible = new HashSet<>();
for (GenshinPlayer player : this.getPlayers()) { for (Player player : this.getPlayers()) {
int RANGE = 100; int RANGE = 100;
Collection<SpawnGroupEntry> entries = list.query( Collection<SpawnGroupEntry> entries = list.query(
new double[] {player.getPos().getX() - RANGE, player.getPos().getZ() - RANGE}, new double[] {player.getPos().getX() - RANGE, player.getPos().getZ() - RANGE},
...@@ -339,7 +340,7 @@ public class GenshinScene { ...@@ -339,7 +340,7 @@ public class GenshinScene {
} }
// World level // World level
WorldLevelData worldLevelData = GenshinData.getWorldLevelDataMap().get(getWorld().getWorldLevel()); WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(getWorld().getWorldLevel());
int worldLevelOverride = 0; int worldLevelOverride = 0;
if (worldLevelData != null) { if (worldLevelData != null) {
...@@ -347,13 +348,13 @@ public class GenshinScene { ...@@ -347,13 +348,13 @@ public class GenshinScene {
} }
// Todo // Todo
List<GenshinEntity> toAdd = new LinkedList<>(); List<GameEntity> toAdd = new LinkedList<>();
List<GenshinEntity> toRemove = new LinkedList<>(); List<GameEntity> toRemove = new LinkedList<>();
for (SpawnDataEntry entry : visible) { for (SpawnDataEntry entry : visible) {
if (!this.getSpawnedEntities().contains(entry) && !this.getDeadSpawnedEntities().contains(entry)) { if (!this.getSpawnedEntities().contains(entry) && !this.getDeadSpawnedEntities().contains(entry)) {
// Spawn entity // Spawn entity
MonsterData data = GenshinData.getMonsterDataMap().get(entry.getMonsterId()); MonsterData data = GameData.getMonsterDataMap().get(entry.getMonsterId());
if (data == null) { if (data == null) {
continue; continue;
...@@ -373,7 +374,7 @@ public class GenshinScene { ...@@ -373,7 +374,7 @@ public class GenshinScene {
} }
} }
for (GenshinEntity entity : this.getEntities().values()) { for (GameEntity entity : this.getEntities().values()) {
if (entity.getSpawnEntry() != null && !visible.contains(entity.getSpawnEntry())) { if (entity.getSpawnEntry() != null && !visible.contains(entity.getSpawnEntry())) {
toRemove.add(entity); toRemove.add(entity);
} }
...@@ -381,11 +382,11 @@ public class GenshinScene { ...@@ -381,11 +382,11 @@ public class GenshinScene {
if (toAdd.size() > 0) { if (toAdd.size() > 0) {
toAdd.stream().forEach(this::addEntityDirectly); toAdd.stream().forEach(this::addEntityDirectly);
this.broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VisionBorn)); this.broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VISION_BORN));
} }
if (toRemove.size() > 0) { if (toRemove.size() > 0) {
toRemove.stream().forEach(this::removeEntityDirectly); toRemove.stream().forEach(this::removeEntityDirectly);
this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VisionRemove)); this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_REMOVE));
} }
} }
...@@ -407,7 +408,7 @@ public class GenshinScene { ...@@ -407,7 +408,7 @@ public class GenshinScene {
} }
public void onPlayerDestroyGadget(int entityId) { public void onPlayerDestroyGadget(int entityId) {
GenshinEntity entity = getEntities().get(entityId); GameEntity entity = getEntities().get(entityId);
if (entity == null || !(entity instanceof EntityClientGadget)) { if (entity == null || !(entity instanceof EntityClientGadget)) {
return; return;
...@@ -425,25 +426,25 @@ public class GenshinScene { ...@@ -425,25 +426,25 @@ public class GenshinScene {
return; return;
} }
this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityDisappearNotify(gadget, VisionType.VisionDie)); this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityDisappearNotify(gadget, VisionType.VISION_DIE));
} }
// Broadcasting // Broadcasting
public void broadcastPacket(GenshinPacket packet) { public void broadcastPacket(BasePacket packet) {
// Send to all players - might have to check if player has been sent data packets // Send to all players - might have to check if player has been sent data packets
for (GenshinPlayer player : this.getPlayers()) { for (Player player : this.getPlayers()) {
player.getSession().send(packet); player.getSession().send(packet);
} }
} }
public void broadcastPacketToOthers(GenshinPlayer excludedPlayer, GenshinPacket packet) { public void broadcastPacketToOthers(Player excludedPlayer, BasePacket packet) {
// Optimization // Optimization
if (this.getPlayerCount() == 1 && this.getPlayers().get(0) == excludedPlayer) { if (this.getPlayerCount() == 1 && this.getPlayers().get(0) == excludedPlayer) {
return; return;
} }
// Send to all players - might have to check if player has been sent data packets // Send to all players - might have to check if player has been sent data packets
for (GenshinPlayer player : this.getPlayers()) { for (Player player : this.getPlayers()) {
if (player == excludedPlayer) { if (player == excludedPlayer) {
continue; continue;
} }
......
package emu.grasscutter.game; package emu.grasscutter.game.world;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
...@@ -8,19 +8,20 @@ import java.util.LinkedList; ...@@ -8,19 +8,20 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import emu.grasscutter.game.entity.GenshinEntity; import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.player.Player.SceneLoadState;
import emu.grasscutter.game.props.ClimateType; import emu.grasscutter.game.props.ClimateType;
import emu.grasscutter.game.props.EnterReason; import emu.grasscutter.game.props.EnterReason;
import emu.grasscutter.game.props.EntityIdType; import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.LifeState; import emu.grasscutter.game.props.LifeState;
import emu.grasscutter.data.GenshinData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.SceneData; import emu.grasscutter.data.def.SceneData;
import emu.grasscutter.game.GenshinPlayer.SceneLoadState;
import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.entity.EntityClientGadget; import emu.grasscutter.game.entity.EntityClientGadget;
import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult;
import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType;
import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType;
...@@ -40,10 +41,10 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; ...@@ -40,10 +41,10 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class World implements Iterable<GenshinPlayer> { public class World implements Iterable<Player> {
private final GenshinPlayer owner; private final Player owner;
private final List<GenshinPlayer> players; private final List<Player> players;
private final Int2ObjectMap<GenshinScene> scenes; private final Int2ObjectMap<Scene> scenes;
private int levelEntityId; private int levelEntityId;
private int nextEntityId = 0; private int nextEntityId = 0;
...@@ -52,11 +53,11 @@ public class World implements Iterable<GenshinPlayer> { ...@@ -52,11 +53,11 @@ public class World implements Iterable<GenshinPlayer> {
private boolean isMultiplayer; private boolean isMultiplayer;
public World(GenshinPlayer player) { public World(Player player) {
this(player, false); this(player, false);
} }
public World(GenshinPlayer player, boolean isMultiplayer) { public World(Player player, boolean isMultiplayer) {
this.owner = player; this.owner = player;
this.players = Collections.synchronizedList(new ArrayList<>()); this.players = Collections.synchronizedList(new ArrayList<>());
this.scenes = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>()); this.scenes = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
...@@ -64,11 +65,11 @@ public class World implements Iterable<GenshinPlayer> { ...@@ -64,11 +65,11 @@ public class World implements Iterable<GenshinPlayer> {
this.levelEntityId = getNextEntityId(EntityIdType.MPLEVEL); this.levelEntityId = getNextEntityId(EntityIdType.MPLEVEL);
this.worldLevel = player.getWorldLevel(); this.worldLevel = player.getWorldLevel();
this.isMultiplayer = isMultiplayer; this.isMultiplayer = isMultiplayer;
this.owner.getServer().registerWorld(this); this.owner.getServer().registerWorld(this);
} }
public GenshinPlayer getHost() { public Player getHost() {
return owner; return owner;
} }
...@@ -95,25 +96,25 @@ public class World implements Iterable<GenshinPlayer> { ...@@ -95,25 +96,25 @@ public class World implements Iterable<GenshinPlayer> {
this.worldLevel = worldLevel; this.worldLevel = worldLevel;
} }
public List<GenshinPlayer> getPlayers() { public List<Player> getPlayers() {
return players; return players;
} }
public Int2ObjectMap<GenshinScene> getScenes() { public Int2ObjectMap<Scene> getScenes() {
return this.scenes; return this.scenes;
} }
public GenshinScene getSceneById(int sceneId) { public Scene getSceneById(int sceneId) {
// Get scene normally // Get scene normally
GenshinScene scene = getScenes().get(sceneId); Scene scene = getScenes().get(sceneId);
if (scene != null) { if (scene != null) {
return scene; return scene;
} }
// Create scene from scene data if it doesnt exist // Create scene from scene data if it doesnt exist
SceneData sceneData = GenshinData.getSceneDataMap().get(sceneId); SceneData sceneData = GameData.getSceneDataMap().get(sceneId);
if (sceneData != null) { if (sceneData != null) {
scene = new GenshinScene(this, sceneData); scene = new Scene(this, sceneData);
this.registerScene(scene); this.registerScene(scene);
return scene; return scene;
} }
...@@ -133,7 +134,7 @@ public class World implements Iterable<GenshinPlayer> { ...@@ -133,7 +134,7 @@ public class World implements Iterable<GenshinPlayer> {
return (idType.getId() << 24) + ++this.nextEntityId; return (idType.getId() << 24) + ++this.nextEntityId;
} }
public synchronized void addPlayer(GenshinPlayer player) { public synchronized void addPlayer(Player player) {
// Check if player already in // Check if player already in
if (getPlayers().contains(player)) { if (getPlayers().contains(player)) {
return; return;
...@@ -159,7 +160,7 @@ public class World implements Iterable<GenshinPlayer> { ...@@ -159,7 +160,7 @@ public class World implements Iterable<GenshinPlayer> {
} }
// Add to scene // Add to scene
GenshinScene scene = this.getSceneById(player.getSceneId()); Scene scene = this.getSceneById(player.getSceneId());
scene.addPlayer(player); scene.addPlayer(player);
// Info packet for other players // Info packet for other players
...@@ -168,7 +169,7 @@ public class World implements Iterable<GenshinPlayer> { ...@@ -168,7 +169,7 @@ public class World implements Iterable<GenshinPlayer> {
} }
} }
public synchronized void removePlayer(GenshinPlayer player) { public synchronized void removePlayer(Player player) {
// Remove team entities // Remove team entities
player.sendPacket( player.sendPacket(
new PacketDelTeamEntityNotify( new PacketDelTeamEntityNotify(
...@@ -182,7 +183,7 @@ public class World implements Iterable<GenshinPlayer> { ...@@ -182,7 +183,7 @@ public class World implements Iterable<GenshinPlayer> {
player.setWorld(null); player.setWorld(null);
// Remove from scene // Remove from scene
GenshinScene scene = this.getSceneById(player.getSceneId()); Scene scene = this.getSceneById(player.getSceneId());
scene.removePlayer(player); scene.removePlayer(player);
// Info packet for other players // Info packet for other players
...@@ -192,61 +193,61 @@ public class World implements Iterable<GenshinPlayer> { ...@@ -192,61 +193,61 @@ public class World implements Iterable<GenshinPlayer> {
// Disband world if host leaves // Disband world if host leaves
if (getHost() == player) { if (getHost() == player) {
List<GenshinPlayer> kicked = new ArrayList<>(this.getPlayers()); List<Player> kicked = new ArrayList<>(this.getPlayers());
for (GenshinPlayer victim : kicked) { for (Player victim : kicked) {
World world = new World(victim); World world = new World(victim);
world.addPlayer(victim); world.addPlayer(victim);
victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.EnterSelf, EnterReason.TeamKick, victim.getSceneId(), victim.getPos())); victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.ENTER_SELF, EnterReason.TeamKick, victim.getSceneId(), victim.getPos()));
} }
} }
} }
public void registerScene(GenshinScene scene) { public void registerScene(Scene scene) {
this.getScenes().put(scene.getId(), scene); this.getScenes().put(scene.getId(), scene);
} }
public void deregisterScene(GenshinScene scene) { public void deregisterScene(Scene scene) {
this.getScenes().remove(scene.getId()); this.getScenes().remove(scene.getId());
} }
public boolean transferPlayerToScene(GenshinPlayer player, int sceneId, Position pos) { public boolean transferPlayerToScene(Player player, int sceneId, Position pos) {
if (GenshinData.getSceneDataMap().get(sceneId) == null) { if (GameData.getSceneDataMap().get(sceneId) == null) {
return false; return false;
} }
GenshinScene oldScene = null; Scene oldScene = null;
if (player.getScene() != null) { if (player.getScene() != null) {
oldScene = player.getScene(); oldScene = player.getScene();
// Dont deregister scenes if the player is going to tp back into them // Dont deregister scenes if the player is going to tp back into them
if (oldScene.getId() == sceneId) { if (oldScene.getId() == sceneId) {
oldScene.setDontDestroyWhenEmpty(true); oldScene.setDontDestroyWhenEmpty(true);
} }
oldScene.removePlayer(player); oldScene.removePlayer(player);
} }
GenshinScene newScene = this.getSceneById(sceneId); Scene newScene = this.getSceneById(sceneId);
newScene.addPlayer(player); newScene.addPlayer(player);
player.getPos().set(pos); player.getPos().set(pos);
if (oldScene != null) { if (oldScene != null) {
oldScene.setDontDestroyWhenEmpty(false); oldScene.setDontDestroyWhenEmpty(false);
} }
// Teleport packet // Teleport packet
if (oldScene == newScene) { if (oldScene == newScene) {
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterGoto, EnterReason.TransPoint, sceneId, pos)); player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.ENTER_GOTO, EnterReason.TransPoint, sceneId, pos));
} else { } else {
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterJump, EnterReason.TransPoint, sceneId, pos)); player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.ENTER_JUMP, EnterReason.TransPoint, sceneId, pos));
} }
return true; return true;
} }
private void updatePlayerInfos(GenshinPlayer paramPlayer) { private void updatePlayerInfos(Player paramPlayer) {
for (GenshinPlayer player : getPlayers()) { for (Player player : getPlayers()) {
// Dont send packets if player is loading in and filter out joining player // Dont send packets if player is loading in and filter out joining player
if (!player.hasSentAvatarDataNotify() || player.getSceneLoadState().getValue() < SceneLoadState.INIT.getValue() || player == paramPlayer) { if (!player.hasSentAvatarDataNotify() || player.getSceneLoadState().getValue() < SceneLoadState.INIT.getValue() || player == paramPlayer) {
continue; continue;
...@@ -269,25 +270,25 @@ public class World implements Iterable<GenshinPlayer> { ...@@ -269,25 +270,25 @@ public class World implements Iterable<GenshinPlayer> {
} }
} }
public void broadcastPacket(GenshinPacket packet) { public void broadcastPacket(BasePacket packet) {
// Send to all players - might have to check if player has been sent data packets // Send to all players - might have to check if player has been sent data packets
for (GenshinPlayer player : this.getPlayers()) { for (Player player : this.getPlayers()) {
player.getSession().send(packet); player.getSession().send(packet);
} }
} }
public void onTick() { public void onTick() {
for (GenshinScene scene : this.getScenes().values()) { for (Scene scene : this.getScenes().values()) {
scene.onTick(); scene.onTick();
} }
} }
public void close() { public void close() {
} }
@Override @Override
public Iterator<GenshinPlayer> iterator() { public Iterator<Player> iterator() {
return getPlayers().iterator(); return getPlayers().iterator();
} }
} }
...@@ -7,7 +7,7 @@ import com.google.protobuf.GeneratedMessageV3; ...@@ -7,7 +7,7 @@ import com.google.protobuf.GeneratedMessageV3;
import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead; import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead;
import emu.grasscutter.utils.Crypto; import emu.grasscutter.utils.Crypto;
public class GenshinPacket { public class BasePacket {
private static final int const1 = 17767; // 0x4567 private static final int const1 = 17767; // 0x4567
private static final int const2 = -30293; // 0x89ab private static final int const2 = -30293; // 0x89ab
...@@ -21,16 +21,16 @@ public class GenshinPacket { ...@@ -21,16 +21,16 @@ public class GenshinPacket {
private boolean useDispatchKey; private boolean useDispatchKey;
public boolean shouldEncrypt = true; public boolean shouldEncrypt = true;
public GenshinPacket(int opcode) { public BasePacket(int opcode) {
this.opcode = opcode; this.opcode = opcode;
} }
public GenshinPacket(int opcode, int clientSequence) { public BasePacket(int opcode, int clientSequence) {
this.opcode = opcode; this.opcode = opcode;
this.buildHeader(clientSequence); this.buildHeader(clientSequence);
} }
public GenshinPacket(int opcode, boolean buildHeader) { public BasePacket(int opcode, boolean buildHeader) {
this.opcode = opcode; this.opcode = opcode;
this.shouldBuildHeader = buildHeader; this.shouldBuildHeader = buildHeader;
} }
...@@ -80,7 +80,7 @@ public class GenshinPacket { ...@@ -80,7 +80,7 @@ public class GenshinPacket {
this.data = proto.build().toByteArray(); this.data = proto.build().toByteArray();
} }
public GenshinPacket buildHeader(int clientSequence) { public BasePacket buildHeader(int clientSequence) {
if (this.getHeader() != null && clientSequence == 0) { if (this.getHeader() != null && clientSequence == 0) {
return this; return this;
} }
......
...@@ -1009,6 +1009,7 @@ public class PacketOpcodes { ...@@ -1009,6 +1009,7 @@ public class PacketOpcodes {
public static final int SetNameCardRsp = 4009; public static final int SetNameCardRsp = 4009;
public static final int SetOpenStateReq = 162; public static final int SetOpenStateReq = 162;
public static final int SetOpenStateRsp = 189; public static final int SetOpenStateRsp = 189;
public static final int SetPlayerBirthdayReq = 4097; public static final int SetPlayerBirthdayReq = 4097;
public static final int SetPlayerBirthdayRsp = 4088; public static final int SetPlayerBirthdayRsp = 4088;
public static final int SetPlayerBornDataReq = 155; public static final int SetPlayerBornDataReq = 155;
...@@ -1034,8 +1035,6 @@ public class PacketOpcodes { ...@@ -1034,8 +1035,6 @@ public class PacketOpcodes {
public static final int ShowTemplateReminderNotify = 3164; public static final int ShowTemplateReminderNotify = 3164;
public static final int SignInInfoReq = 2510; public static final int SignInInfoReq = 2510;
public static final int SignInInfoRsp = 2515; public static final int SignInInfoRsp = 2515;
public static final int SitReq = 354;
public static final int SitRsp = 335;
public static final int SocialDataNotify = 4063; public static final int SocialDataNotify = 4063;
public static final int SpringUseReq = 1720; public static final int SpringUseReq = 1720;
public static final int SpringUseRsp = 1727; public static final int SpringUseRsp = 1727;
......
package emu.grasscutter.net.packet;
public class Retcode {
public static final int SUCCESS = 0;
public static final int FAIL = 1;
}
...@@ -8,7 +8,7 @@ import io.netty.buffer.Unpooled; ...@@ -8,7 +8,7 @@ import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
public abstract class MihoyoKcpChannel extends ChannelInboundHandlerAdapter { public abstract class KcpChannel extends ChannelInboundHandlerAdapter {
private UkcpChannel kcpChannel; private UkcpChannel kcpChannel;
private ChannelHandlerContext ctx; private ChannelHandlerContext ctx;
private boolean isActive; private boolean isActive;
......
...@@ -10,9 +10,9 @@ import io.netty.channel.ChannelMetadata; ...@@ -10,9 +10,9 @@ import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer; import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.nio.AbstractNioMessageChannel; import io.netty.channel.nio.AbstractNioMessageChannel;
public class MihoyoKcpHandshaker extends AbstractNioMessageChannel { public class KcpHandshaker extends AbstractNioMessageChannel {
protected MihoyoKcpHandshaker(Channel parent, SelectableChannel ch, int readInterestOp) { protected KcpHandshaker(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent, ch, readInterestOp); super(parent, ch, readInterestOp);
} }
......
...@@ -13,14 +13,14 @@ import io.netty.channel.EventLoopGroup; ...@@ -13,14 +13,14 @@ import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup;
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public class MihoyoKcpServer extends Thread { public class KcpServer extends Thread {
private EventLoopGroup group; private EventLoopGroup group;
private UkcpServerBootstrap bootstrap; private UkcpServerBootstrap bootstrap;
private ChannelInitializer serverInitializer; private ChannelInitializer serverInitializer;
private InetSocketAddress address; private InetSocketAddress address;
public MihoyoKcpServer(InetSocketAddress address) { public KcpServer(InetSocketAddress address) {
this.address = address; this.address = address;
this.setName("Netty Server Thread"); this.setName("Netty Server Thread");
} }
...@@ -40,7 +40,7 @@ public class MihoyoKcpServer extends Thread { ...@@ -40,7 +40,7 @@ public class MihoyoKcpServer extends Thread {
@Override @Override
public void run() { public void run() {
if (getServerInitializer() == null) { if (getServerInitializer() == null) {
this.setServerInitializer(new MihoyoKcpServerInitializer()); this.setServerInitializer(new KcpServerInitializer());
} }
try { try {
......
...@@ -5,7 +5,7 @@ import io.netty.channel.ChannelInitializer; ...@@ -5,7 +5,7 @@ import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class MihoyoKcpServerInitializer extends ChannelInitializer<UkcpChannel> { public class KcpServerInitializer extends ChannelInitializer<UkcpChannel> {
@Override @Override
protected void initChannel(UkcpChannel ch) throws Exception { protected void initChannel(UkcpChannel ch) throws Exception {
......
...@@ -17,7 +17,7 @@ import java.util.jar.JarEntry; ...@@ -17,7 +17,7 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
/** /**
* Manages the server's plugins & the event system. * Manages the server's plugins and the event system.
*/ */
public final class PluginManager { public final class PluginManager {
private final Map<String, Plugin> plugins = new HashMap<>(); private final Map<String, Plugin> plugins = new HashMap<>();
......
package emu.grasscutter.plugin.api; package emu.grasscutter.plugin.api;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.EnterReason; import emu.grasscutter.game.props.EnterReason;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType;
import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify; import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify;
...@@ -13,16 +13,16 @@ import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify; ...@@ -13,16 +13,16 @@ import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
/** /**
* Hooks into the {@link GenshinPlayer} class, adding convenient ways to do certain things. * Hooks into the {@link Player} class, adding convenient ways to do certain things.
*/ */
public final class PlayerHook { public final class PlayerHook {
private final GenshinPlayer player; private final Player player;
/** /**
* Hooks into the player. * Hooks into the player.
* @param player The player to hook into. * @param player The player to hook into.
*/ */
public PlayerHook(GenshinPlayer player) { public PlayerHook(Player player) {
this.player = player; this.player = player;
} }
...@@ -53,7 +53,7 @@ public final class PlayerHook { ...@@ -53,7 +53,7 @@ public final class PlayerHook {
* Broadcasts the packet sent to all world players. * Broadcasts the packet sent to all world players.
* @param packet The packet to send. * @param packet The packet to send.
*/ */
public void broadcastPacketToWorld(GenshinPacket packet) { public void broadcastPacketToWorld(BasePacket packet) {
this.player.getWorld().broadcastPacket(packet); this.player.getWorld().broadcastPacket(packet);
} }
...@@ -70,7 +70,7 @@ public final class PlayerHook { ...@@ -70,7 +70,7 @@ public final class PlayerHook {
* Revives the specified avatar. * Revives the specified avatar.
* @param avatar The avatar to revive. * @param avatar The avatar to revive.
*/ */
public void reviveAvatar(GenshinAvatar avatar) { public void reviveAvatar(Avatar avatar) {
this.broadcastPacketToWorld(new PacketAvatarLifeStateChangeNotify(avatar)); this.broadcastPacketToWorld(new PacketAvatarLifeStateChangeNotify(avatar));
} }
...@@ -82,7 +82,7 @@ public final class PlayerHook { ...@@ -82,7 +82,7 @@ public final class PlayerHook {
public void teleport(Position position) { public void teleport(Position position) {
this.player.getPos().set(position); this.player.getPos().set(position);
this.player.sendPacket(new PacketPlayerEnterSceneNotify(this.player, this.player.sendPacket(new PacketPlayerEnterSceneNotify(this.player,
EnterType.EnterJump, EnterReason.TransPoint, EnterType.ENTER_JUMP, EnterReason.TransPoint,
this.player.getSceneId(), position this.player.getSceneId(), position
)); ));
} }
...@@ -105,9 +105,9 @@ public final class PlayerHook { ...@@ -105,9 +105,9 @@ public final class PlayerHook {
/** /**
* Gets the currently selected avatar. * Gets the currently selected avatar.
* @return The avatar as an {@link GenshinAvatar}. * @return The avatar as an {@link Avatar}.
*/ */
public GenshinAvatar getCurrentAvatar() { public Avatar getCurrentAvatar() {
return this.getCurrentAvatarEntity().getAvatar(); return this.getCurrentAvatarEntity().getAvatar();
} }
} }
\ No newline at end of file
package emu.grasscutter.plugin.api; package emu.grasscutter.plugin.api;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServer;
import java.util.LinkedList; import java.util.LinkedList;
...@@ -35,7 +35,7 @@ public final class ServerHook { ...@@ -35,7 +35,7 @@ public final class ServerHook {
* Gets all online players. * Gets all online players.
* @return Players connected to the server. * @return Players connected to the server.
*/ */
public List<GenshinPlayer> getOnlinePlayers() { public List<Player> getOnlinePlayers() {
return new LinkedList<>(this.server.getPlayers().values()); return new LinkedList<>(this.server.getPlayers().values());
} }
} }
\ No newline at end of file
...@@ -55,9 +55,14 @@ public final class DispatchServer { ...@@ -55,9 +55,14 @@ public final class DispatchServer {
this.initRegion(); this.initRegion();
} }
@Deprecated
public HttpServer getServer() { public HttpServer getServer() {
return server; return server;
} }
public HttpServer getHttpServer() {
return server;
}
public InetSocketAddress getAddress() { public InetSocketAddress getAddress() {
return address; return address;
...@@ -126,10 +131,10 @@ public final class DispatchServer { ...@@ -126,10 +131,10 @@ public final class DispatchServer {
servers.add(server); servers.add(server);
RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder() RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder()
.setIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty() .setGateserverIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty()
? Grasscutter.getConfig().getGameServerOptions().Ip ? Grasscutter.getConfig().getGameServerOptions().Ip
: Grasscutter.getConfig().getGameServerOptions().PublicIp)) : Grasscutter.getConfig().getGameServerOptions().PublicIp))
.setPort(Grasscutter.getConfig().getGameServerOptions().PublicPort != 0 .setGateserverPort(Grasscutter.getConfig().getGameServerOptions().PublicPort != 0
? Grasscutter.getConfig().getGameServerOptions().PublicPort ? Grasscutter.getConfig().getGameServerOptions().PublicPort
: Grasscutter.getConfig().getGameServerOptions().Port) : Grasscutter.getConfig().getGameServerOptions().Port)
.setSecretKey(ByteString .setSecretKey(ByteString
...@@ -169,8 +174,8 @@ public final class DispatchServer { ...@@ -169,8 +174,8 @@ public final class DispatchServer {
servers.add(server); servers.add(server);
RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder() RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder()
.setIp(regionInfo.Ip) .setGateserverIp(regionInfo.Ip)
.setPort(regionInfo.Port) .setGateserverPort(regionInfo.Port)
.setSecretKey(ByteString .setSecretKey(ByteString
.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin"))) .copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin")))
.build(); .build();
...@@ -181,7 +186,7 @@ public final class DispatchServer { ...@@ -181,7 +186,7 @@ public final class DispatchServer {
} }
QueryRegionListHttpRsp regionList = QueryRegionListHttpRsp.newBuilder() QueryRegionListHttpRsp regionList = QueryRegionListHttpRsp.newBuilder()
.addAllServers(servers) .addAllRegionList(servers)
.setClientSecretKey(rl.getClientSecretKey()) .setClientSecretKey(rl.getClientSecretKey())
.setClientCustomConfigEncrypted(rl.getClientCustomConfigEncrypted()) .setClientCustomConfigEncrypted(rl.getClientCustomConfigEncrypted())
.setEnableLoginPc(true) .setEnableLoginPc(true)
...@@ -203,56 +208,65 @@ public final class DispatchServer { ...@@ -203,56 +208,65 @@ public final class DispatchServer {
} }
return null; return null;
} }
private KeyManagerFactory createKeyManagerFactory(File keystore, String password) throws Exception {
char[] pass = password.toCharArray();
KeyManagerFactory kmf = null;
try (FileInputStream fis = new FileInputStream(keystore)) {
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(fis, pass);
kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, pass);
} catch (Exception e) {
throw e;
}
return kmf;
}
public void start() throws Exception { public void start() throws Exception {
if (Grasscutter.getConfig().getDispatchOptions().UseSSL) { if (Grasscutter.getConfig().getDispatchOptions().UseSSL) {
HttpsServer httpsServer = HttpsServer.create(getAddress(), 0); // Keystore
SSLContext sslContext = SSLContext.getInstance("TLS"); SSLContext sslContext = SSLContext.getInstance("TLS");
try (FileInputStream fis = new FileInputStream(Grasscutter.getConfig().getDispatchOptions().KeystorePath)) { KeyManagerFactory kmf = null;
char[] keystorePassword = Grasscutter.getConfig().getDispatchOptions().KeystorePassword.toCharArray(); File keystoreFile = new File(Grasscutter.getConfig().getDispatchOptions().KeystorePath);
KeyManagerFactory _kmf;
if (keystoreFile.exists()) {
try { try {
KeyStore ks = KeyStore.getInstance("PKCS12"); kmf = createKeyManagerFactory(keystoreFile, Grasscutter.getConfig().getDispatchOptions().KeystorePassword);
ks.load(fis, keystorePassword); } catch (Exception e) {
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); Grasscutter.getLogger().warn("[Dispatch] Unable to load keystore. Trying default keystore password...");
_kmf = kmf;
kmf.init(ks, keystorePassword);
} catch (Exception originalEx) {
try { try {
// try to initialize kmf with the default password kmf = createKeyManagerFactory(keystoreFile, "123456");
char[] defaultPassword = "123456".toCharArray();
Grasscutter.getLogger()
.warn("[Dispatch] Unable to load keystore. Trying default keystore password...");
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(fis, defaultPassword);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, defaultPassword);
_kmf = kmf;
Grasscutter.getLogger().warn( Grasscutter.getLogger().warn(
"[Dispatch] The default keystore password was loaded successfully. Please consider setting the password in config.json."); "[Dispatch] The default keystore password was loaded successfully. Please consider setting the password to 123456 in config.json.");
} catch (Exception ignored) { } catch (Exception e2) {
Grasscutter.getLogger().warn("[Dispatch] Error while loading keystore!"); Grasscutter.getLogger().warn("[Dispatch] Error while loading keystore!");
e2.printStackTrace();
// don't care about the exception for the "123456" default password attempt
originalEx.printStackTrace();
throw originalEx;
} }
} }
}
sslContext.init(_kmf.getKeyManagers(), null, null);
if (kmf == null) {
httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
server = httpsServer;
} catch (BindException ignored) {
Grasscutter.getLogger().error("Unable to bind to port: " + getAddress().getPort() + " (HTTPS)");
server = this.safelyCreateServer(this.getAddress());
} catch (Exception e) {
Grasscutter.getLogger().warn("[Dispatch] No SSL cert found! Falling back to HTTP server."); Grasscutter.getLogger().warn("[Dispatch] No SSL cert found! Falling back to HTTP server.");
Grasscutter.getConfig().getDispatchOptions().UseSSL = false; Grasscutter.getConfig().getDispatchOptions().UseSSL = false;
server = this.safelyCreateServer(this.getAddress()); server = this.safelyCreateServer(this.getAddress());
} }
HttpsServer httpsServer = null;
try {
httpsServer = HttpsServer.create(getAddress(), 0);
sslContext.init(kmf.getKeyManagers(), null, null);
httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
server = httpsServer;
} catch (BindException e) {
Grasscutter.getLogger().error("Unable to bind to port: " + getAddress().getPort() + " (HTTPS)");
}
} else { } else {
server = this.safelyCreateServer(this.getAddress()); server = this.safelyCreateServer(this.getAddress());
} }
......
package emu.grasscutter.server.event.game; package emu.grasscutter.server.event.game;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.server.event.Cancellable; import emu.grasscutter.server.event.Cancellable;
import emu.grasscutter.server.event.ServerEvent; import emu.grasscutter.server.event.ServerEvent;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
public final class SendPacketEvent extends ServerEvent implements Cancellable { public final class SendPacketEvent extends ServerEvent implements Cancellable {
private final GameSession gameSession; private final GameSession gameSession;
private GenshinPacket packet; private BasePacket packet;
public SendPacketEvent(GameSession gameSession, GenshinPacket packet) { public SendPacketEvent(GameSession gameSession, BasePacket packet) {
super(Type.GAME); super(Type.GAME);
this.gameSession = gameSession; this.gameSession = gameSession;
...@@ -20,11 +20,11 @@ public final class SendPacketEvent extends ServerEvent implements Cancellable { ...@@ -20,11 +20,11 @@ public final class SendPacketEvent extends ServerEvent implements Cancellable {
return this.gameSession; return this.gameSession;
} }
public void setPacket(GenshinPacket packet) { public void setPacket(BasePacket packet) {
this.packet = packet; this.packet = packet;
} }
public GenshinPacket getPacket() { public BasePacket getPacket() {
return this.packet; return this.packet;
} }
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment