您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

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");
}
}
}