88import com .lishid .openinv .command .OpenInvCommand ;
99import com .mojang .authlib .GameProfile ;
1010import de .minebench .syncinv .listeners .MapCreationListener ;
11+ import de .minebench .syncinv .listeners .PlayerConnectionValidateLoginListener ;
1112import de .minebench .syncinv .listeners .PlayerFreezeListener ;
1213import de .minebench .syncinv .listeners .PlayerJoinListener ;
14+ import de .minebench .syncinv .listeners .PlayerLoginListener ;
1315import de .minebench .syncinv .listeners .PlayerQuitListener ;
1416import de .minebench .syncinv .messenger .Message ;
1517import de .minebench .syncinv .messenger .MessageType ;
2830import org .bukkit .WorldType ;
2931import org .bukkit .advancement .Advancement ;
3032import org .bukkit .advancement .AdvancementProgress ;
31- import org .bukkit .attribute .Attribute ;
3233import org .bukkit .command .Command ;
3334import org .bukkit .command .CommandExecutor ;
3435import org .bukkit .command .CommandSender ;
4546
4647import java .io .File ;
4748import java .io .IOException ;
49+ import java .lang .reflect .Constructor ;
4850import java .lang .reflect .Field ;
4951import java .lang .reflect .InvocationTargetException ;
5052import java .lang .reflect .Method ;
6163import java .util .Set ;
6264import java .util .UUID ;
6365import java .util .concurrent .TimeUnit ;
66+ import java .util .function .Function ;
6467import java .util .logging .Level ;
6568
6669/*
@@ -155,7 +158,7 @@ public final class SyncInv extends JavaPlugin {
155158 private int newestMap = 0 ;
156159
157160 // Unknown player storing
158- private Method methodGetOfflinePlayer = null ;
161+ private Function < GameProfile , OfflinePlayer > getOfflinePlayer = null ;
159162 private Method methodGetHandle = null ;
160163 private Method methodSetPositionRaw ;
161164 private Field fieldYaw = null ;
@@ -178,13 +181,38 @@ public void onEnable() {
178181 // Plugin startup logic
179182 loadConfig ();
180183
181- playerDataFolder = new File (getServer ().getWorlds ().get (0 ).getWorldFolder (), "playerdata" );
184+ playerDataFolder = getServer ().getMinecraftVersion ().startsWith ("1." )
185+ ? new File (getServer ().getWorlds ().get (0 ).getWorldFolder (), "playerdata" )
186+ : new File (new File (getServer ().getWorlds ().get (0 ).getWorldFolder (), "players" ), "data" );
182187 try {
183- methodGetOfflinePlayer = getServer ().getClass ().getMethod ("getOfflinePlayer" , GameProfile .class );
188+ Method methodGetOfflinePlayer = getServer ().getClass ().getMethod ("getOfflinePlayer" , GameProfile .class );
189+ getOfflinePlayer = (gameProfile -> {
190+ try {
191+ return (OfflinePlayer ) methodGetOfflinePlayer .invoke (getServer (), gameProfile );
192+ } catch (IllegalAccessException | InvocationTargetException e ) {
193+ logDebug ("Could not create offline player for " + gameProfile .getId () + "! " + e .getMessage ());
194+ }
195+ return null ;
196+ });
184197 } catch (NoSuchMethodException e ) {
185- if (storeUnknownPlayers ) {
186- getLogger ().log (Level .WARNING , "Could not load method required to store unknown players. Disabling it!" , e );
187- storeUnknownPlayers = false ;
198+ try {
199+ Class nameAndIdClass = Class .forName ("net.minecraft.server.players.NameAndId" );
200+ Constructor nameAndIdConstructor = nameAndIdClass .getConstructor (GameProfile .class );
201+ Method methodGetOfflinePlayer = getServer ().getClass ().getMethod ("getOfflinePlayer" , nameAndIdClass );
202+ getOfflinePlayer = (gameProfile -> {
203+ try {
204+ Object nameAndId = nameAndIdConstructor .newInstance (gameProfile );
205+ return (OfflinePlayer ) methodGetOfflinePlayer .invoke (getServer (), nameAndId );
206+ } catch (IllegalAccessException | InvocationTargetException | InstantiationException e1 ) {
207+ logDebug ("Could not create offline player for " + gameProfile .getId () + "! " + e .getMessage ());
208+ }
209+ return null ;
210+ });
211+ } catch (NoSuchMethodException | ClassNotFoundException e2 ) {
212+ if (storeUnknownPlayers ) {
213+ getLogger ().log (Level .WARNING , "Could not load method required to store unknown players. Disabling it!" , e );
214+ storeUnknownPlayers = false ;
215+ }
188216 }
189217 }
190218 playerDataCache = CacheBuilder .newBuilder ().expireAfterWrite (queryTimeout , TimeUnit .SECONDS ).build ();
@@ -196,6 +224,14 @@ public void onEnable() {
196224 }
197225
198226 getServer ().getPluginManager ().registerEvents (new PlayerJoinListener (this ), this );
227+ try {
228+ Class .forName ("io.papermc.paper.event.connection.PlayerConnectionValidateLoginEvent" );
229+ getServer ().getPluginManager ().registerEvents (new PlayerConnectionValidateLoginListener (this ), this );
230+ logDebug ("Using Paper connection validate login event" );
231+ } catch (ClassNotFoundException e ) {
232+ getServer ().getPluginManager ().registerEvents (new PlayerLoginListener (this ), this );
233+ logDebug ("Using legacy login event" );
234+ }
199235 getServer ().getPluginManager ().registerEvents (new PlayerQuitListener (this ), this );
200236 getServer ().getPluginManager ().registerEvents (new PlayerFreezeListener (this ), this );
201237 getServer ().getPluginManager ().registerEvents (new MapCreationListener (this ), this );
@@ -226,7 +262,7 @@ public void onEnable() {
226262 openInvCommand .onCommand (sender , command , label , args );
227263 } else {
228264 sender .sendMessage (ChatColor .RED + "Current server does not have newest player data! "
229- + ChatColor .GRAY + "Connecting to server " + query .getYoungestServer () + " which has the newest data..." );
265+ + ChatColor .GRAY + "Connecting to server " + query .getYoungestServer () + " which has the newest data..." );
230266 connectToServer (((Player ) sender ).getUniqueId (), query .getYoungestServer ());
231267 }
232268 });
@@ -304,7 +340,7 @@ public void loadConfig() {
304340 for (SyncType syncType : SyncType .values ()) {
305341 String key = "sync." + syncType .getKey ();
306342 if (!getConfig ().contains (key , true )
307- && getConfig ().contains ("sync-" + syncType .getKey (), true )) {
343+ && getConfig ().contains ("sync-" + syncType .getKey (), true )) {
308344 key = "sync-" + syncType .getKey ();
309345 }
310346 if (getConfig ().getBoolean (key )) {
@@ -362,15 +398,11 @@ && getConfig().contains("sync-" + syncType.getKey(), true)) {
362398 fieldWorldMap .setAccessible (true );
363399 Object worldMap = fieldWorldMap .get (map );
364400 try {
365- fieldMapColor = worldMap .getClass ().getField ("g" );
366- } catch (NoSuchFieldException e ) {
367- try {
368- fieldMapColor = worldMap .getClass ().getField ("colors" );
369- } catch (NoSuchFieldException e1 ) {
370- for (Field field : worldMap .getClass ().getFields ()) {
371- if (field .getType () == byte [].class ) {
372- fieldMapColor = field ;
373- }
401+ fieldMapColor = worldMap .getClass ().getField ("colors" );
402+ } catch (NoSuchFieldException e1 ) {
403+ for (Field field : worldMap .getClass ().getFields ()) {
404+ if (field .getType () == byte [].class ) {
405+ fieldMapColor = field ;
374406 }
375407 }
376408 }
@@ -391,8 +423,8 @@ && getConfig().contains("sync-" + syncType.getKey(), true)) {
391423 if (storeUnknownPlayers && getServer ().getWorld ("world" ) == null && getConfig ().getBoolean ("create-world" )) {
392424 getLogger ().log (Level .INFO , "No world with the name 'world' exists while 'store-unknown-players' is enabled. This world is needed for that functionality to work correctly, creating it... (can be disabled with 'create-world' in the config)" );
393425 World world = getServer ().createWorld (new WorldCreator ("world" )
394- .type (WorldType .FLAT )
395- .generateStructures (false ));
426+ .type (WorldType .FLAT )
427+ .generateStructures (false ));
396428 world .setAutoSave (false );
397429 world .setViewDistance (2 );
398430 world .setKeepSpawnInMemory (false );
@@ -417,14 +449,14 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String
417449
418450 /**
419451 * Get a language message from the config and replace variables in it
420- * @param key The key of the message (lang.<key>)
452+ * @param key The key of the message (lang.<key>)
421453 * @param replacements An array of variables to be replaced with certain strings in the format [var,repl,var,repl,...]
422454 * @return The message string with colorcodes and variables replaced
423455 */
424456 public String getLang (String key , String ... replacements ) {
425457 String msg = ChatColor .translateAlternateColorCodes ('&' , getConfig ().getString ("lang." + key , getName () + ": &cMissing language key &6" + key ));
426458 for (int i = 0 ; i + 1 < replacements .length ; i += 2 ) {
427- msg = msg .replace ("%" + replacements [i ] + "%" , replacements [i + 1 ]);
459+ msg = msg .replace ("%" + replacements [i ] + "%" , replacements [i + 1 ]);
428460 }
429461 return msg ;
430462 }
@@ -440,10 +472,10 @@ public boolean isLocked(UUID playerId) {
440472
441473 /**
442474 * Get the date when a player last logged out
443- * @param playerId The UUID of the player
444- * @param online Whether or not it should return the current time if the player is online
445- * @return The timestamp of his last known data on the server in milliseconds;
446- * 0 if the file doesn't exist or an error occurs. (Take a look at {File#lastModified})
475+ * @param playerId The UUID of the player
476+ * @param online Whether or not it should return the current time if the player is online
477+ * @return The timestamp of his last known data on the server in milliseconds;
478+ * 0 if the file doesn't exist or an error occurs. (Take a look at {File#lastModified})
447479 */
448480 public long getLastSeen (UUID playerId , boolean online ) {
449481 if (online ) {
@@ -473,7 +505,7 @@ public long getLastSeen(UUID playerId, boolean online) {
473505 * @param playerId The UUID of the player
474506 * @param timeStamp The timestamp to set as the last modify time of the file in
475507 * milliseconds.
476- * @return true if the time was successfully set
508+ * @return true if the time was successfully set
477509 */
478510 public boolean setLastSeen (UUID playerId , long timeStamp ) {
479511 File playerDat = getPlayerDataFile (playerId );
@@ -528,7 +560,7 @@ public boolean applyTimedOutQueries() {
528560 /**
529561 * Connect a player to a bungee server
530562 * @param playerId The UUID of the player
531- * @param server The name of the server
563+ * @param server The name of the server
532564 */
533565 public void connectToServer (UUID playerId , String server ) {
534566 Player player = getServer ().getPlayer (playerId );
@@ -542,16 +574,16 @@ public void connectToServer(UUID playerId, String server) {
542574
543575 /**
544576 * Apply a PlayerData object to its player
545- * @param data The data to apply
577+ * @param data The data to apply
546578 */
547579 public void applyData (PlayerData data , Runnable finished ) {
548580 if (data == null )
549581 return ;
550582
551583 if (data .getDataVersion () != getServer ().getUnsafe ().getDataVersion ()) {
552584 getLogger ().log (Level .WARNING , "Received data with "
553- + (data .getDataVersion () < getServer ().getUnsafe ().getDataVersion () ? "older" : "newer" )
554- + " Minecraft data version (" + data .getDataVersion () + ") than this server (" + getServer ().getUnsafe ().getDataVersion () + "). Trying to apply anyways but there will most likely be errors! Please try running the same Server version on all synced servers." );
585+ + (data .getDataVersion () < getServer ().getUnsafe ().getDataVersion () ? "older" : "newer" )
586+ + " Minecraft data version (" + data .getDataVersion () + ") than this server (" + getServer ().getUnsafe ().getDataVersion () + "). Trying to apply anyways but there will most likely be errors! Please try running the same Server version on all synced servers." );
555587 }
556588
557589 runSync (() -> {
@@ -572,10 +604,9 @@ public void applyData(PlayerData data, Runnable finished) {
572604 OfflinePlayer offlinePlayer = getServer ().getOfflinePlayer (data .getPlayerId ());
573605 if (storeUnknownPlayers && !offlinePlayer .hasPlayedBefore ()) {
574606 if (offlinePlayer .getName () == null ) {
575- try {
576- offlinePlayer = (OfflinePlayer ) methodGetOfflinePlayer .invoke (getServer (), new GameProfile (data .getPlayerId (), data .getPlayerName ()));
577- } catch (IllegalAccessException | InvocationTargetException e ) {
578- logDebug ("Could not create offline player for " + data .getPlayerId () + "! " + e .getMessage ());
607+ OfflinePlayer internalOfflinePlayer = getOfflinePlayer .apply (new GameProfile (data .getPlayerId (), data .getPlayerName ()));
608+ if (internalOfflinePlayer != null ) {
609+ offlinePlayer = internalOfflinePlayer ;
579610 }
580611 }
581612 createdNewFile = createNewEmptyData (offlinePlayer .getUniqueId ());
@@ -638,7 +669,7 @@ public void applyData(PlayerData data, Runnable finished) {
638669 }
639670 if (player == null ) {
640671 logDebug ("Could not apply data for player " + data .getPlayerId () + " as he isn't online and "
641- + (getOpenInv () == null ? "this server doesn't have OpenInv installed!" : "never was online on this server before!" ));
672+ + (getOpenInv () == null ? "this server doesn't have OpenInv installed!" : "never was online on this server before!" ));
642673 if (createdNewFile ) {
643674 getPlayerDataFile (data .getPlayerId ()).delete ();
644675 }
@@ -720,7 +751,7 @@ public void applyData(PlayerData data, Runnable finished) {
720751 }
721752 }
722753 if (shouldSync (SyncType .HEALTH )) {
723- player .getAttribute ( Attribute . GENERIC_MAX_HEALTH ). setBaseValue (data .getMaxHealth ());
754+ player .setMaxHealth (data .getMaxHealth ());
724755 }
725756 if (shouldSync (SyncType .HUNGER ))
726757 player .setFoodLevel (data .getFoodLevel ());
@@ -761,7 +792,7 @@ public void applyData(PlayerData data, Runnable finished) {
761792 } catch (NullPointerException ignored ) {
762793 // world is not known
763794 }
764- for (Iterator <Advancement > it = getServer ().advancementIterator (); it .hasNext (); ) {
795+ for (Iterator <Advancement > it = getServer ().advancementIterator (); it .hasNext ();) {
765796 Advancement advancement = it .next ();
766797 Map <String , Long > awarded = data .getAdvancementProgress ().get (advancement .getKey ().toString ());
767798 if (awarded != null ) {
@@ -988,7 +1019,7 @@ public PlayerData getData(Player player) {
9881019 }
9891020
9901021 if (shouldSync (SyncType .ADVANCEMENTS )) {
991- for (Iterator <Advancement > it = getServer ().advancementIterator (); it .hasNext (); ) {
1022+ for (Iterator <Advancement > it = getServer ().advancementIterator (); it .hasNext ();) {
9921023 Advancement advancement = it .next ();
9931024 AdvancementProgress progress = player .getAdvancementProgress (advancement );
9941025 Map <String , Long > awarded = new HashMap <>();
@@ -1075,12 +1106,12 @@ public PlayerData getData(Player player) {
10751106 }
10761107
10771108 MapData mapData = new MapData (
1078- map .getId (),
1079- worldId ,
1080- map .getCenterX (),
1081- map .getCenterZ (),
1082- map .getScale (),
1083- colors
1109+ map .getId (),
1110+ worldId ,
1111+ map .getCenterX (),
1112+ map .getCenterZ (),
1113+ map .getScale (),
1114+ colors
10841115 );
10851116 try {
10861117 // Newer map info
0 commit comments