Custom ranks

This commit is contained in:
Magnus Ulf 2018-12-21 02:41:42 +01:00
parent 0efccf335c
commit cee15b6333
16 changed files with 870 additions and 426 deletions

View File

@ -1,4 +1,5 @@
main: ${project.groupId}.${project.name} main: ${project.groupId}.${project.name}
main: ${project.groupId}.${project.name}
name: ${project.name} name: ${project.name}
version: ${project.version} version: ${project.version}
website: ${project.url} website: ${project.url}
@ -65,7 +66,14 @@ permissions:
factions.powerboost.set: {description: set powerboost, default: false} factions.powerboost.set: {description: set powerboost, default: false}
factions.rank: {description: manage/show ranks, default: false} factions.rank: {description: manage/show ranks, default: false}
factions.rank.show: {description: show rank, default: false} factions.rank.show: {description: show rank, default: false}
factions.rank.action: {description: change rank, default: false} factions.rank.set: {description: set rank, default: false}
factions.rank.list: {description: list ranks, default: false}
factions.rank.edit: {description: edit ranks, default: false}
factions.rank.edit.create: {description: create rank, default: false}
factions.rank.edit.name: {description: set rank name, default: false}
factions.rank.edit.prefix: {description: set rank prefix, default: false}
factions.rank.edit.priority: {description: set rank priority, default: false}
factions.rank.edit.delete: {description: delete rank, default: false}
factions.relation: {description: manage faction relations, default: false} factions.relation: {description: manage faction relations, default: false}
factions.relation.list: {description: list all factions with certain relation, default: false} factions.relation.list: {description: list all factions with certain relation, default: false}
factions.relation.set: {description: set relation wish to another faction, default: false} factions.relation.set: {description: set relation wish to another faction, default: false}
@ -154,6 +162,16 @@ permissions:
factions.powerboost.faction: true factions.powerboost.faction: true
factions.powerboost.player: true factions.powerboost.player: true
factions.powerboost.set: true factions.powerboost.set: true
factions.rank: true
factions.rank.show: true
factions.rank.set: true
factions.rank.list: true
factions.rank.edit: true
factions.rank.edit.create: true
factions.rank.edit.name: true
factions.rank.edit.prefix: true
factions.rank.edit.priority: true
factions.rank.edit.delete: true
factions.promote: true factions.promote: true
factions.relation: true factions.relation: true
factions.relation.list: true factions.relation.list: true
@ -267,7 +285,14 @@ permissions:
factions.powerboost.player: true factions.powerboost.player: true
factions.rank: true factions.rank: true
factions.rank.show: true factions.rank.show: true
factions.rank.action: true factions.rank.set: true
factions.rank.list: true
factions.rank.edit: true
factions.rank.edit.create: true
factions.rank.edit.name: true
factions.rank.edit.prefix: true
factions.rank.edit.priority: true
factions.rank.edit.delete: true
factions.relation: true factions.relation: true
factions.relation.list: true factions.relation.list: true
factions.relation.set: true factions.relation.set: true

View File

@ -65,7 +65,14 @@ public enum Perm implements Identified
POWERBOOST_SET, POWERBOOST_SET,
RANK, RANK,
RANK_SHOW, RANK_SHOW,
RANK_ACTION, RANK_SET,
RANK_LIST,
RANK_EDIT,
RANK_EDIT_CREATE,
RANK_EDIT_NAME,
RANK_EDIT_PREFIX,
RANK_EDIT_PRIORITY,
RANK_EDIT_DELETE,
RELATION, RELATION,
RELATION_SET, RELATION_SET,
RELATION_LIST, RELATION_LIST,

View File

@ -1,387 +1,14 @@
package com.massivecraft.factions.cmd; package com.massivecraft.factions.cmd;
import com.massivecraft.factions.Factions;
import com.massivecraft.factions.Perm;
import com.massivecraft.factions.cmd.type.TypeFaction;
import com.massivecraft.factions.cmd.type.TypeMPlayer;
import com.massivecraft.factions.cmd.type.TypeRank;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.MConf;
import com.massivecraft.factions.entity.MFlag;
import com.massivecraft.factions.entity.MPerm;
import com.massivecraft.factions.entity.MPlayer;
import com.massivecraft.factions.entity.MPlayerColl;
import com.massivecraft.factions.entity.Rank;
import com.massivecraft.factions.event.EventFactionsMembershipChange;
import com.massivecraft.factions.event.EventFactionsMembershipChange.MembershipChangeReason;
import com.massivecraft.factions.event.EventFactionsRankChange;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.util.Txt;
import java.util.HashSet;
import java.util.Set;
public class CmdFactionsRank extends FactionsCommand public class CmdFactionsRank extends FactionsCommand
{ {
// -------------------------------------------- // // -------------------------------------------- //
// FIELDS // FIELDS
// -------------------------------------------- // // -------------------------------------------- //
// These fields are set upon perform() and unset afterwards.
// Target public CmdFactionsRankSet cmdFactionsRankSet = new CmdFactionsRankSet();
private Faction targetFaction = null; public CmdFactionsRankShow cmdFactionsRankShow = new CmdFactionsRankShow();
private MPlayer target = null; public CmdFactionsRankList cmdFactionsRankList = new CmdFactionsRankList();
public CmdFactionsRankEdit cmdFactionsRankEdit = new CmdFactionsRankEdit();
// End faction (the faction they are changed to)
private Faction endFaction = null;
private boolean factionChange = false;
// Ranks
private Rank senderRank = null;
private Rank targetRank = null;
private Rank rank = null;
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdFactionsRank()
{
// Parameters
this.addParameter(TypeMPlayer.get(), "player");
this.addParameter(TypeRank.get(), "rank", "show");
this.addParameter(TypeFaction.get(), "faction", "their");
// Too complicated for that
this.setSwapping(false);
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException
{
// This sets target and much other.
this.registerFields();
// Sometimes we just want to show the rank.
if ( ! this.argIsSet(1))
{
if ( ! Perm.RANK_SHOW.has(sender, true)) return;
this.showRank();
return;
}
// Permission check.
if ( ! Perm.RANK_ACTION.has(sender, true)) return;
// Is the player allowed or not. Method can be found later down.
this.ensureAllowed();
if (factionChange)
{
this.changeFaction();
}
// Does the change make sense.
this.ensureMakesSense();
// Event
EventFactionsRankChange event = new EventFactionsRankChange(sender, target, rank);
event.run();
if (event.isCancelled()) return;
rank = event.getNewRank();
// Change the rank.
this.changeRank();
}
// This is always run after performing a MassiveCommand.
@Override
public void senderFields(boolean set)
{
super.senderFields(set);
if ( ! set)
{
this.unregisterFields();
}
}
// -------------------------------------------- //
// PRIVATE: REGISTER & UNREGISTER
// -------------------------------------------- //
private void registerFields() throws MassiveException
{
// Getting the target and faction.
target = this.readArg(msender);
targetFaction = target.getFaction();
// Ranks
senderRank = msender.getRank();
targetRank = target.getRank();
endFaction = this.readArgAt(2, targetFaction);
factionChange = (endFaction != targetFaction);
// Rank if any passed.
if (this.argIsSet(1))
{
TypeRank typeRank = new TypeRank(endFaction);
rank = typeRank.read(this.argAt(1), sender);
}
}
private void unregisterFields()
{
targetFaction = null;
target = null;
endFaction = null;
factionChange = false;
senderRank = null;
targetRank = null;
rank = null;
}
// -------------------------------------------- //
// PRIVATE: ENSURE
// -------------------------------------------- //
private void ensureAllowed() throws MassiveException
{
// People with permission don't follow the normal rules.
if (msender.isOverriding()) return;
// If somone gets the leadership of wilderness (Which has happened before).
// We can at least try to limit their powers.
if (endFaction.isNone())
{
throw new MassiveException().addMsg("%s <b>doesn't use ranks sorry :(", endFaction.getName());
}
if (target == msender)
{
// Don't change your own rank.
throw new MassiveException().addMsg("<b>The target player mustn't be yourself.");
}
if (factionChange)
{
// Don't change peoples faction
throw new MassiveException().addMsg("<b>You can't change %s's <b>faction.", target.describeTo(msender));
}
if (!MPerm.getPermRank().has(msender, targetFaction, false))
{
throw new MassiveException().addMessage(MPerm.getPermRank().createDeniedMessage(msender, targetFaction));
}
// The following two if statements could be merged.
// But isn't for the sake of nicer error messages.
if (senderRank == targetRank)
{
// You can't change someones rank if it is equal to yours.
throw new MassiveException().addMsg("<h>%s <b>can't manage eachother.", senderRank.getName()+"s");
}
if (senderRank.isLessThan(targetRank))
{
// You can't change someones rank if it is higher than yours.
throw new MassiveException().addMsg("<b>You can't manage people of higher rank.");
}
// The following two if statements could be merged.
// But isn't for the sake of nicer error messages.
if (senderRank == rank && !senderRank.isLeader())
{
// You can't set ranks equal to your own. Unless you are the leader.
throw new MassiveException().addMsg("<b>You can't set ranks equal to your own.");
}
if (senderRank.isLessThan(rank))
{
// You can't set ranks higher than your own.
throw new MassiveException().addMsg("<b>You can't set ranks higher than your own.");
}
}
private void ensureMakesSense() throws MassiveException
{
// Don't change their rank to something they already are.
if (target.getRank() == rank)
{
throw new MassiveException().addMsg("%s <b>is already %s %s.", target.describeTo(msender), Txt.aan(rank.getName()), rank.getName());
}
}
// -------------------------------------------- //
// PRIVATE: SHOW
// -------------------------------------------- //
private void showRank()
{
// Damn you grammar, causing all these checks.
String targetName = target.describeTo(msender, true);
String isAre = (target == msender) ? "are" : "is"; // "you are" or "he is"
String theAan = (targetRank.isLeader()) ? "the" : Txt.aan(targetRank.getName()); // "a member", "an officer" or "the leader"
String rankName = targetRank.getName().toLowerCase();
String ofIn = (targetRank.isLeader()) ? "of" : "in"; // "member in" or "leader of"
String factionName = targetFaction.describeTo(msender, true);
if (targetFaction == msenderFaction)
{
// Having the "Y" in "Your faction" being uppercase in the middle of a sentence makes no sense.
factionName = factionName.toLowerCase();
}
if (targetFaction.isNone())
{
// Wilderness aka none doesn't use ranks
msg("%s <i>%s factionless", targetName, isAre);
}
else
{
// Derp is a member in Faction
msg("%s <i>%s %s <h>%s <i>%s %s<i>.", targetName, isAre, theAan, rankName, ofIn, factionName);
}
}
// -------------------------------------------- //
// PRIVATE: CHANGE FACTION
// -------------------------------------------- //
private void changeFaction() throws MassiveException
{
// Don't change a leader to a new faction.
if (targetRank.isLeader())
{
throw new MassiveException().addMsg("<b>You cannot remove the present leader. Demote them first.");
}
// Event
EventFactionsMembershipChange membershipChangeEvent = new EventFactionsMembershipChange(sender, msender, endFaction, MembershipChangeReason.RANK);
membershipChangeEvent.run();
if (membershipChangeEvent.isCancelled()) throw new MassiveException();
// Apply
target.resetFactionData();
target.setFaction(endFaction);
// No longer invited.
endFaction.uninvite(target);
// Create recipients
Set<MPlayer> recipients = new HashSet<>();
recipients.addAll(targetFaction.getMPlayersWhereOnline(true));
recipients.addAll(endFaction.getMPlayersWhereOnline(true));
recipients.add(msender);
// Send message
for (MPlayer recipient : recipients)
{
recipient.msg("%s <i>was moved from <i>%s to <i>%s<i>.", target.describeTo(recipient), targetFaction.describeTo(recipient), endFaction.describeTo(recipient));
}
// Derplog
if (MConf.get().logFactionJoin)
{
Factions.get().log(Txt.parse("%s moved %s from %s to %s.", msender.getName(), target.getName(), targetFaction.getName(), endFaction.getName()));
}
// Now we don't need the old values.
targetFaction = target.getFaction();
targetRank = target.getRank();
senderRank = msender.getRank(); // In case they changed their own rank
}
// -------------------------------------------- //
// PRIVATE: CHANGE RANK
// -------------------------------------------- //
private void changeRank() throws MassiveException
{
// In case of leadership change, we do special things not done in other rank changes.
if (rank.isLeader())
{
this.changeRankLeader();
}
else
{
this.changeRankOther();
}
}
private void changeRankLeader()
{
// If there is a current leader. Demote & inform them.
MPlayer targetFactionCurrentLeader = targetFaction.getLeader();
if (targetFactionCurrentLeader != null)
{
// Inform & demote the old leader.
targetFactionCurrentLeader.setRank(rank.getRankBelow());
if (targetFactionCurrentLeader != msender)
{
// They kinda know if they fired the command themself.
targetFactionCurrentLeader.msg("<i>You have been demoted from the position of faction leader by %s<i>.", msender.describeTo(targetFactionCurrentLeader, true));
}
}
// Promote the new leader.
target.setRank(rank);
// Inform everyone, this includes sender and target.
for (MPlayer recipient : MPlayerColl.get().getAllOnline())
{
String changerName = senderIsConsole ? "A server admin" : msender.describeTo(recipient);
recipient.msg("%s<i> gave %s<i> the leadership of %s<i>.", changerName, target.describeTo(recipient), targetFaction.describeTo(recipient));
}
}
private void changeRankOther() throws MassiveException
{
// If the target is currently the leader and faction isn't permanent a new leader should be promoted.
// Sometimes a bug occurs and multiple leaders exist. Then we should be able to demote without promoting new leader
if (targetRank.isLeader() && ( ! MConf.get().permanentFactionsDisableLeaderPromotion || ! targetFaction.getFlag(MFlag.ID_PERMANENT)) && targetFaction.getMPlayersWhereRank(targetFaction.getLeaderRank()).size() == 1)
// This if statement is very long. Should I nest it for readability?
{
targetFaction.promoteNewLeader(); // This might disband the faction.
// So if the faction disbanded...
if (targetFaction.detached())
{
// ... we inform the sender.
target.resetFactionData();
throw new MassiveException().addMsg("<i>The target was a leader and got demoted. The faction disbanded and no rank was set.");
}
}
// Create recipients
Set<MPlayer> recipients = new HashSet<>();
recipients.addAll(targetFaction.getMPlayers());
recipients.add(msender);
// Were they demoted or promoted?
String change = (rank.isLessThan(targetRank) ? "demoted" : "promoted");
// The rank will be set before the msg, so they have the appropriate prefix.
target.setRank(rank);
String oldRankName = targetRank.getName().toLowerCase();
String rankName = rank.getName().toLowerCase();
// Send message
for(MPlayer recipient : recipients)
{
String targetName = target.describeTo(recipient, true);
String wasWere = (recipient == target) ? "were" : "was";
recipient.msg("%s<i> %s %s from %s to <h>%s <i>in %s<i>.", targetName, wasWere, change, oldRankName, rankName, targetFaction.describeTo(msender));
}
}
} }

View File

@ -0,0 +1,34 @@
package com.massivecraft.factions.cmd;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.MPlayer;
import com.massivecraft.massivecore.MassiveException;
public class CmdFactionsRankEdit extends FactionsCommand
{
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
public CmdFactionsRankEditCreate cmdFactionsRankEditCreate = new CmdFactionsRankEditCreate();
public CmdFactionsRankEditDelete cmdFactionsRankEditDelete = new CmdFactionsRankEditDelete();
public CmdFactionsRankEditName cmdFactionsRankEditName = new CmdFactionsRankEditName();
public CmdFactionsRankEditPrefix cmdFactionsRankEditPrefix = new CmdFactionsRankEditPrefix();
public CmdFactionsRankEditPriority cmdFactionsRankEditPriority = new CmdFactionsRankEditPriority();
static void ensureAllowed(MPlayer msender, Faction faction) throws MassiveException
{
if (msender.isOverriding()) return;
if (faction != msender.getFaction())
{
throw new MassiveException().addMsg("<b>You can't manage ranks outside your own faction.");
}
if (!msender.getRank().isLeader())
{
throw new MassiveException().addMsg("<b>Only the leader can create ranks.");
}
}
}

View File

@ -0,0 +1,65 @@
package com.massivecraft.factions.cmd;
import com.massivecraft.factions.cmd.type.TypeFaction;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.Rank;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeInteger;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
public class CmdFactionsRankEditCreate extends FactionsCommand
{
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdFactionsRankEditCreate()
{
// Parameters
this.addParameter(TypeString.get(), "name");
this.addParameter(TypeInteger.get(), "priority");
this.addParameter("", TypeString.get(), "prefix", "none");
this.addParameter(TypeFaction.get(), "faction", "you");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException
{
// Args
String name = this.readArg();
Integer priority = this.readArg();
String prefix = this.readArg();
Faction faction = this.readArg(msenderFaction);
CmdFactionsRankEdit.ensureAllowed(msender, faction);
var ranks = faction.getRanks().getAll();
if (ranks.stream().map(Rank::getName).anyMatch(s -> s.equalsIgnoreCase(name)))
{
throw new MassiveException().addMsg("<b>There is already a rank called <h>%s<b>.", name);
}
if (ranks.stream().map(Rank::getPriority).anyMatch(i -> i.equals(priority)))
{
throw new MassiveException().addMsg("<b>There is already a with priority <h>%s<b>.", priority);
}
if (priority > faction.getLeaderRank().getPriority())
{
throw new MassiveException().addMsg("<b>You can't create a rank of higher priority than the leader rank.");
}
Rank rank = new Rank(name, priority, prefix);
faction.getRanks().attach(rank);
// Inform
msg("<i>You created the rank <reset>%s<i>.", rank.getVisual());
msg("<i>You might want to change its permissions:");
CmdFactions.get().cmdFactionsPerm.getTemplate(false, true, sender).messageOne(msender);
}
}

View File

@ -0,0 +1,64 @@
package com.massivecraft.factions.cmd;
import com.massivecraft.factions.cmd.type.TypeFaction;
import com.massivecraft.factions.cmd.type.TypeRank;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.Rank;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
import com.massivecraft.massivecore.util.Txt;
import java.util.stream.Collectors;
public class CmdFactionsRankEditDelete extends FactionsCommand
{
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdFactionsRankEditDelete()
{
// Parameters
this.addParameter(TypeString.get(), "rank");
this.addParameter(TypeFaction.get(), "faction", "you");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException
{
// Args
Faction faction = this.readArgAt(1, msenderFaction);
// Rank if any passed.
TypeRank typeRank = new TypeRank(faction);
Rank rank = typeRank.read(this.argAt(0), sender);
CmdFactionsRankEdit.ensureAllowed(msender, faction);
var ranks = faction.getRanks().getAll();
if (ranks.size() <= 2)
{
throw new MassiveException().addMsg("<b>A faction must have at least two ranks.");
}
var mplayers = faction.getMPlayersWhereRank(rank);
if (!mplayers.isEmpty())
{
var count = mplayers.size();
var names = mplayers.stream().map(m -> m.getDisplayName(sender)).collect(Collectors.toList());
var namesDesc = Txt.implodeCommaAnd(names, Txt.parse("<i>"));
throw new MassiveException().addMsg("<b>This rank is held by <h>%s <b>change their ranks first.", namesDesc);
}
String visual = rank.getVisual();
faction.getRanks().detachEntity(rank);
// Inform
msg("<i>You deleted the rank <reset>%s<i>.", visual);
}
}

View File

@ -0,0 +1,57 @@
package com.massivecraft.factions.cmd;
import com.massivecraft.factions.cmd.type.TypeFaction;
import com.massivecraft.factions.cmd.type.TypeRank;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.Rank;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
public class CmdFactionsRankEditName extends FactionsCommand
{
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdFactionsRankEditName()
{
// Parameters
this.addParameter(TypeRank.get(), "rank");
this.addParameter(TypeString.get(), "new name");
this.addParameter(TypeFaction.get(), "faction", "you");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException
{
// Args
String name = this.readArgAt(1);
Faction faction = this.readArgAt(2, msenderFaction);
// Rank if any passed.
TypeRank typeRank = new TypeRank(faction);
Rank rank = typeRank.read(this.argAt(0), sender);
// Args
CmdFactionsRankEdit.ensureAllowed(msender, faction);
var ranks = faction.getRanks().getAll();
if (ranks.stream().map(Rank::getName).anyMatch(s -> s.equalsIgnoreCase(name)))
{
throw new MassiveException().addMsg("<b>There is already a rank called <h>%s<b>.", name);
}
var priorVisual = rank.getVisual();
rank.setName(name);
// Visual
msg("<i>You renamed the rank from <reset>%s <i>to <reset>%s<i>.", priorVisual, rank.getVisual());
}
}

View File

@ -0,0 +1,50 @@
package com.massivecraft.factions.cmd;
import com.massivecraft.factions.cmd.type.TypeFaction;
import com.massivecraft.factions.cmd.type.TypeRank;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.Rank;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeString;
public class CmdFactionsRankEditPrefix extends FactionsCommand
{
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdFactionsRankEditPrefix()
{
// Parameters
this.addParameter(TypeRank.get(), "rank");
this.addParameter(TypeString.get(), "new prefix");
this.addParameter(TypeFaction.get(), "faction", "you");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException
{
// Args
String prefix = this.readArgAt(1);
Faction faction = this.readArgAt(2, msenderFaction);
// Rank if any passed.
TypeRank typeRank = new TypeRank(faction);
Rank rank = typeRank.read(this.argAt(0), sender);
// Args
CmdFactionsRankEdit.ensureAllowed(msender, faction);
var priorPrefix = rank.getPrefix();
rank.setPrefix(prefix);
// Visual
msg("<i>You changed the prefix of <reset>%s <i>from <h>%s <i>to <h>%s<i>.", rank.getVisual(), priorPrefix, prefix);
}
}

View File

@ -0,0 +1,71 @@
package com.massivecraft.factions.cmd;
import com.massivecraft.factions.cmd.type.TypeFaction;
import com.massivecraft.factions.cmd.type.TypeRank;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.Rank;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.type.primitive.TypeInteger;
public class CmdFactionsRankEditPriority extends FactionsCommand
{
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdFactionsRankEditPriority()
{
// Parameters
this.addParameter(TypeRank.get(), "rank");
this.addParameter(TypeInteger.get(), "new priority");
this.addParameter(TypeFaction.get(), "faction", "you");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException
{
// Args
Integer priority = this.readArgAt(1);
Faction faction = this.readArgAt(2, msenderFaction);
// Rank if any passed.
TypeRank typeRank = new TypeRank(faction);
Rank rank = typeRank.read(this.argAt(0), sender);
CmdFactionsRankEdit.ensureAllowed(msender, faction);
var ranks = faction.getRanks().getAll();
if (ranks.stream().map(Rank::getPriority).anyMatch(s -> s.equals(priority)))
{
throw new MassiveException().addMsg("<b>There is already a rank with the priority <h>%s<b>.", priority);
}
if (rank.isLeader())
{
Rank below = rank.getRankBelow();
if (below.getPriority() > priority)
{
throw new MassiveException().addMsg("<b>The leader rank must have the highest priority.");
}
}
else
{
if (priority >= faction.getLeaderRank().getPriority())
{
throw new MassiveException().addMsg("<b>No rank can have higher priority than the leader rank.");
}
}
var priorPriority = rank.getPriority();
rank.setPriority(priority);
// Visual
msg("<i>You changed the priority of <reset>%s <i>from <h>%s <i>to <h>%s<i>.", rank.getVisual(), priorPriority, priority);
}
}

View File

@ -0,0 +1,43 @@
package com.massivecraft.factions.cmd;
import com.massivecraft.factions.cmd.type.TypeFaction;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.Rank;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.command.Parameter;
import com.massivecraft.massivecore.pager.Pager;
import com.massivecraft.massivecore.pager.Stringifier;
import java.util.Comparator;
public class CmdFactionsRankList extends FactionsCommand
{
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdFactionsRankList()
{
// Parameters
this.addParameter(Parameter.getPage());
this.addParameter(TypeFaction.get(), "faction", "you");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException
{
final int page = this.readArg();
Faction faction = this.readArg(msenderFaction);
var ranks = faction.getRanks().getAll(Comparator.comparingInt(Rank::getPriority).reversed());
String title = "Rank list for " + faction.describeTo(msender);
var pager = new Pager(this, title, page, ranks, (Stringifier<Rank>) (r, i) -> r.getVisual());
pager.message();
}
}

View File

@ -0,0 +1,341 @@
package com.massivecraft.factions.cmd;
import com.massivecraft.factions.Factions;
import com.massivecraft.factions.cmd.type.TypeFaction;
import com.massivecraft.factions.cmd.type.TypeMPlayer;
import com.massivecraft.factions.cmd.type.TypeRank;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.MConf;
import com.massivecraft.factions.entity.MFlag;
import com.massivecraft.factions.entity.MPerm;
import com.massivecraft.factions.entity.MPlayer;
import com.massivecraft.factions.entity.MPlayerColl;
import com.massivecraft.factions.entity.Rank;
import com.massivecraft.factions.event.EventFactionsMembershipChange;
import com.massivecraft.factions.event.EventFactionsMembershipChange.MembershipChangeReason;
import com.massivecraft.factions.event.EventFactionsRankChange;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.util.Txt;
import java.util.HashSet;
import java.util.Set;
public class CmdFactionsRankSet extends FactionsCommand
{
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
// These fields are set upon perform() and unset afterwards.
// Target
private Faction targetFaction = null;
private MPlayer target = null;
// End faction (the faction they are changed to)
private Faction endFaction = null;
private boolean factionChange = false;
// Ranks
private Rank senderRank = null;
private Rank targetRank = null;
private Rank rank = null;
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdFactionsRankSet()
{
// Parameters
this.addParameter(TypeMPlayer.get(), "player");
this.addParameter(TypeRank.get(), "rank");
this.addParameter(TypeFaction.get(), "faction", "their");
// Too complicated for that
this.setSwapping(false);
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException
{
// This sets target and much other.
this.registerFields();
// Is the player allowed or not. Method can be found later down.
this.ensureAllowed();
if (factionChange)
{
this.changeFaction();
}
// Does the change make sense.
this.ensureMakesSense();
// Event
EventFactionsRankChange event = new EventFactionsRankChange(sender, target, rank);
event.run();
if (event.isCancelled()) return;
rank = event.getNewRank();
// Change the rank.
this.changeRank();
}
// This is always run after performing a MassiveCommand.
@Override
public void senderFields(boolean set)
{
super.senderFields(set);
if ( ! set)
{
this.unregisterFields();
}
}
// -------------------------------------------- //
// PRIVATE: REGISTER & UNREGISTER
// -------------------------------------------- //
private void registerFields() throws MassiveException
{
// Getting the target and faction.
target = this.readArg(msender);
targetFaction = target.getFaction();
// Ranks
senderRank = msender.getRank();
targetRank = target.getRank();
endFaction = this.readArgAt(2, targetFaction);
factionChange = (endFaction != targetFaction);
// Rank if any passed.
TypeRank typeRank = new TypeRank(endFaction);
rank = typeRank.read(this.argAt(1), sender);
}
private void unregisterFields()
{
targetFaction = null;
target = null;
endFaction = null;
factionChange = false;
senderRank = null;
targetRank = null;
rank = null;
}
// -------------------------------------------- //
// PRIVATE: ENSURE
// -------------------------------------------- //
private void ensureAllowed() throws MassiveException
{
// People with permission don't follow the normal rules.
if (msender.isOverriding()) return;
// If somone gets the leadership of wilderness (Which has happened before).
// We can at least try to limit their powers.
if (endFaction.isNone())
{
throw new MassiveException().addMsg("%s <b>doesn't use ranks sorry :(", endFaction.getName());
}
if (target == msender)
{
// Don't change your own rank.
throw new MassiveException().addMsg("<b>The target player mustn't be yourself.");
}
if (factionChange)
{
// Don't change peoples faction
throw new MassiveException().addMsg("<b>You can't change %s's <b>faction.", target.describeTo(msender));
}
if (!MPerm.getPermRank().has(msender, targetFaction, false))
{
throw new MassiveException().addMessage(MPerm.getPermRank().createDeniedMessage(msender, targetFaction));
}
// The following two if statements could be merged.
// But isn't for the sake of nicer error messages.
if (senderRank == targetRank)
{
// You can't change someones rank if it is equal to yours.
throw new MassiveException().addMsg("<h>%s <b>can't manage eachother.", senderRank.getName()+"s");
}
if (senderRank.isLessThan(targetRank))
{
// You can't change someones rank if it is higher than yours.
throw new MassiveException().addMsg("<b>You can't manage people of higher rank.");
}
// The following two if statements could be merged.
// But isn't for the sake of nicer error messages.
if (senderRank == rank && !senderRank.isLeader())
{
// You can't set ranks equal to your own. Unless you are the leader.
throw new MassiveException().addMsg("<b>You can't set ranks equal to your own.");
}
if (senderRank.isLessThan(rank))
{
// You can't set ranks higher than your own.
throw new MassiveException().addMsg("<b>You can't set ranks higher than your own.");
}
}
private void ensureMakesSense() throws MassiveException
{
// Don't change their rank to something they already are.
if (target.getRank() == rank)
{
throw new MassiveException().addMsg("%s <b>is already %s %s.", target.describeTo(msender), Txt.aan(rank.getName()), rank.getName());
}
}
// -------------------------------------------- //
// PRIVATE: CHANGE FACTION
// -------------------------------------------- //
private void changeFaction() throws MassiveException
{
// Don't change a leader to a new faction.
if (targetRank.isLeader())
{
throw new MassiveException().addMsg("<b>You cannot remove the present leader. Demote them first.");
}
// Event
EventFactionsMembershipChange membershipChangeEvent = new EventFactionsMembershipChange(sender, msender, endFaction, MembershipChangeReason.RANK);
membershipChangeEvent.run();
if (membershipChangeEvent.isCancelled()) throw new MassiveException();
// Apply
target.resetFactionData();
target.setFaction(endFaction);
// No longer invited.
endFaction.uninvite(target);
// Create recipients
Set<MPlayer> recipients = new HashSet<>();
recipients.addAll(targetFaction.getMPlayersWhereOnline(true));
recipients.addAll(endFaction.getMPlayersWhereOnline(true));
recipients.add(msender);
// Send message
for (MPlayer recipient : recipients)
{
recipient.msg("%s <i>was moved from <i>%s to <i>%s<i>.", target.describeTo(recipient), targetFaction.describeTo(recipient), endFaction.describeTo(recipient));
}
// Derplog
if (MConf.get().logFactionJoin)
{
Factions.get().log(Txt.parse("%s moved %s from %s to %s.", msender.getName(), target.getName(), targetFaction.getName(), endFaction.getName()));
}
// Now we don't need the old values.
targetFaction = target.getFaction();
targetRank = target.getRank();
senderRank = msender.getRank(); // In case they changed their own rank
}
// -------------------------------------------- //
// PRIVATE: CHANGE RANK
// -------------------------------------------- //
private void changeRank() throws MassiveException
{
// In case of leadership change, we do special things not done in other rank changes.
if (rank.isLeader())
{
this.changeRankLeader();
}
else
{
this.changeRankOther();
}
}
private void changeRankLeader()
{
// If there is a current leader. Demote & inform them.
MPlayer targetFactionCurrentLeader = targetFaction.getLeader();
if (targetFactionCurrentLeader != null)
{
// Inform & demote the old leader.
targetFactionCurrentLeader.setRank(rank.getRankBelow());
if (targetFactionCurrentLeader != msender)
{
// They kinda know if they fired the command themself.
targetFactionCurrentLeader.msg("<i>You have been demoted from the position of faction leader by %s<i>.", msender.describeTo(targetFactionCurrentLeader, true));
}
}
// Promote the new leader.
target.setRank(rank);
// Inform everyone, this includes sender and target.
for (MPlayer recipient : MPlayerColl.get().getAllOnline())
{
String changerName = senderIsConsole ? "A server admin" : msender.describeTo(recipient);
recipient.msg("%s<i> gave %s<i> the leadership of %s<i>.", changerName, target.describeTo(recipient), targetFaction.describeTo(recipient));
}
}
private void changeRankOther() throws MassiveException
{
// If the target is currently the leader and faction isn't permanent a new leader should be promoted.
// Sometimes a bug occurs and multiple leaders exist. Then we should be able to demote without promoting new leader
if (targetRank.isLeader() && ( ! MConf.get().permanentFactionsDisableLeaderPromotion || ! targetFaction.getFlag(MFlag.ID_PERMANENT)) && targetFaction.getMPlayersWhereRank(targetFaction.getLeaderRank()).size() == 1)
// This if statement is very long. Should I nest it for readability?
{
targetFaction.promoteNewLeader(); // This might disband the faction.
// So if the faction disbanded...
if (targetFaction.detached())
{
// ... we inform the sender.
target.resetFactionData();
throw new MassiveException().addMsg("<i>The target was a leader and got demoted. The faction disbanded and no rank was set.");
}
}
// Create recipients
Set<MPlayer> recipients = new HashSet<>();
recipients.addAll(targetFaction.getMPlayers());
recipients.add(msender);
// Were they demoted or promoted?
String change = (rank.isLessThan(targetRank) ? "demoted" : "promoted");
// The rank will be set before the msg, so they have the appropriate prefix.
target.setRank(rank);
String oldRankName = targetRank.getName().toLowerCase();
String rankName = rank.getName().toLowerCase();
// Send message
for(MPlayer recipient : recipients)
{
String targetName = target.describeTo(recipient, true);
String wasWere = (recipient == target) ? "were" : "was";
recipient.msg("%s<i> %s %s from %s to <h>%s <i>in %s<i>.", targetName, wasWere, change, oldRankName, rankName, targetFaction.describeTo(msender));
}
}
}

View File

@ -0,0 +1,56 @@
package com.massivecraft.factions.cmd;
import com.massivecraft.factions.cmd.type.TypeMPlayer;
import com.massivecraft.factions.entity.MPlayer;
import com.massivecraft.factions.entity.Rank;
import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.util.Txt;
public class CmdFactionsRankShow extends FactionsCommand
{
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public CmdFactionsRankShow()
{
// Parameters
this.addParameter(TypeMPlayer.get(), "player");
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public void perform() throws MassiveException
{
MPlayer target = this.readArg();
Rank rank = target.getRank();
// Damn you grammar, causing all these checks.
String targetName = target.describeTo(msender, true);
String isAre = (target == msender) ? "are" : "is"; // "you are" or "he is"
String theAan = (rank.isLeader()) ? "the" : Txt.aan(rank.getName()); // "a member", "an officer" or "the leader"
String rankName = rank.getName().toLowerCase();
String ofIn = (rank.isLeader()) ? "of" : "in"; // "member in" or "leader of"
String factionName = target.getFaction().describeTo(msender, true);
if (target.getFaction() == msenderFaction)
{
// Having the "Y" in "Your faction" being uppercase in the middle of a sentence makes no sense.
factionName = factionName.toLowerCase();
}
if (target.getFaction().isNone())
{
// Wilderness aka none doesn't use ranks
msg("%s <i>%s factionless", targetName, isAre);
}
else
{
// Derp is a member in Faction
msg("%s <i>%s %s <h>%s <i>%s %s<i>.", targetName, isAre, theAan, rankName, ofIn, factionName);
}
}
}

View File

@ -4,8 +4,11 @@ import com.massivecraft.factions.Rel;
import com.massivecraft.factions.entity.Faction; import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.Rank; import com.massivecraft.factions.entity.Rank;
import com.massivecraft.massivecore.command.type.TypeAbstractChoice; import com.massivecraft.massivecore.command.type.TypeAbstractChoice;
import com.massivecraft.massivecore.util.MUtil;
import org.bukkit.command.CommandSender;
import java.util.Collections; import java.util.Collections;
import java.util.Set;
public class TypeRank extends TypeAbstractChoice<Rank> public class TypeRank extends TypeAbstractChoice<Rank>
{ {
@ -41,4 +44,22 @@ public class TypeRank extends TypeAbstractChoice<Rank>
private final Faction faction; private final Faction faction;
public Faction getFaction() { return this.faction; } public Faction getFaction() { return this.faction; }
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public boolean isValid(String arg, CommandSender sender)
{
// In the generic case accept all
if (this.getAll().isEmpty()) return true;
else return super.isValid(arg, sender);
}
@Override
public Set<String> getNamesInner(Rank value)
{
return MUtil.set(value.getName(), value.getPrefix() + value.getName());
}
} }

View File

@ -523,10 +523,10 @@ public class Faction extends Entity<Faction> implements FactionsParticipator, MP
private EntityInternalMap<Rank> createRankMap() private EntityInternalMap<Rank> createRankMap()
{ {
var ret = new EntityInternalMap<>(this, Rank.class); var ret = new EntityInternalMap<>(this, Rank.class);
Rank leader = new Rank("Leader", 400); Rank leader = new Rank("Leader", 400, "**");
Rank officer = new Rank("Officer", 300); Rank officer = new Rank("Officer", 300, "*");
Rank member = new Rank("Member", 200); Rank member = new Rank("Member", 200, "+");
Rank recruit = new Rank("Recruit", 100); Rank recruit = new Rank("Recruit", 100, "-");
/*leader.setPermIds(new MassiveList<>(MConf.get().defaultPermsLeader)); /*leader.setPermIds(new MassiveList<>(MConf.get().defaultPermsLeader));
officer.setPermIds(new MassiveList<>(MConf.get().defaultPermsOfficer)); officer.setPermIds(new MassiveList<>(MConf.get().defaultPermsOfficer));

View File

@ -1,6 +1,7 @@
package com.massivecraft.factions.entity; package com.massivecraft.factions.entity;
import com.massivecraft.massivecore.store.EntityInternal; import com.massivecraft.massivecore.store.EntityInternal;
import org.bukkit.ChatColor;
public class Rank extends EntityInternal<Rank> implements MPerm.MPermable public class Rank extends EntityInternal<Rank> implements MPerm.MPermable
{ {
@ -28,19 +29,9 @@ public class Rank extends EntityInternal<Rank> implements MPerm.MPermable
public int getPriority() { return this.priority; } public int getPriority() { return this.priority; }
public void setPriority(int priority) { this.priority = priority; this.changed(); } public void setPriority(int priority) { this.priority = priority; this.changed(); }
public String getPrefix() private String prefix;
{ public String getPrefix() { return this.prefix; }
String ret = ""; public void setPrefix(String prefix) { this.prefix = prefix; this.changed(); }
if (this.isLeader()) ret += "L";
if (this.getName().equalsIgnoreCase("Leader")) ret += "**";
else if (this.getName().equalsIgnoreCase("Officer")) ret += "*";
else if (this.getName().equalsIgnoreCase("Member")) ret += "+";
else if (this.getName().equalsIgnoreCase("Recruit")) ret += "-";
else ret += "=";
return ret;
}
// -------------------------------------------- // // -------------------------------------------- //
// CONSTRUCT // CONSTRUCT
@ -49,13 +40,28 @@ public class Rank extends EntityInternal<Rank> implements MPerm.MPermable
// For GSON // For GSON
private Rank() private Rank()
{ {
this(null,0); this(null,0, "");
} }
public Rank(String name, int priority) public Rank(String name, int priority, String prefix)
{ {
this.name = name; this.name = name;
this.priority = priority; this.priority = priority;
this.prefix = prefix;
}
// -------------------------------------------- //
// VISUAL
// -------------------------------------------- //
public String getVisual()
{
String ret = "";
ret += ChatColor.GREEN.toString();
ret += this.getPrefix();
ret += this.getName();
ret += " (" + this.getPriority() + ")";
return ret;
} }
// -------------------------------------------- // // -------------------------------------------- //
@ -129,27 +135,4 @@ public class Rank extends EntityInternal<Rank> implements MPerm.MPermable
return ret; return ret;
} }
// -------------------------------------------- //
// PERM
// -------------------------------------------- //
/*public boolean addPerm(MPerm mperm)
{
var ret = this.getPermIds().add(mperm.getId());
if (ret) this.changed();
return ret;
}
public boolean removePerm(MPerm mperm)
{
var ret = this.getPermIds().remove(mperm.getId());
if (ret) this.changed();
return ret;
}
public boolean hasPerm(MPerm mperm)
{
return this.getPermIds().contains(mperm.getId());
}*/
} }

View File

@ -41,10 +41,10 @@ public class MigratorFaction002Ranks extends MigratorRoot
String idMember = MStore.createId(); String idMember = MStore.createId();
String idRecruit = MStore.createId(); String idRecruit = MStore.createId();
Rank leader = new Rank("Leader", 400); Rank leader = new Rank("Leader", 400, "**");
Rank officer = new Rank("Officer", 300); Rank officer = new Rank("Officer", 300, "*");
Rank member = new Rank("Member", 200); Rank member = new Rank("Member", 200, "+");
Rank recruit = new Rank("Recruit", 100); Rank recruit = new Rank("Recruit", 100, "-");
Map<String, Rank> map = new MassiveMap<>(); Map<String, Rank> map = new MassiveMap<>();
map.put(idLeader, leader); map.put(idLeader, leader);