Package com.onarandombox.MultiversePortals.utils

Source Code of com.onarandombox.MultiversePortals.utils.PortalManager

/*
* Multiverse 2 Copyright (c) the Multiverse Team 2011.
* Multiverse 2 is licensed under the BSD License.
* For more information please check the README.md file included
* with this project
*/

package com.onarandombox.MultiversePortals.utils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;
import org.bukkit.util.Vector;

import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiversePortals.MVPortal;
import com.onarandombox.MultiversePortals.MultiversePortals;
import com.onarandombox.MultiversePortals.PortalLocation;


/**
* Manages all portals for all worlds.
*
* @author fernferret
*/
public class PortalManager {
    private MultiversePortals plugin;
    private Map<String, MVPortal> portals;

    // For each world, keep a map of chunk hashes (see hashChunk()) to lists of
    // portals in those chunks.
    private Map<MultiverseWorld, Map<Integer, Collection<MVPortal>>> worldChunkPortals;

    // getNearbyPortals() returns this instead of null. =)
    private static final Collection<MVPortal> emptyPortalSet = new ArrayList<MVPortal>();

    public PortalManager(MultiversePortals plugin) {
        this.plugin = plugin;
        this.portals = new HashMap<String, MVPortal>();
        this.worldChunkPortals = new HashMap<MultiverseWorld, Map<Integer, Collection<MVPortal>>>();
    }
    /**
     * Method that checks to see if a player is inside a portal AND if they have perms to use it.
     * @param sender The sender to check.
     * @param l The location they're standing.
     * @return A MVPortal if it's valid, null if not.
     */
    public MVPortal getPortal(Player sender, Location l) {
        if (!this.plugin.getCore().getMVWorldManager().isMVWorld(l.getWorld().getName())) {
            return null;
        }

        MultiverseWorld world = this.plugin.getCore().getMVWorldManager().getMVWorld(l.getWorld().getName());
        for (MVPortal portal : getNearbyPortals(world, l)) {

            // Ignore portals the player can't use.
            if (!MultiversePortals.EnforcePortalAccess || portal.playerCanEnterPortal((Player) sender)) {
                PortalLocation portalLoc = portal.getLocation();
                if (portalLoc.isValidLocation() && portalLoc.getRegion().containsVector(l)) {
                    return portal;
                }
            }
        }

        return null;
    }
    /**
     * Deprecated, use getPortal instead.
     * @deprecated
     */
    @Deprecated
    public MVPortal isPortal(Player sender, Location l) {
        return this.getPortal(sender, l);
    }

    /**
     * Simplified method for seeing if someone is in a portal. We'll check perms later.
     *
     * @param l The location of the player
     *
     * @return True if it is a valid portal location.
     */
    public boolean isPortal(Location l) {
        return this.getPortal(l) != null;
    }

    /**
     * Return a portal at a location.
     * NOTE: If there are more than one portal, order is effectively indeterminate.
     * @param l The location to check at
     * @return Null if no portal found, otherwise the MVPortal at that location.
     */
    public MVPortal getPortal(Location l) {
        MultiverseWorld world = this.plugin.getCore().getMVWorldManager().getMVWorld(l.getWorld().getName());
        for (MVPortal portal : getNearbyPortals(world, l)) {
            MultiverseRegion r = portal.getLocation().getRegion();
            if (r != null && r.containsVector(l)) {
                return portal;
            }
        }
        return null;
    }

    public boolean addPortal(MVPortal portal) {
        if (!this.portals.containsKey(portal.getName())) {
            MultiverseWorld world = this.plugin.getCore().getMVWorldManager().getMVWorld(portal.getWorld());
            addUniquePortal(world, portal.getName(), portal);
            return true;
        }
        return false;
    }

    public boolean addPortal(MultiverseWorld world, String name, String owner, PortalLocation location) {
        if (!this.portals.containsKey(name)) {
            addUniquePortal(world, name, new MVPortal(this.plugin, name, owner, location));
            return true;
        }
        return false;
    }
   
    // Add a portal whose name is already known to be unique.
    private void addUniquePortal(MultiverseWorld world, String name, MVPortal portal) {
        this.portals.put(name, portal);
        addToWorldChunkPortals(world, portal);
    }

    public MVPortal removePortal(String portalName, boolean removeFromConfigs) {
        if (!isPortal(portalName)) {
            return null;
        }
        if (removeFromConfigs) {
            FileConfiguration config = this.plugin.getPortalsConfig();
            config.set("portals." + portalName, null);
            this.plugin.savePortalsConfig();
        }

        MVPortal removed = this.portals.remove(portalName);
        MultiverseWorld world = this.plugin.getCore().getMVWorldManager().getMVWorld(removed.getWorld());
        removeFromWorldChunkPortals(world, removed);

        removed.removePermission();
        Permission portalAccess = this.plugin.getServer().getPluginManager().getPermission("multiverse.portal.access.*");
        Permission exemptAccess = this.plugin.getServer().getPluginManager().getPermission("multiverse.portal.exempt.*");
        Permission portalFill = this.plugin.getServer().getPluginManager().getPermission("multiverse.portal.fill.*");
        if (exemptAccess != null) {
            exemptAccess.getChildren().remove(removed.getExempt().getName());
            this.plugin.getServer().getPluginManager().recalculatePermissionDefaults(exemptAccess);
        }
        if (portalAccess != null) {
            portalAccess.getChildren().remove(removed.getPermission().getName());
            this.plugin.getServer().getPluginManager().recalculatePermissionDefaults(portalAccess);
        }
        if (portalFill != null) {
            portalFill.getChildren().remove(removed.getFillPermission().getName());
            this.plugin.getServer().getPluginManager().recalculatePermissionDefaults(portalFill);
        }
        if (MultiversePortals.ClearOnRemove) {
            // Replace portal blocks in the portal with air. This keeps us from
            // leaving behind portal blocks (which would take an unsuspecting
            // player to the nether instead of their expected destination).

            MultiverseRegion region = removed.getLocation().getRegion();
            replaceInRegion(removed.getWorld(), region, Material.PORTAL, Material.AIR);
        }
        this.plugin.getServer().getPluginManager().removePermission(removed.getPermission());
        this.plugin.getServer().getPluginManager().removePermission(removed.getExempt());
        this.plugin.getServer().getPluginManager().removePermission(removed.getFillPermission());
        return removed;
    }

    public List<MVPortal> getAllPortals() {
        return new ArrayList<MVPortal>(this.portals.values());
    }

    public List<MVPortal> getPortals(CommandSender sender) {
        if (!(sender instanceof Player)) {
            return this.getAllPortals();
        }
        List<MVPortal> all = this.getAllPortals();
        List<MVPortal> validItems = new ArrayList<MVPortal>();
        if (MultiversePortals.EnforcePortalAccess) {
            for (MVPortal p : all) {
                if (p.playerCanEnterPortal((Player) sender)) {
                    validItems.add(p);
                }
            }
        } else {
            validItems = new ArrayList<MVPortal>(all);
        }
        return validItems;
    }

    private List<MVPortal> getPortals(MultiverseWorld world) {
        List<MVPortal> all = this.getAllPortals();
        List<MVPortal> validItems = new ArrayList<MVPortal>();
        for (MVPortal p : all) {
            MultiverseWorld portalworld = p.getLocation().getMVWorld();
            if (portalworld != null && portalworld.equals(world)) {
                validItems.add(p);
            }
        }
        return validItems;
    }

    public List<MVPortal> getPortals(CommandSender sender, MultiverseWorld world) {
        if (!(sender instanceof Player)) {
            return this.getPortals(world);
        }
        List<MVPortal> all = this.getAllPortals();
        List<MVPortal> validItems = new ArrayList<MVPortal>();
        if (MultiversePortals.EnforcePortalAccess) {
            for (MVPortal p : all) {
                if (p.getLocation().isValidLocation() && p.getLocation().getMVWorld().equals(world) &&
                        p.playerCanEnterPortal((Player) sender)) {
                    validItems.add(p);
                }
            }
        } else {
            validItems = new ArrayList<MVPortal>(all);
        }
        return validItems;
    }

    public MVPortal getPortal(String portalName) {
        // Returns null if the portal doesn't exist.
        return this.portals.get(portalName);
    }

    /**
     * Gets a portal with a commandsender and a name. Used as a convenience for portal listing methods
     *
     * @param portalName
     * @param sender
     *
     * @return
     */
    public MVPortal getPortal(String portalName, CommandSender sender) {
        if (!this.plugin.getCore().getMVPerms().hasPermission(sender, "multiverse.portal.access." + portalName, true)) {
            return null;
        }
        return this.getPortal(portalName);
    }

    public boolean isPortal(String portalName) {
        return this.portals.containsKey(portalName);
    }

    public void removeAll(boolean removeFromConfigs) {
        List<String> iterList = new ArrayList<String>(this.portals.keySet());
        for (String s : iterList) {
            this.removePortal(s, removeFromConfigs);
        }
    }
   
    private void replaceInRegion(World world, MultiverseRegion removedRegion, Material oldMaterial, Material newMaterial) {

        int oldMaterialId = oldMaterial.getId();
        int newMaterialId = newMaterial.getId();
       
        // Determine the bounds of the region.
        Vector min = removedRegion.getMinimumPoint();
        Vector max = removedRegion.getMaximumPoint();
        int minX = min.getBlockX(), minY = min.getBlockY(), minZ = min.getBlockZ();
        int maxX = max.getBlockX(), maxY = max.getBlockY(), maxZ = max.getBlockZ();

        for (int x = minX; x <= maxX; x++) {
            for (int y = minY; y <= maxY; y++) {
                for (int z = minZ; z <= maxZ; z++) {
                    Block b = world.getBlockAt(x, y, z);
                    if (b.getTypeId() == oldMaterialId) {
                        b.setTypeId(newMaterialId, false);
                    }
                }
            }
        }
    }
   
    private int blockToChunk(int b) {
        // A block at -5 should be in chunk -1 instead of chunk 0.
        if (b < 0) {
            b -= 16;
        }
        return b / 16;
    }
   
    private int hashChunk(int cx, int cz) {
        return (cx << 16) | (cz & 0xFFFF);
    }
   
    private void addToWorldChunkPortals(MultiverseWorld world, MVPortal portal) {

        Map<Integer, Collection<MVPortal>> chunksToPortals = this.worldChunkPortals.get(world);
        if (chunksToPortals == null) {
            chunksToPortals = new HashMap<Integer, Collection<MVPortal>>();
            this.worldChunkPortals.put(world, chunksToPortals);
        }

        // If this portal spans multiple chunks, we'll add it to each chunk that
        // contains part of it.
        PortalLocation location = portal.getLocation();
        Vector min = location.getMinimum();
        Vector max = location.getMaximum();
        int c1x = blockToChunk(min.getBlockX()), c1z = blockToChunk(min.getBlockZ());
        int c2x = blockToChunk(max.getBlockX()), c2z = blockToChunk(max.getBlockZ());
        for (int cx = c1x; cx <= c2x; cx++) {
            for (int cz = c1z; cz <= c2z; cz++) {
                Integer hashCode = hashChunk(cx, cz);
                Collection<MVPortal> portals = chunksToPortals.get(hashCode);
                if (portals == null) {
                    // For this collection, iteration will be -much- more common
                    // than addition or removal. ArrayList has better iteration
                    // performance than HashSet.
                    portals = new ArrayList<MVPortal>();
                    chunksToPortals.put(hashCode, portals);
                }
                portals.add(portal);
            }
        }
    }
   
    private void removeFromWorldChunkPortals(MultiverseWorld world, MVPortal portal) {
        Map<Integer, Collection<MVPortal>> chunksToPortals = this.worldChunkPortals.get(world);

        if (chunksToPortals == null) {
            // 'world' might be a new instance of an adventure world that's
            // being reloaded. If that's the case, the world object won't be
            // found in worldChunkPortals.
            return;
        }

        PortalLocation location = portal.getLocation();
        Vector min = location.getMinimum();
        Vector max = location.getMaximum();
        int c1x = blockToChunk(min.getBlockX()), c1z = blockToChunk(min.getBlockZ());
        int c2x = blockToChunk(max.getBlockX()), c2z = blockToChunk(max.getBlockZ());

        for (int cx = c1x; cx <= c2x; cx++) {
            for (int cz = c1z; cz <= c2z; cz++) {
                Integer hashCode = hashChunk(cx, cz);
                chunksToPortals.get(hashCode).remove(portal);
            }
        }
    }

    /**
     * Returns portals in the same chunk as the given location.
     *
     * @param location the location
     * @return a collection of nearby portals; may be empty, but will not be null
     */
    private Collection<MVPortal> getNearbyPortals(MultiverseWorld world, Location location) {

        Collection<MVPortal> nearbyPortals = null;

        Map<Integer, Collection<MVPortal>> chunkMap = this.worldChunkPortals.get(world);
        if (chunkMap != null) {
            int cx = blockToChunk(location.getBlockX());
            int cz = blockToChunk(location.getBlockZ());
            Integer hash = hashChunk(cx, cz);

            nearbyPortals = chunkMap.get(hash);
        }

        // Never return null. (This just keeps the caller from having to do a
        // null check.)
        return nearbyPortals != null ? nearbyPortals : emptyPortalSet;
    }
}
TOP

Related Classes of com.onarandombox.MultiversePortals.utils.PortalManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.