diff --git a/src/main/java/de/lunarakai/minecleaner/MinecleanerArena.java b/src/main/java/de/lunarakai/minecleaner/MinecleanerArena.java index 28f751d..4b0c736 100644 --- a/src/main/java/de/lunarakai/minecleaner/MinecleanerArena.java +++ b/src/main/java/de/lunarakai/minecleaner/MinecleanerArena.java @@ -22,9 +22,7 @@ import com.google.common.base.Preconditions; import de.lunarakai.minecleaner.game.BoardSize; import de.lunarakai.minecleaner.game.Cell; import de.lunarakai.minecleaner.game.Game; -import de.lunarakai.minecleaner.game.Tile.TileType; import de.lunarakai.minecleaner.utils.MinecleanerHeads; -import net.md_5.bungee.api.ChatColor; public class MinecleanerArena { private final MinecleanerPlugin plugin; @@ -34,8 +32,7 @@ public class MinecleanerArena { private int widthIndex = 0; private final BlockFace orientation; private ArenaStatus arenaStatus = ArenaStatus.INACTIVE; - private UUID[] blockDisplays = new UUID[81]; // todo needs to be of size boardSizes[widthIndex] - private TileType[] currentMinecleaerTileTypesState; + private UUID[] blockDisplays; private Player currentPlayer; private long currentGameStartTime; @@ -62,7 +59,7 @@ public class MinecleanerArena { this.name = Preconditions.checkNotNull(arenaSection.getString("name")); this.location = Preconditions.checkNotNull(arenaSection.getLocation("location")); this.widthIndex = Preconditions.checkNotNull(arenaSection.getInt("fieldwidth")); - + this.blockDisplays = new UUID[BoardSize.boardSizes[widthIndex] * BoardSize.boardSizes[widthIndex]]; BlockFace orientation = BlockFace.NORTH; try { @@ -88,6 +85,7 @@ public class MinecleanerArena { this.name = Preconditions.checkNotNull(name, "name"); this.location = Preconditions.checkNotNull(location, "location"); this.widthIndex = Preconditions.checkNotNull(widthIndex, ("fieldwidth")); + this.blockDisplays = new UUID[BoardSize.boardSizes[widthIndex] * BoardSize.boardSizes[widthIndex]]; Preconditions.checkArgument(Math.abs(orientation.getModX()) + Math.abs(orientation.getModZ()) == 1, "no cardinal direction"); this.orientation = orientation; @@ -109,8 +107,10 @@ public class MinecleanerArena { BlockData block0 = Material.NETHER_BRICKS.createBlockData(); BlockData block1 = Material.BRICKS.createBlockData(); // todo: larger grids - for (int fx = -1; fx < 2; fx++) { - for (int fy = -1; fy < 2; fy++) { + + + for (int fx = -1; fx < 2 + widthIndex; fx++) { + for (int fy = -1; fy < 2 + widthIndex; fy++) { loc.set(location.getX() + d1x * fx, location.getY() + fy, location.getZ() + d1z * fx); boolean f = (fx + fy) % 2 == 0; world.setBlockData(loc, f ? block0 : block1); @@ -118,6 +118,10 @@ public class MinecleanerArena { } } + + /* + * Bei Größen WidthIndex 1 + 2 -> Mitte = ein Block nach Links unten versetzt + */ public void generateBlockDisplays() { int size = BoardSize.boardSizes[widthIndex]; @@ -148,9 +152,6 @@ public class MinecleanerArena { int d1x = -d0z; int d1z = d0x; - // QWing sudoku = plugin.getGeneratorThread().getSudoku(Difficulty.EASY, true); - // int[] puzzle = sudoku == null ? new int[81] : sudoku.getPuzzle(); - Location loc = location.clone(); for(int fx = 0; fx < size; fx++) { final int fxf = fx; @@ -159,9 +160,11 @@ public class MinecleanerArena { // Todo not correctly alligned at different orientations (other than NORTH) //loc.set(location.getX() + 0.11 - (d1x * fz) / 3.0 + d0x * 0.501 + d1x * 1.847, location.getY() - 0.9725 + fxf / 3.0, location.getZ() + 0.45 - (d1z * fz) / 3.0 + d0z * 0.501 + d1z * 1.847); - loc.set(location.getX() - (d1x * fz) / 3.0 + d0x * 0.55 + d1x * 1.847, location.getY() - 0.8 + fxf / 3.0, location.getZ() + 0.45 - (d1z * fz) / 3.0 + d0z * 0.55 + d1z * 1.847); + loc.set(location.getX() - (d1x * fz) / 3.0 + d0x * 0.55 + d1x * 1.847, + location.getY() - 0.8 + fxf / 3.0, + location.getZ() + 0.45 - (d1z * fz) / 3.0 + d0z * 0.55 + d1z * 1.847); - // Todo: Z-Fighting on Unknown Tile Heads (Front) + // Todo: Z-Fighting on Unknown Tile Heads && Flags(Front) // Todo: Z-Fighting on the Sides for all Tiles Display blockDisplay = world.spawn(loc, ItemDisplay.class, blockdisplay -> { Transformation transformation = blockdisplay.getTransformation(); @@ -176,10 +179,6 @@ public class MinecleanerArena { blockdisplay.setTransformation(newTransform); blockdisplay.setRotation(rotation, -90); - //MinecleanerHeads head = MinecleanerHeads.MINESWEEPER_TILE_UNKNOWN; - - //blockdisplay.setBlock(MINECLEANER_HEADS[10].getHead().getType().createBlockData()); - //blockdisplay.setBlock(head.getHead().clone().getType().createBlockData()); blockdisplay.setItemStack(MinecleanerHeads.MINESWEEPER_TILE_UNKNOWN.getHead()); }); @@ -219,7 +218,6 @@ public class MinecleanerArena { public void startNewGame() { currentMinecleanerGame = new Game(plugin, BoardSize.boardSizes[widthIndex], BoardSize.mineCounter[widthIndex]); currentMinecleanerGame.start(); - //currentMinecleaerTileTypes = currentMinecleanerGame.getMinecleanerPuzzle(widthIndex, widthIndex); arenaStatus = ArenaStatus.PLAYING; } @@ -244,14 +242,13 @@ public class MinecleanerArena { } } - // block displays dont get removed public void removeBlockDisplays() { int size = BoardSize.boardSizes[widthIndex]; World world = location.getWorld(); for(int fx = 0; fx < size; fx++) { for(int fy = 0; fy < size; fy++) { - UUID blockDisplayUuid = blockDisplays[fx + fy * 9]; + UUID blockDisplayUuid = blockDisplays[fx + fy * size]; Entity blockDisplayEntity = blockDisplayUuid != null ? world.getEntity(blockDisplayUuid) : null; if(blockDisplayEntity instanceof Display blockdisplay) { blockDisplayEntity.remove(); @@ -261,66 +258,74 @@ public class MinecleanerArena { } public void flagCell(int x, int y) { - if(currentMinecleanerGame != null) { - // flag block isnt shown / block does not change - //int id = x + y * 9; + if(currentMinecleanerGame != null && !currentMinecleanerGame.gameover) { Cell cell = currentMinecleanerGame.getCell(x, y); - Player player = this.currentPlayer; - player.sendMessage(ChatColor.GOLD + "Cell: Pos(" + cell.position.x + "," + cell.position.y + "):" + " Is Flagged: " + cell.flagged + " ,Exploded: " - + cell.exploded + " Is Revealed: " + cell.revealed); - - currentMinecleanerGame.flag(x, y); - + if(!cell.isRevealed()) { + + Player player = this.currentPlayer; - plugin.getLogger().log(Level.SEVERE, " Is Flagged (before first if): " + cell.isFlagged()); - - if(cell.isFlagged() == true) { - plugin.getLogger().log(Level.SEVERE, "Flagged Cell: [" + cell.position.x + "," + cell.position.y + "]"); - setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_FLAG); - } - - plugin.getLogger().log(Level.SEVERE, " Is Flagged (before second if): " + cell.isFlagged()); + currentMinecleanerGame.flag(x, y); + if(currentMinecleanerGame.gameover) { + plugin.getManager().handleGameover(player, this, true); + } + + //plugin.getLogger().log(Level.SEVERE, " Is Flagged (before first if): " + cell.isFlagged()); + + if(cell.isFlagged() == true) { + plugin.getLogger().log(Level.SEVERE, "Flagged Cell: [" + cell.position.x + "," + cell.position.y + "]"); + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_FLAG); - if(cell.isFlagged() == false) { - plugin.getLogger().log(Level.SEVERE, "Unflagged Cell: [" + cell.position.x + "," + cell.position.y + "]"); - setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_UNKNOWN); + } + + //plugin.getLogger().log(Level.SEVERE, " Is Flagged (before second if): " + cell.isFlagged()); + + if(cell.isFlagged() == false) { + plugin.getLogger().log(Level.SEVERE, "Unflagged Cell: [" + cell.position.x + "," + cell.position.y + "]"); + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_UNKNOWN); + } } + } } public void revealCell(int x, int y) { - if(currentMinecleanerGame != null) { - //int id = x + y * 9; - + if(currentMinecleanerGame != null && !currentMinecleanerGame.gameover) { Cell cell = currentMinecleanerGame.getCell(x, y); - Player player = this.currentPlayer; - - player.sendMessage(ChatColor.GOLD + "Cell: Pos(" + cell.position.x + "," + cell.position.y + "):" + " Is Flagged: " + cell.flagged + " ,Is Revealed: " + cell.revealed + ", CellType: " + cell.getType()); - if(!cell.isFlagged()) { + //int id = x + y * 9; + Player player = this.currentPlayer; + currentMinecleanerGame.reveal(x, y); - } - - if(cell.isRevealed() && cell.isExploded()) { - player.sendMessage(ChatColor.RED + "Game over :("); - } - - setBlockForCellType(x, y, cell); - - ArrayList floodedCells = currentMinecleanerGame.getfloodedCells(); - if(floodedCells != null) { - player.sendMessage(ChatColor.GREEN + " Flooded Cells: [" + floodedCells.size() + "]"); - - for(int i = 0; i < floodedCells.size(); i++) { - Vector2i pos = floodedCells.get(i).position; - setBlockForCellType(pos.x, pos.y, floodedCells.get(i)); + setBlockForCellType(x, y, cell); + + if(currentMinecleanerGame.gameover) { + plugin.getManager().handleGameover(player, this, !(cell.isRevealed() && cell.isExploded())); + } + + ArrayList floodedCells = currentMinecleanerGame.getfloodedCells(); + if(floodedCells != null) { + for(int i = 0; i < floodedCells.size(); i++) { + Vector2i pos = floodedCells.get(i).position; + setBlockForCellType(pos.x, pos.y, floodedCells.get(i)); + } } } } } + public void showMines() { + ArrayList explodedCells = currentMinecleanerGame.getExplodedCells(); + if(explodedCells != null) { + for(int i = 0; i < explodedCells.size(); i++) { + Vector2i pos = explodedCells.get(i).position; + setBlockForCellType(pos.x, pos.y, explodedCells.get(i)); + } + } + + } + private void setBlockForCellType(int x, int y, Cell cell) { switch (cell.getType()) { case Empty: { @@ -374,8 +379,10 @@ public class MinecleanerArena { case Mine: { if(cell.isExploded()) { setDiplayBlock(x, y, MinecleanerHeads.EXPLODED); + } else { + setDiplayBlock(x, y, MinecleanerHeads.TNT); } - setDiplayBlock(x, y, MinecleanerHeads.TNT); + break; } default: { @@ -394,9 +401,9 @@ public class MinecleanerArena { int d1z = d0x; Location loc = location.clone(); - // todo: larger grids - for(int fx = -2; fx < 1; fx++) { - for(int fy = -1; fy < 2; fy++) { + + for(int fx = -2 - widthIndex; fx < 1 ; fx++) { + for(int fy = -1; fy < 2 + widthIndex; fy++) { loc.set(location.getX() + d1x + fx, location.getY() + fy, location.getZ() + d1z * fx); blocks.add(loc.clone()); } @@ -441,5 +448,9 @@ public class MinecleanerArena { public UUID[] getBlockDisplays() { return blockDisplays; } + + public int getSize() { + return BoardSize.boardSizes[widthIndex]; + } } diff --git a/src/main/java/de/lunarakai/minecleaner/MinecleanerListener.java b/src/main/java/de/lunarakai/minecleaner/MinecleanerListener.java index eeea280..1450c67 100644 --- a/src/main/java/de/lunarakai/minecleaner/MinecleanerListener.java +++ b/src/main/java/de/lunarakai/minecleaner/MinecleanerListener.java @@ -44,20 +44,9 @@ public class MinecleanerListener implements Listener { int d1z = d0x; if (e.getBlockFace() == arena.getOrientation()) { - // Raytrace - // kann null sein Player player = e.getPlayer(); - //RayTraceResult rayTraceResult = player.getWorld().rayTraceBlocks(player.getEyeLocation(), player.getEyeLocation().getDirection(), 64.0); - RayTraceResult r2 = player.rayTraceBlocks(20.0); - - //Location loc = e.getInteractionPoint().clone().subtract(arena.getLocation()).subtract(0.5, 0.5, 0.5); // null on left-click - - /* - * TODO: - * [row] [coloumn] results depend on player position (on some player pos it works as it should, on most not) - * - */ + RayTraceResult r2 = player.rayTraceBlocks(36.0); if(r2 != null) { Vector hitPos = r2.getHitPosition(); @@ -76,8 +65,6 @@ public class MinecleanerListener implements Listener { double blockx = (dy / 3.0) * 9.0; double blockz = (dz / 3.0) * 9.0; - - int blockxInt = (int) blockx; int blockzInt = (int) blockz; @@ -106,8 +93,6 @@ public class MinecleanerListener implements Listener { if(e.getAction() == Action.RIGHT_CLICK_BLOCK) { hasRightClicked = true; } - // TODO Doesnt show messages for Cells: [ROW] [>5] (6, 7, 8 are missing) - //player.sendMessage("Arena click! " + blockxInt + " " + blockzInt + " Right Clicked: " + hasRightClicked); plugin.getManager().handleFieldClick(e.getPlayer(), blockxInt, blockzInt, hasRightClicked); } diff --git a/src/main/java/de/lunarakai/minecleaner/MinecleanerManager.java b/src/main/java/de/lunarakai/minecleaner/MinecleanerManager.java index bfbd347..17e584d 100644 --- a/src/main/java/de/lunarakai/minecleaner/MinecleanerManager.java +++ b/src/main/java/de/lunarakai/minecleaner/MinecleanerManager.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.UUID; import java.util.function.Consumer; import java.util.logging.Level; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -26,10 +27,10 @@ import net.md_5.bungee.api.ChatColor; public class MinecleanerManager { private final MinecleanerPlugin plugin; private final Inventory confirmPlayingInventory; - private final StatisticKey statisticsGamesTotal; - @SuppressWarnings("deprecation") + private int prevTick = 0; + public MinecleanerManager(MinecleanerPlugin plugin) { this.plugin = plugin; @@ -76,6 +77,28 @@ public class MinecleanerManager { player.sendMessage(ChatColor.YELLOW + "Du hast eine neue Runde Minecleaner gestartet."); } + public void handleGameover(Player player, MinecleanerArena arena, boolean isSuccessfullyCleared) { + if(!isSuccessfullyCleared) { + player.sendMessage(ChatColor.YELLOW + "Game Over! Du konntest das Feld nicht erfolgreich lösen!"); + arena.showMines(); + + Bukkit.getScheduler().runTaskLater(plugin, () -> { + leaveArena(player, false); + }, 100L); + return; + } + player.sendMessage(ChatColor.YELLOW + "Glückwunsch, du konntest das Feld erfolgreich lösen!"); + PlayerStatistics ps = plugin.getCubesideStatistics().getStatistics(player.getUniqueId()); + ps.increaseScore(statisticsGamesTotal, 1); + + + + Bukkit.getScheduler().runTaskLater(plugin, () -> { + leaveArena(player, false); + }, 100L); + + } + public void clearAllArenas() { for(MinecleanerArena arena : plugin.getArenaList().getArenas()) { if(arena.hasPlayer()) { @@ -93,16 +116,21 @@ public class MinecleanerManager { Preconditions.checkArgument(arena != null, "player is in no arena"); Preconditions.checkState(arena.getArenaStatus() == ArenaStatus.PLAYING, "not running"); - // Fires Twice for Right Click on Same Tick, but only once for left click... stupid :< - if(hasRightClicked) { - // flag - plugin.getLogger().log(Level.SEVERE, " Right Clicked @ Tick: " + plugin.getServer().getCurrentTick()); - arena.flagCell(x, y); - } else { - // reveal - plugin.getLogger().log(Level.SEVERE, " Left Clicked @ Tick: " + plugin.getServer().getCurrentTick()); - arena.revealCell(x, y); + // Feels like a stupid solution for issue described in the next comment + int currentTick = plugin.getServer().getCurrentTick(); + if(prevTick != currentTick) { + // Fires Twice for Right Click on Same Tick, but only once for left click... stupid :< + if(hasRightClicked) { + // flag + plugin.getLogger().log(Level.SEVERE, " Right Clicked @ Tick: " + plugin.getServer().getCurrentTick()); + arena.flagCell(x, y); + } else { + // reveal + plugin.getLogger().log(Level.SEVERE, " Left Clicked @ Tick: " + plugin.getServer().getCurrentTick()); + arena.revealCell(x, y); + } } + prevTick = currentTick; } public void getStatisticsForPlayer(OfflinePlayer player, Consumer callback) { diff --git a/src/main/java/de/lunarakai/minecleaner/MinecleanerPlugin.java b/src/main/java/de/lunarakai/minecleaner/MinecleanerPlugin.java index 28e2181..4261bda 100644 --- a/src/main/java/de/lunarakai/minecleaner/MinecleanerPlugin.java +++ b/src/main/java/de/lunarakai/minecleaner/MinecleanerPlugin.java @@ -23,10 +23,6 @@ public final class MinecleanerPlugin extends JavaPlugin { getServer().getScheduler().runTask(this, this::onLateEnable); } - // TODO: - // doesnt save / load arenas correctly? - // -> can't delete arena after server restart - public void onLateEnable() { playerUUIDCache = (PlayerUUIDCache) getServer().getPluginManager().getPlugin("PlayerUUIDCache"); cubesideStatistics = getServer().getServicesManager().load(CubesideStatisticsAPI.class); diff --git a/src/main/java/de/lunarakai/minecleaner/game/BoardSize.java b/src/main/java/de/lunarakai/minecleaner/game/BoardSize.java index a2c2597..5c95d11 100644 --- a/src/main/java/de/lunarakai/minecleaner/game/BoardSize.java +++ b/src/main/java/de/lunarakai/minecleaner/game/BoardSize.java @@ -3,13 +3,13 @@ package de.lunarakai.minecleaner.game; public class BoardSize { public static int[] boardSizes = { 9, - 15, - 24, // nicht größer als 24 + 12, + 15, // nicht größer als 24 }; public static int[] mineCounter = { 12, - 40, - 100, + 25, + 50, }; } diff --git a/src/main/java/de/lunarakai/minecleaner/game/Game.java b/src/main/java/de/lunarakai/minecleaner/game/Game.java index 77a3e66..e4fc82e 100644 --- a/src/main/java/de/lunarakai/minecleaner/game/Game.java +++ b/src/main/java/de/lunarakai/minecleaner/game/Game.java @@ -17,7 +17,9 @@ public class Game { private Board board; private BoardSize boardSize; private Tilemap tilemap; + private ArrayList floodedCells; + private ArrayList explodedCells; public Game(MinecleanerPlugin plugin, int width, int mineCount) { this.plugin = plugin; @@ -26,6 +28,7 @@ public class Game { this.mineCount = mineCount; this.floodedCells = new ArrayList<>(); + this.explodedCells = new ArrayList<>(); } private void onValidate() { @@ -176,6 +179,10 @@ public class Game { public void flood(Cell cell) { if(cell.isRevealed()) return; if(cell.getType() == Cell.CellType.Mine || cell.getType() == Cell.CellType.Invalid || cell.position == null) return; + + if(cell.isFlagged()) { + cell.setFlaggedState(false); + } cell.setRevealed(); floodedCells.add(cell); @@ -210,12 +217,13 @@ public class Game { if(cell.getType() == Cell.CellType.Mine) { cell.revealed = true; state[x][y] = cell; + explodedCells.add(cell); } } } } - private void checkWinCondition() { + public void checkWinCondition() { for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { Cell cell = state[x][y]; @@ -254,4 +262,8 @@ public class Game { public ArrayList getfloodedCells() { return floodedCells; } + + public ArrayList getExplodedCells() { + return explodedCells; + } }