Skip to main content

Internal Script UIs

Here at Inubot, we have our own config system which automatically deals with quickstart arguments, saving and loading your last config, and even generating the UI itself. The UIs are placed into the extension sidebar in our client, and so we refer to these as internal script UIs

Breakdown

Here is an example UI built by extending ConfigModel and then using our UI annotations library

@Singleton
public class TitheFarmConfig extends ConfigModel {

@SelectorComponent(name = "Strategy", key = "strategy", type = Strategy.class)
public Strategy strategy = Strategy.STRATEGY_BASIC;

@TextFieldComponent(name = "Seeds to withdraw", key = "withdraw_seed", placeholder = "1000",
inputType = TextInputType.NUMERIC, required = false)
public int withdrawSeedAmount = 1000;

@Section(value = "Banking")
public TitheFarmBankingConfig banking;

@Section(value = "Shopping")
public TitheFarmShoppingConfig shopping;

@Singleton
public static class TitheFarmBankingConfig extends ConfigModel {

@CheckBoxComponent(name = "Restocking", key = "restocking")
public boolean restocking = true;

@CheckBoxComponent(name = "Stamina Potions", key = "stamina_potions")
public boolean staminaPotions = false;
}

@Singleton
public static class TitheFarmShoppingConfig extends ConfigModel {

@CheckBoxComponent(name = "Gricoller's can", key = "gricollers_can")
public boolean buyGricollersCan = false;

@CheckBoxComponent(name = "Farmer's outfit", key = "farming_outfit")
public boolean buyFarmingOutfit = false;

@CheckBoxComponent(name = "Herb box", key = "herb_box")
public boolean buyHerbBoxes = false;
}
}

As you can see, each field has an annotation on it. Either marking it as a component with the relevant data, or marking it as a separate section. This essentially tells our UI generator what to do, and everything after that is history. Each component has a name and key. The key must be unique as it is used for saving/loading. Names are whatever text you want to draw on the label. Beyond this, you can take a look at the annotation interfaces in our Javadocs.

So this generates the UI and all, but how do I get the values? That's easy. With some reflection magic, we're able to automatically read values and assign them to your fields - That's right, you don't have to do anything at all. Just declare model = TitheFarmConfig.class in your ScriptMeta and you're good to go! Once the user completes the UI and clicks start, the isBound() method in ConfigModel will return true. So if you need to wait for user input before starting your script logic, all you need is to have a blocking task return !isBound()

Now for quickstart args, they automatically get posted to the logger when a user starts a script. So users can simply copy those, and use them as they need.

Custom internal panels

Similar to the aforementioned internal script UIs, these appear in the side panel of the bot but are more customizable.

First write your usual swing UI code by extending ExtensionPanel.

@Singleton
public class MyPanel extends ExtensionPanel {

public MyPanel() {
//your ui code here
}
}

Once that's done, all that's left is dealing with actually adding it to the side bar, and removing it when your script stops of course - if you'd like to.

  private ExtensionButton button;

@Override
public void initialize() {
ExtensionPanel panel = injector.getInstance(MyPanel.class);
button = ExtensionButton.builder()
.icon(SwingCommons.getScriptImage())
.tooltip("Script")
.priority(-1)
.panel(panel)
.build();

ExtensionUI ui = injector.getInstance(ExtensionUI.class);
ui.addButton(button);
}

@Override
public void shutdown() {
ExtensionUI ui = injector.getInstance(ExtensionUI.class);
ui.removeButton(button);
}

External Script UIs

Last but not least, you're still able to write standard Swing UIs by extending JFrame as you normally would. This however doesn't come with the features that internal script UIs have, and you'll have to deal with handling quickstart and loading/saving all yourself.

Interested in contributing to the docs? Please let me know your GitHub name using a ticket in our Discord