promotional bannermobile promotional banner

BubbleChat

Smooth, animated speech bubbles above players when they chat. Word-by-word reveal, auto-sizing, multi-line wrapping, page indicators, mouth animations, custom colors, and a full per-player settings GUI.

File Details

BubbleChat-1.1.0.jar

  • R
  • Mar 10, 2026
  • 793.94 KB
  • 70
  • Early Access

File Name

BubbleChat-1.1.0.jar

Supported Versions

  • Early Access

v1.1.0

New Features

  • RP Channels — Private roleplay channels with PIN-based joining. Up to 3 channel slots per player. Chat prefixes (rp1, rp2, rp3) to send to specific channels, pbc to force public
  • Dual Visibility — Players in a channel can opt to show bubbles publicly while also sending [RP] text to channel members
  • Channel Confirmation UI — Optional confirmation prompt before switching channels via chat prefix
  • Per-channel Bubble Colors — Distinct tint colors for rp1/rp2/rp3 channels with per-viewer overrides
  • RP Cull Distance — Separate cull distance setting for RP channel bubbles (default 10M)
  • Yell Bubble Range — Separate range for yell-amplified bubble visibility (default 50M)
  • Yell Particle Range — Separate range for yell particle effect visibility (default 75M)
  • Channels Settings Page — New GUI page for managing channel slots, dual visibility, and confirmation toggle
  • Enable/Disable Toggle — Added enable/disable toggle to the main settings page (replaces yell on/off toggle)
  • BubbleChat API — Added UUID-based hasActiveBubble(UUID) overload for cross-plugin reflection
  • BusyBubble API — New BusyBubbleAPI class in ThinkingBubble for cross-plugin communication

Bug Fixes

  • NullPointerException on connect — Added null checks for particleSpawners and particleSystems fields before batching, preventing NPE when cached packets have null maps
  • Particle config log spam — Batched all particle spawner/system packets into 2 combined packets on connect (down from 11+ individual sends), reducing [AssetUpdate] client log messages
  • Channel chat crash — Fixed store.getComponent() called from async chat handler thread instead of world thread, causing silent assertion failure that blocked all channel messages
  • Text persists after bubble expires — Fixed despawn packets sent to wrong viewer set because activeSpeech.remove() was called before getViewers(), breaking channel isolation lookup
  • Dual visibility one-sided — Fixed [RP] text not reaching channel members due to race condition between deferred world.execute() delivery and synchronous vanilla target removal
  • Channel members missing dual-visibility bubble — Fixed getViewers() filtering out channel members from dual-visibility bubbles that should be visible to everyone
  • BusyBubble coexists with BubbleChat — Added bidirectional priority: speech bubbles clear thinking bubbles on send, thinking bubbles won't spawn while a speech bubble is active
  • BusyBubble reflection silently failing — Fixed method lookup targeting PlayerRef parameter instead of UUID, causing the suppression check to always return false
  • Cross-world bubble visibility — Added world UUID check in getViewers() to skip viewers in different world instances (e.g. dungeon portals)

Optimizations

  • getViewers() — Cached prefsStorage.getPrefs() once per viewer (was called up to 4 times per viewer)
  • sendYellParticle() — Cached viewer prefs once per viewer instead of 2 separate lookups
  • performDespawn() / clearSpeech() — Replaced stream().mapToInt().toArray() with direct int[] construction via shared collectDespawnIds() helper
  • clearSpeech() — Eliminated duplicate despawnIds list building (was built twice — before and after state removal)

Compatibility

  • BusyBubble — Full bidirectional priority: speech bubbles clear any active thinking bubble on send, and thinking bubbles won't spawn while a speech bubble is active. When a UI opens, any active speech bubble is also cleared.