11package dev .compactmods .gander .level ;
22
33import java .util .List ;
4+ import java .util .Set ;
45import java .util .function .Supplier ;
56
7+ import it .unimi .dsi .fastutil .longs .LongArraySet ;
8+ import it .unimi .dsi .fastutil .longs .LongOpenHashSet ;
9+
10+ import org .apache .logging .log4j .LogManager ;
11+ import org .apache .logging .log4j .Logger ;
612import org .jetbrains .annotations .NotNull ;
713import org .jetbrains .annotations .Nullable ;
814
5460
5561public class VirtualLevel extends Level implements WorldGenLevel , TickingLevel {
5662
63+ private static Logger LOGS = LogManager .getLogger ();
64+
5765 // private final TickRateManager tickManager = new TickRateManager();
5866 private final RegistryAccess access ;
5967 private final VirtualChunkSource chunkSource ;
@@ -62,6 +70,7 @@ public class VirtualLevel extends Level implements WorldGenLevel, TickingLevel {
6270 private BoundingBox bounds ;
6371 private VirtualEntitySystem entities ;
6472 private final Holder <Biome > biome ;
73+ private final Set <Long > erroredTickingEntities ;
6574
6675 public VirtualLevel (RegistryAccess access ) {
6776 this (
@@ -84,6 +93,7 @@ private VirtualLevel(WritableLevelData pLevelData, ResourceKey<Level> pDimension
8493 this .bounds = BoundingBox .fromCorners (BlockPos .ZERO , BlockPos .ZERO );
8594 this .entities = new VirtualEntitySystem ();
8695 this .biome = pRegistryAccess .registryOrThrow (Registries .BIOME ).getHolderOrThrow (Biomes .PLAINS );
96+ this .erroredTickingEntities = new LongArraySet ();
8797 }
8898
8999 public Holder <Biome > getBiome () {
@@ -177,21 +187,30 @@ public void tick(final float deltaTime) {
177187 }
178188
179189 protected void animateBlockTick (BlockPos pBlockPos ) {
180- BlockState blockstate = this .getBlockState (pBlockPos );
181- blockstate .getBlock ().animateTick (blockstate , this , pBlockPos , random );
182- FluidState fluidstate = this .getFluidState (pBlockPos );
183- if (!fluidstate .isEmpty ()) {
184- fluidstate .animateTick (this , pBlockPos , random );
190+ if (erroredTickingEntities .contains (pBlockPos .asLong ()))
191+ return ;
192+
193+ try {
194+ BlockState blockstate = this .getBlockState (pBlockPos );
195+ blockstate .getBlock ().animateTick (blockstate , this , pBlockPos , random );
196+ FluidState fluidstate = this .getFluidState (pBlockPos );
197+ if (!fluidstate .isEmpty ()) {
198+ fluidstate .animateTick (this , pBlockPos , random );
199+ }
200+
201+ if (!blockstate .isCollisionShapeFullBlock (this , pBlockPos )) {
202+ this .getBiome (pBlockPos )
203+ .value ()
204+ .getAmbientParticle ()
205+ .filter (aps -> aps .canSpawn (random ))
206+ .ifPresent ((p_264703_ ) -> {
207+ this .addParticle (p_264703_ .getOptions (), (double ) pBlockPos .getX () + this .random .nextDouble (), (double ) pBlockPos .getY () + this .random .nextDouble (), (double ) pBlockPos .getZ () + this .random .nextDouble (), 0.0D , 0.0D , 0.0D );
208+ });
209+ }
185210 }
186211
187- if (!blockstate .isCollisionShapeFullBlock (this , pBlockPos )) {
188- this .getBiome (pBlockPos )
189- .value ()
190- .getAmbientParticle ()
191- .filter (aps -> aps .canSpawn (random ))
192- .ifPresent ((p_264703_ ) -> {
193- this .addParticle (p_264703_ .getOptions (), (double ) pBlockPos .getX () + this .random .nextDouble (), (double ) pBlockPos .getY () + this .random .nextDouble (), (double ) pBlockPos .getZ () + this .random .nextDouble (), 0.0D , 0.0D , 0.0D );
194- });
212+ catch (Exception e ) {
213+ erroredTickingEntities .add (pBlockPos .asLong ());
195214 }
196215 }
197216
@@ -206,14 +225,24 @@ protected void tickBlockEntities() {
206225 var ticker = blocks .blockAndFluidStorage ().getBlockState (entityPos ).getTicker (this , blockEntity .getType ());
207226
208227 if (ticker != null )
209- tickBlockEntity (blockEntity , (BlockEntityTicker <BlockEntity >) ticker );
228+ tickBlockEntity (entityPos . asLong (), blockEntity , (BlockEntityTicker <BlockEntity >) ticker );
210229 }
211230 });
212231 }
213232 }
214233
215- private <T extends BlockEntity > void tickBlockEntity (T blockEntity , BlockEntityTicker <T > ticker ) {
216- ticker .tick (this , blockEntity .getBlockPos (), blockEntity .getBlockState (), blockEntity );
234+ private <T extends BlockEntity > void tickBlockEntity (long blockPos , T blockEntity , BlockEntityTicker <T > ticker ) {
235+ if (erroredTickingEntities .contains (blockPos ))
236+ return ;
237+
238+ try {
239+ ticker .tick (this , blockEntity .getBlockPos (), blockEntity .getBlockState (), blockEntity );
240+ } catch (Exception e ) {
241+ erroredTickingEntities .add (blockPos );
242+ LOGS .atFatal ()
243+ .withThrowable (e )
244+ .log ("Failed to tick block entity! Marking the ticker as errored so this does not spam. Source: {}" , blockEntity .getClass ().getSimpleName ());
245+ }
217246 }
218247
219248 @ Override
0 commit comments