mirror of
https://github.com/Quackster/Havana.git
synced 2025-07-02 04:37:47 +00:00
feat: Poker by wackfx
This commit is contained in:
parent
4eed29c0f9
commit
3395b3bcd5
9 changed files with 704 additions and 28 deletions
|
@ -51,6 +51,7 @@ public class GameBattleShip extends GamehallGame {
|
|||
this.gameEnded = false;
|
||||
}
|
||||
|
||||
/*
|
||||
@Override
|
||||
public void joinGame(Player player) {
|
||||
if (!this.gameStarted) {
|
||||
|
@ -78,7 +79,8 @@ public class GameBattleShip extends GamehallGame {
|
|||
this.sendToEveryone(new ITEMMSG(new String[]{this.getGameId(), "OPPONENTS", String.join(Character.toString((char) 13), opponentData)}));
|
||||
this.sendMarkedMap();
|
||||
}
|
||||
|
||||
*/
|
||||
/*
|
||||
@Override
|
||||
public void leaveGame(Player player) {
|
||||
if (this.nextTurn == getPlayerNum(player)) {
|
||||
|
@ -92,6 +94,8 @@ public class GameBattleShip extends GamehallGame {
|
|||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void handleCommand(Player player, Room room, Item item, String command, String[] args) {
|
||||
GameTrigger trigger = (GameTrigger) item.getDefinition().getInteractionType().getTrigger();
|
||||
|
|
|
@ -54,14 +54,12 @@ public class GameChess extends GamehallGame {
|
|||
this.board = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinGame(Player player) { }
|
||||
|
||||
/*
|
||||
@Override
|
||||
public void leaveGame(Player player) {
|
||||
this.playerSides.remove(player);
|
||||
}
|
||||
|
||||
*/
|
||||
@Override
|
||||
public void handleCommand(Player player, Room room, Item item, String command, String[] args) {
|
||||
GameTrigger trigger = (GameTrigger) item.getDefinition().getInteractionType().getTrigger();
|
||||
|
|
|
@ -1,39 +1,293 @@
|
|||
package org.alexdev.havana.game.games.gamehalls;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.alexdev.havana.game.games.gamehalls.utils.GamePokerCombination;
|
||||
import org.alexdev.havana.game.games.gamehalls.utils.GamePokerOptions;
|
||||
import org.alexdev.havana.game.games.triggers.GameTrigger;
|
||||
import org.alexdev.havana.game.item.Item;
|
||||
import org.alexdev.havana.game.player.Player;
|
||||
import org.alexdev.havana.game.room.Room;
|
||||
import org.alexdev.havana.game.games.triggers.GameTrigger;
|
||||
|
||||
import java.util.List;
|
||||
import org.alexdev.havana.messages.outgoing.rooms.games.ITEMMSG;
|
||||
import org.alexdev.havana.messages.types.MessageComposer;
|
||||
|
||||
public class GamePoker extends GamehallGame {
|
||||
public GamePoker(List<int[]> kvp) {
|
||||
super(kvp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gameStart() { }
|
||||
// Players that played at least one round (not on open screen)
|
||||
private List<Player> playersInGame;
|
||||
|
||||
// Players that are currently in round
|
||||
private List<Player> playersPlaying;
|
||||
|
||||
// Changes and cards for this round
|
||||
private List<String> deck;
|
||||
private Map<Player, String[]> playerChanges;
|
||||
private Map<Player, List<String>> playerCards;
|
||||
|
||||
private GamePokerOptions options;
|
||||
|
||||
|
||||
@Override
|
||||
public void gameStop() { }
|
||||
public void gameStart() {
|
||||
this.deck = new ArrayList<>();
|
||||
this.playerCards = new HashMap<>();
|
||||
this.playerChanges = new HashMap<>();
|
||||
this.playersInGame = new ArrayList<>();
|
||||
this.playersPlaying = new ArrayList<>();
|
||||
this.options = new GamePokerOptions(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinGame(Player p) { }
|
||||
|
||||
@Override
|
||||
public void leaveGame(Player player) { }
|
||||
public void gameStop() {
|
||||
this.clearRound();
|
||||
this.playersInGame.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(Player player, Room room, Item item, String command, String[] args) {
|
||||
GameTrigger trigger = (GameTrigger) item.getDefinition().getInteractionType().getTrigger();
|
||||
|
||||
if (command.equals("CLOSE")) {
|
||||
trigger.onEntityLeave(player, player.getRoomUser(), item);
|
||||
return;
|
||||
switch (command) {
|
||||
case "CLOSE" -> {
|
||||
trigger.onEntityLeave(player, player.getRoomUser(), item);
|
||||
this.getDisconnectedPlayers().stream().forEach(this::disconnectPlayer);
|
||||
if (this.isRoundRunning() && this.hasEveryoneChanged())
|
||||
this.endRound();
|
||||
return;
|
||||
}
|
||||
case "OPEN" -> {
|
||||
this.getDisconnectedPlayers().stream().forEach(this::disconnectPlayer);
|
||||
this.broadcastOpponents(player);
|
||||
return;
|
||||
}
|
||||
case "STARTOVER" -> {
|
||||
if (!this.isRoundRunning()) {
|
||||
this.clearRound();
|
||||
this.deck.addAll(GamePokerCombination.getDeck());
|
||||
}
|
||||
this.addPlayerToGame(player);
|
||||
this.addPlayerToRound(player);
|
||||
this.giveCardsToPlayer(player);
|
||||
this.broadcastOpponents();
|
||||
return;
|
||||
}
|
||||
case "CHANGE" -> {
|
||||
this.getDisconnectedPlayers().stream().forEach(this::disconnectPlayer);
|
||||
this.changeCards(player, args);
|
||||
this.broadcastOpponents();
|
||||
if (this.isRoundRunning() && this.hasEveryoneChanged())
|
||||
this.endRound();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPlayerToGame(Player player) {
|
||||
if (this.playersInGame.contains(player))
|
||||
return;
|
||||
|
||||
this.playersInGame.add(player);
|
||||
this.broadcastOpponents();
|
||||
}
|
||||
|
||||
private void addPlayerToRound(Player player) {
|
||||
this.playersPlaying.add(player);
|
||||
|
||||
// Update player with latest state
|
||||
this.playerChanges.keySet().stream()
|
||||
.map(key -> this.formatPlayerChangedUpdate(key))
|
||||
.forEach(entry -> player.send(new ITEMMSG(entry)));
|
||||
|
||||
this.options.onEntry(player);
|
||||
}
|
||||
|
||||
private void giveCardsToPlayer(Player player) {
|
||||
List<String> cards = IntStream.rangeClosed(0, 4)
|
||||
.mapToObj(i -> this.deck.remove(ThreadLocalRandom.current().nextInt(this.deck.size())))
|
||||
.toList();
|
||||
this.playerCards.put(player, cards);
|
||||
this.playerChanges.remove(player);
|
||||
|
||||
player.send(new ITEMMSG(new String[]{this.getGameId(), "YOURCARDS 0/" + this.formatRevealCardsUpdate(player)}));
|
||||
}
|
||||
|
||||
private void changeCards(Player player, String[] sIndexes) {
|
||||
if (this.playerChanges.containsKey(player))
|
||||
return;
|
||||
|
||||
List<String> playerHand = this.playerCards.get(player);
|
||||
List<Integer> cardsToChange = Arrays.asList(sIndexes)
|
||||
.stream()
|
||||
.filter(predicate -> !predicate.isBlank())
|
||||
.map(Integer::parseInt)
|
||||
.filter(index -> index >= 0 && index < playerHand.size())
|
||||
.sorted().collect(Collectors.toList());
|
||||
|
||||
List<String> changeHand = playerHand.stream()
|
||||
.map(card -> {
|
||||
int index = playerHand.indexOf(card);
|
||||
if (cardsToChange.contains(index))
|
||||
return this.deck.remove(ThreadLocalRandom.current().nextInt(this.deck.size()));
|
||||
else
|
||||
return card;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
String[] cardsChanged = cardsToChange.stream().map(String::valueOf).toArray(String[]::new);
|
||||
|
||||
this.playerCards.put(player, changeHand);
|
||||
this.playerChanges.put(player, cardsChanged);
|
||||
|
||||
// Send change event & reveal new cards to player
|
||||
this.sentToPlayingOpponents(player, new ITEMMSG(
|
||||
this.formatPlayerChangedUpdate(player)
|
||||
));
|
||||
|
||||
player.send(new ITEMMSG(
|
||||
String.join(Character.toString((char) 13), new String[]{
|
||||
this.getGameId(),
|
||||
"YOURCARDS 0/" + this.formatRevealCardsUpdate(player)
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
private String formatPlayerChangedUpdate(Player player) {
|
||||
if (!this.playerChanges.containsKey(player))
|
||||
return "";
|
||||
String[] cardsChanged = this.playerChanges.get(player);
|
||||
String change = player.getDetails().getName() + "/" + String.join(" ", cardsChanged);
|
||||
|
||||
return String.join(Character.toString((char) 13), new String[]{
|
||||
this.getGameId(),
|
||||
"CHANGED",
|
||||
change
|
||||
});
|
||||
}
|
||||
|
||||
private String formatRevealCardsUpdate(Player player) {
|
||||
return String.join("/", new String[] {
|
||||
String.join(",", this.playerChanges.containsKey(player) ? "1" : "0", Integer.toString(this.playerChanges.getOrDefault(player, new String[]{}).length)),
|
||||
String.join("/", this.playerCards.get(player))
|
||||
});
|
||||
}
|
||||
|
||||
private void disconnectPlayer(Player player) {
|
||||
if (!this.playersInGame.contains(player))
|
||||
return;
|
||||
|
||||
this.playersInGame.remove(player);
|
||||
this.playersPlaying.remove(player);
|
||||
this.playerChanges.remove(player);
|
||||
this.playerCards.remove(player);
|
||||
|
||||
ITEMMSG itemMessage = new ITEMMSG(String.join(Character.toString((char) 13),
|
||||
this.getGameId(),
|
||||
"OPPONENT_LOGOUT",
|
||||
player.getDetails().getName()
|
||||
));
|
||||
|
||||
for (Player p : this.playersInGame)
|
||||
p.send(itemMessage);
|
||||
}
|
||||
|
||||
private void broadcastOpponents() {
|
||||
for (Player player: this.playersInGame) {
|
||||
this.broadcastOpponents(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcastOpponents(Player player) {
|
||||
List<String> opponentData = new ArrayList<>();
|
||||
opponentData.add(player.getDetails().getName() + " " + Integer.toString(this.playerChanges.getOrDefault(player, new String[]{}).length));
|
||||
|
||||
for (Player p: this.playersInGame) {
|
||||
if (p == player)
|
||||
continue;
|
||||
opponentData.add(p.getDetails().getName() + " " + Integer.toString(this.playerChanges.getOrDefault(p, new String[]{}).length));
|
||||
}
|
||||
player.send(new ITEMMSG(new String[]{this.getGameId(), "OPPONENTS", String.join(Character.toString((char) 13), opponentData)}));
|
||||
}
|
||||
|
||||
private void revealCards() {
|
||||
// Reveal cards to everyone
|
||||
List<String> playerUpdates = new ArrayList<>();
|
||||
for (Player player : this.playersPlaying)
|
||||
playerUpdates.add(player.getDetails().getName() + "/" + this.formatRevealCardsUpdate(player));
|
||||
|
||||
this.sendToPlaying(new ITEMMSG(new String[]{
|
||||
this.getGameId(),
|
||||
"REVEALCARDS",
|
||||
String.join(Character.toString((char) 13), playerUpdates)
|
||||
}));
|
||||
}
|
||||
|
||||
private void endRound() {
|
||||
this.options.onFinish(playerCards);
|
||||
this.revealCards();
|
||||
this.clearRound();
|
||||
}
|
||||
|
||||
private void clearRound() {
|
||||
this.options.clear();
|
||||
this.deck.clear();
|
||||
this.playerCards.clear();
|
||||
this.playerChanges.clear();
|
||||
this.playersPlaying.clear();
|
||||
}
|
||||
|
||||
private List<Player> getDisconnectedPlayers() {
|
||||
List<Player> toDisconnect = new ArrayList<>();
|
||||
|
||||
for (Player player: this.playersInGame) {
|
||||
if (!this.getPlayers().contains(player))
|
||||
toDisconnect.add(player);
|
||||
}
|
||||
|
||||
return toDisconnect;
|
||||
}
|
||||
|
||||
private boolean isRoundRunning() {
|
||||
return !this.deck.isEmpty();
|
||||
}
|
||||
|
||||
private boolean hasEveryoneChanged() {
|
||||
return this.playersPlaying.stream().filter(p -> this.playerChanges.containsKey(p)).count() == this.playersPlaying.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message to all players in game (including sender)
|
||||
* @param messageComposer
|
||||
*/
|
||||
public void sendToPlaying(MessageComposer messageComposer) {
|
||||
for (Player p : this.playersPlaying) {
|
||||
p.send(messageComposer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message to all opponents in game (excluding sender)
|
||||
* @param sender sender
|
||||
* @param messageComposer
|
||||
*/
|
||||
public void sentToPlayingOpponents(Player sender, MessageComposer messageComposer) {
|
||||
for (Player p : this.playersPlaying) {
|
||||
if (p == sender)
|
||||
continue;
|
||||
p.send(messageComposer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMaximumPeopleRequired() {
|
||||
return 4;
|
||||
|
@ -41,7 +295,7 @@ public class GamePoker extends GamehallGame {
|
|||
|
||||
@Override
|
||||
public int getMinimumPeopleRequired() {
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -44,6 +44,7 @@ public class GameTicTacToe extends GamehallGame {
|
|||
this.gameMap = null;
|
||||
}
|
||||
|
||||
/*
|
||||
@Override
|
||||
public void joinGame(Player p) { }
|
||||
|
||||
|
@ -51,7 +52,7 @@ public class GameTicTacToe extends GamehallGame {
|
|||
public void leaveGame(Player player) {
|
||||
this.playerSides.remove(player);
|
||||
}
|
||||
|
||||
*/
|
||||
@Override
|
||||
public void handleCommand(Player player, Room room, Item item, String command, String[] args) {
|
||||
GameTrigger trigger = (GameTrigger) item.getDefinition().getInteractionType().getTrigger();
|
||||
|
|
|
@ -49,17 +49,11 @@ public abstract class GamehallGame {
|
|||
*/
|
||||
public abstract void handleCommand(Player player, Room room, Item item, String command, String[] args);
|
||||
|
||||
/**
|
||||
* Join game handler for player
|
||||
* @param player the player that join
|
||||
*/
|
||||
public abstract void joinGame(Player player);
|
||||
|
||||
/**
|
||||
* Leave game handler for player
|
||||
* @param player the player that leaves
|
||||
*/
|
||||
public abstract void leaveGame(Player player);
|
||||
// public abstract void leaveGame(Player player);
|
||||
|
||||
/**
|
||||
* Gets the unique game ID instance for this pair. Will
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
package org.alexdev.havana.game.games.gamehalls.utils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public enum GamePokerCombination {
|
||||
FIVE_OF_A_KIND("a Five of a kind"),
|
||||
ROYAL_FLUSH("a Royal flush"),
|
||||
STRAIGHT_FLUSH("a Straight flush"),
|
||||
FOUR_OF_A_KIND("a Four of a kind"),
|
||||
FULL_HOUSE("a Full House"),
|
||||
FLUSH("a Flush"),
|
||||
STRAIGHT("a Straight"),
|
||||
THREE_OF_A_KIND("a Three of a kind"),
|
||||
TWO_PAIR("two pairs"),
|
||||
ONE_PAIR("one pair"),
|
||||
HIGH_CARD("an high card");
|
||||
|
||||
final static List<String> Faces = Arrays.asList("2","3","4","5","6","7","8","9","10", "11", "12", "13", "1");
|
||||
final static List<String> Suits = Arrays.asList("h", "d", "c", "s");
|
||||
final static String Joker = "joker";
|
||||
|
||||
private final String name;
|
||||
|
||||
GamePokerCombination(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public int getCombinationRank() {
|
||||
return Math.abs(this.ordinal() - 10);
|
||||
}
|
||||
|
||||
public static List<String> getDeck() {
|
||||
List<String> deck = new ArrayList<>(Arrays.asList(Joker, Joker));
|
||||
|
||||
for (String suit : Suits) {
|
||||
for (String face : Faces) {
|
||||
deck.add(suit + face);
|
||||
}
|
||||
}
|
||||
|
||||
return deck;
|
||||
}
|
||||
|
||||
public static GamePokerCombination getCombination(List<String> hand) {
|
||||
List<String> cards = hand.stream()
|
||||
.filter(card -> !card.equals(Joker))
|
||||
.collect(Collectors.toList());
|
||||
int jokers = hand.size() - cards.size();
|
||||
|
||||
List<Integer> suits = cards.stream()
|
||||
.map(card -> Suits.indexOf(card.substring(0, 1)))
|
||||
.collect(Collectors.toList());
|
||||
List<Integer> faces = cards.stream()
|
||||
.map(card -> Faces.indexOf(card.substring(1)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
if (cards.stream().anyMatch(card -> Collections.frequency(cards, card) > 1) ||
|
||||
faces.stream().anyMatch(face -> face == -1) ||
|
||||
suits.stream().anyMatch(suit -> suit == -1)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean flush = suits.stream().allMatch(suit -> suit.equals(suits.get(0)));
|
||||
List<Integer> groups = Faces.stream()
|
||||
.map(face -> Collections.frequency(faces, Faces.indexOf(face)))
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.collect(Collectors.toList());
|
||||
List<Integer> shifted = faces.stream()
|
||||
.map(face -> (face + 1) % 13)
|
||||
.collect(Collectors.toList());
|
||||
int distance = Math.min(Collections.max(faces) - Collections.min(faces),
|
||||
Collections.max(shifted) - Collections.min(shifted));
|
||||
boolean straight = groups.get(0) == 1 && distance < 5;
|
||||
boolean royal = straight && flush && !faces.stream().anyMatch(face -> face < 8);
|
||||
groups.set(0, groups.get(0) + jokers);
|
||||
|
||||
if (groups.get(0) == 5) {
|
||||
return GamePokerCombination.FIVE_OF_A_KIND;
|
||||
} else if (royal) {
|
||||
return GamePokerCombination.ROYAL_FLUSH;
|
||||
} else if (straight && flush) {
|
||||
return GamePokerCombination.STRAIGHT_FLUSH;
|
||||
} else if (groups.get(0) == 4) {
|
||||
return GamePokerCombination.FOUR_OF_A_KIND;
|
||||
} else if (groups.get(0) == 3 && groups.get(1) == 2) {
|
||||
return GamePokerCombination.FULL_HOUSE;
|
||||
} else if (flush) {
|
||||
return GamePokerCombination.FLUSH;
|
||||
} else if (straight) {
|
||||
return GamePokerCombination.STRAIGHT;
|
||||
} else if (groups.get(0) == 3) {
|
||||
return GamePokerCombination.THREE_OF_A_KIND;
|
||||
} else if (groups.get(0) == 2 && groups.get(1) == 2) {
|
||||
return GamePokerCombination.TWO_PAIR;
|
||||
} else if (groups.get(0) == 2) {
|
||||
return GamePokerCombination.ONE_PAIR;
|
||||
} else {
|
||||
return GamePokerCombination.HIGH_CARD;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,265 @@
|
|||
package org.alexdev.havana.game.games.gamehalls.utils;
|
||||
|
||||
import org.alexdev.havana.dao.mysql.CurrencyDao;
|
||||
import org.alexdev.havana.game.catalogue.CatalogueItem;
|
||||
import org.alexdev.havana.game.catalogue.CatalogueManager;
|
||||
import org.alexdev.havana.game.games.gamehalls.GamePoker;
|
||||
import org.alexdev.havana.game.player.Player;
|
||||
import org.alexdev.havana.messages.outgoing.rooms.user.CHAT_MESSAGE;
|
||||
import org.alexdev.havana.messages.outgoing.user.currencies.CREDIT_BALANCE;
|
||||
import org.alexdev.havana.messages.outgoing.user.currencies.TICKET_BALANCE;
|
||||
import org.alexdev.havana.util.DateUtil;
|
||||
import org.alexdev.havana.util.config.GameConfiguration;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class GamePokerOptions {
|
||||
|
||||
final private GameConfiguration configuration = GameConfiguration.getInstance();
|
||||
final private GamePoker room;
|
||||
|
||||
final private int entryPrice;
|
||||
final private int minPlayers;
|
||||
|
||||
final private boolean redistributeEntry;
|
||||
final private boolean redistributeOnTie;
|
||||
|
||||
final private int creditsBonus;
|
||||
final private boolean creditsBonusOnTie;
|
||||
|
||||
final private String[] raresReward;
|
||||
final private int raresQuantity;
|
||||
final private boolean raresOnTie;
|
||||
|
||||
final private int ticketsReward;
|
||||
final private boolean ticketsOnTie;
|
||||
|
||||
final private boolean announceWinner;
|
||||
final private boolean announceRewards;
|
||||
|
||||
// Stateful - will reset every round
|
||||
private int entryPaid = 0;
|
||||
final private List<String> rewardMessages = new ArrayList<>();
|
||||
|
||||
|
||||
public GamePokerOptions(GamePoker room) {
|
||||
this.room = room;
|
||||
this.entryPrice = this.getInteger("poker.entry.price", 0);
|
||||
this.minPlayers = this.getInteger("poker.reward.min.player", 2);
|
||||
|
||||
this.redistributeEntry = this.getBoolean("poker.entry.price.redistribute", true);
|
||||
this.redistributeOnTie = this.getBoolean("poker.entry.price.redistribute.on.tie", true);
|
||||
|
||||
this.creditsBonus = this.getInteger("poker.reward.credits.bonus", 0);
|
||||
this.creditsBonusOnTie = this.getBoolean("poker.reward.credits.bonus.on.tie", false);
|
||||
|
||||
this.raresReward = this.getString("poker.reward.rares", "").split(",");
|
||||
this.raresQuantity = this.getInteger("poker.reward.rares.quantity", 0);
|
||||
this.raresOnTie = this.getBoolean("poker.reward.rares.on.tie", false);
|
||||
|
||||
this.ticketsReward = this.getInteger("poker.reward.tickets", 0);
|
||||
this.ticketsOnTie = this.getBoolean("poker.reward.tickets.on.tie", false);
|
||||
|
||||
this.announceWinner = this.getBoolean("poker.announce.winner", true);
|
||||
this.announceRewards = this.getBoolean("poker.announce.rewards", false);
|
||||
}
|
||||
|
||||
public void onEntry(Player player) {
|
||||
if (this.entryPrice <= 0)
|
||||
return;
|
||||
CurrencyDao.decreaseCredits(player.getDetails(), this.entryPrice);
|
||||
player.send(new CREDIT_BALANCE(player.getDetails().getCredits()));
|
||||
this.entryPaid += this.entryPrice;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.entryPaid = 0;
|
||||
this.rewardMessages.clear();
|
||||
}
|
||||
|
||||
public void onFinish(Map<Player, List<String>> _players) {
|
||||
List<Player> playing = _players.keySet().stream().collect(Collectors.toList());
|
||||
Pair<GamePokerCombination, List<Player>> winners = this.getWinners(_players);
|
||||
GamePokerCombination winningCombination = winners.getLeft();
|
||||
List<Player> winnerList = winners.getRight();
|
||||
|
||||
if (this.announceWinner)
|
||||
this.showChat(playing, this.getWinnerMessage(winningCombination, winnerList));
|
||||
|
||||
if (playing.size() < this.minPlayers || !this.canReward(winnerList))
|
||||
return;
|
||||
|
||||
this.rewardCredits(winnerList);
|
||||
this.rewardRares(winnerList);
|
||||
this.rewardTickets(winnerList);
|
||||
|
||||
if (this.announceRewards)
|
||||
this.rewardMessages.forEach(msg -> this.showChat(playing, msg));
|
||||
}
|
||||
|
||||
private void rewardCredits(List<Player> winners) {
|
||||
int credits = 0;
|
||||
|
||||
if (this.redistributeEntry && (winners.size() == 1 || this.redistributeOnTie))
|
||||
credits += this.entryPaid;
|
||||
|
||||
if (this.creditsBonus > 0 && (winners.size() == 1 || this.creditsBonusOnTie))
|
||||
credits += this.creditsBonus;
|
||||
|
||||
if (credits == 0)
|
||||
return;
|
||||
|
||||
int creditsPerWinner = (int) Math.floor(credits / winners.size());
|
||||
|
||||
for (Player winner : winners) {
|
||||
CurrencyDao.increaseCredits(winner.getDetails(), creditsPerWinner);
|
||||
winner.send(new CREDIT_BALANCE(winner.getDetails().getCredits()));
|
||||
}
|
||||
|
||||
if (winners.size() > 1)
|
||||
this.rewardMessages.add("Each winner received " + creditsPerWinner + " credits!");
|
||||
else
|
||||
this.rewardMessages.add(winners.get(0).getDetails().getName() + " received " + creditsPerWinner + " credits!");
|
||||
}
|
||||
|
||||
private void rewardRares(List<Player> winners) {
|
||||
if (this.raresReward.length == 0 || this.raresQuantity == 0 || (winners.size() > 1 && !this.raresOnTie))
|
||||
return;
|
||||
|
||||
CatalogueManager catalogue = CatalogueManager.getInstance();
|
||||
CatalogueItem[] rares = new CatalogueItem[this.raresQuantity];
|
||||
String[] rareNames = new String[this.raresQuantity];
|
||||
|
||||
for (int i = 0; i < this.raresQuantity; i++) {
|
||||
int randomIndex = ThreadLocalRandom.current().nextInt(0, this.raresReward.length);
|
||||
CatalogueItem rare = catalogue.getCatalogueItem(this.raresReward[randomIndex]);
|
||||
rares[i] = rare;
|
||||
rareNames[i] = rare.getDefinition().getName();
|
||||
}
|
||||
|
||||
|
||||
for (Player winner : winners) {
|
||||
for (CatalogueItem rare : rares) {
|
||||
try {
|
||||
catalogue.purchase(winner.getDetails(), rare, null, null, DateUtil.getCurrentTimeSeconds());
|
||||
} catch (SQLException e) {
|
||||
// todo: handle exception
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
winner.getInventory().getView("new");
|
||||
// winner.send(new ITEM_DELIVERED());
|
||||
}
|
||||
|
||||
if (winners.size() > 1)
|
||||
this.rewardMessages.add("Each winner received " + String.join(", ", rareNames) + " !");
|
||||
else
|
||||
this.rewardMessages.add(winners.get(0).getDetails().getName() + " received " + String.join(", ", rareNames) + " !");
|
||||
}
|
||||
|
||||
private void rewardTickets(List<Player> winners) {
|
||||
if (this.ticketsReward <= 0 || (winners.size() > 1 && !this.ticketsOnTie))
|
||||
return;
|
||||
|
||||
for (Player winner : winners) {
|
||||
CurrencyDao.increaseTickets(winner.getDetails(), this.ticketsReward);
|
||||
winner.send(new TICKET_BALANCE(winner.getDetails().getTickets()));
|
||||
}
|
||||
|
||||
if (winners.size() > 1)
|
||||
this.rewardMessages.add("Each winner received " + this.ticketsReward + " tickets!");
|
||||
else
|
||||
this.rewardMessages.add(winners.get(0).getDetails().getName() + " received " + this.ticketsReward + " tickets!");
|
||||
}
|
||||
/**
|
||||
* Show chat message to all players in game
|
||||
* @param chat
|
||||
*/
|
||||
private void showChat(List<Player> players, String chat) {
|
||||
for (Player p : players) {
|
||||
p.send(new CHAT_MESSAGE(CHAT_MESSAGE.ChatMessageType.CHAT, p.getRoomUser().getInstanceId(), chat, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the option apply to the current room?
|
||||
* @param option
|
||||
* @return
|
||||
*/
|
||||
private boolean activeInRoom(String option) {
|
||||
String rooms = this.configuration.getString(option + ".only.in.rooms", "");
|
||||
return rooms.isBlank() || rooms.contains(Integer.toString(this.room.getRoomId()));
|
||||
}
|
||||
|
||||
private String getString(String name, String def) {
|
||||
String value = this.configuration.getString(name, def);
|
||||
if (!this.activeInRoom(name))
|
||||
return def;
|
||||
return value;
|
||||
}
|
||||
|
||||
private int getInteger(String name, int def) {
|
||||
int value = this.configuration.getInteger(name);
|
||||
if (!this.activeInRoom(name))
|
||||
return def;
|
||||
return value;
|
||||
}
|
||||
|
||||
private boolean getBoolean(String name, boolean def) {
|
||||
boolean value = this.configuration.getBoolean(name);
|
||||
if (!this.activeInRoom(name))
|
||||
return def;
|
||||
return value;
|
||||
}
|
||||
|
||||
private boolean canReward(List<Player> winners) {
|
||||
boolean isTie = winners.size() > 1;
|
||||
return (
|
||||
(this.redistributeEntry && this.entryPaid > 0 && (!isTie || this.redistributeOnTie)) ||
|
||||
(this.raresReward.length > 0 && (!isTie || this.raresOnTie)) ||
|
||||
(this.ticketsReward > 0 && (!isTie || this.ticketsOnTie)) ||
|
||||
(this.creditsBonus > 0 && (!isTie || this.creditsBonusOnTie))
|
||||
);
|
||||
}
|
||||
|
||||
private String getWinnerMessage(GamePokerCombination combination, List<Player> winners) {
|
||||
if (winners.size() == 1) {
|
||||
String name = winners.get(0).getDetails().getName();
|
||||
return name + " wins this round with " + combination.getName() + ". Congratulations!";
|
||||
} else {
|
||||
String names = String.join(", ", winners.stream().map(p -> p.getDetails().getName()).collect(Collectors.toList()));
|
||||
return "It's a tie! " + names + " all have " + combination.getName() + ". Congratulations!";
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<GamePokerCombination, List<Player>> getWinners(Map<Player, List<String>> players) {
|
||||
List<Player> winners = new ArrayList<>();
|
||||
GamePokerCombination winningCombination = null;
|
||||
|
||||
// Calculate winners
|
||||
for (Player player : players.keySet()) {
|
||||
List<String> hand = players.get(player);
|
||||
GamePokerCombination combination = GamePokerCombination.getCombination(hand);
|
||||
if (winningCombination == null) {
|
||||
winningCombination = combination;
|
||||
winners.add(player);
|
||||
continue;
|
||||
}
|
||||
if (combination.getCombinationRank() > winningCombination.getCombinationRank()) {
|
||||
winningCombination = combination;
|
||||
winners.clear();
|
||||
winners.add(player);
|
||||
} else if (combination.getCombinationRank() == winningCombination.getCombinationRank()) {
|
||||
winners.add(player);
|
||||
}
|
||||
}
|
||||
return Pair.of(winningCombination, winners);
|
||||
}
|
||||
}
|
|
@ -5,15 +5,40 @@ import org.alexdev.havana.server.netty.streams.NettyResponse;
|
|||
|
||||
public class ITEMMSG extends MessageComposer {
|
||||
private final String[] commands;
|
||||
private final boolean delimitate;
|
||||
|
||||
/**
|
||||
* Create a new ITEMMSG with multiple commands.
|
||||
* Each line will be delimited with '\r'
|
||||
* @param commands
|
||||
*/
|
||||
public ITEMMSG(String[] commands) {
|
||||
this.commands = commands;
|
||||
this.delimitate = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ITEMMSG with a single command.
|
||||
* This expects the command to be already delimited
|
||||
* @param command
|
||||
*/
|
||||
public ITEMMSG(String command) {
|
||||
this.commands = new String[]{command};
|
||||
this.delimitate = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(NettyResponse response) {
|
||||
response.write(String.join(Character.toString((char)13), this.commands));
|
||||
for (String value : this.commands) {
|
||||
if (this.delimitate) {
|
||||
response.write(value, '\r');
|
||||
response.write('\r');
|
||||
}
|
||||
else {
|
||||
response.write(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getHeader() {
|
||||
|
|
|
@ -139,6 +139,34 @@ public class GameConfigWriter implements ConfigWriter {
|
|||
|
||||
config.put("messenger.enable.official.update.speed", "false");
|
||||
|
||||
config.put("poker.entry.price", "0");
|
||||
config.put("poker.entry.price.only.in.rooms", "");
|
||||
|
||||
config.put("poker.entry.price.redistribute", "true");
|
||||
config.put("poker.entry.price.redistribute.on.tie", "true");
|
||||
config.put("poker.entry.price.redistribute.only.in.rooms", "");
|
||||
|
||||
config.put("poker.reward.min.player", "2");
|
||||
config.put("poker.reward.min.player.only.in.rooms", "");
|
||||
|
||||
config.put("poker.reward.credits.bonus", "0");
|
||||
config.put("poker.reward.credits.bonus.on.tie", "false");
|
||||
config.put("poker.reward.credits.bonus.only.in.rooms", "");
|
||||
|
||||
config.put("poker.reward.rares", "");
|
||||
config.put("poker.reward.rares.only.in.rooms", "");
|
||||
config.put("poker.reward.rares.quantity", "1");
|
||||
config.put("poker.reward.rares.on.tie", "false");
|
||||
|
||||
config.put("poker.reward.tickets", "0");
|
||||
config.put("poker.reward.tickets.on.tie", "false");
|
||||
config.put("poker.reward.tickets.only.in.rooms", "");
|
||||
|
||||
config.put("poker.announce.winner", "false");
|
||||
config.put("poker.announce.winner.only.in.rooms", "0");
|
||||
config.put("poker.announce.rewards", "false");
|
||||
config.put("poker.announce.rewards.only.in.rooms", "");
|
||||
|
||||
for (var set : CommandManager.getCommands()) {
|
||||
if (set.getValue().getPlayerRank().getRankId() > 1) {
|
||||
config.put("groups.ids.permission." + set.getKey()[0], "");
|
||||
|
|
Loading…
Add table
Reference in a new issue