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.world;
020
021import com.google.inject.Inject;
022import com.google.inject.Singleton;
023import com.plotsquared.core.collection.ArrayUtil;
024import com.plotsquared.core.configuration.file.YamlConfiguration;
025import com.plotsquared.core.generator.SingleWorldGenerator;
026import com.plotsquared.core.inject.annotations.WorldConfig;
027import com.plotsquared.core.listener.PlotListener;
028import com.plotsquared.core.location.Location;
029import com.plotsquared.core.plot.PlotArea;
030import com.plotsquared.core.queue.GlobalBlockQueue;
031import com.plotsquared.core.util.EventDispatcher;
032import com.plotsquared.core.util.SetupUtils;
033import com.sk89q.worldedit.regions.CuboidRegion;
034import org.checkerframework.checker.nullness.qual.NonNull;
035import org.checkerframework.checker.nullness.qual.Nullable;
036
037@Singleton
038public class SinglePlotAreaManager extends DefaultPlotAreaManager {
039
040    private final SinglePlotArea[] array;
041    private SinglePlotArea area;
042    private PlotArea[] all;
043
044    @Inject
045    public SinglePlotAreaManager(
046            final @NonNull EventDispatcher eventDispatcher,
047            final @NonNull PlotListener plotListener,
048            @WorldConfig final @NonNull YamlConfiguration worldConfiguration,
049            final @NonNull GlobalBlockQueue blockQueue
050    ) {
051        this.area = new SinglePlotArea(this, eventDispatcher, plotListener,
052                worldConfiguration, blockQueue
053        );
054        this.array = new SinglePlotArea[]{area};
055        this.all = new PlotArea[]{area};
056        SetupUtils.generators.put(
057                "PlotSquared:single",
058                new SingleWorldGenerator(this).specify("CheckingPlotSquaredGenerator")
059        );
060    }
061
062    public SinglePlotArea getArea() {
063        return area;
064    }
065
066    public void setArea(final @NonNull SinglePlotArea area) {
067        this.area = area;
068        array[0] = area;
069        all = ArrayUtil.concatAll(super.getAllPlotAreas(), array);
070    }
071
072    public boolean isWorld(final @NonNull String id) {
073        char[] chars = id.toCharArray();
074        if (chars.length == 1 && chars[0] == '*') {
075            return true;
076        }
077        int mode = 0;
078        for (char c : chars) {
079            switch (mode) {
080                case 0:
081                    mode = 1;
082                    if (c == '-') {
083                        continue;
084                    }
085                case 1:
086                    if ((c <= '/') || (c >= ':')) {
087                        if (c == '_') {
088                            mode = 2;
089                            continue;
090                        }
091                        return false;
092                    } else {
093                        continue;
094                    }
095                case 2:
096                    mode = 3;
097                    if (c == '-') {
098                        continue;
099                    }
100                case 3:
101                    if ((c <= '/') || (c >= ':')) {
102                        return false;
103                    }
104            }
105        }
106        return mode == 3;
107    }
108
109    @Override
110    public @Nullable PlotArea getApplicablePlotArea(final @Nullable Location location) {
111        if (location == null) {
112            return null;
113        }
114        String world = location.getWorldName();
115        return isWorld(world) || world.equals("*") || super.getAllPlotAreas().length == 0 ?
116                area :
117                super.getApplicablePlotArea(location);
118    }
119
120    @Override
121    public @Nullable PlotArea getPlotArea(final @NonNull String world, final @NonNull String id) {
122        PlotArea found = super.getPlotArea(world, id);
123        if (found != null) {
124            return found;
125        }
126        return isWorld(world) || world.equals("*") ? area : super.getPlotArea(world, id);
127    }
128
129    @Override
130    public @Nullable PlotArea getPlotArea(final @NonNull Location location) {
131        PlotArea found = super.getPlotArea(location);
132        if (found != null) {
133            return found;
134        }
135        return isWorld(location.getWorldName()) || location.getWorldName().equals("*") ? area : null;
136    }
137
138    @Override
139    public @NonNull PlotArea[] getPlotAreas(final @NonNull String world, final @NonNull CuboidRegion region) {
140        PlotArea[] found = super.getPlotAreas(world, region);
141        if (found != null && found.length != 0) {
142            return found;
143        }
144        return isWorld(world) || world.equals("*") ? array : all.length == 0 ? noPlotAreas : found;
145    }
146
147    @Override
148    public @NonNull PlotArea[] getAllPlotAreas() {
149        return all;
150    }
151
152    @Override
153    public @NonNull String[] getAllWorlds() {
154        return super.getAllWorlds();
155    }
156
157    @Override
158    public void addPlotArea(final @NonNull PlotArea area) {
159        if (area == this.area) {
160            return;
161        }
162        super.addPlotArea(area);
163        all = ArrayUtil.concatAll(super.getAllPlotAreas(), array);
164    }
165
166    @Override
167    public void removePlotArea(final @NonNull PlotArea area) {
168        if (area == this.area) {
169            throw new UnsupportedOperationException("Cannot remove base area!");
170        }
171        super.removePlotArea(area);
172    }
173
174    @Override
175    public boolean addWorld(final @NonNull String worldName) {
176        return super.addWorld(worldName);
177    }
178
179    @Override
180    public void removeWorld(final @NonNull String worldName) {
181        super.removeWorld(worldName);
182    }
183
184}