Spaces:
Runtime error
Runtime error
| import os | |
| import json | |
| import shutil | |
| import time | |
| import threading | |
| from gradio import Server | |
| from gradio_client import Client | |
| from fastapi.responses import HTMLResponse | |
| from fastapi.staticfiles import StaticFiles | |
| # --------------------------------------------------------------------------- | |
| # Persistent storage | |
| # --------------------------------------------------------------------------- | |
| DATA_DIR = os.environ.get("DATA_DIR", "/data") | |
| GRID_FILE = os.path.join(DATA_DIR, "grid.json") | |
| IMAGES_DIR = os.path.join(DATA_DIR, "images") | |
| os.makedirs(IMAGES_DIR, exist_ok=True) | |
| _grid_lock = threading.Lock() | |
| def load_grid(): | |
| with _grid_lock: | |
| if os.path.exists(GRID_FILE): | |
| with open(GRID_FILE) as f: | |
| return json.load(f) | |
| return {} | |
| def save_grid(grid): | |
| with _grid_lock: | |
| with open(GRID_FILE, "w") as f: | |
| json.dump(grid, f) | |
| # --------------------------------------------------------------------------- | |
| # FLUX Klein client (lazy init — Space may be sleeping) | |
| # --------------------------------------------------------------------------- | |
| _flux = None | |
| def get_flux(): | |
| global _flux | |
| if _flux is None: | |
| _flux = Client("black-forest-labs/flux-klein-9b-kv") | |
| return _flux | |
| # --------------------------------------------------------------------------- | |
| # Server | |
| # --------------------------------------------------------------------------- | |
| app = Server() | |
| # Serve generated images as static files | |
| app.mount("/images", StaticFiles(directory=IMAGES_DIR), name="images") | |
| async def homepage(): | |
| html_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "index.html") | |
| with open(html_path, "r", encoding="utf-8") as f: | |
| return f.read() | |
| def get_grid() -> str: | |
| """Return all placed buildings as JSON.""" | |
| return json.dumps(load_grid()) | |
| def place_building(x: int, y: int, prompt: str) -> str: | |
| """Generate an isometric building and place it on the grid.""" | |
| key = f"{x},{y}" | |
| grid = load_grid() | |
| if key in grid: | |
| return json.dumps({"error": "Tile already occupied"}) | |
| full_prompt = ( | |
| f"isometric building, white background, game asset, " | |
| f"single building centered, no ground, no shadow, clean edges, " | |
| f"{prompt}" | |
| ) | |
| try: | |
| result, seed = get_flux().predict( | |
| prompt=full_prompt, | |
| input_images=[], | |
| seed=0, | |
| randomize_seed=True, | |
| width=512, | |
| height=512, | |
| num_inference_steps=4, | |
| prompt_upsampling=False, | |
| api_name="/generate", | |
| ) | |
| except Exception as e: | |
| return json.dumps({"error": str(e)}) | |
| # Copy generated image to persistent storage | |
| filename = f"{x}_{y}.webp" | |
| dest = os.path.join(IMAGES_DIR, filename) | |
| shutil.copy2(result, dest) | |
| grid[key] = { | |
| "prompt": prompt, | |
| "seed": seed, | |
| "ts": int(time.time()), | |
| } | |
| save_grid(grid) | |
| return json.dumps({"ok": True, "image": f"/images/{filename}", "seed": seed}) | |
| def remove_building(x: int, y: int) -> str: | |
| """Remove a building from the grid.""" | |
| key = f"{x},{y}" | |
| grid = load_grid() | |
| if key not in grid: | |
| return json.dumps({"error": "No building at this tile"}) | |
| del grid[key] | |
| save_grid(grid) | |
| img_path = os.path.join(IMAGES_DIR, f"{x}_{y}.webp") | |
| if os.path.exists(img_path): | |
| os.remove(img_path) | |
| return json.dumps({"ok": True}) | |
| demo = app | |
| if __name__ == "__main__": | |
| demo.launch(show_error=True, ssr_mode=False) | |