mirror of
				https://github.com/IntellectualSites/PlotSquared.git
				synced 2025-11-04 03:03:43 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			718 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			718 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
// 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.util;
 | 
						|
 | 
						|
import com.intellectualcrafters.plot.PS;
 | 
						|
import com.intellectualcrafters.plot.config.C;
 | 
						|
import com.intellectualcrafters.plot.config.Settings;
 | 
						|
import com.intellectualcrafters.plot.database.DBFunc;
 | 
						|
import com.intellectualcrafters.plot.flag.Flag;
 | 
						|
import com.intellectualcrafters.plot.flag.FlagManager;
 | 
						|
import com.intellectualcrafters.plot.object.ChunkLoc;
 | 
						|
import com.intellectualcrafters.plot.object.ConsolePlayer;
 | 
						|
import com.intellectualcrafters.plot.object.Location;
 | 
						|
import com.intellectualcrafters.plot.object.Plot;
 | 
						|
import com.intellectualcrafters.plot.object.PlotArea;
 | 
						|
import com.intellectualcrafters.plot.object.PlotBlock;
 | 
						|
import com.intellectualcrafters.plot.object.PlotId;
 | 
						|
import com.intellectualcrafters.plot.object.PlotPlayer;
 | 
						|
import com.intellectualcrafters.plot.object.PseudoRandom;
 | 
						|
import com.intellectualcrafters.plot.object.RegionWrapper;
 | 
						|
import com.intellectualcrafters.plot.object.RunnableVal;
 | 
						|
 | 
						|
import java.util.ArrayList;
 | 
						|
import java.util.Collection;
 | 
						|
import java.util.Collections;
 | 
						|
import java.util.HashMap;
 | 
						|
import java.util.List;
 | 
						|
import java.util.Map.Entry;
 | 
						|
import java.util.UUID;
 | 
						|
import java.util.regex.Matcher;
 | 
						|
 | 
						|
/**
 | 
						|
 * plot functions
 | 
						|
 *
 | 
						|
 */
 | 
						|
public class MainUtil {
 | 
						|
    /**
 | 
						|
     * If the NMS code for sending chunk updates is functional<br>
 | 
						|
     *  - E.g. If using an older version of Bukkit, or before the plugin is updated to 1.5<br>
 | 
						|
     *  - Slower fallback code will be used if not.<br>
 | 
						|
     */
 | 
						|
    public static boolean canSendChunk = false;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Cache of mapping x,y,z coordinates to the chunk array<br>
 | 
						|
     *  - Used for efficent world generation<br>
 | 
						|
     */
 | 
						|
    public static short[][] x_loc;
 | 
						|
    public static short[][] y_loc;
 | 
						|
    public static short[][] z_loc;
 | 
						|
    public static short[][][] CACHE_I = null;
 | 
						|
    public static short[][][] CACHE_J = null;
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * This cache is used for world generation and just saves a bit of calculation time when checking if something is in the plot area.
 | 
						|
     */
 | 
						|
    public static void initCache() {
 | 
						|
        if (x_loc == null) {
 | 
						|
            x_loc = new short[16][4096];
 | 
						|
            y_loc = new short[16][4096];
 | 
						|
            z_loc = new short[16][4096];
 | 
						|
            for (int i = 0; i < 16; i++) {
 | 
						|
                final int i4 = i << 4;
 | 
						|
                for (int j = 0; j < 4096; j++) {
 | 
						|
                    final int y = (i4) + (j >> 8);
 | 
						|
                    final int a = (j - ((y & 0xF) << 8));
 | 
						|
                    final int z1 = (a >> 4);
 | 
						|
                    final int x1 = a - (z1 << 4);
 | 
						|
                    x_loc[i][j] = (short) x1;
 | 
						|
                    y_loc[i][j] = (short) y;
 | 
						|
                    z_loc[i][j] = (short) z1;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (CACHE_I == null) {
 | 
						|
            CACHE_I = new short[256][16][16];
 | 
						|
            CACHE_J = new short[256][16][16];
 | 
						|
            for (int x = 0; x < 16; x++) {
 | 
						|
                for (int z = 0; z < 16; z++) {
 | 
						|
                    for (int y = 0; y < 256; y++) {
 | 
						|
                        final short i = (short) (y >> 4);
 | 
						|
                        final short j = (short) (((y & 0xF) << 8) | (z << 4) | x);
 | 
						|
                        CACHE_I[y][x][z] = i;
 | 
						|
                        CACHE_J[y][x][z] = j;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Hashcode of a boolean array.<br>
 | 
						|
     *  - Used for traversing mega plots quickly.  
 | 
						|
     * @param array
 | 
						|
     * @return hashcode
 | 
						|
     */
 | 
						|
    public static int hash(boolean[] array) {
 | 
						|
        if (array.length == 4) {
 | 
						|
            if (!array[0] && !array[1] && !array[2] && !array[3]) {
 | 
						|
                return 0;
 | 
						|
            }
 | 
						|
            return ((array[0] ? 1 : 0) << 3) + ((array[1] ? 1 : 0) << 2) + ((array[2] ? 1 : 0) << 1) + (array[3] ? 1 : 0);
 | 
						|
        }
 | 
						|
        int n = 0;
 | 
						|
        for (int j = 0; j < array.length; ++j) {
 | 
						|
            n = (n << 1) + (array[j] ? 1 : 0);
 | 
						|
        }
 | 
						|
        return n;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Get a list of plot ids within a selection
 | 
						|
     * @param pos1
 | 
						|
     * @param pos2
 | 
						|
     * @return
 | 
						|
     */
 | 
						|
    public static ArrayList<PlotId> getPlotSelectionIds(final PlotId pos1, final PlotId pos2) {
 | 
						|
        final ArrayList<PlotId> myplots = new ArrayList<>();
 | 
						|
        for (int x = pos1.x; x <= pos2.x; x++) {
 | 
						|
            for (int y = pos1.y; y <= pos2.y; y++) {
 | 
						|
                myplots.add(new PlotId(x, y));
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return myplots;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Get the name from a UUID<br>
 | 
						|
     * @param owner
 | 
						|
     * @return The player's name, None, Everyone or Unknown 
 | 
						|
     */
 | 
						|
    public static String getName(final UUID owner) {
 | 
						|
        if (owner == null) {
 | 
						|
            return C.NONE.s();
 | 
						|
        } else if (owner.equals(DBFunc.everyone)) {
 | 
						|
            return C.EVERYONE.s();
 | 
						|
        }
 | 
						|
        final String name = UUIDHandler.getName(owner);
 | 
						|
        if (name == null) {
 | 
						|
            return C.UNKNOWN.s();
 | 
						|
        }
 | 
						|
        return name;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Get the corner locations for a list of regions<br>
 | 
						|
     * @see Plot#getCorners() 
 | 
						|
     * @param world
 | 
						|
     * @param regions
 | 
						|
     * @return
 | 
						|
     */
 | 
						|
    public static Location[] getCorners(String world, Collection<RegionWrapper> regions) {
 | 
						|
        Location min = null;
 | 
						|
        Location max = null;
 | 
						|
        for (RegionWrapper region : regions) {
 | 
						|
            Location[] corners = region.getCorners(world);
 | 
						|
            if (min == null) {
 | 
						|
                min = corners[0];
 | 
						|
                max = corners[1];
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            Location pos1 = corners[0];
 | 
						|
            Location pos2 = corners[1];
 | 
						|
            if (pos2.getX() > max.getX()) {
 | 
						|
                max.setX(pos2.getX());
 | 
						|
            }
 | 
						|
            if (pos1.getX() < min.getX()) {
 | 
						|
                min.setX(pos1.getX());
 | 
						|
            }
 | 
						|
            if (pos2.getZ() > max.getZ()) {
 | 
						|
                max.setZ(pos2.getZ());
 | 
						|
            }
 | 
						|
            if (pos1.getZ() < min.getZ()) {
 | 
						|
                min.setZ(pos1.getZ());
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return new Location[] { min, max };
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Fuzzy plot search with spaces separating terms<br>
 | 
						|
     *  - Terms: id, alias, world, owner, trusted, member
 | 
						|
     * @param search
 | 
						|
     * @return
 | 
						|
     */
 | 
						|
    public static List<Plot> getPlotsBySearch(final String search) {
 | 
						|
        final String[] split = search.split(" ");
 | 
						|
        final int size = split.length * 2;
 | 
						|
        
 | 
						|
        final List<UUID> uuids = new ArrayList<>();
 | 
						|
        PlotId id = null;
 | 
						|
        PlotArea area = null;
 | 
						|
        String alias = null;
 | 
						|
        
 | 
						|
        for (final String term : split) {
 | 
						|
            try {
 | 
						|
                UUID uuid = UUIDHandler.getUUID(term, null);
 | 
						|
                if (uuid == null) {
 | 
						|
                    uuid = UUID.fromString(term);
 | 
						|
                }
 | 
						|
                uuids.add(uuid);
 | 
						|
            } catch (final Exception e) {
 | 
						|
                id = PlotId.fromString(term);
 | 
						|
                if (id != null) {
 | 
						|
                    continue;
 | 
						|
                }
 | 
						|
                area = PS.get().getPlotAreaByString(term);
 | 
						|
                if (area == null) {
 | 
						|
                    alias = term;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        final ArrayList<ArrayList<Plot>> plotList = new ArrayList<>(size);
 | 
						|
        for (int i = 0; i < size; i++) {
 | 
						|
            plotList.add(new ArrayList<Plot>());
 | 
						|
        }
 | 
						|
        
 | 
						|
        for (final Plot plot : PS.get().getPlots()) {
 | 
						|
            int count = 0;
 | 
						|
            if (uuids.size() > 0) {
 | 
						|
                for (final UUID uuid : uuids) {
 | 
						|
                    if (plot.isOwner(uuid)) {
 | 
						|
                        count += 2;
 | 
						|
                    } else if (plot.isAdded(uuid)) {
 | 
						|
                        count++;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if (id != null) {
 | 
						|
                if (plot.getId().equals(id)) {
 | 
						|
                    count++;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if ((area != null) && plot.getArea().equals(area)) {
 | 
						|
                count++;
 | 
						|
            }
 | 
						|
            if ((alias != null) && alias.equals(plot.getAlias())) {
 | 
						|
                count += 2;
 | 
						|
            }
 | 
						|
            if (count != 0) {
 | 
						|
                plotList.get(count - 1).add(plot);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        final List<Plot> plots = new ArrayList<Plot>();
 | 
						|
        for (int i = plotList.size() - 1; i >= 0; i--) {
 | 
						|
            if (plotList.get(i).size() > 0) {
 | 
						|
                plots.addAll(plotList.get(i));
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return plots;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Get the plot from a string<br>
 | 
						|
     * @param player Provides a context for what world to search in. Prefixing the term with 'world_name;' will override this context.  
 | 
						|
     * @param arg The search term
 | 
						|
     * @param message If a message should be sent to the player if a plot cannot be found
 | 
						|
     * @return The plot if only 1 result is found, or null
 | 
						|
     */
 | 
						|
    public static Plot getPlotFromString(final PlotPlayer player, final String arg, final boolean message) {
 | 
						|
        if (arg == null) {
 | 
						|
            if (player == null) {
 | 
						|
                if (message) {
 | 
						|
                    MainUtil.sendMessage(player, C.NOT_VALID_PLOT_WORLD);
 | 
						|
                }
 | 
						|
                return null;
 | 
						|
            }
 | 
						|
            return player.getLocation().getPlotAbs();
 | 
						|
        }
 | 
						|
        PlotArea area = null;
 | 
						|
        PlotId id = null;
 | 
						|
        if (player != null) {
 | 
						|
            area = player.getApplicablePlotArea();
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            area = ConsolePlayer.getConsole().getApplicablePlotArea();
 | 
						|
        }
 | 
						|
        final String[] split = arg.split(";|,");
 | 
						|
        if (split.length == 4) {
 | 
						|
            area = PS.get().getPlotAreaByString(split[0] + ";" + split[1]);
 | 
						|
            id = PlotId.fromString(split[2] + ";" + split[3]);
 | 
						|
        } else if (split.length == 3) {
 | 
						|
            area = PS.get().getPlotAreaByString(split[0]);
 | 
						|
            id = PlotId.fromString(split[1] + ";" + split[2]);
 | 
						|
        } else if (split.length == 2) {
 | 
						|
            id = PlotId.fromString(arg);
 | 
						|
        } else {
 | 
						|
            PlotArea tmp = PS.get().getPlotAreaByString(arg);
 | 
						|
            if (area == null) {
 | 
						|
                if (message) {
 | 
						|
                    MainUtil.sendMessage(player, C.NOT_VALID_PLOT_WORLD);
 | 
						|
                }
 | 
						|
                return null;
 | 
						|
            } else {
 | 
						|
                for (final Plot p : area.getPlots()) {
 | 
						|
                    final String name = p.getAlias();
 | 
						|
                    if ((name.length() != 0) && StringMan.isEqualIgnoreCase(name, arg)) {
 | 
						|
                        return p;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if (message) {
 | 
						|
                    MainUtil.sendMessage(player, C.NOT_VALID_PLOT_ID);
 | 
						|
                }
 | 
						|
                return null;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (id == null) {
 | 
						|
            if (id == null) {
 | 
						|
                if (message) {
 | 
						|
                    MainUtil.sendMessage(player, C.NOT_VALID_PLOT_ID);
 | 
						|
                }
 | 
						|
                return null;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (area == null) {
 | 
						|
            if (message) {
 | 
						|
                MainUtil.sendMessage(player, C.NOT_VALID_PLOT_WORLD);
 | 
						|
            }
 | 
						|
            return null;
 | 
						|
        }
 | 
						|
        return area.getPlotAbs(id);
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Resend the chunk at a location
 | 
						|
     * @param world
 | 
						|
     * @param loc
 | 
						|
     */
 | 
						|
    public static void update(final String world, final ChunkLoc loc) {
 | 
						|
        SetQueue.IMP.queue.sendChunk(world, Collections.singletonList(loc));
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Set a cuboid in the world to a set of blocks.
 | 
						|
     * @param world
 | 
						|
     * @param pos1
 | 
						|
     * @param pos2
 | 
						|
     * @param blocks If multiple blocks are provided, the result will be a random mix
 | 
						|
     */
 | 
						|
    public static void setCuboid(final String world, final Location pos1, final Location pos2, final PlotBlock[] blocks) {
 | 
						|
        if (blocks.length == 1) {
 | 
						|
            setSimpleCuboid(world, pos1, pos2, blocks[0]);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        for (int y = pos1.getY(); y <= pos2.getY(); y++) {
 | 
						|
            for (int x = pos1.getX(); x <= pos2.getX(); x++) {
 | 
						|
                for (int z = pos1.getZ(); z <= pos2.getZ(); z++) {
 | 
						|
                    final int i = PseudoRandom.random.random(blocks.length);
 | 
						|
                    final PlotBlock block = blocks[i];
 | 
						|
                    SetQueue.IMP.setBlock(world, x, y, z, block);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        while (SetQueue.IMP.forceChunkSet());
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Set a cubioid asynchronously to a set of blocks
 | 
						|
     * @param world
 | 
						|
     * @param pos1
 | 
						|
     * @param pos2
 | 
						|
     * @param blocks
 | 
						|
     */
 | 
						|
    public static void setCuboidAsync(final String world, final Location pos1, final Location pos2, final PlotBlock[] blocks) {
 | 
						|
        if (blocks.length == 1) {
 | 
						|
            setSimpleCuboidAsync(world, pos1, pos2, blocks[0]);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        for (int y = pos1.getY(); y <= Math.min(255, pos2.getY()); y++) {
 | 
						|
            for (int x = pos1.getX(); x <= pos2.getX(); x++) {
 | 
						|
                for (int z = pos1.getZ(); z <= pos2.getZ(); z++) {
 | 
						|
                    final int i = PseudoRandom.random.random(blocks.length);
 | 
						|
                    final PlotBlock block = blocks[i];
 | 
						|
                    SetQueue.IMP.setBlock(world, x, y, z, block);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Set a cuboid to a block
 | 
						|
     * @param world
 | 
						|
     * @param pos1
 | 
						|
     * @param pos2
 | 
						|
     * @param newblock
 | 
						|
     */
 | 
						|
    public static void setSimpleCuboid(final String world, final Location pos1, final Location pos2, final PlotBlock newblock) {
 | 
						|
        for (int y = pos1.getY(); y <= pos2.getY(); y++) {
 | 
						|
            for (int x = pos1.getX(); x <= pos2.getX(); x++) {
 | 
						|
                for (int z = pos1.getZ(); z <= pos2.getZ(); z++) {
 | 
						|
                    SetQueue.IMP.setBlock(world, x, y, z, newblock);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        while (SetQueue.IMP.forceChunkSet());
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Set a cuboic asynchronously to a block
 | 
						|
     * @param world
 | 
						|
     * @param pos1
 | 
						|
     * @param pos2
 | 
						|
     * @param newblock
 | 
						|
     */
 | 
						|
    public static void setSimpleCuboidAsync(final String world, final Location pos1, final Location pos2, final PlotBlock newblock) {
 | 
						|
        for (int y = pos1.getY(); y <= Math.min(255, pos2.getY()); y++) {
 | 
						|
            for (int x = pos1.getX(); x <= pos2.getX(); x++) {
 | 
						|
                for (int z = pos1.getZ(); z <= pos2.getZ(); z++) {
 | 
						|
                    SetQueue.IMP.setBlock(world, x, y, z, newblock);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Synchronously set the biome in a selection
 | 
						|
     * @param world
 | 
						|
     * @param p1x
 | 
						|
     * @param p1z
 | 
						|
     * @param p2x
 | 
						|
     * @param p2z
 | 
						|
     * @param biome
 | 
						|
     */
 | 
						|
    public static void setBiome(final String world, final int p1x, final int p1z, final int p2x, final int p2z, final String biome) {
 | 
						|
        RegionWrapper region = new RegionWrapper(p1x, p2x, p1z, p2z);
 | 
						|
        WorldUtil.IMP.setBiomes(world, region, biome);
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Get the heighest block at a location
 | 
						|
     * @param world
 | 
						|
     * @param x
 | 
						|
     * @param z
 | 
						|
     * @return
 | 
						|
     */
 | 
						|
    public static int getHeighestBlock(final String world, final int x, final int z) {
 | 
						|
        final int result = WorldUtil.IMP.getHeighestBlock(world, x, z);
 | 
						|
        if (result == 0) {
 | 
						|
            return 64;
 | 
						|
        }
 | 
						|
        return result;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Send a message to the player
 | 
						|
     *
 | 
						|
     * @param plr Player to recieve message
 | 
						|
     * @param msg Message to send
 | 
						|
     *
 | 
						|
     * @return true Can be used in things such as commands (return PlayerFunctions.sendMessage(...))
 | 
						|
     */
 | 
						|
    public static boolean sendMessage(final PlotPlayer plr, final String msg) {
 | 
						|
        return sendMessage(plr, msg, true);
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Send a message to console
 | 
						|
     * @param caption
 | 
						|
     * @param args
 | 
						|
     */
 | 
						|
    public static void sendConsoleMessage(final C caption, final String... args) {
 | 
						|
        sendMessage(null, caption, args);
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Send a message to a player
 | 
						|
     * @param plr Can be null to represent console, or use ConsolePlayer.getConsole()
 | 
						|
     * @param msg
 | 
						|
     * @param prefix If the message should be prefixed with the configured prefix
 | 
						|
     * @return
 | 
						|
     */
 | 
						|
    public static boolean sendMessage(final PlotPlayer plr, final String msg, final boolean prefix) {
 | 
						|
        if ((msg.length() > 0) && !msg.equals("")) {
 | 
						|
            if (plr == null) {
 | 
						|
                ConsolePlayer.getConsole().sendMessage((prefix ? C.PREFIX.s() : "") + msg);
 | 
						|
            } else {
 | 
						|
                plr.sendMessage((prefix ? C.PREFIX.s() : "") + C.color(msg));
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Send a message to the player
 | 
						|
     *
 | 
						|
     * @param plr Player to receive message
 | 
						|
     * @param c   Caption to send
 | 
						|
     *
 | 
						|
     * @return boolean success
 | 
						|
     */
 | 
						|
    public static boolean sendMessage(final PlotPlayer plr, final C c, final String... args) {
 | 
						|
        return sendMessage(plr, c, (Object[]) args);
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Send a message to the player
 | 
						|
     *
 | 
						|
     * @param plr Player to receive message
 | 
						|
     * @param c   Caption to send
 | 
						|
     *
 | 
						|
     * @return boolean success
 | 
						|
     */
 | 
						|
    public static boolean sendMessage(final PlotPlayer plr, final C c, final Object... args) {
 | 
						|
        if (c.s().length() == 0) {
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
        TaskManager.runTaskAsync(new Runnable() {
 | 
						|
            @Override
 | 
						|
            public void run() {
 | 
						|
                String msg = c.s();
 | 
						|
                if (args.length != 0) {
 | 
						|
                    msg = c.format(c, args);
 | 
						|
                }
 | 
						|
                if (plr != null) {
 | 
						|
                    plr.sendMessage((c.usePrefix() ? C.PREFIX.s() + msg : msg));
 | 
						|
                } else {
 | 
						|
                    ConsolePlayer.getConsole().sendMessage((c.usePrefix() ? C.PREFIX.s() : "") + msg);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        });
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Get the average rating for a plot
 | 
						|
     * @see Plot#getAverageRating()
 | 
						|
     * @param plot
 | 
						|
     * @return
 | 
						|
     */
 | 
						|
    public static double getAverageRating(final Plot plot) {
 | 
						|
        HashMap<UUID, Integer> rating;
 | 
						|
        if (plot.getSettings().ratings != null) {
 | 
						|
            rating = plot.getSettings().ratings;
 | 
						|
        } else if (Settings.CACHE_RATINGS) {
 | 
						|
            rating = new HashMap<>();
 | 
						|
        } else {
 | 
						|
            rating = DBFunc.getRatings(plot);
 | 
						|
        }
 | 
						|
        if ((rating == null) || (rating.size() == 0)) {
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
        double val = 0;
 | 
						|
        int size = 0;
 | 
						|
        for (final Entry<UUID, Integer> entry : rating.entrySet()) {
 | 
						|
            int current = entry.getValue();
 | 
						|
            if ((Settings.RATING_CATEGORIES == null) || (Settings.RATING_CATEGORIES.size() == 0)) {
 | 
						|
                val += current;
 | 
						|
                size++;
 | 
						|
            } else {
 | 
						|
                for (int i = 0; i < Settings.RATING_CATEGORIES.size(); i++) {
 | 
						|
                    val += (current % 10) - 1;
 | 
						|
                    current /= 10;
 | 
						|
                    size++;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return val / size;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * If rating categories are enabled, get the average rating by category.<br>
 | 
						|
     *  - The index corresponds to the index of the category in the config
 | 
						|
     * @param plot
 | 
						|
     * @return
 | 
						|
     */
 | 
						|
    public static double[] getAverageRatings(final Plot plot) {
 | 
						|
        HashMap<UUID, Integer> rating;
 | 
						|
        if (plot.getSettings().ratings != null) {
 | 
						|
            rating = plot.getSettings().ratings;
 | 
						|
        } else if (Settings.CACHE_RATINGS) {
 | 
						|
            rating = new HashMap<>();
 | 
						|
        } else {
 | 
						|
            rating = DBFunc.getRatings(plot);
 | 
						|
        }
 | 
						|
        int size = 1;
 | 
						|
        if (Settings.RATING_CATEGORIES != null) {
 | 
						|
            size = Math.max(1, Settings.RATING_CATEGORIES.size());
 | 
						|
        }
 | 
						|
        final double[] ratings = new double[size];
 | 
						|
        if ((rating == null) || (rating.size() == 0)) {
 | 
						|
            return ratings;
 | 
						|
        }
 | 
						|
        for (final Entry<UUID, Integer> entry : rating.entrySet()) {
 | 
						|
            int current = entry.getValue();
 | 
						|
            if ((Settings.RATING_CATEGORIES == null) || (Settings.RATING_CATEGORIES.size() == 0)) {
 | 
						|
                ratings[0] += current;
 | 
						|
            } else {
 | 
						|
                for (int i = 0; i < Settings.RATING_CATEGORIES.size(); i++) {
 | 
						|
                    ratings[i] += (current % 10) - 1;
 | 
						|
                    current /= 10;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        for (int i = 0; i < size; i++) {
 | 
						|
            ratings[i] /= rating.size();
 | 
						|
        }
 | 
						|
        return ratings;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Format a string with plot information:<br>
 | 
						|
     * %id%, %alias%, %num%, %desc%, %biome%, %owner%, %members%, %trusted%, %helpers%, %denied%, %flags%, %build%, %desc%, %rating%
 | 
						|
     * @param info
 | 
						|
     * @param plot
 | 
						|
     * @param player
 | 
						|
     * @param full
 | 
						|
     * @param whenDone
 | 
						|
     */
 | 
						|
    public static void format(String info, final Plot plot, final PlotPlayer player, final boolean full, final RunnableVal<String> whenDone) {
 | 
						|
        final int num = plot.getConnectedPlots().size();
 | 
						|
        final String alias = plot.getAlias().length() > 0 ? plot.getAlias() : C.NONE.s();
 | 
						|
        final Location bot = plot.getCorners()[0];
 | 
						|
        final String biome = WorldUtil.IMP.getBiome(plot.getArea().worldname, bot.getX(), bot.getZ());
 | 
						|
        final String trusted = getPlayerList(plot.getTrusted());
 | 
						|
        final String members = getPlayerList(plot.getMembers());
 | 
						|
        final String denied = getPlayerList(plot.getDenied());
 | 
						|
        
 | 
						|
        final Flag descriptionFlag = FlagManager.getPlotFlagRaw(plot, "description");
 | 
						|
        final String description = descriptionFlag == null ? C.NONE.s() : descriptionFlag.getValueString();
 | 
						|
        
 | 
						|
        final String flags = StringMan.replaceFromMap(
 | 
						|
        "$2"
 | 
						|
        + (StringMan.join(FlagManager.getPlotFlags(plot.getArea(), plot.getSettings(), true).values(), "").length() > 0 ? StringMan.join(FlagManager.getPlotFlags(
 | 
						|
 | 
						|
                plot.getArea(), plot.getSettings(), true)
 | 
						|
        .values(), "$1, $2") : C.NONE.s()), C.replacements);
 | 
						|
        final boolean build = plot.isAdded(player.getUUID());
 | 
						|
        
 | 
						|
        final String owner = plot.owner == null ? "unowned" : getPlayerList(plot.getOwners());
 | 
						|
        
 | 
						|
        info = info.replaceAll("%id%", plot.getId().toString());
 | 
						|
        info = info.replaceAll("%alias%", alias);
 | 
						|
        info = info.replaceAll("%num%", num + "");
 | 
						|
        info = info.replaceAll("%desc%", description);
 | 
						|
        info = info.replaceAll("%biome%", biome);
 | 
						|
        info = info.replaceAll("%owner%", owner);
 | 
						|
        info = info.replaceAll("%members%", members);
 | 
						|
        info = info.replaceAll("%player%", player != null ? player.getName() : C.NONE.s());
 | 
						|
        info = info.replaceAll("%trusted%", trusted);
 | 
						|
        info = info.replaceAll("%helpers%", members);
 | 
						|
        info = info.replaceAll("%denied%", denied);
 | 
						|
        info = info.replaceAll("%flags%", Matcher.quoteReplacement(flags));
 | 
						|
        info = info.replaceAll("%build%", build + "");
 | 
						|
        info = info.replaceAll("%desc%", "No description set.");
 | 
						|
        if (info.contains("%rating%")) {
 | 
						|
            final String newInfo = info;
 | 
						|
            TaskManager.runTaskAsync(new Runnable() {
 | 
						|
                @Override
 | 
						|
                public void run() {
 | 
						|
                    int max = 10;
 | 
						|
                    if ((Settings.RATING_CATEGORIES != null) && (Settings.RATING_CATEGORIES.size() > 0)) {
 | 
						|
                        max = 8;
 | 
						|
                    }
 | 
						|
                    String info;
 | 
						|
                    if (full && (Settings.RATING_CATEGORIES != null) && (Settings.RATING_CATEGORIES.size() > 1)) {
 | 
						|
                        String rating = "";
 | 
						|
                        String prefix = "";
 | 
						|
                        final double[] ratings = MainUtil.getAverageRatings(plot);
 | 
						|
                        for (int i = 0; i < ratings.length; i++) {
 | 
						|
                            rating += prefix + Settings.RATING_CATEGORIES.get(i) + "=" + String.format("%.1f", ratings[i]);
 | 
						|
                            prefix = ",";
 | 
						|
                        }
 | 
						|
                        info = newInfo.replaceAll("%rating%", rating);
 | 
						|
                    } else {
 | 
						|
                        info = newInfo.replaceAll("%rating%", String.format("%.1f", MainUtil.getAverageRating(plot)) + "/" + max);
 | 
						|
                    }
 | 
						|
                    whenDone.run(info);
 | 
						|
                }
 | 
						|
            });
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        whenDone.run(info);
 | 
						|
    }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Get a list of names given a list of uuids.<br>
 | 
						|
     * - Uses the format {@link C#PLOT_USER_LIST} for the returned string
 | 
						|
     * @param uuids
 | 
						|
     * @return
 | 
						|
     */
 | 
						|
    public static String getPlayerList(final Collection<UUID> uuids) {
 | 
						|
        final ArrayList<UUID> l = new ArrayList<>(uuids);
 | 
						|
        if (l.size() < 1) {
 | 
						|
            return C.NONE.s();
 | 
						|
        }
 | 
						|
        final String c = C.PLOT_USER_LIST.s();
 | 
						|
        final StringBuilder list = new StringBuilder();
 | 
						|
        for (int x = 0; x < l.size(); x++) {
 | 
						|
            if ((x + 1) == l.size()) {
 | 
						|
                list.append(c.replace("%user%", getName(l.get(x))).replace(",", ""));
 | 
						|
            } else {
 | 
						|
                list.append(c.replace("%user%", getName(l.get(x))));
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return list.toString();
 | 
						|
    }
 | 
						|
}
 |