I don't know if anyone will find this interesting, but I thought I'd post about the old mod and the reasons behind scrapping everything for a rewrite.
A few posts back I mentioned that the 1.x codebase made me die a little inside every time I looked at it. To elaborate on that statement:
AgeThe biggest problem is simply that the console mod was
old. This mod dates back to 2012 and was written for Starfarer 0.53a. Back then the API was only
15% the size it is now. I can't overstate just how many problems were caused due to ugly workarounds for missing features (the big ones being campaign-level scripts, keeping track of the combat engine and saving persistent data; though users of the old mod probably know these better as "why isn't the pop-up working?").
That even in this state the mod continued to function with minimal changes until now is a testament to the amazing work Alex put into making the API forwards compatible. That said, using the modern Starsector API methods allows the rewrite to do everything the old one did with a fraction the effort and a
much lower chance of errors.
BloatThe old version had become
insanely bloated, largely due to the necessary workarounds described above.
To throw some numbers at you: the old console's main class was 1,300 lines of code (including 40 lines spent defining variables) and was a confusing mix of static and local code. It also had several commands hard-coded into it. That's pretty reprehensible for a class whose only duties are to check for input, parse and validate entered text, and create and pass arguments into the proper command object.
The new version? Completely static, with 270 lines for the console itself and 150 for the class that handles command loading/storage/lookup. It does virtually everything the old version did in a third the code and with almost none of the complexity! The only command that has any special code dedicated to it is RunCode, and that's just
a single line to prevent it from being parsed into multiple commands since the default command separator is a semicolon.
If you're curious as to how bad it was, you can find the source for the old console
here. Compare to the
new version.
Poor design decisionsThere were a lot of these (having the default console key not easily accessible on several international keyboard layouts was a big one), but for the worst example, here's what you had to go through to implement a custom command in 1.6b:
- Make a script that extends the abstract BaseCommand class. This class contained 20 methods (of which you'd actually care about 3-7 depending on what kind of command you're making) and had default implementations for most of them, so you'd be forced to check BaseCommand's source to see what methods you needed to override. The irony? These extra methods were intended to make writing commands easier, but instead ended up making it a chore for anyone who wasn't already familiar with the codebase.
- Place your script in the data/scripts/console/commands directory. That's the only folder it will accept commands in, for no good reason. Putting it inside data/scripts also means these scripts are loaded by Starsector's built-in compiler, so you can't bundle commands with your mod without creating a dependency on the Console mod. The rewrite suggests putting them somewhere else where they will only be loaded when the Console mod is active.
- Have another script (somewhere, somehow) call Console.registerCommand(<your script's class>). This would throw an Exception if your command was in the wrong package, overwrote a core command, made a mistake extending BaseCommand, or if the code decided it just didn't like you; so you'd also have to write exception handling code. This limited custom commands to those modders who were already proficient in Java (pretty rare at the time).
In the new console, here's the process for adding a custom command:
- Make a script that implements the BaseCommand interface. This interface contains one method - runCommand(). Where this script is placed and how you implement it is completely up to you.
- Describe and point to your command in data/console/commands.csv
- Step 3? What step 3? You're done!
Here's an example of a command implementation in the rewrite:
Spoiler
Here's the code for AddSkillPoints:
package org.lazywizard.console.commands;
import com.fs.starfarer.api.Global;
import org.lazywizard.console.BaseCommand;
import org.lazywizard.console.Console;
import org.lazywizard.console.CommonStrings;
public class AddSkillPoints implements BaseCommand
{
@Override
public CommandResult runCommand(String args, CommandContext context)
{
if (context == CommandContext.COMBAT_MISSION)
{
Console.showMessage(CommonStrings.ERROR_CAMPAIGN_ONLY);
return CommandResult.WRONG_CONTEXT;
}
int amount;
try
{
amount = Integer.parseInt(args);
}
catch (NumberFormatException ex)
{
Console.showMessage("Error: Skill points must be a whole number!");
return CommandResult.BAD_SYNTAX;
}
Global.getSector().getPlayerFleet().getCommanderStats().addSkillPoints(amount);
Console.showMessage("Added " + amount + " skill points to your character.");
return CommandResult.SUCCESS;
}
}
And here's the CSV data for it:
command,class,syntax,help
AddSkillPoints,org.lazywizard.console.commands.AddSkillPoints,addskillpoints <amount>,"Adds the specified amount of skill points to your character."
tl;dr: The old mod was a mess. It's going to be much better now.
You can grab the latest WIP
here if you want to try the rewrite out yourself (this is the same one I posted yesterday). It's pretty much done at this point except for a few new commands I have planned and some bugtesting/polish.