# PostCommand

The PostCommand plugin provides a global announcement system that allows players to broadcast messages to all online users using a chat command. This is useful for creating community engagement, allowing players to share important information, or enabling server-wide communication.

## File Location

`GameServer/Data/Plugins/PostCommand.xml`

## Dependencies

| Depends On | Purpose                                         |
| ---------- | ----------------------------------------------- |
| None       | Standalone plugin with no external dependencies |

## Configuration Sections

### Command

Defines the command name and whether the feature is enabled.

| Attribute | Type    | Default | Description                                                                                                                                                                                            |
| --------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `name`    | string  | "/post" | The chat command that triggers the global broadcast. Players type this followed by their message (e.g., `/post Hello everyone!`). Can be changed to any command name like `/announce` or `/broadcast`. |
| `enabled` | boolean | true    | Master switch for the entire plugin. Set to `false` to disable the command without removing the configuration. Useful for temporarily disabling during maintenance or events.                          |

### Cooldown

Controls how frequently players can use the command to prevent spam.

| Attribute | Type | Default | Description                                                                                                                                                                                                                                                                                                          |
| --------- | ---- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `seconds` | int  | 10      | Cooldown duration in seconds between uses per player. Each player has their own cooldown timer that starts when they successfully send a message. Set to `0` to disable cooldown entirely. Value of `60` means players can broadcast once per minute. Prevents spam while allowing reasonable community interaction. |

### Restrictions

Defines access requirements and message limitations.

| Attribute          | Type | Default | Description                                                                                                                                                                                                                                            |
| ------------------ | ---- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `maxMessageLength` | int  | 100     | Maximum number of characters allowed in the broadcast message (excluding the command itself). Prevents excessively long messages that could disrupt chat. Value of `100` allows for a complete sentence. Value of `200` allows more detailed messages. |
| `minLevel`         | int  | 1       | Minimum character level required to use the command. Value of `1` allows all players. Value of `100` restricts to mid-level characters. Value of `400` limits to endgame players. Use higher values to prevent spam from new accounts.                 |
| `minVIP`           | int  | 0       | Minimum VIP level required to use the command. Currently not enforced (VIP check is not implemented in the code). Prepared for future VIP system integration. Value of `0` means no VIP requirement.                                                   |

## Important Behavior

{% hint style="info" %}
The cooldown is tracked **per player**, not globally. Each player has their own independent cooldown timer. If Player A uses the command, Player B can still use it immediately afterward.
{% endhint %}

{% hint style="warning" %}
The cooldown timer uses `GetTickCount()` internally, which measures elapsed time. If the server is under heavy load or experiences lag, the cooldown timing remains accurate based on real elapsed time, not game ticks.
{% endhint %}

### Message Processing

1. **Command detection**: The plugin checks if the chat message starts with the configured command name (case-insensitive comparison)
2. **Content extraction**: The command name and any leading spaces are stripped from the message
3. **Validation sequence**:
   * Empty message check (must have content after command)
   * Player connection verification
   * Level requirement check
   * Message length validation
   * Cooldown enforcement
4. **Broadcast**: Message is sent to all online players via global chat (appears in chat window, not as center-screen notice)
5. **Logging**: All successful broadcasts are logged with player name and message content

{% hint style="info" %}
When a player attempts to use the command but fails a check (cooldown, level, length), they receive a private error message explaining why their broadcast was rejected. Other players do not see failed attempts.
{% endhint %}

### Chat Hook Integration

The plugin intercepts chat messages before they reach the legacy chat system. When a message starts with the configured command, the plugin:

* Returns `true` to mark the message as handled, preventing it from being processed as a normal chat message
* Broadcasts the content to all players if validation passes
* Shows an error message to the sender if validation fails

This means that `/post Hello` will never appear in normal chat - it's either broadcasted globally or rejected with an error.

## Examples

{% tabs %}
{% tab title="Default Configuration" %}

```xml
<?xml version="1.0" encoding="utf-8"?>
<PostCommand>
    <!-- Command Settings -->
    <Command name="/post" enabled="true" />

    <!-- Cooldown between uses (seconds) -->
    <Cooldown seconds="10" />

    <!-- Restrictions -->
    <Restrictions
        maxMessageLength="100"
        minLevel="1"
        minVIP="0"
    />
</PostCommand>
```

Standard setup with 10-second cooldown, 100-character limit, and no level restriction. Suitable for most servers.
{% endtab %}

{% tab title="Strict Anti-Spam" %}

```xml
<?xml version="1.0" encoding="utf-8"?>
<PostCommand>
    <!-- Command Settings -->
    <Command name="/post" enabled="true" />

    <!-- 2-minute cooldown to reduce spam -->
    <Cooldown seconds="120" />

    <!-- Restrictions -->
    <Restrictions
        maxMessageLength="150"
        minLevel="50"
        minVIP="0"
    />
</PostCommand>
```

Stricter configuration with 2-minute cooldown and level 50 requirement. Reduces spam from new accounts while allowing slightly longer messages.
{% endtab %}

{% tab title="VIP-Only Broadcasts" %}

```xml
<?xml version="1.0" encoding="utf-8"?>
<PostCommand>
    <!-- Command Settings -->
    <Command name="/announce" enabled="true" />

    <!-- Short cooldown for VIP users -->
    <Cooldown seconds="5" />

    <!-- Restrictions -->
    <Restrictions
        maxMessageLength="200"
        minLevel="10"
        minVIP="1"
    />
</PostCommand>
```

Premium configuration for VIP-only announcements with custom command name `/announce`, short cooldown, and extended message length. Note: VIP check is currently not enforced in code (future feature).
{% endtab %}

{% tab title="Event Mode" %}

```xml
<?xml version="1.0" encoding="utf-8"?>
<PostCommand>
    <!-- Temporarily disable during automated events -->
    <Command name="/post" enabled="false" />

    <!-- Cooldown between uses (seconds) -->
    <Cooldown seconds="10" />

    <!-- Restrictions -->
    <Restrictions
        maxMessageLength="100"
        minLevel="1"
        minVIP="0"
    />
</PostCommand>
```

Configuration with plugin disabled. Use this during server-wide events or maintenance when you want to temporarily silence player broadcasts without changing other settings.
{% endtab %}
{% endtabs %}

## Common Issues

{% hint style="warning" %}
**Players see "Please wait X seconds" even though the cooldown period should be over**

The cooldown calculation divides by 1000 to convert milliseconds to seconds. Due to `GetTickCount()` wraparound (occurs approximately every 49.7 days), cooldowns may behave unexpectedly if the server has been running continuously for extended periods. Restart the GameServer process monthly to prevent this rare edge case.
{% endhint %}

{% hint style="warning" %}
**Message appears truncated in chat even though it's under the character limit**

The `maxMessageLength` validation checks the extracted message content (after removing the command name and spaces). However, client-side chat UI may have additional display limitations. If players report truncation, reduce `maxMessageLength` to match client chat window constraints (typically 80-100 characters).
{% endhint %}

{% hint style="info" %}
**Changing the command name requires server restart**

Configuration is loaded during plugin initialization (`Init()`) and when `Reload()` is called. If you change the command name or other settings, restart the GameServer to apply changes. Future versions may support runtime reload via GM command.
{% endhint %}

{% hint style="danger" %}
**VIP restriction does not work**

The `minVIP` attribute is present in the configuration and loaded by the plugin, but the actual VIP level check is not implemented in the code (see line 123-124 in `PostCommandFeature.cpp` - TODO comment). Setting `minVIP` to non-zero values will have no effect until the VIP system integration is completed. Use `minLevel` for access control instead.
{% endhint %}

## Gameplay Impact

### Server Community

* **Increases player interaction**: Players can share achievements, organize parties, or coordinate PvP battles
* **Reduces isolation**: New players can ask questions to the entire server rather than hoping someone is nearby
* **Creates social atmosphere**: Server feels more alive with community announcements

### Potential Concerns

* **Spam risk**: Without proper cooldowns, players can flood chat with repeated messages
* **Off-topic content**: Players may use broadcasts for non-game-related messages
* **Language issues**: Mixed-language servers may have difficulty moderating content

### Recommended Settings by Server Type

| Server Type                         | Cooldown | Min Level | Message Length | Rationale                                        |
| ----------------------------------- | -------- | --------- | -------------- | ------------------------------------------------ |
| **Small Community (<100 players)**  | 10-30s   | 1         | 100-150        | Encourage interaction with minimal restrictions  |
| **Medium Server (100-500 players)** | 30-60s   | 50        | 100            | Balance spam prevention with accessibility       |
| **Large Server (500+ players)**     | 60-120s  | 100       | 80             | Strict control to prevent chat overload          |
| **Competitive/PvP Focus**           | 5-15s    | 1         | 80             | Allow quick coordination but limit length        |
| **Premium/VIP Focus**               | 5-10s    | 10        | 200            | Reward VIP users (when VIP check is implemented) |

## Technical Notes

### Performance

* **Memory usage**: Static cooldown array allocates 4 bytes × `MAX_OBJECT` (typically 5000) = 20KB
* **CPU overhead**: Minimal - only processes chat messages that start with the command string
* **Network impact**: Broadcasts use global chat packet, same as GM announcements

### Cooldown Storage

Cooldown timestamps are stored in a static array indexed by player index. This means:

* Cooldowns persist while the player remains connected
* Cooldowns reset when the player disconnects and reconnects
* Cooldowns are lost on server restart
* Maximum concurrent cooldowns = `MAX_OBJECT` (server capacity)

### Thread Safety

The plugin hooks the chat system which runs on the main game thread. All validation and broadcast operations are thread-safe because they execute synchronously within the chat handler. No mutex or lock is required.
