sb0t protects the chatroom from flooding at two independent layers: a connection-level gate that silently drops rapid reconnections from the same IP, and a per-user message-rate system that tracks packet frequency and repeated content for each logged-in user. Both layers are handled in the main server loop and require no manual configuration beyond enabling theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/AresChat/sb0t/llms.txt
Use this file to discover all available pages before exploring further.
filtering setting.
Layer 1 — Connection Flood Protection
core/ServerCore.cs maintains a dictionary (_connectFlood) that maps IP address strings to a (timestamp, count) tuple. The counter is incremented each time a socket belonging to that IP disconnects, not when it connects:
_connectFlood dictionary is pruned in the 60-second reset loop (see below).
Layer 2 — Per-User Message Rate Limiting
core/FloodControl.cs tracks each user’s packet frequency inside IClient.FloodRecord and makes the flood determination per TCPMsg type.
Packet Counters
For Regular-level users only (client.Level > ILevel.Regular bypasses all per-packet checks), three counters are maintained per 1-second window:
| Counter | Message type | Threshold |
|---|---|---|
packet_counter_main | Public chat (MSG_CHAT_CLIENT_PUBLIC), Emote (MSG_CHAT_CLIENT_EMOTE) | > 3 per second |
packet_counter_pm | Private message (MSG_CHAT_CLIENT_PVT) | > 5 per second |
packet_counter_misc | All other packet types | > 8 per second |
Repeated-Message Detection (IsTextFlood)
A global rolling window of the last 8 public/emote messages (across all users) tracks per-IP post frequency. A user is considered text-flooding if their IP appears 8 consecutive times in the window — i.e., they alone have saturated the last 8 public messages:
last_typer is cleared so the flood trigger resets.
Duplicate-Content Detection
For public messages and emotes, sb0t also checks whether the last 5 messages from a single user are byte-for-byte identical. Ifrecent_posts fills to 5 entries and all match the first, the packet is rejected as a flood:
The AntiFlood Exemption List
commands/AntiFlood.cs maintains an in-memory list of user IDs (ushort) that are allowed to bypass the Flooding() event check. AntiFlood.CanFlood(client) returns true when the user’s ID is in the list, which causes ServerEvents.Flooding() to return false (i.e., “not flooding”):
AntiFlood.Add(client) from a script. The list is reset (AntiFlood.Reset()) at server startup.
The 60-Second Reset Cycle
FloodControl.Reset() clears the last_typer rolling window. It is called:
- Once at server startup.
- Every 60 000 ms (60 seconds) inside the
ServerThreadloop:
FloodRecord) reset independently on the 1-second packet gap described above.
Scripting Hooks
Scripts can intercept and override flood handling through two events:onFloodBefore(userobj, msg)
Called before the server applies its default flood action. Return false to suppress the default response (typically a muzzle or notification). Return true to allow it.
onFlood(userobj)
Called after the flood has been confirmed and the default action has been applied. Use this for logging or secondary responses:
JSScript.cs.
Relevant Settings
Master switch for the message flood filter (
Settings.Filtering). When false, FloodControl.IsFlooding() still runs, but the word filter and related enforcement steps are skipped. Toggle in the GUI Settings → Filtering panel.When
true (Settings.CapsMonitoring), the server monitors excessive use of capital letters in messages. Fires a separate monitoring event; does not use FloodControl directly.When
true (Settings.IdleMonitoring), the server prints a room notice when a user’s idle flag changes. Uses IdleManager, not the flood system.All per-user flood counters and the
AntiFlood exemption list only apply to Regular-level users. Users at Moderator level or above skip every FloodControl check inside FloodControl.IsFlooding() — their messages are never rate-limited or duplicate-checked.