diff --git a/src/main/java/cz/jzitnik/game/Game.java b/src/main/java/cz/jzitnik/game/Game.java index 10145c3..93f18b3 100644 --- a/src/main/java/cz/jzitnik/game/Game.java +++ b/src/main/java/cz/jzitnik/game/Game.java @@ -394,7 +394,7 @@ public class Game extends AutoTransientSupport { Item item = inventory.getItemInHand().get(); - CustomPlaceHandler placeHandler = gameStates.dependencies.placeHandler.get(item.getId()); + CustomPlaceHandler placeHandler = gameStates.dependencies.placeHandler.get(item.getBlock().get().getBlockId()); var blocksRemove = blocks.stream().filter(block -> block.getClass().isAnnotationPresent(BreaksByPlace.class)) .toList(); diff --git a/src/main/java/cz/jzitnik/game/SpriteLoader.java b/src/main/java/cz/jzitnik/game/SpriteLoader.java index 234da0d..960de70 100644 --- a/src/main/java/cz/jzitnik/game/SpriteLoader.java +++ b/src/main/java/cz/jzitnik/game/SpriteLoader.java @@ -158,6 +158,9 @@ public class SpriteLoader { LAVA_BUCKET, MILK_BUCKET, + // Seeds + WHEAT, + // Food ITEM_PORKCHOP, ITEM_COOKED_PORKCHOP, @@ -248,6 +251,9 @@ public class SpriteLoader { SPRITES_MAP.put(SPRITES.HEART, new Heart()); SPRITES_MAP.put(SPRITES.HUNGER, new Hunger()); + // SEEDS + SPRITES_MAP.put(SPRITES.WHEAT, new Farmable("dirt.ans", "grass.ans", "sand.ans")); + // ITEMS // Items @@ -339,8 +345,6 @@ public class SpriteLoader { SPRITES_MAP.put(SPRITES.ITEM_BEEF, new SimpleSprite("items/beef.ans")); SPRITES_MAP.put(SPRITES.ITEM_STEAK, new SimpleSprite("items/steak.ans")); SPRITES_MAP.put(SPRITES.ITEM_APPLE, new SimpleSprite("items/apple.ans")); - - } public static SpriteList load() { diff --git a/src/main/java/cz/jzitnik/game/annotations/ResetSpriteStateOnMine.java b/src/main/java/cz/jzitnik/game/annotations/ResetSpriteStateOnMine.java new file mode 100644 index 0000000..78db303 --- /dev/null +++ b/src/main/java/cz/jzitnik/game/annotations/ResetSpriteStateOnMine.java @@ -0,0 +1,12 @@ +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) +@RequireAnnotation(BlockRegistry.class) +public @interface ResetSpriteStateOnMine { +} diff --git a/src/main/java/cz/jzitnik/game/entities/Block.java b/src/main/java/cz/jzitnik/game/entities/Block.java index a9c04ce..5cb15ea 100644 --- a/src/main/java/cz/jzitnik/game/entities/Block.java +++ b/src/main/java/cz/jzitnik/game/entities/Block.java @@ -70,6 +70,10 @@ public class Block implements Serializable { this.spriteState = MyOptional.of(spriteState); } + public void setSpriteState() { + this.spriteState = MyOptional.empty(); + } + public double calculateHardness(Inventory inventory) { double holdingDecrease = 0; if (inventory.getItemInHand().isPresent() && tool.isPresent() diff --git a/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/grassy/WheatBlock.java b/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/grassy/WheatBlock.java index 9305611..376f3f3 100644 --- a/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/grassy/WheatBlock.java +++ b/src/main/java/cz/jzitnik/game/entities/items/registry/blocks/grassy/WheatBlock.java @@ -3,16 +3,20 @@ package cz.jzitnik.game.entities.items.registry.blocks.grassy; import cz.jzitnik.game.SpriteLoader; import cz.jzitnik.game.annotations.BlockRegistry; import cz.jzitnik.game.annotations.Farmable; +import cz.jzitnik.game.annotations.PlaceOnSolidNoHandler; import cz.jzitnik.game.annotations.ResetDataOnMine; +import cz.jzitnik.game.annotations.ResetSpriteStateOnMine; import cz.jzitnik.game.entities.Block; import cz.jzitnik.game.logic.services.farmable.FarmableData; -@ResetDataOnMine @Farmable -@BlockRegistry("wheat") +@PlaceOnSolidNoHandler +@ResetDataOnMine +@ResetSpriteStateOnMine +@BlockRegistry(value = "wheat", drops = "wheat_seeds") public class WheatBlock extends Block { public WheatBlock() { - super("weat", SpriteLoader.SPRITES.OAK_SAPLING, 0); + super("wheat", SpriteLoader.SPRITES.WHEAT, 0); setData(new FarmableData()); setGhost(true); } diff --git a/src/main/java/cz/jzitnik/game/entities/items/registry/items/grassy/WheatSeedsItem.java b/src/main/java/cz/jzitnik/game/entities/items/registry/items/grassy/WheatSeedsItem.java index 3c18008..1b2a3c0 100644 --- a/src/main/java/cz/jzitnik/game/entities/items/registry/items/grassy/WheatSeedsItem.java +++ b/src/main/java/cz/jzitnik/game/entities/items/registry/items/grassy/WheatSeedsItem.java @@ -5,9 +5,9 @@ import cz.jzitnik.game.annotations.ItemRegistry; import cz.jzitnik.game.entities.items.Item; import cz.jzitnik.game.entities.items.ItemType; -@ItemRegistry(value = "wheat_seeds", block = "grass_bush") +@ItemRegistry(value = "wheat_seeds", block = "wheat") public class WheatSeedsItem extends Item { public WheatSeedsItem() { - super("wheat_seeds", "Wheat seeds", ItemType.USELESS_ITEM, SpriteLoader.SPRITES.ITEM_WHEAT_SEEDS); + super("wheat_seeds", "Wheat seeds", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_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 ef547f5..122079e 100644 --- a/src/main/java/cz/jzitnik/game/generation/Generation.java +++ b/src/main/java/cz/jzitnik/game/generation/Generation.java @@ -36,6 +36,7 @@ public class Generation { game.getInventory().addItem(ItemBlockSupplier.getItem("wooden_hoe")); game.getInventory().addItem(ItemBlockSupplier.getItem("water_bucket")); + game.getInventory().addItem(ItemBlockSupplier.getItem("wheat_seeds")); } private static void initializeWorld(List[][] world) { diff --git a/src/main/java/cz/jzitnik/game/handlers/place/CustomAnnotationHandler.java b/src/main/java/cz/jzitnik/game/handlers/place/CustomAnnotationHandler.java index 23368ec..1da4b39 100644 --- a/src/main/java/cz/jzitnik/game/handlers/place/CustomAnnotationHandler.java +++ b/src/main/java/cz/jzitnik/game/handlers/place/CustomAnnotationHandler.java @@ -15,7 +15,8 @@ public class CustomAnnotationHandler implements CustomPlaceHandler { private final Class clazz; private final DefaultPlaceHandler defaultPlaceHandler = new DefaultPlaceHandler(); - private record BlockDrop(String drops, int percentage) {} + private record BlockDrop(String drops, int percentage) { + } public CustomAnnotationHandler(Class clazz) { this.clazz = clazz; @@ -28,7 +29,11 @@ public class CustomAnnotationHandler implements CustomPlaceHandler { if (clazz.isAnnotationPresent(PlaceOnSolid.class)) { place = placeOnSolid(game, x, y); } - + + if (place && clazz.isAnnotationPresent(Farmable.class)) { + place = placeFarmable(game, x, y); + } + if (place && clazz.isAnnotationPresent(TwoblockBlock.class)) { var blocksTop = game.getWorld()[y - 1][x]; if (!blocksTop.stream().allMatch(block -> block.getBlockId().equals("air"))) { @@ -53,12 +58,10 @@ public class CustomAnnotationHandler implements CustomPlaceHandler { inventory.decreaseItemInHand(); - customPlace = true; return true; } - if (!customPlace && place) { return defaultPlaceHandler.place(game, x, y); } @@ -72,19 +75,27 @@ public class CustomAnnotationHandler implements CustomPlaceHandler { resetDataOnMine(game, x, y); } + if (clazz.isAnnotationPresent(ResetSpriteStateOnMine.class)) { + var blocks = game.getWorld()[y][x]; + + var blockx = blocks.stream().filter(block -> !block.getBlockId().equals("air")).findFirst().get(); + blockx.setSpriteState(); + } + boolean dropDefault = true; if (clazz.isAnnotationPresent(CustomDrops.class) || clazz.isAnnotationPresent(CustomDrop.class)) { - var annotations = clazz.isAnnotationPresent(CustomDrops.class) ? - clazz.getAnnotation(CustomDrops.class).value() : - new CustomDrop[] { clazz.getAnnotation(CustomDrop.class) }; + var annotations = clazz.isAnnotationPresent(CustomDrops.class) + ? clazz.getAnnotation(CustomDrops.class).value() + : new CustomDrop[] { clazz.getAnnotation(CustomDrop.class) }; var hashmap = new HashMap(); for (CustomDrop customDrop : annotations) { hashmap.put(customDrop.tool(), new BlockDrop(customDrop.drops(), customDrop.percentage())); } - if (game.getInventory().getItemInHand().isPresent() && hashmap.containsKey(game.getInventory().getItemInHand().get().getId())) { + if (game.getInventory().getItemInHand().isPresent() + && hashmap.containsKey(game.getInventory().getItemInHand().get().getId())) { BlockDrop blockDrop = hashmap.get(game.getInventory().getItemInHand().get().getId()); Random random = new Random(); int num = random.nextInt(100); @@ -103,10 +114,12 @@ public class CustomAnnotationHandler implements CustomPlaceHandler { if (clazz.isAnnotationPresent(TwoblockBlock.class)) { var blocksTop = game.getWorld()[y - 1][x]; if (blocksTop.stream().anyMatch(i -> !i.getBlockId().equals("air") && !i.isMob())) { - blocksTop.removeAll(blocksTop.stream().filter(i -> !i.getBlockId().equals("air") && !i.isMob()).toList()); + blocksTop.removeAll( + blocksTop.stream().filter(i -> !i.getBlockId().equals("air") && !i.isMob()).toList()); } else { var blocksBottom = game.getWorld()[y + 1][x]; - blocksBottom.removeAll(blocksBottom.stream().filter(i -> !i.getBlockId().equals("air") && !i.isMob()).toList()); + blocksBottom.removeAll( + blocksBottom.stream().filter(i -> !i.getBlockId().equals("air") && !i.isMob()).toList()); } } @@ -133,6 +146,17 @@ public class CustomAnnotationHandler implements CustomPlaceHandler { return true; } + private boolean placeFarmable(Game game, int x, int y) { + var blocksBottom = game.getWorld()[y + 1][x]; + System.out.println("lol"); + + if (blocksBottom.stream().noneMatch(block -> block.getBlockId().equals("farmland"))) { + return false; + } + + return true; + } + private void resetDataOnMine(Game game, int x, int y) { var blocks = game.getWorld()[y][x].stream().filter(i -> !i.getBlockId().equals("air")).toList(); @@ -145,8 +169,9 @@ public class CustomAnnotationHandler implements CustomPlaceHandler { Constructor constructor = block.getData().getClass().getDeclaredConstructor(); Object object = constructor.newInstance(); block.setData(object); - } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | - InvocationTargetException _) { + } catch (NoSuchMethodException | IllegalAccessException | InstantiationException + | InvocationTargetException e) { + e.printStackTrace(); } } } diff --git a/src/main/java/cz/jzitnik/game/handlers/place/PlaceHandler.java b/src/main/java/cz/jzitnik/game/handlers/place/PlaceHandler.java index 1152975..daf1379 100644 --- a/src/main/java/cz/jzitnik/game/handlers/place/PlaceHandler.java +++ b/src/main/java/cz/jzitnik/game/handlers/place/PlaceHandler.java @@ -59,15 +59,15 @@ public class PlaceHandler { for (Class clazz : blocks) { var annotation = clazz.getAnnotation(BlockRegistry.class); var id = annotation.value(); - if (clazz.isAnnotationPresent(PlaceOnSolid.class) || clazz.isAnnotationPresent(ResetDataOnMine.class) || clazz.isAnnotationPresent(BlockDropPercentage.class) || clazz.isAnnotationPresent(CustomDrops.class) || clazz.isAnnotationPresent(CustomDrop.class)) { - try { - placeHandlerList.put(id, new CustomAnnotationHandler(clazz)); - } catch (Exception e) { - e.printStackTrace(); - } + if (clazz.isAnnotationPresent(PlaceOnSolid.class) || clazz.isAnnotationPresent(ResetDataOnMine.class) + || clazz.isAnnotationPresent(BlockDropPercentage.class) + || clazz.isAnnotationPresent(CustomDrops.class) || clazz.isAnnotationPresent(CustomDrop.class) + || clazz.isAnnotationPresent(TwoblockBlock.class) || clazz.isAnnotationPresent(ResetSpriteStateOnMine.class)) { + placeHandlerList.put(id, new CustomAnnotationHandler(clazz)); } - if (clazz.isAnnotationPresent(PlaceOnSolid.class) || clazz.isAnnotationPresent(PlaceOnSolidNoHandler.class)) { + if (clazz.isAnnotationPresent(PlaceOnSolid.class) + || clazz.isAnnotationPresent(PlaceOnSolidNoHandler.class)) { placeOnSolid.add(id); } } diff --git a/src/main/java/cz/jzitnik/game/logic/services/farmable/FarmableData.java b/src/main/java/cz/jzitnik/game/logic/services/farmable/FarmableData.java index d69b24c..6e58155 100644 --- a/src/main/java/cz/jzitnik/game/logic/services/farmable/FarmableData.java +++ b/src/main/java/cz/jzitnik/game/logic/services/farmable/FarmableData.java @@ -1,5 +1,11 @@ package cz.jzitnik.game.logic.services.farmable; -public class FarmableData { +import lombok.Getter; +import lombok.Setter; +@Getter +@Setter +public class FarmableData { + private int age = 0; + private int state = 0; } diff --git a/src/main/java/cz/jzitnik/game/logic/services/farmable/FarmableLogic.java b/src/main/java/cz/jzitnik/game/logic/services/farmable/FarmableLogic.java new file mode 100644 index 0000000..52ccb3d --- /dev/null +++ b/src/main/java/cz/jzitnik/game/logic/services/farmable/FarmableLogic.java @@ -0,0 +1,54 @@ +package cz.jzitnik.game.logic.services.farmable; + +import cz.jzitnik.game.Game; +import cz.jzitnik.game.annotations.CustomLogic; +import cz.jzitnik.game.annotations.Farmable; +import cz.jzitnik.game.logic.CustomLogicInterface; + +@CustomLogic +public class FarmableLogic implements CustomLogicInterface { + private static int RADIUS = 50; + private static int GROW_LENGTH = 5; + + @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 y = startY; y <= endY; y++) { + for (int x = startX; x <= endX; x++) { + var blocks = world[y][x]; + + var farmable = blocks.stream().filter(block -> block.getClass().isAnnotationPresent(Farmable.class)).findFirst(); + + if (farmable.isEmpty()) { + continue; + } + + var farmableBlock = farmable.get(); + var farmableData = (FarmableData) farmableBlock.getData(); + + if (farmableData.getAge() >= GROW_LENGTH) { + if (farmableData.getState() >= 2) { + // Fully grown + continue; + } + + farmableData.setState(farmableData.getState() + 1); + farmableData.setAge(0); + farmableBlock.setSpriteState(cz.jzitnik.game.sprites.Farmable.getState(farmableData.getState())); + } else { + farmableData.setAge(farmableData.getAge() + 1); + } + } + } + } + +} diff --git a/src/main/java/cz/jzitnik/game/logic/services/farmland/FarmlandLogic.java b/src/main/java/cz/jzitnik/game/logic/services/farmland/FarmlandLogic.java index be20e92..7534982 100644 --- a/src/main/java/cz/jzitnik/game/logic/services/farmland/FarmlandLogic.java +++ b/src/main/java/cz/jzitnik/game/logic/services/farmland/FarmlandLogic.java @@ -2,6 +2,7 @@ package cz.jzitnik.game.logic.services.farmland; import cz.jzitnik.game.Game; import cz.jzitnik.game.annotations.CustomLogic; +import cz.jzitnik.game.annotations.Farmable; import cz.jzitnik.game.entities.items.ItemBlockSupplier; import cz.jzitnik.game.logic.CustomLogicInterface; import cz.jzitnik.game.sprites.Farmland.FarmlandState; @@ -69,6 +70,8 @@ public class FarmlandLogic implements CustomLogicInterface { if (farmlandData.getDryAge() >= DRY_TO_DIRT_THRESHOLD) { blocks.remove(farmland); blocks.add(ItemBlockSupplier.getBlock("dirt")); + + world[y-1][x].removeIf(block -> block.getClass().isAnnotationPresent(Farmable.class)); farmlandData.setDryAge(0); } } else { diff --git a/src/main/java/cz/jzitnik/game/sprites/Farmable.java b/src/main/java/cz/jzitnik/game/sprites/Farmable.java new file mode 100644 index 0000000..7020ef1 --- /dev/null +++ b/src/main/java/cz/jzitnik/game/sprites/Farmable.java @@ -0,0 +1,49 @@ +package cz.jzitnik.game.sprites; + +import cz.jzitnik.tui.ResourceLoader; +import cz.jzitnik.tui.Sprite; + +import java.util.Optional; + + +public class Farmable extends Sprite { + private String[] textures; + + public Farmable(String first, String second, String third) { + textures = new String[] {first, second, third}; + } + + + public enum FarmableState { + FIRST, + SECOND, + THIRD + } + + public String getSprite() { + return getSprite(getState(0)); + } + + public String getSprite(Enum e) { + return ResourceLoader.loadResource(textures[switch (e) { + case FarmableState.FIRST -> 0; + case FarmableState.SECOND -> 1; + case FarmableState.THIRD -> 2; + default -> throw new IllegalStateException("Unexpected value: " + e); + }]); + } + + public static FarmableState getState(int num) { + return switch (num) { + case 0 -> FarmableState.FIRST; + case 1 -> FarmableState.SECOND; + case 2 -> FarmableState.THIRD; + default -> throw new IllegalStateException("Unexpected value: " + num); + }; + } + + @Override + public Optional> getStates() { + return Optional.of(FarmableState.class); + } +} diff --git a/src/main/java/cz/jzitnik/tui/Sprite.java b/src/main/java/cz/jzitnik/tui/Sprite.java index bdf2182..14a7599 100644 --- a/src/main/java/cz/jzitnik/tui/Sprite.java +++ b/src/main/java/cz/jzitnik/tui/Sprite.java @@ -7,5 +7,5 @@ public abstract class Sprite> { public abstract String getSprite(E key); - public abstract Optional> getStates(); + public abstract Optional> getStates(); }