MassiveCore - Fixes and tweaks

This commit is contained in:
Olof Larsson 2015-11-24 16:23:07 +01:00
parent 7e313ab085
commit 14ad78ef15
17 changed files with 614 additions and 367 deletions

View File

@ -27,7 +27,6 @@ import com.massivecraft.massivecore.adapter.MsonAdapter;
import com.massivecraft.massivecore.adapter.MsonEventAdapter; import com.massivecraft.massivecore.adapter.MsonEventAdapter;
import com.massivecraft.massivecore.adapter.PlayerInventoryAdapter; import com.massivecraft.massivecore.adapter.PlayerInventoryAdapter;
import com.massivecraft.massivecore.adapter.UUIDAdapter; import com.massivecraft.massivecore.adapter.UUIDAdapter;
import com.massivecraft.massivecore.chestgui.EngineChestGui;
import com.massivecraft.massivecore.collections.BackstringEnumSet; import com.massivecraft.massivecore.collections.BackstringEnumSet;
import com.massivecraft.massivecore.collections.MassiveList; import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.collections.MassiveListDef; import com.massivecraft.massivecore.collections.MassiveListDef;
@ -44,21 +43,27 @@ import com.massivecraft.massivecore.command.massivecore.CmdMassiveCoreBuffer;
import com.massivecraft.massivecore.command.massivecore.CmdMassiveCoreCmdurl; import com.massivecraft.massivecore.command.massivecore.CmdMassiveCoreCmdurl;
import com.massivecraft.massivecore.command.massivecore.CmdMassiveCoreStore; import com.massivecraft.massivecore.command.massivecore.CmdMassiveCoreStore;
import com.massivecraft.massivecore.command.massivecore.CmdMassiveCoreUsys; import com.massivecraft.massivecore.command.massivecore.CmdMassiveCoreUsys;
import com.massivecraft.massivecore.engine.EngineMassiveCoreGank;
import com.massivecraft.massivecore.engine.EngineMassiveCoreChestGui;
import com.massivecraft.massivecore.engine.EngineMassiveCoreCollTick;
import com.massivecraft.massivecore.engine.EngineMassiveCoreCommandRegistration; import com.massivecraft.massivecore.engine.EngineMassiveCoreCommandRegistration;
import com.massivecraft.massivecore.engine.EngineMassiveCoreDatabase;
import com.massivecraft.massivecore.engine.EngineMassiveCoreDestination; import com.massivecraft.massivecore.engine.EngineMassiveCoreDestination;
import com.massivecraft.massivecore.engine.EngineMassiveCoreMain; import com.massivecraft.massivecore.engine.EngineMassiveCoreMain;
import com.massivecraft.massivecore.engine.EngineMassiveCorePlayerLeave;
import com.massivecraft.massivecore.engine.EngineMassiveCorePlayerState;
import com.massivecraft.massivecore.engine.EngineMassiveCorePlayerUpdate; import com.massivecraft.massivecore.engine.EngineMassiveCorePlayerUpdate;
import com.massivecraft.massivecore.engine.EngineMassiveCoreScheduledTeleport;
import com.massivecraft.massivecore.engine.EngineMassiveCoreTeleportMixinCause;
import com.massivecraft.massivecore.engine.EngineMassiveCoreVariable; import com.massivecraft.massivecore.engine.EngineMassiveCoreVariable;
import com.massivecraft.massivecore.engine.EngineMassiveCoreWorldNameSet; import com.massivecraft.massivecore.engine.EngineMassiveCoreWorldNameSet;
import com.massivecraft.massivecore.integration.vault.IntegrationVault; import com.massivecraft.massivecore.integration.vault.IntegrationVault;
import com.massivecraft.massivecore.mixin.EngineTeleportMixinCause;
import com.massivecraft.massivecore.mson.Mson; import com.massivecraft.massivecore.mson.Mson;
import com.massivecraft.massivecore.mson.MsonEvent; import com.massivecraft.massivecore.mson.MsonEvent;
import com.massivecraft.massivecore.ps.PS; import com.massivecraft.massivecore.ps.PS;
import com.massivecraft.massivecore.ps.PSAdapter; import com.massivecraft.massivecore.ps.PSAdapter;
import com.massivecraft.massivecore.store.ModificationPollerLocal; import com.massivecraft.massivecore.store.ModificationPollerLocal;
import com.massivecraft.massivecore.store.ModificationPollerRemote; import com.massivecraft.massivecore.store.ModificationPollerRemote;
import com.massivecraft.massivecore.teleport.EngineScheduledTeleport;
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.PlayerUtil; import com.massivecraft.massivecore.util.PlayerUtil;
@ -189,18 +194,22 @@ public class MassiveCore extends MassivePlugin
IdUtil.setup(); IdUtil.setup();
// Engine // Engine
EngineCollTick.get().activate(); EngineMassiveCoreChestGui.get().activate();
EngineMassiveCoreMain.get().activate(); EngineMassiveCoreCollTick.get().activate();
EngineMassiveCoreVariable.get().activate();
EngineScheduledTeleport.get().activate();
EngineTeleportMixinCause.get().activate();
EngineMassiveCoreWorldNameSet.get().activate();
EngineMassiveCoreCommandRegistration.get().activate(); EngineMassiveCoreCommandRegistration.get().activate();
EngineMassiveCoreDatabase.get().activate();
EngineMassiveCoreDestination.get().activate(); EngineMassiveCoreDestination.get().activate();
EngineMassiveCoreGank.get().activate();
EngineMassiveCoreMain.get().activate();
EngineMassiveCorePlayerLeave.get().activate();
EngineMassiveCorePlayerState.get().activate();
EngineMassiveCorePlayerUpdate.get().activate(); EngineMassiveCorePlayerUpdate.get().activate();
EngineMassiveCoreScheduledTeleport.get().activate();
EngineMassiveCoreTeleportMixinCause.get().activate();
EngineMassiveCoreVariable.get().activate();
EngineMassiveCoreWorldNameSet.get().activate();
PlayerUtil.get().activate(); PlayerUtil.get().activate();
EngineChestGui.get().activate();
EngineGank.get().activate();
// Collections // Collections
MultiverseColl.get().init(); MultiverseColl.get().init();

View File

@ -0,0 +1,51 @@
package com.massivecraft.massivecore;
import java.util.UUID;
import org.bukkit.entity.Player;
import com.massivecraft.massivecore.engine.EngineMassiveCorePlayerState;
/**
* This enumeration is used to keep track of where a player currently is within the login --> join --> play --> leave cycle.
* Bukkit does not provide this information so we forge it as well as we can by listening to LOWEST on a few different events.
*
* When is this information useful?
* For example you may want to handle events differently depending on whether the player actually is online yet.
* Say you want to store last teleport position by logging it on the player teleport event.
* During the login and join phase the server teleports the player around to get the player in position.
* So for such a "last tp position" system you may want to ignore any teleports other than during player state JOINED.
*
* EngineMassiveCorePlayerState takes care of updating the information.
*/
public enum PlayerState
{
// -------------------------------------------- //
// ENUM
// -------------------------------------------- //
LOGASYNC, // During AsyncPlayerLoginEvent
LOGSYNC, // During PlayerLoginEvent
JOINING, // During PlayerJoinEvent
JOINED, // Regular situation. The player is online and playing.
LEAVING, // From the start of EventMassiveCorePlayerLeave till the player actually disconnects.
LEFT, // The player is fully disconnected and offline.
// END OF LIST
;
// -------------------------------------------- //
// STATIC
// -------------------------------------------- //
public static PlayerState get(UUID id)
{
return EngineMassiveCorePlayerState.get().getState(id);
}
public static PlayerState get(Player player)
{
return EngineMassiveCorePlayerState.get().getState(player);
}
}

View File

@ -1,4 +1,4 @@
package com.massivecraft.massivecore.chestgui; package com.massivecraft.massivecore.engine;
import org.bukkit.event.Event.Result; import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -10,17 +10,19 @@ import org.bukkit.plugin.Plugin;
import com.massivecraft.massivecore.EngineAbstract; import com.massivecraft.massivecore.EngineAbstract;
import com.massivecraft.massivecore.MassiveCore; import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.chestgui.ChestAction;
import com.massivecraft.massivecore.chestgui.ChestGui;
import com.massivecraft.massivecore.mixin.Mixin; import com.massivecraft.massivecore.mixin.Mixin;
import com.massivecraft.massivecore.util.InventoryUtil; import com.massivecraft.massivecore.util.InventoryUtil;
public class EngineChestGui extends EngineAbstract public class EngineMassiveCoreChestGui extends EngineAbstract
{ {
// -------------------------------------------- // // -------------------------------------------- //
// INSTANCE & CONSTRUCT // INSTANCE & CONSTRUCT
// -------------------------------------------- // // -------------------------------------------- //
private static EngineChestGui i = new EngineChestGui(); private static EngineMassiveCoreChestGui i = new EngineMassiveCoreChestGui();
public static EngineChestGui get() { return i; } public static EngineMassiveCoreChestGui get() { return i; }
// -------------------------------------------- // // -------------------------------------------- //
// OVERRIDE // OVERRIDE

View File

@ -1,17 +1,19 @@
package com.massivecraft.massivecore; package com.massivecraft.massivecore.engine;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import com.massivecraft.massivecore.EngineAbstract;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.store.Coll; import com.massivecraft.massivecore.store.Coll;
public class EngineCollTick extends EngineAbstract public class EngineMassiveCoreCollTick extends EngineAbstract
{ {
// -------------------------------------------- // // -------------------------------------------- //
// INSTANCE & CONSTRUCT // INSTANCE & CONSTRUCT
// -------------------------------------------- // // -------------------------------------------- //
protected static EngineCollTick i = new EngineCollTick(); protected static EngineMassiveCoreCollTick i = new EngineMassiveCoreCollTick();
public static EngineCollTick get() { return i; } public static EngineMassiveCoreCollTick get() { return i; }
// -------------------------------------------- // // -------------------------------------------- //
// OVERRIDE: ENGINE // OVERRIDE: ENGINE

View File

@ -0,0 +1,260 @@
package com.massivecraft.massivecore.engine;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
import com.massivecraft.massivecore.EngineAbstract;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.collections.MassiveMap;
import com.massivecraft.massivecore.event.EventMassiveCorePlayerLeave;
import com.massivecraft.massivecore.event.EventMassiveCoreSenderRegister;
import com.massivecraft.massivecore.event.EventMassiveCoreSenderUnregister;
import com.massivecraft.massivecore.store.Coll;
import com.massivecraft.massivecore.store.SenderColl;
import com.massivecraft.massivecore.util.IdUtil;
import com.massivecraft.massivecore.util.MUtil;
import com.massivecraft.massivecore.xlib.gson.JsonObject;
public class EngineMassiveCoreDatabase extends EngineAbstract
{
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static EngineMassiveCoreDatabase i = new EngineMassiveCoreDatabase();
public static EngineMassiveCoreDatabase get() { return i; }
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public Plugin getPlugin()
{
return MassiveCore.get();
}
@Override
public void activate()
{
super.activate();
}
// -------------------------------------------- //
// PLAYER AND SENDER REFERENCES
// -------------------------------------------- //
public static Map<String, PlayerLoginEvent> idToPlayerLoginEvent = new MassiveMap<String, PlayerLoginEvent>();
// This method sets the sender reference to what you decide.
public static void setSenderReferences(CommandSender sender, CommandSender reference, PlayerLoginEvent event)
{
if (MUtil.isntSender(sender)) return;
String id = IdUtil.getId(sender);
if (id != null)
{
SenderColl.setSenderReferences(id, reference);
if (event == null)
{
idToPlayerLoginEvent.remove(id);
}
else
{
idToPlayerLoginEvent.put(id, event);
}
}
}
// This method sets the sender reference based on it's online state.
public static void setSenderReferences(Player player, PlayerLoginEvent event)
{
Player reference = player;
if ( ! player.isOnline()) reference = null;
setSenderReferences(player, reference, event);
}
// Same as above but next tick.
public static void setSenderReferencesSoon(final Player player, final PlayerLoginEvent event)
{
Bukkit.getScheduler().scheduleSyncDelayedTask(MassiveCore.get(), new Runnable()
{
@Override
public void run()
{
setSenderReferences(player, event);
}
});
}
@EventHandler(priority = EventPriority.LOWEST)
public void setSenderReferencesLoginLowest(PlayerLoginEvent event)
{
final Player player = event.getPlayer();
// We set the reference at LOWEST so that it's present during this PlayerLoginEvent event.
setSenderReferences(player, player, event);
// And the next tick we update the reference based on it's online state.
// Not all players succeed in logging in. They may for example be banned.
setSenderReferencesSoon(player, null);
}
@EventHandler(priority = EventPriority.MONITOR)
public void setSenderReferencesQuitMonitor(PlayerQuitEvent event)
{
// PlayerQuitEvents are /probably/ trustworthy.
// We check ourselves the next tick just to be on the safe side.
setSenderReferencesSoon(event.getPlayer(), null);
}
@EventHandler(priority = EventPriority.MONITOR)
public void setSenderReferencesRegisterMonitor(EventMassiveCoreSenderRegister event)
{
// This one we can however trust.
setSenderReferences(event.getSender(), event.getSender(), null);
}
@EventHandler(priority = EventPriority.MONITOR)
public void setSenderReferencesUnregisterMonitor(EventMassiveCoreSenderUnregister event)
{
// This one we can however trust.
setSenderReferences(event.getSender(), null, null);
}
// -------------------------------------------- //
// SYNC: LOGIN
// -------------------------------------------- //
// This section handles the automatic sync of a players corresponding massive store entries on login.
// If possible the database IO is made during the AsyncPlayerPreLoginEvent to offloat the main server thread.
protected Map<String, Map<SenderColl<?>, Entry<JsonObject, Long>>> idToRemoteEntries = new ConcurrentHashMap<>();
// Intended to be ran asynchronously.
public void storeRemoteEntries(final String playerId)
{
// Create remote entries ...
Map<SenderColl<?>, Entry<JsonObject, Long>> remoteEntries = createRemoteEntries(playerId);
// ... store them ...
this.idToRemoteEntries.put(playerId, remoteEntries);
// ... and make sure they are removed after 30 seconds.
// Without this we might cause a memory leak.
// Players might trigger AsyncPlayerPreLoginEvent but not PlayerLoginEvent.
// Using WeakHashMap is not an option since the player object does not exist at AsyncPlayerPreLoginEvent.
Bukkit.getScheduler().runTaskLaterAsynchronously(this.getPlugin(), new Runnable()
{
@Override
public void run()
{
idToRemoteEntries.remove(playerId);
}
}, 20*30);
}
// Intended to be ran synchronously.
// It will use remoteEntries from AsyncPlayerPreLoginEvent if possible.
// If no such remoteEntries are available it will create them and thus lock the main server thread a bit.
public Map<SenderColl<?>, Entry<JsonObject, Long>> getRemoteEntries(String playerId)
{
// If there are stored remote entries we used those ...
Map<SenderColl<?>, Entry<JsonObject, Long>> ret = idToRemoteEntries.remove(playerId);
if (ret != null) return ret;
// ... otherwise we create brand new ones.
return createRemoteEntries(playerId);
}
// Used by the two methods above.
public Map<SenderColl<?>, Entry<JsonObject, Long>> createRemoteEntries(String playerId)
{
// Create Ret
Map<SenderColl<?>, Entry<JsonObject, Long>> ret = new HashMap<SenderColl<?>, Entry<JsonObject, Long>>();
// Fill Ret
for (final SenderColl<?> coll : Coll.getSenderInstances())
{
Entry<JsonObject, Long> remoteEntry = coll.getDb().load(coll, playerId);
ret.put(coll, remoteEntry);
}
// Return Ret
return ret;
}
@EventHandler(priority = EventPriority.MONITOR)
public void massiveStoreLoginSync(AsyncPlayerPreLoginEvent event)
{
// DEBUG
// long before = System.nanoTime();
// If the login was allowed ...
if (event.getLoginResult() != Result.ALLOWED) return;
// ... get player id ...
final String playerId = event.getUniqueId().toString();
// ... and store the remote entries.
this.storeRemoteEntries(playerId);
// DEBUG
// long after = System.nanoTime();
// long duration = after - before;
// double ms = (double)duration / 1000000D;
// String message = Txt.parse("<i>AsyncPlayerPreLoginEvent for %s <i>took <h>%.2f <i>ms.", event.getName(), ms);
// MassiveCore.get().log(message);
// NOTE: I get values between 5 and 55 ms!
}
// Can not be cancelled.
@EventHandler(priority = EventPriority.LOWEST)
public void massiveStoreLoginSync(PlayerLoginEvent event)
{
// Get player id ...
Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
final String playerId = player.getUniqueId().toString();
// ... get remote entries ...
Map<SenderColl<?>, Entry<JsonObject, Long>> remoteEntries = getRemoteEntries(playerId);
// ... and sync each of them.
for (Entry<SenderColl<?>, Entry<JsonObject, Long>> entry : remoteEntries.entrySet())
{
SenderColl<?> coll = entry.getKey();
Entry<JsonObject, Long> remoteEntry = entry.getValue();
coll.syncId(playerId, null, remoteEntry);
}
}
// -------------------------------------------- //
// SYNC: LEAVE
// -------------------------------------------- //
@EventHandler(priority = EventPriority.MONITOR)
public void syncOnPlayerLeave(EventMassiveCorePlayerLeave event)
{
final Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
final String id = player.getUniqueId().toString();
for (SenderColl<?> coll : Coll.getSenderInstances())
{
coll.syncId(id);
}
}
}

View File

@ -1,4 +1,4 @@
package com.massivecraft.massivecore; package com.massivecraft.massivecore.engine;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -17,15 +17,15 @@ import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.collections.MassiveMap; import com.massivecraft.massivecore.collections.MassiveMap;
import com.massivecraft.massivecore.util.MUtil; import com.massivecraft.massivecore.util.MUtil;
public class EngineGank extends EngineAbstract public class EngineMassiveCoreGank extends EngineAbstract
{ {
// -------------------------------------------- // // -------------------------------------------- //
// INSTANCE & CONSTRUCT // INSTANCE & CONSTRUCT
// -------------------------------------------- // // -------------------------------------------- //
private static EngineGank i = new EngineGank(); private static EngineMassiveCoreGank i = new EngineMassiveCoreGank();
public static EngineGank get() { return i; } public static EngineMassiveCoreGank get() { return i; }
public EngineGank() {} public EngineMassiveCoreGank() {}
// -------------------------------------------- // // -------------------------------------------- //
// OVERRIDE // OVERRIDE

View File

@ -3,25 +3,18 @@ package com.massivecraft.massivecore.engine;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageByBlockEvent; import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
import org.bukkit.event.player.PlayerChatTabCompleteEvent; import org.bukkit.event.player.PlayerChatTabCompleteEvent;
import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
@ -34,21 +27,14 @@ import com.massivecraft.massivecore.Predicate;
import com.massivecraft.massivecore.PredicateStartsWithIgnoreCase; import com.massivecraft.massivecore.PredicateStartsWithIgnoreCase;
import com.massivecraft.massivecore.SenderPresence; import com.massivecraft.massivecore.SenderPresence;
import com.massivecraft.massivecore.SenderType; import com.massivecraft.massivecore.SenderType;
import com.massivecraft.massivecore.collections.MassiveMap;
import com.massivecraft.massivecore.event.EventMassiveCoreAfterPlayerRespawn; import com.massivecraft.massivecore.event.EventMassiveCoreAfterPlayerRespawn;
import com.massivecraft.massivecore.event.EventMassiveCoreAfterPlayerTeleport; import com.massivecraft.massivecore.event.EventMassiveCoreAfterPlayerTeleport;
import com.massivecraft.massivecore.event.EventMassiveCorePermissionDeniedFormat; import com.massivecraft.massivecore.event.EventMassiveCorePermissionDeniedFormat;
import com.massivecraft.massivecore.event.EventMassiveCorePlayerLeave;
import com.massivecraft.massivecore.event.EventMassiveCorePlayerToRecipientChat; import com.massivecraft.massivecore.event.EventMassiveCorePlayerToRecipientChat;
import com.massivecraft.massivecore.event.EventMassiveCoreSenderRegister;
import com.massivecraft.massivecore.event.EventMassiveCoreSenderUnregister;
import com.massivecraft.massivecore.mixin.Mixin; import com.massivecraft.massivecore.mixin.Mixin;
import com.massivecraft.massivecore.store.Coll;
import com.massivecraft.massivecore.store.SenderColl;
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.SmokeUtil; import com.massivecraft.massivecore.util.SmokeUtil;
import com.massivecraft.massivecore.xlib.gson.JsonObject;
public class EngineMassiveCoreMain extends EngineAbstract public class EngineMassiveCoreMain extends EngineAbstract
{ {
@ -73,7 +59,6 @@ public class EngineMassiveCoreMain extends EngineAbstract
public void activate() public void activate()
{ {
super.activate(); super.activate();
EventMassiveCorePlayerLeave.player2event.clear();
} }
// -------------------------------------------- // // -------------------------------------------- //
@ -186,96 +171,6 @@ public class EngineMassiveCoreMain extends EngineAbstract
event.setCancelled(true); event.setCancelled(true);
} }
// -------------------------------------------- //
// PLAYER AND SENDER REFERENCES
// -------------------------------------------- //
// Note: For now we update both names and ids.
// That way collections in plugins that haven't yet undergone update will still work.
public static Map<String, PlayerLoginEvent> idToPlayerLoginEvent = new MassiveMap<String, PlayerLoginEvent>();
// This method sets the sender reference to what you decide.
public static void setSenderReferences(CommandSender sender, CommandSender reference, PlayerLoginEvent event)
{
if (MUtil.isntSender(sender)) return;
String id = IdUtil.getId(sender);
if (id != null)
{
SenderColl.setSenderReferences(id, reference);
if (event == null)
{
idToPlayerLoginEvent.remove(id);
}
else
{
idToPlayerLoginEvent.put(id, event);
}
}
String name = IdUtil.getName(sender);
if (name != null)
{
SenderColl.setSenderReferences(name, reference);
}
}
// This method sets the sender reference based on it's online state.
public static void setSenderReferences(Player player, PlayerLoginEvent event)
{
Player reference = player;
if ( ! player.isOnline()) reference = null;
setSenderReferences(player, reference, event);
}
// Same as above but next tick.
public static void setSenderReferencesSoon(final Player player, final PlayerLoginEvent event)
{
Bukkit.getScheduler().scheduleSyncDelayedTask(MassiveCore.get(), new Runnable()
{
@Override
public void run()
{
setSenderReferences(player, event);
}
});
}
@EventHandler(priority = EventPriority.LOWEST)
public void setSenderReferencesLoginLowest(PlayerLoginEvent event)
{
final Player player = event.getPlayer();
// We set the reference at LOWEST so that it's present during this PlayerLoginEvent event.
setSenderReferences(player, player, event);
// And the next tick we update the reference based on it's online state.
// Not all players succeed in logging in. They may for example be banned.
setSenderReferencesSoon(player, null);
}
@EventHandler(priority = EventPriority.MONITOR)
public void setSenderReferencesQuitMonitor(PlayerQuitEvent event)
{
// PlayerQuitEvents are /probably/ trustworthy.
// We check ourselves the next tick just to be on the safe side.
setSenderReferencesSoon(event.getPlayer(), null);
}
@EventHandler(priority = EventPriority.MONITOR)
public void setSenderReferencesRegisterMonitor(EventMassiveCoreSenderRegister event)
{
// This one we can however trust.
setSenderReferences(event.getSender(), event.getSender(), null);
}
@EventHandler(priority = EventPriority.MONITOR)
public void setSenderReferencesUnregisterMonitor(EventMassiveCoreSenderUnregister event)
{
// This one we can however trust.
setSenderReferences(event.getSender(), null, null);
}
// -------------------------------------------- // // -------------------------------------------- //
// AFTER EVENTS // AFTER EVENTS
// -------------------------------------------- // // -------------------------------------------- //
@ -332,173 +227,4 @@ public class EngineMassiveCoreMain extends EngineAbstract
}); });
} }
// -------------------------------------------- //
// PLAYER LEAVE EVENT
// -------------------------------------------- //
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void leaveEventKickCall(PlayerKickEvent event)
{
Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
new EventMassiveCorePlayerLeave(player, true, "kick", event.getReason()).run();
}
@EventHandler(priority = EventPriority.MONITOR)
public void leaveEventQuitCall(PlayerQuitEvent event)
{
Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
new EventMassiveCorePlayerLeave(player, false, "quit", null).run();
}
@EventHandler(priority = EventPriority.MONITOR)
public void leaveEventQuitClear(PlayerQuitEvent event)
{
Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
final UUID uuid = player.getUniqueId();
// We do the schedule in order for the set to be correct through out the whole MONITOR priority state.
Bukkit.getScheduler().scheduleSyncDelayedTask(MassiveCore.get(), new Runnable()
{
@Override
public void run()
{
EventMassiveCorePlayerLeave.player2event.remove(uuid);
}
});
}
// -------------------------------------------- //
// MASSIVE STORE: LOGIN SYNC
// -------------------------------------------- //
// This section handles the automatic sync of a players corresponding massive store entries on login.
// If possible the database IO is made during the AsyncPlayerPreLoginEvent to offloat the main server thread.
protected Map<String, Map<SenderColl<?>, Entry<JsonObject, Long>>> idToRemoteEntries = new ConcurrentHashMap<>();
// Intended to be ran asynchronously.
public void storeRemoteEntries(final String playerId)
{
// Create remote entries ...
Map<SenderColl<?>, Entry<JsonObject, Long>> remoteEntries = createRemoteEntries(playerId);
// ... store them ...
this.idToRemoteEntries.put(playerId, remoteEntries);
// ... and make sure they are removed after 30 seconds.
// Without this we might cause a memory leak.
// Players might trigger AsyncPlayerPreLoginEvent but not PlayerLoginEvent.
// Using WeakHashMap is not an option since the player object does not exist at AsyncPlayerPreLoginEvent.
Bukkit.getScheduler().runTaskLaterAsynchronously(this.getPlugin(), new Runnable()
{
@Override
public void run()
{
idToRemoteEntries.remove(playerId);
}
}, 20*30);
}
// Intended to be ran synchronously.
// It will use remoteEntries from AsyncPlayerPreLoginEvent if possible.
// If no such remoteEntries are available it will create them and thus lock the main server thread a bit.
public Map<SenderColl<?>, Entry<JsonObject, Long>> getRemoteEntries(String playerId)
{
// If there are stored remote entries we used those ...
Map<SenderColl<?>, Entry<JsonObject, Long>> ret = idToRemoteEntries.remove(playerId);
if (ret != null) return ret;
// ... otherwise we create brand new ones.
return createRemoteEntries(playerId);
}
// Used by the two methods above.
public Map<SenderColl<?>, Entry<JsonObject, Long>> createRemoteEntries(String playerId)
{
// Create Ret
Map<SenderColl<?>, Entry<JsonObject, Long>> ret = new HashMap<SenderColl<?>, Entry<JsonObject, Long>>();
// Fill Ret
for (final SenderColl<?> coll : Coll.getSenderInstances())
{
Entry<JsonObject, Long> remoteEntry = coll.getDb().load(coll, playerId);
ret.put(coll, remoteEntry);
}
// Return Ret
return ret;
}
@EventHandler(priority = EventPriority.MONITOR)
public void massiveStoreLoginSync(AsyncPlayerPreLoginEvent event)
{
// DEBUG
// long before = System.nanoTime();
// If the login was allowed ...
if (event.getLoginResult() != Result.ALLOWED) return;
// ... get player id ...
final String playerId = event.getUniqueId().toString();
// ... and store the remote entries.
this.storeRemoteEntries(playerId);
// DEBUG
// long after = System.nanoTime();
// long duration = after - before;
// double ms = (double)duration / 1000000D;
// String message = Txt.parse("<i>AsyncPlayerPreLoginEvent for %s <i>took <h>%.2f <i>ms.", event.getName(), ms);
// MassiveCore.get().log(message);
// NOTE: I get values between 5 and 55 ms!
}
// Can not be cancelled.
@EventHandler(priority = EventPriority.LOWEST)
public void massiveStoreLoginSync(PlayerLoginEvent event)
{
// Get player id ...
Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
final String playerId = player.getUniqueId().toString();
// ... get remote entries ...
Map<SenderColl<?>, Entry<JsonObject, Long>> remoteEntries = getRemoteEntries(playerId);
// ... and sync each of them.
for (Entry<SenderColl<?>, Entry<JsonObject, Long>> entry : remoteEntries.entrySet())
{
SenderColl<?> coll = entry.getKey();
Entry<JsonObject, Long> remoteEntry = entry.getValue();
coll.syncId(playerId, null, remoteEntry);
}
}
// -------------------------------------------- //
// SYNC PLAYER ON LOGON AND LEAVE
// -------------------------------------------- //
@EventHandler(priority = EventPriority.MONITOR)
public void syncOnPlayerLeave(EventMassiveCorePlayerLeave event)
{
Player player = event.getPlayer();
this.syncAllForPlayer(player);
}
public void syncAllForPlayer(Player player)
{
if (MUtil.isntPlayer(player)) return;
String playerId = player.getUniqueId().toString();
for (SenderColl<?> coll : Coll.getSenderInstances())
{
coll.syncId(playerId);
}
}
} }

View File

@ -0,0 +1,80 @@
package com.massivecraft.massivecore.engine;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
import com.massivecraft.massivecore.EngineAbstract;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.event.EventMassiveCorePlayerLeave;
import com.massivecraft.massivecore.util.MUtil;
public class EngineMassiveCorePlayerLeave extends EngineAbstract
{
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static EngineMassiveCorePlayerLeave i = new EngineMassiveCorePlayerLeave();
public static EngineMassiveCorePlayerLeave get() { return i; }
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public Plugin getPlugin()
{
return MassiveCore.get();
}
@Override
public void activate()
{
super.activate();
EventMassiveCorePlayerLeave.player2event.clear();
}
// -------------------------------------------- //
// KICK (RUN)
// -------------------------------------------- //
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void runKick(PlayerKickEvent event)
{
final Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
new EventMassiveCorePlayerLeave(player, true, "kick", event.getReason()).run();
}
// -------------------------------------------- //
// QUIT (RUN AND CLEAR)
// -------------------------------------------- //
@EventHandler(priority = EventPriority.MONITOR)
public void runQuit(PlayerQuitEvent event)
{
final Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
final UUID uuid = player.getUniqueId();
new EventMassiveCorePlayerLeave(player, false, "quit", null).run();
// We do the schedule in order for the set to be correct through out the whole MONITOR priority state.
Bukkit.getScheduler().scheduleSyncDelayedTask(MassiveCore.get(), new Runnable()
{
@Override
public void run()
{
EventMassiveCorePlayerLeave.player2event.remove(uuid);
}
});
}
}

View File

@ -0,0 +1,161 @@
package com.massivecraft.massivecore.engine;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
import com.massivecraft.massivecore.EngineAbstract;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.PlayerState;
import com.massivecraft.massivecore.event.EventMassiveCorePlayerLeave;
import com.massivecraft.massivecore.util.MUtil;
public class EngineMassiveCorePlayerState extends EngineAbstract
{
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static EngineMassiveCorePlayerState i = new EngineMassiveCorePlayerState();
public static EngineMassiveCorePlayerState get() { return i; }
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public Plugin getPlugin()
{
return MassiveCore.get();
}
@Override
public void activate()
{
super.activate();
idToState.clear();
for (Player player : MUtil.getOnlinePlayers())
{
idToState.put(player.getUniqueId(), PlayerState.JOINED);
}
}
// -------------------------------------------- //
// STATE STORAGE
// -------------------------------------------- //
protected Map<UUID, PlayerState> idToState = new ConcurrentHashMap<UUID, PlayerState>();
public PlayerState getState(UUID id)
{
PlayerState ret = this.idToState.get(id);
if (ret == null) ret = PlayerState.LEFT;
return ret;
}
public PlayerState getState(Player player)
{
return this.getState(player.getUniqueId());
}
// -------------------------------------------- //
// LOGASYNC
// -------------------------------------------- //
@EventHandler(priority = EventPriority.LOWEST)
public void logasync(AsyncPlayerPreLoginEvent event)
{
final UUID id = event.getUniqueId();
this.idToState.put(id, PlayerState.LOGASYNC);
}
// -------------------------------------------- //
// LOGSYNC
// -------------------------------------------- //
@EventHandler(priority = EventPriority.LOWEST)
public void logsync(PlayerLoginEvent event)
{
final Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
final UUID id = player.getUniqueId();
this.idToState.put(id, PlayerState.LOGSYNC);
}
// -------------------------------------------- //
// JOINING
// -------------------------------------------- //
@EventHandler(priority = EventPriority.LOWEST)
public void joining(PlayerJoinEvent event)
{
final Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
final UUID id = player.getUniqueId();
this.idToState.put(id, PlayerState.JOINING);
}
// -------------------------------------------- //
// JOINED
// -------------------------------------------- //
@EventHandler(priority = EventPriority.MONITOR)
public void joined(PlayerJoinEvent event)
{
final Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
final UUID id = player.getUniqueId();
Bukkit.getScheduler().scheduleSyncDelayedTask(MassiveCore.get(), new Runnable()
{
@Override
public void run()
{
idToState.put(id, PlayerState.JOINED);
}
});
}
// -------------------------------------------- //
// LEAVING
// -------------------------------------------- //
@EventHandler(priority = EventPriority.LOWEST)
public void leaving(EventMassiveCorePlayerLeave event)
{
final Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
final UUID id = player.getUniqueId();
this.idToState.put(id, PlayerState.LEAVING);
}
// -------------------------------------------- //
// LEFT
// -------------------------------------------- //
@EventHandler(priority = EventPriority.MONITOR)
public void left(PlayerQuitEvent event)
{
final Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
final UUID id = player.getUniqueId();
this.idToState.remove(id);
}
}

View File

@ -1,4 +1,4 @@
package com.massivecraft.massivecore.teleport; package com.massivecraft.massivecore.engine;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -16,18 +16,19 @@ import com.massivecraft.massivecore.EngineAbstract;
import com.massivecraft.massivecore.MassiveCore; import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.event.EventMassiveCorePlayerLeave; import com.massivecraft.massivecore.event.EventMassiveCorePlayerLeave;
import com.massivecraft.massivecore.mixin.Mixin; import com.massivecraft.massivecore.mixin.Mixin;
import com.massivecraft.massivecore.teleport.ScheduledTeleport;
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.TimeUnit; import com.massivecraft.massivecore.util.TimeUnit;
public class EngineScheduledTeleport extends EngineAbstract public class EngineMassiveCoreScheduledTeleport extends EngineAbstract
{ {
// -------------------------------------------- // // -------------------------------------------- //
// INSTANCE & CONSTRUCT // INSTANCE & CONSTRUCT
// -------------------------------------------- // // -------------------------------------------- //
private static EngineScheduledTeleport i = new EngineScheduledTeleport(); private static EngineMassiveCoreScheduledTeleport i = new EngineMassiveCoreScheduledTeleport();
public static EngineScheduledTeleport get() { return i; } public static EngineMassiveCoreScheduledTeleport get() { return i; }
// -------------------------------------------- // // -------------------------------------------- //
// SCHEDULED TELEPORT INDEX // SCHEDULED TELEPORT INDEX

View File

@ -1,4 +1,4 @@
package com.massivecraft.massivecore.mixin; package com.massivecraft.massivecore.engine;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
@ -13,15 +13,15 @@ import org.bukkit.plugin.Plugin;
import com.massivecraft.massivecore.EngineAbstract; import com.massivecraft.massivecore.EngineAbstract;
import com.massivecraft.massivecore.MassiveCore; import com.massivecraft.massivecore.MassiveCore;
public class EngineTeleportMixinCause extends EngineAbstract public class EngineMassiveCoreTeleportMixinCause extends EngineAbstract
{ {
// -------------------------------------------- // // -------------------------------------------- //
// INSTANCE & CONSTRUCT // INSTANCE & CONSTRUCT
// -------------------------------------------- // // -------------------------------------------- //
private static EngineTeleportMixinCause i = new EngineTeleportMixinCause(); private static EngineMassiveCoreTeleportMixinCause i = new EngineMassiveCoreTeleportMixinCause();
public static EngineTeleportMixinCause get() { return i; } public static EngineMassiveCoreTeleportMixinCause get() { return i; }
public EngineTeleportMixinCause() {} public EngineMassiveCoreTeleportMixinCause() {}
// -------------------------------------------- // // -------------------------------------------- //
// OVERRIDE // OVERRIDE

View File

@ -9,6 +9,8 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import com.massivecraft.massivecore.util.MUtil;
/** /**
* The EventMassiveCorePlayerLeave is a non-cancellable event. * The EventMassiveCorePlayerLeave is a non-cancellable event.
* It is run at the MONITOR of either PlayerKickEvent or PlayerQuitEvent. * It is run at the MONITOR of either PlayerKickEvent or PlayerQuitEvent.
@ -67,7 +69,8 @@ public class EventMassiveCorePlayerLeave extends Event implements Runnable
@Override @Override
public void run() public void run()
{ {
UUID uuid = this.player.getUniqueId(); if (MUtil.isntPlayer(player)) return;
final UUID uuid = this.player.getUniqueId();
// Someone may already have issued a player leave event for this disconnect. // Someone may already have issued a player leave event for this disconnect.
// We ignore that since we want one leave event called per disconnect only. // We ignore that since we want one leave event called per disconnect only.

View File

@ -4,6 +4,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.permissions.Permissible; import org.bukkit.permissions.Permissible;
import com.massivecraft.massivecore.MassiveCoreMConf; import com.massivecraft.massivecore.MassiveCoreMConf;
import com.massivecraft.massivecore.engine.EngineMassiveCoreTeleportMixinCause;
import com.massivecraft.massivecore.teleport.Destination; import com.massivecraft.massivecore.teleport.Destination;
public abstract class TeleportMixinAbstract implements TeleportMixin public abstract class TeleportMixinAbstract implements TeleportMixin
@ -24,7 +25,7 @@ public abstract class TeleportMixinAbstract implements TeleportMixin
@Override @Override
public boolean isCausedByMixin(PlayerTeleportEvent event) public boolean isCausedByMixin(PlayerTeleportEvent event)
{ {
return EngineTeleportMixinCause.get().isCausedByTeleportMixin(event); return EngineMassiveCoreTeleportMixinCause.get().isCausedByTeleportMixin(event);
} }
@Override @Override

View File

@ -5,6 +5,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import com.massivecraft.massivecore.engine.EngineMassiveCoreTeleportMixinCause;
import com.massivecraft.massivecore.event.EventMassiveCorePlayerPSTeleport; import com.massivecraft.massivecore.event.EventMassiveCorePlayerPSTeleport;
import com.massivecraft.massivecore.ps.PS; import com.massivecraft.massivecore.ps.PS;
import com.massivecraft.massivecore.teleport.Destination; import com.massivecraft.massivecore.teleport.Destination;
@ -49,9 +50,9 @@ public class TeleportMixinDefault extends TeleportMixinAbstract
if (vehicle != null) vehicle.eject(); if (vehicle != null) vehicle.eject();
// Do the teleport // Do the teleport
EngineTeleportMixinCause.get().setMixinCausedTeleportIncoming(true); EngineMassiveCoreTeleportMixinCause.get().setMixinCausedTeleportIncoming(true);
player.teleport(location); player.teleport(location);
EngineTeleportMixinCause.get().setMixinCausedTeleportIncoming(false); EngineMassiveCoreTeleportMixinCause.get().setMixinCausedTeleportIncoming(false);
// Bukkit velocity // Bukkit velocity
Vector velocity = null; Vector velocity = null;

View File

@ -1,5 +1,6 @@
package com.massivecraft.massivecore.teleport; package com.massivecraft.massivecore.teleport;
import com.massivecraft.massivecore.engine.EngineMassiveCoreScheduledTeleport;
import com.massivecraft.massivecore.mixin.Mixin; import com.massivecraft.massivecore.mixin.Mixin;
import com.massivecraft.massivecore.mixin.TeleporterException; import com.massivecraft.massivecore.mixin.TeleporterException;
@ -41,17 +42,17 @@ public class ScheduledTeleport implements Runnable
public boolean isScheduled() public boolean isScheduled()
{ {
return EngineScheduledTeleport.get().isScheduled(this); return EngineMassiveCoreScheduledTeleport.get().isScheduled(this);
} }
public ScheduledTeleport schedule() public ScheduledTeleport schedule()
{ {
return EngineScheduledTeleport.get().schedule(this); return EngineMassiveCoreScheduledTeleport.get().schedule(this);
} }
public boolean unschedule() public boolean unschedule()
{ {
return EngineScheduledTeleport.get().unschedule(this); return EngineMassiveCoreScheduledTeleport.get().unschedule(this);
} }
// -------------------------------------------- // // -------------------------------------------- //

View File

@ -63,6 +63,7 @@ import com.massivecraft.massivecore.Predicate;
import com.massivecraft.massivecore.collections.MassiveList; import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.collections.MassiveSet; import com.massivecraft.massivecore.collections.MassiveSet;
import com.massivecraft.massivecore.collections.MassiveTreeSet; import com.massivecraft.massivecore.collections.MassiveTreeSet;
import com.massivecraft.massivecore.engine.EngineMassiveCoreDatabase;
import com.massivecraft.massivecore.engine.EngineMassiveCoreMain; import com.massivecraft.massivecore.engine.EngineMassiveCoreMain;
import com.massivecraft.massivecore.engine.EngineMassiveCoreWorldNameSet; import com.massivecraft.massivecore.engine.EngineMassiveCoreWorldNameSet;
import com.massivecraft.massivecore.util.extractor.Extractor; import com.massivecraft.massivecore.util.extractor.Extractor;
@ -224,7 +225,7 @@ public class MUtil
if (address != null) return getIp(address); if (address != null) return getIp(address);
String id = IdUtil.getId(player); String id = IdUtil.getId(player);
PlayerLoginEvent event = EngineMassiveCoreMain.idToPlayerLoginEvent.get(id); PlayerLoginEvent event = EngineMassiveCoreDatabase.idToPlayerLoginEvent.get(id);
if (event != null) return getIp(event); if (event != null) return getIp(event);
return null; return null;

View File

@ -2,11 +2,7 @@ package com.massivecraft.massivecore.util;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentSkipListSet;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -19,7 +15,6 @@ import org.bukkit.event.player.PlayerAnimationType;
import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
@ -48,12 +43,6 @@ public class PlayerUtil extends EngineAbstract
idToDamageEvent.clear(); idToDamageEvent.clear();
idToArmSwingEvent.clear(); idToArmSwingEvent.clear();
joinedPlayerIds.clear();
for (Player player : MUtil.getOnlinePlayers())
{
joinedPlayerIds.add(player.getUniqueId());
}
idToLastMoveMillis.clear(); idToLastMoveMillis.clear();
} }
@ -77,47 +66,6 @@ public class PlayerUtil extends EngineAbstract
idToArmSwingEvent.clear(); idToArmSwingEvent.clear();
} }
// -------------------------------------------- //
// IS JOINED
// -------------------------------------------- //
private static Set<UUID> joinedPlayerIds = new ConcurrentSkipListSet<UUID>();
@EventHandler(priority = EventPriority.MONITOR)
public void isJoined(PlayerJoinEvent event)
{
Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
final UUID id = player.getUniqueId();
Bukkit.getScheduler().scheduleSyncDelayedTask(MassiveCore.get(), new Runnable()
{
@Override
public void run()
{
joinedPlayerIds.add(id);
}
});
}
@EventHandler(priority = EventPriority.MONITOR)
public void isJoined(PlayerQuitEvent event)
{
Player player = event.getPlayer();
if (MUtil.isntPlayer(player)) return;
final UUID id = player.getUniqueId();
joinedPlayerIds.remove(id);
}
public static boolean isJoined(Player player)
{
if (player == null) throw new NullPointerException("player was null");
final UUID id = player.getUniqueId();
return joinedPlayerIds.contains(id);
}
// -------------------------------------------- // // -------------------------------------------- //
// LAST MOVE & STAND STILL (MILLIS) // LAST MOVE & STAND STILL (MILLIS)
// -------------------------------------------- // // -------------------------------------------- //