Break Handler
BreakHandlerPlugin is a native break-scheduling plugin registered in
runelite-plugin.properties (config group n3breakhandler, disabled by default).
The plugin ports PiggyPlugins' ChinBreakHandler onto the n3 surfaces.
Architecture
BreakHandlerPlugin- lifecycle, nav button, login-screen/logout state machine, auto bank pin.BreakHandler-@SingletonRxJava3 service bus; registry of consumer plugins, planned/active breaks, and break statistics. The shared coordination point other plugins inject.State- state-machine enum (NULL,LOGIN_SCREEN,INVENTORY,RESUME,LOGOUT*).OptionsConfig/NullConfig- RuneLite config interfaces for the Options tab.ui/-BreakHandlerPanel(tabbed: Plugins / Accounts / Options),BreakHandlerPluginPanel(per-plugin spinners + AFK/Logout),BreakHandlerStatusPanel(live countdown),BreakHandlerAccountPanel(login source),LoginMode.util/-ConfigPanel(generic RuneLite config renderer), spinners/formatters,OnOffToggleButton,IntRandomNumberGenerator,SwingUtilExtended.syncExec.
Reactive bus
BreakHandler exposes RxJava3 Observables (PublishSubject.hide()) for plugin
registration, active plugins, planned breaks, active breaks, the current break,
extra data, and login/logout actions. Panels and the plugin subscribe to drive
their UI and the state machine. currentActiveBreaksSubject carries a
Map.Entry<Plugin, Instant> (AbstractMap.SimpleImmutableEntry) - the n3 port's
replacement for org.apache.commons.lang3.tuple.Pair.
Consumer API
Another plugin injects BreakHandler and calls:
registerPlugin(plugin)/unregisterPlugin(plugin)- appear in the panel.startPlugin(plugin)/stopPlugin(plugin)- begin/stop tracking runtime + breaks.isBreakActive(plugin)/shouldBreak(plugin)- gate work loops.setExtraData(plugin, key, value)- surface live status in the panel.
The plugin schedules breaks itself from the per-plugin threshold spinners; a consumer only needs to register, start, and pause its work while a break is active.
Full automation contract
Full automation plugins must integrate with BreakHandler as an active-only
runtime requirement:
- Register with
registerPlugin(this)on plugin startup andunregisterPlugin(this)on shutdown. - Call
startPlugin(this)only while automation is actively running, andstopPlugin(this)when the plugin is idle, disabled, complete, halted, or shutting down. - Before issuing gameplay actions, check
shouldBreak(this)andisBreakActive(this). If a planned break is due, callstartBreak(this), release any input lock, and skip the action tick.
The current required full automation plugins are Market Alcher, Power Skiller, Tree Woodcutter, Woodcutter, Tutorial Island, Guardians of the Rift, Mule Orchestrator, Bank Stander, Wood Fletcher, GE Buyer, and AIO Fighter. Dialogue Helper, Walk Assistant, Questing Assistant, and Combat Awareness are treated as QoL/helper plugins and are intentionally exempt from this hard requirement. Registered suite/support plugins such as Packet Utils, Profiles, Code Console, Break Handler, Agent Server, and Developer Tools are classified separately in the guardrail because they do not own full automation loops.
State machine
onGameTick drives logout (ESC → logout tab → logout button via
MousePackets/WidgetPackets) and login-screen re-entry through
BlockingEventActions.continueWelcomeScreen(), which resolves visible legacy or
Jagex welcome-screen click targets without hard-coded child IDs in Break Handler.
seconds() (1 Hz RxJava interval)
performs the re-login when all active breaks have elapsed and the client is on
the login screen. Auto bank pin types the PIN one digit per tick against widget
(213, 0) and blocks key presses via VarClientInt.BLOCK_KEYPRESS.
Login sources (Accounts tab)
LoginMode | Re-login behavior |
|---|---|
MANUAL | Username/password/bank-pin entered directly in the tab (n3breakhandler config). |
PROFILES | Reads the n3 Profiles typed ProfileStore (see below). Enabled only when an n3 Profiles unlock password is configured. |
LAUNCHER | Jagex Launcher session already present; just sets GameState.LOGGING_IN. |
Profiles integration (Part C)
When LoginMode.PROFILES is selected, the break handler reads the unified
com.n3plugins.n3Profiles.ProfileStore (decrypted with the configured n3 Profiles
unlock password), not a local credential cache:
- The Accounts dropdown lists
StoredProfile.getLabel()for every stored profile. seconds()re-login looks up the selected label:- LEGACY →
ProfileLoginService.applyLegacyProfile(login, password, false)thenGameState.LOGGING_IN. - JAGEX →
ProfileLoginService.applyJagexProfile(sessionId, characterId, displayName)thenGameState.LOGGING_IN.
- LEGACY →
BreakHandler.getBankPin(ConfigManager)returns the selected LEGACY profile's 4-digit pin, falling back to the manual bank-pin config when the profile has no usable pin or the store is unavailable.
ProfileStore is injected (constructible from ConfigManager alone), so the break
handler reads the same encrypted blob without any cross-plugin singleton sharing.
Configuration (Options tab)
stopAfterBreaks, autoBankPin, autoLoginOnDisconnect, avoidWorldsPlayerCount,
avoidWorldsNumbers, and the Hopping section (hop-after-break, american,
united-kingdom, german, australian). Per-plugin: <plugin>-thresholdfrom/to,
<plugin>-breakfrom/to, <plugin>-enabled, <plugin>-logout.
Testing
.\gradlew.bat test --tests com.n3plugins.breakhandler.* --console plain
LoginModeTest-parse(case-insensitive, null, unknown).IntRandomNumberGeneratorTest- inclusive range, singleton range.BreakHandlerTest-getBankPin(manual, PROFILES fallback, null guards),getOrDefaultFrom/To, plugin registry,shouldBreak,startBreakcounting.AutomationBreakHandlerRegistrationTest- source-level guardrail for required full automation plugin registration, active lifecycle calls, break gating, helper-plugin exemptions, and registered support-plugin classification.
Client-dependent paths (state machine, packet sends, world hopping) are not unit
tested - N3Client is null in the test JVM. See Profiles for the store.
Live validation (pending)
Logout/login state machine on rev239, auto bank pin entry, world hopping filters, PROFILES re-login for both LEGACY and JAGEX profiles end-to-end.
Break Handler Integration Flow
The Break Handler manages breaks using an RxJava3 event bus. Active full automation plugins monitor this status to pause execution, and the Break Handler executes logouts/logins as needed.