AreaShop/AreaShop/src/main/java/me/wiefferink/areashop/managers/SignLinkerManager.java

231 lines
6.2 KiB
Java

package me.wiefferink.areashop.managers;
import me.wiefferink.areashop.features.signs.RegionSign;
import me.wiefferink.areashop.features.signs.SignsFeature;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.Materials;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.util.BlockIterator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
public class SignLinkerManager extends Manager implements Listener {
private final Map<UUID, SignLinker> signLinkers;
private boolean eventsRegistered;
public SignLinkerManager() {
signLinkers = new HashMap<>();
eventsRegistered = false;
}
@Override
public void shutdown() {
for(UUID uuid : signLinkers.keySet()) {
exitSignLinkMode(Bukkit.getPlayer(uuid));
}
}
/**
* Let a player enter sign linking mode.
* @param player The player that has to enter sign linking mode
* @param profile The profile to use for the signs (null for default)
*/
public void enterSignLinkMode(Player player, String profile) {
signLinkers.put(player.getUniqueId(), new SignLinker(player, profile));
plugin.message(player, "linksigns-first");
plugin.message(player, "linksigns-next");
if(!eventsRegistered) {
eventsRegistered = true;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
}
/**
* Let a player exit sign linking mode.
* @param player The player that has to exit sign linking mode
*/
public void exitSignLinkMode(Player player) {
signLinkers.remove(player.getUniqueId());
if(eventsRegistered && signLinkers.isEmpty()) {
eventsRegistered = false;
HandlerList.unregisterAll(this);
}
plugin.message(player, "linksigns-stopped");
}
/**
* Check if the player is in sign linking mode.
* @param player The player to check
* @return true if the player is in sign linking mode, otherwise false
*/
public boolean isInSignLinkMode(Player player) {
return signLinkers.containsKey(player.getUniqueId());
}
/**
* On player interactions.
* @param event The PlayerInteractEvent
*/
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerInteract(PlayerInteractEvent event) {
if(isInSignLinkMode(event.getPlayer())) {
event.setCancelled(true);
Player player = event.getPlayer();
SignLinker linker = signLinkers.get(event.getPlayer().getUniqueId());
if(event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
// Get the region
BlockIterator blockIterator = new BlockIterator(player, 100);
while(blockIterator.hasNext()) {
Block next = blockIterator.next();
List<GeneralRegion> regions = Utils.getRegions(next.getLocation());
if(regions.size() == 1) {
linker.setRegion(regions.get(0));
return;
} else if(regions.size() > 1) {
Set<String> names = new HashSet<>();
for(GeneralRegion region : regions) {
names.add(region.getName());
}
plugin.message(player, "linksigns-multipleRegions", Utils.createCommaSeparatedList(names));
plugin.message(player, "linksigns-multipleRegionsAdvice");
return;
}
}
// No regions found within the maximum range
plugin.message(player, "linksigns-noRegions");
} else if(event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK) {
Block block = null;
BlockIterator blockIterator = new BlockIterator(player, 100);
while(blockIterator.hasNext() && block == null) {
Block next = blockIterator.next();
if(next.getType() != Material.AIR) {
block = next;
}
}
if(block == null || !Materials.isSign(block.getType())) {
plugin.message(player, "linksigns-noSign");
return;
}
RegionSign regionSign = SignsFeature.getSignByLocation(block.getLocation());
if(regionSign != null) {
plugin.message(player, "linksigns-alreadyRegistered", regionSign.getRegion());
return;
}
linker.setSign(block.getLocation(), block.getType(), plugin.getBukkitHandler().getSignFacing(block));
}
}
}
/**
* Handle disconnection players.
* @param event The PlayerQuitEvent
*/
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerLeave(PlayerQuitEvent event) {
exitSignLinkMode(event.getPlayer());
}
/**
* Class to keep track of the signlinking data.
*/
private class SignLinker {
private boolean hasSign = false;
private boolean hasRegion = false;
public final Player linker;
public final String profile;
public GeneralRegion region = null;
public Location location = null;
public Material type = null;
public BlockFace facing = null;
public SignLinker(Player linker, String profile) {
this.linker = linker;
this.profile = profile;
}
public void setRegion(GeneralRegion region) {
this.region = region;
hasRegion = true;
if(!isComplete()) {
plugin.message(linker, "linksigns-regionFound", region);
}
finish();
}
public void setSign(Location location, Material type, BlockFace facing) {
this.location = location;
this.type = type;
this.facing = facing;
hasSign = true;
if(!isComplete()) {
plugin.message(linker, "linksigns-signFound", location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
finish();
}
public void finish() {
if(isComplete()) {
region.getSignsFeature().addSign(location, type, facing, profile);
if(profile == null) {
plugin.message(linker, "addsign-success", region);
} else {
plugin.message(linker, "addsign-successProfile", region, profile);
}
region.update();
reset();
plugin.message(linker, "linksigns-next");
}
}
public void reset() {
hasSign = false;
hasRegion = false;
}
public boolean isComplete() {
return hasSign && hasRegion;
}
}
}