236 lines
7.5 KiB
Java

package cz.jzitnik.game;
import cz.jzitnik.game.items.Item;
import cz.jzitnik.game.items.ItemType;
import cz.jzitnik.game.sprites.Breaking;
import cz.jzitnik.tui.ScreenMovingCalculationProvider;
import cz.jzitnik.tui.ScreenRenderer;
import lombok.Getter;
import lombok.Setter;
import org.jline.terminal.Terminal;
import java.util.ArrayList;
import java.util.List;
@Getter
public class Game {
private List<Block>[][] world = new ArrayList[256][512];
@Setter
private Block player;
private boolean mining = false;
private Inventory inventory = new Inventory();
public Game() {
Generation.generateWorld(this);
}
public int calculateHardness(Block block) {
int holdingDecrease = 0;
if (inventory.getItemInHand().isPresent() && block.getTool().isPresent() && inventory.getItemInHand().get().getType().equals(block.getTool().get())) {
holdingDecrease = inventory.getItemInHand().get().getMiningDecrease();
}
int decrease = block.getHardness() - holdingDecrease;
if (decrease < 0) {
decrease = 0;
}
return decrease;
}
public int[] getPlayerCords() {
for (int i = 0; i < world.length; i++) {
for (int j = 0; j < world[i].length; j++) {
for (Block block : world[i][j]) {
if (block.getBlockId().equals("steve")) {
return new int[]{j, i};
}
}
}
}
return null;
}
public void movePlayerRight(ScreenRenderer screenRenderer) {
int[] cords = getPlayerCords();
if (world[cords[1]][cords[0] + 1].stream().anyMatch(block -> !block.isGhost())) {
return;
}
world[cords[1]][cords[0] + 1].add(player);
world[cords[1]][cords[0]].remove(player);
update(screenRenderer);
}
public void movePlayerLeft(ScreenRenderer screenRenderer) {
int[] cords = getPlayerCords();
if (world[cords[1]][cords[0] - 1].stream().anyMatch(block -> !block.isGhost())) {
return;
}
world[cords[1]][cords[0] - 1].add(player);
world[cords[1]][cords[0]].remove(player);
update(screenRenderer);
}
public void movePlayerUp(ScreenRenderer screenRenderer) {
int[] cords = getPlayerCords();
if (world[cords[1] - 1][cords[0]].stream().anyMatch(block -> !block.isGhost()) || world[cords[1] + 1][cords[0]].stream().anyMatch(Block::isGhost)) {
return;
}
world[cords[1] - 1][cords[0]].add(player);
world[cords[1]][cords[0]].remove(player);
new Thread(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
int[] cords2 = getPlayerCords();
if (world[cords2[1] + 1][cords2[0]].stream().allMatch(Block::isGhost)) {
world[cords2[1] + 1][cords2[0]].add(player);
world[cords2[1]][cords2[0]].remove(player);
screenRenderer.render(this);
}
}).start();
}
public void mine(ScreenRenderer screenRenderer, int x, int y) {
if (mining) {
return;
}
Block breakingBlock = new Block("breaking", SpriteLoader.SPRITES.BREAKING);
world[y][x].add(breakingBlock);
screenRenderer.render(this);
int hardness = calculateHardness(world[y][x].stream().filter(block -> !block.isGhost()).toList().get(0));
this.mining = true;
new Thread(() -> {
try {
Thread.sleep(hardness * 166L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
breakingBlock.setSpriteState(Breaking.BreakingState.SECOND);
screenRenderer.render(this);
try {
Thread.sleep(hardness * 166L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
breakingBlock.setSpriteState(Breaking.BreakingState.THIRD);
screenRenderer.render(this);
try {
Thread.sleep(hardness * 166L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
mining = false;
var blocks = world[y][x];
for (Block block : blocks) {
if (!block.isMineable()) {
continue;
}
if (block.getToolVariants().isEmpty()) {
// Add to inv
block.getDrops().forEach(item -> inventory.addItem(item));
continue;
}
var toolVariants = block.getToolVariants();
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())) {
block.getDrops().forEach(item -> inventory.addItem(item));
}
}
blocks.clear();
blocks.add(new Block("air", SpriteLoader.SPRITES.AIR, true, false));
inventory.getItemInHand().ifPresent(Item::use);
screenRenderer.render(this);
update(screenRenderer);
}).start();
}
public boolean isMineable(int x, int y, Terminal terminal) {
List<Block> blocks = world[y][x];
int[] cords = getPlayerCords();
int playerX = cords[0];
int playerY = cords[1];
int distanceX = Math.abs(playerX - x);
int distanceY = Math.abs(playerY - y);
int[] data = ScreenMovingCalculationProvider.calculate(playerX, playerY, terminal.getHeight(), terminal.getWidth(), world[0].length, world.length);
int startX = data[0];
int endX = data[1];
int startY = data[2];
int endY = data[3];
return
y >= startY && y < endY - 1 && x >= startX && x < endX - 1 &&
!blocks.stream().allMatch(block -> block.getBlockId().equals("air"))
&& distanceX <= 5 && distanceY <= 5
&& !(playerX == x && playerY == y)
&& blocks.stream().anyMatch(Block::isMineable);
}
public void update(ScreenRenderer screenRenderer) {
while (true) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
int[] cords2 = getPlayerCords();
if (world[cords2[1] + 1][cords2[0]].stream().allMatch(Block::isGhost)) {
world[cords2[1] + 1][cords2[0]].add(player);
world[cords2[1]][cords2[0]].remove(player);
screenRenderer.render(this);
} else {
break;
}
}
}
public void build(int x, int y, ScreenRenderer screenRenderer) {
var blocks = world[y][x];
if (!blocks.stream().allMatch(Block::isGhost)) {
return;
}
if (!(inventory.getItemInHand().isPresent() && inventory.getItemInHand().get().getType() == ItemType.BLOCK)) {
return;
}
blocks.removeAll(blocks.stream().filter(block -> block.getBlockId().equals("air")).toList());
blocks.add(inventory.getItemInHand().get().getBlock().get());
screenRenderer.render(this);
}
}