refactor: Rewritten smelting using annotations

This commit is contained in:
Jakub Žitník 2025-03-13 23:12:18 +01:00
parent 412959d456
commit 9aa08dd685
Signed by: jzitnik
GPG Key ID: C577A802A6AF4EF3
27 changed files with 114 additions and 33 deletions

View File

@ -239,7 +239,8 @@ public class Game implements Serializable {
if (inventory.getItemInHand().isPresent()
&& inventory.getItemInHand().get().getToolVariant().isPresent() && block.getTool().isPresent()
&& block.getTool().get().equals(inventory.getItemInHand().get().getType())
&& toolVariants.contains(inventory.getItemInHand().get().getToolVariant().get()) && minedDirectly) {
&& toolVariants.contains(inventory.getItemInHand().get().getToolVariant().get())
&& minedDirectly) {
block.getDrops().forEach(inventory::addItem);
}
}

View File

@ -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.TYPE)
public @interface Fuel {
double value();
}

View File

@ -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.TYPE)
public @interface Smeltable {
String value();
}

View File

@ -127,7 +127,7 @@ public class Furnace implements RightClickHandler, Serializable {
if (x > moveLeft && x <= moveLeft + CELL_WIDTH + BORDER_SIZE && y > 0 && y < CELL_HEIGHT
&& mouseEvent.getType() == MouseEvent.Type.Pressed) {
InventoryItem selectedItem = game.getInventory().getSelectedItemNo(Optional.of(items));
if (selectedItem != null && !Smelting.smeltingList.containsKey(selectedItem.getItem().getFirst().getId())) {
if (selectedItem != null && !game.getGameStates().dependencies.smelting.smeltingList.containsKey(selectedItem.getItem().getFirst().getId())) {
return;
}
@ -143,7 +143,7 @@ public class Furnace implements RightClickHandler, Serializable {
} else if (x > moveLeft && x <= moveLeft + CELL_WIDTH + BORDER_SIZE && y > 2 * CELL_HEIGHT
&& y < 3 * CELL_HEIGHT && mouseEvent.getType() == MouseEvent.Type.Pressed) {
InventoryItem selectedItem = game.getInventory().getSelectedItemNo(Optional.of(items));
if (selectedItem != null && !Smelting.fuelList.containsKey(selectedItem.getItem().getFirst().getId())) {
if (selectedItem != null && !game.getGameStates().dependencies.smelting.fuelList.containsKey(selectedItem.getItem().getFirst().getId())) {
return;
}
@ -201,7 +201,7 @@ public class Furnace implements RightClickHandler, Serializable {
}
if (smelting) {
var supplier = Smelting.smeltingList.get(items[0].getItem().getFirst().getId());
var supplier = game.getGameStates().dependencies.smelting.smeltingList.get(items[0].getItem().getFirst().getId());
if (outputItem == null) {
outputItem = new InventoryItem(1, supplier.get());
} else {
@ -224,7 +224,7 @@ public class Furnace implements RightClickHandler, Serializable {
Thread thread2 = new Thread(() -> {
while (true) {
Item fuel = items[1].getItem().getFirst();
double smelts = Smelting.fuelList.get(fuel.getId());
double smelts = game.getGameStates().dependencies.smelting.fuelList.get(fuel.getId());
items[1].decrease();
if (items[1].getAmount() == 0) {

View File

@ -6,6 +6,7 @@ import cz.jzitnik.game.handlers.pickup.PickupHandlerProvider;
import cz.jzitnik.game.handlers.place.PlaceHandler;
import cz.jzitnik.game.mobs.EntityHurtAnimation;
import cz.jzitnik.game.mobs.EntityKill;
import cz.jzitnik.game.smelting.Smelting;
public class Dependencies {
public PlaceHandler placeHandler = new PlaceHandler();
@ -14,4 +15,5 @@ public class Dependencies {
public PickupHandlerProvider pickupHandlerProvider = new PickupHandlerProvider();
public GameSaver gameSaver = new GameSaver();
public EventHandlerProvider eventHandlerProvider = new EventHandlerProvider();
public Smelting smelting = new Smelting();
}

View File

@ -2,9 +2,11 @@ package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.annotations.Smeltable;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Smeltable("steak")
@ItemRegistry("beef")
public class BeefItem extends Item {
public BeefItem() {

View File

@ -1,10 +1,12 @@
package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.Fuel;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Fuel(80.0)
@ItemRegistry("coal_block")
public class CoalBlockItem extends Item {
public CoalBlockItem() {

View File

@ -1,10 +1,12 @@
package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.Fuel;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Fuel(8.0)
@ItemRegistry("coal")
public class CoalItem extends Item {
public CoalItem() {

View File

@ -2,9 +2,11 @@ package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.annotations.Smeltable;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Smeltable("stone")
@ItemRegistry("cobblestone")
public class CobblestoneItem extends Item {
public CobblestoneItem() {

View File

@ -2,9 +2,11 @@ package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.annotations.Smeltable;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Smeltable("diamond")
@ItemRegistry("diamond_ore")
public class DiamondOreItem extends Item {
public DiamondOreItem() {

View File

@ -2,9 +2,11 @@ package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.annotations.Smeltable;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Smeltable("gold_ingot")
@ItemRegistry("gold_ore")
public class GoldOreItem extends Item {
public GoldOreItem() {

View File

@ -2,9 +2,11 @@ package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.annotations.Smeltable;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Smeltable("iron_ingot")
@ItemRegistry("iron_ore")
public class IronOreItem extends Item {
public IronOreItem() {

View File

@ -1,10 +1,12 @@
package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.Fuel;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Fuel(100.0)
@ItemRegistry(value = "lava_bucket", block = "lava")
public class LavaBucketItem extends Item {
public LavaBucketItem() {

View File

@ -2,9 +2,11 @@ package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.annotations.Smeltable;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Smeltable("cooked_mutton")
@ItemRegistry("mutton")
public class MuttonItem extends Item {
public MuttonItem() {

View File

@ -1,10 +1,14 @@
package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.Fuel;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.annotations.Smeltable;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Smeltable("coal")
@Fuel(1.5)
@ItemRegistry("oak_log")
public class OakLogItem extends Item {
public OakLogItem() {

View File

@ -1,10 +1,12 @@
package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.Fuel;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Fuel(1.5)
@ItemRegistry("oak_planks")
public class OakPlanksItem extends Item {
public OakPlanksItem() {

View File

@ -2,9 +2,11 @@ package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.annotations.Smeltable;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Smeltable("cooked_porkchop")
@ItemRegistry("porkchop")
public class PorkchopItem extends Item {
public PorkchopItem() {

View File

@ -1,10 +1,12 @@
package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.Fuel;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
@Fuel(0.5)
@ItemRegistry("stick")
public class StickItem extends Item {
public StickItem() {

View File

@ -1,11 +1,13 @@
package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.Fuel;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
import cz.jzitnik.game.entities.items.ToolVariant;
@Fuel(1.0)
@ItemRegistry("wooden_axe")
public class WoodenAxeItem extends Item {
public WoodenAxeItem() {

View File

@ -1,11 +1,13 @@
package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.Fuel;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
import cz.jzitnik.game.entities.items.ToolVariant;
@Fuel(1.0)
@ItemRegistry("wooden_hoe")
public class WoodenHoe extends Item {
public WoodenHoe() {

View File

@ -1,11 +1,13 @@
package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.Fuel;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
import cz.jzitnik.game.entities.items.ToolVariant;
@Fuel(1.0)
@ItemRegistry("wooden_pickaxe")
public class WoodenPickaxeItem extends Item {
public WoodenPickaxeItem() {

View File

@ -1,11 +1,13 @@
package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.Fuel;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
import cz.jzitnik.game.entities.items.ToolVariant;
@Fuel(1.0)
@ItemRegistry("wooden_shovel")
public class WoodenShovelItem extends Item {
public WoodenShovelItem() {

View File

@ -2,10 +2,12 @@ package cz.jzitnik.game.entities.items.registry.items;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.annotations.Fuel;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemType;
import cz.jzitnik.game.entities.items.ToolVariant;
@Fuel(1.0)
@ItemRegistry("wooden_sword")
public class WoodenSword extends Item {
public WoodenSword() {

View File

@ -1,6 +1,7 @@
package cz.jzitnik.game.generation;
import cz.jzitnik.game.entities.Block;
import cz.jzitnik.game.entities.items.ItemBlockSupplier;
import cz.jzitnik.game.Game;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.sprites.Steve;
@ -32,6 +33,10 @@ public class Generation {
// Spawn player at a valid starting point
world[terrainHeight[256] - 1][256].add(steveBlock2);
world[terrainHeight[256] - 2][256].add(steveBlock);
game.getInventory().addItem(ItemBlockSupplier.getItem("furnace"));
game.getInventory().addItem(ItemBlockSupplier.getItem("coal"));
game.getInventory().addItem(ItemBlockSupplier.getItem("mutton"));
}
private static void initializeWorld(List<Block>[][] world) {

View File

@ -30,13 +30,17 @@ public class GrassGrowingLogic implements CustomLogicInterface {
List<Block> blocks = world[y][x];
if (blocks.stream().anyMatch(block -> block.getBlockId().equals("dirt"))) {
// Dirt
if (world[y - 1][x].stream().allMatch(block -> block.isGhost() || block.isMob() || block.getBlockId().equals("air")) && random.nextInt(3) < 1 && isGrassBesides(world, x, y)) {
if (world[y - 1][x].stream()
.allMatch(block -> block.isGhost() || block.isMob() || block.getBlockId().equals("air"))
&& random.nextInt(3) < 1 && isGrassBesides(world, x, y)) {
world[y][x].removeIf(block -> block.getBlockId().equals("dirt"));
world[y][x].add(ItemBlockSupplier.getBlock("grass"));
}
} else if (blocks.stream().anyMatch(block -> block.getBlockId().equals("grass"))) {
// Grass
if (!world[y - 1][x].stream().allMatch(block -> block.isGhost() || block.isMob() || block.getBlockId().equals("air")) && random.nextInt(3) < 1) {
if (!world[y - 1][x].stream()
.allMatch(block -> block.isGhost() || block.isMob() || block.getBlockId().equals("air"))
&& random.nextInt(3) < 1) {
world[y][x].removeIf(block -> block.getBlockId().equals("grass"));
world[y][x].add(ItemBlockSupplier.getBlock("dirt"));
}

View File

@ -1,36 +1,41 @@
package cz.jzitnik.game.smelting;
import cz.jzitnik.game.annotations.Fuel;
import cz.jzitnik.game.annotations.ItemRegistry;
import cz.jzitnik.game.annotations.Smeltable;
import cz.jzitnik.game.entities.items.Item;
import cz.jzitnik.game.entities.items.ItemBlockSupplier;
import java.util.HashMap;
import java.util.Set;
import java.util.function.Supplier;
import org.reflections.Reflections;
public class Smelting {
public static final HashMap<String, Supplier<Item>> smeltingList = new HashMap<>();
static {
smeltingList.put("cobblestone", () -> ItemBlockSupplier.getItem("stone"));
smeltingList.put("porkchop", () -> ItemBlockSupplier.getItem("cooked_porkchop"));
smeltingList.put("mutton", () -> ItemBlockSupplier.getItem("cooked_mutton"));
smeltingList.put("iron_ore", () -> ItemBlockSupplier.getItem("iron_ingot"));
smeltingList.put("gold_ore", () -> ItemBlockSupplier.getItem("gold_ingot"));
smeltingList.put("oak_log", () -> ItemBlockSupplier.getItem("coal"));
smeltingList.put("beef", () -> ItemBlockSupplier.getItem("steak"));
smeltingList.put("diamond_ore", () -> ItemBlockSupplier.getItem("diamond"));
public final HashMap<String, Supplier<Item>> smeltingList = new HashMap<>();
public final HashMap<String, Double> fuelList = new HashMap<>();
public Smelting() {
register();
}
public static final HashMap<String, Double> fuelList = new HashMap<>();
static {
fuelList.put("oak_log", 1.5);
fuelList.put("oak_planks", 1.5);
fuelList.put("coal", 8.0);
fuelList.put("coal_block", 80.0);
fuelList.put("wooden_sword", 1.0);
fuelList.put("wooden_pickaxe", 1.0);
fuelList.put("wooden_axe", 1.0);
fuelList.put("wooden_shovel", 1.0);
fuelList.put("wooden_hoe", 1.0);
fuelList.put("stick", 0.5);
fuelList.put("lava_bucket", 100.0);
private void register() {
Reflections reflections = new Reflections("cz.jzitnik.game.entities.items.registry.items");
Set<Class<?>> handlerClasses = reflections
.getTypesAnnotatedWith(ItemRegistry.class);
for (Class<?> clazz : handlerClasses) {
var itemAnnotation = clazz.getAnnotation(ItemRegistry.class);
String id = itemAnnotation.value();
if (clazz.isAnnotationPresent(Fuel.class)) {
var fuelAnnotation = clazz.getAnnotation(Fuel.class);
fuelList.put(id, fuelAnnotation.value());
}
if (clazz.isAnnotationPresent(Smeltable.class)) {
var smeltableAnnotation = clazz.getAnnotation(Smeltable.class);
smeltingList.put(id, () -> ItemBlockSupplier.getItem(smeltableAnnotation.value()));
}
}
}
}

View File

@ -13,16 +13,18 @@ public class SmeltingTest {
@Test
@DisplayName("Verity that all items in Smelting are actual items")
void testAllItems() {
for (String item : Smelting.smeltingList.keySet()) {
Smelting smelting = new Smelting();
for (String item : smelting.smeltingList.keySet()) {
assertDoesNotThrow(() -> ItemBlockSupplier.getItem(item),
"Item " + item + "does not exist but is present as source in Smelting.");
}
for (Supplier<Item> supplier : Smelting.smeltingList.values()) {
for (Supplier<Item> supplier : smelting.smeltingList.values()) {
assertDoesNotThrow(supplier::get, "Item does not exist but is present as result in Smelting.");
}
for (String fuel : Smelting.fuelList.keySet()) {
for (String fuel : smelting.fuelList.keySet()) {
assertDoesNotThrow(() -> ItemBlockSupplier.getItem(fuel),
"Item " + fuel + " does not exist but is present as fuel in Smelting.");
}