Factions Cleanup - Database lazy cleaning

This commit is contained in:
Olof Larsson 2017-03-25 00:47:01 +01:00
parent 4b1068385d
commit 2c58aed1ba
12 changed files with 246 additions and 223 deletions

View File

@ -95,10 +95,6 @@ public class Factions extends MassivePlugin
// FIELDS // FIELDS
// -------------------------------------------- // // -------------------------------------------- //
// Database Initialized
private boolean databaseInitialized;
public boolean isDatabaseInitialized() { return this.databaseInitialized; }
// Mixins // Mixins
@Deprecated public PowerMixin getPowerMixin() { return PowerMixin.get(); } @Deprecated public PowerMixin getPowerMixin() { return PowerMixin.get(); }
@Deprecated public void setPowerMixin(PowerMixin powerMixin) { PowerMixin.get().setInstance(powerMixin); } @Deprecated public void setPowerMixin(PowerMixin powerMixin) { PowerMixin.get().setInstance(powerMixin); }
@ -118,27 +114,27 @@ public class Factions extends MassivePlugin
// TODO: Perhaps this should be placed in the econ integration somewhere? // TODO: Perhaps this should be placed in the econ integration somewhere?
MUtil.registerExtractor(String.class, "accountId", ExtractorFactionAccountId.get()); MUtil.registerExtractor(String.class, "accountId", ExtractorFactionAccountId.get());
// Initialize Database
// MConf should always be activated first for all plugins. It's simply a standard. The config should have no dependencies.
// MFlag and MPerm are both dependency free.
// Next we activate Faction, MPlayer and Board. The order is carefully chosen based on foreign keys and indexing direction.
// MPlayer --> Faction
// We actually only have an index that we maintain for the MPlayer --> Faction one.
// The Board could currently be activated in any order but the current placement is an educated guess.
// In the future we might want to find all chunks from the faction or something similar.
// We also have the /f access system where the player can be granted specific access, possibly supporting the idea of such a reverse index.
this.databaseInitialized = false;
MigratorMConf001EnumerationUtil.get().setActive(true);
MConfColl.get().setActive(true);
MFlagColl.get().setActive(true);
MPermColl.get().setActive(true);
FactionColl.get().setActive(true);
MPlayerColl.get().setActive(true);
BoardColl.get().setActive(true);
this.databaseInitialized = true;
// Activate // Activate
this.activate( this.activate(
// Migrator
MigratorMConf001EnumerationUtil.class,
// Coll
// MConf should always be activated first for all plugins. It's simply a standard. The config should have no dependencies.
// MFlag and MPerm are both dependency free.
// Next we activate Faction, MPlayer and Board. The order is carefully chosen based on foreign keys and indexing direction.
// MPlayer --> Faction
// We actually only have an index that we maintain for the MPlayer --> Faction one.
// The Board could currently be activated in any order but the current placement is an educated guess.
// In the future we might want to find all chunks from the faction or something similar.
// We also have the /f access system where the player can be granted specific access, possibly supporting the idea of such a reverse index.
MConfColl.class,
MFlagColl.class,
MPermColl.class,
FactionColl.class,
MPlayerColl.class,
BoardColl.class,
// Command // Command
CmdFactions.class, CmdFactions.class,

View File

@ -3,13 +3,11 @@ package com.massivecraft.factions;
import com.massivecraft.factions.entity.Faction; import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.FactionColl; import com.massivecraft.factions.entity.FactionColl;
import com.massivecraft.factions.entity.MPlayer; import com.massivecraft.factions.entity.MPlayer;
import com.massivecraft.massivecore.collections.MassiveSet;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
import java.util.TreeSet;
public class TerritoryAccess public class TerritoryAccess
{ {
@ -17,18 +15,16 @@ public class TerritoryAccess
// FIELDS: RAW // FIELDS: RAW
// -------------------------------------------- // // -------------------------------------------- //
// TODO: Remake private final
// no default value, can't be null // no default value, can't be null
public String hostFactionId; private final String hostFactionId;
public String getHostFactionId() { return this.hostFactionId; } public String getHostFactionId() { return this.hostFactionId; }
// default is true // default is true
private final boolean hostFactionAllowed; private final boolean hostFactionAllowed;
public boolean isHostFactionAllowed() { return this.hostFactionAllowed; } public boolean isHostFactionAllowed() { return this.hostFactionAllowed; }
// TODO: Remake private final
// default is empty // default is empty
public Set<String> factionIds; private final Set<String> factionIds;
public Set<String> getFactionIds() { return this.factionIds; } public Set<String> getFactionIds() { return this.factionIds; }
// default is empty // default is empty
@ -53,7 +49,7 @@ public class TerritoryAccess
return valueOf(hostFactionId, with, factionIds, playerIds); return valueOf(hostFactionId, with, factionIds, playerIds);
} }
Set<String> factionIds = new HashSet<>(this.getFactionIds()); Set<String> factionIds = new MassiveSet<>(this.getFactionIds());
if (with) if (with)
{ {
factionIds.add(factionId); factionIds.add(factionId);
@ -68,7 +64,7 @@ public class TerritoryAccess
public TerritoryAccess withPlayerId(String playerId, boolean with) public TerritoryAccess withPlayerId(String playerId, boolean with)
{ {
playerId = playerId.toLowerCase(); playerId = playerId.toLowerCase();
Set<String> playerIds = new HashSet<>(this.getPlayerIds()); Set<String> playerIds = new MassiveSet<>(this.getPlayerIds());
if (with) if (with)
{ {
playerIds.add(playerId); playerIds.add(playerId);
@ -80,17 +76,6 @@ public class TerritoryAccess
return valueOf(hostFactionId, hostFactionAllowed, factionIds, playerIds); return valueOf(hostFactionId, hostFactionAllowed, factionIds, playerIds);
} }
// The complex ones
public TerritoryAccess toggleFactionId(String factionId)
{
return this.withFactionId(factionId, !this.isFactionIdGranted(factionId));
}
public TerritoryAccess togglePlayerId(String playerId)
{
return this.withPlayerId(playerId, !this.isPlayerIdGranted(playerId));
}
// -------------------------------------------- // // -------------------------------------------- //
// FIELDS: DIRECT // FIELDS: DIRECT
// -------------------------------------------- // // -------------------------------------------- //
@ -100,23 +85,33 @@ public class TerritoryAccess
return FactionColl.get().get(this.getHostFactionId()); return FactionColl.get().get(this.getHostFactionId());
} }
public LinkedHashSet<MPlayer> getGrantedMPlayers() public Set<MPlayer> getGrantedMPlayers()
{ {
LinkedHashSet<MPlayer> ret = new LinkedHashSet<>(); // Create
Set<MPlayer> ret = new MassiveSet<>();
// Fill
for (String playerId : this.getPlayerIds()) for (String playerId : this.getPlayerIds())
{ {
ret.add(MPlayer.get(playerId)); ret.add(MPlayer.get(playerId));
} }
// Return
return ret; return ret;
} }
public LinkedHashSet<Faction> getGrantedFactions() public Set<Faction> getGrantedFactions()
{ {
LinkedHashSet<Faction> ret = new LinkedHashSet<>(); // Create
Set<Faction> ret = new MassiveSet<>();
// Fill
for (String factionId : this.getFactionIds()) for (String factionId : this.getFactionIds())
{ {
ret.add(FactionColl.get().get(factionId)); ret.add(FactionColl.get().get(factionId));
} }
// Return
return ret; return ret;
} }
@ -129,7 +124,7 @@ public class TerritoryAccess
if (hostFactionId == null) throw new IllegalArgumentException("hostFactionId was null"); if (hostFactionId == null) throw new IllegalArgumentException("hostFactionId was null");
this.hostFactionId = hostFactionId; this.hostFactionId = hostFactionId;
Set<String> factionIdsInner = new TreeSet<>(); Set<String> factionIdsInner = new MassiveSet<>();
if (factionIds != null) if (factionIds != null)
{ {
factionIdsInner.addAll(factionIds); factionIdsInner.addAll(factionIds);
@ -140,7 +135,7 @@ public class TerritoryAccess
} }
this.factionIds = Collections.unmodifiableSet(factionIdsInner); this.factionIds = Collections.unmodifiableSet(factionIdsInner);
Set<String> playerIdsInner = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); Set<String> playerIdsInner = new MassiveSet<>();
if (playerIds != null) if (playerIds != null)
{ {
for (String playerId : playerIds) for (String playerId : playerIds)
@ -171,20 +166,24 @@ public class TerritoryAccess
// INSTANCE METHODS // INSTANCE METHODS
// -------------------------------------------- // // -------------------------------------------- //
public boolean isFactionIdGranted(String factionId) public boolean isFactionGranted(Faction faction)
{ {
String factionId = faction.getId();
if (this.getHostFactionId().equals(factionId)) if (this.getHostFactionId().equals(factionId))
{ {
return this.isHostFactionAllowed(); return this.isHostFactionAllowed();
} }
return this.getFactionIds().contains(factionId); return this.getFactionIds().contains(factionId);
} }
// Note that the player can have access without being specifically granted. // Note that the player can have access without being specifically granted.
// The player could for example be a member of a granted faction. // The player could for example be a member of a granted faction.
public boolean isPlayerIdGranted(String playerId) public boolean isMPlayerGranted(MPlayer mplayer)
{ {
return this.getPlayerIds().contains(playerId); String mplayerId = mplayer.getId();
return this.getPlayerIds().contains(mplayerId);
} }
// A "default" TerritoryAccess could be serialized as a simple string only. // A "default" TerritoryAccess could be serialized as a simple string only.
@ -203,7 +202,7 @@ public class TerritoryAccess
// null means standard access // null means standard access
public Boolean hasTerritoryAccess(MPlayer mplayer) public Boolean hasTerritoryAccess(MPlayer mplayer)
{ {
if (this.getPlayerIds().contains(mplayer.getId())) return true; if (this.isMPlayerGranted(mplayer)) return true;
String factionId = mplayer.getFaction().getId(); String factionId = mplayer.getFaction().getId();
if (this.getFactionIds().contains(factionId)) return true; if (this.getFactionIds().contains(factionId)) return true;

View File

@ -29,7 +29,7 @@ public class CmdFactionsAccessFaction extends CmdFactionsAccessAbstract
{ {
// Args // Args
Faction faction = this.readArg(); Faction faction = this.readArg();
boolean newValue = this.readArg(!ta.isFactionIdGranted(faction.getId())); boolean newValue = this.readArg(!ta.isFactionGranted(faction));
// MPerm // MPerm
if (!MPerm.getPermAccess().has(msender, hostFaction, true)) return; if (!MPerm.getPermAccess().has(msender, hostFaction, true)) return;

View File

@ -29,7 +29,7 @@ public class CmdFactionsAccessPlayer extends CmdFactionsAccessAbstract
{ {
// Args // Args
MPlayer mplayer = this.readArg(); MPlayer mplayer = this.readArg();
boolean newValue = this.readArg(!ta.isPlayerIdGranted(mplayer.getId())); boolean newValue = this.readArg(!ta.isMPlayerGranted(mplayer));
// MPerm // MPerm
if (!MPerm.getPermAccess().has(msender, hostFaction, true)) return; if (!MPerm.getPermAccess().has(msender, hostFaction, true)) return;

View File

@ -1,10 +1,21 @@
package com.massivecraft.factions.cmd; package com.massivecraft.factions.cmd;
import com.massivecraft.factions.Rel;
import com.massivecraft.factions.TerritoryAccess;
import com.massivecraft.factions.entity.Board;
import com.massivecraft.factions.entity.BoardColl; import com.massivecraft.factions.entity.BoardColl;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.FactionColl;
import com.massivecraft.factions.entity.MPlayer;
import com.massivecraft.factions.entity.MPlayerColl; import com.massivecraft.factions.entity.MPlayerColl;
import com.massivecraft.massivecore.MassiveException; import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.ps.PS;
import com.massivecraft.massivecore.util.Txt; import com.massivecraft.massivecore.util.Txt;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map.Entry;
public class CmdFactionsClean extends FactionsCommand public class CmdFactionsClean extends FactionsCommand
{ {
// -------------------------------------------- // // -------------------------------------------- //
@ -15,22 +26,133 @@ public class CmdFactionsClean extends FactionsCommand
public void perform() throws MassiveException public void perform() throws MassiveException
{ {
Object message; Object message;
int count;
// Apply
int chunks = BoardColl.get().clean();
int players = MPlayerColl.get().clean();
// Title // Title
message = Txt.titleize("Factions Cleaner Results"); message = Txt.titleize("Factions Cleaner Results");
message(message); message(message);
// Chunks // Yada
message = Txt.parse("<h>%d<i> chunks were cleaned.", chunks); cleanMessage(this.cleanPlayer(), "player");
message(message); cleanMessage(this.cleanFactionInvites(), "faction invites");
cleanMessage(this.cleanFactionRelationWhishes(), "faction relation whishes");
cleanMessage(this.cleanBoardHost(), "chunk whole");
cleanMessage(this.cleanBoardGrant(), "chunk access");
}
// Players // -------------------------------------------- //
message = Txt.parse("<h>%d<i> players were cleaned.", players); // CLEAN
message(message); // -------------------------------------------- //
private void cleanMessage(int count, String name)
{
msg("<v>%d<k> %s", count, name);
}
private int cleanPlayer()
{
int ret = 0;
for (MPlayer mplayer : MPlayerColl.get().getAll())
{
if (!mplayer.isFactionOrphan()) continue;
mplayer.resetFactionData();
ret += 1;
}
return ret;
}
private int cleanFactionInvites()
{
int ret = 0;
for (Faction faction : FactionColl.get().getAll())
{
Collection<String> invitedPlayerIds = faction.getInvitedPlayerIds();
if (invitedPlayerIds.isEmpty()) continue;
ret += invitedPlayerIds.size();
invitedPlayerIds.clear();
faction.changed();
}
return ret;
}
private int cleanFactionRelationWhishes()
{
int ret = 0;
for (Faction faction : FactionColl.get().getAll())
{
for (Iterator<Entry<String, Rel>> iterator = faction.getRelationWishes().entrySet().iterator(); iterator.hasNext();)
{
Entry<String, Rel> entry = iterator.next();
String factionId = entry.getKey();
if (FactionColl.get().containsId(factionId)) continue;
iterator.remove();
ret += 1;
faction.changed();
}
}
return ret;
}
private int cleanBoardHost()
{
int ret = 0;
for (Board board : BoardColl.get().getAll())
{
for (Entry<PS, TerritoryAccess> entry : board.getMap().entrySet())
{
PS ps = entry.getKey();
TerritoryAccess territoryAccess = entry.getValue();
String factionId = territoryAccess.getHostFactionId();
if (FactionColl.get().containsId(factionId)) continue;
board.removeAt(ps);
ret += 1;
}
}
return ret;
}
private int cleanBoardGrant()
{
int ret = 0;
for (Board board : BoardColl.get().getAll())
{
for (Entry<PS, TerritoryAccess> entry : board.getMap().entrySet())
{
PS ps = entry.getKey();
TerritoryAccess territoryAccess = entry.getValue();
boolean changed = false;
for (String factionId : territoryAccess.getFactionIds())
{
if (FactionColl.get().containsId(factionId)) continue;
territoryAccess = territoryAccess.withFactionId(factionId, false);
ret += 1;
changed = true;
}
if (changed)
{
board.setTerritoryAccessAt(ps, territoryAccess);
}
}
}
return ret;
} }
} }

View File

@ -157,32 +157,6 @@ public class Board extends Entity<Board> implements BoardInterface
} }
} }
// Removes orphaned foreign keys
@Override
public int clean()
{
int ret = 0;
if (!FactionColl.get().isActive()) return ret;
for (Entry<PS, TerritoryAccess> entry : this.map.entrySet())
{
TerritoryAccess territoryAccess = entry.getValue();
String factionId = territoryAccess.getHostFactionId();
if (FactionColl.get().containsId(factionId)) continue;
PS ps = entry.getKey();
this.removeAt(ps);
ret += 0;
Factions.get().log("Board cleaner removed "+factionId+" from "+ps);
}
return ret;
}
// CHUNKS // CHUNKS
@Override @Override

View File

@ -117,19 +117,6 @@ public class BoardColl extends Coll<Board> implements BoardInterface
} }
} }
@Override
public int clean()
{
int ret = 0;
for (Board board : this.getAll())
{
ret += board.clean();
}
return ret;
}
// CHUNKS // CHUNKS
@Override @Override

View File

@ -21,7 +21,6 @@ public interface BoardInterface
// REMOVE // REMOVE
void removeAt(PS ps); void removeAt(PS ps);
void removeAll(Faction faction); void removeAll(Faction faction);
int clean();
// CHUNKS // CHUNKS
Set<PS> getChunks(Faction faction); Set<PS> getChunks(Faction faction);

View File

@ -10,9 +10,10 @@ import com.massivecraft.factions.predicate.PredicateMPlayerRole;
import com.massivecraft.factions.util.MiscUtil; import com.massivecraft.factions.util.MiscUtil;
import com.massivecraft.factions.util.RelationUtil; import com.massivecraft.factions.util.RelationUtil;
import com.massivecraft.massivecore.collections.MassiveList; import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.collections.MassiveMap;
import com.massivecraft.massivecore.collections.MassiveMapDef; import com.massivecraft.massivecore.collections.MassiveMapDef;
import com.massivecraft.massivecore.collections.MassiveTreeSetDef; import com.massivecraft.massivecore.collections.MassiveSet;
import com.massivecraft.massivecore.comparator.ComparatorCaseInsensitive; import com.massivecraft.massivecore.collections.MassiveSetDef;
import com.massivecraft.massivecore.mixin.MixinMessage; import com.massivecraft.massivecore.mixin.MixinMessage;
import com.massivecraft.massivecore.money.Money; import com.massivecraft.massivecore.money.Money;
import com.massivecraft.massivecore.predicate.Predicate; import com.massivecraft.massivecore.predicate.Predicate;
@ -28,18 +29,14 @@ import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.TreeSet;
public class Faction extends Entity<Faction> implements FactionsParticipator public class Faction extends Entity<Faction> implements FactionsParticipator
{ {
@ -83,9 +80,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
@Override @Override
public void preDetach(String id) public void preDetach(String id)
{ {
// The database must be fully inited. if (!this.isLive()) return;
// We may move factions around during upgrades.
if (!Factions.get().isDatabaseInitialized()) return;
// NOTE: Existence check is required for compatibility with some plugins. // NOTE: Existence check is required for compatibility with some plugins.
// If they have money ... // If they have money ...
@ -94,12 +89,6 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
// ... remove it. // ... remove it.
Money.set(this, null, 0); Money.set(this, null, 0);
} }
// Clean the board
BoardColl.get().clean();
// Clean the mplayers
MPlayerColl.get().clean();
} }
// -------------------------------------------- // // -------------------------------------------- //
@ -146,7 +135,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
// This is the ids of the invited players. // This is the ids of the invited players.
// They are actually "senderIds" since you can invite "@console" to your faction. // They are actually "senderIds" since you can invite "@console" to your faction.
// Null means no one is invited // Null means no one is invited
private MassiveTreeSetDef<String, ComparatorCaseInsensitive> invitedPlayerIds = new MassiveTreeSetDef<>(ComparatorCaseInsensitive.get()); private MassiveSetDef<String> invitedPlayerIds = new MassiveSetDef<>();
// The keys in this map are factionIds. // The keys in this map are factionIds.
// Null means no special relation whishes. // Null means no special relation whishes.
@ -252,8 +241,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
if (target != null) if (target != null)
{ {
target = target.trim(); target = target.trim();
// This code should be kept for a while to clean out the previous default text that was actually stored in the database. if (target.isEmpty())
if (target.length() == 0 || target.equals("Default faction description :("))
{ {
target = null; target = null;
} }
@ -293,7 +281,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
if (target != null) if (target != null)
{ {
target = target.trim(); target = target.trim();
if (target.length() == 0) if (target.isEmpty())
{ {
target = null; target = null;
} }
@ -463,7 +451,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
// RAW // RAW
public TreeSet<String> getInvitedPlayerIds() public Set<String> getInvitedPlayerIds()
{ {
return this.invitedPlayerIds; return this.invitedPlayerIds;
} }
@ -471,14 +459,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
public void setInvitedPlayerIds(Collection<String> invitedPlayerIds) public void setInvitedPlayerIds(Collection<String> invitedPlayerIds)
{ {
// Clean input // Clean input
MassiveTreeSetDef<String, ComparatorCaseInsensitive> target = new MassiveTreeSetDef<>(ComparatorCaseInsensitive.get()); MassiveSetDef<String> target = new MassiveSetDef<>(invitedPlayerIds);
if (invitedPlayerIds != null)
{
for (String invitedPlayerId : invitedPlayerIds)
{
target.add(invitedPlayerId.toLowerCase());
}
}
// Detect Nochange // Detect Nochange
if (MUtil.equals(this.invitedPlayerIds, target)) return; if (MUtil.equals(this.invitedPlayerIds, target)) return;
@ -504,7 +485,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
public boolean setInvited(String playerId, boolean invited) public boolean setInvited(String playerId, boolean invited)
{ {
List<String> invitedPlayerIds = new ArrayList<>(this.getInvitedPlayerIds()); List<String> invitedPlayerIds = new MassiveList<>(this.getInvitedPlayerIds());
boolean ret; boolean ret;
if (invited) if (invited)
{ {
@ -516,7 +497,6 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
} }
this.setInvitedPlayerIds(invitedPlayerIds); this.setInvitedPlayerIds(invitedPlayerIds);
return ret; return ret;
} }
public void setInvited(MPlayer mplayer, boolean invited) public void setInvited(MPlayer mplayer, boolean invited)
@ -526,13 +506,14 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
public List<MPlayer> getInvitedMPlayers() public List<MPlayer> getInvitedMPlayers()
{ {
List<MPlayer> mplayers = new ArrayList<>(); List<MPlayer> mplayers = new MassiveList<>();
for (String id : this.getInvitedPlayerIds()) for (String id : this.getInvitedPlayerIds())
{ {
MPlayer mplayer = MPlayer.get(id); MPlayer mplayer = MPlayer.get(id);
mplayers.add(mplayer); mplayers.add(mplayer);
} }
return mplayers; return mplayers;
} }
@ -604,7 +585,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
public Map<MFlag, Boolean> getFlags() public Map<MFlag, Boolean> getFlags()
{ {
// We start with default values ... // We start with default values ...
Map<MFlag, Boolean> ret = new LinkedHashMap<>(); Map<MFlag, Boolean> ret = new MassiveMap<>();
for (MFlag mflag : MFlag.getAll()) for (MFlag mflag : MFlag.getAll())
{ {
ret.put(mflag, mflag.isStandard()); ret.put(mflag, mflag.isStandard());
@ -638,7 +619,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
public void setFlags(Map<MFlag, Boolean> flags) public void setFlags(Map<MFlag, Boolean> flags)
{ {
Map<String, Boolean> flagIds = new LinkedHashMap<>(); Map<String, Boolean> flagIds = new MassiveMap<>();
for (Entry<MFlag, Boolean> entry : flags.entrySet()) for (Entry<MFlag, Boolean> entry : flags.entrySet())
{ {
flagIds.put(entry.getKey().getId(), entry.getValue()); flagIds.put(entry.getKey().getId(), entry.getValue());
@ -730,10 +711,10 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
public Map<MPerm, Set<Rel>> getPerms() public Map<MPerm, Set<Rel>> getPerms()
{ {
// We start with default values ... // We start with default values ...
Map<MPerm, Set<Rel>> ret = new LinkedHashMap<>(); Map<MPerm, Set<Rel>> ret = new MassiveMap<>();
for (MPerm mperm : MPerm.getAll()) for (MPerm mperm : MPerm.getAll())
{ {
ret.put(mperm, new LinkedHashSet<>(mperm.getStandard())); ret.put(mperm, new MassiveSet<>(mperm.getStandard()));
} }
// ... and if anything is explicitly set we use that info ... // ... and if anything is explicitly set we use that info ...
@ -755,7 +736,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
MPerm mperm = MPerm.get(id); MPerm mperm = MPerm.get(id);
if (mperm == null) continue; if (mperm == null) continue;
ret.put(mperm, new LinkedHashSet<>(entry.getValue())); ret.put(mperm, new MassiveSet<>(entry.getValue()));
} }
return ret; return ret;
@ -763,7 +744,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
public void setPerms(Map<MPerm, Set<Rel>> perms) public void setPerms(Map<MPerm, Set<Rel>> perms)
{ {
Map<String, Set<Rel>> permIds = new LinkedHashMap<>(); Map<String, Set<Rel>> permIds = new MassiveMap<>();
for (Entry<MPerm, Set<Rel>> entry : perms.entrySet()) for (Entry<MPerm, Set<Rel>> entry : perms.entrySet())
{ {
permIds.put(entry.getKey().getId(), entry.getValue()); permIds.put(entry.getKey().getId(), entry.getValue());
@ -1054,7 +1035,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
public List<CommandSender> getOnlineCommandSenders() public List<CommandSender> getOnlineCommandSenders()
{ {
// Create Ret // Create Ret
List<CommandSender> ret = new ArrayList<>(); List<CommandSender> ret = new MassiveList<>();
// Fill Ret // Fill Ret
for (CommandSender sender : IdUtil.getLocalSenders()) for (CommandSender sender : IdUtil.getLocalSenders())
@ -1074,7 +1055,7 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
public List<Player> getOnlinePlayers() public List<Player> getOnlinePlayers()
{ {
// Create Ret // Create Ret
List<Player> ret = new ArrayList<>(); List<Player> ret = new MassiveList<>();
// Fill Ret // Fill Ret
for (Player player : MUtil.getOnlinePlayers()) for (Player player : MUtil.getOnlinePlayers())

View File

@ -47,26 +47,6 @@ public class FactionColl extends Coll<Faction>
this.createSpecialFactions(); this.createSpecialFactions();
} }
@Override
public Faction get(Object oid)
{
Faction ret = super.get(oid);
// We should only trigger automatic clean if the whole database system is initialized.
// A cleaning can only be successful if all data is available.
// Example Reason: When creating the special factions for the first time "createSpecialFactions" a clean would be triggered otherwise.
if (ret == null && Factions.get().isDatabaseInitialized())
{
String message = Txt.parse("<b>Non existing factionId <h>%s <b>requested. <i>Cleaning all boards and mplayers.", this.fixId(oid));
Factions.get().log(message);
BoardColl.get().clean();
MPlayerColl.get().clean();
}
return ret;
}
// -------------------------------------------- // // -------------------------------------------- //
// SPECIAL FACTIONS // SPECIAL FACTIONS
// -------------------------------------------- // // -------------------------------------------- //

View File

@ -27,6 +27,7 @@ import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.lang.ref.WeakReference;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -166,13 +167,20 @@ public class MPlayer extends SenderEntity<MPlayer> implements FactionsParticipat
// Null means default specified in MConf. // Null means default specified in MConf.
private Boolean territoryInfoTitles = null; private Boolean territoryInfoTitles = null;
// The id for the faction this player is currently autoclaiming for. // The Faction this player is currently autoclaiming for.
// Null means the player isn't auto claiming. // Null means the player isn't auto claiming.
// NOTE: This field will not be saved to the database ever. // NOTE: This field will not be saved to the database ever.
private transient Faction autoClaimFaction = null; private transient WeakReference<Faction> autoClaimFaction = new WeakReference<>(null);
public Faction getAutoClaimFaction() { return this.autoClaimFaction; } public Faction getAutoClaimFaction()
public void setAutoClaimFaction(Faction autoClaimFaction) { this.autoClaimFaction = autoClaimFaction; } {
if (this.isFactionOrphan()) return null;
Faction ret = this.autoClaimFaction.get();
if (ret == null) return null;
if (ret.detached()) return null;
return ret;
}
public void setAutoClaimFaction(Faction autoClaimFaction) { this.autoClaimFaction = new WeakReference<>(autoClaimFaction); }
// Does the player have /f seechunk activated? // Does the player have /f seechunk activated?
// NOTE: This field will not be saved to the database ever. // NOTE: This field will not be saved to the database ever.
@ -226,30 +234,42 @@ public class MPlayer extends SenderEntity<MPlayer> implements FactionsParticipat
// FIELD: factionId // FIELD: factionId
// -------------------------------------------- // // -------------------------------------------- //
@Deprecated private Faction getFactionInternal()
public String getDefaultFactionId()
{ {
return MConf.get().defaultPlayerFactionId; String effectiveFactionId = this.convertGet(this.factionId, MConf.get().defaultPlayerFactionId);
return Faction.get(effectiveFactionId);
} }
// This method never returns null public boolean isFactionOrphan()
{
return this.getFactionInternal() == null;
}
@Deprecated
public String getFactionId() public String getFactionId()
{ {
if (this.factionId == null) return MConf.get().defaultPlayerFactionId; return this.getFaction().getId();
return this.factionId;
} }
// This method never returns null // This method never returns null
public Faction getFaction() public Faction getFaction()
{ {
Faction ret = Faction.get(this.getFactionId()); Faction ret;
if (ret == null) ret = Faction.get(MConf.get().defaultPlayerFactionId);
ret = this.getFactionInternal();
// Adopt orphans
if (ret == null)
{
ret = FactionColl.get().getNone();
}
return ret; return ret;
} }
public boolean hasFaction() public boolean hasFaction()
{ {
return !this.getFactionId().equals(Factions.ID_NONE); return !this.getFaction().isNone();
} }
// This setter is so long because it search for default/null case and takes // This setter is so long because it search for default/null case and takes
@ -284,14 +304,10 @@ public class MPlayer extends SenderEntity<MPlayer> implements FactionsParticipat
// FIELD: role // FIELD: role
// -------------------------------------------- // // -------------------------------------------- //
@Deprecated
public Rel getDefaultRole()
{
return MConf.get().defaultPlayerRole;
}
public Rel getRole() public Rel getRole()
{ {
if (this.isFactionOrphan()) return Rel.RECRUIT;
if (this.role == null) return MConf.get().defaultPlayerRole; if (this.role == null) return MConf.get().defaultPlayerRole;
return this.role; return this.role;
} }
@ -314,15 +330,20 @@ public class MPlayer extends SenderEntity<MPlayer> implements FactionsParticipat
// -------------------------------------------- // // -------------------------------------------- //
// FIELD: title // FIELD: title
// -------------------------------------------- // // -------------------------------------------- //
// TODO: Improve upon the has and get stuff.
// TODO: Has should depend on get. Visualisation should be done elsewhere.
public boolean hasTitle() public boolean hasTitle()
{ {
return this.title != null; return !this.isFactionOrphan() && this.title != null;
} }
public String getTitle() public String getTitle()
{ {
if (this.isFactionOrphan()) return NOTITLE;
if (this.hasTitle()) return this.title; if (this.hasTitle()) return this.title;
return NOTITLE; return NOTITLE;
} }
@ -339,15 +360,6 @@ public class MPlayer extends SenderEntity<MPlayer> implements FactionsParticipat
} }
} }
// NOTE: That we parse the title here is considered part of the 1.8 -->
// 2.0 migration.
// This should be removed once the migration phase is considered to be
// over.
if (target != null)
{
target = Txt.parse(target);
}
// Detect Nochange // Detect Nochange
if (MUtil.equals(this.title, target)) return; if (MUtil.equals(this.title, target)) return;

View File

@ -2,8 +2,6 @@ package com.massivecraft.factions.entity;
import com.massivecraft.factions.Factions; import com.massivecraft.factions.Factions;
import com.massivecraft.massivecore.store.SenderColl; import com.massivecraft.massivecore.store.SenderColl;
import com.massivecraft.massivecore.util.IdUtil;
import com.massivecraft.massivecore.util.Txt;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import java.util.Collection; import java.util.Collection;
@ -31,31 +29,6 @@ public class MPlayerColl extends SenderColl<MPlayer>
// EXTRAS // EXTRAS
// -------------------------------------------- // // -------------------------------------------- //
public int clean()
{
int ret = 0;
if (!FactionColl.get().isActive()) return ret;
// For each player ...
for (MPlayer mplayer : this.getAll())
{
// ... who doesn't have a valid faction ...
String factionId = mplayer.getFactionId();
if (FactionColl.get().containsId(factionId)) continue;
// ... reset their faction data ...
mplayer.resetFactionData();
ret += 1;
// ... and log.
String message = Txt.parse("<i>Reset data for <h>%s <i>. Unknown factionId <h>%s", mplayer.getDisplayName(IdUtil.getConsole()), factionId);
Factions.get().log(message);
}
return ret;
}
public void considerRemovePlayerMillis() public void considerRemovePlayerMillis()
{ {
// If the config option is 0 or below that means the server owner want it disabled. // If the config option is 0 or below that means the server owner want it disabled.