Commit dce13cf6 authored by Magix's avatar Magix Committed by GitHub
Browse files

Merge branch 'development' into plugin-system

parents 832c460a b6fedcf2
...@@ -197,8 +197,8 @@ public final class SetStatsCommand implements CommandHandler { ...@@ -197,8 +197,8 @@ public final class SetStatsCommand implements CommandHandler {
float eelec = Integer.parseInt(args.get(1)); float eelec = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity(); EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
float elec = eelec / 10000; float elec = eelec / 10000;
entity.setFightProperty(FightProperty.FIGHT_PROP_CRITICAL_HURT, elec); entity.setFightProperty(FightProperty.FIGHT_PROP_ELEC_ADD_HURT, elec);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CRITICAL_HURT)); entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_ELEC_ADD_HURT));
float igelec = elec * 100; float igelec = elec * 100;
CommandHandler.sendMessage(sender, "Electro DMG Bonus set to " + igelec + "%"); CommandHandler.sendMessage(sender, "Electro DMG Bonus set to " + igelec + "%");
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {
......
...@@ -2,6 +2,7 @@ package emu.grasscutter.command.commands; ...@@ -2,6 +2,7 @@ package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command; import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler; import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.def.AvatarSkillDepotData;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.avatar.GenshinAvatar; import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.entity.EntityAvatar;
...@@ -21,8 +22,9 @@ public class TalentCommand implements CommandHandler { ...@@ -21,8 +22,9 @@ public class TalentCommand implements CommandHandler {
return; return;
} }
if (args.size() < 0 || args.size() < 1){ if (args.size() < 1){
CommandHandler.sendMessage(sender, "To set talent level: /talent set <talentID> <value>"); CommandHandler.sendMessage(sender, "To set talent level: /talent set <talentID> <value>");
CommandHandler.sendMessage(sender, "Another way to set talent level: /talent <n or e or q> <value>");
CommandHandler.sendMessage(sender, "To get talent ID: /talent getid"); CommandHandler.sendMessage(sender, "To get talent ID: /talent getid");
return; return;
} }
...@@ -31,6 +33,7 @@ public class TalentCommand implements CommandHandler { ...@@ -31,6 +33,7 @@ public class TalentCommand implements CommandHandler {
switch (cmdSwitch) { switch (cmdSwitch) {
default: default:
CommandHandler.sendMessage(sender, "To set talent level: /talent set <talentID> <value>"); CommandHandler.sendMessage(sender, "To set talent level: /talent set <talentID> <value>");
CommandHandler.sendMessage(sender, "Another way to set talent level: /talent <n or e or q> <value>");
CommandHandler.sendMessage(sender, "To get talent ID: /talent getid"); CommandHandler.sendMessage(sender, "To get talent ID: /talent getid");
return; return;
case "set": case "set":
...@@ -90,6 +93,45 @@ public class TalentCommand implements CommandHandler { ...@@ -90,6 +93,45 @@ public class TalentCommand implements CommandHandler {
return; return;
} }
break;
case "n": case "e": case "q":
try {
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
GenshinAvatar avatar = entity.getAvatar();
AvatarSkillDepotData SkillDepot = avatar.getData().getSkillDepot();
int skillId;
switch (cmdSwitch) {
default:
skillId = SkillDepot.getSkills().get(0);
break;
case "e":
skillId = SkillDepot.getSkills().get(1);
break;
case "q":
skillId = SkillDepot.getEnergySkill();
break;
}
int nextLevel = Integer.parseInt(args.get(1));
int currentLevel = avatar.getSkillLevelMap().get(skillId);
if (args.size() < 1){
CommandHandler.sendMessage(sender, "To set talent level: /talent <n or e or q> <value>");
return;
}
if (nextLevel > 16){
CommandHandler.sendMessage(sender, "Invalid talent level. Level should be lower than 16");
return;
}
// Upgrade skill
avatar.getSkillLevelMap().put(skillId, nextLevel);
avatar.save();
// Packet
sender.sendPacket(new PacketAvatarSkillChangeNotify(avatar, skillId, currentLevel, nextLevel));
sender.sendPacket(new PacketAvatarSkillUpgradeRsp(avatar, skillId, currentLevel, nextLevel));
CommandHandler.sendMessage(sender, "Set this talent to " + nextLevel + ".");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid talent level.");
return;
}
break; break;
case "getid": case "getid":
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity(); EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
......
package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.utils.Position;
import java.util.List;
@Command(label = "teleport", usage = "teleport <x> <y> <z>", aliases = {"tp"},
description = "Change the player's position.", permission = "player.teleport")
public class TelePortCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
if (sender == null) {
CommandHandler.sendMessage(null, "Run this command in-game.");
return;
}
if (args.size() < 3){
CommandHandler.sendMessage(sender, "Usage: /tp <x> <y> <z> [scene id]");
return;
}
try {
float x = 0f;
float y = 0f;
float z = 0f;
if (args.get(0).contains("~")) {
if (args.get(0).equals("~")) {
x = sender.getPos().getX();
} else {
x = Float.parseFloat(args.get(0).replace("~", "")) + sender.getPos().getX();
}
} else {
x = Float.parseFloat(args.get(0));
}
if (args.get(1).contains("~")) {
if (args.get(1).equals("~")) {
y = sender.getPos().getY();
} else {
y = Float.parseFloat(args.get(1).replace("~", "")) + sender.getPos().getY();
}
} else {
y = Float.parseFloat(args.get(1));
}
if (args.get(2).contains("~")) {
if (args.get(2).equals("~")) {
z = sender.getPos().getZ();
} else {
z = Float.parseFloat(args.get(2).replace("~", "")) + sender.getPos().getZ();
}
} else {
z = Float.parseFloat(args.get(2));
}
int sceneId = sender.getSceneId();
if (args.size() == 4){
sceneId = Integer.parseInt(args.get(3));
}
Position target = new Position(x, y, z);
boolean result = sender.getWorld().transferPlayerToScene(sender, sceneId, target);
if (!result) {
CommandHandler.sendMessage(sender, "Invalid position.");
}
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid position.");
}
}
}
...@@ -31,6 +31,7 @@ public class GenshinData { ...@@ -31,6 +31,7 @@ public class GenshinData {
private static final Int2ObjectMap<AvatarSkillDepotData> avatarSkillDepotDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<AvatarSkillDepotData> avatarSkillDepotDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<AvatarSkillData> avatarSkillDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<AvatarSkillData> avatarSkillDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<AvatarCurveData> avatarCurveDataMap = new Int2ObjectLinkedOpenHashMap<>(); private static final Int2ObjectMap<AvatarCurveData> avatarCurveDataMap = new Int2ObjectLinkedOpenHashMap<>();
private static final Int2ObjectMap<AvatarFetterLevelData> avatarFetterLevelDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<AvatarPromoteData> avatarPromoteDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<AvatarPromoteData> avatarPromoteDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<AvatarTalentData> avatarTalentDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<AvatarTalentData> avatarTalentDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<ProudSkillData> proudSkillDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<ProudSkillData> proudSkillDataMap = new Int2ObjectOpenHashMap<>();
...@@ -57,6 +58,8 @@ public class GenshinData { ...@@ -57,6 +58,8 @@ public class GenshinData {
private static final Int2ObjectMap<SceneData> sceneDataMap = new Int2ObjectLinkedOpenHashMap<>(); private static final Int2ObjectMap<SceneData> sceneDataMap = new Int2ObjectLinkedOpenHashMap<>();
private static final Int2ObjectMap<FetterData> fetterDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<FetterData> fetterDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<FetterCharacterCardData> fetterCharacterCardDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<RewardData> rewardDataMap = new Int2ObjectOpenHashMap<>();
// Cache // Cache
private static Map<Integer, List<Integer>> fetters = new HashMap<>(); private static Map<Integer, List<Integer>> fetters = new HashMap<>();
...@@ -114,6 +117,14 @@ public class GenshinData { ...@@ -114,6 +117,14 @@ public class GenshinData {
return playerLevelDataMap; return playerLevelDataMap;
} }
public static Int2ObjectMap<AvatarFetterLevelData> getAvatarFetterLevelDataMap() {
return avatarFetterLevelDataMap;
}
public static Int2ObjectMap<FetterCharacterCardData> getFetterCharacterCardDataMap() {
return fetterCharacterCardDataMap;
}
public static Int2ObjectMap<AvatarLevelData> getAvatarLevelDataMap() { public static Int2ObjectMap<AvatarLevelData> getAvatarLevelDataMap() {
return avatarLevelDataMap; return avatarLevelDataMap;
} }
...@@ -176,6 +187,11 @@ public class GenshinData { ...@@ -176,6 +187,11 @@ public class GenshinData {
return levelData != null ? levelData.getExp() : 0; return levelData != null ? levelData.getExp() : 0;
} }
public static int getAvatarFetterLevelExpRequired(int level) {
AvatarFetterLevelData levelData = avatarFetterLevelDataMap.get(level);
return levelData != null ? levelData.getExp() : 0;
}
public static Int2ObjectMap<ProudSkillData> getProudSkillDataMap() { public static Int2ObjectMap<ProudSkillData> getProudSkillDataMap() {
return proudSkillDataMap; return proudSkillDataMap;
} }
...@@ -228,6 +244,10 @@ public class GenshinData { ...@@ -228,6 +244,10 @@ public class GenshinData {
return sceneDataMap; return sceneDataMap;
} }
public static Int2ObjectMap<RewardData> getRewardDataMap() {
return rewardDataMap;
}
public static Map<Integer, List<Integer>> getFetterDataEntries() { public static Map<Integer, List<Integer>> getFetterDataEntries() {
if (fetters.isEmpty()) { if (fetters.isEmpty()) {
fetterDataMap.forEach((k, v) -> { fetterDataMap.forEach((k, v) -> {
......
package emu.grasscutter.data.common;
import java.util.List;
public class OpenCondData {
private String CondType;
private List<Integer> ParamList;
public String getCondType() {
return CondType;
}
public void setCondType(String condType) {
CondType = condType;
}
public List<Integer> getParamList() {
return ParamList;
}
public void setParamList(List<Integer> paramList) {
ParamList = paramList;
}
}
package emu.grasscutter.data.common;
public class RewardItemData {
private int ItemId;
private int ItemCount;
public int getItemId() {
return ItemId;
}
public void setItemId(int itemId) {
ItemId = itemId;
}
public int getItemCount() {
return ItemCount;
}
public void setItemCount(int itemCount) {
ItemCount = itemCount;
}
}
...@@ -57,6 +57,8 @@ public class AvatarData extends GenshinResource { ...@@ -57,6 +57,8 @@ public class AvatarData extends GenshinResource {
private IntList abilities; private IntList abilities;
private List<Integer> fetters; private List<Integer> fetters;
private int nameCardRewardId;
private int nameCardId;
@Override @Override
public int getId(){ public int getId(){
...@@ -199,6 +201,14 @@ public class AvatarData extends GenshinResource { ...@@ -199,6 +201,14 @@ public class AvatarData extends GenshinResource {
return fetters; return fetters;
} }
public int getNameCardRewardId() {
return nameCardRewardId;
}
public int getNameCardId() {
return nameCardId;
}
@Override @Override
public void onLoad() { public void onLoad() {
this.skillDepot = GenshinData.getAvatarSkillDepotDataMap().get(this.SkillDepotId); this.skillDepot = GenshinData.getAvatarSkillDepotDataMap().get(this.SkillDepotId);
...@@ -206,6 +216,14 @@ public class AvatarData extends GenshinResource { ...@@ -206,6 +216,14 @@ public class AvatarData extends GenshinResource {
// Get fetters from GenshinData // Get fetters from GenshinData
this.fetters = GenshinData.getFetterDataEntries().get(this.Id); this.fetters = GenshinData.getFetterDataEntries().get(this.Id);
if (GenshinData.getFetterCharacterCardDataMap().get(this.Id) != null) {
this.nameCardRewardId = GenshinData.getFetterCharacterCardDataMap().get(this.Id).getRewardId();
}
if (GenshinData.getRewardDataMap().get(this.nameCardRewardId) != null) {
this.nameCardId = GenshinData.getRewardDataMap().get(this.nameCardRewardId).getRewardItemList().get(0).getItemId();
}
int size = GenshinData.getAvatarCurveDataMap().size(); int size = GenshinData.getAvatarCurveDataMap().size();
this.hpGrowthCurve = new float[size]; this.hpGrowthCurve = new float[size];
this.attackGrowthCurve = new float[size]; this.attackGrowthCurve = new float[size];
......
package emu.grasscutter.data.def;
import emu.grasscutter.data.GenshinResource;
import emu.grasscutter.data.ResourceType;
@ResourceType(name = "AvatarFettersLevelExcelConfigData.json")
public class AvatarFetterLevelData extends GenshinResource {
private int FetterLevel;
private int NeedExp;
@Override
public int getId() {
return this.FetterLevel;
}
public int getLevel() {
return FetterLevel;
}
public int getExp() {
return NeedExp;
}
}
package emu.grasscutter.data.def;
import emu.grasscutter.data.GenshinResource;
import emu.grasscutter.data.ResourceType;
import emu.grasscutter.data.ResourceType.LoadPriority;
@ResourceType(name = "FetterCharacterCardExcelConfigData.json", loadPriority = LoadPriority.HIGHEST)
public class FetterCharacterCardData extends GenshinResource {
private int AvatarId;
private int RewardId;
@Override
public int getId() {
return AvatarId;
}
public int getRewardId() {
return RewardId;
}
@Override
public void onLoad() {
}
}
package emu.grasscutter.data.def; package emu.grasscutter.data.def;
import java.util.List;
import emu.grasscutter.data.GenshinResource; import emu.grasscutter.data.GenshinResource;
import emu.grasscutter.data.ResourceType; import emu.grasscutter.data.ResourceType;
import emu.grasscutter.data.ResourceType.LoadPriority; import emu.grasscutter.data.ResourceType.LoadPriority;
import emu.grasscutter.data.common.OpenCondData;
@ResourceType(name = {"FetterInfoExcelConfigData.json", "FettersExcelConfigData.json", "FetterStoryExcelConfigData.json"}, loadPriority = LoadPriority.HIGHEST) @ResourceType(name = {"FetterInfoExcelConfigData.json", "FettersExcelConfigData.json", "FetterStoryExcelConfigData.json"}, loadPriority = LoadPriority.HIGHEST)
public class FetterData extends GenshinResource { public class FetterData extends GenshinResource {
private int AvatarId; private int AvatarId;
private int FetterId; private int FetterId;
private List<OpenCondData> OpenCond;
@Override @Override
public int getId() { public int getId() {
...@@ -18,6 +22,10 @@ public class FetterData extends GenshinResource { ...@@ -18,6 +22,10 @@ public class FetterData extends GenshinResource {
return AvatarId; return AvatarId;
} }
public List<OpenCondData> getOpenConds() {
return OpenCond;
}
@Override @Override
public void onLoad() { public void onLoad() {
} }
......
package emu.grasscutter.data.def;
import java.util.List;
import emu.grasscutter.data.GenshinResource;
import emu.grasscutter.data.ResourceType;
import emu.grasscutter.data.common.RewardItemData;
@ResourceType(name = "RewardExcelConfigData.json")
public class RewardData extends GenshinResource {
public int RewardId;
public List<RewardItemData> RewardItemList;
@Override
public int getId() {
return RewardId;
}
public List<RewardItemData> getRewardItemList() {
return RewardItemList;
}
@Override
public void onLoad() {
}
}
...@@ -101,7 +101,7 @@ public final class DatabaseManager { ...@@ -101,7 +101,7 @@ public final class DatabaseManager {
} }
public static synchronized int getNextId(Class<?> c) { public static synchronized int getNextId(Class<?> c) {
DatabaseCounter counter = getDatastore().find(DatabaseCounter.class).filter(Filters.eq("_id", c.getName())).first(); DatabaseCounter counter = getDatastore().find(DatabaseCounter.class).filter(Filters.eq("_id", c.getSimpleName())).first();
if (counter == null) { if (counter == null) {
counter = new DatabaseCounter(c.getSimpleName()); counter = new DatabaseCounter(c.getSimpleName());
} }
......
package emu.grasscutter.game; package emu.grasscutter.game;
import java.util.*;
import dev.morphia.annotations.*; import dev.morphia.annotations.*;
import emu.grasscutter.GenshinConstants; import emu.grasscutter.GenshinConstants;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
...@@ -23,7 +21,6 @@ import emu.grasscutter.game.props.ActionReason; ...@@ -23,7 +21,6 @@ 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.net.packet.GenshinPacket;
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
import emu.grasscutter.net.proto.BirthdayOuterClass.Birthday;
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;
import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
...@@ -35,33 +32,13 @@ import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; ...@@ -35,33 +32,13 @@ import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
import emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo; 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.PacketAbilityInvocationsNotify; import emu.grasscutter.server.packet.send.*;
import emu.grasscutter.server.packet.send.PacketAvatarAddNotify;
import emu.grasscutter.server.packet.send.PacketAvatarDataNotify;
import emu.grasscutter.server.packet.send.PacketAvatarGainCostumeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarGainFlycloakNotify;
import emu.grasscutter.server.packet.send.PacketClientAbilityInitFinishNotify;
import emu.grasscutter.server.packet.send.PacketCombatInvocationsNotify;
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
import emu.grasscutter.server.packet.send.PacketItemAddHintNotify;
import emu.grasscutter.server.packet.send.PacketOpenStateUpdateNotify;
import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpResultNotify;
import emu.grasscutter.server.packet.send.PacketPlayerDataNotify;
import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify;
import emu.grasscutter.server.packet.send.PacketPlayerPropNotify;
import emu.grasscutter.server.packet.send.PacketPlayerStoreNotify;
import emu.grasscutter.server.packet.send.PacketPrivateChatNotify;
import emu.grasscutter.server.packet.send.PacketScenePlayerLocationNotify;
import emu.grasscutter.server.packet.send.PacketSetNameCardRsp;
import emu.grasscutter.server.packet.send.PacketStoreWeightLimitNotify;
import emu.grasscutter.server.packet.send.PacketUnlockNameCardNotify;
import emu.grasscutter.server.packet.send.PacketWorldPlayerLocationNotify;
import emu.grasscutter.server.packet.send.PacketWorldPlayerRTTNotify;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
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.*;
@Entity(value = "players", useDiscriminator = false) @Entity(value = "players", useDiscriminator = false)
public class GenshinPlayer { public class GenshinPlayer {
@Id private int id; @Id private int id;
...@@ -96,6 +73,7 @@ public class GenshinPlayer { ...@@ -96,6 +73,7 @@ public class GenshinPlayer {
private MpSettingType mpSetting = MpSettingType.MpSettingEnterAfterApply; private MpSettingType mpSetting = MpSettingType.MpSettingEnterAfterApply;
private boolean showAvatar; private boolean showAvatar;
private ArrayList<AvatarProfileData> shownAvatars; private ArrayList<AvatarProfileData> shownAvatars;
private Set<Integer> rewardedLevels;
private int sceneId; private int sceneId;
private int regionId; private int regionId;
...@@ -113,7 +91,8 @@ public class GenshinPlayer { ...@@ -113,7 +91,8 @@ public class GenshinPlayer {
@Transient private final InvokeHandler<AbilityInvokeEntry> abilityInvokeHandler; @Transient private final InvokeHandler<AbilityInvokeEntry> abilityInvokeHandler;
@Transient private final InvokeHandler<AbilityInvokeEntry> clientAbilityInitFinishHandler; @Transient private final InvokeHandler<AbilityInvokeEntry> clientAbilityInitFinishHandler;
@Deprecated @SuppressWarnings({ "rawtypes", "unchecked" }) // Morphia only! @Deprecated
@SuppressWarnings({"rawtypes", "unchecked"}) // Morphia only!
public GenshinPlayer() { public GenshinPlayer() {
this.inventory = new Inventory(this); this.inventory = new Inventory(this);
this.avatars = new AvatarStorage(this); this.avatars = new AvatarStorage(this);
...@@ -143,6 +122,7 @@ public class GenshinPlayer { ...@@ -143,6 +122,7 @@ public class GenshinPlayer {
this.clientAbilityInitFinishHandler = new InvokeHandler(PacketClientAbilityInitFinishNotify.class); this.clientAbilityInitFinishHandler = new InvokeHandler(PacketClientAbilityInitFinishNotify.class);
this.birthday = new PlayerBirthday(); this.birthday = new PlayerBirthday();
this.rewardedLevels = new HashSet<>();
} }
// On player creation // On player creation
...@@ -581,6 +561,7 @@ public class GenshinPlayer { ...@@ -581,6 +561,7 @@ public class GenshinPlayer {
/** /**
* Sends a message to another player. * Sends a message to another player.
*
* @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.
*/ */
...@@ -647,7 +628,7 @@ public class GenshinPlayer { ...@@ -647,7 +628,7 @@ public class GenshinPlayer {
return onlineInfo.build(); return onlineInfo.build();
} }
public PlayerBirthday getBirthday(){ public PlayerBirthday getBirthday() {
return this.birthday; return this.birthday;
} }
...@@ -656,6 +637,18 @@ public class GenshinPlayer { ...@@ -656,6 +637,18 @@ public class GenshinPlayer {
this.updateProfile(); this.updateProfile();
} }
public boolean hasBirthday() {
return this.birthday.getDay() > 0;
}
public Set<Integer> getRewardedLevels() {
return rewardedLevels;
}
public void setRewardedLevels(Set<Integer> rewardedLevels) {
this.rewardedLevels = rewardedLevels;
}
public SocialDetail.Builder getSocialDetail() { public SocialDetail.Builder getSocialDetail() {
SocialDetail.Builder social = SocialDetail.newBuilder() SocialDetail.Builder social = SocialDetail.newBuilder()
.setUid(this.getUid()) .setUid(this.getUid())
...@@ -734,7 +727,8 @@ public class GenshinPlayer { ...@@ -734,7 +727,8 @@ public class GenshinPlayer {
// Make sure these exist // Make sure these exist
if (this.getTeamManager() == null) { if (this.getTeamManager() == null) {
this.teamManager = new TeamManager(this); this.teamManager = new TeamManager(this);
} if (this.getProfile().getUid() == 0) { }
if (this.getProfile().getUid() == 0) {
this.getProfile().syncWithCharacter(this); this.getProfile().syncWithCharacter(this);
} }
...@@ -773,6 +767,7 @@ public class GenshinPlayer { ...@@ -773,6 +767,7 @@ public class GenshinPlayer {
session.send(new PacketAvatarDataNotify(this)); session.send(new PacketAvatarDataNotify(this));
session.send(new PacketPlayerEnterSceneNotify(this)); // Enter game world session.send(new PacketPlayerEnterSceneNotify(this)); // Enter game world
session.send(new PacketPlayerLevelRewardUpdateNotify(rewardedLevels));
session.send(new PacketOpenStateUpdateNotify()); session.send(new PacketOpenStateUpdateNotify());
// First notify packets sent // First notify packets sent
...@@ -798,7 +793,7 @@ public class GenshinPlayer { ...@@ -798,7 +793,7 @@ public class GenshinPlayer {
} }
public enum SceneLoadState { public enum SceneLoadState {
NONE (0), LOADING (1), INIT (2), LOADED (3); NONE(0), LOADING(1), INIT(2), LOADED(3);
private final int value; private final int value;
......
...@@ -90,6 +90,12 @@ public class GenshinAvatar { ...@@ -90,6 +90,12 @@ public class GenshinAvatar {
private int costume; private int costume;
private int bornTime; private int bornTime;
private int fetterLevel = 1;
private int fetterExp;
private int nameCardRewardId;
private int nameCardId;
public GenshinAvatar() { public GenshinAvatar() {
// Morhpia only! // Morhpia only!
this.equips = new Int2ObjectOpenHashMap<>(); this.equips = new Int2ObjectOpenHashMap<>();
...@@ -107,6 +113,8 @@ public class GenshinAvatar { ...@@ -107,6 +113,8 @@ public class GenshinAvatar {
public GenshinAvatar(AvatarData data) { public GenshinAvatar(AvatarData data) {
this(); this();
this.avatarId = data.getId(); this.avatarId = data.getId();
this.nameCardRewardId = data.getNameCardRewardId();
this.nameCardId = data.getNameCardId();
this.data = data; this.data = data;
this.bornTime = (int) (System.currentTimeMillis() / 1000); this.bornTime = (int) (System.currentTimeMillis() / 1000);
this.flyCloak = 140001; this.flyCloak = 140001;
...@@ -169,6 +177,14 @@ public class GenshinAvatar { ...@@ -169,6 +177,14 @@ public class GenshinAvatar {
this.satiation = satiation; this.satiation = satiation;
} }
public int getNameCardRewardId() {
return nameCardRewardId;
}
public void setNameCardRewardId(int nameCardRewardId) {
this.nameCardRewardId = nameCardRewardId;
}
public int getSatiationPenalty() { public int getSatiationPenalty() {
return satiationPenalty; return satiationPenalty;
} }
...@@ -281,6 +297,30 @@ public class GenshinAvatar { ...@@ -281,6 +297,30 @@ public class GenshinAvatar {
return fetters; return fetters;
} }
public int getFetterLevel() {
return fetterLevel;
}
public void setFetterLevel(int fetterLevel) {
this.fetterLevel = fetterLevel;
}
public int getFetterExp() {
return fetterExp;
}
public void setFetterExp(int fetterExp) {
this.fetterExp = fetterExp;
}
public int getNameCardId() {
return nameCardId;
}
public void setNameCardId(int nameCardId) {
this.nameCardId = nameCardId;
}
public float getCurrentHp() { public float getCurrentHp() {
return currentHp; return currentHp;
} }
...@@ -403,6 +443,8 @@ public class GenshinAvatar { ...@@ -403,6 +443,8 @@ public class GenshinAvatar {
// Fetters // Fetters
this.setFetterList(data.getFetters()); this.setFetterList(data.getFetters());
this.setNameCardRewardId(data.getNameCardRewardId());
this.setNameCardId(data.getNameCardId());
// Get hp percent, set to 100% if none // Get hp percent, set to 100% if none
float hpPercent = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) <= 0 ? 1f : this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) / this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); float hpPercent = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) <= 0 ? 1f : this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) / this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
...@@ -701,9 +743,14 @@ public class GenshinAvatar { ...@@ -701,9 +743,14 @@ public class GenshinAvatar {
} }
public AvatarInfo toProto() { public AvatarInfo toProto() {
int fetterLevel = this.getFetterLevel();
AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder() AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder()
.setExpLevel(10) .setExpLevel(fetterLevel);
.setExpNumber(6325); // Highest Level
if (fetterLevel != 10) {
avatarFetter.setExpNumber(this.getFetterExp());
}
if (this.getFetterList() != null) { if (this.getFetterList() != null) {
for (int i = 0; i < this.getFetterList().size(); i++) { for (int i = 0; i < this.getFetterList().size(); i++) {
...@@ -715,6 +762,12 @@ public class GenshinAvatar { ...@@ -715,6 +762,12 @@ public class GenshinAvatar {
} }
} }
int cardId = this.getNameCardId();
if (this.getPlayer().getNameCardList().contains(cardId)) {
avatarFetter.addRewardedFetterLevelList(10);
}
AvatarInfo.Builder avatarInfo = AvatarInfo.newBuilder() AvatarInfo.Builder avatarInfo = AvatarInfo.newBuilder()
.setAvatarId(this.getAvatarId()) .setAvatarId(this.getAvatarId())
.setGuid(this.getGuid()) .setGuid(this.getGuid())
......
...@@ -90,7 +90,7 @@ public class GenshinItem { ...@@ -90,7 +90,7 @@ public class GenshinItem {
// Equip data // Equip data
if (getItemType() == ItemType.ITEM_WEAPON) { if (getItemType() == ItemType.ITEM_WEAPON) {
this.level = 1; this.level = this.count > 1 ? this.count : 1;
this.affixes = new ArrayList<>(2); this.affixes = new ArrayList<>(2);
if (getItemData().getSkillAffix() != null) { if (getItemData().getSkillAffix() != null) {
for (int skillAffix : getItemData().getSkillAffix()) { for (int skillAffix : getItemData().getSkillAffix()) {
......
...@@ -711,6 +711,31 @@ public class InventoryManager { ...@@ -711,6 +711,31 @@ 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) {
// May work. Not test.
int maxLevel = 10; // Keep it until I think of a more "elegant" way
int level = avatar.getFetterLevel();
int exp = avatar.getFetterExp();
int reqExp = GenshinData.getAvatarFetterLevelExpRequired(level);
while (expGain > 0 && reqExp > 0 && level < maxLevel) {
int toGain = Math.min(expGain, reqExp - exp);
exp += toGain;
expGain -= toGain;
if (exp >= reqExp) {
exp = 0;
level += 1;
reqExp = GenshinData.getAvatarFetterLevelExpRequired(level);
}
}
avatar.setFetterLevel(level);
avatar.setFetterExp(exp);
avatar.save();
player.sendPacket(new PacketAvatarPropNotify(avatar));
}
public void upgradeAvatarSkill(GenshinPlayer player, long guid, int skillId) { public void upgradeAvatarSkill(GenshinPlayer player, long guid, int skillId) {
// Sanity checks // Sanity checks
GenshinAvatar avatar = player.getAvatars().getAvatarByGuid(guid); GenshinAvatar avatar = player.getAvatars().getAvatarByGuid(guid);
......
package emu.grasscutter.game.player; package emu.grasscutter.game.player;
import dev.morphia.annotations.Entity;
import emu.grasscutter.net.proto.BirthdayOuterClass.Birthday; import emu.grasscutter.net.proto.BirthdayOuterClass.Birthday;
@Entity
public class PlayerBirthday { public class PlayerBirthday {
private int day; private int day;
private int month; private int month;
......
...@@ -64,9 +64,8 @@ public class MihoyoKcpServer extends Thread { ...@@ -64,9 +64,8 @@ public class MihoyoKcpServer extends Thread {
// Wait until the server socket is closed. // Wait until the server socket is closed.
f.channel().closeFuture().sync(); f.channel().closeFuture().sync();
} catch (Exception e) { } catch (Exception exception) {
// TODO Auto-generated catch block Grasscutter.getLogger().error("Unable to start game server.", exception);
e.printStackTrace();
} finally { } finally {
// Close // Close
finish(); finish();
......
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.def.RewardData;
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketAvatarDataNotify;
import emu.grasscutter.server.packet.send.PacketAvatarFetterDataNotify;
import emu.grasscutter.server.packet.send.PacketAvatarFetterLevelRewardRsp;
import emu.grasscutter.server.packet.send.PacketItemAddHintNotify;
import emu.grasscutter.server.packet.send.PacketUnlockNameCardNotify;
import emu.grasscutter.net.packet.PacketHandler;
@Opcodes(PacketOpcodes.AvatarFetterLevelRewardReq)
public class HandlerAvatarFetterLevelRewardReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
AvatarFetterLevelRewardReq req = AvatarFetterLevelRewardReq.parseFrom(payload);
if (req.getFetterLevel() < 10) {
// You don't have a full level of fetter level, why do you want to get a divorce certificate?
session.send(new PacketAvatarFetterLevelRewardRsp(req.getAvatarGuid(), req.getFetterLevel()));
} else {
long avatarGuid = req.getAvatarGuid();
GenshinAvatar avatar = session
.getPlayer()
.getAvatars()
.getAvatarByGuid(avatarGuid);
int rewardId = avatar.getNameCardRewardId();
RewardData card = GenshinData.getRewardDataMap().get(rewardId);
int cardId = card.getRewardItemList().get(0).getItemId();
if (session.getPlayer().getNameCardList().contains(cardId)) {
// Already got divorce certificate.
session.getPlayer().sendPacket(new PacketAvatarFetterLevelRewardRsp(req.getAvatarGuid(), req.getFetterLevel(), rewardId));
return;
}
GenshinItem item = new GenshinItem(cardId);
session.getPlayer().getInventory().addItem(item);
session.getPlayer().sendPacket(new PacketItemAddHintNotify(item, ActionReason.FetterLevelReward));
session.getPlayer().sendPacket(new PacketUnlockNameCardNotify(cardId));
session.send(new PacketAvatarFetterDataNotify(avatar));
session.send(new PacketAvatarDataNotify(avatar.getPlayer()));
session.send(new PacketAvatarFetterLevelRewardRsp(avatarGuid, req.getFetterLevel(), rewardId));
}
}
}
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