Skip to content

Commit

Permalink
Merge pull request #637 from misternebula/dev
Browse files Browse the repository at this point in the history
0.30.0
  • Loading branch information
misternebula authored Jul 31, 2023
2 parents 10c9121 + b2962e1 commit aa6b670
Show file tree
Hide file tree
Showing 351 changed files with 764 additions and 369 deletions.
61 changes: 61 additions & 0 deletions APITestMod/APITestMod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using OWML.Common;
using OWML.ModHelper;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace APITestMod;

public class APITestMod : ModBehaviour
{
public void Start()
{
var qsbAPI = ModHelper.Interaction.TryGetModApi<IQSBAPI>("Raicuparta.QuantumSpaceBuddies");
var menuFrameworkAPI = ModHelper.Interaction.TryGetModApi<IMenuAPI>("_nebula.MenuFramework");

LoadManager.OnCompleteSceneLoad += (oldScene, newScene) =>
{
if (newScene != OWScene.SolarSystem)
{
return;
}

var button = menuFrameworkAPI.PauseMenu_MakeSimpleButton("QSB Api Test");

qsbAPI.OnPlayerJoin().AddListener((uint playerId) => ModHelper.Console.WriteLine($"{playerId} joined the game!", MessageType.Success));
qsbAPI.OnPlayerLeave().AddListener((uint playerId) => ModHelper.Console.WriteLine($"{playerId} left the game!", MessageType.Success));

button.onClick.AddListener(() =>
{
ModHelper.Console.WriteLine("TESTING QSB API!");

ModHelper.Console.WriteLine($"Local Player ID : {qsbAPI.GetLocalPlayerID()}");

ModHelper.Console.WriteLine("Player IDs :");

foreach (var playerID in qsbAPI.GetPlayerIDs())
{
ModHelper.Console.WriteLine($" - id:{playerID} name:{qsbAPI.GetPlayerName(playerID)}");
}

ModHelper.Console.WriteLine("Setting custom data as \"QSB TEST STRING\"");
qsbAPI.SetCustomData(qsbAPI.GetLocalPlayerID(), "APITEST.TESTSTRING", "QSB TEST STRING");
ModHelper.Console.WriteLine($"Retreiving custom data : {qsbAPI.GetCustomData<string>(qsbAPI.GetLocalPlayerID(), "APITEST.TESTSTRING")}");

ModHelper.Console.WriteLine("Sending string message test...");
qsbAPI.RegisterHandler<string>("apitest-string", MessageHandler);
qsbAPI.SendMessage("apitest-string", "STRING MESSAGE", true);

ModHelper.Console.WriteLine("Sending int message test...");
qsbAPI.RegisterHandler<int>("apitest-int", MessageHandler);
qsbAPI.SendMessage("apitest-int", 123, true);

ModHelper.Console.WriteLine("Sending float message test...");
qsbAPI.RegisterHandler<float>("apitest-float", MessageHandler);
qsbAPI.SendMessage("apitest-float", 3.14f, true);
});
};
}

private void MessageHandler<T>(uint from, T data)
=> ModHelper.Console.WriteLine($"Got : {data}");
}
22 changes: 22 additions & 0 deletions APITestMod/APITestMod.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<RootNamespace>APITestMod</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputPath Condition="Exists('$(OwmlDir)')">$(OwmlDir)\Mods\_nebula.QSBAPITest</OutputPath>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="OuterWildsGameLibs" Version="1.1.13.457" IncludeAssets="compile" />
<PackageReference Include="OWML" Version="2.9.5" IncludeAssets="compile" />
</ItemGroup>

<ItemGroup>
<None Update="manifest.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
23 changes: 23 additions & 0 deletions APITestMod/IMenuAPI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using UnityEngine;
using UnityEngine.UI;

namespace APITestMod;

public interface IMenuAPI
{
// Title screen
GameObject TitleScreen_MakeMenuOpenButton(string name, int index, Menu menuToOpen);
GameObject TitleScreen_MakeSceneLoadButton(string name, int index, SubmitActionLoadScene.LoadableScenes sceneToLoad, PopupMenu confirmPopup = null);
Button TitleScreen_MakeSimpleButton(string name, int index);
// Pause menu
GameObject PauseMenu_MakeMenuOpenButton(string name, Menu menuToOpen, Menu customMenu = null);
GameObject PauseMenu_MakeSceneLoadButton(string name, SubmitActionLoadScene.LoadableScenes sceneToLoad, PopupMenu confirmPopup = null, Menu customMenu = null);
Button PauseMenu_MakeSimpleButton(string name, Menu customMenu = null);
Menu PauseMenu_MakePauseListMenu(string title);
// Misc
PopupMenu MakeTwoChoicePopup(string message, string confirmText, string cancelText);
PopupInputMenu MakeInputFieldPopup(string message, string placeholderMessage, string confirmText, string cancelText);
PopupMenu MakeInfoPopup(string message, string continueButtonText);
// Startup Popups
void RegisterStartupPopup(string message);
}
71 changes: 71 additions & 0 deletions APITestMod/IQSBAPI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using OWML.Common;
using UnityEngine.Events;

public interface IQSBAPI
{
/// <summary>
/// If called, all players connected to YOUR hosted game must have this mod installed.
/// </summary>
void RegisterRequiredForAllPlayers(IModBehaviour mod);

/// <summary>
/// Returns the player ID of the current player.
/// </summary>
uint GetLocalPlayerID();

/// <summary>
/// Returns the name of a given player.
/// </summary>
/// <param name="playerID">The ID of the player you want the name of.</param>
string GetPlayerName(uint playerID);

/// <summary>
/// Returns the list of IDs of all connected players.
/// </summary>
uint[] GetPlayerIDs();

/// <summary>
/// Invoked when a player joins the game.
/// </summary>
UnityEvent<uint> OnPlayerJoin();

/// <summary>
/// Invoked when a player leaves the game.
/// </summary>
UnityEvent<uint> OnPlayerLeave();

/// <summary>
/// Sets some arbitrary data for a given player.
/// </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 to access this data by.</param>
/// <param name="data">The data to set.</param>
void SetCustomData<T>(uint playerId, string key, T data);

/// <summary>
/// Returns some arbitrary data from a given player.
/// </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);

/// <summary>
/// Sends a message containing arbitrary data to every player.
/// </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>
/// <param name="data">The data to send.</param>
/// <param name="receiveLocally">If true, the action given to <see cref="RegisterHandler{T}"/> will also be called on the same client that is sending the message.</param>
void SendMessage<T>(string messageType, T data, bool receiveLocally = false);

/// <summary>
/// Registers an action to be called when a message is received.
/// </summary>
/// <typeparam name="T">The type of the data in the message.</typeparam>
/// <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);
}
9 changes: 9 additions & 0 deletions APITestMod/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"filename": "APITestMod.dll",
"author": "_nebula",
"name": "QSB API Test Mod",
"uniqueName": "_nebula.QSBAPITest",
"version": "1.0.0",
"owmlVersion": "2.9.5",
"dependencies": [ "Raicuparta.QuantumSpaceBuddies", "_nebula.MenuFramework" ]
}
2 changes: 1 addition & 1 deletion EpicRerouter/EpicRerouter.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="OuterWildsGameLibs" Version="1.1.13.457" IncludeAssets="compile" />
<PackageReference Include="OWML" Version="2.9.3" IncludeAssets="compile" />
<PackageReference Include="OWML" Version="2.9.5" IncludeAssets="compile" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion MirrorWeaver/MirrorWeaver.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OuterWildsGameLibs" Version="1.1.13.457" />
<PackageReference Include="OWML" Version="2.9.3" />
<PackageReference Include="OWML" Version="2.9.5" />
<Reference Include="../Mirror/*.dll" />
</ItemGroup>
<ItemGroup>
Expand Down
6 changes: 6 additions & 0 deletions QSB.sln
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EpicOnlineTransport", "Epic
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EpicRerouter", "EpicRerouter\EpicRerouter.csproj", "{639EFAEE-C4A1-4DA2-8457-D0472A9F6343}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "APITestMod", "APITestMod\APITestMod.csproj", "{0A10143E-6C00-409B-B3A5-C54C1B01599D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -42,6 +44,10 @@ Global
{639EFAEE-C4A1-4DA2-8457-D0472A9F6343}.Debug|Any CPU.Build.0 = Debug|Any CPU
{639EFAEE-C4A1-4DA2-8457-D0472A9F6343}.Release|Any CPU.ActiveCfg = Release|Any CPU
{639EFAEE-C4A1-4DA2-8457-D0472A9F6343}.Release|Any CPU.Build.0 = Release|Any CPU
{0A10143E-6C00-409B-B3A5-C54C1B01599D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A10143E-6C00-409B-B3A5-C54C1B01599D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A10143E-6C00-409B-B3A5-C54C1B01599D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A10143E-6C00-409B-B3A5-C54C1B01599D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
27 changes: 27 additions & 0 deletions QSB/API/AddonDataManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using QSB.Utility;

namespace QSB.API;

public static class AddonDataManager
{
private static readonly Dictionary<string, Action<uint, object>> _handlers = new();

public static void OnReceiveDataMessage(string messageType, object data, uint from)
{
DebugLog.DebugWrite($"Received data message of message type \"{messageType}\" from {from}!");
if (!_handlers.TryGetValue(messageType, out var handler))
{
return;
}

handler(from, data);
}

public static void RegisterHandler<T>(string messageType, 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));
}
}
72 changes: 72 additions & 0 deletions QSB/API/IQSBAPI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using OWML.Common;
using UnityEngine.Events;

public interface IQSBAPI
{
/// <summary>
/// If called, all players connected to YOUR hosted game must have this mod installed.
/// </summary>
void RegisterRequiredForAllPlayers(IModBehaviour mod);

/// <summary>
/// Returns the player ID of the current player.
/// </summary>
uint GetLocalPlayerID();

/// <summary>
/// Returns the name of a given player.
/// </summary>
/// <param name="playerID">The ID of the player you want the name of.</param>
string GetPlayerName(uint playerID);

/// <summary>
/// Returns the list of IDs of all connected players.
/// </summary>
uint[] GetPlayerIDs();

/// <summary>
/// Invoked when a player joins the game.
/// </summary>
UnityEvent<uint> OnPlayerJoin();

/// <summary>
/// Invoked when a player leaves the game.
/// </summary>
UnityEvent<uint> OnPlayerLeave();

/// <summary>
/// Sets some arbitrary data for a given player.
/// </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 to access this data by.</param>
/// <param name="data">The data to set.</param>
void SetCustomData<T>(uint playerId, string key, T data);

/// <summary>
/// Returns some arbitrary data from a given player.
/// </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);

/// <summary>
/// Sends a message containing arbitrary data to every player.
/// </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>
/// <param name="data">The data to send.</param>
/// <param name="receiveLocally">If true, the action given to <see cref="RegisterHandler{T}"/> will also be called on the same client that is sending the message.</param>
void SendMessage<T>(string messageType, T data, bool receiveLocally = false);

/// <summary>
/// Registers an action to be called when a message is received.
/// </summary>
/// <typeparam name="T">The type of the data in the message.</typeparam>
/// <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);
}
41 changes: 41 additions & 0 deletions QSB/API/Messages/AddonDataMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using QSB.Messaging;

namespace QSB.API.Messages;

public class AddonDataMessage : QSBMessage<(string messageType, 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 override void OnReceiveLocal()
{
if (Data.receiveLocally)
{
OnReceiveRemote();
}
}

public override void OnReceiveRemote()
{
var obj = Bytes2Obj(Data.data);
AddonDataManager.OnReceiveDataMessage(Data.messageType, obj, From);
}
}
Loading

0 comments on commit aa6b670

Please sign in to comment.