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.PlotSquared;
022import com.plotsquared.core.database.DBFunc;
023import com.plotsquared.core.location.BlockLoc;
024import com.plotsquared.core.location.Location;
025import com.plotsquared.core.util.RegionUtil;
026import com.sk89q.worldedit.regions.CuboidRegion;
027import org.checkerframework.checker.nullness.qual.NonNull;
028import org.checkerframework.checker.nullness.qual.Nullable;
029
030import java.util.HashSet;
031import java.util.UUID;
032import java.util.function.Consumer;
033
034public class PlotCluster {
035
036    public PlotArea area;
037    public PlotSettings settings;
038    public UUID owner;
039    public HashSet<UUID> helpers = new HashSet<>();
040    public HashSet<UUID> invited = new HashSet<>();
041    public int temp;
042    private PlotId pos1;
043    private PlotId pos2;
044    private CuboidRegion region;
045
046    public PlotCluster(PlotArea area, PlotId pos1, PlotId pos2, UUID owner) {
047        this.area = area;
048        this.pos1 = pos1;
049        this.pos2 = pos2;
050        this.owner = owner;
051        this.settings = new PlotSettings();
052        this.temp = -1;
053        setRegion();
054    }
055
056    public PlotCluster(PlotArea area, PlotId pos1, PlotId pos2, UUID owner, int temp) {
057        this.area = area;
058        this.pos1 = pos1;
059        this.pos2 = pos2;
060        this.owner = owner;
061        this.settings = new PlotSettings();
062        this.temp = temp;
063        setRegion();
064    }
065
066    public PlotId getP1() {
067        return this.pos1;
068    }
069
070    public void setP1(PlotId id) {
071        this.pos1 = id;
072        setRegion();
073    }
074
075    public PlotId getP2() {
076        return this.pos2;
077    }
078
079    public void setP2(PlotId id) {
080        this.pos2 = id;
081        setRegion();
082    }
083
084    private void setRegion() {
085        this.region = RegionUtil.createRegion(this.pos1.getX(), this.pos2.getX(), 0, 0,
086                this.pos1.getY(), this.pos2.getY()
087        );
088    }
089
090    /**
091     * Returns a region of PlotIDs
092     *
093     * @deprecated - returns region of IDs, not of actual blocks.
094     */
095    @Deprecated
096    public CuboidRegion getRegion() {
097        return this.region;
098    }
099
100    public boolean isOwner(UUID uuid) {
101        return uuid.equals(owner);
102    }
103
104    public boolean isAdded(UUID uuid) {
105        return this.owner.equals(uuid) || this.invited.contains(uuid) || this.invited
106                .contains(DBFunc.EVERYONE) || this.helpers.contains(uuid) || this.helpers
107                .contains(DBFunc.EVERYONE);
108    }
109
110    public boolean hasHelperRights(UUID uuid) {
111        return this.owner.equals(uuid) || this.helpers.contains(uuid) || this.helpers
112                .contains(DBFunc.EVERYONE);
113    }
114
115    public String getName() {
116        return this.settings.getAlias();
117    }
118
119    /**
120     * Get the area (in plots).
121     *
122     * @return area of plots
123     */
124    public int getArea() {
125        return (1 + this.pos2.getX() - this.pos1.getX()) * (1 + this.pos2.getY() - this.pos1.getY());
126    }
127
128    public void setArea(PlotArea plotArea) {
129        if (this.area != null) {
130            this.area.removeCluster(this);
131        }
132        this.area = plotArea;
133        plotArea.addCluster(this);
134    }
135
136    @Override
137    public int hashCode() {
138        return this.pos1.hashCode();
139    }
140
141    @Override
142    public boolean equals(Object obj) {
143        if (this == obj) {
144            return true;
145        }
146        if (obj == null) {
147            return false;
148        }
149        if (getClass() != obj.getClass()) {
150            return false;
151        }
152        PlotCluster other = (PlotCluster) obj;
153        return this.pos1.equals(other.pos1) && this.pos2.equals(other.pos2) && this.area
154                .equals(other.area);
155    }
156
157    @Override
158    public String toString() {
159        return this.area + ";" + this.pos1.toString() + ";" + this.pos2.toString();
160    }
161
162    public void getHome(final @NonNull Consumer<Location> result) {
163        final BlockLoc home = this.settings.getPosition();
164        Consumer<Location> locationConsumer = toReturn ->
165                PlotSquared.platform().worldUtil().getHighestBlock(this.area.getWorldName(), toReturn.getX(), toReturn.getZ(),
166                        highest -> {
167                            if (highest <= area.getMinBuildHeight()) {
168                                highest = 63;
169                            }
170                            if (highest > toReturn.getY()) {
171                                result.accept(toReturn.withY(1 + highest));
172                            } else {
173                                result.accept(toReturn);
174                            }
175                        }
176                );
177        if (home.getY() == Integer.MIN_VALUE) {
178            // default pos
179            Plot center = getCenterPlot();
180            center.getHome(location -> {
181                Location toReturn = location;
182                if (toReturn.getY() <= area.getMinBuildHeight()) {
183                    PlotManager manager = this.area.getPlotManager();
184                    Location locationSign = manager.getSignLoc(center);
185                    toReturn = toReturn.withY(locationSign.getY());
186                }
187                locationConsumer.accept(toReturn);
188            });
189        } else {
190            locationConsumer.accept(getClusterBottom().add(home.getX(), home.getY(), home.getZ()));
191        }
192    }
193
194    public @NonNull PlotId getCenterPlotId() {
195        final PlotId bot = getP1();
196        final PlotId top = getP2();
197        return PlotId.of((bot.getX() + top.getX()) / 2, (bot.getY() + top.getY()) / 2);
198    }
199
200    public @Nullable Plot getCenterPlot() {
201        return this.area.getPlotAbs(getCenterPlotId());
202    }
203
204    public Location getClusterBottom() {
205        PlotManager manager = this.area.getPlotManager();
206        return manager.getPlotBottomLocAbs(getP1());
207    }
208
209    public Location getClusterTop() {
210        PlotManager manager = this.area.getPlotManager();
211        return manager.getPlotTopLocAbs(getP2());
212    }
213
214    public boolean intersects(PlotId pos1, PlotId pos2) {
215        return pos1.getX() <= this.pos2.getX() && pos2.getX() >= this.pos1.getX() &&
216                pos1.getY() <= this.pos2.getY() && pos2.getY() >= this.pos1.getY();
217    }
218
219    public boolean contains(PlotId id) {
220        return this.pos1.getX() <= id.getX() && this.pos1.getY() <= id.getY() &&
221                this.pos2.getX() >= id.getX() && this.pos2.getY() >= id.getY();
222    }
223
224}