diff --git a/src/com/massivecraft/factions/engine/EngineChunkChange.java b/src/com/massivecraft/factions/engine/EngineChunkChange.java index f010d44e..4208c4cf 100644 --- a/src/com/massivecraft/factions/engine/EngineChunkChange.java +++ b/src/com/massivecraft/factions/engine/EngineChunkChange.java @@ -19,6 +19,7 @@ import org.bukkit.ChatColor; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -204,6 +205,32 @@ public class EngineChunkChange extends Engine } } + // Ensure claims are properly connected when unclaiming + if (newFaction.isNone() && MConf.get().claimsMustBeConnected && MConf.get().claimsMustBeConnectedStrict) + { + for (Entry> entry : currentFactionChunks.entrySet()) + { + Faction faction = entry.getKey(); + Set factionRemovedChunks = entry.getValue(); + + Set pssBefore = BoardColl.get().getChunks(faction); + + // Get how many "forests" of claims there are right now + List> forestsBefore = BoardColl.getForests(pssBefore); + + Set pssAfter = new MassiveSet<>(pssBefore); + pssAfter.removeAll(factionRemovedChunks); + + List> forestsAfter = BoardColl.getForests(pssAfter); + if (forestsAfter.size() > forestsBefore.size()) + { + mplayer.msg("Claims must be connected. You can't make them unconnected by unclaiming."); + event.setCancelled(true); + return; + } + } + } + // For each of the old factions ... for (Entry> entry : currentFactionChunks.entrySet()) { diff --git a/src/com/massivecraft/factions/entity/BoardColl.java b/src/com/massivecraft/factions/entity/BoardColl.java index f9a1d412..014a06ca 100644 --- a/src/com/massivecraft/factions/entity/BoardColl.java +++ b/src/com/massivecraft/factions/entity/BoardColl.java @@ -1,6 +1,7 @@ package com.massivecraft.factions.entity; import com.massivecraft.factions.TerritoryAccess; +import com.massivecraft.massivecore.collections.MassiveList; import com.massivecraft.massivecore.collections.MassiveMap; import com.massivecraft.massivecore.collections.MassiveSet; import com.massivecraft.massivecore.entity.MassiveCoreMConf; @@ -9,9 +10,11 @@ import com.massivecraft.massivecore.store.Coll; import com.massivecraft.massivecore.util.MUtil; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.Stack; import java.util.stream.Collectors; public class BoardColl extends Coll implements BoardInterface @@ -390,5 +393,44 @@ public class BoardColl extends Coll implements BoardInterface // Return return ret; } - + + public static List> getForests(Collection pss) + { + List> forests = new MassiveList<>(); + List discovered = new MassiveList<>(); + + outer: + for (PS ps : pss) + { + if (discovered.contains(ps)) continue outer; + + List forest = new MassiveList<>(); + forests.add(forest); + + Stack stack = new Stack<>(); + stack.push(ps); + inner: + while (!stack.empty()) + { + PS elm = stack.pop(); + if (discovered.contains(elm)) continue inner; + System.out.println(elm); + discovered.add(elm); + forest.add(elm); + + addIfInSource(elm.withChunkX(elm.getChunkX() + 1), stack, pss); + addIfInSource(elm.withChunkX(elm.getChunkX() - 1), stack, pss); + addIfInSource(elm.withChunkZ(elm.getChunkZ() + 1), stack, pss); + addIfInSource(elm.withChunkZ(elm.getChunkZ() - 1), stack, pss); + } + } + + return forests; + } + + private static void addIfInSource(PS ps, Stack stack, Collection source) + { + if (source.contains(ps)) stack.push(ps); + } + } diff --git a/src/com/massivecraft/factions/entity/MConf.java b/src/com/massivecraft/factions/entity/MConf.java index a6c364fb..ab321f4b 100644 --- a/src/com/massivecraft/factions/entity/MConf.java +++ b/src/com/massivecraft/factions/entity/MConf.java @@ -207,6 +207,11 @@ public class MConf extends Entity // If you set this to false you will allow factions to claim more than one base per world map. // That would makes outposts possible but also potentially ugly weird claims messing up your Dynmap and ingame experiance. public boolean claimsMustBeConnected = true; + + // Must claims be connected to each other enforced strictly? + // If this is enabled there is also done a check on + // unclaim which makes sure you can't make two different bases by unclaiming land. + public boolean claimsMustBeConnectedStrict = false; // Would you like to allow unconnected claims when conquering land from another faction? // Setting this to true would allow taking over someone elses base even if claims normally have to be connected.