mirror of
https://github.com/rommapp/romm.git
synced 2026-02-18 00:27:41 +01:00
225 lines
7.2 KiB
Python
225 lines
7.2 KiB
Python
from typing import Any, NotRequired, TypedDict
|
|
|
|
from endpoints.netplay import DEFAULT_MAX_PLAYERS
|
|
from handler.netplay_handler import NetplayPlayerInfo, NetplayRoom, netplay_handler
|
|
from handler.socket_handler import netplay_socket_handler
|
|
|
|
|
|
class RoomDataExtra(TypedDict):
|
|
sessionid: str | None
|
|
userid: str | None
|
|
playerId: str | None
|
|
room_name: NotRequired[str]
|
|
game_id: NotRequired[str]
|
|
domain: NotRequired[str]
|
|
player_name: NotRequired[str]
|
|
room_password: NotRequired[str]
|
|
|
|
|
|
class RoomData(TypedDict):
|
|
extra: RoomDataExtra
|
|
maxPlayers: NotRequired[int]
|
|
|
|
|
|
@netplay_socket_handler.socket_server.on("open-room") # type: ignore
|
|
async def open_room(sid: str, data: RoomData):
|
|
extra_data = data["extra"]
|
|
|
|
session_id = extra_data.get("sessionid")
|
|
player_id = extra_data.get("userid") or extra_data.get("playerId")
|
|
|
|
if not session_id or not player_id:
|
|
return "Invalid data: sessionId and playerId required"
|
|
|
|
if await netplay_handler.get(session_id):
|
|
return "Room already exists"
|
|
|
|
new_room = NetplayRoom(
|
|
owner=sid,
|
|
players={
|
|
player_id: NetplayPlayerInfo(
|
|
socketId=sid,
|
|
player_name=extra_data.get("player_name") or f"Player {player_id}",
|
|
userid=extra_data.get("userid"),
|
|
playerId=extra_data.get("playerId"),
|
|
)
|
|
},
|
|
peers=[],
|
|
room_name=extra_data.get("room_name") or f"Room {session_id}",
|
|
game_id=extra_data.get("game_id") or "default",
|
|
domain=extra_data.get("domain", None),
|
|
password=extra_data.get("room_password", None),
|
|
max_players=data.get("maxPlayers") or DEFAULT_MAX_PLAYERS,
|
|
)
|
|
await netplay_handler.set(session_id, new_room)
|
|
|
|
await netplay_socket_handler.socket_server.enter_room(sid, session_id)
|
|
await netplay_socket_handler.socket_server.save_session(
|
|
sid,
|
|
{
|
|
"session_id": session_id,
|
|
"player_id": player_id,
|
|
},
|
|
)
|
|
await netplay_socket_handler.socket_server.emit(
|
|
"users-updated", new_room["players"], room=session_id
|
|
)
|
|
|
|
|
|
@netplay_socket_handler.socket_server.on("join-room") # type: ignore
|
|
async def join_room(sid: str, data: RoomData):
|
|
extra_data = data["extra"]
|
|
|
|
session_id = extra_data.get("sessionid")
|
|
player_id = extra_data.get("userid") or extra_data.get("playerId")
|
|
|
|
if not session_id or not player_id:
|
|
return "Invalid data: sessionId and playerId required"
|
|
|
|
current_room = await netplay_handler.get(session_id)
|
|
if not current_room:
|
|
return "Room not found"
|
|
|
|
if current_room["password"] and current_room["password"] != extra_data.get(
|
|
"room_password"
|
|
):
|
|
return "Incorrect password"
|
|
|
|
if len(current_room["players"].keys()) >= current_room["max_players"]:
|
|
return "Room is full"
|
|
|
|
current_room["players"][player_id] = NetplayPlayerInfo(
|
|
socketId=sid,
|
|
player_name=extra_data.get("player_name") or f"Player {player_id}",
|
|
userid=extra_data.get("userid"),
|
|
playerId=extra_data.get("playerId"),
|
|
)
|
|
await netplay_handler.set(session_id, current_room)
|
|
|
|
await netplay_socket_handler.socket_server.enter_room(sid, session_id)
|
|
await netplay_socket_handler.socket_server.save_session(
|
|
sid,
|
|
{
|
|
"session_id": session_id,
|
|
"player_id": player_id,
|
|
},
|
|
)
|
|
await netplay_socket_handler.socket_server.emit(
|
|
"users-updated", current_room["players"], room=session_id
|
|
)
|
|
|
|
return None, current_room["players"]
|
|
|
|
|
|
async def _handle_leave(sid: str, session_id: str, player_id: str):
|
|
current_room = await netplay_handler.get(session_id)
|
|
if not current_room:
|
|
return
|
|
|
|
current_room["players"].pop(player_id, None)
|
|
|
|
if not current_room["players"]:
|
|
await netplay_handler.delete([session_id])
|
|
# Notify clients that the room is now empty
|
|
await netplay_socket_handler.socket_server.emit(
|
|
"users-updated", {}, room=session_id
|
|
)
|
|
return
|
|
|
|
if sid == current_room["owner"]:
|
|
# Owner left, assign a new one
|
|
remaining_players = list(current_room["players"].values())
|
|
if remaining_players:
|
|
current_room["owner"] = remaining_players[0]["socketId"]
|
|
|
|
await netplay_handler.set(session_id, current_room)
|
|
await netplay_socket_handler.socket_server.emit(
|
|
"users-updated", current_room["players"], room=session_id
|
|
)
|
|
|
|
|
|
@netplay_socket_handler.socket_server.on("leave-room") # type: ignore
|
|
async def leave_room(sid: str):
|
|
stored_session = await netplay_socket_handler.socket_server.get_session(sid)
|
|
session_id = stored_session.get("session_id")
|
|
player_id = stored_session.get("player_id")
|
|
|
|
if session_id and player_id:
|
|
await _handle_leave(sid, session_id, player_id)
|
|
await netplay_socket_handler.socket_server.leave_room(sid, session_id)
|
|
|
|
|
|
class WebRTCSignalData(TypedDict, total=False):
|
|
target: str
|
|
candidate: Any
|
|
offer: Any
|
|
answer: Any
|
|
requestRenegotiate: bool
|
|
|
|
|
|
@netplay_socket_handler.socket_server.on("webrtc-signal") # type: ignore
|
|
async def webrtc_signal(sid: str, data: WebRTCSignalData):
|
|
target = data.get("target")
|
|
request_renegotiate = data.get("requestRenegotiate", False)
|
|
|
|
if request_renegotiate:
|
|
if not target:
|
|
return
|
|
await netplay_socket_handler.socket_server.emit(
|
|
"webrtc-signal",
|
|
{"sender": sid, "requestRenegotiate": True},
|
|
to=target,
|
|
)
|
|
else:
|
|
if not target:
|
|
return # drop message—no recipient
|
|
await netplay_socket_handler.socket_server.emit(
|
|
"webrtc-signal",
|
|
{
|
|
"sender": sid,
|
|
"candidate": data.get("candidate"),
|
|
"offer": data.get("offer"),
|
|
"answer": data.get("answer"),
|
|
},
|
|
to=target,
|
|
)
|
|
|
|
|
|
@netplay_socket_handler.socket_server.on("webrtc-signal-error") # type: ignore
|
|
async def webrtc_signal_error(_sid: str, _error: str, _data: Any):
|
|
pass
|
|
|
|
|
|
@netplay_socket_handler.socket_server.on("disconnect") # type: ignore
|
|
async def disconnect(sid: str):
|
|
stored_session = await netplay_socket_handler.socket_server.get_session(sid)
|
|
session_id = stored_session.get("session_id")
|
|
player_id = stored_session.get("player_id")
|
|
|
|
if session_id and player_id:
|
|
await _handle_leave(sid, session_id, player_id)
|
|
|
|
|
|
async def _broadcast_to_room(sid: str, event: str, data: Any):
|
|
stored_session = await netplay_socket_handler.socket_server.get_session(sid)
|
|
session_id = stored_session.get("session_id")
|
|
if session_id:
|
|
await netplay_socket_handler.socket_server.emit(
|
|
event, data, room=session_id, skip_sid=sid
|
|
)
|
|
|
|
|
|
@netplay_socket_handler.socket_server.on("data-message") # type: ignore
|
|
async def data_message(sid: str, data: Any):
|
|
await _broadcast_to_room(sid, "data-message", data)
|
|
|
|
|
|
@netplay_socket_handler.socket_server.on("snapshot") # type: ignore
|
|
async def snapshot(sid: str, data: Any):
|
|
await _broadcast_to_room(sid, "snapshot", data)
|
|
|
|
|
|
@netplay_socket_handler.socket_server.on("input") # type: ignore
|
|
async def input(sid: str, data: Any):
|
|
await _broadcast_to_room(sid, "input", data)
|