3333import net .minecraft .world .level .BlockEventData ;
3434import net .minecraft .world .level .block .Block ;
3535import net .minecraft .world .level .block .entity .BlockEntity ;
36- import net .minecraft .world .level .block .entity .TickingBlockEntity ;
3736import net .minecraft .world .level .material .FluidState ;
3837import org .apache .logging .log4j .Level ;
3938import org .apache .logging .log4j .Marker ;
5150import org .spongepowered .api .world .BlockChangeFlags ;
5251import org .spongepowered .api .world .LocatableBlock ;
5352import org .spongepowered .common .SpongeCommon ;
54- import org .spongepowered .common .accessor .world .level .chunk .LevelChunk$BoundTickingBlockEntityAccessor ;
55- import org .spongepowered .common .accessor .world .level .chunk .LevelChunk$RebindableTickingBlockEntityWrapperAccessor ;
56- import org .spongepowered .common .accessor .world .level .chunk .LevelChunkAccessor ;
5753import org .spongepowered .common .block .SpongeBlockSnapshot ;
5854import org .spongepowered .common .bridge .CreatorTrackedBridge ;
5955import org .spongepowered .common .bridge .TrackableBridge ;
6056import org .spongepowered .common .bridge .world .TrackedWorldBridge ;
6157import org .spongepowered .common .bridge .world .inventory .ViewableInventoryBridge ;
6258import org .spongepowered .common .bridge .world .level .TrackableBlockEventDataBridge ;
63- import org .spongepowered .common .bridge .world .level .block .entity .BlockEntityBridge ;
64- import org .spongepowered .common .bridge .world .level .chunk .ActiveChunkReferantBridge ;
6559import org .spongepowered .common .bridge .world .level .chunk .LevelChunkBridge ;
66- import org .spongepowered .common .bridge .world .level .chunk .TrackedLevelChunkBridge ;
6760import org .spongepowered .common .entity .PlayerTracker ;
6861import org .spongepowered .common .event .ShouldFire ;
6962import org .spongepowered .common .event .SpongeCommonEventFactory ;
8578import java .util .Optional ;
8679import java .util .Set ;
8780import java .util .UUID ;
88- import java .util .function .Consumer ;
81+ import java .util .function .BooleanSupplier ;
8982import java .util .function .Supplier ;
9083
9184/**
@@ -103,7 +96,7 @@ public final class TrackingUtil {
10396
10497 public static final int WIDTH = 40 ;
10598
106- public static void tickEntity (final Consumer < net .minecraft .world .entity .Entity > consumer , final net . minecraft . world . entity . Entity entity ) {
99+ public static void tickEntity (final net .minecraft .world .entity .Entity entity , final Runnable tick ) {
107100 Preconditions .checkArgument (entity instanceof Entity , () -> String .format ("Entity %s is not an instance of SpongeAPI's Entity!" , entity ));
108101 Objects .requireNonNull (entity , "Cannot capture on a null ticking entity!" );
109102 if (!((TrackableBridge ) entity ).bridge$shouldTick ()) {
@@ -112,13 +105,13 @@ public static void tickEntity(final Consumer<net.minecraft.world.entity.Entity>
112105
113106 final EntityTickContext tickContext = TickPhase .Tick .ENTITY .createPhaseContext (PhaseTracker .SERVER ).source (entity );
114107 try (final EntityTickContext context = tickContext ) {
115- if (entity instanceof CreatorTrackedBridge ) {
116- (( CreatorTrackedBridge ) entity ) .tracker$getNotifierUUID ().ifPresent (context ::notifier );
117- (( CreatorTrackedBridge ) entity ) .tracker$getCreatorUUID ().ifPresent (context ::creator );
108+ if (entity instanceof CreatorTrackedBridge ctb ) {
109+ ctb .tracker$getNotifierUUID ().ifPresent (context ::notifier );
110+ ctb .tracker$getCreatorUUID ().ifPresent (context ::creator );
118111 }
119112 context .buildAndSwitch ();
120113 PhaseTracker .LOGGER .trace (TrackingUtil .ENTITY_TICK , () -> "Wrapping Entity Tick: " + entity .toString ());
121- consumer . accept ( entity );
114+ tick . run ( );
122115 if (ShouldFire .MOVE_ENTITY_EVENT ) {
123116 SpongeCommonEventFactory .callNaturalMoveEntityEvent (entity );
124117 }
@@ -130,78 +123,50 @@ public static void tickEntity(final Consumer<net.minecraft.world.entity.Entity>
130123 }
131124 }
132125
133- private static Optional <net .minecraft .world .level .block .entity .BlockEntity > getTickingBlockEntity (
134- final TickingBlockEntity ticker ) {
135- if (ticker instanceof LevelChunk$BoundTickingBlockEntityAccessor beAccessor ) {
136- return Optional .of (beAccessor .accessor$blockEntity ());
137- } else if (ticker instanceof LevelChunk$RebindableTickingBlockEntityWrapperAccessor beAccessor ) {
138- return getTickingBlockEntity (beAccessor .accessor$ticker ());
139- } else if (ticker == LevelChunkAccessor .accessor$NULL_TICKER ()) {
140- return Optional .empty ();
141- }
142- return Optional .empty ();
143- }
144-
145126 @ SuppressWarnings ({"unused" , "try" })
146- public static void tickTileEntity (final TrackedWorldBridge mixinWorldServer , final TickingBlockEntity tile ) {
147- Objects .requireNonNull (tile , "Cannot capture on a null ticking tile entity!" );
148- final Optional <BlockEntity > tickingBlockEntity = getTickingBlockEntity (tile );
149- if (!tickingBlockEntity .isPresent ()) {
150- return ;
151- }
152- final net .minecraft .world .level .block .entity .BlockEntity blockEntity = tickingBlockEntity .get ();
127+ public static void tickTileEntity (final BlockEntity blockEntity , final Runnable tick ) {
128+ Objects .requireNonNull (blockEntity , "Cannot capture on a null ticking tile entity!" );
153129 if (!((org .spongepowered .api .block .entity .BlockEntity ) blockEntity ).isTicking ()) {
154130 return ;
155131 }
156- final BlockEntityBridge mixinTileEntity = (BlockEntityBridge ) tickingBlockEntity .get ();
157- final BlockPos pos = blockEntity .getBlockPos ();
158- final @ Nullable LevelChunkBridge chunk = ((ActiveChunkReferantBridge ) blockEntity ).bridge$getActiveChunk ();
159132 if (!((TrackableBridge ) blockEntity ).bridge$shouldTick ()) {
160133 return ;
161134 }
162- if (chunk == null ) {
163- ((ActiveChunkReferantBridge ) blockEntity ).bridge$setActiveChunk ((TrackedLevelChunkBridge ) blockEntity .getLevel ().getChunkAt (blockEntity .getBlockPos ()));
164- }
165135
166- final TileEntityTickContext context = TickPhase .Tick .TILE_ENTITY .createPhaseContext (PhaseTracker .SERVER ).source (mixinTileEntity );
136+ final TileEntityTickContext context = TickPhase .Tick .TILE_ENTITY .createPhaseContext (PhaseTracker .SERVER ).source (blockEntity );
167137 try (final PhaseContext <@ NonNull ?> phaseContext = context ) {
168-
169- if (blockEntity instanceof CreatorTrackedBridge ) {
138+ if (blockEntity instanceof CreatorTrackedBridge ctb ) {
170139 // Add notifier and owner so we don't have to perform lookups during the phases and other processing
171- (( CreatorTrackedBridge ) blockEntity ) .tracker$getNotifierUUID ().ifPresent (phaseContext ::notifier );
140+ ctb .tracker$getNotifierUUID ().ifPresent (phaseContext ::notifier );
172141 // Allow the tile entity to validate the owner of itself. As long as the tile entity
173142 // chunk is already loaded and activated, and the tile entity has already loaded
174143 // the owner of itself.
175- (( CreatorTrackedBridge ) blockEntity ) .tracker$getCreatorUUID ().ifPresent (phaseContext ::creator );
144+ ctb .tracker$getCreatorUUID ().ifPresent (phaseContext ::creator );
176145 }
177146
178147 // Finally, switch the context now that we have the owner and notifier
179148 phaseContext .buildAndSwitch ();
180149
181- PhaseTracker .LOGGER .trace (TrackingUtil .BLOCK_ENTITY_TICK , () -> "Wrapping Entity Tick: " + tile . toString () );
182- tile . tick ();
150+ PhaseTracker .LOGGER .trace (TrackingUtil .BLOCK_ENTITY_TICK , () -> "Wrapping Entity Tick: " + blockEntity );
151+ tick . run ();
183152
184153 // If we know the viewers force broadcast now to associate the inventory change with its blockentity
185154 // otherwise the viewing players update this during their ticking
186- if (blockEntity instanceof ViewableInventoryBridge ) {
187- final Set <ServerPlayer > players = (( ViewableInventoryBridge ) blockEntity ) .viewableBridge$getViewers ();
188- if (players .size () > 0 ) {
155+ if (blockEntity instanceof ViewableInventoryBridge vib ) {
156+ final Set <ServerPlayer > players = vib .viewableBridge$getViewers ();
157+ if (! players .isEmpty () ) {
189158 players .forEach (player -> player .containerMenu .broadcastChanges ());
190159 }
191160 }
192161
193162 } catch (final Exception e ) {
194163 PhasePrinter .printExceptionFromPhase (PhaseTracker .getInstance ().stack , e , context );
195164 }
196- // We delay clearing active chunk if TE is invalidated during tick so we must remove it after
197- if (blockEntity .isRemoved ()) {
198- ((ActiveChunkReferantBridge ) blockEntity ).bridge$setActiveChunk (null );
199- }
200165 }
201166
202- @ SuppressWarnings ("rawtypes" )
203167 public static void updateTickBlock (
204- final TrackedWorldBridge mixinWorld , final net .minecraft .world .level .block .state .BlockState block , final BlockPos pos , final RandomSource random ) {
168+ final TrackedWorldBridge mixinWorld , final net .minecraft .world .level .block .state .BlockState block ,
169+ final BlockPos pos , final Runnable tick ) {
205170 final ServerLevel world = (ServerLevel ) mixinWorld ;
206171 final org .spongepowered .api .world .server .ServerWorld apiWorld = (org .spongepowered .api .world .server .ServerWorld ) world ;
207172
@@ -225,15 +190,15 @@ public static void updateTickBlock(
225190 try (final PhaseContext <@ NonNull ?> context = phaseContext ) {
226191 context .buildAndSwitch ();
227192 PhaseTracker .LOGGER .trace (TrackingUtil .BLOCK_TICK , () -> "Wrapping Block Tick: " + block .toString ());
228- block . tick ( world , pos , random );
193+ tick . run ( );
229194 } catch (final Exception | NoClassDefFoundError e ) {
230195 PhasePrinter .printExceptionFromPhase (PhaseTracker .getInstance ().stack , e , phaseContext );
231196
232197 }
233198 }
234199
235200 public static void updateTickFluid (
236- final TrackedWorldBridge mixinWorld , final FluidState fluidState , final BlockPos pos
201+ final TrackedWorldBridge mixinWorld , final FluidState fluidState , final BlockPos pos , final Runnable tick
237202 ) {
238203 final ServerLevel world = (ServerLevel ) mixinWorld ;
239204 final org .spongepowered .api .world .server .ServerWorld apiWorld = (org .spongepowered .api .world .server .ServerWorld ) world ;
@@ -261,16 +226,18 @@ public static void updateTickFluid(
261226 try (final PhaseContext <?> context = phaseContext ) {
262227 context .buildAndSwitch ();
263228 PhaseTracker .LOGGER .trace (TrackingUtil .FLUID_TICK , () -> "Wrapping Fluid Tick: " + fluidState .toString ());
264- fluidState . tick ( world , pos );
229+ tick . run ( );
265230 } catch (final Exception | NoClassDefFoundError e ) {
266231 PhasePrinter .printExceptionFromPhase (PhaseTracker .getInstance ().stack , e , phaseContext );
267232
268233 }
269234 }
270235
271236 @ SuppressWarnings ("rawtypes" )
272- public static void randomTickBlock (final TrackedWorldBridge mixinWorld ,
273- final net .minecraft .world .level .block .state .BlockState state , final BlockPos pos , final RandomSource random ) {
237+ public static void randomTickBlock (
238+ final TrackedWorldBridge mixinWorld , final net .minecraft .world .level .block .state .BlockState state ,
239+ final BlockPos pos , final RandomSource random , final Runnable tick
240+ ) {
274241 final ServerLevel world = (ServerLevel ) mixinWorld ;
275242 final org .spongepowered .api .world .server .ServerWorld apiWorld = (org .spongepowered .api .world .server .ServerWorld ) world ;
276243
@@ -299,14 +266,17 @@ public static void randomTickBlock(final TrackedWorldBridge mixinWorld,
299266 try (final PhaseContext <@ NonNull ?> context = phaseContext ) {
300267 context .buildAndSwitch ();
301268 PhaseTracker .LOGGER .trace (TrackingUtil .BLOCK_TICK , "Wrapping Random Block Tick: {}" , state );
302- state . randomTick ( world , pos , random );
269+ tick . run ( );
303270 } catch (final Exception | NoClassDefFoundError e ) {
304271 PhasePrinter .printExceptionFromPhase (PhaseTracker .getInstance ().stack , e , phaseContext );
305272 }
306273 }
307274 @ SuppressWarnings ("rawtypes" )
308- public static void randomTickFluid (final TrackedWorldBridge mixinWorld ,
309- final FluidState state , final BlockPos pos , final RandomSource random ) {
275+ public static void randomTickFluid (
276+ final TrackedWorldBridge mixinWorld ,
277+ final FluidState state , final BlockPos pos , final RandomSource random ,
278+ final Runnable tick
279+ ) {
310280 final ServerLevel world = (ServerLevel ) mixinWorld ;
311281 final org .spongepowered .api .world .server .ServerWorld apiWorld = (org .spongepowered .api .world .server .ServerWorld ) world ;
312282
@@ -338,20 +308,20 @@ public static void randomTickFluid(final TrackedWorldBridge mixinWorld,
338308 try (final PhaseContext <@ NonNull ?> context = phaseContext ) {
339309 context .buildAndSwitch ();
340310 PhaseTracker .LOGGER .trace (TrackingUtil .FLUID_TICK , () -> "Wrapping Random Fluid Tick: " + state .toString ());
341- state . randomTick ( world , pos , random );
311+ tick . run ( );
342312 } catch (final Exception | NoClassDefFoundError e ) {
343313 PhasePrinter .printExceptionFromPhase (PhaseTracker .getInstance ().stack , e , phaseContext );
344314 }
345315 }
346316
347- public static boolean fireMinecraftBlockEvent (final ServerLevel worldIn , final BlockEventData event ,
348- final net . minecraft . world . level . block . state . BlockState currentState
317+ public static boolean fireMinecraftBlockEvent (
318+ final BlockEventData event , final BooleanSupplier tick
349319 ) {
350320 final TrackableBlockEventDataBridge blockEvent = (TrackableBlockEventDataBridge ) (Object ) event ;
351321 final @ Nullable Object source = blockEvent .bridge$getTileEntity () != null ? blockEvent .bridge$getTileEntity () : blockEvent .bridge$getTickingLocatable ();
352322 if (source == null ) {
353323 // No source present which means we are ignoring the phase state
354- return currentState . triggerEvent ( worldIn , event . pos (), event . paramA (), event . paramB () );
324+ return tick . getAsBoolean ( );
355325 }
356326 final BlockEventTickContext phaseContext = TickPhase .Tick .BLOCK_EVENT .createPhaseContext (PhaseTracker .SERVER );
357327 phaseContext .source (source );
@@ -365,7 +335,7 @@ public static boolean fireMinecraftBlockEvent(final ServerLevel worldIn, final B
365335 boolean result = true ;
366336 try (final BlockEventTickContext o = phaseContext ) {
367337 o .buildAndSwitch ();
368- phaseContext .setEventSucceeded (currentState . triggerEvent ( worldIn , event . pos (), event . paramA (), event . paramB () ));
338+ phaseContext .setEventSucceeded (tick . getAsBoolean ( ));
369339 // We need to grab the result here as the phase context close will trigger a reset
370340 result = phaseContext .wasNotCancelled ();
371341 } // We can't return onBlockEventReceived because the phase state may have cancelled all transactions
0 commit comments