chat: player-to-player tavern chat (4.3.0)
- backend: in-memory ring buffer POST/GET /agents/tavern-chat
{id,name,text}, last ~60, control-char sanitized
- RpgTavern: Enter/T (or 💬) opens a chat bar; your line floats as a
canvas speech bubble above your avatar for ~5.5s AND lands in a small
chat log; others' bubbles render above their avatars (keyed by presence
id); typing freezes movement
- verified across two browsers: A's message appeared in B's log and as a
bubble over A's avatar
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
a22e5407ab
commit
3b92827563
@ -17,7 +17,7 @@
|
||||
@media (prefers-reduced-motion: reduce) { .app-loading-gem { animation: none; transform: rotate(45deg); } }
|
||||
</style>
|
||||
<meta name="description" content="amerc is the agent mercenary tavern — hire, run, publish, and remotely deliver AI agents across software boundaries. No infrastructure, just skills." />
|
||||
<meta name="version" content="4.2.0-world" />
|
||||
<meta name="version" content="4.3.0-chat" />
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||
<link rel="icon" href="/app-192.png" type="image/png" sizes="192x192" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "amerc-site",
|
||||
"version": "4.2.0-world",
|
||||
"version": "4.3.0-chat",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@ -133,6 +133,8 @@ function presenceList(exclude) {
|
||||
for (const [k, v] of presence) { if (now - v.at > PRESENCE_TTL) { presence.delete(k); continue; } if (k !== exclude) out.push(v); }
|
||||
return out.slice(0, 50);
|
||||
}
|
||||
// tavern chat: a tiny in-memory ring buffer of recent player messages.
|
||||
const tavernChat = []; let chatSeq = 0;
|
||||
// file rendezvous: producer's request stream is piped to the consumer's
|
||||
// response when it claims the token. The server never writes the bytes.
|
||||
const FILE_CLAIM_MS = 5 * 60 * 1000;
|
||||
@ -544,6 +546,20 @@ const server = http.createServer(async (req, res) => {
|
||||
}
|
||||
if (path === '/agents/presence' && method === 'GET') return send(res, 200, { ok: true, players: presenceList(null) });
|
||||
|
||||
// tavern chat (public lobby chat — bubbles + a small log)
|
||||
if (path === '/agents/tavern-chat' && method === 'POST') {
|
||||
const b = await readBody(req) || {};
|
||||
const text = String(b.text || '').replace(/[ | ||||