docs: Add javadoc

This commit is contained in:
2026-02-24 21:01:32 +01:00
parent f2b6200355
commit 6710426fad
195 changed files with 3162 additions and 3 deletions

View File

@@ -1,5 +1,10 @@
package cz.jzitnik.common; package cz.jzitnik.common;
/**
* Configuration constants for the common module.
*
* @author Jakub Žitník (jzitnik)
*/
public class Config { public class Config {
public static final int WORLD_PASSWORD_LENGTH = 5; public static final int WORLD_PASSWORD_LENGTH = 5;
} }

View File

@@ -10,6 +10,11 @@ import java.awt.image.BufferedImage;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
/**
* Represents coordinates in a room.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
@ToString @ToString
@Getter @Getter
@@ -17,6 +22,12 @@ public class RoomCords implements Cloneable, Serializable {
private int x; private int x;
private int y; private int y;
/**
* Calculates the center coordinate based on a texture's dimensions.
*
* @param texture The texture to calculate the center for
* @return A new RoomCords instance representing the center
*/
public RoomCords calculateCenter(BufferedImage texture) { public RoomCords calculateCenter(BufferedImage texture) {
return new RoomCords( return new RoomCords(
x + texture.getWidth() / 2, x + texture.getWidth() / 2,
@@ -24,6 +35,12 @@ public class RoomCords implements Cloneable, Serializable {
); );
} }
/**
* Constructs RoomCords with specified x and y values.
*
* @param x The x coordinate
* @param y The y coordinate
*/
@JsonCreator @JsonCreator
public RoomCords( public RoomCords(
@JsonProperty("x") int x, @JsonProperty("x") int x,
@@ -32,15 +49,34 @@ public class RoomCords implements Cloneable, Serializable {
updateCords(x, y); updateCords(x, y);
} }
/**
* Updates the coordinates with new x and y values.
*
* @param x The new x coordinate
* @param y The new y coordinate
*/
public void updateCords(int x, int y) { public void updateCords(int x, int y) {
this.x = x; this.x = x;
this.y = y; this.y = y;
} }
/**
* Updates the coordinates using another RoomCords instance.
*
* @param roomCords The RoomCords instance to copy values from
*/
public void updateCords(RoomCords roomCords) { public void updateCords(RoomCords roomCords) {
updateCords(roomCords.getX(), roomCords.getY()); updateCords(roomCords.getX(), roomCords.getY());
} }
/**
* Updates the coordinates only if the new position does not collide with specified colliders.
*
* @param colliders The list of colliders in the room
* @param x The target x coordinate
* @param y The target y coordinate
* @param playerCollider The collider of the player
*/
public void updateCordsWithColliders(List<RoomPart> colliders, int x, int y, RoomPart playerCollider) { public void updateCordsWithColliders(List<RoomPart> colliders, int x, int y, RoomPart playerCollider) {
var normalizedPlayerCollider = new RoomPart( var normalizedPlayerCollider = new RoomPart(
new RoomCords(playerCollider.getStart().getX() + x, playerCollider.getStart().getY() + y), new RoomCords(playerCollider.getStart().getX() + x, playerCollider.getStart().getY() + y),
@@ -53,6 +89,11 @@ public class RoomCords implements Cloneable, Serializable {
updateCords(x, y); updateCords(x, y);
} }
/**
* Creates and returns a copy of this object.
*
* @return A clone of this instance
*/
@Override @Override
public RoomCords clone() { public RoomCords clone() {
try { try {

View File

@@ -7,12 +7,23 @@ import lombok.ToString;
import java.io.Serializable; import java.io.Serializable;
/**
* Represents a rectangular part of a room, defined by start and end coordinates.
*
* @author Jakub Žitník (jzitnik)
*/
@Data @Data
@ToString @ToString
public class RoomPart implements Serializable { public class RoomPart implements Serializable {
private RoomCords start; private RoomCords start;
private RoomCords end; private RoomCords end;
/**
* Constructs a RoomPart with specified start and end coordinates.
*
* @param start The start coordinates (top-left)
* @param end The end coordinates (bottom-right)
*/
@JsonCreator @JsonCreator
public RoomPart( public RoomPart(
@JsonProperty("start") RoomCords start, @JsonProperty("start") RoomCords start,
@@ -22,6 +33,12 @@ public class RoomPart implements Serializable {
this.end = end; this.end = end;
} }
/**
* Checks if the given coordinates are within this room part.
*
* @param cords The coordinates to check
* @return true if the coordinates are within this part, false otherwise
*/
public boolean isWithin(RoomCords cords) { public boolean isWithin(RoomCords cords) {
return cords.getX() >= start.getX() && return cords.getX() >= start.getX() &&
cords.getX() <= end.getX() && cords.getX() <= end.getX() &&
@@ -30,7 +47,10 @@ public class RoomPart implements Serializable {
} }
/** /**
* Checks if this GameRoomPart overlaps with another. * Checks if this RoomPart overlaps with another.
*
* @param other The other RoomPart to check for overlap
* @return true if it overlaps, false otherwise
*/ */
public boolean isOverlapping(RoomPart other) { public boolean isOverlapping(RoomPart other) {
return start.getX() <= other.getEnd().getX() && return start.getX() <= other.getEnd().getX() &&

View File

@@ -9,6 +9,11 @@ import lombok.Setter;
import java.io.Serializable; import java.io.Serializable;
/**
* Data required for player creation.
*
* @author Jakub Žitník (jzitnik)
*/
@Getter @Getter
public final class PlayerCreation implements Serializable { public final class PlayerCreation implements Serializable {
@Setter @Setter
@@ -16,6 +21,12 @@ public final class PlayerCreation implements Serializable {
private final RoomCords playerCords; private final RoomCords playerCords;
private final RoomPart collider; private final RoomPart collider;
/**
* Constructs a PlayerCreation instance.
*
* @param playerCords The player's initial coordinates
* @param collider The player's collider
*/
@JsonCreator @JsonCreator
public PlayerCreation( public PlayerCreation(
@JsonProperty("playerCords") RoomCords playerCords, @JsonProperty("playerCords") RoomCords playerCords,

View File

@@ -2,5 +2,10 @@ package cz.jzitnik.common.socket;
import java.io.Serializable; import java.io.Serializable;
/**
* Base interface for all messages sent over the socket.
*
* @author Jakub Žitník (jzitnik)
*/
public interface SocketMessage extends Serializable { public interface SocketMessage extends Serializable {
} }

View File

@@ -2,5 +2,10 @@ package cz.jzitnik.common.socket.messages;
import cz.jzitnik.common.socket.SocketMessage; import cz.jzitnik.common.socket.SocketMessage;
/**
* Test message for socket communication.
*
* @author Jakub Žitník (jzitnik)
*/
public class Test implements SocketMessage { public class Test implements SocketMessage {
} }

View File

@@ -2,5 +2,10 @@ package cz.jzitnik.common.socket.messages.game;
import cz.jzitnik.common.socket.SocketMessage; import cz.jzitnik.common.socket.SocketMessage;
/**
* Message indicating that the game has been won.
*
* @author Jakub Žitník (jzitnik)
*/
public record GameWin() implements SocketMessage { public record GameWin() implements SocketMessage {
} }

View File

@@ -2,5 +2,11 @@ package cz.jzitnik.common.socket.messages.game;
import cz.jzitnik.common.socket.SocketMessage; import cz.jzitnik.common.socket.SocketMessage;
/**
* Message indicating that a player has died.
*
* @param playerId The ID of the player who died.
* @author Jakub Žitník (jzitnik)
*/
public record PlayerDeath(int playerId) implements SocketMessage { public record PlayerDeath(int playerId) implements SocketMessage {
} }

View File

@@ -2,5 +2,11 @@ package cz.jzitnik.common.socket.messages.game.connection;
import cz.jzitnik.common.socket.SocketMessage; import cz.jzitnik.common.socket.SocketMessage;
/**
* Message sent to request connection to a game.
*
* @param gamePass The password of the game to connect to.
* @author Jakub Žitník (jzitnik)
*/
public record ConnectToAGame(String gamePass) implements SocketMessage { public record ConnectToAGame(String gamePass) implements SocketMessage {
} }

View File

@@ -5,20 +5,45 @@ import cz.jzitnik.common.socket.SocketMessage;
import java.util.List; import java.util.List;
/**
* Response message sent after a connection request to a game.
*
* @param responseType The type of response (SUCCESS or GAME_DOES_NOT_EXIST).
* @param playerCreation Information about the player being created.
* @param existingPlayers List of existing players in the game.
* @author Jakub Žitník (jzitnik)
*/
public record ConnectToAGameResponse(ResponseType responseType, PlayerCreation playerCreation, List<PlayerCreation> existingPlayers) implements SocketMessage { public record ConnectToAGameResponse(ResponseType responseType, PlayerCreation playerCreation, List<PlayerCreation> existingPlayers) implements SocketMessage {
/**
* Enum representing the possible response types for game connection.
*/
private enum ResponseType { private enum ResponseType {
GAME_DOES_NOT_EXIST, GAME_DOES_NOT_EXIST,
SUCCESS SUCCESS
} }
/**
* Default constructor representing a failed connection (game does not exist).
*/
public ConnectToAGameResponse() { public ConnectToAGameResponse() {
this(ResponseType.GAME_DOES_NOT_EXIST, null, null); this(ResponseType.GAME_DOES_NOT_EXIST, null, null);
} }
/**
* Constructor for a successful connection.
*
* @param playerCreation Information about the player being created.
* @param existingPlayers List of existing players in the game.
*/
public ConnectToAGameResponse(PlayerCreation playerCreation, List<PlayerCreation> existingPlayers) { public ConnectToAGameResponse(PlayerCreation playerCreation, List<PlayerCreation> existingPlayers) {
this(ResponseType.SUCCESS, playerCreation, existingPlayers); this(ResponseType.SUCCESS, playerCreation, existingPlayers);
} }
/**
* Checks if the connection was successful.
*
* @return true if successful, false otherwise.
*/
public boolean success() { public boolean success() {
return responseType == ResponseType.SUCCESS; return responseType == ResponseType.SUCCESS;
} }

View File

@@ -2,5 +2,10 @@ package cz.jzitnik.common.socket.messages.game.creation;
import cz.jzitnik.common.socket.SocketMessage; import cz.jzitnik.common.socket.SocketMessage;
/**
* Message sent to request game creation.
*
* @author Jakub Žitník (jzitnik)
*/
public class CreateGame implements SocketMessage { public class CreateGame implements SocketMessage {
} }

View File

@@ -5,6 +5,11 @@ import cz.jzitnik.common.socket.SocketMessage;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/**
* Response message sent after a game is created.
*
* @author Jakub Žitník (jzitnik)
*/
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public class CreateGameResponse implements SocketMessage { public class CreateGameResponse implements SocketMessage {

View File

@@ -2,6 +2,13 @@ package cz.jzitnik.common.socket.messages.items;
import cz.jzitnik.common.socket.SocketMessage; import cz.jzitnik.common.socket.SocketMessage;
/**
* Message indicating that an item was taken from a chest.
*
* @param roomId The ID of the room where the chest is located.
* @param id The ID of the item taken.
* @author Jakub Žitník (jzitnik)
*/
public record ItemTookFromChest( public record ItemTookFromChest(
String roomId, // For faster lookup i guess String roomId, // For faster lookup i guess
int id int id

View File

@@ -3,6 +3,16 @@ package cz.jzitnik.common.socket.messages.player;
import cz.jzitnik.common.models.coordinates.RoomCords; import cz.jzitnik.common.models.coordinates.RoomCords;
import cz.jzitnik.common.socket.SocketMessage; import cz.jzitnik.common.socket.SocketMessage;
/**
* Message sent when a player's arrival status in a room changes.
*
* @param id The ID of the player.
* @param playerCords The current coordinates of the player.
* @param playerRotation The current rotation of the player.
* @param arrived Whether the player has arrived or departed.
* @param rerender Whether a rerender is requested.
* @author Jakub Žitník (jzitnik)
*/
public record PlayerArrivalChange(int id, RoomCords playerCords, PlayerRotation playerRotation, public record PlayerArrivalChange(int id, RoomCords playerCords, PlayerRotation playerRotation,
boolean arrived, boolean rerender) implements SocketMessage { boolean arrived, boolean rerender) implements SocketMessage {
} }

View File

@@ -2,5 +2,11 @@ package cz.jzitnik.common.socket.messages.player;
import cz.jzitnik.common.socket.SocketMessage; import cz.jzitnik.common.socket.SocketMessage;
/**
* Message indicating that a player has disconnected.
*
* @param playerId The ID of the player who disconnected.
* @author Jakub Žitník (jzitnik)
*/
public record PlayerDisconnected(int playerId) implements SocketMessage { public record PlayerDisconnected(int playerId) implements SocketMessage {
} }

View File

@@ -3,5 +3,11 @@ package cz.jzitnik.common.socket.messages.player;
import cz.jzitnik.common.models.player.PlayerCreation; import cz.jzitnik.common.models.player.PlayerCreation;
import cz.jzitnik.common.socket.SocketMessage; import cz.jzitnik.common.socket.SocketMessage;
/**
* Message indicating that a new player has joined the game.
*
* @param playerCreation Information about the player who joined.
* @author Jakub Žitník (jzitnik)
*/
public record PlayerJoined(PlayerCreation playerCreation) implements SocketMessage { public record PlayerJoined(PlayerCreation playerCreation) implements SocketMessage {
} }

View File

@@ -3,5 +3,12 @@ package cz.jzitnik.common.socket.messages.player;
import cz.jzitnik.common.models.coordinates.RoomCords; import cz.jzitnik.common.models.coordinates.RoomCords;
import cz.jzitnik.common.socket.SocketMessage; import cz.jzitnik.common.socket.SocketMessage;
/**
* Message sent when a player moves.
*
* @param newCords The new coordinates of the player.
* @param playerRotation The rotation of the player.
* @author Jakub Žitník (jzitnik)
*/
public record PlayerMove(RoomCords newCords, PlayerRotation playerRotation) implements SocketMessage { public record PlayerMove(RoomCords newCords, PlayerRotation playerRotation) implements SocketMessage {
} }

View File

@@ -5,6 +5,11 @@ import cz.jzitnik.common.socket.SocketMessage;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/**
* Message sent when another player moves within the same room.
*
* @author Jakub Žitník (jzitnik)
*/
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public class PlayerMovedInUrRoom implements SocketMessage { public class PlayerMovedInUrRoom implements SocketMessage {

View File

@@ -1,5 +1,10 @@
package cz.jzitnik.common.socket.messages.player; package cz.jzitnik.common.socket.messages.player;
/**
* Enum representing the possible rotations of a player.
*
* @author Jakub Žitník (jzitnik)
*/
public enum PlayerRotation { public enum PlayerRotation {
FRONT, BACK, LEFT, RIGHT FRONT, BACK, LEFT, RIGHT
} }

View File

@@ -3,6 +3,14 @@ package cz.jzitnik.common.socket.messages.room;
import cz.jzitnik.common.models.coordinates.RoomCords; import cz.jzitnik.common.models.coordinates.RoomCords;
import cz.jzitnik.common.socket.SocketMessage; import cz.jzitnik.common.socket.SocketMessage;
/**
* Message sent to request moving a player to a new room.
*
* @param newRoomId The ID of the room to move to.
* @param oldCords The coordinates in the old room.
* @param newCords The initial coordinates in the new room.
* @author Jakub Žitník (jzitnik)
*/
public record MovePlayerRoom(String newRoomId, RoomCords oldCords, RoomCords newCords) implements SocketMessage { public record MovePlayerRoom(String newRoomId, RoomCords oldCords, RoomCords newCords) implements SocketMessage {
} }

View File

@@ -9,13 +9,37 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/**
* Response message sent after a player moves to a different room.
*
* @param players Set of players currently in the new room.
* @author Jakub Žitník (jzitnik)
*/
public record MovePlayerRoomResponse(Set<Registry> players) implements SocketMessage { public record MovePlayerRoomResponse(Set<Registry> players) implements SocketMessage {
/**
* Represents a registry of a player in a room.
*
* @param id The ID of the player.
* @param cords The coordinates of the player.
* @param playerRotation The rotation of the player.
*/
public record Registry(int id, RoomCords cords, PlayerRotation playerRotation) implements Serializable {} public record Registry(int id, RoomCords cords, PlayerRotation playerRotation) implements Serializable {}
/**
* Gets a player's registry by their ID.
*
* @param id The ID of the player to find.
* @return An Optional containing the registry if found, otherwise empty.
*/
public Optional<Registry> getById(int id) { public Optional<Registry> getById(int id) {
return players.stream().filter(registry -> registry.id == id).findFirst(); return players.stream().filter(registry -> registry.id == id).findFirst();
} }
/**
* Gets the set of IDs of all players in the response.
*
* @return A Set of player IDs.
*/
public Set<Integer> getIds() { public Set<Integer> getIds() {
return players.stream().map(Registry::id).collect(Collectors.toSet()); return players.stream().map(Registry::id).collect(Collectors.toSet());
} }

View File

@@ -17,6 +17,11 @@ import lombok.extern.slf4j.Slf4j;
import java.io.IOException; import java.io.IOException;
/**
* Command line interface handler using Lanterna.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
@Dependency @Dependency
public class Cli implements Runnable { public class Cli implements Runnable {
@@ -29,6 +34,9 @@ public class Cli implements Runnable {
@InjectState @InjectState
private RunningState runningState; private RunningState runningState;
/**
* Runs the CLI thread, handling terminal input and events.
*/
@Override @Override
public void run() { public void run() {
// Start event manager thread // Start event manager thread

View File

@@ -14,6 +14,11 @@ import org.reflections.Reflections;
import java.io.IOException; import java.io.IOException;
/**
* Main game class responsible for initialization and starting the game loop.
*
* @author Jakub Žitník (jzitnik)
*/
public class Game { public class Game {
private final DependencyManager dependencyManager = new DependencyManager(new Reflections("cz.jzitnik.client")); private final DependencyManager dependencyManager = new DependencyManager(new Reflections("cz.jzitnik.client"));
@@ -32,6 +37,11 @@ public class Game {
@InjectDependency @InjectDependency
private GlobalIOHandlerRepository globalIOHandlerRepository; private GlobalIOHandlerRepository globalIOHandlerRepository;
/**
* Starts the game by injecting dependencies and initializing managers.
*
* @throws IOException If an I/O error occurs
*/
public void start() throws IOException { public void start() throws IOException {
dependencyManager.inject(this); dependencyManager.inject(this);

View File

@@ -4,7 +4,18 @@ package cz.jzitnik.client;
import java.io.IOException; import java.io.IOException;
/**
* Main entry point for the client application.
*
* @author Jakub Žitník (jzitnik)
*/
public class Main { public class Main {
/**
* Main method that starts the game.
*
* @param args Command line arguments
* @throws IOException If an I/O error occurs
*/
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
new Game().start(); new Game().start();
} }

View File

@@ -5,8 +5,18 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
/**
* Annotation to mark a class as a configuration component loaded from a YAML file.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public @interface Config { public @interface Config {
/**
* The YAML file name.
*
* @return file name
*/
String value(); String value();
} }

View File

@@ -5,9 +5,18 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
/**
* Annotation to mark a class as a dependency for the DependencyManager.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public @interface Dependency { public @interface Dependency {
/** Custom alias **/ /**
* Custom alias for the dependency.
*
* @return Alias class
*/
Class<?> value() default Object.class; Class<?> value() default Object.class;
} }

View File

@@ -7,8 +7,18 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
/**
* Annotation to mark a class as an event handler for a specific Event type.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public @interface EventHandler { public @interface EventHandler {
/**
* The type of Event this handler handles.
*
* @return Event class
*/
Class<? extends Event> value(); Class<? extends Event> value();
} }

View File

@@ -5,6 +5,11 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
/**
* Annotation to mark a method to be called after dependency injection.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
public @interface PostInit { public @interface PostInit {

View File

@@ -6,9 +6,24 @@ import java.lang.annotation.Target;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* Annotation to mark a task for periodic execution.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public @interface ScheduledTask { public @interface ScheduledTask {
/**
* Execution rate.
*
* @return rate
*/
long rate(); long rate();
/**
* Time unit for the rate.
*
* @return rate unit
*/
TimeUnit rateUnit(); TimeUnit rateUnit();
} }

View File

@@ -7,8 +7,18 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/**
* Annotation to mark a class as a socket event handler for a specific SocketMessage type.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public @interface SocketEventHandler { public @interface SocketEventHandler {
/**
* The type of SocketMessage this handler handles.
*
* @return SocketMessage class
*/
Class<? extends SocketMessage> value(); Class<? extends SocketMessage> value();
} }

View File

@@ -5,6 +5,11 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
/**
* Annotation to mark a class as a state component.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public @interface State { public @interface State {

View File

@@ -5,6 +5,11 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
/**
* Annotation to mark a class for automatic thread registration.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public @interface ThreadRegistry { public @interface ThreadRegistry {

View File

@@ -5,6 +5,11 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/**
* Annotation to inject a configuration component into a field.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD}) @Target({ElementType.FIELD})
public @interface InjectConfig { public @interface InjectConfig {

View File

@@ -5,6 +5,11 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/**
* Annotation to inject a dependency into a field.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD}) @Target({ElementType.FIELD})
public @interface InjectDependency { public @interface InjectDependency {

View File

@@ -5,6 +5,11 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/**
* Annotation to inject a state component into a field.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD}) @Target({ElementType.FIELD})
public @interface InjectState { public @interface InjectState {

View File

@@ -4,10 +4,25 @@ import com.googlecode.lanterna.input.KeyType;
import java.lang.annotation.*; import java.lang.annotation.*;
/**
* Annotation to mark a method as a keyboard press handler.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Repeatable(KeyboardPressHandlers.class) @Repeatable(KeyboardPressHandlers.class)
public @interface KeyboardPressHandler { public @interface KeyboardPressHandler {
/**
* The key type to handle.
*
* @return key type
*/
KeyType keyType() default KeyType.Character; KeyType keyType() default KeyType.Character;
/**
* The specific character to handle (if keyType is Character).
*
* @return character
*/
char character() default '\0'; char character() default '\0';
} }

View File

@@ -5,8 +5,18 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/**
* Container annotation for repeatable KeyboardPressHandler.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
public @interface KeyboardPressHandlers { public @interface KeyboardPressHandlers {
/**
* Array of KeyboardPressHandler annotations.
*
* @return handlers
*/
KeyboardPressHandler[] value(); KeyboardPressHandler[] value();
} }

View File

@@ -5,8 +5,18 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
/**
* Annotation to mark a method as a mouse handler.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
public @interface MouseHandler { public @interface MouseHandler {
/**
* The type of mouse action to handle.
*
* @return handler type
*/
MouseHandlerType value(); MouseHandlerType value();
} }

View File

@@ -1,5 +1,10 @@
package cz.jzitnik.client.annotations.ui; package cz.jzitnik.client.annotations.ui;
/**
* Enum representing types of mouse handlers.
*
* @author Jakub Žitník (jzitnik)
*/
public enum MouseHandlerType { public enum MouseHandlerType {
CLICK, CLICK,
MOVE, MOVE,

View File

@@ -5,6 +5,11 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
/**
* Annotation to mark a method as a rendering method.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
public @interface Render { public @interface Render {

View File

@@ -5,6 +5,11 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
/**
* Annotation to mark a class as a UI component.
*
* @author Jakub Žitník (jzitnik)
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public @interface UI { public @interface UI {

View File

@@ -4,8 +4,19 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import cz.jzitnik.client.annotations.Config; import cz.jzitnik.client.annotations.Config;
/**
* Configuration for core game logic.
*
* @param itemDropDisappearMinutes Minutes before a dropped item disappears
* @author Jakub Žitník (jzitnik)
*/
@Config("core_logic.yaml") @Config("core_logic.yaml")
public record CoreLogic(int itemDropDisappearMinutes) { public record CoreLogic(int itemDropDisappearMinutes) {
/**
* Constructs a CoreLogic configuration instance.
*
* @param itemDropDisappearMinutes Disappear timeout in minutes
*/
@JsonCreator @JsonCreator
public CoreLogic( public CoreLogic(
@JsonProperty("itemDropDisappearMinutes") int itemDropDisappearMinutes @JsonProperty("itemDropDisappearMinutes") int itemDropDisappearMinutes

View File

@@ -4,8 +4,23 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import cz.jzitnik.client.annotations.Config; import cz.jzitnik.client.annotations.Config;
/**
* Configuration for debugging features.
*
* @param renderColliders Whether to render colliders
* @param renderPlayerCollider Whether to render the player's collider
* @param showPlayerCordsLogs Whether to show player coordinate logs
* @author Jakub Žitník (jzitnik)
*/
@Config("debugging.yaml") @Config("debugging.yaml")
public record Debugging(boolean renderColliders, boolean renderPlayerCollider, boolean showPlayerCordsLogs) { public record Debugging(boolean renderColliders, boolean renderPlayerCollider, boolean showPlayerCordsLogs) {
/**
* Constructs a Debugging configuration instance.
*
* @param renderColliders Whether to render colliders
* @param renderPlayerCollider Whether to render the player's collider
* @param showPlayerCordsLogs Whether to show player coordinate logs
*/
@JsonCreator @JsonCreator
public Debugging( public Debugging(
@JsonProperty("renderColliders") boolean renderColliders, @JsonProperty("renderColliders") boolean renderColliders,

View File

@@ -4,8 +4,19 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import cz.jzitnik.client.annotations.Config; import cz.jzitnik.client.annotations.Config;
/**
* Configuration for microphone input.
*
* @param volumeThreshold The volume threshold for activation
* @author Jakub Žitník (jzitnik)
*/
@Config("microphone.yaml") @Config("microphone.yaml")
public record MicrophoneConfig(float volumeThreshold) { public record MicrophoneConfig(float volumeThreshold) {
/**
* Constructs a MicrophoneConfig instance.
*
* @param volumeThreshold The volume threshold
*/
@JsonCreator @JsonCreator
public MicrophoneConfig( public MicrophoneConfig(
@JsonProperty("volumeThreshold") float volumeThreshold @JsonProperty("volumeThreshold") float volumeThreshold

View File

@@ -5,6 +5,18 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import cz.jzitnik.client.annotations.Config; import cz.jzitnik.client.annotations.Config;
import cz.jzitnik.client.events.handlers.PlayerMoveEventHandler; import cz.jzitnik.client.events.handlers.PlayerMoveEventHandler;
/**
* Configuration for player-related settings.
*
* @param playerReach The distance a player can reach
* @param playerMoveDistance The distance a player moves normally
* @param playerMoveDistanceSprinting The distance a player moves while sprinting
* @param sprintKey The key used for sprinting
* @param swingTimeMs Time in milliseconds for a weapon swing
* @param staminaIncreaseRateMs Rate at which stamina increases
* @param staminaDelayMs Delay before stamina starts increasing
* @author Jakub Žitník (jzitnik)
*/
@Config("player.yaml") @Config("player.yaml")
public record PlayerConfig( public record PlayerConfig(
double playerReach, double playerReach,
@@ -15,6 +27,17 @@ public record PlayerConfig(
int staminaIncreaseRateMs, int staminaIncreaseRateMs,
int staminaDelayMs int staminaDelayMs
) { ) {
/**
* Constructs a PlayerConfig instance.
*
* @param playerReach Player reach
* @param playerMoveDistance Move distance
* @param playerMoveDistanceSprinting Sprint move distance
* @param sprintKey Sprint key
* @param swingTimeMs Swing time
* @param staminaIncreaseRateMs Stamina increase rate
* @param staminaDelayMs Stamina delay
*/
@JsonCreator @JsonCreator
public PlayerConfig( public PlayerConfig(
@JsonProperty("playerReach") double playerReach, @JsonProperty("playerReach") double playerReach,

View File

@@ -4,8 +4,21 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import cz.jzitnik.client.annotations.Config; import cz.jzitnik.client.annotations.Config;
/**
* Configuration for thread pool sizes.
*
* @param eventThreadCount Number of threads for events
* @param taskThreadCount Number of threads for tasks
* @author Jakub Žitník (jzitnik)
*/
@Config("threads.yaml") @Config("threads.yaml")
public record ThreadPoolConfig(int eventThreadCount, int taskThreadCount) { public record ThreadPoolConfig(int eventThreadCount, int taskThreadCount) {
/**
* Constructs a ThreadPoolConfig instance.
*
* @param eventThreadCount Event thread count
* @param taskThreadCount Task thread count
*/
@JsonCreator @JsonCreator
public ThreadPoolConfig( public ThreadPoolConfig(
@JsonProperty("eventThreadCount") int eventThreadCount, @JsonProperty("eventThreadCount") int eventThreadCount,

View File

@@ -2,6 +2,10 @@ package cz.jzitnik.client.events;
import cz.jzitnik.client.utils.events.Event; import cz.jzitnik.client.utils.events.Event;
/** Custom event without any handler **/ /**
* Event indicating that the application should exit.
*
* @author Jakub Žitník (jzitnik)
*/
public class ExitEvent implements Event { public class ExitEvent implements Event {
} }

View File

@@ -5,6 +5,11 @@ import cz.jzitnik.client.utils.events.Event;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/**
* Event triggered when a key is pressed.
*
* @author Jakub Žitník (jzitnik)
*/
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public class KeyboardPressEvent implements Event { public class KeyboardPressEvent implements Event {

View File

@@ -4,11 +4,28 @@ import com.googlecode.lanterna.TerminalPosition;
import com.googlecode.lanterna.input.MouseActionType; import com.googlecode.lanterna.input.MouseActionType;
import cz.jzitnik.client.utils.events.Event; import cz.jzitnik.client.utils.events.Event;
/**
* Event triggered by a mouse action.
*
* @author Jakub Žitník (jzitnik)
*/
public class MouseAction extends com.googlecode.lanterna.input.MouseAction implements Event { public class MouseAction extends com.googlecode.lanterna.input.MouseAction implements Event {
/**
* Constructs a MouseAction.
*
* @param actionType The type of action
* @param button The button involved
* @param position The terminal position
*/
public MouseAction(MouseActionType actionType, int button, TerminalPosition position) { public MouseAction(MouseActionType actionType, int button, TerminalPosition position) {
super(actionType, button, position); super(actionType, button, position);
} }
/**
* Constructs a MouseAction from an existing Lanterna MouseAction.
*
* @param mouseAction The Lanterna mouse action
*/
public MouseAction(com.googlecode.lanterna.input.MouseAction mouseAction) { public MouseAction(com.googlecode.lanterna.input.MouseAction mouseAction) {
this(mouseAction.getActionType(), mouseAction.getButton(), mouseAction.getPosition()); this(mouseAction.getActionType(), mouseAction.getButton(), mouseAction.getPosition());
} }

View File

@@ -4,6 +4,11 @@ import cz.jzitnik.client.utils.events.Event;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/**
* Event triggered by a mouse movement.
*
* @author Jakub Žitník (jzitnik)
*/
@AllArgsConstructor @AllArgsConstructor
@Getter @Getter
public class MouseMoveEvent implements Event { public class MouseMoveEvent implements Event {

View File

@@ -5,6 +5,11 @@ import cz.jzitnik.client.utils.events.Event;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/**
* Event triggered when a player attempts to move.
*
* @author Jakub Žitník (jzitnik)
*/
@AllArgsConstructor @AllArgsConstructor
@Getter @Getter
public class PlayerMoveEvent implements Event { public class PlayerMoveEvent implements Event {

View File

@@ -4,6 +4,11 @@ import cz.jzitnik.client.utils.events.Event;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/**
* Event requesting a rerender of a specific part of the screen.
*
* @author Jakub Žitník (jzitnik)
*/
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public class RerenderPart implements Event { public class RerenderPart implements Event {

View File

@@ -5,6 +5,11 @@ import cz.jzitnik.client.utils.events.Event;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/**
* Event triggered when the terminal is resized.
*
* @author Jakub Žitník (jzitnik)
*/
@AllArgsConstructor @AllArgsConstructor
@Getter @Getter
public class TerminalResizeEvent implements Event { public class TerminalResizeEvent implements Event {

View File

@@ -2,5 +2,10 @@ package cz.jzitnik.client.events;
import cz.jzitnik.client.utils.events.Event; import cz.jzitnik.client.utils.events.Event;
/**
* Event triggered when the terminal window is too small to render the game.
*
* @author Jakub Žitník (jzitnik)
*/
public class TerminalTooSmallEvent implements Event { public class TerminalTooSmallEvent implements Event {
} }

View File

@@ -18,6 +18,11 @@ import lombok.extern.slf4j.Slf4j;
import java.io.IOException; import java.io.IOException;
/**
* Handler for the RerenderScreen event in the CLI.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
@EventHandler(RerenderScreen.class) @EventHandler(RerenderScreen.class)
public class CliHandler extends AbstractEventHandler<RerenderScreen> { public class CliHandler extends AbstractEventHandler<RerenderScreen> {
@@ -30,6 +35,11 @@ public class CliHandler extends AbstractEventHandler<RerenderScreen> {
@InjectState @InjectState
private RenderState renderState; private RenderState renderState;
/**
* Handles the RerenderScreen event by drawing requested parts of the screen buffer to the terminal.
*
* @param event The RerenderScreen event
*/
@Override @Override
public void handle(RerenderScreen event) { public void handle(RerenderScreen event) {
if (renderState.isTerminalTooSmall()) { if (renderState.isTerminalTooSmall()) {
@@ -79,6 +89,13 @@ public class CliHandler extends AbstractEventHandler<RerenderScreen> {
} }
} }
/**
* Resolves the final pixel color by blending with the global override buffer.
*
* @param buffer The base pixel from the rendered buffer
* @param globalOverride The pixel from the global override buffer
* @return The final pixel to draw
*/
private Pixel getPixel(Pixel buffer, AlphaPixel globalOverride) { private Pixel getPixel(Pixel buffer, AlphaPixel globalOverride) {
if (globalOverride instanceof Empty) { if (globalOverride instanceof Empty) {
return buffer; return buffer;
@@ -97,6 +114,14 @@ public class CliHandler extends AbstractEventHandler<RerenderScreen> {
return new ColoredPixel(blended); return new ColoredPixel(blended);
} }
/**
* Blends two colors using an alpha value.
*
* @param base The base color
* @param overlay The overlay color
* @param alpha The alpha transparency of the overlay
* @return The blended color
*/
private TextColor blendColors(TextColor base, TextColor overlay, float alpha) { private TextColor blendColors(TextColor base, TextColor overlay, float alpha) {
int r = blend(base.getRed(), overlay.getRed(), alpha); int r = blend(base.getRed(), overlay.getRed(), alpha);
int g = blend(base.getGreen(), overlay.getGreen(), alpha); int g = blend(base.getGreen(), overlay.getGreen(), alpha);
@@ -105,10 +130,27 @@ public class CliHandler extends AbstractEventHandler<RerenderScreen> {
return new TextColor.RGB(r, g, b); return new TextColor.RGB(r, g, b);
} }
/**
* Internal helper to blend a single color channel.
*
* @param base Base channel value
* @param overlay Overlay channel value
* @param alpha Alpha transparency
* @return Blended channel value
*/
private int blend(int base, int overlay, float alpha) { private int blend(int base, int overlay, float alpha) {
return Math.round(base * (1 - alpha) + overlay * alpha); return Math.round(base * (1 - alpha) + overlay * alpha);
} }
/**
* Draws a "half-pixel" using Unicode character '▄' to achieve higher vertical resolution.
*
* @param tg The TextGraphics context
* @param x X terminal position
* @param y Y terminal position
* @param topColor Color for the top half
* @param bottomColor Color for the bottom half
*/
private void drawHalfPixel(TextGraphics tg, int x, int y, private void drawHalfPixel(TextGraphics tg, int x, int y,
TextColor topColor, TextColor topColor,
TextColor bottomColor) { TextColor bottomColor) {

View File

@@ -26,6 +26,11 @@ import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/**
* Handler for the Dialog event.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
@EventHandler(Dialog.class) @EventHandler(Dialog.class)
public class DialogEventHandler extends AbstractEventHandler<Dialog> { public class DialogEventHandler extends AbstractEventHandler<Dialog> {
@@ -53,13 +58,23 @@ public class DialogEventHandler extends AbstractEventHandler<Dialog> {
private static final int WIDTH = 350; private static final int WIDTH = 350;
private static final int MARGIN_BOTTOM = 15; private static final int MARGIN_BOTTOM = 15;
/** Padding for the dialog box. */
public static final int PADDING = 7; public static final int PADDING = 7;
private static final int BUTTON_TEXT_PADDING = 4; private static final int BUTTON_TEXT_PADDING = 4;
private static final int QUESTION_ACTIONS_GAP = 10; private static final int QUESTION_ACTIONS_GAP = 10;
/** Height of a button in the dialog. */
public static final int BUTTON_HEIGHT = 15; public static final int BUTTON_HEIGHT = 15;
/** Padding for buttons in the dialog. */
public static final int BUTTON_PADDING = 5; public static final int BUTTON_PADDING = 5;
private static final float FONT_SIZE = 15f; private static final float FONT_SIZE = 15f;
/**
* Calculates the total height required for buttons in a dialog.
*
* @param dialog The dialog
* @param gameState Current game state
* @return Calculated height
*/
public static int calculateButtonHeight(Dialog dialog, GameState gameState) { public static int calculateButtonHeight(Dialog dialog, GameState gameState) {
if (dialog.getOnEnd() instanceof OnEnd.AskQuestion askQuestion) { if (dialog.getOnEnd() instanceof OnEnd.AskQuestion askQuestion) {
int count = askQuestion.answers(gameState).length; int count = askQuestion.answers(gameState).length;
@@ -68,6 +83,13 @@ public class DialogEventHandler extends AbstractEventHandler<Dialog> {
return 0; return 0;
} }
/**
* Calculates the starting Y coordinate for buttons.
*
* @param textRenderer The text renderer
* @param dialog The dialog
* @return Starting Y coordinate
*/
public static int getYStartButtons(TextRenderer textRenderer, Dialog dialog) { public static int getYStartButtons(TextRenderer textRenderer, Dialog dialog) {
var textSize = textRenderer.measureText( var textSize = textRenderer.measureText(
dialog.getText(), dialog.getText(),
@@ -78,6 +100,14 @@ public class DialogEventHandler extends AbstractEventHandler<Dialog> {
return PADDING + textSize.height + BUTTON_PADDING; return PADDING + textSize.height + BUTTON_PADDING;
} }
/**
* Calculates the overall size of the dialog box.
*
* @param textRenderer The text renderer
* @param dialog The dialog
* @param gameState Current game state
* @return The terminal size
*/
public static TerminalSize getSize(TextRenderer textRenderer, Dialog dialog, GameState gameState) { public static TerminalSize getSize(TextRenderer textRenderer, Dialog dialog, GameState gameState) {
var textSize = textRenderer.measureText( var textSize = textRenderer.measureText(
dialog.getText(), dialog.getText(),
@@ -96,12 +126,24 @@ public class DialogEventHandler extends AbstractEventHandler<Dialog> {
); );
} }
/**
* Calculates the starting terminal position for the dialog box.
*
* @param terminalSize Current terminal size
* @param size Size of the dialog box
* @return Starting position
*/
public static TerminalPosition getStart(TerminalSize terminalSize, TerminalSize size) { public static TerminalPosition getStart(TerminalSize terminalSize, TerminalSize size) {
int startY = terminalSize.getRows() * 2 - MARGIN_BOTTOM - size.getRows(); int startY = terminalSize.getRows() * 2 - MARGIN_BOTTOM - size.getRows();
int startX = (terminalSize.getColumns() / 2) - (size.getColumns() / 2); int startX = (terminalSize.getColumns() / 2) - (size.getColumns() / 2);
return new TerminalPosition(startX, startY); return new TerminalPosition(startX, startY);
} }
/**
* Handles the Dialog event by rendering it with typing animation.
*
* @param event The Dialog event
*/
@Override @Override
public void handle(Dialog event) { public void handle(Dialog event) {
boolean onlyLast = dialogState.getCurrentDialog() == event; boolean onlyLast = dialogState.getCurrentDialog() == event;

View File

@@ -10,11 +10,21 @@ import cz.jzitnik.client.utils.events.EventManager;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
/**
* Handler for the DroppedItemRerender event.
*
* @author Jakub Žitník (jzitnik)
*/
@EventHandler(DroppedItemRerender.class) @EventHandler(DroppedItemRerender.class)
public class DroppedItemRerenderHandler extends AbstractEventHandler<DroppedItemRerender> { public class DroppedItemRerenderHandler extends AbstractEventHandler<DroppedItemRerender> {
@InjectDependency @InjectDependency
private EventManager eventManager; private EventManager eventManager;
/**
* Handles the DroppedItemRerender event by emitting a RerenderPart event.
*
* @param event The DroppedItemRerender event
*/
@Override @Override
public void handle(DroppedItemRerender event) { public void handle(DroppedItemRerender event) {
RoomCords droppedItemCords = event.droppedItem().getCords(); RoomCords droppedItemCords = event.droppedItem().getCords();

View File

@@ -10,6 +10,11 @@ import cz.jzitnik.client.utils.ThreadManager;
import cz.jzitnik.client.utils.events.AbstractEventHandler; import cz.jzitnik.client.utils.events.AbstractEventHandler;
import cz.jzitnik.client.utils.roomtasks.RoomTaskScheduler; import cz.jzitnik.client.utils.roomtasks.RoomTaskScheduler;
/**
* Handler for the ExitEvent.
*
* @author Jakub Žitník (jzitnik)
*/
@EventHandler(ExitEvent.class) @EventHandler(ExitEvent.class)
public class ExitEventHandler extends AbstractEventHandler<ExitEvent> { public class ExitEventHandler extends AbstractEventHandler<ExitEvent> {
@InjectDependency @InjectDependency
@@ -24,6 +29,11 @@ public class ExitEventHandler extends AbstractEventHandler<ExitEvent> {
@InjectDependency @InjectDependency
private ScheduledTaskManager scheduledTaskManager; private ScheduledTaskManager scheduledTaskManager;
/**
* Handles the ExitEvent by shutting down all managers and setting the running state to false.
*
* @param event The ExitEvent
*/
@Override @Override
public void handle(ExitEvent event) { public void handle(ExitEvent event) {
threadManager.shutdownAll(); threadManager.shutdownAll();

View File

@@ -12,6 +12,11 @@ import cz.jzitnik.client.utils.events.EventManager;
import java.io.IOException; import java.io.IOException;
/**
* Handler for the FullRedrawEvent.
*
* @author Jakub Žitník (jzitnik)
*/
@EventHandler(FullRedrawEvent.class) @EventHandler(FullRedrawEvent.class)
public class FullRedrawEventHandler extends AbstractEventHandler<FullRedrawEvent> { public class FullRedrawEventHandler extends AbstractEventHandler<FullRedrawEvent> {
@InjectDependency @InjectDependency
@@ -20,6 +25,11 @@ public class FullRedrawEventHandler extends AbstractEventHandler<FullRedrawEvent
@InjectState @InjectState
private TerminalState terminalState; private TerminalState terminalState;
/**
* Handles the FullRedrawEvent by clearing the terminal and emitting a FullRoomDraw event.
*
* @param event The FullRedrawEvent
*/
@Override @Override
public void handle(FullRedrawEvent event) { public void handle(FullRedrawEvent event) {
terminalState.getTerminalScreen().clear(); terminalState.getTerminalScreen().clear();

View File

@@ -32,6 +32,11 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* Handler for the FullRoomDraw event.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
@EventHandler(FullRoomDraw.class) @EventHandler(FullRoomDraw.class)
public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> { public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
@@ -55,6 +60,11 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
@InjectDependency @InjectDependency
private GlobalIOHandlerRepository globalIOHandlerRepository; private GlobalIOHandlerRepository globalIOHandlerRepository;
/**
* Handles the FullRoomDraw event by rendering the entire room and players.
*
* @param event The FullRoomDraw event
*/
@Override @Override
public void handle(FullRoomDraw event) { public void handle(FullRoomDraw event) {
try { try {
@@ -103,6 +113,9 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
} }
} }
/**
* Enum representing door positions in a room.
*/
public enum DoorPosition { public enum DoorPosition {
TOP, TOP,
LEFT, LEFT,

View File

@@ -9,6 +9,11 @@ import cz.jzitnik.client.ui.Inventory;
import cz.jzitnik.client.utils.events.AbstractEventHandler; import cz.jzitnik.client.utils.events.AbstractEventHandler;
import cz.jzitnik.client.utils.events.EventManager; import cz.jzitnik.client.utils.events.EventManager;
/**
* Handler for the InventoryRerender event.
*
* @author Jakub Žitník (jzitnik)
*/
@EventHandler(InventoryRerender.class) @EventHandler(InventoryRerender.class)
public class InventoryRerenderHandler extends AbstractEventHandler<InventoryRerender> { public class InventoryRerenderHandler extends AbstractEventHandler<InventoryRerender> {
@InjectDependency @InjectDependency
@@ -17,6 +22,11 @@ public class InventoryRerenderHandler extends AbstractEventHandler<InventoryRere
@InjectDependency @InjectDependency
private Inventory inventory; private Inventory inventory;
/**
* Handles the InventoryRerender event by rerendering the inventory UI component.
*
* @param event The InventoryRerender event
*/
@Override @Override
public void handle(InventoryRerender event) { public void handle(InventoryRerender event) {
inventory.renderInventoryRerender(); inventory.renderInventoryRerender();

View File

@@ -8,6 +8,11 @@ import cz.jzitnik.client.game.GameState;
import cz.jzitnik.client.utils.GlobalIOHandlerRepository; import cz.jzitnik.client.utils.GlobalIOHandlerRepository;
import cz.jzitnik.client.utils.events.AbstractEventHandler; import cz.jzitnik.client.utils.events.AbstractEventHandler;
/**
* Handler for the KeyboardPressEvent.
*
* @author Jakub Žitník (jzitnik)
*/
@EventHandler(KeyboardPressEvent.class) @EventHandler(KeyboardPressEvent.class)
public class KeyboardPressEventHandler extends AbstractEventHandler<KeyboardPressEvent> { public class KeyboardPressEventHandler extends AbstractEventHandler<KeyboardPressEvent> {
@InjectState @InjectState
@@ -16,6 +21,11 @@ public class KeyboardPressEventHandler extends AbstractEventHandler<KeyboardPres
@InjectDependency @InjectDependency
private GlobalIOHandlerRepository globalIOHandlerRepository; private GlobalIOHandlerRepository globalIOHandlerRepository;
/**
* Handles the KeyboardPressEvent by delegating to the current screen or the global repository.
*
* @param event The KeyboardPressEvent
*/
@Override @Override
public void handle(KeyboardPressEvent event) { public void handle(KeyboardPressEvent event) {
if (gameState.getScreen() != null) { if (gameState.getScreen() != null) {

View File

@@ -18,6 +18,11 @@ import cz.jzitnik.client.utils.events.EventManager;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Stream; import java.util.stream.Stream;
/**
* Handler for the MouseAction event.
*
* @author Jakub Žitník (jzitnik)
*/
@EventHandler(MouseAction.class) @EventHandler(MouseAction.class)
public class MouseActionEventHandler extends AbstractEventHandler<MouseAction> { public class MouseActionEventHandler extends AbstractEventHandler<MouseAction> {
@InjectDependency @InjectDependency
@@ -38,6 +43,11 @@ public class MouseActionEventHandler extends AbstractEventHandler<MouseAction> {
@InjectDependency @InjectDependency
private DependencyManager dependencyManager; private DependencyManager dependencyManager;
/**
* Handles the MouseAction event by delegating to screens, repositories, or performing interactions.
*
* @param event The MouseAction event
*/
@Override @Override
public void handle(MouseAction event) { public void handle(MouseAction event) {
if (gameState.getScreen() != null) { if (gameState.getScreen() != null) {

View File

@@ -32,6 +32,11 @@ import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
/**
* Handler for the MouseMoveEvent.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
@EventHandler(MouseMoveEvent.class) @EventHandler(MouseMoveEvent.class)
public class MouseMoveEventHandler extends AbstractEventHandler<MouseMoveEvent> { public class MouseMoveEventHandler extends AbstractEventHandler<MouseMoveEvent> {
@@ -58,6 +63,17 @@ public class MouseMoveEventHandler extends AbstractEventHandler<MouseMoveEvent>
@InjectConfig @InjectConfig
private PlayerConfig playerConfig; private PlayerConfig playerConfig;
/**
* Calculates the distance from a point to a rectangle.
*
* @param px Point X
* @param py Point Y
* @param rectTopLeftX Rectangle top-left X
* @param rectTopLeftY Rectangle top-left Y
* @param rectBottomRightX Rectangle bottom-right X
* @param rectBottomRightY Rectangle bottom-right Y
* @return Distance as double
*/
private double distancePointToRect( private double distancePointToRect(
double px, double py, double px, double py,
double rectTopLeftX, double rectTopLeftY, double rectTopLeftX, double rectTopLeftY,
@@ -81,6 +97,11 @@ public class MouseMoveEventHandler extends AbstractEventHandler<MouseMoveEvent>
} }
} }
/**
* Handles the MouseMoveEvent by updating selectable object states based on hover and distance.
*
* @param event The MouseMoveEvent
*/
@Override @Override
public void handle(MouseMoveEvent event) { public void handle(MouseMoveEvent event) {
if (event.getMouseAction() != null) { if (event.getMouseAction() != null) {

View File

@@ -26,6 +26,11 @@ import lombok.extern.slf4j.Slf4j;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
/**
* Handler for the PlayerMoveEvent.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
@EventHandler(PlayerMoveEvent.class) @EventHandler(PlayerMoveEvent.class)
public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent> { public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent> {
@@ -50,6 +55,11 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
@InjectDependency @InjectDependency
private Stats stats; private Stats stats;
/**
* Handles the PlayerMoveEvent by updating player position and triggering rerenders.
*
* @param event The PlayerMoveEvent
*/
@Override @Override
public void handle(PlayerMoveEvent event) { public void handle(PlayerMoveEvent event) {
if (renderState.isTerminalTooSmall()) { if (renderState.isTerminalTooSmall()) {
@@ -159,6 +169,9 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
}); });
} }
/**
* Enum representing keys that can be used for sprinting.
*/
public static enum SprintKey { public static enum SprintKey {
CTRL, CTRL,
SHIFT, SHIFT,

View File

@@ -9,6 +9,11 @@ import cz.jzitnik.client.ui.Stats;
import cz.jzitnik.client.utils.events.AbstractEventHandler; import cz.jzitnik.client.utils.events.AbstractEventHandler;
import cz.jzitnik.client.utils.events.EventManager; import cz.jzitnik.client.utils.events.EventManager;
/**
* Handler for the RenderStats event.
*
* @author Jakub Žitník (jzitnik)
*/
@EventHandler(RenderStats.class) @EventHandler(RenderStats.class)
public class RenderStatsHandler extends AbstractEventHandler<RenderStats> { public class RenderStatsHandler extends AbstractEventHandler<RenderStats> {
@InjectDependency @InjectDependency
@@ -17,6 +22,11 @@ public class RenderStatsHandler extends AbstractEventHandler<RenderStats> {
@InjectDependency @InjectDependency
private Stats stats; private Stats stats;
/**
* Handles the RenderStats event by rerendering the stats UI component.
*
* @param event The RenderStats event
*/
@Override @Override
public void handle(RenderStats event) { public void handle(RenderStats event) {
stats.rerender(); stats.rerender();

View File

@@ -20,6 +20,11 @@ import cz.jzitnik.client.utils.events.EventManager;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
/**
* Handler for the RerenderPart event.
*
* @author Jakub Žitník (jzitnik)
*/
@EventHandler(RerenderPart.class) @EventHandler(RerenderPart.class)
public class RerenderPartHandler extends AbstractEventHandler<RerenderPart> { public class RerenderPartHandler extends AbstractEventHandler<RerenderPart> {
@InjectState @InjectState
@@ -40,6 +45,11 @@ public class RerenderPartHandler extends AbstractEventHandler<RerenderPart> {
@InjectDependency @InjectDependency
private EventManager eventManager; private EventManager eventManager;
/**
* Handles the RerenderPart event by rerendering a portion of the screen.
*
* @param event The RerenderPart event
*/
@Override @Override
public void handle(RerenderPart event) { public void handle(RerenderPart event) {
int forStartX = event.getForStartX(); int forStartX = event.getForStartX();

View File

@@ -21,6 +21,11 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* Handler for the RoomChangeEvent.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
@EventHandler(RoomChangeEvent.class) @EventHandler(RoomChangeEvent.class)
public class RoomChangeEventHandler extends AbstractEventHandler<RoomChangeEvent> { public class RoomChangeEventHandler extends AbstractEventHandler<RoomChangeEvent> {
@@ -32,6 +37,11 @@ public class RoomChangeEventHandler extends AbstractEventHandler<RoomChangeEvent
@InjectDependency @InjectDependency
private RoomTaskScheduler roomTaskScheduler; private RoomTaskScheduler roomTaskScheduler;
/**
* Handles the RoomChangeEvent by changing the current room and moving the player.
*
* @param event The RoomChangeEvent
*/
@Override @Override
public void handle(RoomChangeEvent event) { public void handle(RoomChangeEvent event) {
RoomCords playerCords = gameState.getPlayer().getPlayerCords(); RoomCords playerCords = gameState.getPlayer().getPlayerCords();

View File

@@ -8,11 +8,21 @@ import cz.jzitnik.client.utils.events.AbstractEventHandler;
import java.io.IOException; import java.io.IOException;
/**
* Handler for the SendSocketMessageEvent.
*
* @author Jakub Žitník (jzitnik)
*/
@EventHandler(SendSocketMessageEvent.class) @EventHandler(SendSocketMessageEvent.class)
public class SendSocketMessageEventHandler extends AbstractEventHandler<SendSocketMessageEvent> { public class SendSocketMessageEventHandler extends AbstractEventHandler<SendSocketMessageEvent> {
@InjectDependency @InjectDependency
private Client client; private Client client;
/**
* Handles the SendSocketMessageEvent by sending the message through the client.
*
* @param event The SendSocketMessageEvent
*/
@Override @Override
public void handle(SendSocketMessageEvent event) { public void handle(SendSocketMessageEvent event) {
try { try {

View File

@@ -15,6 +15,11 @@ import cz.jzitnik.client.utils.events.AbstractEventHandler;
import cz.jzitnik.client.utils.events.EventManager; import cz.jzitnik.client.utils.events.EventManager;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
/**
* Handler for the TerminalResizeEvent.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
@EventHandler(TerminalResizeEvent.class) @EventHandler(TerminalResizeEvent.class)
public class TerminalResizeEventHandler extends AbstractEventHandler<TerminalResizeEvent> { public class TerminalResizeEventHandler extends AbstractEventHandler<TerminalResizeEvent> {
@@ -29,6 +34,11 @@ public class TerminalResizeEventHandler extends AbstractEventHandler<TerminalRes
private boolean screenRerendering = false; private boolean screenRerendering = false;
/**
* Handles the TerminalResizeEvent by reinitializing buffers and triggering a full redraw.
*
* @param event The TerminalResizeEvent
*/
@Override @Override
public void handle(TerminalResizeEvent event) { public void handle(TerminalResizeEvent event) {
TerminalSize size = event.getNewSize(); TerminalSize size = event.getNewSize();

View File

@@ -14,11 +14,21 @@ import cz.jzitnik.client.utils.events.AbstractEventHandler;
import java.io.IOException; import java.io.IOException;
import java.util.EnumSet; import java.util.EnumSet;
/**
* Handler for the TerminalTooSmallEvent.
*
* @author Jakub Žitník (jzitnik)
*/
@EventHandler(TerminalTooSmallEvent.class) @EventHandler(TerminalTooSmallEvent.class)
public class TerminalTooSmallEventHandler extends AbstractEventHandler<TerminalTooSmallEvent> { public class TerminalTooSmallEventHandler extends AbstractEventHandler<TerminalTooSmallEvent> {
@InjectState @InjectState
private TerminalState terminalState; private TerminalState terminalState;
/**
* Handles the TerminalTooSmallEvent by rendering a warning message directly to the terminal.
*
* @param event The TerminalTooSmallEvent
*/
@Override @Override
public void handle(TerminalTooSmallEvent event) { public void handle(TerminalTooSmallEvent event) {
// Directly render the message for the user // Directly render the message for the user

View File

@@ -2,6 +2,12 @@ package cz.jzitnik.client.game;
import com.googlecode.lanterna.TextColor; import com.googlecode.lanterna.TextColor;
/**
* Global game constants.
*
* @author Jakub Žitník (jzitnik)
*/
public class Constants { public class Constants {
/** The default background color for the game. */
public static final TextColor BACKGROUND_COLOR = new TextColor.RGB(4, 4, 16); public static final TextColor BACKGROUND_COLOR = new TextColor.RGB(4, 4, 16);
} }

View File

@@ -4,7 +4,24 @@ import cz.jzitnik.common.models.coordinates.RoomCords;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
/**
* Interface representing a player-like entity in the game.
*
* @author Jakub Žitník (jzitnik)
*/
public interface GamePlayer { public interface GamePlayer {
/**
* Gets the player's coordinates.
*
* @return RoomCords instance
*/
RoomCords getPlayerCords(); RoomCords getPlayerCords();
/**
* Gets the player's current texture.
*
* @param resourceManager The resource manager to load texture
* @return BufferedImage texture
*/
BufferedImage getTexture(ResourceManager resourceManager); BufferedImage getTexture(ResourceManager resourceManager);
} }

View File

@@ -14,6 +14,11 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
/**
* Represents a room in the game.
*
* @author Jakub Žitník (jzitnik)
*/
@JsonIdentityInfo( @JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class, generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id" property = "id"
@@ -45,6 +50,15 @@ public class GameRoom {
private GameRoom up; private GameRoom up;
private GameRoom down; private GameRoom down;
/**
* Constructs a GameRoom.
*
* @param id Room ID
* @param objects List of objects in the room
* @param colliders List of colliders
* @param mobs List of mobs
* @param texture Texture resource
*/
@JsonCreator @JsonCreator
public GameRoom( public GameRoom(
@JsonProperty("id") String id, @JsonProperty("id") String id,
@@ -72,21 +86,41 @@ public class GameRoom {
this.overrideBuffer = overrideBuffer; this.overrideBuffer = overrideBuffer;
} }
/**
* Sets the room to the west (left).
*
* @param west West room
*/
@JsonSetter("west") @JsonSetter("west")
public void setWest(GameRoom west) { public void setWest(GameRoom west) {
if (west != null) this.left = west; if (west != null) this.left = west;
} }
/**
* Sets the room to the east (right).
*
* @param east East room
*/
@JsonSetter("east") @JsonSetter("east")
public void setEast(GameRoom east) { public void setEast(GameRoom east) {
if (east != null) this.right = east; if (east != null) this.right = east;
} }
/**
* Sets the room to the north (up).
*
* @param north North room
*/
@JsonSetter("north") @JsonSetter("north")
public void setNorth(GameRoom north) { public void setNorth(GameRoom north) {
if (north != null) this.up = north; if (north != null) this.up = north;
} }
/**
* Sets the room to the south (down).
*
* @param south South room
*/
@JsonSetter("south") @JsonSetter("south")
public void setSouth(GameRoom south) { public void setSouth(GameRoom south) {
if (south != null) this.down = south; if (south != null) this.down = south;

View File

@@ -11,6 +11,11 @@ import lombok.Setter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/**
* Holds the current state of the game.
*
* @author Jakub Žitník (jzitnik)
*/
@RequiredArgsConstructor @RequiredArgsConstructor
@State @State
public class GameState { public class GameState {
@@ -30,10 +35,20 @@ public class GameState {
private final List<OtherPlayer> otherPlayers = new ArrayList<>(); private final List<OtherPlayer> otherPlayers = new ArrayList<>();
/**
* Gets a list of visible other players.
*
* @return List of visible other players
*/
public List<OtherPlayer> getOtherPlayers() { public List<OtherPlayer> getOtherPlayers() {
return otherPlayers.stream().filter(OtherPlayer::isVisible).toList(); return otherPlayers.stream().filter(OtherPlayer::isVisible).toList();
} }
/**
* Gets a list of all other players.
*
* @return List of all other players
*/
public List<OtherPlayer> getAllOtherPlayers() { public List<OtherPlayer> getAllOtherPlayers() {
return otherPlayers; return otherPlayers;
} }
@@ -45,6 +60,11 @@ public class GameState {
@Getter @Getter
private Screen screen; private Screen screen;
/**
* Sets the current screen and injects its dependencies.
*
* @param screen The screen to set
*/
public void setScreen(Screen screen) { public void setScreen(Screen screen) {
if (screen != null) { if (screen != null) {
dependencyManager.inject(screen); dependencyManager.inject(screen);

View File

@@ -9,6 +9,11 @@ import lombok.Setter;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
/**
* Represents another player connected to the same game.
*
* @author Jakub Žitník (jzitnik)
*/
@Getter @Getter
public class OtherPlayer implements GamePlayer { public class OtherPlayer implements GamePlayer {
private final int id; private final int id;
@@ -19,11 +24,20 @@ public class OtherPlayer implements GamePlayer {
@Setter @Setter
private boolean visible; private boolean visible;
/**
* Constructs an OtherPlayer.
*
* @param playerCreation Player creation data
*/
public OtherPlayer(PlayerCreation playerCreation) { public OtherPlayer(PlayerCreation playerCreation) {
this.id = playerCreation.getId(); this.id = playerCreation.getId();
this.playerCords = playerCreation.getPlayerCords(); this.playerCords = playerCreation.getPlayerCords();
} }
/**
* {@inheritDoc}
*/
@Override
public BufferedImage getTexture(ResourceManager resourceManager) { public BufferedImage getTexture(ResourceManager resourceManager) {
BufferedImage resource = resourceManager.getResource(switch (playerRotation) { BufferedImage resource = resourceManager.getResource(switch (playerRotation) {
case FRONT -> ResourceManager.Resource.PLAYER_FRONT; case FRONT -> ResourceManager.Resource.PLAYER_FRONT;

View File

@@ -22,11 +22,18 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* Represents the local player.
*
* @author Jakub Žitník (jzitnik)
*/
@Getter @Getter
@Slf4j @Slf4j
public class Player implements GamePlayer { public class Player implements GamePlayer {
private final int id; private final int id;
/** Maximum stamina value. */
public static final int MAX_STAMINA = 20; public static final int MAX_STAMINA = 20;
/** Maximum health value. */
public static final int MAX_HEALTH = 30; public static final int MAX_HEALTH = 30;
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
@@ -43,24 +50,47 @@ public class Player implements GamePlayer {
private boolean hitAnimationOn = false; private boolean hitAnimationOn = false;
private ScheduledFuture<?> currentTimeoutHitAnimation = null; private ScheduledFuture<?> currentTimeoutHitAnimation = null;
/**
* Constructs a Player.
*
* @param playerCreation Player creation data
*/
public Player(PlayerCreation playerCreation) { public Player(PlayerCreation playerCreation) {
this.playerCords = playerCreation.getPlayerCords(); this.playerCords = playerCreation.getPlayerCords();
this.collider = playerCreation.getCollider(); this.collider = playerCreation.getCollider();
this.id = playerCreation.getId(); this.id = playerCreation.getId();
} }
/**
* Increases player stamina.
*/
public void increaseStamina() { public void increaseStamina() {
stamina++; stamina++;
} }
/**
* Decreases player stamina.
*/
public void decreaseStamina() { public void decreaseStamina() {
stamina--; stamina--;
} }
/**
* Restores player health.
*
* @param amount Amount to restore
*/
public void addHealth(int amount) { public void addHealth(int amount) {
health = Math.min(MAX_HEALTH, health + amount); health = Math.min(MAX_HEALTH, health + amount);
} }
/**
* Deals damage to the player.
*
* @param amount Damage amount
* @param dependencyManager Dependency manager
* @return true if player died
*/
public boolean dealDamage(int amount, DependencyManager dependencyManager) { public boolean dealDamage(int amount, DependencyManager dependencyManager) {
if (health - amount <= 0) { if (health - amount <= 0) {
health = 0; health = 0;
@@ -88,6 +118,11 @@ public class Player implements GamePlayer {
return false; return false;
} }
/**
* Triggers a rerender of the player.
*
* @param dependencyManager Dependency manager
*/
private void rerender(DependencyManager dependencyManager) { private void rerender(DependencyManager dependencyManager) {
ResourceManager resourceManager = dependencyManager.getDependencyOrThrow(ResourceManager.class); ResourceManager resourceManager = dependencyManager.getDependencyOrThrow(ResourceManager.class);
EventManager eventManager = dependencyManager.getDependencyOrThrow(EventManager.class); EventManager eventManager = dependencyManager.getDependencyOrThrow(EventManager.class);
@@ -104,6 +139,10 @@ public class Player implements GamePlayer {
}); });
} }
/**
* {@inheritDoc}
*/
@Override
public BufferedImage getTexture(ResourceManager resourceManager) { public BufferedImage getTexture(ResourceManager resourceManager) {
BufferedImage resource = resourceManager.getResource(switch (playerRotation) { BufferedImage resource = resourceManager.getResource(switch (playerRotation) {
case FRONT -> ResourceManager.Resource.PLAYER_FRONT; case FRONT -> ResourceManager.Resource.PLAYER_FRONT;
@@ -119,6 +158,11 @@ public class Player implements GamePlayer {
return resource; return resource;
} }
/**
* Gets the damage dealt by the player with their current weapon.
*
* @return Damage value
*/
public int getDamageDeal() { public int getDamageDeal() {
int damage = 1; int damage = 1;
@@ -131,6 +175,12 @@ public class Player implements GamePlayer {
return damage; return damage;
} }
/**
* Adds an item to the player's inventory.
*
* @param item Item to add
* @return true if item was added, false if inventory is full
*/
public boolean addItem(GameItem item) { public boolean addItem(GameItem item) {
boolean added = false; boolean added = false;
for (int i = 0; i < inventory.length; i++) { for (int i = 0; i < inventory.length; i++) {
@@ -144,6 +194,11 @@ public class Player implements GamePlayer {
return added; return added;
} }
/**
* Triggers a weapon swing animation.
*
* @param delayMs Duration of the swing
*/
public void swing(int delayMs) { public void swing(int delayMs) {
if (swinging) { if (swinging) {
return; return;

View File

@@ -3,7 +3,18 @@ package cz.jzitnik.client.game;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Represents a requirement (e.g. an item) needed to enter a room.
*
* @param itemType The type of item required
* @author Jakub Žitník (jzitnik)
*/
public record Requirement(String itemType) { public record Requirement(String itemType) {
/**
* Constructs a Requirement.
*
* @param itemType The type of item required
*/
@JsonCreator @JsonCreator
public Requirement( public Requirement(
@JsonProperty("item") String itemType @JsonProperty("item") String itemType

View File

@@ -11,11 +11,19 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.HashMap; import java.util.HashMap;
/**
* Manages loading and caching of game resources (textures, audio).
*
* @author Jakub Žitník (jzitnik)
*/
@Dependency @Dependency
public class ResourceManager { public class ResourceManager {
@InjectDependency @InjectDependency
private ClassLoader classLoader; private ClassLoader classLoader;
/**
* Enum representing available game resources.
*/
@AllArgsConstructor @AllArgsConstructor
@Getter @Getter
public enum Resource { public enum Resource {
@@ -69,6 +77,12 @@ public class ResourceManager {
private final HashMap<Resource, BufferedImage> resourceCache = new HashMap<>(); private final HashMap<Resource, BufferedImage> resourceCache = new HashMap<>();
/**
* Retrieves a texture resource by its enum key.
*
* @param resource The resource key
* @return The loaded BufferedImage
*/
public BufferedImage getResource(Resource resource) { public BufferedImage getResource(Resource resource) {
if (resourceCache.containsKey(resource)) { if (resourceCache.containsKey(resource)) {
return resourceCache.get(resource); return resourceCache.get(resource);
@@ -88,6 +102,12 @@ public class ResourceManager {
} }
} }
/**
* Retrieves a texture resource by its path.
*
* @param path The resource path
* @return The loaded BufferedImage
*/
public BufferedImage getResource(String path) { public BufferedImage getResource(String path) {
InputStream is = classLoader.getResourceAsStream(path); InputStream is = classLoader.getResourceAsStream(path);
if (is == null) { if (is == null) {
@@ -101,6 +121,12 @@ public class ResourceManager {
} }
} }
/**
* Gets a resource input stream by path.
*
* @param path The resource path
* @return InputStream for the resource
*/
public InputStream getResourceAsStream(String path) { public InputStream getResourceAsStream(String path) {
return classLoader.getResourceAsStream(path); return classLoader.getResourceAsStream(path);
} }

View File

@@ -5,6 +5,11 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import cz.jzitnik.client.utils.events.Event; import cz.jzitnik.client.utils.events.Event;
import lombok.Getter; import lombok.Getter;
/**
* Represents a dialog sequence in the game.
*
* @author Jakub Žitník (jzitnik)
*/
@Getter @Getter
public class Dialog implements Event { public class Dialog implements Event {
/** /**
@@ -14,6 +19,12 @@ public class Dialog implements Event {
private final String text; private final String text;
private final OnEnd onEnd; private final OnEnd onEnd;
/**
* Constructs a Dialog.
*
* @param text The dialog text
* @param onEnd Action to perform when dialog ends
*/
@JsonCreator @JsonCreator
public Dialog( public Dialog(
@JsonProperty("text") String text, @JsonProperty("text") String text,

View File

@@ -20,6 +20,11 @@ import lombok.RequiredArgsConstructor;
import java.util.Arrays; import java.util.Arrays;
import java.util.Optional; import java.util.Optional;
/**
* Interface for actions to perform at the end of a dialog.
*
* @author Jakub Žitník (jzitnik)
*/
@JsonTypeInfo( @JsonTypeInfo(
use = JsonTypeInfo.Id.NAME, use = JsonTypeInfo.Id.NAME,
property = "type" property = "type"
@@ -31,10 +36,18 @@ import java.util.Optional;
@JsonSubTypes.Type(value = OnEnd.GiveItem.class, name = "give_item") @JsonSubTypes.Type(value = OnEnd.GiveItem.class, name = "give_item")
}) })
public interface OnEnd { public interface OnEnd {
/** Terminal dialog action. */
record End() implements OnEnd { record End() implements OnEnd {
} }
/** Action that gives an item to the player. */
class GiveItem extends RunCode { class GiveItem extends RunCode {
/**
* Constructs a GiveItem action.
*
* @param item Item to give
* @param onEnd Next action
*/
@JsonCreator @JsonCreator
public GiveItem( public GiveItem(
@JsonProperty("item") GameItem item, @JsonProperty("item") GameItem item,
@@ -43,6 +56,7 @@ public interface OnEnd {
super(new Run(item), onEnd); super(new Run(item), onEnd);
} }
/** Internal runnable to give the item. */
@RequiredArgsConstructor @RequiredArgsConstructor
private static class Run implements Runnable { private static class Run implements Runnable {
private final GameItem item; private final GameItem item;
@@ -56,6 +70,9 @@ public interface OnEnd {
@InjectDependency @InjectDependency
private ResourceManager resourceManager; private ResourceManager resourceManager;
/**
* {@inheritDoc}
*/
@Override @Override
public void run() { public void run() {
Player player = gameState.getPlayer(); Player player = gameState.getPlayer();
@@ -72,6 +89,7 @@ public interface OnEnd {
} }
} }
/** Action that runs arbitrary code. */
@Getter @Getter
@RequiredArgsConstructor @RequiredArgsConstructor
class RunCode implements OnEnd { class RunCode implements OnEnd {
@@ -79,24 +97,44 @@ public interface OnEnd {
private final OnEnd onEnd; private final OnEnd onEnd;
} }
/** Action that continues to another dialog. */
record Continue(Dialog nextDialog) implements OnEnd { record Continue(Dialog nextDialog) implements OnEnd {
/**
* Constructs a Continue action.
*
* @param nextDialog The next dialog
*/
@JsonCreator @JsonCreator
public Continue(@JsonProperty("nextDialog") Dialog nextDialog) { public Continue(@JsonProperty("nextDialog") Dialog nextDialog) {
this.nextDialog = nextDialog; this.nextDialog = nextDialog;
} }
} }
/** Action that asks the player a question with multiple answers. */
record AskQuestion(Answer[] answers) implements OnEnd { record AskQuestion(Answer[] answers) implements OnEnd {
/**
* Constructs an AskQuestion action.
*
* @param answers Possible answers
*/
@JsonCreator @JsonCreator
public AskQuestion(@JsonProperty("answers") Answer[] answers) { public AskQuestion(@JsonProperty("answers") Answer[] answers) {
this.answers = answers; this.answers = answers;
} }
/** Represents a single answer to a question. */
public record Answer( public record Answer(
String answer, String answer,
Dialog dialog, Dialog dialog,
Optional<Requirement> requirement Optional<Requirement> requirement
) { ) {
/**
* Constructs an Answer.
*
* @param answer Answer text
* @param dialog Resulting dialog
* @param requirement Requirement to see this answer
*/
@JsonCreator @JsonCreator
public Answer( public Answer(
@JsonProperty("answer") String answer, @JsonProperty("answer") String answer,
@@ -106,6 +144,9 @@ public interface OnEnd {
this(answer, dialog, Optional.ofNullable(requirement)); this(answer, dialog, Optional.ofNullable(requirement));
} }
/**
* Checks if the answer is valid for the current state.
*/
private boolean isValid(GameState gameState) { private boolean isValid(GameState gameState) {
if (requirement.isPresent()) { if (requirement.isPresent()) {
Requirement requirement = requirement().get(); Requirement requirement = requirement().get();
@@ -126,6 +167,12 @@ public interface OnEnd {
} }
} }
/**
* Gets valid answers for the current game state.
*
* @param gameState Current game state
* @return Array of valid answers
*/
public Answer[] answers(GameState gameState) { public Answer[] answers(GameState gameState) {
return Arrays.stream(answers) return Arrays.stream(answers)
.filter(answer -> answer.isValid(gameState)) .filter(answer -> answer.isValid(gameState))

View File

@@ -1,10 +1,23 @@
package cz.jzitnik.client.game.exceptions; package cz.jzitnik.client.game.exceptions;
/**
* Exception thrown when coordinates are invalid.
*
* @author Jakub Žitník (jzitnik)
*/
public class InvalidCoordinatesException extends RuntimeException { public class InvalidCoordinatesException extends RuntimeException {
/**
* Constructs an InvalidCoordinatesException with message.
*
* @param message The error message
*/
public InvalidCoordinatesException(String message) { public InvalidCoordinatesException(String message) {
super(message); super(message);
} }
/**
* Constructs an InvalidCoordinatesException.
*/
public InvalidCoordinatesException() { public InvalidCoordinatesException() {
super(); super();
} }

View File

@@ -8,6 +8,11 @@ import lombok.Getter;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
/**
* Represents an item in the game.
*
* @author Jakub Žitník (jzitnik)
*/
@Getter @Getter
public class GameItem implements Renderable { public class GameItem implements Renderable {
private final ItemType<?> type; private final ItemType<?> type;
@@ -16,6 +21,15 @@ public class GameItem implements Renderable {
private final String name; private final String name;
private final int id; private final int id;
/**
* Constructs a GameItem.
*
* @param id Item ID
* @param name Item name
* @param type Item type
* @param resource Texture resource
* @param resourceManager Resource manager
*/
@JsonCreator @JsonCreator
public GameItem( public GameItem(
@JsonProperty("id") int id, @JsonProperty("id") int id,

View File

@@ -1,6 +1,14 @@
package cz.jzitnik.client.game.items.types; package cz.jzitnik.client.game.items.types;
/**
* Represents a beast skin item type.
*
* @author Jakub Žitník (jzitnik)
*/
public class BeastSkin implements ItemType<BeastSkin> { public class BeastSkin implements ItemType<BeastSkin> {
/**
* {@inheritDoc}
*/
@Override @Override
public Class<BeastSkin> getItemType() { public Class<BeastSkin> getItemType() {
return BeastSkin.class; return BeastSkin.class;

View File

@@ -3,10 +3,26 @@ package cz.jzitnik.client.game.items.types;
import cz.jzitnik.client.utils.DependencyManager; import cz.jzitnik.client.utils.DependencyManager;
import cz.jzitnik.client.utils.StateManager; import cz.jzitnik.client.utils.StateManager;
/**
* Interface for items that can be interacted with.
*
* @author Jakub Žitník (jzitnik)
*/
public interface InteractableItem { public interface InteractableItem {
/**
* Performs interaction with the item.
*
* @param dependencyManager The dependency manager
* @param stateManager The state manager
* @return Result of the interaction
*/
InteractableItemResponse interact(DependencyManager dependencyManager, StateManager stateManager); InteractableItemResponse interact(DependencyManager dependencyManager, StateManager stateManager);
/**
* Response types for item interaction.
*/
enum InteractableItemResponse { enum InteractableItemResponse {
/** Clear the item from inventory. */
CLEAR_ITEM, CLEAR_ITEM,
} }
} }

View File

@@ -5,6 +5,12 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
import cz.jzitnik.client.game.items.types.food.Food; import cz.jzitnik.client.game.items.types.food.Food;
import cz.jzitnik.client.game.items.types.weapons.Sword; import cz.jzitnik.client.game.items.types.weapons.Sword;
/**
* Interface representing a type of game item.
*
* @param <T> The class type of the item
* @author Jakub Žitník (jzitnik)
*/
@JsonTypeInfo( @JsonTypeInfo(
use = JsonTypeInfo.Id.NAME, use = JsonTypeInfo.Id.NAME,
property = "name" property = "name"
@@ -17,5 +23,10 @@ import cz.jzitnik.client.game.items.types.weapons.Sword;
@JsonSubTypes.Type(value = BeastSkin.class, name = "beast_skin"), @JsonSubTypes.Type(value = BeastSkin.class, name = "beast_skin"),
}) })
public interface ItemType<T> { public interface ItemType<T> {
/**
* Gets the class representing this item type.
*
* @return The item type class
*/
Class<T> getItemType(); Class<T> getItemType();
} }

View File

@@ -1,6 +1,14 @@
package cz.jzitnik.client.game.items.types; package cz.jzitnik.client.game.items.types;
/**
* Represents a junk item type.
*
* @author Jakub Žitník (jzitnik)
*/
public class Junk implements ItemType<Junk> { public class Junk implements ItemType<Junk> {
/**
* {@inheritDoc}
*/
@Override @Override
public Class<Junk> getItemType() { public Class<Junk> getItemType() {
return Junk.class; return Junk.class;

View File

@@ -1,6 +1,14 @@
package cz.jzitnik.client.game.items.types; package cz.jzitnik.client.game.items.types;
/**
* Represents a key item type.
*
* @author Jakub Žitník (jzitnik)
*/
public class Key implements ItemType<Key> { public class Key implements ItemType<Key> {
/**
* {@inheritDoc}
*/
@Override @Override
public Class<Key> getItemType() { public Class<Key> getItemType() {
return Key.class; return Key.class;

View File

@@ -10,9 +10,19 @@ import cz.jzitnik.client.utils.DependencyManager;
import cz.jzitnik.client.utils.StateManager; import cz.jzitnik.client.utils.StateManager;
import cz.jzitnik.client.utils.events.EventManager; import cz.jzitnik.client.utils.events.EventManager;
/**
* Represents a food item that can be consumed to restore health.
*
* @author Jakub Žitník (jzitnik)
*/
public class Food implements InteractableItem, ItemType<Food> { public class Food implements InteractableItem, ItemType<Food> {
private final int addHealth; private final int addHealth;
/**
* Constructs a Food item with specified health restoration value.
*
* @param addHealth Health to add when consumed
*/
@JsonCreator @JsonCreator
public Food( public Food(
@JsonProperty("addHealth") int addHealth @JsonProperty("addHealth") int addHealth
@@ -20,6 +30,13 @@ public class Food implements InteractableItem, ItemType<Food> {
this.addHealth = addHealth; this.addHealth = addHealth;
} }
/**
* Interacts with the food item (consumes it).
*
* @param dependencyManager The dependency manager
* @param stateManager The state manager
* @return Response indicating the item should be cleared
*/
@Override @Override
public InteractableItemResponse interact(DependencyManager dependencyManager, StateManager stateManager) { public InteractableItemResponse interact(DependencyManager dependencyManager, StateManager stateManager) {
GameState gameState = stateManager.getOrThrow(GameState.class); GameState gameState = stateManager.getOrThrow(GameState.class);
@@ -31,6 +48,9 @@ public class Food implements InteractableItem, ItemType<Food> {
return InteractableItemResponse.CLEAR_ITEM; return InteractableItemResponse.CLEAR_ITEM;
} }
/**
* {@inheritDoc}
*/
@Override @Override
public Class<Food> getItemType() { public Class<Food> getItemType() {
return Food.class; return Food.class;

View File

@@ -1,5 +1,15 @@
package cz.jzitnik.client.game.items.types.interfaces; package cz.jzitnik.client.game.items.types.interfaces;
/**
* Interface for game items that can deal damage.
*
* @author Jakub Žitník (jzitnik)
*/
public interface WeaponInterface { public interface WeaponInterface {
/**
* Gets the damage dealt by the weapon.
*
* @return Damage value
*/
int getDamageDeal(); int getDamageDeal();
} }

View File

@@ -3,7 +3,17 @@ package cz.jzitnik.client.game.items.types.weapons;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Represents a sword weapon.
*
* @author Jakub Žitník (jzitnik)
*/
public class Sword extends Weapon { public class Sword extends Weapon {
/**
* Constructs a Sword with specified damage.
*
* @param dealDamage Damage dealt by the sword
*/
@JsonCreator @JsonCreator
public Sword( public Sword(
@JsonProperty("dealDamage") int dealDamage @JsonProperty("dealDamage") int dealDamage

View File

@@ -4,15 +4,28 @@ import cz.jzitnik.client.game.items.types.ItemType;
import cz.jzitnik.client.game.items.types.interfaces.WeaponInterface; import cz.jzitnik.client.game.items.types.interfaces.WeaponInterface;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
/**
* Base class for all weapon items.
*
* @author Jakub Žitník (jzitnik)
*/
@AllArgsConstructor @AllArgsConstructor
public abstract class Weapon implements ItemType<Weapon>, WeaponInterface { public abstract class Weapon implements ItemType<Weapon>, WeaponInterface {
private final int dealDamage; private final int dealDamage;
/**
* {@inheritDoc}
*/
@Override @Override
public final Class<Weapon> getItemType() { public final Class<Weapon> getItemType() {
return Weapon.class; return Weapon.class;
} }
/**
* Gets the damage dealt by this weapon.
*
* @return Damage value
*/
@Override @Override
public int getDamageDeal() { public int getDamageDeal() {
return dealDamage; return dealDamage;

View File

@@ -14,10 +14,25 @@ import cz.jzitnik.client.states.DialogState;
import cz.jzitnik.client.utils.events.EventManager; import cz.jzitnik.client.utils.events.EventManager;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
/**
* A mob that triggers a dialog when interacted with.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
public class DialogMob extends Mob { public class DialogMob extends Mob {
protected Dialog dialog; protected Dialog dialog;
/**
* Constructs a DialogMob.
*
* @param texture Texture resource
* @param tasks Tasks
* @param cords Coordinates
* @param collider Collider
* @param dialog Dialog to trigger
* @param resourceManager Resource manager
*/
@JsonCreator @JsonCreator
public DialogMob( public DialogMob(
@JsonProperty("texture") ResourceManager.Resource texture, @JsonProperty("texture") ResourceManager.Resource texture,
@@ -37,6 +52,9 @@ public class DialogMob extends Mob {
@InjectState @InjectState
private DialogState dialogState; private DialogState dialogState;
/**
* {@inheritDoc}
*/
@Override @Override
public void interact() { public void interact() {
log.debug("Interacting with dialog mob!"); log.debug("Interacting with dialog mob!");

View File

@@ -20,8 +20,16 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* Abstract base class for mobs that can be hit and killed.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
public abstract class HittableMob extends Mob { public abstract class HittableMob extends Mob {
/**
* Called when the mob is killed.
*/
public abstract void onKilled(); public abstract void onKilled();
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
@@ -31,6 +39,9 @@ public abstract class HittableMob extends Mob {
private boolean hitAnimationOn = false; private boolean hitAnimationOn = false;
/**
* {@inheritDoc}
*/
@Override @Override
public BufferedImage getTexture() { public BufferedImage getTexture() {
if (hitAnimationOn) { if (hitAnimationOn) {
@@ -40,6 +51,12 @@ public abstract class HittableMob extends Mob {
return texture; return texture;
} }
/**
* Applies a red factor to an image, used for hit animation.
*
* @param src The source image
* @return The red-tinted image
*/
public static BufferedImage applyRedFactor(BufferedImage src) { public static BufferedImage applyRedFactor(BufferedImage src) {
final float redFactor = 2f; final float redFactor = 2f;
int width = src.getWidth(); int width = src.getWidth();
@@ -68,11 +85,23 @@ public abstract class HittableMob extends Mob {
@InjectDependency @InjectDependency
private RoomTaskScheduler roomTaskScheduler; private RoomTaskScheduler roomTaskScheduler;
/**
* Constructs a HittableMob.
*
* @param texture Texture
* @param tasks Tasks
* @param cords Coordinates
* @param collider Collider
* @param health Initial health
*/
public HittableMob(BufferedImage texture, MobRoomTask[] tasks, RoomCords cords, RoomPart collider, int health) { public HittableMob(BufferedImage texture, MobRoomTask[] tasks, RoomCords cords, RoomPart collider, int health) {
super(texture, tasks, cords, collider); super(texture, tasks, cords, collider);
this.health = health; this.health = health;
} }
/**
* {@inheritDoc}
*/
@Override @Override
public final void interact() { public final void interact() {
health -= gameState.getPlayer().getDamageDeal(); health -= gameState.getPlayer().getDamageDeal();
@@ -106,6 +135,9 @@ public abstract class HittableMob extends Mob {
}, 250, TimeUnit.MILLISECONDS); }, 250, TimeUnit.MILLISECONDS);
} }
/**
* Triggers a rerender of the mob's position.
*/
private void rerender() { private void rerender() {
int forStartX = cords.getX(); int forStartX = cords.getX();
int forStartY = cords.getY(); int forStartY = cords.getY();

View File

@@ -21,6 +21,11 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
/**
* A hittable mob that drops items when killed.
*
* @author Jakub Žitník (jzitnik)
*/
public class HittableMobDrops extends HittableMob { public class HittableMobDrops extends HittableMob {
private static final int DROP_ITEM_ON_GROUND_RADIUS = 30; private static final int DROP_ITEM_ON_GROUND_RADIUS = 30;
private final GameItem[] itemsDrops; private final GameItem[] itemsDrops;
@@ -29,6 +34,17 @@ public class HittableMobDrops extends HittableMob {
@InjectDependency @InjectDependency
private EventManager eventManager; private EventManager eventManager;
/**
* Constructs a HittableMobDrops instance.
*
* @param texture Texture resource
* @param tasks Tasks
* @param cords Coordinates
* @param collider Collider
* @param health Initial health
* @param itemsDrops Items to drop on death
* @param resourceManager Resource manager
*/
@JsonCreator @JsonCreator
public HittableMobDrops( public HittableMobDrops(
@JsonProperty("texture") ResourceManager.Resource texture, @JsonProperty("texture") ResourceManager.Resource texture,
@@ -49,6 +65,9 @@ public class HittableMobDrops extends HittableMob {
public void afterKill() { public void afterKill() {
} }
/**
* {@inheritDoc}
*/
@Override @Override
public final void onKilled() { public final void onKilled() {
boolean addedIntoInventory = false; boolean addedIntoInventory = false;
@@ -77,6 +96,15 @@ public class HittableMobDrops extends HittableMob {
eventManager.emitEvent(events, this::afterKill); eventManager.emitEvent(events, this::afterKill);
} }
/**
* Drops an item at a random position near specified coordinates.
*
* @param x Center X
* @param y Center Y
* @param currentRoom The current room
* @param item The item to drop
* @return A DroppedItemRerender event
*/
public static Event dropItem(int x, int y, GameRoom currentRoom, GameItem item) { public static Event dropItem(int x, int y, GameRoom currentRoom, GameItem item) {
double angle = ThreadLocalRandom.current().nextDouble(0, Math.PI * 2); double angle = ThreadLocalRandom.current().nextDouble(0, Math.PI * 2);
double radius = ThreadLocalRandom.current().nextDouble(0, DROP_ITEM_ON_GROUND_RADIUS); double radius = ThreadLocalRandom.current().nextDouble(0, DROP_ITEM_ON_GROUND_RADIUS);

View File

@@ -8,7 +8,22 @@ import cz.jzitnik.client.game.ResourceManager;
import cz.jzitnik.client.game.mobs.tasks.MobRoomTask; import cz.jzitnik.client.game.mobs.tasks.MobRoomTask;
import cz.jzitnik.common.models.coordinates.RoomCords; import cz.jzitnik.common.models.coordinates.RoomCords;
/**
* A hittable mob that does not drop any items when killed.
*
* @author Jakub Žitník (jzitnik)
*/
public class HittableMobNoDrops extends HittableMob { public class HittableMobNoDrops extends HittableMob {
/**
* Constructs a HittableMobNoDrops instance.
*
* @param texture Texture resource
* @param tasks Tasks
* @param cords Coordinates
* @param collider Collider
* @param health Initial health
* @param resourceManager Resource manager
*/
@JsonCreator @JsonCreator
public HittableMobNoDrops( public HittableMobNoDrops(
@JsonProperty("texture") ResourceManager.Resource texture, @JsonProperty("texture") ResourceManager.Resource texture,
@@ -21,6 +36,9 @@ public class HittableMobNoDrops extends HittableMob {
super(resourceManager.getResource(texture), tasks, cords, collider, health); super(resourceManager.getResource(texture), tasks, cords, collider, health);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void onKilled() { public void onKilled() {

View File

@@ -15,6 +15,11 @@ import lombok.Setter;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
/**
* Abstract base class for all mobs in the game.
*
* @author Jakub Žitník (jzitnik)
*/
@JsonTypeInfo( @JsonTypeInfo(
use = JsonTypeInfo.Id.NAME, use = JsonTypeInfo.Id.NAME,
property = "type" property = "type"
@@ -39,6 +44,11 @@ public abstract class Mob implements Renderable, Selectable {
@InjectDependency @InjectDependency
private RoomTaskScheduler roomTaskScheduler; private RoomTaskScheduler roomTaskScheduler;
/**
* Updates the tasks associated with this mob and registers them.
*
* @param tasks The new tasks
*/
protected void updateTasks(MobRoomTask[] tasks) { protected void updateTasks(MobRoomTask[] tasks) {
var oldTasks = this.tasks; var oldTasks = this.tasks;
this.tasks = tasks; this.tasks = tasks;
@@ -46,6 +56,14 @@ public abstract class Mob implements Renderable, Selectable {
roomTaskScheduler.registerNewMob(this, oldTasks); roomTaskScheduler.registerNewMob(this, oldTasks);
} }
/**
* Constructs a Mob.
*
* @param texture The mob's texture
* @param tasks Tasks associated with the mob
* @param cords Initial coordinates
* @param collider The mob's collider
*/
public Mob(BufferedImage texture, MobRoomTask[] tasks, RoomCords cords, RoomPart collider) { public Mob(BufferedImage texture, MobRoomTask[] tasks, RoomCords cords, RoomPart collider) {
this.texture = texture; this.texture = texture;
this.tasks = tasks == null ? new MobRoomTask[] {} : tasks; this.tasks = tasks == null ? new MobRoomTask[] {} : tasks;

View File

@@ -20,9 +20,20 @@ import lombok.Setter;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* Task that makes a mob follow the player only when they make noise.
*
* @author Jakub Žitník (jzitnik)
*/
public class BlindMobFollowingPlayerTask extends MobRoomTask { public class BlindMobFollowingPlayerTask extends MobRoomTask {
private final Task task; private final Task task;
/**
* Constructs a BlindMobFollowingPlayerTask.
*
* @param speed Mob movement speed
* @param updateRateMs Execution rate in milliseconds
*/
@JsonCreator @JsonCreator
public BlindMobFollowingPlayerTask( public BlindMobFollowingPlayerTask(
@JsonProperty("speed") int speed, @JsonProperty("speed") int speed,
@@ -33,11 +44,17 @@ public class BlindMobFollowingPlayerTask extends MobRoomTask {
this.task = task; this.task = task;
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void setOwner(Mob mob) { public void setOwner(Mob mob) {
task.setMob(mob); task.setMob(mob);
} }
/**
* Internal task runnable logic.
*/
@RequiredArgsConstructor @RequiredArgsConstructor
private static class Task implements Runnable { private static class Task implements Runnable {
@Setter @Setter
@@ -68,6 +85,9 @@ public class BlindMobFollowingPlayerTask extends MobRoomTask {
@InjectConfig @InjectConfig
private MicrophoneConfig microphoneConfig; private MicrophoneConfig microphoneConfig;
/**
* {@inheritDoc}
*/
@Override @Override
public void run() { public void run() {
if (playerCords == null || (microphoneState.isMicrophoneSetup() && microphoneState.getMicrophoneVolume() > microphoneConfig.volumeThreshold())) { if (playerCords == null || (microphoneState.isMicrophoneSetup() && microphoneState.getMicrophoneVolume() > microphoneConfig.volumeThreshold())) {

View File

@@ -16,10 +16,22 @@ import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* Task that makes a mob attack the player if within reach.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
public class EnemyPlayerAttackingTask extends MobRoomTask { public class EnemyPlayerAttackingTask extends MobRoomTask {
private final Task task; private final Task task;
/**
* Constructs an EnemyPlayerAttackingTask.
*
* @param updateRateMs Execution rate in milliseconds
* @param reach Attack reach
* @param damage Attack damage
*/
@JsonCreator @JsonCreator
public EnemyPlayerAttackingTask( public EnemyPlayerAttackingTask(
@JsonProperty("updateRateMs") long updateRateMs, @JsonProperty("updateRateMs") long updateRateMs,
@@ -31,11 +43,17 @@ public class EnemyPlayerAttackingTask extends MobRoomTask {
this.task = task; this.task = task;
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void setOwner(Mob mob) { public void setOwner(Mob mob) {
task.setMob(mob); task.setMob(mob);
} }
/**
* Internal task runnable logic.
*/
@RequiredArgsConstructor @RequiredArgsConstructor
private static class Task implements Runnable { private static class Task implements Runnable {
private final double reach; private final double reach;
@@ -52,6 +70,9 @@ public class EnemyPlayerAttackingTask extends MobRoomTask {
@InjectDependency @InjectDependency
private DependencyManager dependencyManager; private DependencyManager dependencyManager;
/**
* {@inheritDoc}
*/
@Override @Override
public void run() { public void run() {
RoomCords playerCords = gameState.getPlayer().getPlayerCords(); RoomCords playerCords = gameState.getPlayer().getPlayerCords();

View File

@@ -29,10 +29,21 @@ import java.awt.image.BufferedImage;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* Task that makes a mob follow the player using A* pathfinding.
*
* @author Jakub Žitník (jzitnik)
*/
@Slf4j @Slf4j
public class MobFollowingPlayerTask extends MobRoomTask { public class MobFollowingPlayerTask extends MobRoomTask {
private final Task task; private final Task task;
/**
* Constructs a MobFollowingPlayerTask.
*
* @param speed Mob movement speed
* @param updateRateMs Execution rate in milliseconds
*/
@JsonCreator @JsonCreator
public MobFollowingPlayerTask( public MobFollowingPlayerTask(
@JsonProperty("speed") int speed, @JsonProperty("speed") int speed,
@@ -43,11 +54,17 @@ public class MobFollowingPlayerTask extends MobRoomTask {
this.task = task; this.task = task;
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void setOwner(Mob mob) { public void setOwner(Mob mob) {
task.setMob(mob); task.setMob(mob);
} }
/**
* Internal task runnable logic.
*/
@RequiredArgsConstructor @RequiredArgsConstructor
static class Task implements Runnable { static class Task implements Runnable {
private final int speed; private final int speed;
@@ -71,6 +88,19 @@ public class MobFollowingPlayerTask extends MobRoomTask {
@InjectConfig @InjectConfig
private Debugging debugging; private Debugging debugging;
/**
* Core logic to move a mob towards player coordinates.
*
* @param playerCords Target player coordinates
* @param mob Mob instance to move
* @param gameState Current game state
* @param speed Movement speed
* @param resourceManager Resource manager
* @param terminalState Terminal state
* @param screenBuffer Screen buffer
* @param debugging Debugging config
* @param eventManager Event manager
*/
protected static void moveMob(RoomCords playerCords, Mob mob, GameState gameState, int speed, ResourceManager resourceManager, TerminalState terminalState, ScreenBuffer screenBuffer, Debugging debugging, EventManager eventManager) { protected static void moveMob(RoomCords playerCords, Mob mob, GameState gameState, int speed, ResourceManager resourceManager, TerminalState terminalState, ScreenBuffer screenBuffer, Debugging debugging, EventManager eventManager) {
RoomCords mobCords = mob.getCords(); RoomCords mobCords = mob.getCords();
List<RoomPart> solidParts = gameState.getCurrentRoom().getColliders(); List<RoomPart> solidParts = gameState.getCurrentRoom().getColliders();
@@ -112,6 +142,9 @@ public class MobFollowingPlayerTask extends MobRoomTask {
} }
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void run() { public void run() {
moveMob(gameState.getPlayer().getPlayerCords(), mob, gameState, speed, resourceManager, terminalState, screenBuffer, debugging, eventManager); moveMob(gameState.getPlayer().getPlayerCords(), mob, gameState, speed, resourceManager, terminalState, screenBuffer, debugging, eventManager);

Some files were not shown because too many files have changed in this diff Show More