ADD : 후원 이벤트 처리 스크립트 추가
This commit is contained in:
parent
5209862678
commit
fd7a89701d
8
Assets/Scripts/WefLab.meta
Normal file
8
Assets/Scripts/WefLab.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8cc56f0c0c16686438285879ef2a7583
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
729
Assets/Scripts/WefLab/WefLabWebSocketClient.cs
Normal file
729
Assets/Scripts/WefLab/WefLabWebSocketClient.cs
Normal file
@ -0,0 +1,729 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Networking;
|
||||
using WebSocketSharp;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace WefLab
|
||||
{
|
||||
/// <summary>
|
||||
/// Donation data structure
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class DonationData
|
||||
{
|
||||
public string platform;
|
||||
public string donationType;
|
||||
public int amount;
|
||||
public string message;
|
||||
public string donorName;
|
||||
public long timestamp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unity event with donation data parameter
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class DonationEvent : UnityEvent<DonationData> { }
|
||||
|
||||
/// <summary>
|
||||
/// Donation event trigger based on amount range
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class DonationEventTrigger
|
||||
{
|
||||
[Tooltip("Name for this donation trigger (e.g., 'Small Donation', 'Large Donation')")]
|
||||
public string triggerName = "New Trigger";
|
||||
|
||||
[Header("Amount Range")]
|
||||
[Tooltip("Minimum donation amount (inclusive)")]
|
||||
public int minAmount = 0;
|
||||
|
||||
[Tooltip("Maximum donation amount (inclusive, -1 for unlimited)")]
|
||||
public int maxAmount = -1;
|
||||
|
||||
[Header("Event Settings")]
|
||||
[Tooltip("Number of times to repeat the event (minimum 1)")]
|
||||
[Min(1)]
|
||||
public int repeatCount = 1;
|
||||
|
||||
[Tooltip("Delay between each repeat in seconds (0 for immediate)")]
|
||||
[Min(0)]
|
||||
public float repeatDelay = 0f;
|
||||
|
||||
[Header("Event")]
|
||||
[Tooltip("Unity event to trigger when donation amount is in range")]
|
||||
public DonationEvent onDonation;
|
||||
|
||||
/// <summary>
|
||||
/// Check if donation amount is within range
|
||||
/// </summary>
|
||||
public bool IsInRange(int amount)
|
||||
{
|
||||
if (amount < minAmount)
|
||||
return false;
|
||||
|
||||
if (maxAmount >= 0 && amount > maxAmount)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WefLab WebSocket client for receiving donation events
|
||||
/// Implements Engine.IO v4 and Socket.IO protocol
|
||||
/// </summary>
|
||||
public class WefLabWebSocketClient : MonoBehaviour
|
||||
{
|
||||
[Header("WefLab Settings")]
|
||||
[Tooltip("WefLab page URL (e.g., https://weflab.com/page/guPK2ODAmmRvYG4)")]
|
||||
public string pageUrl = "https://weflab.com/page/guPK2ODAmmRvYG4";
|
||||
|
||||
[Header("Donation Event Triggers")]
|
||||
[Tooltip("Donation event triggers based on amount ranges")]
|
||||
public DonationEventTrigger[] donationTriggers = Array.Empty<DonationEventTrigger>();
|
||||
|
||||
// Hidden connection info
|
||||
[HideInInspector] public bool isConnected = false;
|
||||
[HideInInspector] public string currentSid = "";
|
||||
[HideInInspector] public string extractedUserIdx = "";
|
||||
|
||||
// WebSocket connection
|
||||
private WebSocket ws;
|
||||
private string userIdx = ""; // Will be extracted from page
|
||||
private string socketSid = "";
|
||||
private bool isExtracting = false;
|
||||
|
||||
// Ping/Pong settings
|
||||
private float pingInterval = 30f;
|
||||
private float lastPingTime = 0f;
|
||||
|
||||
// Thread-safe action queue for main thread
|
||||
private Queue<Action> mainThreadActions = new Queue<Action>();
|
||||
private object actionLock = new object();
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Extract user idx from page URL and then connect
|
||||
StartCoroutine(ExtractUserIdxAndConnect());
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// Execute queued actions on main thread
|
||||
lock (actionLock)
|
||||
{
|
||||
while (mainThreadActions.Count > 0)
|
||||
{
|
||||
mainThreadActions.Dequeue()?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract user index from page URL and connect
|
||||
/// </summary>
|
||||
private IEnumerator ExtractUserIdxAndConnect()
|
||||
{
|
||||
if (string.IsNullOrEmpty(pageUrl))
|
||||
{
|
||||
Debug.LogError("[WefLab] Page URL is empty! Please set the page URL in Inspector.");
|
||||
yield break;
|
||||
}
|
||||
|
||||
isExtracting = true;
|
||||
Debug.Log($"[WefLab] Fetching page URL: {pageUrl}");
|
||||
|
||||
// Fetch the page HTML
|
||||
using (UnityWebRequest request = UnityWebRequest.Get(pageUrl))
|
||||
{
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
if (request.result != UnityWebRequest.Result.Success)
|
||||
{
|
||||
Debug.LogError($"[WefLab] Failed to fetch page: {request.error}");
|
||||
isExtracting = false;
|
||||
yield break;
|
||||
}
|
||||
|
||||
string htmlContent = request.downloadHandler.text;
|
||||
|
||||
// Extract userIdx from JavaScript in the page
|
||||
// Look for pattern: loginData = {...}
|
||||
Match loginDataMatch = Regex.Match(htmlContent, @"loginData\s*=\s*(\{[^;]+\});", RegexOptions.Singleline);
|
||||
|
||||
if (loginDataMatch.Success)
|
||||
{
|
||||
try
|
||||
{
|
||||
string loginDataJson = loginDataMatch.Groups[1].Value;
|
||||
var loginData = JsonConvert.DeserializeObject<JObject>(loginDataJson);
|
||||
|
||||
// Extract idx from loginData
|
||||
userIdx = loginData["idx"]?.ToString() ?? "";
|
||||
|
||||
if (!string.IsNullOrEmpty(userIdx))
|
||||
{
|
||||
extractedUserIdx = userIdx;
|
||||
Debug.Log($"[WefLab] Successfully extracted userIdx: {userIdx}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("[WefLab] userIdx not found in loginData");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[WefLab] Error parsing loginData: {ex.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("[WefLab] Could not find loginData in page HTML");
|
||||
}
|
||||
}
|
||||
|
||||
isExtracting = false;
|
||||
|
||||
// Connect if we successfully extracted the userIdx
|
||||
if (!string.IsNullOrEmpty(userIdx))
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("[WefLab] Cannot connect - userIdx extraction failed");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connect to WefLab WebSocket server
|
||||
/// </summary>
|
||||
public void Connect()
|
||||
{
|
||||
if (ws != null && ws.IsAlive)
|
||||
{
|
||||
Debug.LogWarning("[WefLab] Already connected");
|
||||
return;
|
||||
}
|
||||
|
||||
// Build WebSocket URL
|
||||
string wsUrl = $"wss://ssmain.weflab.com/socket.io/?idx={userIdx}&type=page&page=alert&EIO=4&transport=websocket";
|
||||
|
||||
Debug.Log($"[WefLab] Connecting to: {wsUrl}");
|
||||
|
||||
ws = new WebSocket(wsUrl);
|
||||
|
||||
// Event handlers
|
||||
ws.OnOpen += OnWebSocketOpen;
|
||||
ws.OnMessage += OnWebSocketMessage;
|
||||
ws.OnError += OnWebSocketError;
|
||||
ws.OnClose += OnWebSocketClose;
|
||||
|
||||
// Connect
|
||||
ws.ConnectAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnect from WebSocket
|
||||
/// </summary>
|
||||
public void Disconnect()
|
||||
{
|
||||
if (ws != null)
|
||||
{
|
||||
ws.Close();
|
||||
ws = null;
|
||||
}
|
||||
|
||||
isConnected = false;
|
||||
socketSid = "";
|
||||
currentSid = "";
|
||||
}
|
||||
|
||||
#region WebSocket Event Handlers
|
||||
|
||||
private void OnWebSocketOpen(object sender, EventArgs e)
|
||||
{
|
||||
EnqueueMainThreadAction(() =>
|
||||
{
|
||||
Debug.Log("[WefLab] WebSocket connection opened");
|
||||
});
|
||||
}
|
||||
|
||||
private void OnWebSocketMessage(object sender, MessageEventArgs e)
|
||||
{
|
||||
string data = e.Data;
|
||||
|
||||
EnqueueMainThreadAction(() =>
|
||||
{
|
||||
ProcessMessage(data);
|
||||
});
|
||||
}
|
||||
|
||||
private void OnWebSocketError(object sender, ErrorEventArgs e)
|
||||
{
|
||||
EnqueueMainThreadAction(() =>
|
||||
{
|
||||
Debug.LogError($"[WefLab] WebSocket error: {e.Message}");
|
||||
if (e.Exception != null)
|
||||
{
|
||||
Debug.LogError($"[WefLab] Exception: {e.Exception}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void OnWebSocketClose(object sender, CloseEventArgs e)
|
||||
{
|
||||
EnqueueMainThreadAction(() =>
|
||||
{
|
||||
Debug.Log($"[WefLab] WebSocket closed. Code: {e.Code}, Reason: {e.Reason}");
|
||||
isConnected = false;
|
||||
socketSid = "";
|
||||
currentSid = "";
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Message Processing
|
||||
|
||||
/// <summary>
|
||||
/// Process incoming WebSocket message
|
||||
/// </summary>
|
||||
private void ProcessMessage(string data)
|
||||
{
|
||||
if (string.IsNullOrEmpty(data))
|
||||
return;
|
||||
|
||||
// Get message type (first character or first two characters)
|
||||
string messageType = data.Length >= 2 && char.IsDigit(data[1])
|
||||
? data.Substring(0, 2)
|
||||
: data.Substring(0, 1);
|
||||
|
||||
string payload = data.Substring(messageType.Length);
|
||||
|
||||
switch (messageType)
|
||||
{
|
||||
case "0": // Engine.IO OPEN
|
||||
HandleEngineOpen(payload);
|
||||
break;
|
||||
|
||||
case "2": // Engine.IO PING
|
||||
HandlePing();
|
||||
break;
|
||||
|
||||
case "3": // Engine.IO PONG
|
||||
Debug.Log("[WefLab] Received PONG");
|
||||
break;
|
||||
|
||||
case "40": // Socket.IO CONNECT
|
||||
HandleSocketConnect(payload);
|
||||
break;
|
||||
|
||||
case "42": // Socket.IO EVENT
|
||||
HandleSocketEvent(payload);
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.Log($"[WefLab] Unknown message type: {messageType} | Data: {data}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle Engine.IO OPEN message (handshake)
|
||||
/// </summary>
|
||||
private void HandleEngineOpen(string payload)
|
||||
{
|
||||
try
|
||||
{
|
||||
var openData = JsonConvert.DeserializeObject<JObject>(payload);
|
||||
currentSid = openData["sid"]?.ToString() ?? "";
|
||||
|
||||
if (openData["pingInterval"] != null)
|
||||
{
|
||||
pingInterval = openData["pingInterval"].Value<float>() / 1000f; // Convert to seconds
|
||||
}
|
||||
|
||||
Debug.Log($"[WefLab] Engine.IO OPEN - SID: {currentSid}, PingInterval: {pingInterval}s");
|
||||
Debug.Log($"[WefLab] Full handshake data: {payload}");
|
||||
|
||||
// Send Socket.IO CONNECT
|
||||
SendSocketConnect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[WefLab] Error parsing OPEN message: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle Engine.IO PING
|
||||
/// </summary>
|
||||
private void HandlePing()
|
||||
{
|
||||
Debug.Log("[WefLab] Received PING, sending PONG");
|
||||
SendMessage("3"); // Send PONG
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle Socket.IO CONNECT response
|
||||
/// </summary>
|
||||
private void HandleSocketConnect(string payload)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(payload))
|
||||
{
|
||||
var connectData = JsonConvert.DeserializeObject<JObject>(payload);
|
||||
socketSid = connectData["sid"]?.ToString() ?? "";
|
||||
Debug.Log($"[WefLab] Socket.IO CONNECT - SID: {socketSid}");
|
||||
Debug.Log($"[WefLab] Full connect data: {payload}");
|
||||
}
|
||||
|
||||
isConnected = true;
|
||||
|
||||
// Send join message
|
||||
SendJoinMessage();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[WefLab] Error parsing Socket.IO CONNECT: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle Socket.IO EVENT message (donation data)
|
||||
/// </summary>
|
||||
private void HandleSocketEvent(string payload)
|
||||
{
|
||||
try
|
||||
{
|
||||
var eventArray = JsonConvert.DeserializeObject<JArray>(payload);
|
||||
|
||||
if (eventArray == null || eventArray.Count < 2)
|
||||
{
|
||||
Debug.LogWarning($"[WefLab] Invalid event format: {payload}");
|
||||
return;
|
||||
}
|
||||
|
||||
string eventName = eventArray[0].ToString();
|
||||
var eventData = eventArray[1] as JObject;
|
||||
|
||||
Debug.Log($"[WefLab] ========== EVENT RECEIVED ==========");
|
||||
Debug.Log($"[WefLab] Event Name: {eventName}");
|
||||
Debug.Log($"[WefLab] Event Data: {eventData?.ToString(Formatting.Indented)}");
|
||||
Debug.Log($"[WefLab] ===================================");
|
||||
|
||||
if (eventName == "msg")
|
||||
{
|
||||
HandleMessageEvent(eventData);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[WefLab] Error parsing Socket.IO EVENT: {ex.Message}");
|
||||
Debug.LogError($"[WefLab] Payload: {payload}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle "msg" event (donation notifications)
|
||||
/// </summary>
|
||||
private void HandleMessageEvent(JObject msgData)
|
||||
{
|
||||
if (msgData == null)
|
||||
return;
|
||||
|
||||
string msgType = msgData["type"]?.ToString() ?? "";
|
||||
|
||||
switch (msgType)
|
||||
{
|
||||
case "test_donation":
|
||||
HandleTestDonation(msgData);
|
||||
break;
|
||||
|
||||
case "donation":
|
||||
case "SENDBALLOON":
|
||||
case "cheese":
|
||||
case "superchat":
|
||||
case "bits":
|
||||
HandleDonation(msgData);
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.Log($"[WefLab] Unhandled message type: {msgType}");
|
||||
Debug.Log($"[WefLab] Data: {msgData.ToString(Formatting.Indented)}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalize donation amount to unified currency (Chzzk standard: 1 = 1 KRW)
|
||||
/// SOOP (Afreeca): 1 balloon = 100 KRW → multiply by 100
|
||||
/// Chzzk: 1 cheese = 1 KRW → no conversion
|
||||
/// YouTube: Keep as-is (already in KRW equivalent)
|
||||
/// Twitch: Keep as-is
|
||||
/// </summary>
|
||||
private static int NormalizeDonationAmount(string platform, int rawAmount)
|
||||
{
|
||||
platform = platform.ToLower();
|
||||
|
||||
if (platform == "afreeca" || platform == "soop")
|
||||
{
|
||||
// SOOP: 1 balloon = 100 KRW
|
||||
return rawAmount * 100;
|
||||
}
|
||||
|
||||
// Chzzk, YouTube, Twitch: no conversion needed
|
||||
return rawAmount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle test donation event
|
||||
/// </summary>
|
||||
private void HandleTestDonation(JObject msgData)
|
||||
{
|
||||
if (msgData["data"] is not JObject donationDataJson)
|
||||
return;
|
||||
|
||||
string platform = donationDataJson["platform"]?.ToString() ?? "unknown";
|
||||
string type = donationDataJson["type"]?.ToString() ?? "unknown";
|
||||
int rawAmount = 0;
|
||||
|
||||
// Parse amount
|
||||
if (int.TryParse(donationDataJson["value"]?.ToString(), out int parsedAmount))
|
||||
{
|
||||
rawAmount = parsedAmount;
|
||||
}
|
||||
|
||||
// Normalize amount based on platform
|
||||
int amount = NormalizeDonationAmount(platform, rawAmount);
|
||||
|
||||
string message = donationDataJson["msg"]?.ToString() ?? "";
|
||||
long timestamp = donationDataJson["time"]?.Value<long>() ?? 0;
|
||||
|
||||
Debug.Log($"[WefLab] *** TEST DONATION ***");
|
||||
Debug.Log($"[WefLab] Platform: {platform}");
|
||||
Debug.Log($"[WefLab] Type: {type}");
|
||||
Debug.Log($"[WefLab] Raw Amount: {rawAmount} → Normalized: {amount} KRW");
|
||||
Debug.Log($"[WefLab] Message: {message}");
|
||||
Debug.Log($"[WefLab] Timestamp: {timestamp}");
|
||||
|
||||
// Create donation data and trigger events
|
||||
DonationData donation = new()
|
||||
{
|
||||
platform = platform,
|
||||
donationType = type,
|
||||
amount = amount,
|
||||
message = message,
|
||||
donorName = "Test Donor",
|
||||
timestamp = timestamp
|
||||
};
|
||||
|
||||
TriggerDonationEvents(donation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle real donation event
|
||||
/// </summary>
|
||||
private void HandleDonation(JObject msgData)
|
||||
{
|
||||
Debug.Log($"[WefLab] *** REAL DONATION ***");
|
||||
Debug.Log($"[WefLab] Full donation data: {msgData.ToString(Formatting.Indented)}");
|
||||
|
||||
if (msgData["data"] is not JObject donationDataJson)
|
||||
return;
|
||||
|
||||
string platform = msgData["platform"]?.ToString() ?? "unknown";
|
||||
string type = msgData["type"]?.ToString() ?? "unknown";
|
||||
int rawAmount = 0;
|
||||
|
||||
// Parse amount from different possible fields
|
||||
if (donationDataJson["value"] != null && int.TryParse(donationDataJson["value"].ToString(), out int parsedValue))
|
||||
{
|
||||
rawAmount = parsedValue;
|
||||
}
|
||||
else if (donationDataJson["amount"] != null && int.TryParse(donationDataJson["amount"].ToString(), out int parsedAmount))
|
||||
{
|
||||
rawAmount = parsedAmount;
|
||||
}
|
||||
|
||||
// Normalize amount based on platform
|
||||
int amount = NormalizeDonationAmount(platform, rawAmount);
|
||||
|
||||
string message = donationDataJson["msg"]?.ToString() ?? donationDataJson["message"]?.ToString() ?? "";
|
||||
string donorName = donationDataJson["nickname"]?.ToString() ?? donationDataJson["name"]?.ToString() ?? "Anonymous";
|
||||
long timestamp = donationDataJson["time"]?.Value<long>() ?? DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
|
||||
// Create donation data
|
||||
DonationData donation = new()
|
||||
{
|
||||
platform = platform,
|
||||
donationType = type,
|
||||
amount = amount,
|
||||
message = message,
|
||||
donorName = donorName,
|
||||
timestamp = timestamp
|
||||
};
|
||||
|
||||
Debug.Log($"[WefLab] Donation: {donorName} - {rawAmount} → {amount} KRW ({platform})");
|
||||
|
||||
// Trigger events
|
||||
TriggerDonationEvents(donation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trigger donation events based on amount range
|
||||
/// </summary>
|
||||
private void TriggerDonationEvents(DonationData donation)
|
||||
{
|
||||
if (donationTriggers == null || donationTriggers.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("[WefLab] No donation triggers configured");
|
||||
return;
|
||||
}
|
||||
|
||||
bool triggeredAny = false;
|
||||
|
||||
// Check each trigger
|
||||
foreach (var trigger in donationTriggers)
|
||||
{
|
||||
if (trigger == null)
|
||||
continue;
|
||||
|
||||
// Check if donation amount is in range
|
||||
if (trigger.IsInRange(donation.amount))
|
||||
{
|
||||
Debug.Log($"[WefLab] Triggering: {trigger.triggerName} (Amount: {donation.amount}, Range: {trigger.minAmount}-{(trigger.maxAmount >= 0 ? trigger.maxAmount.ToString() : "unlimited")}, Repeat: {trigger.repeatCount}x)");
|
||||
|
||||
// Start coroutine to handle repeated invocation
|
||||
StartCoroutine(InvokeRepeatedEvent(trigger, donation));
|
||||
triggeredAny = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!triggeredAny)
|
||||
{
|
||||
Debug.LogWarning($"[WefLab] No triggers matched for donation amount: {donation.amount}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine to invoke event multiple times with delay
|
||||
/// </summary>
|
||||
private IEnumerator InvokeRepeatedEvent(DonationEventTrigger trigger, DonationData donation)
|
||||
{
|
||||
for (int i = 0; i < trigger.repeatCount; i++)
|
||||
{
|
||||
// Invoke the event
|
||||
trigger.onDonation?.Invoke(donation);
|
||||
|
||||
// Wait for delay before next repetition (skip on last iteration)
|
||||
if (i < trigger.repeatCount - 1 && trigger.repeatDelay > 0)
|
||||
{
|
||||
yield return new WaitForSeconds(trigger.repeatDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Send Messages
|
||||
|
||||
/// <summary>
|
||||
/// Send Socket.IO CONNECT message (40)
|
||||
/// </summary>
|
||||
private void SendSocketConnect()
|
||||
{
|
||||
Debug.Log("[WefLab] Sending Socket.IO CONNECT (40)");
|
||||
SendMessage("40");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send join message to subscribe to donation events
|
||||
/// </summary>
|
||||
private void SendJoinMessage()
|
||||
{
|
||||
var joinData = new
|
||||
{
|
||||
type = "join",
|
||||
page = "page",
|
||||
idx = userIdx,
|
||||
pageid = "alert",
|
||||
preset = "0"
|
||||
};
|
||||
|
||||
var message = new object[] { "msg", joinData };
|
||||
string json = JsonConvert.SerializeObject(message);
|
||||
string fullMessage = "42" + json;
|
||||
|
||||
Debug.Log($"[WefLab] Sending JOIN message: {fullMessage}");
|
||||
SendMessage(fullMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send raw message through WebSocket
|
||||
/// </summary>
|
||||
private void SendMessage(string message)
|
||||
{
|
||||
if (ws != null && ws.IsAlive)
|
||||
{
|
||||
ws.Send(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[WefLab] Cannot send message - WebSocket not connected");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Thread Safety
|
||||
|
||||
/// <summary>
|
||||
/// Enqueue action to be executed on main thread
|
||||
/// </summary>
|
||||
private void EnqueueMainThreadAction(Action action)
|
||||
{
|
||||
lock (actionLock)
|
||||
{
|
||||
mainThreadActions.Enqueue(action);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reconnect to WebSocket
|
||||
/// </summary>
|
||||
public void Reconnect()
|
||||
{
|
||||
Disconnect();
|
||||
Connect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if connected
|
||||
/// </summary>
|
||||
public bool IsConnected()
|
||||
{
|
||||
return isConnected && ws != null && ws.IsAlive;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/WefLab/WefLabWebSocketClient.cs.meta
Normal file
2
Assets/Scripts/WefLab/WefLabWebSocketClient.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b7cb7cbeddf11148824325615980e1a
|
||||
Loading…
x
Reference in New Issue
Block a user