From 1c1c51d5ca6327a162e9f159ef6df40b9bacf35a Mon Sep 17 00:00:00 2001 From: ruby Date: Wed, 7 Aug 2024 23:07:31 +1200 Subject: [PATCH] Start on game logic --- .../com/pobnellion/floorGame/FloorGame.java | 1 + .../floorGame/command/CommandFloorGame.java | 5 ++ .../command/TabCompleterFloorGame.java | 26 ++++--- .../com/pobnellion/floorGame/game/Floor.java | 72 +++++++++++++++++-- .../floorGame/game/GameInstance.java | 36 +++++++--- 5 files changed, 115 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/pobnellion/floorGame/FloorGame.java b/src/main/java/com/pobnellion/floorGame/FloorGame.java index 6d1afef..0089ef9 100644 --- a/src/main/java/com/pobnellion/floorGame/FloorGame.java +++ b/src/main/java/com/pobnellion/floorGame/FloorGame.java @@ -35,6 +35,7 @@ public final class FloorGame extends JavaPlugin { public static boolean StartGame() { if (gameInstance == null) { gameInstance = new GameInstance(GameConfig.LoadFromFile()); + gameInstance.Start(); return true; } diff --git a/src/main/java/com/pobnellion/floorGame/command/CommandFloorGame.java b/src/main/java/com/pobnellion/floorGame/command/CommandFloorGame.java index 9a63967..80a3f31 100644 --- a/src/main/java/com/pobnellion/floorGame/command/CommandFloorGame.java +++ b/src/main/java/com/pobnellion/floorGame/command/CommandFloorGame.java @@ -13,6 +13,11 @@ public class CommandFloorGame implements CommandExecutor { @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!sender.hasPermission("floorGame.admin")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to run this command"); + return true; + } + if (args.length == 0) return false; diff --git a/src/main/java/com/pobnellion/floorGame/command/TabCompleterFloorGame.java b/src/main/java/com/pobnellion/floorGame/command/TabCompleterFloorGame.java index 6bbce0d..6b44e2a 100644 --- a/src/main/java/com/pobnellion/floorGame/command/TabCompleterFloorGame.java +++ b/src/main/java/com/pobnellion/floorGame/command/TabCompleterFloorGame.java @@ -4,23 +4,30 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; +import org.bukkit.util.StringUtil; +import java.util.ArrayList; import java.util.List; public class TabCompleterFloorGame implements TabCompleter { @Override public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { - if (args.length == 1) - return List.of("start", "stop", "config"); - - if (!args[0].equalsIgnoreCase("config")) + if (!sender.hasPermission("floorGame.admin") || args.length == 0) return List.of(); - if (args.length == 2) - return List.of("playerJoinArea", "spectatorJoinArea", "postGameTpLocation", "floorCenter", "tileSize", + List options; + + if (args.length == 1) + options = List.of("start", "stop", "config"); + + else if (!args[0].equalsIgnoreCase("config")) + return List.of(); + + else if (args.length == 2) + options = List.of("playerJoinArea", "spectatorJoinArea", "postGameTpLocation", "floorCenter", "tileSize", "gridSize", "failLimit", "playersHaveKnockbackStick", "playersHaveFishingRod", "spectatorsCanMessWithPlayers"); - return switch (args[1]) { + else options = switch (args[1]) { case "playerJoinArea", "spectatorJoinArea" -> AreaCompleter(sender, args, 3); case "postGameTpLocation", "floorCenter" -> LocationCompleter(sender, args, 3); case "playersHaveKnockbackStick", "playersHaveFishingRod", "spectatorsCanMessWithPlayers" -> @@ -28,8 +35,7 @@ public class TabCompleterFloorGame implements TabCompleter { default -> List.of(); }; - // TODO: limit options based on current arg value - // https://www.spigotmc.org/threads/how-to-create-a-tabcompleter-for-a-command.591865/ + return StringUtil.copyPartialMatches(args[args.length - 1].toLowerCase(), options, new ArrayList<>()); } private List AreaCompleter(CommandSender sender, String[] args, int locationArgIndex) { @@ -47,8 +53,6 @@ public class TabCompleterFloorGame implements TabCompleter { if (!(sender instanceof Player)) return List.of(); - sender.sendMessage(Integer.toString(args.length)); - if (args.length - locationArgIndex >= 3) return List.of(); diff --git a/src/main/java/com/pobnellion/floorGame/game/Floor.java b/src/main/java/com/pobnellion/floorGame/game/Floor.java index 1f03f93..33d3d32 100644 --- a/src/main/java/com/pobnellion/floorGame/game/Floor.java +++ b/src/main/java/com/pobnellion/floorGame/game/Floor.java @@ -2,6 +2,7 @@ package com.pobnellion.floorGame.game; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.World; import java.util.HashSet; import java.util.Random; @@ -34,12 +35,20 @@ public class Floor { colours = colourSet.toArray(new Material[0]); } + public void Init() { + Reset(); + FillWalls(xzCorner.getBlockY(), xzCorner.getBlockY() + 15, Material.BARRIER); + } + public void Reset() { for (int row = 0; row < gridSize; row++) { for (int col = 0; col < gridSize; col++) { - FillTile(xzCorner.clone().add(row * tileSize, 0, col * tileSize), colourGrid[row][col]); + FillTile(xzCorner.getBlockX() + row * tileSize, + xzCorner.getBlockZ() + col * tileSize, + colourGrid[row][col]); } } + FillWalls(xzCorner.getBlockY() + 2, xzCorner.getBlockY() + 4, Material.BARRIER); } public void Clear() { @@ -48,21 +57,72 @@ public class Floor { xzCorner.clone().add(row, 0, col).getBlock().setType(Material.AIR); } } + FillWalls(xzCorner.getBlockY(), xzCorner.getBlockY() + 15, Material.AIR); } public void SoloTile(Material material) { for (int row = 0; row < gridSize; row++) { for (int col = 0; col < gridSize; col++) { if (colourGrid[row][col] != material) - FillTile(xzCorner.clone().add(row * tileSize, 0, col * tileSize), Material.AIR); + FillTile(xzCorner.getBlockX() + row * tileSize, + xzCorner.getBlockZ() + col * tileSize, + Material.AIR); } } + + FillWalls(xzCorner.getBlockY() + 2, xzCorner.getBlockY() + 4, material); } - private void FillTile(Location location, Material material) { - for (int row = 0; row < tileSize; row++) { - for (int col = 0; col < tileSize; col++) { - location.clone().add(row, 0, col).getBlock().setType(material); + private void FillTile(int xMin, int zMin, Material material) { + FillArea(xzCorner.getWorld(), xMin, xzCorner.getBlockY(), zMin, + xMin + tileSize, xzCorner.getBlockY(), zMin + tileSize, material); + } + + private void FillWalls(int yMin, int yMax, Material material) { + var floorSize = tileSize * gridSize + 1; + FillArea(xzCorner.getWorld(), + xzCorner.getBlockX() - 1, + yMin, + xzCorner.getBlockZ() - 1, + xzCorner.getBlockX() - 1, + yMax, + xzCorner.getBlockZ() + floorSize, + material); + + FillArea(xzCorner.getWorld(), + xzCorner.getBlockX() - 1, + yMin, + xzCorner.getBlockZ() - 1, + xzCorner.getBlockX() + floorSize, + yMax, + xzCorner.getBlockZ() - 1, + material); + + FillArea(xzCorner.getWorld(), + xzCorner.getBlockX() + floorSize, + yMin, + xzCorner.getBlockZ() - 1, + xzCorner.getBlockX() + floorSize, + yMax, + xzCorner.getBlockX() + floorSize, + material); + + FillArea(xzCorner.getWorld(), + xzCorner.getBlockX() + floorSize, + yMin, + xzCorner.getBlockZ() + floorSize, + xzCorner.getBlockX() - 1, + yMax, + xzCorner.getBlockX() + floorSize, + material); + } + + private void FillArea(World world, int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, Material material) { + for (int x = xMin; x < xMax; x++) { + for (int y = yMin; y < yMax; y++) { + for (int z = zMin; z < zMax; z++) { + world.getBlockAt(x, y, z).setType(material); + } } } } diff --git a/src/main/java/com/pobnellion/floorGame/game/GameInstance.java b/src/main/java/com/pobnellion/floorGame/game/GameInstance.java index 97ecacd..5396549 100644 --- a/src/main/java/com/pobnellion/floorGame/game/GameInstance.java +++ b/src/main/java/com/pobnellion/floorGame/game/GameInstance.java @@ -13,6 +13,7 @@ public class GameInstance { private final ArrayList players = new ArrayList<>(); private final ArrayList spectators = new ArrayList<>(); private final GameConfig config; + public int round; public GameInstance(GameConfig config) { floor = new Floor(config.getFloorCenter(), config.getGridSize(), config.getTileSize(), config.getAvailableColours()); @@ -30,12 +31,18 @@ public class GameInstance { else if (IsInBounds(player.getLocation(), config.getSpectatorJoinArea()[0], config.getSpectatorJoinArea()[1])) spectators.add(player); }); + } + + public void Start() { + floor.Init(); + + var playerTpLocation = config.getFloorCenter().clone().add(0, 2, 0); + var spectatorTpLocation = config.getFloorCenter().clone().add(0, 15, 0); + players.forEach(player -> player.teleport(playerTpLocation)); + spectators.forEach(player -> player.teleport(spectatorTpLocation)); + + - new BukkitRunnable() { - public void run() { - GameLoopTask(); - } - }.runTaskTimerAsynchronously(FloorGame.GetInstance(), 0, 10_000); } private void GameLoopTask() { @@ -43,6 +50,8 @@ public class GameInstance { var colour = floor.colours[rand.nextInt(floor.colours.length)]; floor.SoloTile(colour); + var roundTime = 1 + floor.tileSize * 0.5 - round * (0.2 * floor.tileSize); + new BukkitRunnable() { public void run() { floor.Reset(); @@ -51,10 +60,21 @@ public class GameInstance { } public void Stop() { - floor.Clear(); + new BukkitRunnable() { + public void run() { + floor.Clear(); - players.forEach(player -> player.teleport(config.getPostGameTpLocation())); - spectators.forEach(player -> player.teleport(config.getPostGameTpLocation())); + players.forEach(player -> player.teleport(config.getPostGameTpLocation())); + spectators.forEach(player -> player.teleport(config.getPostGameTpLocation())); + } + }.runTask(FloorGame.GetInstance()); + } + + private double GetRoundTime() { + if (round < 40) + return 1 + 0.5 * floor.tileSize - 0.08 * floor.tileSize * round * 0.1; + + // TODO: flatter line after round 40 } private boolean IsInBounds(Location location, Location bounds1, Location bounds2) {