diff --git a/src/main/java/cz/jzitnik/game/annotations/Sapling.java b/src/main/java/cz/jzitnik/game/annotations/Sapling.java new file mode 100644 index 0000000..0d28a56 --- /dev/null +++ b/src/main/java/cz/jzitnik/game/annotations/Sapling.java @@ -0,0 +1,11 @@ +package cz.jzitnik.game.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Sapling { +} diff --git a/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/OakSaplingBlock.java b/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/OakSaplingBlock.java index 114910b..16ceb06 100644 --- a/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/OakSaplingBlock.java +++ b/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/OakSaplingBlock.java @@ -2,13 +2,16 @@ package cz.jzitnik.game.entities.items.registry.blocks; import cz.jzitnik.game.SpriteLoader; import cz.jzitnik.game.annotations.BlockRegistry; +import cz.jzitnik.game.annotations.Sapling; import cz.jzitnik.game.entities.Block; import cz.jzitnik.game.logic.services.saplings.SaplingData; +@Sapling @BlockRegistry("oak_sapling") public class OakSaplingBlock extends Block { public OakSaplingBlock() { super("oak_sapling", SpriteLoader.SPRITES.OAK_SAPLING, 0); setData(new SaplingData()); + setGhost(true); } } diff --git a/src/main/java/cz/jzitnik/game/generation/Generation.java b/src/main/java/cz/jzitnik/game/generation/Generation.java index 2d80827..f1ea7ed 100644 --- a/src/main/java/cz/jzitnik/game/generation/Generation.java +++ b/src/main/java/cz/jzitnik/game/generation/Generation.java @@ -34,6 +34,8 @@ public class Generation { // Spawn player at a valid starting point world[terrainHeight[256] - 1][256].add(steveBlock2); world[terrainHeight[256] - 2][256].add(steveBlock); + + game.getInventory().addItem(ItemBlockSupplier.getItem("oak_sapling")); } private static void initializeWorld(List[][] world) { @@ -96,31 +98,31 @@ public class Generation { if (treeBase - 3 < 0) continue; - // Place trunk - for (int j = 0; j < 3; j++) { - if (treeBase - j >= 0) { - world[treeBase - j - 1][i].add(ItemBlockSupplier.getBlock("oak_log")); - } + tree(world, i, treeBase); + } + } + + public static void tree(List[][] world, int i, int treeBase) { + for (int j = 0; j < 3; j++) { + if (treeBase - j >= 0) { + world[treeBase - j - 1][i].add(ItemBlockSupplier.getBlock("oak_log")); } + } - int leafY = treeBase - 4; + int leafY = treeBase - 4; - // 2D Pyramid-shaped leaf placement - for (int layer = 0; layer < 3; layer++) { - int size = 5 - (layer * 2); - int offsetY = leafY - layer; + for (int layer = 0; layer < 3; layer++) { + int size = 5 - (layer * 2); + int offsetY = leafY - layer; - for (int dx = -size / 2; dx <= size / 2; dx++) { - int x = i + dx; - int y = offsetY; + for (int dx = -size / 2; dx <= size / 2; dx++) { + int x = i + dx; + int y = offsetY; - if (x >= 0 && x < world[0].length && y >= 0) { - world[y][x].add(ItemBlockSupplier.getBlock("oak_leaves")); - } + if (x >= 0 && x < world[0].length && y >= 0) { + world[y][x].add(ItemBlockSupplier.getBlock("oak_leaves")); } } } } - - } diff --git a/src/main/java/cz/jzitnik/game/logic/services/saplings/SaplingLogic.java b/src/main/java/cz/jzitnik/game/logic/services/saplings/SaplingLogic.java index ff7fefd..3a237f4 100644 --- a/src/main/java/cz/jzitnik/game/logic/services/saplings/SaplingLogic.java +++ b/src/main/java/cz/jzitnik/game/logic/services/saplings/SaplingLogic.java @@ -1,15 +1,95 @@ package cz.jzitnik.game.logic.services.saplings; import cz.jzitnik.game.Game; +import cz.jzitnik.game.annotations.BlockRegistry; import cz.jzitnik.game.annotations.CustomLogic; +import cz.jzitnik.game.annotations.Sapling; +import cz.jzitnik.game.entities.Block; +import cz.jzitnik.game.generation.Generation; import cz.jzitnik.game.logic.CustomLogicInterface; +import org.reflections.Reflections; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; @CustomLogic public class SaplingLogic implements CustomLogicInterface { private static final int RADIUS = 30; + private static final Set saplings = new HashSet<>(); + + public SaplingLogic() { + Reflections reflections = new Reflections("cz.jzitnik.game.entities.items.registry.blocks"); + Set> handlerClasses = reflections.getTypesAnnotatedWith(Sapling.class); + + for (Class clazz : handlerClasses) { + if (clazz.isAnnotationPresent(BlockRegistry.class)) { + String value = clazz.getAnnotation(BlockRegistry.class).value(); + saplings.add(value); + } + } + } + @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); + + for (int x = startX; x <= endX; x++) { + for (int y = startY; y <= endY; y++) { + var blocks = world[y][x]; + if (blocks.stream().anyMatch(block -> saplings.contains(block.getBlockId()))) { + sapling(game, x, y); + } + } + } + } + + private boolean check(Block block) { + return block.isMob() || block.getBlockId().equals("air") || saplings.contains(block.getBlockId()); + } + + private boolean canGrowSapling(List[][] world, int x, int y) { + return + world[y][x].stream().allMatch(this::check) && + world[y - 1][x].stream().allMatch(this::check) && + world[y - 2][x].stream().allMatch(this::check) && + world[y - 3][x].stream().allMatch(this::check) && + world[y - 4][x].stream().allMatch(this::check) && + world[y - 5][x].stream().allMatch(this::check) && + world[y - 3][x - 2].stream().allMatch(this::check) && + world[y - 3][x - 1].stream().allMatch(this::check) && + world[y - 3][x + 1].stream().allMatch(this::check) && + world[y - 3][x + 2].stream().allMatch(this::check) && + world[y - 4][x - 1].stream().allMatch(this::check) && + world[y - 4][x + 1].stream().allMatch(this::check); + } + + private void sapling(Game game, int x, int y) { + var world = game.getWorld(); + if (!canGrowSapling(world, x, y)) { + return; + } + + var sapling = world[y][x].stream().filter(i -> saplings.contains(i.getBlockId())).findFirst().get(); + var data = (SaplingData) sapling.getData(); + + if (data.getGrowWait() == 1) { + // Grow + world[y][x].remove(sapling); + Generation.tree(world, x, y + 1); + + return; + } + + data.setGrowWait(data.getGrowWait() - 1); } }