001    package org.bukkit;
002    
003    import java.util.Random;
004    import org.bukkit.command.CommandSender;
005    import org.bukkit.generator.ChunkGenerator;
006    import org.bukkit.plugin.Plugin;
007    
008    /**
009     * Represents various types of options that may be used to create a world.
010     */
011    public class WorldCreator {
012        private final String name;
013        private long seed;
014        private World.Environment environment = World.Environment.NORMAL;
015        private ChunkGenerator generator = null;
016        private WorldType type = WorldType.NORMAL;
017        private boolean generateStructures = true;
018    
019        /**
020         * Creates an empty WorldCreationOptions for the given world name
021         *
022         * @param name Name of the world that will be created
023         */
024        public WorldCreator(String name) {
025            if (name == null) {
026                throw new IllegalArgumentException("World name cannot be null");
027            }
028    
029            this.name = name;
030            this.seed = (new Random()).nextLong();
031        }
032    
033        /**
034         * Copies the options from the specified world
035         *
036         * @param world World to copy options from
037         * @return This object, for chaining
038         */
039        public WorldCreator copy(World world) {
040            if (world == null) {
041                throw new IllegalArgumentException("World cannot be null");
042            }
043    
044            seed = world.getSeed();
045            environment = world.getEnvironment();
046            generator = world.getGenerator();
047    
048            return this;
049        }
050    
051        /**
052         * Copies the options from the specified {@link WorldCreator}
053         *
054         * @param creator World creator to copy options from
055         * @return This object, for chaining
056         */
057        public WorldCreator copy(WorldCreator creator) {
058            if (creator == null) {
059                throw new IllegalArgumentException("Creator cannot be null");
060            }
061    
062            seed = creator.seed();
063            environment = creator.environment();
064            generator = creator.generator();
065    
066            return this;
067        }
068    
069        /**
070         * Gets the name of the world that is to be loaded or created.
071         *
072         * @return World name
073         */
074        public String name() {
075            return name;
076        }
077    
078        /**
079         * Gets the seed that will be used to create this world
080         *
081         * @return World seed
082         */
083        public long seed() {
084            return seed;
085        }
086    
087        /**
088         * Sets the seed that will be used to create this world
089         *
090         * @param seed World seed
091         * @return This object, for chaining
092         */
093        public WorldCreator seed(long seed) {
094            this.seed = seed;
095    
096            return this;
097        }
098    
099        /**
100         * Gets the environment that will be used to create or load the world
101         *
102         * @return World environment
103         */
104        public World.Environment environment() {
105            return environment;
106        }
107    
108        /**
109         * Sets the environment that will be used to create or load the world
110         *
111         * @param env World environment
112         * @return This object, for chaining
113         */
114        public WorldCreator environment(World.Environment env) {
115            this.environment = env;
116    
117            return this;
118        }
119    
120        /**
121         * Gets the type of the world that will be created or loaded
122         *
123         * @return World type
124         */
125        public WorldType type() {
126            return type;
127        }
128    
129        /**
130         * Sets the type of the world that will be created or loaded
131         *
132         * @param type World type
133         * @return This object, for chaining
134         */
135        public WorldCreator type(WorldType type) {
136            this.type = type;
137    
138            return this;
139        }
140    
141        /**
142         * Gets the generator that will be used to create or load the world.
143         * <p>
144         * This may be null, in which case the "natural" generator for this
145         * environment will be used.
146         *
147         * @return Chunk generator
148         */
149        public ChunkGenerator generator() {
150            return generator;
151        }
152    
153        /**
154         * Sets the generator that will be used to create or load the world.
155         * <p>
156         * This may be null, in which case the "natural" generator for this
157         * environment will be used.
158         *
159         * @param generator Chunk generator
160         * @return This object, for chaining
161         */
162        public WorldCreator generator(ChunkGenerator generator) {
163            this.generator = generator;
164    
165            return this;
166        }
167    
168        /**
169         * Sets the generator that will be used to create or load the world.
170         * <p>
171         * This may be null, in which case the "natural" generator for this
172         * environment will be used.
173         * <p>
174         * If the generator cannot be found for the given name, the natural
175         * environment generator will be used instead and a warning will be
176         * printed to the console.
177         *
178         * @param generator Name of the generator to use, in "plugin:id" notation
179         * @return This object, for chaining
180         */
181        public WorldCreator generator(String generator) {
182            this.generator = getGeneratorForName(name, generator, Bukkit.getConsoleSender());
183    
184            return this;
185        }
186    
187        /**
188         * Sets the generator that will be used to create or load the world.
189         * <p>
190         * This may be null, in which case the "natural" generator for this
191         * environment will be used.
192         * <p>
193         * If the generator cannot be found for the given name, the natural
194         * environment generator will be used instead and a warning will be
195         * printed to the specified output
196         *
197         * @param generator Name of the generator to use, in "plugin:id" notation
198         * @param output {@link CommandSender} that will receive any error
199         *     messages
200         * @return This object, for chaining
201         */
202        public WorldCreator generator(String generator, CommandSender output) {
203            this.generator = getGeneratorForName(name, generator, output);
204    
205            return this;
206        }
207    
208        /**
209         * Sets whether or not worlds created or loaded with this creator will
210         * have structures.
211         *
212         * @param generate Whether to generate structures
213         * @return This object, for chaining
214         */
215        public WorldCreator generateStructures(boolean generate) {
216            this.generateStructures = generate;
217    
218            return this;
219        }
220    
221        /**
222         * Gets whether or not structures will be generated in the world.
223         *
224         * @return True if structures will be generated
225         */
226        public boolean generateStructures() {
227            return generateStructures;
228        }
229    
230        /**
231         * Creates a world with the specified options.
232         * <p>
233         * If the world already exists, it will be loaded from disk and some
234         * options may be ignored.
235         *
236         * @return Newly created or loaded world
237         */
238        public World createWorld() {
239            return Bukkit.createWorld(this);
240        }
241    
242        /**
243         * Creates a new {@link WorldCreator} for the given world name
244         *
245         * @param name Name of the world to load or create
246         * @return Resulting WorldCreator
247         */
248        public static WorldCreator name(String name) {
249            return new WorldCreator(name);
250        }
251    
252        /**
253         * Attempts to get the {@link ChunkGenerator} with the given name.
254         * <p>
255         * If the generator is not found, null will be returned and a message will
256         * be printed to the specified {@link CommandSender} explaining why.
257         * <p>
258         * The name must be in the "plugin:id" notation, or optionally just
259         * "plugin", where "plugin" is the safe-name of a plugin and "id" is an
260         * optional unique identifier for the generator you wish to request from
261         * the plugin.
262         *
263         * @param world Name of the world this will be used for
264         * @param name Name of the generator to retrieve
265         * @param output Where to output if errors are present
266         * @return Resulting generator, or null
267         */
268        public static ChunkGenerator getGeneratorForName(String world, String name, CommandSender output) {
269            ChunkGenerator result = null;
270    
271            if (world == null) {
272                throw new IllegalArgumentException("World name must be specified");
273            }
274    
275            if (output == null) {
276                output = Bukkit.getConsoleSender();
277            }
278    
279            if (name != null) {
280                String[] split = name.split(":", 2);
281                String id = (split.length > 1) ? split[1] : null;
282                Plugin plugin = Bukkit.getPluginManager().getPlugin(split[0]);
283    
284                if (plugin == null) {
285                    output.sendMessage("Could not set generator for world '" + world + "': Plugin '" + split[0] + "' does not exist");
286                } else if (!plugin.isEnabled()) {
287                    output.sendMessage("Could not set generator for world '" + world + "': Plugin '" + plugin.getDescription().getFullName() + "' is not enabled");
288                } else {
289                    result = plugin.getDefaultWorldGenerator(world, id);
290                }
291            }
292    
293            return result;
294        }
295    }