001 /**
002 * Jetrix TetriNET Server
003 * Copyright (C) 2001-2003 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 java.util.*;
023
024 import net.jetrix.*;
025 import net.jetrix.messages.channel.CommandMessage;
026 import net.jetrix.messages.channel.PlineMessage;
027
028 /**
029 * CommandManager
030 *
031 * @author Emmanuel Bourg
032 * @version $Revision: 798 $, $Date: 2009-02-18 16:24:28 +0100 (Wed, 18 Feb 2009) $
033 */
034 public class CommandManager
035 {
036 private static CommandManager instance = new CommandManager();
037
038 /** aliases->commands Map */
039 private Map<String, Command> commands;
040
041 /** Set of commands sorted alphabetically by the main alias */
042 private Map<String, Command> commandSet;
043
044 private CommandManager()
045 {
046 commands = new TreeMap<String, Command>();
047 commandSet = new TreeMap<String, Command>();
048 }
049
050 public static CommandManager getInstance()
051 {
052 return instance;
053 }
054
055 /**
056 * Register a new command.
057 */
058 public void addCommand(Command command)
059 {
060 for (String alias : command.getAliases())
061 {
062 addCommandAlias(command, alias);
063 }
064
065 if (command.getAliases().length > 0)
066 {
067 commandSet.put(command.getAliases()[0], command);
068 }
069 }
070
071 /**
072 * Register a new alias for a command.
073 */
074 public void addCommandAlias(Command command, String alias)
075 {
076 commands.put(alias.toLowerCase(), command);
077 }
078
079 /**
080 * Remove a command.
081 */
082 public void removeCommand(Command command)
083 {
084 Iterator<String> aliases = commands.keySet().iterator();
085 while (aliases.hasNext())
086 {
087 if (commands.get(aliases.next()).getClass().equals(command.getClass()))
088 {
089 aliases.remove();
090 }
091 }
092
093 Iterator<Command> cmds = commandSet.values().iterator();
094 while (cmds.hasNext())
095 {
096 if (cmds.next().getClass().equals(command.getClass()))
097 {
098 cmds.remove();
099 }
100 }
101 }
102
103 /**
104 * Return the command matching the specified alias. The alias is not
105 * case sensitive. If no command matches the exact alias specified,
106 * it will return the first command starting with the alias.
107 */
108 public Command getCommand(String alias)
109 {
110 alias = alias.toLowerCase();
111 Command command = commands.get(alias);
112
113 if (command == null)
114 {
115 Iterator<String> aliases = commands.keySet().iterator();
116 while (command == null && aliases.hasNext())
117 {
118 String name = aliases.next();
119 if (name.startsWith(alias))
120 {
121 command = commands.get(name);
122 }
123 }
124 }
125
126 return command;
127 }
128
129 /**
130 * Return all commands available to clients with the lowest
131 * access level.
132 */
133 public Iterator<Command> getCommands()
134 {
135 return getCommands(AccessLevel.PLAYER);
136 }
137
138 /**
139 * Return all commands available to clients with the specified
140 * access level.
141 */
142 public Iterator<Command> getCommands(final int accessLevel)
143 {
144 List<Command> commands = new ArrayList<Command>();
145
146 for (Command command : commandSet.values())
147 {
148 if (command.getAccessLevel() <= accessLevel)
149 {
150 commands.add(command);
151 }
152 }
153
154 return commands.iterator();
155 }
156
157 /**
158 * Execute the command specified in the message. This method checks if
159 * the client has the access level required to use the command.
160 */
161 public void execute(CommandMessage m)
162 {
163 execute(m, getCommand(m.getCommand()));
164 }
165
166 /**
167 * Execute an unregistered command.
168 */
169 public void execute(CommandMessage m, Command command)
170 {
171 Client client = (Client) m.getSource();
172 if (command == null)
173 {
174 PlineMessage response = new PlineMessage();
175 response.setKey("command.invalid");
176 client.send(response);
177 }
178 else
179 {
180 // check the access level
181 if (client.getUser().getAccessLevel() >= command.getAccessLevel())
182 {
183 // check the number of parameters
184 if (command instanceof ParameterCommand && m.getParameterCount() < ((ParameterCommand) command).getParameterCount())
185 {
186 // not enough parameters
187 PlineMessage response = new PlineMessage();
188 response.setText(colorizeUsage(command.getUsage(client.getUser().getLocale())));
189 client.send(response);
190 return;
191 }
192
193 // execute the command
194 try
195 {
196 command.execute(m);
197 }
198 catch (Exception e)
199 {
200 e.printStackTrace();
201 }
202 }
203 else
204 {
205 // denying access
206 PlineMessage response = new PlineMessage();
207 response.setKey("command.denied");
208 client.send(response);
209 }
210 }
211 }
212
213 /**
214 * Clear all commands.
215 */
216 public void clear()
217 {
218 commands.clear();
219 commandSet.clear();
220 }
221
222 /**
223 * Return a colorized usage string of the specified command.
224 */
225 String colorizeUsage(String usage)
226 {
227 usage = usage.trim();
228 int i = usage.indexOf(" ");
229
230 StringBuilder colorized = new StringBuilder();
231 colorized.append("<red>");
232
233 if (i > -1)
234 {
235 colorized.append(usage.substring(0, i));
236 colorized.append(" <blue>");
237 colorized.append(usage.substring(i + 1));
238 }
239 else
240 {
241 colorized.append(usage);
242 }
243
244 return colorized.toString();
245 }
246
247 }