Commit 716380a0 authored by Melledy's avatar Melledy
Browse files

Merge branch 'development' into java-16

parents 09c8ed34 627d3dda
package emu.grasscutter.data.def;
import emu.grasscutter.data.GenshinResource;
import emu.grasscutter.data.ResourceType;
import emu.grasscutter.data.ResourceType.LoadPriority;
@ResourceType(name = {"FetterInfoExcelConfigData.json", "FettersExcelConfigData.json", "FetterStoryExcelConfigData.json"}, loadPriority = LoadPriority.HIGHEST)
public class FetterData extends GenshinResource {
private int AvatarId;
private int FetterId;
@Override
public int getId() {
return FetterId;
}
public int getAvatarId() {
return AvatarId;
}
@Override
public void onLoad() {
}
}
......@@ -66,7 +66,7 @@ public final class DatabaseHelper {
}
public static void saveAccount(Account account) {
DatabaseManager.getDatastore().save(account);
DatabaseManager.getAccountDatastore().save(account);
}
public static Account getAccountByName(String username) {
......
package emu.grasscutter.database;
import com.mongodb.MongoClientURI;
import com.mongodb.MongoCommandException;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
......@@ -18,7 +19,12 @@ import emu.grasscutter.game.friends.Friendship;
import emu.grasscutter.game.inventory.GenshinItem;
public final class DatabaseManager {
private static MongoClient mongoClient;
private static MongoClient dispatchMongoClient;
private static Datastore datastore;
private static Datastore dispatchDatastore;
private static final Class<?>[] mappedClasses = new Class<?>[] {
DatabaseCounter.class, Account.class, GenshinPlayer.class, GenshinAvatar.class, GenshinItem.class, Friendship.class
......@@ -31,6 +37,16 @@ public final class DatabaseManager {
public static MongoDatabase getDatabase() {
return getDatastore().getDatabase();
}
// Yes. I very dislike this method. However, this will be good for now.
// TODO: Add dispatch routes for player account management
public static Datastore getAccountDatastore() {
if(Grasscutter.getConfig().RunMode.equalsIgnoreCase("GAME_ONLY")) {
return dispatchDatastore;
} else {
return datastore;
}
}
public static void initialize() {
// Initialize
......@@ -60,6 +76,28 @@ public final class DatabaseManager {
datastore.ensureIndexes();
}
}
if(Grasscutter.getConfig().RunMode.equalsIgnoreCase("GAME_ONLY")) {
dispatchMongoClient = MongoClients.create(Grasscutter.getConfig().getGameServerOptions().DispatchServerDatabaseUrl);
dispatchDatastore = Morphia.createDatastore(dispatchMongoClient, Grasscutter.getConfig().getGameServerOptions().DispatchServerDatabaseCollection);
// Ensure indexes for dispatch server
try {
dispatchDatastore.ensureIndexes();
} catch (MongoCommandException e) {
Grasscutter.getLogger().info("Mongo index error: ", e);
// Duplicate index error
if (e.getCode() == 85) {
// Drop all indexes and re add them
MongoIterable<String> collections = dispatchDatastore.getDatabase().listCollectionNames();
for (String name : collections) {
dispatchDatastore.getDatabase().getCollection(name).dropIndexes();
}
// Add back indexes
dispatchDatastore.ensureIndexes();
}
}
}
}
public static synchronized int getNextId(Class<?> c) {
......
......@@ -8,6 +8,10 @@ import emu.grasscutter.utils.Utils;
import java.util.ArrayList;
import java.util.List;
import org.bson.Document;
import com.mongodb.DBObject;
@Entity(value = "accounts", useDiscriminator = false)
public class Account {
@Id private String id;
......@@ -17,7 +21,7 @@ public class Account {
private String username;
private String password; // Unused for now
private int playerId;
@AlsoLoad("playerUid") private int playerId;
private String email;
private String token;
......@@ -61,7 +65,7 @@ public class Account {
this.token = token;
}
public int getPlayerId() {
public int getPlayerUid() {
return this.playerId;
}
......@@ -117,13 +121,12 @@ public class Account {
public void save() {
DatabaseHelper.saveAccount(this);
}
// TODO: Find an implementation for this. Morphia 2.0 breaks this method for some reason?
// @PreLoad
// public void onLoad(DBObject object) {
// // Grant the superuser permissions to accounts created before the permissions update
// if (!object.containsField("permissions")) {
// this.addPermission("*");
// }
// }
@PreLoad
public void onLoad(Document document) {
// Grant the superuser permissions to accounts created before the permissions update
if (!document.containsKey("permissions")) {
this.addPermission("*");
}
}
}
......@@ -31,6 +31,7 @@ import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo;
import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason;
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
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.GameSession;
import emu.grasscutter.server.packet.send.PacketAbilityInvocationsNotify;
......@@ -49,9 +50,11 @@ 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;
......@@ -101,6 +104,7 @@ public class GenshinPlayer {
@Transient private int enterSceneToken;
@Transient private SceneLoadState sceneState;
@Transient private boolean hasSentAvatarDataNotify;
@Transient private long nextSendPlayerLocTime = 0;
@Transient private final Int2ObjectMap<CoopRequest> coopRequests;
@Transient private final InvokeHandler<CombatInvokeEntry> combatInvokeHandler;
......@@ -121,6 +125,12 @@ public class GenshinPlayer {
}
this.properties.put(prop.getId(), 0);
}
this.gachaInfo = new PlayerGachaInfo();
this.nameCardList = new HashSet<>();
this.flyCloakList = new HashSet<>();
this.costumeList = new HashSet<>();
this.setSceneId(3);
this.setRegionId(1);
this.sceneState = SceneLoadState.NONE;
......@@ -140,11 +150,6 @@ public class GenshinPlayer {
this.nickname = "Traveler";
this.signature = "";
this.teamManager = new TeamManager(this);
this.gachaInfo = new PlayerGachaInfo();
this.playerProfile = new PlayerProfile(this);
this.nameCardList = new HashSet<>();
this.flyCloakList = new HashSet<>();
this.costumeList = new HashSet<>();
this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, 1);
this.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, 1);
this.setProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, 50);
......@@ -288,7 +293,7 @@ public class GenshinPlayer {
}
private float getExpModifier() {
return Grasscutter.getConfig().getGameRates().ADVENTURE_EXP_RATE;
return Grasscutter.getConfig().getGameServerOptions().getGameRates().ADVENTURE_EXP_RATE;
}
// Affected by exp rate
......@@ -347,7 +352,6 @@ public class GenshinPlayer {
public PlayerProfile getProfile() {
if (this.playerProfile == null) {
this.playerProfile = new PlayerProfile(this);
this.save();
}
return playerProfile;
}
......@@ -654,6 +658,13 @@ public class GenshinPlayer {
return social;
}
public WorldPlayerLocationInfo getWorldPlayerLocationInfo() {
return WorldPlayerLocationInfo.newBuilder()
.setSceneId(this.getSceneId())
.setPlayerLoc(this.getPlayerLocationInfo())
.build();
}
public PlayerLocationInfo getPlayerLocationInfo() {
return PlayerLocationInfo.newBuilder()
.setUid(this.getUid())
......@@ -679,9 +690,22 @@ public class GenshinPlayer {
}
// Ping
if (this.getWorld() != null) {
this.sendPacket(new PacketWorldPlayerRTTNotify(this.getWorld())); // Player ping
// RTT notify - very important to send this often
this.sendPacket(new PacketWorldPlayerRTTNotify(this.getWorld()));
// Update player locations if in multiplayer every 5 seconds
long time = System.currentTimeMillis();
if (this.getWorld().isMultiplayer() && this.getScene() != null && time > nextSendPlayerLocTime) {
this.sendPacket(new PacketWorldPlayerLocationNotify(this.getWorld()));
this.sendPacket(new PacketScenePlayerLocationNotify(this.getScene()));
this.resetSendPlayerLocTime();
}
}
}
public void resetSendPlayerLocTime() {
this.nextSendPlayerLocTime = System.currentTimeMillis() + 5000;
}
@PostLoad
private void onLoad() {
......@@ -696,12 +720,8 @@ public class GenshinPlayer {
// Make sure these exist
if (this.getTeamManager() == null) {
this.teamManager = new TeamManager(this);
} if (this.getGachaInfo() == null) {
this.gachaInfo = new PlayerGachaInfo();
} if (this.nameCardList == null) {
this.nameCardList = new HashSet<>();
} if (this.costumeList == null) {
this.costumeList = new HashSet<>();
} if (this.getProfile().getUid() == 0) {
this.getProfile().syncWithCharacter(this);
}
// Check if player object exists in server
......
......@@ -34,7 +34,8 @@ public class GenshinScene {
private int time;
private ClimateType climate;
private int weather;
public GenshinScene(World world, SceneData sceneData) {
this.world = world;
this.sceneData = sceneData;
......@@ -89,10 +90,18 @@ public class GenshinScene {
return climate;
}
public int getWeather() {
return weather;
}
public void setClimate(ClimateType climate) {
this.climate = climate;
}
public void setWeather(int weather) {
this.weather = weather;
}
public boolean isInScene(GenshinEntity entity) {
return this.entities.containsKey(entity.getId());
}
......
......@@ -15,7 +15,7 @@ public class TeamInfo {
public TeamInfo() {
this.name = "";
this.avatars = new ArrayList<>(Grasscutter.getConfig().getServerOptions().MaxAvatarsInTeam);
this.avatars = new ArrayList<>(Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam);
}
public String getName() {
......@@ -39,7 +39,7 @@ public class TeamInfo {
}
public boolean addAvatar(GenshinAvatar avatar) {
if (size() >= Grasscutter.getConfig().getServerOptions().MaxAvatarsInTeam || contains(avatar)) {
if (size() >= Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam || contains(avatar)) {
return false;
}
......@@ -59,7 +59,7 @@ public class TeamInfo {
}
public void copyFrom(TeamInfo team) {
copyFrom(team, Grasscutter.getConfig().getServerOptions().MaxAvatarsInTeam);
copyFrom(team, Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam);
}
public void copyFrom(TeamInfo team, int maxTeamSize) {
......
......@@ -166,13 +166,13 @@ public class TeamManager {
public int getMaxTeamSize() {
if (getPlayer().isInMultiplayer()) {
int max = Grasscutter.getConfig().getServerOptions().MaxAvatarsInTeamMultiplayer;
int max = Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeamMultiplayer;
if (getPlayer().getWorld().getHost() == this.getPlayer()) {
return Math.max(1, (int) Math.ceil(max / (double) getWorld().getPlayerCount()));
}
return Math.max(1, (int) Math.floor(max / (double) getWorld().getPlayerCount()));
}
return Grasscutter.getConfig().getServerOptions().MaxAvatarsInTeam;
return Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam;
}
// Methods
......
......@@ -206,32 +206,16 @@ public class World implements Iterable<GenshinPlayer> {
public void deregisterScene(GenshinScene scene) {
this.getScenes().remove(scene.getId());
}
public boolean forceTransferPlayerToScene(GenshinPlayer player, int sceneId, Position pos) {
// Forces the client to reload the scene map to prevent the player from falling off the map.
if (GenshinData.getSceneDataMap().get(sceneId) == null) {
return false;
}
if (player.getScene() != null) {
player.getScene().removePlayer(player);
}
GenshinScene scene = this.getSceneById(sceneId);
scene.addPlayer(player);
player.getPos().set(pos);
// Teleport packet
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterSelf, EnterReason.TransPoint, sceneId, pos));
return true;
}
public boolean transferPlayerToScene(GenshinPlayer player, int sceneId, Position pos) {
if (player.getScene().getId() == sceneId || GenshinData.getSceneDataMap().get(sceneId) == null) {
if (GenshinData.getSceneDataMap().get(sceneId) == null) {
return false;
}
Integer oldSceneId = null;
if (player.getScene() != null) {
oldSceneId = player.getScene().getId();
player.getScene().removePlayer(player);
}
......@@ -240,7 +224,11 @@ public class World implements Iterable<GenshinPlayer> {
player.getPos().set(pos);
// Teleport packet
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterSelf, EnterReason.TransPoint, sceneId, pos));
if (oldSceneId.equals(sceneId)) {
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterGoto, EnterReason.TransPoint, sceneId, pos));
} else {
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterJump, EnterReason.TransPoint, sceneId, pos));
}
return true;
}
......
package emu.grasscutter.game.avatar;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
......@@ -13,6 +15,7 @@ import dev.morphia.annotations.Indexed;
import dev.morphia.annotations.PostLoad;
import dev.morphia.annotations.PrePersist;
import dev.morphia.annotations.Transient;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.common.FightPropData;
import emu.grasscutter.data.custom.OpenConfigEntry;
......@@ -38,10 +41,13 @@ import emu.grasscutter.game.inventory.EquipType;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.FetterState;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo;
import emu.grasscutter.net.proto.FetterDataOuterClass.FetterData;
import emu.grasscutter.net.proto.AvatarInfoOuterClass.AvatarInfo;
import emu.grasscutter.server.packet.send.PacketAbilityChangeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarEquipChangeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarFightPropNotify;
import emu.grasscutter.utils.ProtoHelper;
......@@ -69,8 +75,10 @@ public class GenshinAvatar {
@Transient private final Int2ObjectMap<GenshinItem> equips;
@Transient private final Int2FloatOpenHashMap fightProp;
@Transient private final Set<String> bonusAbilityList;
@Transient private Set<String> extraAbilityEmbryos;
private List<Integer> fetters;
private Map<Integer, Integer> skillLevelMap; // Talent levels
private Map<Integer, Integer> proudSkillBonusMap; // Talent bonus levels (from const)
private int skillDepotId;
......@@ -86,8 +94,9 @@ public class GenshinAvatar {
// Morhpia only!
this.equips = new Int2ObjectOpenHashMap<>();
this.fightProp = new Int2FloatOpenHashMap();
this.bonusAbilityList = new HashSet<>();
this.proudSkillBonusMap = new HashMap<>(); // TODO Move to genshin avatar
this.extraAbilityEmbryos = new HashSet<>();
this.proudSkillBonusMap = new HashMap<>();
this.fetters = new ArrayList<>(); // TODO Move to genshin avatar
}
// On creation
......@@ -260,8 +269,16 @@ public class GenshinAvatar {
return proudSkillBonusMap;
}
public Set<String> getBonusAbilityList() {
return bonusAbilityList;
public Set<String> getExtraAbilityEmbryos() {
return extraAbilityEmbryos;
}
public void setFetterList(List<Integer> fetterList) {
this.fetters = fetterList;
}
public List<Integer> getFetterList() {
return fetters;
}
public float getCurrentHp() {
......@@ -347,14 +364,14 @@ public class GenshinAvatar {
item.setEquipCharacter(this.getAvatarId());
item.save();
if (this.getPlayer().hasSentAvatarDataNotify()) {
this.getPlayer().sendPacket(new PacketAvatarEquipChangeNotify(this, item));
}
if (shouldRecalc) {
this.recalcStats();
}
if (this.getPlayer().hasSentAvatarDataNotify()) {
this.getPlayer().sendPacket(new PacketAvatarEquipChangeNotify(this, item));
}
return true;
}
......@@ -371,11 +388,21 @@ public class GenshinAvatar {
}
public void recalcStats() {
recalcStats(false);
}
public void recalcStats(boolean forceSendAbilityChange) {
// Setup
AvatarData data = this.getAvatarData();
AvatarPromoteData promoteData = GenshinData.getAvatarPromoteData(data.getAvatarPromoteId(), this.getPromoteLevel());
Int2IntOpenHashMap setMap = new Int2IntOpenHashMap();
this.getBonusAbilityList().clear();
// Extra ability embryos
Set<String> prevExtraAbilityEmbryos = this.getExtraAbilityEmbryos();
this.extraAbilityEmbryos = new HashSet<>();
// Fetters
this.setFetterList(data.getFetters());
// 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);
......@@ -458,7 +485,7 @@ public class GenshinAvatar {
}
// Add any skill strings from this affix
this.addToAbilityList(affix.getOpenConfig(), true);
this.addToExtraAbilityEmbryos(affix.getOpenConfig(), true);
} else {
break;
}
......@@ -505,7 +532,7 @@ public class GenshinAvatar {
}
// Add any skill strings from this affix
this.addToAbilityList(affix.getOpenConfig(), true);
this.addToExtraAbilityEmbryos(affix.getOpenConfig(), true);
}
}
}
......@@ -538,7 +565,7 @@ public class GenshinAvatar {
}
// Add any skill strings from this proud skill
this.addToAbilityList(proudSkillData.getOpenConfig(), true);
this.addToExtraAbilityEmbryos(proudSkillData.getOpenConfig(), true);
}
// Constellations
......@@ -550,7 +577,7 @@ public class GenshinAvatar {
}
// Add any skill strings from this constellation
this.addToAbilityList(avatarTalentData.getOpenConfig(), false);
this.addToExtraAbilityEmbryos(avatarTalentData.getOpenConfig(), false);
}
}
......@@ -573,11 +600,17 @@ public class GenshinAvatar {
// Packet
if (getPlayer() != null && getPlayer().hasSentAvatarDataNotify()) {
// Update stats for client
getPlayer().sendPacket(new PacketAvatarFightPropNotify(this));
// Update client abilities
EntityAvatar entity = this.getAsEntity();
if (entity != null && (!this.getExtraAbilityEmbryos().equals(prevExtraAbilityEmbryos) || forceSendAbilityChange)) {
getPlayer().sendPacket(new PacketAbilityChangeNotify(entity));
}
}
}
public void addToAbilityList(String openConfig, boolean forceAdd) {
public void addToExtraAbilityEmbryos(String openConfig, boolean forceAdd) {
if (openConfig == null || openConfig.length() == 0) {
return;
}
......@@ -586,14 +619,14 @@ public class GenshinAvatar {
if (entry == null) {
if (forceAdd) {
// Add config string to ability skill list anyways
this.getBonusAbilityList().add(openConfig);
this.getExtraAbilityEmbryos().add(openConfig);
}
return;
}
if (entry.getAddAbilities() != null) {
for (String ability : entry.getAddAbilities()) {
this.getBonusAbilityList().add(ability);
this.getExtraAbilityEmbryos().add(ability);
}
}
}
......@@ -668,6 +701,20 @@ public class GenshinAvatar {
}
public AvatarInfo toProto() {
AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder()
.setExpLevel(10)
.setExpNumber(6325); // Highest Level
if (this.getFetterList() != null) {
for (int i = 0; i < this.getFetterList().size(); i++) {
avatarFetter.addFetterList(
FetterData.newBuilder()
.setFetterId(this.getFetterList().get(i))
.setFetterState(FetterState.FINISH.getValue())
);
}
}
AvatarInfo.Builder avatarInfo = AvatarInfo.newBuilder()
.setAvatarId(this.getAvatarId())
.setGuid(this.getGuid())
......@@ -681,7 +728,7 @@ public class GenshinAvatar {
.putAllProudSkillExtraLevel(getProudSkillBonusMap())
.setAvatarType(1)
.setBornTime(this.getBornTime())
.setFetterInfo(AvatarFetterInfo.newBuilder().setExpLevel(1))
.setFetterInfo(avatarFetter)
.setWearingFlycloakId(this.getFlyCloak())
.setCostumeId(this.getCostume());
......
......@@ -223,8 +223,8 @@ public class EntityAvatar extends GenshinEntity {
}
}
// Add equip abilities
if (this.getAvatar().getBonusAbilityList().size() > 0) {
for (String skill : this.getAvatar().getBonusAbilityList()) {
if (this.getAvatar().getExtraAbilityEmbryos().size() > 0) {
for (String skill : this.getAvatar().getExtraAbilityEmbryos()) {
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId)
.setAbilityNameHash(Utils.abilityHash(skill))
......
......@@ -220,7 +220,7 @@ public class FriendsList {
friendship.setOwner(getPlayer());
// Check if friend is online
GenshinPlayer friend = getPlayer().getSession().getServer().getPlayerByUid(friendship.getFriendProfile().getId());
GenshinPlayer friend = getPlayer().getSession().getServer().getPlayerByUid(friendship.getFriendProfile().getUid());
if (friend != null) {
// Set friend to online mode
friendship.setFriendProfile(friend);
......
......@@ -88,7 +88,7 @@ public class Friendship {
public FriendBrief toProto() {
FriendBrief proto = FriendBrief.newBuilder()
.setUid(getFriendProfile().getId())
.setUid(getFriendProfile().getUid())
.setNickname(getFriendProfile().getName())
.setLevel(getFriendProfile().getPlayerLevel())
.setAvatar(HeadImage.newBuilder().setAvatarId(getFriendProfile().getAvatarId()))
......
......@@ -8,7 +8,7 @@ import emu.grasscutter.utils.Utils;
public class PlayerProfile {
@Transient private GenshinPlayer player;
private int id;
@AlsoLoad("id") private int uid;
private int nameCard;
private int avatarId;
private String name;
......@@ -23,12 +23,12 @@ public class PlayerProfile {
public PlayerProfile() { }
public PlayerProfile(GenshinPlayer player) {
this.id = player.getUid();
this.uid = player.getUid();
this.syncWithCharacter(player);
}
public int getId() {
return id;
public int getUid() {
return uid;
}
public GenshinPlayer getPlayer() {
......@@ -88,6 +88,7 @@ public class PlayerProfile {
return;
}
this.uid = player.getUid();
this.name = player.getNickname();
this.avatarId = player.getHeadImage();
this.signature = player.getSignature();
......
......@@ -92,7 +92,7 @@ public class GachaBanner {
}
public GachaInfo toProto() {
String record = "http://" + (Grasscutter.getConfig().DispatchServerPublicIp.isEmpty() ? Grasscutter.getConfig().DispatchServerIp : Grasscutter.getConfig().DispatchServerPublicIp) + "/gacha";
String record = "http://" + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getDispatchOptions().Ip : Grasscutter.getConfig().getDispatchOptions().PublicIp) + "/gacha";
GachaInfo.Builder info = GachaInfo.newBuilder()
.setGachaType(this.getGachaType())
......
......@@ -218,7 +218,6 @@ public class GachaManager {
addStarglitter = 2;
// Add 1 const
gachaItem.addTransferItems(GachaTransferItem.newBuilder().setItem(ItemParam.newBuilder().setItemId(constItemId).setCount(1)).setIsTransferItemNew(constItem == null));
gachaItem.addTokenItemList(ItemParam.newBuilder().setItemId(constItemId).setCount(1));
player.getInventory().addItem(constItemId, 1);
} else {
// Is max const
......@@ -300,7 +299,7 @@ public class GachaManager {
@Subscribe
public synchronized void watchBannerJson(GameServerTickEvent tickEvent) {
if(Grasscutter.getConfig().getServerOptions().WatchGacha) {
if(Grasscutter.getConfig().getGameServerOptions().WatchGacha) {
try {
WatchKey watchKey = watchService.take();
......
......@@ -37,10 +37,10 @@ public class Inventory implements Iterable<GenshinItem> {
this.store = new Long2ObjectOpenHashMap<>();
this.inventoryTypes = new Int2ObjectOpenHashMap<>();
this.createInventoryTab(ItemType.ITEM_WEAPON, new EquipInventoryTab(Grasscutter.getConfig().getServerOptions().InventoryLimitWeapon));
this.createInventoryTab(ItemType.ITEM_RELIQUARY, new EquipInventoryTab(Grasscutter.getConfig().getServerOptions().InventoryLimitRelic));
this.createInventoryTab(ItemType.ITEM_MATERIAL, new MaterialInventoryTab(Grasscutter.getConfig().getServerOptions().InventoryLimitMaterial));
this.createInventoryTab(ItemType.ITEM_FURNITURE, new MaterialInventoryTab(Grasscutter.getConfig().getServerOptions().InventoryLimitFurniture));
this.createInventoryTab(ItemType.ITEM_WEAPON, new EquipInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitWeapon));
this.createInventoryTab(ItemType.ITEM_RELIQUARY, new EquipInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitRelic));
this.createInventoryTab(ItemType.ITEM_MATERIAL, new MaterialInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitMaterial));
this.createInventoryTab(ItemType.ITEM_FURNITURE, new MaterialInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitFurniture));
}
public GenshinPlayer getPlayer() {
......
......@@ -589,7 +589,6 @@ public class InventoryManager {
// Update proud skills
AvatarSkillDepotData skillDepot = GenshinData.getAvatarSkillDepotDataMap().get(avatar.getSkillDepotId());
boolean hasAddedProudSkill = false;
if (skillDepot != null && skillDepot.getInherentProudSkillOpens() != null) {
for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) {
......@@ -599,7 +598,6 @@ public class InventoryManager {
if (openData.getNeedAvatarPromoteLevel() == avatar.getPromoteLevel()) {
int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1;
if (GenshinData.getProudSkillDataMap().containsKey(proudSkillId)) {
hasAddedProudSkill = true;
avatar.getProudSkillList().add(proudSkillId);
player.sendPacket(new PacketProudSkillChangeNotify(avatar));
}
......@@ -607,20 +605,13 @@ public class InventoryManager {
}
}
// Racalc stats and save avatar
avatar.recalcStats();
avatar.save();
// Resend ability embryos if proud skill has been added
if (hasAddedProudSkill && avatar.getAsEntity() != null) {
player.sendPacket(new PacketAbilityChangeNotify(avatar.getAsEntity()));
}
// TODO Send entity prop update packet to world
// Packets
player.sendPacket(new PacketAvatarPropNotify(avatar));
player.sendPacket(new PacketAvatarPromoteRsp(avatar));
// TODO Send entity prop update packet to world
avatar.recalcStats(true);
avatar.save();
}
public void upgradeAvatar(GenshinPlayer player, long guid, int itemId, int count) {
......@@ -827,25 +818,20 @@ public class InventoryManager {
// Apply + recalc
avatar.getTalentIdList().add(talentData.getId());
avatar.setCoreProudSkillLevel(currentTalentLevel + 1);
avatar.recalcStats();
// Packet
player.sendPacket(new PacketAvatarUnlockTalentNotify(avatar, nextTalentId));
player.sendPacket(new PacketUnlockAvatarTalentRsp(avatar, nextTalentId));
// Proud skill bonus map
// Proud skill bonus map (Extra skills)
OpenConfigEntry entry = GenshinData.getOpenConfigEntries().get(talentData.getOpenConfig());
if (entry != null && entry.getExtraTalentIndex() > 0) {
avatar.recalcProudSkillBonusMap();
player.sendPacket(new PacketProudSkillExtraLevelNotify(avatar, entry.getExtraTalentIndex()));
}
// Resend ability embryos
if (avatar.getAsEntity() != null) {
player.sendPacket(new PacketAbilityChangeNotify(avatar.getAsEntity()));
}
// Save avatar
// Recalc + save avatar
avatar.recalcStats(true);
avatar.save();
}
......
package emu.grasscutter.game.props;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public enum FetterState {
NONE(0),
NOT_OPEN(1),
OPEN(1),
FINISH(3);
private final int value;
private static final Int2ObjectMap<FetterState> map = new Int2ObjectOpenHashMap<>();
private static final Map<String, FetterState> stringMap = new HashMap<>();
static {
Stream.of(values()).forEach(e -> {
map.put(e.getValue(), e);
stringMap.put(e.name(), e);
});
}
private FetterState(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static FetterState getTypeByValue(int value) {
return map.getOrDefault(value, NONE);
}
public static FetterState getTypeByName(String name) {
return stringMap.getOrDefault(name, NONE);
}
}
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