forked from jzitnik/twodcraft
feat: Implemented lava and infinite water source
This commit is contained in:
parent
8aa0cba5df
commit
2065f8ea2a
@ -3,15 +3,10 @@ package cz.jzitnik.game.crafting.recipes;
|
|||||||
import cz.jzitnik.game.annotations.CraftingRecipeRegistry;
|
import cz.jzitnik.game.annotations.CraftingRecipeRegistry;
|
||||||
|
|
||||||
@CraftingRecipeRegistry(
|
@CraftingRecipeRegistry(
|
||||||
/*recipe = {
|
recipe = {
|
||||||
"iron_ingot", "_", "iron_ingot",
|
"iron_ingot", "_", "iron_ingot",
|
||||||
"_", "iron_ingot", "_",
|
"_", "iron_ingot", "_",
|
||||||
"_", "_", "_"
|
"_", "_", "_"
|
||||||
},*/
|
|
||||||
recipe = {
|
|
||||||
"dirt", "_", "_",
|
|
||||||
"_", "_", "_",
|
|
||||||
"_", "_", "_"
|
|
||||||
},
|
},
|
||||||
result = "bucket",
|
result = "bucket",
|
||||||
amount = 1
|
amount = 1
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package cz.jzitnik.game.entities.items.registry.blocks;
|
||||||
|
|
||||||
|
import cz.jzitnik.game.SpriteLoader;
|
||||||
|
import cz.jzitnik.game.annotations.BlockRegistry;
|
||||||
|
import cz.jzitnik.game.entities.Block;
|
||||||
|
import cz.jzitnik.game.logic.services.flowing.lava.LavaData;
|
||||||
|
import cz.jzitnik.game.sprites.Lava;
|
||||||
|
|
||||||
|
@BlockRegistry(value = "lava", drops = "lava_bucket")
|
||||||
|
public class LavaBlock extends Block {
|
||||||
|
public LavaBlock() {
|
||||||
|
super("lava", SpriteLoader.SPRITES.LAVA);
|
||||||
|
setMineable(false);
|
||||||
|
setSpriteState(Lava.LavaState.FIRST);
|
||||||
|
setData(new LavaData());
|
||||||
|
setFlowing(true);
|
||||||
|
setGhost(true);
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@ package cz.jzitnik.game.entities.items.registry.blocks;
|
|||||||
import cz.jzitnik.game.SpriteLoader;
|
import cz.jzitnik.game.SpriteLoader;
|
||||||
import cz.jzitnik.game.annotations.BlockRegistry;
|
import cz.jzitnik.game.annotations.BlockRegistry;
|
||||||
import cz.jzitnik.game.entities.Block;
|
import cz.jzitnik.game.entities.Block;
|
||||||
import cz.jzitnik.game.logic.services.water.WaterData;
|
import cz.jzitnik.game.logic.services.flowing.water.WaterData;
|
||||||
import cz.jzitnik.game.sprites.Water;
|
import cz.jzitnik.game.sprites.Water;
|
||||||
|
|
||||||
@BlockRegistry(value = "water", drops = "water_bucket")
|
@BlockRegistry(value = "water", drops = "water_bucket")
|
||||||
|
@ -5,7 +5,7 @@ import cz.jzitnik.game.annotations.ItemRegistry;
|
|||||||
import cz.jzitnik.game.entities.items.Item;
|
import cz.jzitnik.game.entities.items.Item;
|
||||||
import cz.jzitnik.game.entities.items.ItemType;
|
import cz.jzitnik.game.entities.items.ItemType;
|
||||||
|
|
||||||
@ItemRegistry("lava_bucket")
|
@ItemRegistry(value = "lava_bucket", block = "lava")
|
||||||
public class LavaBucketItem extends Item {
|
public class LavaBucketItem extends Item {
|
||||||
public LavaBucketItem() {
|
public LavaBucketItem() {
|
||||||
super("lava_bucket", "Lava bucket", ItemType.PICKUPER, SpriteLoader.SPRITES.LAVA_BUCKET);
|
super("lava_bucket", "Lava bucket", ItemType.PICKUPER, SpriteLoader.SPRITES.LAVA_BUCKET);
|
||||||
|
@ -23,6 +23,7 @@ public class Generation {
|
|||||||
Block steveBlock2 = new Block("steve", SpriteLoader.SPRITES.STEVE);
|
Block steveBlock2 = new Block("steve", SpriteLoader.SPRITES.STEVE);
|
||||||
steveBlock2.setSpriteState(Steve.SteveState.SECOND);
|
steveBlock2.setSpriteState(Steve.SteveState.SECOND);
|
||||||
steveBlock2.setGhost(true);
|
steveBlock2.setGhost(true);
|
||||||
|
steveBlock2.setMob(true);
|
||||||
|
|
||||||
int[] terrainHeight = generateTerrain();
|
int[] terrainHeight = generateTerrain();
|
||||||
|
|
||||||
@ -35,7 +36,6 @@ public class Generation {
|
|||||||
// Spawn player at a valid starting point
|
// Spawn player at a valid starting point
|
||||||
world[terrainHeight[256] - 1][256].add(steveBlock2);
|
world[terrainHeight[256] - 1][256].add(steveBlock2);
|
||||||
world[terrainHeight[256] - 2][256].add(steveBlock);
|
world[terrainHeight[256] - 2][256].add(steveBlock);
|
||||||
world[terrainHeight[256] - 1][256 + 1].add(ItemBlockSupplier.getBlock("water"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void initializeWorld(List<Block>[][] world) {
|
private static void initializeWorld(List<Block>[][] world) {
|
||||||
|
@ -5,7 +5,7 @@ import cz.jzitnik.game.annotations.PickupHandler;
|
|||||||
import cz.jzitnik.game.entities.Block;
|
import cz.jzitnik.game.entities.Block;
|
||||||
import cz.jzitnik.game.entities.items.Item;
|
import cz.jzitnik.game.entities.items.Item;
|
||||||
import cz.jzitnik.game.handlers.pickup.CustomPickupHandler;
|
import cz.jzitnik.game.handlers.pickup.CustomPickupHandler;
|
||||||
import cz.jzitnik.game.logic.services.water.FlowingData;
|
import cz.jzitnik.game.logic.services.flowing.FlowingData;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -35,8 +35,23 @@ public class BucketPickupHandler implements CustomPickupHandler {
|
|||||||
game.getInventory().decreaseItemInHand();
|
game.getInventory().decreaseItemInHand();
|
||||||
game.getInventory().addItem(returnItems);
|
game.getInventory().addItem(returnItems);
|
||||||
|
|
||||||
|
if (!block.getBlockId().equals("water") || !isInfiniteWaterSource(game, x, y)) {
|
||||||
world[y][x].remove(world[y][x].stream().filter(Block::isFlowing).findFirst().get());
|
world[y][x].remove(world[y][x].stream().filter(Block::isFlowing).findFirst().get());
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isInfiniteWaterSource(Game game, int x, int y) {
|
||||||
|
var world = game.getWorld();
|
||||||
|
|
||||||
|
var leftBlock = world[y][x - 1].stream().filter(Block::isFlowing).findFirst();
|
||||||
|
var rightBlock = world[y][x + 1].stream().filter(Block::isFlowing).findFirst();
|
||||||
|
|
||||||
|
if (leftBlock.isPresent() && ((FlowingData) leftBlock.get().getData()).isSource()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rightBlock.isPresent() && ((FlowingData) rightBlock.get().getData()).isSource();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package cz.jzitnik.game.logic.services.water;
|
package cz.jzitnik.game.logic.services.flowing;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
@ -0,0 +1,5 @@
|
|||||||
|
package cz.jzitnik.game.logic.services.flowing.lava;
|
||||||
|
|
||||||
|
import cz.jzitnik.game.logic.services.flowing.FlowingData;
|
||||||
|
|
||||||
|
public class LavaData extends FlowingData {}
|
@ -0,0 +1,123 @@
|
|||||||
|
package cz.jzitnik.game.logic.services.flowing.lava;
|
||||||
|
|
||||||
|
import cz.jzitnik.game.Game;
|
||||||
|
import cz.jzitnik.game.annotations.CustomLogic;
|
||||||
|
import cz.jzitnik.game.entities.Block;
|
||||||
|
import cz.jzitnik.game.entities.items.ItemBlockSupplier;
|
||||||
|
import cz.jzitnik.game.logic.CustomLogicInterface;
|
||||||
|
import cz.jzitnik.game.sprites.Lava;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@CustomLogic
|
||||||
|
public class LavaLogic implements CustomLogicInterface {
|
||||||
|
private static final int RADIUS = 20;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
private static class WaterBlock {
|
||||||
|
private Block block;
|
||||||
|
private int x;
|
||||||
|
private int y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nextIteration(Game game) {
|
||||||
|
int[] data = game.getPlayerCords();
|
||||||
|
var world = game.getWorld();
|
||||||
|
int playerX = data[0];
|
||||||
|
int playerY = data[1];
|
||||||
|
|
||||||
|
int startX = Math.max(0, playerX - RADIUS);
|
||||||
|
int startY = Math.max(0, playerY - RADIUS);
|
||||||
|
int endX = Math.min(world[0].length - 1, playerX + RADIUS);
|
||||||
|
int endY = Math.min(world.length - 1, playerY + RADIUS);
|
||||||
|
|
||||||
|
List<WaterBlock> sourceBlocks = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int y = startY; y <= endY; y++) {
|
||||||
|
for (int x = startX; x <= endX; x++) {
|
||||||
|
var blocks = world[y][x];
|
||||||
|
|
||||||
|
var waterSourceBlocks = blocks.stream().filter(block -> block.getBlockId().equals("lava") && ((LavaData) block.getData()).isSource()).toList();
|
||||||
|
if (!waterSourceBlocks.isEmpty()) {
|
||||||
|
sourceBlocks.add(new WaterBlock(waterSourceBlocks.getFirst(), x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
world[y][x].removeAll(blocks.stream().filter(i -> i.getBlockId().equals("lava") && !((LavaData) i.getData()).isSource()).toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (WaterBlock sourceBlock : sourceBlocks) {
|
||||||
|
int x = sourceBlock.getX();
|
||||||
|
int y = sourceBlock.getY();
|
||||||
|
|
||||||
|
flow(world, x, y, 5, new HashSet<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
checkFire(game, startX, endX, startY, endY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flow(List<Block>[][] world, int x, int y, int strength, Set<Point> visited) {
|
||||||
|
if (y + 1 < world.length && waterCanFlow(world[y+1][x])) {
|
||||||
|
Block newWater = ItemBlockSupplier.getBlock("lava");
|
||||||
|
newWater.setSpriteState(Lava.LavaState.get(5));
|
||||||
|
((LavaData) newWater.getData()).setSource(false);
|
||||||
|
world[y+1][x].add(newWater);
|
||||||
|
flow(world, x, y + 1, 5, visited);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strength == 1 || visited.contains(new Point(x, y))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
visited.add(new Point(x, y));
|
||||||
|
|
||||||
|
if (x - 1 >= 0 && waterCanFlow(world[y][x-1])) {
|
||||||
|
Block newWater = ItemBlockSupplier.getBlock("lava");
|
||||||
|
newWater.setSpriteState(Lava.LavaState.get(strength - 1));
|
||||||
|
((LavaData) newWater.getData()).setSource(false);
|
||||||
|
world[y][x-1].add(newWater);
|
||||||
|
flow(world, x - 1, y, strength - 1, visited);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x + 1 < world[y].length && waterCanFlow(world[y][x+1])) {
|
||||||
|
Block newWater = ItemBlockSupplier.getBlock("lava");
|
||||||
|
newWater.setSpriteState(Lava.LavaState.get(strength - 1));
|
||||||
|
((LavaData) newWater.getData()).setSource(false);
|
||||||
|
world[y][x+1].add(newWater);
|
||||||
|
flow(world, x + 1, y, strength - 1, visited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkFire(Game game, int startX, int endX, int startY, int endY) {
|
||||||
|
var world = game.getWorld();
|
||||||
|
for (int y = startY; y <= endY; y++) {
|
||||||
|
for (int x = startX; x <= endX; x++) {
|
||||||
|
var blocks = world[y][x];
|
||||||
|
if (blocks.stream().anyMatch(block -> block.getBlockId().equals("lava"))) {
|
||||||
|
var entities = blocks.stream().filter(Block::isMob).toList();
|
||||||
|
for (Block block : entities) {
|
||||||
|
if (block.getBlockId().equals("steve")) {
|
||||||
|
game.getPlayer().setHealth(game.getPlayer().getHealth() - 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
block.decreaseHp(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean waterCanFlow(List<Block> blocks) {
|
||||||
|
return blocks.stream().allMatch(block -> block.getBlockId().equals("steve") || block.getBlockId().equals("air") || block.isMob());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package cz.jzitnik.game.logic.services.flowing.water;
|
||||||
|
|
||||||
|
import cz.jzitnik.game.logic.services.flowing.FlowingData;
|
||||||
|
|
||||||
|
public class WaterData extends FlowingData {}
|
@ -1,4 +1,4 @@
|
|||||||
package cz.jzitnik.game.logic.services.water;
|
package cz.jzitnik.game.logic.services.flowing.water;
|
||||||
|
|
||||||
import cz.jzitnik.game.Game;
|
import cz.jzitnik.game.Game;
|
||||||
import cz.jzitnik.game.annotations.CustomLogic;
|
import cz.jzitnik.game.annotations.CustomLogic;
|
@ -1,3 +0,0 @@
|
|||||||
package cz.jzitnik.game.logic.services.water;
|
|
||||||
|
|
||||||
public class WaterData extends FlowingData {}
|
|
Loading…
x
Reference in New Issue
Block a user