GameEntity.java 8.19 KB
Newer Older
Melledy's avatar
Melledy committed
1
2
package emu.grasscutter.game.entity;

Melledy's avatar
Melledy committed
3
4
5
import java.util.HashMap;
import java.util.Map;

Melledy's avatar
Melledy committed
6
import emu.grasscutter.game.player.Player;
Melledy's avatar
Melledy committed
7
8
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.LifeState;
Melledy's avatar
Melledy committed
9
import emu.grasscutter.game.world.Scene;
Melledy's avatar
Melledy committed
10
import emu.grasscutter.game.world.SpawnDataEntry;
Melledy's avatar
Melledy committed
11
import emu.grasscutter.game.world.World;
12
import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair;
Melledy's avatar
Melledy committed
13
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
Melledy's avatar
Melledy committed
14
15
16
17
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
18
import emu.grasscutter.server.event.entity.EntityDamageEvent;
19
import emu.grasscutter.server.event.entity.EntityDeathEvent;
Melledy's avatar
Melledy committed
20
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
Melledy's avatar
Melledy committed
21
import emu.grasscutter.utils.Position;
22
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
Melledy's avatar
Melledy committed
23
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
Melledy's avatar
Melledy committed
24
25
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
Melledy's avatar
Melledy committed
26

27
public abstract class GameEntity {
github-actions's avatar
github-actions committed
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    protected int id;
    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;

    // Abilities
    private Map<String, Float> metaOverrideMap;
    private Int2ObjectMap<String> metaModifiers;

    public GameEntity(Scene scene) {
        this.scene = scene;
        this.moveState = MotionState.MOTION_STATE_NONE;
    }

    public int getId() {
        return this.id;
    }

    public int getEntityType() {
        return this.getId() >> 24;
    }

    public World getWorld() {
        return this.getScene().getWorld();
    }

    public Scene getScene() {
        return this.scene;
    }

    public boolean isAlive() {
        return true;
    }

    public LifeState getLifeState() {
        return this.isAlive() ? LifeState.LIFE_ALIVE : LifeState.LIFE_DEAD;
    }

    public Map<String, Float> getMetaOverrideMap() {
        if (this.metaOverrideMap == null) {
            this.metaOverrideMap = new HashMap<>();
        }
        return this.metaOverrideMap;
    }

    public Int2ObjectMap<String> getMetaModifiers() {
        if (this.metaModifiers == null) {
            this.metaModifiers = new Int2ObjectOpenHashMap<>();
        }
        return this.metaModifiers;
    }
Melledy's avatar
Melledy committed
86

github-actions's avatar
github-actions committed
87
    public abstract Int2FloatOpenHashMap getFightProperties();
KingRainbow44's avatar
KingRainbow44 committed
88

github-actions's avatar
github-actions committed
89
    public abstract Position getPosition();
KingRainbow44's avatar
KingRainbow44 committed
90

github-actions's avatar
github-actions committed
91
    public abstract Position getRotation();
KingRainbow44's avatar
KingRainbow44 committed
92

github-actions's avatar
github-actions committed
93
94
95
    public MotionState getMotionState() {
        return moveState;
    }
Melledy's avatar
Melledy committed
96

github-actions's avatar
github-actions committed
97
98
99
    public void setMotionState(MotionState moveState) {
        this.moveState = moveState;
    }
KingRainbow44's avatar
KingRainbow44 committed
100

github-actions's avatar
github-actions committed
101
102
103
    public int getLastMoveSceneTimeMs() {
        return lastMoveSceneTimeMs;
    }
KingRainbow44's avatar
KingRainbow44 committed
104

github-actions's avatar
github-actions committed
105
106
107
    public void setLastMoveSceneTimeMs(int lastMoveSceneTimeMs) {
        this.lastMoveSceneTimeMs = lastMoveSceneTimeMs;
    }
KingRainbow44's avatar
KingRainbow44 committed
108

github-actions's avatar
github-actions committed
109
110
111
    public int getLastMoveReliableSeq() {
        return lastMoveReliableSeq;
    }
KingRainbow44's avatar
KingRainbow44 committed
112

github-actions's avatar
github-actions committed
113
114
115
    public void setLastMoveReliableSeq(int lastMoveReliableSeq) {
        this.lastMoveReliableSeq = lastMoveReliableSeq;
    }
KingRainbow44's avatar
KingRainbow44 committed
116

github-actions's avatar
github-actions committed
117
118
119
    public void setFightProperty(FightProperty prop, float value) {
        this.getFightProperties().put(prop.getId(), value);
    }
KingRainbow44's avatar
KingRainbow44 committed
120

github-actions's avatar
github-actions committed
121
122
123
    private void setFightProperty(int id, float value) {
        this.getFightProperties().put(id, value);
    }
124

github-actions's avatar
github-actions committed
125
    public void addFightProperty(FightProperty prop, float value) {
126
        this.getFightProperties().put(prop.getId(), this.getFightProperty(prop) + value);
github-actions's avatar
github-actions committed
127
    }
KingRainbow44's avatar
KingRainbow44 committed
128

github-actions's avatar
github-actions committed
129
    public float getFightProperty(FightProperty prop) {
130
        return this.getFightProperties().getOrDefault(prop.getId(), 0f);
github-actions's avatar
github-actions committed
131
    }
132

github-actions's avatar
github-actions committed
133
    public void addAllFightPropsToEntityInfo(SceneEntityInfo.Builder entityInfo) {
134
        for (Int2FloatMap.Entry entry : this.getFightProperties().int2FloatEntrySet()) {
github-actions's avatar
github-actions committed
135
136
137
138
139
140
141
            if (entry.getIntKey() == 0) {
                continue;
            }
            FightPropPair fightProp = FightPropPair.newBuilder().setPropType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build();
            entityInfo.addFightPropList(fightProp);
        }
    }
KingRainbow44's avatar
KingRainbow44 committed
142

github-actions's avatar
github-actions committed
143
144
145
    public int getBlockId() {
        return blockId;
    }
146

github-actions's avatar
github-actions committed
147
148
149
    public void setBlockId(int blockId) {
        this.blockId = blockId;
    }
KingRainbow44's avatar
KingRainbow44 committed
150

github-actions's avatar
github-actions committed
151
152
153
    public int getConfigId() {
        return configId;
    }
KingRainbow44's avatar
KingRainbow44 committed
154

github-actions's avatar
github-actions committed
155
156
157
    public void setConfigId(int configId) {
        this.configId = configId;
    }
Melledy's avatar
Melledy committed
158

github-actions's avatar
github-actions committed
159
160
161
    public int getGroupId() {
        return groupId;
    }
Melledy's avatar
Melledy committed
162

github-actions's avatar
github-actions committed
163
164
165
    public void setGroupId(int groupId) {
        this.groupId = groupId;
    }
KingRainbow44's avatar
KingRainbow44 committed
166

github-actions's avatar
github-actions committed
167
168
    protected MotionInfo getMotionInfo() {
        MotionInfo proto = MotionInfo.newBuilder()
169
170
                .setPos(this.getPosition().toProto())
                .setRot(this.getRotation().toProto())
github-actions's avatar
github-actions committed
171
172
173
                .setSpeed(Vector.newBuilder())
                .setState(this.getMotionState())
                .build();
Melledy's avatar
Melledy committed
174

github-actions's avatar
github-actions committed
175
176
        return proto;
    }
KingRainbow44's avatar
KingRainbow44 committed
177

github-actions's avatar
github-actions committed
178
179
180
    public SpawnDataEntry getSpawnEntry() {
        return spawnEntry;
    }
KingRainbow44's avatar
KingRainbow44 committed
181

github-actions's avatar
github-actions committed
182
183
184
    public void setSpawnEntry(SpawnDataEntry spawnEntry) {
        this.spawnEntry = spawnEntry;
    }
KingRainbow44's avatar
KingRainbow44 committed
185

github-actions's avatar
github-actions committed
186
187
188
189
    public float heal(float amount) {
        if (this.getFightProperties() == null) {
            return 0f;
        }
KingRainbow44's avatar
KingRainbow44 committed
190

191
192
        float curHp = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
        float maxHp = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
KingRainbow44's avatar
KingRainbow44 committed
193

github-actions's avatar
github-actions committed
194
195
196
        if (curHp >= maxHp) {
            return 0f;
        }
KingRainbow44's avatar
KingRainbow44 committed
197

github-actions's avatar
github-actions committed
198
199
        float healed = Math.min(maxHp - curHp, amount);
        this.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, healed);
KingRainbow44's avatar
KingRainbow44 committed
200

201
        this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP));
KingRainbow44's avatar
KingRainbow44 committed
202

github-actions's avatar
github-actions committed
203
204
        return healed;
    }
KingRainbow44's avatar
KingRainbow44 committed
205

github-actions's avatar
github-actions committed
206
    public void damage(float amount) {
207
        this.damage(amount, 0);
github-actions's avatar
github-actions committed
208
    }
KingRainbow44's avatar
KingRainbow44 committed
209

github-actions's avatar
github-actions committed
210
    public void damage(float amount, int killerId) {
211
212
        // Check if the entity has properties.
        if (this.getFightProperties() == null) {
github-actions's avatar
github-actions committed
213
214
215
            return;
        }

216
217
        // Invoke entity damage event.
        EntityDamageEvent event = new EntityDamageEvent(this, amount, this.getScene().getEntityById(killerId));
github-actions's avatar
github-actions committed
218
        event.call();
赵怡然's avatar
赵怡然 committed
219
        if (event.isCanceled()) {
220
221
            return; // If the event is canceled, do not damage the entity.
        }
github-actions's avatar
github-actions committed
222
223

        if (getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) != Float.POSITIVE_INFINITY) {
赵怡然's avatar
赵怡然 committed
224
225
226
          // Add negative HP to the current HP property.
          this.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, -(event.getDamage()));
        }
github-actions's avatar
github-actions committed
227
228
229

        // Check if dead
        boolean isDead = false;
230
231
        if (this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) <= 0f) {
            this.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0f);
github-actions's avatar
github-actions committed
232
233
234
235
236
237
            isDead = true;
        }

        // Packets
        this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP));

238
        // Check if dead.
github-actions's avatar
github-actions committed
239
        if (isDead) {
240
            this.getScene().killEntity(this, killerId);
github-actions's avatar
github-actions committed
241
242
        }
    }
KingRainbow44's avatar
KingRainbow44 committed
243
244
245
246
247
248
249
250
251
252
253
254

    /**
     * Move this entity to a new position.
     * @param position The new position.
     * @param rotation The new rotation.
     */
    public void move(Position position, Position rotation) {
        // Set the position and rotation.
        this.getPosition().set(position);
        this.getRotation().set(rotation);
    }

github-actions's avatar
github-actions committed
255
    /**
Melledy's avatar
Melledy committed
256
257
     * Called when a player interacts with this entity
     * @param player Player that is interacting with this entity
github-actions's avatar
github-actions committed
258
     * @param interactReq Interact request protobuf data
Melledy's avatar
Melledy committed
259
260
     */
    public void onInteract(Player player, GadgetInteractReq interactReq) {
github-actions's avatar
github-actions committed
261

Melledy's avatar
Melledy committed
262
    }
github-actions's avatar
github-actions committed
263

264
265
266
    /**
     * Called when this entity is added to the world
     */
github-actions's avatar
github-actions committed
267
    public void onCreate() {
KingRainbow44's avatar
KingRainbow44 committed
268

github-actions's avatar
github-actions committed
269
    }
KingRainbow44's avatar
KingRainbow44 committed
270

github-actions's avatar
github-actions committed
271
    /**
272
273
274
     * Called when this entity dies
     * @param killerId Entity id of the entity that killed this entity
     */
github-actions's avatar
github-actions committed
275
    public void onDeath(int killerId) {
276
277
278
        // Invoke entity death event.
        EntityDeathEvent event = new EntityDeathEvent(this, killerId);
        event.call();
github-actions's avatar
github-actions committed
279
    }
KingRainbow44's avatar
KingRainbow44 committed
280

github-actions's avatar
github-actions committed
281
    public abstract SceneEntityInfo toProto();
Melledy's avatar
Melledy committed
282
}