From 4ef8e217ad5c98176208e36f9d7708112b81f6d7 Mon Sep 17 00:00:00 2001 From: jzitnik-dev Date: Thu, 13 Mar 2025 13:24:43 +0100 Subject: [PATCH] feat: Water breaks grass --- src/main/java/cz/jzitnik/Main.java | 2 +- .../game/annotations/BreakableByWater.java | 11 ++++++++ .../java/cz/jzitnik/game/entities/Player.java | 14 +++++++++- .../items/registry/blocks/GrassBushBlock.java | 2 ++ .../jzitnik/game/generation/Generation.java | 3 ++- .../logic/services/flowing/FlowingLogic.java | 27 ++++++++++++------- .../services/suffocating/Suffocating.java | 23 ++++++++++++++++ .../game/threads/list/NoHungerThread.java | 2 +- 8 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 src/main/java/cz/jzitnik/game/annotations/BreakableByWater.java create mode 100644 src/main/java/cz/jzitnik/game/logic/services/suffocating/Suffocating.java diff --git a/src/main/java/cz/jzitnik/Main.java b/src/main/java/cz/jzitnik/Main.java index 1131fba..4e434f9 100644 --- a/src/main/java/cz/jzitnik/Main.java +++ b/src/main/java/cz/jzitnik/Main.java @@ -48,7 +48,7 @@ public class Main { e.printStackTrace(); } - if ( game.getWindow() == Window.WORLD) { + if (game.getWindow() == Window.WORLD) { screenRenderer.render(game); } diff --git a/src/main/java/cz/jzitnik/game/annotations/BreakableByWater.java b/src/main/java/cz/jzitnik/game/annotations/BreakableByWater.java new file mode 100644 index 0000000..cd25e2e --- /dev/null +++ b/src/main/java/cz/jzitnik/game/annotations/BreakableByWater.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; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface BreakableByWater { +} diff --git a/src/main/java/cz/jzitnik/game/entities/Player.java b/src/main/java/cz/jzitnik/game/entities/Player.java index c24d5b9..0dca2c1 100644 --- a/src/main/java/cz/jzitnik/game/entities/Player.java +++ b/src/main/java/cz/jzitnik/game/entities/Player.java @@ -32,7 +32,19 @@ public class Player implements Serializable { public void fell() { int damage = Math.max(fallDistance - 3, 0); - health = Math.max(0, health - damage); + dealDamage(damage); fallDistance = 0; } + + public synchronized void dealDamage(int amount) { + health = Math.max(0, health - amount); + + if (health == 0) { + // TODO: Implement dead + } + } + + public synchronized void dealDamage() { + dealDamage(1); + } } diff --git a/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/GrassBushBlock.java b/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/GrassBushBlock.java index 054d9b6..909d23c 100644 --- a/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/GrassBushBlock.java +++ b/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/GrassBushBlock.java @@ -3,11 +3,13 @@ package cz.jzitnik.game.entities.items.registry.blocks; import cz.jzitnik.game.SpriteLoader; import cz.jzitnik.game.annotations.BlockDropPercentage; import cz.jzitnik.game.annotations.BlockRegistry; +import cz.jzitnik.game.annotations.BreakableByWater; import cz.jzitnik.game.annotations.CustomDrop; import cz.jzitnik.game.annotations.PlaceOnSolid; import cz.jzitnik.game.entities.Block; @PlaceOnSolid +@BreakableByWater @CustomDrop(tool = "shears", drops = "grass_bush") @BlockDropPercentage(13) @BlockRegistry(value = "grass_bush", drops = "wheat_seeds") diff --git a/src/main/java/cz/jzitnik/game/generation/Generation.java b/src/main/java/cz/jzitnik/game/generation/Generation.java index ea45ac0..4654056 100644 --- a/src/main/java/cz/jzitnik/game/generation/Generation.java +++ b/src/main/java/cz/jzitnik/game/generation/Generation.java @@ -34,7 +34,8 @@ public class Generation { world[terrainHeight[256] - 1][256].add(steveBlock2); world[terrainHeight[256] - 2][256].add(steveBlock); - game.getInventory().addItem(ItemBlockSupplier.getItem("shears")); + game.getInventory().addItem(ItemBlockSupplier.getItem("water_bucket")); + game.getInventory().addItem(ItemBlockSupplier.getItem("lava_bucket")); } private static void initializeWorld(List[][] world) { diff --git a/src/main/java/cz/jzitnik/game/logic/services/flowing/FlowingLogic.java b/src/main/java/cz/jzitnik/game/logic/services/flowing/FlowingLogic.java index bbed62f..1e10773 100644 --- a/src/main/java/cz/jzitnik/game/logic/services/flowing/FlowingLogic.java +++ b/src/main/java/cz/jzitnik/game/logic/services/flowing/FlowingLogic.java @@ -1,6 +1,7 @@ package cz.jzitnik.game.logic.services.flowing; import cz.jzitnik.game.Game; +import cz.jzitnik.game.annotations.BreakableByWater; import cz.jzitnik.game.annotations.CustomLogic; import cz.jzitnik.game.entities.Block; import cz.jzitnik.game.entities.items.ItemBlockSupplier; @@ -67,6 +68,14 @@ public class FlowingLogic implements CustomLogicInterface { private void flow(List[][] world, int x, int y, int strength, Set visited, String liquidId) { if (y + 1 < world.length && canFlowInto(world[y + 1][x])) { + var blocks = world[y + 1][x]; + List remove = new ArrayList<>(); + for (Block block : blocks) { + if (block.getClass().isAnnotationPresent(BreakableByWater.class)) { + remove.add(block); + } + } + blocks.removeAll(remove); Block newLiquid = ItemBlockSupplier.getBlock(liquidId); newLiquid.setSpriteState(Water.WaterState.get(5)); ((FlowingData) newLiquid.getData()).setSource(false); @@ -94,16 +103,14 @@ public class FlowingLogic implements CustomLogicInterface { } private void transformOrFlow(List[][] world, int newX, int newY, int strength, Set visited, String liquidId) { - var targetBlocks = world[newY][newX]; - boolean hasWater = targetBlocks.stream().anyMatch(b -> b.getBlockId().equals("water")); - boolean hasLava = targetBlocks.stream().anyMatch(b -> b.getBlockId().equals("lava")); - - if (liquidId.equals("water") && hasLava) { - return; - } - if (liquidId.equals("lava") && hasWater) { - return; + var blocks = world[newY][newX]; + List remove = new ArrayList<>(); + for (Block block : blocks) { + if (block.getClass().isAnnotationPresent(BreakableByWater.class)) { + remove.add(block); + } } + blocks.removeAll(remove); Block newLiquid = ItemBlockSupplier.getBlock(liquidId); newLiquid.setSpriteState(Water.WaterState.get(strength - 1)); @@ -114,6 +121,6 @@ public class FlowingLogic implements CustomLogicInterface { private boolean canFlowInto(List blocks) { return blocks.stream().allMatch( - block -> block.getBlockId().equals("steve") || block.getBlockId().equals("air") || block.isMob() || block.isFlowing()); + block -> block.getBlockId().equals("steve") || block.getBlockId().equals("air") || block.isMob() || block.isFlowing() || block.getClass().isAnnotationPresent(BreakableByWater.class)); } } diff --git a/src/main/java/cz/jzitnik/game/logic/services/suffocating/Suffocating.java b/src/main/java/cz/jzitnik/game/logic/services/suffocating/Suffocating.java new file mode 100644 index 0000000..98d7669 --- /dev/null +++ b/src/main/java/cz/jzitnik/game/logic/services/suffocating/Suffocating.java @@ -0,0 +1,23 @@ +package cz.jzitnik.game.logic.services.suffocating; + +import cz.jzitnik.game.Game; +import cz.jzitnik.game.annotations.CustomLogic; +import cz.jzitnik.game.logic.CustomLogicInterface; + +@CustomLogic +public class Suffocating implements CustomLogicInterface { + @Override + public void nextIteration(Game game) { + var world = game.getWorld(); + int[] data = game.getPlayerCords(); + int x = data[0]; + int y = data[1]; + + var blocks = world[y - 1][x]; + + if (blocks.stream().anyMatch(i -> !i.isGhost())) { + // Deal damage when solid block + game.getPlayer().dealDamage(); + } + } +} diff --git a/src/main/java/cz/jzitnik/game/threads/list/NoHungerThread.java b/src/main/java/cz/jzitnik/game/threads/list/NoHungerThread.java index 60ec560..676a8c2 100644 --- a/src/main/java/cz/jzitnik/game/threads/list/NoHungerThread.java +++ b/src/main/java/cz/jzitnik/game/threads/list/NoHungerThread.java @@ -15,7 +15,7 @@ public class NoHungerThread extends Thread { try { Thread.sleep(3000); if (player.getHunger() == 0) { - player.setHealth(player.getHealth() - 1); + player.dealDamage(); } } catch (InterruptedException e) { break;