feat: Multiplayer (#3)
Reviewed-on: https://gitea.local.jzitnik.dev/jzitnik/game/pulls/3 Co-authored-by: jzitnik-dev <email@jzitnik.dev> Co-committed-by: jzitnik-dev <email@jzitnik.dev>
This commit is contained in:
39
common/.gitignore
vendored
Normal file
39
common/.gitignore
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
.kotlin
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
3
common/.idea/.gitignore
generated
vendored
Normal file
3
common/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
7
common/.idea/encodings.xml
generated
Normal file
7
common/.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
14
common/.idea/misc.xml
generated
Normal file
14
common/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" default="true" project-jdk-name="openjdk-25" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
6
common/.idea/vcs.xml
generated
Normal file
6
common/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
63
common/pom.xml
Normal file
63
common/pom.xml
Normal file
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>cz.jzitnik</groupId>
|
||||
<artifactId>game-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>common</artifactId>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.42</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<source>25</source>
|
||||
<target>25</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>tools.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>3.0.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>tools.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-yaml</artifactId>
|
||||
<version>3.0.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.42</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>2.0.17</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
5
common/src/main/java/cz/jzitnik/common/Config.java
Normal file
5
common/src/main/java/cz/jzitnik/common/Config.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package cz.jzitnik.common;
|
||||
|
||||
public class Config {
|
||||
public static final int WORLD_PASSWORD_LENGTH = 5;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package cz.jzitnik.common.models.coordinates;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@ToString
|
||||
@Getter
|
||||
public class RoomCords implements Cloneable, Serializable {
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
@JsonCreator
|
||||
public RoomCords(
|
||||
@JsonProperty("x") int x,
|
||||
@JsonProperty("y") int y
|
||||
) {
|
||||
updateCords(x, y);
|
||||
}
|
||||
|
||||
public void updateCords(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public void updateCords(RoomCords roomCords) {
|
||||
updateCords(roomCords.getX(), roomCords.getY());
|
||||
}
|
||||
|
||||
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),
|
||||
new RoomCords(playerCollider.getEnd().getX() + x, playerCollider.getEnd().getY() + y)
|
||||
);
|
||||
|
||||
if (colliders.stream().anyMatch(collider -> collider.isOverlapping(normalizedPlayerCollider))) {
|
||||
return;
|
||||
}
|
||||
updateCords(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoomCords clone() {
|
||||
try {
|
||||
return (RoomCords) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the Euclidean distance between this coordinate and another.
|
||||
*
|
||||
* @param other The other RoomCords instance
|
||||
* @return The distance as a double
|
||||
*/
|
||||
public double calculateDistance(RoomCords other) {
|
||||
if (other == null) {
|
||||
throw new IllegalArgumentException("Cannot calculate distance to null");
|
||||
}
|
||||
return Math.hypot(this.x - other.x, this.y - other.y);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package cz.jzitnik.common.models.coordinates;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
public class RoomPart implements Serializable {
|
||||
private RoomCords start;
|
||||
private RoomCords end;
|
||||
|
||||
@JsonCreator
|
||||
public RoomPart(
|
||||
@JsonProperty("start") RoomCords start,
|
||||
@JsonProperty("end") RoomCords end
|
||||
) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public boolean isWithin(RoomCords cords) {
|
||||
return cords.getX() >= start.getX() &&
|
||||
cords.getX() <= end.getX() &&
|
||||
cords.getY() >= start.getY() &&
|
||||
cords.getY() <= end.getY();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this GameRoomPart overlaps with another.
|
||||
*/
|
||||
public boolean isOverlapping(RoomPart other) {
|
||||
return start.getX() <= other.getEnd().getX() &&
|
||||
end.getX() >= other.getStart().getX() &&
|
||||
start.getY() <= other.getEnd().getY() &&
|
||||
end.getY() >= other.getStart().getY();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cz.jzitnik.common.models.player;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import cz.jzitnik.common.models.coordinates.RoomCords;
|
||||
import cz.jzitnik.common.models.coordinates.RoomPart;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Getter
|
||||
public final class PlayerCreation implements Serializable {
|
||||
@Setter
|
||||
private int id;
|
||||
private final RoomCords playerCords;
|
||||
private final RoomPart collider;
|
||||
|
||||
@JsonCreator
|
||||
public PlayerCreation(
|
||||
@JsonProperty("playerCords") RoomCords playerCords,
|
||||
@JsonProperty("collider") RoomPart collider
|
||||
) {
|
||||
this.playerCords = playerCords;
|
||||
this.collider = collider;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package cz.jzitnik.common.socket;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface SocketMessage extends Serializable {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package cz.jzitnik.common.socket.messages;
|
||||
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
public class Test implements SocketMessage {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package cz.jzitnik.common.socket.messages.game.connection;
|
||||
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
public record ConnectToAGame(String gamePass) implements SocketMessage {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cz.jzitnik.common.socket.messages.game.connection;
|
||||
|
||||
import cz.jzitnik.common.models.player.PlayerCreation;
|
||||
import cz.jzitnik.common.socket.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, null);
|
||||
}
|
||||
|
||||
public ConnectToAGameResponse(PlayerCreation playerCreation, List<PlayerCreation> existingPlayers) {
|
||||
this(ResponseType.SUCCESS, playerCreation, existingPlayers);
|
||||
}
|
||||
|
||||
public boolean success() {
|
||||
return responseType == ResponseType.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package cz.jzitnik.common.socket.messages.game.creation;
|
||||
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
public class CreateGame implements SocketMessage {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package cz.jzitnik.common.socket.messages.game.creation;
|
||||
|
||||
import cz.jzitnik.common.models.player.PlayerCreation;
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class CreateGameResponse implements SocketMessage {
|
||||
private final String gamePassword;
|
||||
private final PlayerCreation ownerPlayer;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cz.jzitnik.common.socket.messages.items;
|
||||
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
public record ItemTookFromChest(
|
||||
String roomId, // For faster lookup i guess
|
||||
int id
|
||||
) implements SocketMessage {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package cz.jzitnik.common.socket.messages.player;
|
||||
|
||||
import cz.jzitnik.common.models.coordinates.RoomCords;
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
public record PlayerArrivalChange(int id, RoomCords playerCords, PlayerRotation playerRotation,
|
||||
boolean arrived, boolean rerender) implements SocketMessage {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package cz.jzitnik.common.socket.messages.player;
|
||||
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
public record PlayerDisconnected(int playerId) implements SocketMessage {
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
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, PlayerRotation playerRotation) implements SocketMessage {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package cz.jzitnik.common.socket.messages.player;
|
||||
|
||||
import cz.jzitnik.common.models.coordinates.RoomCords;
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class PlayerMovedInUrRoom implements SocketMessage {
|
||||
private int playerId;
|
||||
private RoomCords cords;
|
||||
private PlayerRotation playerRotation;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package cz.jzitnik.common.socket.messages.player;
|
||||
|
||||
public enum PlayerRotation {
|
||||
FRONT, BACK, LEFT, RIGHT
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package cz.jzitnik.common.socket.messages.room;
|
||||
|
||||
import cz.jzitnik.common.models.coordinates.RoomCords;
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
|
||||
public record MovePlayerRoom(String newRoomId, RoomCords oldCords, RoomCords newCords) implements SocketMessage {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cz.jzitnik.common.socket.messages.room;
|
||||
|
||||
import cz.jzitnik.common.models.coordinates.RoomCords;
|
||||
import cz.jzitnik.common.socket.SocketMessage;
|
||||
import cz.jzitnik.common.socket.messages.player.PlayerRotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public record MovePlayerRoomResponse(Set<Registry> players) implements SocketMessage {
|
||||
public record Registry(int id, RoomCords cords, PlayerRotation playerRotation) implements Serializable {}
|
||||
|
||||
public Optional<Registry> getById(int id) {
|
||||
return players.stream().filter(registry -> registry.id == id).findFirst();
|
||||
}
|
||||
|
||||
public Set<Integer> getIds() {
|
||||
return players.stream().map(Registry::id).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user