twodcraft/src/main/java/cz/jzitnik/game/ui/Inventory.java

393 lines
13 KiB
Java

package cz.jzitnik.game.ui;
import cz.jzitnik.game.items.InventoryItem;
import cz.jzitnik.game.items.Item;
import cz.jzitnik.tui.utils.SpriteCombiner;
import cz.jzitnik.tui.SpriteList;
import cz.jzitnik.tui.utils.Numbers;
import lombok.Getter;
import lombok.Setter;
import org.jline.terminal.Terminal;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Getter
public class Inventory {
public static final int INVENTORY_SIZE_PX = 470;
public static final int COLUMN_AMOUNT = 5;
public static final int ROW_AMOUNT = 4;
private final InventoryItem[] items = new InventoryItem[20];
private final InventoryItem[] hotbar = new InventoryItem[9];
private final SmallCraftingTable smallCraftingTable = new SmallCraftingTable( this);
@Setter
private int itemInhHandIndex = 0;
@Setter
private int selectedItemInv = -1;
@Setter
private boolean rightClick = false;
public Optional<Item> getItemInHand() {
if (hotbar[itemInhHandIndex] == null) {
return Optional.empty();
}
return Optional.of(hotbar[itemInhHandIndex].getItem().getLast());
}
public void decreaseItemInHand() {
if (hotbar[itemInhHandIndex] == null) {
return;
}
if (hotbar[itemInhHandIndex].getAmount() == 1) {
hotbar[itemInhHandIndex] = null;
return;
}
hotbar[itemInhHandIndex].decrease();
}
private void placeItem(Item item) {
var inventoryItem = new InventoryItem(item);
// Try to place to hotbar
for (int i = 0; i < hotbar.length; i++) {
if (hotbar[i] == null) {
hotbar[i] = inventoryItem;
return;
}
}
// Try to place to inventory
for (int i = 0; i < items.length; i++) {
if (items[i] == null) {
items[i] = inventoryItem;
break;
}
}
// If inventory is full the item is lost
}
public void addItem(InventoryItem item) {
for (int i = 0; i < item.getAmount(); i++) {
addItem(item.getItem().get(i));
}
}
public void addItem(Item item) {
if (!item.isStackable()) {
placeItem(item);
return;
}
// Try to stack in hotbar
for (InventoryItem value : hotbar) {
if (value != null && value.getItem().getFirst().equals(item) && value.getAmount() < item.getStackAmount()) {
value.add(item);
return;
}
}
// Try to stack in inventory
for (InventoryItem inventoryItem : items) {
if (inventoryItem != null && inventoryItem.getItem().getFirst().equals(item) && inventoryItem.getAmount() < item.getStackAmount()) {
inventoryItem.add(item);
return;
}
}
// If stacking didn't work try to add it to inventory
placeItem(item);
}
private String getHotbarBackground() {
StringBuilder sprite = new StringBuilder();
for (int i = 0; i < 25; i++) {
sprite.append("\033[38;5;245;48;5;245m▓".repeat(50));
sprite.append("\n");
}
return sprite.toString();
}
public void renderHotbar(StringBuilder buffer, SpriteList spriteList, Terminal terminal, boolean isFull) {
int termWidth = terminal.getWidth();
int startLeft = (termWidth / 2) - (INVENTORY_SIZE_PX / 2);
List<String> sprites = getSprites(hotbar, spriteList, (isFull ? selectedItemInv - 20 : itemInhHandIndex));
for (int i = 0; i < 26; i++) {
// Empty left space
buffer.append("\033[0m ".repeat(Math.max(0, startLeft)));
if (i == 0 || i == 25) {
buffer.append("\033[38;5;231;48;5;231m▓".repeat(INVENTORY_SIZE_PX - 2));
} else {
for (int j = 0; j < 9; j++) {
buffer.append("\033[38;5;231;48;5;231m▓".repeat(2));
if (sprites.get(j) == null) {
buffer.append("\033[0m ".repeat(50));
continue;
}
String x = sprites.get(j).split("\n")[i];
buffer.append(x);
}
}
buffer.append("\033[38;5;231;48;5;231m▓".repeat(2));
buffer.append("\033[0m\n");
}
}
public void renderFull(StringBuilder buffer, Terminal terminal, SpriteList spriteList, boolean includeCrafting, Optional<Integer> moveTopCustom) {
int widthPixels = COLUMN_AMOUNT * (50 + 4) + 2;
int heightPixels = ROW_AMOUNT * (25 + 1);
int moveLeft = Math.max(0, (terminal.getWidth() / 2) - (widthPixels / 2));
int moveTop = moveTopCustom.orElse((terminal.getHeight() / 2) - (heightPixels / 2));
List<String> sprites = getSprites(items, spriteList, selectedItemInv);
// Top center
buffer.append("\n".repeat(Math.max(0, moveTopCustom.isPresent() ? 0 : moveTop)));
buffer.append("\033[0m ".repeat(moveLeft));
buffer.append("\033[38;5;231;48;5;231m▓".repeat(widthPixels)).append("\033[0m\n");
String[] craftingTable = smallCraftingTable.render(spriteList).toString().split("\n");
int spacesFromTop = (ROW_AMOUNT - SmallCraftingTable.ROW_AMOUNT) / 2;
for (int i = 0; i < ROW_AMOUNT; i++) {
for (int j = 0; j < 26; j++) {
buffer.append("\033[0m ".repeat(moveLeft));
if (j < 25) {
buffer.append("\033[38;5;231;48;5;231m▓");
for (int k = 0; k < COLUMN_AMOUNT; k++) {
buffer.append("\033[38;5;231;48;5;231m▓".repeat(2));
var item = items[i * COLUMN_AMOUNT + k];
if (item == null) {
buffer.append("\033[0m ".repeat(50));
buffer.append("\033[38;5;231;48;5;231m▓".repeat(2));
continue;
}
var sprite = sprites.get(i * COLUMN_AMOUNT + k).split("\n");
buffer.append(sprite[j]);
buffer.append("\033[38;5;231;48;5;231m▓".repeat(2));
}
buffer.append("\033[38;5;231;48;5;231m▓");
} else {
buffer.append("\033[38;5;231;48;5;231m▓".repeat(widthPixels));
if (i == 0 && includeCrafting) {
buffer.append("\033[0m").append(" ".repeat(20));
buffer.append("\033[38;5;231;48;5;231m▓".repeat(106));
}
}
if (i + 1 > spacesFromTop && includeCrafting) {
int craftingIndex = ((i - spacesFromTop) * 26) + j;
if (craftingIndex < craftingTable.length) {
buffer.append("\033[0m").append(" ".repeat(20));
buffer.append(craftingTable[craftingIndex]);
}
}
buffer.append("\n");
}
}
buffer.append("\n".repeat(10));
renderHotbar(buffer, spriteList, terminal, true);
}
public List<String> getSprites(InventoryItem[] items, SpriteList spriteList, int selectedItem) {
List<String> sprites = new ArrayList<>();
for (int i = 0; i < items.length; i++) {
var item = items[i];
if (item == null) {
if (i == selectedItem) {
sprites.add(getHotbarBackground());
continue;
}
sprites.add(null);
continue;
}
if (i == selectedItem) {
sprites.add(SpriteCombiner.combineTwoSprites(getHotbarBackground(), SpriteCombiner.combineTwoSprites(
spriteList.getSprite(item.getItem().getFirst().getSprite()).getSprite(),
Numbers.getNumberSprite(item.getAmount())
)));
continue;
}
sprites.add(SpriteCombiner.combineTwoSprites(
spriteList.getSprite(item.getItem().getFirst().getSprite()).getSprite(),
Numbers.getNumberSprite(item.getAmount())
));
}
return sprites;
}
public InventoryDTO getItem(int index, Optional<InventoryItem[]> i) {
if (index < 20) {
// Normal inventory
return new InventoryDTO(items, index);
} else if (index >= 50) {
return new InventoryDTO(i.get(), index - 50);
} else if (index >= 29) {
// Small crafting table
return new InventoryDTO(smallCraftingTable.getItems(), index - 29);
} else {
// Hotbar
return new InventoryDTO(hotbar, index - 20);
}
}
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) {
InventoryItem temp;
InventoryDTO data = getItem(selectedItemInv, i);
temp = data.getObj()[data.getIndex()];
data.getObj()[data.getIndex()] = null;
selectedItemInv = -1;
rightClick = false;
return temp;
}
public InventoryItem getOne(Optional<InventoryItem[]> i) {
InventoryDTO inventoryItem = getItem(selectedItemInv, i);
if (inventoryItem.getIndex() == -1) {
return null;
}
InventoryItem item = inventoryItem.getObj()[inventoryItem.getIndex()];
if (item.getAmount() == 1) {
return getSelectedItem(i);
}
rightClick = false;
var ij = new InventoryItem(1, item.getItem().getLast());
item.decrease();
return ij;
}
public InventoryItem getHalf(Optional<InventoryItem[]> i) {
InventoryDTO inventoryItem = getItem(selectedItemInv, i);
InventoryItem item = inventoryItem.getObj()[inventoryItem.getIndex()];
if (item.getAmount() == 1) {
return getSelectedItem(i);
}
int half = item.getAmount() / 2;
var inv = new InventoryItem();
for (int j = 0; j < half; j++) {
inv.add(item.getItem().getLast());
item.decrease();
}
selectedItemInv = -1;
rightClick = false;
return inv;
}
public boolean hasSelectedItem() {
return selectedItemInv != -1;
}
public boolean mergeItems(int indexFrom, int indexTo, Optional<InventoryItem[]> i) {
InventoryDTO fromData = getItem(indexFrom, i);
InventoryDTO toData = getItem(indexTo, i);
InventoryItem fromItem = fromData.getObj()[fromData.getIndex()];
InventoryItem toItem = toData.getObj()[toData.getIndex()];
if (fromItem == null || toItem == null) {
return false; // Nothing to merge
}
if (!fromItem.getItem().getFirst().isStackable() || !toItem.getItem().getFirst().isStackable()) {
return false;
}
if (!fromItem.getItem().getFirst().equals(toItem.getItem().getFirst())) {
return false; // Different items cannot be merged
}
while (true) {
if (toItem.getAmount() == 64) {
break;
}
if (fromItem.getAmount() == 0) {
fromData.getObj()[fromData.getIndex()] = null;
break;
}
toItem.add(fromItem.getItem().getLast());
fromItem.decrease();
}
selectedItemInv = -1;
return true;
}
public void mergeOne(int fromIndex, int toIndex, Optional<InventoryItem[]> i) {
InventoryDTO fromSlot = getItem(fromIndex, i);
InventoryDTO toSlot = getItem(toIndex, i);
InventoryItem fromItem = fromSlot.getObj()[fromSlot.getIndex()];
InventoryItem toItem = toSlot.getObj()[toSlot.getIndex()];
if (fromItem == null || !fromItem.getItem().getFirst().equals(toItem.getItem().getFirst()) || toItem.getAmount() >= fromItem.getItem().getFirst().getStackAmount()) {
return; // Can't merge
}
// Move only one item
toItem.add(fromItem.getItem().getLast());
fromItem.decrease();
// Remove source item if empty
if (fromItem.getAmount() <= 0) {
fromSlot.getObj()[fromSlot.getIndex()] = null;
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;
}
}
}