Use new inactivity cleanup system

This commit is contained in:
Magnus Ulf Jørgensen 2017-05-19 08:47:42 +02:00
parent 9ed9ad4f82
commit b681ee01a4
9 changed files with 150 additions and 266 deletions

View File

@ -3,9 +3,9 @@ package com.massivecraft.factions.cmd;
import com.massivecraft.factions.cmd.type.TypeMPlayer; import com.massivecraft.factions.cmd.type.TypeMPlayer;
import com.massivecraft.factions.entity.MConf; import com.massivecraft.factions.entity.MConf;
import com.massivecraft.factions.entity.MPlayer; import com.massivecraft.factions.entity.MPlayer;
import com.massivecraft.factions.event.EventFactionsRemovePlayerMillis;
import com.massivecraft.massivecore.MassiveException; import com.massivecraft.massivecore.MassiveException;
import com.massivecraft.massivecore.Progressbar; import com.massivecraft.massivecore.Progressbar;
import com.massivecraft.massivecore.event.EventMassiveCorePlayercleanToleranceMillis;
import com.massivecraft.massivecore.util.TimeDiffUtil; import com.massivecraft.massivecore.util.TimeDiffUtil;
import com.massivecraft.massivecore.util.TimeUnit; import com.massivecraft.massivecore.util.TimeUnit;
import com.massivecraft.massivecore.util.Txt; import com.massivecraft.massivecore.util.Txt;
@ -80,12 +80,12 @@ public class CmdFactionsPlayer extends FactionsCommand
msg("<a>Power per Death: <v>%.2f", mplayer.getPowerPerDeath()); msg("<a>Power per Death: <v>%.2f", mplayer.getPowerPerDeath());
// Display automatic kick / remove info if the system is in use // Display automatic kick / remove info if the system is in use
if (MConf.get().removePlayerMillisDefault <= 0) return; if (MConf.get().playercleanToleranceMillis <= 0) return;
EventFactionsRemovePlayerMillis event = new EventFactionsRemovePlayerMillis(false, mplayer); EventMassiveCorePlayercleanToleranceMillis event = new EventMassiveCorePlayercleanToleranceMillis(mplayer);
event.run(); event.run();
msg("<i>Automatic removal after %s <i>of inactivity:", format(event.getMillis())); msg("<i>Automatic removal after %s <i>of inactivity:", format(event.getToleranceMillis()));
for (Entry<String, Long> causeMillis : event.getCauseMillis().entrySet()) for (Entry<String, Long> causeMillis : event.getToleranceCauseMillis().entrySet())
{ {
String cause = causeMillis.getKey(); String cause = causeMillis.getKey();
long millis = causeMillis.getValue(); long millis = causeMillis.getValue();

View File

@ -0,0 +1,97 @@
package com.massivecraft.factions.engine;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.MConf;
import com.massivecraft.factions.entity.MPlayer;
import com.massivecraft.factions.entity.MPlayerColl;
import com.massivecraft.massivecore.Engine;
import com.massivecraft.massivecore.event.EventMassiveCorePlayercleanToleranceMillis;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import java.util.Map;
import java.util.Map.Entry;
public class EnginePlayerclean extends Engine
{
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static EnginePlayerclean i = new EnginePlayerclean();
public static EnginePlayerclean get() { return i; }
// -------------------------------------------- //
// REMOVE PLAYER MILLIS
// -------------------------------------------- //
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void ageBonus(EventMassiveCorePlayercleanToleranceMillis event)
{
if (event.getColl() != MPlayerColl.get()) return;
applyPlayerAgeBonus(event);
applyFactionAgeBonus(event);
}
public void applyPlayerAgeBonus(EventMassiveCorePlayercleanToleranceMillis event)
{
// Calculate First Played
Long firstPlayed = event.getEntity().getFirstPlayed();
Long age = 0L;
if (firstPlayed != null)
{
age = System.currentTimeMillis() - firstPlayed;
}
// Calculate the Bonus!
Long bonus = calculateBonus(age, MConf.get().playercleanToleranceMillisPlayerAgeToBonus);
if (bonus == null) return;
// Apply
event.getToleranceCauseMillis().put("Player Age Bonus", bonus);
}
public void applyFactionAgeBonus(EventMassiveCorePlayercleanToleranceMillis event)
{
// Calculate Faction Age
Faction faction = ((MPlayer)event.getEntity()).getFaction();
long age = 0L;
if ( ! faction.isNone())
{
age = faction.getAge();
}
// Calculate the Bonus!
Long bonus = calculateBonus(age, MConf.get().playercleanToleranceMillisFactionAgeToBonus);
if (bonus == null) return;
// Apply
event.getToleranceCauseMillis().put("Faction Age Bonus", bonus);
}
private Long calculateBonus(long age, Map<Long, Long> ageToBonus)
{
if (ageToBonus.isEmpty()) return null;
Long bonus = 0L;
for (Entry<Long, Long> entry : ageToBonus.entrySet())
{
Long key = entry.getKey();
if (key == null) continue;
Long value = entry.getValue();
if (value == null) continue;
if (age >= key)
{
bonus = value;
break;
}
}
return bonus;
}
}

View File

@ -351,6 +351,16 @@ public class Faction extends Entity<Faction> implements FactionsParticipator
this.changed(); this.changed();
} }
public long getAge()
{
return this.getAge(System.currentTimeMillis());
}
public long getAge(long now)
{
return now - this.getCreatedAtMillis();
}
// -------------------------------------------- // // -------------------------------------------- //
// FIELD: home // FIELD: home
// -------------------------------------------- // // -------------------------------------------- //

View File

@ -60,7 +60,7 @@ public class MConf extends Entity<MConf>
// VERSION // VERSION
// -------------------------------------------- // // -------------------------------------------- //
public int version = 1; public int version = 2;
// -------------------------------------------- // // -------------------------------------------- //
// COMMAND ALIASES // COMMAND ALIASES
@ -111,17 +111,17 @@ public class MConf extends Entity<MConf>
// The Default // The Default
@EditorType(TypeMillisDiff.class) @EditorType(TypeMillisDiff.class)
public long removePlayerMillisDefault = 10 * TimeUnit.MILLIS_PER_DAY; // 10 days public long playercleanToleranceMillis = 10 * TimeUnit.MILLIS_PER_DAY; // 10 days
// Player Age Bonus // Player Age Bonus
@EditorTypeInner({TypeMillisDiff.class, TypeMillisDiff.class}) @EditorTypeInner({TypeMillisDiff.class, TypeMillisDiff.class})
public Map<Long, Long> removePlayerMillisPlayerAgeToBonus = MUtil.map( public Map<Long, Long> playercleanToleranceMillisPlayerAgeToBonus = MUtil.map(
2 * TimeUnit.MILLIS_PER_WEEK, 10 * TimeUnit.MILLIS_PER_DAY // +10 days after 2 weeks 2 * TimeUnit.MILLIS_PER_WEEK, 10 * TimeUnit.MILLIS_PER_DAY // +10 days after 2 weeks
); );
// Faction Age Bonus // Faction Age Bonus
@EditorTypeInner({TypeMillisDiff.class, TypeMillisDiff.class}) @EditorTypeInner({TypeMillisDiff.class, TypeMillisDiff.class})
public Map<Long, Long> removePlayerMillisFactionAgeToBonus = MUtil.map( public Map<Long, Long> playercleanToleranceMillisFactionAgeToBonus = MUtil.map(
4 * TimeUnit.MILLIS_PER_WEEK, 10 * TimeUnit.MILLIS_PER_DAY, // +10 days after 4 weeks 4 * TimeUnit.MILLIS_PER_WEEK, 10 * TimeUnit.MILLIS_PER_DAY, // +10 days after 4 weeks
2 * TimeUnit.MILLIS_PER_WEEK, 5 * TimeUnit.MILLIS_PER_DAY // +5 days after 2 weeks 2 * TimeUnit.MILLIS_PER_WEEK, 5 * TimeUnit.MILLIS_PER_DAY // +5 days after 2 weeks
); );

View File

@ -11,7 +11,6 @@ import com.massivecraft.factions.event.EventFactionsChunksChange;
import com.massivecraft.factions.event.EventFactionsDisband; import com.massivecraft.factions.event.EventFactionsDisband;
import com.massivecraft.factions.event.EventFactionsMembershipChange; import com.massivecraft.factions.event.EventFactionsMembershipChange;
import com.massivecraft.factions.event.EventFactionsMembershipChange.MembershipChangeReason; import com.massivecraft.factions.event.EventFactionsMembershipChange.MembershipChangeReason;
import com.massivecraft.factions.event.EventFactionsRemovePlayerMillis;
import com.massivecraft.factions.mixin.PowerMixin; import com.massivecraft.factions.mixin.PowerMixin;
import com.massivecraft.factions.util.RelationUtil; import com.massivecraft.factions.util.RelationUtil;
import com.massivecraft.massivecore.mixin.MixinSenderPs; import com.massivecraft.massivecore.mixin.MixinSenderPs;
@ -19,6 +18,7 @@ import com.massivecraft.massivecore.mixin.MixinTitle;
import com.massivecraft.massivecore.ps.PS; import com.massivecraft.massivecore.ps.PS;
import com.massivecraft.massivecore.ps.PSFormatHumanSpace; import com.massivecraft.massivecore.ps.PSFormatHumanSpace;
import com.massivecraft.massivecore.store.SenderEntity; import com.massivecraft.massivecore.store.SenderEntity;
import com.massivecraft.massivecore.store.inactive.Inactive;
import com.massivecraft.massivecore.util.IdUtil; import com.massivecraft.massivecore.util.IdUtil;
import com.massivecraft.massivecore.util.MUtil; import com.massivecraft.massivecore.util.MUtil;
import com.massivecraft.massivecore.util.Txt; import com.massivecraft.massivecore.util.Txt;
@ -34,7 +34,7 @@ import java.util.Iterator;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
public class MPlayer extends SenderEntity<MPlayer> implements FactionsParticipator public class MPlayer extends SenderEntity<MPlayer> implements FactionsParticipator, Inactive
{ {
// -------------------------------------------- // // -------------------------------------------- //
// META // META
@ -702,56 +702,6 @@ public class MPlayer extends SenderEntity<MPlayer> implements FactionsParticipat
return BoardColl.get().getFactionAt(ps).getRelationTo(this) == Rel.ENEMY; return BoardColl.get().getFactionAt(ps).getRelationTo(this) == Rel.ENEMY;
} }
// -------------------------------------------- //
// INACTIVITY TIMEOUT
// -------------------------------------------- //
public long getRemovePlayerMillis(boolean async)
{
EventFactionsRemovePlayerMillis event = new EventFactionsRemovePlayerMillis(async, this);
event.run();
return event.getMillis();
}
public boolean considerRemovePlayerMillis(boolean async)
{
// This may or may not be required.
// Some users have been reporting a loop issue with the same player
// detaching over and over again.
// Maybe skipping ahead if the player is detached will solve the issue.
if (this.detached()) return false;
// Get the last activity millis.
long lastActivityMillis = this.getLastActivityMillis();
// Consider
long toleranceMillis = this.getRemovePlayerMillis(async);
if (System.currentTimeMillis() - lastActivityMillis <= toleranceMillis) return false;
// Inform
if (MConf.get().logFactionLeave || MConf.get().logFactionKick)
{
Factions.get().log("Player " + this.getName() + " was auto-removed due to inactivity.");
}
// Apply
// Promote a new leader if required.
if (this.getRole() == Rel.LEADER)
{
Faction faction = this.getFaction();
if (faction != null)
{
this.getFaction().promoteNewLeader();
}
}
this.leave();
this.detach();
return true;
}
// -------------------------------------------- // // -------------------------------------------- //
// ACTIONS // ACTIONS
// -------------------------------------------- // // -------------------------------------------- //

View File

@ -1,10 +1,6 @@
package com.massivecraft.factions.entity; package com.massivecraft.factions.entity;
import com.massivecraft.factions.Factions;
import com.massivecraft.massivecore.store.SenderColl; import com.massivecraft.massivecore.store.SenderColl;
import org.bukkit.Bukkit;
import java.util.Collection;
public class MPlayerColl extends SenderColl<MPlayer> public class MPlayerColl extends SenderColl<MPlayer>
{ {
@ -14,6 +10,10 @@ public class MPlayerColl extends SenderColl<MPlayer>
private static MPlayerColl i = new MPlayerColl(); private static MPlayerColl i = new MPlayerColl();
public static MPlayerColl get() { return i; } public static MPlayerColl get() { return i; }
public MPlayerColl()
{
this.setPlayercleanTaskEnabled(true);
}
// -------------------------------------------- // // -------------------------------------------- //
// STACK TRACEABILITY // STACK TRACEABILITY
@ -29,29 +29,10 @@ public class MPlayerColl extends SenderColl<MPlayer>
// EXTRAS // EXTRAS
// -------------------------------------------- // // -------------------------------------------- //
public void considerRemovePlayerMillis() @Override
public long getPlayercleanToleranceMillis()
{ {
// If the config option is 0 or below that means the server owner want it disabled. return MConf.get().playercleanToleranceMillis;
if (MConf.get().removePlayerMillisDefault <= 0.0) return;
// For each of the offline players...
// NOTE: If the player is currently online it's most definitely not inactive.
// NOTE: This check catches some important special cases like the @console "player".
final Collection<MPlayer> mplayersOffline = this.getAllOffline();
Bukkit.getScheduler().runTaskAsynchronously(Factions.get(), new Runnable()
{
@Override
public void run()
{
// For each offline player ...
for (MPlayer mplayer : mplayersOffline)
{
// ... see if they should be removed.
mplayer.considerRemovePlayerMillis(true);
}
}
});
} }
} }

View File

@ -0,0 +1,23 @@
package com.massivecraft.factions.entity.migrator;
import com.massivecraft.factions.entity.MConf;
import com.massivecraft.massivecore.store.migrator.MigratorFieldRename;
import com.massivecraft.massivecore.store.migrator.MigratorRoot;
public class MigratorMConf002Playerclean extends MigratorRoot
{
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static MigratorMConf002Playerclean i = new MigratorMConf002Playerclean();
public static MigratorMConf002Playerclean get() { return i; }
private MigratorMConf002Playerclean()
{
super(MConf.class);
this.addInnerMigrator(MigratorFieldRename.get("removePlayerMillisDefault", "playercleanToleranceMillis"));
this.addInnerMigrator(MigratorFieldRename.get("removePlayerMillisPlayerAgeToBonus", "playercleanToleranceMillisPlayerAgeToBonus"));
this.addInnerMigrator(MigratorFieldRename.get("removePlayerMillisFactionAgeToBonus", "playercleanToleranceMillisFactionAgeToBonus"));
}
}

View File

@ -1,138 +0,0 @@
package com.massivecraft.factions.event;
import com.massivecraft.factions.entity.Faction;
import com.massivecraft.factions.entity.MConf;
import com.massivecraft.factions.entity.MPlayer;
import com.massivecraft.massivecore.event.EventMassiveCore;
import org.bukkit.event.HandlerList;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
public class EventFactionsRemovePlayerMillis extends EventMassiveCore
{
// -------------------------------------------- //
// REQUIRED EVENT CODE
// -------------------------------------------- //
private static final HandlerList handlers = new HandlerList();
@Override public HandlerList getHandlers() { return handlers; }
public static HandlerList getHandlerList() { return handlers; }
// -------------------------------------------- //
// FIELD
// -------------------------------------------- //
private final MPlayer mplayer;
public MPlayer getMPlayer() { return this.mplayer; }
private long millis;
public long getMillis() { return this.millis; }
public void setMillis(long millis) { this.millis = millis; }
private Map<String, Long> causeMillis = new LinkedHashMap<>();
public Map<String, Long> getCauseMillis() { return this.causeMillis; }
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public EventFactionsRemovePlayerMillis(boolean async, MPlayer mplayer)
{
super(async);
this.mplayer = mplayer;
this.millis = MConf.get().removePlayerMillisDefault;
// Default
this.causeMillis.put("Default", MConf.get().removePlayerMillisDefault);
// Player Age Bonus
this.applyPlayerAgeBonus();
// Faction Age Bonus
this.applyFactionAgeBonus();
}
// -------------------------------------------- //
// UTIL
// -------------------------------------------- //
public void applyPlayerAgeBonus()
{
// Skip if this bonus is totally disabled.
// We don't want it showing up with 0 for everyone.
if (MConf.get().removePlayerMillisPlayerAgeToBonus.isEmpty()) return;
// Calculate First Played
Long firstPlayed = this.getMPlayer().getFirstPlayed();
Long age = 0L;
if (firstPlayed != null)
{
age = System.currentTimeMillis() - firstPlayed;
}
// Calculate the Bonus!
long bonus = 0;
for (Entry<Long, Long> entry : MConf.get().removePlayerMillisPlayerAgeToBonus.entrySet())
{
Long key = entry.getKey();
if (key == null) continue;
Long value = entry.getValue();
if (value == null) continue;
if (age >= key)
{
bonus = value;
break;
}
}
// Apply
this.setMillis(this.getMillis() + bonus);
// Inform
this.getCauseMillis().put("Player Age Bonus", bonus);
}
public void applyFactionAgeBonus()
{
// Skip if this bonus is totally disabled.
// We don't want it showing up with 0 for everyone.
if (MConf.get().removePlayerMillisFactionAgeToBonus.isEmpty()) return;
// Calculate Faction Age
Faction faction = this.getMPlayer().getFaction();
long age = 0;
if ( ! faction.isNone())
{
age = System.currentTimeMillis() - faction.getCreatedAtMillis();
}
// Calculate the Bonus!
long bonus = 0;
for (Entry<Long, Long> entry : MConf.get().removePlayerMillisFactionAgeToBonus.entrySet())
{
Long key = entry.getKey();
if (key == null) continue;
Long value = entry.getValue();
if (value == null) continue;
if (age >= key)
{
bonus = value;
break;
}
}
// Apply
this.setMillis(this.getMillis() + bonus);
// Inform
this.getCauseMillis().put("Faction Age Bonus", bonus);
}
}

View File

@ -1,39 +0,0 @@
package com.massivecraft.factions.task;
import com.massivecraft.factions.entity.MConf;
import com.massivecraft.factions.entity.MPlayerColl;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.ModuloRepeatTask;
import com.massivecraft.massivecore.util.TimeUnit;
public class TaskPlayerDataRemove extends ModuloRepeatTask
{
// -------------------------------------------- //
// INSTANCE
// -------------------------------------------- //
private static TaskPlayerDataRemove i = new TaskPlayerDataRemove();
public static TaskPlayerDataRemove get() { return i; }
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public long getDelayMillis()
{
// The interval is determined by the MConf rather than being set with setDelayMillis.
return (long) (MConf.get().taskPlayerDataRemoveMinutes * TimeUnit.MILLIS_PER_MINUTE);
}
@Override
public void invoke(long now)
{
// If this is the task server ...
if (!MassiveCore.isTaskServer()) return;
// ... check players for expiration.
MPlayerColl.get().considerRemovePlayerMillis();
}
}