diff --git a/src/main/java/cz/jzitnik/game/crafting/recipes/BucketRecipe.java b/src/main/java/cz/jzitnik/game/crafting/recipes/BucketRecipe.java index 21290ba..637cea3 100644 --- a/src/main/java/cz/jzitnik/game/crafting/recipes/BucketRecipe.java +++ b/src/main/java/cz/jzitnik/game/crafting/recipes/BucketRecipe.java @@ -3,15 +3,10 @@ package cz.jzitnik.game.crafting.recipes; import cz.jzitnik.game.annotations.CraftingRecipeRegistry; @CraftingRecipeRegistry( - /*recipe = { + recipe = { "iron_ingot", "_", "iron_ingot", "_", "iron_ingot", "_", "_", "_", "_" - },*/ - recipe = { - "dirt", "_", "_", - "_", "_", "_", - "_", "_", "_" }, result = "bucket", amount = 1 diff --git a/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/LavaBlock.java b/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/LavaBlock.java new file mode 100644 index 0000000..f5c6139 --- /dev/null +++ b/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/LavaBlock.java @@ -0,0 +1,19 @@ +package cz.jzitnik.game.entities.items.registry.blocks; + +import cz.jzitnik.game.SpriteLoader; +import cz.jzitnik.game.annotations.BlockRegistry; +import cz.jzitnik.game.entities.Block; +import cz.jzitnik.game.logic.services.flowing.lava.LavaData; +import cz.jzitnik.game.sprites.Lava; + +@BlockRegistry(value = "lava", drops = "lava_bucket") +public class LavaBlock extends Block { + public LavaBlock() { + super("lava", SpriteLoader.SPRITES.LAVA); + setMineable(false); + setSpriteState(Lava.LavaState.FIRST); + setData(new LavaData()); + setFlowing(true); + setGhost(true); + } +} diff --git a/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/WaterBlock.java b/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/WaterBlock.java index 483d168..376e66d 100644 --- a/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/WaterBlock.java +++ b/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/WaterBlock.java @@ -3,7 +3,7 @@ package cz.jzitnik.game.entities.items.registry.blocks; import cz.jzitnik.game.SpriteLoader; import cz.jzitnik.game.annotations.BlockRegistry; import cz.jzitnik.game.entities.Block; -import cz.jzitnik.game.logic.services.water.WaterData; +import cz.jzitnik.game.logic.services.flowing.water.WaterData; import cz.jzitnik.game.sprites.Water; @BlockRegistry(value = "water", drops = "water_bucket") diff --git a/src/main/java/cz/jzitnik/game/entities/items/registry/items/LavaBucketItem.java b/src/main/java/cz/jzitnik/game/entities/items/registry/items/LavaBucketItem.java index a721c10..3df78c0 100644 --- a/src/main/java/cz/jzitnik/game/entities/items/registry/items/LavaBucketItem.java +++ b/src/main/java/cz/jzitnik/game/entities/items/registry/items/LavaBucketItem.java @@ -5,7 +5,7 @@ import cz.jzitnik.game.annotations.ItemRegistry; import cz.jzitnik.game.entities.items.Item; import cz.jzitnik.game.entities.items.ItemType; -@ItemRegistry("lava_bucket") +@ItemRegistry(value = "lava_bucket", block = "lava") public class LavaBucketItem extends Item { public LavaBucketItem() { super("lava_bucket", "Lava bucket", ItemType.PICKUPER, SpriteLoader.SPRITES.LAVA_BUCKET); diff --git a/src/main/java/cz/jzitnik/game/generation/Generation.java b/src/main/java/cz/jzitnik/game/generation/Generation.java index 1820e5f..5a70b6b 100644 --- a/src/main/java/cz/jzitnik/game/generation/Generation.java +++ b/src/main/java/cz/jzitnik/game/generation/Generation.java @@ -23,6 +23,7 @@ public class Generation { Block steveBlock2 = new Block("steve", SpriteLoader.SPRITES.STEVE); steveBlock2.setSpriteState(Steve.SteveState.SECOND); steveBlock2.setGhost(true); + steveBlock2.setMob(true); int[] terrainHeight = generateTerrain(); @@ -35,7 +36,6 @@ public class Generation { // Spawn player at a valid starting point world[terrainHeight[256] - 1][256].add(steveBlock2); world[terrainHeight[256] - 2][256].add(steveBlock); - world[terrainHeight[256] - 1][256 + 1].add(ItemBlockSupplier.getBlock("water")); } private static void initializeWorld(List[][] world) { diff --git a/src/main/java/cz/jzitnik/game/handlers/pickup/handlers/BucketPickupHandler.java b/src/main/java/cz/jzitnik/game/handlers/pickup/handlers/BucketPickupHandler.java index 5d0458b..69e87c0 100644 --- a/src/main/java/cz/jzitnik/game/handlers/pickup/handlers/BucketPickupHandler.java +++ b/src/main/java/cz/jzitnik/game/handlers/pickup/handlers/BucketPickupHandler.java @@ -5,7 +5,7 @@ import cz.jzitnik.game.annotations.PickupHandler; import cz.jzitnik.game.entities.Block; import cz.jzitnik.game.entities.items.Item; import cz.jzitnik.game.handlers.pickup.CustomPickupHandler; -import cz.jzitnik.game.logic.services.water.FlowingData; +import cz.jzitnik.game.logic.services.flowing.FlowingData; import java.util.List; @@ -35,8 +35,23 @@ public class BucketPickupHandler implements CustomPickupHandler { game.getInventory().decreaseItemInHand(); game.getInventory().addItem(returnItems); - world[y][x].remove(world[y][x].stream().filter(Block::isFlowing).findFirst().get()); + if (!block.getBlockId().equals("water") || !isInfiniteWaterSource(game, x, y)) { + world[y][x].remove(world[y][x].stream().filter(Block::isFlowing).findFirst().get()); + } return true; } + + private boolean isInfiniteWaterSource(Game game, int x, int y) { + var world = game.getWorld(); + + var leftBlock = world[y][x - 1].stream().filter(Block::isFlowing).findFirst(); + var rightBlock = world[y][x + 1].stream().filter(Block::isFlowing).findFirst(); + + if (leftBlock.isPresent() && ((FlowingData) leftBlock.get().getData()).isSource()) { + return true; + } + + return rightBlock.isPresent() && ((FlowingData) rightBlock.get().getData()).isSource(); + } } diff --git a/src/main/java/cz/jzitnik/game/logic/services/water/FlowingData.java b/src/main/java/cz/jzitnik/game/logic/services/flowing/FlowingData.java similarity index 73% rename from src/main/java/cz/jzitnik/game/logic/services/water/FlowingData.java rename to src/main/java/cz/jzitnik/game/logic/services/flowing/FlowingData.java index 20bdf8f..4056f4a 100644 --- a/src/main/java/cz/jzitnik/game/logic/services/water/FlowingData.java +++ b/src/main/java/cz/jzitnik/game/logic/services/flowing/FlowingData.java @@ -1,4 +1,4 @@ -package cz.jzitnik.game.logic.services.water; +package cz.jzitnik.game.logic.services.flowing; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/cz/jzitnik/game/logic/services/flowing/lava/LavaData.java b/src/main/java/cz/jzitnik/game/logic/services/flowing/lava/LavaData.java new file mode 100644 index 0000000..615529e --- /dev/null +++ b/src/main/java/cz/jzitnik/game/logic/services/flowing/lava/LavaData.java @@ -0,0 +1,5 @@ +package cz.jzitnik.game.logic.services.flowing.lava; + +import cz.jzitnik.game.logic.services.flowing.FlowingData; + +public class LavaData extends FlowingData {} diff --git a/src/main/java/cz/jzitnik/game/logic/services/flowing/lava/LavaLogic.java b/src/main/java/cz/jzitnik/game/logic/services/flowing/lava/LavaLogic.java new file mode 100644 index 0000000..dba4de2 --- /dev/null +++ b/src/main/java/cz/jzitnik/game/logic/services/flowing/lava/LavaLogic.java @@ -0,0 +1,123 @@ +package cz.jzitnik.game.logic.services.flowing.lava; + +import cz.jzitnik.game.Game; +import cz.jzitnik.game.annotations.CustomLogic; +import cz.jzitnik.game.entities.Block; +import cz.jzitnik.game.entities.items.ItemBlockSupplier; +import cz.jzitnik.game.logic.CustomLogicInterface; +import cz.jzitnik.game.sprites.Lava; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.awt.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@CustomLogic +public class LavaLogic implements CustomLogicInterface { + private static final int RADIUS = 20; + + @AllArgsConstructor + @Getter + private static class WaterBlock { + private Block block; + private int x; + private int y; + } + + @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); + + List sourceBlocks = new ArrayList<>(); + + for (int y = startY; y <= endY; y++) { + for (int x = startX; x <= endX; x++) { + var blocks = world[y][x]; + + var waterSourceBlocks = blocks.stream().filter(block -> block.getBlockId().equals("lava") && ((LavaData) block.getData()).isSource()).toList(); + if (!waterSourceBlocks.isEmpty()) { + sourceBlocks.add(new WaterBlock(waterSourceBlocks.getFirst(), x, y)); + } + + world[y][x].removeAll(blocks.stream().filter(i -> i.getBlockId().equals("lava") && !((LavaData) i.getData()).isSource()).toList()); + } + } + + + for (WaterBlock sourceBlock : sourceBlocks) { + int x = sourceBlock.getX(); + int y = sourceBlock.getY(); + + flow(world, x, y, 5, new HashSet<>()); + } + + checkFire(game, startX, endX, startY, endY); + } + + public void flow(List[][] world, int x, int y, int strength, Set visited) { + if (y + 1 < world.length && waterCanFlow(world[y+1][x])) { + Block newWater = ItemBlockSupplier.getBlock("lava"); + newWater.setSpriteState(Lava.LavaState.get(5)); + ((LavaData) newWater.getData()).setSource(false); + world[y+1][x].add(newWater); + flow(world, x, y + 1, 5, visited); + return; + } + + if (strength == 1 || visited.contains(new Point(x, y))) { + return; + } + visited.add(new Point(x, y)); + + if (x - 1 >= 0 && waterCanFlow(world[y][x-1])) { + Block newWater = ItemBlockSupplier.getBlock("lava"); + newWater.setSpriteState(Lava.LavaState.get(strength - 1)); + ((LavaData) newWater.getData()).setSource(false); + world[y][x-1].add(newWater); + flow(world, x - 1, y, strength - 1, visited); + } + + if (x + 1 < world[y].length && waterCanFlow(world[y][x+1])) { + Block newWater = ItemBlockSupplier.getBlock("lava"); + newWater.setSpriteState(Lava.LavaState.get(strength - 1)); + ((LavaData) newWater.getData()).setSource(false); + world[y][x+1].add(newWater); + flow(world, x + 1, y, strength - 1, visited); + } + } + + public void checkFire(Game game, int startX, int endX, int startY, int endY) { + var world = game.getWorld(); + for (int y = startY; y <= endY; y++) { + for (int x = startX; x <= endX; x++) { + var blocks = world[y][x]; + if (blocks.stream().anyMatch(block -> block.getBlockId().equals("lava"))) { + var entities = blocks.stream().filter(Block::isMob).toList(); + for (Block block : entities) { + if (block.getBlockId().equals("steve")) { + game.getPlayer().setHealth(game.getPlayer().getHealth() - 1); + continue; + } + block.decreaseHp(1); + } + } + } + } + } + + + private boolean waterCanFlow(List blocks) { + return blocks.stream().allMatch(block -> block.getBlockId().equals("steve") || block.getBlockId().equals("air") || block.isMob()); + } +} diff --git a/src/main/java/cz/jzitnik/game/logic/services/flowing/water/WaterData.java b/src/main/java/cz/jzitnik/game/logic/services/flowing/water/WaterData.java new file mode 100644 index 0000000..4cc782f --- /dev/null +++ b/src/main/java/cz/jzitnik/game/logic/services/flowing/water/WaterData.java @@ -0,0 +1,5 @@ +package cz.jzitnik.game.logic.services.flowing.water; + +import cz.jzitnik.game.logic.services.flowing.FlowingData; + +public class WaterData extends FlowingData {} diff --git a/src/main/java/cz/jzitnik/game/logic/services/water/WaterLogic.java b/src/main/java/cz/jzitnik/game/logic/services/flowing/water/WaterLogic.java similarity index 98% rename from src/main/java/cz/jzitnik/game/logic/services/water/WaterLogic.java rename to src/main/java/cz/jzitnik/game/logic/services/flowing/water/WaterLogic.java index ec545d4..89510a0 100644 --- a/src/main/java/cz/jzitnik/game/logic/services/water/WaterLogic.java +++ b/src/main/java/cz/jzitnik/game/logic/services/flowing/water/WaterLogic.java @@ -1,4 +1,4 @@ -package cz.jzitnik.game.logic.services.water; +package cz.jzitnik.game.logic.services.flowing.water; import cz.jzitnik.game.Game; import cz.jzitnik.game.annotations.CustomLogic; diff --git a/src/main/java/cz/jzitnik/game/logic/services/water/WaterData.java b/src/main/java/cz/jzitnik/game/logic/services/water/WaterData.java deleted file mode 100644 index 562c57c..0000000 --- a/src/main/java/cz/jzitnik/game/logic/services/water/WaterData.java +++ /dev/null @@ -1,3 +0,0 @@ -package cz.jzitnik.game.logic.services.water; - -public class WaterData extends FlowingData {}