Et Futurum Requiem

Et Futurum Requiem

105k Downloads

Server Crash - NullPointerException in ETFuturum when Generating Bee Nests with EnderIO Planter

Closed this issue · 27 comments

commented

Initial Questions

  • I have searched this issue tracker and there is nothing similar already, and this is not on the list of known issues. Posting on a closed issue saying the bug still exists will prompt us to investigate and reopen it once we confirm your report.
  • I have verified that this issue occurs in a SUPPORTED environment, meaning I can reproduce this WITHOUT OptiFine, and without Bukkit+Forge server software like KCauldron, Thermos, Crucible, Mohist etc

Mod Version

2.6.2

Describe the Issue

Bug Description:
When ETFuturum's bee nest generation is enabled alongside EnderIO's Farming Station, attempting to grow trees that spawn bee nests causes a server crash due to NullPointerException at WorldEventHandler.tryPlaceBeeNest:194. The crash occurs during world tick when the sapling growth event is processed.

Reproduction Steps:

  1. Enable B:enableBeetroot=true in ETFuturum config
  2. Configure EnderIO Farming Station to plant saplings
  3. Allow automatic tree growth with bee nest generation
  4. Server crashes immediately with stack trace

Relevant Configuration:

# ETFuturum Config
B:enableBeetroot=true

Conflicting Mods

Affected Mods & Versions:

  • Et Futurum Requiem: etfuturum-2.6.2
  • EnderIO: 2.9.2-GTNH
  • Minecraft Forge: 1664

Crash Report

Crash Log: [https://gist.github.com/Icetebe/8a8710ff84ec71b580ad08b10dd95f17] Critical stack trace excerpt: java 复制 java.lang.NullPointerException: Exception ticking world at ganymedes01.etfuturum.core.handlers.WorldEventHandler.tryPlaceBeeNest(WorldEventHandler.java:194) at ganymedes01.etfuturum.core.handlers.WorldEventHandler.onSaplingGrow(WorldEventHandler.java:125) ... [remaining stack trace]

Other Details

No response

commented

Thanks for the extra info. Mind sending the whole crash report and not just a slice of it?

commented

Thanks for the extra info. Mind sending the whole crash report and not just a slice of it?

https://gist.github.com/Icetebe/a9803523584a6723c801830a1367af90

commented

Try Crucible instead of Uranium. Once again, please do not lie in your bug report.

I have tested the issue on a server and could not reproduce it. If the issue still happens after using Crucible, report it to them.

commented

Try Crucible instead of Uranium. Once again, please do not lie in your bug report.

I have tested the issue on a server and could not reproduce it. If the issue still happens after using Crucible, report it to them.

I am using an advanced hybrid server, and it feels like the crashes are not related to the server core. It is clearly a conflict between mod functionalities.

commented

Did you try without the hybrid server software?

commented

Did you try without the hybrid server software?

The crash incident (possibly a conflict arising from the Ender IO Farming Station generating an oak tree simultaneously with a bee hive) occurs probabilistically. It happens approximately 3 to 4 times a day during player sessions, but not consistently. If I were to switch to a different server for testing, other errors might emerge, and it would require some time. I am willing to give it a try.

commented

I didn't close this issue because I still have the benefit of the doubt it isn't the hybrid server software, since you have many other mods. Please let me know if you can reproduce the issue otherwise, since I couldn't.

commented

I didn't close this issue because I still have the benefit of the doubt it isn't the hybrid server software, since you have many other mods. Please let me know if you can reproduce the issue otherwise, since I couldn't.

After switching to the Crucible server core, I am unable to start the server. Unfortunately, I cannot reproduce the issue with other server cores.

commented

That might mean the Uranium server core is the issue. At the moment, since the issue is random, I'll leave it open, and test more later.

I've been meaning to get around to make the unsupported mods tick box not required, so I'll still leave this open for documentation purposes.

commented

I have faced the same issue, to be honest, have faced it like in around 19/03/2024

The bug is something that 'should not happen', but it does :/

Its random, very rare, i reopened my server for like 5 days, happened only once.

CrashReport Stacktrace
Time: 3/11/25, 8:37 PM
Description: Exception ticking world

java.lang.NullPointerException: Cannot invoke "ganymedes01.etfuturum.tileentities.TileEntityBeeHive.maxHiveSize()" because "hive" is null
  at ganymedes01.etfuturum.core.handlers.WorldEventHandler.tryPlaceBeeNest(WorldEventHandler.java:194)
  at ganymedes01.etfuturum.core.handlers.WorldEventHandler.onSaplingGrow(WorldEventHandler.java:125)
  at cpw.mods.fml.common.eventhandler.ASMEventHandler_677_WorldEventHandler_onSaplingGrow_SaplingGrowTreeEvent.invoke(.dynamic)
  at cpw.mods.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:54)
  at cpw.mods.fml.common.eventhandler.EventBus.post(EventBus.java:168)
  at net.minecraftforge.event.terraingen.TerrainGen.saplingGrowTree(TerrainGen.java:57)
  at net.minecraft.block.BlockSapling.func_149878_d(BlockSapling.java:113)
  at net.minecraft.block.BlockSapling.func_149879_c(BlockSapling.java:107)
  at net.minecraft.block.BlockSapling.func_149674_a(BlockSapling.java:57)
  at com.github.terminatornl.tiquality.tracking.tickexecutors.ForgeTickExecutor.onBlockTick(ForgeTickExecutor.java:19)
  at com.github.terminatornl.tiquality.tracking.TrackerBase.doBlockTick(TrackerBase.java:374)
  at com.github.terminatornl.tiquality.tracking.TickHub.onBlockTick(TickHub.java:23)
  at net.minecraft.world.WorldServer.redirect$zzh000$tiquality$onRandomBlockTick(WorldServer.java:2023)
  at net.minecraft.world.WorldServer.func_147456_g(WorldServer.java:564)
  at net.minecraft.world.WorldServer.func_72835_b(WorldServer.java:283)
  at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:966)
  at net.minecraft.server.dedicated.DedicatedServer.func_71190_q(DedicatedServer.java:462)
  at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:845)
  at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:695)
  at java.base/java.lang.Thread.run(Thread.java:1583)

Somehow it seems the setBlock fails to create the tile entity and then its null.
It was tested on Crucible latest staging build (and as the same error happened more than a year ago, can be an inconpatibility with any part.

Even though i do not feel satisfied with just adding a null-check, its what i have done for my modpack.
I will not open a pull-request with a partial-fix, but for my server this is what i have done:

Image

7dd6742

Image

commented

Both reproduction cases have been confirmed on hybrid server software. I am now more suspicious this is caused by hybrid server software and would not happen in vanilla. I see you are a dev, though, so would you be able to look at the function that sets the tile entity and see if there are any major differences in Forge vs Crucible, that could cause the tile entity to not be created?

I have had the idea to allow a server on vanilla to run overnight with many planters running, I will do this a few times and if I cannot get it to happen, I will strongly believe this is a Crucible issue.

commented

Sure, i can take a look.

Cauldron has a specific logic for sapplings, maybe its causing the issue here

Image

I don't undestand it yet though. Gona take a look

commented

Yes, basically is because of that.
When SaplingGrowTreeEvent is fired, that captureTreeGeneration is on.

And when the captureTreeGeneration is on, no tiles are created, thats why there is no tile for that block.

This is not a bug on Thermos itself, but the logic of bukkit implementation, given that happened on Paper as well.

https://git.moe.team/OpenSource/PaperMC/commit/6515ea4957c5ebc8b88e3f7581a8a4dbb55fecb1?style=split&whitespace=show-all&show-outdated=

I'm gonna take a look on their fix and try to apply on Crucible directly! (Maybe)

On paper, their fix was to manually check if the block generated was not a bee nest '-'

Image

commented

The why this happens is because Bukkit needs to fire the StructureGrowEvent, and to cancel that event, no tiles could have been created.

So, to support any hybrid, the tile should only be checked after the bukkit event, so, in this case, the easier approach would be:

if (BukkitCompat.isHybrid()) {
  placeTheBlock()
   
  wait 1 tick {
    getBlockAtLocationToSeeIfItsStillThere()
    populateTheTileWithBees()
  }

}else {
  placeTheBlock()
  populateTheTileWithBeens()
}

If you want i can test the solution and create the pull-request

commented

I don't like the idea of scheduling the code to write a one tick delay, I will think of something else.

commented

Why not just cancel the Forge event itself (mixin to where the event itself is fired and cancel it there to be 100% sure it precedes any mod event)

The entire reason this happens is because the event fires when it shouldn't. Instead of the blocks being placed and then immediately erased, they shouldn't have been generated at all; this seems like a way too roundabout way for the hybrid to cancel the event. Forge just doesn't run the code, so why not make Bukkit do the same?

commented

[1]-
SaplingGrowTreeEvent is not cancelable!
Its an instruction event. It tells mods that ''hey, a sappling generated a tree, now do your thing''
So there is no way to cancel the SaplingGrowTreeEvent.

[2]-
That is not true on the Bukkit version of the event! Bukkit has the StructureGrowEvent that is cancelable.

[3]-
So, the problem is, we have a forge event that has no cancel logic, that will define 'create a block here, here and here'
(The SaplingGrowTreeEvent on forge already sets the blocks, but on hybrid, it create 'BlockSnapshots', that is the why there is not tile at the given time, when inside the captureTreeGeneration, all blocks that are set on the world are just VirtualBlocks.

[4] -
So, following the logic:
1- SaplingGrowTreeEvent is fired
2- Mods try to set blocks on worlds, hybrid blocks these operations and create VirtualBlocks
3- Hybrid send these VirtualBlocks to the bukkit event StructureGrowEvent
4- If the StructureGrowEvent is cancelaed, its all okay, because only VirtualBlocks were created,
5- if StructureGrowEvent is not cancealed, hybrid place these VirtualBlocks on the world (only then creating the tiles)

commented

PostTreeGenerateEvent is not cancelable!

PostTreeGenerateEvent is custom, not in forge. Additionally, this only fires for natural trees and not sapling trees, so it is not relevant. You shouldn't have to worry about my custom event because it's not really relevant to this issue. If my custom event can also trigger the issue, then I will fix the custom event on my end.

This happens with the sapling event. I also suggested doing it with mixins (you could do it with your patches but I don't recommend adding more patches if you can help it) so the cancelability of the event is not really relevant because patching it out, it wouldn't even fire.

My idea is basically doing this collection of blocks shouldn't be necessary. Unless that information is used in any other crucial way. This seems like a fragile and roundabout behavior for the event succeeding.

commented

My bad, it was not PostTreeGenerateEvent, it was SaplingGrowTreeEvent!

gonna fix my text

commented

Hybrids try to respect both FORGE and Bukkit, to respect Bukkit, when fireing the StructureGrowEvent it must already have all blocks that will be placed on the world.

That is not possible without fireing the SaplingGrowTreeEvent

Hybrid will:
1- Fire SaplingGrowTreeEvent on FORGE to gather information of the blocks that will be spawned.
2- Fire StructureGrowEvent on BUKKIT to know if should proceed

commented

I don't think you are seeing my point, and not firing the event when the sapling isn't supposed to actually grow still respects the event.

Why collect the blocks that will generate if that information is only used to place them where they belong on event success?

I don't think it's disrespectful to forge to not fire an event that's not being used. It's certainly better than using a hacky list that breaks mods. If the event isn't supposed to be fired then I don't need it.

The event not giving me fake blocks and the tile entity being 100% placed are both expected vanilla behaviors, breaking them certainly is not respecting Forge

commented

[1] - Your code is correct, is follwing FORGE pattern. So if you intedend to keep support only for forge, its perftly fine, there is no error on your logic! On forge, the blocks must exist at the exact moment they are placed.

[2] -

Why collect the blocks that will generate if that information is only used to place them where they belong on event success?

Because BUKKIT needs that. Its Bukkit pattern, check their api on latest minecraft version over here

Check Bukkit API here: JavaDoc https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/world/StructureGrowEvent.html

Image

[3] - Is not a question of ONLY BEING a 'expected vanilla behaviors', its a question of: by respecting FORGE's behavior, it will never be compatible with Spigot. ITs a tradeoff situation.

I think a more suitable way to fix the compatibility issue might be inside Hodgepodge as it already has some specific fixes that are directed for hybrids, and in case other mods needs the same thing, the fixes would be consolidated in one place.

I was wrong, can be fixed on Crucible with some rework!

commented

My final say on the matter is that really you shouldn't be firing the event. When the event is fired, it's expected that a tree will be there. Since there's no tree there, mods will of course break. I can't be the only one.

If you believe this is unfixable, then I guess it will just be unfixable.

commented

Gonna give a try on inverting the event order on forge and see what happens

commented

I wouldn't mind helping whenever I get the chance. It may be a while before I can, though. And it seems like the setup of crew-sable is a bit special. Last I checked, it requires Linux, but that's good because I do almost everything on Linux anyways.

Just curious, why did that used to be a requirement?

commented

Doing a quick look right now and this one is both a simple fix but also a bit complex edge case. Cauldron is making use of BlockSnapshot and redirecting world get/set block during sappling generation, so far so good, however that snapshot system sucks and is slow (it loops through all snapshots during getblock instead of at least using a long hash map for quick fetch) and does not account for tile entities. I'll make some changes to have block snapshots hold the block entity as well and remove that ugly for loop.

commented

Just curious, why did that used to be a requirement?

Forge gradle, decompilation varies from system to system, and it was all random, now it should be stable and work anywhere, even on windows.