Hello community! As the title says, for the time being I am halting active development on ACEO ModLoader. Excuse the long post, but I’ll try to explain everything.
Why?
In order for me to explain why, we’re going to have to get a little bit technical, so bear with me. All the reasons development is stopped are about the game’s internal code: I’ve tried making headway into a few mods that had interest in the community before (Cargo, catering, etc.) But the way everything is structured code-wise makes it very difficult - almost impossible in some cases - to add features or extend on currently implemented features.
Disclaimer:
Once again, some information in this post may reveal some of the internal workings of Airport CEO, and I still have not been given explicit permission to do what I am doing nor have I found an official Terms of Service. In the event the devs disapprove of this level of reverse-engineering, this post and the ModLoader project will be taken down.
Continuing on, the (current) hard difficulty of modding Airport CEO generally comes down to 2 problems:
The Enum Conundrum
Enums are special “types” that contain constant values that developers can use to assign to variables to make code more readable and testable. For example (from MSDN):
// Declaration:
enum Day { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };
// Can then be called like this, makes code nicer. No more ugly number-dictionaries!
var dayOfWeek = Day.Monday;
The problem with enums is they are sealed objects. This means you CANNOT modify an enum after compile time, meaning wherever the developer uses enums, we can’t modify, add or remove enum types ourselves. And the developers use enums everywhere. Vehicle types, flights, aircraft, and more are all stored in enums.
Not to mention all the enums are in a really big Enums
class… uhhh…
Anyway, let me give a good example I tried working on earlier this week: I tried making a fully-featured sample mod that actually adds something to the game besides changing values to show off what ModLoader could (or in this case, couldn’t) do: I was going to implement catering trucks and add them to the turnaround system. In order for me to add a catering vehicle type, I needed to add a “catering” type to the vehicles enum that the developers use. For reference, here’s all the vehicle types the game currently has:
As you can see, we need a “Catering” vehicle type to continue.
Since I can’t edit this enum, the only real way to work around this problem is to create my OWN enum (I’ll call it VehicleTypeExtended
). BUT, there’s a problem: even if I make my own enum all the Airport CEO functions take the old VehicleType
enum as arguments, so I need to replace/extend all the original functions with custom ones that take VehicleTypeExtended
instead. In the case of overriding this particular enum, my disassembler says there are 26 functions that have VehicleType
in their parameter list… you can see where this is going.
Even if I rewrote all these functions, any update the developers push out to any of these functions will break the mod, and we’re back at square 1. Not to mention that this is just for one mod… what if another mod wants to add a maintenance truck? They’ll have to rewrite all the functions for themselves too. This is enough to stop most modders in their tracks and give up completely as changing this functionality is practically impossible from a modder’s perspective. So… what can I do about all these enums? Nothing. But, the developers can.
How can the developers fix this?
Class inheritance. I notice the devs are not using the power of OOP (object-oriented programming) to get around all these enums and instead are putting code inside Models and Controllers (kind of like MVC). What if we rewrote the VehicleType enum and all the associated functions into classes with inheritance?
Example:
class Vehicle { // contains general vehicle code, like pathfinding and turnaround positions };
class FuelTruck : Vehicle { // contains fuel-truck specific code };
class CateringTruck : Vehicle { // this class can be added by a mod easily! };
Switching to this format also makes the code more testable and debuggable - if a bug happens only on fuel trucks but on other vehicles, narrowing down the bug gets a lot easier. The downside to switching to class inheritance is that most code in Airport CEO would require a MASSIVE rewrite, introducing a whole LOT of other problems! Even if the devs take this advice, I don’t see this happening anytime soon, as it’s just two developers (and Jettuh) and that’s a LOT of code to rewrite and test - just to make debugging and modding easier.
The second problem doesn’t necessarily make modding impossible, but it does make it much harder:
Namespace Collisions
OOP-heavy languages (like C#) have things called namespaces, think of them as giant containers for code. It’s always good practice to put your code in a namespace. Right now, all Airport CEO code (scripts, etc.) is not inside anything. This means it is floating around in what we call the “global namesapce,” meaning as soon as you inject a method, every class, variable, etc. is immediately accessible. While this isn’t a problem for Airport CEO specifically, it IS a giant problem for mods. A mod could change, add, or remove anything - even if a mod is inside it’s own namespace, it becomes harder for mods to play nice with each other. For example, say a mod developer accidentally overwrites HelpPanelUI
with his/her own class without sticking his/her mod in a namespace. The compiler will think everything’s OK, but in reality Airport CEO’s HelpPanelUI
gets completely overwritten by the mod’s HelpPanelUI
. If the developer didn’t implement everything from the class properly (or didn’t at all), the entire class is gone/at the whim of the mod developer. This can lead to some crazy-looking thrown exceptions, undefined behavior and potentially a game crash!
How can the developers fix this?
This one’s a lot easier than the other to fix: it’s as simple as sticking all the code inside a namespace, be it “airportceo” or “apoapsis” or anything the devs decide. If everything’s inside its own namespace on both the game-side and mod-side, the two can interact with each other without mods metaphorically “stepping on” game code they shouldn’t be stepping on. I imagine on the source-side (the side of the code us end-users/players can’t see) the devs are using a lot of individual UnityScript files, so the hard part comes in adding the namespaces in to all of these files.
What’s Next?
ModLoader will continue to be hosted as an open-source project on my GitHub, however I will no longer work on it until the developers either implement a modding SDK or make the code more malleable internally, as modders won’t find very much to mod without resolutions.
Finals are coming up in my country, so I’m in for a hell of a month
In addition, I have been contacted by the devs of SimAirport to open dialogue about a ModLoader port for their game or even an official modding API. While I haven’t promised anything, I AM going to spend some time looking through their game over the next couple of weeks. @Olof and @Fredrik please do not hesitate to contact me in any way if you have any comments or questions about the above… and of course if this post is stepping over the intellectual-property boundary a little TOO much please let me know and I’ll take everything down swiftly.