diff --git a/src/main/java/de/lunarakai/minecleaner/ArenaList.java b/src/main/java/de/lunarakai/minecleaner/ArenaList.java index 197e45f..d669c4a 100644 --- a/src/main/java/de/lunarakai/minecleaner/ArenaList.java +++ b/src/main/java/de/lunarakai/minecleaner/ArenaList.java @@ -121,7 +121,11 @@ public class ArenaList { public MinecleanerArena getArenaAtBlock(Block block) { return arenaBlocks.get(block.getLocation()); } - + + public MinecleanerArena getArenaForBlockDisplay(UUID id) { + return arenaBlockDisplays.get(id); + } + public void removeArena(MinecleanerArena arena) { if(arena.hasPlayer()) { plugin.getManager().leaveArena(arena.getCurrentPlayer(), true); diff --git a/src/main/java/de/lunarakai/minecleaner/MinecleanerArena.java b/src/main/java/de/lunarakai/minecleaner/MinecleanerArena.java index 037a4f2..338121c 100644 --- a/src/main/java/de/lunarakai/minecleaner/MinecleanerArena.java +++ b/src/main/java/de/lunarakai/minecleaner/MinecleanerArena.java @@ -28,7 +28,7 @@ public class MinecleanerArena { private int widthIndex = 0; private final BlockFace orientation; private ArenaStatus arenaStatus = ArenaStatus.INACTIVE; - private UUID[] blockDisplays = new UUID[widthIndex * widthIndex]; + private UUID[] blockDisplays = new UUID[81]; // todo needs to be of size boardSizes[widthIndex] private Player currentPlayer; private long currentGameStartTime; @@ -87,10 +87,9 @@ public class MinecleanerArena { BlockData block0 = Material.NETHER_BRICKS.createBlockData(); BlockData block1 = Material.BRICKS.createBlockData(); - - 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); + 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); boolean f = (fx + fy) % 2 == 0; world.setBlockData(loc, f ? block0 : block1); } @@ -133,13 +132,14 @@ public class MinecleanerArena { final int fxf = fx; for(int fz = 0; fz < 9; fz++) { final int fzf = fz; + // Todo not correctly alligned at different orientations (other than NORTH) - loc.set(location.getX() + 0.5 - (d1x * fz) / 3.0 + d0x * 0.501 + d1x * 1.847, location.getY() + fxf / 3.0, location.getZ() + 0.5 - (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); Display blockDisplay = world.spawn(loc, BlockDisplay.class, blockdisplay -> { Transformation transformation = blockdisplay.getTransformation(); Transformation newTransform; - Vector3f newTranslationScale = new Vector3f(0.25f, 0.25f, 0.25f); + Vector3f newTranslationScale = new Vector3f(0.30f, 0.25f, 0.25f); newTransform = new Transformation( transformation.getTranslation(), transformation.getLeftRotation(), @@ -167,6 +167,7 @@ public class MinecleanerArena { } public void startNewGame() { + currentMinecleanerGame = new Game(); currentMinecleanerGame.start(); arenaStatus = ArenaStatus.PLAYING; } @@ -176,11 +177,8 @@ public class MinecleanerArena { Preconditions.checkState(arenaStatus == ArenaStatus.INACTIVE); this.arenaStatus = ArenaStatus.CONFIRM_PLAYING; this.currentPlayer = player; - } - - public void removePlayer() { this.arenaStatus = ArenaStatus.INACTIVE; this.currentPlayer = null; @@ -188,9 +186,9 @@ public class MinecleanerArena { public void removeBlockDisplays() { World world = location.getWorld(); - for(int fx = 0; fx < matchWidthIndexToActualWidth(widthIndex); fx++) { - for(int fy = 0; fy < matchWidthIndexToActualWidth(widthIndex); fy++) { - UUID blockDisplayUuid = blockDisplays[fx + fy * matchWidthIndexToActualWidth(widthIndex)]; + for(int fx = 0; fx < 9; fx++) { + for(int fy = 0; fy < 9; fy++) { + UUID blockDisplayUuid = blockDisplays[fx + fy * 9]; Entity blockDisplayEntity = blockDisplayUuid != null ? world.getEntity(blockDisplayUuid) : null; if(blockDisplayEntity instanceof Display blockdisplay) { blockDisplayEntity.remove(); @@ -201,7 +199,7 @@ public class MinecleanerArena { public void flagCell(int x, int y) { if(currentMinecleanerGame != null) { - int id = x + y * matchWidthIndexToActualWidth(widthIndex); + int id = x + y * 9; boolean unflaggedCell = currentMinecleanerGame.flag(x, y); if(!unflaggedCell) { // todo set flag head on block display @@ -213,7 +211,7 @@ public class MinecleanerArena { public void revealCell(int x, int y) { if(currentMinecleanerGame != null) { - int id = x + y * matchWidthIndexToActualWidth(widthIndex); + int id = x + y * 9; // todo check if cell is flagged already currentMinecleanerGame.reveal(x, y); // todo update block of blockdisplay diff --git a/src/main/java/de/lunarakai/minecleaner/MinecleanerListener.java b/src/main/java/de/lunarakai/minecleaner/MinecleanerListener.java index 06c75b9..aa407ba 100644 --- a/src/main/java/de/lunarakai/minecleaner/MinecleanerListener.java +++ b/src/main/java/de/lunarakai/minecleaner/MinecleanerListener.java @@ -1,11 +1,21 @@ package de.lunarakai.minecleaner; +import java.util.Iterator; +import org.bukkit.Location; import org.bukkit.block.Block; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockPistonExtendEvent; +import org.bukkit.event.block.BlockPistonRetractEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.EquipmentSlot; import net.md_5.bungee.api.ChatColor; @@ -23,10 +33,41 @@ public class MinecleanerListener implements Listener { Block block = e.getClickedBlock(); MinecleanerArena arena = plugin.getArenaList().getPlayerArena(e.getPlayer()); if(arena != null) { + e.setCancelled(true); + MinecleanerArena arenaClicked = plugin.getArenaList().getArenaAtBlock(block); + if(arenaClicked == arena && arena.getArenaStatus() == ArenaStatus.PLAYING) { + int d0x = arena.getOrientation().getModX(); + int d0z = arena.getOrientation().getModZ(); + int d1x = -d0z; + int d1z = d0x; - // TODO - e.getPlayer().sendMessage(ChatColor.GREEN + "Minecleaner Arena!!"); + if (e.getBlockFace() == arena.getOrientation()) { + Location loc = e.getInteractionPoint().clone().subtract(arena.getLocation()).subtract(0.5, 0.5, 0.5); // null on left-click + double lx = loc.getX(); + double ly = loc.getY(); + double lz = loc.getZ(); + double dy = ly + 1.5; + double dz = -d1x * lx - d1z * lz + 1.5; + double blockx = (dy / 3.0) * 9.0; + double blockz = (dz / 3.0) * 9.0; + + int blockxInt = (int) blockx; + int blockzInt = (int) blockz; + blockx -= blockxInt; + blockz -= blockzInt; + if (blockx >= 0.1 && blockx <= 0.9 && blockz >= 0.1 && blockz <= 0.9) { + boolean hasRightClicked = false; + if(e.getAction() == Action.RIGHT_CLICK_BLOCK) { + hasRightClicked = true; + } + // TODO Doesnt show messages for Cells: [ROW] [>5] (6, 7, 8 are missing) + + e.getPlayer().sendMessage("Arena click! " + blockxInt + " " + blockzInt + " Right Clicked: " + hasRightClicked); + //plugin.getManager().handleFieldClick(e.getPlayer(), blockxInt, blockzInt, hasRightClicked); + } + } + } } else { arena = plugin.getArenaList().getArenaAtBlock(block); if(arena != null) { @@ -43,6 +84,57 @@ public class MinecleanerListener implements Listener { } } + @EventHandler + public void onEntityDamage(EntityDamageEvent e) { + if(plugin.getArenaList().getArenaForBlockDisplay(e.getEntity().getUniqueId()) != null) { + e.setCancelled(true); + } + } + + @EventHandler + public void onPlayerInventoryClick(InventoryClickEvent e) { + if(e.getWhoClicked() instanceof Player player) { + MinecleanerArena arena = plugin.getArenaList().getPlayerArena(player); + if(arena != null) { + if(e.getInventory().equals(plugin.getManager().getConfirmPlayingInventory())) { + e.setCancelled(true); + if(arena.getArenaStatus() == ArenaStatus.CONFIRM_PLAYING) { + int slot = e.getRawSlot(); + boolean hasConfirmed = slot == 1 ? true : false; + if(hasConfirmed) { + plugin.getManager().startGame(player); + player.closeInventory(); + } + } + } + } + } + } + + @EventHandler + public void onPlayerInventoryClose(InventoryCloseEvent e) { + if(e.getPlayer() instanceof Player player) { + MinecleanerArena arena = plugin.getArenaList().getPlayerArena(player); + if(arena != null) { + if(arena.getArenaStatus() == ArenaStatus.CONFIRM_PLAYING && e.getInventory().equals(plugin.getManager().getConfirmPlayingInventory())) { + plugin.getManager().leaveArena(player, false); + } + } + } + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent e) { + final Player player = e.getPlayer(); + MinecleanerArena arena = plugin.getArenaList().getPlayerArena(player); + if(arena != null) { + if(arena.isTooFarAway(player)) { + player.sendMessage(ChatColor.YELLOW + "Du hast dich zu weit von der Arena entfernt. Das Spiel wurde abgebrochen."); + plugin.getManager().leaveArena(player, false); + } + } + } + @EventHandler public void onPlayerQuit(PlayerQuitEvent e) { MinecleanerArena arena = plugin.getArenaList().getPlayerArena(e.getPlayer()); @@ -50,5 +142,37 @@ public class MinecleanerListener implements Listener { plugin.getManager().leaveArena(e.getPlayer(), false); } } + + @EventHandler + public void onBlockBurn(BlockBurnEvent e) { + if(plugin.getArenaList().getArenaAtBlock(e.getBlock()) != null) { + e.setCancelled(true); + return; + } + } + + @EventHandler + public void onBlockPistonExtend(BlockPistonExtendEvent e) { + Iterator it = e.getBlocks().iterator(); + while(it.hasNext()) { + Block block = it.next(); + if(plugin.getArenaList().getArenaAtBlock(block) != null) { + e.setCancelled(true); + return; + } + } + } + + @EventHandler + public void onBlockPistonRetract(BlockPistonRetractEvent e) { + Iterator it = e.getBlocks().iterator(); + while(it.hasNext()) { + Block block = it.next(); + if(plugin.getArenaList().getArenaAtBlock(block) != null) { + e.setCancelled(true); + return; + } + } + } } diff --git a/src/main/java/de/lunarakai/minecleaner/MinecleanerManager.java b/src/main/java/de/lunarakai/minecleaner/MinecleanerManager.java index 516c543..4c54ecd 100644 --- a/src/main/java/de/lunarakai/minecleaner/MinecleanerManager.java +++ b/src/main/java/de/lunarakai/minecleaner/MinecleanerManager.java @@ -4,8 +4,12 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.function.Consumer; +import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; import com.google.common.base.Preconditions; import de.iani.cubesidestats.api.PlayerStatistics; import de.iani.cubesidestats.api.PlayerStatisticsQueryKey; @@ -13,17 +17,28 @@ import de.iani.cubesidestats.api.PlayerStatisticsQueryKey.QueryType; import de.iani.cubesidestats.api.StatisticKey; import de.iani.cubesidestats.api.StatisticsQueryKey; import de.iani.cubesidestats.api.TimeFrame; +import de.iani.cubesideutils.bukkit.items.ItemStacks; import de.iani.playerUUIDCache.CachedPlayer; import net.md_5.bungee.api.ChatColor; public class MinecleanerManager { private final MinecleanerPlugin plugin; + private final Inventory confirmPlayingInventory; private final StatisticKey statisticsGamesTotal; + @SuppressWarnings("deprecation") public MinecleanerManager(MinecleanerPlugin plugin) { this.plugin = plugin; + // Deprecated + this.confirmPlayingInventory = plugin.getServer().createInventory(null, InventoryType.HOPPER, "Möchtest du Minecleaner spielen?"); + this.confirmPlayingInventory.setItem(1, + ItemStacks.lore(ItemStacks.rename(new ItemStack(Material.GREEN_CONCRETE), ChatColor.GREEN + "Bestätigen"))); + this.confirmPlayingInventory.setItem(3, + ItemStacks.lore(ItemStacks.rename(new ItemStack(Material.RED_CONCRETE), ChatColor.RED + "Abbrechen"))); + + statisticsGamesTotal = plugin.getCubesideStatistics().getStatisticKey("minecleaner.gamesTotal"); statisticsGamesTotal.setIsMonthlyStats(true); statisticsGamesTotal.setDisplayName("Runden gespielt"); @@ -38,6 +53,7 @@ public class MinecleanerManager { Preconditions.checkArgument(arena.getArenaStatus() == ArenaStatus.INACTIVE, "arena is in use"); arena.addJoiningPlayer(player); plugin.getArenaList().setArenaForPlayer(player, arena); + player.openInventory(confirmPlayingInventory); } public void leaveArena(Player player, boolean message) { @@ -50,6 +66,26 @@ public class MinecleanerManager { } } + public void startGame(Player player) { + MinecleanerArena arena = plugin.getArenaList().getPlayerArena(player); + Preconditions.checkArgument(arena != null, "player is in no arena"); + Preconditions.checkState(arena.getArenaStatus() == ArenaStatus.CONFIRM_PLAYING, "not confirming playing status"); + arena.startNewGame(); + player.sendMessage(ChatColor.YELLOW + "Du hast eine neue Runde Minecleaner gestartet."); + } + + public void clearAllArenas() { + for(MinecleanerArena arena : plugin.getArenaList().getArenas()) { + if(arena.hasPlayer()) { + leaveArena(arena.getCurrentPlayer(), true); + } + } + } + + public Inventory getConfirmPlayingInventory() { + return confirmPlayingInventory; + } + public void getStatisticsForPlayer(OfflinePlayer player, Consumer callback) { List keys = new ArrayList<>(); PlayerStatistics pStatistics = plugin.getCubesideStatistics().getStatistics(player.getUniqueId()); diff --git a/src/main/java/de/lunarakai/minecleaner/MinecleanerPlugin.java b/src/main/java/de/lunarakai/minecleaner/MinecleanerPlugin.java index 1833190..28e2181 100644 --- a/src/main/java/de/lunarakai/minecleaner/MinecleanerPlugin.java +++ b/src/main/java/de/lunarakai/minecleaner/MinecleanerPlugin.java @@ -10,14 +10,6 @@ import de.lunarakai.minecleaner.commands.ListCommand; import de.lunarakai.minecleaner.commands.StatsCommand; public final class MinecleanerPlugin extends JavaPlugin { - - - // ------------------------------ - // TODO: start a new game (via ui) - // TODO: For testing purposes -> write coords of cell into chat - // Format: Cell(X,Y) - CellType: Type - // ------------------------------ - public static final String PERMISSION_PLAY = "minecleaner.play"; public static final String PERMISSION_ADMIN = "minecleaner.admin"; @@ -29,9 +21,12 @@ public final class MinecleanerPlugin extends JavaPlugin { @Override public void onEnable() { 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); @@ -51,7 +46,9 @@ public final class MinecleanerPlugin extends JavaPlugin { @Override public void onDisable() { - // Plugin shutdown logic + if(minecleanerManager != null) { + minecleanerManager.clearAllArenas(); + } } public ArenaList getArenaList() { diff --git a/src/main/java/de/lunarakai/minecleaner/game/Board.java b/src/main/java/de/lunarakai/minecleaner/game/Board.java index bfaa507..a67fbfb 100644 --- a/src/main/java/de/lunarakai/minecleaner/game/Board.java +++ b/src/main/java/de/lunarakai/minecleaner/game/Board.java @@ -4,7 +4,7 @@ public class Board { public Tilemap tilemap; - public void draw(Cell[][] state) { + public void draw(Cell[][] state, Tilemap tilemap) { tilemap.clearAllTiles(); int width = state[0].length; diff --git a/src/main/java/de/lunarakai/minecleaner/game/Game.java b/src/main/java/de/lunarakai/minecleaner/game/Game.java index abb40c3..739bc93 100644 --- a/src/main/java/de/lunarakai/minecleaner/game/Game.java +++ b/src/main/java/de/lunarakai/minecleaner/game/Game.java @@ -12,12 +12,15 @@ public class Game { private boolean gameover; private Board board; private BoardSize boardSize; + private Tilemap tilemap; private void onValidate() { mineCount = MathUtils.clamp(mineCount, 0, width*height); } public void start() { + board = new Board(); + int[] _boardSizes = boardSize.boardSizes; int[] _mineCounter = boardSize.mineCounter; @@ -31,6 +34,9 @@ public class Game { private void newGame() { state = new Cell[width][height]; + Tile[][] tile = new Tile[width][height]; + + tilemap = new Tilemap(tile); gameover = false; @@ -38,7 +44,7 @@ public class Game { generateMines(); generateNumbers(); - board.draw(state); + board.draw(state, tilemap); } private void generateCells() { @@ -129,7 +135,7 @@ public class Game { cell.flagged = !cell.flagged; state[x][y] = cell; - board.draw(state); + board.draw(state, tilemap); return isFlaggedAlready; } @@ -159,7 +165,7 @@ public class Game { checkWinCondition(); break; } - board.draw(state); + board.draw(state, tilemap); return hitMine; }