Skip to content

Adding a Game Command ​

Using Commands::AutoGroupSharedOrders (vehicle auto-grouping) implemented in this project as a template, this describes the complete steps to add a new command in jrpm.

1. Declare in the Command Enum ​

src/command_type.h, enum class Commands insert mid-sequence (will shift subsequent IDs):

cpp
AddSharedVehiclesToGroup,               ///< add all other shared vehicles to a group which are missing
AutoGroupSharedOrders,                  ///< auto-group all vehicles by their shared order lists

2. Declare the Command Handler and Registration ​

src/group_cmd.h (DEF_CMD_TUPLE_NT simultaneously declares the handler function and registers CommandTraits):

cpp
DEF_CMD_TUPLE_NT(Commands::AutoGroupSharedOrders, CmdAutoGroupSharedOrders, {}, CommandType::RouteManagement, CmdDataT<VehicleType>)
  • _NT: No tile parameter (use DEF_CMD_TUPLE for tile-based commands);
  • CmdDataT<...>: Parameter type list, the handler unpacks them in order.

3. Implement the Handler ​

src/group_cmd.cpp:

cpp
CommandCost CmdAutoGroupSharedOrders(DoCommandFlags flags, VehicleType type)
{
    if (!IsCompanyBuildableVehicleType(type)) return CMD_ERROR;

    CommandCost total_cost;
    for (const Vehicle *v : Vehicle::IterateTypeFrontOnly(type)) {
        // ... business logic ...
        CommandCost ret = Command<Commands::CreateGroupFromList>::Do(flags, vli, CargoFilterCriteria::CF_ANY, name);
        if (ret.Failed()) return ret;
        total_cost.AddCost(ret.GetCost());
    }
    return total_cost;
}

Key points:

  • Return CMD_ERROR to indicate failure (CommandCost(INVALID_STRING_ID));
  • flags.Test(DoCommandFlag::Execute) gates "actual execution" vs "test mode";
  • Nested commands use Command<Commands::X>::Do(flags, ...);
  • GUI/network calls use Command<Commands::X>::Post(err_string, args...) (auto network sync).

4. Add Entry Points ​

Window Button (Optional) ​

  1. Add WID_XXX to src/widgets/<system>_widget.h enum;
  2. Add button to the window NWidget layout;
  3. Add case in OnClick:
    cpp
    case WID_GL_AUTOGROUP_SHARED: {
        Command<Commands::AutoGroupSharedOrders>::Post(STR_ERROR_GROUP_CAN_T_CREATE, this->vli.vtype);
        break;
    }

Console Command (Optional) ​

src/console_cmds.cpp:

cpp
static bool ConAutoGroup(std::span<std::string_view> argv) { /* ... */ }
// In IConsoleStdLibRegister():
IConsole::CmdRegister("autogroup", ConAutoGroup);

Strings (Optional) ​

Add to src/lang/english.txt (e.g., STR_GROUP_AUTOGROUP_SHARED_TOOLTIP).

5. Completion Checklist ​

  • [ ] command_type.h enum
  • [ ] <system>_cmd.h DEF_CMD_TUPLE*
  • [ ] <system>_cmd.cpp handler
  • [ ] (Optional) Widget/console/strings
  • [ ] Network and save auto-adaptation (auto-generated by CommandTraits)