您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
188 行
6.2 KiB
188 行
6.2 KiB
using System;
|
|
using System.Runtime.InteropServices;
|
|
using Newtonsoft.Json;
|
|
using System.Collections.Generic;
|
|
using MetaCity.Core.Messages;
|
|
using UnityEngine;
|
|
using UnityConsole;
|
|
|
|
namespace MetaCity.Core
|
|
{
|
|
public class SyncController : MonoBehaviour
|
|
{
|
|
public static SyncController Instance { get; private set; }
|
|
|
|
public PlayerInfo LocalPlayerInfo;
|
|
|
|
[NonSerialized]
|
|
public GameObject LocalPlayer;
|
|
|
|
private readonly Dictionary<string, GameObject> _players = new Dictionary<string, GameObject>();
|
|
|
|
private float _elapsedTimeFromLastStamp = 0f;
|
|
|
|
private float _stampInterval = 1f;
|
|
|
|
private Dictionary<MessageType, string> messageCache = new Dictionary<MessageType, string>();
|
|
|
|
[DllImport("__Internal")]
|
|
private static extern void SendMessageToJs(string jsonMessage);
|
|
|
|
public Action<MessageType, string> ReceiveMessageEvent;
|
|
|
|
private void Awake()
|
|
{
|
|
if (Instance != null && Instance != this)
|
|
{
|
|
Destroy(this);
|
|
}
|
|
else
|
|
{
|
|
Instance = this;
|
|
}
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
ConsoleCommandsDatabase.RegisterCommand("ReceiveMessage", (args =>
|
|
{
|
|
if (args.Length != 2)
|
|
{
|
|
return ConsoleCommandResult.Failed("Must have 2 params. `ReceiveMessage type_int message_string`");
|
|
}
|
|
var messageType = Int32.Parse(args[0]);
|
|
var messageBody = args[1];
|
|
ReceiveMessageEvent.Invoke((MessageType)messageType, messageBody);
|
|
return ConsoleCommandResult.Succeeded();
|
|
}));
|
|
#if !UNITY_EDITOR && UNITY_WEBGL
|
|
// disable WebGLInput.captureAllKeyboardInput so elements in web page can handle keyboard inputs
|
|
// WebGLInput.captureAllKeyboardInput = false;
|
|
#endif
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
#if !UNITY_EDITOR && (UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX)
|
|
string message = CloudStreaming.PeekMessage();
|
|
if (message != null)
|
|
{
|
|
ReceiveMessage(message);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
public void ReportError(string message, bool isFatal)
|
|
{
|
|
SendMessage(MessageType.GameError, message);
|
|
if (isFatal)
|
|
{
|
|
Application.Quit(-1);
|
|
}
|
|
}
|
|
|
|
public void SendMessage(MessageType type, string body = "", bool ignoreIfNotChanged = false)
|
|
{
|
|
string message = JsonConvert.SerializeObject(new Message(type, body));
|
|
if (ignoreIfNotChanged)
|
|
{
|
|
string oldMessage;
|
|
messageCache.TryGetValue(type, out oldMessage);
|
|
if (message.Equals(oldMessage))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
messageCache[type] = message;
|
|
#if !UNITY_EDITOR && UNITY_WEBGL
|
|
SendMessageToJs(message);
|
|
#elif !UNITY_EDITOR && (UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX)
|
|
CloudStreaming.PostMessage(message);
|
|
#else
|
|
Debug.Log($"[SendMessage] MessageType: {type.ToString()} {type}\n {body}");
|
|
#endif
|
|
}
|
|
|
|
public void ReceiveMessage(string jsonMessage)
|
|
{
|
|
Message message = JsonConvert.DeserializeObject<Message>(jsonMessage);
|
|
switch (message.type)
|
|
{
|
|
case MessageType.ApplicationQuit:
|
|
#if UNITY_EDITOR
|
|
UnityEditor.EditorApplication.isPlaying = false;
|
|
#else
|
|
Application.Quit();
|
|
#endif
|
|
break;
|
|
case MessageType.EnableConsole:
|
|
ConsoleController.Instance.toggleKey = message.body == "1" ? KeyCode.BackQuote : KeyCode.None;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
Debug.LogWarning("Processing message:" + jsonMessage);
|
|
ReceiveMessageEvent.Invoke(message.type, message.body);
|
|
}
|
|
|
|
// Invoke when MessageType.PlayerJoins received
|
|
public void RegisterPlayer(string userId, GameObject player)
|
|
{
|
|
_players.TryAdd(userId, player);
|
|
}
|
|
|
|
// Invoke when MessageType.PlayerExits received
|
|
public void UnregisterPlayer(string userId)
|
|
{
|
|
_players.Remove(userId);
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
// join meeting
|
|
_elapsedTimeFromLastStamp += Time.deltaTime;
|
|
if (_elapsedTimeFromLastStamp >= _stampInterval)
|
|
{
|
|
_elapsedTimeFromLastStamp = 0;
|
|
// Try to join meeting
|
|
if (LocalPlayerInfo != null)
|
|
{
|
|
SortedList<float, string> characters = new SortedList<float, string>();
|
|
// GetCharactersWithinDistance(Self.Position, 2f, characters, true, false);
|
|
GetPlayerWithinSphere(10f, characters, true);
|
|
// Send available players to prepare join meeting
|
|
SendMessage(MessageType.JoinMeeting, String.Join(",", characters.Values), true);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void GetPlayerWithinSphere(float radius, SortedList<float, string> charactersOut,
|
|
bool excludeSelf = false, bool requireIdle = false)
|
|
{
|
|
float num = radius * radius;
|
|
|
|
foreach (var kv in _players)
|
|
{
|
|
string userId = kv.Key;
|
|
GameObject player = kv.Value;
|
|
if (excludeSelf && userId == LocalPlayerInfo.userId)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var dist = (LocalPlayer.transform.position - player.transform.position).sqrMagnitude;
|
|
if (dist < num)
|
|
{
|
|
charactersOut.Add(dist, userId);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
ConsoleCommandsDatabase.UnRegisterCommand("ReceiveMessage");
|
|
}
|
|
}
|
|
}
|