mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-29 10:43:14 +00:00
Implement food buffs
This commit is contained in:
parent
e9a95b89cf
commit
0d17c4a088
@ -76,6 +76,7 @@ public class GameData {
|
|||||||
private static final ArrayList<CodexReliquaryData> codexReliquaryArrayList = new ArrayList<>();
|
private static final ArrayList<CodexReliquaryData> codexReliquaryArrayList = new ArrayList<>();
|
||||||
private static final Int2ObjectMap<FetterCharacterCardData> fetterCharacterCardDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<FetterCharacterCardData> fetterCharacterCardDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
private static final Int2ObjectMap<RewardData> rewardDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<RewardData> rewardDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
private static final Int2ObjectMap<WorldAreaData> worldAreaDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<WorldAreaData> worldAreaDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
private static final Int2ObjectMap<WorldLevelData> worldLevelDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<WorldLevelData> worldLevelDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
private static final Int2ObjectMap<DailyDungeonData> dailyDungeonDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<DailyDungeonData> dailyDungeonDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
@ -90,6 +91,7 @@ public class GameData {
|
|||||||
private static final Int2ObjectMap<TowerFloorData> towerFloorDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<TowerFloorData> towerFloorDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
private static final Int2ObjectMap<TowerLevelData> towerLevelDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<TowerLevelData> towerLevelDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
private static final Int2ObjectMap<TowerScheduleData> towerScheduleDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<TowerScheduleData> towerScheduleDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
|
private static final Int2ObjectMap<BuffData> buffDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
private static final Int2ObjectMap<ForgeData> forgeDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<ForgeData> forgeDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
private static final Int2ObjectMap<HomeWorldLevelData> homeWorldLevelDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<HomeWorldLevelData> homeWorldLevelDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
private static final Int2ObjectMap<FurnitureMakeConfigData> furnitureMakeConfigDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<FurnitureMakeConfigData> furnitureMakeConfigDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
@ -448,4 +450,8 @@ public class GameData {
|
|||||||
public static Int2ObjectMap<CookBonusData> getCookBonusDataMap() {
|
public static Int2ObjectMap<CookBonusData> getCookBonusDataMap() {
|
||||||
return cookBonusDataMap;
|
return cookBonusDataMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Int2ObjectMap<BuffData> getBuffDataMap() {
|
||||||
|
return buffDataMap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,9 @@ public class ItemUseData {
|
|||||||
private String[] useParam;
|
private String[] useParam;
|
||||||
|
|
||||||
public ItemUseOp getUseOp() {
|
public ItemUseOp getUseOp() {
|
||||||
|
if (useOp == null) {
|
||||||
|
useOp = ItemUseOp.ITEM_USE_NONE;
|
||||||
|
}
|
||||||
return useOp;
|
return useOp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
src/main/java/emu/grasscutter/data/excels/BuffData.java
Normal file
25
src/main/java/emu/grasscutter/data/excels/BuffData.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package emu.grasscutter.data.excels;
|
||||||
|
|
||||||
|
import emu.grasscutter.data.GameResource;
|
||||||
|
import emu.grasscutter.data.ResourceType;
|
||||||
|
import emu.grasscutter.game.props.ServerBuffType;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@ResourceType(name = "BuffExcelConfigData.json")
|
||||||
|
@Getter
|
||||||
|
public class BuffData extends GameResource {
|
||||||
|
private int groupId;
|
||||||
|
private int serverBuffId;
|
||||||
|
private float time;
|
||||||
|
private boolean isPersistent;
|
||||||
|
private ServerBuffType serverBuffType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return this.serverBuffId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onLoad() {
|
||||||
|
this.serverBuffType = this.serverBuffType != null ? this.serverBuffType : ServerBuffType.SERVER_BUFF_NONE;
|
||||||
|
}
|
||||||
|
}
|
@ -150,6 +150,7 @@ public class Player {
|
|||||||
@Getter private transient BattlePassManager battlePassManager;
|
@Getter private transient BattlePassManager battlePassManager;
|
||||||
@Getter private transient CookingManager cookingManager;
|
@Getter private transient CookingManager cookingManager;
|
||||||
@Getter private transient ActivityManager activityManager;
|
@Getter private transient ActivityManager activityManager;
|
||||||
|
@Getter private transient PlayerBuffManager buffManager;
|
||||||
|
|
||||||
// Manager data (Save-able to the database)
|
// Manager data (Save-able to the database)
|
||||||
private PlayerProfile playerProfile;
|
private PlayerProfile playerProfile;
|
||||||
@ -195,6 +196,7 @@ public class Player {
|
|||||||
this.abilityManager = new AbilityManager(this);
|
this.abilityManager = new AbilityManager(this);
|
||||||
this.deforestationManager = new DeforestationManager(this);
|
this.deforestationManager = new DeforestationManager(this);
|
||||||
this.questManager = new QuestManager(this);
|
this.questManager = new QuestManager(this);
|
||||||
|
this.buffManager = new PlayerBuffManager(this);
|
||||||
this.position = new Position(GameConstants.START_POSITION);
|
this.position = new Position(GameConstants.START_POSITION);
|
||||||
this.rotation = new Position(0, 307, 0);
|
this.rotation = new Position(0, 307, 0);
|
||||||
this.sceneId = 3;
|
this.sceneId = 3;
|
||||||
@ -1182,6 +1184,8 @@ public class Player {
|
|||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Handle buff
|
||||||
|
this.getBuffManager().onTick();
|
||||||
// Ping
|
// Ping
|
||||||
if (this.getWorld() != null) {
|
if (this.getWorld() != null) {
|
||||||
// RTT notify - very important to send this often
|
// RTT notify - very important to send this often
|
||||||
|
176
src/main/java/emu/grasscutter/game/player/PlayerBuffManager.java
Normal file
176
src/main/java/emu/grasscutter/game/player/PlayerBuffManager.java
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
package emu.grasscutter.game.player;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import emu.grasscutter.data.GameData;
|
||||||
|
import emu.grasscutter.data.excels.BuffData;
|
||||||
|
import emu.grasscutter.net.proto.ServerBuffChangeNotifyOuterClass.ServerBuffChangeNotify.ServerBuffChangeType;
|
||||||
|
import emu.grasscutter.net.proto.ServerBuffOuterClass.ServerBuff;
|
||||||
|
import emu.grasscutter.server.packet.send.PacketServerBuffChangeNotify;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter(AccessLevel.PRIVATE)
|
||||||
|
public class PlayerBuffManager extends BasePlayerManager {
|
||||||
|
private int nextBuffUid;
|
||||||
|
|
||||||
|
private final List<PlayerBuff> pendingBuffs;
|
||||||
|
private final Int2ObjectMap<PlayerBuff> buffs; // Server buffs
|
||||||
|
|
||||||
|
public PlayerBuffManager(Player player) {
|
||||||
|
super(player);
|
||||||
|
this.buffs = new Int2ObjectOpenHashMap<>();
|
||||||
|
this.pendingBuffs = new LinkedList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a new uid for a server buff
|
||||||
|
* @return New integer buff uid
|
||||||
|
*/
|
||||||
|
private int getNextBuffUid() {
|
||||||
|
return ++nextBuffUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the player has a buff with this group id
|
||||||
|
* @param groupId Buff group id
|
||||||
|
* @return True if a buff with this group id exists
|
||||||
|
*/
|
||||||
|
public synchronized boolean hasBuff(int groupId) {
|
||||||
|
return this.getBuffs().containsKey(groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all player buffs
|
||||||
|
*/
|
||||||
|
public synchronized void clearBuffs() {
|
||||||
|
// Remove from player
|
||||||
|
getPlayer().sendPacket(
|
||||||
|
new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, getBuffs().values())
|
||||||
|
);
|
||||||
|
|
||||||
|
// Clear
|
||||||
|
getBuffs().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a server buff to the player.
|
||||||
|
* @param buffId Server buff id
|
||||||
|
* @return True if a buff was added
|
||||||
|
*/
|
||||||
|
public boolean addBuff(int buffId) {
|
||||||
|
return addBuff(buffId, -1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a server buff to the player.
|
||||||
|
* @param buffId Server buff id
|
||||||
|
* @param duration Duration of the buff in seconds. Set to 0 for an infinite buff.
|
||||||
|
* @return True if a buff was added
|
||||||
|
*/
|
||||||
|
public synchronized boolean addBuff(int buffId, float duration) {
|
||||||
|
// Get buff excel data
|
||||||
|
BuffData buffData = GameData.getBuffDataMap().get(buffId);
|
||||||
|
if (buffData == null) return false;
|
||||||
|
|
||||||
|
// Set duration
|
||||||
|
if (duration < 0f) {
|
||||||
|
duration = buffData.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dont add buff if duration is equal or less than 0
|
||||||
|
if (duration <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear previous buff if it exists
|
||||||
|
if (this.hasBuff(buffData.getGroupId())) {
|
||||||
|
this.removeBuff(buffData.getGroupId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and store buff
|
||||||
|
PlayerBuff buff = new PlayerBuff(getNextBuffUid(), buffData, duration);
|
||||||
|
getBuffs().put(buff.getGroupId(), buff);
|
||||||
|
|
||||||
|
// Packet
|
||||||
|
getPlayer().sendPacket(new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_ADD_SERVER_BUFF, buff));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a buff by its group id
|
||||||
|
* @param buffGroupId Server buff group id
|
||||||
|
* @return True if a buff was remove
|
||||||
|
*/
|
||||||
|
public synchronized boolean removeBuff(int buffGroupId) {
|
||||||
|
PlayerBuff buff = this.getBuffs().get(buffGroupId);
|
||||||
|
|
||||||
|
if (buff != null) {
|
||||||
|
getPlayer().sendPacket(
|
||||||
|
new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, buff)
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void onTick() {
|
||||||
|
// Skip if no buffs
|
||||||
|
if (getBuffs().size() == 0) return;
|
||||||
|
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// Add to pending buffs to remove if buff has expired
|
||||||
|
for (PlayerBuff buff : getBuffs().values()) {
|
||||||
|
if (currentTime > buff.getEndTime()) {
|
||||||
|
this.getPendingBuffs().add(buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.getPendingBuffs().size() > 0) {
|
||||||
|
// Send packet
|
||||||
|
getPlayer().sendPacket(
|
||||||
|
new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, this.pendingBuffs)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Remove buff from player buff map
|
||||||
|
for (PlayerBuff buff : this.getPendingBuffs()) {
|
||||||
|
getBuffs().remove(buff.getGroupId());
|
||||||
|
}
|
||||||
|
this.getPendingBuffs().clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public static class PlayerBuff {
|
||||||
|
private final int uid;
|
||||||
|
private final BuffData buffData;
|
||||||
|
private final long endTime;
|
||||||
|
|
||||||
|
public PlayerBuff(int uid, BuffData buffData, float duration) {
|
||||||
|
this.uid = uid;
|
||||||
|
this.buffData = buffData;
|
||||||
|
this.endTime = System.currentTimeMillis() + ((long) duration * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGroupId() {
|
||||||
|
return getBuffData().getGroupId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerBuff toProto() {
|
||||||
|
return ServerBuff.newBuilder()
|
||||||
|
.setServerBuffUid(this.getUid())
|
||||||
|
.setServerBuffId(this.getBuffData().getId())
|
||||||
|
.setServerBuffType(this.getBuffData().getServerBuffType().getValue())
|
||||||
|
.setInstancedModifierId(1)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
src/main/java/emu/grasscutter/game/props/ServerBuffType.java
Normal file
34
src/main/java/emu/grasscutter/game/props/ServerBuffType.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package emu.grasscutter.game.props;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
|
||||||
|
public enum ServerBuffType {
|
||||||
|
SERVER_BUFF_NONE (0),
|
||||||
|
SERVER_BUFF_AVATAR (1),
|
||||||
|
SERVER_BUFF_TEAM (2),
|
||||||
|
SERVER_BUFF_TOWER (3);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
private static final Int2ObjectMap<ServerBuffType> map = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
Stream.of(values()).forEach(e -> {
|
||||||
|
map.put(e.getValue(), e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServerBuffType(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerBuffType getTypeByValue(int value) {
|
||||||
|
return map.getOrDefault(value, SERVER_BUFF_NONE);
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ import emu.grasscutter.data.GameData;
|
|||||||
import emu.grasscutter.data.binout.OpenConfigEntry;
|
import emu.grasscutter.data.binout.OpenConfigEntry;
|
||||||
import emu.grasscutter.data.binout.OpenConfigEntry.SkillPointModifier;
|
import emu.grasscutter.data.binout.OpenConfigEntry.SkillPointModifier;
|
||||||
import emu.grasscutter.data.common.ItemParamData;
|
import emu.grasscutter.data.common.ItemParamData;
|
||||||
|
import emu.grasscutter.data.common.ItemUseData;
|
||||||
import emu.grasscutter.data.excels.AvatarPromoteData;
|
import emu.grasscutter.data.excels.AvatarPromoteData;
|
||||||
import emu.grasscutter.data.excels.AvatarSkillData;
|
import emu.grasscutter.data.excels.AvatarSkillData;
|
||||||
import emu.grasscutter.data.excels.AvatarSkillDepotData;
|
import emu.grasscutter.data.excels.AvatarSkillDepotData;
|
||||||
@ -821,6 +822,8 @@ public class InventorySystem extends BaseGameSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
used = player.getTeamManager().reviveAvatar(target) ? 1 : 0;
|
used = player.getTeamManager().reviveAvatar(target) ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
used = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MATERIAL_NOTICE_ADD_HP:
|
case MATERIAL_NOTICE_ADD_HP:
|
||||||
@ -940,9 +943,24 @@ public class InventorySystem extends BaseGameSystem {
|
|||||||
// If we used at least one item, or one of the methods called here reports using the item successfully,
|
// If we used at least one item, or one of the methods called here reports using the item successfully,
|
||||||
// we return the item to make UseItemRsp a success.
|
// we return the item to make UseItemRsp a success.
|
||||||
if (used > 0) {
|
if (used > 0) {
|
||||||
|
// Handle use params, mainly server buffs
|
||||||
|
for (ItemUseData useData : useItem.getItemData().getItemUse()) {
|
||||||
|
switch (useData.getUseOp()) {
|
||||||
|
case ITEM_USE_ADD_SERVER_BUFF -> {
|
||||||
|
int buffId = Integer.parseInt(useData.getUseParam()[0]);
|
||||||
|
float time = Float.parseFloat(useData.getUseParam()[1]);
|
||||||
|
|
||||||
|
player.getBuffManager().addBuff(buffId, time);
|
||||||
|
}
|
||||||
|
default -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove item from inventory since we used it
|
||||||
player.getInventory().removeItem(useItem, used);
|
player.getInventory().removeItem(useItem, used);
|
||||||
return useItem;
|
return useItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useSuccess) {
|
if (useSuccess) {
|
||||||
return useItem;
|
return useItem;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package emu.grasscutter.server.packet.send;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import emu.grasscutter.game.entity.EntityAvatar;
|
||||||
|
import emu.grasscutter.game.player.Player;
|
||||||
|
import emu.grasscutter.game.player.PlayerBuffManager.PlayerBuff;
|
||||||
|
import emu.grasscutter.net.packet.BasePacket;
|
||||||
|
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||||
|
import emu.grasscutter.net.proto.ServerBuffChangeNotifyOuterClass.ServerBuffChangeNotify;
|
||||||
|
import emu.grasscutter.net.proto.ServerBuffChangeNotifyOuterClass.ServerBuffChangeNotify.ServerBuffChangeType;
|
||||||
|
|
||||||
|
public class PacketServerBuffChangeNotify extends BasePacket {
|
||||||
|
|
||||||
|
public PacketServerBuffChangeNotify(Player player, ServerBuffChangeType changeType, PlayerBuff buff) {
|
||||||
|
super(PacketOpcodes.ServerBuffChangeNotify);
|
||||||
|
|
||||||
|
var proto = ServerBuffChangeNotify.newBuilder();
|
||||||
|
|
||||||
|
for (EntityAvatar entity : player.getTeamManager().getActiveTeam()) {
|
||||||
|
proto.addAvatarGuidList(entity.getAvatar().getGuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
proto.setServerBuffChangeType(changeType);
|
||||||
|
proto.addServerBuffList(buff.toProto());
|
||||||
|
|
||||||
|
this.setData(proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketServerBuffChangeNotify(Player player, ServerBuffChangeType changeType, Collection<PlayerBuff> buffs) {
|
||||||
|
super(PacketOpcodes.ServerBuffChangeNotify);
|
||||||
|
|
||||||
|
var proto = ServerBuffChangeNotify.newBuilder();
|
||||||
|
|
||||||
|
for (EntityAvatar entity : player.getTeamManager().getActiveTeam()) {
|
||||||
|
proto.addAvatarGuidList(entity.getAvatar().getGuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
proto.setServerBuffChangeType(changeType);
|
||||||
|
proto.addAllServerBuffList(buffs.stream().map(PlayerBuff::toProto).toList());
|
||||||
|
|
||||||
|
this.setData(proto);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user