awacke1 commited on
Commit
b599290
·
verified ·
1 Parent(s): 79afa72

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +62 -110
index.html CHANGED
@@ -26,20 +26,15 @@
26
 
27
  let scene, camera, renderer;
28
  let raycaster, mouse;
29
- let socket = null;
30
- let connectionRetries = 0;
31
- const MAX_RETRIES = 5;
32
 
33
  // Access State from Streamlit
34
  const myUsername = window.USERNAME || `User_${Math.random().toString(36).substring(2, 6)}`;
35
- const websocketUrl = window.WEBSOCKET_URL || "ws://localhost:8765";
36
  let selectedObjectType = window.SELECTED_OBJECT_TYPE || "None";
37
  const plotWidth = window.PLOT_WIDTH || 50.0;
38
  const plotDepth = window.PLOT_DEPTH || 50.0;
39
-
40
- // World State
41
- const worldObjects = new Map();
42
- const groundMeshes = {};
43
 
44
  // Materials
45
  const groundMaterial = new THREE.MeshStandardMaterial({ color: 0x55aa55, roughness: 0.9, metalness: 0.1, side: THREE.DoubleSide });
@@ -78,8 +73,6 @@
78
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
79
  document.body.appendChild(renderer.domElement);
80
 
81
- connectWebSocket();
82
-
83
  document.addEventListener('mousemove', onMouseMove, false);
84
  document.addEventListener('click', onDocumentClick, false);
85
  document.addEventListener('contextmenu', onRightClick, false);
@@ -87,7 +80,10 @@
87
 
88
  window.updateSelectedObjectType = updateSelectedObjectType;
89
 
90
- console.log(`Three.js Initialized for user: ${myUsername}. Connecting to ${websocketUrl}...`);
 
 
 
91
  animate();
92
  }
93
 
@@ -130,89 +126,17 @@
130
  return groundMesh;
131
  }
132
 
133
- function connectWebSocket() {
134
- console.log("Attempting WebSocket connection...");
135
- socket = new WebSocket(websocketUrl);
136
-
137
- socket.onopen = () => {
138
- console.log("WebSocket connection established.");
139
- connectionRetries = 0;
140
- };
141
-
142
- socket.onmessage = (event) => {
143
- try {
144
- const data = JSON.parse(event.data);
145
- console.log("WebSocket message received:", data);
146
- handleWebSocketMessage(data);
147
- } catch (e) {
148
- console.error("Failed to parse WebSocket message:", event.data, e);
149
- }
150
- };
151
-
152
- socket.onerror = (error) => {
153
- console.error("WebSocket error:", error);
154
- };
155
-
156
- socket.onclose = (event) => {
157
- console.warn(`WebSocket connection closed. Code: ${event.code}, Reason: ${event.reason}. Clean: ${event.wasClean}`);
158
- socket = null;
159
- if (connectionRetries < MAX_RETRIES) {
160
- connectionRetries++;
161
- const delay = Math.pow(2, connectionRetries) * 1000;
162
- console.log(`Attempting reconnection in ${delay / 1000}s...`);
163
- setTimeout(connectWebSocket, delay);
164
- } else {
165
- console.error("WebSocket reconnection failed after max retries.");
166
- }
167
- };
168
- }
169
-
170
- function sendWebSocketMessage(type, payload) {
171
- if (socket && socket.readyState === WebSocket.OPEN) {
172
- const message = JSON.stringify({ type, payload });
173
- socket.send(message);
174
- } else {
175
- console.warn("WebSocket not open. Message not sent:", type, payload);
176
  }
177
- }
178
-
179
- function handleWebSocketMessage(data) {
180
- const { type, payload } = data;
181
-
182
- switch (type) {
183
- case "initial_state":
184
- console.log(`Received initial world state with ${Object.keys(payload).length} objects.`);
185
- clearWorldObjects();
186
- for (const obj_id in payload) {
187
- createAndPlaceObject(payload[obj_id], false);
188
- }
189
- break;
190
- case "object_placed":
191
- console.log(`Object placed by ${payload.username}:`, payload.object_data);
192
- createAndPlaceObject(payload.object_data, false);
193
- break;
194
- case "object_deleted":
195
- console.log(`Object deleted by ${payload.username}:`, payload.obj_id);
196
- removeObjectById(payload.obj_id);
197
- break;
198
- case "user_join":
199
- console.log(`User joined: ${payload.username} (${payload.id})`);
200
- break;
201
- case "user_leave":
202
- console.log(`User left: ${payload.username} (${payload.id})`);
203
- break;
204
- case "user_rename":
205
- console.log(`User ${payload.old_username} is now ${payload.new_username}`);
206
- break;
207
- case "chat_message":
208
- console.log(`Chat from ${payload.username}: ${payload.message}`);
209
- break;
210
- case "tool_selected":
211
- console.log(`Tool selected by ${payload.username}: ${payload.tool_type}`);
212
- selectedObjectType = payload.tool_type;
213
- break;
214
- default:
215
- console.warn("Received unknown WebSocket message type:", type);
216
  }
217
  }
218
 
@@ -222,17 +146,22 @@
222
  scene.remove(mesh);
223
  }
224
  worldObjects.clear();
 
 
 
 
 
 
225
  }
226
 
227
- function removeObjectById(obj_id) {
228
- if (worldObjects.has(obj_id)) {
229
- const mesh = worldObjects.get(obj_id);
230
- scene.remove(mesh);
231
- worldObjects.delete(obj_id);
232
- console.log(`Removed object ${obj_id} from scene.`);
233
- } else {
234
- console.warn(`Attempted to remove non-existent object ID: ${obj_id}`);
235
- }
236
  }
237
 
238
  function createAndPlaceObject(objData, isNewlyPlacedLocally) {
@@ -590,10 +519,11 @@
590
 
591
  createAndPlaceObject(newObjData, true);
592
 
593
- sendWebSocketMessage("place_object", {
594
- username: myUsername,
595
- object_data: newObjData
596
- });
 
597
  }
598
  }
599
 
@@ -605,10 +535,22 @@
605
  if (intersects.length > 0) {
606
  const obj_id = intersects[0].object.userData.obj_id;
607
  console.log(`Deleting object ${obj_id}`);
608
- sendWebSocketMessage("delete_object", {
609
- username: myUsername,
610
- obj_id: obj_id
611
- });
 
 
 
 
 
 
 
 
 
 
 
 
612
  }
613
  }
614
 
@@ -628,6 +570,16 @@
628
  renderer.render(scene, camera);
629
  }
630
 
 
 
 
 
 
 
 
 
 
 
631
  init();
632
  </script>
633
  </body>
 
26
 
27
  let scene, camera, renderer;
28
  let raycaster, mouse;
29
+ let worldObjects = new Map();
30
+ let groundMeshes = {};
 
31
 
32
  // Access State from Streamlit
33
  const myUsername = window.USERNAME || `User_${Math.random().toString(36).substring(2, 6)}`;
 
34
  let selectedObjectType = window.SELECTED_OBJECT_TYPE || "None";
35
  const plotWidth = window.PLOT_WIDTH || 50.0;
36
  const plotDepth = window.PLOT_DEPTH || 50.0;
37
+ const worldState = window.WORLD_STATE || { objects: {}, players: {} };
 
 
 
38
 
39
  // Materials
40
  const groundMaterial = new THREE.MeshStandardMaterial({ color: 0x55aa55, roughness: 0.9, metalness: 0.1, side: THREE.DoubleSide });
 
73
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
74
  document.body.appendChild(renderer.domElement);
75
 
 
 
76
  document.addEventListener('mousemove', onMouseMove, false);
77
  document.addEventListener('click', onDocumentClick, false);
78
  document.addEventListener('contextmenu', onRightClick, false);
 
80
 
81
  window.updateSelectedObjectType = updateSelectedObjectType;
82
 
83
+ // Initialize scene with world state
84
+ loadWorldState();
85
+
86
+ console.log(`Three.js Initialized for user: ${myUsername}`);
87
  animate();
88
  }
89
 
 
126
  return groundMesh;
127
  }
128
 
129
+ function loadWorldState() {
130
+ clearWorldObjects();
131
+ const objects = worldState.objects || {};
132
+ for (const obj_id in objects) {
133
+ createAndPlaceObject(objects[obj_id], false);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  }
135
+ // Initialize player positions (visualize as markers)
136
+ const players = worldState.players || {};
137
+ for (const username in players) {
138
+ const pos = players[username].position;
139
+ createPlayerMarker(username, pos);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  }
141
  }
142
 
 
146
  scene.remove(mesh);
147
  }
148
  worldObjects.clear();
149
+ // Clear player markers
150
+ scene.children.forEach(child => {
151
+ if (child.userData.isPlayerMarker) {
152
+ scene.remove(child);
153
+ }
154
+ });
155
  }
156
 
157
+ function createPlayerMarker(username, position) {
158
+ const geometry = new THREE.SphereGeometry(0.3, 8, 8);
159
+ const material = new THREE.MeshBasicMaterial({ color: username === myUsername ? 0x0000ff : 0xff0000 });
160
+ const marker = new THREE.Mesh(geometry, material);
161
+ marker.position.set(position.x, position.y + 0.5, position.z);
162
+ marker.userData.isPlayerMarker = true;
163
+ marker.userData.username = username;
164
+ scene.add(marker);
 
165
  }
166
 
167
  function createAndPlaceObject(objData, isNewlyPlacedLocally) {
 
519
 
520
  createAndPlaceObject(newObjData, true);
521
 
522
+ // Send place action to Streamlit
523
+ window.parent.postMessage({
524
+ type: 'place_object',
525
+ payload: { username: myUsername, object_data: newObjData }
526
+ }, '*');
527
  }
528
  }
529
 
 
535
  if (intersects.length > 0) {
536
  const obj_id = intersects[0].object.userData.obj_id;
537
  console.log(`Deleting object ${obj_id}`);
538
+ removeObjectById(obj_id);
539
+ window.parent.postMessage({
540
+ type: 'delete_object',
541
+ payload: { username: myUsername, obj_id: obj_id }
542
+ }, '*');
543
+ }
544
+ }
545
+
546
+ function removeObjectById(obj_id) {
547
+ if (worldObjects.has(obj_id)) {
548
+ const mesh = worldObjects.get(obj_id);
549
+ scene.remove(mesh);
550
+ worldObjects.delete(obj_id);
551
+ console.log(`Removed object ${obj_id} from scene.`);
552
+ } else {
553
+ console.warn(`Attempted to remove non-existent object ID: ${obj_id}`);
554
  }
555
  }
556
 
 
570
  renderer.render(scene, camera);
571
  }
572
 
573
+ // Listen for messages from Streamlit
574
+ window.addEventListener('message', (event) => {
575
+ const data = event.data;
576
+ if (data.type === 'place_object') {
577
+ createAndPlaceObject(data.payload.object_data, false);
578
+ } else if (data.type === 'delete_object') {
579
+ removeObjectById(data.payload.obj_id);
580
+ }
581
+ });
582
+
583
  init();
584
  </script>
585
  </body>