// Path: src/main/java/net/frozenbit/plugin5zig/cubecraft/gamemodes/CubeCraftGameMode.java
// public abstract class CubeCraftGameMode extends GameMode {
//     protected List<CubeCraftPlayer> players = new CopyOnWriteArrayList<>();
//     private String kit;
//     private boolean kitsEnabled;
//     private int pointsEarned;
// 
//     public CubeCraftPlayer getPlayerByName(String name) {
//         for (CubeCraftPlayer player : players) {
//             if (player.getName().equals(name)) {
//                 return player;
//             }
//         }
//         return null;
//     }
// 
//     /**
//      * @return A list of players currently in this gamemode. The list can be modified, however
//      * {@link #playerListUpdate()} MUST be called afterwards.
//      */
//     public List<CubeCraftPlayer> getPlayers() {
//         return players;
//     }
// 
//     public void playerListUpdate() {
//     }
// 
//     public String getKit() {
//         return kit;
//     }
// 
//     public void setKit(String kit) {
//         this.kit = kit;
//     }
// 
//     public boolean hasKitsEnabled() {
//         return kitsEnabled;
//     }
// 
//     public void setKitsEnabled(boolean kitsEnabled) {
//         this.kitsEnabled = kitsEnabled;
//     }
// 
//     public int getPointsEarned() {
//         return pointsEarned;
//     }
// 
//     public void addPointsEarned(int pointsEarned) {
//         this.pointsEarned += pointsEarned;
//     }
// 
//     public boolean isStalkerEnabled() {
//         return true;
//     }
// 
//     /**
//      * Return a singleton instance for the stalker of this gamemode. Before calling this method
//      * always check {@link #isStalkerEnabled()}.
//      * <p>
//      * Implementing classes that do not need a stalker must overwrite {@link #isStalkerEnabled()}
//      * and should throw an exception here.
//      *
//      * @return A stalker singleton.
//      */
//     public abstract Stalker getStalker();
// }
// 
// Path: src/main/java/net/frozenbit/plugin5zig/cubecraft/gamemodes/VotableCubeCraftGameMode.java
// public abstract class VotableCubeCraftGameMode extends CubeCraftGameMode {
//     private Table<CubeCraftPlayer, String, String> votes = HashBasedTable.create();
//     private Map<String, String> draw = new HashMap<>();
//     private TimeLootVotableMode.LootType chestType = TimeLootVotableMode.LootType.NONE;
//     private long lastDrawResultTime;
//     private ArrayList<String> formattedVoterList;
//     private String formattedVoteResult;
// 
//     protected abstract String formatVoteString(CubeCraftPlayer player, Map<String, String> vote);
// 
//     protected abstract String formatVoteResult(Map<String, String> draw);
// 
//     protected abstract boolean isShownInVoterList(CubeCraftPlayer player);
// 
//     protected abstract String[] getVoteCategories();
// 
//     public final long getVoteResultTime() {
//         return lastDrawResultTime;
//     }
// 
//     public final String getVoteResult() {
//         if (formattedVoteResult == null) {
//             formattedVoteResult = isDrawDone() ? formatVoteResult(Collections.unmodifiableMap(draw)) : "";
//         }
//         return formattedVoteResult;
//     }
// 
//     public boolean isDrawDone() {
//         for (String category : getVoteCategories()) {
//             if (!draw.containsKey(category)) {
//                 return false;
//             }
//         }
//         return true;
//     }
// 
//     public final List<String> getFormattedVoterList() {
//         if (formattedVoterList == null) {
//             formattedVoterList = new ArrayList<>();
//             for (CubeCraftPlayer player : players) {
//                 if (isShownInVoterList(player)) {
//                     formattedVoterList.add(formatVoteString(player, votes.row(player)));
//                 }
//             }
//         }
//         return formattedVoterList;
//     }
// 
//     @Override
//     public void playerListUpdate() {
//         super.playerListUpdate();
//         formattedVoterList = null;
//     }
// 
//     public final void onDrawResult(String category, String vote) {
//         draw.put(category, vote);
//         lastDrawResultTime = System.currentTimeMillis();
//         formattedVoteResult = null;
//     }
// 
//     public final void onVote(String playerName, String category, String vote) {
//         CubeCraftPlayer voter = getPlayerByName(playerName);
//         votes.put(voter, category, vote);
//         formattedVoterList = null;
//     }
// 
// }


import com.google.common.base.Splitter;
import eu.the5zig.mod.The5zigAPI;
import eu.the5zig.mod.server.GameState;
import eu.the5zig.mod.server.IPatternResult;
import eu.the5zig.mod.util.NetworkPlayerInfo;
import eu.the5zig.util.minecraft.ChatColor;
import net.frozenbit.plugin5zig.cubecraft.*;
import net.frozenbit.plugin5zig.cubecraft.gamemodes.CubeCraftGameMode;
import net.frozenbit.plugin5zig.cubecraft.gamemodes.VotableCubeCraftGameMode;
import java.util.*;
import java.util.regex.Pattern;
import static java.lang.String.format;
                }
                if (gameMode.isStalkerEnabled()) {
                    gameMode.getStalker().onKill(match.get(0), match.get(1));
                }
                break;
            }
            case "points":
                gameMode.addPointsEarned(Integer.parseInt(match.get(0)));
                break;
            case "playerList":
                updatePlayerList(gameMode, match);
                if (gameMode.isStalkerEnabled()) {
                    gameMode.getStalker().onPlayerListUpdate(gameMode.getPlayers());
                }
                break;
            case "selfWin":
            case "selfDeath": {
                if (!summaryShown) {
                    summaryShown = true;
                    long gameTime = (System.currentTimeMillis() - gameMode.getTime()) / 1000;
                    long minutes = gameTime / 60;
                    long seconds = gameTime % 60;
                    The5zigAPI.getAPI().messagePlayer(
                            format("%sGame ended after %d:%02d! You killed %d players and earned %d points ",
                                    ChatColor.GOLD, minutes, seconds, gameMode.getKills(),
                                    gameMode.getPointsEarned()));
                }
                break;
            }
            case "vote": {
// Path: src/main/java/net/frozenbit/plugin5zig/cubecraft/gamemodes/CubeCraftGameMode.java
// public abstract class CubeCraftGameMode extends GameMode {
//     protected List<CubeCraftPlayer> players = new CopyOnWriteArrayList<>();
//     private String kit;
//     private boolean kitsEnabled;
//     private int pointsEarned;
// 
//     public CubeCraftPlayer getPlayerByName(String name) {
//         for (CubeCraftPlayer player : players) {
//             if (player.getName().equals(name)) {
//                 return player;
//             }
//         }
//         return null;
//     }
// 
//     /**
//      * @return A list of players currently in this gamemode. The list can be modified, however
//      * {@link #playerListUpdate()} MUST be called afterwards.
//      */
//     public List<CubeCraftPlayer> getPlayers() {
//         return players;
//     }
// 
//     public void playerListUpdate() {
//     }
// 
//     public String getKit() {
//         return kit;
//     }
// 
//     public void setKit(String kit) {
//         this.kit = kit;
//     }
// 
//     public boolean hasKitsEnabled() {
//         return kitsEnabled;
//     }
// 
//     public void setKitsEnabled(boolean kitsEnabled) {
//         this.kitsEnabled = kitsEnabled;
//     }
// 
//     public int getPointsEarned() {
//         return pointsEarned;
//     }
// 
//     public void addPointsEarned(int pointsEarned) {
//         this.pointsEarned += pointsEarned;
//     }
// 
//     public boolean isStalkerEnabled() {
//         return true;
//     }
// 
//     /**
//      * Return a singleton instance for the stalker of this gamemode. Before calling this method
//      * always check {@link #isStalkerEnabled()}.
//      * <p>
//      * Implementing classes that do not need a stalker must overwrite {@link #isStalkerEnabled()}
//      * and should throw an exception here.
//      *
//      * @return A stalker singleton.
//      */
//     public abstract Stalker getStalker();
// }
// 
// Path: src/main/java/net/frozenbit/plugin5zig/cubecraft/gamemodes/VotableCubeCraftGameMode.java
// public abstract class VotableCubeCraftGameMode extends CubeCraftGameMode {
//     private Table<CubeCraftPlayer, String, String> votes = HashBasedTable.create();
//     private Map<String, String> draw = new HashMap<>();
//     private TimeLootVotableMode.LootType chestType = TimeLootVotableMode.LootType.NONE;
//     private long lastDrawResultTime;
//     private ArrayList<String> formattedVoterList;
//     private String formattedVoteResult;
// 
//     protected abstract String formatVoteString(CubeCraftPlayer player, Map<String, String> vote);
// 
//     protected abstract String formatVoteResult(Map<String, String> draw);
// 
//     protected abstract boolean isShownInVoterList(CubeCraftPlayer player);
// 
//     protected abstract String[] getVoteCategories();
// 
//     public final long getVoteResultTime() {
//         return lastDrawResultTime;
//     }
// 
//     public final String getVoteResult() {
//         if (formattedVoteResult == null) {
//             formattedVoteResult = isDrawDone() ? formatVoteResult(Collections.unmodifiableMap(draw)) : "";
//         }
//         return formattedVoteResult;
//     }
// 
//     public boolean isDrawDone() {
//         for (String category : getVoteCategories()) {
//             if (!draw.containsKey(category)) {
//                 return false;
//             }
//         }
//         return true;
//     }
// 
//     public final List<String> getFormattedVoterList() {
//         if (formattedVoterList == null) {
//             formattedVoterList = new ArrayList<>();
//             for (CubeCraftPlayer player : players) {
//                 if (isShownInVoterList(player)) {
//                     formattedVoterList.add(formatVoteString(player, votes.row(player)));
//                 }
//             }
//         }
//         return formattedVoterList;
//     }
// 
//     @Override
//     public void playerListUpdate() {
//         super.playerListUpdate();
//         formattedVoterList = null;
//     }
// 
//     public final void onDrawResult(String category, String vote) {
//         draw.put(category, vote);
//         lastDrawResultTime = System.currentTimeMillis();
//         formattedVoteResult = null;
//     }
// 
//     public final void onVote(String playerName, String category, String vote) {
//         CubeCraftPlayer voter = getPlayerByName(playerName);
//         votes.put(voter, category, vote);
//         formattedVoterList = null;
//     }
// 
// }


// Path: src/main/java/net/frozenbit/plugin5zig/cubecraft/listeners/AbstractCubeCraftGameListener.java
import com.google.common.base.Splitter;
import eu.the5zig.mod.The5zigAPI;
import eu.the5zig.mod.server.GameState;
import eu.the5zig.mod.server.IPatternResult;
import eu.the5zig.mod.util.NetworkPlayerInfo;
import eu.the5zig.util.minecraft.ChatColor;
import net.frozenbit.plugin5zig.cubecraft.*;
import net.frozenbit.plugin5zig.cubecraft.gamemodes.CubeCraftGameMode;
import net.frozenbit.plugin5zig.cubecraft.gamemodes.VotableCubeCraftGameMode;
import java.util.*;
import java.util.regex.Pattern;
import static java.lang.String.format;

                }
                if (gameMode.isStalkerEnabled()) {
                    gameMode.getStalker().onKill(match.get(0), match.get(1));
                }
                break;
            }
            case "points":
                gameMode.addPointsEarned(Integer.parseInt(match.get(0)));
                break;
            case "playerList":
                updatePlayerList(gameMode, match);
                if (gameMode.isStalkerEnabled()) {
                    gameMode.getStalker().onPlayerListUpdate(gameMode.getPlayers());
                }
                break;
            case "selfWin":
            case "selfDeath": {
                if (!summaryShown) {
                    summaryShown = true;
                    long gameTime = (System.currentTimeMillis() - gameMode.getTime()) / 1000;
                    long minutes = gameTime / 60;
                    long seconds = gameTime % 60;
                    The5zigAPI.getAPI().messagePlayer(
                            format("%sGame ended after %d:%02d! You killed %d players and earned %d points ",
                                    ChatColor.GOLD, minutes, seconds, gameMode.getKills(),
                                    gameMode.getPointsEarned()));
                }
                break;
            }
            case "vote": {
                if (gameMode instanceof VotableCubeCraftGameMode) {