//////////////////////////////////////////////////////////////////////////////////////////////////// // PlotSquared - A plot manager and world generator for the Bukkit API / // Copyright (c) 2014 IntellectualSites/IntellectualCrafters / // / // This program is free software; you can redistribute it and/or modify / // it under the terms of the GNU General Public License as published by / // the Free Software Foundation; either version 3 of the License, or / // (at your option) any later version. / // / // This program is distributed in the hope that it will be useful, / // but WITHOUT ANY WARRANTY; without even the implied warranty of / // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the / // GNU General Public License for more details. / // / // You should have received a copy of the GNU General Public License / // along with this program; if not, write to the Free Software Foundation, / // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA / // / // You can contact us via: support@intellectualsites.com / //////////////////////////////////////////////////////////////////////////////////////////////////// package com.intellectualcrafters.plot.object; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map.Entry; import java.util.UUID; import com.intellectualcrafters.plot.PS; import com.intellectualcrafters.plot.database.DBFunc; import com.intellectualcrafters.plot.flag.Flag; import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.MainUtil; /** * The plot class * * @author Citymonstret * @author Empire92 */ @SuppressWarnings("javadoc") public class Plot implements Cloneable { /** * plot ID */ public final PlotId id; /** * plot world */ public final String world; /** * plot owner */ public UUID owner; /** * List of trusted (with plot permissions) */ public HashSet trusted; /** * List of members users (with plot permissions) */ public HashSet members; /** * List of denied players */ public HashSet denied; /** * External settings class
* - Please favor the methods over direct access to this class
* - The methods are more likely to be left unchanged from version changes
*/ public PlotSettings settings; /** * Has the plot changed since the last save cycle? */ public boolean hasChanged = false; public boolean countsTowardsMax = true; /** * If this plot is temporary i.e. not stored in the DB */ public final boolean temp; /** * Constructor for a new plot * * @param world * @param id * @param owner */ public Plot(String world, PlotId id, UUID owner) { this.world = world; this.id = id; this.owner = owner; this.settings = new PlotSettings(this); this.trusted = new HashSet<>(); this.members = new HashSet<>(); this.denied = new HashSet<>(); this.temp = false; } /** * Constructor for a temporary plot * * @param world * @param id * @param owner * @param temp */ public Plot(String world, PlotId id, UUID owner, boolean temp) { this.world = world; this.id = id; this.owner = owner; this.settings = new PlotSettings(this); this.trusted = new HashSet<>(); this.members = new HashSet<>(); this.denied = new HashSet<>(); this.temp = temp; } /** * Constructor for a saved plots * * @param id * @param owner * @param trusted * @param denied * @param merged */ public Plot(final PlotId id, final UUID owner, final HashSet trusted, final HashSet members, final HashSet denied, final String alias, final BlockLoc position, final Collection flags, final String world, final boolean[] merged) { this.id = id; this.settings = new PlotSettings(this); this.owner = owner; this.members = members; this.trusted = trusted; this.denied = denied; this.settings.setAlias(alias); this.settings.setPosition(position); this.settings.setMerged(merged); if (flags != null) { for (Flag flag : flags) { this.settings.flags.put(flag.getKey(), flag); } } this.world = world; this.temp = false; } /** * Check if the plot has a set owner * * @return false if there is no owner */ public boolean hasOwner() { return this.owner != null; } public boolean isOwner(UUID uuid) { return PlotHandler.isOwner(this, uuid); } /** * Get a list of owner UUIDs for a plot (supports multi-owner mega-plots) * @return */ public HashSet getOwners() { return PlotHandler.getOwners(this); } /** * Check if the player is either the owner or on the trusted list * * @param uuid * * @return true if the player is added as a helper or is the owner */ public boolean isAdded(final UUID uuid) { return PlotHandler.isAdded(this, uuid); } /** * Should the player be allowed to enter? * * @param uuid * * @return boolean false if the player is allowed to enter */ public boolean isDenied(final UUID uuid) { return (this.denied != null) && ((this.denied.contains(DBFunc.everyone) && !this.isAdded(uuid)) || (!this.isAdded(uuid) && this.denied.contains(uuid))); } /** * Get the plot ID */ public PlotId getId() { return this.id; } /** * Get a clone of the plot * * @return Plot */ @Override public Object clone() throws CloneNotSupportedException { final Plot p = (Plot) super.clone(); if (!p.equals(this) || (p != this)) { return new Plot(this.id, this.owner, this.trusted, this.members, this.denied, this.settings.getAlias(), this.settings.getPosition(), this.settings.flags.values(), this.world, this.settings.getMerged()); } return p; } /** * Deny someone (use DBFunc.addDenied() as well) * * @param uuid */ public void addDenied(final UUID uuid) { if (this.denied.add(uuid)) DBFunc.setDenied(this, uuid); } /** * Add someone as a helper (use DBFunc as well) * * @param uuid */ public void addTrusted(final UUID uuid) { if (this.trusted.add(uuid)) DBFunc.setTrusted(this, uuid); } /** * Add someone as a trusted user (use DBFunc as well) * * @param uuid */ public void addMember(final UUID uuid) { if (this.members.add(uuid)) DBFunc.setMember(this, uuid); } /** * Set the plot owner * @param owner */ public void setOwner(final UUID owner) { if (!this.owner.equals(owner)) { this.owner = owner; DBFunc.setOwner(this, owner); } } /** * Clear a plot * @see MainUtil#clear(Plot, boolean, Runnable) * @see MainUtil#clearAsPlayer(Plot, boolean, Runnable) * @see #delete() to clear and delete a plot * @param whenDone A runnable to execute when clearing finishes, or null */ public void clear(Runnable whenDone) { MainUtil.clear(this, false, whenDone); } /** * Delete a plot * @see PS#removePlot(String, PlotId, boolean) * @see #clear(Runnable) to simply clear a plot */ public void delete() { MainUtil.removeSign(this); MainUtil.clear(this, true, new Runnable() { @Override public void run() { if (PS.get().removePlot(world, id, true)) { DBFunc.delete(Plot.this); } } }); } public void unclaim() { if (PS.get().removePlot(world, id, true)) { DBFunc.delete(Plot.this); } } /** * Unlink a plot and remove the roads * @see MainUtil#unlinkPlot(Plot) * @return true if plot was linked */ public boolean unlink() { return MainUtil.unlinkPlot(this); } /** * Return the home location for the plot * @see MainUtil#getPlotHome(Plot) * @return Home location */ public Location getHome() { return MainUtil.getPlotHome(this); } /** * Get the ratings associated with a plot
* - The rating object may contain multiple categories * @return Map of user who rated to the rating */ public HashMap getRatings() { HashMap map = new HashMap(); for (Entry entry : settings.ratings.entrySet()) { map.put(entry.getKey(), new Rating(entry.getValue())); } return map; } /** * Set the home location * @param loc */ public void setHome(BlockLoc loc) { BlockLoc pos = this.settings.getPosition(); if ((pos == null && loc == null) || (pos != null && pos.equals(loc))) { return; } this.settings.setPosition(loc); if (this.settings.getPosition() == null) { DBFunc.setPosition(this, ""); } else { DBFunc.setPosition(this, this.settings.getPosition().toString()); } } /** * Set the plot alias * @param alias */ public void setAlias(String alias) { String name = this.settings.getAlias(); if (alias == null) { alias = ""; } if (name.equals(alias)) { return; } this.settings.setAlias(alias); DBFunc.setAlias(this, alias); } /** * Resend all chunks inside the plot to nearby players
* This should not need to be called * @see MainUtil#update(Plot) */ public void refreshChunks() { MainUtil.update(this); } /** * Remove the plot sign if it is set */ public void removeSign() { MainUtil.removeSign(this); } /** * Set the plot sign if plot signs are enabled */ public void setSign() { MainUtil.setSign(this); } /** * Register a plot and create it in the database
* - The plot will not be created if the owner is null
* - This will not save any trusted etc in the DB, those should be set after plot creation * @return true if plot was created successfully */ public boolean create() { return MainUtil.createPlot(owner, this); } /** * Auto merge the plot with any adjacent plots of the same owner * @see MainUtil#autoMerge(Plot, UUID) to specify the owner */ public void autoMerge() { MainUtil.autoMerge(this, owner); } /** * Set the plot biome */ public void setBiome(String biome) { MainUtil.setBiome(this, biome); } /** * Return the top location for the plot * @return */ public Location getTop() { return MainUtil.getPlotTopLoc(world, id); } /** * Return the bottom location for the plot * @return */ public Location getBottom() { return MainUtil.getPlotBottomLoc(world, id); } /** * Get the top plot, or this plot if it is not part of a mega plot * @return The bottom plot */ public Plot getTopPlot() { return MainUtil.getTopPlot(this); } /** * Get the bottom plot, or this plot if it is not part of a mega plot * @return The bottom plot */ public Plot getBottomPlot() { return MainUtil.getBottomPlot(this); } /** * Swap the plot contents and settings with another location
* - The destination must correspond to a valid plot of equal dimensions * @see ChunkManager#swap(String, bot1, top1, bot2, top2) to swap terrain * @see MainUtil#getPlotSelectionIds(PlotId, PlotId) to get the plots inside a selection * @see MainUtil#swapData(String, PlotId, PlotId, Runnable) to swap plot settings * @param other The other plot id to swap with * @param whenDone A task to run when finished, or null * @see MainUtil#swapData(String, PlotId, PlotId, Runnable) * @return boolean if swap was successful */ public boolean swap(PlotId destination, Runnable whenDone) { return MainUtil.swap(world, id, destination, whenDone); } /** * Move the plot to an empty location
* - The location must be empty * @param destination Where to move the plot * @param whenDone A task to run when done, or null * @return if the move was successful */ public boolean move(Plot destination, Runnable whenDone) { return MainUtil.move(this, destination, whenDone); } /** * Copy the plot contents and settings to another location
* - The destination must correspond to an empty location * @param destination The location to copy to * @param whenDone The task to run when done * @return If the copy was successful */ public boolean copy(PlotId destination, Runnable whenDone) { return MainUtil.copy(world, id, destination, whenDone); } /** * Get plot display name * * @return alias if set, else id */ @Override public String toString() { if (this.settings.getAlias().length() > 1) { return this.settings.getAlias(); } return this.world + ";" + this.getId().x + ";" + this.getId().y; } /** * Remove a denied player (use DBFunc as well) * * @param uuid */ public boolean removeDenied(final UUID uuid) { if (this.denied.remove(uuid)) { DBFunc.removeDenied(this, uuid); return true; } return false; } /** * Remove a helper (use DBFunc as well) * * @param uuid */ public boolean removeTrusted(final UUID uuid) { if (this.trusted.remove(uuid)) { DBFunc.removeTrusted(this, uuid); return true; } return false; } /** * Remove a trusted user (use DBFunc as well) * * @param uuid */ public boolean removeMember(final UUID uuid) { if (this.members.remove(uuid)) { DBFunc.removeMember(this, uuid); return true; } return false; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Plot other = (Plot) obj; return ((this.id.x.equals(other.id.x)) && (this.id.y.equals(other.id.y)) && (this.world.equals(other.world))); } /** * Get the plot hashcode * * @return integer. You can easily make this a character array
xI = c[0] x = c[1 -> xI...] yI = c[xI ... + 1] y * = c[xI ... + 2 -> yI ...] */ @Override public int hashCode() { return this.id.hashCode(); } }