Spaces:
Sleeping
Sleeping
File size: 5,603 Bytes
41c1a97 55e0bb5 689ff91 41c1a97 55e0bb5 bcaa97a 434590c 55e0bb5 bcaa97a 55e0bb5 d9c5a9e 55e0bb5 d9c5a9e 55e0bb5 a2141e7 55e0bb5 a2141e7 55e0bb5 a2141e7 55e0bb5 a2141e7 55e0bb5 a2141e7 55e0bb5 a2141e7 55e0bb5 50498a4 55e0bb5 7825ef7 55e0bb5 d9c5a9e 55e0bb5 b704ae5 55e0bb5 b704ae5 55e0bb5 b704ae5 55e0bb5 7825ef7 f32aedf 55e0bb5 a2141e7 55e0bb5 434590c 55e0bb5 434590c 55e0bb5 434590c 55e0bb5 7825ef7 55e0bb5 7825ef7 89b923d 7825ef7 55e0bb5 4fa9b7a 55e0bb5 89b923d 55e0bb5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# app.py
import streamlit as st
# st.set_page_config MUST be the first Streamlit command
st.set_page_config(page_title="Infinite World Builder", layout="wide")
import streamlit.components.v1 as components
import os, json, time, uuid, math
from datetime import datetime
# --- Global State File ---
GLOBAL_STATE_FILE = "global_state.json"
# If the global state file does not exist, create it with an empty state.
if not os.path.exists(GLOBAL_STATE_FILE):
empty_state = {
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"game_state": [], # List of object records
"player_position": {"x": 0, "y": 0, "z": 0}
}
with open(GLOBAL_STATE_FILE, "w", encoding="utf-8") as f:
json.dump(empty_state, f, indent=2)
def load_global_state():
try:
with open(GLOBAL_STATE_FILE, "r", encoding="utf-8") as f:
return json.load(f)
except Exception as e:
st.error(f"Error loading global state: {e}")
return {"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"), "game_state": [], "player_position": {"x":0, "y":0, "z":0}}
def save_global_state(state):
try:
with open(GLOBAL_STATE_FILE, "w", encoding="utf-8") as f:
json.dump(state, f, indent=2)
except Exception as e:
st.error(f"Error saving global state: {e}")
# --- Initialize global state in session_state ---
if "global_state" not in st.session_state:
st.session_state["global_state"] = load_global_state()
# --- Utility: Update Global State with New Objects ---
def add_objects_to_global(new_objects, player_position):
"""
Merge new object records into the global state.
Each object is expected to have a unique 'obj_id'. If not, one is generated.
"""
state = st.session_state["global_state"]
# Create dictionary of existing objects by obj_id
existing = {obj["obj_id"]: obj for obj in state.get("game_state", []) if "obj_id" in obj}
for obj in new_objects:
obj_id = obj.get("obj_id", str(uuid.uuid4()))
obj["obj_id"] = obj_id
existing[obj_id] = obj
state["game_state"] = list(existing.values())
# Update player position and timestamp (for simplicity, overwrite with latest)
state["player_position"] = player_position
state["timestamp"] = time.strftime("%Y-%m-%d %H:%M:%S")
st.session_state["global_state"] = state
save_global_state(state)
# --- Sidebar Controls ---
with st.sidebar:
st.title("🏗️ World Controls")
# Button to force reload global state from file.
if st.button("🔄 Reload Global State"):
st.session_state["global_state"] = load_global_state()
st.success("Global state reloaded.")
# Button to clear the global state.
if st.button("🗑️ Clear Global State"):
empty = {
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"game_state": [],
"player_position": {"x": 0, "y": 0, "z": 0}
}
st.session_state["global_state"] = empty
save_global_state(empty)
st.success("Global state cleared.")
st.markdown("---")
st.header("Download Global Save as Markdown")
state = st.session_state["global_state"]
default_md_name = state.get("timestamp", "save").replace(":", "").replace(" ", "_") + ".md"
download_name = st.text_input("Override File Name", value=default_md_name)
md_outline = f"""# Global Save: {download_name}
- ⏰ **Timestamp:** {state.get("timestamp", "N/A")}
- 🎮 **Number of Game Objects:** {len(state.get("game_state", []))}
- 🧭 **Player Position:** {state.get("player_position", {"x":0, "y":0, "z":0})}
## Game Objects:
"""
for i, obj in enumerate(state.get("game_state", []), start=1):
obj_type = obj.get("type", "Unknown")
pos = (obj.get("x", 0), obj.get("y", 0), obj.get("z", 0))
md_outline += f"- {i}. ✨ **{obj_type}** at {pos}\n"
st.download_button("Download Markdown Save", data=md_outline, file_name=download_name, mime="text/markdown")
# --- Process Save Data from JavaScript ---
# The JS component will set st.session_state["js_save_data"] to a JSON string when an object is placed.
save_data_from_js = st.session_state.get("js_save_data", None)
if save_data_from_js:
try:
payload = json.loads(save_data_from_js) if isinstance(save_data_from_js, str) else save_data_from_js
if isinstance(payload, dict) and "playerPosition" in payload and "objectsToSave" in payload:
player_pos = payload["playerPosition"]
objects = payload["objectsToSave"]
add_objects_to_global(objects, player_pos)
st.success("Global state updated with new objects.")
st.session_state["js_save_data"] = None
st.experimental_rerun()
except Exception as e:
st.error(f"Error processing JS save data: {e}")
st.session_state["js_save_data"] = None
# --- Inject Global State into JavaScript ---
injected_state = {
"GLOBAL_STATE": st.session_state["global_state"]
}
html_file_path = "index.html"
try:
with open(html_file_path, "r", encoding="utf-8") as f:
html_template = f.read()
js_injection_script = f"""
<script>
// Inject the global state from Streamlit into the web app.
window.GLOBAL_STATE = {json.dumps(injected_state["GLOBAL_STATE"])};
console.log("Injected Global State:", window.GLOBAL_STATE);
</script>
"""
html_content = html_template.replace("</head>", js_injection_script + "\n</head>", 1)
components.html(html_content, height=750, scrolling=True)
except Exception as e:
st.error(f"Error loading index.html: {e}")
|