Railcraft

Railcraft

34M Downloads

Funky Locomotion / World Anchors (interaction)

therealpygon opened this issue ยท 17 comments

commented

World Anchors continuously add additional force loaded chunks when moved by Funky Locomotion, but do not allow the older force loaded chunks no longer in range to unload.

Railcraft_1.7.10-9.4.0.0.jar
funky-locomotion-1.7.10-beta-3.jar

commented

A single World Anchor keeps the thing loaded just fine, and it's not really an issue of block updates. It's a FL-RC mod interaction that causes old chunks to not unload, which makes Forge cranky.

We haven't found a workaround so far, other than to use cart-based World Anchors. (However, this doesn't work for my particular case, since it has other, unrelated issues with frame machines: namely, clipping through the machine itself and falling into the abyss when it moves. That's just how all entities are, unfortunately, and is not RC's fault at all.)

commented

I'll take your word for it. I can only say that I replicated that chunks loaded by World Anchors would not unload when moved by Funky Locomotion (in fact, I seemed to reach a limit where no more chunks could be force-loaded), while ChickenChunks loader had no issue releasing/unloading while being moved. I would have assumed that the underlying force-loading/unloading mechanics of Forge would be the same in both cases, but I don't have much modding experience.

commented

Unlikely, they release their tickets when moved (invalidated). Its then up to the Forge Chunkloader Manager to clean up after the released ticket.

If that's not happening, you'll need to take it to Forge.

commented

No, ChickenChunks is filled with questionable hacks that override default Forge behavior.

commented

Also, its known that the Cauldron version of the Chunk Manager is horrible broken if that is relevant.

commented

I can verify this issue: after running a Funky Locomotion machine with a world anchor on it in a straight line for a while, the world anchor shuts off and I receive this error on the server console:

[13:59:11] [Server thread/INFO] [FML]: The mod Railcraft has attempted to allocate a chunkloading ticket beyond it's currently allocated maximum : 200

This is in creative single-player mode, and I'm not running Cauldron. Forge version is fairly recent, 1291. I have not personally tested ChickenChunks in this scenario, however.

I would greatly appreciate any progress on this issue, whether here or from the Forge guys, since World Anchor carts (or carts in general) don't play nice with Funky Locomotion (particularly in the face of server reboots). A pure World Anchor solution would be preferable.

commented

couldn't it just be that funky locomotion isn't calling the invalidate function? it even has an api where almost non of it's functions even get called so i wouldn't be suprised if this would be the cause of the issue

commented

The Anchors should only be able to have a single ticket at a time. So unless Funky Locomotion does something exceedingly odd, like recreate the tile entity on move without invalidating the old one, then it shouldn't be possible to have danglers. Anyway, Anchors worked fine with Redpower Frames and were tested extensively with them. Any issues are likely with Funky Locomotion's handling of Tile Entities.

commented

A suggestion would be to recreate your issue at https://github.com/rwtema/FunkyLocomotion and reference this issue.

commented

I dug around in the RailCraft, Chicken Chunks, and Funky Locomotion codes, and noticed a few things that may help. For reference, here are the files I've found to be interesting:

As near as I can tell, FL moves a TileEntity as follows (a more experienced modder's confirmation would be great here):

  1. DefaultMoveFactory.java:destroyBlock(): saves the TileEntity to NBT data, then clears the block in the chunk
  2. MoveManager.java:line 160: calls world.removeTileEntity() to remove the actual TileEntity
  3. Later, DefaultMoveFactory.java:recreateBlock(): recreates the TileEntity via DefaultMoveFactory:loadTile(), which calls TileEntity.createAndLoadEntity(tileTagSavedFromBefore).

Here's one theory I have: the WorldAnchor TileEntity is being destroyed by FL via World.removeTileEntity(), which assumedly calls deactivate() on the WorldAnchor deep down somewhere. According to RC code, deactivate() does nothing immediately, but defers releasing the Ticket until the next call to updateEntity(). However, this call will never come, since the TileEntity has just been destroyed. Then, FL recreates the WorldAnchor, which acquires a new ticket, since its local ticket is null (it has just been loaded from NBT). Repeat until all Forge tickets for RC are exhausted.

Perhaps this differs from how RedPower did it; perhaps RedPower simply moved the TileEntity without recreating it (which is possibly why RP frames were buggier than FL's; some TileEntities don't expect to be moved).

I believe the reason the WorldAnchor code works fine under normal circumstances is that deactivate() is never called without a follow-up updateEntity(), except when the block is physically broken, and this scenario has special code to explicitly release the ticket first (TileAnchorWorld.java:onBlockRemoval()).

As for why CC doesn't have this problem, if the theory above is correct, then it is because CC releases tickets immediately on deactivate() without deferring, then reacquires on activate().
Possibly also relevant, CC stores its Forge Tickets outside of the chunkloader TileEntities themselves (in a hash table or something), instead of inside the TileEntities like RC. (I'm not qualified to judge whether any of these ways is right or wrong; I'm just noting the differences.)
As to why this doesn't cause the chunks to unload during FL movement with CC, perhaps FL itself has some mechanism to keep the chunk loaded long enough to complete the move, though I was unable to find explicit code for this. Perhaps something similar to vanilla hoppers is going on?

As for a possible solution, that's out of my league. It seems to me the cleanest way would be to implement FL's IMoveFactory to give RC full control (https://github.com/rwtema/FunkyLocomotion/blob/master/src/main/java/framesapi/IMoveFactory.java), at which point RC could do...something...to mitigate the issue, but submitting a push request for that is beyond me.

Hope at least something in this post is helpful. To be perfectly clear, I'm not intending to blame anyone or demand anyone make changes, I'm just trying to contribute what I can to the issue. Thanks!

commented

The reason for the delay is that the chunk loader must remain active while being moved. If it was to discard its ticket during the move process, the chunk would unload. Defeating the purpose.

commented

I see no way to support both methods of moving tile entities...at least not without making the Ticket management external. And that would require a large amount of new code.

commented

Well, I suppose I could assign a UUID to each Anchor TileEntity that is serialized, and then have it always grab the Ticket from a static Map using the UUID.

commented

Based on reading the CC code, it seems like those chunkloaders actually do discard the ticket during the move process, and it appears to still work fine. Could be FL temporarily keeps the relevant chunks loaded by itself until after the move, perhaps another difference of FL frames from RP frames.

So, if we're lucky, it may be as simple as making it release the ticket immediately. Worth a test? I'd be willing to run the experiment, if it would help.

commented

I'm not going to break every other method of moving tile entities just to fix Funky Locomotion. And hopefully I won't have to.

commented

Ah, of course, good point. Thanks for tackling this, good luck!

commented

We always just used two anchors / chunk loaders on each frame ship so that it would always be loaded. Nice to know that when they move that they are still loaded. As a temporary fix, could you not just have another block go into the block space on the next move? Would this not cause a block update?