001package fr.aumgn.dac2.game.colonnisation;
002
003import java.util.ArrayList;
004import java.util.Arrays;
005import java.util.List;
006import java.util.Map;
007import java.util.Map.Entry;
008
009import org.bukkit.World;
010import org.bukkit.command.CommandSender;
011import org.bukkit.entity.Player;
012
013import fr.aumgn.bukkitutils.localization.PluginMessages;
014import fr.aumgn.bukkitutils.playerref.PlayerRef;
015import fr.aumgn.bukkitutils.playerref.map.PlayersRefHashMap;
016import fr.aumgn.bukkitutils.playerref.map.PlayersRefMap;
017import fr.aumgn.bukkitutils.timer.Timer;
018import fr.aumgn.dac2.DAC;
019import fr.aumgn.dac2.arena.regions.Pool;
020import fr.aumgn.dac2.game.AbstractGame;
021import fr.aumgn.dac2.game.GameParty;
022import fr.aumgn.dac2.game.GameTimer;
023import fr.aumgn.dac2.game.start.GameStartData;
024import fr.aumgn.dac2.game.start.PlayerStartData;
025import fr.aumgn.dac2.shape.column.Column;
026import fr.aumgn.dac2.shape.column.ColumnPattern;
027import fr.aumgn.dac2.shape.column.GlassyPattern;
028
029public class Colonnisation extends AbstractGame {
030
031    private final GameParty<ColonnPlayer> party;
032    private final PlayersRefMap<ColonnPlayer> playersMap;
033
034    private final Runnable turnTimedOut = new Runnable() {
035        @Override
036        public void run() {
037            turnTimedOut();
038        }
039    };
040
041    private boolean finished;
042    private Timer timer;
043    private int setupTurns;
044
045    public Colonnisation(DAC dac, GameStartData data) {
046        super(dac, data);
047
048        Map<PlayerRef, ? extends PlayerStartData> playersData =
049                data.getPlayersData();
050        List<ColonnPlayer> list =
051                new ArrayList<ColonnPlayer>(playersData.size());
052        playersMap = new PlayersRefHashMap<ColonnPlayer>();
053
054        for (Entry<PlayerRef, ? extends PlayerStartData> entry :
055                playersData.entrySet()) {
056            PlayerRef playerId = entry.getKey();
057            ColonnPlayer player = new ColonnPlayer(playerId,
058                    playersData.get(playerId));
059            list.add(player);
060            playersMap.put(playerId, player);
061        }
062        party = new GameParty<ColonnPlayer>(this, ColonnPlayer.class, list);
063
064        finished = false;
065    }
066
067    @Override
068    public void start() {
069        resetPoolOnStart();
070
071        double size = arena.getPool().size2D();
072        double setupColumns = size * dac.getConfig().getColonnisationRatio();
073        setupTurns = (int) Math.ceil(setupColumns / party.size());
074
075        send("colonnisation.start");
076        send("colonnisation.playerslist");
077        for (ColonnPlayer player : party.iterable()) {
078            send("colonnisation.start.playerentry", player.getIndex() + 1,
079                    player.getDisplayName());
080        }
081        send("colonnisation.setup.turns", setupTurns);
082        nextTurn();
083    }
084
085    @Override
086    public void onNewTurn() {
087        setupTurns--;
088        if (setupTurns == 0) {
089            send("colonnisation.setup.finished");
090            send("colonnisation.enjoy");
091        }
092    }
093
094    private void nextTurn() {
095        ColonnPlayer player = party.nextTurn();
096
097        if (!player.isOnline()) {
098            send("colonnisation.playerturn.notconnected",
099                    player.getDisplayName());
100            removePlayer(player);
101            if (!finished) {
102                nextTurn();
103            }
104            return;
105        }
106
107        if (timer != null) {
108            timer.cancel();
109        }
110        timer = new GameTimer(dac, this, turnTimedOut);
111        timer.start();
112
113        send("colonnisation.playerturn", player.getDisplayName());
114        tpBeforeJump(player);
115    }
116
117    private void turnTimedOut() {
118        ColonnPlayer player = party.getCurrent();
119        removePlayer(player);
120        if (!finished) {
121            nextTurn();
122        }
123    }
124
125    private void removePlayer(ColonnPlayer player) {
126        party.removePlayer(player);
127        playersMap.remove(player.playerId);
128        spectators.add(player.playerId);
129        if (party.size() < 2) {
130            dac.getStages().stop(this);
131        }
132    }
133
134    @Override
135    public void stop(boolean force) {
136        finished = true;
137        resetPoolOnEnd();
138        if (timer != null) {
139            timer.cancel();
140        }
141
142        if (force) {
143            send("colonnisation.stopped");
144        } else {
145            send("colonnisation.finished");
146        }
147
148        ColonnPlayer[] ranking = party.iterable().clone();
149        Arrays.sort(ranking);
150
151        int index = ranking.length - 1;
152        send("colonnisation.winner", ranking[index].getDisplayName(),
153                ranking[index].getScore());
154        index--;
155        for (; index >= 0; index--) {
156            send("colonnisation.ranking", ranking.length - index,
157                    ranking[index].getDisplayName(), ranking[index].getScore());
158        }
159    }
160
161    @Override
162    public boolean contains(Player player) {
163        return playersMap.containsKey(player);
164    }
165
166    @Override
167    public void sendMessage(String message) {
168        for (ColonnPlayer player : party.iterable()) {
169            player.sendMessage(message);
170        }
171        sendSpectators(message);
172    }
173
174    @Override
175    public boolean isPlayerTurn(Player player) {
176        ColonnPlayer gamePlayer = playersMap.get(player);
177        return gamePlayer != null && party.isTurn(gamePlayer);
178    }
179
180    @Override
181    public void onJumpSuccess(Player player) {
182        ColonnPlayer gamePlayer = playersMap.get(player);
183        World world = arena.getWorld();
184        Pool pool = arena.getPool();
185
186        Column column = pool.getColumn(player);
187        ColumnPattern pattern;
188        if (setupTurns > 0) {
189            pattern = dac.getConfig().getNeutralPattern();
190            send("colonnisation.setup.success", gamePlayer.getDisplayName());
191        } else {
192            pattern = gamePlayer.getColumnPattern();
193            boolean isADAC = column.isADAC(world);
194            if (isADAC) {
195                gamePlayer.incrementMultiplier();
196                pattern = new GlassyPattern(pattern);
197            }
198
199            PoolVisitor visitor = new PoolVisitor(world, pool,
200                    gamePlayer.getColor());
201            int points = visitor.visit(column.getPos());
202            points *= gamePlayer.getMultiplier();
203            gamePlayer.addPoints(points);
204
205            if (isADAC) {
206                send("colonnisation.multiplier.increment",
207                        gamePlayer.getMultiplier());
208            }
209            send("colonnisation.jump.success", gamePlayer.getDisplayName(),
210                    points, gamePlayer.getScore());
211        }
212
213        column.set(world, pattern);
214        tpAfterJumpSuccess(gamePlayer, column);
215        if (pool.isFilled(world)) {
216            dac.getStages().stop(this);
217        } else {
218            nextTurn();
219        }
220    }
221
222    @Override
223    public void onJumpFail(Player player) {
224        ColonnPlayer gamePlayer = playersMap.get(player);
225
226        send("colonnisation.jump.fail", gamePlayer.getDisplayName());
227        if (gamePlayer.getMultiplier() > 1) {
228            gamePlayer.resetMultiplier();
229            send("colonnisation.multiplier.reset");
230        }
231
232        tpAfterJumpFail(gamePlayer);
233        nextTurn();
234    }
235
236    @Override
237    public void onQuit(Player player) {
238        ColonnPlayer gamePlayer = playersMap.get(player);
239        removePlayer(gamePlayer);
240        send("colonnisation.player.quit", gamePlayer.getDisplayName(),
241                gamePlayer.getScore());
242        if (!finished) {
243            nextTurn();
244        }
245    }
246
247    @Override
248    public void list(CommandSender sender) {
249        PluginMessages messages = dac.getMessages();
250
251        sender.sendMessage(messages.get("colonnisation.playerslist"));
252        for (ColonnPlayer player : party.iterable()) {
253            sender.sendMessage(messages.get("colonnisation.playerentry", 
254                    player.getIndex(), player.getDisplayName(),
255                    player.getScore()));
256        }
257    }
258}