package cz.jzitnik.game.handlers.place; import cz.jzitnik.game.Game; import cz.jzitnik.game.annotations.*; import cz.jzitnik.game.entities.Block; import cz.jzitnik.game.entities.items.InventoryItem; import cz.jzitnik.game.entities.items.ItemBlockSupplier; import cz.jzitnik.game.logic.services.farmable.FarmableData; import cz.jzitnik.game.sprites.TwoBlockSprite; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Random; public class CustomAnnotationHandler implements CustomPlaceHandler { private final Class clazz; private final DefaultPlaceHandler defaultPlaceHandler = new DefaultPlaceHandler(); private final Random random = new Random(); private record BlockDrop(String drops, int percentage) { } public CustomAnnotationHandler(Class clazz) { this.clazz = clazz; } @Override public boolean place(Game game, int x, int y) { boolean place = true; boolean customPlace = false; 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"))) { place = false; } } if (place && clazz.isAnnotationPresent(TwoblockBlock.class)) { var inventory = game.getInventory(); var blocks = game.getWorld()[y][x]; var blocksTop = game.getWorld()[y - 1][x]; Block block = inventory.getItemInHand().get().getBlock().get(); block.setSpriteState(TwoBlockSprite.TwoBlockSpriteState.BOTTOM); blocks.add(block); blocks.removeAll(blocks.stream().filter(Block::isFlowing).toList()); Block block2 = ItemBlockSupplier.getBlock(block.getBlockId()); block2.setSpriteState(TwoBlockSprite.TwoBlockSpriteState.TOP); blocksTop.add(block2); blocksTop.removeAll(blocksTop.stream().filter(Block::isFlowing).toList()); inventory.decreaseItemInHand(); customPlace = true; return true; } if (!customPlace && place) { return defaultPlaceHandler.place(game, x, y); } return false; } @Override public boolean mine(Game game, int x, int y) { boolean dropDefault = true; if (clazz.isAnnotationPresent(Farmable.class)) { var blocks = game.getWorld()[y][x]; var blockx = blocks.stream().filter(block -> !block.getBlockId().equals("air")).findFirst().get(); var data = (FarmableData) blockx.getData(); if (data.getState() == 2) { dropDefault = false; var annotation = clazz.getAnnotation(Farmable.class); var growDrop = annotation.value(); var seedDrop = blockx.getDrops().get(0); var seedDropAmount = random.nextInt(4); if (seedDropAmount != 0) { game.getInventory().addItem(new InventoryItem(seedDropAmount, seedDrop)); } game.getInventory().addItem(ItemBlockSupplier.getItem(growDrop)); } } if (clazz.isAnnotationPresent(ResetDataOnMine.class)) { 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(); } 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 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())) { BlockDrop blockDrop = hashmap.get(game.getInventory().getItemInHand().get().getId()); Random random = new Random(); int num = random.nextInt(100); if (num < blockDrop.percentage) { dropDefault = false; game.getInventory().addItem(ItemBlockSupplier.getItem(blockDrop.drops())); } } } if (dropDefault && clazz.isAnnotationPresent(BlockDropPercentage.class)) { dropDefault = blockDropPercentage(game, x, y); } 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()); } else { var blocksBottom = game.getWorld()[y + 1][x]; blocksBottom.removeAll( blocksBottom.stream().filter(i -> !i.getBlockId().equals("air") && !i.isMob()).toList()); } } defaultPlaceHandler.mine(game, x, y); return dropDefault; } private boolean blockDropPercentage(Game game, int x, int y) { var annotation = clazz.getAnnotation(BlockDropPercentage.class); int percentage = annotation.value(); Random random = new Random(); return random.nextInt(100) < percentage; } private boolean placeOnSolid(Game game, int x, int y) { var blocksBottom = game.getWorld()[y + 1][x]; if (blocksBottom.stream().allMatch(Block::isGhost)) { return false; } return true; } private boolean placeFarmable(Game game, int x, int y) { var blocksBottom = game.getWorld()[y + 1][x]; 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(); for (Block block : blocks) { if (block.getData() == null) { continue; } try { Constructor constructor = block.getData().getClass().getDeclaredConstructor(); Object object = constructor.newInstance(); block.setData(object); } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { e.printStackTrace(); } } } }