Mulligan coding x2

This commit is contained in:
Michael Wain 2024-11-10 02:14:32 +03:00
parent 9f9c82474e
commit a7052548e5
8 changed files with 220 additions and 221 deletions

View File

@ -44,6 +44,10 @@ public class GameConnection extends Thread {
if( room.isEmpty() ||
!room.get().getPassword().equals(handshake.getPassword()) ||
!room.get().getPlayers().stream().anyMatch(p -> p.getUserId().longValue() == handshake.getClientHandle()) ) {
log.error("Handshake error details: room={}; password_equals={}; containsPlayer={}", room.isEmpty(),
room.get().getPassword().equals(handshake.getPassword()),
room.get().getPlayers().stream().anyMatch(p -> p.getUserId().longValue() == handshake.getClientHandle()));
log.error("Handshake error pwd: client={}; orig={}", handshake.getPassword(), room.get().getPassword());
log.error("Handshake failed!");
return;
}

View File

@ -1,10 +1,12 @@
package com.alterdekim.hearthhack.component;
import com.alterdekim.hearthhack.component.interfaces.OnRoomFullCallback;
import com.alterdekim.hearthhack.config.ObjectConfig;
import com.alterdekim.hearthhack.dto.RoomPlayerDTO;
import com.alterdekim.hearthhack.service.RoomService;
import com.alterdekim.hearthhack.service.UserService;
import jakarta.annotation.PostConstruct;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
@ -29,7 +31,10 @@ public class GamePool {
private final ConcurrentHashMap<Long, GameRoom> games = new ConcurrentHashMap<>();
private static final int PLAYERS_COUNT = 1; // TODO: MAKE 2 PLAYERS FOR PRODUCTION
@Getter
private final ConcurrentHashMap<Long, OnRoomFullCallback> callbacks = new ConcurrentHashMap<>();
public static final int PLAYERS_COUNT = 2; // TODO: MAKE 2 PLAYERS FOR PRODUCTION
@Scheduled(fixedRate = 200)
private void refreshRooms() {
@ -40,8 +45,12 @@ public class GamePool {
List<RoomPlayerDTO> players = r.getPlayers();
log.info("Put room by id: {}", r.getId());
games.put(r.getId(), new GameRoom(players, userService, r.getRoomPassword(), config));
players.stream()
.filter(p -> callbacks.containsKey(p.getUserId()))
.forEach(p -> callbacks.get(p.getUserId()).onRoomFull());
roomService.removeRoom(r.getId());
});
// TODO: move gamemaster thread stuff here
}
@PostConstruct

View File

@ -245,67 +245,73 @@ public class GameRoom extends Thread implements IGameRoom {
@Override
public void createGameEntity() {
// TODO: rewrite board generation, and send each packet not via broadcast, but via target send.
log.info("create Game Entity");
PegasusGame.PowerHistory powerHistory = PegasusGame.PowerHistory.newBuilder()
.addList(PegasusGame.PowerHistoryData.newBuilder()
.setCreateGame(PegasusGame.PowerHistoryCreateGame.newBuilder()
.setGameEntity(PegasusGame.Entity.newBuilder()
.setId(1)
.addTags(PegasusGame.Tag.newBuilder()
.setName(10)
.setValue(85)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.CARDTYPE.getValue())
.setValue(TagCardType.GAME.ordinal())
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.TURN.getValue())
.setValue(1)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.STATE.getValue())
.setValue(TagState.RUNNING.ordinal())
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.ZONE.getValue())
.setValue(TagZone.PLAY.ordinal())
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.ENTITY_ID.getValue())
.setValue(1)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.STEP.getValue())
.setValue(TagStep.BEGIN_MULLIGAN.ordinal()) // 10
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.NEXT_STEP.getValue())
.setValue(TagStep.BEGIN_MULLIGAN.ordinal()) // 12
)
)
.addAllPlayers(createPlayersEntity())
)
).build();
for( RoomPlayerDTO player : this.players ) {
PegasusGame.PowerHistory powerHistory = PegasusGame.PowerHistory.newBuilder()
.addList(PegasusGame.PowerHistoryData.newBuilder()
.setCreateGame(PegasusGame.PowerHistoryCreateGame.newBuilder()
.setGameEntity(PegasusGame.Entity.newBuilder()
.setId(1)
.addTags(PegasusGame.Tag.newBuilder()
.setName(10)
.setValue(85)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.CARDTYPE.getValue())
.setValue(TagCardType.GAME.ordinal())
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.TURN.getValue())
.setValue(1)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.STATE.getValue())
.setValue(TagState.RUNNING.ordinal())
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.ZONE.getValue())
.setValue(TagZone.PLAY.ordinal())
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.ENTITY_ID.getValue())
.setValue(1)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.STEP.getValue())
.setValue(TagStep.BEGIN_MULLIGAN.ordinal()) // 10
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.NEXT_STEP.getValue())
.setValue(TagStep.BEGIN_MULLIGAN.ordinal()) // 12
)
)
.addAllPlayers(createPlayersEntity(player))
)
).build();
this.send(player.getUserId(), new PegasusPacket(19, 0, powerHistory.toByteArray()));
}
this.broadcast(new PegasusPacket(19, 0, powerHistory.toByteArray()));
this.nextGlobalState();
}
public List<PegasusGame.Player> createPlayersEntity() {
public List<PegasusGame.Player> createPlayersEntity(RoomPlayerDTO player) {
log.info("create Players entities");
List<PegasusGame.Player> pls = new ArrayList<>();
List<RoomPlayerDTO> rel_players = new ArrayList<>(Collections.singletonList(player));
players.stream().filter(p -> p.getUserId().longValue() != p.getUserId().longValue()).forEach(rel_players::add);
for( int i = 2, pi = 0; i < 4; i++, pi++ ) {
final PegasusGame.Entity.Builder entity = PegasusGame.Entity.newBuilder().setId(i == 2 ? 3 : 2);
if( pi < this.players.size() ) {
players.get(pi).setController(i == 2 ? 2 : 1);
if( pi < rel_players.size() ) {
rel_players.get(pi).setController(i == 2 ? 2 : 1);
GameDeck gd = new GameDeck();
userService.getDeckContentForDeckId(players.get(pi).getUserId(), players.get(pi).getDeckId())
userService.getDeckContentForDeckId(rel_players.get(pi).getUserId(), rel_players.get(pi).getDeckId())
.stream()
.map(d -> card2Entity(d.getAssetId()).get())
.forEach(gd::addCard);
decks.put(players.get(pi).getUserId(), gd);
decks.put(rel_players.get(pi).getUserId(), gd);
}
if( i == 2 ) {
@ -403,7 +409,7 @@ public class GameRoom extends Thread implements IGameRoom {
PegasusGame.Player.newBuilder()
.setId(i)
.setGameAccountId(bnets.get(i-2))
.setCardBack(pi < this.players.size() ? userService.getCardBackById(players.get(pi).getUserId()).getBackId() : 0)
.setCardBack(pi < rel_players.size() ? userService.getCardBackById(rel_players.get(pi).getUserId()).getBackId() : 0)
.setEntity(entity)
.build()
);
@ -414,86 +420,19 @@ public class GameRoom extends Thread implements IGameRoom {
@Override
public void createDeckEntities() {
log.info("create Deck Entities");
// sugar for debug with 1 player. Must be erased after debug.
this.players.forEach(this::generateDeck);
}
private void generateDeck(RoomPlayerDTO p1) {
PegasusGame.PowerHistory.Builder pw = PegasusGame.PowerHistory.newBuilder();
for(int i = 0; i < 26; i++, this.entity_id++) {
pw.addList(PegasusGame.PowerHistoryData.newBuilder()
.setFullEntity(PegasusGame.PowerHistoryEntity.newBuilder()
.setEntity(this.entity_id)
.setName("")
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.ENTITY_ID.getValue())
.setValue(this.entity_id)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.CONTROLLER.getValue())
.setValue(1)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.ZONE.getValue())
.setValue(TagZone.DECK.ordinal())
)
)
);
}
List<RoomPlayerDTO> rel_players = new ArrayList<>(Collections.singletonList(p1));
players.stream().filter(p -> p.getUserId().longValue() != p.getUserId().longValue()).forEach(rel_players::add);
for(int i = 1; i <= 5; i++, this.entity_id++) {
pw.addList(PegasusGame.PowerHistoryData.newBuilder()
.setFullEntity(PegasusGame.PowerHistoryEntity.newBuilder()
.setEntity(this.entity_id)
.setName("")
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.ENTITY_ID.getValue())
.setValue(this.entity_id)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.CONTROLLER.getValue())
.setValue(1)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.ZONE_POSITION.getValue())
.setValue(i)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.ZONE.getValue())
.setValue(TagZone.HAND.ordinal())
)
)
);
}
List<PegasusGame.PowerHistoryEntity.Builder> ens = List.of(
card2Entity("TB_SPT_Boss").get(),
card2Entity("CS1h_001").get()
);
//this.hero_p1 = this.entity_id;
for(int i = 0; i < 2; i++, this.entity_id++) {
pw.addList(PegasusGame.PowerHistoryData.newBuilder()
.setFullEntity(ens.get(i)
.setEntity(this.entity_id)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.ENTITY_ID.getValue())
.setValue(this.entity_id)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.CONTROLLER.getValue())
.setValue(1)
)
.addTags(PegasusGame.Tag.newBuilder()
.setName(GameTag.ZONE.getValue())
.setValue(TagZone.PLAY.ordinal())
)
)
);
}
// other player
for( RoomPlayerDTO player : this.players ) {
for( RoomPlayerDTO player : rel_players ) {
int di = 0;
for (int i = 0; i < 26; i++, this.entity_id++, di++) {
PegasusGame.PowerHistoryEntity.Builder b = di < this.decks.get(player.getUserId()).getSize() ? this.decks.get(player.getUserId()).getCard(di) : PegasusGame.PowerHistoryEntity.newBuilder();
log.info("bBuilder: {}", b.getName());
pw.addList(PegasusGame.PowerHistoryData.newBuilder()
.setFullEntity(b
.setEntity(this.entity_id)
@ -516,7 +455,6 @@ public class GameRoom extends Thread implements IGameRoom {
for (int i = 1; i <= 3; i++, this.entity_id++, di++) {
PegasusGame.PowerHistoryEntity.Builder b = di < this.decks.get(player.getUserId()).getSize() ? this.decks.get(player.getUserId()).getCard(di) : PegasusGame.PowerHistoryEntity.newBuilder();
log.info("HAND: {}; {}; {}; {}", b, di < this.decks.get(player.getUserId()).getSize(), di, this.decks.get(player.getUserId()).getSize());
pw.addList(PegasusGame.PowerHistoryData.newBuilder()
.setFullEntity(b
.setEntity(this.entity_id)
@ -568,7 +506,7 @@ public class GameRoom extends Thread implements IGameRoom {
this.entity_id++;
}
this.broadcast(new PegasusPacket(19, 0, pw.build().toByteArray()));
this.send(p1.getUserId(), new PegasusPacket(19, 0, pw.build().toByteArray()));
this.nextGlobalState();
}
@ -576,10 +514,16 @@ public class GameRoom extends Thread implements IGameRoom {
@Override
public void createPlayerHeroEntity() {
log.info("Player hero entity");
this.players.forEach(this::generateHeroes);
}
private void generateHeroes(RoomPlayerDTO p1) {
PegasusGame.PowerHistory.Builder pw = PegasusGame.PowerHistory.newBuilder();
for(RoomPlayerDTO player : players) {
List<RoomPlayerDTO> rel_players = new ArrayList<>(Collections.singletonList(p1));
players.stream().filter(p -> p.getUserId().longValue() != p.getUserId().longValue()).forEach(rel_players::add);
for(RoomPlayerDTO player : rel_players) {
Optional<Deck> deck = userService.getDecksForUser(player.getUserId())
.stream()
.filter(d -> d.getId().longValue() == player.getDeckId().longValue())
@ -646,7 +590,7 @@ public class GameRoom extends Thread implements IGameRoom {
.setChoiceType(1)
.setCountMin(0)
.setCountMax(3)
.addAllEntities(decks.get(players.get(0).getUserId())
.addAllEntities(decks.get(rel_players.get(0).getUserId())
.getHandCards()
.stream()
.map(PegasusGame.PowerHistoryEntity.Builder::getEntity)
@ -656,9 +600,9 @@ public class GameRoom extends Thread implements IGameRoom {
.setPlayerId(2)
.build();
this.broadcast(new PegasusPacket( 17, 0, entityChoices.toByteArray()));
this.send(p1.getUserId(), new PegasusPacket( 17, 0, entityChoices.toByteArray()));
this.broadcast(new PegasusPacket(19, 0, pw.build().toByteArray()));
this.send(p1.getUserId(), new PegasusPacket(19, 0, pw.build().toByteArray()));
this.entity_id++;
@ -689,6 +633,10 @@ public class GameRoom extends Thread implements IGameRoom {
this.players.forEach(p -> this.outcomeQueue.add(new OutcomeGamePacket(p.getUserId(), packet)));
}
private void send(Long playerId, PegasusPacket packet) {
this.outcomeQueue.add(new OutcomeGamePacket(playerId, packet));
}
private void nextGlobalState() {
this.globalState = GameState.next(this.globalState);
}

View File

@ -39,6 +39,9 @@ public class TcpConnection extends Thread {
@Getter
private final RoomService roomService;
@Getter
private final GamePool gamePool;
@Getter
@Setter
private Long userId;

View File

@ -40,6 +40,9 @@ public class TcpServer extends ReflectionLoader<Processor> {
@Autowired
private RoomService roomService;
@Autowired
private GamePool gamePool;
@Scheduled(fixedDelay = 5000)
private void start() {
try {
@ -59,7 +62,7 @@ public class TcpServer extends ReflectionLoader<Processor> {
while(true) {
SSLSocket s = (SSLSocket) serverSocket.accept();
TcpConnection c = new TcpConnection(s, this.getParsers(), dbfConfig, userService, roomService);
TcpConnection c = new TcpConnection(s, this.getParsers(), dbfConfig, userService, roomService, gamePool);
connections.add(c);
c.start();
log.info("New Connection Established From {}", s.getInetAddress().toString());

View File

@ -0,0 +1,5 @@
package com.alterdekim.hearthhack.component.interfaces;
public interface OnRoomFullCallback {
void onRoomFull();
}

View File

@ -2,14 +2,19 @@ package com.alterdekim.hearthhack.component.processor;
import com.alterdekim.Protocol;
import com.alterdekim.hearthhack.component.TcpConnection;
import com.alterdekim.hearthhack.component.interfaces.OnRoomFullCallback;
import com.alterdekim.hearthhack.dto.RoomDTO;
import com.alterdekim.hearthhack.util.BattleNetPacket;
import com.alterdekim.hearthhack.util.GameType;
import com.google.protobuf.ByteString;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.UUID;
import static com.alterdekim.hearthhack.component.GamePool.PLAYERS_COUNT;
@Slf4j
public class GameMasterProcessor extends Processor {
@ -21,7 +26,7 @@ public class GameMasterProcessor extends Processor {
// FindGameRequest FindGameResponse game_master
// GameType
Protocol.FindGameRequest gameRequest = Protocol.FindGameRequest.parseFrom(packet.getBody());
log.info("FindGameRequest: {}", gameRequest);
//log.info("FindGameRequest: {}", gameRequest);
Protocol.Attribute a = gameRequest.getProperties().getCreationAttributesList().stream()
.filter(p -> p.hasName() && p.getName().equals("type"))
.findFirst()
@ -62,8 +67,11 @@ public class GameMasterProcessor extends Processor {
conn.send(new BattleNetPacket(header, notification.toByteArray()));
String pwd = UUID.randomUUID().toString();
Long roomId = conn.getRoomService().createRoom(new RoomDTO(pwd)); // TODO: make 1 player rooms check.
final String uuid = UUID.randomUUID().toString();
Long roomId = conn.getRoomService().findRoomWithPlayer().orElse(conn.getRoomService().createRoom(new RoomDTO(uuid))); // TODO: make 1 player rooms check.
log.info("Got roomID (join/create): {}", roomId);
final String pwd = conn.getRoomService().findById(roomId).orElse(new RoomDTO(uuid)).getRoomPassword();
conn.getRoomService().joinRoom(roomId, conn.getUserId(),
gameRequest.getPlayerList().get(0)
.getAttributeList()
@ -75,97 +83,104 @@ public class GameMasterProcessor extends Processor {
.getIntValue()
); // TODO: make 1 player rooms check.
Thread.sleep(1000L);
Protocol.Notification n1 = Protocol.Notification.newBuilder()
.setType("G_RESULT")
.setSenderId(Protocol.EntityId.newBuilder()
.setLow(0)
.setHigh(144115188075855872L))
.setTargetId(Protocol.EntityId.newBuilder()
.setLow(78330215L)
.setHigh(144115198130930503L))
.addAttribute(Protocol.Attribute.newBuilder()
.setName("game_request_id")
.setValue(
Protocol.Variant.newBuilder()
.setUintValue(1338541484650062879L * 10L)
)
)
.addAttribute(Protocol.Attribute.newBuilder()
.setName("game_handle")
.setValue(
Protocol.Variant.newBuilder()
.setMessageValue(
Protocol.GameHandle.newBuilder()
.setFactoryId( (143637261465044426L * 100L) + 14L )
.setGameId(Protocol.EntityId.newBuilder()
.setHigh(432345578572981998L)
.setLow((123678367967794400L * 100L) + 12L))
.build()
.toByteString()
)
)
)
.addAttribute(Protocol.Attribute.newBuilder()
.setName("connection_info")
.setValue(
Protocol.Variant.newBuilder()
.setMessageValue(
Protocol.ConnectInfo.newBuilder()
.setMemberId(Protocol.EntityId.newBuilder()
.setHigh(144115198130930503L)
.setLow(78330215L)
conn.getGamePool().getCallbacks().put(conn.getUserId(), new OnRoomFullCallback() {
@Override
public void onRoomFull() {
try {
Protocol.Notification n1 = Protocol.Notification.newBuilder()
.setType("G_RESULT")
.setSenderId(Protocol.EntityId.newBuilder()
.setLow(0)
.setHigh(144115188075855872L))
.setTargetId(Protocol.EntityId.newBuilder()
.setLow(78330215L)
.setHigh(144115198130930503L))
.addAttribute(Protocol.Attribute.newBuilder()
.setName("game_request_id")
.setValue(
Protocol.Variant.newBuilder()
.setUintValue(1338541484650062879L * 10L)
)
)
.addAttribute(Protocol.Attribute.newBuilder()
.setName("game_handle")
.setValue(
Protocol.Variant.newBuilder()
.setMessageValue(
Protocol.GameHandle.newBuilder()
.setFactoryId((143637261465044426L * 100L) + 14L)
.setGameId(Protocol.EntityId.newBuilder()
.setHigh(432345578572981998L)
.setLow((123678367967794400L * 100L) + 12L))
.build()
.toByteString()
)
.setHost("192.168.0.10")
.setPort(3724)
.setToken(ByteString.copyFromUtf8(pwd)) // password
.addAttribute(Protocol.Attribute
.newBuilder()
.setName("version")
.setValue(Protocol.Variant.newBuilder().setStringValue("eiK2qv")))
.addAttribute(Protocol.Attribute
.newBuilder()
.setName("game")
.setValue(Protocol.Variant.newBuilder().setIntValue(roomId))) // game_id
.addAttribute(Protocol.Attribute
.newBuilder()
.setName("player")
.setValue(Protocol.Variant.newBuilder().setIntValue(1L)))
.addAttribute(Protocol.Attribute
.newBuilder()
.setName("id")
.setValue(Protocol.Variant.newBuilder().setIntValue(conn.getUserId())))
.addAttribute(Protocol.Attribute
.newBuilder()
.setName("resumable")
.setValue(Protocol.Variant.newBuilder().setBoolValue(true)))
.addAttribute(Protocol.Attribute
.newBuilder()
.setName("spectator_password")
.setValue(Protocol.Variant.newBuilder().setStringValue("oDipIf")))
.build().toByteString()
)
)
)
.addAttribute(Protocol.Attribute.newBuilder()
.setName("error")
.setValue(
Protocol.Variant.newBuilder()
.setUintValue(0)
)
).build();
)
)
.addAttribute(Protocol.Attribute.newBuilder()
.setName("connection_info")
.setValue(
Protocol.Variant.newBuilder()
.setMessageValue(
Protocol.ConnectInfo.newBuilder()
.setMemberId(Protocol.EntityId.newBuilder()
.setHigh(144115198130930503L)
.setLow(78330215L)
)
.setHost("192.168.0.10")
.setPort(3724)
.setToken(ByteString.copyFromUtf8(pwd)) // password
.addAttribute(Protocol.Attribute
.newBuilder()
.setName("version")
.setValue(Protocol.Variant.newBuilder().setStringValue("eiK2qv")))
.addAttribute(Protocol.Attribute
.newBuilder()
.setName("game")
.setValue(Protocol.Variant.newBuilder().setIntValue(roomId))) // game_id
.addAttribute(Protocol.Attribute
.newBuilder()
.setName("player")
.setValue(Protocol.Variant.newBuilder().setIntValue(1L)))
.addAttribute(Protocol.Attribute
.newBuilder()
.setName("id")
.setValue(Protocol.Variant.newBuilder().setIntValue(conn.getUserId())))
.addAttribute(Protocol.Attribute
.newBuilder()
.setName("resumable")
.setValue(Protocol.Variant.newBuilder().setBoolValue(true)))
.addAttribute(Protocol.Attribute
.newBuilder()
.setName("spectator_password")
.setValue(Protocol.Variant.newBuilder().setStringValue("oDipIf")))
.build().toByteString()
)
)
)
.addAttribute(Protocol.Attribute.newBuilder()
.setName("error")
.setValue(
Protocol.Variant.newBuilder()
.setUintValue(0)
)
).build();
header = Protocol.Header.newBuilder()
.setServiceId(4)
.setMethodId(1)
.setSize(n1.getSerializedSize())
.setToken(conn.nextToken())
.setObjectId(0)
.setStatus(0)
.build();
Protocol.Header header = Protocol.Header.newBuilder()
.setServiceId(4)
.setMethodId(1)
.setSize(n1.getSerializedSize())
.setToken(conn.nextToken())
.setObjectId(0)
.setStatus(0)
.build();
conn.send(new BattleNetPacket(header, n1.toByteArray()));
conn.send(new BattleNetPacket(header, n1.toByteArray()));
} catch (Exception e) {
log.error("GameMasterCallback: {}", e.getMessage());
}
}
});
}
@Override

View File

@ -3,6 +3,7 @@ package com.alterdekim.hearthhack.service;
import com.alterdekim.hearthhack.dto.RoomDTO;
import com.alterdekim.hearthhack.dto.RoomPlayerDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
@ -12,6 +13,9 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
import static com.alterdekim.hearthhack.component.GamePool.PLAYERS_COUNT;
@Slf4j
@Service
public class RoomService implements IService {
@ -56,4 +60,12 @@ public class RoomService implements IService {
r.getPlayers().add(new RoomPlayerDTO(userId, deckId));
map.put(roomId, r);
}
public Optional<Long> findRoomWithPlayer() {
return this.map.values()
.stream()
.filter(r -> !r.getPlayers().isEmpty() && r.getPlayers().size() < PLAYERS_COUNT)
.map(RoomDTO::getId)
.findFirst();
}
}