001    /**
002     * Jetrix TetriNET Server
003     * Copyright (C) 2001-2004  Emmanuel Bourg
004     *
005     * This program is free software; you can redistribute it and/or
006     * modify it under the terms of the GNU General Public License
007     * as published by the Free Software Foundation; either version 2
008     * of the License, or (at your option) any later version.
009     *
010     * This program is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013     * GNU General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License
016     * along with this program; if not, write to the Free Software
017     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
018     */
019    
020    package net.jetrix.commands;
021    
022    import static net.jetrix.GameState.*;
023    
024    import java.util.*;
025    
026    import net.jetrix.*;
027    import net.jetrix.messages.channel.StartGameMessage;
028    import net.jetrix.messages.channel.CommandMessage;
029    import net.jetrix.messages.channel.GmsgMessage;
030    import net.jetrix.messages.channel.PlineMessage;
031    
032    /**
033     * Start the game.
034     *
035     * @author Emmanuel Bourg
036     * @version $Revision: 859 $, $Date: 2010-05-06 12:55:26 +0200 (jeu., 06 mai 2010) $
037     */
038    public class StartCommand extends AbstractCommand
039    {
040        public String getAlias()
041        {
042            return "start";
043        }
044    
045        public String getUsage(Locale locale)
046        {
047            return "/start <" + Language.getText("command.params.seconds", locale) + ">";
048        }
049    
050        public void execute(CommandMessage m)
051        {
052            Client client = (Client) m.getSource();
053            Channel channel = client.getChannel();
054    
055            if (channel != null && channel.getGameState() == STOPPED)
056            {
057                // delay in seconds for the countdown
058                int delay = 0;
059    
060                if (m.getParameterCount() > 0)
061                {
062                    delay = m.getIntParameter(0, delay);
063                }
064    
065                // the delay is capped at 20 seconds
066                delay = Math.min(delay, 20);
067    
068                if (delay > 0)
069                {
070                    // tell who started the game
071                    PlineMessage message = new PlineMessage();
072                    message.setKey("channel.game.started-by", client.getUser().getName());
073                    channel.send(message);
074    
075                    (new StartCommand.CountDown(channel, delay)).start();
076                }
077                else
078                {
079                    StartGameMessage start = new StartGameMessage();
080                    start.setSlot(channel.getClientSlot(client));
081                    start.setSource(client);
082                    channel.send(start);
083                }
084            }
085        }
086    
087        /**
088         * A countdown thread to delay the beginning of the game.
089         */
090        public static class CountDown extends Thread
091        {
092            private Channel channel;
093            private int delay;
094            /** */
095            private static Map<Channel, CountDown> countdowns = new HashMap<Channel, CountDown>();
096    
097            /**
098             * Construct a new game countdown.
099             *
100             * @param channel the channel where game will start
101             * @param delay   the delay in seconds for this countdown
102             */
103            public CountDown(Channel channel, int delay)
104            {
105                this.channel = channel;
106                this.delay = delay;
107            }
108    
109            public void run()
110            {
111                // don't start the countdown is the game has already started
112                if (channel.getGameState() != STOPPED) return;
113    
114                // don't start the countdown if another one is already running
115                if (countdowns.get(channel) != null) return;
116                countdowns.put(channel, this);
117    
118                PlineMessage getready1 = new PlineMessage();
119                GmsgMessage getready2 = new GmsgMessage();
120                getready1.setKey("command.start.get_ready");
121                getready2.setKey("command.start.get_ready");
122                channel.send(getready1);
123                channel.send(getready2);
124    
125                // start the count down...
126                for (int i = delay; i > 0; i--)
127                {
128                    PlineMessage msg1 = new PlineMessage();
129                    GmsgMessage msg2 = new GmsgMessage();
130    
131                    // plural or singular ? :)
132                    String key = "command.start.second" + (i > 1 ? "s" : "");
133                    msg1.setKey(key, i);
134                    msg2.setKey(key, i);
135                    
136                    channel.send(msg1);
137                    channel.send(msg2);
138                    try
139                    {
140                        sleep(1000);
141                    }
142                    catch (InterruptedException e)
143                    {
144                    }
145    
146                    // cancel the countdown if the game has started
147                    if (channel.getGameState() != STOPPED)
148                    {
149                        countdowns.put(channel, null);
150                        return;
151                    }
152                }
153    
154                // announce "GO!"
155                PlineMessage go1 = new PlineMessage();
156                GmsgMessage go2 = new GmsgMessage();
157                go1.setKey("command.start.go");
158                go2.setKey("command.start.go");
159                channel.send(go1);
160                channel.send(go2);
161    
162                // start the game
163                StartGameMessage start = new StartGameMessage();
164                channel.send(start);
165    
166                countdowns.put(channel, null);
167            }
168        }
169    }