diff --git a/Plugins/Mineplex.Core/src/mineplex/core/game/nano/NanoDisplay.java b/Plugins/Mineplex.Core/src/mineplex/core/game/nano/NanoDisplay.java index 09d7f8889..3465f8df9 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/game/nano/NanoDisplay.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/game/nano/NanoDisplay.java @@ -32,6 +32,7 @@ public enum NanoDisplay implements Display SPLEEF(20, "AAAAAAAA! Spleef", Material.DIAMOND_SPADE), SPLOOR(21, "Sploor", Material.DIAMOND_BARDING), TERRITORY(22, "Slime Territory", Material.MONSTER_EGG, UtilEnt.getEntityEggData(EntityType.SLIME)), + MINEKART(23, "MineKart", Material.COMMAND_MINECART), ; public static NanoDisplay getFromId(int gameId) diff --git a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/GameType.java b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/GameType.java index 1d845b54c..b88b455aa 100644 --- a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/GameType.java +++ b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/GameType.java @@ -16,6 +16,7 @@ import mineplex.game.nano.game.games.hotpotato.HotPotato; import mineplex.game.nano.game.games.jumprope.JumpRope; import mineplex.game.nano.game.games.kingslime.KingSlime; import mineplex.game.nano.game.games.microbattle.MicroBattle; +import mineplex.game.nano.game.games.minekart.MineKart; import mineplex.game.nano.game.games.mobfarm.MobFarm; import mineplex.game.nano.game.games.musicminecart.MusicMinecarts; import mineplex.game.nano.game.games.oits.SnowballTrouble; @@ -52,7 +53,8 @@ public enum GameType PARKOUR(Parkour.class, NanoDisplay.PARKOUR), BAWK_BAWK(BawkBawk.class, NanoDisplay.BAWK_BAWK), QUICK(Quick.class, NanoDisplay.QUICK), - DROPPER(Dropper.class, NanoDisplay.DROPPER); + DROPPER(Dropper.class, NanoDisplay.DROPPER), + MINEKART(MineKart.class, NanoDisplay.MINEKART); private static String maps() { diff --git a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/Kart.java b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/Kart.java new file mode 100644 index 000000000..8ec6184df --- /dev/null +++ b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/Kart.java @@ -0,0 +1,102 @@ +package mineplex.game.nano.game.games.minekart; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Sheep; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilEnt; + +public class Kart +{ + + private final Player _driver; + private final LivingEntity _vehicle; + + private int _lap, _lapCheckpoint, _lapKeyCheckpoint; + + private Vector _velocity; + private boolean _crashed; + + Kart(MineKart game, Player driver) + { + _driver = driver; + + _vehicle = driver.getWorld().spawn(driver.getLocation(), Sheep.class); + + UtilEnt.vegetate(_vehicle, true); + UtilEnt.ghost(_vehicle, true, false); + UtilEnt.setFakeHead(_vehicle, true); + + _lap = 1; + + _velocity = new Vector(); + + _vehicle.setPassenger(driver); + } + + public void remove() + { + _vehicle.remove(); + } + + public Player getDriver() + { + return _driver; + } + + public LivingEntity getVehicle() + { + return _vehicle; + } + + public void setLap(int lap) + { + _lap = lap; + } + + public int getLap() + { + return _lap; + } + + public void setLapCheckpoint(int lapCheckpoint) + { + _lapCheckpoint = lapCheckpoint; + } + + public int getLapCheckpoint() + { + return _lapCheckpoint; + } + + public void setLapKeyCheckpoint(int lapKeyCheckpoint) + { + _lapKeyCheckpoint = lapKeyCheckpoint; + } + + public int getLapKeyCheckpoint() + { + return _lapKeyCheckpoint; + } + + public void setVelocity(Vector velocity) + { + _velocity = velocity; + } + + public Vector getVelocity() + { + return _velocity; + } + + public void setCrashed(boolean crashed) + { + _crashed = crashed; + } + + public boolean isCrashed() + { + return _crashed; + } +} diff --git a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/KartCheckpoint.java b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/KartCheckpoint.java new file mode 100644 index 000000000..02fe9c38d --- /dev/null +++ b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/KartCheckpoint.java @@ -0,0 +1,44 @@ +package mineplex.game.nano.game.games.minekart; + +import java.util.Arrays; + +import org.bukkit.Location; + +import mineplex.core.common.util.UtilAlg; + +public class KartCheckpoint +{ + + private final Location _cornerA, _cornerB; + private final int _index; + private final boolean _key; + + KartCheckpoint(Location cornerA, Location cornerB, int index, boolean key) + { + _cornerA = cornerA; + _cornerB = cornerB; + _index = index; + _key = key; + } + + public boolean isInBox(Location location) + { + return UtilAlg.inBoundingBox(location, _cornerA, _cornerB); + } + + public Location getCenter() + { + return UtilAlg.getAverageLocation(Arrays.asList(_cornerA, _cornerB)); + } + + public int getIndex() + { + return _index; + } + + public boolean isKey() + { + return _key; + } + +} diff --git a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/KartController.java b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/KartController.java new file mode 100644 index 000000000..cf62f4e12 --- /dev/null +++ b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/KartController.java @@ -0,0 +1,73 @@ +package mineplex.game.nano.game.games.minekart; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.util.Vector; + +public class KartController +{ + + void applyAirDrag(Kart kart) + { + Vector velocity = kart.getVelocity().multiply(0.96); + + if (velocity.length() < 0.05) + { + velocity.multiply(0); + } + } + + void collideBlock(Kart kart) + { + Location location = kart.getVehicle().getLocation().add(0, 0.5, 0); + + if (location.getBlock().getType() != Material.AIR) + { + kart.getVelocity().multiply(-0.5); + kart.getVelocity().setY(0.5); + kart.setCrashed(true); + } + } + + void accelerate(Kart kart) + { + if (kart.isCrashed()) + { + return; + } + + Vector velocity = kart.getVelocity(); + Vector player = kart.getDriver().getLocation().getDirection().setY(0).multiply(0.04); + + if (velocity.lengthSquared() == 0) + { + velocity = player; + + if (velocity.lengthSquared() == 0) + { + return; + } + + kart.setVelocity(velocity); + } + + velocity.add(player); + } + + void applyTopSpeed(Kart kart) + { + if (kart.isCrashed()) + { + return; + } + + Vector velocity = kart.getVelocity(); + + if (velocity.length() > 1) + { + kart.setVelocity(velocity.clone() + .setY(0) + .normalize()); + } + } +} diff --git a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/MineKart.java b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/MineKart.java new file mode 100644 index 000000000..b32296b80 --- /dev/null +++ b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/MineKart.java @@ -0,0 +1,245 @@ +package mineplex.game.nano.game.games.minekart; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.nano.NanoManager; +import mineplex.game.nano.game.GameType; +import mineplex.game.nano.game.SoloGame; +import mineplex.game.nano.game.event.PlayerGameApplyEvent; +import mineplex.game.nano.game.event.PlayerGameRespawnEvent; +import mineplex.game.nano.game.event.PlayerStateChangeEvent; + +public class MineKart extends SoloGame +{ + + private int _spawnIndex; + + private final List _checkpoints, _keyCheckpoints; + private Location _faceLocation; + + private final Map _karts; + private final KartController _controller; + + public MineKart(NanoManager manager) + { + super(manager, GameType.MINEKART, new String[] + { + "#BringBackMineKart" + }); + + _checkpoints = new ArrayList<>(); + _keyCheckpoints = new ArrayList<>(); + _karts = new HashMap<>(); + _controller = new KartController(); + + _teamComponent.setAdjustSpawnYaw(false); + + _damageComponent.setDamage(false); + } + + @Override + protected void parseData() + { + _mineplexWorld.getSpongeLocations().forEach((key, locations) -> + { + if (!key.startsWith("CP") || locations.size() < 2) + { + return; + } + + String[] args = key.split(" "); + int index; + + try + { + index = Integer.parseInt(args[1]); + } + catch (NumberFormatException ex) + { + ex.printStackTrace(); + return; + } + + KartCheckpoint checkpoint = new KartCheckpoint(locations.get(0), locations.get(1), index, args.length > 2); + + _checkpoints.add(checkpoint); + + if (checkpoint.isKey()) + { + _keyCheckpoints.add(checkpoint); + } + }); + + _faceLocation = getCheckpoint(0).getCenter(); + + _playersTeam.getSpawns().sort(Comparator.comparingDouble(o -> UtilMath.offsetSquared(o, _faceLocation))); + _keyCheckpoints.sort(Comparator.comparingInt(KartCheckpoint::getIndex)); + } + + @Override + public void disable() + { + _checkpoints.clear(); + } + + @EventHandler + public void playerApply(PlayerGameApplyEvent event) + { + Location location = _playersTeam.getSpawns().get(_spawnIndex); + location.setYaw((Math.round(UtilAlg.GetYaw(UtilAlg.getTrajectory(location, _faceLocation)) / 90F) & 0x3) * 90F); + event.setRespawnLocation(location); + + _spawnIndex = (_spawnIndex + 1) % _playersTeam.getSpawns().size(); + } + + @EventHandler + public void playerRespawn(PlayerGameRespawnEvent event) + { + Player player = event.getPlayer(); + + _manager.runSyncLater(() -> + { + _worldComponent.setCreatureAllowOverride(true); + + Kart kart = new Kart(this, player); + _karts.put(player, kart); + + player.getInventory().addItem(new ItemStack(Material.STONE_SWORD)); + + _worldComponent.setCreatureAllowOverride(false); + }, 1); + } + + @EventHandler + public void updateKartControl(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK || !isLive()) + { + return; + } + + _karts.forEach((player, kart) -> + { + LivingEntity vehicle = kart.getVehicle(); + + if (vehicle.getPassenger() == null || !vehicle.getPassenger().equals(player)) + { + vehicle.setPassenger(player); + } + + Location location = vehicle.getLocation(); + KartCheckpoint checkpoint = getCheckpoint(location); + + if (checkpoint != null) + { + player.sendMessage("Lap node = " + checkpoint.getIndex()); + kart.setLapCheckpoint(checkpoint.getIndex()); + + if (checkpoint.isKey()) + { + int keyIndex = _keyCheckpoints.indexOf(checkpoint); + + player.sendMessage("Lap key node = " + keyIndex + " kart node = " + kart.getLapKeyCheckpoint()); + + if (kart.getLapKeyCheckpoint() + 1 == keyIndex) + { + kart.setLapKeyCheckpoint(keyIndex); + player.sendMessage("Lap key node = " + keyIndex + " goal = " + (_keyCheckpoints.size() - 1)); + } + } + + if (checkpoint.getIndex() == 0 && kart.getLapKeyCheckpoint() == _keyCheckpoints.size() - 1) + { + kart.setLap(kart.getLap() + 1); + kart.setLapKeyCheckpoint(0); + player.sendMessage("Lap = " + kart.getLap()); + } + } + + boolean canControl = true; + + if (kart.isCrashed()) + { + if (UtilEnt.isGrounded(kart.getVehicle())) + { + kart.setCrashed(false); + player.sendMessage("setCrashed(false)"); + } + else + { + player.sendMessage("canControl = false"); + canControl = false; + } + } + + _controller.applyAirDrag(kart); + + _controller.collideBlock(kart); + + // Accelerate + if (canControl && player.isBlocking()) + { + _controller.accelerate(kart); + _controller.applyTopSpeed(kart); + } + + double velocityLength = kart.getVelocity().length(); + +// player.sendMessage("v=" + velocityLength); + + location.add(kart.getVelocity()); + location.setDirection(kart.getVelocity()); + UtilEnt.setPosition(vehicle, location); + UtilEnt.CreatureLook(vehicle, location.getYaw()); + + location.getWorld().playSound(location, Sound.PIG_IDLE, (float) (.1 + velocityLength / 2), (float) (.5 + velocityLength)); + }); + } + + @EventHandler + public void playerOut(PlayerStateChangeEvent event) + { + if (!event.isAlive()) + { + Kart kart = _karts.remove(event.getPlayer()); + + if (kart != null) + { + kart.remove(); + } + } + } + + public KartCheckpoint getCheckpoint(int index) + { + return _checkpoints.stream() + .filter(checkpoint -> checkpoint.getIndex() == index) + .findFirst() + .orElse(null); + } + + public KartCheckpoint getCheckpoint(Location location) + { + return _checkpoints.stream() + .filter(checkpoint -> checkpoint.isInBox(location)) + .findFirst() + .orElse(null); + } +}