de59059
AKL City ยท akl-city.git
Branches > main > de59059 > files
Clean up Minecarts.java
Commit: de59059babb0f64a3d844549515d45587756fd72
Parent: 09ec71f
1 changed file:
src/main/java/dev/grahp/aklcity/Minecarts.java view file
@@ -2,96 +2,52 @@ import static dev.grahp.aklcity.PlayerUtils.isHoldingFist; -import org.bukkit.event.Listener;-import org.bukkit.event.EventHandler;-import org.bukkit.Material;-import org.bukkit.Location;+import org.bukkit.*;+import org.bukkit.event.*;+import org.bukkit.event.vehicle.*;+import org.bukkit.event.player.PlayerInteractEvent;+import org.bukkit.event.block.Action; import org.bukkit.block.Block;-import org.bukkit.entity.Minecart;-import org.bukkit.entity.Vehicle;-import org.bukkit.entity.Player;-import org.bukkit.event.vehicle.VehicleMoveEvent;-import org.bukkit.util.Vector;-import org.bukkit.Bukkit; import org.bukkit.block.data.Powerable;-import java.util.HashSet;-import java.util.Set;-import java.util.UUID;-import java.util.Map;-import java.util.HashMap;+import org.bukkit.entity.*;+import org.bukkit.util.Vector; import org.bukkit.scheduler.BukkitTask; +import java.util.*;+ import net.kyori.adventure.text.Component; -import org.bukkit.World;--import org.bukkit.event.vehicle.VehicleExitEvent;-import org.bukkit.event.vehicle.VehicleEnterEvent;--import org.bukkit.event.player.PlayerInteractEvent;-import org.bukkit.event.block.Action; // TODO: // - Stops mobs from pathfinding onto rails? Or... Just kill them when they do smiemsie, keep momentum+// Somehow tell whether the player is going the wrong way? public class Minecarts implements Listener {+ private static final Material stopperRailMaterial = Material.DETECTOR_RAIL;+ private static final long timeToWaitForMinecartsToBeKilledAfterBeingDismounted = 5L;+ private static final double minecartVelocityThreshold = 0.001;+ private static final long ticksToStopAtStops = 20L;+ private static final long extraTicksToDismountAfterDeparting = 10L; - // Returns a safe place to dismount the player if there is one, or just the normal position a player would dismount a minecart from.- private Location findSafeDismount(Minecart cart) {- Location base = cart.getLocation();- World world = base.getWorld();-- // for (int dx = -2; dx <= 2; dx++) {- // for (int dz = -2; dz <= 2; dz++) {- //- // Location feet = base.clone().add(dx, 0, dz);- //- // Block ground = feet.clone().subtract(0, 1, 0).getBlock();- // Block feetBlock = feet.getBlock();- // Block headBlock = feet.clone().add(0, 1, 0).getBlock();- //- // boolean solidGround = ground.getType().isSolid();- // boolean clear = feetBlock.isPassable() && headBlock.isPassable();- // boolean notRail =- // !feetBlock.getType().toString().endsWith("RAIL") &&- // !ground.getType().toString().endsWith("RAIL");- //- // if (solidGround && clear && notRail) {- // return feet.add(0.5, 0, 0.5);- // }- // }- // }- //- // Bukkit.broadcastMessage("choosing default");- return base;+ /// Returns whether a player is in a Minecart+ private boolean isPlayerInMinecart(Minecart cart) {+ return !cart.getPassengers().isEmpty() && cart.getPassengers().get(0) instanceof Player; } - private Player playerInMinecart(Minecart cart) {- if (!cart.getPassengers().isEmpty() && cart.getPassengers().get(0) instanceof Player p) {- return p;- }- return null;- }-+ // TODO should find a safe point to dismount the player and tp them there private void dismount(Minecart cart) { cart.eject();- // var p = playerInMinecart(cart);- // if (p != null) {- // p.teleport(findSafeDismount(cart));- // } } private void killMinecart(Minecart cart) { dismount(cart);- Timers.schedule(5L, () -> {+ Timers.schedule(timeToWaitForMinecartsToBeKilledAfterBeingDismounted, () -> { if (!cart.isDead()) { cart.remove(); } }); } - private static final Material stopperRailMaterial = Material.DETECTOR_RAIL;- /// Returns whether a Minecart is on top of a rail that it should slow down and allow the player to exit for private boolean isOnStopperRail(Minecart cart) { return cart.getLocation().getBlock().getType() == stopperRailMaterial;@@ -99,97 +55,99 @@ /// Returns whether a Minecart is stopped, or moving so slow that it's basically not moving at all private boolean isCartStopped(Minecart cart) {- return cart.getVelocity().lengthSquared() < 0.001;+ return cart.getVelocity().lengthSquared() < minecartVelocityThreshold; } @EventHandler public void onEnterMinecart(VehicleEnterEvent e) { if (e.getVehicle() instanceof Minecart && e.getEntered() instanceof Player p) {+ // Needs to be delayed a tick to override the normal message Timers.runNextTick(() -> {- p.sendActionBar(- Component.text("Press ")- .append(Component.keybind("key.sneak"))- .append(Component.text(" to exit at the next stop"))- );+ p.sendActionBar(+ Component.text("Press ")+ .append(Component.keybind("key.sneak"))+ .append(Component.text(" to exit at the next stop"))+ ); }); } } - private static Map<UUID, Location> stopLocations = new HashMap();- @EventHandler- public void onExitMinecart(VehicleExitEvent e) {+ public void onExitingMinecart(VehicleExitEvent e) { if (e.getVehicle() instanceof Minecart cart && cart.getPassengers().get(0) instanceof Player p) {- if (isOnStopperRail(cart) || isCartStopped(cart)) {+ if (isCartStopped(cart)) { killMinecart(cart);- } else if (stopLocations.containsKey(p.getUniqueId())) {- // TODO looks similar to killMinecart...- cart.eject();- cart.remove();- p.teleport(stopLocations.get(p.getUniqueId()));+ if (stopLocations.containsKey(cart)) {+ p.teleport(stopLocations.get(cart));+ } } else { e.setCancelled(true); p.sendActionBar(Component.text("You may only exit at a stop!")); }- stopLocations.remove(p.getUniqueId());+ stopLocations.remove(cart); } } - // Called once when a Minecart enters a stop- public BukkitTask onEnterStop(Minecart cart) {- var p = playerInMinecart(cart);- if (p == null) {- killMinecart(cart);- return null;- } else {- var velocity = cart.getVelocity().clone();- cart.setVelocity(new Vector(0, 0, 0));- var puuid = p.getUniqueId();- stopLocations.put(puuid, cart.getLocation());+ private Map<Minecart, Location> stopLocations = new HashMap();+ private Map<Minecart, Vector> previousSpeeds = new HashMap();+ private Set<Minecart> cartsAtStops = new HashSet(); - var task = Timers.schedule(20L, () -> {- if (!cart.isDead() && cart.isValid()) {- cart.setVelocity(velocity.normalize().multiply(0.4));- }+ private enum StopType {+ NORMAL, // Waited for the minecart to stop at its stop and then continue on+ SKIPPED // Manually pressed W to move on to the next stop+ }++ /// Departs the Minecart from the stop it's stopped at.+ /// When called after a cart has already departed, does nothing.+ /// After a delay, a stopped minecart will automatically go forward,+ /// but the player may choose to do this manually. When skipping a stop,+ /// extra leeway is not given to allow the player to exit the stop after the+ /// cart has resumed motion.+ private void departFromStop(Minecart cart, StopType type) {+ if (!cart.isDead() && cart.isValid() && cartsAtStops.contains(cart) && previousSpeeds.containsKey(cart)) {+ cart.setVelocity(previousSpeeds.get(cart).normalize().multiply(0.4));+ }+ switch (type) {+ case NORMAL -> Timers.schedule(extraTicksToDismountAfterDeparting, () -> {+ stopLocations.remove(cart); });- // TODO also need to clear the stop when the player chooses to go forwards on their own- Timers.schedule(30L, () -> {- stopLocations.remove(puuid); // Could clear the wrong thing?- });- return task;+ case SKIPPED -> stopLocations.remove(cart); }+ previousSpeeds.remove(cart); } - private static Set<UUID> cartsAtStops = new HashSet();- private static Map<UUID, BukkitTask> tasks = new HashMap();+ public void onEnterStop(Minecart cart) {+ if (!isPlayerInMinecart(cart)) {+ killMinecart(cart);+ } else {+ cartsAtStops.add(cart);+ previousSpeeds.put(cart, cart.getVelocity().clone());+ stopLocations.put(cart, cart.getLocation());+ cart.setVelocity(new Vector(0, 0, 0));++ Timers.schedule(ticksToStopAtStops, () -> {+ departFromStop(cart, StopType.NORMAL);+ });+ }+ } // TODO Being block-based has the fundamental problem that travelling too fast can cause you to skip over a block entirely @EventHandler public void onMove(VehicleMoveEvent e) {- if (e.getVehicle() instanceof Minecart cart && cart.getPassengers().get(0) instanceof Player p) {- var uuid = cart.getUniqueId();- if (isOnStopperRail(cart)) {- if (cartsAtStops.contains(uuid)) {- // If you're moving forward, resume velocity.- // TODO Extract this and the task above yeag- if (cart.getVelocity().lengthSquared() > 0) {- tasks.get(uuid).cancel();- // Only runninng after the timer has been set...- if (!cart.isDead() && cart.isValid()) {- cart.setVelocity(cart.getVelocity().clone().normalize().multiply(0.4));- stopLocations.remove(p.getUniqueId());- }- }- } else {- var task = onEnterStop(cart);- if (task != null) {- tasks.put(uuid, task);- }- cartsAtStops.add(uuid);- }- } else {- cartsAtStops.remove(uuid);- tasks.remove(uuid);+ if (e.getVehicle() instanceof Minecart cart && isPlayerInMinecart(cart)) {+ var movingAtStop = isOnStopperRail(cart);+ var alreadyAtStop = cartsAtStops.contains(cart);++ if (movingAtStop && !alreadyAtStop) {+ onEnterStop(cart);+ }++ if (movingAtStop && alreadyAtStop) {+ departFromStop(cart, StopType.SKIPPED);+ }++ if (!movingAtStop) {+ cartsAtStops.remove(cart); } } }