awacke1 commited on
Commit
85e1821
Β·
verified Β·
1 Parent(s): e471d04

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -18
app.py CHANGED
@@ -106,7 +106,7 @@ def generate_filename(content, username, extension):
106
  def initialize_history_file():
107
  ensure_dir(SAVED_WORLDS_DIR)
108
  if not os.path.exists(WORLD_STATE_FILE):
109
- initial_state = {"objects": {}, "players": {}, "action_history": []}
110
  with open(WORLD_STATE_FILE, 'w', encoding='utf-8') as f:
111
  json.dump(initial_state, f, indent=2)
112
 
@@ -115,14 +115,14 @@ def read_history_file():
115
  try:
116
  with open(WORLD_STATE_FILE, 'r', encoding='utf-8') as f:
117
  state = json.load(f)
118
- # Ensure all expected keys exist
119
  state.setdefault("objects", {})
120
  state.setdefault("players", {})
121
  state.setdefault("action_history", [])
 
122
  return state
123
  except Exception as e:
124
  print(f"Error reading history file: {e}")
125
- return {"objects": {}, "players": {}, "action_history": []}
126
 
127
  def write_history_file(state):
128
  with state_lock:
@@ -273,7 +273,7 @@ async def save_and_log_chat(username, message, voice):
273
  update_action_history(username, "chat", {"message": message}, state)
274
  return md_file_path, audio_file
275
 
276
- # πŸ’Ύ Save World State: Saves current state to a named file
277
  def save_world_state(world_name):
278
  if not world_name.strip():
279
  st.error("World name cannot be empty.")
@@ -284,6 +284,7 @@ def save_world_state(world_name):
284
  save_path = os.path.join(SAVED_WORLDS_DIR, filename)
285
 
286
  state = read_history_file()
 
287
  try:
288
  with open(save_path, 'w', encoding='utf-8') as f:
289
  json.dump(state, f, indent=2)
@@ -295,7 +296,7 @@ def save_world_state(world_name):
295
  st.error(f"Failed to save world: {e}")
296
  return False
297
 
298
- # πŸ“‚ Load World State: Loads a saved state from a file
299
  def load_world_state(filename):
300
  load_path = os.path.join(SAVED_WORLDS_DIR, filename)
301
  if not os.path.exists(load_path):
@@ -307,9 +308,11 @@ def load_world_state(filename):
307
  state.setdefault("objects", {})
308
  state.setdefault("players", {})
309
  state.setdefault("action_history", [])
 
310
  write_history_file(state)
311
  st.session_state.world_state = state
312
  st.session_state.action_history = state["action_history"]
 
313
  print(f"Loaded world state from {load_path}")
314
  st.success(f"Loaded world {filename}")
315
  st.rerun()
@@ -336,6 +339,7 @@ def handle_js_messages():
336
  action = data.get("type")
337
  payload = data.get("payload", {})
338
  username = payload.get("username", st.session_state.username)
 
339
  if action == "place_object":
340
  state = persist_world_objects(payload["object_data"], username, "place")
341
  st.session_state.world_state = state
@@ -348,6 +352,14 @@ def handle_js_messages():
348
  state = update_player_state(username, payload["position"])
349
  st.session_state.world_state = state
350
  st.rerun()
 
 
 
 
 
 
 
 
351
  except json.JSONDecodeError:
352
  print(f"Invalid JS message: {message}")
353
  except Exception as e:
@@ -385,10 +397,10 @@ def init_session_state():
385
  'username': None,
386
  'autosend': False,
387
  'last_message': "",
388
- 'selected_object': 'None',
389
  'paste_image_base64': "",
390
  'new_world_name': "MyWorld",
391
- 'world_state': {"objects": {}, "players": {}, "action_history": []}
392
  }
393
  for k, v in defaults.items():
394
  if k not in st.session_state:
@@ -408,6 +420,7 @@ def init_session_state():
408
  state = read_history_file()
409
  st.session_state.world_state = state
410
  st.session_state.action_history = state.get("action_history", [])
 
411
  update_player_state(st.session_state.username)
412
 
413
  # ==============================================================================
@@ -718,8 +731,8 @@ def render_sidebar():
718
  "Time": entry["timestamp"],
719
  "Player": entry["username"],
720
  "Action": entry["action"].capitalize(),
721
- "Object Type": data.get("type", "N/A"),
722
- "Position": position_str
723
  })
724
  elif entry["action"] == "move":
725
  pos = data.get("position", {})
@@ -728,16 +741,33 @@ def render_sidebar():
728
  "Time": entry["timestamp"],
729
  "Player": entry["username"],
730
  "Action": "Move",
731
- "Object Type": "Player",
732
- "Position": position_str
733
  })
734
  elif entry["action"] == "chat":
735
  history_data.append({
736
  "Time": entry["timestamp"],
737
  "Player": entry["username"],
738
  "Action": "Chat",
739
- "Object Type": "Message",
740
- "Position": data.get("message", "N/A")[:50]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
741
  })
742
  if history_data:
743
  st.dataframe(pd.DataFrame(history_data), height=200, use_container_width=True)
@@ -798,16 +828,20 @@ def render_sidebar():
798
  if cols[col_idx % 5].button(emoji, key=button_key, help=name, type=button_type, use_container_width=True):
799
  if st.session_state.selected_object != name:
800
  st.session_state.selected_object = name
801
- update_player_state(st.session_state.username)
802
- update_action_history(st.session_state.username, "tool_change", {"tool": name}, read_history_file())
 
 
803
  st.rerun()
804
  col_idx += 1
805
  st.markdown("---")
806
  if st.button("🚫 Clear Tool", key="clear_tool", use_container_width=True):
807
  if st.session_state.selected_object != 'None':
808
  st.session_state.selected_object = 'None'
809
- update_player_state(st.session_state.username)
810
- update_action_history(st.session_state.username, "tool_change", {"tool": "None"}, read_history_file())
 
 
811
  st.rerun()
812
 
813
  st.markdown("---")
@@ -843,6 +877,7 @@ def render_main_content():
843
  st.header("Shared 3D World")
844
  st.caption("Click to place objects with the selected tool, or click to move player. Right-click to delete. State is saved in history.json.")
845
  state = st.session_state.world_state
 
846
  html_file_path = 'index.html'
847
  try:
848
  with open(html_file_path, 'r', encoding='utf-8') as f:
@@ -895,10 +930,11 @@ def render_main_content():
895
  st.header("πŸ“‚ Files & Settings")
896
  st.subheader("πŸ’Ύ World State Management")
897
  if st.button("Clear World State", key="clear_world_state"):
898
- state = {"objects": {}, "players": {}, "action_history": []}
899
  write_history_file(state)
900
  st.session_state.world_state = state
901
  st.session_state.action_history = []
 
902
  st.success("World state cleared!")
903
  st.rerun()
904
 
 
106
  def initialize_history_file():
107
  ensure_dir(SAVED_WORLDS_DIR)
108
  if not os.path.exists(WORLD_STATE_FILE):
109
+ initial_state = {"objects": {}, "players": {}, "action_history": [], "selected_object": "None"}
110
  with open(WORLD_STATE_FILE, 'w', encoding='utf-8') as f:
111
  json.dump(initial_state, f, indent=2)
112
 
 
115
  try:
116
  with open(WORLD_STATE_FILE, 'r', encoding='utf-8') as f:
117
  state = json.load(f)
 
118
  state.setdefault("objects", {})
119
  state.setdefault("players", {})
120
  state.setdefault("action_history", [])
121
+ state.setdefault("selected_object", "None")
122
  return state
123
  except Exception as e:
124
  print(f"Error reading history file: {e}")
125
+ return {"objects": {}, "players": {}, "action_history": [], "selected_object": "None"}
126
 
127
  def write_history_file(state):
128
  with state_lock:
 
273
  update_action_history(username, "chat", {"message": message}, state)
274
  return md_file_path, audio_file
275
 
276
+ # πŸ’Ύ Save World State: Saves current state including selected tool
277
  def save_world_state(world_name):
278
  if not world_name.strip():
279
  st.error("World name cannot be empty.")
 
284
  save_path = os.path.join(SAVED_WORLDS_DIR, filename)
285
 
286
  state = read_history_file()
287
+ state["selected_object"] = st.session_state.selected_object
288
  try:
289
  with open(save_path, 'w', encoding='utf-8') as f:
290
  json.dump(state, f, indent=2)
 
296
  st.error(f"Failed to save world: {e}")
297
  return False
298
 
299
+ # πŸ“‚ Load World State: Loads a saved state including selected tool
300
  def load_world_state(filename):
301
  load_path = os.path.join(SAVED_WORLDS_DIR, filename)
302
  if not os.path.exists(load_path):
 
308
  state.setdefault("objects", {})
309
  state.setdefault("players", {})
310
  state.setdefault("action_history", [])
311
+ state.setdefault("selected_object", "None")
312
  write_history_file(state)
313
  st.session_state.world_state = state
314
  st.session_state.action_history = state["action_history"]
315
+ st.session_state.selected_object = state["selected_object"]
316
  print(f"Loaded world state from {load_path}")
317
  st.success(f"Loaded world {filename}")
318
  st.rerun()
 
339
  action = data.get("type")
340
  payload = data.get("payload", {})
341
  username = payload.get("username", st.session_state.username)
342
+ state = read_history_file()
343
  if action == "place_object":
344
  state = persist_world_objects(payload["object_data"], username, "place")
345
  st.session_state.world_state = state
 
352
  state = update_player_state(username, payload["position"])
353
  st.session_state.world_state = state
354
  st.rerun()
355
+ elif action == "tool_change":
356
+ tool = payload.get("tool", "None")
357
+ state["selected_object"] = tool
358
+ st.session_state.selected_object = tool
359
+ write_history_file(state)
360
+ update_action_history(username, "tool_change", {"tool": tool}, state)
361
+ st.session_state.world_state = state
362
+ st.rerun()
363
  except json.JSONDecodeError:
364
  print(f"Invalid JS message: {message}")
365
  except Exception as e:
 
397
  'username': None,
398
  'autosend': False,
399
  'last_message': "",
400
+ 'selected_object': "None",
401
  'paste_image_base64': "",
402
  'new_world_name': "MyWorld",
403
+ 'world_state': {"objects": {}, "players": {}, "action_history": [], "selected_object": "None"}
404
  }
405
  for k, v in defaults.items():
406
  if k not in st.session_state:
 
420
  state = read_history_file()
421
  st.session_state.world_state = state
422
  st.session_state.action_history = state.get("action_history", [])
423
+ st.session_state.selected_object = state.get("selected_object", "None")
424
  update_player_state(st.session_state.username)
425
 
426
  # ==============================================================================
 
731
  "Time": entry["timestamp"],
732
  "Player": entry["username"],
733
  "Action": entry["action"].capitalize(),
734
+ "Type": data.get("type", "N/A"),
735
+ "Details": position_str
736
  })
737
  elif entry["action"] == "move":
738
  pos = data.get("position", {})
 
741
  "Time": entry["timestamp"],
742
  "Player": entry["username"],
743
  "Action": "Move",
744
+ "Type": "Player",
745
+ "Details": position_str
746
  })
747
  elif entry["action"] == "chat":
748
  history_data.append({
749
  "Time": entry["timestamp"],
750
  "Player": entry["username"],
751
  "Action": "Chat",
752
+ "Type": "Message",
753
+ "Details": data.get("message", "N/A")[:50]
754
+ })
755
+ elif entry["action"] == "tool_change":
756
+ tool = data.get("tool", "None")
757
+ history_data.append({
758
+ "Time": entry["timestamp"],
759
+ "Player": entry["username"],
760
+ "Action": "Tool Change",
761
+ "Type": "Tool",
762
+ "Details": f"Selected {tool}"
763
+ })
764
+ elif entry["action"] == "rename":
765
+ history_data.append({
766
+ "Time": entry["timestamp"],
767
+ "Player": entry["username"],
768
+ "Action": "Rename",
769
+ "Type": "Username",
770
+ "Details": f"From {data.get('old_username')} to {data.get('new_username')}"
771
  })
772
  if history_data:
773
  st.dataframe(pd.DataFrame(history_data), height=200, use_container_width=True)
 
828
  if cols[col_idx % 5].button(emoji, key=button_key, help=name, type=button_type, use_container_width=True):
829
  if st.session_state.selected_object != name:
830
  st.session_state.selected_object = name
831
+ state = read_history_file()
832
+ state["selected_object"] = name
833
+ write_history_file(state)
834
+ update_action_history(st.session_state.username, "tool_change", {"tool": name}, state)
835
  st.rerun()
836
  col_idx += 1
837
  st.markdown("---")
838
  if st.button("🚫 Clear Tool", key="clear_tool", use_container_width=True):
839
  if st.session_state.selected_object != 'None':
840
  st.session_state.selected_object = 'None'
841
+ state = read_history_file()
842
+ state["selected_object"] = "None"
843
+ write_history_file(state)
844
+ update_action_history(st.session_state.username, "tool_change", {"tool": "None"}, state)
845
  st.rerun()
846
 
847
  st.markdown("---")
 
877
  st.header("Shared 3D World")
878
  st.caption("Click to place objects with the selected tool, or click to move player. Right-click to delete. State is saved in history.json.")
879
  state = st.session_state.world_state
880
+ state["selected_object"] = st.session_state.selected_object
881
  html_file_path = 'index.html'
882
  try:
883
  with open(html_file_path, 'r', encoding='utf-8') as f:
 
930
  st.header("πŸ“‚ Files & Settings")
931
  st.subheader("πŸ’Ύ World State Management")
932
  if st.button("Clear World State", key="clear_world_state"):
933
+ state = {"objects": {}, "players": {}, "action_history": [], "selected_object": "None"}
934
  write_history_file(state)
935
  st.session_state.world_state = state
936
  st.session_state.action_history = []
937
+ st.session_state.selected_object = "None"
938
  st.success("World state cleared!")
939
  st.rerun()
940