Commit 01b190bc authored by Magix's avatar Magix Committed by GitHub
Browse files

UPGRADE TO 1.1.0 POG

Merge `development` into `stable`
parents 6b81b888 1beddf16
package emu.grasscutter.game.entity;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
import emu.grasscutter.net.proto.FightPropPairOuterClass.*;
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo;
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
import emu.grasscutter.net.proto.VehicleInfoOuterClass.*;
import emu.grasscutter.net.proto.VehicleMemberOuterClass.*;
import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
import java.util.List;
import java.util.ArrayList;
public class EntityVehicle extends EntityBaseGadget {
private final Player owner;
private final Int2FloatOpenHashMap fightProp;
private final Position pos;
private final Position rot;
private final int pointId;
private final int gadgetId;
private float curStamina;
private List<VehicleMember> vehicleMembers;
public EntityVehicle(Scene scene, Player player, int gadgetId, int pointId, Position pos, Position rot) {
super(scene);
this.owner = player;
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
this.fightProp = new Int2FloatOpenHashMap();
this.pos = new Position(pos);
this.rot = new Position(rot);
this.gadgetId = gadgetId;
this.pointId = pointId;
this.curStamina = 240;
this.vehicleMembers = new ArrayList<VehicleMember>();
}
@Override
public int getGadgetId() { return gadgetId; }
public Player getOwner() {
return owner;
}
public float getCurStamina() { return curStamina; }
public void setCurStamina(float stamina) { this.curStamina = stamina; }
public int getPointId() { return pointId; }
public List<VehicleMember> getVehicleMembers() { return vehicleMembers; }
@Override
public Int2FloatOpenHashMap getFightProperties() {
return fightProp;
}
@Override
public Position getPosition() { return this.pos; }
@Override
public Position getRotation() {
return this.rot;
}
@Override
public SceneEntityInfo toProto() {
VehicleInfo vehicle = VehicleInfo.newBuilder()
.setOwnerUid(this.owner.getUid())
.setCurStamina(getCurStamina())
.build();
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(getPosition().toProto()))
.setBornPos(getPosition().toProto())
.build();
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder()
.setGadgetId(this.getGadgetId())
.setAuthorityPeerId(this.getOwner().getPeerId())
.setIsEnableInteract(true)
.setVehicleInfo(vehicle);
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId())
.setEntityType(ProtEntityType.PROT_ENTITY_GADGET)
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder()))
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setGadget(gadgetInfo)
.setEntityAuthorityInfo(authority)
.setLifeState(1);
PropPair pair = PropPair.newBuilder()
.setType(PlayerProperty.PROP_LEVEL.getId())
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 47))
.build();
for (Int2FloatMap.Entry entry : getFightProperties().int2FloatEntrySet()) {
if (entry.getIntKey() == 0) {
continue;
}
FightPropPair fightProp = FightPropPair.newBuilder().setPropType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build();
entityInfo.addFightPropList(fightProp);
}
entityInfo.addPropList(pair);
return entityInfo.build();
}
}
package emu.grasscutter.game.entity;
import emu.grasscutter.game.GenshinScene;
import emu.grasscutter.game.World;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.LifeState;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.game.world.SpawnDataEntry;
import emu.grasscutter.game.world.World;
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
......@@ -11,28 +12,37 @@ import emu.grasscutter.net.proto.VectorOuterClass.Vector;
import emu.grasscutter.utils.Position;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public abstract class GenshinEntity {
public abstract class GameEntity {
protected int id;
private final GenshinScene scene;
private final Scene scene;
private SpawnDataEntry spawnEntry;
private int blockId;
private int configId;
private int groupId;
private MotionState moveState;
private int lastMoveSceneTimeMs;
private int lastMoveReliableSeq;
public GenshinEntity(GenshinScene scene) {
public GameEntity(Scene scene) {
this.scene = scene;
this.moveState = MotionState.MotionNone;
this.moveState = MotionState.MOTION_NONE;
}
public int getId() {
return this.id;
}
public int getEntityType() {
return getId() >> 24;
}
public World getWorld() {
return this.getScene().getWorld();
}
public GenshinScene getScene() {
public Scene getScene() {
return this.scene;
}
......@@ -94,6 +104,30 @@ public abstract class GenshinEntity {
return getFightProperties().getOrDefault(prop.getId(), 0f);
}
public int getBlockId() {
return blockId;
}
public void setBlockId(int blockId) {
this.blockId = blockId;
}
public int getConfigId() {
return configId;
}
public void setConfigId(int configId) {
this.configId = configId;
}
public int getGroupId() {
return groupId;
}
public void setGroupId(int groupId) {
this.groupId = groupId;
}
protected MotionInfo getMotionInfo() {
MotionInfo proto = MotionInfo.newBuilder()
.setPos(getPosition().toProto())
......@@ -104,4 +138,12 @@ public abstract class GenshinEntity {
return proto;
}
public SpawnDataEntry getSpawnEntry() {
return spawnEntry;
}
public void setSpawnEntry(SpawnDataEntry spawnEntry) {
this.spawnEntry = spawnEntry;
}
}
package emu.grasscutter.game.expedition;
import dev.morphia.annotations.Entity;
@Entity
public class ExpeditionInfo {
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public int getExpId() {
return expId;
}
public void setExpId(int expId) {
this.expId = expId;
}
public int getHourTime() {
return hourTime;
}
public void setHourTime(int hourTime) {
this.hourTime = hourTime;
}
public int getStartTime() {
return startTime;
}
public void setStartTime(int startTime) {
this.startTime = startTime;
}
private int state;
private int expId;
private int hourTime;
private int startTime;
}
package emu.grasscutter.game.expedition;
import com.google.gson.reflect.TypeToken;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.server.game.GameServer;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.io.FileReader;
import java.util.Collection;
import java.util.List;
public class ExpeditionManager {
public GameServer getGameServer() {
return gameServer;
}
private final GameServer gameServer;
public Int2ObjectMap<List<ExpeditionRewardDataList>> getExpeditionRewardDataList() { return expeditionRewardData; }
private final Int2ObjectMap<List<ExpeditionRewardDataList>> expeditionRewardData;
public ExpeditionManager(GameServer gameServer) {
this.gameServer = gameServer;
this.expeditionRewardData = new Int2ObjectOpenHashMap<>();
this.load();
}
public synchronized void load() {
try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "ExpeditionReward.json")) {
getExpeditionRewardDataList().clear();
List<ExpeditionRewardInfo> banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ExpeditionRewardInfo.class).getType());
if(banners.size() > 0) {
for (ExpeditionRewardInfo di : banners) {
getExpeditionRewardDataList().put(di.getExpId(), di.getExpeditionRewardDataList());
}
Grasscutter.getLogger().info("Expedition reward successfully loaded.");
} else {
Grasscutter.getLogger().error("Unable to load expedition reward. Expedition reward size is 0.");
}
} catch (Exception e) {
Grasscutter.getLogger().error("Unable to load expedition reward.", e);
}
}
}
package emu.grasscutter.game.expedition;
public class ExpeditionRewardData {
private int itemId;
private int minCount;
private int maxCount;
public int getItemId() {
return itemId;
}
public int getMinCount() { return minCount; }
public int getMaxCount() {
return maxCount;
}
}
package emu.grasscutter.game.expedition;
import java.util.List;
public class ExpeditionRewardDataList {
public int getHourTime() {
return hourTime;
}
public List<ExpeditionRewardData> getExpeditionRewardData() {
return expeditionRewardData;
}
private int hourTime;
private List<ExpeditionRewardData> expeditionRewardData;
}
package emu.grasscutter.game.expedition;
import java.util.List;
public class ExpeditionRewardInfo {
public int getExpId() {
return expId;
}
public List<ExpeditionRewardDataList> getExpeditionRewardDataList() {
return expeditionRewardDataList;
}
private int expId;
private List<ExpeditionRewardDataList> expeditionRewardDataList;
}
......@@ -3,7 +3,7 @@ package emu.grasscutter.game.friends;
import java.util.List;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.proto.DealAddFriendResultTypeOuterClass.DealAddFriendResultType;
import emu.grasscutter.server.packet.send.PacketAskAddFriendNotify;
import emu.grasscutter.server.packet.send.PacketAskAddFriendRsp;
......@@ -14,20 +14,20 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class FriendsList {
private final GenshinPlayer player;
private final Player player;
private final Int2ObjectMap<Friendship> friends;
private final Int2ObjectMap<Friendship> pendingFriends;
private boolean loaded = false;
public FriendsList(GenshinPlayer player) {
public FriendsList(Player player) {
this.player = player;
this.friends = new Int2ObjectOpenHashMap<Friendship>();
this.pendingFriends = new Int2ObjectOpenHashMap<Friendship>();
}
public GenshinPlayer getPlayer() {
public Player getPlayer() {
return player;
}
......@@ -83,7 +83,7 @@ public class FriendsList {
return;
}
GenshinPlayer target = getPlayer().getSession().getServer().getPlayerByUid(targetUid, true);
Player target = getPlayer().getSession().getServer().getPlayerByUid(targetUid, true);
if (target == null) {
return; // Should never happen
}
......@@ -104,7 +104,7 @@ public class FriendsList {
}
// Handle
if (result == DealAddFriendResultType.DealAddFriendAccept) { // Request accepted
if (result == DealAddFriendResultType.DEAL_ADD_FRIEND_ACCEPT) { // Request accepted
myFriendship.setIsFriend(true);
theirFriendship.setIsFriend(true);
......@@ -143,7 +143,7 @@ public class FriendsList {
myFriendship.delete();
Friendship theirFriendship = null;
GenshinPlayer friend = myFriendship.getFriendProfile().getPlayer();
Player friend = myFriendship.getFriendProfile().getPlayer();
if (friend != null) {
// Friend online
theirFriendship = friend.getFriendsList().getFriendById(this.getPlayer().getUid());
......@@ -165,7 +165,7 @@ public class FriendsList {
}
public synchronized void sendFriendRequest(int targetUid) {
GenshinPlayer target = getPlayer().getSession().getServer().getPlayerByUid(targetUid, true);
Player target = getPlayer().getSession().getServer().getPlayerByUid(targetUid, true);
if (target == null || target == this.getPlayer()) {
return;
......@@ -220,7 +220,7 @@ public class FriendsList {
friendship.setOwner(getPlayer());
// Check if friend is online
GenshinPlayer friend = getPlayer().getSession().getServer().getPlayerByUid(friendship.getFriendProfile().getUid());
Player friend = getPlayer().getSession().getServer().getPlayerByUid(friendship.getFriendProfile().getUid());
if (friend != null) {
// Set friend to online mode
friendship.setFriendProfile(friend);
......
package emu.grasscutter.game.friends;
import emu.grasscutter.net.proto.PlatformTypeOuterClass;
import org.bson.types.ObjectId;
import dev.morphia.annotations.*;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.proto.FriendBriefOuterClass.FriendBrief;
import emu.grasscutter.net.proto.FriendOnlineStateOuterClass.FriendOnlineState;
import emu.grasscutter.net.proto.HeadImageOuterClass.HeadImage;
import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture;
@Entity(value = "friendships", noClassnameStored = true)
@Entity(value = "friendships", useDiscriminator = false)
public class Friendship {
@Id private ObjectId id;
@Transient private GenshinPlayer owner;
@Transient private Player owner;
@Indexed private int ownerId;
@Indexed private int friendId;
......@@ -25,7 +26,7 @@ public class Friendship {
@Deprecated // Morphia use only
public Friendship() { }
public Friendship(GenshinPlayer owner, GenshinPlayer friend, GenshinPlayer asker) {
public Friendship(Player owner, Player friend, Player asker) {
this.setOwner(owner);
this.ownerId = owner.getUid();
this.friendId = friend.getUid();
......@@ -33,11 +34,11 @@ public class Friendship {
this.askerId = asker.getUid();
}
public GenshinPlayer getOwner() {
public Player getOwner() {
return owner;
}
public void setOwner(GenshinPlayer owner) {
public void setOwner(Player owner) {
this.owner = owner;
}
......@@ -69,7 +70,7 @@ public class Friendship {
return profile;
}
public void setFriendProfile(GenshinPlayer character) {
public void setFriendProfile(Player character) {
if (character == null || this.friendId != character.getUid()) return;
this.profile = character.getProfile();
}
......@@ -91,16 +92,16 @@ public class Friendship {
.setUid(getFriendProfile().getUid())
.setNickname(getFriendProfile().getName())
.setLevel(getFriendProfile().getPlayerLevel())
.setAvatar(HeadImage.newBuilder().setAvatarId(getFriendProfile().getAvatarId()))
.setProfilePicture(ProfilePicture.newBuilder().setAvatarId(getFriendProfile().getAvatarId()))
.setWorldLevel(getFriendProfile().getWorldLevel())
.setSignature(getFriendProfile().getSignature())
.setOnlineState(getFriendProfile().isOnline() ? FriendOnlineState.FRIEND_ONLINE : FriendOnlineState.FRIEND_DISCONNECT)
.setOnlineState(getFriendProfile().isOnline() ? FriendOnlineState.FRIEND_ONLINE : FriendOnlineState.FREIEND_DISCONNECT)
.setIsMpModeAvailable(true)
.setLastActiveTime(getFriendProfile().getLastActiveTime())
.setNameCardId(getFriendProfile().getNameCard())
.setParam(getFriendProfile().getDaysSinceLogin())
.setUnk1(1)
.setUnk2(3)
.setIsGameSource(true)
.setPlatformType(PlatformTypeOuterClass.PlatformType.PC)
.build();
return proto;
......
package emu.grasscutter.game.friends;
import dev.morphia.annotations.*;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.utils.Utils;
@Entity
public class PlayerProfile {
@Transient private GenshinPlayer player;
@Transient private Player player;
@AlsoLoad("id") private int uid;
private int nameCard;
......@@ -21,7 +22,7 @@ public class PlayerProfile {
@Deprecated // Morphia only
public PlayerProfile() { }
public PlayerProfile(GenshinPlayer player) {
public PlayerProfile(Player player) {
this.uid = player.getUid();
this.syncWithCharacter(player);
}
......@@ -30,11 +31,11 @@ public class PlayerProfile {
return uid;
}
public GenshinPlayer getPlayer() {
public Player getPlayer() {
return player;
}
public synchronized void setPlayer(GenshinPlayer player) {
public synchronized void setPlayer(Player player) {
this.player = player;
}
......@@ -82,7 +83,7 @@ public class PlayerProfile {
return this.getPlayer() != null;
}
public void syncWithCharacter(GenshinPlayer player) {
public void syncWithCharacter(Player player) {
if (player == null) {
return;
}
......
......@@ -16,8 +16,8 @@ public class GachaBanner {
private int sortId;
private int[] rateUpItems1;
private int[] rateUpItems2;
private int minItemType = 1;
private int maxItemType = 2;
private int baseYellowWeight = 60; // Max 10000
private int basePurpleWeight = 510; // Max 10000
private int eventChance = 50; // Chance to win a featured event item
private int softPity = 75;
private int hardPity = 90;
......@@ -63,6 +63,14 @@ public class GachaBanner {
return sortId;
}
public int getBaseYellowWeight() {
return baseYellowWeight;
}
public int getBasePurpleWeight() {
return basePurpleWeight;
}
public int[] getRateUpItems1() {
return rateUpItems1;
}
......@@ -70,14 +78,6 @@ public class GachaBanner {
public int[] getRateUpItems2() {
return rateUpItems2;
}
public int getMinItemType() {
return minItemType;
}
public int getMaxItemType() {
return maxItemType;
}
public int getSoftPity() {
return softPity - 1;
......@@ -91,9 +91,21 @@ public class GachaBanner {
return eventChance;
}
@Deprecated
public GachaInfo toProto() {
String record = "http://" + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getDispatchOptions().Ip : Grasscutter.getConfig().getDispatchOptions().PublicIp) + "/gacha";
return toProto("");
}
public GachaInfo toProto(String sessionKey) {
String record = "http" + (Grasscutter.getConfig().getDispatchOptions().FrontHTTPS ? "s" : "") + "://"
+ (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ?
Grasscutter.getConfig().getDispatchOptions().Ip :
Grasscutter.getConfig().getDispatchOptions().PublicIp)
+ ":"
+ Integer.toString(Grasscutter.getConfig().getDispatchOptions().PublicPort == 0 ?
Grasscutter.getConfig().getDispatchOptions().Port :
Grasscutter.getConfig().getDispatchOptions().PublicPort)
+ "/gacha?s=" + sessionKey + "&gachaType=" + gachaType;
// Grasscutter.getLogger().info("record = " + record);
GachaInfo.Builder info = GachaInfo.newBuilder()
.setGachaType(this.getGachaType())
.setScheduleId(this.getScheduleId())
......
......@@ -12,13 +12,15 @@ import com.google.gson.reflect.TypeToken;
import com.sun.nio.file.SensitivityWatchEventModifier;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.gacha.GachaBanner.BannerType;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.inventory.MaterialType;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.proto.GachaItemOuterClass.GachaItem;
import emu.grasscutter.net.proto.GachaTransferItemOuterClass.GachaTransferItem;
import emu.grasscutter.net.proto.GetGachaInfoRspOuterClass.GetGachaInfoRsp;
......@@ -89,7 +91,7 @@ public class GachaManager {
}
}
public synchronized void doPulls(GenshinPlayer player, int gachaType, int times) {
public synchronized void doPulls(Player player, int gachaType, int times) {
// Sanity check
if (times != 10 && times != 1) {
return;
......@@ -108,7 +110,7 @@ public class GachaManager {
// Spend currency
if (banner.getCostItem() > 0) {
GenshinItem costItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(banner.getCostItem());
GameItem costItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(banner.getCostItem());
if (costItem == null || costItem.getCount() < times) {
return;
}
......@@ -125,14 +127,14 @@ public class GachaManager {
int itemId = 0;
int bonusYellowChance = gachaInfo.getPity5() >= banner.getSoftPity() ? 100 * (gachaInfo.getPity5() - banner.getSoftPity() - 1): 0;
int yellowChance = 60 + (int) Math.floor(100f * (gachaInfo.getPity5() / (banner.getSoftPity() - 1D))) + bonusYellowChance;
int purpleChance = 10000 - (510 + (int) Math.floor(790f * (gachaInfo.getPity4() / 8f)));
int yellowChance = banner.getBaseYellowWeight() + (int) Math.floor(100f * (gachaInfo.getPity5() / (banner.getSoftPity() - 1D))) + bonusYellowChance;
int purpleChance = 10000 - (banner.getBasePurpleWeight() + (int) Math.floor(790f * (gachaInfo.getPity4() / 8f)));
if (random <= yellowChance || gachaInfo.getPity5() >= banner.getHardPity()) {
if (banner.getRateUpItems1().length > 0) {
int eventChance = this.randomRange(1, 100);
if (eventChance >= banner.getEventChance() || gachaInfo.getFailedFeaturedItemPulls() >= 1) {
if (eventChance <= banner.getEventChance() || gachaInfo.getFailedFeaturedItemPulls() >= 1) {
itemId = getRandom(banner.getRateUpItems1());
gachaInfo.setFailedFeaturedItemPulls(0);
} else {
......@@ -142,7 +144,7 @@ public class GachaManager {
}
if (itemId == 0) {
int typeChance = this.randomRange(banner.getMinItemType(), banner.getMaxItemType());
int typeChance = this.randomRange(banner.getBannerType() == BannerType.WEAPON ? 2 : 1, banner.getBannerType() == BannerType.EVENT ? 1 : 2);
if (typeChance == 1) {
itemId = getRandom(this.yellowAvatars);
} else {
......@@ -163,7 +165,7 @@ public class GachaManager {
}
if (itemId == 0) {
int typeChance = this.randomRange(banner.getMinItemType(), banner.getMaxItemType());
int typeChance = this.randomRange(banner.getBannerType() == BannerType.WEAPON ? 2 : 1, banner.getBannerType() == BannerType.EVENT ? 1 : 2);
if (typeChance == 1) {
itemId = getRandom(this.purpleAvatars);
} else {
......@@ -191,10 +193,14 @@ public class GachaManager {
int stardust = 0, starglitter = 0;
for (int itemId : wonItems) {
ItemData itemData = GenshinData.getItemDataMap().get(itemId);
ItemData itemData = GameData.getItemDataMap().get(itemId);
if (itemData == null) {
continue;
}
// Write gacha record
GachaRecord gachaRecord = new GachaRecord(itemId, player.getUid(), gachaType);
DatabaseHelper.saveGachaRecord(gachaRecord);
// Create gacha item
GachaItem.Builder gachaItem = GachaItem.newBuilder();
......@@ -204,11 +210,11 @@ public class GachaManager {
// Const check
if (itemData.getMaterialType() == MaterialType.MATERIAL_AVATAR) {
int avatarId = (itemData.getId() % 1000) + 10000000;
GenshinAvatar avatar = player.getAvatars().getAvatarById(avatarId);
Avatar avatar = player.getAvatars().getAvatarById(avatarId);
if (avatar != null) {
int constLevel = avatar.getCoreProudSkillLevel();
int constItemId = itemData.getId() + 100;
GenshinItem constItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(constItemId);
GameItem constItem = player.getInventory().getInventoryTab(ItemType.ITEM_MATERIAL).getItemById(constItemId);
if (constItem != null) {
constLevel += constItem.getCount();
}
......@@ -249,7 +255,7 @@ public class GachaManager {
}
// Create item
GenshinItem item = new GenshinItem(itemData);
GameItem item = new GameItem(itemData);
gachaItem.setGachaItem(item.toItemParam());
player.getInventory().addItem(item);
......@@ -286,8 +292,6 @@ public class GachaManager {
this.watchService = FileSystems.getDefault().newWatchService();
Path path = new File(Grasscutter.getConfig().DATA_FOLDER).toPath();
path.register(watchService, new WatchEvent.Kind[]{StandardWatchEventKinds.ENTRY_MODIFY}, SensitivityWatchEventModifier.HIGH);
server.OnGameServerTick.register(this);
} catch (Exception e) {
Grasscutter.getLogger().error("Unable to load the Gacha Manager Watch Service. If ServerOptions.watchGacha is true it will not auto-reload");
e.printStackTrace();
......@@ -322,6 +326,7 @@ public class GachaManager {
}
}
@Deprecated
private synchronized GetGachaInfoRsp createProto() {
GetGachaInfoRsp.Builder proto = GetGachaInfoRsp.newBuilder().setGachaRandom(12345);
......@@ -331,12 +336,26 @@ public class GachaManager {
return proto.build();
}
private synchronized GetGachaInfoRsp createProto(String sessionKey) {
GetGachaInfoRsp.Builder proto = GetGachaInfoRsp.newBuilder().setGachaRandom(12345);
for (GachaBanner banner : getGachaBanners().values()) {
proto.addGachaInfoList(banner.toProto(sessionKey));
}
return proto.build();
}
@Deprecated
public GetGachaInfoRsp toProto() {
if (this.cachedProto == null) {
this.cachedProto = createProto();
}
return this.cachedProto;
}
public GetGachaInfoRsp toProto(String sessionKey) {
return createProto(sessionKey);
}
}
package emu.grasscutter.game.gacha;
import java.util.Date;
import org.bson.types.ObjectId;
import dev.morphia.annotations.*;
@Entity(value = "gachas", useDiscriminator = false)
public class GachaRecord {
@Id private ObjectId id;
@Indexed private int ownerId;
private Date transactionDate;
private int itemID;
@Indexed private int gachaType;
public GachaRecord() {}
public GachaRecord(int itemId ,int ownerId, int gachaType){
this.transactionDate = new Date();
this.itemID = itemId;
this.ownerId = ownerId;
this.gachaType = gachaType;
}
public int getOwnerId() {
return ownerId;
}
public void setOwnerId(int ownerId) {
this.ownerId = ownerId;
}
public int getGachaType() {
return gachaType;
}
public void setGachaType(int type) {
this.gachaType = type;
}
public Date getTransactionDate() {
return transactionDate;
}
public void setTransactionDate(Date transactionDate) {
this.transactionDate = transactionDate;
}
public int getItemID() {
return itemID;
}
public void setItemID(int itemID) {
this.itemID = itemID;
}
public ObjectId getId(){
return id;
}
public void setId(ObjectId id) {
this.id = id;
}
public String toString() {
return toJsonString();
}
public String toJsonString() {
return "{\"time\": " + this.transactionDate.getTime() + ",\"item\":" + this.itemID + "}";
}
}
package emu.grasscutter.game.gacha;
import dev.morphia.annotations.Entity;
@Entity
public class PlayerGachaBannerInfo {
private int pity5 = 0;
private int pity4 = 0;
......
package emu.grasscutter.game.gacha;
import dev.morphia.annotations.Entity;
@Entity
public class PlayerGachaInfo {
private PlayerGachaBannerInfo standardBanner;
private PlayerGachaBannerInfo eventCharacterBanner;
......
......@@ -4,26 +4,26 @@ import java.util.HashSet;
import java.util.Set;
public class EquipInventoryTab implements InventoryTab {
private final Set<GenshinItem> items;
private final Set<GameItem> items;
private final int maxCapacity;
public EquipInventoryTab(int maxCapacity) {
this.items = new HashSet<GenshinItem>();
this.items = new HashSet<GameItem>();
this.maxCapacity = maxCapacity;
}
@Override
public GenshinItem getItemById(int id) {
public GameItem getItemById(int id) {
return null;
}
@Override
public void onAddItem(GenshinItem item) {
public void onAddItem(GameItem item) {
this.items.add(item);
}
@Override
public void onRemoveItem(GenshinItem item) {
public void onRemoveItem(GameItem item) {
this.items.remove(item);
}
......
......@@ -13,13 +13,13 @@ import dev.morphia.annotations.Indexed;
import dev.morphia.annotations.PostLoad;
import dev.morphia.annotations.Transient;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.GenshinDepot;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.GameDepot;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.data.def.ReliquaryAffixData;
import emu.grasscutter.data.def.ReliquaryMainPropData;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.EquipOuterClass.Equip;
......@@ -34,8 +34,8 @@ import emu.grasscutter.net.proto.SceneWeaponInfoOuterClass.SceneWeaponInfo;
import emu.grasscutter.net.proto.WeaponOuterClass.Weapon;
import emu.grasscutter.utils.WeightedList;
@Entity(value = "items", noClassnameStored = true)
public class GenshinItem {
@Entity(value = "items", useDiscriminator = false)
public class GameItem {
@Id private ObjectId id;
@Indexed private int ownerId;
private int itemId;
......@@ -62,23 +62,23 @@ public class GenshinItem {
private int equipCharacter;
@Transient private int weaponEntityId;
public GenshinItem() {
public GameItem() {
// Morphia only
}
public GenshinItem(int itemId) {
this(GenshinData.getItemDataMap().get(itemId));
public GameItem(int itemId) {
this(GameData.getItemDataMap().get(itemId));
}
public GenshinItem(int itemId, int count) {
this(GenshinData.getItemDataMap().get(itemId), count);
public GameItem(int itemId, int count) {
this(GameData.getItemDataMap().get(itemId), count);
}
public GenshinItem(ItemData data) {
public GameItem(ItemData data) {
this(data, 1);
}
public GenshinItem(ItemData data, int count) {
public GameItem(ItemData data, int count) {
this.itemId = data.getId();
this.itemData = data;
......@@ -90,7 +90,7 @@ public class GenshinItem {
// Equip data
if (getItemType() == ItemType.ITEM_WEAPON) {
this.level = 1;
this.level = Math.max(this.count, 1);
this.affixes = new ArrayList<>(2);
if (getItemData().getSkillAffix() != null) {
for (int skillAffix : getItemData().getSkillAffix()) {
......@@ -103,7 +103,7 @@ public class GenshinItem {
this.level = 1;
this.appendPropIdList = new ArrayList<>();
// Create main property
ReliquaryMainPropData mainPropData = GenshinDepot.getRandomRelicMainProp(getItemData().getMainPropDepotId());
ReliquaryMainPropData mainPropData = GameDepot.getRandomRelicMainProp(getItemData().getMainPropDepotId());
if (mainPropData != null) {
this.mainPropId = mainPropData.getId();
}
......@@ -124,9 +124,9 @@ public class GenshinItem {
return ownerId;
}
public void setOwner(GenshinPlayer player) {
public void setOwner(Player player) {
this.ownerId = player.getUid();
this.guid = player.getNextGenshinGuid();
this.guid = player.getNextGameGuid();
}
public int getItemId() {
return itemId;
......@@ -244,6 +244,10 @@ public class GenshinItem {
return mainPropId;
}
public void setMainPropId(int mainPropId) {
this.mainPropId = mainPropId;
}
public List<Integer> getAppendPropIdList() {
return appendPropIdList;
}
......@@ -261,7 +265,7 @@ public class GenshinItem {
}
private void addNewAppendProp() {
List<ReliquaryAffixData> affixList = GenshinDepot.getRandomRelicAffixList(getItemData().getAppendPropDepotId());
List<ReliquaryAffixData> affixList = GameDepot.getRandomRelicAffixList(getItemData().getAppendPropDepotId());
if (affixList == null) {
return;
......@@ -269,13 +273,13 @@ public class GenshinItem {
// Build blacklist - Dont add same stat as main/sub stat
Set<FightProperty> blacklist = new HashSet<>();
ReliquaryMainPropData mainPropData = GenshinData.getReliquaryMainPropDataMap().get(this.getMainPropId());
ReliquaryMainPropData mainPropData = GameData.getReliquaryMainPropDataMap().get(this.getMainPropId());
if (mainPropData != null) {
blacklist.add(mainPropData.getFightProp());
}
int len = Math.min(4, this.getAppendPropIdList().size());
for (int i = 0; i < len; i++) {
ReliquaryAffixData affixData = GenshinData.getReliquaryAffixDataMap().get((int) this.getAppendPropIdList().get(i));
ReliquaryAffixData affixData = GameData.getReliquaryAffixDataMap().get((int) this.getAppendPropIdList().get(i));
if (affixData != null) {
blacklist.add(affixData.getFightProp());
}
......@@ -299,7 +303,7 @@ public class GenshinItem {
}
private void upgradeRandomAppendProp() {
List<ReliquaryAffixData> affixList = GenshinDepot.getRandomRelicAffixList(getItemData().getAppendPropDepotId());
List<ReliquaryAffixData> affixList = GameDepot.getRandomRelicAffixList(getItemData().getAppendPropDepotId());
if (affixList == null) {
return;
......@@ -309,7 +313,7 @@ public class GenshinItem {
Set<FightProperty> whitelist = new HashSet<>();
int len = Math.min(4, this.getAppendPropIdList().size());
for (int i = 0; i < len; i++) {
ReliquaryAffixData affixData = GenshinData.getReliquaryAffixDataMap().get((int) this.getAppendPropIdList().get(i));
ReliquaryAffixData affixData = GameData.getReliquaryAffixDataMap().get((int) this.getAppendPropIdList().get(i));
if (affixData != null) {
whitelist.add(affixData.getFightProp());
}
......@@ -331,7 +335,7 @@ public class GenshinItem {
@PostLoad
public void onLoad() {
if (this.itemData == null) {
this.itemData = GenshinData.getItemDataMap().get(getItemId());
this.itemData = GameData.getItemDataMap().get(getItemId());
}
}
......@@ -371,6 +375,32 @@ public class GenshinItem {
return relicInfo;
}
public Weapon toWeaponProto() {
Weapon.Builder weapon = Weapon.newBuilder()
.setLevel(this.getLevel())
.setExp(this.getExp())
.setPromoteLevel(this.getPromoteLevel());
if (this.getAffixes() != null && this.getAffixes().size() > 0) {
for (int affix : this.getAffixes()) {
weapon.putAffixMap(affix, this.getRefinement());
}
}
return weapon.build();
}
public Reliquary toReliquaryProto() {
Reliquary.Builder relic = Reliquary.newBuilder()
.setLevel(this.getLevel())
.setExp(this.getExp())
.setPromoteLevel(this.getPromoteLevel())
.setMainPropId(this.getMainPropId())
.addAllAppendPropIdList(this.getAppendPropIdList());
return relic.build();
}
public Item toProto() {
Item.Builder proto = Item.newBuilder()
.setGuid(this.getGuid())
......@@ -378,35 +408,13 @@ public class GenshinItem {
switch (getItemType()) {
case ITEM_WEAPON:
Weapon.Builder weapon = Weapon.newBuilder()
.setLevel(this.getLevel())
.setExp(this.getExp())
.setPromoteLevel(this.getPromoteLevel());
if (this.getAffixes() != null && this.getAffixes().size() > 0) {
for (int affix : this.getAffixes()) {
weapon.putAffixMap(affix, this.getRefinement());
}
}
Weapon weapon = this.toWeaponProto();
proto.setEquip(Equip.newBuilder().setWeapon(weapon).setIsLocked(this.isLocked()).build());
break;
case ITEM_RELIQUARY:
Reliquary relic = Reliquary.newBuilder()
.setLevel(this.getLevel())
.setExp(this.getExp())
.setPromoteLevel(this.getPromoteLevel())
.setMainPropId(this.getMainPropId())
.addAllAppendPropIdList(this.getAppendPropIdList())
.build();
Reliquary relic = this.toReliquaryProto();
proto.setEquip(Equip.newBuilder().setReliquary(relic).setIsLocked(this.isLocked()).build());
break;
case ITEM_MATERIAL:
Material material = Material.newBuilder()
.setCount(getCount())
.build();
proto.setMaterial(material);
break;
case ITEM_FURNITURE:
Furniture furniture = Furniture.newBuilder()
.setCount(getCount())
......@@ -414,6 +422,10 @@ public class GenshinItem {
proto.setFurniture(furniture);
break;
default:
Material material = Material.newBuilder()
.setCount(getCount())
.build();
proto.setMaterial(material);
break;
}
......
......@@ -5,20 +5,22 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import emu.grasscutter.GenshinConstants;
import emu.grasscutter.GameConstants;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.AvatarCostumeData;
import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.data.def.AvatarFlycloakData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.avatar.AvatarStorage;
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam;
import emu.grasscutter.server.packet.send.PacketAvatarEquipChangeNotify;
import emu.grasscutter.server.packet.send.PacketItemAddHintNotify;
import emu.grasscutter.server.packet.send.PacketStoreItemChangeNotify;
import emu.grasscutter.server.packet.send.PacketStoreItemDelNotify;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
......@@ -26,13 +28,13 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
public class Inventory implements Iterable<GenshinItem> {
private final GenshinPlayer player;
public class Inventory implements Iterable<GameItem> {
private final Player player;
private final Long2ObjectMap<GenshinItem> store;
private final Long2ObjectMap<GameItem> store;
private final Int2ObjectMap<InventoryTab> inventoryTypes;
public Inventory(GenshinPlayer player) {
public Inventory(Player player) {
this.player = player;
this.store = new Long2ObjectOpenHashMap<>();
this.inventoryTypes = new Int2ObjectOpenHashMap<>();
......@@ -43,7 +45,7 @@ public class Inventory implements Iterable<GenshinItem> {
this.createInventoryTab(ItemType.ITEM_FURNITURE, new MaterialInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitFurniture));
}
public GenshinPlayer getPlayer() {
public Player getPlayer() {
return player;
}
......@@ -51,7 +53,7 @@ public class Inventory implements Iterable<GenshinItem> {
return this.getPlayer().getAvatars();
}
public Long2ObjectMap<GenshinItem> getItems() {
public Long2ObjectMap<GameItem> getItems() {
return store;
}
......@@ -67,7 +69,7 @@ public class Inventory implements Iterable<GenshinItem> {
this.getInventoryTypes().put(type.getValue(), tab);
}
public GenshinItem getItemByGuid(long id) {
public GameItem getItemByGuid(long id) {
return this.getItems().get(id);
}
......@@ -76,19 +78,19 @@ public class Inventory implements Iterable<GenshinItem> {
}
public boolean addItem(int itemId, int count) {
ItemData itemData = GenshinData.getItemDataMap().get(itemId);
ItemData itemData = GameData.getItemDataMap().get(itemId);
if (itemData == null) {
return false;
}
GenshinItem item = new GenshinItem(itemData, count);
GameItem item = new GameItem(itemData, count);
return addItem(item);
}
public boolean addItem(GenshinItem item) {
GenshinItem result = putItem(item);
public boolean addItem(GameItem item) {
GameItem result = putItem(item);
if (result != null) {
getPlayer().sendPacket(new PacketStoreItemChangeNotify(result));
......@@ -98,34 +100,56 @@ public class Inventory implements Iterable<GenshinItem> {
return false;
}
public void addItems(Collection<GenshinItem> items) {
List<GenshinItem> changedItems = new LinkedList<>();
public boolean addItem(GameItem item, ActionReason reason) {
boolean result = addItem(item);
for (GenshinItem item : items) {
GenshinItem result = putItem(item);
if (result != null) {
changedItems.add(result);
}
if (result && reason != null) {
getPlayer().sendPacket(new PacketItemAddHintNotify(item, reason));
}
getPlayer().sendPacket(new PacketStoreItemChangeNotify(changedItems));
return result;
}
public boolean addItem(GameItem item, ActionReason reason, boolean forceNotify) {
boolean result = addItem(item);
if (reason != null && (forceNotify || result)) {
getPlayer().sendPacket(new PacketItemAddHintNotify(item, reason));
}
return result;
}
public void addItemParams(Collection<ItemParam> items) {
List<GenshinItem> changedItems = new LinkedList<>();
public void addItems(Collection<GameItem> items) {
this.addItems(items, null);
}
public void addItems(Collection<GameItem> items, ActionReason reason) {
List<GameItem> changedItems = new LinkedList<>();
for (ItemParam itemParam : items) {
GenshinItem toAdd = new GenshinItem(itemParam.getItemId(), itemParam.getCount());
GenshinItem result = putItem(toAdd);
for (GameItem item : items) {
GameItem result = putItem(item);
if (result != null) {
changedItems.add(result);
}
}
if (changedItems.size() == 0) {
return;
}
if (reason != null) {
getPlayer().sendPacket(new PacketItemAddHintNotify(changedItems, reason));
}
getPlayer().sendPacket(new PacketStoreItemChangeNotify(changedItems));
}
private synchronized GenshinItem putItem(GenshinItem item) {
public void addItemParams(Collection<ItemParam> items) {
addItems(items.stream().map(param -> new GameItem(param.getItemId(), param.getCount())).toList(), null);
}
private synchronized GameItem putItem(GameItem item) {
// Dont add items that dont have a valid item definition.
if (item.getItemData() == null) {
return null;
......@@ -140,32 +164,35 @@ public class Inventory implements Iterable<GenshinItem> {
if (tab.getSize() >= tab.getMaxCapacity()) {
return null;
}
// Duplicates cause problems
item.setCount(Math.max(item.getCount(), 1));
// Adds to inventory
putItem(item, tab);
} else if (type == ItemType.ITEM_VIRTUAL) {
// Handle
this.addVirtualItem(item.getItemId(), item.getCount());
return null;
return item;
} else if (item.getItemData().getMaterialType() == MaterialType.MATERIAL_AVATAR) {
// Get avatar id
int avatarId = (item.getItemId() % 1000) + 10000000;
// Dont let people give themselves extra main characters
if (avatarId == GenshinConstants.MAIN_CHARACTER_MALE || avatarId == GenshinConstants.MAIN_CHARACTER_FEMALE) {
if (avatarId == GameConstants.MAIN_CHARACTER_MALE || avatarId == GameConstants.MAIN_CHARACTER_FEMALE) {
return null;
}
// Add avatar
AvatarData avatarData = GenshinData.getAvatarDataMap().get(avatarId);
AvatarData avatarData = GameData.getAvatarDataMap().get(avatarId);
if (avatarData != null && !player.getAvatars().hasAvatar(avatarId)) {
this.getPlayer().addAvatar(new GenshinAvatar(avatarData));
this.getPlayer().addAvatar(new Avatar(avatarData));
}
return null;
} else if (item.getItemData().getMaterialType() == MaterialType.MATERIAL_FLYCLOAK) {
AvatarFlycloakData flycloakData = GenshinData.getAvatarFlycloakDataMap().get(item.getItemId());
AvatarFlycloakData flycloakData = GameData.getAvatarFlycloakDataMap().get(item.getItemId());
if (flycloakData != null && !player.getFlyCloakList().contains(item.getItemId())) {
getPlayer().addFlycloak(item.getItemId());
}
return null;
} else if (item.getItemData().getMaterialType() == MaterialType.MATERIAL_COSTUME) {
AvatarCostumeData costumeData = GenshinData.getAvatarCostumeDataItemIdMap().get(item.getItemId());
AvatarCostumeData costumeData = GameData.getAvatarCostumeDataItemIdMap().get(item.getItemId());
if (costumeData != null && !player.getCostumeList().contains(costumeData.getId())) {
getPlayer().addCostume(costumeData.getId());
}
......@@ -176,7 +203,7 @@ public class Inventory implements Iterable<GenshinItem> {
}
return null;
} else if (tab != null) {
GenshinItem existingItem = tab.getItemById(item.getItemId());
GameItem existingItem = tab.getItemById(item.getItemId());
if (existingItem == null) {
// Item type didnt exist before, we will add it to main inventory map if there is enough space
if (tab.getSize() >= tab.getMaxCapacity()) {
......@@ -194,12 +221,13 @@ public class Inventory implements Iterable<GenshinItem> {
}
// Set ownership and save to db
item.save();
if (item.getItemData().getItemType() != ItemType.ITEM_VIRTUAL)
item.save();
return item;
}
private synchronized void putItem(GenshinItem item, InventoryTab tab) {
private synchronized void putItem(GameItem item, InventoryTab tab) {
// Set owner and guid FIRST!
item.setOwner(getPlayer());
// Put in item store
......@@ -212,25 +240,29 @@ public class Inventory implements Iterable<GenshinItem> {
private void addVirtualItem(int itemId, int count) {
switch (itemId) {
case 101: // Character exp
for (EntityAvatar entity : getPlayer().getTeamManager().getActiveTeam()) {
getPlayer().getServer().getInventoryManager().upgradeAvatar(player, entity.getAvatar(), count);
}
getPlayer().getServer().getInventoryManager().upgradeAvatar(player, getPlayer().getTeamManager().getCurrentAvatarEntity().getAvatar(), count);
break;
case 102: // Adventure exp
getPlayer().addExpDirectly(count);
break;
case 105: // Companionship exp
getPlayer().getServer().getInventoryManager().upgradeAvatarFetterLevel(player, getPlayer().getTeamManager().getCurrentAvatarEntity().getAvatar(), count);
break;
case 201: // Primogem
getPlayer().setPrimogems(player.getPrimogems() + count);
break;
case 202: // Mora
getPlayer().setMora(player.getMora() + count);
break;
case 203: // Genesis Crystals
getPlayer().setCrystals(player.getCrystals() + count);
break;
}
}
public void removeItems(List<GenshinItem> items) {
public void removeItems(List<GameItem> items) {
// TODO Bulk delete
for (GenshinItem item : items) {
for (GameItem item : items) {
this.removeItem(item, item.getCount());
}
}
......@@ -240,7 +272,7 @@ public class Inventory implements Iterable<GenshinItem> {
}
public synchronized boolean removeItem(long guid, int count) {
GenshinItem item = this.getItemByGuid(guid);
GameItem item = this.getItemByGuid(guid);
if (item == null) {
return false;
......@@ -249,17 +281,21 @@ public class Inventory implements Iterable<GenshinItem> {
return removeItem(item, count);
}
public synchronized boolean removeItem(GenshinItem item) {
public synchronized boolean removeItem(GameItem item) {
return removeItem(item, item.getCount());
}
public synchronized boolean removeItem(GenshinItem item, int count) {
public synchronized boolean removeItem(GameItem item, int count) {
// Sanity check
if (count <= 0 || item == null) {
return false;
}
item.setCount(item.getCount() - count);
if (item.getItemData().isEquip()) {
item.setCount(0);
} else {
item.setCount(item.getCount() - count);
}
if (item.getCount() <= 0) {
// Remove from inventory tab too
......@@ -282,7 +318,7 @@ public class Inventory implements Iterable<GenshinItem> {
return true;
}
private void deleteItem(GenshinItem item, InventoryTab tab) {
private void deleteItem(GameItem item, InventoryTab tab) {
getItems().remove(item.getGuid());
if (tab != null) {
tab.onRemoveItem(item);
......@@ -290,8 +326,8 @@ public class Inventory implements Iterable<GenshinItem> {
}
public boolean equipItem(long avatarGuid, long equipGuid) {
GenshinAvatar avatar = getPlayer().getAvatars().getAvatarByGuid(avatarGuid);
GenshinItem item = this.getItemByGuid(equipGuid);
Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(avatarGuid);
GameItem item = this.getItemByGuid(equipGuid);
if (avatar != null && item != null) {
return avatar.equipItem(item, true);
......@@ -301,7 +337,7 @@ public class Inventory implements Iterable<GenshinItem> {
}
public boolean unequipItem(long avatarGuid, int slot) {
GenshinAvatar avatar = getPlayer().getAvatars().getAvatarByGuid(avatarGuid);
Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(avatarGuid);
EquipType equipType = EquipType.getTypeByValue(slot);
if (avatar != null && equipType != EquipType.EQUIP_WEAPON) {
......@@ -316,15 +352,15 @@ public class Inventory implements Iterable<GenshinItem> {
}
public void loadFromDatabase() {
List<GenshinItem> items = DatabaseHelper.getInventoryItems(getPlayer());
List<GameItem> items = DatabaseHelper.getInventoryItems(getPlayer());
for (GenshinItem item : items) {
for (GameItem item : items) {
// Should never happen
if (item.getObjectId() == null) {
continue;
}
ItemData itemData = GenshinData.getItemDataMap().get(item.getItemId());
ItemData itemData = GameData.getItemDataMap().get(item.getItemId());
if (itemData == null) {
continue;
}
......@@ -340,7 +376,7 @@ public class Inventory implements Iterable<GenshinItem> {
// Equip to a character if possible
if (item.isEquipped()) {
GenshinAvatar avatar = getPlayer().getAvatars().getAvatarById(item.getEquipCharacter());
Avatar avatar = getPlayer().getAvatars().getAvatarById(item.getEquipCharacter());
boolean hasEquipped = false;
if (avatar != null) {
......@@ -356,7 +392,7 @@ public class Inventory implements Iterable<GenshinItem> {
}
@Override
public Iterator<GenshinItem> iterator() {
public Iterator<GameItem> iterator() {
return this.getItems().values().iterator();
}
}
package emu.grasscutter.game.inventory;
public interface InventoryTab {
public GenshinItem getItemById(int id);
public GameItem getItemById(int id);
public void onAddItem(GenshinItem item);
public void onAddItem(GameItem item);
public void onRemoveItem(GenshinItem item);
public void onRemoveItem(GameItem item);
public int getSize();
......
......@@ -4,7 +4,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class MaterialInventoryTab implements InventoryTab {
private final Int2ObjectMap<GenshinItem> items;
private final Int2ObjectMap<GameItem> items;
private final int maxCapacity;
public MaterialInventoryTab(int maxCapacity) {
......@@ -13,17 +13,17 @@ public class MaterialInventoryTab implements InventoryTab {
}
@Override
public GenshinItem getItemById(int id) {
public GameItem getItemById(int id) {
return this.items.get(id);
}
@Override
public void onAddItem(GenshinItem item) {
public void onAddItem(GameItem item) {
this.items.put(item.getItemId(), item);
}
@Override
public void onRemoveItem(GenshinItem item) {
public void onRemoveItem(GameItem item) {
this.items.remove(item.getItemId());
}
......
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