Skip to content

Commit 7fd2c32

Browse files
committed
Added room type game logic, refactored matchmaking
1 parent 392a9c6 commit 7fd2c32

18 files changed

Lines changed: 196 additions & 50 deletions

File tree

example/src/main/java/io/github/tfkfan/orbital/core/model/DefaultPlayer.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ public class DefaultPlayer extends BasePlayer<Vector2D> {
2222
protected Map<Direction, Boolean> movingState;
2323
Double ABS_PLAYER_SPEED = 5.0;
2424

25-
public DefaultPlayer(Long id, GameRoom gameRoom, PlayerSession userSession, JsonObject inputData) {
25+
public DefaultPlayer(Long id,
26+
GameRoom gameRoom,
27+
PlayerSession userSession,
28+
JsonObject inputData) {
2629
super(id, gameRoom, userSession);
2730
movingState = Arrays.stream(Direction.values())
2831
.collect(Collectors.toMap(direction -> direction, t -> false));

example/src/main/java/io/github/tfkfan/orbital/core/room/DefaultGameRoom.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,33 @@
33
import io.github.tfkfan.orbital.core.configuration.props.RoomConfig;
44
import io.github.tfkfan.orbital.core.event.KeyDownPlayerEvent;
55
import io.github.tfkfan.orbital.core.manager.GameManager;
6+
import io.github.tfkfan.orbital.core.math.Vector2D;
7+
import io.github.tfkfan.orbital.core.math.random.Random;
8+
import io.github.tfkfan.orbital.core.math.random.RandomBiInitializer;
9+
import io.github.tfkfan.orbital.core.math.random.RandomInitializer;
610
import io.github.tfkfan.orbital.core.model.DefaultPlayer;
711
import io.github.tfkfan.orbital.core.session.PlayerSession;
812
import io.github.tfkfan.orbital.core.state.GameState;
913

14+
import java.util.Collection;
15+
import java.util.List;
1016
import java.util.UUID;
1117

1218
public class DefaultGameRoom extends AbstractGameRoom<GameState> {
1319

14-
public DefaultGameRoom(String verticleId, UUID gameRoomId,
20+
public DefaultGameRoom(String verticleId, UUID gameRoomId, RoomType roomType,
1521
GameState state,
1622
GameManager gameManager,
1723
RoomConfig roomConfig) {
18-
super(state, verticleId, gameRoomId, gameManager, roomConfig);
24+
super(state, verticleId, gameRoomId, roomType, gameManager, roomConfig);
25+
}
26+
27+
@Override
28+
public void onJoin(PlayerSession playerSession) {
29+
super.onJoin(playerSession);
30+
final DefaultPlayer player = (DefaultPlayer) playerSession.getPlayer();
31+
if (player.isNpc())
32+
player.setPosition(Random.getRandomVector2D(0, 1000));
1933
}
2034

2135
@Override

example/src/main/resources/application.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ server:
22
port: 8085
33
roomVerticleInstances: 5
44
room:
5-
maxPlayers: 1
5+
maxPlayers: 10
66
loopRate: 50
77
initDelay: 1
88
startDelay: 5000

example/src/main/resources/static/app.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ function clear() {
3939
function drawPlayers() {
4040
for (let i in players) {
4141
let p = players[i];
42-
fillCircle(p.position.x, p.position.y, "black", 50);
42+
const color = selfId !== p.id ? "red" : "black";
43+
fillCircle(p.position.x, p.position.y, color, 50);
4344
}
4445
}
4546

@@ -70,7 +71,11 @@ document.onkeyup = (event) => {
7071
ws.send(ws.PLAYER_KEY_DOWN, {key: "LEFT", state: false});
7172
};
7273

73-
document.getElementById("joinBtn").onclick = () => ws.send(ws.JOIN, {})
74+
document.getElementById("joinBtn").onclick = () => {
75+
const isTraining = document.getElementById("isTrainingCheckBox").value
76+
const roomType = isTraining ? "TRAINING" : "BATTLE_ROYALE";
77+
ws.send(ws.JOIN, {roomType})
78+
}
7479

7580
ws.init("ws://localhost:8085/game")
7681
.then(() => console.log("Connection established"));

example/src/main/resources/static/index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
<div style="width:300px; position:fixed; right:10px;">
1212
<div>
1313
<button id="joinBtn">Join</button>
14+
<label>
15+
<input id="isTrainingCheckBox" type="checkbox">
16+
Training
17+
</label>
1418
</div>
1519
<div>
1620
<span>current player stats</span>

orbital-core/src/main/java/io/github/tfkfan/orbital/core/configuration/Fields.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ public interface Fields {
44
String id = "id";
55
String roomId = "roomId";
66
String action = "action";
7+
String roomType = "roomType";
78
String sessions = "sessions";
89
String sessionId = "sessionId";
910
String admin = "admin";
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package io.github.tfkfan.orbital.core.factory;
2+
3+
import io.github.tfkfan.orbital.core.configuration.props.RoomConfig;
4+
import io.github.tfkfan.orbital.core.manager.GameManager;
5+
import io.github.tfkfan.orbital.core.room.GameRoom;
6+
import io.github.tfkfan.orbital.core.room.RoomType;
7+
import io.github.tfkfan.orbital.core.state.GameState;
8+
9+
import java.util.UUID;
10+
11+
public class BaseGameRoomFactory<R extends GameRoom, S extends GameState> implements GameRoomFactory<R, S> {
12+
13+
@Override
14+
public R createGameRoom(String verticleId, UUID roomId, RoomType roomType, S gameState, GameManager gameManager, RoomConfig roomConfig) {
15+
return null;
16+
}
17+
}

orbital-core/src/main/java/io/github/tfkfan/orbital/core/factory/GameRoomFactory.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
import io.github.tfkfan.orbital.core.configuration.props.RoomConfig;
44
import io.github.tfkfan.orbital.core.manager.GameManager;
55
import io.github.tfkfan.orbital.core.room.GameRoom;
6+
import io.github.tfkfan.orbital.core.room.RoomType;
67
import io.github.tfkfan.orbital.core.state.GameState;
78

89
import java.util.UUID;
910

1011
public interface GameRoomFactory<R extends GameRoom, S extends GameState> {
11-
R createGameRoom(String verticleId, UUID roomId,
12+
R createGameRoom(String verticleId,
13+
UUID roomId,
14+
RoomType roomType,
1215
S gameState,
1316
GameManager gameManager,
1417
RoomConfig roomConfig);

orbital-core/src/main/java/io/github/tfkfan/orbital/core/manager/BaseMatchmakerManager.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.github.tfkfan.orbital.core.configuration.props.RoomConfig;
77
import io.github.tfkfan.orbital.core.event.*;
88
import io.github.tfkfan.orbital.core.network.message.Message;
9+
import io.github.tfkfan.orbital.core.room.RoomType;
910
import io.github.tfkfan.orbital.core.route.MessageRoute;
1011
import io.github.tfkfan.orbital.core.session.GatewaySession;
1112
import io.github.tfkfan.orbital.core.shared.ActionType;
@@ -17,6 +18,7 @@
1718
import io.vertx.core.json.JsonObject;
1819
import lombok.extern.slf4j.Slf4j;
1920

21+
import java.util.Collections;
2022
import java.util.List;
2123
import java.util.UUID;
2224
import java.util.stream.Collectors;
@@ -53,23 +55,43 @@ public void onConnect(GatewaySession data) {
5355

5456
//Default matchmaking implementation
5557
protected void onJoin(GameRoomJoinEvent joinEvent) {
58+
final RoomType roomType = RoomType.getOrDefault(joinEvent.getData(), RoomType.BATTLE_ROYALE);
59+
60+
if (RoomType.TRAINING.equals(roomType)) {
61+
handleJoinTraining(joinEvent);
62+
return;
63+
}
64+
65+
handleJoin(roomType, joinEvent);
66+
}
67+
68+
protected void handleJoinTraining(final GameRoomJoinEvent joinEvent) {
69+
newRoomEvent(newRoomId(), RoomType.TRAINING, Collections.singletonList(joinEvent));
70+
}
71+
72+
protected void handleJoin(final RoomType roomType, final GameRoomJoinEvent joinEvent) {
5673
playersQueue.add(joinEvent);
5774

58-
final GatewaySession session = joinEvent.getSession();
59-
session.send(new Message(MessageTypes.GAME_ROOM_JOIN_WAIT));
75+
joinEvent.getSession().send(new Message(MessageTypes.GAME_ROOM_JOIN_WAIT));
6076

6177
if (playersQueue.size() < roomConfig.getMaxPlayers())
6278
return;
6379

64-
final UUID roomId = UUID.randomUUID();
65-
final List<GameRoomJoinEvent> userSessions = playersQueue.chunk(roomConfig.getMaxPlayers());
80+
newRoomEvent(newRoomId(), roomType, playersQueue.chunk(roomConfig.getMaxPlayers()));
81+
}
82+
83+
private UUID newRoomId() {
84+
return UUID.randomUUID();
85+
}
6686

87+
protected void newRoomEvent(final UUID roomId, final RoomType roomType, final List<GameRoomJoinEvent> userSessions) {
6788
eventBus.sender(Constants.ROOM_VERTICAL_CHANNEL, new DeliveryOptions()
6889
.setLocalOnly(true)
6990
.setSendTimeout(1000))
7091
.write(new JsonObject()
7192
.put(Fields.action, ActionType.NEW_ROOM)
7293
.put(Fields.roomId, roomId.toString())
94+
.put(Fields.roomType, roomType.toString())
7395
.put(Fields.sessions, new JsonArray(userSessions.stream().map(e ->
7496
new JsonObject()
7597
.put(Fields.sessionId, e.getSession().getId())

orbital-core/src/main/java/io/github/tfkfan/orbital/core/manager/impl/GameManagerImpl.java

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,20 @@
88
import io.github.tfkfan.orbital.core.factory.PlayerFactory;
99
import io.github.tfkfan.orbital.core.manager.GameManager;
1010
import io.github.tfkfan.orbital.core.metrics.registrar.GameManagerMetricsRegistrar;
11+
import io.github.tfkfan.orbital.core.model.players.Player;
1112
import io.github.tfkfan.orbital.core.room.GameRoom;
13+
import io.github.tfkfan.orbital.core.room.RoomType;
1214
import io.github.tfkfan.orbital.core.session.PlayerSession;
1315
import io.github.tfkfan.orbital.core.shared.ActionType;
1416
import io.github.tfkfan.orbital.core.state.GameState;
1517
import io.vertx.core.Vertx;
1618
import io.vertx.core.eventbus.Message;
19+
import io.vertx.core.json.JsonArray;
1720
import io.vertx.core.json.JsonObject;
1821
import io.vertx.micrometer.backends.BackendRegistries;
1922
import lombok.extern.slf4j.Slf4j;
2023

21-
import java.util.HashMap;
22-
import java.util.Map;
23-
import java.util.Objects;
24-
import java.util.UUID;
24+
import java.util.*;
2525

2626
@Slf4j
2727
public class GameManagerImpl<R extends GameRoom, S extends GameState> implements GameManager {
@@ -62,31 +62,62 @@ protected void onMessage(Message<JsonObject> message) {
6262
ActionType actionType = ActionType.valueOf(rawAction);
6363
if (actionType.equals(ActionType.NEW_ROOM)) {
6464
final S gameState = gameStateFactory.get();
65+
final RoomType roomType = RoomType.valueOf(json.getString(Fields.roomType));
6566
final UUID roomId = UUID.fromString(json.getString(Fields.roomId));
66-
final GameRoom room = gameRoomFactory.createGameRoom(verticleId, roomId, gameState,
67-
this, roomConfig);
68-
room.onCreate();
69-
70-
json.getJsonArray(Fields.sessions)
71-
.stream()
72-
.forEach(s -> {
73-
JsonObject session = (JsonObject) s;
74-
final String sessionId = session
75-
.getString(Fields.sessionId);
76-
final boolean isAdmin = session.getBoolean(Fields.admin);
77-
final PlayerSession userSession = new PlayerSession(sessionId, isAdmin);
78-
gameState.addPlayer(playerFactory.createPlayer(gameState.nextPlayerId(),
79-
room, userSession, session.getJsonObject(Fields.initialData)));
80-
playerSessionsMap.put(sessionId, userSession);
81-
room.onJoin(userSession);
82-
});
83-
84-
gameRoomMap.put(room.key(), room);
67+
final GameRoom room = createRoom(roomId, roomType, gameState, json.getJsonArray(Fields.sessions));
8568
room.onStart();
8669
}
8770
}
8871
}
8972

73+
protected GameRoom createRoom(final UUID roomId, final RoomType roomType, final S gameState, JsonArray playersSessions) {
74+
validatePlayersCount(roomType, playersSessions, roomId);
75+
76+
final GameRoom room = gameRoomFactory.createGameRoom(verticleId, roomId, roomType,
77+
gameState, this, roomConfig);
78+
room.onCreate();
79+
80+
playersSessions.forEach(s -> addPlayerSession(gameState, room, (JsonObject) s));
81+
82+
if (RoomType.TRAINING.equals(roomType))
83+
addNpcSessions(gameState, room, roomConfig.getMaxPlayers() - 1);
84+
85+
gameRoomMap.put(room.key(), room);
86+
return room;
87+
}
88+
89+
protected void addNpcSessions(S gameState, GameRoom room, int count) {
90+
for (int id = 0; id < count; id++)
91+
addPlayerSession(gameState, room, Integer.toString(id),
92+
false,
93+
true,
94+
null);
95+
}
96+
97+
protected void postPlayerSessionHandle(final Player player) {
98+
99+
}
100+
101+
protected void addPlayerSession(S gameState, GameRoom room, JsonObject session) {
102+
addPlayerSession(gameState, room, session
103+
.getString(Fields.sessionId),
104+
session.getBoolean(Fields.admin),
105+
false,
106+
session.getJsonObject(Fields.initialData));
107+
}
108+
109+
protected void addPlayerSession(S gameState, GameRoom room, String sessionId,
110+
boolean isAdmin, boolean isNpc,
111+
JsonObject initialData) {
112+
final PlayerSession userSession = new PlayerSession(sessionId, isAdmin, isNpc);
113+
final Player player = playerFactory.createPlayer(gameState.nextPlayerId(),
114+
room, userSession, initialData);
115+
gameState.addPlayer(player);
116+
playerSessionsMap.put(sessionId, userSession);
117+
room.onJoin(userSession);
118+
postPlayerSessionHandle(player);
119+
}
120+
90121
@Override
91122
public void onBattleEnd(GameRoom room) {
92123
gameRoomMap.remove(room.key());
@@ -105,4 +136,10 @@ public Integer totalPlayers() {
105136
public String id() {
106137
return verticleId;
107138
}
139+
140+
protected void validatePlayersCount(final RoomType roomType, final JsonArray playersSessions, final UUID roomId) {
141+
if (RoomType.TRAINING.equals(roomType) && playersSessions.size() > 1 || !RoomType.TRAINING.equals(roomType) && playersSessions.size() >= roomConfig.getMaxPlayers())
142+
throw new IllegalArgumentException("Invalid players count received for room: " + roomId);
143+
144+
}
108145
}

0 commit comments

Comments
 (0)