Wurst-Imperium / Wurst7

Minecraft Wurst Hacked Client v7
https://www.wurstclient.net/download/?utm_source=GitHub&utm_medium=Wurst+Client&utm_content=Wurst7+GitHub+repo+sidebar+website+link
GNU General Public License v3.0
1.01k stars 416 forks source link

X-Ray: compatilbility with Sodium #287

Closed James-E-A closed 8 months ago

James-E-A commented 3 years ago

Description

X-Wurst is (still) incompatible with Sodium. I tested it myself on a fresh profile today.

While, unfortunately, the OptiFine dev is being petty and combative about this, making #174 conceptually wontfix/upstream-blocked, I see that, with Sodium, there are no such artificial obstacles (and it's open-source, to boot).

I'd like to formally open the ticket on this. Sodium has been a life-saver for me.

EcoBuilder13 commented 3 years ago

@JamesTheAwesomeDude Try using Indium, it is an experiential addon for Sodium which adds Fabric Rendering API support. Make sure you read the instructions and you can either build from source or download pre-built jars from Github CI.

holysnipz commented 3 years ago

@EcoBuilder13 still not working, same result

EcoBuilder13 commented 3 years ago

@holysnipz I just looked at the code for the X-Ray hack and I think I know why Indium doesn't fix it. Indium only adds the Fabric Rending API to the game in a way that Sodium can run it. In XRayHack.java I am seeing custom rendering calls created by Wurst. This means the problem is caused with the rendering code that Wurst uses is not compatible with Sodium. The only way I see this getting fixed is if they Wurst developers make their custom rendering able with Sodium.

XfedeX commented 3 years ago

that would be VERY useful!!!!!!

Alexander01998 commented 3 years ago

@EcoBuilder13 it's actually BlockModelRendererMixin that is having trouble with Sodium.

Sodium seems to bypass Minecraft's BlockModelRenderer.renderSmooth() and BlockModelRenderer.renderFlat() calls, so although Wurst's mixin is still applied, it doesn't do anything with Sodium (or OptiFine) installed.

It would seem that if we could find Sodium's replacement for BlockModelRenderer and mixin into that, then X-Ray would work again. Though from looking at Sodium's source code, it doesn't seem to be that simple.

EcoBuilder13 commented 3 years ago

@Alexander01998 Cool, now that we know exactly what the problem is it is much easier to find a fix. I have a good feeling that Sodium replaces renderSmooth() and renderFlat() with it's own versions. I checked the mixin for BlockModelRenderer in Sodium and it does not look like it contains the new methods. I don't know the names of the new methods but there are people on their Discord server (as of posting the link times out for me I am looking to get it fixed) who know more about the internals of Sodium. For compatibility you could detect when Sodium is installed and say something like if sodiumDetected = true then foobar.sodiumRenderSmooth(); else foobar.renderSmooth();. This would basically run the Sodium rendering call when it is detected but other wise call the vanilla one so that the end user does not have to adjust settings/config. If something like that works the way I think it would.

Alexander01998 commented 3 years ago

I'll try to explain some more:

X-Ray works by overwriting Minecraft's decision of which blocks to render and which blocks to hide.

Normally, when Minecraft decides whether or not to render a block, it calls the following methods in order:

  1. BlockRenderManager.renderBlock()
  2. BlockModelRenderer.render()
  3. either BlockModelRenderer.renderSmooth() or BlockModelRenderer.renderFlat()

Each of these methods have a boolean cull parameter that, if set to false, causes the block to be rendered even when it's behind other blocks. This is how X-Ray can show ores that would normally be hidden.

The other thing that X-Ray needs to do is to hide all of the non-ore blocks that would normally be rendered. It does this by simply cancelling the method call.

In vanilla, that gives me three options for where to place the X-Ray logic. Currently X-Ray uses renderSmooth() / renderFlat(), but the other two would work just as well.

Now this is what happens if Sodium is installed:

  1. ???
  2. modified version of BlockModelRenderer.render() that doesn't have boolean cull
  3. BlockModelRenderer.renderQuad() (also doesn't have boolean cull)

As you can see, that seemingly leaves zero options for where to put the X-Ray logic.

So far I haven't been able to figure out what step 1 gets replaced with, I only know that the original BlockRenderManager.renderBlock() doesn't get called anymore.

Step 2 and 3 have become pretty useless for X-Ray. It could still cancel these methods, but it can't force them to render their block.

Since these methods have seemingly no logic in them for deciding which blocks to render, that gives me a suspicion that Sodium might make that decision somewhere else, before any of these methods are called. But where this happens and how it works is a mystery to me.

x86k commented 3 years ago

The EMC framework (used by Aristois) specifically contains mixins for Sodium. https://gitlab.com/EMC-Framework/EMC/-/blob/1.16.5/src/main/java/me/deftware/mixin/mixins/integration/MixinSodiumBlockOcclusionCache.java https://gitlab.com/EMC-Framework/EMC/-/blob/1.16.5/src/main/resources/mixins.sodium.json

Furthermore, it appears that the X-Ray hack in Wurst utilizes the same method listed in the EMC mixin. https://github.com/Wurst-Imperium/Wurst7/blob/master/src/main/java/net/wurstclient/hacks/XRayHack.java

LukasMFR commented 3 years ago

Any update ? Thanks

RealIndica commented 3 years ago

How about you write a separate sodium compatible x-ray that doesn't mess with the blocks rendering.

Do it the old fashioned way : Loop through blocks (distance set to your render distance), get their positions, convert positions to screen positions, draw an overlay.

or

Hook sodium's render method and create another renderer on top of that. You will just have to make sodium's render not execute with x-ray on, but only show your own renderer. Making sodium's renderer temporally null should be fairly simple with patching.

pseudocode :

[Hook("-insert sodium block render function here-")]
class Patch 
{
     void Prefix() //this is called before sodiums render is called
     {
          if (xray == true)
          {
               //do your x-ray work here
              return false; //prevent sodiums render function from being called
          }
          else
          {
               return true; //allow sodiums render function to be called
           }
     }
}

(I am a c# developer, although java is very similar I am definitely not an expert lol)

github-actions[bot] commented 8 months ago

This issue has been open for a while with no recent activity. If this issue is still important to you, please add a comment within the next 7 days to keep it open. Otherwise, the issue will be automatically closed to free up time for other tasks.

Issues should be closed if: