feat: Multiplayer #3

Merged
jzitnik merged 14 commits from multiplayer into main 2026-02-04 10:37:42 +00:00
26 changed files with 322 additions and 92 deletions
Showing only changes of commit e3f5c12b43 - Show all commits

View File

@@ -3,18 +3,20 @@ package cz.jzitnik.common.socket.messages.game.connection;
import cz.jzitnik.common.models.player.PlayerCreation;
import cz.jzitnik.common.socket.SocketMessage;
public record ConnectToAGameResponse(ResponseType responseType, PlayerCreation playerCreation) implements SocketMessage {
import java.util.List;
public record ConnectToAGameResponse(ResponseType responseType, PlayerCreation playerCreation, List<PlayerCreation> existingPlayers) implements SocketMessage {
private enum ResponseType {
GAME_DOES_NOT_EXIST,
SUCCESS
}
public ConnectToAGameResponse() {
this(ResponseType.GAME_DOES_NOT_EXIST, null);
this(ResponseType.GAME_DOES_NOT_EXIST, null, null);
}
public ConnectToAGameResponse(PlayerCreation playerCreation) {
this(ResponseType.SUCCESS, playerCreation);
public ConnectToAGameResponse(PlayerCreation playerCreation, List<PlayerCreation> existingPlayers) {
this(ResponseType.SUCCESS, playerCreation, existingPlayers);
}
public boolean success() {

View File

@@ -0,0 +1,6 @@
package cz.jzitnik.common.socket.messages.player;
import cz.jzitnik.common.socket.SocketMessage;
public record PlayerArrivalChange(int id, boolean arrived) implements SocketMessage {
}

View File

@@ -0,0 +1,7 @@
package cz.jzitnik.common.socket.messages.player;
import cz.jzitnik.common.models.player.PlayerCreation;
import cz.jzitnik.common.socket.SocketMessage;
public record PlayerJoined(PlayerCreation playerCreation) implements SocketMessage {
}

View File

@@ -3,5 +3,5 @@ package cz.jzitnik.common.socket.messages.player;
import cz.jzitnik.common.models.coordinates.RoomCords;
import cz.jzitnik.common.socket.SocketMessage;
public record PlayerMove(RoomCords newCords) implements SocketMessage {
public record PlayerMove(RoomCords newCords, PlayerRotation playerRotation) implements SocketMessage {
}

View File

@@ -10,4 +10,5 @@ import lombok.Getter;
public class PlayerMovedInUrRoom implements SocketMessage {
private int playerId;
private RoomCords cords;
private PlayerRotation playerRotation;
}

View File

@@ -0,0 +1,5 @@
package cz.jzitnik.common.socket.messages.player;
public enum PlayerRotation {
FRONT, BACK, LEFT, RIGHT
}

View File

@@ -75,7 +75,7 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
int startX = start.getX();
int startY = start.getY();
RerenderUtils.rerenderPart(0, width - 1, 0, height - 1, startX, startY, currentRoom, room, player, playerTexture, screenBuffer, resourceManager, debugging);
RerenderUtils.rerenderPart(0, width - 1, 0, height - 1, startX, startY, currentRoom, room, player, screenBuffer, resourceManager, debugging, gameState.getOtherPlayers());
if (event.isFullRerender()) {
globalIOHandlerRepository.renderAll();
}

View File

@@ -177,10 +177,10 @@ public class MouseMoveEventHandler extends AbstractEventHandler<MouseMoveEvent>
currentRoom,
room,
player,
playerTexture,
screenBuffer,
resourceManager,
debugging
debugging,
gameState.getOtherPlayers()
);
parts.add(new RerenderScreen.ScreenPart(

View File

@@ -9,10 +9,7 @@ import cz.jzitnik.client.annotations.injectors.InjectState;
import cz.jzitnik.client.config.Debugging;
import cz.jzitnik.client.config.PlayerConfig;
import cz.jzitnik.client.events.*;
import cz.jzitnik.client.game.GameRoom;
import cz.jzitnik.client.game.GameState;
import cz.jzitnik.client.game.Player;
import cz.jzitnik.client.game.ResourceManager;
import cz.jzitnik.client.game.*;
import cz.jzitnik.common.models.coordinates.RoomCords;
import cz.jzitnik.client.states.RenderState;
import cz.jzitnik.client.states.ScreenBuffer;
@@ -24,6 +21,7 @@ import cz.jzitnik.client.utils.events.AbstractEventHandler;
import cz.jzitnik.client.utils.events.Event;
import cz.jzitnik.client.utils.events.EventManager;
import cz.jzitnik.common.socket.messages.player.PlayerMove;
import cz.jzitnik.common.socket.messages.player.PlayerRotation;
import lombok.extern.slf4j.Slf4j;
import java.awt.image.BufferedImage;
@@ -77,46 +75,46 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
case 'w' -> {
if (originalPlayerY <= 10) {
if (originalPlayerX >= 80 && originalPlayerX <= 105) {
player.setPlayerRotation(Player.PlayerRotation.BACK);
player.setPlayerRotation(PlayerRotation.BACK);
eventManager.emitEvent(new RoomChangeEvent(FullRoomDrawHandler.DoorPosition.TOP));
}
return;
}
playerCords.updateCordsWithColliders(currentRoom.getColliders(), player.getPlayerCords().getX(), playerCords.getY() - moveStep, player.getCollider());
player.setPlayerRotation(Player.PlayerRotation.BACK);
player.setPlayerRotation(PlayerRotation.BACK);
}
case 'a' -> {
if (originalPlayerX <= 30) {
if (originalPlayerY >= 35 && originalPlayerY <= 65) {
player.setPlayerRotation(Player.PlayerRotation.LEFT);
player.setPlayerRotation(PlayerRotation.LEFT);
eventManager.emitEvent(new RoomChangeEvent(FullRoomDrawHandler.DoorPosition.LEFT));
}
return;
}
playerCords.updateCordsWithColliders(currentRoom.getColliders(), player.getPlayerCords().getX() - moveStep, playerCords.getY(), player.getCollider());
player.setPlayerRotation(Player.PlayerRotation.LEFT);
player.setPlayerRotation(PlayerRotation.LEFT);
}
case 's' -> {
if (originalPlayerY >= 110) {
if (originalPlayerX >= 75 && originalPlayerX <= 105) {
player.setPlayerRotation(Player.PlayerRotation.FRONT);
player.setPlayerRotation(PlayerRotation.FRONT);
eventManager.emitEvent(new RoomChangeEvent(FullRoomDrawHandler.DoorPosition.BOTTOM));
}
return;
}
playerCords.updateCordsWithColliders(currentRoom.getColliders(), player.getPlayerCords().getX(), playerCords.getY() + moveStep, player.getCollider());
player.setPlayerRotation(Player.PlayerRotation.FRONT);
player.setPlayerRotation(PlayerRotation.FRONT);
}
case 'd' -> {
if (originalPlayerX >= 155) {
if (originalPlayerY >= 40 && originalPlayerY <= 60) {
player.setPlayerRotation(Player.PlayerRotation.RIGHT);
player.setPlayerRotation(PlayerRotation.RIGHT);
eventManager.emitEvent(new RoomChangeEvent(FullRoomDrawHandler.DoorPosition.RIGHT));
}
return;
}
playerCords.updateCordsWithColliders(currentRoom.getColliders(), player.getPlayerCords().getX() + moveStep, playerCords.getY(), player.getCollider());
player.setPlayerRotation(Player.PlayerRotation.RIGHT);
player.setPlayerRotation(PlayerRotation.RIGHT);
}
}
playerMovementState.setLastMovement(System.currentTimeMillis());
@@ -141,10 +139,10 @@ public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent
int startX = start.getX();
int startY = start.getY();
RerenderUtils.rerenderPart(forStartX, forEndX, forStartY, forEndY, startX, startY, currentRoom, room, player, playerTexture, screenBuffer, resourceManager, debugging);
RerenderUtils.rerenderPart(forStartX, forEndX, forStartY, forEndY, startX, startY, currentRoom, room, player, screenBuffer, resourceManager, debugging, gameState.getOtherPlayers());
eventManager.emitEvent(new Event[]{
new SendSocketMessageEvent(new PlayerMove(playerCords)),
new SendSocketMessageEvent(new PlayerMove(playerCords, player.getPlayerRotation())),
new MouseMoveEvent(null),
new RerenderScreen(
new RerenderScreen.ScreenPart[]{

View File

@@ -62,10 +62,10 @@ public class RerenderPartHandler extends AbstractEventHandler<RerenderPart> {
currentRoom,
room,
gameState.getPlayer(),
gameState.getPlayer().getTexture(resourceManager),
screenBuffer,
resourceManager,
debugging
debugging,
gameState.getOtherPlayers()
);
eventManager.emitEvent(

View File

@@ -0,0 +1,10 @@
package cz.jzitnik.client.game;
import cz.jzitnik.common.models.coordinates.RoomCords;
import java.awt.image.BufferedImage;
public interface GamePlayer {
RoomCords getPlayerCords();
BufferedImage getTexture(ResourceManager resourceManager);
}

View File

@@ -24,9 +24,16 @@ public class GameState {
@Setter
private Player player;
@Getter
private final List<OtherPlayer> otherPlayers = new ArrayList<>();
public List<OtherPlayer> getOtherPlayers() {
return otherPlayers.stream().filter(OtherPlayer::isVisible).toList();
}
public List<OtherPlayer> getAllOtherPlayers() {
return otherPlayers;
}
@Getter
@Setter
private Interactable interacting;

View File

@@ -1,20 +1,41 @@
package cz.jzitnik.client.game;
import cz.jzitnik.client.game.mobs.HittableMob;
import cz.jzitnik.common.models.coordinates.RoomCords;
import cz.jzitnik.common.models.player.PlayerCreation;
import cz.jzitnik.common.socket.messages.player.PlayerRotation;
import lombok.Getter;
import lombok.Setter;
import java.awt.image.BufferedImage;
@Getter
public class OtherPlayer {
public class OtherPlayer implements GamePlayer {
private final int id;
private boolean hitAnimationOn = false;
private final RoomCords playerCords;
@Setter
private Player.PlayerRotation playerRotation = Player.PlayerRotation.FRONT;
private PlayerRotation playerRotation = PlayerRotation.FRONT;
@Setter
private boolean visible;
public OtherPlayer(PlayerCreation playerCreation) {
this.id = playerCreation.getId();
this.playerCords = playerCreation.getPlayerCords();
}
public BufferedImage getTexture(ResourceManager resourceManager) {
BufferedImage resource = resourceManager.getResource(switch (playerRotation) {
case FRONT -> ResourceManager.Resource.PLAYER_FRONT;
case BACK -> ResourceManager.Resource.PLAYER_BACK;
case LEFT -> ResourceManager.Resource.PLAYER_LEFT;
case RIGHT -> ResourceManager.Resource.PLAYER_RIGHT;
});
if (hitAnimationOn) {
return HittableMob.applyRedFactor(resource);
}
return resource;
}
}

View File

@@ -11,6 +11,7 @@ import cz.jzitnik.client.utils.DependencyManager;
import cz.jzitnik.client.utils.events.Event;
import cz.jzitnik.client.utils.events.EventManager;
import cz.jzitnik.common.models.player.PlayerCreation;
import cz.jzitnik.common.socket.messages.player.PlayerRotation;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@@ -23,7 +24,7 @@ import java.util.concurrent.TimeUnit;
@Getter
@Slf4j
public class Player {
public class Player implements GamePlayer {
private final int id;
public static final int MAX_STAMINA = 20;
public static final int MAX_HEALTH = 30;
@@ -155,7 +156,4 @@ public class Player {
}, delayMs, TimeUnit.MILLISECONDS);
}
public enum PlayerRotation {
FRONT, BACK, LEFT, RIGHT
}
}

View File

@@ -96,7 +96,7 @@ public class MobFollowingPlayerTask extends MobRoomTask {
Player player = gameState.getPlayer();
BufferedImage playerTexture = player.getTexture(resourceManager);
RerenderUtils.rerenderPart(forStartX, forEndX, forStartY, forEndY, startX, startY, gameState.getCurrentRoom(), room, player, playerTexture, screenBuffer, resourceManager, debugging);
RerenderUtils.rerenderPart(forStartX, forEndX, forStartY, forEndY, startX, startY, gameState.getCurrentRoom(), room, player, screenBuffer, resourceManager, debugging, gameState.getOtherPlayers());
eventManager.emitEvent(new Event[]{
new MouseMoveEvent(null),

View File

@@ -101,7 +101,6 @@ public final class Chest extends GameObject implements UIClickHandler {
Player player = gameState.getPlayer();
BufferedImage roomTexture = resourceManager.getResource(currentRoom.getTexture());
BufferedImage playerTexture = player.getTexture(resourceManager);
BufferedImage chestTexture = getTexture();
var buffer = screenBuffer.getRenderedBuffer();
@@ -141,7 +140,7 @@ public final class Chest extends GameObject implements UIClickHandler {
renderMaxX = Math.max(renderMaxX, prevDisplayStartX + prevWidth);
clearPreviousUI(
currentRoom, roomTexture, player, playerTexture,
currentRoom, roomTexture, player, resourceManager,
buffer, overrideBuffer, start,
guiStartY,
prevGuiStartX,
@@ -171,7 +170,7 @@ public final class Chest extends GameObject implements UIClickHandler {
GameRoom room,
BufferedImage roomTexture,
Player player,
BufferedImage playerTexture,
ResourceManager resourceManager,
Pixel[][] buffer,
Pixel[][] overrideBuffer,
RoomCords start,
@@ -188,10 +187,11 @@ public final class Chest extends GameObject implements UIClickHandler {
null,
new HashSet<>(),
player,
playerTexture,
resourceManager,
x,
y,
debugging
debugging,
gameState.getOtherPlayers()
).pixel();
buffer[y + start.getY()][x + start.getX()] = pixelToColored(pixel);

View File

@@ -3,10 +3,12 @@ package cz.jzitnik.client.socket.events;
import cz.jzitnik.client.annotations.SocketEventHandler;
import cz.jzitnik.client.annotations.injectors.InjectDependency;
import cz.jzitnik.client.annotations.injectors.InjectState;
import cz.jzitnik.client.events.FullRoomDraw;
import cz.jzitnik.client.events.TerminalResizeEvent;
import cz.jzitnik.client.game.GameState;
import cz.jzitnik.client.game.OtherPlayer;
import cz.jzitnik.client.game.Player;
import cz.jzitnik.client.socket.AbstractSocketEventHandler;
import cz.jzitnik.client.states.TerminalState;
import cz.jzitnik.client.utils.events.EventManager;
import cz.jzitnik.common.socket.messages.game.connection.ConnectToAGameResponse;
import lombok.extern.slf4j.Slf4j;
@@ -18,6 +20,8 @@ public class ConnectGameHandler extends AbstractSocketEventHandler<ConnectToAGam
private GameState gameState;
@InjectDependency
private EventManager eventManager;
@InjectState
private TerminalState terminalState;
@Override
public void handle(ConnectToAGameResponse event) {
@@ -27,7 +31,8 @@ public class ConnectGameHandler extends AbstractSocketEventHandler<ConnectToAGam
}
gameState.setPlayer(new Player(event.playerCreation()));
gameState.getAllOtherPlayers().addAll(event.existingPlayers().stream().map(OtherPlayer::new).toList());
gameState.setScreen(null);
eventManager.emitEvent(new FullRoomDraw());
eventManager.emitEvent(new TerminalResizeEvent(terminalState.getTerminalScreen().getTerminalSize()));
}
}

View File

@@ -0,0 +1,24 @@
package cz.jzitnik.client.socket.events;
import cz.jzitnik.client.annotations.SocketEventHandler;
import cz.jzitnik.client.annotations.injectors.InjectState;
import cz.jzitnik.client.game.GameState;
import cz.jzitnik.client.game.OtherPlayer;
import cz.jzitnik.client.socket.AbstractSocketEventHandler;
import cz.jzitnik.common.socket.messages.player.PlayerArrivalChange;
@SocketEventHandler(PlayerArrivalChange.class)
public class PlayerArrivalChangeHandler extends AbstractSocketEventHandler<PlayerArrivalChange> {
@InjectState
private GameState gameState;
@Override
public void handle(PlayerArrivalChange event) {
var allPlayers = gameState.getAllOtherPlayers();
for (OtherPlayer player : allPlayers) {
if (player.getId() == event.id()) {
player.setVisible(event.arrived());
}
}
}
}

View File

@@ -0,0 +1,22 @@
package cz.jzitnik.client.socket.events;
import cz.jzitnik.client.annotations.SocketEventHandler;
import cz.jzitnik.client.annotations.injectors.InjectState;
import cz.jzitnik.client.game.GameState;
import cz.jzitnik.client.game.OtherPlayer;
import cz.jzitnik.client.socket.AbstractSocketEventHandler;
import cz.jzitnik.common.socket.messages.player.PlayerJoined;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@SocketEventHandler(PlayerJoined.class)
public class PlayerJoinedHandler extends AbstractSocketEventHandler<PlayerJoined> {
@InjectState
private GameState gameState;
@Override
public void handle(PlayerJoined event) {
log.debug("Player joined: {}", event.playerCreation().getId());
gameState.getAllOtherPlayers().add(new OtherPlayer(event.playerCreation()));
}
}

View File

@@ -0,0 +1,94 @@
package cz.jzitnik.client.socket.events;
import com.googlecode.lanterna.TerminalPosition;
import cz.jzitnik.client.annotations.SocketEventHandler;
import cz.jzitnik.client.annotations.injectors.InjectConfig;
import cz.jzitnik.client.annotations.injectors.InjectDependency;
import cz.jzitnik.client.annotations.injectors.InjectState;
import cz.jzitnik.client.config.Debugging;
import cz.jzitnik.client.events.MouseMoveEvent;
import cz.jzitnik.client.events.RerenderScreen;
import cz.jzitnik.client.game.GameRoom;
import cz.jzitnik.client.game.GameState;
import cz.jzitnik.client.game.OtherPlayer;
import cz.jzitnik.client.game.ResourceManager;
import cz.jzitnik.client.socket.AbstractSocketEventHandler;
import cz.jzitnik.client.states.ScreenBuffer;
import cz.jzitnik.client.states.TerminalState;
import cz.jzitnik.client.ui.Stats;
import cz.jzitnik.client.utils.RerenderUtils;
import cz.jzitnik.client.utils.events.Event;
import cz.jzitnik.client.utils.events.EventManager;
import cz.jzitnik.common.socket.messages.player.PlayerMovedInUrRoom;
import lombok.extern.slf4j.Slf4j;
import java.awt.image.BufferedImage;
@Slf4j
@SocketEventHandler(PlayerMovedInUrRoom.class)
public class PlayerMovedInUrRoomHandler extends AbstractSocketEventHandler<PlayerMovedInUrRoom> {
@InjectState
private GameState gameState;
@InjectDependency
private EventManager eventManager;
@InjectDependency
private ResourceManager resourceManager;
@InjectState
private ScreenBuffer screenBuffer;
@InjectConfig
private Debugging debugging;
@InjectState
private TerminalState terminalState;
@Override
public void handle(PlayerMovedInUrRoom event) {
log.debug("Player moved: {}", event.getPlayerId());
OtherPlayer otherPlayer = gameState.getAllOtherPlayers().stream().filter(otherPlayer1 -> otherPlayer1.getId() == event.getPlayerId()).findFirst().get();
otherPlayer.setPlayerRotation(event.getPlayerRotation());
var oldCords = otherPlayer.getPlayerCords();
var newCords = event.getCords();
GameRoom currentRoom = gameState.getCurrentRoom();
BufferedImage playerTexture = otherPlayer.getTexture(resourceManager);
BufferedImage room = resourceManager.getResource(currentRoom.getTexture());
int originalPlayerX = oldCords.getX();
int originalPlayerY = oldCords.getY();
int newPlayerX = newCords.getX();
int newPlayerY = newCords.getY();
int forStartX = Math.min(originalPlayerX, newPlayerX);
int forStartY = Math.min(originalPlayerY, newPlayerY);
int forEndX = Math.max(originalPlayerX, newPlayerX) + playerTexture.getWidth();
int forEndY = Math.max(originalPlayerY, newPlayerY) + playerTexture.getHeight();
var start = RerenderUtils.getStart(room, terminalState.getTerminalScreen().getTerminalSize());
int startX = start.getX();
int startY = start.getY();
otherPlayer.getPlayerCords().updateCords(newCords);
RerenderUtils.rerenderPart(forStartX, forEndX, forStartY, forEndY, startX, startY, currentRoom, room, gameState.getPlayer(), screenBuffer, resourceManager, debugging, gameState.getOtherPlayers());
eventManager.emitEvent(new Event[]{
new MouseMoveEvent(null),
new RerenderScreen(
new RerenderScreen.ScreenPart[]{
new RerenderScreen.ScreenPart(
new TerminalPosition(forStartX + startX, forStartY + startY),
new TerminalPosition(forEndX + 1 + startX, forEndY + startY)
),
new RerenderScreen.ScreenPart(
new TerminalPosition(Stats.OFFSET_X, Stats.OFFSET_X),
new TerminalPosition(Stats.OFFSET_X + Stats.WIDTH, Stats.OFFSET_Y + Stats.HEIGHT)
)
}
)
});
}
}

View File

@@ -4,9 +4,7 @@ import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.TextColor;
import cz.jzitnik.client.config.Debugging;
import cz.jzitnik.client.events.handlers.FullRoomDrawHandler;
import cz.jzitnik.client.game.GameRoom;
import cz.jzitnik.client.game.Player;
import cz.jzitnik.client.game.ResourceManager;
import cz.jzitnik.client.game.*;
import cz.jzitnik.client.game.mobs.Mob;
import cz.jzitnik.client.game.objects.DroppedItem;
import cz.jzitnik.client.game.objects.GameObject;
@@ -19,8 +17,11 @@ import lombok.extern.slf4j.Slf4j;
import java.awt.image.BufferedImage;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Slf4j
public class RerenderUtils {
@@ -36,14 +37,14 @@ public class RerenderUtils {
return new RoomCords(x, y);
}
public static void rerenderPart(int startX, int endX, int startY, int endY, int screenStartX, int screenStartY, GameRoom currentRoom, BufferedImage room, Player player, BufferedImage playerTexture, ScreenBuffer screenBuffer, ResourceManager resourceManager, Debugging debugging) {
public static void rerenderPart(int startX, int endX, int startY, int endY, int screenStartX, int screenStartY, GameRoom currentRoom, BufferedImage room, Player player, ScreenBuffer screenBuffer, ResourceManager resourceManager, Debugging debugging, List<OtherPlayer> otherPlayers) {
var buffer = screenBuffer.getRenderedBuffer();
var overrideBuffer = currentRoom.getOverrideBuffer();
BufferedImage doors = resourceManager.getResource(ResourceManager.Resource.DOORS);
Set<FullRoomDrawHandler.DoorPosition> doorPositions = RerenderUtils.getDoorPositions(currentRoom);
for (int x = startX; x <= endX; x++) {
for (int y = startY; y <= endY; y++) {
PixelResult pixelResult = getPixel(currentRoom, room, doors, doorPositions, player, playerTexture, x, y, debugging);
PixelResult pixelResult = getPixel(currentRoom, room, doors, doorPositions, player, resourceManager, x, y, debugging, otherPlayers);
int pixel = pixelResult.pixel();
int red = (pixel >> 16) & 0xff;
@@ -63,26 +64,34 @@ public class RerenderUtils {
public record PixelResult(int pixel, boolean isPlayer) {
}
public static PixelResult getPixel(GameRoom currentRoom, BufferedImage room, BufferedImage doors, Set<FullRoomDrawHandler.DoorPosition> doorPositions, Player player, BufferedImage playerTexture, int x, int y, Debugging debugging) {
public static PixelResult getPixel(GameRoom currentRoom, BufferedImage room, BufferedImage doors, Set<FullRoomDrawHandler.DoorPosition> doorPositions, Player player, ResourceManager resourceManager, int x, int y, Debugging debugging, List<OtherPlayer> visiblePlayer) {
float factor = 1.5f; // brightness multiplier
if (debugging.renderColliders() && currentRoom.getColliders().stream().anyMatch(collider -> collider.isWithin(new RoomCords(x, y)))) {
return new PixelResult(0xFFFF0000, false);
}
if (x >= player.getPlayerCords().getX() && x < player.getPlayerCords().getX() + playerTexture.getWidth() - 1 && y >= player.getPlayerCords().getY() && y <= player.getPlayerCords().getY() + playerTexture.getHeight() - 1) {
int relativeX = x - player.getPlayerCords().getX();
int relativeY = y - player.getPlayerCords().getY();
var playerCollider = player.getCollider();
List<GamePlayer> players = Stream.concat(
Stream.of(player),
visiblePlayer.stream()
).toList();
if (debugging.renderPlayerCollider() && playerCollider.isWithin(new RoomCords(relativeX, relativeY))) {
return new PixelResult(0xFFFF0000, false);
}
var playerCollider = player.getCollider();
for (GamePlayer player1 : players) {
var playerTexture = player1.getTexture(resourceManager);
if (x >= player1.getPlayerCords().getX() && x < player1.getPlayerCords().getX() + playerTexture.getWidth() - 1 && y >= player1.getPlayerCords().getY() && y <= player1.getPlayerCords().getY() + playerTexture.getHeight() - 1) {
int relativeX = x - player1.getPlayerCords().getX();
int relativeY = y - player1.getPlayerCords().getY();
int pixel = playerTexture.getRGB(relativeX, relativeY);
int alpha = (pixel >> 24) & 0xff;
if (debugging.renderPlayerCollider() && playerCollider.isWithin(new RoomCords(relativeX, relativeY))) {
return new PixelResult(0xFFFF0000, false);
}
if (alpha != 0) {
return new PixelResult(pixel, true);
int pixel = playerTexture.getRGB(relativeX, relativeY);
int alpha = (pixel >> 24) & 0xff;
if (alpha != 0) {
return new PixelResult(pixel, true);
}
}
}

View File

@@ -1,33 +1,33 @@
- id: "spawn"
texture: "ROOM1"
mobs:
- type: "hittable_drops"
texture: "PLAYER_FRONT"
cords:
x: 100
y: 100
collider:
start:
x: 0
y: 52
end:
x: 44
y: 78
health: 10
itemsDrops:
- name: "Apple"
type:
name: "food"
addHealth: 1
texture: "APPLE"
tasks:
- type: "blind_following_player"
speed: 1
updateRateMs: 100
- type: "attacking_player"
damage: 5
reach: 15
updateRateMs: 500
#mobs:
# - type: "hittable_drops"
# texture: "PLAYER_FRONT"
# cords:
# x: 100
# y: 100
# collider:
# start:
# x: 0
# y: 52
# end:
# x: 44
# y: 78
# health: 10
# itemsDrops:
# - name: "Apple"
# type:
# name: "food"
# addHealth: 1
# texture: "APPLE"
# tasks:
# - type: "blind_following_player"
# speed: 1
# updateRateMs: 100
# - type: "attacking_player"
# damage: 5
# reach: 15
# updateRateMs: 500
west: "empty"
east: "truhlaright"
north: null

View File

@@ -3,6 +3,8 @@ package cz.jzitnik.server.events.handlers;
import cz.jzitnik.common.models.player.PlayerCreation;
import cz.jzitnik.common.socket.messages.game.connection.ConnectToAGame;
import cz.jzitnik.common.socket.messages.game.connection.ConnectToAGameResponse;
import cz.jzitnik.common.socket.messages.player.PlayerArrivalChange;
import cz.jzitnik.common.socket.messages.player.PlayerJoined;
import cz.jzitnik.server.annotations.EventHandler;
import cz.jzitnik.server.context.GlobalContext;
import cz.jzitnik.server.events.AbstractEventHandler;
@@ -35,12 +37,23 @@ public class ConnectToAGameHandler extends AbstractEventHandler<ConnectToAGame>
ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
ObjectReader playerReader = objectMapper.readerFor(PlayerCreation.class);
PlayerCreation player = playerReader.readValue(getClass().getClassLoader().getResourceAsStream("setup/player.yaml"));
client.setPlayer(new Player(game.getPlayers().size(), player.getPlayerCords()));
player.setId(game.getPlayers().size());
client.setPlayer(new Player(player));
client.setGame(game);
client.getPlayer().setCurrentRoom(globalContext.getProperties().getProperty("rooms.default"));
String defaultRoomId = globalContext.getProperties().getProperty("rooms.default");
client.getPlayer().setCurrentRoom(defaultRoomId);
client.getSession().sendMessage(new ConnectToAGameResponse(player, game.getPlayers().stream().map(client1 -> client1.getPlayer().toPlayerCreation()).toList()));
for (Client cl : game.getPlayers()) {
cl.getSession().sendMessage(new PlayerJoined(player));
if (cl.getPlayer().getCurrentRoom().equals(defaultRoomId)) {
cl.getSession().sendMessage(new PlayerArrivalChange(client.getPlayer().getId(), true));
client.getSession().sendMessage(new PlayerArrivalChange(cl.getPlayer().getId(), true));
}
}
game.getPlayers().add(client);
client.getSession().sendMessage(new ConnectToAGameResponse(player));
}
}

View File

@@ -35,7 +35,7 @@ public class CreateGameHandler extends AbstractEventHandler<CreateGame> {
PlayerCreation player = playerReader.readValue(getClass().getClassLoader().getResourceAsStream("setup/player.yaml"));
player.setId(id);
client.setPlayer(new Player(id, player.getPlayerCords()));
client.setPlayer(new Player(player));
CreateGameResponse gameResponse = new CreateGameResponse(pass, player);
Game game = new Game(

View File

@@ -19,7 +19,7 @@ public class PlayerMoveHandler extends AbstractEventHandler<PlayerMove> {
for (Client player : client.getGame().getPlayers()) {
if (player.getPlayer().getCurrentRoom().equals(client.getPlayer().getCurrentRoom()) && player.getPlayer().getId() != client.getPlayer().getId()) {
player.getSession().sendMessage(new PlayerMovedInUrRoom(client.getPlayer().getId(), event.newCords()));
player.getSession().sendMessage(new PlayerMovedInUrRoom(client.getPlayer().getId(), event.newCords(), event.playerRotation()));
}
}
}

View File

@@ -1,15 +1,23 @@
package cz.jzitnik.server.game;
import cz.jzitnik.common.models.coordinates.RoomCords;
import cz.jzitnik.common.models.player.PlayerCreation;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@Getter
@RequiredArgsConstructor
public class Player {
private final int id;
private final RoomCords cords;
@Setter
private String currentRoom;
public Player(PlayerCreation creation) {
id = creation.getId();
cords = creation.getPlayerCords();
}
public PlayerCreation toPlayerCreation() {
return new PlayerCreation(cords, null);
}
}