from flask import jsonify, request import screens from core.flask_app import app @app.route("/game//triggers/objects-catalog", methods=["GET"]) def triggers_objects_catalog(slug): """Catalogue des objets de scène éligibles à un déclencheur, pour la grille "choisis un objet" de la modale d'ajout (voir screens.list_all_collision_objects).""" return jsonify(screens.list_all_collision_objects(slug)) @app.route("/game//triggers", methods=["GET"]) def triggers_get(slug): """TOUS les déclencheurs du jeu (voir screens.list_all_triggers) — plus de recherche inversée par quête, la logique est portée directement par chaque déclencheur.""" return jsonify(screens.list_all_triggers(slug)) @app.route("/game//triggers", methods=["POST"]) def triggers_add(slug): """Ajoute un déclencheur sur l'objet choisi — body {object_id, rule}, `rule` construite par l'assistant "déclencheur -> action" (voir openTriggerWizard, static/js/scenes/collision-rules-editor.js) : n'importe quel type de déclencheur/action qu'il propose passe donc déjà tel quel, sans changement à faire ici si de nouveaux types apparaissent un jour. Même contrat "liste ENTIÈRE" que l'éditeur de collision (routes/scenes/scene_object_collision_rules.py) : on recharge les règles existantes de l'objet, on y ajoute la nouvelle, on sauvegarde la liste complète.""" body = request.get_json(silent=True) or {} try: object_id = int(body.get("object_id")) except (TypeError, ValueError): return jsonify({"error": "object_id invalide"}), 400 obj = screens.get_scene_object(slug, object_id) if obj is None: return jsonify({"error": "objet introuvable"}), 404 new_rule = body.get("rule") if not isinstance(new_rule, dict): return jsonify({"error": "rule invalide"}), 400 rules = screens.resolve_collision_rules(obj) rules.append(new_rule) sanitized = screens.sanitize_collision_rules(rules) screens.set_scene_object_collision_rules(slug, object_id, sanitized) return jsonify({"ok": True}) @app.route("/game//triggers/", methods=["DELETE"]) def triggers_delete(slug, object_id): """Retire TOUTES les règles de collision de CET objet — sans quête pour distinguer "cette règle-ci" d'une autre, un objet ne porte de toute façon en pratique qu'un seul déclencheur à la fois (posé par l'assistant, jamais cumulé).""" obj = screens.get_scene_object(slug, object_id) if obj is None: return jsonify({"error": "objet introuvable"}), 404 screens.set_scene_object_collision_rules(slug, object_id, []) return jsonify({"ok": True}) @app.route("/game//triggers//dialogue", methods=["POST"]) def trigger_dialogue_update(slug, object_id): """Édition EN LIGNE des répliques d'UN dialogue précis (voir screens/rendering/collision_rules.py::"dialogue".dialogue) — body {dialogue_id, lines}. 404 si `dialogue_id` ne correspond à aucun dialogue de CET objet (règle supprimée entre-temps, référence orpheline).""" obj = screens.get_scene_object(slug, object_id) if obj is None: return jsonify({"error": "objet introuvable"}), 404 body = request.get_json(silent=True) or {} dialogue_id = body.get("dialogue_id") if not isinstance(dialogue_id, str) or not dialogue_id.strip(): return jsonify({"error": "dialogue_id invalide"}), 400 rules = screens.resolve_collision_rules(obj) if not screens.set_dialogue_lines_in_rules(rules, dialogue_id, body.get("lines")): return jsonify({"error": "dialogue introuvable"}), 404 sanitized = screens.sanitize_collision_rules(rules) screens.set_scene_object_collision_rules(slug, object_id, sanitized) return jsonify({"ok": True}) @app.route("/game//triggers//append-action", methods=["POST"]) def trigger_append_action(slug, object_id): """"+ Ajouter une action" en bout de chaîne (voir screens/rendering/ collision_rules.py::set_then_action_in_rules, static/js/triggers/ trigger-editor.js) — body {after_id, action} : `after_id` est le dialogue.id (feuille "dialogue") ou id (feuille "variable") de la DERNIÈRE feuille d'une chaîne. 404 si `after_id` introuvable ou si cette feuille a déjà un "then" (jamais écrasé par cette route — un nouvel appel doit d'abord recharger la chaîne à jour).""" if screens.get_scene_object(slug, object_id) is None: return jsonify({"error": "objet introuvable"}), 404 body = request.get_json(silent=True) or {} after_id = body.get("after_id") if not isinstance(after_id, str) or not after_id.strip(): return jsonify({"error": "after_id invalide"}), 400 # Chemin d'écriture PARTAGÉ avec l'agent IA (voir ai/tools.py) — # ni cette route ni l'agent n'écrivent _collision_rules directement. if not screens.append_action_to_trigger(slug, object_id, after_id, body.get("action")): return jsonify({"error": "action précédente introuvable ou déjà chaînée"}), 404 return jsonify({"ok": True})