mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-01-30 03:32:47 +00:00
Merge branch 'dev' into steamworks-v3
This commit is contained in:
commit
b4763c835e
@ -4,11 +4,27 @@ using UnityEngine.Events;
|
||||
|
||||
public interface IQSBAPI
|
||||
{
|
||||
#region General
|
||||
|
||||
/// <summary>
|
||||
/// If called, all players connected to YOUR hosted game must have this mod installed.
|
||||
/// </summary>
|
||||
void RegisterRequiredForAllPlayers(IModBehaviour mod);
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the current player is the host.
|
||||
/// </summary>
|
||||
bool GetIsHost();
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the current player is in multiplayer.
|
||||
/// </summary>
|
||||
bool GetIsInMultiplayer();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Player
|
||||
|
||||
/// <summary>
|
||||
/// Returns the player ID of the current player.
|
||||
/// </summary>
|
||||
@ -22,16 +38,18 @@ public interface IQSBAPI
|
||||
|
||||
/// <summary>
|
||||
/// Returns the list of IDs of all connected players.
|
||||
///
|
||||
/// The first player in the list is the host.
|
||||
/// </summary>
|
||||
uint[] GetPlayerIDs();
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a player joins the game.
|
||||
/// Invoked when any player (local or remote) joins the game.
|
||||
/// </summary>
|
||||
UnityEvent<uint> OnPlayerJoin();
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a player leaves the game.
|
||||
/// Invoked when any player (local or remote) leaves the game.
|
||||
/// </summary>
|
||||
UnityEvent<uint> OnPlayerLeave();
|
||||
|
||||
@ -53,8 +71,14 @@ public interface IQSBAPI
|
||||
/// <returns>The data requested. If key is not valid, returns default.</returns>
|
||||
T GetCustomData<T>(uint playerId, string key);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Messaging
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message containing arbitrary data to every player.
|
||||
///
|
||||
/// Keep your messages under around 1100 bytes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data being sent. This type must be serializable.</typeparam>
|
||||
/// <param name="messageType">The unique key of the message.</param>
|
||||
@ -70,4 +94,6 @@ public interface IQSBAPI
|
||||
/// <param name="messageType">The unique key of the message.</param>
|
||||
/// <param name="handler">The action to be ran when the message is received. The uint is the player ID that sent the messsage.</param>
|
||||
void RegisterHandler<T>(string messageType, Action<uint, T> handler);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_USING/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">NEXT_LINE_SHIFTED_2</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=API/@EntryIndexedValue">API</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=QSB/@EntryIndexedValue">QSB</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UWP/@EntryIndexedValue">UWP</s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
|
@ -1,27 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OWML.Common;
|
||||
using QSB.Utility;
|
||||
|
||||
namespace QSB.API;
|
||||
|
||||
public static class AddonDataManager
|
||||
{
|
||||
private static readonly Dictionary<string, Action<uint, object>> _handlers = new();
|
||||
private static readonly Dictionary<int, Action<uint, object>> _handlers = new();
|
||||
|
||||
public static void OnReceiveDataMessage(string messageType, object data, uint from)
|
||||
public static void OnReceiveDataMessage(int hash, object data, uint from)
|
||||
{
|
||||
DebugLog.DebugWrite($"Received data message of message type \"{messageType}\" from {from}!");
|
||||
if (!_handlers.TryGetValue(messageType, out var handler))
|
||||
DebugLog.DebugWrite($"Received addon message of with hash {hash} from {from}!");
|
||||
if (!_handlers.TryGetValue(hash, out var handler))
|
||||
{
|
||||
DebugLog.DebugWrite($"unknown addon message type with hash {hash}", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
handler(from, data);
|
||||
}
|
||||
|
||||
public static void RegisterHandler<T>(string messageType, Action<uint, T> handler)
|
||||
public static void RegisterHandler<T>(int hash, Action<uint, T> handler)
|
||||
{
|
||||
DebugLog.DebugWrite($"Registering handler for \"{messageType}\" with type of {typeof(T).Name}");
|
||||
_handlers.Add(messageType, (from, data) => handler(from, (T)data));
|
||||
DebugLog.DebugWrite($"Registering addon message handler for hash {hash} with type {typeof(T).Name}");
|
||||
_handlers.Add(hash, (from, data) => handler(from, (T)data));
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,27 @@ using UnityEngine.Events;
|
||||
|
||||
public interface IQSBAPI
|
||||
{
|
||||
#region General
|
||||
|
||||
/// <summary>
|
||||
/// If called, all players connected to YOUR hosted game must have this mod installed.
|
||||
/// </summary>
|
||||
void RegisterRequiredForAllPlayers(IModBehaviour mod);
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the current player is the host.
|
||||
/// </summary>
|
||||
bool GetIsHost();
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the current player is in multiplayer.
|
||||
/// </summary>
|
||||
bool GetIsInMultiplayer();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Player
|
||||
|
||||
/// <summary>
|
||||
/// Returns the player ID of the current player.
|
||||
/// </summary>
|
||||
@ -22,21 +38,25 @@ public interface IQSBAPI
|
||||
|
||||
/// <summary>
|
||||
/// Returns the list of IDs of all connected players.
|
||||
///
|
||||
/// The first player in the list is the host.
|
||||
/// </summary>
|
||||
uint[] GetPlayerIDs();
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a player joins the game.
|
||||
/// Invoked when any player (local or remote) joins the game.
|
||||
/// </summary>
|
||||
UnityEvent<uint> OnPlayerJoin();
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a player leaves the game.
|
||||
/// Invoked when any player (local or remote) leaves the game.
|
||||
/// </summary>
|
||||
UnityEvent<uint> OnPlayerLeave();
|
||||
|
||||
/// <summary>
|
||||
/// Sets some arbitrary data for a given player.
|
||||
///
|
||||
/// Not synced.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data.</typeparam>
|
||||
/// <param name="playerId">The ID of the player.</param>
|
||||
@ -46,15 +66,23 @@ public interface IQSBAPI
|
||||
|
||||
/// <summary>
|
||||
/// Returns some arbitrary data from a given player.
|
||||
///
|
||||
/// Not synced.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data.</typeparam>
|
||||
/// <param name="playerId">The ID of the player.</param>
|
||||
/// <param name="key">The unique key of the data you want to access.</param>
|
||||
/// <returns>The data requested. If key is not valid, returns default.</returns>
|
||||
T GetCustomData<T>(uint playerId, string key);
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Messaging
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message containing arbitrary data to every player.
|
||||
///
|
||||
/// Keep your messages under around 1100 bytes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data being sent. This type must be serializable.</typeparam>
|
||||
/// <param name="messageType">The unique key of the message.</param>
|
||||
@ -70,4 +98,6 @@ public interface IQSBAPI
|
||||
/// <param name="messageType">The unique key of the message.</param>
|
||||
/// <param name="handler">The action to be ran when the message is received. The uint is the player ID that sent the messsage.</param>
|
||||
void RegisterHandler<T>(string messageType, Action<uint, T> handler);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
11
QSB/API/Messages/AddonCustomDataSyncMessage.cs
Normal file
11
QSB/API/Messages/AddonCustomDataSyncMessage.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using QSB.Messaging;
|
||||
using QSB.Player;
|
||||
using QSB.Utility;
|
||||
|
||||
namespace QSB.API.Messages;
|
||||
|
||||
public class AddonCustomDataSyncMessage : QSBMessage<(uint playerId, string key, byte[] data)>
|
||||
{
|
||||
public AddonCustomDataSyncMessage(uint playerId, string key, object data) : base((playerId, key, data.ToBytes())) { }
|
||||
public override void OnReceiveRemote() => QSBPlayerManager.GetPlayer(Data.playerId).SetCustomData(Data.key, Data.data.ToObject());
|
||||
}
|
@ -1,29 +1,11 @@
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using QSB.Messaging;
|
||||
using QSB.Messaging;
|
||||
using QSB.Utility;
|
||||
|
||||
namespace QSB.API.Messages;
|
||||
|
||||
public class AddonDataMessage : QSBMessage<(string messageType, byte[] data, bool receiveLocally)>
|
||||
public class AddonDataMessage : QSBMessage<(int hash, byte[] data, bool receiveLocally)>
|
||||
{
|
||||
public AddonDataMessage(string messageType, object data, bool receiveLocally) : base((messageType, Obj2Bytes(data), receiveLocally)) { }
|
||||
|
||||
private static byte[] Obj2Bytes(object obj)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
var bf = new BinaryFormatter();
|
||||
bf.Serialize(ms, obj);
|
||||
var bytes = ms.ToArray();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private static object Bytes2Obj(byte[] bytes)
|
||||
{
|
||||
using var ms = new MemoryStream(bytes);
|
||||
var bf = new BinaryFormatter();
|
||||
var obj = bf.Deserialize(ms);
|
||||
return obj;
|
||||
}
|
||||
public AddonDataMessage(int hash, object data, bool receiveLocally) : base((hash, data.ToBytes(), receiveLocally)) { }
|
||||
|
||||
public override void OnReceiveLocal()
|
||||
{
|
||||
@ -35,7 +17,7 @@ public class AddonDataMessage : QSBMessage<(string messageType, byte[] data, boo
|
||||
|
||||
public override void OnReceiveRemote()
|
||||
{
|
||||
var obj = Bytes2Obj(Data.data);
|
||||
AddonDataManager.OnReceiveDataMessage(Data.messageType, obj, From);
|
||||
var obj = Data.data.ToObject();
|
||||
AddonDataManager.OnReceiveDataMessage(Data.hash, obj, From);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Mirror;
|
||||
using OWML.Common;
|
||||
using QSB.API.Messages;
|
||||
using QSB.Messaging;
|
||||
using QSB.Player;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace QSB.API;
|
||||
@ -16,22 +17,24 @@ public class QSBAPI : IQSBAPI
|
||||
QSBCore.Addons.Add(uniqueName, mod);
|
||||
}
|
||||
|
||||
public bool GetIsHost() => QSBCore.IsHost;
|
||||
public bool GetIsInMultiplayer() => QSBCore.IsInMultiplayer;
|
||||
|
||||
public uint GetLocalPlayerID() => QSBPlayerManager.LocalPlayerId;
|
||||
public string GetPlayerName(uint playerId) => QSBPlayerManager.GetPlayer(playerId).Name;
|
||||
public uint[] GetPlayerIDs() => QSBPlayerManager.PlayerList.Select(x => x.PlayerId).ToArray();
|
||||
|
||||
public UnityEvent<uint> OnPlayerJoin() => QSBAPIEvents.OnPlayerJoinEvent;
|
||||
|
||||
public UnityEvent<uint> OnPlayerLeave() => QSBAPIEvents.OnPlayerLeaveEvent;
|
||||
|
||||
public void SetCustomData<T>(uint playerId, string key, T data) => QSBPlayerManager.GetPlayer(playerId).SetCustomData(key, data);
|
||||
public T GetCustomData<T>(uint playerId, string key) => QSBPlayerManager.GetPlayer(playerId).GetCustomData<T>(key);
|
||||
|
||||
public void SendMessage<T>(string messageType, T data, uint to = uint.MaxValue, bool receiveLocally = false)
|
||||
=> new AddonDataMessage(messageType, data, receiveLocally) {To = to} .Send();
|
||||
=> new AddonDataMessage(messageType.GetStableHashCode(), data, receiveLocally) { To = to }.Send();
|
||||
|
||||
public void RegisterHandler<T>(string messageType, Action<uint, T> handler)
|
||||
=> AddonDataManager.RegisterHandler(messageType, handler);
|
||||
=> AddonDataManager.RegisterHandler(messageType.GetStableHashCode(), handler);
|
||||
}
|
||||
|
||||
internal static class QSBAPIEvents
|
||||
@ -43,6 +46,7 @@ internal static class QSBAPIEvents
|
||||
}
|
||||
|
||||
internal class PlayerEvent : UnityEvent<uint> { }
|
||||
internal static PlayerEvent OnPlayerJoinEvent = new PlayerEvent();
|
||||
internal static PlayerEvent OnPlayerLeaveEvent = new PlayerEvent();
|
||||
|
||||
internal static readonly PlayerEvent OnPlayerJoinEvent = new();
|
||||
internal static readonly PlayerEvent OnPlayerLeaveEvent = new();
|
||||
}
|
||||
|
@ -257,7 +257,10 @@ public class RespawnOnDeath : MonoBehaviour
|
||||
var sectorList = PlayerTransformSync.LocalInstance.SectorDetector.SectorList;
|
||||
if (sectorList.All(x => x.Type != Sector.Name.TimberHearth))
|
||||
{
|
||||
// stops sectors from breaking when you die on TH??
|
||||
// Spooky scary legacy code?
|
||||
// Original comment was "stops sectors from breaking when you die on TH??"
|
||||
// I think dying on TH used to break all the sectors. Something about you not technically re-entering TH when dying inside it.
|
||||
// I commented out these lines, and everything seemed fine. But I'm not gonna touch them just in case. :P
|
||||
Locator.GetPlayerSectorDetector().RemoveFromAllSectors();
|
||||
Locator.GetPlayerCameraDetector().GetComponent<AudioDetector>().DeactivateAllVolumes(0f);
|
||||
}
|
||||
|
@ -645,6 +645,7 @@ public class MenuManager : MonoBehaviour, IAddComponentOnStart
|
||||
}
|
||||
|
||||
LoadGame(PlayerData.GetWarpedToTheEye());
|
||||
// wait until scene load and then wait until Start has ran
|
||||
Delay.RunWhen(() => TimeLoop._initialized, QSBNetworkManager.singleton.StartHost);
|
||||
};
|
||||
|
||||
@ -655,6 +656,7 @@ public class MenuManager : MonoBehaviour, IAddComponentOnStart
|
||||
else
|
||||
{
|
||||
LoadGame(PlayerData.GetWarpedToTheEye());
|
||||
// wait until scene load and then wait until Start has ran
|
||||
Delay.RunWhen(() => TimeLoop._initialized, QSBNetworkManager.singleton.StartHost);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ using QSB.WorldSync;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
@ -29,20 +28,19 @@ public static class QSBMessageManager
|
||||
{
|
||||
#region inner workings
|
||||
|
||||
internal static readonly Type[] _types;
|
||||
internal static readonly Dictionary<Type, ushort> _typeToId = new();
|
||||
internal static readonly Dictionary<int, Type> _types = new();
|
||||
|
||||
private static string _rxPath;
|
||||
private static string _txPath;
|
||||
|
||||
static QSBMessageManager()
|
||||
{
|
||||
_types = typeof(QSBMessage).GetDerivedTypes().ToArray();
|
||||
for (ushort i = 0; i < _types.Length; i++)
|
||||
foreach (var type in typeof(QSBMessage).GetDerivedTypes())
|
||||
{
|
||||
_typeToId.Add(_types[i], i);
|
||||
var hash = type.FullName.GetStableHashCode();
|
||||
_types.Add(hash, type);
|
||||
// call static constructor of message if needed
|
||||
RuntimeHelpers.RunClassConstructor(_types[i].TypeHandle);
|
||||
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,6 +64,11 @@ public static class QSBMessageManager
|
||||
|
||||
private static void OnServerReceive(QSBMessage msg)
|
||||
{
|
||||
if (msg == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.To == uint.MaxValue)
|
||||
{
|
||||
NetworkServer.SendToAll<Wrapper>(msg);
|
||||
@ -101,9 +104,9 @@ public static class QSBMessageManager
|
||||
var player = QSBPlayerManager.GetPlayer(msg.From);
|
||||
|
||||
if (!player.IsReady
|
||||
&& player.PlayerId != QSBPlayerManager.LocalPlayerId
|
||||
&& player.State is ClientState.AliveInSolarSystem or ClientState.AliveInEye or ClientState.DeadInSolarSystem
|
||||
&& msg is not (PlayerInformationMessage or PlayerReadyMessage or RequestStateResyncMessage or ServerStateMessage))
|
||||
&& player.PlayerId != QSBPlayerManager.LocalPlayerId
|
||||
&& player.State is ClientState.AliveInSolarSystem or ClientState.AliveInEye or ClientState.DeadInSolarSystem
|
||||
&& msg is not (PlayerInformationMessage or PlayerReadyMessage or RequestStateResyncMessage or ServerStateMessage))
|
||||
{
|
||||
//DebugLog.ToConsole($"Warning - Got message {msg} from player {msg.From}, but they were not ready. Asking for state resync, just in case.", MessageType.Warning);
|
||||
new RequestStateResyncMessage().Send();
|
||||
@ -208,8 +211,12 @@ public static class ReaderWriterExtensions
|
||||
{
|
||||
private static QSBMessage ReadQSBMessage(this NetworkReader reader)
|
||||
{
|
||||
var id = reader.ReadUShort();
|
||||
var type = QSBMessageManager._types[id];
|
||||
var hash = reader.ReadInt();
|
||||
if (!QSBMessageManager._types.TryGetValue(hash, out var type))
|
||||
{
|
||||
DebugLog.DebugWrite($"unknown QSBMessage type with hash {hash}", MessageType.Error);
|
||||
return null;
|
||||
}
|
||||
var msg = (QSBMessage)FormatterServices.GetUninitializedObject(type);
|
||||
msg.Deserialize(reader);
|
||||
return msg;
|
||||
@ -218,8 +225,8 @@ public static class ReaderWriterExtensions
|
||||
private static void WriteQSBMessage(this NetworkWriter writer, QSBMessage msg)
|
||||
{
|
||||
var type = msg.GetType();
|
||||
var id = QSBMessageManager._typeToId[type];
|
||||
writer.Write(id);
|
||||
var hash = type.FullName.GetStableHashCode();
|
||||
writer.WriteInt(hash);
|
||||
msg.Serialize(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ public abstract class QSBPatch
|
||||
public void DoPatches(Harmony instance) => instance.PatchAll(GetType());
|
||||
|
||||
/// <summary>
|
||||
/// this is true when a message is received remotely (OnReceiveRemote) or a player leaves (OnRemovePlayer)
|
||||
/// this is true when a message is received remotely (OnReceiveRemote) or a remote player joins/leaves (OnAddPlayer/OnRemovePlayer)
|
||||
/// </summary>
|
||||
public static bool Remote;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using OWML.Common;
|
||||
using QSB.API.Messages;
|
||||
using QSB.ClientServerStateSync;
|
||||
using QSB.ClientServerStateSync.Messages;
|
||||
using QSB.Messaging;
|
||||
@ -50,5 +51,11 @@ public class RequestStateResyncMessage : QSBMessage
|
||||
}
|
||||
|
||||
new PlayerInformationMessage { To = From }.Send();
|
||||
|
||||
// Initial sync of all custom data from APIs
|
||||
foreach (var kvp in QSBPlayerManager.LocalPlayer._customData)
|
||||
{
|
||||
new AddonCustomDataSyncMessage(QSBPlayerManager.LocalPlayerId, kvp.Key, kvp.Value) { To = From }.Send();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
using OWML.Common;
|
||||
using QSB.Animation.Player;
|
||||
using QSB.API.Messages;
|
||||
using QSB.Audio;
|
||||
using QSB.ClientServerStateSync;
|
||||
using QSB.HUD;
|
||||
using QSB.Messaging;
|
||||
using QSB.ModelShip;
|
||||
using QSB.Patches;
|
||||
using QSB.Player.Messages;
|
||||
using QSB.Player.TransformSync;
|
||||
using QSB.QuantumSync.WorldObjects;
|
||||
@ -179,10 +181,18 @@ public partial class PlayerInfo
|
||||
HUDBox.OnRespawn();
|
||||
}
|
||||
|
||||
private Dictionary<string, object> _customData = new();
|
||||
// internal for RequestStateResyncMessage
|
||||
internal readonly Dictionary<string, object> _customData = new();
|
||||
|
||||
public void SetCustomData<T>(string key, T data)
|
||||
=> _customData[key] = data;
|
||||
{
|
||||
_customData[key] = data;
|
||||
|
||||
if (!QSBPatch.Remote)
|
||||
{
|
||||
new AddonCustomDataSyncMessage(PlayerId, key, data).Send();
|
||||
}
|
||||
}
|
||||
|
||||
public T GetCustomData<T>(string key)
|
||||
{
|
||||
|
@ -36,7 +36,9 @@ public class PlayerTransformSync : SectoredTransformSync
|
||||
var player = new PlayerInfo(this);
|
||||
QSBPlayerManager.PlayerList.SafeAdd(player);
|
||||
base.OnStartClient();
|
||||
QSBPatch.Remote = !isLocalPlayer;
|
||||
QSBPlayerManager.OnAddPlayer?.SafeInvoke(Player);
|
||||
QSBPatch.Remote = false;
|
||||
DebugLog.DebugWrite($"Create Player : {Player}", MessageType.Info);
|
||||
|
||||
JoinLeaveSingularity.Create(Player, true);
|
||||
@ -49,7 +51,7 @@ public class PlayerTransformSync : SectoredTransformSync
|
||||
JoinLeaveSingularity.Create(Player, false);
|
||||
|
||||
// TODO : Maybe move this to a leave event...? Would ensure everything could finish up before removing the player
|
||||
QSBPatch.Remote = true;
|
||||
QSBPatch.Remote = !isLocalPlayer;
|
||||
QSBPlayerManager.OnRemovePlayer?.SafeInvoke(Player);
|
||||
QSBPatch.Remote = false;
|
||||
base.OnStopClient();
|
||||
|
@ -301,9 +301,9 @@ public class QSBCore : ModBehaviour
|
||||
|
||||
foreach (var type in addonAssembly.GetTypes())
|
||||
{
|
||||
if (typeof(QSBMessage).IsAssignableFrom(type) || typeof(WorldObjectManager).IsAssignableFrom(type) || typeof(IWorldObject).IsAssignableFrom(type))
|
||||
if (typeof(WorldObjectManager).IsAssignableFrom(type) || typeof(IWorldObject).IsAssignableFrom(type))
|
||||
{
|
||||
DebugLog.ToConsole($"Addon \"{uniqueName}\" cannot be cosmetic, as it creates networking events or objects.", MessageType.Error);
|
||||
DebugLog.ToConsole($"Addon \"{uniqueName}\" cannot be cosmetic, as it creates networking objects.", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ using QSB.WorldSync;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using QSB.API;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB;
|
||||
|
@ -21,26 +21,24 @@ public static class DebugLog
|
||||
message = $"[{ProcessInstanceId}] " + message;
|
||||
}
|
||||
|
||||
var @this = QSBCore.Helper != null ? QSBCore.Helper.Console : ModConsole.OwmlConsole;
|
||||
var Logger = @this.GetValue<IModLogger>("Logger");
|
||||
var _socket = @this.GetValue<IModSocket>("_socket");
|
||||
// copied from https://github.com/ow-mods/owml/blob/master/src/OWML.Logging/ModSocketOutput.cs#L33
|
||||
Logger?.Log($"{type}: {message}");
|
||||
|
||||
_socket.WriteToSocket(new ModSocketMessage
|
||||
{
|
||||
var Logger = ModConsole.OwmlConsole.GetValue<IModLogger>("Logger");
|
||||
var _socket = ModConsole.OwmlConsole.GetValue<IModSocket>("_socket");
|
||||
SenderName = "QSB",
|
||||
SenderType = GetCallingType(),
|
||||
Type = type,
|
||||
Message = message
|
||||
});
|
||||
|
||||
Logger?.Log($"{type}: {message}");
|
||||
|
||||
_socket.WriteToSocket(new ModSocketMessage
|
||||
{
|
||||
SenderName = "QSB",
|
||||
SenderType = GetCallingType(),
|
||||
Type = type,
|
||||
Message = message
|
||||
});
|
||||
|
||||
if (type == MessageType.Fatal)
|
||||
{
|
||||
_socket.Close();
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
if (type == MessageType.Fatal)
|
||||
{
|
||||
_socket.Close();
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,10 @@ using OWML.Common;
|
||||
using QSB.Player;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
@ -237,5 +239,28 @@ public static class Extensions
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// only works for c# serializable objects
|
||||
/// </summary>
|
||||
public static byte[] ToBytes(this object obj)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
var bf = new BinaryFormatter();
|
||||
bf.Serialize(ms, obj);
|
||||
var bytes = ms.ToArray();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// only works for c# serializable objects
|
||||
/// </summary>
|
||||
public static object ToObject(this byte[] bytes)
|
||||
{
|
||||
using var ms = new MemoryStream(bytes);
|
||||
var bf = new BinaryFormatter();
|
||||
var obj = bf.Deserialize(ms);
|
||||
return obj;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
"body": "- Disable *all* other mods. (Can heavily affect performance)\n- Make sure you are not running any other network-intensive applications."
|
||||
},
|
||||
"uniqueName": "Raicuparta.QuantumSpaceBuddies",
|
||||
"version": "0.30.1",
|
||||
"version": "0.30.2",
|
||||
"owmlVersion": "2.9.5",
|
||||
"dependencies": [ "_nebula.MenuFramework", "JohnCorby.VanillaFix" ],
|
||||
"pathsToPreserve": [ "debugsettings.json" ],
|
||||
|
Loading…
x
Reference in New Issue
Block a user