11package com .ishland .c2me .rewrites .chunksystem .common .statuses ;
22
3+ import com .ibm .asyncutil .util .Either ;
34import com .ishland .c2me .base .common .GlobalExecutors ;
45import com .ishland .c2me .base .common .config .ModStatuses ;
56import com .ishland .c2me .base .common .registry .SerializerAccess ;
2223import com .ishland .flowsched .scheduler .Cancellable ;
2324import com .ishland .flowsched .scheduler .ItemHolder ;
2425import com .ishland .flowsched .scheduler .KeyStatusPair ;
26+ import com .ishland .flowsched .util .Assertions ;
2527import io .reactivex .rxjava3 .annotations .NonNull ;
2628import io .reactivex .rxjava3 .core .Completable ;
2729import io .reactivex .rxjava3 .core .Single ;
2830import io .reactivex .rxjava3 .schedulers .Schedulers ;
2931import net .minecraft .nbt .NbtCompound ;
30- import net .minecraft .registry .RegistryKeys ;
3132import net .minecraft .server .MinecraftServer ;
3233import net .minecraft .server .world .ServerWorld ;
3334import net .minecraft .util .math .ChunkPos ;
@@ -59,13 +60,13 @@ public ReadFromDisk(int ordinal) {
5960 }
6061
6162 @ Override
62- public CompletionStage < Void > upgradeToThis (ChunkLoadingContext context , Cancellable cancellable ) {
63+ public Completable upgradeToThis (ChunkLoadingContext context , Cancellable cancellable ) {
6364 final Single <ProtoChunk > single = invokeVanillaLoad (context )
6465 .retryWhen (RxJavaUtils .retryWithExponentialBackoff (5 , 100 ));
6566 return finalizeLoading (context , single );
6667 }
6768
68- protected @ NotNull CompletionStage < Void > finalizeLoading (ChunkLoadingContext context , Single <ProtoChunk > single ) {
69+ protected @ NotNull Completable finalizeLoading (ChunkLoadingContext context , Single <ProtoChunk > single ) {
6970 return single
7071 .doOnError (throwable -> {
7172 MinecraftServer server = ((IThreadedAnvilChunkStorage ) context .tacs ()).getWorld ().getServer ();
@@ -85,14 +86,15 @@ public CompletionStage<Void> upgradeToThis(ChunkLoadingContext context, Cancella
8586 }
8687 })
8788 .ignoreElement ()
88- .cache ()
89- .toCompletionStage (null );
89+ .cache ();
9090 }
9191
9292 protected @ NonNull Single <ProtoChunk > invokeVanillaLoad (ChunkLoadingContext context ) {
9393 return invokeInitialChunkRead (context )
9494 .observeOn (Schedulers .from (((IThreadedAnvilChunkStorage ) context .tacs ()).getMainThreadExecutor ()))
9595 .map (chunkSerializer -> {
96+ Assertions .assertTrue (((IThreadedAnvilChunkStorage ) context .tacs ()).getMainThreadExecutor ().isOnThread ());
97+
9698 try (var ignored = ThreadInstrumentation .getCurrent ().begin (new ChunkTaskWork (context , this , true ))) {
9799 if (chunkSerializer .isPresent ()) {
98100 return chunkSerializer .get ().convert (
@@ -153,14 +155,17 @@ public CompletionStage<Void> upgradeToThis(ChunkLoadingContext context, Cancella
153155 }
154156
155157 @ Override
156- public CompletionStage < Void > downgradeFromThis (ChunkLoadingContext context , Cancellable cancellable ) {
158+ public Completable downgradeFromThis (ChunkLoadingContext context , Cancellable cancellable ) {
157159 final AtomicBoolean loadedToWorld = new AtomicBoolean (false );
158- return syncWithLightEngine (context ).thenApplyAsync (unused -> {
160+ return Completable .defer (() -> Completable .fromCompletionStage (syncWithLightEngine (context )))
161+ .observeOn (Schedulers .from (((IThreadedAnvilChunkStorage ) context .tacs ()).getMainThreadExecutor ()))
162+ .andThen (Completable .defer (() -> {
163+ Assertions .assertTrue (((IThreadedAnvilChunkStorage ) context .tacs ()).getMainThreadExecutor ().isOnThread ());
164+
159165 try (var ignored = ThreadInstrumentation .getCurrent ().begin (new ChunkTaskWork (context , this , false ))) {
160166 if (context .holder ().getTargetStatus ().ordinal () > this .ordinal ()) { // saving cancelled
161- // LOGGER.info("Cancelling unload of {}", context.holder().getKey());
162167 cancellable .cancel ();
163- return CompletableFuture .< Void > failedFuture (new CancellationException ());
168+ return Completable . error (new CancellationException ());
164169 }
165170 final ChunkState chunkState = context .holder ().getItem ().get ();
166171 Chunk chunk = chunkState .chunk ();
@@ -175,14 +180,14 @@ public CompletionStage<Void> downgradeFromThis(ChunkLoadingContext context, Canc
175180 LifecycleEventInvoker .invokeChunkUnload (((IThreadedAnvilChunkStorage ) context .tacs ()).getWorld (), worldChunk );
176181 }
177182
178- CompletionStage < Void > asyncSaveFuture ;
183+ Completable asyncSaveFuture ;
179184 if ((context .holder ().getFlags () & ItemHolder .FLAG_BROKEN ) != 0 && chunk instanceof ProtoChunk ) { // do not save broken ProtoChunks
180185 LOGGER .warn ("Not saving partially generated broken chunk {}" , context .holder ().getKey ());
181- asyncSaveFuture = CompletableFuture . completedStage (( Void ) null );
186+ asyncSaveFuture = Completable . complete ( );
182187 } else if (chunk instanceof WorldChunk && !chunkState .reachedStatus ().isAtLeast (ChunkStatus .FULL )) {
183188 // do not save WorldChunks that doesn't reach full status: Vanilla behavior
184189 // If saved, block entities will be lost
185- asyncSaveFuture = CompletableFuture . completedStage (( Void ) null );
190+ asyncSaveFuture = Completable . complete ( );
186191 } else {
187192 asyncSaveFuture = asyncSave (context , chunk );
188193 }
@@ -201,29 +206,30 @@ public CompletionStage<Void> downgradeFromThis(ChunkLoadingContext context, Canc
201206
202207 return asyncSaveFuture ;
203208 }
204- }, ((IThreadedAnvilChunkStorage ) context .tacs ()).getMainThreadExecutor ())
205- .thenCompose (Function .identity ());
209+ }));
206210 }
207211
208- private CompletionStage < Void > asyncSave (ChunkLoadingContext context , Chunk chunk ) {
212+ private Completable asyncSave (ChunkLoadingContext context , Chunk chunk ) {
209213 ((IThreadedAnvilChunkStorage ) context .tacs ()).getPointOfInterestStorage ().saveChunk (chunk .getPos ());
210214 if (!chunk .tryMarkSaved ()) {
211- return CompletableFuture . completedStage ( null );
215+ return Completable . complete ( );
212216 } else {
213217 ChunkPos chunkPos = chunk .getPos ();
214218
215219 SerializedChunk serializer = SerializedChunk .fromChunk (((IThreadedAnvilChunkStorage ) context .tacs ()).getWorld (), chunk );
216- return CompletableFuture .supplyAsync (() -> {
220+ return Single
221+ .<Either <NbtCompound , byte []>>fromCallable (() -> {
217222 try (var ignored = ThreadInstrumentation .getCurrent ().begin (new ChunkTaskWork (context , this , false ))) {
218223 return SerializerAccess .getSerializer ().serialize (serializer );
219224 }
220- }, GlobalExecutors .prioritizedScheduler .executor (16 ) /* boost priority as we are serializing an unloaded chunk */ )
221- .thenCompose ((either ) -> {
225+ })
226+ .subscribeOn (Schedulers .from (GlobalExecutors .prioritizedScheduler .executor (16 ) /* boost priority as we are serializing an unloaded chunk */ ))
227+ .flatMapCompletable (either -> {
222228 if (either .left ().isPresent ()) {
223229 NbtCompound nbtCompound = either .left ().get ();
224- return context .tacs ().setNbt (chunkPos , () -> nbtCompound );
230+ return Completable . fromCompletionStage ( context .tacs ().setNbt (chunkPos , () -> nbtCompound ) );
225231 } else {
226- return (( IDirectStorage ) ((IVersionedChunkStorage ) context .tacs ()).getWorker ()).setRawChunkData (chunkPos , either .right ().get ());
232+ return Completable . fromCompletionStage ((( IDirectStorage ) ((IVersionedChunkStorage ) context .tacs ()).getWorker ()).setRawChunkData (chunkPos , either .right ().get () ));
227233 }
228234 });
229235 }
0 commit comments