1313import org .mvplugins .multiverse .inventories .commands .InventoriesCommand ;
1414import org .mvplugins .multiverse .inventories .config .InventoriesConfig ;
1515import org .mvplugins .multiverse .inventories .profile .GlobalProfile ;
16- import org .mvplugins .multiverse .inventories .profile .ProfileCacheManager ;
1716import org .mvplugins .multiverse .inventories .profile .ProfileDataSource ;
1817import org .mvplugins .multiverse .inventories .profile .key .GlobalProfileKey ;
1918import org .mvplugins .multiverse .inventories .profile .key .ProfileKey ;
20- import org .mvplugins .multiverse .inventories .profile .key .ProfileType ;
2119import org .mvplugins .multiverse .inventories .profile .key .ProfileTypes ;
2220import org .mvplugins .multiverse .inventories .profile .key .ContainerType ;
2321import org .mvplugins .multiverse .inventories .profile .ProfileFilesLocator ;
24- import org .mvplugins .multiverse .inventories .util .ItemStackConverter ;
2522
2623import java .io .File ;
2724import java .nio .charset .StandardCharsets ;
2825import java .util .ArrayList ;
29- import java .util .HashMap ;
26+ import java .util .Arrays ;
3027import java .util .HashSet ;
3128import java .util .List ;
32- import java .util .Map ;
3329import java .util .Set ;
3430import java .util .UUID ;
3531import java .util .concurrent .CompletableFuture ;
@@ -41,32 +37,24 @@ final class MigrateInventorySerializationCommand extends InventoriesCommand {
4137 private final CommandQueueManager commandQueueManager ;
4238 private final ProfileDataSource profileDataSource ;
4339 private final InventoriesConfig inventoriesConfig ;
44- private final ProfileCacheManager profileCacheManager ;
4540 private final ProfileFilesLocator profileFilesLocator ;
4641
4742 @ Inject
4843 MigrateInventorySerializationCommand (
4944 @ NotNull CommandQueueManager commandQueueManager ,
5045 @ NotNull ProfileDataSource profileDataSource ,
5146 @ NotNull InventoriesConfig inventoriesConfig ,
52- @ NotNull ProfileCacheManager profileCacheManager ,
5347 @ NotNull ProfileFilesLocator profileFilesLocator
5448 ) {
5549 this .commandQueueManager = commandQueueManager ;
5650 this .profileDataSource = profileDataSource ;
5751 this .inventoriesConfig = inventoriesConfig ;
58- this .profileCacheManager = profileCacheManager ;
5952 this .profileFilesLocator = profileFilesLocator ;
6053 }
6154
6255 @ Subcommand ("bulkedit migrate inventory-serialization nbt" )
6356 @ CommandPermission ("multiverse.inventories.bulkedit" )
6457 void onNbtCommand (MVCommandIssuer issuer ) {
65- if (!ItemStackConverter .hasByteSerializeSupport ()) {
66- issuer .sendMessage ("NBT serialization is only supported on PaperMC 1.20.2 or higher!" );
67- issuer .sendMessage ("Conversion to NBT is not possible on your current server version." );
68- return ;
69- }
7058 commandQueueManager .addToQueue (CommandQueuePayload .issuer (issuer )
7159 .prompt (Message .of ("Are you sure you want to migrate all player data to NBT?" ))
7260 .action (() -> doMigration (issuer , true )));
@@ -81,114 +69,84 @@ void onBukkitCommand(MVCommandIssuer issuer) {
8169 }
8270
8371 private void doMigration (MVCommandIssuer issuer , boolean useByteSerialization ) {
84- issuer .sendMessage ("Updating config and clearing caches..." );
8572 inventoriesConfig .setUseByteSerializationForInventoryData (useByteSerialization );
8673 inventoriesConfig .save ();
87- profileCacheManager .clearAllCache ();
8874
8975 long startTime = System .nanoTime ();
9076 AtomicLong profileCounter = new AtomicLong (0 );
9177
92- Map <ContainerType , List <String >> containerNames = new HashMap <>();
93- for (ContainerType type : ContainerType .values ()) {
94- containerNames .put (type , profileDataSource .listContainerDataNames (type ));
95- }
96-
97- Set <String > playerIdentifiers = new HashSet <>();
9878 // Scan global files
79+ Set <String > fileNamesSet = new HashSet <>();
9980 profileFilesLocator .listGlobalFiles ().forEach (file ->
100- playerIdentifiers .add (Files .getNameWithoutExtension (file .getName ())));
81+ fileNamesSet .add (Files .getNameWithoutExtension (file .getName ())));
10182
10283 // Scan world and group files
10384 for (ContainerType type : ContainerType .values ()) {
10485 for (File folder : profileFilesLocator .listProfileContainerFolders (type )) {
10586 profileFilesLocator .listPlayerProfileFiles (type , folder .getName ()).forEach (file ->
106- playerIdentifiers .add (Files .getNameWithoutExtension (file .getName ())));
87+ fileNamesSet .add (Files .getNameWithoutExtension (file .getName ())));
10788 }
10889 }
10990
110- issuer .sendMessage ("Found " + playerIdentifiers .size () + " unique player identifiers to migrate." );
91+ List <String > fileNames = new ArrayList <>(fileNamesSet );
92+ issuer .sendMessage ("Found " + fileNames .size () + " unique players to migrate." );
11193
112- migrateNextPlayer (issuer , new ArrayList <>(playerIdentifiers ), 0 , containerNames , profileCounter )
113- .thenRun (() -> {
114- long timeDuration = (System .nanoTime () - startTime ) / 1000000 ;
115- issuer .sendMessage ("Updated " + profileCounter .get () + " player profiles." );
116- issuer .sendMessage ("Bulk edit completed in " + timeDuration + " ms." );
117- });
118- }
119-
120- private CompletableFuture <Void > migrateNextPlayer (
121- MVCommandIssuer issuer ,
122- List <String > playerIdentifiers ,
123- int index ,
124- Map <ContainerType , List <String >> containerNames ,
125- AtomicLong profileCounter
126- ) {
127- if (index >= playerIdentifiers .size ()) {
128- return CompletableFuture .completedFuture (null );
129- }
94+ CompletableFuture <Void > future = CompletableFuture .completedFuture (null );
95+ for (int i = 0 ; i < fileNames .size (); i ++) {
96+ final int index = i ;
97+ final String fileName = fileNames .get (i );
98+
99+ future = future .thenCompose (v -> {
100+ UUID playerUUID ;
101+ try {
102+ playerUUID = UUID .fromString (fileName );
103+ } catch (IllegalArgumentException e ) {
104+ playerUUID = UUID .nameUUIDFromBytes (("OfflinePlayer:" + fileName ).getBytes (StandardCharsets .UTF_8 ));
105+ }
130106
131- String playerIdentifier = playerIdentifiers .get (index );
132- UUID playerUUID ;
133- try {
134- playerUUID = UUID .fromString (playerIdentifier );
135- } catch (IllegalArgumentException e ) {
136- playerUUID = UUID .nameUUIDFromBytes (("OfflinePlayer:" + playerIdentifier ).getBytes (StandardCharsets .UTF_8 ));
137- }
107+ if (index % 100 == 0 ) {
108+ issuer .sendMessage ("Processed " + index + " players..." );
109+ }
138110
139- if (index % 50 == 0 && index > 0 ) {
140- issuer .sendMessage ("Processed " + index + " players..." );
111+ return profileDataSource .getGlobalProfile (GlobalProfileKey .of (playerUUID , fileName ))
112+ .thenCompose (profile -> run (profile , profileCounter ))
113+ .exceptionally (throwable -> {
114+ issuer .sendMessage ("Error updating player " + fileName + ": " + throwable .getMessage ());
115+ return null ;
116+ });
117+ });
141118 }
142119
143- return profileDataSource .getGlobalProfile (GlobalProfileKey .of (playerUUID , playerIdentifier ))
144- .thenCompose (profile -> run (issuer , profile , containerNames , profileCounter ))
145- .exceptionally (throwable -> {
146- issuer .sendMessage ("Error updating player " + playerIdentifier + ": " + throwable .getMessage ());
147- return null ;
148- })
149- .thenCompose (v -> migrateNextPlayer (issuer , playerIdentifiers , index + 1 , containerNames , profileCounter ));
120+ future .thenRun (() -> {
121+ long timeDuration = (System .nanoTime () - startTime ) / 1000000 ;
122+ issuer .sendMessage ("Updated " + profileCounter .get () + " player profiles." );
123+ issuer .sendMessage ("Bulk edit completed in " + timeDuration + " ms." );
124+ });
150125 }
151126
152- private CompletableFuture <Void > run (
153- MVCommandIssuer issuer ,
154- GlobalProfile profile ,
155- Map <ContainerType , List <String >> containerNames ,
156- AtomicLong profileCounter
157- ) {
158- String playerName = profile .getLastKnownName ();
159- if (playerName == null || playerName .isEmpty ()) {
160- playerName = profile .getPlayerUUID ().toString ();
161- }
162-
163- CompletableFuture <Void > future = CompletableFuture .completedFuture (null );
164- for (ContainerType containerType : ContainerType .values ()) {
165- List <String > dataNames = containerNames .get (containerType );
166- for (String dataName : dataNames ) {
167- for (ProfileType profileType : ProfileTypes .getTypes ()) {
168- ProfileKey profileKey = ProfileKey .of (
169- containerType ,
170- dataName ,
171- profileType ,
172- profile .getPlayerUUID (),
173- playerName
174- );
175- future = future .thenCompose (v -> profileDataSource .getPlayerProfile (profileKey )
176- .thenCompose (playerProfile -> {
177- if (playerProfile .getData ().isEmpty ()) {
178- return CompletableFuture .completedFuture (null );
179- }
180- profileCounter .incrementAndGet ();
181- return profileDataSource .updatePlayerProfile (playerProfile );
182- })
183- .exceptionally (throwable -> {
184- issuer .sendMessage (String .format ("Error migrating profile %s %s/%s for player %s: %s" ,
185- containerType , dataName , profileType , profile .getPlayerUUID (), throwable .getMessage ()));
186- return null ;
187- })
188- );
189- }
190- }
127+ private CompletableFuture <Void > run (GlobalProfile profile , AtomicLong profileCounter ) {
128+ String fileName = profile .getLastKnownName ();
129+ if (fileName == null || fileName .isEmpty ()) {
130+ fileName = profile .getPlayerUUID ().toString ();
191131 }
192- return future ;
132+ final String finalFileName = fileName ;
133+
134+ return CompletableFuture .allOf (Arrays .stream (ContainerType .values ())
135+ .flatMap (containerType -> profileDataSource .listContainerDataNames (containerType ).stream ()
136+ .flatMap (dataName -> ProfileTypes .getTypes ().stream ()
137+ .map (profileType -> profileDataSource .getPlayerProfile (ProfileKey .of (
138+ containerType ,
139+ dataName ,
140+ profileType ,
141+ profile .getPlayerUUID (),
142+ finalFileName
143+ )).thenCompose (playerProfile -> {
144+ if (playerProfile .getData ().isEmpty ()) {
145+ return CompletableFuture .completedFuture (null );
146+ }
147+ profileCounter .incrementAndGet ();
148+ return profileDataSource .updatePlayerProfile (playerProfile );
149+ }))))
150+ .toArray (CompletableFuture []::new ));
193151 }
194152}
0 commit comments