Skip to content

Commit

Permalink
Improve movement handling logic for players and entities
Browse files Browse the repository at this point in the history
Refactor movement handling to a generic method for players and entities, improving consistency across various movement events. The change simplifies the event handling flow and ensures that protection checks are consistently applied to teleports, entity movements, and vehicle movements.
  • Loading branch information
NonSwag committed Nov 18, 2024
1 parent 7a13024 commit 4dc13b6
Showing 1 changed file with 57 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package net.thenextlvl.protect.listener;

import io.papermc.paper.event.entity.EntityMoveEvent;
import lombok.RequiredArgsConstructor;
import net.thenextlvl.protect.ProtectPlugin;
import net.thenextlvl.protect.area.Area;
import net.thenextlvl.protect.area.event.player.PlayerAreaEnterEvent;
import net.thenextlvl.protect.area.event.player.PlayerAreaLeaveEvent;
import net.thenextlvl.protect.area.event.player.PlayerAreaTransitionEvent;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
Expand All @@ -14,53 +18,78 @@
import org.bukkit.event.vehicle.VehicleEnterEvent;
import org.bukkit.event.vehicle.VehicleMoveEvent;

import java.util.List;
import java.util.stream.Stream;

@RequiredArgsConstructor
public class MovementListener implements Listener {
private final ProtectPlugin plugin;

@SuppressWarnings("IsCancelled")
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent event) {
onPlayerMove(event);
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPlayerMove(PlayerMoveEvent event) {
if (!event.hasChangedBlock()) return;
Stream.concat(plugin.areaProvider().getAreas(event.getFrom()), plugin.areaProvider().getAreas(event.getTo()))
.forEach(area -> {
if (!area.contains(event.getFrom()) && area.contains(event.getTo())) {
event.setCancelled(!new PlayerAreaEnterEvent(event.getPlayer(), area).callEvent());
} else if (area.contains(event.getFrom()) && !area.contains(event.getTo())) {
event.setCancelled(!new PlayerAreaLeaveEvent(event.getPlayer(), area).callEvent());
}
});
if (event.isCancelled()) return;
var from = plugin.areaProvider().getArea(event.getFrom());
var to = plugin.areaProvider().getArea(event.getTo());
if (from.equals(to)) return;
event.setCancelled(!new PlayerAreaTransitionEvent(event.getPlayer(), from, to).callEvent());
if (canMove(event.getPlayer(), event.getFrom(), event.getTo())) return;
event.getFrom().setPitch(event.getTo().getPitch());
event.getFrom().setYaw(event.getTo().getYaw());
event.setCancelled(true);
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent event) {
onPlayerMove(event);
public void onEntityMove(EntityMoveEvent event) {
if (!event.hasChangedBlock()) return;
if (canMove(event.getEntity(), event.getFrom(), event.getTo())) return;
event.getFrom().setPitch(event.getTo().getPitch());
event.getFrom().setYaw(event.getTo().getYaw());
event.setCancelled(true);
}

@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onVehicleEnter(VehicleEnterEvent event) {
if (!(event.getEntered() instanceof Player player)) return;
var movement = new PlayerMoveEvent(player, player.getLocation(), event.getVehicle().getLocation());
onPlayerMove(movement);
event.setCancelled(movement.isCancelled());
if (canMove(player, player.getLocation(), event.getVehicle().getLocation())) return;
event.setCancelled(true);
}

@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onVehicleEnter(VehicleMoveEvent event) {
List.copyOf(event.getVehicle().getPassengers()).stream()
.filter(entity -> entity instanceof Player)
.forEach(entity -> {
var movement = new PlayerMoveEvent((Player) entity, event.getFrom(), event.getTo());
onPlayerMove(movement);
if (movement.isCancelled()) event.getVehicle().removePassenger(entity);
});
public void onVehicleMove(VehicleMoveEvent event) {
if (canMove(event.getVehicle(), event.getFrom(), event.getTo())) return;
event.getVehicle().teleportAsync(event.getFrom());
}

private boolean canMove(Entity entity, Location from, Location to) {
return Stream.concat(
plugin.areaProvider().getAreas(from),
plugin.areaProvider().getAreas(to)
).distinct().allMatch(area -> {
if (!area.contains(from) && area.contains(to)) return canEnter(entity, from, to, area);
if (area.contains(from) && !area.contains(to)) return canLeave(entity, from, to, area);
return true;
});

}

private boolean canEnter(Entity entity, Location from, Location to, Area area) {
return (entity instanceof Player player
&& new PlayerAreaEnterEvent(player, area).callEvent()
&& canTransition(player, from, to))
|| plugin.protectionService().canEnter(entity, area);
}

private boolean canLeave(Entity entity, Location from, Location to, Area area) {
return (entity instanceof Player player
&& new PlayerAreaLeaveEvent(player, area).callEvent()
&& canTransition(player, from, to))
|| plugin.protectionService().canLeave(entity, area);
}

private boolean canTransition(Player player, Location from, Location to) {
var areaFrom = plugin.areaProvider().getArea(from);
var areaTo = plugin.areaProvider().getArea(to);

return areaFrom.equals(areaTo) || new PlayerAreaTransitionEvent(player, areaFrom, areaTo).callEvent();
}
}

0 comments on commit 4dc13b6

Please sign in to comment.