Slightly better claim messages. Much better LWC.
This commit is contained in:
		@@ -394,6 +394,9 @@ public class MConf extends Entity<MConf>
 | 
			
		||||
	// INTEGRATION: LWC
 | 
			
		||||
	// -------------------------------------------- //
 | 
			
		||||
	
 | 
			
		||||
	public boolean lwcMustHaveBuildRightsToCreate = true;
 | 
			
		||||
	public boolean lwcRemoveIfNoBuildRights = false;
 | 
			
		||||
	
 | 
			
		||||
	public Map<EventFactionsChunkChangeType, Boolean> lwcRemoveOnChange = MUtil.map(
 | 
			
		||||
		EventFactionsChunkChangeType.BUY, false,
 | 
			
		||||
		EventFactionsChunkChangeType.SELL, false,
 | 
			
		||||
 
 | 
			
		||||
@@ -814,10 +814,10 @@ public class MPlayer extends SenderEntity<MPlayer> implements EconomyParticipato
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		String chunkString = chunk.toString(PSFormatHumanSpace.get());
 | 
			
		||||
		String typeString = event.getType().toString().toLowerCase();
 | 
			
		||||
		String typeString = event.getType().past;
 | 
			
		||||
		for (MPlayer informee : informees)
 | 
			
		||||
		{
 | 
			
		||||
			informee.msg("<h>%s<i> did %s %s <i>for <h>%s<i> from <h>%s<i>.", this.describeTo(informee, true), typeString, chunkString, newFaction.describeTo(informee), oldFaction.describeTo(informee));
 | 
			
		||||
			informee.msg("<h>%s<i> %s %s <i>| <h>%s<i> --> <h>%s", this.describeTo(informee, true), typeString, chunkString, oldFaction.describeTo(informee, true), newFaction.describeTo(informee, true));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ public abstract class EventFactionsAbstractSender extends EventMassiveCore
 | 
			
		||||
	
 | 
			
		||||
	private final CommandSender sender;
 | 
			
		||||
	public CommandSender getSender() { return this.sender; }
 | 
			
		||||
	public MPlayer getUSender() { return this.sender == null ? null : MPlayer.get(this.sender); }
 | 
			
		||||
	public MPlayer getMSender() { return this.sender == null ? null : MPlayer.get(this.sender); }
 | 
			
		||||
	
 | 
			
		||||
	// -------------------------------------------- //
 | 
			
		||||
	// CONSTRUCT
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,7 @@ public class EventFactionsChunkChange extends EventFactionsAbstractSender
 | 
			
		||||
		if (currentFaction.isNone()) return EventFactionsChunkChangeType.BUY;
 | 
			
		||||
		if (newFaction.isNormal()) return EventFactionsChunkChangeType.CONQUER;
 | 
			
		||||
		
 | 
			
		||||
		MPlayer usender = this.getUSender();
 | 
			
		||||
		MPlayer usender = this.getMSender();
 | 
			
		||||
		if (usender != null && usender.getFaction() == currentFaction) return EventFactionsChunkChangeType.SELL;
 | 
			
		||||
		
 | 
			
		||||
		return EventFactionsChunkChangeType.PILLAGE;
 | 
			
		||||
 
 | 
			
		||||
@@ -2,9 +2,33 @@ package com.massivecraft.factions.event;
 | 
			
		||||
 | 
			
		||||
public enum EventFactionsChunkChangeType
 | 
			
		||||
{
 | 
			
		||||
	BUY,
 | 
			
		||||
	SELL,
 | 
			
		||||
	CONQUER,
 | 
			
		||||
	PILLAGE,
 | 
			
		||||
	// -------------------------------------------- //
 | 
			
		||||
	// ENUM
 | 
			
		||||
	// -------------------------------------------- //
 | 
			
		||||
	
 | 
			
		||||
	BUY("buy", "bought"),
 | 
			
		||||
	SELL("sell", "sold"),
 | 
			
		||||
	CONQUER("conquer", "conquered"),
 | 
			
		||||
	PILLAGE("pillage", "pillaged"),
 | 
			
		||||
	
 | 
			
		||||
	// END OF LIST
 | 
			
		||||
	;
 | 
			
		||||
	
 | 
			
		||||
	// -------------------------------------------- //
 | 
			
		||||
	// FIELDS
 | 
			
		||||
	// -------------------------------------------- //
 | 
			
		||||
	
 | 
			
		||||
	public final String now;
 | 
			
		||||
	public final String past;
 | 
			
		||||
	
 | 
			
		||||
	// -------------------------------------------- //
 | 
			
		||||
	// CONSTRUCT
 | 
			
		||||
	// -------------------------------------------- //
 | 
			
		||||
	
 | 
			
		||||
	EventFactionsChunkChangeType(String now, String past)
 | 
			
		||||
	{
 | 
			
		||||
		this.now = now;
 | 
			
		||||
		this.past = past;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,11 +29,11 @@ public class EventFactionsPvpDisallowed extends EventFactionsAbstract
 | 
			
		||||
	
 | 
			
		||||
	private final Player attacker;
 | 
			
		||||
	public Player getAttacker() { return this.attacker; }
 | 
			
		||||
	public MPlayer getUAttacker() { return this.attacker == null ? null : MPlayer.get(this.attacker); }
 | 
			
		||||
	public MPlayer getMAttacker() { return this.attacker == null ? null : MPlayer.get(this.attacker); }
 | 
			
		||||
	
 | 
			
		||||
	private final Player defender;
 | 
			
		||||
	public Player getDefender() { return this.defender; }
 | 
			
		||||
	public MPlayer getUDefender() { return this.defender == null ? null : MPlayer.get(this.defender); }
 | 
			
		||||
	public MPlayer getMDefender() { return this.defender == null ? null : MPlayer.get(this.defender); }
 | 
			
		||||
	
 | 
			
		||||
	private final EntityDamageByEntityEvent event;
 | 
			
		||||
	public EntityDamageByEntityEvent getEvent() { return this.event; }
 | 
			
		||||
 
 | 
			
		||||
@@ -228,6 +228,8 @@ public abstract class ChannelFactionsAbstract implements Channel
 | 
			
		||||
	{
 | 
			
		||||
		Set<Player> ret = new HashSet<Player>();
 | 
			
		||||
		
 | 
			
		||||
		// TODO: Dormant non-erased universe support?
 | 
			
		||||
		
 | 
			
		||||
		MPlayer fpsender = MPlayer.get(sender);
 | 
			
		||||
		Faction faction = fpsender.getFaction();
 | 
			
		||||
		String universe = fpsender.getUniverse();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,15 @@
 | 
			
		||||
package com.massivecraft.factions.integration.lwc;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.Chunk;
 | 
			
		||||
import org.bukkit.Material;
 | 
			
		||||
import org.bukkit.block.Block;
 | 
			
		||||
import org.bukkit.block.BlockState;
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.event.EventHandler;
 | 
			
		||||
import org.bukkit.event.EventPriority;
 | 
			
		||||
import org.bukkit.plugin.Plugin;
 | 
			
		||||
 | 
			
		||||
import com.griefcraft.lwc.LWC;
 | 
			
		||||
import com.griefcraft.model.Protection;
 | 
			
		||||
import com.griefcraft.sql.PhysDB;
 | 
			
		||||
import com.massivecraft.factions.Factions;
 | 
			
		||||
import com.massivecraft.factions.entity.Faction;
 | 
			
		||||
import com.massivecraft.factions.entity.MConf;
 | 
			
		||||
@@ -21,6 +18,7 @@ import com.massivecraft.factions.event.EventFactionsChunkChange;
 | 
			
		||||
import com.massivecraft.factions.event.EventFactionsChunkChangeType;
 | 
			
		||||
import com.massivecraft.massivecore.EngineAbstract;
 | 
			
		||||
import com.massivecraft.massivecore.ps.PS;
 | 
			
		||||
import com.massivecraft.massivecore.util.IdUtil;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public class EngineLwc extends EngineAbstract
 | 
			
		||||
@@ -72,54 +70,70 @@ public class EngineLwc extends EngineAbstract
 | 
			
		||||
		if (remove == false) return;
 | 
			
		||||
		
 | 
			
		||||
		// ... then remove for all other factions than the new one.
 | 
			
		||||
		removeAlienProtections(event.getChunk(), newFaction);
 | 
			
		||||
		// First we wait one tick to make sure the chunk ownership changes have been applied.
 | 
			
		||||
		// Then we remove the protections but we do it asynchronously to not lock the main thread.
 | 
			
		||||
		removeAlienProtectionsAsyncNextTick(event.getChunk(), newFaction);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// -------------------------------------------- //
 | 
			
		||||
	// UTIL
 | 
			
		||||
	// -------------------------------------------- //
 | 
			
		||||
	
 | 
			
		||||
	public static void removeAlienProtections(PS chunkPs, Faction faction)
 | 
			
		||||
	// This method causes LWC to run an SQL query which can take a few milliseconds.
 | 
			
		||||
	// For that reason this method should not be executed in the main server thread.
 | 
			
		||||
	// After looking through the source code of LWC I am also hopeful this is thread safe. 
 | 
			
		||||
	public static List<Protection> getProtectionsInChunk(PS chunkPs)
 | 
			
		||||
	{
 | 
			
		||||
		final int xmin = chunkPs.getChunkX() * 16;
 | 
			
		||||
		final int xmax = xmin + 15;
 | 
			
		||||
		
 | 
			
		||||
		final int ymin = 0;
 | 
			
		||||
		final int ymax = 255;
 | 
			
		||||
		
 | 
			
		||||
		final int zmin = chunkPs.getChunkZ() * 16;
 | 
			
		||||
		final int zmax = zmin + 15;
 | 
			
		||||
		
 | 
			
		||||
		PhysDB db = LWC.getInstance().getPhysicalDatabase();
 | 
			
		||||
		return db.loadProtections(chunkPs.getWorld(), xmin, xmax, ymin, ymax, zmin, zmax);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// As with the method above: Thread safe and slow. Do run asynchronously.
 | 
			
		||||
	public static void removeAlienProtectionsRaw(PS chunkPs, Faction faction)
 | 
			
		||||
	{
 | 
			
		||||
		List<MPlayer> nonAliens = faction.getMPlayers();
 | 
			
		||||
		for (Protection protection : getProtectionsInChunk(chunkPs))
 | 
			
		||||
		{
 | 
			
		||||
			MPlayer owner = MPlayer.get(protection.getOwner());
 | 
			
		||||
			// NOTE: The LWC protection owner is still the name and not the UUID. For that reason we must convert it. 
 | 
			
		||||
			String ownerName = protection.getOwner();
 | 
			
		||||
			String ownerId = IdUtil.getId(ownerName);
 | 
			
		||||
			MPlayer owner = MPlayer.get(ownerId);
 | 
			
		||||
			if (nonAliens.contains(owner)) continue;
 | 
			
		||||
			protection.remove();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public static List<Protection> getProtectionsInChunk(PS chunkPs)
 | 
			
		||||
	public static void removeAlienProtectionsAsync(final PS chunkPs, final Faction faction)
 | 
			
		||||
	{
 | 
			
		||||
		List<Protection> ret = new ArrayList<Protection>();
 | 
			
		||||
		
 | 
			
		||||
		// Get the chunk
 | 
			
		||||
		Chunk chunk = null;
 | 
			
		||||
		try
 | 
			
		||||
		Bukkit.getScheduler().runTaskAsynchronously(Factions.get(), new Runnable()
 | 
			
		||||
		{
 | 
			
		||||
			chunk = chunkPs.asBukkitChunk(true);
 | 
			
		||||
		}
 | 
			
		||||
		catch (Exception e)
 | 
			
		||||
		{
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		for (BlockState blockState : chunk.getTileEntities())
 | 
			
		||||
		{
 | 
			
		||||
			// TODO: Can something else be protected by LWC? Or is it really only chests?
 | 
			
		||||
			// TODO: How about we run through each block in the chunk just to be on the safe side?
 | 
			
		||||
			if (blockState.getType() != Material.CHEST) continue;
 | 
			
		||||
			Block block = blockState.getBlock();
 | 
			
		||||
			
 | 
			
		||||
			Protection protection = LWC.getInstance().findProtection(block);
 | 
			
		||||
			if (protection == null) continue;
 | 
			
		||||
			
 | 
			
		||||
			ret.add(protection);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return ret;
 | 
			
		||||
			@Override
 | 
			
		||||
			public void run()
 | 
			
		||||
			{
 | 
			
		||||
				removeAlienProtectionsRaw(chunkPs, faction);
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public static void removeAlienProtectionsAsyncNextTick(final PS chunkPs, final Faction faction)
 | 
			
		||||
	{
 | 
			
		||||
		Bukkit.getScheduler().runTaskLater(Factions.get(), new Runnable()
 | 
			
		||||
		{
 | 
			
		||||
			@Override
 | 
			
		||||
			public void run()
 | 
			
		||||
			{
 | 
			
		||||
				removeAlienProtectionsAsync(chunkPs, faction);
 | 
			
		||||
			}
 | 
			
		||||
		}, 0);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,24 @@
 | 
			
		||||
package com.massivecraft.factions.integration.lwc;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.Location;
 | 
			
		||||
import org.bukkit.Sound;
 | 
			
		||||
import org.bukkit.block.Block;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
 | 
			
		||||
import com.griefcraft.lwc.LWC;
 | 
			
		||||
import com.griefcraft.model.Protection;
 | 
			
		||||
import com.griefcraft.scripting.JavaModule;
 | 
			
		||||
import com.griefcraft.scripting.event.LWCProtectionInteractEvent;
 | 
			
		||||
import com.griefcraft.scripting.event.LWCProtectionRegisterEvent;
 | 
			
		||||
import com.massivecraft.factions.Factions;
 | 
			
		||||
import com.massivecraft.factions.entity.MConf;
 | 
			
		||||
import com.massivecraft.factions.entity.MPlayer;
 | 
			
		||||
import com.massivecraft.factions.listeners.FactionsListenerMain;
 | 
			
		||||
import com.massivecraft.massivecore.mixin.Mixin;
 | 
			
		||||
import com.massivecraft.massivecore.ps.PS;
 | 
			
		||||
import com.massivecraft.massivecore.util.IdUtil;
 | 
			
		||||
import com.massivecraft.massivecore.util.SmokeUtil;
 | 
			
		||||
import com.massivecraft.massivecore.util.Txt;
 | 
			
		||||
 | 
			
		||||
@SuppressWarnings("unused")
 | 
			
		||||
public class FactionsLwcModule extends JavaModule
 | 
			
		||||
@@ -31,12 +44,61 @@ public class FactionsLwcModule extends JavaModule
 | 
			
		||||
	// -------------------------------------------- //
 | 
			
		||||
	// OVERRIDE
 | 
			
		||||
	// -------------------------------------------- //
 | 
			
		||||
	// 
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public void onRegisterProtection(LWCProtectionRegisterEvent event)
 | 
			
		||||
	{
 | 
			
		||||
		if (FactionsListenerMain.canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), false)) return;
 | 
			
		||||
		// If this feature is enabled ...
 | 
			
		||||
		if ( ! MConf.get().lwcMustHaveBuildRightsToCreate) return;
 | 
			
		||||
		
 | 
			
		||||
		// ... and the player don't have build rights here ...
 | 
			
		||||
		// NOTE: We verbosely check the build rights so that a proper info message is sent 
 | 
			
		||||
		if (FactionsListenerMain.canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), true)) return;
 | 
			
		||||
		
 | 
			
		||||
		// ... then cancel the event.
 | 
			
		||||
		event.setCancelled(true);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public void onProtectionInteract(LWCProtectionInteractEvent event)
 | 
			
		||||
	{
 | 
			
		||||
		// If this feature is enabled ...
 | 
			
		||||
		if ( ! MConf.get().lwcRemoveIfNoBuildRights) return;
 | 
			
		||||
		
 | 
			
		||||
		// ... gather data ...
 | 
			
		||||
		final Protection protection = event.getProtection();
 | 
			
		||||
		final Block block = protection.getBlock();
 | 
			
		||||
		final PS ps = PS.valueOf(block);
 | 
			
		||||
		// NOTE: The LWC protection owner is still the name and not the UUID. For that reason we must convert it. 
 | 
			
		||||
		final String ownerName = protection.getOwner();
 | 
			
		||||
		final String ownerId = IdUtil.getId(ownerName);
 | 
			
		||||
		final MPlayer mowner = MPlayer.get(ownerId);
 | 
			
		||||
		if (mowner == null) return;
 | 
			
		||||
		
 | 
			
		||||
		// ... and if the protection owner no longer has build rights for the area ...
 | 
			
		||||
		// NOTE: We silently check the build rights for the protection owner.
 | 
			
		||||
		// NOTE: The protection owner may even be offline at the moment.
 | 
			
		||||
		if (FactionsListenerMain.canPlayerBuildAt(mowner, ps, false)) return;
 | 
			
		||||
		
 | 
			
		||||
		// ... remove the protection ...
 | 
			
		||||
		protection.remove();
 | 
			
		||||
		
 | 
			
		||||
		// ... cancel the event ...
 | 
			
		||||
		// NOTE: The first time you click nothing but the unlock should happen.
 | 
			
		||||
		// NOTE: This way it's more obvious the auto unlock system kicked in.
 | 
			
		||||
		// NOTE: No inventory will get opened.
 | 
			
		||||
		event.setResult(Result.CANCEL);
 | 
			
		||||
		
 | 
			
		||||
		// ... play FX ...
 | 
			
		||||
		Location location = block.getLocation();
 | 
			
		||||
		SmokeUtil.spawnCloudSimple(location);
 | 
			
		||||
		location.getWorld().playSound(location, Sound.DOOR_OPEN, 1, 1);
 | 
			
		||||
		
 | 
			
		||||
		// ... and inform.
 | 
			
		||||
		Player player = event.getPlayer();
 | 
			
		||||
		String message = Txt.parse("<i>Factions removed <h>%s's <i>LWC. They lacked build rights.", mowner.getDisplayName(player));
 | 
			
		||||
		player.sendMessage(message);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -75,7 +75,7 @@ public class FactionsListenerEcon implements Listener
 | 
			
		||||
	public void takeOnDisband(EventFactionsDisband event)
 | 
			
		||||
	{
 | 
			
		||||
		// If there is a usender ...
 | 
			
		||||
		MPlayer usender = event.getUSender();
 | 
			
		||||
		MPlayer usender = event.getMSender();
 | 
			
		||||
		if (usender == null) return;
 | 
			
		||||
		
 | 
			
		||||
		// ... and economy is enabled ...
 | 
			
		||||
@@ -100,7 +100,7 @@ public class FactionsListenerEcon implements Listener
 | 
			
		||||
	public static void payForAction(EventFactionsAbstractSender event, Double cost, String desc)
 | 
			
		||||
	{
 | 
			
		||||
		// If there is a sender ...
 | 
			
		||||
		MPlayer usender = event.getUSender();
 | 
			
		||||
		MPlayer usender = event.getMSender();
 | 
			
		||||
		if (usender == null) return;
 | 
			
		||||
		
 | 
			
		||||
		// ... and there is a cost ...
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user