LMSDev / lcpdfr_public

The public code repository for LCPDFR developed by G17 Media from 2008-2015. Code release publicly in July 2022.
Other
34 stars 9 forks source link

Compiles fine but can't load in GTA IV 1.0.7.0 + some questions #1

Closed sjain882 closed 1 year ago

sjain882 commented 1 year ago

Hi LMS,

First of all a huge thanks for making the source code of LCPDFR public.

I had some quick questions:

  1. Is this version of LCPDFR equal to v1.1 on the LCPDFR.com website and is it designed for 1.0.7.0, or does it include fixes for Complete Edition? (Wondering if it's related to the below).

  2. Is this project intended (even if not guaranteed) to be downloaded, compiled and work right out of the box just like the LCPDFR version on LCPDFR.com. Asking incase there is any code or dependencies you couldn't include for legal reasons, etc.

I am encountering a problem where I can compile the project just fine, but if I install it (over the top of an existing LCPDFR installation, so files like LCPDFR.ini and other required files are present), I get a loop of LCPDFR has encountered an error, which has been logged to LCPDFR.log on game startup. Please see the below details.

Development environment:


What I've tried:


The error looping inside LCPDFR.log - happens immediately as I load into the game with Niko in the apartment (i.e., I don't even need to press ALT+P):

Click to expand ``` [ERROR - 09:12:17] [Main] CRITICAL ERROR DURING MAINLOOP! REPORT THIS ISSUE AT LCPDFR.COM BY INCLUDING THIS LOGFILE. [ERROR - 09:12:17] [] System.IndexOutOfRangeException: Index was outside the bounds of the array. at LCPD_First_Response.Engine.Scripting.Entities.Persona.LoadPersonaData() in C:\LCPDFR-Clone\...\LCPD First Response\Engine\Scripting\Entities\Persona.cs:line 254 at LCPD_First_Response.Engine.Scripting.Entities.Persona.Initialize() in C:\LCPDFR-Clone\...\LCPD First Response\Engine\Scripting\Entities\Persona.cs:line 142 at LCPD_First_Response.Engine.Scripting.Entities.Persona..ctor(CPed ped) in C:\LCPDFR-Clone\...\LCPD First Response\Engine\Scripting\Entities\Persona.cs:line 58 at LCPD_First_Response.Engine.Scripting.Entities.PedData..ctor(CPed ped) in C:\LCPDFR-Clone\...\LCPD First Response\Engine\Scripting\Entities\PedData.cs:line 110 at LCPD_First_Response.Engine.Scripting.Entities.CPed.Initialize() in C:\LCPDFR-Clone\...\LCPD First Response\Engine\Scripting\Entities\CPed.cs:line 530 at LCPD_First_Response.Engine.Scripting.Entities.CPed..ctor(Boolean isPlayer) in C:\LCPDFR-Clone\...\LCPD First Response\Engine\Scripting\Entities\CPed.cs:line 453 at LCPD_First_Response.Engine.Scripting.Entities.CPlayer.get_Ped() in C:\LCPDFR-Clone\...\LCPD First Response\Engine\Scripting\Entities\CPlayer.cs:line 173 at LCPD_First_Response.Engine.Scripting.Entities.ArrowCheckpoint.Process() in C:\LCPDFR-Clone\...\LCPD First Response\Engine\Scripting\Entities\ArrowCheckpoint.cs:line 214 at LCPD_First_Response.Engine.Main.Process() in C:\LCPDFR-Clone\...\LCPD First Response\Engine\Main.cs:line 296 [ERROR - 09:12:17] [ExceptionHandler] LCPD_First_Response.Engine.Scripting.Entities.Persona.LoadPersonaData() L_0029 LCPD_First_Response.Engine.Scripting.Entities.Persona.Initialize() L_0001 LCPD_First_Response.Engine.Scripting.Entities.Persona..ctor(CPed ped) L_0021 LCPD_First_Response.Engine.Scripting.Entities.PedData..ctor(CPed ped) L_0057 LCPD_First_Response.Engine.Scripting.Entities.CPed.Initialize() L_0193 LCPD_First_Response.Engine.Scripting.Entities.CPed..ctor(Boolean isPlayer) L_0026 LCPD_First_Response.Engine.Scripting.Entities.CPlayer.get_Ped() L_0035 LCPD_First_Response.Engine.Scripting.Entities.ArrowCheckpoint.Process() L_0024 LCPD_First_Response.Engine.Main.Process() L_0090 Error hash: F79C186AC2BFEDC67C31AD547EADB4484B0AF13A ```

If i do ReloadScripts, the error looping stops, and I get one error this time as LCPDFR Loader tries to start (a standard scripthook error with white text, like Error in script LCPDFR.Loader_loader!):

Click to expand ``` 2022-12-30 09:46:36 - Error during Tick in script 'LCPDFR_Loader.Loader': System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object. at LCPD_First_Response.Engine.Main.Tick() in C:\LCPDFR-Clone\...\LCPD First Response\Engine\Main.cs:line 244 at LCPD_First_Response.Engine.Main.Main_Tick(Object sender, EventArgs e) in C:\LCPDFR-Clone\...\LCPD First Response\Engine\Main.cs:line 211 --- End of inner exception stack trace --- at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) at LCPDFR_Loader.Test.Tick(Object sender, EventArgs e) at LCPDFR_Loader.Loader.Loader_Tick(Object sender, EventArgs e) at GTA.Script.TryTick() at GTA.Script.DoTick() at GTA.ScriptThread.OnTick() ```

The only thing I can notice that may be contributing here is a major difference in file sizes in LCPD First Response.dll:

This discrepancy only changes by about 100kb whether I compile in Debug or Release. So there's still a big difference.

Hence why I made this issue. Apologies if I'm missing anything obvious, but it looks like I'm missing some resources or something important in my DLL. Are there any special build options or includes I am missing?

Thanks.

LMSDev commented 1 year ago

I did test the build when we first released it with the first commit from the repo and then I applied some changes necessary to get it to build for someone else (the person originally pushing for open sourcing). Hence I am fairly confident that it does work. Looking at your error, it seems you might be missing some resource files or perhaps they get embedded funnily. Have a look at https://github.com/LMSDev/lcpdfr_public/blob/4e2c37e3b9a2996e4230675ccc369fd8b121baf9/LCPD%20First%20Response/Engine/Scripting/Entities/Persona.cs#L252

This seems to return an array of size 0 for you and hence crashes on the line below (254). It is supposed to pull in this file: https://github.com/LMSDev/lcpdfr_public/blob/4e2c37e3b9a2996e4230675ccc369fd8b121baf9/LCPD%20First%20Response/Resources/Names.dat#L2

I would recommend double checking what is going on with the resources file and why they might not get loaded. I cannot test the repo right now on my end as I do not have the game installed, but if you do find that something is broken in the current project settings, please let me know and I can update it.

sjain882 commented 1 year ago

Thanks for your fast reply and pointers! I managed to fix the issue. Always seems to happen soon after I writeup a GitHub issue/StackOverflow post... 😅

I was quite close to sorting this on my own if I had just looked a little closer into the stack trace...

First of all I checked my fresh compile in dnSpy and verified that all the resources files were present and looked in order. So the project settings seem to be okay.

I discovered that the .dat file is split into array elements by new lines as follows:

https://github.com/LMSDev/lcpdfr_public/blob/4e2c37e3b9a2996e4230675ccc369fd8b121baf9/LCPD%20First%20Response/Engine/IO/FileParser.cs#L24

https://github.com/LMSDev/lcpdfr_public/blob/4e2c37e3b9a2996e4230675ccc369fd8b121baf9/LCPD%20First%20Response/Engine/IO/FileParser.cs#L25

The problem is that Environment.NewLine is only CRLF on Windows. A quick check of the .dat file in Notepad++ revealed that all of the line endings were LF only (Unix).

I can only assume the files were changed from CRLF to LF at some point when pushing the project to git, which is why you might not have encountered this issue with a test build originating from the git project.

The solution was to change all the line endings from LF to CRLF in the .dat files. Compiled fresh and LCPDFR loaded just fine in-game.

For reference, I did it recursively on the entire project for peace of mind by running this command in a cmd window at the project root directory: for /R %f in (*.dat) do UNIX2DOS "%f" (Unix2Dos)

TL;DR:

Oh and by the way, the file size discrepancy is still present. I can only assume it's due to some kind of compiler optimisations introduced between 2015 and 2022.

I'll leave this issue open incase you want to make any changes and then close it etc, but this is solved on my end. Thanks 🙂

LMSDev commented 1 year ago

Nice find! I presume we all use the default Git for Windows setting which sets autocrlf to true but your config might be different and hence the line endings did not get converted properly. I will see if I can migrate it to use gitattributes at some point instead so it remains consistent across environments.