GTNewHorizons / GT-New-Horizons-Modpack

A big progressive questing modpack for Minecraft 1.7.10 balanced around the mod GregTech.
https://www.gtnewhorizons.com/
Other
1.02k stars 311 forks source link

Add an option to spatial IO ports to disable block updates #17540

Open ivelieu opened 1 month ago

ivelieu commented 1 month ago

Your GTNH Discord Username

ivelieu

Your Pack Version

2.6.1

Your Proposal

My proposal is to add an option to spatial IO ports to disable block updates on the spatial transition. I'm not suggesting to remove the edge traversal neighbor updates however, just the block updates for the main bulk of the spatial region.

As discussed with @AbdielKavash on the GTNH official discord, spatial IO ports cause horrendous TPS if they are activated frequently. I did some testing and this is due to this loop: https://github.com/GTNewHorizons/Applied-Energistics-2-Unofficial/blob/5a8393bd573869c3ba6bea8c3b7b9af6f6b67953/src/main/java/appeng/spatial/StorageHelper.java#L211-L217

For example, I tried to move a 50x50x50 spatial IO region of GT ore all at once and if I do this against the border of the spatial IO boundary, I will get a my client got kicked due to stack overflow due to neighbor updates:

java.lang.StackOverflowError
~[GT_Block_Ores_Abstract.class:?]
    at RFB-Launch//net.minecraft.world.World.func_147453_f(World.java:3875) ~[ahb.class:?]
    at RFB-Launch//net.minecraft.world.World.func_147455_a(World.java:2603) ~[ahb.class:?]
    at RFB-Launch//net.minecraft.world.chunk.Chunk.func_150806_e(Chunk.java:851) ~[apx.class:?]
    at RFB-Launch//net.minecraft.world.World.func_147438_o(World.java:2540) ~[ahb.class:?]
    at RFB-Launch//gregtech.common.blocks.GT_Block_Ores_Abstract.onNeighborChange(GT_Block_Ores_Abstract.java:110) ~[GT_Block_Ores_Abstract.class:?]
    at RFB-Launch//net.minecraft.world.World.func_147453_f(World.java:3875) ~[ahb.class:?]
Stopped watching the game log because the log length surpassed 100000 lines.
You may have to fix your mods because the game is still logging to files and likely wasting harddrive space at an alarming rate!

This error is preventable by not placing ores on the boundary (although when I do that I get a different error over the same region which crashes my client):

java.lang.IllegalStateException: Already tesselating!
    at net.minecraft.client.renderer.Tessellator.startDrawing(Tessellator.java:394) ~[bmh.class:?]
    at net.minecraft.client.renderer.Tessellator.startDrawingQuads(Tessellator.java:384) ~[bmh.class:?]
    at net.minecraft.client.renderer.RenderGlobal.renderSky(RenderGlobal.java:1830) ~[bma.class:?]
    at net.minecraft.client.renderer.EntityRenderer.renderWorld(EntityRenderer.java:1616) ~[blt.class:?]
    at net.minecraft.client.renderer.EntityRenderer.updateCameraAndRender(EntityRenderer.java:1388) ~[blt.class:?]
    at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1001) ~[bao.class:?]
    at net.minecraft.client.Minecraft.run(Minecraft.java:4110) [bao.class:?]
    at net.minecraft.client.main.Main.main(SourceFile:148) [Main.class:?]
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?]
    at java.lang.reflect.Method.invoke(Method.java:580) ~[?:?]
    at net.minecraft.launchwrapper.Launch.rfb$realLaunch(Launch.java:250) [Launch.class:?]
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:35) [Launch.class:?]
    at net.minecraft.launchwrapper.Launch.main(Launch.java:60) [Launch.class:?]
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?]
    at java.lang.reflect.Method.invoke(Method.java:580) ~[?:?]
    at com.gtnewhorizons.retrofuturabootstrap.Main.main(Main.java:219) [lwjgl3ify-2.0.9-forgePatches.jar:?]
    at org.prismlauncher.launcher.impl.StandardLauncher.launch(StandardLauncher.java:100) [NewLaunch.jar:?]
    at org.prismlauncher.EntryPoint.listen(EntryPoint.java:129) [NewLaunch.jar:?]
    at org.prismlauncher.EntryPoint.main(EntryPoint.java:70) [NewLaunch.jar:?]

but even when I do that -- and move my character away from the area, and in an effort to reduce lighting updates by covering all the blocks being moved or running the simulation in a 0 brightness personal dimension, and chunkloading the chunks inside the spatial IO dimension to reduce file IO bottlenecks, the performance is still pretty terrible, and this is mostly due to block updates on the blocks which are moved.

Right after the block update part of the spatial IO code is a loop after it which calls neighbor change on the edges of the bounding box bordering the spatial IO area, which I am not suggesting to remove as there is potential for abuse like de-forming multiblocks: https://github.com/GTNewHorizons/Applied-Energistics-2-Unofficial/blob/5a8393bd573869c3ba6bea8c3b7b9af6f6b67953/src/main/java/appeng/spatial/StorageHelper.java#L219-237

To my best knowledge there is no way to abuse disabling block updates on the spatial IO transition.

I am OK to try writing the change on my own if there is consensus for it, I am just asking for other people's thoughts first.

Your Goal

Make spatial IO viable for complex automation, including but not limited to destroying blood magic meteors, in a TPS-friendly way.

Your Vision

Spatial IO is one of the less popular mechanics of applied energistics, but with all the complex automation in GTNH I think it would be really interesting if it were a more viable method of problem solving for automation. Especially given that you can perform spatial IO inside spatial cell dimensions, there are almost limitless possibilities, the only real obstacle being the current poor performance.

Final Checklist

AbdielKavash commented 1 month ago

I would love to see SpAE get some love, especially if the performance is this bad. However at the same time I would also want to see some other valid use cases; as I don't know if it is worth the effort just for meteor mining. And being able to move blocks without causing block updates might be borderline exploitable.

ivelieu commented 1 month ago

I left out other applications for brevity, not for lack of examples. If this change was made:

You would be able to do 2d and 3d multi-state animations like this at a much larger scale and have it be TPS friendly: https://github.com/user-attachments/assets/d530ba96-fc8f-4ebc-923a-2078993a70e4 https://github.com/user-attachments/assets/5ac50575-ed13-4a60-ac2d-5f7e14f3f185

You would be able to have self-moving objects at a massive scale, including miners, entire chunks of the world, self-expanding multiblocks using formation planes, and can literally automate base expansion -- why build using loki when you can tell your ae2 network to do it for you? You can safely formation plane and annihilation plane any relevant GT TEs, and move the rest with spatial IO. Any individual blocks that need configuring can be configured en masse elsewhere (e.g. cover copy paste tool) and their NBT will be respected by formation planes. Important here here is the edge traversal neighbor updates for the ae2 multiparts are cheap by comparison, but without block updates on the bulk the TPS of this design would be viable. It is greatly simplified logic using spatial IO compared to using frames for everything (which is borderline impossible), as you only need to move the spatial IO control circuitry rather than the whole object inside the region.

https://github.com/user-attachments/assets/f3f4c5cd-f28d-4fe1-b4b9-52f4607bf9a1

You would be able to implement on-demand crops using proxy patterns similar to what I did in a modpack divine journey 2 at a far larger scale. This would actually be a TPS saver as it would reduce the number of crops which need to be chunkloaded at any one time, in addition to being able to more efficiently use world accelerator power. The only current drawback in GTNH is the massive TPS spike due to block updates during the transition. https://github.com/user-attachments/assets/8ea819b1-4a3d-4e17-8136-25dca2101d73

About the borderline exploitable part - I want to emphasise that by keeping the edge traversal neighbor updates, I don't think there is any potential for abuse, since blocks inside the bulk of the spatial IO transition (i.e. not on the border of the bounding box) won't be able to tell the difference between the states before and after a teleport. The only way that their interaction could be modified post-teleport is with transvector interfaces or remote IO remote interfaces, which not only wouldn't have any potential for exploitation as these call block updates themselves, but in my opinion it's actually a clever tool to use in spatial IO automation.