Files
HytaleMMORPG/src/main/java/com/disklexar/mmorpg/combat/PassiveEffectService.java
T
gpatruno 3710a28ae0
Build / build (push) Has been cancelled
first
2026-06-05 15:00:58 +02:00

93 lines
3.4 KiB
Java

package com.disklexar.mmorpg.combat;
import com.disklexar.mmorpg.MmorpgPlugin;
import com.disklexar.mmorpg.core.service.Service;
import com.disklexar.mmorpg.player.OnlinePlayer;
import com.disklexar.mmorpg.player.OnlinePlayerRegistry;
import com.disklexar.mmorpg.player.PlayerSessionService;
import com.disklexar.mmorpg.player.model.PlayerProfile;
import com.disklexar.mmorpg.rpg.power.PowerCatalog;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.protocol.MovementSettings;
import com.hypixel.hytale.server.core.entity.entities.player.movement.MovementManager;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import javax.annotation.Nonnull;
import java.util.concurrent.ScheduledFuture;
/**
* Reconciles passive movement effects every couple of seconds.
* <p>
* The "Sprinter" power grants {@code +10%} base movement speed while the player is out of combat;
* the bonus is removed while in combat and restored afterwards.
*/
public final class PassiveEffectService implements Service {
private static final long RECONCILE_PERIOD = 2_000L;
private final MmorpgScheduler scheduler;
private final OnlinePlayerRegistry online;
private final PlayerSessionService sessions;
private final CombatStateService combatState;
private ScheduledFuture<?> task;
public PassiveEffectService(
@Nonnull MmorpgPlugin plugin,
@Nonnull MmorpgScheduler scheduler,
@Nonnull OnlinePlayerRegistry online,
@Nonnull PlayerSessionService sessions,
@Nonnull CombatStateService combatState) {
this.scheduler = scheduler;
this.online = online;
this.sessions = sessions;
this.combatState = combatState;
}
@Override
public void start() {
task = scheduler.runRepeating(this::reconcileAll, RECONCILE_PERIOD, RECONCILE_PERIOD);
}
@Override
public void shutdown() {
if (task != null) {
task.cancel(false);
task = null;
}
}
private void reconcileAll() {
for (OnlinePlayer player : online.all()) {
PlayerProfile profile = sessions.getSession(player.uuid());
if (profile == null) {
continue;
}
boolean sprinter = profile.getPowers().contains(PowerCatalog.SPRINTER.id());
boolean active = sprinter && !combatState.isInCombat(player.uuid());
player.world().execute(() -> applySpeed(player, active));
}
}
private void applySpeed(@Nonnull OnlinePlayer player, boolean buffed) {
Store<EntityStore> store = player.world().getEntityStore().getStore();
Ref<EntityStore> ref = player.entityRef();
MovementManager movement = store.getComponent(ref, MovementManager.getComponentType());
if (movement == null) {
return;
}
MovementSettings defaults = movement.getDefaultSettings();
MovementSettings current = movement.getSettings();
if (defaults == null || current == null) {
return;
}
float baseline = defaults.baseSpeed;
float target = buffed ? baseline * (float) (1.0 + PowerCatalog.SPRINTER_SPEED_BONUS) : baseline;
if (Math.abs(current.baseSpeed - target) > 0.0001f) {
current.baseSpeed = target;
movement.update(player.playerRef().getPacketHandler());
}
}
}