Skip to content

Commit

Permalink
Merge pull request #94 from TheNextLvl-net/movement-handling
Browse files Browse the repository at this point in the history
Improve movement handling logic for players and entities
  • Loading branch information
NonSwag authored Nov 18, 2024
2 parents c884054 + 4dc13b6 commit 183670c
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 183670c

Please sign in to comment.