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;
020
021import com.plotsquared.core.command.Template;
022import com.plotsquared.core.configuration.Settings;
023import com.plotsquared.core.location.Location;
024import com.plotsquared.core.player.PlotPlayer;
025import com.plotsquared.core.queue.QueueCoordinator;
026import com.plotsquared.core.util.FileBytes;
027import com.sk89q.worldedit.function.pattern.Pattern;
028import org.checkerframework.checker.nullness.qual.NonNull;
029import org.checkerframework.checker.nullness.qual.Nullable;
030
031import java.io.IOException;
032import java.util.Collections;
033import java.util.HashSet;
034import java.util.List;
035
036public abstract class PlotManager {
037
038    private final PlotArea plotArea;
039
040    public PlotManager(@NonNull PlotArea plotArea) {
041        this.plotArea = plotArea;
042    }
043
044    /*
045     * Plot locations (methods with Abs in them will not need to consider mega
046     * plots).
047     */
048    public abstract PlotId getPlotIdAbs(int x, int y, int z);
049
050    public abstract PlotId getPlotId(int x, int y, int z);
051
052    // If you have a circular plot, just return the corner if it were a square
053    public abstract Location getPlotBottomLocAbs(@NonNull PlotId plotId);
054
055    // the same applies here
056    public abstract Location getPlotTopLocAbs(@NonNull PlotId plotId);
057
058    public abstract boolean clearPlot(
059            @NonNull Plot plot,
060            @Nullable Runnable whenDone,
061            @Nullable PlotPlayer<?> actor,
062            @Nullable QueueCoordinator queue
063    );
064
065    public abstract boolean claimPlot(@NonNull Plot plot, @Nullable QueueCoordinator queue);
066
067    /**
068     * Completes block changes associated with plot unclaim.
069     *
070     * @param plot     plot to unclaim
071     * @param whenDone task to run when plot is unclaimed
072     * @param queue    Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
073     *                 otherwise writes to the queue but does not enqueue.
074     * @return success or not
075     */
076    public abstract boolean unClaimPlot(@NonNull Plot plot, @Nullable Runnable whenDone, @Nullable QueueCoordinator queue);
077
078    /**
079     * Retrieves the location of where a sign should be for a plot.
080     *
081     * @param plot The plot
082     * @return The location where a sign should be
083     */
084    public abstract Location getSignLoc(@NonNull Plot plot);
085
086    /**
087     * Get an array of the plot's component values as string
088     *
089     * @param plotId plotId to get components of
090     * @return array of plot's component values
091     */
092    public abstract String[] getPlotComponents(@NonNull PlotId plotId);
093
094    /**
095     * Set the specified components to the specified Pattern on the specified plot.
096     *
097     * @param plotId    id of plot to set component to
098     * @param component FLOOR, WALL, AIR, MAIN, MIDDLE, OUTLINE, BORDER, ALL (floor, air and main).
099     * @param blocks    Pattern to set component to
100     * @param actor     The player executing the task
101     * @param queue     Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
102     *                  otherwise writes to the queue but does not enqueue.
103     * @return success or not
104     */
105    public abstract boolean setComponent(
106            @NonNull PlotId plotId,
107            @NonNull String component,
108            @NonNull Pattern blocks,
109            @Nullable PlotPlayer<?> actor,
110            @Nullable QueueCoordinator queue
111    );
112
113    /**
114     * Create the road east of the plot (not schematic-based)
115     *
116     * @param plot  plot to create the road for
117     * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
118     *              otherwise writes to the queue but does not enqueue.
119     * @return success or not
120     */
121    public abstract boolean createRoadEast(@NonNull Plot plot, @Nullable QueueCoordinator queue);
122
123    /**
124     * Create the road south of the plot (not schematic-based)
125     *
126     * @param plot  plot to create the road for
127     * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
128     *              otherwise writes to the queue but does not enqueue.
129     * @return success or not
130     */
131    public abstract boolean createRoadSouth(@NonNull Plot plot, @Nullable QueueCoordinator queue);
132
133    /**
134     * Create the south-east corner of the road (intersection, not schematic-based)
135     *
136     * @param plot  plot to create the road for
137     * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
138     *              otherwise writes to the queue but does not enqueue.
139     * @return success or not
140     */
141    public abstract boolean createRoadSouthEast(@NonNull Plot plot, @Nullable QueueCoordinator queue);
142
143    /**
144     * Replace the road to the east of the plot with standard plot blocks (for when merging plots)
145     *
146     * @param plot  plot to remove east road from
147     * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
148     *              otherwise writes to the queue but does not enqueue.
149     * @return success or not
150     */
151    public abstract boolean removeRoadEast(@NonNull Plot plot, @Nullable QueueCoordinator queue);
152
153    /**
154     * Replace the road to the south of the plot with standard plot blocks (for when merging plots)
155     *
156     * @param plot  plot to remove south road from
157     * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
158     *              otherwise writes to the queue but does not enqueue.
159     * @return success or not
160     */
161    public abstract boolean removeRoadSouth(@NonNull Plot plot, @Nullable QueueCoordinator queue);
162
163    /**
164     * Replace the road to the south east of the plot (intersection) with standard plot blocks (for when merging plots)
165     *
166     * @param plot  plot to remove south east road intersection from
167     * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
168     *              otherwise writes to the queue but does not enqueue.
169     * @return success or not
170     */
171    public abstract boolean removeRoadSouthEast(@NonNull Plot plot, @Nullable QueueCoordinator queue);
172
173    public abstract boolean startPlotMerge(@NonNull List<PlotId> plotIds, @Nullable QueueCoordinator queue);
174
175    public abstract boolean startPlotUnlink(@NonNull List<PlotId> plotIds, @Nullable QueueCoordinator queue);
176
177    /**
178     * Finishing off plot merging by adding in the walls surrounding the plot (OPTIONAL)(UNFINISHED).
179     *
180     * @param plotIds list of PlotIds to finish the merge for
181     * @param queue   Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
182     *                otherwise writes to the queue but does not enqueue.
183     * @return {@code false} if part if the merge failed, otherwise {@code true} if successful.
184     */
185    public abstract boolean finishPlotMerge(@NonNull List<PlotId> plotIds, @Nullable QueueCoordinator queue);
186
187    /**
188     * Finished off an unlink by resetting the top wall block for unlinked plots
189     *
190     * @param plotIds list of PlotIds to reset the top wall block of
191     * @param queue   Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
192     *                otherwise writes to the queue but does not enqueue.
193     * @return success or not
194     */
195    public abstract boolean finishPlotUnlink(@NonNull List<PlotId> plotIds, @Nullable QueueCoordinator queue);
196
197    public void exportTemplate() throws IOException {
198        HashSet<FileBytes> files =
199                new HashSet<>(Collections.singletonList(new FileBytes(
200                        Settings.Paths.TEMPLATES + "/tmp-data.yml",
201                        Template.getBytes(plotArea)
202                )));
203        Template.zipAll(plotArea.getWorldName(), files);
204    }
205
206    /**
207     * @return the world height
208     * @deprecated In favor of custom world heights within 1.17 and therefore scheduled for removal without replacement
209     */
210    @Deprecated(forRemoval = true, since = "6.0.0")
211    public int getWorldHeight() {
212        return 255;
213    }
214
215    /**
216     * Sets all the blocks along all the plot walls to their correct state (claimed or unclaimed).
217     *
218     * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
219     *              otherwise writes to the queue but does not enqueue.
220     * @return {@code true} if the wall blocks were successfully set
221     */
222    public boolean regenerateAllPlotWalls(@Nullable QueueCoordinator queue) {
223        boolean success = true;
224        for (Plot plot : plotArea.getPlots()) {
225            if (plot.hasOwner()) {
226                success &= claimPlot(plot, queue);
227            } else {
228                success &= unClaimPlot(plot, null, queue);
229            }
230        }
231        return success;
232    }
233
234}