feat: Implemented furnace

This commit is contained in:
Jakub Žitník 2025-02-27 07:54:33 +01:00
parent 91724dbeb2
commit e6bcce7765
Signed by: jzitnik
GPG Key ID: C577A802A6AF4EF3
26 changed files with 527 additions and 108 deletions

View File

@ -26,7 +26,7 @@
<dependency> <dependency>
<groupId>org.jline</groupId> <groupId>org.jline</groupId>
<artifactId>jline-reader</artifactId> <artifactId>jline-reader</artifactId>
<version>3.20.0</version> <!-- or another stable version --> <version>3.20.0</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -1,12 +1,9 @@
package cz.jzitnik; package cz.jzitnik;
import cz.jzitnik.game.Game; import cz.jzitnik.game.Game;
import cz.jzitnik.game.MouseHandler; import cz.jzitnik.game.ui.*;
import cz.jzitnik.tui.MouseHandler;
import cz.jzitnik.game.SpriteLoader; import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.ui.Chest;
import cz.jzitnik.game.ui.CloseHandler;
import cz.jzitnik.game.ui.Window;
import cz.jzitnik.game.ui.InventoryClickHandler;
import cz.jzitnik.tui.ScreenRenderer; import cz.jzitnik.tui.ScreenRenderer;
import org.jline.terminal.MouseEvent; import org.jline.terminal.MouseEvent;
import org.jline.terminal.Terminal; import org.jline.terminal.Terminal;
@ -53,6 +50,7 @@ public class Main {
case INVENTORY -> InventoryClickHandler.click(mouseEvent, terminal, screenRenderer, game, Optional.empty(), Optional.empty()); case INVENTORY -> InventoryClickHandler.click(mouseEvent, terminal, screenRenderer, game, Optional.empty(), Optional.empty());
case CRAFTING_TABLE -> game.getGameStates().craftingTable.click(mouseEvent, terminal, screenRenderer); case CRAFTING_TABLE -> game.getGameStates().craftingTable.click(mouseEvent, terminal, screenRenderer);
case CHEST -> ((Chest) game.getWorld()[game.getGameStates().clickY][game.getGameStates().clickX].stream().filter(i -> i.getBlockId().equals("chest")).toList().getFirst().getData()).click(game, mouseEvent, terminal, screenRenderer); case CHEST -> ((Chest) game.getWorld()[game.getGameStates().clickY][game.getGameStates().clickX].stream().filter(i -> i.getBlockId().equals("chest")).toList().getFirst().getData()).click(game, mouseEvent, terminal, screenRenderer);
case FURNACE -> ((Furnace) game.getWorld()[game.getGameStates().clickY][game.getGameStates().clickX].stream().filter(i -> i.getBlockId().equals("furnace")).toList().getFirst().getData()).click(game, mouseEvent, terminal, screenRenderer);
} }
} }
} }

View File

@ -5,8 +5,10 @@ import cz.jzitnik.game.items.ItemType;
import cz.jzitnik.game.sprites.Breaking; import cz.jzitnik.game.sprites.Breaking;
import cz.jzitnik.game.sprites.Steve; import cz.jzitnik.game.sprites.Steve;
import cz.jzitnik.game.ui.Chest; import cz.jzitnik.game.ui.Chest;
import cz.jzitnik.game.ui.Furnace;
import cz.jzitnik.game.ui.Window; import cz.jzitnik.game.ui.Window;
import cz.jzitnik.game.ui.Inventory; import cz.jzitnik.game.ui.Inventory;
import cz.jzitnik.tui.RightClickHandler;
import cz.jzitnik.tui.ScreenMovingCalculationProvider; import cz.jzitnik.tui.ScreenMovingCalculationProvider;
import cz.jzitnik.tui.ScreenRenderer; import cz.jzitnik.tui.ScreenRenderer;
import lombok.Getter; import lombok.Getter;
@ -179,7 +181,9 @@ public class Game {
for (Block block : blocks) { for (Block block : blocks) {
if (block.getBlockId().equals("chest")) { if (block.getBlockId().equals("chest")) {
((Chest) block.getData()).breakChest(this); ((Chest) block.getData()).breakBlock(this);
} else if (block.getBlockId().equals("furnace")) {
((Furnace) block.getData()).breakBlock(this);
} }
} }

View File

@ -17,6 +17,7 @@ public class SpriteLoader {
BEDROCK, BEDROCK,
BREAKING, BREAKING,
COBBLESTONE, COBBLESTONE,
FURNACE,
CHEST, CHEST,
CRAFTING_TABLE, CRAFTING_TABLE,
@ -38,6 +39,8 @@ public class SpriteLoader {
ITEM_OAK_PLANKS, ITEM_OAK_PLANKS,
ITEM_STICK, ITEM_STICK,
ITEM_COBBLESTONE, ITEM_COBBLESTONE,
ITEM_STONE,
ITEM_FURNACE,
ITEM_CRAFTING_TABLE, ITEM_CRAFTING_TABLE,
ITEM_CHEST ITEM_CHEST
@ -48,7 +51,7 @@ public class SpriteLoader {
static { static {
SPRITES_MAP.put(SPRITES.AIR, new Air()); SPRITES_MAP.put(SPRITES.AIR, new Air());
SPRITES_MAP.put(SPRITES.DIRT, new SimpleSprite("dirt.ans")); SPRITES_MAP.put(SPRITES.DIRT, new SimpleSprite("dirt.ans"));
SPRITES_MAP.put(SPRITES.GRASS, new Grass()); SPRITES_MAP.put(SPRITES.GRASS, new SimpleSprite("grass.ans"));
SPRITES_MAP.put(SPRITES.STONE, new SimpleSprite("stone.ans")); SPRITES_MAP.put(SPRITES.STONE, new SimpleSprite("stone.ans"));
SPRITES_MAP.put(SPRITES.STEVE, new Steve()); SPRITES_MAP.put(SPRITES.STEVE, new Steve());
SPRITES_MAP.put(SPRITES.BEDROCK, new SimpleSprite("bedrock.ans")); SPRITES_MAP.put(SPRITES.BEDROCK, new SimpleSprite("bedrock.ans"));
@ -59,6 +62,7 @@ public class SpriteLoader {
SPRITES_MAP.put(SPRITES.CRAFTING_TABLE, new SimpleSprite("crafting_table.ans")); SPRITES_MAP.put(SPRITES.CRAFTING_TABLE, new SimpleSprite("crafting_table.ans"));
SPRITES_MAP.put(SPRITES.CHEST, new SimpleSprite("chest.ans")); SPRITES_MAP.put(SPRITES.CHEST, new SimpleSprite("chest.ans"));
SPRITES_MAP.put(SPRITES.COBBLESTONE, new SimpleSprite("cobblestone.ans")); SPRITES_MAP.put(SPRITES.COBBLESTONE, new SimpleSprite("cobblestone.ans"));
SPRITES_MAP.put(SPRITES.FURNACE, new Furnace());
SPRITES_MAP.put(SPRITES.WOODEN_PICKAXE, new SimpleSprite("items/wooden_pickaxe.ans")); SPRITES_MAP.put(SPRITES.WOODEN_PICKAXE, new SimpleSprite("items/wooden_pickaxe.ans"));
SPRITES_MAP.put(SPRITES.STONE_PICKAXE, new SimpleSprite("items/stone_pickaxe.ans")); SPRITES_MAP.put(SPRITES.STONE_PICKAXE, new SimpleSprite("items/stone_pickaxe.ans"));
@ -72,7 +76,9 @@ public class SpriteLoader {
SPRITES_MAP.put(SPRITES.ITEM_STICK, new SimpleSprite("items/stick.ans")); SPRITES_MAP.put(SPRITES.ITEM_STICK, new SimpleSprite("items/stick.ans"));
SPRITES_MAP.put(SPRITES.ITEM_CRAFTING_TABLE, new SimpleSprite("items/crafting_table.ans")); SPRITES_MAP.put(SPRITES.ITEM_CRAFTING_TABLE, new SimpleSprite("items/crafting_table.ans"));
SPRITES_MAP.put(SPRITES.ITEM_COBBLESTONE, new SimpleSprite("items/cobblestone.ans")); SPRITES_MAP.put(SPRITES.ITEM_COBBLESTONE, new SimpleSprite("items/cobblestone.ans"));
SPRITES_MAP.put(SPRITES.ITEM_STONE, new SimpleSprite("items/stone.ans"));
SPRITES_MAP.put(SPRITES.ITEM_CHEST, new SimpleSprite("items/chest.ans")); SPRITES_MAP.put(SPRITES.ITEM_CHEST, new SimpleSprite("items/chest.ans"));
SPRITES_MAP.put(SPRITES.ITEM_FURNACE, new SimpleSprite("items/furnace.ans"));
} }
public static SpriteList<SPRITES> load() { public static SpriteList<SPRITES> load() {

View File

@ -90,10 +90,10 @@ public class CraftingRecipeList {
}, () -> new InventoryItem(1, ItemBlockSupplier.Items.stoneShovel()))); }, () -> new InventoryItem(1, ItemBlockSupplier.Items.stoneShovel())));
recipes.add(new CraftingRecipe(new String[][]{ recipes.add(new CraftingRecipe(new String[][]{
{"dirt", null, null}, {"cobblestone", "cobblestone", "cobblestone"},
{null, null, null}, {"cobblestone", null, "cobblestone"},
{null, null, null} {"cobblestone", "cobblestone", "cobblestone"}
}, () -> new InventoryItem(1, ItemBlockSupplier.Items.chest()))); }, () -> new InventoryItem(1, ItemBlockSupplier.Items.furnace())));
} }
public static Optional<CraftingRecipe> getRecipe(String[] r) { public static Optional<CraftingRecipe> getRecipe(String[] r) {

View File

@ -15,8 +15,10 @@ public class InventoryItem {
public InventoryItem(int amount, Item item) { public InventoryItem(int amount, Item item) {
this.amount = amount; this.amount = amount;
this.item = new ArrayList<>(); this.item = new ArrayList<>();
for (int i = 0; i < amount; i++) {
this.item.add(item); this.item.add(item);
} }
}
public InventoryItem() { public InventoryItem() {
this.item = new ArrayList<>(); this.item = new ArrayList<>();
@ -33,10 +35,6 @@ public class InventoryItem {
item.add(i); item.add(i);
} }
public void setAmount(int amount) {
this.amount = amount;
}
public InventoryItem(Item item) { public InventoryItem(Item item) {
this.amount = 1; this.amount = 1;
this.item = new ArrayList<>(); this.item = new ArrayList<>();

View File

@ -3,6 +3,7 @@ package cz.jzitnik.game.items;
import cz.jzitnik.game.SpriteLoader; import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.Block; import cz.jzitnik.game.Block;
import cz.jzitnik.game.ui.Chest; import cz.jzitnik.game.ui.Chest;
import cz.jzitnik.game.ui.Furnace;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -17,6 +18,9 @@ public class ItemBlockSupplier {
public static Item cobblestone(Block ref) { public static Item cobblestone(Block ref) {
return new Item("cobblestone", "Cobblestone", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_COBBLESTONE, ref); return new Item("cobblestone", "Cobblestone", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_COBBLESTONE, ref);
} }
public static Item stone(Block ref) {
return new Item("stone", "Stone", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_STONE, ref);
}
public static Item oakLog(Block ref) { public static Item oakLog(Block ref) {
return new Item("oak_log", "Oak log", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_OAK_LOG, ref); return new Item("oak_log", "Oak log", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_OAK_LOG, ref);
} }
@ -29,6 +33,9 @@ public class ItemBlockSupplier {
public static Item chest(Block ref) { public static Item chest(Block ref) {
return new Item("chest", "Chest", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_CHEST, ref); return new Item("chest", "Chest", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_CHEST, ref);
} }
public static Item furnace(Block ref) {
return new Item("furnace", "Furnace", ItemType.BLOCK, SpriteLoader.SPRITES.ITEM_FURNACE, ref);
}
} }
public static class Blocks { public static class Blocks {
@ -72,6 +79,12 @@ public class ItemBlockSupplier {
block.setDrops(List.of(Helper.chest(block))); block.setDrops(List.of(Helper.chest(block)));
return block; return block;
} }
public static Block furnace() {
var block = new Block("furnace", SpriteLoader.SPRITES.FURNACE, 15, ItemType.PICKAXE, Arrays.stream(ToolVariant.values()).toList());
block.setData(new Furnace(block));
block.setDrops(List.of(Helper.furnace(block)));
return block;
}
} }
// I hate this but whatever // I hate this but whatever
@ -112,5 +125,11 @@ public class ItemBlockSupplier {
public static Item stoneShovel() { public static Item stoneShovel() {
return new Item("stone_shovel", "Stone shovel", ItemType.SHOVEL, SpriteLoader.SPRITES.STONE_SHOVEL, ToolVariant.STONE, 0.5, 132, false); return new Item("stone_shovel", "Stone shovel", ItemType.SHOVEL, SpriteLoader.SPRITES.STONE_SHOVEL, ToolVariant.STONE, 0.5, 132, false);
} }
public static Item stone() {
return Helper.stone(Blocks.stone());
}
public static Item furnace() {
return Helper.furnace(Blocks.furnace());
}
} }
} }

View File

@ -0,0 +1,21 @@
package cz.jzitnik.game.smelting;
import cz.jzitnik.game.items.Item;
import cz.jzitnik.game.items.ItemBlockSupplier;
import java.util.HashMap;
import java.util.function.Supplier;
public class Smelting {
public static final HashMap<String, Supplier<Item>> smeltingList = new HashMap<>();
static {
smeltingList.put("cobblestone", ItemBlockSupplier.Items::stone);
}
public static final HashMap<String, Double> fuelList = new HashMap<>();
static {
fuelList.put("oak_log", 1.5);
fuelList.put("oak_planks", 1.5);
}
}

View File

@ -0,0 +1,25 @@
package cz.jzitnik.game.sprites;
import cz.jzitnik.tui.ResourceLoader;
import cz.jzitnik.tui.Sprite;
public class Furnace extends Sprite {
public enum FurnaceState {
OFF,
ON,
}
public String getSprite() {
return ResourceLoader.loadResource("furnace.ans");
}
public String getSprite(Enum e) {
return ResourceLoader.loadResource(
switch (e) {
case FurnaceState.OFF -> "furnace.ans";
case FurnaceState.ON -> "furnace2.ans";
default -> throw new IllegalStateException("Unexpected value: " + e);
}
);
}
}

View File

@ -1,14 +0,0 @@
package cz.jzitnik.game.sprites;
import cz.jzitnik.tui.ResourceLoader;
import cz.jzitnik.tui.Sprite;
public class Grass extends Sprite {
public String getSprite() {
return ResourceLoader.loadResource("grass.ans");
}
public String getSprite(Enum key) {
throw new RuntimeException("Imposible state");
}
}

View File

@ -1,15 +1,12 @@
package cz.jzitnik.game.ui; package cz.jzitnik.game.ui;
import cz.jzitnik.game.Game; import cz.jzitnik.game.Game;
import cz.jzitnik.game.crafting.CraftingRecipe;
import cz.jzitnik.game.crafting.CraftingRecipeList;
import cz.jzitnik.game.items.InventoryItem; import cz.jzitnik.game.items.InventoryItem;
import cz.jzitnik.tui.ScreenRenderer; import cz.jzitnik.tui.ScreenRenderer;
import cz.jzitnik.tui.SpriteList; import cz.jzitnik.tui.SpriteList;
import org.jline.terminal.MouseEvent; import org.jline.terminal.MouseEvent;
import org.jline.terminal.Terminal; import org.jline.terminal.Terminal;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -17,7 +14,7 @@ public class Chest {
private static final int ROW_AMOUNT = 4; private static final int ROW_AMOUNT = 4;
private static final int COLUMN_AMOUNT = 6; private static final int COLUMN_AMOUNT = 6;
private static final int CELL_WIDTH = 50; private static final int CELL_WIDTH = 50;
private static final int CELL_HEIGHT = 25; private static final int CELL_HEIGHT = 26;
private static final int BORDER_SIZE = 2; private static final int BORDER_SIZE = 2;
private final InventoryItem[] items = new InventoryItem[ROW_AMOUNT * COLUMN_AMOUNT]; private final InventoryItem[] items = new InventoryItem[ROW_AMOUNT * COLUMN_AMOUNT];
@ -31,10 +28,6 @@ public class Chest {
List<String> sprites = game.getInventory().getSprites(items, spriteList, inventory.getSelectedItemInv() - 50); List<String> sprites = game.getInventory().getSprites(items, spriteList, inventory.getSelectedItemInv() - 50);
Optional<CraftingRecipe> recipe = CraftingRecipeList.getRecipe(Arrays.stream(items).map(item -> item == null ? null: item.getItem().getFirst().getId()).toArray(String[]::new));
Optional<InventoryItem> craftedItem = recipe.map(craftingRecipe -> craftingRecipe.getItemSupplier().get());
for (int i = 0; i < ROW_AMOUNT; i++) { for (int i = 0; i < ROW_AMOUNT; i++) {
for (int j = 0; j < CELL_HEIGHT; j++) { for (int j = 0; j < CELL_HEIGHT; j++) {
buffer.append("\033[0m").append(" ".repeat(moveLeft)); buffer.append("\033[0m").append(" ".repeat(moveLeft));
@ -48,7 +41,7 @@ public class Chest {
buffer.append("\033[0m ".repeat(CELL_WIDTH)); buffer.append("\033[0m ".repeat(CELL_WIDTH));
} else { } else {
String[] spriteLines = sprite.split("\n"); String[] spriteLines = sprite.split("\n");
buffer.append(spriteLines[j + 1]); buffer.append(spriteLines[j - 1]);
} }
} }
buffer.append("\033[38;5;231;48;5;231m▓".repeat(BORDER_SIZE)); buffer.append("\033[38;5;231;48;5;231m▓".repeat(BORDER_SIZE));
@ -68,8 +61,8 @@ public class Chest {
public void click(Game game, MouseEvent mouseEvent, Terminal terminal, ScreenRenderer screenRenderer) { public void click(Game game, MouseEvent mouseEvent, Terminal terminal, ScreenRenderer screenRenderer) {
int x = mouseEvent.getX(); int x = mouseEvent.getX();
int y = mouseEvent.getY(); int y = mouseEvent.getY();
int widthPixels = COLUMN_AMOUNT * (CELL_WIDTH + BORDER_SIZE) + BORDER_SIZE; int widthPixels = COLUMN_AMOUNT * (CELL_WIDTH + BORDER_SIZE) + BORDER_SIZE + 5;
int heightPixels = ROW_AMOUNT * (CELL_HEIGHT + 1); int heightPixels = ROW_AMOUNT * (CELL_HEIGHT) - 10;
int moveLeft = (terminal.getWidth() / 2) - (widthPixels / 2); int moveLeft = (terminal.getWidth() / 2) - (widthPixels / 2);
if (x > moveLeft && x <= moveLeft + widthPixels && y > 0 && y <= heightPixels && mouseEvent.getType() == MouseEvent.Type.Pressed) { if (x > moveLeft && x <= moveLeft + widthPixels && y > 0 && y <= heightPixels && mouseEvent.getType() == MouseEvent.Type.Pressed) {
@ -89,7 +82,7 @@ public class Chest {
InventoryClickHandler.click(mouseEvent, terminal, screenRenderer, game, Optional.of(size + 20), Optional.of(items)); InventoryClickHandler.click(mouseEvent, terminal, screenRenderer, game, Optional.of(size + 20), Optional.of(items));
} }
public void breakChest(Game game) { public void breakBlock(Game game) {
for (var i = 0; i < items.length; i++) { for (var i = 0; i < items.length; i++) {
if (items[i] == null) { if (items[i] == null) {
continue; continue;

View File

@ -14,6 +14,7 @@ public class CloseHandler {
static { static {
handles.put(Window.CRAFTING_TABLE, game -> game.getGameStates().craftingTable.exit()); handles.put(Window.CRAFTING_TABLE, game -> game.getGameStates().craftingTable.exit());
handles.put(Window.INVENTORY, game -> game.getInventory().exit());
} }
public static void handle(Window window, Game game) { public static void handle(Window window, Game game) {

View File

@ -128,7 +128,7 @@ public class CraftingTable {
return; return;
} }
if (x > moveLeft && x <= moveLeft + widthPixels && y > 0 && y <= heightPixels && mouseEvent.getType() == MouseEvent.Type.Pressed) { if (x > moveLeft && x <= moveLeft + widthPixels && y > 0 && y < heightPixels && mouseEvent.getType() == MouseEvent.Type.Pressed) {
if (mouseEvent.getType() != MouseEvent.Type.Pressed) return; if (mouseEvent.getType() != MouseEvent.Type.Pressed) return;
int blockX = (x - moveLeft) / 52; int blockX = (x - moveLeft) / 52;

View File

@ -0,0 +1,257 @@
package cz.jzitnik.game.ui;
import cz.jzitnik.game.Block;
import cz.jzitnik.game.Game;
import cz.jzitnik.game.items.InventoryItem;
import cz.jzitnik.game.items.Item;
import cz.jzitnik.game.smelting.Smelting;
import cz.jzitnik.tui.ScreenRenderer;
import cz.jzitnik.tui.SpriteList;
import cz.jzitnik.tui.utils.Numbers;
import cz.jzitnik.tui.utils.SpriteCombiner;
import org.jline.terminal.MouseEvent;
import org.jline.terminal.Terminal;
import java.util.List;
import java.util.Optional;
public class Furnace {
private final Block block;
private final InventoryItem[] items = new InventoryItem[2];
private InventoryItem outputItem;
private int size;
private boolean smelting;
private static final int COLUMN_AMOUNT = 3;
private static final int CELL_WIDTH = 50;
private static final int CELL_HEIGHT = 27;
private static final int BORDER_SIZE = 2;
public Furnace(Block block) {
this.block = block;
}
public void render(Game game, StringBuilder buffer, Terminal terminal, SpriteList spriteList) {
int widthPixels = COLUMN_AMOUNT * (CELL_WIDTH + BORDER_SIZE) + BORDER_SIZE;
var inventory = game.getInventory();
int moveLeft = (terminal.getWidth() / 2) - (widthPixels / 2);
List<String> sprites = game.getInventory().getSprites(items, spriteList, inventory.getSelectedItemInv() - 50);
String[] outputSprite = outputItem == null ? null : SpriteCombiner.combineTwoSprites(
spriteList.getSprite(outputItem.getItem().getFirst().getSprite()).getSprite(),
Numbers.getNumberSprite(outputItem.getAmount())
).split("\n");
for (int j = 0; j < CELL_HEIGHT; j++) {
buffer.append("\033[0m").append(" ".repeat(moveLeft));
buffer.append("\033[38;5;231;48;5;231m▓".repeat(BORDER_SIZE));
if (j == 0 || j == CELL_HEIGHT - 1) {
buffer.append("\033[38;5;231;48;5;231m▓".repeat(CELL_WIDTH));
} else {
if (items[0] == null) {
buffer.append("\033[0m ".repeat(CELL_WIDTH));
} else {
String sprite = sprites.get(0);
String[] spriteLines = sprite.split("\n");
buffer.append(spriteLines[j - 1]);
}
}
buffer.append("\033[38;5;231;48;5;231m▓".repeat(BORDER_SIZE));
buffer.append("\n");
}
for (int j = 0; j < CELL_HEIGHT; j++) {
buffer.append("\033[0m").append(" ".repeat(moveLeft));
buffer.append("\033[0m").append(" ".repeat(2 * (2 * BORDER_SIZE + CELL_WIDTH)));
buffer.append("\033[38;5;231;48;5;231m▓".repeat(BORDER_SIZE));
if (j == 0 || j == CELL_HEIGHT - 1) {
buffer.append("\033[38;5;231;48;5;231m▓".repeat(CELL_WIDTH));
} else {
if (outputItem == null) {
buffer.append("\033[0m ".repeat(CELL_WIDTH));
} else {
buffer.append(outputSprite[j - 1]);
}
}
buffer.append("\033[38;5;231;48;5;231m▓".repeat(BORDER_SIZE));
buffer.append("\n");
}
for (int j = 0; j < CELL_HEIGHT; j++) {
buffer.append("\033[0m").append(" ".repeat(moveLeft));
buffer.append("\033[38;5;231;48;5;231m▓".repeat(BORDER_SIZE));
if (j == 0 || j == CELL_HEIGHT - 1) {
buffer.append("\033[38;5;231;48;5;231m▓".repeat(CELL_WIDTH));
} else {
if (items[1] == null) {
buffer.append("\033[0m ".repeat(CELL_WIDTH));
} else {
String sprite = sprites.get(1);
String[] spriteLines = sprite.split("\n");
buffer.append(spriteLines[j - 1]);
}
}
buffer.append("\033[38;5;231;48;5;231m▓".repeat(BORDER_SIZE));
buffer.append("\n");
}
buffer.append("\n".repeat(20));
size = buffer.toString().split("\n").length;
game.getInventory().renderFull(buffer, terminal, spriteList, false, Optional.of(size));
}
public void click(Game game, MouseEvent mouseEvent, Terminal terminal, ScreenRenderer screenRenderer) {
int x = mouseEvent.getX();
int y = mouseEvent.getY();
int widthPixels = COLUMN_AMOUNT * (CELL_WIDTH + BORDER_SIZE) + BORDER_SIZE;
int moveLeft = (terminal.getWidth() / 2) - (widthPixels / 2);
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())) {
return;
}
InventoryClickHandler.handleItemClick(mouseEvent, game.getInventory(), items, 0, 50, Optional.of(items));
screenRenderer.render(game);
checkSmelt(game, screenRenderer);
} else if (x > moveLeft + (2 * (2 * BORDER_SIZE + CELL_WIDTH)) && x <= moveLeft + (3 * (2 * BORDER_SIZE + CELL_WIDTH)) && y > CELL_HEIGHT && y <= 2*CELL_HEIGHT && mouseEvent.getType() == MouseEvent.Type.Pressed) {
pickup(game);
screenRenderer.render(game);
} 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())) {
return;
}
InventoryClickHandler.handleItemClick(mouseEvent, game.getInventory(), items, 1, 50, Optional.of(items));
screenRenderer.render(game);
checkSmelt(game, screenRenderer);
} else {
InventoryClickHandler.click(mouseEvent, terminal, screenRenderer, game, Optional.of(size + 20), Optional.of(items));
}
}
public void setSmelting(boolean smelting) {
this.smelting = smelting;
this.block.setSpriteState(smelting ? cz.jzitnik.game.sprites.Furnace.FurnaceState.ON : cz.jzitnik.game.sprites.Furnace.FurnaceState.OFF);
}
public void checkSmelt(Game game, ScreenRenderer screenRenderer) {
if (items[0] == null || items[1] == null) {
return;
}
if (!smelting) {
startSmelting(game, screenRenderer);
}
}
public void rerender(Game game, ScreenRenderer screenRenderer) {
if (game.getWindow() == Window.FURNACE) {
screenRenderer.render(game);
}
}
public void pickup(Game game) {
if (outputItem == null) {
return;
}
game.getInventory().addItem(outputItem);
outputItem = null;
}
public void startSmelting(Game game, ScreenRenderer screenRenderer) {
setSmelting(true);
// Add smelt item
Thread thread1 = new Thread(() -> {
while (true) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (smelting) {
var supplier = Smelting.smeltingList.get(items[0].getItem().getFirst().getId());
if (outputItem == null) {
outputItem = new InventoryItem(1, supplier.get());
} else {
outputItem.add(supplier.get());
}
items[0].decrease();
if (items[0].getAmount() == 0) {
items[0] = null;
}
rerender(game, screenRenderer);
}
if (items[0] == null || !smelting) {
break;
}
}
});
Thread thread2 = new Thread(() -> {
while (true) {
Item fuel = items[1].getItem().getFirst();
double smelts = Smelting.fuelList.get(fuel.getId());
items[1].decrease();
if (items[1].getAmount() == 0) {
items[1] = null;
}
rerender(game, screenRenderer);
try {
Thread.sleep((long) (10000 * smelts));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (items[0] == null || items[1] == null) {
setSmelting(false);
rerender(game, screenRenderer);
break;
}
rerender(game, screenRenderer);
}
});
thread1.start();
thread2.start();
}
public void breakBlock(Game game) {
for (var i = 0; i < items.length; i++) {
if (items[i] == null) {
continue;
}
game.getInventory().addItem(items[i]);
items[i] = null;
}
if (outputItem != null) {
game.getInventory().addItem(outputItem);
outputItem = null;
}
setSmelting(false);
}
}

View File

@ -19,9 +19,9 @@ public class Inventory {
public static final int COLUMN_AMOUNT = 5; public static final int COLUMN_AMOUNT = 5;
public static final int ROW_AMOUNT = 4; public static final int ROW_AMOUNT = 4;
private InventoryItem[] items = new InventoryItem[20]; private final InventoryItem[] items = new InventoryItem[20];
private InventoryItem[] hotbar = new InventoryItem[9]; private final InventoryItem[] hotbar = new InventoryItem[9];
private SmallCraftingTable smallCraftingTable = new SmallCraftingTable( this); private final SmallCraftingTable smallCraftingTable = new SmallCraftingTable( this);
@Setter @Setter
private int itemInhHandIndex = 0; private int itemInhHandIndex = 0;
@ -253,6 +253,14 @@ public class Inventory {
} }
} }
public InventoryItem getSelectedItemNo(Optional<InventoryItem[]> i) {
InventoryDTO data = getItem(selectedItemInv, i);
if (selectedItemInv == -1) {
return null;
}
return data.getObj()[data.getIndex()];
}
public InventoryItem getSelectedItem(Optional<InventoryItem[]> i) { public InventoryItem getSelectedItem(Optional<InventoryItem[]> i) {
InventoryItem temp; InventoryItem temp;
InventoryDTO data = getItem(selectedItemInv, i); InventoryDTO data = getItem(selectedItemInv, i);
@ -267,6 +275,9 @@ public class Inventory {
public InventoryItem getOne(Optional<InventoryItem[]> i) { public InventoryItem getOne(Optional<InventoryItem[]> i) {
InventoryDTO inventoryItem = getItem(selectedItemInv, i); InventoryDTO inventoryItem = getItem(selectedItemInv, i);
if (inventoryItem.getIndex() == -1) {
return null;
}
InventoryItem item = inventoryItem.getObj()[inventoryItem.getIndex()]; InventoryItem item = inventoryItem.getObj()[inventoryItem.getIndex()];
if (item.getAmount() == 1) { if (item.getAmount() == 1) {
return getSelectedItem(i); return getSelectedItem(i);
@ -363,4 +374,17 @@ public class Inventory {
selectedItemInv = -1; selectedItemInv = -1;
} }
} }
public void exit() {
// Put all items from crafting to inv
for (int i = 0; i < smallCraftingTable.getItems().length; i++) {
InventoryItem item = smallCraftingTable.getItems()[i];
if (item == null) {
continue;
}
addItem(item);
smallCraftingTable.getItems()[i] = null;
}
}
} }

View File

@ -38,14 +38,20 @@ public class InventoryClickHandler {
int startLeftCrafting = moveLeft + (COLUMN_AMOUNT * (50 + 4) + 2) + 20; int startLeftCrafting = moveLeft + (COLUMN_AMOUNT * (50 + 4) + 2) + 20;
int startTopCrafting = moveTop + 26; int startTopCrafting = moveTop + 26;
if (x < startLeftCrafting || y < startTopCrafting || x > startLeftCrafting + 167 || y > startTopCrafting + 52) return false; if (x < startLeftCrafting || y < startTopCrafting || x > startLeftCrafting + 166 || y > startTopCrafting + 51) return false;
int craftX = x - startLeftCrafting; int craftX = x - startLeftCrafting;
int craftY = y - startTopCrafting; int craftY = y - startTopCrafting;
if (craftX > 106 && craftY > 10 && craftY < 37) { if (craftX > 116) {
if (craftY > 10 && craftY < 37) {
inventory.getSmallCraftingTable().pickup(); inventory.getSmallCraftingTable().pickup();
screenRenderer.render(game); screenRenderer.render(game);
}
return true;
}
if (craftX > 105) {
return true; return true;
} }
@ -59,7 +65,7 @@ public class InventoryClickHandler {
int startLeftHotbar = (terminal.getWidth() / 2) - (INVENTORY_SIZE_PX / 2) + 2; int startLeftHotbar = (terminal.getWidth() / 2) - (INVENTORY_SIZE_PX / 2) + 2;
int startTopHotbar = moveTop + (ROW_AMOUNT * (25 + 1)) + 10; int startTopHotbar = moveTop + (ROW_AMOUNT * (25 + 1)) + 10;
if (x < startLeftHotbar || y < startTopHotbar || x > startLeftHotbar + INVENTORY_SIZE_PX || y > startTopHotbar + 26) return false; if (x < startLeftHotbar || y < startTopHotbar || x > startLeftHotbar + INVENTORY_SIZE_PX - 2 || y > startTopHotbar + 26) return false;
int index = (x - startLeftHotbar) / 52; int index = (x - startLeftHotbar) / 52;
handleItemClick(mouseEvent, inventory, inventory.getHotbar(), index, 20, i); handleItemClick(mouseEvent, inventory, inventory.getHotbar(), index, 20, i);
@ -74,7 +80,7 @@ public class InventoryClickHandler {
int widthPixels = COLUMN_AMOUNT * (50 + 4) + 2; int widthPixels = COLUMN_AMOUNT * (50 + 4) + 2;
int heightPixels = ROW_AMOUNT * (25 + 1); int heightPixels = ROW_AMOUNT * (25 + 1);
if (fx < 0 || fx > widthPixels || fy < 0 || fy > heightPixels) return; if (fx < 0 || fx > widthPixels - 3 || fy < 0 || fy > heightPixels - 1) return;
int blockIndex = (fy / 26) * COLUMN_AMOUNT + (fx / 54); int blockIndex = (fy / 26) * COLUMN_AMOUNT + (fx / 54);
handleItemClick(mouseEvent, inventory, inventory.getItems(), blockIndex, 0, i); handleItemClick(mouseEvent, inventory, inventory.getItems(), blockIndex, 0, i);

View File

@ -4,5 +4,6 @@ public enum Window {
WORLD, WORLD,
INVENTORY, INVENTORY,
CRAFTING_TABLE, CRAFTING_TABLE,
CHEST CHEST,
FURNACE
} }

View File

@ -1,8 +1,7 @@
package cz.jzitnik.game; package cz.jzitnik.tui;
import cz.jzitnik.game.Game;
import cz.jzitnik.game.ui.Window; import cz.jzitnik.game.ui.Window;
import cz.jzitnik.tui.ScreenMovingCalculationProvider;
import cz.jzitnik.tui.ScreenRenderer;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.jline.terminal.MouseEvent; import org.jline.terminal.MouseEvent;
import org.jline.terminal.Terminal; import org.jline.terminal.Terminal;

View File

@ -1,5 +1,7 @@
package cz.jzitnik.game; package cz.jzitnik.tui;
import cz.jzitnik.game.Block;
import cz.jzitnik.game.Game;
import cz.jzitnik.game.ui.Window; import cz.jzitnik.game.ui.Window;
import java.util.HashMap; import java.util.HashMap;
@ -18,6 +20,7 @@ public class RightClickHandler {
HashMap<String, Function3<Integer, Integer>> functionMap = new HashMap<>(); HashMap<String, Function3<Integer, Integer>> functionMap = new HashMap<>();
functionMap.put("crafting_table", game.getGameStates().craftingTable::render); functionMap.put("crafting_table", game.getGameStates().craftingTable::render);
functionMap.put("chest", (Integer ignored, Integer ignored2) -> game.setWindow(Window.CHEST)); functionMap.put("chest", (Integer ignored, Integer ignored2) -> game.setWindow(Window.CHEST));
functionMap.put("furnace", (Integer ignored, Integer ignored2) -> game.setWindow(Window.FURNACE));
game.getGameStates().clickX = x; game.getGameStates().clickX = x;
game.getGameStates().clickY = y; game.getGameStates().clickY = y;

View File

@ -4,6 +4,7 @@ import cz.jzitnik.game.Block;
import cz.jzitnik.game.Game; import cz.jzitnik.game.Game;
import cz.jzitnik.game.sprites.Steve; import cz.jzitnik.game.sprites.Steve;
import cz.jzitnik.game.ui.Chest; import cz.jzitnik.game.ui.Chest;
import cz.jzitnik.game.ui.Furnace;
import cz.jzitnik.tui.utils.SpriteCombiner; import cz.jzitnik.tui.utils.SpriteCombiner;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -48,6 +49,7 @@ public class ScreenRenderer {
case INVENTORY -> game.getInventory().renderFull(main, terminal, spriteList, true, Optional.empty()); case INVENTORY -> game.getInventory().renderFull(main, terminal, spriteList, true, Optional.empty());
case CRAFTING_TABLE -> game.getGameStates().craftingTable.render(main, terminal, spriteList); case CRAFTING_TABLE -> game.getGameStates().craftingTable.render(main, terminal, spriteList);
case CHEST -> ((Chest) game.getWorld()[game.getGameStates().clickY][game.getGameStates().clickX].stream().filter(i -> i.getBlockId().equals("chest")).toList().getFirst().getData()).render(game, main, terminal, spriteList); case CHEST -> ((Chest) game.getWorld()[game.getGameStates().clickY][game.getGameStates().clickX].stream().filter(i -> i.getBlockId().equals("chest")).toList().getFirst().getData()).render(game, main, terminal, spriteList);
case FURNACE -> ((Furnace) game.getWorld()[game.getGameStates().clickY][game.getGameStates().clickX].stream().filter(i -> i.getBlockId().equals("furnace")).toList().getFirst().getData()).render(game, main, terminal, spriteList);
case WORLD -> { case WORLD -> {
// World // World

View File

@ -1,26 +1,25 @@
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓              
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                   
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                  
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓              
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓             
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                 
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓              
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓             
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓              
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓              
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓         
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓              
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                   
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                    
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓              
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                  
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                  
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓            
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                  
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                  
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓            
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                 
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓       


View File

@ -0,0 +1,25 @@
         
                     
                    
                       
                     
                  
              
                    
             
             
            
                     
                  
                
         
                
                 
                  
                  
              
               
               
             
            
          

View File

@ -0,0 +1,25 @@
                
                       
                      
                       
                         
                    
                 
                     
                       
                    
                
                  
                         
                        
              
                     
                     
                      
                        
                         
                       
                        
                         
                         
                         

View File

@ -0,0 +1,25 @@
                                                 
                                             
                                         
                                    
                                
                            
                          
                        
                        
                         
                          
                        
                         
                      
                          
                          
                          
                        
                     
                         
                              
                                 
                                        
                                             
                                                 

View File

@ -0,0 +1,25 @@
                                                 
                                             
                                        
                                     
                               
                           
                      
                          
                           
                       
                         
                          
                         
                         
                        
                          
                          
                       
                        
                          
                              
                                   
                                        
                                             
                                                 

View File

@ -1,23 +0,0 @@
                         
        ▒▒▒▒▒▒▒▒▒▒       
       ▒ ▓▒▓▒▒▓▒▓ ▒      
       ▒▒▒▒▒▒▒▒▒▒▒▒      
       ▒▒▒ ░░░░ ▒▒▒      
          ░▒▒▒▒▒         
           ▓▒▒▒          
                         
 ▒▓▓▒▒▓            ▒▒▒▒▒▒
 ▒▓▓▒▒▓            ▒▒▒▒▒▒
 ▒▒▒▒▒▓            ▒▒▒▒▒▒
 ▒▒▒▒▓▓            ▒▒▒▒▒▒
 ▒▒▒▒▒▓▒░░░░░░░░   ▒▒▒▒▒▒
 ▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▒░ ▒▒▒▒▓▒
       ▒▒▒▒▒▒▒▒▒▒▒▒      
       ▒▒▒▒▒▒▒▒▒▒▒▒      
       ▒▒▒▒▒▒▒▒▒▒▒▒      
       ▒▒▒▒▒▒▒▒▒▒▒▒      
       ▒▒▒▒▒▒▒▒▒▒▒▒      
       ▒▒▒▒▒▒▒▒▒▒▒▒      
       ▒▒▒▒▒▒▒▒▒▒▒▒      
       ▓▓▓▓▓▓▓▓▓▓▓▓