mdbd/src/main/java/dev/loki/gate/ExitGate.java

153 lines
4.4 KiB
Java

package dev.loki.gate;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.World;
public class ExitGate {
private final Location location;
private GateState state;
private double progress;
private double savedProgress; // сохраняется при уходе игрока
private boolean powered;
public enum GateState {
CLOSED,
OPENING,
OPEN
}
public ExitGate(Location location) {
this.location = location;
this.state = GateState.CLOSED;
this.progress = 0.0;
this.savedProgress = 0.0;
this.powered = false;
}
public Location getLocation() {
return location;
}
/** Place a HOPPER block at this gate's location for player interaction. */
public void spawnGateBlock() {
if (location.getWorld() == null) return;
location.getBlock().setType(org.bukkit.Material.HOPPER, false);
}
/** Remove the interaction block (e.g. when gate opens or on cleanup). */
public void removeGateBlock() {
if (location.getWorld() == null) return;
location.getBlock().setType(org.bukkit.Material.AIR, false);
}
public GateState getState() {
return state;
}
public boolean isClosed() {
return state == GateState.CLOSED;
}
public boolean isOpening() {
return state == GateState.OPENING;
}
public boolean isOpen() {
return state == GateState.OPEN;
}
public double getProgress() {
return progress;
}
public int getProgressPercent() {
return (int) (progress * 100);
}
public boolean isPowered() {
return powered;
}
public void setPowered(boolean powered) {
this.powered = powered;
if (powered && state == GateState.CLOSED) {
state = GateState.OPENING;
}
}
public void startOpening() {
if (state == GateState.CLOSED && powered) {
state = GateState.OPENING;
playOpenSound();
}
}
public void updateProgress(double delta) {
if (state != GateState.OPENING) return;
// Линейная установка — delta это абсолютный шаг, не additive accumulation
progress = Math.min(1.0, progress + delta);
if (progress >= 1.0) {
progress = 1.0;
state = GateState.OPEN;
playOpenedSound();
}
}
/** Прямая установка прогресса (для линейного расчёта в GateOpening). */
public void setProgressDirect(double value) {
if (state != GateState.OPENING) return;
progress = Math.min(1.0, Math.max(0.0, value));
if (progress >= 1.0) {
progress = 1.0;
state = GateState.OPEN;
removeGateBlock();
playOpenedSound();
}
}
public double getSavedProgress() { return savedProgress; }
/** Сохранить текущий прогресс (вызывается когда игрок уходит от ворот) */
public void saveProgress() { savedProgress = progress; }
/** Восстановить сохранённый прогресс (вызывается когда игрок подходит снова) */
public void restoreProgress() { progress = savedProgress; }
public void reset() {
removeGateBlock();
this.state = GateState.CLOSED;
this.progress = 0.0;
this.savedProgress = 0.0;
this.powered = false;
}
public boolean isInRange(Location playerLoc, double radius) {
return location.distance(playerLoc) <= radius;
}
public void playOpenSound() {
World world = location.getWorld();
if (world != null) {
world.playSound(location, Sound.BLOCK_IRON_DOOR_OPEN, 1.0f, 0.8f);
}
}
public void playOpenedSound() {
World world = location.getWorld();
if (world != null) {
world.playSound(location, Sound.BLOCK_IRON_DOOR_CLOSE, 1.0f, 1.2f);
world.playSound(location, Sound.ENTITY_PLAYER_LEVELUP, 0.5f, 1.0f);
}
}
public void spawnOpenParticles() {
World world = location.getWorld();
if (world == null) return;
world.spawnParticle(org.bukkit.Particle.PORTAL,
location.clone().add(0.5, 1.5, 0.5),
50, 0.5, 1.0, 0.5, 0.1);
}
}