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.configuration;
020
021import com.plotsquared.core.plot.BlockBucket;
022import com.plotsquared.core.plot.PlotAreaTerrainType;
023import com.plotsquared.core.plot.PlotAreaType;
024import com.plotsquared.core.util.MathMan;
025import com.sk89q.worldedit.function.pattern.Pattern;
026import com.sk89q.worldedit.world.biome.BiomeType;
027import com.sk89q.worldedit.world.biome.BiomeTypes;
028import com.sk89q.worldedit.world.block.BlockState;
029import org.checkerframework.checker.nullness.qual.NonNull;
030
031import java.util.Optional;
032import java.util.function.Function;
033import java.util.function.IntFunction;
034import java.util.function.Supplier;
035
036/**
037 * Main Configuration Utility
038 */
039public class ConfigurationUtil {
040
041    public static final SettingValue<Integer> INTEGER = new SettingValue<>("INTEGER") {
042        @Override
043        public boolean validateValue(String string) {
044            try {
045                Integer.parseInt(string);
046                return true;
047            } catch (NumberFormatException ignored) {
048                return false;
049            }
050        }
051
052        @Override
053        public Integer parseString(String string) {
054            return Integer.parseInt(string);
055        }
056    };
057    public static final SettingValue<Boolean> BOOLEAN = new SettingValue<>("BOOLEAN") {
058        @Override
059        public boolean validateValue(String string) {
060            //noinspection ResultOfMethodCallIgnored
061            Boolean.parseBoolean(string);
062            return true;
063        }
064
065        @Override
066        public Boolean parseString(String string) {
067            return Boolean.parseBoolean(string);
068        }
069    };
070    public static final SettingValue<BiomeType> BIOME = new SettingValue<>("BIOME") {
071        @Override
072        public boolean validateValue(String string) {
073            try {
074                return BiomeTypes.get(string) != null;
075            } catch (Exception ignored) {
076                return false;
077            }
078        }
079
080        @Override
081        public BiomeType parseString(String string) {
082            if (validateValue(string)) {
083                return BiomeTypes.get(string.toLowerCase());
084            }
085            return BiomeTypes.FOREST;
086        }
087    };
088
089    public static final SettingValue<BlockBucket> BLOCK_BUCKET =
090            new SettingValue<>("BLOCK_BUCKET") {
091
092                @Override
093                public BlockBucket parseString(final String string) {
094                    BlockBucket bucket = new BlockBucket(string);
095                    bucket.compile();
096                    Pattern pattern = bucket.toPattern();
097                    return pattern != null ? bucket : null;
098                }
099
100                @Override
101                public boolean validateValue(final String string) {
102                    try {
103                        return parseString(string) != null;
104                    } catch (Exception e) {
105                        return false;
106                    }
107                }
108            };
109
110    private static <T> T getValueFromConfig(
111            ConfigurationSection config, String path,
112            IntFunction<Optional<T>> intParser, Function<String, Optional<T>> textualParser,
113            Supplier<T> defaultValue
114    ) {
115        String value = config.getString(path);
116        if (value == null) {
117            return defaultValue.get();
118        }
119        if (MathMan.isInteger(value)) {
120            return intParser.apply(Integer.parseInt(value)).orElseGet(defaultValue);
121        }
122        return textualParser.apply(value).orElseGet(defaultValue);
123    }
124
125    public static PlotAreaType getType(ConfigurationSection config) {
126        return getValueFromConfig(config, "generator.type", PlotAreaType::fromLegacyInt,
127                PlotAreaType::fromString, () -> PlotAreaType.NORMAL
128        );
129    }
130
131    public static PlotAreaTerrainType getTerrain(ConfigurationSection config) {
132        return getValueFromConfig(config, "generator.terrain", PlotAreaTerrainType::fromLegacyInt,
133                PlotAreaTerrainType::fromString, () -> PlotAreaTerrainType.NONE
134        );
135    }
136
137
138    public static final class UnknownBlockException extends IllegalArgumentException {
139
140        private final String unknownValue;
141
142        UnknownBlockException(final @NonNull String unknownValue) {
143            super(String.format("\"%s\" is not a valid block", unknownValue));
144            this.unknownValue = unknownValue;
145        }
146
147        public String getUnknownValue() {
148            return this.unknownValue;
149        }
150
151    }
152
153
154    /**
155     * Create your own SettingValue object to make the management of plotworld configuration easier
156     */
157    public abstract static class SettingValue<T> {
158
159        private final String type;
160
161        SettingValue(String type) {
162            this.type = type;
163        }
164
165        public String getType() {
166            return this.type;
167        }
168
169        public abstract T parseString(String string);
170
171        public abstract boolean validateValue(String string);
172
173    }
174
175
176    public static final class UnsafeBlockException extends IllegalArgumentException {
177
178        private final BlockState unsafeBlock;
179
180        UnsafeBlockException(final @NonNull BlockState unsafeBlock) {
181            super(String.format("%s is not a valid block", unsafeBlock));
182            this.unsafeBlock = unsafeBlock;
183        }
184
185        public BlockState getUnsafeBlock() {
186            return this.unsafeBlock;
187        }
188
189    }
190
191}