feat: Twoblock block
Added new Sprite for creating two block tall blocks. This sprite takes 2 sprite files (top, bottom). Also created new annotation that handles breaking and placing two block tall blocks and also manages the sprite state.
This commit is contained in:
@ -1,7 +1,6 @@
|
||||
package cz.jzitnik.game;
|
||||
|
||||
import cz.jzitnik.game.sprites.*;
|
||||
import cz.jzitnik.game.sprites.SimpleSprite;
|
||||
import cz.jzitnik.tui.Sprite;
|
||||
import cz.jzitnik.tui.SpriteList;
|
||||
|
||||
@ -42,6 +41,7 @@ public class SpriteLoader {
|
||||
OXEYE_DAISY,
|
||||
AZURE_BLUET,
|
||||
LILY_OF_THE_VALLEY,
|
||||
LILAC,
|
||||
|
||||
// Ores
|
||||
COAL_ORE,
|
||||
@ -94,6 +94,9 @@ public class SpriteLoader {
|
||||
ITEM_OBSIDIAN,
|
||||
ITEM_SAND,
|
||||
|
||||
// Tall Flowers
|
||||
ITEM_LILAC,
|
||||
|
||||
// Ore Items
|
||||
ITEM_COAL_ORE,
|
||||
ITEM_IRON_ORE,
|
||||
@ -224,6 +227,7 @@ public class SpriteLoader {
|
||||
SPRITES_MAP.put(SPRITES.BLUE_ORCHID, new SimpleSprite("blue_orchid.ans"));
|
||||
SPRITES_MAP.put(SPRITES.OXEYE_DAISY, new SimpleSprite("oxeye_daisy.ans"));
|
||||
SPRITES_MAP.put(SPRITES.AZURE_BLUET, new SimpleSprite("azure_bluet.ans"));
|
||||
SPRITES_MAP.put(SPRITES.LILAC, new TwoBlockSprite("lilac_top.ans", "lilac_bottom.ans"));
|
||||
|
||||
// Grass
|
||||
SPRITES_MAP.put(SPRITES.GRASS_BUSH, new SimpleSprite("grass_bush.ans"));
|
||||
@ -262,6 +266,9 @@ public class SpriteLoader {
|
||||
SPRITES_MAP.put(SPRITES.ITEM_OBSIDIAN, new SimpleSprite("items/obsidian.ans"));
|
||||
SPRITES_MAP.put(SPRITES.ITEM_SAND, new SimpleSprite("items/sand.ans"));
|
||||
|
||||
// Tall flowers
|
||||
SPRITES_MAP.put(SPRITES.ITEM_LILAC, new SimpleSprite("items/lilac.ans"));
|
||||
|
||||
// Ore Items
|
||||
SPRITES_MAP.put(SPRITES.ITEM_COAL_ORE, new SimpleSprite("items/coal_ore.ans"));
|
||||
SPRITES_MAP.put(SPRITES.ITEM_IRON_ORE, new SimpleSprite("items/iron_ore.ans"));
|
||||
|
@ -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;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface BlockBreakAction {
|
||||
String value();
|
||||
}
|
11
src/main/java/cz/jzitnik/game/annotations/TwoblockBlock.java
Normal file
11
src/main/java/cz/jzitnik/game/annotations/TwoblockBlock.java
Normal file
@ -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;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface TwoblockBlock {
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package cz.jzitnik.game.blocks;
|
||||
|
||||
import cz.jzitnik.game.annotations.BlockBreakAction;
|
||||
import cz.jzitnik.game.annotations.RightClickLogic;
|
||||
import cz.jzitnik.game.entities.Block;
|
||||
import cz.jzitnik.game.Game;
|
||||
@ -251,6 +252,7 @@ public class Furnace implements RightClickHandler, Serializable {
|
||||
thread2.start();
|
||||
}
|
||||
|
||||
@BlockBreakAction("furnace")
|
||||
public void breakBlock(Game game) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
if (items[i] == null) {
|
||||
|
@ -0,0 +1,21 @@
|
||||
package cz.jzitnik.game.entities.items.registry.blocks.grassy.flowers;
|
||||
|
||||
import cz.jzitnik.game.SpriteLoader;
|
||||
import cz.jzitnik.game.annotations.BlockRegistry;
|
||||
import cz.jzitnik.game.annotations.BreakableByWater;
|
||||
import cz.jzitnik.game.annotations.BreaksFalling;
|
||||
import cz.jzitnik.game.annotations.PlaceOnSolid;
|
||||
import cz.jzitnik.game.annotations.TwoblockBlock;
|
||||
import cz.jzitnik.game.entities.Block;
|
||||
|
||||
@PlaceOnSolid
|
||||
@BreakableByWater
|
||||
@BreaksFalling
|
||||
@TwoblockBlock
|
||||
@BlockRegistry(value = "lilac")
|
||||
public class LilacBlock extends Block {
|
||||
public LilacBlock() {
|
||||
super("lilac", SpriteLoader.SPRITES.LILAC, 0);
|
||||
setGhost(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package cz.jzitnik.game.entities.items.registry.items.grassy.flowers;
|
||||
|
||||
import cz.jzitnik.game.SpriteLoader;
|
||||
import cz.jzitnik.game.annotations.ItemRegistry;
|
||||
import cz.jzitnik.game.entities.items.Item;
|
||||
import cz.jzitnik.game.entities.items.ItemType;
|
||||
|
||||
@ItemRegistry("lilac")
|
||||
public class LilacItem extends Item {
|
||||
public LilacItem() {
|
||||
super("lilac", "Lilac", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_LILAC);
|
||||
}
|
||||
}
|
@ -34,7 +34,10 @@ public class Generation {
|
||||
world[terrainHeight[256] - 1][256].add(steveBlock2);
|
||||
world[terrainHeight[256] - 2][256].add(steveBlock);
|
||||
|
||||
game.getInventory().addItem(ItemBlockSupplier.getItem("lava_bucket"));
|
||||
game.getInventory().addItem(ItemBlockSupplier.getItem("furnace"));
|
||||
game.getInventory().addItem(ItemBlockSupplier.getItem("coal"));
|
||||
game.getInventory().addItem(ItemBlockSupplier.getItem("oak_log"));
|
||||
game.getInventory().addItem(ItemBlockSupplier.getItem("diamond_pickaxe"));
|
||||
}
|
||||
|
||||
private static void initializeWorld(List<Block>[][] world) {
|
||||
|
@ -0,0 +1,49 @@
|
||||
package cz.jzitnik.game.handlers;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.Scanners;
|
||||
import org.reflections.util.ConfigurationBuilder;
|
||||
|
||||
import cz.jzitnik.game.Game;
|
||||
import cz.jzitnik.game.annotations.MineEventHandler;
|
||||
|
||||
public class BreakBlockActionProvider {
|
||||
private HashMap<String, Function<Game, Void>> actions = new HashMap<>();
|
||||
|
||||
public BreakBlockActionProvider() {
|
||||
register();
|
||||
}
|
||||
|
||||
private void register() {
|
||||
Reflections reflections = new Reflections(
|
||||
new ConfigurationBuilder()
|
||||
.forPackage("cz.jzitnik.game.handlers.events.handlers.mine")
|
||||
.addScanners(Scanners.MethodsAnnotated)
|
||||
);
|
||||
Set<Method> mineHandlers = reflections.getMethodsAnnotatedWith(MineEventHandler.class);
|
||||
|
||||
for (Method method : mineHandlers) {
|
||||
if (method.getParameterCount() == 1 &&
|
||||
method.getParameterTypes()[0] == Game.class)
|
||||
try {
|
||||
Object instance = method.getDeclaringClass().getDeclaredConstructor().newInstance();
|
||||
Function<ScreenRenderer, Game, Integer, Integer> handler = (screenRenderer, game, x, y) -> {
|
||||
try {
|
||||
method.invoke(instance, screenRenderer, game, x, y);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
};
|
||||
this.mineHandlers.add(handler);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import cz.jzitnik.game.Game;
|
||||
import cz.jzitnik.game.annotations.*;
|
||||
import cz.jzitnik.game.entities.Block;
|
||||
import cz.jzitnik.game.entities.items.ItemBlockSupplier;
|
||||
import cz.jzitnik.game.sprites.TwoBlockSprite;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@ -22,11 +23,47 @@ public class CustomAnnotationHandler implements CustomPlaceHandler {
|
||||
|
||||
@Override
|
||||
public boolean place(Game game, int x, int y) {
|
||||
boolean place = true;
|
||||
boolean customPlace = false;
|
||||
if (clazz.isAnnotationPresent(PlaceOnSolid.class)) {
|
||||
return placeOnSolid(game, x, y);
|
||||
place = placeOnSolid(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;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultPlaceHandler.place(game, x, y);
|
||||
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
|
||||
@ -63,6 +100,16 @@ public class CustomAnnotationHandler implements CustomPlaceHandler {
|
||||
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;
|
||||
@ -83,7 +130,7 @@ public class CustomAnnotationHandler implements CustomPlaceHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
return defaultPlaceHandler.place(game, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void resetDataOnMine(Game game, int x, int y) {
|
||||
|
37
src/main/java/cz/jzitnik/game/sprites/TwoBlockSprite.java
Normal file
37
src/main/java/cz/jzitnik/game/sprites/TwoBlockSprite.java
Normal file
@ -0,0 +1,37 @@
|
||||
package cz.jzitnik.game.sprites;
|
||||
|
||||
import cz.jzitnik.tui.ResourceLoader;
|
||||
import cz.jzitnik.tui.Sprite;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class TwoBlockSprite extends Sprite {
|
||||
public enum TwoBlockSpriteState {
|
||||
TOP, BOTTOM
|
||||
}
|
||||
|
||||
private final String top;
|
||||
private final String bottom;
|
||||
|
||||
public TwoBlockSprite(String top, String bottom) {
|
||||
this.top = top;
|
||||
this.bottom = bottom;
|
||||
}
|
||||
|
||||
public String getSprite() {
|
||||
return getSprite(TwoBlockSpriteState.TOP);
|
||||
}
|
||||
|
||||
public String getSprite(Enum key) {
|
||||
return ResourceLoader.loadResource(switch (key) {
|
||||
case TwoBlockSpriteState.TOP -> top;
|
||||
case TwoBlockSpriteState.BOTTOM -> bottom;
|
||||
default -> throw new RuntimeException("Invalid state!");
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Class<Enum>> getStates() {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user