Truinto / ONI-Modloader-SimpleMods

OxygenNotIncluded Mods
MIT License
16 stars 6 forks source link

Code issues #44

Closed Poorseven closed 9 months ago

Poorseven commented 9 months ago

Hello friend, I am using part of your code to change to my own favorite mod, but I found a problem that your folder does not have a reference to your original program, if it is my problem please remind me, if it is not, please bother to send a thank you. The problem is that "SolidTransferArm" does not include the definition of "IsPickupableRelevantToMyInterests"
------Machine flip

Truinto commented 9 months ago

Hehe. So I collected a lot of experience with modding unity games. One common issue is that the devs set a lot of fields/methods to private. Which sucks to work with. Sometimes even a whole class is private and you spend hours figuring out how to access something via reflection. But there is a trick (which I never saw in the ONI community, but elsewhere). You can recompile the assembly and set everything to public, then reference this for your project. You also need to allow unsafe code (otherwise you get access violation exceptions). Afterwards you can access every little field or method. You don't need to ship the recompiled assembly. Access level isn't checked later.

So if you want to join me with this huge advantage, install the package 'AssemblyPublicizer', add a job to recompile the game's assemblies, and reference this new file inplace of the original. The original package has a small bug which I encountered for ONI specifically. I made a fix, which you find in this repo 'src/assemblypublicizer.1.0.3.nupkg' (this is the full package plus fix).

Here is the build task: (need to change path to GameManaged)

<PropertyGroup>
  <GameManaged>D:\Programme\Steam\SteamApps\common\OxygenNotIncluded\OxygenNotIncluded_Data\Managed\</GameManaged>
</PropertyGroup>
<Target Name="Publicize" BeforeTargets="PreBuildEvent;Clean" AfterTargets="">
  <ItemGroup>
    <PublicizeInput Include="$(GameManaged)\Assembly-CSharp.dll" />
    <PublicizeInput Include="$(GameManaged)\Assembly-CSharp-firstpass.dll" />
  </ItemGroup>
  <PublicizeTask InputAssemblies="@(PublicizeInput)" OutputDir="$(GameManaged)\" />
</Target>

Also replace the references to the game files, like so. You need to clean or build once for the job (build task) to run. Until then the files won't be there (obviously).

<ItemGroup>
  <Reference Include="Assembly-CSharp_public" HintPath="$(GameManaged)\Assembly-CSharp_public.dll" />
  <Reference Include="Assembly-CSharp-firstpass_public" HintPath="$(GameManaged)\Assembly-CSharp-firstpass_public.dll" />
</ItemGroup>
Truinto commented 9 months ago

Clarification, since you probably didn't realize. The method SolidTransferArm.IsPickupableRelevantToMyInterests is part of the game's code. The reason your IDE doesn't like it, is because the method is set to private. Following the instructions above will trick your IDE in believing it were set to public. Which will just work, because during execution the methods access level is usually ignored.

Poorseven commented 9 months ago

Okay thank you