001/*
002 * PlotSquared, a land and world management plugin for Minecraft.
003 * Copyright (C) IntellectualSites <https://intellectualsites.com>
004 * Copyright (C) IntellectualSites team and contributors
005 *
006 * This program is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
018 */
019package com.plotsquared.core.generator;
020
021import com.plotsquared.core.configuration.ConfigurationNode;
022import com.plotsquared.core.configuration.ConfigurationSection;
023import com.plotsquared.core.configuration.ConfigurationUtil;
024import com.plotsquared.core.configuration.Settings;
025import com.plotsquared.core.configuration.caption.TranslatableCaption;
026import com.plotsquared.core.configuration.file.YamlConfiguration;
027import com.plotsquared.core.inject.annotations.WorldConfig;
028import com.plotsquared.core.plot.BlockBucket;
029import com.plotsquared.core.plot.PlotId;
030import com.plotsquared.core.queue.GlobalBlockQueue;
031import com.sk89q.worldedit.function.pattern.Pattern;
032import com.sk89q.worldedit.world.block.BlockTypes;
033import org.apache.logging.log4j.LogManager;
034import org.apache.logging.log4j.Logger;
035import org.checkerframework.checker.nullness.qual.NonNull;
036
037import javax.annotation.Nullable;
038
039@SuppressWarnings("WeakerAccess")
040public abstract class ClassicPlotWorld extends SquarePlotWorld {
041
042    private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + ClassicPlotWorld.class.getSimpleName());
043
044    public int ROAD_HEIGHT = 62;
045    public int PLOT_HEIGHT = 62;
046    public int WALL_HEIGHT = 62;
047    public BlockBucket MAIN_BLOCK = new BlockBucket(BlockTypes.STONE);
048    public BlockBucket TOP_BLOCK = new BlockBucket(BlockTypes.GRASS_BLOCK);
049    public BlockBucket WALL_BLOCK = new BlockBucket(BlockTypes.STONE_SLAB);
050    public BlockBucket CLAIMED_WALL_BLOCK = new BlockBucket(BlockTypes.SANDSTONE_SLAB);
051    public BlockBucket WALL_FILLING = new BlockBucket(BlockTypes.STONE);
052    public BlockBucket ROAD_BLOCK = new BlockBucket(BlockTypes.QUARTZ_BLOCK);
053    public boolean PLOT_BEDROCK = true;
054    public boolean PLACE_TOP_BLOCK = true;
055    public boolean COMPONENT_BELOW_BEDROCK = false;
056
057    public ClassicPlotWorld(
058            final @NonNull String worldName,
059            final @Nullable String id,
060            final @NonNull IndependentPlotGenerator generator,
061            final @Nullable PlotId min,
062            final @Nullable PlotId max,
063            @WorldConfig final @NonNull YamlConfiguration worldConfiguration,
064            final @NonNull GlobalBlockQueue blockQueue
065    ) {
066        super(worldName, id, generator, min, max, worldConfiguration, blockQueue);
067    }
068
069    private static BlockBucket createCheckedBlockBucket(String input, BlockBucket def) {
070        final BlockBucket bucket = new BlockBucket(input);
071        Pattern pattern = null;
072        try {
073            pattern = bucket.toPattern();
074        } catch (Exception ignore) {
075        }
076        if (pattern == null) {
077            LOGGER.error("Failed to parse pattern '{}', check your worlds.yml", input);
078            LOGGER.error("Falling back to {}", def);
079            return def;
080        }
081        return bucket;
082    }
083
084    /**
085     * CONFIG NODE | DEFAULT VALUE | DESCRIPTION | CONFIGURATION TYPE | REQUIRED FOR INITIAL SETUP.
086     *
087     * <p>Set the last boolean to false if you do not check a specific config node to be set while using the setup
088     * command - this may be useful if a config value can be changed at a later date, and has no impact on the actual
089     * world generation</p>
090     */
091    @NonNull
092    @Override
093    public ConfigurationNode[] getSettingNodes() {
094        return new ConfigurationNode[]{
095                new ConfigurationNode("plot.height", this.PLOT_HEIGHT, TranslatableCaption.of("setup.plot_height"),
096                        ConfigurationUtil.INTEGER
097                ),
098                new ConfigurationNode("plot.size", this.PLOT_WIDTH, TranslatableCaption.of("setup.plot_width"),
099                        ConfigurationUtil.INTEGER
100                ),
101                new ConfigurationNode("plot.filling", this.MAIN_BLOCK, TranslatableCaption.of("setup.plot_block"),
102                        ConfigurationUtil.BLOCK_BUCKET
103                ),
104                new ConfigurationNode("wall.place_top_block", this.PLACE_TOP_BLOCK,
105                        TranslatableCaption.of("setup.top_block_boolean"), ConfigurationUtil.BOOLEAN
106                ),
107                new ConfigurationNode("plot.floor", this.TOP_BLOCK, TranslatableCaption.of("setup.plot_block_floor"),
108                        ConfigurationUtil.BLOCK_BUCKET
109                ),
110                new ConfigurationNode("wall.block", this.WALL_BLOCK, TranslatableCaption.of("setup.top_wall_block"),
111                        ConfigurationUtil.BLOCK_BUCKET
112                ),
113                new ConfigurationNode("wall.block_claimed", this.CLAIMED_WALL_BLOCK,
114                        TranslatableCaption.of("setup.wall_block_claimed"), ConfigurationUtil.BLOCK_BUCKET
115                ),
116                new ConfigurationNode("road.width", this.ROAD_WIDTH, TranslatableCaption.of("setup.road_width"),
117                        ConfigurationUtil.INTEGER
118                ),
119                new ConfigurationNode("road.height", this.ROAD_HEIGHT, TranslatableCaption.of("setup.road_height"),
120                        ConfigurationUtil.INTEGER
121                ),
122                new ConfigurationNode("road.block", this.ROAD_BLOCK, TranslatableCaption.of("setup.road_block"),
123                        ConfigurationUtil.BLOCK_BUCKET
124                ),
125                new ConfigurationNode("wall.filling", this.WALL_FILLING, TranslatableCaption.of("setup.wall_filling_block"),
126                        ConfigurationUtil.BLOCK_BUCKET
127                ),
128                new ConfigurationNode("wall.height", this.WALL_HEIGHT, TranslatableCaption.of("setup.wall_height"),
129                        ConfigurationUtil.INTEGER
130                ),
131                new ConfigurationNode("plot.bedrock", this.PLOT_BEDROCK, TranslatableCaption.of("setup.bedrock_boolean"),
132                        ConfigurationUtil.BOOLEAN
133                ),
134                new ConfigurationNode("world.component_below_bedrock", this.COMPONENT_BELOW_BEDROCK, TranslatableCaption.of(
135                        "setup.component_below_bedrock_boolean"), ConfigurationUtil.BOOLEAN
136                )};
137    }
138
139    /**
140     * This method is called when a world loads. Make sure you set all your constants here. You are provided with the
141     * configuration section for that specific world.
142     */
143    @Override
144    public void loadConfiguration(ConfigurationSection config) {
145        super.loadConfiguration(config);
146        this.PLOT_BEDROCK = config.getBoolean("plot.bedrock");
147        this.PLOT_HEIGHT = Math.min(getMaxGenHeight(), config.getInt("plot.height"));
148        this.MAIN_BLOCK = createCheckedBlockBucket(config.getString("plot.filling"), MAIN_BLOCK);
149        this.TOP_BLOCK = createCheckedBlockBucket(config.getString("plot.floor"), TOP_BLOCK);
150        this.WALL_BLOCK = createCheckedBlockBucket(config.getString("wall.block"), WALL_BLOCK);
151        this.ROAD_HEIGHT = Math.min(getMaxGenHeight(), config.getInt("road.height"));
152        this.ROAD_BLOCK = createCheckedBlockBucket(config.getString("road.block"), ROAD_BLOCK);
153        this.WALL_FILLING = createCheckedBlockBucket(config.getString("wall.filling"), WALL_FILLING);
154        this.PLACE_TOP_BLOCK = config.getBoolean("wall.place_top_block");
155        this.WALL_HEIGHT = Math.min(getMaxGenHeight() - (PLACE_TOP_BLOCK ? 1 : 0), config.getInt("wall.height"));
156        this.CLAIMED_WALL_BLOCK = createCheckedBlockBucket(config.getString("wall.block_claimed"), CLAIMED_WALL_BLOCK);
157        this.COMPONENT_BELOW_BEDROCK = config.getBoolean("world.component_below_bedrock");
158    }
159
160    @Override
161    public int getMinComponentHeight() {
162        return COMPONENT_BELOW_BEDROCK && getMinGenHeight() >= getMinBuildHeight()
163                ? getMinGenHeight() + (PLOT_BEDROCK ? 1 : 0)
164                : getMinBuildHeight();
165    }
166
167    int schematicStartHeight() {
168        int plotRoadMin = Math.min(PLOT_HEIGHT, ROAD_HEIGHT);
169        if (!Settings.Schematics.USE_WALL_IN_ROAD_SCHEM_HEIGHT) {
170            return plotRoadMin;
171        }
172        return Math.min(WALL_HEIGHT, plotRoadMin);
173    }
174
175}