From 527cc0cf50e5fe78ba74f13c71831bff2398b0b0 Mon Sep 17 00:00:00 2001 From: jzitnik-dev Date: Sat, 8 Mar 2025 13:11:42 +0100 Subject: [PATCH] feat: Implemented falling trees --- .../services/leaves/LeavesFallingLogic.java | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/main/java/cz/jzitnik/game/logic/services/leaves/LeavesFallingLogic.java diff --git a/src/main/java/cz/jzitnik/game/logic/services/leaves/LeavesFallingLogic.java b/src/main/java/cz/jzitnik/game/logic/services/leaves/LeavesFallingLogic.java new file mode 100644 index 0000000..07beb05 --- /dev/null +++ b/src/main/java/cz/jzitnik/game/logic/services/leaves/LeavesFallingLogic.java @@ -0,0 +1,90 @@ +package cz.jzitnik.game.logic.services.leaves; + +import cz.jzitnik.game.Game; +import cz.jzitnik.game.annotations.CustomLogic; +import cz.jzitnik.game.entities.Block; +import cz.jzitnik.game.logic.CustomLogicInterface; + +import java.util.*; + +@CustomLogic +public class LeavesFallingLogic implements CustomLogicInterface { + private static final int RADIUS = 30; + private final Random random = new Random(); + + @Override + public void nextIteration(Game game) { + int[] data = game.getPlayerCords(); + var world = game.getWorld(); + int playerX = data[0]; + int playerY = data[1]; + + int startX = Math.max(0, playerX - RADIUS); + int startY = Math.max(0, playerY - RADIUS); + int endX = Math.min(world[0].length - 1, playerX + RADIUS); + int endY = Math.min(world.length - 1, playerY + RADIUS); + + Set supportedLeaves = findSupportedLeaves(world, startX, startY, endX, endY); + List fallingLeaves = new ArrayList<>(); + + for (int x = startX; x <= endX; x++) { + for (int y = startY; y <= endY; y++) { + List blocks = world[y][x]; + if (blocks.stream().anyMatch(block -> block.getBlockId().equals("oak_leaves"))) { + String key = x + "," + y; + if (!supportedLeaves.contains(key)) { + fallingLeaves.add(new int[]{x, y}); + } + } + } + } + + if (!fallingLeaves.isEmpty() && random.nextInt(4) < 1) { + int[] leafToRemove = fallingLeaves.get(random.nextInt(fallingLeaves.size())); + int leafX = leafToRemove[0]; + int leafY = leafToRemove[1]; + + world[leafY][leafX].removeIf(block -> block.getBlockId().equals("oak_leaves")); + } + } + + private Set findSupportedLeaves(List[][] world, int startX, int startY, int endX, int endY) { + Set supportedLeaves = new HashSet<>(); + Queue queue = new LinkedList<>(); + + for (int x = startX; x <= endX; x++) { + for (int y = startY; y <= endY; y++) { + List blocks = world[y][x]; + if (blocks.stream().anyMatch(block -> block.getBlockId().equals("oak_log"))) { + queue.add(new int[]{x, y}); + } + } + } + + int[][] directions = {{0,1}, {1,0}, {0,-1}, {-1,0}, {-1,1}, {1,1}, {-1,-1}, {1,-1}}; + + while (!queue.isEmpty()) { + int[] pos = queue.poll(); + int cx = pos[0]; + int cy = pos[1]; + + for (int[] dir : directions) { + int nx = cx + dir[0]; + int ny = cy + dir[1]; + + if (nx >= startX && nx <= endX && ny >= startY && ny <= endY) { + List neighborBlocks = world[ny][nx]; + if (neighborBlocks.stream().anyMatch(block -> block.getBlockId().equals("oak_leaves"))) { + String key = nx + "," + ny; + if (!supportedLeaves.contains(key)) { + supportedLeaves.add(key); + queue.add(new int[]{nx, ny}); + } + } + } + } + } + + return supportedLeaves; + } +}