Work on TerritoryAccess and permissions.

This commit is contained in:
Olof Larsson 2013-04-29 12:48:11 +02:00
parent 3a6bca872f
commit 709c1fe80d
12 changed files with 132 additions and 189 deletions

View File

@ -2,19 +2,17 @@ package com.massivecraft.factions;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.entity.BoardColls;
import com.massivecraft.factions.entity.UPlayer;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.UConf;
import com.massivecraft.mcore.ps.PS;
import com.massivecraft.mcore.util.Txt;
/**
* Permissions that you (a player) may or may not have in the territory of a certain faction.
@ -26,21 +24,21 @@ public enum FPerm
// ENUM
// -------------------------------------------- //
BUILD("build", "edit the terrain", Rel.LEADER, Rel.OFFICER, Rel.MEMBER, Rel.ALLY),
PAINBUILD("painbuild", "edit, take damage"),
DOOR("door", "use doors", Rel.LEADER, Rel.OFFICER, Rel.MEMBER, Rel.RECRUIT, Rel.ALLY),
BUTTON("button", "use stone buttons", Rel.LEADER, Rel.OFFICER, Rel.MEMBER, Rel.RECRUIT, Rel.ALLY),
LEVER("lever", "use levers", Rel.LEADER, Rel.OFFICER, Rel.MEMBER, Rel.RECRUIT, Rel.ALLY),
CONTAINER("container", "use containers", Rel.LEADER, Rel.OFFICER, Rel.MEMBER),
BUILD(true, "build", "edit the terrain", Rel.LEADER, Rel.OFFICER, Rel.MEMBER, Rel.ALLY),
PAINBUILD(true, "painbuild", "edit, take damage"),
DOOR(true, "door", "use doors", Rel.LEADER, Rel.OFFICER, Rel.MEMBER, Rel.RECRUIT, Rel.ALLY),
BUTTON(true, "button", "use stone buttons", Rel.LEADER, Rel.OFFICER, Rel.MEMBER, Rel.RECRUIT, Rel.ALLY),
LEVER(true, "lever", "use levers", Rel.LEADER, Rel.OFFICER, Rel.MEMBER, Rel.RECRUIT, Rel.ALLY),
CONTAINER(true, "container", "use containers", Rel.LEADER, Rel.OFFICER, Rel.MEMBER),
INVITE("invite", "invite players", Rel.LEADER, Rel.OFFICER),
KICK("kick", "kick members", Rel.LEADER, Rel.OFFICER),
SETHOME("sethome", "set the home", Rel.LEADER, Rel.OFFICER),
WITHDRAW("withdraw", "withdraw money", Rel.LEADER, Rel.OFFICER),
TERRITORY("territory", "claim or unclaim", Rel.LEADER, Rel.OFFICER),
ACCESS("access", "grant territory", Rel.LEADER, Rel.OFFICER),
DISBAND("disband", "disband the faction", Rel.LEADER),
PERMS("perms", "manage permissions", Rel.LEADER),
INVITE(false, "invite", "invite players", Rel.LEADER, Rel.OFFICER),
KICK(false, "kick", "kick members", Rel.LEADER, Rel.OFFICER),
SETHOME(false, "sethome", "set the home", Rel.LEADER, Rel.OFFICER),
WITHDRAW(false, "withdraw", "withdraw money", Rel.LEADER, Rel.OFFICER),
TERRITORY(false, "territory", "claim or unclaim", Rel.LEADER, Rel.OFFICER),
ACCESS(false, "access", "grant territory", Rel.LEADER, Rel.OFFICER),
DISBAND(false, "disband", "disband the faction", Rel.LEADER),
PERMS(false, "perms", "manage permissions", Rel.LEADER),
// END OF LIST
;
@ -49,6 +47,9 @@ public enum FPerm
// FIELDS
// -------------------------------------------- //
private final boolean territoryPerm;
public boolean isTerritoryPerm() { return this.territoryPerm; }
private final String nicename;
public String getNicename() { return this.nicename; }
@ -62,8 +63,9 @@ public enum FPerm
// CONSTRUCT
// -------------------------------------------- //
private FPerm(final String nicename, final String desc, final Rel... rels)
private FPerm(boolean territoryPerm, final String nicename, final String desc, final Rel... rels)
{
this.territoryPerm = territoryPerm;
this.nicename = nicename;
this.desc = desc;
@ -120,7 +122,62 @@ public enum FPerm
}
// -------------------------------------------- //
// UTIL
// HAS?
// -------------------------------------------- //
public String createDeniedMessage(UPlayer uplayer, Faction hostFaction)
{
String ret = Txt.parse("%s<b> does not allow you to %s<b>.", hostFaction.describeTo(uplayer, true), this.getDescription());
if (Perm.ADMIN.has(uplayer.getPlayer()))
{
ret += Txt.parse("\n<i>You can bypass by using " + Factions.get().getOuterCmdFactions().cmdFactionsAdmin.getUseageTemplate(false));
}
return ret;
}
public boolean has(Faction faction, Faction hostFaction)
{
Rel rel = faction.getRelationTo(hostFaction);
return hostFaction.getPermittedRelations(this).contains(rel);
}
public boolean has(UPlayer uplayer, Faction hostFaction, boolean verboose)
{
if (uplayer.isUsingAdminMode()) return true;
Faction faction = uplayer.getFaction();
if (this.has(faction, hostFaction)) return true;
if (verboose) uplayer.sendMessage(this.createDeniedMessage(uplayer, hostFaction));
return false;
}
public boolean has(UPlayer uplayer, PS ps, boolean verboose)
{
if (uplayer.isUsingAdminMode()) return true;
TerritoryAccess ta = BoardColls.get().getTerritoryAccessAt(ps);
Faction hostFaction = ta.getHostFaction(ps);
if (this.isTerritoryPerm())
{
Boolean hasTerritoryAccess = ta.hasTerritoryAccess(uplayer);
if (hasTerritoryAccess != null)
{
if (verboose && !hasTerritoryAccess)
{
uplayer.sendMessage(this.createDeniedMessage(uplayer, hostFaction));
}
return hasTerritoryAccess;
}
}
return this.has(uplayer, hostFaction, verboose);
}
// -------------------------------------------- //
// UTIL: ASCII
// -------------------------------------------- //
public static String getStateHeaders()
@ -160,82 +217,5 @@ public enum FPerm
}
return ret;
}
// Perms which apply strictly to granting territory access
// TODO: This should be a boolean field within the class itself!
private static final Set<FPerm> TerritoryPerms = EnumSet.of(BUILD, DOOR, BUTTON, LEVER, CONTAINER);
public boolean isTerritoryPerm()
{
return TerritoryPerms.contains(this);
}
private static final String errorpattern = "%s<b> does not allow you to %s<b>.";
public boolean has(Object testSubject, Faction hostFaction, boolean informIfNot)
{
RelationParticipator rpSubject = null;
if (testSubject instanceof CommandSender)
{
rpSubject = UPlayer.get(testSubject);
}
else if (testSubject instanceof RelationParticipator)
{
rpSubject = (RelationParticipator) testSubject;
}
else
{
return false;
}
Rel rel = rpSubject.getRelationTo(hostFaction);
// TODO: Create better description messages like: "You must at least be officer".
boolean ret = hostFaction.getPermittedRelations(this).contains(rel);
if (rpSubject instanceof UPlayer && ret == false && ((UPlayer)rpSubject).isUsingAdminMode()) ret = true;
if (!ret && informIfNot && rpSubject instanceof UPlayer)
{
UPlayer uplayer = (UPlayer)rpSubject;
uplayer.msg(errorpattern, hostFaction.describeTo(uplayer, true), this.getDescription());
if (Perm.ADMIN.has(uplayer.getPlayer()))
{
uplayer.msg("<i>You can bypass by using " + Factions.get().getOuterCmdFactions().cmdFactionsAdmin.getUseageTemplate(false));
}
}
return ret;
}
public boolean has(Object testSubject, Faction hostFaction)
{
return this.has(testSubject, hostFaction, false);
}
public boolean has(Object testSubject, PS ps, boolean informIfNot)
{
TerritoryAccess access = BoardColls.get().getTerritoryAccessAt(ps);
if (this.isTerritoryPerm())
{
if (access.subjectHasAccess(testSubject)) return true;
if (access.subjectAccessIsRestricted(testSubject))
{
if (informIfNot)
{
UPlayer notify = null;
if (testSubject instanceof CommandSender)
notify = UPlayer.get(testSubject);
else if (testSubject instanceof UPlayer)
notify = (UPlayer)testSubject;
if (notify != null)
notify.msg("<b>This territory owned by your faction has restricted access.");
}
return false;
}
}
return this.has(testSubject, BoardColls.get().getFactionAt(ps), informIfNot);
}
public boolean has(Object testSubject, PS ps)
{
return this.has(testSubject, ps, false);
}
}

View File

@ -7,9 +7,6 @@ import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.massivecraft.factions.entity.FactionColl;
import com.massivecraft.factions.entity.UPlayer;
import com.massivecraft.factions.entity.Faction;
@ -199,66 +196,24 @@ public class TerritoryAccess
{
return this.isHostFactionAllowed() && this.getFactionIds().isEmpty() && this.getPlayerIds().isEmpty();
}
// -------------------------------------------- //
// HAS CHECK
// -------------------------------------------- //
// TODO: This looks like an extractor in my eyes.
// TODO: Perhaps create a factionId extractor?
public boolean doesHostFactionMatch(Object testSubject)
// true means elevated access
// false means decreased access
// null means standard access
public Boolean hasTerritoryAccess(UPlayer uplayer)
{
String factionId = null;
if (testSubject instanceof String)
{
factionId = (String)testSubject;
}
else if (testSubject instanceof CommandSender)
{
factionId = UPlayer.get(testSubject).getFactionId();
}
else if (testSubject instanceof UPlayer)
{
factionId = ((UPlayer)testSubject).getFactionId();
}
else if (testSubject instanceof Faction)
{
factionId = ((Faction)testSubject).getId();
}
return this.getHostFactionId().equals(factionId);
}
// -------------------------------------------- //
// DERPINGTON CHECKS
// -------------------------------------------- //
// these return false if not granted explicit access, or true if granted explicit access (in FPlayer or Faction lists)
// they do not take into account hostFactionAllowed, which will need to be checked separately (as to not override FPerms which are denied for faction members and such)
public boolean subjectHasAccess(Object testSubject)
{
if (testSubject instanceof Player)
{
return fPlayerHasAccess(UPlayer.get(testSubject));
}
else if (testSubject instanceof UPlayer)
{
return fPlayerHasAccess((UPlayer)testSubject);
}
else if (testSubject instanceof Faction)
{
return factionHasAccess((Faction)testSubject);
}
return false;
}
public boolean fPlayerHasAccess(UPlayer fplayer)
{
return this.isPlayerIdGranted(fplayer.getId()) || this.isFactionIdGranted(fplayer.getFaction().getId());
}
public boolean factionHasAccess(Faction faction)
{
return this.isFactionIdGranted(faction.getId());
}
// this should normally only be checked after running subjectHasAccess() or fPlayerHasAccess() above to see if they have access explicitly granted
public boolean subjectAccessIsRestricted(Object testSubject)
{
return (!this.isHostFactionAllowed() && this.doesHostFactionMatch(testSubject));
if (this.getPlayerIds().contains(uplayer.getId())) return true;
String factionId = uplayer.getFactionId();
if (this.getFactionIds().contains(factionId)) return true;
if (this.getHostFactionId().equals(factionId) && !this.isHostFactionAllowed()) return false;
return null;
}
}

View File

@ -39,7 +39,7 @@ public class CmdFactionsClaim extends FCommand
if (forFaction == null) return;
// FPerm
if (forFaction.isNormal() && !FPerm.TERRITORY.has(sender, forFaction, true)) return;
if (forFaction.isNormal() && !FPerm.TERRITORY.has(usender, forFaction, true)) return;
// Validate
if (radius < 1)

View File

@ -36,7 +36,7 @@ public class CmdFactionsDisband extends FCommand
if (faction == null) return;
// FPerm
if ( ! FPerm.DISBAND.has(sender, faction, true)) return;
if ( ! FPerm.DISBAND.has(usender, faction, true)) return;
// Verify
if (faction.getFlag(FFlag.PERMANENT))

View File

@ -46,7 +46,7 @@ public class CmdFactionsInvite extends FCommand
}
// FPerm
if ( ! FPerm.INVITE.has(sender, usenderFaction, true)) return;
if ( ! FPerm.INVITE.has(usender, usenderFaction, true)) return;
// Event
FactionsEventInvitedChange event = new FactionsEventInvitedChange(sender, uplayer, usenderFaction, newInvited);

View File

@ -57,7 +57,7 @@ public class CmdFactionsKick extends FCommand
// FPerm
Faction uplayerFaction = uplayer.getFaction();
if (!FPerm.KICK.has(sender, uplayerFaction, true)) return;
if (!FPerm.KICK.has(usender, uplayerFaction, true)) return;
// Event
FactionsEventMembershipChange event = new FactionsEventMembershipChange(sender, uplayer, FactionColls.get().get(uplayer).getNone(), MembershipChangeReason.KICK);

View File

@ -57,7 +57,7 @@ public class CmdFactionsPerm extends FCommand
}
// Do the sender have the right to change perms for this faction?
if ( ! FPerm.PERMS.has(sender, faction, true)) return;
if ( ! FPerm.PERMS.has(usender, faction, true)) return;
Rel rel = this.arg(2, ARRel.get());
if (rel == null) return;

View File

@ -42,7 +42,7 @@ public class CmdFactionsSethome extends FCommand
}
// FPerm
if ( ! FPerm.SETHOME.has(sender, faction, true)) return;
if ( ! FPerm.SETHOME.has(usender, faction, true)) return;
// Verify
if (!usender.isUsingAdminMode() && !faction.isValidHome(newHome))

View File

@ -30,7 +30,7 @@ public class CmdFactionsUnclaim extends FCommand
Faction newFaction = FactionColls.get().get(me).getNone();
// FPerm
if (!FPerm.TERRITORY.has(sender, usenderFaction, true)) return;
if (!FPerm.TERRITORY.has(usender, usenderFaction, true)) return;
// Apply
if (usender.tryClaim(newFaction, chunk, true, true)) return;

View File

@ -38,7 +38,7 @@ public class CmdFactionsUnclaimall extends FCommand
Faction newFaction = FactionColls.get().get(faction).getNone();
// FPerm
if (!FPerm.TERRITORY.has(sender, faction, true)) return;
if (!FPerm.TERRITORY.has(usender, faction, true)) return;
// Apply
BoardColl boardColl = BoardColls.get().get(faction);

View File

@ -89,7 +89,7 @@ public class Econ
if (i == fI && fI == fYou) return true;
// Factions can be controlled by those that have permissions
if (you instanceof Faction && FPerm.WITHDRAW.has(i, fYou, false)) return true;
if (you instanceof Faction && FPerm.WITHDRAW.has(fI, fYou)) return true;
// Otherwise you may not! ;,,;
i.msg("<h>%s<i> lacks permission to control <h>%s's<i> money.", i.describeTo(i, true), you.describeTo(i));

View File

@ -138,17 +138,26 @@ public class FactionsListenerMain implements Listener
player.sendMessage(msg);
}
// show access info message if needed
// Show access level message if it changed.
TerritoryAccess accessFrom = BoardColls.get().getTerritoryAccessAt(chunkFrom);
Boolean hasTerritoryAccessFrom = accessFrom.hasTerritoryAccess(uplayer);
TerritoryAccess accessTo = BoardColls.get().getTerritoryAccessAt(chunkTo);
if (!accessTo.isDefault())
Boolean hasTerritoryAccessTo = accessTo.hasTerritoryAccess(uplayer);
if (!MUtil.equals(hasTerritoryAccessFrom, hasTerritoryAccessTo))
{
if (accessTo.subjectHasAccess(uplayer))
if (hasTerritoryAccessTo == null)
{
uplayer.msg("<g>You have access to this area.");
uplayer.msg("<i>You have standard access to this area.");
}
else if (accessTo.subjectAccessIsRestricted(uplayer))
else if (hasTerritoryAccessTo)
{
uplayer.msg("<b>This area has restricted access.");
uplayer.msg("<g>You have elevated access to this area.");
}
else
{
uplayer.msg("<b>You have decreased access to this area.");
}
}
}
@ -691,33 +700,32 @@ public class FactionsListenerMain implements Listener
// FLAG: BUILD
// -------------------------------------------- //
public static boolean canPlayerBuildAt(Player player, PS ps, boolean justCheck)
public static boolean canPlayerBuildAt(Player player, PS ps, boolean verboose)
{
String name = player.getName();
if (MConf.get().playersWhoBypassAllProtection.contains(name)) return true;
UPlayer me = UPlayer.get(player);
if (me.isUsingAdminMode()) return true;
UPlayer uplayer = UPlayer.get(player);
if (uplayer.isUsingAdminMode()) return true;
Faction factionHere = BoardColls.get().getFactionAt(ps);
if ( ! FPerm.BUILD.has(me, ps) && FPerm.PAINBUILD.has(me, ps))
if (!FPerm.BUILD.has(uplayer, ps, false) && FPerm.PAINBUILD.has(uplayer, ps, false))
{
if (!justCheck)
if (verboose)
{
me.msg("<b>It is painful to build in the territory of %s<b>.", factionHere.describeTo(me));
Faction hostFaction = BoardColls.get().getFactionAt(ps);
uplayer.msg("<b>It is painful to build in the territory of %s<b>.", hostFaction.describeTo(uplayer));
player.damage(UConf.get(player).actionDeniedPainAmount);
}
return true;
}
return FPerm.BUILD.has(me, ps, true);
return FPerm.BUILD.has(uplayer, ps, verboose);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void blockBuild(HangingPlaceEvent event)
{
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getEntity()), false)) return;
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getEntity()), true)) return;
event.setCancelled(true);
}
@ -731,7 +739,7 @@ public class FactionsListenerMain implements Listener
Entity breaker = entityEvent.getRemover();
if (! (breaker instanceof Player)) return;
if ( ! canPlayerBuildAt((Player)breaker, PS.valueOf(event.getEntity()), false))
if ( ! canPlayerBuildAt((Player)breaker, PS.valueOf(event.getEntity()), true))
{
event.setCancelled(true);
}
@ -742,7 +750,7 @@ public class FactionsListenerMain implements Listener
{
if (!event.canBuild()) return;
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), false)) return;
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), true)) return;
event.setBuild(false);
event.setCancelled(true);
@ -751,7 +759,7 @@ public class FactionsListenerMain implements Listener
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void blockBuild(BlockBreakEvent event)
{
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), false)) return;
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), true)) return;
event.setCancelled(true);
}
@ -761,7 +769,7 @@ public class FactionsListenerMain implements Listener
{
if (!event.getInstaBreak()) return;
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), false)) return;
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), true)) return;
event.setCancelled(true);
}
@ -781,7 +789,7 @@ public class FactionsListenerMain implements Listener
if (targetFaction == pistonFaction) return;
// if potentially pushing into air/water/lava in another territory, we need to check it out
if ((targetBlock.isEmpty() || targetBlock.isLiquid()) && ! FPerm.BUILD.has(pistonFaction, PS.valueOf(targetBlock)))
if ((targetBlock.isEmpty() || targetBlock.isLiquid()) && ! FPerm.BUILD.has(pistonFaction, targetFaction))
{
event.setCancelled(true);
}
@ -811,7 +819,7 @@ public class FactionsListenerMain implements Listener
Faction targetFaction = BoardColls.get().getFactionAt(retractPs);
if (targetFaction == pistonFaction) return;
if (!FPerm.BUILD.has(pistonFaction, retractPs))
if (!FPerm.BUILD.has(pistonFaction, targetFaction))
{
event.setCancelled(true);
}