chore: Some changes

This commit is contained in:
2025-09-20 21:39:25 +02:00
parent 61dee148e4
commit e9ffb5d29f
15 changed files with 171 additions and 25 deletions

View File

@ -634,4 +634,8 @@ public class Game {
}
}
}
public Object getContext(Class clazz) {
return gameStates.globalContextProvider.getMap(clazz);
}
}

View File

@ -336,7 +336,7 @@ public class SpriteLoader {
SPRITES_MAP.put(SPRITES.WOODEN_SHOVEL, new SimpleSprite("items/wooden_shovel.ans"));
SPRITES_MAP.put(SPRITES.WOODEN_HOE, new SimpleSprite("items/wooden_hoe.ans"));
SPRITES_MAP.put(SPRITES.STONE_SWORD, new SimpleSprite("items/wooden_sword.ans"));
SPRITES_MAP.put(SPRITES.STONE_SWORD, new SimpleSprite("items/stone_sword.ans"));
SPRITES_MAP.put(SPRITES.STONE_PICKAXE, new SimpleSprite("items/stone_pickaxe.ans"));
SPRITES_MAP.put(SPRITES.STONE_AXE, new SimpleSprite("items/stone_axe.ans"));
SPRITES_MAP.put(SPRITES.STONE_SHOVEL, new SimpleSprite("items/stone_shovel.ans"));

View File

@ -0,0 +1,9 @@
package cz.jzitnik.game.annotations;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface GlobalContext {
}

View File

@ -0,0 +1,66 @@
package cz.jzitnik.game.blocks;
import cz.jzitnik.game.Game;
import cz.jzitnik.game.annotations.RightClickLogic;
import cz.jzitnik.game.context.list.BedSleepGlobalContext;
import cz.jzitnik.game.handlers.rightclick.RightClickHandler;
import cz.jzitnik.tui.ScreenRenderer;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@RightClickLogic
public class Bed implements RightClickHandler {
@Override
public void onBlockRightClick(int x, int y, Game game, ScreenRenderer screenRenderer) {
BedSleepGlobalContext bedSleepGlobalContext =
(BedSleepGlobalContext) game.getContext(BedSleepGlobalContext.class);
if (bedSleepGlobalContext.isSleeping() || game.getDaytime() < 200 || game.getDaytime() > 500) {
return; // already in progress
}
bedSleepGlobalContext.setSleeping(true);
int targetTime = 500;
int step = 10;
long delayMillis = 50; // animation speed
// Create a brand-new scheduler for this run
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
final ScheduledFuture<?>[] futureHolder = new ScheduledFuture<?>[1];
Runnable sleepTask = () -> {
int currentTime = game.getDaytime();
if (currentTime == targetTime) {
// cancel this repeating task + shut down the scheduler
futureHolder[0].cancel(false);
scheduler.shutdown();
bedSleepGlobalContext.setSleeping(false);
return;
}
int nextTime = (currentTime + step) % 600;
if (currentTime < targetTime && nextTime >= targetTime) {
nextTime = targetTime;
}
if (nextTime < currentTime && nextTime >= targetTime) {
nextTime = targetTime;
}
game.setDaytime(nextTime);
screenRenderer.render(game);
};
// Schedule the task and keep its handle
futureHolder[0] = scheduler.scheduleAtFixedRate(
sleepTask, 0, delayMillis, TimeUnit.MILLISECONDS);
}
}

View File

@ -22,7 +22,7 @@ import java.util.Optional;
@RightClickLogic
public class Furnace implements RightClickHandler, Serializable {
private final Block block;
private Block block;
private final InventoryItem[] items = new InventoryItem[2];
private InventoryItem outputItem;
private int size;
@ -37,6 +37,8 @@ public class Furnace implements RightClickHandler, Serializable {
this.block = block;
}
public Furnace() {}
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();
@ -193,7 +195,7 @@ public class Furnace implements RightClickHandler, Serializable {
// Add smelt item
Thread thread1 = new Thread(() -> {
while (true) {
do {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
@ -215,10 +217,7 @@ public class Furnace implements RightClickHandler, Serializable {
rerender(game, screenRenderer);
}
if (items[0] == null || !smelting) {
break;
}
}
} while (items[0] != null && smelting);
});
Thread thread2 = new Thread(() -> {

View File

@ -0,0 +1,33 @@
package cz.jzitnik.game.context;
import cz.jzitnik.game.annotations.GlobalContext;
import org.reflections.Reflections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class GlobalContextProvider {
private final Map<Class, Object> data = new HashMap<>();
private boolean loaded = false;
public Object getMap(Class<?> clazz) {
if (!loaded) {
Reflections reflections = new Reflections("cz.jzitnik.game.context");
Set<Class<?>> handlerClasses = reflections.getTypesAnnotatedWith(GlobalContext.class);
for (Class<?> claz : handlerClasses) {
try {
Object instance = claz.getDeclaredConstructor().newInstance();
data.put(claz, instance);
} catch (Exception e) {
e.printStackTrace();
}
}
loaded = true;
}
return data.get(clazz);
}
}

View File

@ -0,0 +1,12 @@
package cz.jzitnik.game.context.list;
import cz.jzitnik.game.annotations.GlobalContext;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@GlobalContext
public class BedSleepGlobalContext {
private boolean sleeping = false;
}

View File

@ -92,22 +92,33 @@ public class CraftingRecipeList {
}
public static boolean are2DArraysIdentical(String[][] array1, String[][] array2, boolean usingRegex) {
if (array1 == null || array2 == null) {
return array1 == array2;
}
if (array1.length != array2.length) {
return false;
}
for (int i = 0; i < array1.length; i++) {
if (array1[i] == null || array2[i] == null) {
if (array1[i] != array2[i]) return false;
continue;
}
if (array1[i].length != array2[i].length) {
return false;
}
for (int j = 0; j < array1[i].length; j++) {
if (array1[i][j] == null && array2[i][j] != null) {
return false;
}
if (array1[i][j] != null
&& (usingRegex ? !array2[i][j].matches(array1[i][j]) : !array1[i][j].equals(array2[i][j]))) {
return false;
String a = array1[i][j];
String b = array2[i][j];
if (a == null || b == null) {
if (a != b) return false; // one null, one not -> false
} else {
boolean equal = usingRegex ? b.matches(a) : a.equals(b);
if (!equal) return false;
}
}
}

View File

@ -1,11 +1,13 @@
package cz.jzitnik.game.entities;
import cz.jzitnik.game.Game;
import cz.jzitnik.game.context.GlobalContextProvider;
import cz.jzitnik.game.ui.CraftingTable;
public class GameStates {
public CraftingTable craftingTable;
public Dependencies dependencies;
public GlobalContextProvider globalContextProvider = new GlobalContextProvider();
public int clickX = -1;
public int clickY = -1;

View File

@ -41,6 +41,14 @@ public class Player {
fallDistance++;
}
public void resetHealth() {
health = 10;
}
public void resetHunger() {
hunger = 10;
}
public void fell(List<Block> fallblock, Game game, ScreenRenderer screenRenderer) {
var block = fallblock.stream().filter(b -> b.getClass().isAnnotationPresent(ReduceFallDamage.class))
.findFirst();

View File

@ -5,7 +5,8 @@ import cz.jzitnik.game.annotations.*;
import cz.jzitnik.game.core.reducefalldamage.BedFallDamageReducer;
import cz.jzitnik.game.core.sound.SoundKey;
import cz.jzitnik.game.entities.Block;
import cz.jzitnik.game.sprites.Bed;
import static cz.jzitnik.game.sprites.Bed.BedState;
import cz.jzitnik.game.blocks.Bed;
@MineSound(SoundKey.WOOD_DIG)
@PlaceSound(SoundKey.WOOD_DIG)
@ -17,6 +18,7 @@ public class BedBlock extends Block {
public BedBlock() {
super("bed", SpriteLoader.SPRITES.BED, 2);
setGhost(true);
setSpriteState(Bed.BedState.RIGHT);
setSpriteState(BedState.RIGHT);
setData(new Bed());
}
}

View File

@ -2,9 +2,11 @@ package cz.jzitnik.game.entities.items.registry.items.ores.coal;
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("coal")
@ItemRegistry("coal_ore")
public class CoalOreItem extends Item {
public CoalOreItem() {

View File

@ -34,12 +34,11 @@ public class ZombieLogic
@Override
public void spawn(int playerX, int playerY, Game game, Terminal terminal) {
int[] view = ScreenMovingCalculationProvider.calculate(playerX, playerY, terminal.getHeight(), terminal.getWidth(), game.getWorld()[0].length, game.getWorld().length);
var world = game.getWorld();
int startX = view[0];
int endX = view[1];
attemptZombieSpawn(startX - 20, startX - 5, playerY, game);
attemptZombieSpawn(endX + 5, endX + 20, playerY, game);
//attemptZombieSpawn(startX - 20, startX - 5, playerY, game);
//attemptZombieSpawn(endX + 5, endX + 20, playerY, game);
}
private void attemptZombieSpawn(int startX, int endX, int centerY, Game game) {
@ -106,8 +105,8 @@ public class ZombieLogic
@Override
public void killed(Game game, Block mob) {
int rottenFlesh = random.nextInt(3) + 1;
InventoryItem drop = new InventoryItem(rottenFlesh, ItemBlockSupplier.getItem("rotten_flesh"));
game.getInventory().addItem(drop);
//InventoryItem drop = new InventoryItem(rottenFlesh, ItemBlockSupplier.getItem("rotten_flesh"));
//game.getInventory().addItem(drop);
}
public static <K, V> Map.Entry<K, V> getRandomEntry(HashMap<K, V> map) {

View File

@ -110,6 +110,9 @@ public class DeathScreen {
if (buttony > top && buttony < bottom) {
if (type == MouseEvent.Type.Pressed) {
game.setWindow(Window.WORLD);
game.getPlayer().resetHealth();
game.getPlayer().resetHunger();
screenRenderer.render(game);
return;
}
if (!buttonHover) {

View File

@ -81,11 +81,7 @@ public abstract class Sprite<E extends Enum<E>> {
protected final String getResource(E key) {
var resource = resources.get(key);
if (resource.isEmpty()) {
return loadResource(key);
} else {
return resource.get();
}
return resource.orElseGet(() -> loadResource(key));
}
/**