Back to Main Page


A single page briefly covering the history and evolution of the Tracker mod and app combination.

 

Tracker - A mod and an app, sharing without caring.


I originaly mentioned this mod and app pairing in my World Guide mod pages but as I am twiddling my thumbs once again, I decided to create a page about it.

The mod and app wore born part out of necessity and part out of sheer curiosity... and also for a mod that never really got started due to problems I could never solve. That mod was my bus schedule system, that was intended to add functional scheduled buses into GTA traffic. That had 3 major problems that forced me to give up on it but as part of that idea, I created a bus-route creation app.

Whilst this app had no communication functionality, the intention was to also use it like a GPS tracking system to monitor the buses... which never happened.

So for quite a while, the app was used as nothing more than a map viewer. You could pan round the map, you could zoom to one of 4 zoom levels, so it had all the basic functionality working. A key part of this being able to work was a custom MarshalBitmap class I wrote to extract areas of bitmap data and create new bitmaps from them. This class worked really well but it was another of those techniques that probably took me over ten years to learn, due to my inability to take in information. One day it just clicked, suddenly seemed very simple and thus the class wa born. This transformed any app I wrote using bitmap data from a sluggish mess, into a usable app. But it had an achiles heel when you resized the window. The image would appeared skewed and I wasn't sure why, so I just ignored it for now. **

Then I started to create mods that were all focused on locations and that caused the app to gain some new abilities and a new name, Coordinate Tracker. I switched to using a darker version of the map and started to give it functions to read in location data from different file types. Pixels were then plotted at those locations, so I now had the ability to visualise those locations on the map.

That's a section of the map showing the WGS locations in Sandy Shores. The locations were shown as bigger pixels in this original app, to make them more visible at a quick glance.

It was around this time I got the idea of also using it to track the player's position, so a Player Watch option was added to the menu. This was also the time when the mod side of the pairing was first created... and where the troubles really became apparent. The mod and app needed to communicate and the last time I had written any form of communication software, was in 68000 assembler on the Atari ST, to transmit Sysex (System Exclusive) data between my ST and my Korg M1 synthesizer. That was around 1988, almost 30 years ago at the time I was writing this mod.

The biggest hindrance I have with writing software is I'm hopeless at learning anything that relies on reading technical documentation. I spent hours, days, weeks... reading page after page about inter-process communication and the only thing I learned, was that it was too complicated for me to understand and it was never going to happen. Then I stumbled across a page talking about memory-mapped files (MMF), which is like a shared file but it exists in memory while it is being used. It was fairly fast but a pain to work with if things were run in the wrong order... but it worked.

So I created a basic tracker struct that held a small amount of information, the mod compressed the data and then wrote it into the MMF, the app read that data and processed it. I now had the ability to see the player on the map. The ability to lock onto a coordinate was already in the app, it's how you scrolled around it, so getting it to scroll with the player was a simple task. By getting it to set a pixel into the image when it processed the data, it was now able to show exactly where the player had been... this was a real game-changer for WGS research. I could see exactly which streets I had been down, so I knew which streets remained unchecked.

The actual TrackerStruct contained quite a bit of information about the entities being collected.

    public struct TrackerStruct
    {
        public TrackerStructType StructType; // 0 = Player, 1 = Ped, 2 = Animal, 3 = Vehicle
        public TrackerStructGender Gender; // 0 = Female, 1 = Male, 2 = Undefined (for animals)
        public MotionType Motion; // 0 = Ground, 1 = Air, 2 = Water, 3 = Rail
        public int ModelHash;
        public Vector3 Position;
        public float Heading;
        public StatusFlags Status;
    }

The Status parameter is a collection of Flags that are bitpacked into 2 bytes. This allows me to potentially store a lot of status information in a very small amount of data space.

[Flags]
public enum StatusFlags
{
    Emergency = 1,
    Selected = 2,
    Persistent = 4,
    Enemy = 8,
    Dead = 16,
};

The order of the flags has no real definition but it doesn't really matter, the order has no relevance.

A header struct was also created and that contained info about time of day, weather, current map zone and street names for the player... just general stuff. That was tagged onto the front of the sent data and is displayed in the side-panel in the app.

I also added a File System Watcher to the app and what that does, is watch a directory for any new or changed files. I set that to watch the WGS location folder and as I saved new versions of the location files from the Location Collector mod, the app responded by updating the map with the new locations. The app essentially became a hub for coordinating the data from two mods and displaying it all in a visual fashion.

So by now, I had a mod that could collect and process entities into TrackerStructs and then save that data. I had an app that could read that data and transform it into a map full of moving circles. After a revision to the UI which added a collection of filters to the side-panel on screen and a shift to a darker UI theme, I was at this stage... which was pretty much what I wanted the app to be.

 

And that's how it remained for quite a long while. After losing interest in modding, the mod and app had no reason to expand into anything more. All I really used the app for was seeing where coordinates were on the map, because it could display GTAV coordinates based on the cursor position... useful for seeing where map addons had been placed.

Then I made a comment on this site that prompted someone from my past (Tobsi Cred) to get back in touch. While my skills had been stagnating and going unused, theirs had been in full-speed-ahead mode. One particular area they were excelling in, was the one that I had failed so miserably at and that was app-to-app communication via TCP. They introduced me to third-party libraries I had never heard of, created demo apps to show me how it worked and generally pointed me in exactly the direction I need to go in, to finally take this app where I always believed it was meant to go.

It still took me time because if I read too much in the source, my brain just switched off and I was lost again. Thankfully, the library was noob-friendly and I managed to replace the Memory Mapped File system with proper communication code. Instead of the app having to check the MMF for data when a timer went off, it could now just sit and wait until it received data and then act on it. It was a far better system, far more efficient and far more stable. What it also did, and this was a key point, was it allowed me to run the app on a second PC on my LAN.

Because it was now more efficient, the temptation was there to make the mod transmit a bit more data for the app to display. So the status flags expanded to this:

[Flags]
public enum StatusFlags
{
    Emergency = 1,
    Selected = 2,
    Persistent = 4,
    Enemy = 8,
    Dead = 16,
    Parked = 32,
    Scenario = 64,
    Hidden = 128
};

You can see there are 3 more flags added, Parked, Scenario and Hidden. So now I could display all those cars that had been spawned into the world in various parking positions, that gave me a more accurate representation of what vehicles were really being spawned. The Scenario flag let me determine which Peds were randomly wandering and which were taking part in defined scenarios. Now I could display information like this:

You can see all the parked vehicles in the world (shown with an outer green ring), you can see all the peds in scenarios (shown with a yellow outer ring). This image shows the different types more clearly.

The world started to make much more sense with respect to how many things were present and what they were doing. But sometimes, all this information is too much, or just unnecessary. The app had filters to turn the display of certain entities on or off but I decided to implement further filtering in the mod itself. That meant instead of sending too much data and then not showing it, you simply didn't send the data for things you didn't want to see.

So vehicles could now toggle between All, Only Parked, Only Moving or None. Peds could be All, Only in Scenario, Not in Scenario and None. Animals could toggle between their different motion types.

The final status flag (up to now) was more of a novelty feature that I waned to try. Things were getting messy, so I had made some changes to the draw-order in the app to make sure the player was always drawn last. I had Z-sorted the data, so things lower down were drawn under things higher up but I wanted to show when things were under bridges, in tunnels etc...

So for just vehicles, a ray is cast 35 metres directly upwards and if it hits part of the map, it is marked as hidden. I first tried not drawing things that were hidden but wasn't overly happy, so I switched to using darker versions of the chosen colours. So you can still see the vehicles are there but you also know they are under something. The penalty is that casting so many rays hits the performance, so you can choose to not do that test by changing a setting in the mod ini file.

That got things visually just where I wanted them but there were a couple of functionality changes required because of my 2-PC setup. The first one was configuration of the IP address of the server in the app. Running on the same PC it was 127.0.0.1, running on the second PC it was a LAN address. So I added some code to check for the machine name and to then configure itself based on that name. That name was also used to force the sleep modes off, as my second PC shuts certain things down after 2 minutes. I don't normally need to see what it is doing but didn't want to mess changing settings every time I wanted to run the app. Thankfully, StackOverflow provided a nice solution that can disable power related shutdowns and then re-enable them when you exit the app... that all works perfectly.

The second one was for the mod itself. You can set the server IP in the ini file but that also meant changing that IP depending on where the app was running. I didn't want to be forced to use my second PC every time, so I added some code that tried to connect to 127.0.0.1 first and if that failed, it would use the ini file value and connect to that instead. So it caters for all situations and I don't need to manually change anything.

So everything was working great, apart from two things:
1) The map being skewed at certain window sizes. **
2) A strange situation where firemen stopped being registered when they were walking back to the fire truck.

Number 1 was something I had tried to fix a couple of times. I had one error caused by the Bitmap.Stride value that I thought was causing it but while it was affecting some things, it wasn't this. I then thought it might have been odd pixel widths (odd as in 1, 3, 5 etc... not odd as in strange) causing it and adding code to deal with that almost had me fooled into thinking it had worked. It hadn't, I just got lucky with the values I ended up with when I resized the window. The actual problem was the width needed to be divisible by 4, so it seemed to be a memory alignment issue. A small piece of code later and that problem now seems to be completely cured... touch-wood.

I also fixed another problem at the same time that was causing the screen to go blank during a resize. Fixing those two simple problems makes a huge difference in how it appears while you are resizing the window, so they were worth fixing.

Number 2 was just bizarre and I still don't understand what was happening. To make peds eligible for processing, I was checking if (Ped.IsOnFoot), because I didn't want it drawing peds that were inside a vehicle. That worked in every situation, apart from when the firemen were walking back to the fire truck. I have no idea why it failed but changing it to if (!Ped.IsInVehicle() && !Ped.IsSittingInVehicle()) has fixed it, so they don't disappear anymore, until they actually get into the fire truck.

So as of 13th October 2020, the mod and app work as they should. The irony is that after fixing all the things that were broken, I probably still won't use them because I am still not really interested in modding. That is the dilemma of a brain that doesn't want to create anything but can't let go of things that don't work properly.

Update 15th October: Talk about speaking too soon... I kept looking at the date and time and thinking "That just doesn't look right" and it turns out it was because it wasn't just right, it was just wrong. I was moving through the header data by too small an amount on the first element, meaning the values I thought were Date and Time, weren't Date and Time. Having corrected the step size for the first header element, date and time are now showing correctly.

I have also added additional data to the struct number output, showing the number of each type of each struct. So Peds now show total number, then Scenario and Non-Scenario numbers, which means I can see better how each set of values is broken down into specific types.

I will leave this one final video of the app running, showing all the new features that have been added.

 

If anyone watches that and thinks "It's not very exciting" or "There's not much info on it" or "That was a boring piece of crap"... you're right. I didn't really want to make it and couldn't be arsed doing much with it. It just shows the current state of things with it, nothing more.

It probably would have been better with it running on my second PC while it was recording but my second PC is limited spec. It's a dual-core CPU, has a small SSD for the main drive and just 30GB of free space (out of 74GB total) on another drive. The only capture software I have on it is Fraps, which saves as avi files which are huge, even at 30fps. The PC is perfect for running the app but it's the opposite when it comes to recording what it's doing. But running the app and running OBS recording a window and running the game in fullscreen was not a recipe for a good recording process.

I hate recording videos and then editing them and then trying to make them interesting and then sitting there while Vegas takes all day to render it out and then waiting for Handbrake to re-encode it to get it to a decent size and then waiting for it to upload. That's why I make them unlisted, so only people crazy enough to come here find them.