Immersive Railroading

Immersive Railroading

3M Downloads

BetterPortals compatibility

Johni0702 opened this issue ยท 5 comments

commented

Johni0702/BetterPortals#178

BetterPortals allows one to have see-through and loading-screen-less portals. It does that by spawning fake players on the server, tunneling their packets to the client and then swapping out mc.player, mc.world, etc as needed during world ticking and rendering.

After using one of BP's portals, IR's MagicEntity will be re-added to the world again and again each tick.
Also, regardless of whether one uses a portal, the MagicEntity will only exist in the main world, not in any of the secondary ones (i.e. IR stuff on the other side of portals will not be rendered).

This is afaict the relevant code:
https://github.com/cam72cam/ImmersiveRailroading/blob/57625ee20d4017eb18748836bf28bfc8e88277b7/src/main/java/cam72cam/immersiverailroading/proxy/ClientProxy.java#L771-L794
It's called during the ClientTickEvent, so one important detail to know about BP is that the ClientTickEvent is called only once with the main world active (since I figured calling it with each world each tick is going to break more than it's going to solve).

IR only ever creates a single MagicEntity which it then moves from world to world. I'm not sure if there's some deeper reason for that but if there isn't, then fixing the first issue should be relatively simple:
If IR were to not keep track of the MagicEntity via a static field but instead just create a new one for each world which doesn't have already have one, that'll probably solve the infinite re-adding (which presumably happens because it's not removed properly from the old world).

What remains is spawning a MagicEntity in secondary worlds (i.e. those visible through the portal) in the first place because, as mentioned above, the ClientTickEvent is only ever fired for the main world.

The best I can come up with (since there are no WorldTick events on the client), is spawning the MagicEntity into the world on WorldEvent.Load (and hoping no third-party mod removes them after that; though even if one does, the MagicEntity in the main world will still be re-spawned by the ClientTickEvent handler and secondary worlds are secondary anyway).
I'm not entirely sure if the entity can be made to tick properly even when there are no chunks loaded yet (it has to tick because that's the only way it'll ever start moving in front of the player).

Scratch that, I just realized that moving the MagicEntity in front of the player won't be sufficient to make sure it's always rendered, since BP's only rendering chunks visible through portals and there's no guarantee that the fake player is even inside one of those (BP uses a dedicated camera entity during rendering since the same world may be rendered from multiple angles during the same frame if there are multiple portals).

Different idea for secondary worlds:
I see that IR also supports rendering its stuff in the RenderWorldLastEvent. This only happens when useShaderFriendlyRender is false. Is that referring to OF shaders? Cause if so, then I could just go ahead and flick that config option via reflection from BP whenever rendering a secondary world. OF shaders do not support rendering multiple different worlds anyway. Any reason not do go that route?

commented

@Johni0702 can you take a look at the latest builds and see how it works?

commented

AFAICT this is fully working now (BP 0.3.7.1, IR 1.7.2, TrackAPI 1.2).

Though tbh I'm not entirely sure why that is. This should still be valid afaict but when actually testing it, rails render in both dimensions right from the start:

While that will solve the first issue of infinite entity spawning, it'll unfortunately still probably not render correctly in secondary worlds because BP is swapping out the RenderGlobal as well and ClientTickEvent is only called for the main world.

Could you move the updateTileEntities call into one of the render events, e.g. RenderWorldLastEvent (there doesn't appear to be a RenderWorldFirstEvent)? Those should be called for all worlds which are rendered, i.e. also for secondary ones.

commented

That would be a good temporary fix.

I am working on a large rewrite for the next version which removes the magic entity. Here's the replacement: https://github.com/cam72cam/ImmersiveRailroading/blob/modcore/src/main/java/cam72cam/immersiverailroading/proxy/ClientProxy.java#L630

It uses a global tile entity which should not be tied to a specific world.

commented

Using a global tile entity sounds like a really good solution (one I might actually use for BP as well since it also suffers from that issue).

While that will solve the first issue of infinite entity spawning, it'll unfortunately still probably not render correctly in secondary worlds because BP is swapping out the RenderGlobal as well and ClientTickEvent is only called for the main world.

Could you move the updateTileEntities call into one of the render events, e.g. RenderWorldLastEvent (there doesn't appear to be a RenderWorldFirstEvent)? Those should be called for all worlds which are rendered, i.e. also for secondary ones.

commented

ModCore is getting close to done in IR. Once I have the test build out we can start looking at tweaking it for compatibility