diff --git a/src/com/massivecraft/factions/cmd/CmdFactionsClean.java b/src/com/massivecraft/factions/cmd/CmdFactionsClean.java index 11211517..e06544ba 100644 --- a/src/com/massivecraft/factions/cmd/CmdFactionsClean.java +++ b/src/com/massivecraft/factions/cmd/CmdFactionsClean.java @@ -6,13 +6,14 @@ import com.massivecraft.factions.entity.Board; import com.massivecraft.factions.entity.BoardColl; import com.massivecraft.factions.entity.Faction; import com.massivecraft.factions.entity.FactionColl; +import com.massivecraft.factions.entity.Invitation; import com.massivecraft.factions.entity.MPlayer; import com.massivecraft.factions.entity.MPlayerColl; import com.massivecraft.massivecore.MassiveException; import com.massivecraft.massivecore.ps.PS; +import com.massivecraft.massivecore.store.EntityInternalMap; import com.massivecraft.massivecore.util.Txt; -import java.util.Collection; import java.util.Iterator; import java.util.Map.Entry; @@ -70,11 +71,11 @@ public class CmdFactionsClean extends FactionsCommand for (Faction faction : FactionColl.get().getAll()) { - Collection invitedPlayerIds = faction.getInvitedPlayerIds(); - if (invitedPlayerIds.isEmpty()) continue; + EntityInternalMap invitations = faction.getInvitations(); + if (invitations.isEmpty()) continue; - ret += invitedPlayerIds.size(); - invitedPlayerIds.clear(); + ret += invitations.size(); + invitations.clear(); faction.changed(); } diff --git a/src/com/massivecraft/factions/cmd/CmdFactionsInviteAdd.java b/src/com/massivecraft/factions/cmd/CmdFactionsInviteAdd.java index f9fb4582..0ef2be4b 100644 --- a/src/com/massivecraft/factions/cmd/CmdFactionsInviteAdd.java +++ b/src/com/massivecraft/factions/cmd/CmdFactionsInviteAdd.java @@ -1,12 +1,14 @@ package com.massivecraft.factions.cmd; import com.massivecraft.factions.cmd.type.TypeMPlayer; +import com.massivecraft.factions.entity.Invitation; import com.massivecraft.factions.entity.MPerm; import com.massivecraft.factions.entity.MPlayer; import com.massivecraft.factions.event.EventFactionsInvitedChange; import com.massivecraft.massivecore.MassiveException; import com.massivecraft.massivecore.command.type.container.TypeSet; import com.massivecraft.massivecore.mson.Mson; +import com.massivecraft.massivecore.util.IdUtil; import com.massivecraft.massivecore.util.Txt; import org.bukkit.ChatColor; @@ -34,6 +36,9 @@ public class CmdFactionsInviteAdd extends FactionsCommand // Args Collection mplayers = this.readArg(); + String senderId = IdUtil.getId(sender); + long creationMillis = System.currentTimeMillis(); + // MPerm if ( ! MPerm.getPermInvite().has(msender, msenderFaction, true)) return; @@ -62,7 +67,8 @@ public class CmdFactionsInviteAdd extends FactionsCommand msenderFaction.msg("%s invited %s to your faction.", msender.describeTo(msenderFaction, true), mplayer.describeTo(msenderFaction)); // Apply - msenderFaction.setInvited(mplayer, true); + Invitation invitation = new Invitation(senderId, creationMillis); + msenderFaction.invite(mplayer.getId(), invitation); msenderFaction.changed(); } else diff --git a/src/com/massivecraft/factions/cmd/CmdFactionsInviteList.java b/src/com/massivecraft/factions/cmd/CmdFactionsInviteList.java index 994a14cd..b59de368 100644 --- a/src/com/massivecraft/factions/cmd/CmdFactionsInviteList.java +++ b/src/com/massivecraft/factions/cmd/CmdFactionsInviteList.java @@ -1,18 +1,26 @@ package com.massivecraft.factions.cmd; import com.massivecraft.factions.Perm; -import com.massivecraft.factions.Rel; import com.massivecraft.factions.cmd.type.TypeFaction; import com.massivecraft.factions.entity.Faction; +import com.massivecraft.factions.entity.Invitation; import com.massivecraft.factions.entity.MPerm; -import com.massivecraft.factions.entity.MPlayer; import com.massivecraft.massivecore.MassiveException; +import com.massivecraft.massivecore.collections.MassiveList; import com.massivecraft.massivecore.command.Parameter; +import com.massivecraft.massivecore.comparator.ComparatorSmart; +import com.massivecraft.massivecore.mixin.MixinDisplayName; import com.massivecraft.massivecore.pager.Pager; import com.massivecraft.massivecore.pager.Stringifier; +import com.massivecraft.massivecore.util.TimeDiffUtil; +import com.massivecraft.massivecore.util.TimeUnit; import com.massivecraft.massivecore.util.Txt; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map.Entry; public class CmdFactionsInviteList extends FactionsCommand { @@ -45,25 +53,39 @@ public class CmdFactionsInviteList extends FactionsCommand if ( ! MPerm.getPermInvite().has(msender, msenderFaction, true)) return; // Pager Create - final List mplayers = faction.getInvitedMPlayers(); - final Pager pager = new Pager<>(this, "Invited Players List", page, mplayers, new Stringifier() + final List> invitations = new MassiveList<>(faction.getInvitations().entrySet()); + + Collections.sort(invitations, new Comparator>() { - public String toString(MPlayer target, int index) + @Override + public int compare(Entry i1, Entry i2) { - // TODO: Madus would like to implement this in MPlayer - String targetName = target.getDisplayName(msender); - String isAre = target == msender ? "are" : "is"; - Rel targetRank = target.getRole(); - Faction targetFaction = target.getFaction(); - String theAan = targetRank == Rel.LEADER ? "the" : Txt.aan(targetRank.name()); - String rankName = Txt.getNicedEnum(targetRank).toLowerCase(); - String ofIn = targetRank == Rel.LEADER ? "of" : "in"; - String factionName = targetFaction.describeTo(msender, true); - if (targetFaction == msenderFaction) + return ComparatorSmart.get().compare(i2.getValue().getCreationMillis(), i1.getValue().getCreationMillis()); + } + }); + + final long now = System.currentTimeMillis(); + + final Pager> pager = new Pager<>(this, "Invited Players List", page, invitations, new Stringifier>() + { + public String toString(Entry entry, int index) + { + String inviteeId = entry.getKey(); + String inviterId = entry.getValue().getInviterId(); + + String inviteeDisplayName = MixinDisplayName.get().getDisplayName(inviteeId, sender); + String inviterDisplayName = inviterId != null ? MixinDisplayName.get().getDisplayName(inviterId, sender) : Txt.parse("unknown"); + + String ageDesc = ""; + if (entry.getValue().getCreationMillis() != null) { - factionName = factionName.toLowerCase(); + long millis = now - entry.getValue().getCreationMillis(); + LinkedHashMap ageUnitcounts = TimeDiffUtil.limit(TimeDiffUtil.unitcounts(millis, TimeUnit.getAllButMillis()), 2); + ageDesc = TimeDiffUtil.formatedMinimal(ageUnitcounts, ""); + ageDesc = " " + ageDesc + Txt.parse(" ago"); } - return Txt.parse("%s %s %s %s %s %s.", targetName, isAre, theAan, rankName, ofIn, factionName); + + return Txt.parse("%s was invited by %s%s.", inviteeDisplayName, inviterDisplayName, ageDesc); } }); diff --git a/src/com/massivecraft/factions/cmd/CmdFactionsInviteRemove.java b/src/com/massivecraft/factions/cmd/CmdFactionsInviteRemove.java index dd82fa00..a71e6a4b 100644 --- a/src/com/massivecraft/factions/cmd/CmdFactionsInviteRemove.java +++ b/src/com/massivecraft/factions/cmd/CmdFactionsInviteRemove.java @@ -39,15 +39,18 @@ public class CmdFactionsInviteRemove extends FactionsCommand // Args if ("all".equalsIgnoreCase(this.argAt(0))) { - List invitedPlayers = msenderFaction.getInvitedMPlayers(); + Set ids = msenderFaction.getInvitations().keySet(); // Doesn't show up if list is empty. Test at home if it worked. - if (invitedPlayers == null || invitedPlayers.isEmpty()) + if (ids == null || ids.isEmpty()) { - msg("Your faction has not invited anyone."); - return; + throw new MassiveException().addMsg("No one is invited to your faction."); } all = true; - mplayers.addAll(invitedPlayers); + + for (String id : ids) + { + mplayers.add(MPlayer.get(id)); + } } else { @@ -98,7 +101,7 @@ public class CmdFactionsInviteRemove extends FactionsCommand } // Apply - msenderFaction.setInvited(mplayer, false); + msenderFaction.uninvite(msender); // If all, we do this at last. So we only do it once. if (! all) msenderFaction.changed(); diff --git a/src/com/massivecraft/factions/cmd/CmdFactionsJoin.java b/src/com/massivecraft/factions/cmd/CmdFactionsJoin.java index 6f8152ed..5c31a00d 100644 --- a/src/com/massivecraft/factions/cmd/CmdFactionsJoin.java +++ b/src/com/massivecraft/factions/cmd/CmdFactionsJoin.java @@ -117,7 +117,7 @@ public class CmdFactionsJoin extends FactionsCommand mplayer.resetFactionData(); mplayer.setFaction(faction); - faction.setInvited(mplayer, false); + faction.uninvite(mplayer); // Derplog if (MConf.get().logFactionJoin) diff --git a/src/com/massivecraft/factions/cmd/CmdFactionsKick.java b/src/com/massivecraft/factions/cmd/CmdFactionsKick.java index c1e22716..8fd55e2c 100644 --- a/src/com/massivecraft/factions/cmd/CmdFactionsKick.java +++ b/src/com/massivecraft/factions/cmd/CmdFactionsKick.java @@ -92,7 +92,7 @@ public class CmdFactionsKick extends FactionsCommand { mplayerFaction.promoteNewLeader(); } - mplayerFaction.setInvited(mplayer, false); + mplayerFaction.uninvite(mplayer); mplayer.resetFactionData(); } diff --git a/src/com/massivecraft/factions/cmd/CmdFactionsRank.java b/src/com/massivecraft/factions/cmd/CmdFactionsRank.java index b9e0098a..33fa267d 100644 --- a/src/com/massivecraft/factions/cmd/CmdFactionsRank.java +++ b/src/com/massivecraft/factions/cmd/CmdFactionsRank.java @@ -281,7 +281,7 @@ public class CmdFactionsRank extends FactionsCommand target.setFaction(endFaction); // No longer invited. - endFaction.setInvited(target, false); + endFaction.uninvite(target); // Create recipients Set recipients = new HashSet<>(); diff --git a/src/com/massivecraft/factions/entity/Faction.java b/src/com/massivecraft/factions/entity/Faction.java index 3868a110..17b0ed59 100644 --- a/src/com/massivecraft/factions/entity/Faction.java +++ b/src/com/massivecraft/factions/entity/Faction.java @@ -13,7 +13,6 @@ import com.massivecraft.massivecore.collections.MassiveList; import com.massivecraft.massivecore.collections.MassiveMap; import com.massivecraft.massivecore.collections.MassiveMapDef; import com.massivecraft.massivecore.collections.MassiveSet; -import com.massivecraft.massivecore.collections.MassiveSetDef; import com.massivecraft.massivecore.mixin.MixinMessage; import com.massivecraft.massivecore.money.Money; import com.massivecraft.massivecore.predicate.Predicate; @@ -21,6 +20,7 @@ import com.massivecraft.massivecore.predicate.PredicateAnd; import com.massivecraft.massivecore.predicate.PredicateVisibleTo; import com.massivecraft.massivecore.ps.PS; import com.massivecraft.massivecore.store.Entity; +import com.massivecraft.massivecore.store.EntityInternalMap; import com.massivecraft.massivecore.store.SenderColl; import com.massivecraft.massivecore.util.IdUtil; import com.massivecraft.massivecore.util.MUtil; @@ -70,7 +70,7 @@ public class Faction extends Entity implements FactionsParticipator this.setCreatedAtMillis(that.createdAtMillis); this.setHome(that.home); this.setPowerBoost(that.powerBoost); - this.setInvitedPlayerIds(that.invitedPlayerIds); + this.invitations.load(that.invitations); this.setRelationWishes(that.relationWishes); this.setFlagIds(that.flags); this.setPermIds(that.perms); @@ -92,6 +92,12 @@ public class Faction extends Entity implements FactionsParticipator } } + // -------------------------------------------- // + // VERSION + // -------------------------------------------- // + + public int version = 1; + // -------------------------------------------- // // FIELDS: RAW // -------------------------------------------- // @@ -136,7 +142,7 @@ public class Faction extends Entity implements FactionsParticipator // This is the ids of the invited players. // They are actually "senderIds" since you can invite "@console" to your faction. // Null means no one is invited - private MassiveSetDef invitedPlayerIds = new MassiveSetDef<>(); + private EntityInternalMap invitations = new EntityInternalMap<>(this, Invitation.class); // The keys in this map are factionIds. // Null means no special relation whishes. @@ -436,31 +442,14 @@ public class Faction extends Entity implements FactionsParticipator // RAW - public Set getInvitedPlayerIds() - { - return this.invitedPlayerIds; - } - public void setInvitedPlayerIds(Collection invitedPlayerIds) - { - // Clean input - MassiveSetDef target = new MassiveSetDef<>(invitedPlayerIds); - - // Detect Nochange - if (MUtil.equals(this.invitedPlayerIds, target)) return; - - // Apply - this.invitedPlayerIds = target; - - // Mark as changed - this.changed(); - } + public EntityInternalMap getInvitations() { return this.invitations; } // FINER public boolean isInvited(String playerId) { - return this.getInvitedPlayerIds().contains(playerId); + return this.getInvitations().containsKey(playerId); } public boolean isInvited(MPlayer mplayer) @@ -468,38 +457,20 @@ public class Faction extends Entity implements FactionsParticipator return this.isInvited(mplayer.getId()); } - public boolean setInvited(String playerId, boolean invited) + public boolean uninvite(String playerId) { - List invitedPlayerIds = new MassiveList<>(this.getInvitedPlayerIds()); - boolean ret; - if (invited) - { - ret = invitedPlayerIds.add(playerId); - } - else - { - ret = invitedPlayerIds.remove(playerId); - } - this.setInvitedPlayerIds(invitedPlayerIds); - return ret; + return this.getInvitations().remove(playerId) != null; } - public void setInvited(MPlayer mplayer, boolean invited) + public boolean uninvite(MPlayer mplayer) { - this.setInvited(mplayer.getId(), invited); + return uninvite(mplayer.getId()); } - public List getInvitedMPlayers() + public void invite(String playerId, Invitation invitation) { - List mplayers = new MassiveList<>(); - - for (String id : this.getInvitedPlayerIds()) - { - MPlayer mplayer = MPlayer.get(id); - mplayers.add(mplayer); - } - - return mplayers; + uninvite(playerId); + this.invitations.attach(invitation, playerId); } // -------------------------------------------- // diff --git a/src/com/massivecraft/factions/entity/Invitation.java b/src/com/massivecraft/factions/entity/Invitation.java new file mode 100644 index 00000000..1588214a --- /dev/null +++ b/src/com/massivecraft/factions/entity/Invitation.java @@ -0,0 +1,47 @@ +package com.massivecraft.factions.entity; + +import com.massivecraft.massivecore.store.EntityInternal; + +public class Invitation extends EntityInternal +{ + // -------------------------------------------- // + // OVERRIDE: ENTITY + // -------------------------------------------- // + + @Override + public Invitation load(Invitation that) + { + this.inviterId = that.inviterId; + this.creationMillis = that.creationMillis; + + return this; + } + + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // + + private String inviterId; + public String getInviterId() { return inviterId; } + public void setInviterId(String inviterId) { this.inviterId = inviterId; } + + private Long creationMillis; + public Long getCreationMillis() { return creationMillis; } + public void setCreationMillis(Long creationMillis) { this.creationMillis = creationMillis; } + + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public Invitation() + { + this(null, null); + } + + public Invitation(String inviterId, Long creationMillis) + { + this.inviterId = inviterId; + this.creationMillis = creationMillis; + } + +} diff --git a/src/com/massivecraft/factions/entity/MPlayer.java b/src/com/massivecraft/factions/entity/MPlayer.java index 3e10a404..94571614 100644 --- a/src/com/massivecraft/factions/entity/MPlayer.java +++ b/src/com/massivecraft/factions/entity/MPlayer.java @@ -70,7 +70,7 @@ public class MPlayer extends SenderEntity implements FactionsParticipat return this; } - + // -------------------------------------------- // // IS DEFAULT // -------------------------------------------- // diff --git a/src/com/massivecraft/factions/entity/migrator/MigratorFaction001Invitations.java b/src/com/massivecraft/factions/entity/migrator/MigratorFaction001Invitations.java new file mode 100644 index 00000000..7d7e0369 --- /dev/null +++ b/src/com/massivecraft/factions/entity/migrator/MigratorFaction001Invitations.java @@ -0,0 +1,69 @@ +package com.massivecraft.factions.entity.migrator; + +import com.massivecraft.factions.entity.Faction; +import com.massivecraft.massivecore.store.migrator.MigratorFieldConvert; +import com.massivecraft.massivecore.store.migrator.MigratorFieldRename; +import com.massivecraft.massivecore.store.migrator.MigratorRoot; +import com.massivecraft.massivecore.xlib.gson.JsonElement; +import com.massivecraft.massivecore.xlib.gson.JsonObject; + +public class MigratorFaction001Invitations extends MigratorRoot +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static com.massivecraft.factions.entity.migrator.MigratorFaction001Invitations i = new com.massivecraft.factions.entity.migrator.MigratorFaction001Invitations(); + public static com.massivecraft.factions.entity.migrator.MigratorFaction001Invitations get() { return i; } + private MigratorFaction001Invitations() + { + super(Faction.class); + this.addInnerMigrator(MigratorFieldRename.get("invitedPlayerIds", "invitations")); + this.addInnerMigrator(new MigratorFaction001InvitationsField()); + } + + public class MigratorFaction001InvitationsField extends MigratorFieldConvert + { + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + private MigratorFaction001InvitationsField() + { + super("invitations"); + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + public Object migrateInner(JsonElement idList) + { + JsonObject ret = new JsonObject(); + //EntityInternalMap ret = new EntityInternalMap<>(null, Invitation.class); + + // If non-null + if (!idList.isJsonNull()) + { + // ... and proper type ... + if (!idList.isJsonArray()) throw new IllegalArgumentException(idList.toString()); + + // ... fill! + for (JsonElement playerId : idList.getAsJsonArray()) + { + String id = playerId.getAsString(); + + // Create invitation + JsonObject invitation = new JsonObject(); + + // Attach + ret.add(id, invitation); + } + } + + return ret; + } + + } + +}