package cz.jzitnik.game; import cz.jzitnik.game.items.Item; import cz.jzitnik.game.items.ItemType; import cz.jzitnik.game.sprites.Breaking; import cz.jzitnik.game.sprites.Window; import cz.jzitnik.game.ui.Inventory; import cz.jzitnik.tui.ScreenMovingCalculationProvider; import cz.jzitnik.tui.ScreenRenderer; import lombok.Getter; import lombok.Setter; import org.jline.terminal.Terminal; import java.util.ArrayList; import java.util.List; @Getter public class Game { private List[][] world = new ArrayList[256][512]; @Setter private Block player; private boolean mining = false; @Setter private Window window = Window.WORLD; //jsonignore private final GameStates gameStates = new GameStates(this); private final Inventory inventory = new Inventory(); public Game() { Generation.generateWorld(this); } public int[] getPlayerCords() { for (int i = 0; i < world.length; i++) { for (int j = 0; j < world[i].length; j++) { for (Block block : world[i][j]) { if (block.getBlockId().equals("steve")) { return new int[]{j, i}; } } } } return null; } public void movePlayerRight(ScreenRenderer screenRenderer) { if (window != Window.WORLD) { return; } int[] cords = getPlayerCords(); if (world[cords[1]][cords[0] + 1].stream().anyMatch(block -> !block.isGhost())) { return; } world[cords[1]][cords[0] + 1].add(player); world[cords[1]][cords[0]].remove(player); screenRenderer.render(this); update(screenRenderer); } public void movePlayerLeft(ScreenRenderer screenRenderer) { if (window != Window.WORLD) { return; } int[] cords = getPlayerCords(); if (world[cords[1]][cords[0] - 1].stream().anyMatch(block -> !block.isGhost())) { return; } world[cords[1]][cords[0] - 1].add(player); world[cords[1]][cords[0]].remove(player); screenRenderer.render(this); update(screenRenderer); } public void movePlayerUp(ScreenRenderer screenRenderer) { if (window != Window.WORLD) { return; } int[] cords = getPlayerCords(); if (world[cords[1] - 1][cords[0]].stream().anyMatch(block -> !block.isGhost()) || world[cords[1] + 1][cords[0]].stream().anyMatch(Block::isGhost)) { return; } world[cords[1] - 1][cords[0]].add(player); world[cords[1]][cords[0]].remove(player); new Thread(() -> { try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } int[] cords2 = getPlayerCords(); if (world[cords2[1] + 1][cords2[0]].stream().allMatch(Block::isGhost)) { world[cords2[1] + 1][cords2[0]].add(player); world[cords2[1]][cords2[0]].remove(player); screenRenderer.render(this); } }).start(); } public void mine(ScreenRenderer screenRenderer, int x, int y) { if (mining || window != Window.WORLD) { return; } Block breakingBlock = new Block("breaking", SpriteLoader.SPRITES.BREAKING); world[y][x].add(breakingBlock); screenRenderer.render(this); int hardness = world[y][x].stream().filter(block -> !block.isGhost()).toList().get(0).calculateHardness(inventory); this.mining = true; new Thread(() -> { try { Thread.sleep(hardness * 166L); } catch (InterruptedException e) { throw new RuntimeException(e); } breakingBlock.setSpriteState(Breaking.BreakingState.SECOND); screenRenderer.render(this); try { Thread.sleep(hardness * 166L); } catch (InterruptedException e) { throw new RuntimeException(e); } breakingBlock.setSpriteState(Breaking.BreakingState.THIRD); screenRenderer.render(this); try { Thread.sleep(hardness * 166L); } catch (InterruptedException e) { throw new RuntimeException(e); } mining = false; var blocks = world[y][x]; for (Block block : blocks) { if (!block.isMineable()) { continue; } if (block.getToolVariants().isEmpty()) { // Add to inv block.getDrops().forEach(item -> inventory.addItem(item)); continue; } var toolVariants = block.getToolVariants(); if (inventory.getItemInHand().isPresent() && inventory.getItemInHand().get().getToolVariant().isPresent() && block.getTool().isPresent() && block.getTool().get().equals(inventory.getItemInHand().get().getType()) && toolVariants.contains(inventory.getItemInHand().get().getToolVariant().get())) { block.getDrops().forEach(item -> inventory.addItem(item)); } } blocks.clear(); blocks.add(new Block("air", SpriteLoader.SPRITES.AIR, true, false)); inventory.getItemInHand().ifPresent(Item::use); screenRenderer.render(this); update(screenRenderer); }).start(); } public boolean isMineable(int x, int y, Terminal terminal) { List blocks = world[y][x]; int[] cords = getPlayerCords(); int playerX = cords[0]; int playerY = cords[1]; int distanceX = Math.abs(playerX - x); int distanceY = Math.abs(playerY - y); int[] data = ScreenMovingCalculationProvider.calculate(playerX, playerY, terminal.getHeight(), terminal.getWidth(), world[0].length, world.length); int startX = data[0]; int endX = data[1]; int startY = data[2]; int endY = data[3]; return y >= startY && y < endY - 1 && x >= startX && x < endX - 1 && !blocks.stream().allMatch(block -> block.getBlockId().equals("air")) && distanceX <= 5 && distanceY <= 5 && !(playerX == x && playerY == y) && blocks.stream().anyMatch(Block::isMineable); } public void update(ScreenRenderer screenRenderer) { while (true) { try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } int[] cords2 = getPlayerCords(); if (world[cords2[1] + 1][cords2[0]].stream().allMatch(Block::isGhost)) { world[cords2[1] + 1][cords2[0]].add(player); world[cords2[1]][cords2[0]].remove(player); screenRenderer.render(this); } else { break; } } } public void build(int x, int y, ScreenRenderer screenRenderer) { if (window != Window.WORLD) { return; } var blocks = world[y][x]; int[] cords = getPlayerCords(); int playerX = cords[0]; int playerY = cords[1]; int distanceX = Math.abs(playerX - x); int distanceY = Math.abs(playerY - y); if (distanceX > 5 || distanceY > 5) { return; } if (!blocks.stream().allMatch(block -> block.getBlockId().equals("air"))) { RightClickHandler.handle(x, y, this); screenRenderer.render(this); return; } if (!(inventory.getItemInHand().isPresent() && inventory.getItemInHand().get().getType() == ItemType.BLOCK)) { return; } blocks.removeAll(blocks.stream().filter(block -> block.getBlockId().equals("air")).toList()); blocks.add(inventory.getItemInHand().get().getBlock().get()); inventory.decreaseItemInHand(); screenRenderer.render(this); } public void changeSlot(int slot, ScreenRenderer screenRenderer) { if (window != Window.WORLD) { return; } inventory.setItemInhHandIndex(slot); screenRenderer.render(this); } }