How to set up the player report system in MU Online
Build a player report system on your MU Online server, from the in-game command to the moderation panel, with a sortable queue, anti-spam and an audit trail so that reports turn into fair, traceable actions.
A MU Online server with no reporting channel becomes a guessing game: the staff only finds out about a problem when someone shouts in Discord or when half the community has already left. A well-built report system flips that around — it brings the structured report to the moderation team, with who,
A MU Online server with no reporting channel becomes a guessing game: the staff only finds out about a problem when someone shouts in Discord or when half the community has already left. A well-built report system flips that around — it brings the structured report to the moderation team, with who, what, when and evidence, inside a queue you can triage. This guide shows how to set up that system end to end: from the in-game command to the moderation queue, with anti-spam to prevent abuse and an audit trail so every action is traceable. The command names, tables and limits mentioned are examples that vary by season/emulator; adapt them to your own setup.
Prerequisites
To build the report system you need:
- Administrative access to the server and the database (SQL Server, MySQL or your emulator's DBMS) with permission to create tables.
- A definition of how the player will report: an in-game chat command, a form on the website, a Discord channel — or a combination.
- Access to the GameServer if you want a native command; otherwise, an alternative path (GM command, external integration) that writes to the same database.
- A moderation interface: it can be an admin page on the website, a simple panel, or even standardized SQL queries at the start.
- A written moderation policy — what is reportable, what the punishments are and the proportionality. Without a clear rule, the system becomes chaos.
- An alert channel (Discord/email) to notify the staff when a high-priority report comes in.
If the server is still being built, lay the foundation first with how to create a MU Online server and come back to add moderation.
Anatomy of a report system
Before setting it up, understand the four parts that every report system has:
- Input — the means by which the player files the report (in-game command, website, Discord).
- Storage — where the report is saved with all the fields needed to investigate.
- Moderation — the queue the staff uses to triage, investigate and decide.
- Action and audit — the punishment applied and the immutable record of who did what and why.
Beginner servers usually build only the input ("I added a /report command") and forget the other three. Then the report drops into a file no one reads. The value is in the queue and the audit, not in the command.
Stage 1 — Model the reports table
Start with storage, because it defines what data the input needs to collect. A minimal structure (example, varies by season/emulator):
CREATE TABLE PlayerReports (
ReportId INT IDENTITY PRIMARY KEY,
ReporterAcc VARCHAR(50) NOT NULL, -- who reported
TargetAcc VARCHAR(50) NOT NULL, -- target
TargetChar VARCHAR(50), -- target character
Category VARCHAR(30) NOT NULL, -- type (bug abuse, insult, cheat...)
Description NVARCHAR(500), -- player's account of events
Evidence NVARCHAR(500), -- screenshot/link/serial if any
MapContext VARCHAR(50), -- map/coords at the moment
Status VARCHAR(20) DEFAULT 'open',
Priority VARCHAR(10) DEFAULT 'normal',
CreatedAt DATETIME DEFAULT GETDATE(),
HandledBy VARCHAR(50), -- GM who took it
Resolution NVARCHAR(500), -- decision made
ResolvedAt DATETIME
);
Note that the table already provides for Status, Priority, HandledBy and Resolution — the fields that turn a loose report into a queue item with an owner and an outcome. Modeling this now avoids rework later.
Stage 2 — Define the report categories
Clear categories speed up triage and educate the player about what is reportable. A typical set:
| Category | Example | Suggested priority |
|---|---|---|
| Cheat/hack | Speed hack, teleport, impossible damage | High |
| Bug abuse | Exploiting an item/quest/event bug | High |
| Fraud/scam | Trade scam, unkept promise | Medium |
| Harassment/insult | Serious offense, hate speech | Medium |
| Spam/flood | Chat pollution, advertising | Low |
| Inappropriate name | Offensive nick | Low |
The priorities are examples that vary by season/emulator and by the server's culture — a hardcore server may treat bug abuse with maximum severity, another may prioritize harassment. What matters is that each category has a default priority so the queue can sort itself.
Stage 3 — Set up the in-game input
The channel closest to the player is the chat command. If your emulator allows a native command, add something like /report <nick> <category> <description>. If you cannot easily touch the GameServer, use one of these alternatives:
- Assisted GM command: the player calls a GM who logs the report — it works, but it depends on staff being online.
- External integration: the player reports via the website/Discord providing the nick, and a service writes to the same table.
When setting up the in-game command, capture the context automatically: the reporter's map and coordinates at the moment, the timestamp and, if possible, the target by proximity. Automatic context is worth more than a typed description, because the player forgets details and the system does not.
Logical flow of the command (pseudocode):
on receiving /report target category description:
if anti_spam_blocks(reporter): reply "wait before reporting again"; return
validate that 'target' exists
write to PlayerReports with context (map, coords, time)
set Priority from the category
if Priority == high: fire alert to staff
reply to the player "report logged, thank you"
Stage 4 — Implement anti-spam and anti-abuse
Reporting is a double-edged sword: without control, players use it to persecute rivals and to flood the queue. Protect the system with:
- Per-reporter cooldown: a maximum number of reports per time window (e.g. N per hour). Prevents individual flooding.
- Deduplication by target: if the same reporter already reported the same target in the same category recently, group them instead of creating a duplicate.
- Coordinated-report detection: many reports against the same target within minutes, coming from linked accounts (same IP, rival guild), is a sign of persecution — flag it for manual review, not for automatic punishment.
- Weight by reporter reputation: reports from people who historically report with merit count more in triage than reports from someone who only files frivolous ones.
Example cooldown check:
-- How many reports has this player filed in the last hour?
SELECT COUNT(*) AS recentes
FROM PlayerReports
WHERE ReporterAcc = @acc
AND CreatedAt > DATEADD(HOUR, -1, GETDATE());
-- If 'recentes' >= limit, block the new report
The key point: a mass report is never automatic proof. It raises the priority for moderation to look at, it does not apply a punishment. Punishment comes from the investigation, not from the report count.
Stage 5 — Build the moderation queue
The staff needs a sortable view, not a raw table. At a minimum, the queue must allow:
- Sorting by priority and age — what is high and old shows up at the top.
- Filtering by status —
open,under review,resolved. - Taking a case — the GM marks
HandledByto prevent two moderators from working the same report. - Seeing the target's history — repeat offenses change the decision.
Base queue query:
-- Work queue: open, most urgent first
SELECT ReportId, TargetChar, Category, Priority, Description, CreatedAt
FROM PlayerReports
WHERE Status = 'open'
ORDER BY
CASE Priority WHEN 'high' THEN 1 WHEN 'normal' THEN 2 ELSE 3 END,
CreatedAt ASC;
Start with standardized queries if you have no panel; evolve to an admin page on the website when the volume grows. The panel is convenience — the sorted queue is the essential part.
Stage 6 — Investigate before acting
The report is the start of the investigation, not the end. When taking a case, the GM should:
- Read the account and the context captured (map, time, attached evidence).
- Confirm with a second source — trade/drop logs, chat logs, movement, or live observation. Report + evidence, never report alone.
- Check the target's repeat offenses in the table history.
- Rule out bad faith by the reporter — persecution, revenge, a frivolous report.
Only after that is the decision made. Punishing based only on the text of a report is the fastest path to injustice and to the community losing trust in the system.
Stage 7 — Action, resolution and audit
When closing the case, record everything:
- Update
Statustoresolved, fill inResolutionwith the decision and the justification, andResolvedAt. - Apply the proportional punishment (warning, mute, kick, suspension, ban) according to the written policy.
- Record the action in a separate, immutable audit trail — who punished, who was punished, why, when and based on which report. This trail protects the staff from accusations of persecution and creates precedent.
Example of an audit record:
INSERT INTO ModerationAudit (ReportId, ModAcc, TargetAcc, Action, Reason, ActedAt)
VALUES (@reportId, @gm, @target, 'suspension_3d', 'bug abuse confirmed by log', GETDATE());
Closing the loop — a report becomes a recorded decision — is what distinguishes a moderation system from a suggestion box no one reads.
Stage 8 — Feedback to the reporter and transparency
A system that swallows reports without any return loses buy-in. Without exposing third-party punishment details, give the reporter a sign that the report was handled: a "your report was reviewed and the appropriate action was taken" already sustains trust. Publishing general statistics (how many reports per week, average response time) without names reinforces the perception that moderation works.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| No one reads the reports | Only the input was built, no queue | Model status/priority and build the triage queue |
| Players flood reports | No anti-spam | Apply a per-reporter cooldown and deduplication by target |
| Punishment challenged as persecution | No audit trail | Record each action with its base report and justification |
| Mass report punishing the innocent | Count treated as proof | A report raises priority; punishment comes from the investigation |
| Two GMs work the same case | No "taken by" field | Use HandledBy and the "under review" status |
| Reporter gives up on the system | No feedback | Give a minimal return that it was reviewed |
| Queue grows endlessly | No prioritization/retention | Sort by priority and set retention per type |
Launch checklist
- Reports table modeled with status, priority, owner and resolution
- Report categories defined with a default priority
- Input set up (in-game command, website or Discord) capturing automatic context
- Anti-spam active (cooldown, deduplication, coordinated-report detection)
- Sortable moderation queue (sort, filter, take a case)
- Written moderation policy communicated to the community
- High-priority alert reaching the staff (Discord/email)
- Investigation procedure with a defined second source
- Immutable audit trail recording each action
- Minimal feedback to the reporter implemented
- Report retention policy aligned with the server logs
- Team trained never to punish based on a report without evidence
A report system is not a command — it is a flow: structured input, prioritized queue, evidence-based investigation and an immutable audit. Build the four parts and reports stop being noise and turn into fair, traceable action, which is what keeps your server's community trusting the moderation.
Frequently asked questions
Do I need to modify the emulator to have in-game reporting?
It depends on how you implement it. A chat command that writes to a database may require touching the GameServer if you want a native command, but you can work around it with a GM command that simply logs the report, or with an external channel (website/Discord) integrated with the same database. The degree of modification varies by season/emulator.
How do I stop players from using reports to persecute rivals?
With anti-spam and a repeat-offense threshold. Limit reports per player per time window, group reports by target, and treat a coordinated mass report as suspicious, not as proof. Moderation always confirms with evidence (log, screenshot, testimony) before punishing. The exact limits vary by season/emulator.
Is anonymous reporting better than identified reporting?
Each has a trade-off. Anonymous reduces fear of retaliation and increases volume; identified holds the reporter accountable and discourages abuse. Many servers use identified internally (the staff sees who reported) but anonymous toward the target (the reported player never finds out). Choose according to your server's culture.
How long should I keep the reports?
Keep reports that led to a punishment and those from repeat offenders for a long time, because historical context weighs on future decisions. Frivolous reports or ones resolved without action can have shorter retention. Align this with your log policy. The ideal periods vary by season/emulator and database capacity.
Does the report system replace active moderation?
No. It is a signal input, not a substitute for a present GM. Reporting brings the problem to you faster, but investigating, deciding and applying the punishment is still up to the team. A good system saves the moderation's time; it does not eliminate it. The weight varies by season/emulator.