Optimistic player data creation. Updating of world / player name. (+)
Create PlayerData instances if events allow proceeding: * AsyncPlayerPreLogin. * PlayerLogin (schedule for removal if denied). Update world data: * PlayerLogin * (PlayerJoin, ...) Update player name and log: * PlayerLogin * PlayerJoin (+) PlayerData.updateCurrentWorld -> only do something if the WorldData instance has changed.
This commit is contained in:
parent
e20fe539ef
commit
6bddb1a834
|
@ -112,7 +112,10 @@ public class PlayerData implements IPlayerData {
|
|||
private static float heavyLoad = 500000f / (float) ticksMonitored;
|
||||
|
||||
// Default tags.
|
||||
// TODO: Move elsewhere (API?)
|
||||
public static final String TAG_NOTIFY_OFF = "notify_off";
|
||||
/** Optimistic player data creation. */
|
||||
public static final String TAG_OPTIMISTIC_CREATE = "optimistic_create";
|
||||
|
||||
private static final short frequentTaskLazyDefaultDelay = 10;
|
||||
private static final short frequentTaskUnregisterDefaultDelay = 2;
|
||||
|
@ -142,9 +145,9 @@ public class PlayerData implements IPlayerData {
|
|||
|
||||
// TODO: Names could/should get updated. (In which case?)
|
||||
/** Exact case name of the player. */
|
||||
private final String playerName;
|
||||
private String playerName;
|
||||
/** Lower case name of the player. */
|
||||
private final String lcName;
|
||||
private String playerNameLowerCase;
|
||||
|
||||
private long lastJoinTime = 0;
|
||||
|
||||
|
@ -195,10 +198,15 @@ public class PlayerData implements IPlayerData {
|
|||
final PermissionRegistry permissionRegistry) {
|
||||
this.playerId = playerId;
|
||||
this.playerName = playerName;
|
||||
this.lcName = playerName.toLowerCase();
|
||||
this.playerNameLowerCase = playerName.toLowerCase();
|
||||
this.permissionRegistry = permissionRegistry;
|
||||
}
|
||||
|
||||
void updatePlayerName(final String exactPlayerName) {
|
||||
this.playerName = exactPlayerName;
|
||||
this.playerNameLowerCase = exactPlayerName.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run with DataManager frequent tasks (each tick).
|
||||
*
|
||||
|
@ -486,8 +494,10 @@ public class PlayerData implements IPlayerData {
|
|||
*/
|
||||
void updateCurrentWorld(final IWorldData worldData) {
|
||||
// TODO: Consider storing last world too.
|
||||
currentWorldData = worldData;
|
||||
checkTypeTree.getNode(CheckType.ALL).updateDebug(worldData);
|
||||
if (currentWorldData != worldData) {
|
||||
currentWorldData = worldData;
|
||||
checkTypeTree.getNode(CheckType.ALL).updateDebug(worldData);
|
||||
}
|
||||
}
|
||||
|
||||
private void invalidateOffline() {
|
||||
|
@ -627,7 +637,7 @@ public class PlayerData implements IPlayerData {
|
|||
|
||||
@Override
|
||||
public String getPlayerNameLowerCase() {
|
||||
return lcName;
|
||||
return playerNameLowerCase;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -33,9 +33,11 @@ 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.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerKickEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
|
||||
|
@ -219,6 +221,31 @@ public class PlayerDataManager implements IPlayerDataManager, ComponentWithName
|
|||
playerLeaves(event.getPlayer());
|
||||
}
|
||||
},
|
||||
new MiniListener<AsyncPlayerPreLoginEvent>() {
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
@RegisterMethodWithOrder(tag = "system.nocheatplus.datamanager", beforeTag = ".*")
|
||||
@Override
|
||||
public void onEvent(final AsyncPlayerPreLoginEvent event) {
|
||||
// TODO: Maintain a flag for precondition (e.g. ProtocolLib present).
|
||||
if (event.getLoginResult() == AsyncPlayerPreLoginEvent.Result.ALLOWED) {
|
||||
onAsyncPlayerPreLogin(event);
|
||||
}
|
||||
}
|
||||
},
|
||||
new MiniListener<PlayerLoginEvent>() {
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
@RegisterMethodWithOrder(tag = "system.nocheatplus.datamanager", beforeTag = ".*")
|
||||
@Override
|
||||
public void onEvent(final PlayerLoginEvent event) {
|
||||
// TODO: Maintain a flag for precondition (e.g. ProtocolLib present).
|
||||
if (event.getResult() == PlayerLoginEvent.Result.ALLOWED) {
|
||||
onPlayerLogin(event);
|
||||
}
|
||||
else {
|
||||
onPlayerLoginDenied(event);
|
||||
}
|
||||
}
|
||||
},
|
||||
new MiniListener<PlayerJoinEvent>() {
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
@RegisterMethodWithOrder(tag = "system.nocheatplus.datamanager", beforeTag = ".*")
|
||||
|
@ -555,6 +582,70 @@ public class PlayerDataManager implements IPlayerDataManager, ComponentWithName
|
|||
playerMap.remove(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure a PlayerData instance exists for later use.
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
private void onAsyncPlayerPreLogin(final AsyncPlayerPreLoginEvent event) {
|
||||
final UUID playerId = event.getUniqueId(); // Treat carefully :).
|
||||
if (playerData.containsKey(playerId)) {
|
||||
// Skip if a PlayerData instance already exists.
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// Create with default world data.
|
||||
getPlayerData(playerId, event.getName(), true, worldDataManager.getDefaultWorldData()).addTag(PlayerData.TAG_OPTIMISTIC_CREATE);
|
||||
}
|
||||
}
|
||||
|
||||
private void onPlayerLoginDenied(final PlayerLoginEvent event) {
|
||||
// Consistency check existing data.
|
||||
final UUID playerId = event.getPlayer().getUniqueId();
|
||||
final PlayerData pData = getPlayerData(playerId);
|
||||
if (pData != null && pData.hasTag(PlayerData.TAG_OPTIMISTIC_CREATE)) {
|
||||
bulkPlayerDataRemoval.add(playerId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Just update the world data for later use.
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
private void onPlayerLogin(final PlayerLoginEvent event) {
|
||||
// Consistency check existing data.
|
||||
final Player player = event.getPlayer();
|
||||
final UUID playerId = player.getUniqueId();
|
||||
final PlayerData pData = getPlayerData(playerId);
|
||||
if (pData == null) {
|
||||
// Create an instance.
|
||||
// TODO: Legacy server compatibility with world getting?
|
||||
getPlayerData(player);
|
||||
}
|
||||
else {
|
||||
// Consistency check.
|
||||
final String playerName = pData.getPlayerName();
|
||||
if (!playerName.equals(player.getName())) {
|
||||
updatePlayerName(playerId, playerName, pData, "login");
|
||||
}
|
||||
// Update world.
|
||||
pData.updateCurrentWorld(worldDataManager.getWorldData(player.getWorld()));
|
||||
}
|
||||
pData.removeTag(PlayerData.TAG_OPTIMISTIC_CREATE);
|
||||
}
|
||||
|
||||
private void updatePlayerName(final UUID playerId, final String playerName,
|
||||
final PlayerData pData, String tag) {
|
||||
// Name change.
|
||||
pData.updatePlayerName(playerName);
|
||||
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().info(Streams.STATUS,
|
||||
CheckUtils.getLogMessagePrefix(playerName, null)
|
||||
+ " Update player name for id " + playerId + ": " + playerName
|
||||
+ "(" + tag + (pData.hasTag(PlayerData.TAG_OPTIMISTIC_CREATE) ?
|
||||
", optimistically created data" : "") + ")");
|
||||
}
|
||||
|
||||
private void playerJoins(final PlayerJoinEvent event) {
|
||||
final long timeNow = System.currentTimeMillis();
|
||||
final Player player = event.getPlayer();
|
||||
|
@ -564,10 +655,12 @@ public class PlayerDataManager implements IPlayerDataManager, ComponentWithName
|
|||
addOnlinePlayer(player);
|
||||
//
|
||||
final PlayerData pData = getPlayerData(player, true);
|
||||
/*
|
||||
* TODO: Now we update the world already with getPlayerData, in case
|
||||
* it's just been created...
|
||||
*/
|
||||
// Consistency check.
|
||||
final String playerName = pData.getPlayerName();
|
||||
if (!playerName.equals(player.getName())) {
|
||||
updatePlayerName(playerId, playerName, pData, "login");
|
||||
}
|
||||
// Data stuff.
|
||||
final Collection<Class<? extends IDataOnJoin>> types = factoryRegistry.getGroupedTypes(IDataOnJoin.class);
|
||||
pData.onPlayerJoin(player, player.getWorld(), timeNow, worldDataManager, types);
|
||||
pData.getGenericInstance(CombinedData.class).lastJoinTime = timeNow;
|
||||
|
|
|
@ -1278,7 +1278,7 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
|
|||
}
|
||||
final Player player = event.getPlayer();
|
||||
// Check if login is denied (plus expiration check).
|
||||
// TODO: Store by id + HashMapLOW.
|
||||
// TODO: Store by id + HashMapLOW + AsyncPlayerPreLogin.
|
||||
if (checkDenyLoginsNames(player.getName())) {
|
||||
if (DataManager.getPlayerData(player).hasPermission(Permissions.BYPASS_DENY_LOGIN, player)) {
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue