twodcraft/src/main/java/cz/jzitnik/game/handlers/place/CustomAnnotationHandler.java
2025-03-25 12:58:14 +01:00

203 lines
7.3 KiB
Java

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<String, BlockDrop>();
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();
}
}
}
}