Tangle Dink Plugin combines two workflows in one RuneLite sidebar entry:
- Player-data synchronization against a remote API
- Clan chat webhook forwarding to a configurable endpoint
It also includes a modular sidebar with collapsible feature folders so the plugin can grow without turning the main panel into a hard-coded list of special cases.
The plugin is split into:
api/for HTTP clients and shared request executionsync/for manifest loading, snapshot capture, delta calculation, retry state, and submissionclanchat/for clan message classification, filtering, queueing, and webhook deliverycollectionlog/for the explicit collection-log capture flow and item mappingfeatures/for sidebar feature modules and their panelsui/for the main sidebar panel and navigation
The main plugin stays small. It starts and stops the top-level services, wires RuneLite events to the relevant service methods, and adds the single sidebar button.
Add a new feature module under src/main/java/tccrewplugin/features/..., implement PluginFeature, and register it in FeatureManager. The sidebar navigation is data-driven from the registry, so the navigation UI does not need a new branch for each feature.
Player sync uses:
GET {apiBaseUrl}/api/sync/manifestPOST {apiBaseUrl}/api/sync/submit
The API token is sent as a bearer token. Keep the default apiBaseUrl as a development placeholder until you point it at a real service.
Example manifest:
{
"version": 1,
"varbits": [4101, 4102],
"varps": [1, 2],
"collectionLogItems": [11832, 11834]
}Example submission:
{
"schemaVersion": 1,
"username": "Player Name",
"profile": "STANDARD",
"pluginVersion": "1.0.0",
"capturedAt": "2026-07-17T22:30:00Z",
"data": {
"varbits": {
"4101": 1
},
"varps": {},
"levels": {
"Attack": 99
},
"collectionLog": {
"mappingVersion": 1,
"itemCount": 1572,
"ownedCount": 400,
"slots": "AAQIECBA..."
}
}
}The plugin keeps the last successful snapshot per username and profile type, and only submits deltas.
Clan chat forwarding uses:
POST {clanWebhookEndpoint}
Content-Type: application/json
Authorization: Bearer {clanWebhookSecret}Bearer token mode is the default. A secret-header compatibility mode is also supported, using X-Clan-Webhook-Secret.
The endpoint and secret are configurable at runtime and do not require a RuneLite restart to take effect. Disabling clan webhooks stops delivery immediately.
The clan service only forwards a message when all of the following are true:
- Clan webhooks are enabled
- Endpoint and secret are present
- The player is logged in
- The message type is enabled
- The clan matches
requiredClanNamewhen that filter is set - Guest broadcasts are allowed when the message is guest-related
- The message is not a duplicate
- The message is not plugin-generated loopback text
Matching is case-insensitive and whitespace-normalized.
Guest support is disabled by default. A guest broadcast is only treated as guest-related when the message itself is classified as a guest event. If approvedGuestUsernames is set, only normalized names in that allowlist are accepted.
Webhook payloads are typed and versioned. A simplified example:
{
"schemaVersion": 1,
"eventId": "04bfed56-85fd-4b03-bb63-d3e5129cd88c",
"eventType": "CLAN_CHAT_MESSAGE",
"occurredAt": "2026-07-17T22:45:00Z",
"pluginVersion": "1.0.0",
"player": {
"username": "Local Player",
"profile": "STANDARD",
"world": 420
},
"clan": {
"name": "Example Clan"
},
"message": {
"type": "CHAT",
"sender": "Clan Member",
"senderRank": "GENERAL",
"text": "Example clan message",
"guest": false
}
}Test webhooks are marked as TEST and never impersonate a real clan member.
Enabled clan messages are transmitted to the configured external endpoint and may become visible in downstream systems such as Discord. Player sync submissions are username-based and are not cryptographic proof of account ownership.
The plugin does not log API tokens or webhook secrets. Collection-log capture is explicit user action, not continuous scraping.
Collection-log sync only begins when you trigger the capture action in the sidebar. The plugin does not continuously scrape the collection log in the background.
The test tree includes a lightweight development-only mock server with these endpoints:
GET /api/sync/manifestPOST /api/sync/submitPOST /api/clan/webhook
It sanitizes captured JSON, validates a development token/secret, and can be configured to return retryable status codes such as 429 and 500.
From the plugin root:
./gradlew runThen follow the Jagex account development-client instructions:
https://github.com/runelite/runelite/wiki/Using-Jagex-Accounts
This plugin reimplements the behavior of WikiSync and clan-chat-webhook rather than copying their source code wholesale. The reference projects were inspected for behavior and structure, but no substantial source code was imported into this repository.