Tetra/Minesweeper/Assets/Scripts/RemoteStatePusher.cs
2025-05-01 01:48:08 -07:00

116 lines
3.9 KiB
C#

using UnityEngine;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Collections;
// DTOs (make sure these match your existing definitions)
[Serializable]
public class TileDto {
public int x, y;
public bool isRevealed, isFlagged;
public int nearbyMines;
public string aura;
}
[Serializable]
public class PieceDto {
public string type;
public List<Vector2Int> cells;
}
[Serializable]
public class BoardStateDto {
public string gameId;
public List<TileDto> board;
public PieceDto nextPiece;
public PieceDto heldPiece;
public List<Vector2Int> ghostCells;
}
public class RemoteStatePusher : MonoBehaviour {
// WebGL plugin externs
[DllImport("__Internal")] static extern void WSInit(string url);
[DllImport("__Internal")] static extern void WSSend(string json);
GameManager _gm;
TetrominoSpawner _spawner;
void Awake() {
_gm = GameObject.FindWithTag("GameController").GetComponent<GameManager>();
_spawner = FindObjectOfType<TetrominoSpawner>();
}
IEnumerator Start() {
#if UNITY_WEBGL && !UNITY_EDITOR
var gameId = GameSession.Instance.GameId;
WSInit($"ws://localhost:3250/ws?gameId={gameId}");
yield return new WaitForSeconds(0.1f);
Debug.Log("[RemoteStatePusher] WS initialized");
#endif
// hook into your game events
GameManager.OnNewPieceEvent += PushCurrentState;
GameManager.OnHardDropEvent += PushCurrentState;
GameManager.OnLeftStuckEvent += PushCurrentState;
GameManager.OnRightStuckEvent += PushCurrentState;
GameManager.OnMinoLockEvent += PushCurrentState;
yield break;
}
void OnDestroy() {
// unhook events if you like
GameManager.OnNewPieceEvent -= PushCurrentState;
GameManager.OnHardDropEvent -= PushCurrentState;
GameManager.OnLeftStuckEvent -= PushCurrentState;
GameManager.OnRightStuckEvent -= PushCurrentState;
GameManager.OnMinoLockEvent -= PushCurrentState;
// clean up WebSocket connection if neede
}
void PushCurrentState() {
var dto = GetBoardState();
dto.gameId = GameSession.Instance.GameId;
var json = JsonUtility.ToJson(dto);
Debug.Log($"[RemoteStatePusher] Sending state: {json}");
#if UNITY_WEBGL && !UNITY_EDITOR
WSSend(json);
#endif
}
BoardStateDto GetBoardState() {
var dto = new BoardStateDto { board = new List<TileDto>(), gameId = GameSession.Instance.GameId };
for (int x = 0; x < _gm.sizeX; x++) {
for (int y = 0; y < _gm.sizeY; y++) {
var go = GameManager.gameBoard[x][y];
if (go == null) continue;
var tile = go.GetComponent<Tile>();
dto.board.Add(new TileDto {
x = x,
y = y,
isRevealed = tile.isRevealed,
isFlagged = tile.isFlagged,
nearbyMines = tile.isRevealed ? tile.nearbyMines : -1,
aura = tile.aura.ToString()
});
}
}
dto.nextPiece = _spawner.tetrominoPreviewList.Count > 0
? BuildPieceDto(_spawner.tetrominoPreviewList[0])
: null;
var holdComp = UnityEngine.Object.FindFirstObjectByType<HoldTetromino>();
dto.heldPiece = (holdComp != null && holdComp.heldTetromino != null)
? BuildPieceDto(holdComp.heldTetromino)
: null;
return dto;
}
PieceDto BuildPieceDto(GameObject piece) {
var group = piece.GetComponent<Group>();
var cells = new List<Vector2Int>();
foreach (var t in group.GetChildTiles())
cells.Add(new Vector2Int(t.coordX, t.coordY));
return new PieceDto {
type = group.tetrominoType.ToString(),
cells = cells
};
}
}