hytopia
Version:
The HYTOPIA SDK makes it easy for developers to create massively multiplayer games using JavaScript or TypeScript.
216 lines (189 loc) • 5.21 kB
HTML
<!-- Template for Agent Chat Bubble -->
<template id="agent-chat">
<div class="agent-chat">
<div class="agent-header">
<div class="agent-name"></div>
</div>
<div class="chat-bubble">
<div class="message"></div>
</div>
</div>
</template>
<div id="agent-thoughts-panel">
<h2>Agent Thoughts</h2>
<div id="thoughts-container">
<!-- Thoughts will be inserted here -->
</div>
</div>
<style>
/* Chat Bubble Styles */
.agent-chat {
position: absolute;
top: -40px;
left: 50%;
transform: translateX(-50%);
text-align: center;
pointer-events: none;
width: 500px;
}
.agent-header {
margin-bottom: 8px;
}
.agent-name {
background: #4a5568;
color: white;
padding: 4px 12px;
border-radius: 12px;
display: inline-block;
font-weight: bold;
font-size: 16px;
text-shadow: 0 1px 2px rgba(0,0,0,0.2);
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.chat-bubble {
background: rgba(255, 255, 255, 0.9);
color: black;
padding: 8px 12px;
border-radius: 16px;
width: 100%;
max-width: 500px;
border: 1px solid rgba(0, 0, 0, 0.1);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
opacity: 1;
transition: opacity 0.3s ease;
display: inline-block;
min-width: 200px;
}
.chat-bubble.fade {
opacity: 0;
}
.message {
font-size: 14px;
word-wrap: break-word;
line-height: 1.4;
white-space: pre-wrap;
}
/* Thoughts Panel Styles */
#upgrade-panel {
position: absolute;
right: 20px;
top: 20px;
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 15px;
border-radius: 8px;
min-width: 200px;
font-family: Arial, sans-serif;
}
#agent-thoughts-panel {
position: absolute;
right: 20px;
top: 200px;
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 15px;
border-radius: 8px;
min-width: 250px;
max-width: 300px;
font-family: Arial, sans-serif;
}
#agent-thoughts-panel h2 {
margin: 0 0 10px 0;
font-size: 16px;
color: #3498db;
}
.thought-entry {
margin-bottom: 15px;
padding: 10px;
background: rgba(255, 255, 255, 0.1);
border-radius: 6px;
}
.thought-agent-name {
color: #3498db;
font-weight: bold;
margin-bottom: 5px;
}
.thought-text {
font-style: italic;
font-size: 14px;
line-height: 1.4;
}
/* Add these styles */
.inventory-list {
margin-top: 8px;
font-size: 12px;
color: #aaa;
}
.inventory-item {
display: flex;
justify-content: space-between;
padding: 2px 0;
}
.inventory-item-name {
color: #ddd;
}
.inventory-item-quantity {
color: #888;
}
</style>
<script>
// Register chat bubble template
hytopia.registerSceneUITemplate('agent-chat', (id, onState) => {
const element = document.getElementById('agent-chat').content.cloneNode(true);
const container = element.querySelector('.agent-chat');
const bubble = container.querySelector('.chat-bubble');
const messageEl = container.querySelector('.message');
let fadeTimeout;
onState(data => {
// Set agent name
const nameEl = container.querySelector('.agent-name');
if (nameEl && data.agentName) {
nameEl.textContent = data.agentName;
}
// Agent header is always visible
container.style.display = 'block';
if (data.message) {
// Clear any existing timeout
clearTimeout(fadeTimeout);
// Show new message
messageEl.textContent = data.message;
bubble.classList.remove('fade');
bubble.style.display = 'block';
// Set timeout to fade after 5 seconds
fadeTimeout = setTimeout(() => {
bubble.classList.add('fade');
setTimeout(() => {
bubble.style.display = 'none';
}, 300); // Match transition duration
}, 5000);
} else {
// Hide only the chat bubble if there's no message
bubble.style.display = 'none';
}
});
return element;
});
// Handle received data from server
hytopia.onData((data) => {
console.log(data);
if (data.type === 'agentThoughts') {
const container = document.getElementById('thoughts-container');
container.innerHTML = data.agents.map(agent => `
<div class="thought-entry">
<div class="thought-agent-name">${agent.name}</div>
<div class="thought-text">${agent.lastThought}</div>
${agent.inventory && agent.inventory.length > 0 ? `
<div class="inventory-list">
${agent.inventory.map(item => `
<div class="inventory-item">
<span class="inventory-item-name">${item.name}</span>
<span class="inventory-item-quantity">x${item.quantity}</span>
</div>
`).join('')}
</div>
` : ''}
</div>
`).join('');
}
});
</script>