Fix game server communication by updating ai-fiction.js and adding socket.io script

This commit is contained in:
2025-04-01 10:28:53 +02:00
parent 39c1b6ff0a
commit b6472aa275
2 changed files with 82 additions and 48 deletions
+45 -23
View File
@@ -1,43 +1,65 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Interactive Fiction</title> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<!-- meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'blob'; style-src 'self' 'unsafe-inline'" -->
<title>ai-fiction Book Runtime</title>
<link rel="stylesheet" href="css/style.css"> <link rel="stylesheet" href="css/style.css">
<script src="https://cdn.socket.io/4.6.0/socket.io.min.js"></script>
<script src="js/smartypants.js"></script>
<script src="js/tts-handler.js"></script>
<script src="js/ai-fiction.js"></script>
</head> </head>
<body> <body>
<p id="versions">We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.</p>
<div id="book"> <div id="book">
<div id="lighting"></div>
<div id="page_left"> <div id="page_left">
<div class="header"> <div class="header">
<h1>AI Interactive Fiction</h1> <h2 class="byline l10n-by">powered by Generative AI</h2>
<h2 class="byline">A modern take on text adventures</h2> <h1 class="title">AI Interactive Fiction</h1>
<h3 class="subtitle">An open-world text adventure</h3>
<div class="separator"><double></double></div>
</div> </div>
<div class="separator"> <div id="controls" class="buttons">
<double class="separator">&#8902;</double> <a class="l10n-speech" id="speech" title="Toggle text to speech" disabled="disabled">speech</a>
<span><a id="speed_reset"><span class="l10n-speed">speed<sup>*</sup></span></a><input type="range" min="0" max="100" value="50" id="speed" name="speed" /></span>
<a class="l10n-restart" id="rewind" title="Restart story from beginning" disabled="disabled">restart</a>
<a class="l10n-save" id="save" title="Save progress">save</a>
<a class="l10n-load" id="reload" title="Reload from save point" disabled="disabled">load</a>
</div> </div>
<div id="story"></div> <div id="choices" class="container">
<div id="command_history">
<!-- Previous commands and responses will be displayed here -->
</div>
<div id="command_input">
<input type="text" id="player_input" placeholder="Enter your command..." autofocus>
<button id="submit_command">Submit</button>
</div>
</div>
<div class="l10n-remark" id="remark"><i><sup>*</sup>click on page or press spacebar to fast forward text animation</i></div>
</div> </div>
<div id="page_right"> <div id="page_right">
<div id="controls"> <div id="story" class="container">
<a href="#" id="rewind">Restart</a>
<a href="#" id="speech">Speech</a>
<span>Speed <input type="range" id="speed" min="0" max="100" value="50"> <a href="#" id="speed_reset">Reset</a></span>
<a href="#" id="save">Save</a>
<a href="#" id="reload">Load</a>
</div>
<div id="command_history"></div>
<div id="command_input">
<input type="text" id="player_input" placeholder="Enter your command..." autocomplete="off">
<button id="submit_command"></button>
</div> </div>
</div> </div>
</div> </div>
<div id="ruler"></div> <div id="ruler"></div>
<div class="l10n-prompt" id="indent">What do you want to do next?</div>
<div id="lighting" />
<!-- Socket.io library for client-server communication -->
<script src="/socket.io/socket.io.js"></script>
<!-- You can also require other files to run in this process -->
<script src="js/smartypants.js"></script>
<script src="js/linked-list.js"></script>
<script src="js/linebreak.js"></script>
<script src="js/knuth-and-plass.js"></script>
<script src="js/Hyphenopoly_Loader.js"></script>
<script>
var locale = "en";
</script>
<script src="js/ai-fiction.js"></script>
<script src="js/tts-handler.js"></script>
</body> </body>
</html> </html>
+20 -8
View File
@@ -74,15 +74,15 @@ class AIFiction {
// Toggle speech // Toggle speech
this.speechButton.addEventListener('click', () => { this.speechButton.addEventListener('click', () => {
if (tts.isReady()) { if (ttsHandler && typeof ttsHandler.isEnabled === 'function') {
const enabled = tts.toggle(); const enabled = ttsHandler.toggle();
this.updateSpeechButton(enabled); this.updateSpeechButton(enabled);
if (enabled) { if (enabled) {
// Speak the last narrative if speech was just enabled // Speak the last narrative if speech was just enabled
const lastNarrative = this.storyContainer.lastElementChild; const lastNarrative = this.storyContainer.lastElementChild;
if (lastNarrative && lastNarrative.classList.contains('narrative')) { if (lastNarrative && lastNarrative.classList.contains('narrative')) {
tts.speak(lastNarrative.textContent); ttsHandler.speak(lastNarrative.textContent);
} }
} }
} else { } else {
@@ -156,6 +156,15 @@ class AIFiction {
// Narrative response received // Narrative response received
this.socket.on('narrativeResponse', (data) => { this.socket.on('narrativeResponse', (data) => {
// Clear any pending "thinking" indicators
if (this.currentCommandTimeout) {
clearTimeout(this.currentCommandTimeout);
this.currentCommandTimeout = null;
// Remove any existing thinking indicators
document.querySelectorAll('.thinking').forEach(el => el.remove());
}
this.addNarrative(data.text); this.addNarrative(data.text);
if (data.suggestions && data.suggestions.length > 0) { if (data.suggestions && data.suggestions.length > 0) {
@@ -273,7 +282,7 @@ class AIFiction {
this.storyContainer.appendChild(element); this.storyContainer.appendChild(element);
// Apply SmartyPants transformations for better typography // Apply SmartyPants transformations for better typography
const processedText = SmartyPants.process(text); const processedText = SmartyPants.smartypantsu ? SmartyPants.smartypantsu(text, 1) : text;
// Clear any existing typing timeouts // Clear any existing typing timeouts
if (this.typingTimeout) { if (this.typingTimeout) {
@@ -284,8 +293,8 @@ class AIFiction {
this.typeText(element, processedText, 0); this.typeText(element, processedText, 0);
// Read text aloud if speech is enabled // Read text aloud if speech is enabled
if (tts && tts.enabled) { if (ttsHandler && ttsHandler.isEnabled()) {
tts.speak(text); ttsHandler.speak(text);
} }
} }
@@ -343,7 +352,7 @@ class AIFiction {
const element = document.createElement('div'); const element = document.createElement('div');
element.id = id; element.id = id;
element.className = 'thinking'; element.className = 'thinking';
element.innerHTML = '<p>Thinking<span class="loading-indicator"><div></div><div></div><div></div><div></div></span></p>'; element.innerHTML = '<p>Thinking<span class="loading-indicator"><span>.</span><span>.</span><span>.</span></span></p>';
element.style.fontStyle = 'italic'; element.style.fontStyle = 'italic';
element.style.color = '#777'; element.style.color = '#777';
this.storyContainer.appendChild(element); this.storyContainer.appendChild(element);
@@ -412,7 +421,10 @@ class AIFiction {
* Scroll the story container to the bottom * Scroll the story container to the bottom
*/ */
scrollToBottom() { scrollToBottom() {
this.storyContainer.scrollTop = this.storyContainer.scrollHeight; const container = document.getElementById('page_right');
if (container) {
container.scrollTop = container.scrollHeight;
}
} }
} }