[Chore]: Reafactoring Match daten #14
16 changed files with 204 additions and 136 deletions
13
src/main/java/de/towerdefence/server/match/Enemy.java
Normal file
13
src/main/java/de/towerdefence/server/match/Enemy.java
Normal file
|
@ -0,0 +1,13 @@
|
|||
package de.towerdefence.server.match;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public class Enemy {
|
||||
private int poxX;
|
||||
private int posY;
|
||||
}
|
45
src/main/java/de/towerdefence/server/match/GameSession.java
Normal file
45
src/main/java/de/towerdefence/server/match/GameSession.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
package de.towerdefence.server.match;
|
||||
|
||||
import de.towerdefence.server.match.callbacks.PlayerMoneyCallback;
|
||||
import de.towerdefence.server.match.exeptions.InvalidPlacementException;
|
||||
import de.towerdefence.server.match.exeptions.InvalidPlacementReason;
|
||||
import de.towerdefence.server.player.Player;
|
||||
import lombok.Getter;
|
||||
|
||||
public class GameSession {
|
||||
final static int START_MONEY = 50;
|
||||
final static int MAP_SIZE_X = 10;
|
||||
final static int MAP_SIZE_Y = 20;
|
||||
|
||||
private final Tower[][] towers = new Tower[MAP_SIZE_X][MAP_SIZE_Y];
|
||||
|
||||
private final Player player;
|
||||
@Getter
|
||||
private int money;
|
||||
private final PlayerMoneyCallback moneyCallback;
|
||||
|
||||
public GameSession(Player player, PlayerMoneyCallback moneyCallback) {
|
||||
this.player = player;
|
||||
this.moneyCallback = moneyCallback;
|
||||
this.money = START_MONEY;
|
||||
}
|
||||
|
||||
public void placeTower(Tower tower, int x, int y) throws InvalidPlacementException {
|
||||
if (x < 0 || y < 0 || x + 1 > MAP_SIZE_X || y + 1 > MAP_SIZE_Y) {
|
||||
throw new InvalidPlacementException(InvalidPlacementReason.OUT_OF_BOUNDS);
|
||||
}
|
||||
if (towers[x][y] != null) {
|
||||
throw new InvalidPlacementException(InvalidPlacementReason.LOCATION_USED);
|
||||
}
|
||||
if (money < Tower.COST) {
|
||||
throw new InvalidPlacementException(InvalidPlacementReason.NOT_ENOUGH_MONEY);
|
||||
}
|
||||
money -= Tower.COST;
|
||||
moneyCallback.call(player, money);
|
||||
towers[x][y] = tower;
|
||||
}
|
||||
|
||||
public void addMoney(int amount) {
|
||||
money += amount;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
package de.towerdefence.server.match;
|
||||
|
||||
import de.towerdefence.server.match.callbacks.PlayerMoneyCallback;
|
||||
import de.towerdefence.server.player.Player;
|
||||
import de.towerdefence.server.server.channels.match.money.PlayerMoneyCallback;
|
||||
import de.towerdefence.server.server.channels.match.placing.InvalidPlacementReason;
|
||||
import de.towerdefence.server.server.channels.match.placing.Tower;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Optional;
|
||||
|
@ -11,21 +9,12 @@ import java.util.Optional;
|
|||
@Getter
|
||||
public class Match {
|
||||
|
||||
public static final int TOWER_PRICE = 20;
|
||||
public final static int MAP_SIZE_X = 10;
|
||||
public final static int MAP_SIZE_Y = 20;
|
||||
public final static int START_MONEY = 50;
|
||||
private final String matchId;
|
||||
private final Player player1;
|
||||
private final Player player2;
|
||||
private int player1Money = START_MONEY;
|
||||
private int player2Money = START_MONEY;
|
||||
private PlayerMoneyCallback player1MoneyCallback;
|
||||
private PlayerMoneyCallback player2MoneyCallback;
|
||||
private final Tower[][] player1Map = new Tower[MAP_SIZE_X][MAP_SIZE_Y];
|
||||
private final Tower[][] player2Map = new Tower[MAP_SIZE_X][MAP_SIZE_Y];
|
||||
private boolean isPlayer1Connected = false;
|
||||
private boolean isPlayer2Connected = false;
|
||||
|
||||
private GameSession player1Session;
|
||||
private GameSession player2Session;
|
||||
|
||||
public Match(String matchId, Player player1, Player player2) {
|
||||
this.matchId = matchId;
|
||||
|
@ -33,100 +22,48 @@ public class Match {
|
|||
this.player2 = player2;
|
||||
}
|
||||
|
||||
public Player getOpponent(Player player) {
|
||||
public Optional<Player> getOpponent(Player player) {
|
||||
boolean isPlayer1 = player1.equals(player);
|
||||
boolean isPlayer2 = player2.equals(player);
|
||||
if (!isPlayer1 && !isPlayer2) {
|
||||
return null;
|
||||
}
|
||||
if (isPlayer1) {
|
||||
return player2;
|
||||
}
|
||||
return player1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return opponent
|
||||
*/
|
||||
public Player addTower(Player player, Tower tower, int x, int y) throws InvalidPlacementException {
|
||||
if (player != player1 && player != player2) {
|
||||
return null;
|
||||
}
|
||||
if (x < 0 || y < 0 || x + 1 > Match.MAP_SIZE_X || y + 1 > Match.MAP_SIZE_Y) {
|
||||
throw new InvalidPlacementException(InvalidPlacementReason.OUT_OF_BOUNDS);
|
||||
}
|
||||
if (player == player1) {
|
||||
if (player1Map[x][y] != null) {
|
||||
throw new InvalidPlacementException(InvalidPlacementReason.LOCATION_USED);
|
||||
}
|
||||
removeMoney(player, TOWER_PRICE);
|
||||
player1MoneyCallback.call(player1, player1Money);
|
||||
player1Map[x][y] = tower;
|
||||
} else {
|
||||
if (player2Map[x][y] != null) {
|
||||
throw new InvalidPlacementException(InvalidPlacementReason.LOCATION_USED);
|
||||
}
|
||||
removeMoney(player, TOWER_PRICE);
|
||||
player2MoneyCallback.call(player2, player2Money);
|
||||
player2Map[x][y] = tower;
|
||||
}
|
||||
return getOpponent(player);
|
||||
}
|
||||
|
||||
// INFO: MoneyHandling
|
||||
|
||||
public Optional<Integer> getPlayerMoney(Player player) {
|
||||
if (player != player1 && player != player2) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (player == player1) {
|
||||
return Optional.of(player1Money);
|
||||
} else {
|
||||
return Optional.of(player2Money);
|
||||
if (isPlayer1) {
|
||||
return Optional.of(player2);
|
||||
}
|
||||
return Optional.of(player1);
|
||||
}
|
||||
|
||||
public Optional<GameSession> getPlayerGameSession(Player player) {
|
||||
boolean isPlayer1 = player1.equals(player);
|
||||
boolean isPlayer2 = player2.equals(player);
|
||||
if (!isPlayer1 && !isPlayer2) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (isPlayer1) {
|
||||
return Optional.of(player1Session);
|
||||
}
|
||||
return Optional.of(player2Session);
|
||||
|
||||
}
|
||||
|
||||
public void connectPlayer(Player player, PlayerMoneyCallback moneyCallback) {
|
||||
boolean isPlayer1 = player1.equals(player);
|
||||
boolean isPlayer2 = player2.equals(player);
|
||||
if (!isPlayer1 && !isPlayer2) {
|
||||
return;
|
||||
}
|
||||
if (isPlayer1 && player1Session == null) {
|
||||
this.player1Session = new GameSession(player, moneyCallback);
|
||||
return;
|
||||
}
|
||||
if (isPlayer2 && player2Session == null) {
|
||||
this.player2Session = new GameSession(player, moneyCallback);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void addMoney(int money) {
|
||||
player1Money += money;
|
||||
player2Money += money;
|
||||
}
|
||||
|
||||
public void removeMoney(Player player, int price) throws InvalidPlacementException {
|
||||
if (player == player1) {
|
||||
if (price < player1Money) {
|
||||
player1Money -= price;
|
||||
} else {
|
||||
throw new InvalidPlacementException(InvalidPlacementReason.NOT_ENOUGH_MONEY);
|
||||
}
|
||||
}
|
||||
if (player == player2) {
|
||||
if (price < player2Money) {
|
||||
player2Money -= price;
|
||||
} else {
|
||||
throw new InvalidPlacementException(InvalidPlacementReason.NOT_ENOUGH_MONEY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlayerMoneyCallback(Player player, PlayerMoneyCallback playerMoneyCallback) {
|
||||
if (player == player1) {
|
||||
this.player1MoneyCallback = playerMoneyCallback;
|
||||
}
|
||||
if (player == player2) {
|
||||
this.player2MoneyCallback = playerMoneyCallback;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if both players are connected
|
||||
*/
|
||||
public boolean setPlayerConnected(Player player) {
|
||||
if (player == player1) {
|
||||
isPlayer1Connected = true;
|
||||
}
|
||||
if (player == player2) {
|
||||
isPlayer2Connected = true;
|
||||
}
|
||||
return isPlayer1Connected && isPlayer2Connected;
|
||||
public boolean hasMatchStarted() {
|
||||
return player1Session != null && player2Session != null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package de.towerdefence.server.match;
|
||||
|
||||
import de.towerdefence.server.match.callbacks.PlayerMoneyCallback;
|
||||
import de.towerdefence.server.match.exeptions.InvalidPlacementException;
|
||||
import de.towerdefence.server.match.exeptions.InvalidPlacementReason;
|
||||
import de.towerdefence.server.match.exeptions.NotInMatchException;
|
||||
import de.towerdefence.server.player.Player;
|
||||
import de.towerdefence.server.server.channels.match.money.PlayerMoneyCallback;
|
||||
import de.towerdefence.server.server.channels.match.placing.Tower;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -29,33 +31,53 @@ public class MatchService {
|
|||
/**
|
||||
* @return opponent
|
||||
*/
|
||||
public Player placeTower(Player player, int x, int y) throws InvalidPlacementException{
|
||||
return playerMatches.get(player).addTower(player, new Tower(), x, y);
|
||||
public Player placeTower(Player player, int x, int y) throws NotInMatchException, InvalidPlacementException {
|
||||
Match match = playerMatches.get(player);
|
||||
if (!match.hasMatchStarted()) {
|
||||
throw new InvalidPlacementException(InvalidPlacementReason.MATCH_NOT_STARTED);
|
||||
}
|
||||
Optional<GameSession> playerSession = match.getPlayerGameSession(player);
|
||||
if (playerSession.isEmpty()) {
|
||||
throw new NotInMatchException();
|
||||
}
|
||||
Optional<Player> opponent = match.getOpponent(player);
|
||||
if (opponent.isEmpty()) {
|
||||
throw new NotInMatchException();
|
||||
}
|
||||
playerSession.get().placeTower(new Tower(), x, y);
|
||||
return opponent.get();
|
||||
}
|
||||
|
||||
|
||||
public void playerConnected(Player player, PlayerMoneyCallback callback) {
|
||||
public void playerConnected(Player player, PlayerMoneyCallback moneyCallback) {
|
||||
Match match = playerMatches.get(player);
|
||||
Optional<Integer> currentMoney = match.getPlayerMoney(player);
|
||||
if (currentMoney.isEmpty()) {
|
||||
match.connectPlayer(player, moneyCallback);
|
||||
Optional<GameSession> optionalPlayerSession = match.getPlayerGameSession(player);
|
||||
if (optionalPlayerSession.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
match.setPlayerMoneyCallback(player, callback);
|
||||
callback.call(player, currentMoney.get());
|
||||
boolean matchStarted =match.setPlayerConnected(player);
|
||||
if (!matchStarted) {
|
||||
GameSession playerSession = optionalPlayerSession.get();
|
||||
moneyCallback.call(player, playerSession.getMoney());
|
||||
if (!match.hasMatchStarted()) {
|
||||
return;
|
||||
}
|
||||
Optional<Player> optionalOpponent = match.getOpponent(player);
|
||||
if (optionalOpponent.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Player opponent = optionalOpponent.get();
|
||||
Optional<GameSession> optionalOpponentSession = match.getPlayerGameSession(opponent);
|
||||
if (optionalOpponentSession.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
GameSession opponentSession = optionalOpponentSession.get();
|
||||
ScheduledFuture<?> moneyTask = scheduler.scheduleAtFixedRate(
|
||||
() -> {
|
||||
match.addMoney(3);
|
||||
match.getPlayer1MoneyCallback().call(match.getPlayer1(), match.getPlayer1Money());
|
||||
match.getPlayer2MoneyCallback().call(match.getPlayer2(), match.getPlayer2Money());
|
||||
},
|
||||
5,
|
||||
5,
|
||||
TimeUnit.SECONDS
|
||||
);
|
||||
() -> {
|
||||
playerSession.addMoney(3);
|
||||
opponentSession.addMoney(3);
|
||||
},
|
||||
5,
|
||||
5,
|
||||
TimeUnit.SECONDS);
|
||||
moneyTasks.put(match, moneyTask);
|
||||
}
|
||||
}
|
||||
|
|
5
src/main/java/de/towerdefence/server/match/Tower.java
Normal file
5
src/main/java/de/towerdefence/server/match/Tower.java
Normal file
|
@ -0,0 +1,5 @@
|
|||
package de.towerdefence.server.match;
|
||||
|
||||
public class Tower {
|
||||
public static final int COST = 20;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package de.towerdefence.server.server.channels.match.money;
|
||||
package de.towerdefence.server.match.callbacks;
|
||||
|
||||
import de.towerdefence.server.player.Player;
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package de.towerdefence.server.match;
|
||||
package de.towerdefence.server.match.exeptions;
|
||||
|
||||
import de.towerdefence.server.server.channels.match.placing.InvalidPlacementReason;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package de.towerdefence.server.server.channels.match.placing;
|
||||
package de.towerdefence.server.match.exeptions;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
@ -6,6 +6,7 @@ import lombok.Getter;
|
|||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum InvalidPlacementReason {
|
||||
MATCH_NOT_STARTED("match-not-started"),
|
||||
OUT_OF_BOUNDS("out-of-bounds"),
|
||||
LOCATION_USED("location-used"),
|
||||
NOT_ENOUGH_MONEY("not-enough-money");
|
|
@ -0,0 +1,4 @@
|
|||
package de.towerdefence.server.match.exeptions;
|
||||
|
||||
public class NotInMatchException extends RuntimeException {
|
||||
}
|
|
@ -39,6 +39,7 @@ public abstract class JsonWebsocketHandler extends TextWebSocketHandler {
|
|||
protected void closeSession(WebSocketSession session, CloseStatus reason){
|
||||
if(session.isOpen()){
|
||||
try{
|
||||
sessionPlayers.remove(session);
|
||||
session.close(reason);
|
||||
} catch (Exception exception) {
|
||||
logger.info("Unable to Close the Session", exception);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package de.towerdefence.server.server.channels.match;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.towerdefence.server.match.InvalidPlacementException;
|
||||
import de.towerdefence.server.match.MatchService;
|
||||
import de.towerdefence.server.match.exeptions.InvalidPlacementException;
|
||||
import de.towerdefence.server.match.exeptions.NotInMatchException;
|
||||
import de.towerdefence.server.player.Player;
|
||||
import de.towerdefence.server.server.JsonWebsocketHandler;
|
||||
import de.towerdefence.server.server.channels.match.money.PlayerMoneyMessage;
|
||||
|
@ -47,6 +48,13 @@ public class MatchWebsocketHandler extends JsonWebsocketHandler {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void closeSession(WebSocketSession session, CloseStatus reason) {
|
||||
Player player = sessionPlayers.get(session);
|
||||
super.closeSession(session, reason);
|
||||
playerSessions.remove(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
|
||||
try {
|
||||
|
@ -80,6 +88,9 @@ public class MatchWebsocketHandler extends JsonWebsocketHandler {
|
|||
} catch (InvalidPlacementException exception) {
|
||||
new InvalidPlacementMessage(msg.getX(), msg.getY(), exception.getReason()).send(session);
|
||||
return;
|
||||
} catch (NotInMatchException ignored) {
|
||||
this.closeSession(session, CloseStatus.BAD_DATA);
|
||||
return;
|
||||
}
|
||||
WebSocketSession opponentSession = playerSessions.get(opponent);
|
||||
new TowerPlacedMessage(msg.getX(), msg.getY(), GamePlayerMap.PLAYER).send(session);
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package de.towerdefence.server.server.channels.match;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import de.towerdefence.server.server.JsonMessage;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class PlayerMoneyMessage extends JsonMessage {
|
||||
|
||||
private final int playerMoney;
|
||||
|
||||
@Override
|
||||
protected String getMessageId() {
|
||||
return "PlayerMoney";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, JsonNode> getData(JsonNodeFactory factory) {
|
||||
return Map.of(
|
||||
"playerMoney", factory.numberNode(this.playerMoney)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@ package de.towerdefence.server.server.channels.match.placing;
|
|||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
|
||||
import de.towerdefence.server.match.exeptions.InvalidPlacementReason;
|
||||
import de.towerdefence.server.server.JsonMessage;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
|
@ -22,9 +24,8 @@ public class InvalidPlacementMessage extends JsonMessage {
|
|||
@Override
|
||||
protected Map<String, JsonNode> getData(JsonNodeFactory factory) {
|
||||
return Map.of(
|
||||
"x", factory.numberNode(this.x),
|
||||
"y", factory.numberNode(this.y),
|
||||
"reason", factory.textNode(this.reason.getJsonName())
|
||||
);
|
||||
"x", factory.numberNode(this.x),
|
||||
"y", factory.numberNode(this.y),
|
||||
"reason", factory.textNode(this.reason.getJsonName()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
package de.towerdefence.server.server.channels.match.placing;
|
||||
|
||||
public class Tower {
|
||||
}
|
|
@ -19,4 +19,10 @@
|
|||
<Class name="de.towerdefence.server.match.confirmation.MatchConfirmationService"/>
|
||||
<Bug code="M,D,SF"/>
|
||||
</Match>
|
||||
<Match>
|
||||
<!-- This is Only a Placeholder Object, thus it's not a bad practice to instance it-->
|
||||
<Class name="de.towerdefence.server.match.MatchService"/>
|
||||
<Method name="placeTower"/>
|
||||
<Bug code="L,B,ISC"/>
|
||||
</Match>
|
||||
</FindBugsFilter>
|
||||
|
|
|
@ -216,6 +216,7 @@ channels:
|
|||
reason:
|
||||
type: string
|
||||
enum:
|
||||
- "match-not-started"
|
||||
- "out-of-bounds"
|
||||
- "location-used"
|
||||
- "not-enough-money"
|
||||
|
|
Loading…
Add table
Reference in a new issue