fix
This commit is contained in:
parent
89dc9eb00d
commit
957ab4a5a2
149 changed files with 5379 additions and 3263 deletions
308
src/main/java/dev/loki/phase/GameplayInteraction.java
Normal file
308
src/main/java/dev/loki/phase/GameplayInteraction.java
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
package dev.loki.phase;
|
||||
|
||||
import dev.loki.core.GameSession;
|
||||
import dev.loki.gate.ExitGate;
|
||||
import dev.loki.gate.GateManager;
|
||||
import dev.loki.gate.GateOpening;
|
||||
import dev.loki.hook.Hook;
|
||||
import dev.loki.hook.HookManager;
|
||||
import dev.loki.hook.HookRescue;
|
||||
import dev.loki.hook.HookSabotage;
|
||||
import dev.loki.killer.GeneratorKick;
|
||||
import dev.loki.listener.PlayerInteractListener;
|
||||
import dev.loki.listener.PlayerMoveListener;
|
||||
import dev.loki.player.BasePlayer;
|
||||
import dev.loki.player.Killer;
|
||||
import dev.loki.player.PlayerState;
|
||||
import dev.loki.player.Survivor;
|
||||
import dev.loki.survivor.SurvivorController;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Handles listener wiring for player interactions.
|
||||
*/
|
||||
public class GameplayInteraction {
|
||||
|
||||
private PlayerMoveListener moveListener;
|
||||
private PlayerInteractListener interactListener;
|
||||
private GateManager gateManager;
|
||||
private HookManager hookManager;
|
||||
private HookRescue hookRescue;
|
||||
private HookSabotage hookSabotage;
|
||||
private GeneratorKick generatorKick;
|
||||
private GameplayDamageSystem damageSystem;
|
||||
private dev.loki.chest.ChestManager chestManager;
|
||||
private dev.loki.chest.ChestOpening chestOpening;
|
||||
private GateOpening gateOpening;
|
||||
private dev.loki.objective.GeneratorRepair generatorRepair;
|
||||
private boolean allGensDone;
|
||||
private final Map<UUID, Long> killerLastSneakMs = new HashMap<>();
|
||||
private final Map<UUID, SurvivorController> survivorControllers = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Wire all listeners.
|
||||
*/
|
||||
public void wire(GameSession session) {
|
||||
wireMoveListener(session);
|
||||
wireInteractListener(session);
|
||||
wireSurvivorHealing(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize SurvivorControllers with a survivorLookup so healing
|
||||
* can find ANY player's Survivor instance (for healing other survivors).
|
||||
*/
|
||||
private void wireSurvivorHealing(GameSession session) {
|
||||
survivorControllers.clear();
|
||||
for (BasePlayer bp : session.getPlayers().values()) {
|
||||
if (bp.isKiller()) continue;
|
||||
Survivor survivor = (Survivor) bp;
|
||||
SurvivorController controller = new SurvivorController(survivor, session.getConfig());
|
||||
controller.getHealing().setSurvivorLookup(player -> {
|
||||
BasePlayer found = session.getPlayer(player.getUniqueId());
|
||||
if (found == null || found.isKiller()) return null;
|
||||
return (Survivor) found;
|
||||
});
|
||||
survivorControllers.put(survivor.getUuid(), controller);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMoveListener(PlayerMoveListener moveListener) {
|
||||
this.moveListener = moveListener;
|
||||
}
|
||||
|
||||
public void setInteractListener(PlayerInteractListener interactListener) {
|
||||
this.interactListener = interactListener;
|
||||
}
|
||||
|
||||
public void setManagers(GateManager gateManager,
|
||||
HookManager hookManager, HookRescue hookRescue,
|
||||
HookSabotage hookSabotage, GeneratorKick generatorKick,
|
||||
GameplayDamageSystem damageSystem,
|
||||
dev.loki.chest.ChestManager chestManager,
|
||||
dev.loki.chest.ChestOpening chestOpening,
|
||||
GateOpening gateOpening,
|
||||
dev.loki.objective.GeneratorRepair generatorRepair) {
|
||||
this.gateManager = gateManager;
|
||||
this.hookManager = hookManager;
|
||||
this.hookRescue = hookRescue;
|
||||
this.hookSabotage = hookSabotage;
|
||||
this.generatorKick = generatorKick;
|
||||
this.damageSystem = damageSystem;
|
||||
this.chestManager = chestManager;
|
||||
this.chestOpening = chestOpening;
|
||||
this.gateOpening = gateOpening;
|
||||
this.generatorRepair = generatorRepair;
|
||||
}
|
||||
|
||||
public void setAllGensDone(boolean allGensDone) {
|
||||
this.allGensDone = allGensDone;
|
||||
}
|
||||
|
||||
private void wireMoveListener(GameSession session) {
|
||||
if (moveListener == null) return;
|
||||
moveListener.setOnSurvivorMove((survivor, loc) -> {
|
||||
if (!allGensDone) return;
|
||||
if (survivor.getState() == PlayerState.ESCAPED) return;
|
||||
ExitGate gate = gateManager.getGateAt(loc, 3.0);
|
||||
if (gate != null && gate.isOpen()) {
|
||||
survivor.setState(PlayerState.ESCAPED);
|
||||
Player p = survivor.getPlayer();
|
||||
if (p != null) {
|
||||
p.playSound(loc, Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.2f);
|
||||
Bukkit.broadcast(Component.text(
|
||||
"[DBD] " + p.getName() + " сбежал через ворота!", NamedTextColor.GOLD));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void wireInteractListener(GameSession session) {
|
||||
if (interactListener == null) return;
|
||||
|
||||
// Rescue
|
||||
interactListener.setOnRescueAttempt((player, ignored) -> {
|
||||
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
||||
if (bp == null || bp.isKiller()) return;
|
||||
Survivor rescuer = (Survivor) bp;
|
||||
// Cannot rescue if you're hooked, downed, or carried
|
||||
if (rescuer.getState() == PlayerState.HOOKED ||
|
||||
rescuer.getState() == PlayerState.DOWNED ||
|
||||
rescuer.getState() == PlayerState.CARRIED) return;
|
||||
Hook hook = hookManager.findNearestOccupiedHook(player.getLocation(), 3.0);
|
||||
if (hook != null) hookRescue.startRescue(rescuer, hook);
|
||||
});
|
||||
|
||||
// Right-click attack (hook carrying / pickup downed)
|
||||
interactListener.setOnAttack((player, isRightClick) -> {
|
||||
if (!isRightClick) return;
|
||||
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
||||
if (bp == null || !bp.isKiller()) return;
|
||||
Killer killer = (Killer) bp;
|
||||
|
||||
if (killer.isCarrying()) {
|
||||
for (BasePlayer other : session.getPlayers().values()) {
|
||||
if (!other.isKiller() && other.getState() == PlayerState.CARRIED) {
|
||||
Survivor carried = (Survivor) other;
|
||||
if (hookManager.tryHookSurvivor(carried, player.getLocation())) {
|
||||
killer.setCarrying(false);
|
||||
Hook nearest = hookManager.findNearestOccupiedHook(player.getLocation(), 5.0);
|
||||
if (nearest != null) {
|
||||
Player vp = carried.getPlayer();
|
||||
if (vp != null) vp.teleport(nearest.getLocation());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Survivor target = damageSystem.getPlayerManager().getNearestSurvivorInState(
|
||||
player, PlayerState.DOWNED, 3.0);
|
||||
if (target != null) {
|
||||
boolean picked = damageSystem.getKillerController().tryPickup(killer, target);
|
||||
if (!picked) player.sendMessage(Component.text(
|
||||
"[DBD] Не удалось подобрать выжившего.", NamedTextColor.RED));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Sneak: killer → Hook / GeneratorKick / carry pickup, survivor → Sabotage
|
||||
interactListener.setOnKillerSneak((player, isSneaking) -> {
|
||||
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
||||
if (bp == null) return;
|
||||
if (bp.isKiller()) {
|
||||
Killer killer = (Killer) bp;
|
||||
if (isSneaking) {
|
||||
// #1: Hook carried survivor if near a hook
|
||||
if (killer.isCarrying()) {
|
||||
for (BasePlayer other : session.getPlayers().values()) {
|
||||
if (!other.isKiller() && other.getState() == PlayerState.CARRIED) {
|
||||
Survivor carried = (Survivor) other;
|
||||
if (hookManager.tryHookSurvivor(carried, player.getLocation())) {
|
||||
killer.setCarrying(false);
|
||||
Hook nearest = hookManager.findNearestOccupiedHook(player.getLocation(), 5.0);
|
||||
if (nearest != null) {
|
||||
Player vp = carried.getPlayer();
|
||||
if (vp != null) vp.teleport(nearest.getLocation());
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// #2: Double-sneak to pickup downed survivor
|
||||
long now = System.currentTimeMillis();
|
||||
Long last = killerLastSneakMs.get(player.getUniqueId());
|
||||
if (last != null && now - last < 450 && !killer.isCarrying()) {
|
||||
Survivor target = damageSystem.getPlayerManager().getNearestSurvivorInState(
|
||||
player, PlayerState.DOWNED, 3.0);
|
||||
if (target != null) {
|
||||
damageSystem.getKillerController().tryPickup(killer, target);
|
||||
}
|
||||
}
|
||||
killerLastSneakMs.put(player.getUniqueId(), now);
|
||||
generatorKick.startCharging(killer);
|
||||
} else {
|
||||
generatorKick.stopCharging(killer.getUuid());
|
||||
}
|
||||
} else {
|
||||
Survivor surv = (Survivor) bp;
|
||||
if (surv.getState() == PlayerState.HOOKED) {
|
||||
// Hook recovery is handled elsewhere
|
||||
} else {
|
||||
if (isSneaking) hookSabotage.startSabotage(surv);
|
||||
else hookSabotage.stopSabotage(surv.getUuid());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Generator repair
|
||||
interactListener.setOnGeneratorInteract((player, action) -> {
|
||||
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
||||
if (bp == null || bp.isKiller()) return;
|
||||
if (generatorRepair == null) return;
|
||||
|
||||
var genManager = session.getGeneratorManager();
|
||||
if (genManager == null) return;
|
||||
double range = session.getConfig().getGeneratorInteractionRange();
|
||||
var generator = genManager.getNearestGenerator(player.getLocation(), range);
|
||||
if (generator != null) {
|
||||
generatorRepair.startRepair(player, generator);
|
||||
}
|
||||
});
|
||||
|
||||
// Chest
|
||||
interactListener.setOnChestInteract((player, ignored) -> {
|
||||
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
||||
if (bp == null || bp.isKiller()) return;
|
||||
var chest = chestManager.getNearestChest(player.getLocation(), 3.0);
|
||||
if (chest != null) chestOpening.startOpening(player, chest);
|
||||
});
|
||||
|
||||
// Healing: survivor sneaks near injured/downed survivor
|
||||
interactListener.setOnHealSneak((healer, target) -> {
|
||||
SurvivorController controller = survivorControllers.get(healer.getUniqueId());
|
||||
if (controller != null) {
|
||||
controller.onHealAttempt(target);
|
||||
}
|
||||
});
|
||||
|
||||
// #11: Carried survivor shift-spam to escape from killer
|
||||
interactListener.setOnCarriedShift((player, isSneaking) -> {
|
||||
if (!isSneaking) return;
|
||||
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
||||
if (bp == null || bp.isKiller()) return;
|
||||
Survivor survivor = (Survivor) bp;
|
||||
if (survivor.getState() != PlayerState.CARRIED) return;
|
||||
damageSystem.getKillerController().getCarry().onSurvivorShift(survivor.getUuid());
|
||||
});
|
||||
|
||||
// Gate (uses hatch callback - triggered on PORTAL/HOPPER interaction)
|
||||
interactListener.setOnHatchInteract((player, ignored) -> {
|
||||
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
||||
if (bp == null || bp.isKiller()) return;
|
||||
Survivor survivor = (Survivor) bp;
|
||||
ExitGate gate = gateManager.getGateAt(player.getLocation(), 3.0);
|
||||
if (gate != null && !gate.isOpen() && gateOpening != null) {
|
||||
gateOpening.tryStartOpening(survivor, session.getPlugin());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tick all survivor controllers (healing, movement, etc.)
|
||||
*/
|
||||
public void tickSurvivors() {
|
||||
for (SurvivorController controller : survivorControllers.values()) {
|
||||
controller.tick();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all listener callbacks.
|
||||
*/
|
||||
public void clear() {
|
||||
survivorControllers.clear();
|
||||
if (moveListener != null) moveListener.setOnSurvivorMove(null);
|
||||
if (interactListener != null) {
|
||||
interactListener.setOnRescueAttempt(null);
|
||||
interactListener.setOnChestInteract(null);
|
||||
interactListener.setOnAttack(null);
|
||||
interactListener.setOnKillerSneak(null);
|
||||
interactListener.setOnHealSneak(null);
|
||||
interactListener.setOnCarriedShift(null);
|
||||
interactListener.setOnGeneratorInteract(null);
|
||||
interactListener.setOnHatchInteract(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue