Fix debuffs from summoned skills not expiring

This commit is contained in:
Melledy
2023-12-14 06:22:49 -08:00
parent 8eab7cef9e
commit d9785289dd
8 changed files with 158 additions and 97 deletions

View File

@@ -19,9 +19,9 @@ public final class EntityBuffChangeInfoOuterClass {
private static final long serialVersionUID = 0L; private static final long serialVersionUID = 0L;
/** /**
* <code>optional uint32 CBOEIMDHBIJ = 5;</code> * <code>optional uint32 remove_buff_id = 5;</code>
*/ */
private int cBOEIMDHBIJ; private int removeBuffId;
/** /**
* <code>optional uint32 entity_id = 8;</code> * <code>optional uint32 entity_id = 8;</code>
@@ -29,9 +29,9 @@ public final class EntityBuffChangeInfoOuterClass {
private int entityId; private int entityId;
/** /**
* <code>optional .BuffInfo buff_change_info = 4;</code> * <code>optional .BuffInfo add_buff_info = 4;</code>
*/ */
private final BuffInfoOuterClass.BuffInfo buffChangeInfo = BuffInfoOuterClass.BuffInfo.newInstance(); private final BuffInfoOuterClass.BuffInfo addBuffInfo = BuffInfoOuterClass.BuffInfo.newInstance();
private EntityBuffChangeInfo() { private EntityBuffChangeInfo() {
} }
@@ -49,59 +49,59 @@ public final class EntityBuffChangeInfoOuterClass {
public EntityBuffChangeInfo clearInfo() { public EntityBuffChangeInfo clearInfo() {
if (hasInfo()) { if (hasInfo()) {
clearCBOEIMDHBIJ(); clearRemoveBuffId();
clearBuffChangeInfo(); clearAddBuffInfo();
} }
return this; return this;
} }
private void clearInfoOtherCBOEIMDHBIJ() { private void clearInfoOtherRemoveBuffId() {
if ((((bitField0_ & 0x00000002)) != 0)) { if ((((bitField0_ & 0x00000002)) != 0)) {
clearBuffChangeInfo(); clearAddBuffInfo();
} }
} }
private void clearInfoOtherBuffChangeInfo() { private void clearInfoOtherAddBuffInfo() {
if ((((bitField0_ & 0x00000001)) != 0)) { if ((((bitField0_ & 0x00000001)) != 0)) {
clearCBOEIMDHBIJ(); clearRemoveBuffId();
} }
} }
/** /**
* <code>optional uint32 CBOEIMDHBIJ = 5;</code> * <code>optional uint32 remove_buff_id = 5;</code>
* @return whether the cBOEIMDHBIJ field is set * @return whether the removeBuffId field is set
*/ */
public boolean hasCBOEIMDHBIJ() { public boolean hasRemoveBuffId() {
return (bitField0_ & 0x00000001) != 0; return (bitField0_ & 0x00000001) != 0;
} }
/** /**
* <code>optional uint32 CBOEIMDHBIJ = 5;</code> * <code>optional uint32 remove_buff_id = 5;</code>
* @return this * @return this
*/ */
public EntityBuffChangeInfo clearCBOEIMDHBIJ() { public EntityBuffChangeInfo clearRemoveBuffId() {
bitField0_ &= ~0x00000001; bitField0_ &= ~0x00000001;
cBOEIMDHBIJ = 0; removeBuffId = 0;
return this; return this;
} }
/** /**
* <code>optional uint32 CBOEIMDHBIJ = 5;</code> * <code>optional uint32 remove_buff_id = 5;</code>
* @return the cBOEIMDHBIJ * @return the removeBuffId
*/ */
public int getCBOEIMDHBIJ() { public int getRemoveBuffId() {
return cBOEIMDHBIJ; return removeBuffId;
} }
/** /**
* <code>optional uint32 CBOEIMDHBIJ = 5;</code> * <code>optional uint32 remove_buff_id = 5;</code>
* @param value the cBOEIMDHBIJ to set * @param value the removeBuffId to set
* @return this * @return this
*/ */
public EntityBuffChangeInfo setCBOEIMDHBIJ(final int value) { public EntityBuffChangeInfo setRemoveBuffId(final int value) {
clearInfoOtherCBOEIMDHBIJ(); clearInfoOtherRemoveBuffId();
bitField0_ |= 0x00000001; bitField0_ |= 0x00000001;
cBOEIMDHBIJ = value; removeBuffId = value;
return this; return this;
} }
@@ -143,39 +143,39 @@ public final class EntityBuffChangeInfoOuterClass {
} }
/** /**
* <code>optional .BuffInfo buff_change_info = 4;</code> * <code>optional .BuffInfo add_buff_info = 4;</code>
* @return whether the buffChangeInfo field is set * @return whether the addBuffInfo field is set
*/ */
public boolean hasBuffChangeInfo() { public boolean hasAddBuffInfo() {
return (bitField0_ & 0x00000002) != 0; return (bitField0_ & 0x00000002) != 0;
} }
/** /**
* <code>optional .BuffInfo buff_change_info = 4;</code> * <code>optional .BuffInfo add_buff_info = 4;</code>
* @return this * @return this
*/ */
public EntityBuffChangeInfo clearBuffChangeInfo() { public EntityBuffChangeInfo clearAddBuffInfo() {
bitField0_ &= ~0x00000002; bitField0_ &= ~0x00000002;
buffChangeInfo.clear(); addBuffInfo.clear();
return this; return this;
} }
/** /**
* <code>optional .BuffInfo buff_change_info = 4;</code> * <code>optional .BuffInfo add_buff_info = 4;</code>
* *
* This method returns the internal storage object without modifying any has state. * This method returns the internal storage object without modifying any has state.
* The returned object should not be modified and be treated as read-only. * The returned object should not be modified and be treated as read-only.
* *
* Use {@link #getMutableBuffChangeInfo()} if you want to modify it. * Use {@link #getMutableAddBuffInfo()} if you want to modify it.
* *
* @return internal storage object for reading * @return internal storage object for reading
*/ */
public BuffInfoOuterClass.BuffInfo getBuffChangeInfo() { public BuffInfoOuterClass.BuffInfo getAddBuffInfo() {
return buffChangeInfo; return addBuffInfo;
} }
/** /**
* <code>optional .BuffInfo buff_change_info = 4;</code> * <code>optional .BuffInfo add_buff_info = 4;</code>
* *
* This method returns the internal storage object and sets the corresponding * This method returns the internal storage object and sets the corresponding
* has state. The returned object will become part of this message and its * has state. The returned object will become part of this message and its
@@ -183,21 +183,21 @@ public final class EntityBuffChangeInfoOuterClass {
* *
* @return internal storage object for modifications * @return internal storage object for modifications
*/ */
public BuffInfoOuterClass.BuffInfo getMutableBuffChangeInfo() { public BuffInfoOuterClass.BuffInfo getMutableAddBuffInfo() {
clearInfoOtherBuffChangeInfo(); clearInfoOtherAddBuffInfo();
bitField0_ |= 0x00000002; bitField0_ |= 0x00000002;
return buffChangeInfo; return addBuffInfo;
} }
/** /**
* <code>optional .BuffInfo buff_change_info = 4;</code> * <code>optional .BuffInfo add_buff_info = 4;</code>
* @param value the buffChangeInfo to set * @param value the addBuffInfo to set
* @return this * @return this
*/ */
public EntityBuffChangeInfo setBuffChangeInfo(final BuffInfoOuterClass.BuffInfo value) { public EntityBuffChangeInfo setAddBuffInfo(final BuffInfoOuterClass.BuffInfo value) {
clearInfoOtherBuffChangeInfo(); clearInfoOtherAddBuffInfo();
bitField0_ |= 0x00000002; bitField0_ |= 0x00000002;
buffChangeInfo.copyFrom(value); addBuffInfo.copyFrom(value);
return this; return this;
} }
@@ -206,9 +206,9 @@ public final class EntityBuffChangeInfoOuterClass {
cachedSize = other.cachedSize; cachedSize = other.cachedSize;
if ((bitField0_ | other.bitField0_) != 0) { if ((bitField0_ | other.bitField0_) != 0) {
bitField0_ = other.bitField0_; bitField0_ = other.bitField0_;
cBOEIMDHBIJ = other.cBOEIMDHBIJ; removeBuffId = other.removeBuffId;
entityId = other.entityId; entityId = other.entityId;
buffChangeInfo.copyFrom(other.buffChangeInfo); addBuffInfo.copyFrom(other.addBuffInfo);
} }
return this; return this;
} }
@@ -219,14 +219,14 @@ public final class EntityBuffChangeInfoOuterClass {
return this; return this;
} }
cachedSize = -1; cachedSize = -1;
if (other.hasCBOEIMDHBIJ()) { if (other.hasRemoveBuffId()) {
setCBOEIMDHBIJ(other.cBOEIMDHBIJ); setRemoveBuffId(other.removeBuffId);
} }
if (other.hasEntityId()) { if (other.hasEntityId()) {
setEntityId(other.entityId); setEntityId(other.entityId);
} }
if (other.hasBuffChangeInfo()) { if (other.hasAddBuffInfo()) {
getMutableBuffChangeInfo().mergeFrom(other.buffChangeInfo); getMutableAddBuffInfo().mergeFrom(other.addBuffInfo);
} }
return this; return this;
} }
@@ -238,9 +238,9 @@ public final class EntityBuffChangeInfoOuterClass {
} }
cachedSize = -1; cachedSize = -1;
bitField0_ = 0; bitField0_ = 0;
cBOEIMDHBIJ = 0; removeBuffId = 0;
entityId = 0; entityId = 0;
buffChangeInfo.clear(); addBuffInfo.clear();
return this; return this;
} }
@@ -251,7 +251,7 @@ public final class EntityBuffChangeInfoOuterClass {
} }
cachedSize = -1; cachedSize = -1;
bitField0_ = 0; bitField0_ = 0;
buffChangeInfo.clearQuick(); addBuffInfo.clearQuick();
return this; return this;
} }
@@ -265,16 +265,16 @@ public final class EntityBuffChangeInfoOuterClass {
} }
EntityBuffChangeInfo other = (EntityBuffChangeInfo) o; EntityBuffChangeInfo other = (EntityBuffChangeInfo) o;
return bitField0_ == other.bitField0_ return bitField0_ == other.bitField0_
&& (!hasCBOEIMDHBIJ() || cBOEIMDHBIJ == other.cBOEIMDHBIJ) && (!hasRemoveBuffId() || removeBuffId == other.removeBuffId)
&& (!hasEntityId() || entityId == other.entityId) && (!hasEntityId() || entityId == other.entityId)
&& (!hasBuffChangeInfo() || buffChangeInfo.equals(other.buffChangeInfo)); && (!hasAddBuffInfo() || addBuffInfo.equals(other.addBuffInfo));
} }
@Override @Override
public void writeTo(final ProtoSink output) throws IOException { public void writeTo(final ProtoSink output) throws IOException {
if ((bitField0_ & 0x00000001) != 0) { if ((bitField0_ & 0x00000001) != 0) {
output.writeRawByte((byte) 40); output.writeRawByte((byte) 40);
output.writeUInt32NoTag(cBOEIMDHBIJ); output.writeUInt32NoTag(removeBuffId);
} }
if ((bitField0_ & 0x00000004) != 0) { if ((bitField0_ & 0x00000004) != 0) {
output.writeRawByte((byte) 64); output.writeRawByte((byte) 64);
@@ -282,7 +282,7 @@ public final class EntityBuffChangeInfoOuterClass {
} }
if ((bitField0_ & 0x00000002) != 0) { if ((bitField0_ & 0x00000002) != 0) {
output.writeRawByte((byte) 34); output.writeRawByte((byte) 34);
output.writeMessageNoTag(buffChangeInfo); output.writeMessageNoTag(addBuffInfo);
} }
} }
@@ -290,13 +290,13 @@ public final class EntityBuffChangeInfoOuterClass {
protected int computeSerializedSize() { protected int computeSerializedSize() {
int size = 0; int size = 0;
if ((bitField0_ & 0x00000001) != 0) { if ((bitField0_ & 0x00000001) != 0) {
size += 1 + ProtoSink.computeUInt32SizeNoTag(cBOEIMDHBIJ); size += 1 + ProtoSink.computeUInt32SizeNoTag(removeBuffId);
} }
if ((bitField0_ & 0x00000004) != 0) { if ((bitField0_ & 0x00000004) != 0) {
size += 1 + ProtoSink.computeUInt32SizeNoTag(entityId); size += 1 + ProtoSink.computeUInt32SizeNoTag(entityId);
} }
if ((bitField0_ & 0x00000002) != 0) { if ((bitField0_ & 0x00000002) != 0) {
size += 1 + ProtoSink.computeMessageSizeNoTag(buffChangeInfo); size += 1 + ProtoSink.computeMessageSizeNoTag(addBuffInfo);
} }
return size; return size;
} }
@@ -309,9 +309,9 @@ public final class EntityBuffChangeInfoOuterClass {
while (true) { while (true) {
switch (tag) { switch (tag) {
case 40: { case 40: {
// cBOEIMDHBIJ // removeBuffId
clearInfoOtherCBOEIMDHBIJ(); clearInfoOtherRemoveBuffId();
cBOEIMDHBIJ = input.readUInt32(); removeBuffId = input.readUInt32();
bitField0_ |= 0x00000001; bitField0_ |= 0x00000001;
tag = input.readTag(); tag = input.readTag();
if (tag != 64) { if (tag != 64) {
@@ -328,9 +328,9 @@ public final class EntityBuffChangeInfoOuterClass {
} }
} }
case 34: { case 34: {
// buffChangeInfo // addBuffInfo
clearInfoOtherBuffChangeInfo(); clearInfoOtherAddBuffInfo();
input.readMessage(buffChangeInfo); input.readMessage(addBuffInfo);
bitField0_ |= 0x00000002; bitField0_ |= 0x00000002;
tag = input.readTag(); tag = input.readTag();
if (tag != 0) { if (tag != 0) {
@@ -355,13 +355,13 @@ public final class EntityBuffChangeInfoOuterClass {
public void writeTo(final JsonSink output) throws IOException { public void writeTo(final JsonSink output) throws IOException {
output.beginObject(); output.beginObject();
if ((bitField0_ & 0x00000001) != 0) { if ((bitField0_ & 0x00000001) != 0) {
output.writeUInt32(FieldNames.cBOEIMDHBIJ, cBOEIMDHBIJ); output.writeUInt32(FieldNames.removeBuffId, removeBuffId);
} }
if ((bitField0_ & 0x00000004) != 0) { if ((bitField0_ & 0x00000004) != 0) {
output.writeUInt32(FieldNames.entityId, entityId); output.writeUInt32(FieldNames.entityId, entityId);
} }
if ((bitField0_ & 0x00000002) != 0) { if ((bitField0_ & 0x00000002) != 0) {
output.writeMessage(FieldNames.buffChangeInfo, buffChangeInfo); output.writeMessage(FieldNames.addBuffInfo, addBuffInfo);
} }
output.endObject(); output.endObject();
} }
@@ -373,11 +373,12 @@ public final class EntityBuffChangeInfoOuterClass {
} }
while (!input.isAtEnd()) { while (!input.isAtEnd()) {
switch (input.readFieldHash()) { switch (input.readFieldHash()) {
case 1350914854: { case -1339555214:
if (input.isAtField(FieldNames.cBOEIMDHBIJ)) { case 927119308: {
if (input.isAtField(FieldNames.removeBuffId)) {
if (!input.trySkipNullValue()) { if (!input.trySkipNullValue()) {
clearInfoOtherCBOEIMDHBIJ(); clearInfoOtherRemoveBuffId();
cBOEIMDHBIJ = input.readUInt32(); removeBuffId = input.readUInt32();
bitField0_ |= 0x00000001; bitField0_ |= 0x00000001;
} }
} else { } else {
@@ -397,12 +398,12 @@ public final class EntityBuffChangeInfoOuterClass {
} }
break; break;
} }
case -731204303: case 1797813090:
case -369384975: { case 888334076: {
if (input.isAtField(FieldNames.buffChangeInfo)) { if (input.isAtField(FieldNames.addBuffInfo)) {
if (!input.trySkipNullValue()) { if (!input.trySkipNullValue()) {
clearInfoOtherBuffChangeInfo(); clearInfoOtherAddBuffInfo();
input.readMessage(buffChangeInfo); input.readMessage(addBuffInfo);
bitField0_ |= 0x00000002; bitField0_ |= 0x00000002;
} }
} else { } else {
@@ -463,11 +464,11 @@ public final class EntityBuffChangeInfoOuterClass {
* Contains name constants used for serializing JSON * Contains name constants used for serializing JSON
*/ */
static class FieldNames { static class FieldNames {
static final FieldName cBOEIMDHBIJ = FieldName.forField("CBOEIMDHBIJ"); static final FieldName removeBuffId = FieldName.forField("removeBuffId", "remove_buff_id");
static final FieldName entityId = FieldName.forField("entityId", "entity_id"); static final FieldName entityId = FieldName.forField("entityId", "entity_id");
static final FieldName buffChangeInfo = FieldName.forField("buffChangeInfo", "buff_change_info"); static final FieldName addBuffInfo = FieldName.forField("addBuffInfo", "add_buff_info");
} }
} }
} }

View File

@@ -59,6 +59,7 @@ import emu.lunarcore.proto.SimpleAvatarInfoOuterClass.SimpleAvatarInfo;
import emu.lunarcore.proto.SimpleInfoOuterClass.SimpleInfo; import emu.lunarcore.proto.SimpleInfoOuterClass.SimpleInfo;
import emu.lunarcore.server.game.GameServer; import emu.lunarcore.server.game.GameServer;
import emu.lunarcore.server.game.GameSession; import emu.lunarcore.server.game.GameSession;
import emu.lunarcore.server.game.Tickable;
import emu.lunarcore.server.packet.BasePacket; import emu.lunarcore.server.packet.BasePacket;
import emu.lunarcore.server.packet.CmdId; import emu.lunarcore.server.packet.CmdId;
import emu.lunarcore.server.packet.send.*; import emu.lunarcore.server.packet.send.*;
@@ -73,7 +74,7 @@ import lombok.Setter;
@Entity(value = "players", useDiscriminator = false) @Entity(value = "players", useDiscriminator = false)
@Getter @Getter
public class Player { public class Player implements Tickable {
@Id private int uid; @Id private int uid;
@Indexed private String accountUid; @Indexed private String accountUid;
private String name; private String name;
@@ -519,27 +520,26 @@ public class Player {
return amount; return amount;
} }
private void updateStamina() { private void updateStamina(long timestamp) {
// Get current timestamp // Setup on change flag
long time = System.currentTimeMillis();
boolean hasChanged = false; boolean hasChanged = false;
// Check if we can add stamina // Check if we can add stamina
while (time >= this.nextStaminaRecover) { while (timestamp >= this.nextStaminaRecover) {
// Add stamina // Add stamina
if (this.stamina < GameConstants.MAX_STAMINA) { if (this.stamina < GameConstants.MAX_STAMINA) {
this.stamina += 1; this.stamina += 1;
hasChanged = true; hasChanged = true;
} else if (this.stamina < GameConstants.MAX_STAMINA_RESERVE) { } else if (this.stamina < GameConstants.MAX_STAMINA_RESERVE) {
double rate = LunarCore.getConfig().getServerOptions().getStaminaReserveRecoveryRate(); double rate = LunarCore.getConfig().getServerOptions().getStaminaReserveRecoveryRate();
double amount = (time - this.nextStaminaRecover) / (rate * 1000D); double amount = (timestamp - this.nextStaminaRecover) / (rate * 1000D);
this.staminaReserve = Math.min(this.staminaReserve + amount, GameConstants.MAX_STAMINA_RESERVE); this.staminaReserve = Math.min(this.staminaReserve + amount, GameConstants.MAX_STAMINA_RESERVE);
hasChanged = true; hasChanged = true;
} }
// Calculate next stamina recover time // Calculate next stamina recover time
if (this.stamina >= GameConstants.MAX_STAMINA) { if (this.stamina >= GameConstants.MAX_STAMINA) {
this.nextStaminaRecover = time; this.nextStaminaRecover = timestamp;
} }
this.nextStaminaRecover += LunarCore.getConfig().getServerOptions().getStaminaRecoveryRate() * 1000; this.nextStaminaRecover += LunarCore.getConfig().getServerOptions().getStaminaRecoveryRate() * 1000;
@@ -722,12 +722,12 @@ public class Player {
} }
} }
public void onTick() { public void onTick(long timestamp, long delta) {
// Update stamina // Update stamina
this.updateStamina(); this.updateStamina(timestamp);
// Scene update // Scene update
if (this.getScene() != null) { if (this.getScene() != null) {
this.getScene().onTick(); this.getScene().onTick(timestamp, delta);
} }
} }
@@ -746,7 +746,7 @@ public class Player {
this.getRogueManager().loadFromDatabase(); this.getRogueManager().loadFromDatabase();
// Update stamina // Update stamina
this.updateStamina(); this.updateStamina(System.currentTimeMillis());
// Check instances // Check instances
if (this.getChallengeInstance() != null && !this.getChallengeInstance().validate(this)) { if (this.getChallengeInstance() != null && !this.getChallengeInstance().validate(this)) {

View File

@@ -19,6 +19,7 @@ import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
import emu.lunarcore.proto.SceneEntityGroupInfoOuterClass.SceneEntityGroupInfo; import emu.lunarcore.proto.SceneEntityGroupInfoOuterClass.SceneEntityGroupInfo;
import emu.lunarcore.proto.SceneGroupStateOuterClass.SceneGroupState; import emu.lunarcore.proto.SceneGroupStateOuterClass.SceneGroupState;
import emu.lunarcore.proto.SceneInfoOuterClass.SceneInfo; import emu.lunarcore.proto.SceneInfoOuterClass.SceneInfo;
import emu.lunarcore.server.game.Tickable;
import emu.lunarcore.server.packet.send.PacketActivateFarmElementScRsp; import emu.lunarcore.server.packet.send.PacketActivateFarmElementScRsp;
import emu.lunarcore.server.packet.send.PacketRefreshTriggerByClientScNotify; import emu.lunarcore.server.packet.send.PacketRefreshTriggerByClientScNotify;
import emu.lunarcore.server.packet.send.PacketSceneGroupRefreshScNotify; import emu.lunarcore.server.packet.send.PacketSceneGroupRefreshScNotify;
@@ -29,7 +30,7 @@ import lombok.Getter;
import us.hebi.quickbuf.RepeatedInt; import us.hebi.quickbuf.RepeatedInt;
@Getter @Getter
public class Scene { public class Scene implements Tickable {
private final Player player; private final Player player;
private final MazePlaneExcel excel; private final MazePlaneExcel excel;
private final FloorInfo floorInfo; private final FloorInfo floorInfo;
@@ -352,13 +353,20 @@ public class Scene {
// Player events // Player events
public void onTick() { @Override
public synchronized void onTick(long timestamp, long delta) {
// Remove summoned unit if it expired // Remove summoned unit if it expired
if (this.getPlayerSummon() != null) { if (this.getPlayerSummon() != null) {
if (this.getPlayerSummon().isExpired()) { if (this.getPlayerSummon().isExpired()) {
this.removeSummonUnit(); this.removeSummonUnit();
} }
} }
// Tick entities
for (GameEntity entity : this.getEntities().values()) {
if (entity instanceof Tickable tickableEntity) {
tickableEntity.onTick(timestamp, delta);
}
}
} }
public void onBattleStart(Battle battle) { public void onBattleStart(Battle battle) {

View File

@@ -21,6 +21,10 @@ public class SceneBuff {
this.expiry = this.createTime + duration; this.expiry = this.createTime + duration;
} }
public boolean isExpired(long timestamp) {
return timestamp > this.expiry;
}
// Serialization // Serialization
public BuffInfo toProto() { public BuffInfo toProto() {

View File

@@ -10,6 +10,8 @@ import emu.lunarcore.game.scene.triggers.PropTriggerType;
import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo; import emu.lunarcore.proto.MotionInfoOuterClass.MotionInfo;
import emu.lunarcore.proto.SceneEntityInfoOuterClass.SceneEntityInfo; import emu.lunarcore.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.lunarcore.proto.SceneNpcMonsterInfoOuterClass.SceneNpcMonsterInfo; import emu.lunarcore.proto.SceneNpcMonsterInfoOuterClass.SceneNpcMonsterInfo;
import emu.lunarcore.server.game.Tickable;
import emu.lunarcore.server.packet.send.PacketSyncEntityBuffChangeListScNotify;
import emu.lunarcore.util.Position; import emu.lunarcore.util.Position;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@@ -17,7 +19,7 @@ import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@Getter @Getter
public class EntityMonster implements GameEntity { public class EntityMonster implements GameEntity, Tickable {
@Setter private NpcMonsterExcel excel; @Setter private NpcMonsterExcel excel;
@Setter private int entityId; @Setter private int entityId;
@Setter private int worldLevel; @Setter private int worldLevel;
@@ -56,7 +58,7 @@ public class EntityMonster implements GameEntity {
} }
} }
public SceneBuff addBuff(int caster, int buffId, int duration) { public synchronized SceneBuff addBuff(int caster, int buffId, int duration) {
if (this.buffs == null) { if (this.buffs == null) {
this.buffs = new Int2ObjectOpenHashMap<>(); this.buffs = new Int2ObjectOpenHashMap<>();
} }
@@ -69,12 +71,12 @@ public class EntityMonster implements GameEntity {
return buff; return buff;
} }
public void applyBuffs(Battle battle) { public synchronized void applyBuffs(Battle battle) {
if (this.buffs == null) return; if (this.buffs == null) return;
for (var entry : this.buffs.int2ObjectEntrySet()) { for (var entry : this.buffs.int2ObjectEntrySet()) {
// Check expiry for buff // Check expiry for buff
if (entry.getValue().getExpiry() < battle.getTimestamp()) { if (entry.getValue().isExpired(battle.getTimestamp())) {
continue; continue;
} }
@@ -100,6 +102,26 @@ public class EntityMonster implements GameEntity {
getScene().invokePropTrigger(PropTriggerType.MONSTER_DIE, this.getGroupId(), this.getInstId()); getScene().invokePropTrigger(PropTriggerType.MONSTER_DIE, this.getGroupId(), this.getInstId());
} }
@Override
public synchronized void onTick(long timestamp, long delta) {
// Check if we need to remove any buffs
if (this.buffs != null && this.buffs.size() > 0) {
var it = this.buffs.values().iterator();
while (it.hasNext()) {
var buff = it.next();
if (buff.isExpired(timestamp)) {
// Safely remove from iterator
it.remove();
// Send packet to notify the client that we are removing the buff
getScene().getPlayer().sendPacket(new PacketSyncEntityBuffChangeListScNotify(this.getEntityId(), buff.getBuffId()));
}
}
}
}
@Override @Override
public SceneEntityInfo toSceneEntityProto() { public SceneEntityInfo toSceneEntityProto() {
var monster = SceneNpcMonsterInfo.newInstance() var monster = SceneNpcMonsterInfo.newInstance()

View File

@@ -27,6 +27,7 @@ public class GameServer extends KcpServer {
private final Int2ObjectMap<Player> players; private final Int2ObjectMap<Player> players;
private final Timer gameLoopTimer; private final Timer gameLoopTimer;
private long lastTickTime;
// Managers // Managers
@Getter private final GameServerPacketHandler packetHandler; @Getter private final GameServerPacketHandler packetHandler;
@@ -56,6 +57,7 @@ public class GameServer extends KcpServer {
this.shopService = new ShopService(this); this.shopService = new ShopService(this);
// Game loop // Game loop
this.lastTickTime = System.currentTimeMillis();
this.gameLoopTimer = new Timer(); this.gameLoopTimer = new Timer();
this.gameLoopTimer.scheduleAtFixedRate(new TimerTask() { this.gameLoopTimer.scheduleAtFixedRate(new TimerTask() {
@Override @Override
@@ -173,10 +175,14 @@ public class GameServer extends KcpServer {
} }
private void onTick() { private void onTick() {
long timestamp = System.currentTimeMillis();
long delta = timestamp - lastTickTime;
this.lastTickTime = timestamp;
synchronized (this.players) { synchronized (this.players) {
for (Player player : this.players.values()) { for (Player player : this.players.values()) {
try { try {
player.onTick(); player.onTick(timestamp, delta);
} catch (Exception e) { } catch (Exception e) {
LunarCore.getLogger().error("[UID: " + player.getUid() + "] Player tick error: ", e); LunarCore.getLogger().error("[UID: " + player.getUid() + "] Player tick error: ", e);
} }

View File

@@ -0,0 +1,7 @@
package emu.lunarcore.server.game;
public interface Tickable {
public void onTick(long timestamp, long delta);
}

View File

@@ -12,7 +12,20 @@ public class PacketSyncEntityBuffChangeListScNotify extends BasePacket {
super(CmdId.SyncEntityBuffChangeListScNotify); super(CmdId.SyncEntityBuffChangeListScNotify);
var buffChange = EntityBuffChangeInfo.newInstance().setEntityId(entityId) var buffChange = EntityBuffChangeInfo.newInstance().setEntityId(entityId)
.setBuffChangeInfo(buff.toProto()) .setAddBuffInfo(buff.toProto())
.setEntityId(entityId);
var data = SyncEntityBuffChangeListScNotify.newInstance()
.addEntityBuffInfoList(buffChange);
this.setData(data);
}
public PacketSyncEntityBuffChangeListScNotify(int entityId, int removeBuffId) {
super(CmdId.SyncEntityBuffChangeListScNotify);
var buffChange = EntityBuffChangeInfo.newInstance().setEntityId(entityId)
.setRemoveBuffId(removeBuffId)
.setEntityId(entityId); .setEntityId(entityId);
var data = SyncEntityBuffChangeListScNotify.newInstance() var data = SyncEntityBuffChangeListScNotify.newInstance()