docs: Add javadoc
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
package cz.jzitnik.common;
|
||||
|
||||
/**
|
||||
* Configuration constants for the common module.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public class Config {
|
||||
public static final int WORLD_PASSWORD_LENGTH = 5;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@ import java.awt.image.BufferedImage;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents coordinates in a room.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
@ToString
|
||||
@Getter
|
||||
@@ -17,6 +22,12 @@ public class RoomCords implements Cloneable, Serializable {
|
||||
private int x;
|
||||
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) {
|
||||
return new RoomCords(
|
||||
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
|
||||
public RoomCords(
|
||||
@JsonProperty("x") int x,
|
||||
@@ -32,15 +49,34 @@ public class RoomCords implements Cloneable, Serializable {
|
||||
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) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the coordinates using another RoomCords instance.
|
||||
*
|
||||
* @param roomCords The RoomCords instance to copy values from
|
||||
*/
|
||||
public void updateCords(RoomCords roomCords) {
|
||||
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) {
|
||||
var normalizedPlayerCollider = new RoomPart(
|
||||
new RoomCords(playerCollider.getStart().getX() + x, playerCollider.getStart().getY() + y),
|
||||
@@ -53,6 +89,11 @@ public class RoomCords implements Cloneable, Serializable {
|
||||
updateCords(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a copy of this object.
|
||||
*
|
||||
* @return A clone of this instance
|
||||
*/
|
||||
@Override
|
||||
public RoomCords clone() {
|
||||
try {
|
||||
|
||||
@@ -7,12 +7,23 @@ import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represents a rectangular part of a room, defined by start and end coordinates.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
public class RoomPart implements Serializable {
|
||||
private RoomCords start;
|
||||
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
|
||||
public RoomPart(
|
||||
@JsonProperty("start") RoomCords start,
|
||||
@@ -22,6 +33,12 @@ public class RoomPart implements Serializable {
|
||||
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) {
|
||||
return cords.getX() >= start.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) {
|
||||
return start.getX() <= other.getEnd().getX() &&
|
||||
|
||||
@@ -9,6 +9,11 @@ import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Data required for player creation.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Getter
|
||||
public final class PlayerCreation implements Serializable {
|
||||
@Setter
|
||||
@@ -16,6 +21,12 @@ public final class PlayerCreation implements Serializable {
|
||||
private final RoomCords playerCords;
|
||||
private final RoomPart collider;
|
||||
|
||||
/**
|
||||
* Constructs a PlayerCreation instance.
|
||||
*
|
||||
* @param playerCords The player's initial coordinates
|
||||
* @param collider The player's collider
|
||||
*/
|
||||
@JsonCreator
|
||||
public PlayerCreation(
|
||||
@JsonProperty("playerCords") RoomCords playerCords,
|
||||
|
||||
@@ -2,5 +2,10 @@ package cz.jzitnik.common.socket;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Base interface for all messages sent over the socket.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public interface SocketMessage extends Serializable {
|
||||
}
|
||||
|
||||
@@ -2,5 +2,10 @@ package cz.jzitnik.common.socket.messages;
|
||||
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
/**
|
||||
* Test message for socket communication.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public class Test implements SocketMessage {
|
||||
}
|
||||
|
||||
@@ -2,5 +2,10 @@ package cz.jzitnik.common.socket.messages.game;
|
||||
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
/**
|
||||
* Message indicating that the game has been won.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public record GameWin() implements SocketMessage {
|
||||
}
|
||||
|
||||
@@ -2,5 +2,11 @@ package cz.jzitnik.common.socket.messages.game;
|
||||
|
||||
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 {
|
||||
}
|
||||
|
||||
@@ -2,5 +2,11 @@ package cz.jzitnik.common.socket.messages.game.connection;
|
||||
|
||||
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 {
|
||||
}
|
||||
|
||||
@@ -5,20 +5,45 @@ import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
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 {
|
||||
/**
|
||||
* Enum representing the possible response types for game connection.
|
||||
*/
|
||||
private enum ResponseType {
|
||||
GAME_DOES_NOT_EXIST,
|
||||
SUCCESS
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor representing a failed connection (game does not exist).
|
||||
*/
|
||||
public ConnectToAGameResponse() {
|
||||
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) {
|
||||
this(ResponseType.SUCCESS, playerCreation, existingPlayers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the connection was successful.
|
||||
*
|
||||
* @return true if successful, false otherwise.
|
||||
*/
|
||||
public boolean success() {
|
||||
return responseType == ResponseType.SUCCESS;
|
||||
}
|
||||
|
||||
@@ -2,5 +2,10 @@ package cz.jzitnik.common.socket.messages.game.creation;
|
||||
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
/**
|
||||
* Message sent to request game creation.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public class CreateGame implements SocketMessage {
|
||||
}
|
||||
|
||||
@@ -5,6 +5,11 @@ import cz.jzitnik.common.socket.SocketMessage;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Response message sent after a game is created.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class CreateGameResponse implements SocketMessage {
|
||||
|
||||
@@ -2,6 +2,13 @@ package cz.jzitnik.common.socket.messages.items;
|
||||
|
||||
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(
|
||||
String roomId, // For faster lookup i guess
|
||||
int id
|
||||
|
||||
@@ -3,6 +3,16 @@ package cz.jzitnik.common.socket.messages.player;
|
||||
import cz.jzitnik.common.models.coordinates.RoomCords;
|
||||
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,
|
||||
boolean arrived, boolean rerender) implements SocketMessage {
|
||||
}
|
||||
|
||||
@@ -2,5 +2,11 @@ package cz.jzitnik.common.socket.messages.player;
|
||||
|
||||
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 {
|
||||
}
|
||||
|
||||
@@ -3,5 +3,11 @@ package cz.jzitnik.common.socket.messages.player;
|
||||
import cz.jzitnik.common.models.player.PlayerCreation;
|
||||
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 {
|
||||
}
|
||||
|
||||
@@ -3,5 +3,12 @@ package cz.jzitnik.common.socket.messages.player;
|
||||
import cz.jzitnik.common.models.coordinates.RoomCords;
|
||||
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 {
|
||||
}
|
||||
|
||||
@@ -5,6 +5,11 @@ import cz.jzitnik.common.socket.SocketMessage;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Message sent when another player moves within the same room.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class PlayerMovedInUrRoom implements SocketMessage {
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
package cz.jzitnik.common.socket.messages.player;
|
||||
|
||||
/**
|
||||
* Enum representing the possible rotations of a player.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public enum PlayerRotation {
|
||||
FRONT, BACK, LEFT, RIGHT
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@ package cz.jzitnik.common.socket.messages.room;
|
||||
import cz.jzitnik.common.models.coordinates.RoomCords;
|
||||
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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -9,13 +9,37 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
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 {
|
||||
/**
|
||||
* 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 {}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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() {
|
||||
return players.stream().map(Registry::id).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@@ -17,6 +17,11 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Command line interface handler using Lanterna.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
@Dependency
|
||||
public class Cli implements Runnable {
|
||||
@@ -29,6 +34,9 @@ public class Cli implements Runnable {
|
||||
@InjectState
|
||||
private RunningState runningState;
|
||||
|
||||
/**
|
||||
* Runs the CLI thread, handling terminal input and events.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
// Start event manager thread
|
||||
|
||||
@@ -14,6 +14,11 @@ import org.reflections.Reflections;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Main game class responsible for initialization and starting the game loop.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public class Game {
|
||||
private final DependencyManager dependencyManager = new DependencyManager(new Reflections("cz.jzitnik.client"));
|
||||
|
||||
@@ -32,6 +37,11 @@ public class Game {
|
||||
@InjectDependency
|
||||
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 {
|
||||
dependencyManager.inject(this);
|
||||
|
||||
|
||||
@@ -4,7 +4,18 @@ package cz.jzitnik.client;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Main entry point for the client application.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
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 {
|
||||
new Game().start();
|
||||
}
|
||||
|
||||
@@ -5,8 +5,18 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
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)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Config {
|
||||
/**
|
||||
* The YAML file name.
|
||||
*
|
||||
* @return file name
|
||||
*/
|
||||
String value();
|
||||
}
|
||||
|
||||
@@ -5,9 +5,18 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
/**
|
||||
* Annotation to mark a class as a dependency for the DependencyManager.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Dependency {
|
||||
/** Custom alias **/
|
||||
/**
|
||||
* Custom alias for the dependency.
|
||||
*
|
||||
* @return Alias class
|
||||
*/
|
||||
Class<?> value() default Object.class;
|
||||
}
|
||||
@@ -7,8 +7,18 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
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)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface EventHandler {
|
||||
/**
|
||||
* The type of Event this handler handles.
|
||||
*
|
||||
* @return Event class
|
||||
*/
|
||||
Class<? extends Event> value();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
/**
|
||||
* Annotation to mark a method to be called after dependency injection.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface PostInit {
|
||||
|
||||
@@ -6,9 +6,24 @@ import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Annotation to mark a task for periodic execution.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ScheduledTask {
|
||||
/**
|
||||
* Execution rate.
|
||||
*
|
||||
* @return rate
|
||||
*/
|
||||
long rate();
|
||||
/**
|
||||
* Time unit for the rate.
|
||||
*
|
||||
* @return rate unit
|
||||
*/
|
||||
TimeUnit rateUnit();
|
||||
}
|
||||
|
||||
@@ -7,8 +7,18 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
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)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface SocketEventHandler {
|
||||
/**
|
||||
* The type of SocketMessage this handler handles.
|
||||
*
|
||||
* @return SocketMessage class
|
||||
*/
|
||||
Class<? extends SocketMessage> value();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
/**
|
||||
* Annotation to mark a class as a state component.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface State {
|
||||
|
||||
@@ -5,6 +5,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
/**
|
||||
* Annotation to mark a class for automatic thread registration.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ThreadRegistry {
|
||||
|
||||
@@ -5,6 +5,11 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation to inject a configuration component into a field.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
public @interface InjectConfig {
|
||||
|
||||
@@ -5,6 +5,11 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation to inject a dependency into a field.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
public @interface InjectDependency {
|
||||
|
||||
@@ -5,6 +5,11 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation to inject a state component into a field.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
public @interface InjectState {
|
||||
|
||||
@@ -4,10 +4,25 @@ import com.googlecode.lanterna.input.KeyType;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Annotation to mark a method as a keyboard press handler.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@Repeatable(KeyboardPressHandlers.class)
|
||||
public @interface KeyboardPressHandler {
|
||||
/**
|
||||
* The key type to handle.
|
||||
*
|
||||
* @return key type
|
||||
*/
|
||||
KeyType keyType() default KeyType.Character;
|
||||
/**
|
||||
* The specific character to handle (if keyType is Character).
|
||||
*
|
||||
* @return character
|
||||
*/
|
||||
char character() default '\0';
|
||||
}
|
||||
|
||||
@@ -5,8 +5,18 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Container annotation for repeatable KeyboardPressHandler.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface KeyboardPressHandlers {
|
||||
/**
|
||||
* Array of KeyboardPressHandler annotations.
|
||||
*
|
||||
* @return handlers
|
||||
*/
|
||||
KeyboardPressHandler[] value();
|
||||
}
|
||||
|
||||
@@ -5,8 +5,18 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
/**
|
||||
* Annotation to mark a method as a mouse handler.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface MouseHandler {
|
||||
/**
|
||||
* The type of mouse action to handle.
|
||||
*
|
||||
* @return handler type
|
||||
*/
|
||||
MouseHandlerType value();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
package cz.jzitnik.client.annotations.ui;
|
||||
|
||||
/**
|
||||
* Enum representing types of mouse handlers.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public enum MouseHandlerType {
|
||||
CLICK,
|
||||
MOVE,
|
||||
|
||||
@@ -5,6 +5,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
/**
|
||||
* Annotation to mark a method as a rendering method.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Render {
|
||||
|
||||
@@ -5,6 +5,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
/**
|
||||
* Annotation to mark a class as a UI component.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface UI {
|
||||
|
||||
@@ -4,8 +4,19 @@ import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
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")
|
||||
public record CoreLogic(int itemDropDisappearMinutes) {
|
||||
/**
|
||||
* Constructs a CoreLogic configuration instance.
|
||||
*
|
||||
* @param itemDropDisappearMinutes Disappear timeout in minutes
|
||||
*/
|
||||
@JsonCreator
|
||||
public CoreLogic(
|
||||
@JsonProperty("itemDropDisappearMinutes") int itemDropDisappearMinutes
|
||||
|
||||
@@ -4,8 +4,23 @@ import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
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")
|
||||
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
|
||||
public Debugging(
|
||||
@JsonProperty("renderColliders") boolean renderColliders,
|
||||
|
||||
@@ -4,8 +4,19 @@ import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
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")
|
||||
public record MicrophoneConfig(float volumeThreshold) {
|
||||
/**
|
||||
* Constructs a MicrophoneConfig instance.
|
||||
*
|
||||
* @param volumeThreshold The volume threshold
|
||||
*/
|
||||
@JsonCreator
|
||||
public MicrophoneConfig(
|
||||
@JsonProperty("volumeThreshold") float volumeThreshold
|
||||
|
||||
@@ -5,6 +5,18 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import cz.jzitnik.client.annotations.Config;
|
||||
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")
|
||||
public record PlayerConfig(
|
||||
double playerReach,
|
||||
@@ -15,6 +27,17 @@ public record PlayerConfig(
|
||||
int staminaIncreaseRateMs,
|
||||
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
|
||||
public PlayerConfig(
|
||||
@JsonProperty("playerReach") double playerReach,
|
||||
|
||||
@@ -4,8 +4,21 @@ import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
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")
|
||||
public record ThreadPoolConfig(int eventThreadCount, int taskThreadCount) {
|
||||
/**
|
||||
* Constructs a ThreadPoolConfig instance.
|
||||
*
|
||||
* @param eventThreadCount Event thread count
|
||||
* @param taskThreadCount Task thread count
|
||||
*/
|
||||
@JsonCreator
|
||||
public ThreadPoolConfig(
|
||||
@JsonProperty("eventThreadCount") int eventThreadCount,
|
||||
|
||||
@@ -2,6 +2,10 @@ package cz.jzitnik.client.events;
|
||||
|
||||
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 {
|
||||
}
|
||||
|
||||
@@ -5,6 +5,11 @@ import cz.jzitnik.client.utils.events.Event;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Event triggered when a key is pressed.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class KeyboardPressEvent implements Event {
|
||||
|
||||
@@ -4,11 +4,28 @@ import com.googlecode.lanterna.TerminalPosition;
|
||||
import com.googlecode.lanterna.input.MouseActionType;
|
||||
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 {
|
||||
/**
|
||||
* 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) {
|
||||
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) {
|
||||
this(mouseAction.getActionType(), mouseAction.getButton(), mouseAction.getPosition());
|
||||
}
|
||||
|
||||
@@ -4,6 +4,11 @@ import cz.jzitnik.client.utils.events.Event;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Event triggered by a mouse movement.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class MouseMoveEvent implements Event {
|
||||
|
||||
@@ -5,6 +5,11 @@ import cz.jzitnik.client.utils.events.Event;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Event triggered when a player attempts to move.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class PlayerMoveEvent implements Event {
|
||||
|
||||
@@ -4,6 +4,11 @@ import cz.jzitnik.client.utils.events.Event;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Event requesting a rerender of a specific part of the screen.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class RerenderPart implements Event {
|
||||
|
||||
@@ -5,6 +5,11 @@ import cz.jzitnik.client.utils.events.Event;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Event triggered when the terminal is resized.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class TerminalResizeEvent implements Event {
|
||||
|
||||
@@ -2,5 +2,10 @@ package cz.jzitnik.client.events;
|
||||
|
||||
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 {
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Handler for the RerenderScreen event in the CLI.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
@EventHandler(RerenderScreen.class)
|
||||
public class CliHandler extends AbstractEventHandler<RerenderScreen> {
|
||||
@@ -30,6 +35,11 @@ public class CliHandler extends AbstractEventHandler<RerenderScreen> {
|
||||
@InjectState
|
||||
private RenderState renderState;
|
||||
|
||||
/**
|
||||
* Handles the RerenderScreen event by drawing requested parts of the screen buffer to the terminal.
|
||||
*
|
||||
* @param event The RerenderScreen event
|
||||
*/
|
||||
@Override
|
||||
public void handle(RerenderScreen event) {
|
||||
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) {
|
||||
if (globalOverride instanceof Empty) {
|
||||
return buffer;
|
||||
@@ -97,6 +114,14 @@ public class CliHandler extends AbstractEventHandler<RerenderScreen> {
|
||||
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) {
|
||||
int r = blend(base.getRed(), overlay.getRed(), 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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,
|
||||
TextColor topColor,
|
||||
TextColor bottomColor) {
|
||||
|
||||
@@ -26,6 +26,11 @@ import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Handler for the Dialog event.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
@EventHandler(Dialog.class)
|
||||
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 MARGIN_BOTTOM = 15;
|
||||
/** Padding for the dialog box. */
|
||||
public static final int PADDING = 7;
|
||||
private static final int BUTTON_TEXT_PADDING = 4;
|
||||
private static final int QUESTION_ACTIONS_GAP = 10;
|
||||
/** Height of a button in the dialog. */
|
||||
public static final int BUTTON_HEIGHT = 15;
|
||||
/** Padding for buttons in the dialog. */
|
||||
public static final int BUTTON_PADDING = 5;
|
||||
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) {
|
||||
if (dialog.getOnEnd() instanceof OnEnd.AskQuestion askQuestion) {
|
||||
int count = askQuestion.answers(gameState).length;
|
||||
@@ -68,6 +83,13 @@ public class DialogEventHandler extends AbstractEventHandler<Dialog> {
|
||||
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) {
|
||||
var textSize = textRenderer.measureText(
|
||||
dialog.getText(),
|
||||
@@ -78,6 +100,14 @@ public class DialogEventHandler extends AbstractEventHandler<Dialog> {
|
||||
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) {
|
||||
var textSize = textRenderer.measureText(
|
||||
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) {
|
||||
int startY = terminalSize.getRows() * 2 - MARGIN_BOTTOM - size.getRows();
|
||||
int startX = (terminalSize.getColumns() / 2) - (size.getColumns() / 2);
|
||||
return new TerminalPosition(startX, startY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the Dialog event by rendering it with typing animation.
|
||||
*
|
||||
* @param event The Dialog event
|
||||
*/
|
||||
@Override
|
||||
public void handle(Dialog event) {
|
||||
boolean onlyLast = dialogState.getCurrentDialog() == event;
|
||||
|
||||
@@ -10,11 +10,21 @@ import cz.jzitnik.client.utils.events.EventManager;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* Handler for the DroppedItemRerender event.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@EventHandler(DroppedItemRerender.class)
|
||||
public class DroppedItemRerenderHandler extends AbstractEventHandler<DroppedItemRerender> {
|
||||
@InjectDependency
|
||||
private EventManager eventManager;
|
||||
|
||||
/**
|
||||
* Handles the DroppedItemRerender event by emitting a RerenderPart event.
|
||||
*
|
||||
* @param event The DroppedItemRerender event
|
||||
*/
|
||||
@Override
|
||||
public void handle(DroppedItemRerender event) {
|
||||
RoomCords droppedItemCords = event.droppedItem().getCords();
|
||||
|
||||
@@ -10,6 +10,11 @@ import cz.jzitnik.client.utils.ThreadManager;
|
||||
import cz.jzitnik.client.utils.events.AbstractEventHandler;
|
||||
import cz.jzitnik.client.utils.roomtasks.RoomTaskScheduler;
|
||||
|
||||
/**
|
||||
* Handler for the ExitEvent.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@EventHandler(ExitEvent.class)
|
||||
public class ExitEventHandler extends AbstractEventHandler<ExitEvent> {
|
||||
@InjectDependency
|
||||
@@ -24,6 +29,11 @@ public class ExitEventHandler extends AbstractEventHandler<ExitEvent> {
|
||||
@InjectDependency
|
||||
private ScheduledTaskManager scheduledTaskManager;
|
||||
|
||||
/**
|
||||
* Handles the ExitEvent by shutting down all managers and setting the running state to false.
|
||||
*
|
||||
* @param event The ExitEvent
|
||||
*/
|
||||
@Override
|
||||
public void handle(ExitEvent event) {
|
||||
threadManager.shutdownAll();
|
||||
|
||||
@@ -12,6 +12,11 @@ import cz.jzitnik.client.utils.events.EventManager;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Handler for the FullRedrawEvent.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@EventHandler(FullRedrawEvent.class)
|
||||
public class FullRedrawEventHandler extends AbstractEventHandler<FullRedrawEvent> {
|
||||
@InjectDependency
|
||||
@@ -20,6 +25,11 @@ public class FullRedrawEventHandler extends AbstractEventHandler<FullRedrawEvent
|
||||
@InjectState
|
||||
private TerminalState terminalState;
|
||||
|
||||
/**
|
||||
* Handles the FullRedrawEvent by clearing the terminal and emitting a FullRoomDraw event.
|
||||
*
|
||||
* @param event The FullRedrawEvent
|
||||
*/
|
||||
@Override
|
||||
public void handle(FullRedrawEvent event) {
|
||||
terminalState.getTerminalScreen().clear();
|
||||
|
||||
@@ -32,6 +32,11 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Handler for the FullRoomDraw event.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
@EventHandler(FullRoomDraw.class)
|
||||
public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
|
||||
@@ -55,6 +60,11 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
|
||||
@InjectDependency
|
||||
private GlobalIOHandlerRepository globalIOHandlerRepository;
|
||||
|
||||
/**
|
||||
* Handles the FullRoomDraw event by rendering the entire room and players.
|
||||
*
|
||||
* @param event The FullRoomDraw event
|
||||
*/
|
||||
@Override
|
||||
public void handle(FullRoomDraw event) {
|
||||
try {
|
||||
@@ -103,6 +113,9 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum representing door positions in a room.
|
||||
*/
|
||||
public enum DoorPosition {
|
||||
TOP,
|
||||
LEFT,
|
||||
|
||||
@@ -9,6 +9,11 @@ import cz.jzitnik.client.ui.Inventory;
|
||||
import cz.jzitnik.client.utils.events.AbstractEventHandler;
|
||||
import cz.jzitnik.client.utils.events.EventManager;
|
||||
|
||||
/**
|
||||
* Handler for the InventoryRerender event.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@EventHandler(InventoryRerender.class)
|
||||
public class InventoryRerenderHandler extends AbstractEventHandler<InventoryRerender> {
|
||||
@InjectDependency
|
||||
@@ -17,6 +22,11 @@ public class InventoryRerenderHandler extends AbstractEventHandler<InventoryRere
|
||||
@InjectDependency
|
||||
private Inventory inventory;
|
||||
|
||||
/**
|
||||
* Handles the InventoryRerender event by rerendering the inventory UI component.
|
||||
*
|
||||
* @param event The InventoryRerender event
|
||||
*/
|
||||
@Override
|
||||
public void handle(InventoryRerender event) {
|
||||
inventory.renderInventoryRerender();
|
||||
|
||||
@@ -8,6 +8,11 @@ import cz.jzitnik.client.game.GameState;
|
||||
import cz.jzitnik.client.utils.GlobalIOHandlerRepository;
|
||||
import cz.jzitnik.client.utils.events.AbstractEventHandler;
|
||||
|
||||
/**
|
||||
* Handler for the KeyboardPressEvent.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@EventHandler(KeyboardPressEvent.class)
|
||||
public class KeyboardPressEventHandler extends AbstractEventHandler<KeyboardPressEvent> {
|
||||
@InjectState
|
||||
@@ -16,6 +21,11 @@ public class KeyboardPressEventHandler extends AbstractEventHandler<KeyboardPres
|
||||
@InjectDependency
|
||||
private GlobalIOHandlerRepository globalIOHandlerRepository;
|
||||
|
||||
/**
|
||||
* Handles the KeyboardPressEvent by delegating to the current screen or the global repository.
|
||||
*
|
||||
* @param event The KeyboardPressEvent
|
||||
*/
|
||||
@Override
|
||||
public void handle(KeyboardPressEvent event) {
|
||||
if (gameState.getScreen() != null) {
|
||||
|
||||
@@ -18,6 +18,11 @@ import cz.jzitnik.client.utils.events.EventManager;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Handler for the MouseAction event.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@EventHandler(MouseAction.class)
|
||||
public class MouseActionEventHandler extends AbstractEventHandler<MouseAction> {
|
||||
@InjectDependency
|
||||
@@ -38,6 +43,11 @@ public class MouseActionEventHandler extends AbstractEventHandler<MouseAction> {
|
||||
@InjectDependency
|
||||
private DependencyManager dependencyManager;
|
||||
|
||||
/**
|
||||
* Handles the MouseAction event by delegating to screens, repositories, or performing interactions.
|
||||
*
|
||||
* @param event The MouseAction event
|
||||
*/
|
||||
@Override
|
||||
public void handle(MouseAction event) {
|
||||
if (gameState.getScreen() != null) {
|
||||
|
||||
@@ -32,6 +32,11 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Handler for the MouseMoveEvent.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
@EventHandler(MouseMoveEvent.class)
|
||||
public class MouseMoveEventHandler extends AbstractEventHandler<MouseMoveEvent> {
|
||||
@@ -58,6 +63,17 @@ public class MouseMoveEventHandler extends AbstractEventHandler<MouseMoveEvent>
|
||||
@InjectConfig
|
||||
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(
|
||||
double px, double py,
|
||||
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
|
||||
public void handle(MouseMoveEvent event) {
|
||||
if (event.getMouseAction() != null) {
|
||||
|
||||
@@ -26,6 +26,11 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* Handler for the PlayerMoveEvent.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
@EventHandler(PlayerMoveEvent.class)
|
||||
public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent> {
|
||||
@@ -50,6 +55,11 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
|
||||
@InjectDependency
|
||||
private Stats stats;
|
||||
|
||||
/**
|
||||
* Handles the PlayerMoveEvent by updating player position and triggering rerenders.
|
||||
*
|
||||
* @param event The PlayerMoveEvent
|
||||
*/
|
||||
@Override
|
||||
public void handle(PlayerMoveEvent event) {
|
||||
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 {
|
||||
CTRL,
|
||||
SHIFT,
|
||||
|
||||
@@ -9,6 +9,11 @@ import cz.jzitnik.client.ui.Stats;
|
||||
import cz.jzitnik.client.utils.events.AbstractEventHandler;
|
||||
import cz.jzitnik.client.utils.events.EventManager;
|
||||
|
||||
/**
|
||||
* Handler for the RenderStats event.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@EventHandler(RenderStats.class)
|
||||
public class RenderStatsHandler extends AbstractEventHandler<RenderStats> {
|
||||
@InjectDependency
|
||||
@@ -17,6 +22,11 @@ public class RenderStatsHandler extends AbstractEventHandler<RenderStats> {
|
||||
@InjectDependency
|
||||
private Stats stats;
|
||||
|
||||
/**
|
||||
* Handles the RenderStats event by rerendering the stats UI component.
|
||||
*
|
||||
* @param event The RenderStats event
|
||||
*/
|
||||
@Override
|
||||
public void handle(RenderStats event) {
|
||||
stats.rerender();
|
||||
|
||||
@@ -20,6 +20,11 @@ import cz.jzitnik.client.utils.events.EventManager;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* Handler for the RerenderPart event.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@EventHandler(RerenderPart.class)
|
||||
public class RerenderPartHandler extends AbstractEventHandler<RerenderPart> {
|
||||
@InjectState
|
||||
@@ -40,6 +45,11 @@ public class RerenderPartHandler extends AbstractEventHandler<RerenderPart> {
|
||||
@InjectDependency
|
||||
private EventManager eventManager;
|
||||
|
||||
/**
|
||||
* Handles the RerenderPart event by rerendering a portion of the screen.
|
||||
*
|
||||
* @param event The RerenderPart event
|
||||
*/
|
||||
@Override
|
||||
public void handle(RerenderPart event) {
|
||||
int forStartX = event.getForStartX();
|
||||
|
||||
@@ -21,6 +21,11 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Handler for the RoomChangeEvent.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
@EventHandler(RoomChangeEvent.class)
|
||||
public class RoomChangeEventHandler extends AbstractEventHandler<RoomChangeEvent> {
|
||||
@@ -32,6 +37,11 @@ public class RoomChangeEventHandler extends AbstractEventHandler<RoomChangeEvent
|
||||
@InjectDependency
|
||||
private RoomTaskScheduler roomTaskScheduler;
|
||||
|
||||
/**
|
||||
* Handles the RoomChangeEvent by changing the current room and moving the player.
|
||||
*
|
||||
* @param event The RoomChangeEvent
|
||||
*/
|
||||
@Override
|
||||
public void handle(RoomChangeEvent event) {
|
||||
RoomCords playerCords = gameState.getPlayer().getPlayerCords();
|
||||
|
||||
@@ -8,11 +8,21 @@ import cz.jzitnik.client.utils.events.AbstractEventHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Handler for the SendSocketMessageEvent.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@EventHandler(SendSocketMessageEvent.class)
|
||||
public class SendSocketMessageEventHandler extends AbstractEventHandler<SendSocketMessageEvent> {
|
||||
@InjectDependency
|
||||
private Client client;
|
||||
|
||||
/**
|
||||
* Handles the SendSocketMessageEvent by sending the message through the client.
|
||||
*
|
||||
* @param event The SendSocketMessageEvent
|
||||
*/
|
||||
@Override
|
||||
public void handle(SendSocketMessageEvent event) {
|
||||
try {
|
||||
|
||||
@@ -15,6 +15,11 @@ import cz.jzitnik.client.utils.events.AbstractEventHandler;
|
||||
import cz.jzitnik.client.utils.events.EventManager;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Handler for the TerminalResizeEvent.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
@EventHandler(TerminalResizeEvent.class)
|
||||
public class TerminalResizeEventHandler extends AbstractEventHandler<TerminalResizeEvent> {
|
||||
@@ -29,6 +34,11 @@ public class TerminalResizeEventHandler extends AbstractEventHandler<TerminalRes
|
||||
|
||||
private boolean screenRerendering = false;
|
||||
|
||||
/**
|
||||
* Handles the TerminalResizeEvent by reinitializing buffers and triggering a full redraw.
|
||||
*
|
||||
* @param event The TerminalResizeEvent
|
||||
*/
|
||||
@Override
|
||||
public void handle(TerminalResizeEvent event) {
|
||||
TerminalSize size = event.getNewSize();
|
||||
|
||||
@@ -14,11 +14,21 @@ import cz.jzitnik.client.utils.events.AbstractEventHandler;
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* Handler for the TerminalTooSmallEvent.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@EventHandler(TerminalTooSmallEvent.class)
|
||||
public class TerminalTooSmallEventHandler extends AbstractEventHandler<TerminalTooSmallEvent> {
|
||||
@InjectState
|
||||
private TerminalState terminalState;
|
||||
|
||||
/**
|
||||
* Handles the TerminalTooSmallEvent by rendering a warning message directly to the terminal.
|
||||
*
|
||||
* @param event The TerminalTooSmallEvent
|
||||
*/
|
||||
@Override
|
||||
public void handle(TerminalTooSmallEvent event) {
|
||||
// Directly render the message for the user
|
||||
|
||||
@@ -2,6 +2,12 @@ package cz.jzitnik.client.game;
|
||||
|
||||
import com.googlecode.lanterna.TextColor;
|
||||
|
||||
/**
|
||||
* Global game constants.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public class Constants {
|
||||
/** The default background color for the game. */
|
||||
public static final TextColor BACKGROUND_COLOR = new TextColor.RGB(4, 4, 16);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,24 @@ import cz.jzitnik.common.models.coordinates.RoomCords;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* Interface representing a player-like entity in the game.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public interface GamePlayer {
|
||||
/**
|
||||
* Gets the player's coordinates.
|
||||
*
|
||||
* @return RoomCords instance
|
||||
*/
|
||||
RoomCords getPlayerCords();
|
||||
|
||||
/**
|
||||
* Gets the player's current texture.
|
||||
*
|
||||
* @param resourceManager The resource manager to load texture
|
||||
* @return BufferedImage texture
|
||||
*/
|
||||
BufferedImage getTexture(ResourceManager resourceManager);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents a room in the game.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@JsonIdentityInfo(
|
||||
generator = ObjectIdGenerators.PropertyGenerator.class,
|
||||
property = "id"
|
||||
@@ -45,6 +50,15 @@ public class GameRoom {
|
||||
private GameRoom up;
|
||||
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
|
||||
public GameRoom(
|
||||
@JsonProperty("id") String id,
|
||||
@@ -72,21 +86,41 @@ public class GameRoom {
|
||||
this.overrideBuffer = overrideBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the room to the west (left).
|
||||
*
|
||||
* @param west West room
|
||||
*/
|
||||
@JsonSetter("west")
|
||||
public void setWest(GameRoom west) {
|
||||
if (west != null) this.left = west;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the room to the east (right).
|
||||
*
|
||||
* @param east East room
|
||||
*/
|
||||
@JsonSetter("east")
|
||||
public void setEast(GameRoom east) {
|
||||
if (east != null) this.right = east;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the room to the north (up).
|
||||
*
|
||||
* @param north North room
|
||||
*/
|
||||
@JsonSetter("north")
|
||||
public void setNorth(GameRoom north) {
|
||||
if (north != null) this.up = north;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the room to the south (down).
|
||||
*
|
||||
* @param south South room
|
||||
*/
|
||||
@JsonSetter("south")
|
||||
public void setSouth(GameRoom south) {
|
||||
if (south != null) this.down = south;
|
||||
|
||||
@@ -11,6 +11,11 @@ import lombok.Setter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Holds the current state of the game.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@State
|
||||
public class GameState {
|
||||
@@ -30,10 +35,20 @@ public class GameState {
|
||||
|
||||
private final List<OtherPlayer> otherPlayers = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Gets a list of visible other players.
|
||||
*
|
||||
* @return List of visible other players
|
||||
*/
|
||||
public List<OtherPlayer> getOtherPlayers() {
|
||||
return otherPlayers.stream().filter(OtherPlayer::isVisible).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all other players.
|
||||
*
|
||||
* @return List of all other players
|
||||
*/
|
||||
public List<OtherPlayer> getAllOtherPlayers() {
|
||||
return otherPlayers;
|
||||
}
|
||||
@@ -45,6 +60,11 @@ public class GameState {
|
||||
@Getter
|
||||
private Screen screen;
|
||||
|
||||
/**
|
||||
* Sets the current screen and injects its dependencies.
|
||||
*
|
||||
* @param screen The screen to set
|
||||
*/
|
||||
public void setScreen(Screen screen) {
|
||||
if (screen != null) {
|
||||
dependencyManager.inject(screen);
|
||||
|
||||
@@ -9,6 +9,11 @@ import lombok.Setter;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* Represents another player connected to the same game.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Getter
|
||||
public class OtherPlayer implements GamePlayer {
|
||||
private final int id;
|
||||
@@ -19,11 +24,20 @@ public class OtherPlayer implements GamePlayer {
|
||||
@Setter
|
||||
private boolean visible;
|
||||
|
||||
/**
|
||||
* Constructs an OtherPlayer.
|
||||
*
|
||||
* @param playerCreation Player creation data
|
||||
*/
|
||||
public OtherPlayer(PlayerCreation playerCreation) {
|
||||
this.id = playerCreation.getId();
|
||||
this.playerCords = playerCreation.getPlayerCords();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public BufferedImage getTexture(ResourceManager resourceManager) {
|
||||
BufferedImage resource = resourceManager.getResource(switch (playerRotation) {
|
||||
case FRONT -> ResourceManager.Resource.PLAYER_FRONT;
|
||||
|
||||
@@ -22,11 +22,18 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Represents the local player.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Getter
|
||||
@Slf4j
|
||||
public class Player implements GamePlayer {
|
||||
private final int id;
|
||||
/** Maximum stamina value. */
|
||||
public static final int MAX_STAMINA = 20;
|
||||
/** Maximum health value. */
|
||||
public static final int MAX_HEALTH = 30;
|
||||
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
@@ -43,24 +50,47 @@ public class Player implements GamePlayer {
|
||||
private boolean hitAnimationOn = false;
|
||||
private ScheduledFuture<?> currentTimeoutHitAnimation = null;
|
||||
|
||||
/**
|
||||
* Constructs a Player.
|
||||
*
|
||||
* @param playerCreation Player creation data
|
||||
*/
|
||||
public Player(PlayerCreation playerCreation) {
|
||||
this.playerCords = playerCreation.getPlayerCords();
|
||||
this.collider = playerCreation.getCollider();
|
||||
this.id = playerCreation.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases player stamina.
|
||||
*/
|
||||
public void increaseStamina() {
|
||||
stamina++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases player stamina.
|
||||
*/
|
||||
public void decreaseStamina() {
|
||||
stamina--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores player health.
|
||||
*
|
||||
* @param amount Amount to restore
|
||||
*/
|
||||
public void addHealth(int 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) {
|
||||
if (health - amount <= 0) {
|
||||
health = 0;
|
||||
@@ -88,6 +118,11 @@ public class Player implements GamePlayer {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a rerender of the player.
|
||||
*
|
||||
* @param dependencyManager Dependency manager
|
||||
*/
|
||||
private void rerender(DependencyManager dependencyManager) {
|
||||
ResourceManager resourceManager = dependencyManager.getDependencyOrThrow(ResourceManager.class);
|
||||
EventManager eventManager = dependencyManager.getDependencyOrThrow(EventManager.class);
|
||||
@@ -104,6 +139,10 @@ public class Player implements GamePlayer {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public BufferedImage getTexture(ResourceManager resourceManager) {
|
||||
BufferedImage resource = resourceManager.getResource(switch (playerRotation) {
|
||||
case FRONT -> ResourceManager.Resource.PLAYER_FRONT;
|
||||
@@ -119,6 +158,11 @@ public class Player implements GamePlayer {
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the damage dealt by the player with their current weapon.
|
||||
*
|
||||
* @return Damage value
|
||||
*/
|
||||
public int getDamageDeal() {
|
||||
int damage = 1;
|
||||
|
||||
@@ -131,6 +175,12 @@ public class Player implements GamePlayer {
|
||||
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) {
|
||||
boolean added = false;
|
||||
for (int i = 0; i < inventory.length; i++) {
|
||||
@@ -144,6 +194,11 @@ public class Player implements GamePlayer {
|
||||
return added;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a weapon swing animation.
|
||||
*
|
||||
* @param delayMs Duration of the swing
|
||||
*/
|
||||
public void swing(int delayMs) {
|
||||
if (swinging) {
|
||||
return;
|
||||
|
||||
@@ -3,7 +3,18 @@ package cz.jzitnik.client.game;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
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) {
|
||||
/**
|
||||
* Constructs a Requirement.
|
||||
*
|
||||
* @param itemType The type of item required
|
||||
*/
|
||||
@JsonCreator
|
||||
public Requirement(
|
||||
@JsonProperty("item") String itemType
|
||||
|
||||
@@ -11,11 +11,19 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Manages loading and caching of game resources (textures, audio).
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Dependency
|
||||
public class ResourceManager {
|
||||
@InjectDependency
|
||||
private ClassLoader classLoader;
|
||||
|
||||
/**
|
||||
* Enum representing available game resources.
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum Resource {
|
||||
@@ -69,6 +77,12 @@ public class ResourceManager {
|
||||
|
||||
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) {
|
||||
if (resourceCache.containsKey(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) {
|
||||
InputStream is = classLoader.getResourceAsStream(path);
|
||||
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) {
|
||||
return classLoader.getResourceAsStream(path);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,11 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import cz.jzitnik.client.utils.events.Event;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Represents a dialog sequence in the game.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Getter
|
||||
public class Dialog implements Event {
|
||||
/**
|
||||
@@ -14,6 +19,12 @@ public class Dialog implements Event {
|
||||
private final String text;
|
||||
private final OnEnd onEnd;
|
||||
|
||||
/**
|
||||
* Constructs a Dialog.
|
||||
*
|
||||
* @param text The dialog text
|
||||
* @param onEnd Action to perform when dialog ends
|
||||
*/
|
||||
@JsonCreator
|
||||
public Dialog(
|
||||
@JsonProperty("text") String text,
|
||||
|
||||
@@ -20,6 +20,11 @@ import lombok.RequiredArgsConstructor;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Interface for actions to perform at the end of a dialog.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@JsonTypeInfo(
|
||||
use = JsonTypeInfo.Id.NAME,
|
||||
property = "type"
|
||||
@@ -31,10 +36,18 @@ import java.util.Optional;
|
||||
@JsonSubTypes.Type(value = OnEnd.GiveItem.class, name = "give_item")
|
||||
})
|
||||
public interface OnEnd {
|
||||
/** Terminal dialog action. */
|
||||
record End() implements OnEnd {
|
||||
}
|
||||
|
||||
/** Action that gives an item to the player. */
|
||||
class GiveItem extends RunCode {
|
||||
/**
|
||||
* Constructs a GiveItem action.
|
||||
*
|
||||
* @param item Item to give
|
||||
* @param onEnd Next action
|
||||
*/
|
||||
@JsonCreator
|
||||
public GiveItem(
|
||||
@JsonProperty("item") GameItem item,
|
||||
@@ -43,6 +56,7 @@ public interface OnEnd {
|
||||
super(new Run(item), onEnd);
|
||||
}
|
||||
|
||||
/** Internal runnable to give the item. */
|
||||
@RequiredArgsConstructor
|
||||
private static class Run implements Runnable {
|
||||
private final GameItem item;
|
||||
@@ -56,6 +70,9 @@ public interface OnEnd {
|
||||
@InjectDependency
|
||||
private ResourceManager resourceManager;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
Player player = gameState.getPlayer();
|
||||
@@ -72,6 +89,7 @@ public interface OnEnd {
|
||||
}
|
||||
}
|
||||
|
||||
/** Action that runs arbitrary code. */
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
class RunCode implements OnEnd {
|
||||
@@ -79,24 +97,44 @@ public interface OnEnd {
|
||||
private final OnEnd onEnd;
|
||||
}
|
||||
|
||||
/** Action that continues to another dialog. */
|
||||
record Continue(Dialog nextDialog) implements OnEnd {
|
||||
/**
|
||||
* Constructs a Continue action.
|
||||
*
|
||||
* @param nextDialog The next dialog
|
||||
*/
|
||||
@JsonCreator
|
||||
public Continue(@JsonProperty("nextDialog") Dialog nextDialog) {
|
||||
this.nextDialog = nextDialog;
|
||||
}
|
||||
}
|
||||
|
||||
/** Action that asks the player a question with multiple answers. */
|
||||
record AskQuestion(Answer[] answers) implements OnEnd {
|
||||
/**
|
||||
* Constructs an AskQuestion action.
|
||||
*
|
||||
* @param answers Possible answers
|
||||
*/
|
||||
@JsonCreator
|
||||
public AskQuestion(@JsonProperty("answers") Answer[] answers) {
|
||||
this.answers = answers;
|
||||
}
|
||||
|
||||
/** Represents a single answer to a question. */
|
||||
public record Answer(
|
||||
String answer,
|
||||
Dialog dialog,
|
||||
Optional<Requirement> requirement
|
||||
) {
|
||||
/**
|
||||
* Constructs an Answer.
|
||||
*
|
||||
* @param answer Answer text
|
||||
* @param dialog Resulting dialog
|
||||
* @param requirement Requirement to see this answer
|
||||
*/
|
||||
@JsonCreator
|
||||
public Answer(
|
||||
@JsonProperty("answer") String answer,
|
||||
@@ -106,6 +144,9 @@ public interface OnEnd {
|
||||
this(answer, dialog, Optional.ofNullable(requirement));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the answer is valid for the current state.
|
||||
*/
|
||||
private boolean isValid(GameState gameState) {
|
||||
if (requirement.isPresent()) {
|
||||
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) {
|
||||
return Arrays.stream(answers)
|
||||
.filter(answer -> answer.isValid(gameState))
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
package cz.jzitnik.client.game.exceptions;
|
||||
|
||||
/**
|
||||
* Exception thrown when coordinates are invalid.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public class InvalidCoordinatesException extends RuntimeException {
|
||||
/**
|
||||
* Constructs an InvalidCoordinatesException with message.
|
||||
*
|
||||
* @param message The error message
|
||||
*/
|
||||
public InvalidCoordinatesException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an InvalidCoordinatesException.
|
||||
*/
|
||||
public InvalidCoordinatesException() {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,11 @@ import lombok.Getter;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* Represents an item in the game.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Getter
|
||||
public class GameItem implements Renderable {
|
||||
private final ItemType<?> type;
|
||||
@@ -16,6 +21,15 @@ public class GameItem implements Renderable {
|
||||
private final String name;
|
||||
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
|
||||
public GameItem(
|
||||
@JsonProperty("id") int id,
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
package cz.jzitnik.client.game.items.types;
|
||||
|
||||
/**
|
||||
* Represents a beast skin item type.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public class BeastSkin implements ItemType<BeastSkin> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Class<BeastSkin> getItemType() {
|
||||
return BeastSkin.class;
|
||||
|
||||
@@ -3,10 +3,26 @@ package cz.jzitnik.client.game.items.types;
|
||||
import cz.jzitnik.client.utils.DependencyManager;
|
||||
import cz.jzitnik.client.utils.StateManager;
|
||||
|
||||
/**
|
||||
* Interface for items that can be interacted with.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* Response types for item interaction.
|
||||
*/
|
||||
enum InteractableItemResponse {
|
||||
/** Clear the item from inventory. */
|
||||
CLEAR_ITEM,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.weapons.Sword;
|
||||
|
||||
/**
|
||||
* Interface representing a type of game item.
|
||||
*
|
||||
* @param <T> The class type of the item
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@JsonTypeInfo(
|
||||
use = JsonTypeInfo.Id.NAME,
|
||||
property = "name"
|
||||
@@ -17,5 +23,10 @@ import cz.jzitnik.client.game.items.types.weapons.Sword;
|
||||
@JsonSubTypes.Type(value = BeastSkin.class, name = "beast_skin"),
|
||||
})
|
||||
public interface ItemType<T> {
|
||||
/**
|
||||
* Gets the class representing this item type.
|
||||
*
|
||||
* @return The item type class
|
||||
*/
|
||||
Class<T> getItemType();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
package cz.jzitnik.client.game.items.types;
|
||||
|
||||
/**
|
||||
* Represents a junk item type.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public class Junk implements ItemType<Junk> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Class<Junk> getItemType() {
|
||||
return Junk.class;
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
package cz.jzitnik.client.game.items.types;
|
||||
|
||||
/**
|
||||
* Represents a key item type.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public class Key implements ItemType<Key> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Class<Key> getItemType() {
|
||||
return Key.class;
|
||||
|
||||
@@ -10,9 +10,19 @@ import cz.jzitnik.client.utils.DependencyManager;
|
||||
import cz.jzitnik.client.utils.StateManager;
|
||||
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> {
|
||||
private final int addHealth;
|
||||
|
||||
/**
|
||||
* Constructs a Food item with specified health restoration value.
|
||||
*
|
||||
* @param addHealth Health to add when consumed
|
||||
*/
|
||||
@JsonCreator
|
||||
public Food(
|
||||
@JsonProperty("addHealth") int addHealth
|
||||
@@ -20,6 +30,13 @@ public class Food implements InteractableItem, ItemType<Food> {
|
||||
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
|
||||
public InteractableItemResponse interact(DependencyManager dependencyManager, StateManager stateManager) {
|
||||
GameState gameState = stateManager.getOrThrow(GameState.class);
|
||||
@@ -31,6 +48,9 @@ public class Food implements InteractableItem, ItemType<Food> {
|
||||
return InteractableItemResponse.CLEAR_ITEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Class<Food> getItemType() {
|
||||
return Food.class;
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
package cz.jzitnik.client.game.items.types.interfaces;
|
||||
|
||||
/**
|
||||
* Interface for game items that can deal damage.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public interface WeaponInterface {
|
||||
/**
|
||||
* Gets the damage dealt by the weapon.
|
||||
*
|
||||
* @return Damage value
|
||||
*/
|
||||
int getDamageDeal();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,17 @@ package cz.jzitnik.client.game.items.types.weapons;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Represents a sword weapon.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public class Sword extends Weapon {
|
||||
/**
|
||||
* Constructs a Sword with specified damage.
|
||||
*
|
||||
* @param dealDamage Damage dealt by the sword
|
||||
*/
|
||||
@JsonCreator
|
||||
public Sword(
|
||||
@JsonProperty("dealDamage") int dealDamage
|
||||
|
||||
@@ -4,15 +4,28 @@ import cz.jzitnik.client.game.items.types.ItemType;
|
||||
import cz.jzitnik.client.game.items.types.interfaces.WeaponInterface;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
/**
|
||||
* Base class for all weapon items.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public abstract class Weapon implements ItemType<Weapon>, WeaponInterface {
|
||||
private final int dealDamage;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final Class<Weapon> getItemType() {
|
||||
return Weapon.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the damage dealt by this weapon.
|
||||
*
|
||||
* @return Damage value
|
||||
*/
|
||||
@Override
|
||||
public int getDamageDeal() {
|
||||
return dealDamage;
|
||||
|
||||
@@ -14,10 +14,25 @@ import cz.jzitnik.client.states.DialogState;
|
||||
import cz.jzitnik.client.utils.events.EventManager;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* A mob that triggers a dialog when interacted with.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
public class DialogMob extends Mob {
|
||||
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
|
||||
public DialogMob(
|
||||
@JsonProperty("texture") ResourceManager.Resource texture,
|
||||
@@ -37,6 +52,9 @@ public class DialogMob extends Mob {
|
||||
@InjectState
|
||||
private DialogState dialogState;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void interact() {
|
||||
log.debug("Interacting with dialog mob!");
|
||||
|
||||
@@ -20,8 +20,16 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Abstract base class for mobs that can be hit and killed.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class HittableMob extends Mob {
|
||||
/**
|
||||
* Called when the mob is killed.
|
||||
*/
|
||||
public abstract void onKilled();
|
||||
|
||||
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
|
||||
@@ -31,6 +39,9 @@ public abstract class HittableMob extends Mob {
|
||||
|
||||
private boolean hitAnimationOn = false;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public BufferedImage getTexture() {
|
||||
if (hitAnimationOn) {
|
||||
@@ -40,6 +51,12 @@ public abstract class HittableMob extends Mob {
|
||||
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) {
|
||||
final float redFactor = 2f;
|
||||
int width = src.getWidth();
|
||||
@@ -68,11 +85,23 @@ public abstract class HittableMob extends Mob {
|
||||
@InjectDependency
|
||||
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) {
|
||||
super(texture, tasks, cords, collider);
|
||||
this.health = health;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final void interact() {
|
||||
health -= gameState.getPlayer().getDamageDeal();
|
||||
@@ -106,6 +135,9 @@ public abstract class HittableMob extends Mob {
|
||||
}, 250, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a rerender of the mob's position.
|
||||
*/
|
||||
private void rerender() {
|
||||
int forStartX = cords.getX();
|
||||
int forStartY = cords.getY();
|
||||
|
||||
@@ -21,6 +21,11 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* A hittable mob that drops items when killed.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
public class HittableMobDrops extends HittableMob {
|
||||
private static final int DROP_ITEM_ON_GROUND_RADIUS = 30;
|
||||
private final GameItem[] itemsDrops;
|
||||
@@ -29,6 +34,17 @@ public class HittableMobDrops extends HittableMob {
|
||||
@InjectDependency
|
||||
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
|
||||
public HittableMobDrops(
|
||||
@JsonProperty("texture") ResourceManager.Resource texture,
|
||||
@@ -49,6 +65,9 @@ public class HittableMobDrops extends HittableMob {
|
||||
public void afterKill() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final void onKilled() {
|
||||
boolean addedIntoInventory = false;
|
||||
@@ -77,6 +96,15 @@ public class HittableMobDrops extends HittableMob {
|
||||
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) {
|
||||
double angle = ThreadLocalRandom.current().nextDouble(0, Math.PI * 2);
|
||||
double radius = ThreadLocalRandom.current().nextDouble(0, DROP_ITEM_ON_GROUND_RADIUS);
|
||||
|
||||
@@ -8,7 +8,22 @@ import cz.jzitnik.client.game.ResourceManager;
|
||||
import cz.jzitnik.client.game.mobs.tasks.MobRoomTask;
|
||||
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 {
|
||||
/**
|
||||
* 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
|
||||
public HittableMobNoDrops(
|
||||
@JsonProperty("texture") ResourceManager.Resource texture,
|
||||
@@ -21,6 +36,9 @@ public class HittableMobNoDrops extends HittableMob {
|
||||
super(resourceManager.getResource(texture), tasks, cords, collider, health);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onKilled() {
|
||||
|
||||
|
||||
@@ -15,6 +15,11 @@ import lombok.Setter;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* Abstract base class for all mobs in the game.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@JsonTypeInfo(
|
||||
use = JsonTypeInfo.Id.NAME,
|
||||
property = "type"
|
||||
@@ -39,6 +44,11 @@ public abstract class Mob implements Renderable, Selectable {
|
||||
@InjectDependency
|
||||
private RoomTaskScheduler roomTaskScheduler;
|
||||
|
||||
/**
|
||||
* Updates the tasks associated with this mob and registers them.
|
||||
*
|
||||
* @param tasks The new tasks
|
||||
*/
|
||||
protected void updateTasks(MobRoomTask[] tasks) {
|
||||
var oldTasks = this.tasks;
|
||||
this.tasks = tasks;
|
||||
@@ -46,6 +56,14 @@ public abstract class Mob implements Renderable, Selectable {
|
||||
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) {
|
||||
this.texture = texture;
|
||||
this.tasks = tasks == null ? new MobRoomTask[] {} : tasks;
|
||||
|
||||
@@ -20,9 +20,20 @@ import lombok.Setter;
|
||||
|
||||
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 {
|
||||
private final Task task;
|
||||
|
||||
/**
|
||||
* Constructs a BlindMobFollowingPlayerTask.
|
||||
*
|
||||
* @param speed Mob movement speed
|
||||
* @param updateRateMs Execution rate in milliseconds
|
||||
*/
|
||||
@JsonCreator
|
||||
public BlindMobFollowingPlayerTask(
|
||||
@JsonProperty("speed") int speed,
|
||||
@@ -33,11 +44,17 @@ public class BlindMobFollowingPlayerTask extends MobRoomTask {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setOwner(Mob mob) {
|
||||
task.setMob(mob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal task runnable logic.
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
private static class Task implements Runnable {
|
||||
@Setter
|
||||
@@ -68,6 +85,9 @@ public class BlindMobFollowingPlayerTask extends MobRoomTask {
|
||||
@InjectConfig
|
||||
private MicrophoneConfig microphoneConfig;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
if (playerCords == null || (microphoneState.isMicrophoneSetup() && microphoneState.getMicrophoneVolume() > microphoneConfig.volumeThreshold())) {
|
||||
|
||||
@@ -16,10 +16,22 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Task that makes a mob attack the player if within reach.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
public class EnemyPlayerAttackingTask extends MobRoomTask {
|
||||
private final Task task;
|
||||
|
||||
/**
|
||||
* Constructs an EnemyPlayerAttackingTask.
|
||||
*
|
||||
* @param updateRateMs Execution rate in milliseconds
|
||||
* @param reach Attack reach
|
||||
* @param damage Attack damage
|
||||
*/
|
||||
@JsonCreator
|
||||
public EnemyPlayerAttackingTask(
|
||||
@JsonProperty("updateRateMs") long updateRateMs,
|
||||
@@ -31,11 +43,17 @@ public class EnemyPlayerAttackingTask extends MobRoomTask {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setOwner(Mob mob) {
|
||||
task.setMob(mob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal task runnable logic.
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
private static class Task implements Runnable {
|
||||
private final double reach;
|
||||
@@ -52,6 +70,9 @@ public class EnemyPlayerAttackingTask extends MobRoomTask {
|
||||
@InjectDependency
|
||||
private DependencyManager dependencyManager;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
RoomCords playerCords = gameState.getPlayer().getPlayerCords();
|
||||
|
||||
@@ -29,10 +29,21 @@ import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Task that makes a mob follow the player using A* pathfinding.
|
||||
*
|
||||
* @author Jakub Žitník (jzitnik)
|
||||
*/
|
||||
@Slf4j
|
||||
public class MobFollowingPlayerTask extends MobRoomTask {
|
||||
private final Task task;
|
||||
|
||||
/**
|
||||
* Constructs a MobFollowingPlayerTask.
|
||||
*
|
||||
* @param speed Mob movement speed
|
||||
* @param updateRateMs Execution rate in milliseconds
|
||||
*/
|
||||
@JsonCreator
|
||||
public MobFollowingPlayerTask(
|
||||
@JsonProperty("speed") int speed,
|
||||
@@ -43,11 +54,17 @@ public class MobFollowingPlayerTask extends MobRoomTask {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setOwner(Mob mob) {
|
||||
task.setMob(mob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal task runnable logic.
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static class Task implements Runnable {
|
||||
private final int speed;
|
||||
@@ -71,6 +88,19 @@ public class MobFollowingPlayerTask extends MobRoomTask {
|
||||
@InjectConfig
|
||||
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) {
|
||||
RoomCords mobCords = mob.getCords();
|
||||
List<RoomPart> solidParts = gameState.getCurrentRoom().getColliders();
|
||||
@@ -112,6 +142,9 @@ public class MobFollowingPlayerTask extends MobRoomTask {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
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
Reference in New Issue
Block a user