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.plot.flag.types;
020
021import com.plotsquared.core.configuration.caption.Caption;
022import com.plotsquared.core.configuration.caption.TranslatableCaption;
023import com.plotsquared.core.plot.flag.FlagParseException;
024import com.plotsquared.core.util.BlockUtil;
025import com.sk89q.worldedit.world.block.BlockCategory;
026import com.sk89q.worldedit.world.block.BlockState;
027import com.sk89q.worldedit.world.block.BlockType;
028import org.checkerframework.checker.nullness.qual.NonNull;
029
030import java.util.ArrayList;
031import java.util.Collection;
032import java.util.List;
033import java.util.stream.Collectors;
034
035public abstract class BlockTypeListFlag<F extends ListFlag<BlockTypeWrapper, F>>
036        extends ListFlag<BlockTypeWrapper, F> {
037
038    public static boolean skipCategoryVerification = false;
039
040    protected BlockTypeListFlag(List<BlockTypeWrapper> blockTypeList, Caption description) {
041        super(blockTypeList, TranslatableCaption.of("flags.flag_category_block_list"), description);
042    }
043
044    @Override
045    public F parse(@NonNull String input) throws FlagParseException {
046        final List<BlockTypeWrapper> parsedBlocks = new ArrayList<>();
047        final String[] split = input.replaceAll("\\s+", "").split(",(?![^\\(\\[]*[\\]\\)])");
048        if (split.length == 0) {
049            return this.flagOf(parsedBlocks);
050        }
051        for (final String blockString : split) {
052            final BlockTypeWrapper blockTypeWrapper;
053            final BlockState blockState = BlockUtil.get(blockString);
054            if (blockState == null) {
055                // If it's not a block state, we assume it's a block category
056                blockTypeWrapper = getCategory(blockString);
057            } else {
058                blockTypeWrapper = BlockTypeWrapper.get(blockState.getBlockType());
059            }
060            if (!parsedBlocks.contains(blockTypeWrapper)) {
061                parsedBlocks.add(blockTypeWrapper);
062            }
063        }
064        return this.flagOf(parsedBlocks);
065    }
066
067    @Override
068    public String getExample() {
069        return "air,grass_block";
070    }
071
072    @Override
073    public Collection<String> getTabCompletions() {
074        final Collection<String> tabCompletions = new ArrayList<>();
075        tabCompletions.addAll(
076                BlockType.REGISTRY.keySet().stream().map(val -> val.replace("minecraft:", ""))
077                        .collect(Collectors.toList()));
078        tabCompletions.addAll(
079                BlockCategory.REGISTRY.keySet().stream().map(val -> "#" + val.replace("minecraft:", ""))
080                        .collect(Collectors.toList()));
081        return tabCompletions;
082    }
083
084    private BlockTypeWrapper getCategory(final String blockString) throws FlagParseException {
085        if (!blockString.startsWith("#")) {
086            throw new FlagParseException(this, blockString, TranslatableCaption.of("flags.flag_error_invalid_block"));
087        }
088        String categoryId = blockString.substring(1);
089        BlockTypeWrapper blockTypeWrapper;
090        if (skipCategoryVerification) {
091            blockTypeWrapper = BlockTypeWrapper.get(categoryId);
092        } else {
093            BlockCategory blockCategory = BlockCategory.REGISTRY.get(categoryId);
094            if (blockCategory == null) {
095                throw new FlagParseException(this, blockString, TranslatableCaption.of("flags.flag_error_invalid_block"));
096            }
097            blockTypeWrapper = BlockTypeWrapper.get(blockCategory);
098        }
099        return blockTypeWrapper;
100    }
101
102}