import eventlet eventlet.monkey_patch() import os import random from flask import Flask, render_template, request, jsonify, send_from_directory from flask_socketio import SocketIO, emit app = Flask(__name__, template_folder='templates') app.config['SECRET_KEY'] = 'gamerjam-1920-secret' # SocketIO mit Transports-Optimierung socketio = SocketIO(app, cors_allowed_origins="*", async_mode='eventlet') # Speichert Spieler-Daten: { email: {data} } players = {} # Mapping von Socket-ID zu E-Mail: { sid: email } sid_to_email = {} def get_ready_stats(): # Wir zählen nur Spieler, die aktuell eine aktive Socket-Verbindung haben active_emails = sid_to_email.values() total = len(active_emails) ready = sum(1 for email in active_emails if players.get(email, {}).get('ready', False)) return ready, total @app.route('/') def index(): return render_template('index.html') @app.route('/login', methods=['POST']) def login(): data = request.json email = data.get('email', '').lower().strip() if not email: return jsonify({'error': 'No email'}), 400 if email not in players: # Erster Spieler wird Admin is_first = len(players) == 0 players[email] = { 'email': email, 'money': 1000, 'is_admin': is_first, 'ready': False } return jsonify(players[email]) @app.route("/assets/") def serve_assets(filename): return send_from_directory('assets', filename) @socketio.on('join_race') def on_join(data): email = data.get('email', '').lower().strip() if email: # Verknüpfe die aktuelle Socket-ID mit der E-Mail sid_to_email[request.sid] = email if email in players: # Falls der Spieler nach einem Refresh wiederkommt, ready zurücksetzen players[email]['ready'] = False ready, total = get_ready_stats() emit('ready_update', {'ready': ready, 'total': total}, broadcast=True) @socketio.on('disconnect') def on_disconnect(): # Wenn ein User die Seite schließt if request.sid in sid_to_email: email = sid_to_email.pop(request.sid) # Optional: Spieler ganz löschen oder nur ready auf False if email in players: players[email]['ready'] = False # Wenn du willst, dass die Zahl im Button sofort sinkt: # players.pop(email) # Nur einkommentieren, wenn Daten nicht gespeichert werden müssen ready, total = get_ready_stats() emit('ready_update', {'ready': ready, 'total': total}, broadcast=True) @socketio.on('chat_message') def handle_chat_message(data): emit('new_chat_message', data, broadcast=True) @socketio.on('player_ready') def on_player_ready(data): email = data.get('email', '').lower().strip() if email in players: players[email]['ready'] = True ready, total = get_ready_stats() emit('ready_update', {'ready': ready, 'total': total}, broadcast=True) @socketio.on('start_race') def on_start_race(data): email = data.get('email', '').lower().strip() if email in players and players[email]['is_admin']: # Bereit-Status für alle AKTIVEN zurücksetzen for p_email in sid_to_email.values(): if p_email in players: players[p_email]['ready'] = False speeds = [random.uniform(0.8, 1.2) for _ in range(6)] emit('race_started', {'speeds': speeds}, broadcast=True) ready, total = get_ready_stats() emit('ready_update', {'ready': ready, 'total': total}, broadcast=True) @socketio.on('update_money') def on_update_money(data): email = data.get('email', '').lower().strip() new_money = data.get('money') if email in players: players[email]['money'] = new_money if __name__ == '__main__': socketio.run(app, host='0.0.0.0', port=7860, debug=False)