PlayerBuffManager.java 5.38 KB
Newer Older
Melledy's avatar
Melledy committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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;
github-actions's avatar
github-actions committed
21

Melledy's avatar
Melledy committed
22
23
    private final List<PlayerBuff> pendingBuffs;
    private final Int2ObjectMap<PlayerBuff> buffs; // Server buffs
github-actions's avatar
github-actions committed
24

Melledy's avatar
Melledy committed
25
26
27
28
29
    public PlayerBuffManager(Player player) {
        super(player);
        this.buffs = new Int2ObjectOpenHashMap<>();
        this.pendingBuffs = new LinkedList<>();
    }
github-actions's avatar
github-actions committed
30

Melledy's avatar
Melledy committed
31
32
33
34
35
36
37
    /**
     * Gets a new uid for a server buff
     * @return New integer buff uid
     */
    private int getNextBuffUid() {
        return ++nextBuffUid;
    }
github-actions's avatar
github-actions committed
38

Melledy's avatar
Melledy committed
39
40
41
42
43
44
45
46
    /**
     * 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);
    }
github-actions's avatar
github-actions committed
47

Melledy's avatar
Melledy committed
48
49
50
51
52
53
54
55
    /**
     * 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())
        );
github-actions's avatar
github-actions committed
56

Melledy's avatar
Melledy committed
57
58
59
        // Clear
        getBuffs().clear();
    }
github-actions's avatar
github-actions committed
60

Melledy's avatar
Melledy committed
61
62
63
64
65
66
67
68
    /**
     * 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);
    }
github-actions's avatar
github-actions committed
69

Melledy's avatar
Melledy committed
70
71
72
73
74
75
76
77
78
79
    /**
     * 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;
github-actions's avatar
github-actions committed
80

Melledy's avatar
Melledy committed
81
82
83
84
        // Set duration
        if (duration < 0f) {
            duration = buffData.getTime();
        }
github-actions's avatar
github-actions committed
85

Melledy's avatar
Melledy committed
86
87
88
89
        // Dont add buff if duration is equal or less than 0
        if (duration <= 0) {
            return false;
        }
github-actions's avatar
github-actions committed
90

Melledy's avatar
Melledy committed
91
92
93
94
        // Clear previous buff if it exists
        if (this.hasBuff(buffData.getGroupId())) {
            this.removeBuff(buffData.getGroupId());
        }
github-actions's avatar
github-actions committed
95

Melledy's avatar
Melledy committed
96
97
98
        // Create and store buff
        PlayerBuff buff = new PlayerBuff(getNextBuffUid(), buffData, duration);
        getBuffs().put(buff.getGroupId(), buff);
github-actions's avatar
github-actions committed
99

Melledy's avatar
Melledy committed
100
101
        // Packet
        getPlayer().sendPacket(new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_ADD_SERVER_BUFF, buff));
github-actions's avatar
github-actions committed
102

Melledy's avatar
Melledy committed
103
104
        return true;
    }
github-actions's avatar
github-actions committed
105

Melledy's avatar
Melledy committed
106
107
108
109
110
111
112
    /**
     * 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);
github-actions's avatar
github-actions committed
113

Melledy's avatar
Melledy committed
114
115
116
117
118
119
        if (buff != null) {
            getPlayer().sendPacket(
                new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, buff)
            );
            return true;
        }
github-actions's avatar
github-actions committed
120

Melledy's avatar
Melledy committed
121
122
        return false;
    }
github-actions's avatar
github-actions committed
123

Melledy's avatar
Melledy committed
124
125
126
    public synchronized void onTick() {
        // Skip if no buffs
        if (getBuffs().size() == 0) return;
github-actions's avatar
github-actions committed
127

Melledy's avatar
Melledy committed
128
        long currentTime = System.currentTimeMillis();
github-actions's avatar
github-actions committed
129

Melledy's avatar
Melledy committed
130
131
132
133
134
135
        // Add to pending buffs to remove if buff has expired
        for (PlayerBuff buff : getBuffs().values()) {
            if (currentTime > buff.getEndTime()) {
                this.getPendingBuffs().add(buff);
            }
        }
github-actions's avatar
github-actions committed
136

Melledy's avatar
Melledy committed
137
138
139
140
141
        if (this.getPendingBuffs().size() > 0) {
            // Send packet
            getPlayer().sendPacket(
                new PacketServerBuffChangeNotify(getPlayer(), ServerBuffChangeType.SERVER_BUFF_CHANGE_TYPE_DEL_SERVER_BUFF, this.pendingBuffs)
            );
github-actions's avatar
github-actions committed
142

Melledy's avatar
Melledy committed
143
144
145
146
147
148
149
            // Remove buff from player buff map
            for (PlayerBuff buff : this.getPendingBuffs()) {
                getBuffs().remove(buff.getGroupId());
            }
            this.getPendingBuffs().clear();
        }
    }
github-actions's avatar
github-actions committed
150

Melledy's avatar
Melledy committed
151
152
153
154
155
    @Getter
    public static class PlayerBuff {
        private final int uid;
        private final BuffData buffData;
        private final long endTime;
github-actions's avatar
github-actions committed
156

Melledy's avatar
Melledy committed
157
158
159
160
161
        public PlayerBuff(int uid, BuffData buffData, float duration) {
            this.uid = uid;
            this.buffData = buffData;
            this.endTime = System.currentTimeMillis() + ((long) duration * 1000);
        }
github-actions's avatar
github-actions committed
162

Melledy's avatar
Melledy committed
163
164
165
166
167
168
169
170
171
172
173
174
175
176
        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();
        }
    }
}