refactor and bug fixes

This commit is contained in:
Johannes Schmelz 2024-11-17 17:43:05 +01:00
parent 62c363068b
commit 1d69bcc814
5 changed files with 262 additions and 67 deletions

View File

@ -10,8 +10,6 @@ package pp.monopoly.game.server;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import com.jme3.math.ColorRGBA;
import pp.monopoly.message.server.DiceResult; import pp.monopoly.message.server.DiceResult;
import pp.monopoly.model.FieldVisitor; import pp.monopoly.model.FieldVisitor;
import pp.monopoly.model.Figure; import pp.monopoly.model.Figure;
@ -33,87 +31,175 @@ import pp.monopoly.model.fields.WacheField;
public class Player implements FieldVisitor<Void>{ public class Player implements FieldVisitor<Void>{
private final int id; private final int id;
private String name; private String name;
private ColorRGBA color; private PlayerColor color;
private int accountBalance = 0; private int accountBalance = 0;
private Figure figure; private Figure figure;
private List<PropertyField> properties; private List<PropertyField> properties;
private int getOutOfJailCard; private int getOutOfJailCard;
private int fieldID; private int fieldID;
private DiceResult rollResult; private DiceResult rollResult;
private PlayerHandler handler; private final PlayerHandler handler;
private PlayerState state = new LobbyState(); private PlayerState state = new LobbyState();
/**
* Constructs a player with the speciefied params
* @param id the id of the player
* @param name the name of the player
* @param handler the PlayerHandler thispalyer is a part of
*/
public Player(int id, String name, PlayerHandler handler) { public Player(int id, String name, PlayerHandler handler) {
this.name = name; this.name = name;
this.id = id; this.id = id;
this.handler = handler; this.handler = handler;
} }
public Player(int id) { /**
* Constructs a player with the specified id
* @param id the id of the player
* @param handler the PlayerHandler this player is a part of
*/
public Player(int id, PlayerHandler handler) {
this.id = id; this.id = id;
this.handler = handler;
} }
public void setName(String name) { /**
* Set the name of the Player
* @param name the new name
*/
void setName(String name) {
this.name = name; this.name = name;
} }
public void setColor(ColorRGBA color) { /**
* Set the PlayerColor
* @param color the color to be set to
*/
void setColor(PlayerColor color) {
this.color = color; this.color = color;
} }
/**
* Returns this players id
* @return th eid of this player
*/
public int getId() { public int getId() {
return id; return id;
} }
/**
* Returns the current position of the player
* @return the current position of this player
*/
public int getFieldID() { public int getFieldID() {
return fieldID; return fieldID;
} }
/**
* Moves by the specified amount of steps
* @param steps the number of steps to move
* @return the new position
*/
public int move(int steps){ public int move(int steps){
return fieldID = (fieldID+steps)%40; return movePos(fieldID+steps);
} }
/**
* Moves the player to the specified Position on the board
* @param position the position to move to
* @return the new position
*/
public int movePos(int position){ public int movePos(int position){
return fieldID = (fieldID+position)%40; fieldID = fieldID+position;
if(fieldID >= 40) {
fieldID = fieldID%40;
earnMoney(2000);
}
return fieldID;
} }
/**
* Gets all the properties owned by this player
* @return List of all properties owned by this player
*/
public List<PropertyField> getProperties() { public List<PropertyField> getProperties() {
return properties; return properties;
} }
/**
* Buy the speciefied property.
* Properties can olny be bought when they are not sold yet and you have enough money left to buy
* @param property to property to be bought
*/
public void buyProperty(PropertyField property) { public void buyProperty(PropertyField property) {
if (property.getOwner() == null && accountBalance >= property.getPrice()) {
properties.add(property); properties.add(property);
pay(property.getPrice());
}
} }
/**
* Sell the property
* @param property the property to be sold
*/
public void sellProperty(PropertyField property) { public void sellProperty(PropertyField property) {
if (property.getOwner() == this) {
properties.remove(property); properties.remove(property);
property.setOwner(null);
}
} }
/**
* Gets this players current accountBalanece
* @return the amount of money currently owned by this player
*/
public int getAccountBalance() { public int getAccountBalance() {
return accountBalance; return accountBalance;
} }
/**
* Removed the speciefied amount of money to this players accountabalance
* @param amount the amount to be removed
*/
public void pay(int amount) { public void pay(int amount) {
accountBalance -= amount; accountBalance -= amount;
} }
/**
* Add the speciefied amount of money to this players accountabalance
* @param amount the amount to be added
*/
public void earnMoney(int amount) { public void earnMoney(int amount) {
accountBalance += amount; accountBalance += amount;
} }
/**
* Return the players name
* @return the name of this player
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
* Return the number of GEtOutOfJailCards owned by this player
* @return
*/
public int getNumJailCard() { public int getNumJailCard() {
return getOutOfJailCard; return getOutOfJailCard;
} }
/**
* Adds a GetOutOfJailCard
*/
public void addJailCard() { public void addJailCard() {
getOutOfJailCard++; getOutOfJailCard++;
} }
/**
* Removes a GetOutOfJailCard.
* Removes one single card per call, to a minimum of 0 cards
*/
public void removeJailCard() { public void removeJailCard() {
if (getOutOfJailCard ==0) { if (getOutOfJailCard ==0) {
throw new IllegalStateException("Has no JailCard to remove"); throw new IllegalStateException("Has no JailCard to remove");
@ -121,10 +207,16 @@ public class Player implements FieldVisitor<Void>{
getOutOfJailCard--; getOutOfJailCard--;
} }
/**
* Handles the logic of paying the jail bail
*/
public void payBail() { public void payBail() {
state.payBail(); state.payBail();
} }
/**
* Handles the logic of using a GetOutOfJailCard
*/
public void useJailCard() { public void useJailCard() {
state.useJailCard(); state.useJailCard();
} }
@ -160,7 +252,7 @@ public class Player implements FieldVisitor<Void>{
@Override @Override
public Void visit(GulagField field) { public Void visit(GulagField field) {
//do nothing state = new JailState();
return null; return null;
} }
@ -179,13 +271,12 @@ public class Player implements FieldVisitor<Void>{
@Override @Override
public Void visit(WacheField field) { public Void visit(WacheField field) {
movePos(10); movePos(10);
state = new JailState();
return null; return null;
} }
@Override @Override
public Void visit(GoField field) { public Void visit(GoField field) {
accountBalance += 4000; earnMoney(2000);
GulagField res = (GulagField) handler.getLogic().getBoardManager().getFieldAtIndex(10); GulagField res = (GulagField) handler.getLogic().getBoardManager().getFieldAtIndex(10);
res.accept(this); res.accept(this);
return null; return null;
@ -200,6 +291,11 @@ public class Player implements FieldVisitor<Void>{
return null; return null;
} }
/**
* Return the number of Properties of the speciefied fild type
* @param field the type of field to search for
* @return the number of the fields owned with the specified type
*/
public int getNumProp(PropertyField field) { public int getNumProp(PropertyField field) {
int count = 0; int count = 0;
for (PropertyField propertyField : properties) { for (PropertyField propertyField : properties) {
@ -241,8 +337,20 @@ public class Player implements FieldVisitor<Void>{
* A interface representing the PlayerStates * A interface representing the PlayerStates
*/ */
private interface PlayerState { private interface PlayerState {
/**
* Handles the logic for rolling Dice
* @return the {@link DiceResult} of this the DiceRoll
*/
DiceResult rollDice(); DiceResult rollDice();
/**
* Handles the logic for paying the Jail Bail
*/
void payBail(); void payBail();
/**
* Handles the action of using a GetOutOfJail Card
*/
void useJailCard(); void useJailCard();
} }

View File

@ -0,0 +1,35 @@
package pp.monopoly.game.server;
import com.jme3.math.ColorRGBA;
/**
* Enum representing six distinct colors for players in the game.
*/
public enum PlayerColor {
GREEN_LIGHT(new ColorRGBA(0 / 255f, 204 / 255f, 0 / 255f, 1)), // Hex: 00cc00
RED(new ColorRGBA(255 / 255f, 0 / 255f, 0 / 255f, 1)), // Hex: ff0000
BLUE(new ColorRGBA(0 / 255f, 0 / 255f, 204 / 255f, 1)), // Hex: 0000cc
PINK(new ColorRGBA(255 / 255f, 77 / 255f, 166 / 255f, 1)), // Hex: ff4da6
GREEN_DARK(new ColorRGBA(0 / 255f, 102 / 255f, 0 / 255f, 1)), // Hex: 006600
YELLOW(new ColorRGBA(255 / 255f, 255 / 255f, 0 / 255f, 1)); // Hex: ffff00
private final ColorRGBA color;
/**
* Constructs a PlayerColor with the specified ColorRGBA value.
*
* @param color the ColorRGBA value associated with the player color
*/
PlayerColor(ColorRGBA color) {
this.color = color;
}
/**
* Gets the ColorRGBA value of the player color.
*
* @return the ColorRGBA value
*/
public ColorRGBA getColor() {
return color;
}
}

View File

@ -4,36 +4,66 @@ import java.util.LinkedList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
/**
* A class for helping with player actions and managing thier turns
*/
public class PlayerHandler { public class PlayerHandler {
private List<Player> players = new LinkedList<>(); private List<Player> players = new LinkedList<>();
private Set<Player> readyPlayers = new HashSet<>(); private Set<Player> readyPlayers = new HashSet<>();
private ServerGameLogic logic; private ServerGameLogic logic;
/**
* Contructs a PlayerHandler
* @param logic the {@link ServerGameLogic} this PlayerHandler is a part of
*/
PlayerHandler(ServerGameLogic logic) { PlayerHandler(ServerGameLogic logic) {
this.logic = logic; this.logic = logic;
} }
/**
* Contructs a PlayerHandler
* @param logic the {@link ServerGameLogic} this PlayerHandler is a part of
* @param p1 a Player to be added
*/
PlayerHandler(ServerGameLogic logic, Player p1) { PlayerHandler(ServerGameLogic logic, Player p1) {
this(logic); this(logic);
players.add(p1); players.add(p1);
} }
/**
* Contructs a PlayerHandler
* @param logic the {@link ServerGameLogic} this PlayerHandler is a part of
* @param players a Collection of Players to be added
*/
PlayerHandler(ServerGameLogic logic, Collection<Player> players) { PlayerHandler(ServerGameLogic logic, Collection<Player> players) {
this(logic); this(logic);
players.addAll(players); players.addAll(players);
} }
/**
* Return the number of players
* @return number of players in the game
*/
public int getPlayerCount() { public int getPlayerCount() {
return players.size(); return players.size();
} }
/**
* Chechs if all players are ready to start the game
* @return {@code true} if all players are ready, otherwise {@code false}
*/
public boolean allPlayersReady() { public boolean allPlayersReady() {
if (readyPlayers.size() == players.size()) return true; if (readyPlayers.size() == players.size()) return true;
return false; return false;
} }
/**
* Sets a players Ready status
* @param player the player to alter
* @param ready the new Status
*/
void setPlayerReady(Player player, boolean ready) { void setPlayerReady(Player player, boolean ready) {
if (!players.contains(player)) { if (!players.contains(player)) {
throw new IllegalArgumentException("Player does not belong to this PlayerHandler"); throw new IllegalArgumentException("Player does not belong to this PlayerHandler");
@ -46,6 +76,10 @@ public class PlayerHandler {
} }
} }
/**
* Adds a player to the Queue
* @param player the player to be added to the queue
*/
void addPlayer(Player player) { void addPlayer(Player player) {
if (players.contains(player)) { if (players.contains(player)) {
throw new IllegalArgumentException("Player already registered"); throw new IllegalArgumentException("Player already registered");
@ -53,20 +87,49 @@ public class PlayerHandler {
players.add(player); players.add(player);
} }
/**
* Removes the specified Player from the Queue
* @param player the player to be removed
*/
void removePlayer(Player player) { void removePlayer(Player player) {
players.remove(player); players.remove(player);
} }
Player getPlayerAtIndex(int i) { /**
return players.get(i); * Gets Player based on their id in the Queue
* @param index the index of the queue
* @return the Player at the required index
*/
Player getPlayerAtIndex(int index) {
return players.get(index);
} }
/**
* Completes a player turn and return the next player
* @return the next players who is active
*/
Player nextPlayer() { Player nextPlayer() {
players.addLast(players.removeFirst()); players.addLast(players.removeFirst());
return players.getFirst(); return players.getFirst();
} }
/**
* Returns the {@link ServerGameLogic} of this PlayerHandler
* @return the {@link ServerGameLogic} of this PlayerHandler
*/
ServerGameLogic getLogic() { ServerGameLogic getLogic() {
return logic; return logic;
} }
/**
* Gets a player based on their id
* @param id the id to be searched for
* @return the player with the required id
*/
Player getPlayerById(int id) {
for (Player player : players) {
if (player.getId() == id) return player;
}
throw new NoSuchElementException("Player mit id "+id+" existiert nicht");
}
} }

View File

@ -6,14 +6,11 @@ import pp.monopoly.message.server.ServerMessage;
import pp.monopoly.message.server.TradeReply; import pp.monopoly.message.server.TradeReply;
import pp.monopoly.message.server.TradeRequest; import pp.monopoly.message.server.TradeRequest;
import pp.monopoly.message.server.ViewAssetsResponse; import pp.monopoly.message.server.ViewAssetsResponse;
import pp.monopoly.message.server.DiceResult;
import pp.monopoly.model.fields.BoardManager; import pp.monopoly.model.fields.BoardManager;
import pp.monopoly.model.fields.PropertyField; import pp.monopoly.model.fields.PropertyField;
import java.lang.System.Logger; import java.lang.System.Logger;
import java.lang.System.Logger.Level; import java.lang.System.Logger.Level;
import java.util.List;
import java.util.Random;
/** /**
* Controls the server-side game logic for Monopoly. * Controls the server-side game logic for Monopoly.
@ -59,16 +56,6 @@ public class ServerGameLogic implements ClientInterpreter {
state = newState; state = newState;
} }
/**
* Retrieves the player associated with the specified connection ID.
*
* @param id the connection ID of the client
* @return the Player associated with the given ID, or null if not found
*/
public Player getPlayerById(int id) {
return playerHandler.getPlayerAtIndex(id);
}
/** /**
* Sends a message to a specified player. * Sends a message to a specified player.
* *
@ -85,15 +72,15 @@ public class ServerGameLogic implements ClientInterpreter {
} }
/** /**
* Adds a new player to the game if the game is in the CREATEGAME state and the maximum * Adds a new player to the game if the game is in the LOBBY state and the maximum
* player limit has not been reached. * player limit has not been reached.
* *
* @param player the Player to add to the game * @param player the Player to add to the game
* @return the added Player, or null if the player could not be added * @return the added Player, or null if the player could not be added
*/ */
public Player addPlayer(Player player) { public Player addPlayer(Player player) {
if (state != ServerState.CREATEGAME) { if (state != ServerState.LOBBY) {
LOGGER.log(Level.WARNING, "Cannot add player; game is not in CREATEGAME state."); LOGGER.log(Level.WARNING, "Cannot add player; game is not in LOBBY state.");
return null; return null;
} }
@ -103,32 +90,11 @@ public class ServerGameLogic implements ClientInterpreter {
} }
playerHandler.addPlayer(player); playerHandler.addPlayer(player);
LOGGER.log(Level.DEBUG, "Player added: {0}", player.getName()); LOGGER.log(Level.DEBUG, "Player added: {0}", player.getId());
if (playerHandler.getPlayerCount() == MAX_PLAYERS) {
LOGGER.log(Level.INFO, "Maximum number of players reached. Starting game.");
setState(ServerState.INGAME);
}
return player; return player;
} }
/**
* Marks a player as ready and transitions the game state to PLAY if all players are ready.
*
* @param player the Player to mark as ready
* @param status true if the player is ready, false otherwise
*/
void playerReady(Player player, boolean status) {
playerHandler.setPlayerReady(player, status);
LOGGER.log(Level.DEBUG, "Player {0} is now ready: {1}", player.getName(), status);
if (playerHandler.allPlayersReady() && playerHandler.getPlayerCount() > 1) {
setState(ServerState.INGAME);
LOGGER.log(Level.INFO, "All players are ready. Transitioning game state to PLAY.");
}
}
/** /**
* Handles a BuyPropertyRequest from a player, allowing the player to purchase a property * Handles a BuyPropertyRequest from a player, allowing the player to purchase a property
* if it is unowned and they have sufficient funds. * if it is unowned and they have sufficient funds.
@ -138,7 +104,7 @@ public class ServerGameLogic implements ClientInterpreter {
*/ */
@Override @Override
public void received(BuyPropertyRequest msg, int from) { public void received(BuyPropertyRequest msg, int from) {
Player player = getPlayerById(from); Player player = playerHandler.getPlayerById(from);
if (player != null && state == ServerState.INGAME) { if (player != null && state == ServerState.INGAME) {
PropertyField property = (PropertyField) boardManager.getFieldAtIndex(player.move(0)); // Assuming player position for property PropertyField property = (PropertyField) boardManager.getFieldAtIndex(player.move(0)); // Assuming player position for property
@ -161,7 +127,7 @@ public class ServerGameLogic implements ClientInterpreter {
*/ */
@Override @Override
public void received(EndTurn msg, int from) { public void received(EndTurn msg, int from) {
Player player = getPlayerById(from); Player player = playerHandler.getPlayerById(from);
if (player != null && state == ServerState.INGAME) { if (player != null && state == ServerState.INGAME) {
LOGGER.log(Level.DEBUG, "Ending turn for player {0}", player.getName()); LOGGER.log(Level.DEBUG, "Ending turn for player {0}", player.getName());
playerHandler.nextPlayer(); playerHandler.nextPlayer();
@ -176,9 +142,11 @@ public class ServerGameLogic implements ClientInterpreter {
*/ */
@Override @Override
public void received(PlayerReady msg, int from) { public void received(PlayerReady msg, int from) {
Player player = getPlayerById(from); Player player = playerHandler.getPlayerById(from);
if (player != null) { if (player != null) {
playerReady(player, true); player.setName(msg.getName());
player.setColor(msg.getColor());
player.setName(msg.getName());
LOGGER.log(Level.DEBUG, "Player {0} is ready", player.getName()); LOGGER.log(Level.DEBUG, "Player {0} is ready", player.getName());
} }
} }
@ -191,7 +159,7 @@ public class ServerGameLogic implements ClientInterpreter {
*/ */
@Override @Override
public void received(RollDice msg, int from) { public void received(RollDice msg, int from) {
Player player = getPlayerById(from); Player player = playerHandler.getPlayerById(from);
if (player != null && state == ServerState.INGAME) { if (player != null && state == ServerState.INGAME) {
send(player, player.rollDice()); send(player, player.rollDice());
} }
@ -205,12 +173,12 @@ public class ServerGameLogic implements ClientInterpreter {
*/ */
@Override @Override
public void received(TradeOffer msg, int from) { public void received(TradeOffer msg, int from) {
Player sender = getPlayerById(from); Player sender = playerHandler.getPlayerById(from);
Player receiver = getPlayerById(msg.getReceiverId()); Player receiver = playerHandler.getPlayerById(msg.getReceiverId());
if (sender != null && receiver != null) { if (sender != null && receiver != null) {
LOGGER.log(Level.INFO, "Player {0} offers a trade to player {1}", sender.getName(), receiver.getName()); LOGGER.log(Level.INFO, "Player {0} offers a trade to player {1}", sender.getName(), receiver.getName());
send(getPlayerById(msg.getReceiverId()), new TradeRequest(msg.getReceiverId(), msg.getTradeHandler())); send(playerHandler.getPlayerById(msg.getReceiverId()), new TradeRequest(msg.getReceiverId(), msg.getTradeHandler()));
} }
} }
@ -222,8 +190,8 @@ public class ServerGameLogic implements ClientInterpreter {
*/ */
@Override @Override
public void received(TradeResponse msg, int from) { public void received(TradeResponse msg, int from) {
Player responder = getPlayerById(from); Player responder = playerHandler.getPlayerById(from);
Player initiator = getPlayerById(msg.getInitiatorId()); Player initiator = playerHandler.getPlayerById(msg.getInitiatorId());
if (responder != null && initiator != null) { if (responder != null && initiator != null) {
LOGGER.log(Level.INFO, "Player {0} responded to trade with player {1}", responder.getName(), initiator.getName()); LOGGER.log(Level.INFO, "Player {0} responded to trade with player {1}", responder.getName(), initiator.getName());
@ -239,7 +207,7 @@ public class ServerGameLogic implements ClientInterpreter {
*/ */
@Override @Override
public void received(ViewAssetsRequest msg, int from) { public void received(ViewAssetsRequest msg, int from) {
Player player = getPlayerById(from); Player player = playerHandler.getPlayerById(from);
if (player != null) { if (player != null) {
LOGGER.log(Level.DEBUG, "Processing ViewAssetsRequest for player {0}", player.getName()); LOGGER.log(Level.DEBUG, "Processing ViewAssetsRequest for player {0}", player.getName());

View File

@ -1,10 +1,14 @@
package pp.monopoly.message.client; package pp.monopoly.message.client;
import pp.monopoly.game.server.PlayerColor;
/** /**
* Represents a message indicating the player is ready to play. * Represents a message indicating the player is ready to play.
*/ */
public class PlayerReady extends ClientMessage{ public class PlayerReady extends ClientMessage{
private boolean isReady; private boolean isReady;
private String name;
private PlayerColor color;
/** /**
* Constructs a PlayerReady message. * Constructs a PlayerReady message.
@ -15,6 +19,22 @@ public class PlayerReady extends ClientMessage{
this.isReady = isReady; this.isReady = isReady;
} }
/**
* Getter for the Name
* @return the Name
*/
public String getName() {
return name;
}
/**
* Getter for the Playercolor
* @return the Playercolor
*/
public PlayerColor getColor() {
return color;
}
/** /**
* Checks if the player is ready. * Checks if the player is ready.
* *
@ -24,6 +44,7 @@ public class PlayerReady extends ClientMessage{
return isReady; return isReady;
} }
@Override @Override
public void accept(ClientInterpreter interpreter, int from) { public void accept(ClientInterpreter interpreter, int from) {
interpreter.received(this, from); interpreter.received(this, from);