Big Reactors

Big Reactors

11M Downloads

Crash multiblock structure

Magiks21 opened this issue ยท 14 comments

commented

Found the crash issue before that was squashed in 0.3.0
(#98)

Seems to have returned in 0.4.1A2

Sorry if this is already fixed.
Used in FTB Infinity 1.7x v1.2.0

https://gist.github.com/Magiks21/be8bb88aea0292bbb749

commented

hmm i think i should have done it earlier :D.

commented

Yeah, I'll give it a shot. Is there a place to grab deobf/dev builds of TiCon?

commented

Yes, we have a public jenkins. This is the release version for 1.8.3b: https://dvs1.progwml6.com/jenkins/job/TConstruct_1.7.x/919/

commented

Any progress on this?

commented

Working on it now.

commented

Looks like this is my bug. The problem seems to be that the invalidate calls are evaluated on the server after tickEnd() but before tickBegin(). This leaves a one-tick race condition whereby a controller which shouldn't be ticked is ticked, which violates a bunch of runtime assumptions.

(a) You remove the entire top of the reactor, causing BR to look at the topmost block in the reactor's bounding box, grab a TE and try to cast it to a ControlRod.

(b) You break all the fuel rods.

It's going to take some digging to figure out how to solve this correctly. It might be as simple as doing all the recalculation logic in TickBegin instead of trying to be clever with TickBegin/TickEnd.

commented

Those are different callstacks, so they're different crashes.

This looks like the sort of thing which would occur if, somehow, you created a reactor with no fuel rods. Can you supply any information as to how this occurred?

commented

Interrogated users to get the info you needed.

Turned out someone used a hammer from TiC with a silk touch upgrade on it. harvested the area with the fuel rod. Maybe server timing sync fell out and tried to reassemble the multiblock without the fuel rod?

commented

Ah yes. Using a TIC hammer on a reactor is on the "don't do that" list. The TIC hammer's multi-block breaking seems to happen outside of the normal tick loop, so all sorts of stuff breaks, and there's pretty much nothing I can do to guard against it.

commented

To be exact tic breaks the additional blocks during the blockbreak of the original block. It's behaving exactly like vanilla, except it all happens within 1 call.

Is a callback missing that big reactors relies on for its multiblock logic? All appropriate callbacks and events should get called/fired.

commented

So, the call-chain works like this:

This will also mark the controller dirty, which will then (on the subsequent Server TickEnd call) revalidate the multiblock. Since the multiblock is inevitably now invalid, it will split apart and not run the MultiblockReactor::updateServer method, which is where the crash is emerging.

So what I'm wondering is:
(a) Is Invalidate getting called for all the blocks the TIC hammer is breaking?
(b) If so, then is the BlockBreak occurring after the server's TickEnd and before the server's next TickBegin calls? That would mean the controller is clean on TickEnd, has some blocks removed, and then is ticked in the subsequent TickBegin.

I thought all world modifications happened after TickBegin but before TickEnd, at least based on my observations when initially building BeefCore. (Maybe something moved around?)

commented

I am, for the most part, following this. However, I have a large server full of players wondering why they cannot use hammers (And possibly other items that cause large scale block breaking?) to disassemble their reactors (and maybe other multiblocks).

Would it be selfish of me to ask for help explaining it to them? The explanation I have currently I'm finding shaky at best. And I know pointing the general pop from my server to this ticket will just confuse them more.

commented

The easiest way to explain it is basically, "there's a bug in BR or a bug in TIC, not sure which at the moment, just don't do it."

commented

The hammer calls the same vanilla functions that a regular block break would also call, during the blockbreaking of the original block:

From that it should behave exactly as if the blocks were broken by a player one after another in the same tick.

Maybe you can put a breakpoint into the invalidate function and see if it's called for each block if you break it with a tinkers hammer?