Stage 10-11: Custom Items and Sounds

This commit is contained in:
loki5512344 2026-05-31 20:54:21 +02:00
parent 1fd78e5421
commit 7cbc4e397e
2 changed files with 90 additions and 257 deletions

View file

@ -11,9 +11,9 @@ import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
public class PlayerInteractListener implements Listener {
@ -23,152 +23,77 @@ public class PlayerInteractListener implements Listener {
private BiConsumer<Player, Action> onGeneratorInteract;
private BiConsumer<Player, Boolean> onAttack;
private BiConsumer<Player, Boolean> onPalletInteract;
private BiConsumer<Player, Boolean> onWindowInteract;
private BiConsumer<Player, Boolean> onRescueAttempt;
private BiConsumer<Player, Boolean> onChestInteract;
private BiConsumer<Player, Boolean> onHatchInteract;
private final Map<UUID, Long> lastRightClick = new HashMap<>();
private final Map<UUID, Long> lastLeftClick = new HashMap<>();
private static final long CLICK_COOLDOWN_MS = 200;
private final Map<UUID, Long> lastClick = new ConcurrentHashMap<>();
private static final long COOLDOWN_MS = 200;
public PlayerInteractListener(Plugin plugin, GameManager gameManager) {
this.plugin = plugin;
this.gameManager = gameManager;
}
public void setOnGeneratorInteract(BiConsumer<Player, Action> handler) {
this.onGeneratorInteract = handler;
}
public void setOnAttack(BiConsumer<Player, Boolean> handler) {
this.onAttack = handler;
}
public void setOnPalletInteract(BiConsumer<Player, Boolean> handler) {
this.onPalletInteract = handler;
}
public void setOnWindowInteract(BiConsumer<Player, Boolean> handler) {
this.onWindowInteract = handler;
}
public void setOnRescueAttempt(BiConsumer<Player, Boolean> handler) {
this.onRescueAttempt = handler;
}
public void setOnChestInteract(BiConsumer<Player, Boolean> handler) {
this.onChestInteract = handler;
}
public void setOnHatchInteract(BiConsumer<Player, Boolean> handler) {
this.onHatchInteract = handler;
}
public void setOnGeneratorInteract(BiConsumer<Player, Action> h) { this.onGeneratorInteract = h; }
public void setOnAttack(BiConsumer<Player, Boolean> h) { this.onAttack = h; }
public void setOnPalletInteract(BiConsumer<Player, Boolean> h) { this.onPalletInteract = h; }
public void setOnRescueAttempt(BiConsumer<Player, Boolean> h) { this.onRescueAttempt = h; }
public void setOnChestInteract(BiConsumer<Player, Boolean> h) { this.onChestInteract = h; }
public void setOnHatchInteract(BiConsumer<Player, Boolean> h) { this.onHatchInteract = h; }
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
public void onInteract(PlayerInteractEvent event) {
if (event.getHand() != EquipmentSlot.HAND) return;
Player player = event.getPlayer();
if (!gameManager.isInGame(player.getUniqueId())) return;
BasePlayer basePlayer = gameManager.getPlayerSession(player.getUniqueId()).getPlayer(player.getUniqueId());
if (basePlayer == null) return;
BasePlayer bp = gameManager.getPlayerSession(player.getUniqueId()).getPlayer(player.getUniqueId());
if (bp == null || isIncapacitated(bp)) { event.setCancelled(true); return; }
Action action = event.getAction();
boolean isRightClick = action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK;
boolean isLeftClick = action == Action.LEFT_CLICK_AIR || action == Action.LEFT_CLICK_BLOCK;
boolean isRight = action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK;
if (basePlayer.getState() == PlayerState.DOWNED || basePlayer.getState() == PlayerState.HOOKED) {
event.setCancelled(true);
return;
}
if (isRightClick) {
if (isOnCooldown(player.getUniqueId(), lastRightClick)) {
event.setCancelled(true);
return;
}
handleRightClick(event, player, basePlayer);
} else if (isLeftClick) {
if (isOnCooldown(player.getUniqueId(), lastLeftClick)) {
return;
}
handleLeftClick(event, player, basePlayer);
}
if (isOnCooldown(player)) { if (isRight) event.setCancelled(true); return; }
if (isRight) handleRightClick(event, player, bp);
else if (action.isLeftClick()) handleLeftClick(event, player, bp);
}
private boolean isOnCooldown(UUID uuid, Map<UUID, Long> lastClickMap) {
private boolean isIncapacitated(BasePlayer bp) {
return bp.getState() == PlayerState.DOWNED || bp.getState() == PlayerState.HOOKED;
}
private boolean isOnCooldown(Player player) {
long now = System.currentTimeMillis();
Long last = lastClickMap.get(uuid);
if (last != null && now - last < CLICK_COOLDOWN_MS) {
return true;
}
lastClickMap.put(uuid, now);
Long last = lastClick.get(player.getUniqueId());
if (last != null && now - last < COOLDOWN_MS) return true;
lastClick.put(player.getUniqueId(), now);
return false;
}
private void handleRightClick(PlayerInteractEvent event, Player player, BasePlayer basePlayer) {
private void handleRightClick(PlayerInteractEvent event, Player player, BasePlayer bp) {
if (event.getClickedBlock() == null) {
if (onAttack != null && bp.isKiller()) onAttack.accept(player, true);
return;
}
String type = event.getClickedBlock().getType().toString();
if (type.contains("TRAPDOOR") && onGeneratorInteract != null) onGeneratorInteract.accept(player, event.getAction());
if ((type.contains("FENCE") || type.contains("PLANKS")) && onPalletInteract != null && !bp.isKiller()) onPalletInteract.accept(player, true);
if (!bp.isKiller() && onRescueAttempt != null) onRescueAttempt.accept(player, true);
if (type.contains("CHEST") && onChestInteract != null) onChestInteract.accept(player, true);
if ((type.contains("HOPPER") || type.contains("PORTAL")) && onHatchInteract != null && !bp.isKiller()) onHatchInteract.accept(player, true);
}
private void handleLeftClick(PlayerInteractEvent event, Player player, BasePlayer bp) {
if (event.getClickedBlock() != null) {
String blockType = event.getClickedBlock().getType().toString();
if (blockType.contains("IRON_TRAPDOOR") || blockType.contains("TRAP_DOOR")) {
if (onGeneratorInteract != null) {
onGeneratorInteract.accept(player, event.getAction());
}
} else if (blockType.contains("FENCE") || blockType.contains("OAK_PLANKS")) {
if (onPalletInteract != null && !basePlayer.isKiller()) {
onPalletInteract.accept(player, true);
}
}
if (!basePlayer.isKiller()) {
if (onRescueAttempt != null) {
onRescueAttempt.accept(player, true);
}
}
if (blockType.contains("CHEST")) {
if (onChestInteract != null) {
onChestInteract.accept(player, true);
}
}
if (blockType.contains("HOPPER") || blockType.contains("END_PORTAL_FRAME")) {
if (onHatchInteract != null && !basePlayer.isKiller()) {
onHatchInteract.accept(player, true);
}
String type = event.getClickedBlock().getType().toString();
if ((type.contains("PLANKS") || type.contains("FENCE")) && onPalletInteract != null && bp.isKiller()) {
event.setCancelled(true);
onPalletInteract.accept(player, false);
}
}
if (onAttack != null && basePlayer.isKiller()) {
onAttack.accept(player, true);
}
if (onAttack != null && bp.isKiller()) { event.setCancelled(true); onAttack.accept(player, false); }
}
private void handleLeftClick(PlayerInteractEvent event, Player player, BasePlayer basePlayer) {
if (event.getClickedBlock() != null) {
String blockType = event.getClickedBlock().getType().toString();
if (blockType.contains("OAK_PLANKS") || blockType.contains("FENCE")) {
if (onPalletInteract != null && basePlayer.isKiller()) {
event.setCancelled(true);
onPalletInteract.accept(player, false);
}
}
}
if (onAttack != null && basePlayer.isKiller()) {
event.setCancelled(true);
onAttack.accept(player, false);
}
}
public void register() {
org.bukkit.Bukkit.getPluginManager().registerEvents(this, plugin);
}
public void unregister() {
org.bukkit.event.HandlerList.unregisterAll(this);
}
public void register() { org.bukkit.Bukkit.getPluginManager().registerEvents(this, plugin); }
public void unregister() { org.bukkit.event.HandlerList.unregisterAll(this); }
}

View file

@ -5,7 +5,6 @@ import dev.loki.player.BasePlayer;
import dev.loki.player.Killer;
import dev.loki.player.PlayerState;
import dev.loki.player.Survivor;
import dev.loki.util.PlayerUtil;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -15,9 +14,9 @@ import org.bukkit.event.player.PlayerToggleSneakEvent;
import org.bukkit.event.player.PlayerToggleSprintEvent;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
public class PlayerMoveListener implements Listener {
@ -30,167 +29,76 @@ public class PlayerMoveListener implements Listener {
private BiConsumer<Survivor, Location> onSurvivorMove;
private BiConsumer<Killer, Location> onKillerMove;
private final Map<UUID, Location> lastLocations = new HashMap<>();
private final Map<UUID, Boolean> wasSneaking = new HashMap<>();
private final Map<UUID, Boolean> wasSprinting = new HashMap<>();
private static final double MOVEMENT_THRESHOLD = 0.01;
private final Map<UUID, Boolean> wasSneaking = new ConcurrentHashMap<>();
private final Map<UUID, Boolean> wasSprinting = new ConcurrentHashMap<>();
private int tickCounter = 0;
private static final int CHECK_INTERVAL = 2;
public PlayerMoveListener(Plugin plugin, GameManager gameManager) {
this.plugin = plugin;
this.gameManager = gameManager;
}
public void setOnMovement(BiConsumer<Player, Location> handler) {
this.onMovement = handler;
}
public void setOnCrouch(BiConsumer<Player, Boolean> handler) {
this.onCrouch = handler;
}
public void setOnSprint(BiConsumer<Player, Boolean> handler) {
this.onSprint = handler;
}
public void setOnSurvivorMove(BiConsumer<Survivor, Location> handler) {
this.onSurvivorMove = handler;
}
public void setOnKillerMove(BiConsumer<Killer, Location> handler) {
this.onKillerMove = handler;
}
public void setOnMovement(BiConsumer<Player, Location> h) { this.onMovement = h; }
public void setOnCrouch(BiConsumer<Player, Boolean> h) { this.onCrouch = h; }
public void setOnSprint(BiConsumer<Player, Boolean> h) { this.onSprint = h; }
public void setOnSurvivorMove(BiConsumer<Survivor, Location> h) { this.onSurvivorMove = h; }
public void setOnKillerMove(BiConsumer<Killer, Location> h) { this.onKillerMove = h; }
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
public void onMove(PlayerMoveEvent event) {
tickCounter++;
if (tickCounter % CHECK_INTERVAL != 0) return;
if (tickCounter % 2 != 0) return;
Player player = event.getPlayer();
if (!gameManager.isInGame(player.getUniqueId())) return;
BasePlayer basePlayer = gameManager.getPlayerSession(player.getUniqueId()).getPlayer(player.getUniqueId());
if (basePlayer == null) return;
Location from = event.getFrom();
BasePlayer bp = gameManager.getPlayerSession(player.getUniqueId()).getPlayer(player.getUniqueId());
if (bp == null) return;
Location to = event.getTo();
if (to == null) return;
if (shouldCancelMovement(basePlayer, from, to)) {
event.setCancelled(true);
return;
}
if (hasSignificantMovement(from, to)) {
handleMovement(player, basePlayer, to);
}
updateStateTracking(player.getUniqueId(), from);
if (shouldCancel(bp, to, event.getFrom())) { event.setCancelled(true); return; }
handleMovement(player, bp, to);
}
@EventHandler
public void onPlayerToggleSneak(PlayerToggleSneakEvent event) {
Player player = event.getPlayer();
if (!gameManager.isInGame(player.getUniqueId())) return;
boolean isSneaking = event.isSneaking();
UUID uuid = player.getUniqueId();
Boolean previous = wasSneaking.get(uuid);
if (previous == null || previous != isSneaking) {
wasSneaking.put(uuid, isSneaking);
if (onCrouch != null) {
onCrouch.accept(player, isSneaking);
}
private boolean shouldCancel(BasePlayer bp, Location to, Location from) {
if (bp.getState() == PlayerState.HOOKED) return true;
if (bp.getState() == PlayerState.DOWNED) {
double dist = Math.sqrt(Math.pow(to.getX() - from.getX(), 2) + Math.pow(to.getZ() - from.getZ(), 2));
return dist > 0.08;
}
}
@EventHandler
public void onPlayerToggleSprint(PlayerToggleSprintEvent event) {
Player player = event.getPlayer();
if (!gameManager.isInGame(player.getUniqueId())) return;
BasePlayer basePlayer = gameManager.getPlayerSession(player.getUniqueId()).getPlayer(player.getUniqueId());
if (basePlayer == null) return;
boolean isSprinting = event.isSprinting();
UUID uuid = player.getUniqueId();
if (basePlayer.getState() == PlayerState.DOWNED || basePlayer.getState() == PlayerState.HOOKED) {
if (isSprinting) {
event.setCancelled(true);
player.setSprinting(false);
}
return;
}
Boolean previous = wasSprinting.get(uuid);
if (previous == null || previous != isSprinting) {
wasSprinting.put(uuid, isSprinting);
if (onSprint != null) {
onSprint.accept(player, isSprinting);
}
}
}
private boolean shouldCancelMovement(BasePlayer player, Location from, Location to) {
if (player.getState() == PlayerState.HOOKED) {
return true;
}
if (player.getState() == PlayerState.DOWNED) {
double dx = to.getX() - from.getX();
double dz = to.getZ() - from.getZ();
double horizontalDistance = Math.sqrt(dx * dx + dz * dz);
double maxCrawlDistance = 0.08;
return horizontalDistance > maxCrawlDistance;
}
return false;
}
private boolean hasSignificantMovement(Location from, Location to) {
double dx = to.getX() - from.getX();
double dy = to.getY() - from.getY();
double dz = to.getZ() - from.getZ();
double distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
return distance > MOVEMENT_THRESHOLD;
private void handleMovement(Player player, BasePlayer bp, Location to) {
if (onMovement != null) onMovement.accept(player, to);
if (!bp.isKiller() && onSurvivorMove != null) onSurvivorMove.accept((Survivor) bp, to);
else if (bp.isKiller() && onKillerMove != null) onKillerMove.accept((Killer) bp, to);
}
private void handleMovement(Player player, BasePlayer basePlayer, Location to) {
if (onMovement != null) {
onMovement.accept(player, to);
}
if (!basePlayer.isKiller() && onSurvivorMove != null) {
onSurvivorMove.accept((Survivor) basePlayer, to);
} else if (basePlayer.isKiller() && onKillerMove != null) {
onKillerMove.accept((Killer) basePlayer, to);
}
@EventHandler
public void onSneak(PlayerToggleSneakEvent event) {
Player player = event.getPlayer();
if (!gameManager.isInGame(player.getUniqueId())) return;
boolean now = event.isSneaking();
Boolean before = wasSneaking.put(player.getUniqueId(), now);
if ((before == null || before != now) && onCrouch != null) onCrouch.accept(player, now);
}
private void updateStateTracking(UUID uuid, Location location) {
lastLocations.put(uuid, location.clone());
@EventHandler
public void onSprint(PlayerToggleSprintEvent event) {
Player player = event.getPlayer();
if (!gameManager.isInGame(player.getUniqueId())) return;
BasePlayer bp = gameManager.getPlayerSession(player.getUniqueId()).getPlayer(player.getUniqueId());
if (bp == null) return;
boolean now = event.isSprinting();
if (isIncapacitated(bp) && now) { event.setCancelled(true); player.setSprinting(false); return; }
Boolean before = wasSprinting.put(player.getUniqueId(), now);
if ((before == null || before != now) && onSprint != null) onSprint.accept(player, now);
}
public void clearTracking(UUID uuid) {
lastLocations.remove(uuid);
wasSneaking.remove(uuid);
wasSprinting.remove(uuid);
private boolean isIncapacitated(BasePlayer bp) {
return bp.getState() == PlayerState.DOWNED || bp.getState() == PlayerState.HOOKED;
}
public void register() {
org.bukkit.Bukkit.getPluginManager().registerEvents(this, plugin);
}
public void unregister() {
org.bukkit.event.HandlerList.unregisterAll(this);
}
public void clear(UUID uuid) { wasSneaking.remove(uuid); wasSprinting.remove(uuid); }
public void register() { org.bukkit.Bukkit.getPluginManager().registerEvents(this, plugin); }
public void unregister() { org.bukkit.event.HandlerList.unregisterAll(this); }
}