How the PHPDTS Chat System Retrieves and Displays Messages Using getchat()
The PHPDTS chat system relies on the getchat() function defined in include/global.func.php to query the MySQL chat table for new messages, format them as HTML based on message type, and deliver them via JSON endpoints or direct template rendering.
The PHPDTS (PHP Deathmatch Translation System) repository implements a lightweight chat subsystem that bridges database storage and real-time browser updates. Understanding how to retrieve and display messages in this open-source game engine requires examining the getchat() function, which serves as the central retrieval mechanism for all chat-related views. This implementation pattern supports both AJAX polling for live updates and server-side rendering for full page loads.
How getchat() Retrieves Messages from the Database
The core retrieval logic resides in include/global.func.php between lines 82 and 120. When invoked, getchat() accepts three parameters: $last (the last message ID the client knows), $team (the current player's team ID), and $chatlimit (maximum rows to return).
First, the function determines the fetch limit. If the caller does not supply a limit, the global $chatlimit value is used as the default.
Next, it executes a selective SQL query against the chat table:
$result = $db->query(
"SELECT * FROM {$tablepre}chat WHERE cid>'$last'
AND (type!='1' OR (type='1' AND recv='$team'))
ORDER BY cid desc LIMIT $limit"
);
This query implements privacy controls for team-only chat (type = 1). Messages marked as type 1 only appear in results when the current player belongs to the same $team as the recipient specified in the recv column. The descending order by cid ensures the newest messages appear first.
Formatting and Sanitizing Chat Output
After retrieval, getchat() prepares a result container array containing lastcid (tracking the highest message ID processed) and an empty msg list. The function then iterates over each database row to construct HTML fragments.
Location and Metadata Preparation
Some chat types reference map locations. According to the source at global.func.php#L89-L92, the function builds $tplsinfo by merging $plsinfo and $hplsinfo arrays so that place names display correctly in message contexts.
Message Processing Pipeline
For each row, the function performs three critical transformations:
- Security sanitization – Raw messages pass through
htmlspecialchars()to prevent XSS attacks. - Emoji replacement – Tokens like
[emoji]convert to<img>tags for graphical display as seen atglobal.func.php#L96-L98. - Type-based formatting – Different CSS classes apply based on the chat type (global, clan, system, death, etc.).
The HTML construction follows this pattern for normal global chat (type 0) at global.func.php#L99-L114:
$msg = "【{$chatinfo[$chat['type']]}】{$chat['send']}:{$chat['msg']}"
.date("(H:i:s)", $chat['time']).'<br>';
Other types receive specific styling classes such as clan, lime, red, or yellow to differentiate system announcements from player dialogue.
Delivering Messages to the Frontend
The PHPDTS architecture supports multiple consumption patterns for chat data, enabling both real-time updates and static page rendering.
AJAX Polling via chat.php
The chat.php script serves as the primary endpoint for live chat updates. It calls getchat($lastcid, $teamID) and encodes the result as JSON:
$chatdata = getchat($lastcid, $teamID);
echo compatible_json_encode($chatdata);
Client-side JavaScript polls this endpoint every few seconds, injecting new HTML fragments into the chat panel and updating the lastcid cursor to avoid duplicates.
Full Page Rendering in game.php
For initial page loads, game.php fetches the complete chat history by passing 0 as the last CID:
$chatdata = getchat(0, $teamID);
$emdata = get_emdata();
include template('chat');
The templates/nouveau/chat.htm template receives the $chatdata['msg'] array and iterates over it to print formatted messages directly into the HTML response.
News Integration
The news.php file demonstrates alternative usage by calling getchat(0,'',$chatinnews) to embed recent chat activity within news views, proving the function's flexibility across different contexts.
Code Implementation Examples
Inserting a Chat Message
When players submit messages, chat.php handles the database insertion:
if ($sendmode == 'send' && $chatmsg) {
$db->query(
"INSERT INTO {$tablepre}chat (type,`time`,send,msg)
VALUES ('0','$now','$cuser','$chatmsg')"
);
}
Client-Side Polling Implementation
The browser polls for updates using JavaScript:
setInterval(function () {
fetch('chat.php?lastcid=' + lastSeenCid)
.then(r => r.json())
.then(data => {
Object.values(data.msg).forEach(html =>
chatBox.insertAdjacentHTML('beforeend', html)
);
lastSeenCid = data.lastcid;
});
}, 2000);
Server-Side Template Rendering
The returned data structure follows this associative array format:
[
'lastcid' => 15420,
'msg' => [
15418 => '【全体】Player1:Hello world!(14:32:01)<br>',
15419 => '【队伍】Player2:Strategy?<br>',
15420 => '<span class="red">【系统】Player3 has died.</span><br>'
]
]
Summary
getchat()ininclude/global.func.phpserves as the central retrieval function for all chat operations, querying the MySQLchattable with CID-based pagination.- Privacy filtering occurs at the database level, ensuring team-only messages (
type = 1) only reach authorized team members via the$teamparameter. - Output formatting combines
htmlspecialchars()sanitization, emoji token replacement, and type-specific CSS classes to generate safe, styled HTML fragments. - Dual delivery modes support both AJAX JSON responses through
chat.phpand server-side template rendering ingame.phpandnews.php. - Cursor-based pagination using
lastcidprevents duplicate message delivery during long polling cycles.
Frequently Asked Questions
How does getchat() filter team-only messages in PHPDTS?
The function applies SQL-level filtering in the WHERE clause: AND (type!='1' OR (type='1' AND recv='$team')). This ensures rows with type = 1 (team-only) only return when the current player's team ID matches the recv column value. Global messages (type 0) bypass this restriction and appear for all users.
What data structure does getchat() return?
The function returns an associative array containing two keys: lastcid (an integer representing the highest message ID processed) and msg (an array mapping CID integers to HTML strings). This structure allows callers to track synchronization state while receiving ready-to-render message fragments.
How are emojis rendered in the PHPDTS chat system?
During message iteration, getchat() applies a replacement function that transforms [emoji] tokens into <img> tags. This occurs after htmlspecialchars() sanitization but before HTML concatenation, ensuring emoji images render safely within the formatted output strings stored in $chatdata['msg'].
Which files are responsible for displaying chat messages?
Three primary files handle display: chat.php (AJAX JSON endpoint for live updates), game.php (full-page server-side rendering using templates/nouveau/chat.htm), and news.php (embedding chat within news views). All three rely on getchat() defined in include/global.func.php for message retrieval.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →