ModLoader Development Halted


#1

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 :slight_smile:
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.


#2

hope the devs sort this out for you :slight_smile:


#3

Used the MVC model type for development a lot, worked nice as a system.


#4

Hi,

Thanks for taking your time into looking into potential modding of Airport CEO. I can start by saying that the code is far from ready to receive code based modding. There is simply too much legacy and overall fixing that needs to be sorted out first, but it is of course interesting that you decided to take a look at it, although it might be just a bit too early. :slight_smile:

Let’s comment on the issues you found. Enums, is a great example and yes we do use them quite frequently which was super easy and helpful way in the beginning of the development process but have become sort of a pain due to the inflexibility you mention. We did actually change this on a few places like aircraft, where each type like “B737” used to be an enum. To prepare for future modding we created a custom “enum” or simple type variable that can be loaded via JSON, which will enable modders to add their own aircraft type later on.

{  
   "AircraftTypes":[  
      {  
         "id":"B737800",
         "size":1
      }
   ]
}

Regarding class inheritance. We already use this principle divided into model and controller so for example we have a VehicleController which has the logic you describe and a VehicleModel that stores model data. Then we have a FuelTruckController etc but I guess what you mean is that we should skip model/controller and use a single class as both model and controller? Or did I miss something? :slight_smile:

Yea, namespace. Fully aware of that and not a big thing to change later on.

I think once we are more ready we can set together a chat/focus group with skilled modders to discuss how we can better accommodate for more complex modding because we are definitely prepared to make necessary changes for it. :slight_smile:


#5

Excellent, great to see a dev reply. Loading data in via JSON is a good way to solve that problem and negate the need for a modder to override IL-level stuff. I completely understand the “legacy code” stuff lol, the world would be a better place if we didn’t look at our past code and wonder what the hell we were thinking…

To expand on the class inheritance bit, I took a second look at the disassembled class diagrams - it looks like you ARE already inheriting your vehicles the smart way, I apparently just didn’t catch it because I was so focused on “why is there an enum here???” :slight_smile: That combined with holding to MVC principles in game development is pretty difficult, as my gut instinct is to just put all functionality in one larger class and derive from there, so I’ll at least give you props for sticking to that. :slight_smile: I don’t blame you that modding is pretty far down the list of priorities, you’ve definitely got quite a bit to go game-wise, which is why I’ll be pivoting to other projects for now. I’ll continue to watch the game pretty closely though :slight_smile:

Good luck with the game, and let me know if you need a second opinion or even help (I’m freelancing part-time this summer!)


#6

@Fredrik

Love the progress so far on the game. It has a lot of true potential. This game is actually getting me into wanting to learn programming to be able to mod it. I came across ben’s post here to see he was way ahead of me. I agree the game is still fairly early in development to mod (though not impossible, just really difficult).

Is there a time frame when you guys will start rewriting legacy code to make it easier for you guys and modders? I understand you guys have far more important things to do, though I bet it would be easier to adjust the code now while there isn’t that many features. I’m going to start playing with what you guys have made so far and see what I’m able to manipulate. I’m excited for future updates! =)

Thanks!


#7

Hi, I’m happy to hear that our game inspired you to learn programming and that you want to dig into it. :slight_smile: Our stand point here is basically that we need to make a finished game first, that is our top priority. Also it will depend on what kind of control and detail we want to give modders. For example the content modding is quite easy and maybe even buildable objects later on but things like behaviour modding is a different level and we cannot guarantee that it will possible. So I guess we need to get to a full stable version and then see what is possible. Rewriting legacy code is extremely time consuming and is sometimes not even possible.