File size: 5,127 Bytes
e7b6ed2
d917c9b
5ca5f01
e7b6ed2
 
 
1b2b6c5
e7b6ed2
 
 
d917c9b
 
d941195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d917c9b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d941195
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
---
title: 🧜‍♀️Streamlit🧠CV📚Scroller
emoji: 🧜‍♀️📚🧜‍♂️
colorFrom: gray
colorTo: pink
sdk: streamlit
sdk_version: 1.45.0
app_file: app.py
pinned: false
license: mit
short_description: 🧠CV Scroller🧜‍♀️🧜‍♂️🧜3D Graphs
---


## 📂 File Cast & Roles

- **`app.py`** — 🧑‍✈️ **The Conductor**  
  Orchestrates Streamlit:  
  - Loads per‑plot CSVs (your saved “tiles”)  
  - Fetches the **GameState vault**  
  - Injects everything into the browser  
  - Listens for your “💾 Save” click and hands new objects off to both the plot‑file writer **and** the GameState vault

- **`gamestate.py`** — 💼 **The Vault**  
  A thread‑safe singleton that:  
  - On startup, reads `world_state.csv``world_state[]`  
  - On update, merges in new objects by `obj_id` and writes back to `world_state.csv`  
  - Serves as the **shared truth** for everyone who joins

- **`index.html`** — 🎭 **The Stage**  
  Three.js world where:  
  - Injected arrays (`ALL_INITIAL_OBJECTS`, `PLOTS_METADATA`, `GAME_STATE`) arrive as `window…` variables  
  - Ground tiles and objects are rendered from those arrays  
  - Local clicks spawn new objects into a **sessionStorage** “back‑pocket” until you hit Save  
  - A tiny 5 s timer peeks at `window.GAME_STATE` so you can see others’ updates in near‑real time

- **`requirements.txt`** — 🛠️ **The Toolbox**  
  Lists exactly the small helper you need (`streamlit_js_eval`) to bridge JS ↔️ Python

---

## 🔄 How State Sticks

1. **Persistent CSVs**  
   - **Per‑plot files** (`plot_X3_Z2.csv`) hold each tile’s snapshot  
   - **Global file** (`world_state.csv`) holds the universal list of all objects

2. **In‑Memory Caching**  
   - `@st.cache_data` for plot metadata (avoids re‑reading disk for 1 h)  
   - `@st.cache_resource` for the GameState singleton (one vault, never re‑instantiated)

3. **Browser Session Storage**  
   - Unsaved objects live in `sessionStorage` so you don’t lose placements on refresh  
   - Cleared only when you “Reset” or after a successful Save

4. **JS ↔️ Python Bridge**  
   - JS `getSaveDataAndPosition()` → returns your new objects + player coords as JSON  
   - Streamlit parses that, writes CSV, merges vault, clears caches, and **reruns** to inject the fresh state back into the Stage

---

## 🌊 Flow of Play (Intuition)

1. **Boot Up**  
   - Conductor (`app.py`) reads all the saved chunks → tells the Stage (`index.html`) “Here’s what’s out there!”

2. **Explore & Build**  
   - You walk around (WASD) and click to place “House🌳Rock🏠Tree”  
   - New pieces go into your **back pocket** (`sessionStorage`)—invisible until saved

3. **Save the Day**  
   - Hit “💾 Save” → Conductor grabs your pocket’s contents  
   - Vault (`GameState`) merges them into the master record  
   - Plot files get updated so new visitors see your work

4. **Collaborate in Near‑Real Time**  
   - Every 5 s the Stage peeks at `window.GAME_STATE`  
   - You see newcomers’ additions pop in without a full reload

✨  a tiny toolbox keep a **persistent**, **shared**, **interactive** 3D world humming! 🎉```




- 🐍 **Python Startup**  
  - 📂 `load_plot_metadata()` → scan `saved_worlds/` for `plot_X…_Z…csv` (cached)  
  - 📑 `load_plot_objects()` → read CSV → build `ALL_INITIAL_OBJECTS`  
  - 🔒 `get_game_state()` → singleton `GameState` → load/hold `world_state.csv`  
  - 🚀 Inject → `ALL_INITIAL_OBJECTS`, `PLOTS_METADATA`, `GAME_STATE` into `index.html`

- 💾 **Save Flow**  
  - 🖱️ User clicks “💾 Save” → JS `getSaveDataAndPosition()` → returns JSON payload  
  - 🔄 Py parses → computes `plot_X…_Z….csv` → `save_plot_data()` writes per‑plot file  
  - ➕ `game_state.update_state()` merges into `world_state.csv`  
  - 🔁 `load_plot_metadata.clear()` + `st.rerun()` → refreshed state

- 🌐 **Three.js Init**  
  - 🌟 `init()` → scene, camera, lights  
  - 🛤️ `setupInitialGround()` → one plane per saved plot (or at 0,0)  
  - 👤 `setupPlayer()` → capsule mesh at center  
  - 📦 `loadInitialObjects()` → instantiate all persisted objects

- 🎮 **Interaction & Local State**  
  - 🖱️ `onDocumentClick()` → raycast → spawn `House/Tree/Rock…` → add to `newlyPlacedObjects`  
  - 💾 `saveUnsavedState()` → persist `newlyPlacedObjects` to `sessionStorage`  
  - 🔄 `restoreUnsavedState()` on reload → rehydrate unsaved objects  
  - 🗑️ `resetNewlyPlacedObjects()` → clear sessionStorage

- ⏩ **Game Loop**  
  - 🔑 `onKeyDown`/`onKeyUp` → track WASD/Arrows  
  - 🚶 `updatePlayerMovement()` → camera‑relative walk + `checkAndExpandGround()`  
  - 🌱 `checkAndExpandGround()` → add placeholder planes around player  
  - 📽️ `animate()` → movement, camera lerp, `renderer.render()`

- 🔄 **Collab Sync**  
  - ⏲️ `setInterval(pollGameState, 5000)` → logs or applies updated `window.GAME_STATE`  

✨ **All set!** end‑to‑end state protocol.