diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TestWorld.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TestWorld.java index 2cbcb60..2be8734 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TestWorld.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TestWorld.java @@ -6,6 +6,7 @@ import com.jme3.math.Vector3f; import pp.monopoly.client.MonopolyApp; import pp.monopoly.client.gui.popups.BuyCard; +import pp.monopoly.client.gui.popups.ConfirmTrade; import pp.monopoly.client.gui.popups.EventCardPopup; import pp.monopoly.client.gui.popups.FoodFieldCard; import pp.monopoly.client.gui.popups.GateFieldCard; @@ -150,6 +151,8 @@ public class TestWorld implements GameEventListener{ new LooserPopUp(app).open(); } else if(event.msg().equals("timeout")) { new TimeOut(app).open(); + } else if (event.msg().equals("tradeRequest")) { + new ConfirmTrade(app).open(); } } diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TradeMenu.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TradeMenu.java index a5029b2..b731ae3 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TradeMenu.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TradeMenu.java @@ -1,8 +1,5 @@ package pp.monopoly.client.gui; -import static java.lang.Math.min; - -import com.jme3.app.Application; import com.jme3.material.Material; import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; @@ -15,13 +12,16 @@ import com.simsilica.lemur.component.SpringGridLayout; import com.simsilica.lemur.core.VersionedList; import com.simsilica.lemur.core.VersionedReference; import com.simsilica.lemur.style.ElementId; +import com.simsilica.lemur.text.DocumentModel; + import pp.dialog.Dialog; import pp.monopoly.client.MonopolyApp; -import pp.monopoly.game.server.Player; +import pp.monopoly.message.client.TradeOffer; import pp.monopoly.model.TradeHandler; import pp.monopoly.model.fields.PropertyField; import pp.monopoly.notification.Sound; +import java.util.HashSet; import java.util.Set; public class TradeMenu extends Dialog { @@ -29,15 +29,18 @@ public class TradeMenu extends Dialog { private final TradeHandler tradeHandler; private final Container mainContainer; + private Geometry background; private Selector leftBuildingSelector, leftSpecialCardSelector; private Selector rightBuildingSelector, rightSpecialCardSelector; private TextField leftSelectionsField, rightSelectionsField; private TextField leftCurrencyInput, rightCurrencyInput; - private VersionedReference> selectionRef; // Reference to track selector changes - private String valueSelected = ""; // To keep track of the last selected value - private String buildingSelected = ""; - private String specialCardSelected = ""; + private VersionedReference> leftBuildingRef, rightBuildingRef; + private VersionedReference leftCurrencyRef, rightCurrencyRef; + private VersionedReference> leftCardRef, rightCardRef; + + private Set rightselBuildings = new HashSet<>(); + private Set leftselBuildings = new HashSet<>(); private static final ColorRGBA TRANSLUCENT_WHITE = new ColorRGBA(1, 1, 1, 0.5f); @@ -51,6 +54,8 @@ public class TradeMenu extends Dialog { mainContainer = createMainContainer(); app.getGuiNode().attachChild(mainContainer); positionMainContainer(); + + initializeReferences(); } private Container createMainContainer() { @@ -81,15 +86,17 @@ public class TradeMenu extends Dialog { Container buttons = mainContent.addChild(new Container(new SpringGridLayout())); Button cancel = new Button("Abbrechen"); - cancel.addClickCommands(s-> ifTopDialog( () -> { + cancel.addClickCommands(s -> ifTopDialog(() -> { close(); app.getGameLogic().playSound(Sound.BUTTON); })); Button trade = new Button("Handeln"); - trade.addClickCommands(s-> ifTopDialog( () -> { - close(); + trade.addClickCommands(s -> ifTopDialog(() -> { app.getGameLogic().playSound(Sound.BUTTON); + setTrades(); + app.getGameLogic().send(new TradeOffer(tradeHandler)); + close(); })); buttons.addChild(cancel); @@ -98,6 +105,26 @@ public class TradeMenu extends Dialog { return mainContent; } + private void setTrades() { + tradeHandler.setOfferedAmount(Integer.parseInt(leftCurrencyInput.getText())); + tradeHandler.setRequestedAmount(Integer.parseInt(rightCurrencyInput.getText())); + tradeHandler.setOfferedJailCards(Integer.parseInt(leftSpecialCardSelector.getSelectedItem())); + tradeHandler.setRequestedJailCards(Integer.parseInt(rightSpecialCardSelector.getSelectedItem())); + + Set offeredProperties = new HashSet<>(); + for (String propertyString : leftselBuildings) { + offeredProperties.add( (PropertyField) app.getGameLogic().getBoardManager().getFieldByName(propertyString)); + } + + Set requestedProperties = new HashSet<>(); + for (String propertyString : rightselBuildings) { + requestedProperties.add( (PropertyField) app.getGameLogic().getBoardManager().getFieldByName(propertyString)); + } + + tradeHandler.setOfferedProperties(offeredProperties); + tradeHandler.setRequestedProperties(requestedProperties); + } + private Container createTradeColumn(String label, boolean isLeft) { Container column = new Container(new SpringGridLayout(Axis.Y, Axis.X)); column.setBackground(new QuadBackgroundComponent(ColorRGBA.White)); @@ -108,7 +135,6 @@ public class TradeMenu extends Dialog { column.addChild(new Label("Gebäude:")); Selector buildingSelector = createPropertySelector(isLeft); - buildingSelector.getPopupContainer().setBackground(new QuadBackgroundComponent(ColorRGBA.Orange)); column.addChild(buildingSelector); column.addChild(new Label("Währung:")); @@ -116,8 +142,7 @@ public class TradeMenu extends Dialog { column.addChild(currencyInput); column.addChild(new Label("Sonderkarten:")); - Selector specialCardSelector = createSpecialCardSelector(); - specialCardSelector.getPopupContainer().setBackground(new QuadBackgroundComponent(ColorRGBA.Orange)); + Selector specialCardSelector = createSpecialCardSelector(isLeft); styleSelector(specialCardSelector); column.addChild(specialCardSelector); @@ -135,10 +160,10 @@ public class TradeMenu extends Dialog { return selector; } - private Selector createSpecialCardSelector() { + private Selector createSpecialCardSelector(boolean isLeft) { VersionedList numbers = new VersionedList<>(); - for (int i = 0; i <= app.getGameLogic().getPlayerHandler().getPlayerById(tradeHandler.getReceiver().getId()).getNumJailCard(); i++) { - numbers.add(i+""); + for (int i = 0; i <= app.getGameLogic().getPlayerHandler().getPlayerById(isLeft ? tradeHandler.getReceiver().getId() : tradeHandler.getSender().getId()).getNumJailCard(); i++) { + numbers.add(i + ""); } Selector selector = new Selector<>(numbers, "glass"); styleSelector(selector); @@ -147,72 +172,43 @@ public class TradeMenu extends Dialog { private Iterable getPropertyFields(boolean isLeft) { return app.getGameLogic() - .getBoardManager() - .getPropertyFields(app.getGameLogic() - .getPlayerHandler() - .getPlayerById(isLeft ? tradeHandler.getReceiver().getId() : tradeHandler.getSender().getId()) - .getProperties()); + .getBoardManager() + .getPropertyFields(app.getGameLogic() + .getPlayerHandler() + .getPlayerById(isLeft ? tradeHandler.getReceiver().getId() : tradeHandler.getSender().getId()) + .getProperties()); } private TextField createCurrencyInput() { - TextField currencyInput = new TextField(""); + TextField currencyInput = new TextField("0"); styleTextField(currencyInput); return currencyInput; } - /** - * Creates the middle section with selection fields and arrows. - * - * @return The middle section container. - */ private Container createMiddleSection() { Container middleSection = new Container(new SpringGridLayout(Axis.Y, Axis.X)); middleSection.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f))); - // Add combined label for the top Label middleLabelTop = middleSection.addChild(new Label("Gebäude: Währung: Sonderkarten:")); middleLabelTop.setFontSize(24); middleLabelTop.setInsets(new Insets3f(5, 5, 5, 5)); - // Add the left selection field (Quellobjekte) leftSelectionsField = middleSection.addChild(new TextField("")); leftSelectionsField.setPreferredSize(new Vector3f(600, 50, 0)); - // Add arrows Label arrows = middleSection.addChild(new Label("⇅")); arrows.setFontSize(40); - // Add the right selection field (Zielobjekte) rightSelectionsField = middleSection.addChild(new TextField("")); rightSelectionsField.setPreferredSize(new Vector3f(600, 50, 0)); - // Add combined label for the bottom Label middleLabelBottom = middleSection.addChild(new Label("Gebäude: Währung: Sonderkarten:")); middleLabelBottom.setFontSize(24); middleLabelBottom.setInsets(new Insets3f(5, 5, 5, 5)); - // Spacer - Label spacer = middleSection.addChild(new Label("")); - spacer.setPreferredSize(new Vector3f(1, 50, 0)); - return middleSection; } - - private TextField createSelectionsField(Container parent, boolean isLeft) { - TextField field = new TextField(""); - field.setPreferredSize(new Vector3f(600, 50, 0)); - parent.addChild(field); - - return field; - } - - private Label createArrowLabel() { - Label arrowLabel = new Label("⇅"); - arrowLabel.setFontSize(40); - return arrowLabel; - } - private void styleSelector(Selector selector) { selector.setInsets(new Insets3f(5, 10, 5, 10)); selector.setBackground(new QuadBackgroundComponent(ColorRGBA.Black)); @@ -246,7 +242,7 @@ public class TradeMenu extends Dialog { private void addBackgroundImage() { Texture backgroundImage = app.getAssetManager().loadTexture("Pictures/unibw-Bib2.png"); Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight()); - Geometry background = new Geometry("Background", quad); + background = new Geometry("Background", quad); Material backgroundMaterial = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md"); backgroundMaterial.setTexture("ColorMap", backgroundImage); background.setMaterial(backgroundMaterial); @@ -254,6 +250,56 @@ public class TradeMenu extends Dialog { app.getGuiNode().attachChild(background); } + private void initializeReferences() { + leftBuildingRef = leftBuildingSelector.getSelectionModel().createReference(); + leftCardRef = leftSpecialCardSelector.getSelectionModel().createReference(); + leftCurrencyRef = leftCurrencyInput.getDocumentModel().createReference(); + + rightBuildingRef = rightBuildingSelector.getSelectionModel().createReference(); + rightCardRef = rightSpecialCardSelector.getSelectionModel().createReference(); + rightCurrencyRef = rightCurrencyInput.getDocumentModel().createReference(); + } + + @Override + public void update(float delta) { + if (leftBuildingRef.update() || leftCardRef.update() || leftCurrencyRef.update()) { + updateSelections(leftSelectionsField, leftBuildingSelector, leftCurrencyInput, leftSpecialCardSelector, true); + } + + if (rightBuildingRef.update() || rightCardRef.update() || rightCurrencyRef.update()) { + updateSelections(rightSelectionsField, rightBuildingSelector, rightCurrencyInput, rightSpecialCardSelector, false); + } + } + + private void updateSelections(TextField target, Selector building, TextField currency, Selector card, boolean isLeft) { + StringBuilder buildingText = new StringBuilder(); + if (isLeft) { + if (leftselBuildings.contains(building.getSelectedItem())) { + leftselBuildings.remove(building.getSelectedItem()); // Remove if already selected + } else { + leftselBuildings.add(building.getSelectedItem()); // Add if not already selected + } + for (String property : leftselBuildings) { + buildingText.append(property); + buildingText.append(", "); + } + } else { + if (rightselBuildings.contains(building.getSelectedItem())) { + rightselBuildings.remove(building.getSelectedItem()); // Remove if already selected + } else { + rightselBuildings.add(building.getSelectedItem()); // Add if not already selected + } + for (String property : rightselBuildings) { + buildingText.append(property); + buildingText.append(", "); + } + } + + String currencyText = currency.getText() != null ? currency.getText().trim() : ""; + String cardText = card.getSelectedItem() != null ? card.getSelectedItem() : ""; + target.setText(String.join(" | ", buildingText, currencyText, cardText)); + } + @Override public void escape() { new SettingsMenu(app).open(); @@ -262,44 +308,7 @@ public class TradeMenu extends Dialog { @Override public void close() { app.getGuiNode().detachChild(mainContainer); + app.getGuiNode().detachChild(background); super.close(); } - - /** - * Updates the dialog periodically, called by the dialog manager. - * - * @param delta The time elapsed since the last update. - */ - @Override - public void update(float delta) { - // Check if the selection has changed - // if (selectionRef.update()) { - // String selected = playerSelector.getSelectedItem(); - // if (!selected.equals(lastSelected)) { - // lastSelected = selected; - // onDropdownSelectionChanged(selected); - } - } - - - - /** - * Handles dropdown selection changes and updates the trade handler. - * - * @param selected The selected item from the dropdown. - */ - /* private void onDropdownSelectionChanged(String selected) { - app.getGameLogic().playSound(Sound.BUTTON); - int idStart = selected.indexOf("(ID: ") + 5; // Find start of the ID - int idEnd = selected.indexOf(")", idStart); // Find end of the ID - String idStr = selected.substring(idStart, idEnd); // Extract the ID as a string - int playerId = Integer.parseInt(idStr); // Convert the ID to an integer - - // Find the player by ID - Player selectedPlayer = app.getGameLogic().getPlayerHandler().getPlayerById(playerId); - - if (selectedPlayer != null) { - - } - }*/ - +} diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/game/client/ClientGameLogic.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/game/client/ClientGameLogic.java index a7f48bc..b291327 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/game/client/ClientGameLogic.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/game/client/ClientGameLogic.java @@ -300,13 +300,13 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker { */ @Override public void received(TradeReply msg) { - if (msg.getTradeHandler().getStatus()) { + // if (msg.getTradeHandler().getStatus()) { - playSound(Sound.TRADE_ACCEPTED); - } else { + // playSound(Sound.TRADE_ACCEPTED); + // } else { - playSound(Sound.TRADE_REJECTED); - } + // playSound(Sound.TRADE_REJECTED); + // } } /** @@ -316,7 +316,8 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker { */ @Override public void received(TradeRequest msg) { - + System.out.println("Angebot angekommen"); + notifyListeners(new PopUpEvent("tradeRequest")); } /** diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/game/server/ServerGameLogic.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/game/server/ServerGameLogic.java index 21e1c4d..900afd1 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/game/server/ServerGameLogic.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/game/server/ServerGameLogic.java @@ -232,11 +232,11 @@ public class ServerGameLogic implements ClientInterpreter { @Override public void received(TradeOffer msg, int from) { Player sender = playerHandler.getPlayerById(from); - Player receiver = playerHandler.getPlayerById(msg.getReceiverId()); + Player receiver = msg.getTradeHandler().getReceiver(); if (sender != null && receiver != null) { LOGGER.log(Level.INFO, "Player {0} offers a trade to player {1}", sender.getName(), receiver.getName()); - send(playerHandler.getPlayerById(msg.getReceiverId()), new TradeRequest(msg.getReceiverId(), msg.getTradeHandler())); + send(receiver, new TradeRequest(msg.getTradeHandler())); } } diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/message/client/TradeOffer.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/message/client/TradeOffer.java index edb885f..560ecad 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/message/client/TradeOffer.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/message/client/TradeOffer.java @@ -9,7 +9,6 @@ import pp.monopoly.model.TradeHandler; */ @Serializable public class TradeOffer extends ClientMessage{ - private int receiverId; private TradeHandler tradehandler; /** @@ -23,12 +22,10 @@ public class TradeOffer extends ClientMessage{ * @param receiverId the ID of the player receiving the Request * @param tradehandler the tradehandler */ - public TradeOffer(int receiverId, TradeHandler tradehandler) { - this.receiverId = receiverId; + public TradeOffer(TradeHandler tradehandler) { this.tradehandler = tradehandler; } - public int getReceiverId() { return receiverId; } public TradeHandler getTradeHandler() { return tradehandler; } @Override diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/message/server/TradeRequest.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/message/server/TradeRequest.java index 7afeb34..c98ada9 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/message/server/TradeRequest.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/message/server/TradeRequest.java @@ -9,7 +9,6 @@ import pp.monopoly.model.TradeHandler; */ @Serializable public class TradeRequest extends ServerMessage{ - private int receiverId; private TradeHandler tradehandler; @@ -24,12 +23,10 @@ public class TradeRequest extends ServerMessage{ * @param receiverId the ID of the player receiving the Request * @param tradehandler the tradehandler */ - public TradeRequest(int receiverId, TradeHandler tradehandler) { - this.receiverId = receiverId; + public TradeRequest(TradeHandler tradehandler) { this.tradehandler = tradehandler; } - public int getReceiverId() { return receiverId; } public TradeHandler getTradeHandler() { return tradehandler; } diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/model/TradeHandler.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/model/TradeHandler.java index fe0aa48..7c94f6e 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/model/TradeHandler.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/model/TradeHandler.java @@ -3,23 +3,30 @@ package pp.monopoly.model; import pp.monopoly.game.server.Player; import pp.monopoly.model.fields.PropertyField; -import java.util.List; +import java.util.HashSet; +import java.util.Set; + +import com.jme3.network.serializing.Serializable; /** * Handles a single trade between two players. * Encapsulates trade details, validation, acceptance, and rejection. */ +@Serializable public class TradeHandler { private final Player sender; private Player receiver; private int offeredAmount; - private List offeredProperties; + private Set offeredProperties = new HashSet<>(); private int offeredJailCards; private int requestedAmount; - private List requestedProperties; + private Set requestedProperties = new HashSet<>(); private int requestedJailCards; - private Boolean status = null; + + private TradeHandler() { + sender = null; + } /** * Constructs a TradeHandler for a single trade instance. @@ -33,8 +40,8 @@ public class TradeHandler { * @param requestedProperties the properties requested from the receiver * @param requestedJailCards the jail cards requested from the receiver */ - public TradeHandler(Player sender, Player receiver, int offeredAmount, List offeredProperties, - int offeredJailCards, int requestedAmount, List requestedProperties, int requestedJailCards) { + public TradeHandler(Player sender, Player receiver, int offeredAmount, Set offeredProperties, + int offeredJailCards, int requestedAmount, Set requestedProperties, int requestedJailCards) { this.sender = sender; this.receiver = receiver; this.offeredAmount = offeredAmount; @@ -69,7 +76,7 @@ public class TradeHandler { return offeredJailCards; } - public List getOfferedProperties() { + public Set getOfferedProperties() { return offeredProperties; } @@ -85,7 +92,7 @@ public class TradeHandler { return requestedJailCards; } - public List getRequestedProperties() { + public Set getRequestedProperties() { return requestedProperties; } @@ -93,10 +100,6 @@ public class TradeHandler { return sender; } - public Boolean getStatus() { - return status; - } - /** * Initiates the trade and validates its terms. * @@ -234,7 +237,7 @@ public class TradeHandler { this.offeredJailCards = offeredJailCards; } - public void setOfferedProperties(List offeredProperties) { + public void setOfferedProperties(Set offeredProperties) { this.offeredProperties = offeredProperties; } @@ -250,7 +253,7 @@ public class TradeHandler { this.requestedJailCards = requestedJailCards; } - public void setRequestedProperties(List requestedProperties) { + public void setRequestedProperties(Set requestedProperties) { this.requestedProperties = requestedProperties; } } diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/model/fields/BoardManager.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/model/fields/BoardManager.java index c1cd718..b55b01f 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/model/fields/BoardManager.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/model/fields/BoardManager.java @@ -72,6 +72,15 @@ public class BoardManager { return fields; } + public Field getFieldByName(String name) { + for (Field field : board) { + if (field.getName().equals(name)) { + return field; + } + } + throw new NoSuchElementException(); + } + /** * Method to find the Field at specific index diff --git a/Projekte/monopoly/server/src/main/java/pp/monopoly/server/MonopolyServer.java b/Projekte/monopoly/server/src/main/java/pp/monopoly/server/MonopolyServer.java index 562093a..3b44378 100644 --- a/Projekte/monopoly/server/src/main/java/pp/monopoly/server/MonopolyServer.java +++ b/Projekte/monopoly/server/src/main/java/pp/monopoly/server/MonopolyServer.java @@ -44,10 +44,13 @@ import pp.monopoly.message.server.GameStart; import pp.monopoly.message.server.NextPlayerTurn; import pp.monopoly.message.server.PlayerStatusUpdate; import pp.monopoly.message.server.ServerMessage; +import pp.monopoly.message.server.TradeReply; +import pp.monopoly.message.server.TradeRequest; import pp.monopoly.message.server.ViewAssetsResponse; import pp.monopoly.model.Figure; import pp.monopoly.model.IntPoint; import pp.monopoly.model.LimitedLinkedList; +import pp.monopoly.model.TradeHandler; import pp.monopoly.model.fields.BoardManager; import pp.monopoly.model.fields.BuildingProperty; import pp.monopoly.model.fields.EventField; @@ -164,6 +167,9 @@ public class MonopolyServer implements MessageListener, Connec Serializer.registerClass(EventField.class); Serializer.registerClass(GulagField.class); Serializer.registerClass(FineField.class); + Serializer.registerClass(TradeRequest.class); + Serializer.registerClass(TradeReply.class); + Serializer.registerClass(TradeHandler.class); } private void registerListeners() {