From 14629a35710b4f5585323c6d48b8d7a1df5e0667 Mon Sep 17 00:00:00 2001 From: LunarAkai Date: Fri, 22 Mar 2024 15:09:52 +0100 Subject: [PATCH] Somewhat functional, still has issues --- .gitignore | 3 +- .../de/lunarakai/minecleaner/ArenaList.java | 4 +- .../minecleaner/MinecleanerArena.java | 176 ++++++++---------- .../minecleaner/MinecleanerListener.java | 2 +- .../minecleaner/MinecleanerManager.java | 4 + .../de/lunarakai/minecleaner/game/Cell.java | 2 +- .../de/lunarakai/minecleaner/game/Game.java | 31 +-- .../minecleaner/utils/MinecleanerHeads.java | 3 + 8 files changed, 109 insertions(+), 116 deletions(-) diff --git a/.gitignore b/.gitignore index b3e3d23..bd4b3c6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ # Project exclude paths /target/ -/.vscode \ No newline at end of file +/.vscode +*.log diff --git a/src/main/java/de/lunarakai/minecleaner/ArenaList.java b/src/main/java/de/lunarakai/minecleaner/ArenaList.java index 6f5fbaf..3229b0d 100644 --- a/src/main/java/de/lunarakai/minecleaner/ArenaList.java +++ b/src/main/java/de/lunarakai/minecleaner/ArenaList.java @@ -131,12 +131,12 @@ public class ArenaList { plugin.getManager().leaveArena(arena.getCurrentPlayer(), true); } - for(UUID id : arena.getBlockDisplays()) { // TODO + for(UUID id : arena.getBlockDisplays()) { if(id != null) { arenaBlockDisplays.remove(id); } } - for(Location block : arena.getBlocks()) { // TODO + for(Location block : arena.getBlocks()) { arenaBlocks.remove(block); } arena.removeBlockDisplays(); diff --git a/src/main/java/de/lunarakai/minecleaner/MinecleanerArena.java b/src/main/java/de/lunarakai/minecleaner/MinecleanerArena.java index 9ff5009..28f751d 100644 --- a/src/main/java/de/lunarakai/minecleaner/MinecleanerArena.java +++ b/src/main/java/de/lunarakai/minecleaner/MinecleanerArena.java @@ -4,15 +4,16 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; +import java.util.logging.Level; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.BlockFace; import org.bukkit.block.data.BlockData; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.BlockDisplay; import org.bukkit.entity.Display; import org.bukkit.entity.Entity; +import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.Player; import org.bukkit.util.Transformation; import org.joml.Vector2i; @@ -20,7 +21,6 @@ import org.joml.Vector3f; import com.google.common.base.Preconditions; import de.lunarakai.minecleaner.game.BoardSize; import de.lunarakai.minecleaner.game.Cell; -import de.lunarakai.minecleaner.game.Cell.CellType; import de.lunarakai.minecleaner.game.Game; import de.lunarakai.minecleaner.game.Tile.TileType; import de.lunarakai.minecleaner.utils.MinecleanerHeads; @@ -43,19 +43,6 @@ public class MinecleanerArena { private final Location tempLoc = new Location(null, 0, 0, 0); - // CUSTOM HEADS - // https://minecraft-heads.com/custom-heads/head/6048-minesweeper-0-tile - // https://minecraft-heads.com/custom-heads/head/6047-minesweeper-1-tile - // https://minecraft-heads.com/custom-heads/head/6046-minesweeper-2-tile - // https://minecraft-heads.com/custom-heads/head/6045-minesweeper-3-tile - // https://minecraft-heads.com/custom-heads/head/6044-minesweeper-4-tile - // https://minecraft-heads.com/custom-heads/head/6043-minesweeper-5-tile - // https://minecraft-heads.com/custom-heads/head/6042-minesweeper-6-tile - // https://minecraft-heads.com/custom-heads/head/6041-minesweeper-7-tile - // https://minecraft-heads.com/custom-heads/head/6040-minesweeper-8-tile - // https://minecraft-heads.com/custom-heads/head/6039-minesweeper-flag-tile - // https://minecraft-heads.com/custom-heads/head/6038-minesweeper-unknown-tile - public static final MinecleanerHeads[] MINECLEANER_HEADS = { MinecleanerHeads.MINESWEEPER_TILE_0, MinecleanerHeads.MINESWEEPER_TILE_1, @@ -75,6 +62,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")); + BlockFace orientation = BlockFace.NORTH; try { @@ -120,6 +108,7 @@ 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++) { loc.set(location.getX() + d1x * fx, location.getY() + fy, location.getZ() + d1z * fx); @@ -130,6 +119,8 @@ public class MinecleanerArena { } public void generateBlockDisplays() { + int size = BoardSize.boardSizes[widthIndex]; + World world = location.getWorld(); for(UUID id : blockDisplays) { if(id != null) { @@ -161,19 +152,21 @@ public class MinecleanerArena { // int[] puzzle = sudoku == null ? new int[81] : sudoku.getPuzzle(); Location loc = location.clone(); - for(int fx = 0; fx < 9; fx++) { + for(int fx = 0; fx < size; fx++) { final int fxf = fx; - for(int fz = 0; fz < 9; fz++) { + for(int fz = 0; fz < size; fz++) { final int fzf = fz; // 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() + 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); - // Todo: ItemDisplay für Köpfe - Display blockDisplay = world.spawn(loc, BlockDisplay.class, blockdisplay -> { + // Todo: Z-Fighting on Unknown Tile Heads (Front) + // Todo: Z-Fighting on the Sides for all Tiles + Display blockDisplay = world.spawn(loc, ItemDisplay.class, blockdisplay -> { Transformation transformation = blockdisplay.getTransformation(); Transformation newTransform; - Vector3f newTranslationScale = new Vector3f(0.30f, 0.25f, 0.25f); + Vector3f newTranslationScale = new Vector3f(0.65f, 0.65f, 0.65f); newTransform = new Transformation( transformation.getTranslation(), transformation.getLeftRotation(), @@ -181,16 +174,18 @@ public class MinecleanerArena { transformation.getRightRotation()); blockdisplay.setTransformation(newTransform); - blockdisplay.setRotation(rotation + 90, 0); + 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.setBlock(Material.BEDROCK.createBlockData()); + blockdisplay.setItemStack(MinecleanerHeads.MINESWEEPER_TILE_UNKNOWN.getHead()); }); + + if(blockDisplay != null) { - blockDisplays[fxf + fzf * 9] = blockDisplay.getUniqueId(); + blockDisplays[fxf + fzf * size] = blockDisplay.getUniqueId(); } } } @@ -210,18 +205,19 @@ public class MinecleanerArena { arenaSection.set("blockdisplays", blockDisplays); } - private void setDiplayBlock(int x, int y, Material block) { - UUID blockDisplayId = blockDisplays[x + y *9]; - Entity blockDisplay = blockDisplayId != null ? location.getWorld().getEntity(blockDisplayId) : null; - if(blockDisplay instanceof BlockDisplay) { - BlockDisplay display = (BlockDisplay) blockDisplay; - display.setBlock(block.createBlockData()); - } + private void setDiplayBlock(int x, int y, MinecleanerHeads head) { + int size = BoardSize.boardSizes[widthIndex]; + UUID blockDisplayId = blockDisplays[x + y * size]; + Entity blockDisplay = blockDisplayId != null ? location.getWorld().getEntity(blockDisplayId) : null; + if(blockDisplay instanceof ItemDisplay) { + ItemDisplay display = (ItemDisplay) blockDisplay; + display.setItemStack(head.getHead()); + } } public void startNewGame() { - currentMinecleanerGame = new Game(plugin, 9, 12); + currentMinecleanerGame = new Game(plugin, BoardSize.boardSizes[widthIndex], BoardSize.mineCounter[widthIndex]); currentMinecleanerGame.start(); //currentMinecleaerTileTypes = currentMinecleanerGame.getMinecleanerPuzzle(widthIndex, widthIndex); arenaStatus = ArenaStatus.PLAYING; @@ -235,22 +231,26 @@ public class MinecleanerArena { } public void removePlayer() { + int size = BoardSize.boardSizes[widthIndex]; + this.arenaStatus = ArenaStatus.INACTIVE; this.currentPlayer = null; this.currentMinecleanerGame = null; - for(int x = 0; x < 9; x++) { - for(int y = 0; y < 9; y++) { - setDiplayBlock(x, y, Material.BEDROCK); + for(int x = 0; x < size; x++) { + for(int y = 0; y < size; y++) { + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_UNKNOWN); } } } // block displays dont get removed public void removeBlockDisplays() { + int size = BoardSize.boardSizes[widthIndex]; + World world = location.getWorld(); - for(int fx = 0; fx < 9; fx++) { - for(int fy = 0; fy < 9; fy++) { + for(int fx = 0; fx < size; fx++) { + for(int fy = 0; fy < size; fy++) { UUID blockDisplayUuid = blockDisplays[fx + fy * 9]; Entity blockDisplayEntity = blockDisplayUuid != null ? world.getEntity(blockDisplayUuid) : null; if(blockDisplayEntity instanceof Display blockdisplay) { @@ -262,52 +262,50 @@ public class MinecleanerArena { public void flagCell(int x, int y) { if(currentMinecleanerGame != null) { - int id = x + y * 9; - + // flag block isnt shown / block does not change + //int id = x + y * 9; 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 + ", CellType: " + cell.getType()); - if(cell.getType() == CellType.Number) { - player.sendMessage(ChatColor.GREEN + " Number: " + cell.number); - } + + cell.exploded + " Is Revealed: " + cell.revealed); - if(!cell.isRevealed() && !cell.isFlagged()) { - // todo set flag head on block display - currentMinecleanerGame.flag(x, y); - setDiplayBlock(x, y, Material.ORANGE_CONCRETE); - } else if(!cell.isRevealed() && cell.isFlagged() ){ - // todo set normal head on block display - setDiplayBlock(x, y, Material.BEDROCK); - } else { - return; + currentMinecleanerGame.flag(x, y); + + + 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()); + + if(cell.isFlagged() == false) { + plugin.getLogger().log(Level.SEVERE, "Unflagged Cell: [" + cell.position.x + "," + cell.position.y + "]"); + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_UNKNOWN); } } } - private boolean isRevealedCell(int x, int y) { - Cell cell = currentMinecleanerGame.getCell(x, y); - if(cell.revealed) { - return true; - } - return false; - } - - public void revealCell(int x, int y) { if(currentMinecleanerGame != null) { //int id = x + y * 9; + 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 + ", CellType: " + cell.getType()); + 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.getType() == CellType.Number) { - player.sendMessage(ChatColor.GREEN + " Number: " + cell.number); - } + if(!cell.isFlagged()) { + currentMinecleanerGame.reveal(x, y); + } + + if(cell.isRevealed() && cell.isExploded()) { + player.sendMessage(ChatColor.RED + "Game over :("); + } - currentMinecleanerGame.reveal(x, y); setBlockForCellType(x, y, cell); @@ -317,15 +315,9 @@ public class MinecleanerArena { for(int i = 0; i < floodedCells.size(); i++) { Vector2i pos = floodedCells.get(i).position; - player.sendMessage(ChatColor.GREEN + " Cell(" + pos.x + pos.y + ")"); setBlockForCellType(pos.x, pos.y, floodedCells.get(i)); } } - - - - // Todo: Logic for flood - // todo update block of blockdisplay } } @@ -333,7 +325,7 @@ public class MinecleanerArena { switch (cell.getType()) { case Empty: { if(!cell.isRevealed() || !cell.isFlagged() || !cell.isExploded()) { - setDiplayBlock(x, y, Material.GRAY_CONCRETE); + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_0); } break; } @@ -341,35 +333,35 @@ public class MinecleanerArena { if(!cell.isRevealed() || !cell.isFlagged() || !cell.isExploded()) { switch(cell.number) { case 1: { - setDiplayBlock(x, y, Material.LIME_CONCRETE_POWDER); + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_1); break; } case 2: { - setDiplayBlock(x, y, Material.GREEN_CONCRETE_POWDER); + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_2); break; } case 3: { - setDiplayBlock(x, y, Material.YELLOW_CONCRETE_POWDER); + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_3); break; } case 4: { - setDiplayBlock(x, y, Material.ORANGE_CONCRETE_POWDER); + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_4); break; } case 5: { - setDiplayBlock(x, y, Material.RED_CONCRETE_POWDER); + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_5); break; } case 6: { - setDiplayBlock(x, y, Material.LIGHT_BLUE_CONCRETE_POWDER); + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_6); break; } case 7: { - setDiplayBlock(x, y, Material.BLUE_CONCRETE_POWDER); + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_7); break; } case 8: { - setDiplayBlock(x, y, Material.BLACK_CONCRETE_POWDER); + setDiplayBlock(x, y, MinecleanerHeads.MINESWEEPER_TILE_8); break; } default: { @@ -380,10 +372,10 @@ public class MinecleanerArena { break; } case Mine: { - if(cell.exploded) { - setDiplayBlock(x, y, Material.YELLOW_CONCRETE); + if(cell.isExploded()) { + setDiplayBlock(x, y, MinecleanerHeads.EXPLODED); } - setDiplayBlock(x, y, Material.TNT); + setDiplayBlock(x, y, MinecleanerHeads.TNT); break; } default: { @@ -394,19 +386,6 @@ public class MinecleanerArena { } - private int matchWidthIndexToActualWidth(int widthIndex) { - switch (widthIndex) { - case 0: - return BoardSize.boardSizes[0]; - case 1: - return BoardSize.boardSizes[1]; - case 2: - return BoardSize.boardSizes[2]; - default: - return BoardSize.boardSizes[0]; - } - } - public List getBlocks() { ArrayList blocks = new ArrayList<>(); int d0x = orientation.getModX(); @@ -415,6 +394,7 @@ 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++) { loc.set(location.getX() + d1x + fx, location.getY() + fy, location.getZ() + d1z * fx); diff --git a/src/main/java/de/lunarakai/minecleaner/MinecleanerListener.java b/src/main/java/de/lunarakai/minecleaner/MinecleanerListener.java index 77e74ef..eeea280 100644 --- a/src/main/java/de/lunarakai/minecleaner/MinecleanerListener.java +++ b/src/main/java/de/lunarakai/minecleaner/MinecleanerListener.java @@ -108,7 +108,7 @@ public class MinecleanerListener implements Listener { } // TODO Doesnt show messages for Cells: [ROW] [>5] (6, 7, 8 are missing) - player.sendMessage("Arena click! " + blockxInt + " " + blockzInt + " Right Clicked: " + hasRightClicked); + //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 207a34b..bfbd347 100644 --- a/src/main/java/de/lunarakai/minecleaner/MinecleanerManager.java +++ b/src/main/java/de/lunarakai/minecleaner/MinecleanerManager.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.function.Consumer; +import java.util.logging.Level; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -92,11 +93,14 @@ 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); } } diff --git a/src/main/java/de/lunarakai/minecleaner/game/Cell.java b/src/main/java/de/lunarakai/minecleaner/game/Cell.java index a1719e2..bf7de12 100644 --- a/src/main/java/de/lunarakai/minecleaner/game/Cell.java +++ b/src/main/java/de/lunarakai/minecleaner/game/Cell.java @@ -45,7 +45,7 @@ public class Cell { this.exploded = true; } public boolean isExploded() { - return revealed; + return exploded; } diff --git a/src/main/java/de/lunarakai/minecleaner/game/Game.java b/src/main/java/de/lunarakai/minecleaner/game/Game.java index 9ba009a..77a3e66 100644 --- a/src/main/java/de/lunarakai/minecleaner/game/Game.java +++ b/src/main/java/de/lunarakai/minecleaner/game/Game.java @@ -135,10 +135,9 @@ public class Game { return; } - cell.flagged = !cell.flagged; + cell.flagged = !cell.isFlagged(); state[x][y] = cell; board.draw(state, tilemap); - return; } public void reveal(int x, int y) { @@ -156,7 +155,7 @@ public class Game { break; } case Empty: { - if(!floodedCells.isEmpty()) { + if(!floodedCells.isEmpty()) {; floodedCells.clear(); } flood(cell); @@ -176,21 +175,27 @@ 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.getType() == Cell.CellType.Mine || cell.getType() == Cell.CellType.Invalid || cell.position == null) return; + cell.setRevealed(); floodedCells.add(cell); - state[cell.position.x][cell.position.y] = cell; + state[cell.position.x][cell.position.y] = cell; - if(cell.getType() == Cell.CellType.Empty) { - flood(getCell(cell.position.x -1, cell.position.y)); - flood(getCell(cell.position.x +1, cell.position.y)); - flood(getCell(cell.position.x, cell.position.y -1)); - flood(getCell(cell.position.x, cell.position.y +1)); - } + if(isValid(cell.position.x -1, cell.position.y)) { + flood(getCell(cell.position.x -1, cell.position.y)); + } + if(isValid(cell.position.x +1, cell.position.y)) { + flood(getCell(cell.position.x +1, cell.position.y)); - // TODO: return cellpos of flooded cell to update the block displays + } + if(isValid(cell.position.x, cell.position.y -1)) { + flood(getCell(cell.position.x, cell.position.y -1)); + } + if(isValid(cell.position.x, cell.position.y +1)) { + flood(getCell(cell.position.x, cell.position.y +1)); + } + } } private void explode(Cell cell) { diff --git a/src/main/java/de/lunarakai/minecleaner/utils/MinecleanerHeads.java b/src/main/java/de/lunarakai/minecleaner/utils/MinecleanerHeads.java index db31903..caa46e4 100644 --- a/src/main/java/de/lunarakai/minecleaner/utils/MinecleanerHeads.java +++ b/src/main/java/de/lunarakai/minecleaner/utils/MinecleanerHeads.java @@ -22,6 +22,9 @@ public enum MinecleanerHeads { MINESWEEPER_TILE_8("168c915e-87c9-4c14-a297-3aafa692d3a5", "Minesweeper Tile 8", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODI3MWNkZDM4ZThhN2M3NDIzMWFmOGExNTU2MThmNGZmY2I3ZjkxN2U4ODI2YzJiM2MxODM2ZDFiZDExNmQzIn19fQ=="), MINESWEEPER_TILE_FLAG("ae508256-8113-463c-adce-877bad2227c0", "Minesweeper Tile Flag", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg0YTdmY2IyNDc0MDZlMzUzYTM2ZTU1NmFkMTk1NzhjM2ViZTRlMTU1ODFkYjEwNmQxNWE1Y2I5ZGFkIn19fQ=="), MINESWEEPER_TILE_UNKNOWN("2fe94bff-c5c1-410e-8c99-cf713c850930", "Minesweeper Tile Unknown", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzdmMWVhMjZlYTVlNjg1YjJmMmY4NzY0OTAxYmU5MTRmZTM1NTU5Y2IxZWNiMWVmMzRiN2U0NmFiYzhlZTU0MCJ9fX0="), + // TODO (needs fitting heads) + TNT("22a627e8-e68a-4fca-ad91-7d14c36e8556", "Minesweeper TNT", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGVlYmI4YjAzY2QyN2QzNDM1ZTExNTYxNmI4ZWQzNWRjYjQyN2FmNWIwYjFjYzUyNmQzMjY1YTcyZDQ5M2UifX19"), + EXPLODED("166a5608-5206-49bb-a325-fbcd9564dc2b", "Minesweeper Exploded", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjgzMWQ1NzIxOTUwZWZhOWFhNzk5NjdlYjE5MTZhYmViNjRjOTc4ZWE4NTkzYTBjNjgzMzU0ODA5YzZjMzYxZCJ9fX0="), ; private ItemStack head;