refactor: Config in files

This commit is contained in:
2026-01-24 21:40:44 +01:00
parent 743ad8e760
commit 6e665dbbdd
24 changed files with 161 additions and 107 deletions

View File

@@ -8,4 +8,5 @@ import java.lang.annotation.ElementType;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Config {
String value();
}

View File

@@ -1,10 +1,16 @@
package cz.jzitnik.config;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import cz.jzitnik.annotations.Config;
import lombok.Getter;
@Config
@Getter
public class CoreLogic {
private final int itemDropDisappearMinutes = 5;
@Config("core_logic.yaml")
public record CoreLogic(int itemDropDisappearMinutes) {
@JsonCreator
public CoreLogic(
@JsonProperty("itemDropDisappearMinutes") int itemDropDisappearMinutes
) {
this.itemDropDisappearMinutes = itemDropDisappearMinutes;
}
}

View File

@@ -1,11 +1,19 @@
package cz.jzitnik.config;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import cz.jzitnik.annotations.Config;
import lombok.Getter;
@Getter
@Config
public class Debugging {
private final boolean renderColliders = false;
private final boolean renderPlayerCollider = false;
@Config("debugging.yaml")
public record Debugging(boolean renderColliders, boolean renderPlayerCollider, boolean showPlayerCordsLogs) {
@JsonCreator
public Debugging(
@JsonProperty("renderColliders") boolean renderColliders,
@JsonProperty("renderPlayerCollider") boolean renderPlayerCollider,
@JsonProperty("showPlayerCordsLogs") boolean showPlayerCordsLogs
) {
this.renderColliders = renderColliders;
this.renderPlayerCollider = renderPlayerCollider;
this.showPlayerCordsLogs = showPlayerCordsLogs;
}
}

View File

@@ -1,10 +0,0 @@
package cz.jzitnik.config;
import cz.jzitnik.annotations.Config;
import lombok.Getter;
@Getter
@Config
public class Logging {
private final boolean showPlayerCordsLogs = false;
}

View File

@@ -1,10 +1,15 @@
package cz.jzitnik.config;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import cz.jzitnik.annotations.Config;
import lombok.Getter;
@Getter
@Config
public class MicrophoneConfig {
private final float volumeThreshold = 3f;
@Config("microphone.yaml")
public record MicrophoneConfig(float volumeThreshold) {
@JsonCreator
public MicrophoneConfig(
@JsonProperty("volumeThreshold") float volumeThreshold
) {
this.volumeThreshold = volumeThreshold;
}
}

View File

@@ -1,18 +1,36 @@
package cz.jzitnik.config;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import cz.jzitnik.annotations.Config;
import cz.jzitnik.events.handlers.PlayerMoveEventHandler;
import lombok.Getter;
@Getter
@Config
public class PlayerConfig {
private final double playerReach = 50;
private final int playerMoveDistance = 3;
private final int playerMoveDistanceSprinting = 6;
private final PlayerMoveEventHandler.SprintKey sprintKey = PlayerMoveEventHandler.SprintKey.CTRL;
private final int swingTimeMs = 500;
private final int staminaIncreaseRateMs = 500;
private final int staminaDelayMs = 1000;
@Config("player.yaml")
public record PlayerConfig(
double playerReach,
int playerMoveDistance,
int playerMoveDistanceSprinting,
PlayerMoveEventHandler.SprintKey sprintKey,
int swingTimeMs,
int staminaIncreaseRateMs,
int staminaDelayMs
) {
@JsonCreator
public PlayerConfig(
@JsonProperty("playerReach") double playerReach,
@JsonProperty("playerMoveDistance") int playerMoveDistance,
@JsonProperty("playerMoveDistanceSprinting") int playerMoveDistanceSprinting,
@JsonProperty("sprintKey") PlayerMoveEventHandler.SprintKey sprintKey,
@JsonProperty("swingTimeMs") int swingTimeMs,
@JsonProperty("staminaIncreaseRateMs") int staminaIncreaseRateMs,
@JsonProperty("staminaDelayMs") int staminaDelayMs
) {
this.playerReach = playerReach;
this.playerMoveDistance = playerMoveDistance;
this.playerMoveDistanceSprinting = playerMoveDistanceSprinting;
this.sprintKey = sprintKey;
this.swingTimeMs = swingTimeMs;
this.staminaIncreaseRateMs = staminaIncreaseRateMs;
this.staminaDelayMs = staminaDelayMs;
}
}

View File

@@ -1,11 +1,18 @@
package cz.jzitnik.config;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import cz.jzitnik.annotations.Config;
import lombok.Getter;
@Getter
@Config
public class ThreadPoolConfig {
private final int eventThreadCount = 8;
private final int taskThreadCount = 6;
@Config("threads.yaml")
public record ThreadPoolConfig(int eventThreadCount, int taskThreadCount) {
@JsonCreator
public ThreadPoolConfig(
@JsonProperty("eventThreadCount") int eventThreadCount,
@JsonProperty("taskThreadCount") int taskThreadCount
) {
this.eventThreadCount = eventThreadCount;
this.taskThreadCount = taskThreadCount;
}
}

View File

@@ -73,7 +73,7 @@ public class MouseActionEventHandler extends AbstractEventHandler<MouseAction> {
Optional<? extends Selectable> object = combined.filter(Selectable::isSelected).findFirst();
gameState.getPlayer().swing(playerConfig.getSwingTimeMs());
gameState.getPlayer().swing(playerConfig.swingTimeMs());
object.ifPresent(selectable -> {
dependencyManager.inject(selectable);

View File

@@ -133,7 +133,7 @@ public class MouseMoveEventHandler extends AbstractEventHandler<MouseMoveEvent>
objXEnd, objYEnd
);
if (distance > playerConfig.getPlayerReach()) {
if (distance > playerConfig.playerReach()) {
return false;
}

View File

@@ -7,7 +7,6 @@ import cz.jzitnik.annotations.injectors.InjectConfig;
import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.config.Debugging;
import cz.jzitnik.config.Logging;
import cz.jzitnik.config.PlayerConfig;
import cz.jzitnik.events.MouseMoveEvent;
import cz.jzitnik.events.PlayerMoveEvent;
@@ -50,8 +49,6 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
private PlayerConfig playerConfig;
@InjectState
private RenderState renderState;
@InjectConfig
private Logging logging;
@InjectState
private PlayerMovementState playerMovementState;
@InjectDependency
@@ -68,13 +65,13 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
RoomCords playerCords = player.getPlayerCords();
GameRoom currentRoom = gameState.getCurrentRoom();
boolean isSprinting = player.getStamina() > 0 && switch (playerConfig.getSprintKey()) {
boolean isSprinting = player.getStamina() > 0 && switch (playerConfig.sprintKey()) {
case CTRL -> event.getKeyStroke().isCtrlDown();
case SHIFT -> event.getKeyStroke().isShiftDown();
case ALT -> event.getKeyStroke().isAltDown();
};
int moveStep = isSprinting ? playerConfig.getPlayerMoveDistanceSprinting() : playerConfig.getPlayerMoveDistance();
int moveStep = isSprinting ? playerConfig.playerMoveDistanceSprinting() : playerConfig.playerMoveDistance();
int originalPlayerX = playerCords.getX();
int originalPlayerY = playerCords.getY();
@@ -132,7 +129,7 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
int newPlayerX = playerCords.getX();
int newPlayerY = playerCords.getY();
if (logging.isShowPlayerCordsLogs()) {
if (debugging.showPlayerCordsLogs()) {
log.debug("x: {}, y: {}", newPlayerX, newPlayerY);
}
BufferedImage playerTexture = player.getTexture(resourceManager);

View File

@@ -70,7 +70,7 @@ public class BlindMobFollowingPlayerTask extends MobRoomTask {
@Override
public void run() {
if (playerCords == null || (microphoneState.isMicrophoneSetup() && microphoneState.getMicrophoneVolume() > microphoneConfig.getVolumeThreshold())) {
if (playerCords == null || (microphoneState.isMicrophoneSetup() && microphoneState.getMicrophoneVolume() > microphoneConfig.volumeThreshold())) {
playerCords = gameState.getPlayer().getPlayerCords().clone();
}

View File

@@ -2,7 +2,6 @@ package cz.jzitnik.game.setup;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import cz.jzitnik.annotations.Dependency;
import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState;
@@ -10,7 +9,6 @@ import cz.jzitnik.game.GameRoom;
import cz.jzitnik.game.GameState;
import cz.jzitnik.game.Player;
import cz.jzitnik.game.ResourceManager;
import cz.jzitnik.utils.DependencyManager;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
@@ -26,19 +24,17 @@ public class GameSetup {
private ResourceManager resourceManager;
@InjectDependency
private DependencyManager dependencyManager;
private ObjectMapper objectMapper;
public void setup() throws IOException {
//gameState.setScreen(new IntroScene(dependencyManager));
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
mapper.setInjectableValues(dependencyManager);
List<GameRoom> rooms = mapper.readValue(
List<GameRoom> rooms = objectMapper.readValue(
resourceManager.getResourceAsStream("setup/rooms.yaml"),
new TypeReference<>() {
}
);
Player player = mapper.readValue(resourceManager.getResourceAsStream("setup/player.yaml"), Player.class);
Player player = objectMapper.readValue(resourceManager.getResourceAsStream("setup/player.yaml"), Player.class);
gameState.setCurrentRoom(rooms.getFirst());
gameState.setPlayer(player);

View File

@@ -40,10 +40,10 @@ public class StaminaIncreaseTask implements Runnable {
}
long nowTime = System.currentTimeMillis();
if (nowTime - playerMovementState.getLastMovement() >= playerConfig.getStaminaDelayMs() && gameState.getPlayer().getStamina() < Player.MAX_STAMINA) {
if (nowTime - playerMovementState.getLastMovement() >= playerConfig.staminaDelayMs() && gameState.getPlayer().getStamina() < Player.MAX_STAMINA) {
IncreaseStamina instance = new IncreaseStamina();
dependencyManager.inject(instance);
playerMovementState.setStaminaIncreaseSchedule(scheduledTaskManager.tempScheduleFixedRate(instance, playerConfig.getStaminaIncreaseRateMs(), TimeUnit.MILLISECONDS));
playerMovementState.setStaminaIncreaseSchedule(scheduledTaskManager.tempScheduleFixedRate(instance, playerConfig.staminaIncreaseRateMs(), TimeUnit.MILLISECONDS));
}
}
@@ -65,7 +65,7 @@ public class StaminaIncreaseTask implements Runnable {
long nowTime = System.currentTimeMillis();
Player player = gameState.getPlayer();
if (player.getStamina() >= Player.MAX_STAMINA || nowTime - playerMovementState.getLastMovement() < playerConfig.getStaminaDelayMs()) {
if (player.getStamina() >= Player.MAX_STAMINA || nowTime - playerMovementState.getLastMovement() < playerConfig.staminaDelayMs()) {
ScheduledFuture<?> future = playerMovementState.getStaminaIncreaseSchedule();
playerMovementState.setStaminaIncreaseSchedule(null);
future.cancel(false);

View File

@@ -144,7 +144,7 @@ public class Inventory {
if (droppedItem.getRoom() == currentRoom) {
eventManager.emitEvent(new DroppedItemRerender(droppedItem));
}
}, coreLogic.getItemDropDisappearMinutes(), TimeUnit.MINUTES);
}, coreLogic.itemDropDisappearMinutes(), TimeUnit.MINUTES);
currentRoom.getDroppedItems().add(droppedItem);
inventory[inventoryState.selectedItem] = null;
inventoryState.selectedItem = -1;

View File

@@ -3,10 +3,8 @@ package cz.jzitnik.utils;
// Don't blame me that I'm using field injection instead of construction injection. I just like it more, leave me alone.
// Yes, I know I'll suffer in the unit tests. (who said there will be any? hmmm)
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.InjectableValues;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.google.common.collect.ClassToInstanceMap;
import com.google.common.collect.MutableClassToInstanceMap;
import cz.jzitnik.annotations.Config;
@@ -18,10 +16,12 @@ import cz.jzitnik.annotations.injectors.InjectState;
import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;
import java.lang.reflect.Constructor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.*;
@Slf4j
@@ -29,48 +29,26 @@ public class DependencyManager extends InjectableValues {
private final ClassToInstanceMap<Object> configs = MutableClassToInstanceMap.create();
private final ClassToInstanceMap<Object> data = MutableClassToInstanceMap.create();
public <T> T getDependencyOrThrow(Class<T> clazz) {
T instance = data.getInstance(clazz);
if (instance == null) {
throw new RuntimeException("Class was not found!");
}
return instance;
}
public <T> Optional<T> getDependency(Class<T> clazz) {
return Optional.ofNullable(data.getInstance(clazz));
}
public <T> Optional<T> getConfig(Class<T> clazz) {
return Optional.ofNullable(configs.getInstance(clazz));
}
public <T> T getConfigOrThrow(Class<T> clazz) {
T instance = configs.getInstance(clazz);
if (instance == null) {
throw new RuntimeException("Class was not found!");
}
return instance;
}
public DependencyManager(Reflections reflections) {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
mapper.setInjectableValues(this);
data.put(ObjectMapper.class, mapper);
data.put(ClassLoader.class, DependencyManager.class.getClassLoader());
Set<Class<?>> configClasses = reflections.getTypesAnnotatedWith(Config.class);
for (Class<?> configClass : configClasses) {
try {
Constructor<?> constructor = configClass.getDeclaredConstructor();
var instance = constructor.newInstance();
Config config = configClass.getAnnotation(Config.class);
assert config != null;
Path filePath = Path.of("config", config.value());
InputStream stream = DependencyManager.class.getClassLoader().getResourceAsStream(filePath.toString());
Object instance = mapper.readValue(stream, configClass);
configs.put(configClass, instance);
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
IllegalAccessException e) {
} catch (IOException e) {
log.error("Failed to instantiate config class: {}", configClass.getName(), e);
}
}
data.put(ClassLoader.class, DependencyManager.class.getClassLoader());
Set<Class<?>> classes = reflections.getTypesAnnotatedWith(Dependency.class);
// Construct all classes
@@ -99,6 +77,7 @@ public class DependencyManager extends InjectableValues {
Object instance = constructor.newInstance(params);
Dependency annotation = clazz.getAnnotation(Dependency.class);
assert annotation != null;
if (annotation.value() != Object.class) {
data.put(annotation.value(), instance);
} else {
@@ -117,6 +96,34 @@ public class DependencyManager extends InjectableValues {
}
public <T> T getDependencyOrThrow(Class<T> clazz) {
T instance = data.getInstance(clazz);
if (instance == null) {
throw new RuntimeException("Class was not found!");
}
return instance;
}
public <T> Optional<T> getDependency(Class<T> clazz) {
return Optional.ofNullable(data.getInstance(clazz));
}
public <T> Optional<T> getConfig(Class<T> clazz) {
return Optional.ofNullable(configs.getInstance(clazz));
}
public <T> T getConfigOrThrow(Class<T> clazz) {
T instance = configs.getInstance(clazz);
if (instance == null) {
throw new RuntimeException("Class was not found!");
}
return instance;
}
public void inject(Object instance) {
StateManager stateManager = (StateManager) data.get(StateManager.class);
@@ -206,7 +213,7 @@ public class DependencyManager extends InjectableValues {
ctxt.reportInputMismatch(forProperty,
"No injectable value found for type: %s", clazz.getName());
} else if (valueId instanceof String key) {
for (Object dep: data.values()) {
for (Object dep : data.values()) {
if (dep.getClass().getName().equalsIgnoreCase(key)) return dep;
}
for (Object dep : configs.values()) {

View File

@@ -7,7 +7,6 @@ import cz.jzitnik.events.handlers.FullRoomDrawHandler;
import cz.jzitnik.game.GameRoom;
import cz.jzitnik.game.Player;
import cz.jzitnik.game.ResourceManager;
import cz.jzitnik.game.mobs.HittableMob;
import cz.jzitnik.game.mobs.Mob;
import cz.jzitnik.game.objects.DroppedItem;
import cz.jzitnik.game.objects.GameObject;
@@ -66,7 +65,7 @@ public class RerenderUtils {
public static PixelResult getPixel(GameRoom currentRoom, BufferedImage room, BufferedImage doors, Set<FullRoomDrawHandler.DoorPosition> doorPositions, Player player, BufferedImage playerTexture, int x, int y, Debugging debugging) {
float factor = 1.5f; // brightness multiplier
if (debugging.isRenderColliders() && currentRoom.getColliders().stream().anyMatch(collider -> collider.isWithin(new RoomCords(x, y)))) {
if (debugging.renderColliders() && currentRoom.getColliders().stream().anyMatch(collider -> collider.isWithin(new RoomCords(x, y)))) {
return new PixelResult(0xFFFF0000, false);
}
@@ -75,7 +74,7 @@ public class RerenderUtils {
int relativeY = y - player.getPlayerCords().getY();
var playerCollider = player.getCollider();
if (debugging.isRenderPlayerCollider() && playerCollider.isWithin(new RoomCords(relativeX, relativeY))) {
if (debugging.renderPlayerCollider() && playerCollider.isWithin(new RoomCords(relativeX, relativeY))) {
return new PixelResult(0xFFFF0000, false);
}

View File

@@ -2,6 +2,7 @@ package cz.jzitnik.utils;
import cz.jzitnik.annotations.Dependency;
import cz.jzitnik.annotations.ScheduledTask;
import cz.jzitnik.annotations.injectors.InjectConfig;
import cz.jzitnik.config.ThreadPoolConfig;
import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;
@@ -16,10 +17,13 @@ import java.util.concurrent.TimeUnit;
@Slf4j
@Dependency
public class ScheduledTaskManager {
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(new ThreadPoolConfig().getTaskThreadCount());
ScheduledExecutorService scheduler;
private final HashSet<Registry> instances = new HashSet<>();
private final DependencyManager dependencyManager;
@InjectConfig
private ThreadPoolConfig threadPoolConfig;
public ScheduledTaskManager(Reflections reflections, DependencyManager dependencyManager) {
this.dependencyManager = dependencyManager;
var classes = reflections.getTypesAnnotatedWith(ScheduledTask.class);
@@ -42,6 +46,7 @@ public class ScheduledTaskManager {
}
public void startAll() {
scheduler = Executors.newScheduledThreadPool(threadPoolConfig.taskThreadCount());
for (Registry instance : instances) {
dependencyManager.inject(instance.runnable);
scheduler.scheduleAtFixedRate(instance.runnable, 0, instance.scheduledTask.rate(), instance.scheduledTask.rateUnit());

View File

@@ -89,7 +89,7 @@ public class EventManager extends Thread {
dependencyManager.inject(instance);
}
eventExecutor = Executors.newFixedThreadPool(threadPoolConfig.getEventThreadCount());
eventExecutor = Executors.newFixedThreadPool(threadPoolConfig.eventThreadCount());
while (runningState.isRunning()) {
try {
EventRecord event = eventQueue.take();

View File

@@ -31,7 +31,7 @@ public class RoomTaskScheduler {
@PostInit
public void initExecutor() {
scheduler = Executors.newScheduledThreadPool(threadPoolConfig.getTaskThreadCount());
scheduler = Executors.newScheduledThreadPool(threadPoolConfig.taskThreadCount());
}
public void shutdownTasks() {

View File

@@ -0,0 +1 @@
itemDropDisappearMinutes: 5

View File

@@ -0,0 +1,3 @@
renderColliders: false
renderPlayerCollider: false
showPlayerCordsLogs: false

View File

@@ -0,0 +1 @@
volumeThreshold: 3.0

View File

@@ -0,0 +1,8 @@
playerReach: 50
playerMoveDistance: 3
playerMoveDistanceSprinting: 6
sprintKey: "CTRL"
swingTimeMs: 500
staminaIncreaseRateMs: 500
staminaDelayMs: 1000

View File

@@ -0,0 +1,2 @@
eventThreadCount: 8
taskThreadCount: 6