Skip to content

Commit

Permalink
Merge branch 'dev' into spectate-new
Browse files Browse the repository at this point in the history
  • Loading branch information
misternebula committed Sep 29, 2023
2 parents cb46bdb + ef8afd0 commit 105061c
Show file tree
Hide file tree
Showing 464 changed files with 4,175 additions and 2,918 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
name: Build

on: push
on:
push:
paths-ignore:
- "*.md"
- "LICENSE"
- ".gitignore"

jobs:
build:
Expand Down
91 changes: 91 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Create Release

on:
workflow_dispatch:
inputs:
prerelease:
description: Prerelease
type: boolean
bypassCheck:
description: Bypass Version Check
type: boolean

permissions:
contents: write

env:
PROJ_USERNAME: Raicuparta
PROJ_NAME: QuantumSpaceBuddies
REAL_PROJ_NAME: QSB

jobs:
pre_job:
name: Check For Other Releases
outputs:
version: ${{ steps.out.outputs.version }}
exists: ${{ steps.out.outputs.exists }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: "actions/checkout@v3"

- name: Fetch
run: git fetch

- name: Read Manifest
id: read-manifest
run: echo "manifest=$(< ./${{ env.REAL_PROJ_NAME }}/manifest.json sed ':a;N;$!ba;s/\n/ /g')" >> $GITHUB_OUTPUT

- name: Check For Release
id: check-tag
run: echo "exists=$(git ls-remote --exit-code --tags origin ${{ env.TAG }} >/dev/null 2>&1 && echo true || echo false)" >> $GITHUB_OUTPUT
env:
TAG: "v${{fromJson(steps.read-manifest.outputs.manifest).version}}"

- name: Output Version Info
id: out
run: |
echo "version=${{fromJson(steps.read-manifest.outputs.manifest).version}}" >> $GITHUB_OUTPUT
echo "exists=${{steps.check-tag.outputs.exists}}" >> $GITHUB_OUTPUT
- name: Error
if: ${{ steps.out.outputs.exists != 'false' && (!inputs.bypassCheck) }}
run: echo "::error file=manifest.json,title=Refusing to Release::Your mod was not released because there is already a release with the version in manifest.json"
release:
needs: pre_job
if: ${{ (needs.pre_job.outputs.version != '0.0.0') && (needs.pre_job.outputs.exists == 'false') || (inputs.bypassCheck) }}
name: Create Release
runs-on: windows-latest
steps:
- name: Checkout
uses: "actions/checkout@v3"

- name: Setup .NET
uses: "actions/setup-dotnet@v3"

- name: Remove .csproj.user
run: if (Test-Path ${{ env.REAL_PROJ_NAME }}/${{ env.REAL_PROJ_NAME }}.csproj.user) { rm ${{ env.REAL_PROJ_NAME }}/${{ env.REAL_PROJ_NAME }}.csproj.user }

- name: Build Mod
run: dotnet build -c Release

- name: Upload Artifact
uses: "actions/upload-artifact@v3"
with:
name: "${{ env.PROJ_USERNAME }}.${{ env.PROJ_NAME }}"
path: "${{ env.REAL_PROJ_NAME }}/bin/Release"

- name: Zip For Release
run: 7z a ${{ env.PROJ_USERNAME }}.${{ env.PROJ_NAME }}.zip ./${{ env.REAL_PROJ_NAME }}/bin/Release/**

- name: Create Release
uses: "ncipollo/release-action@v1"
with:
allowUpdates: true
commit: ${{ github.ref_name }}
tag: v${{ needs.pre_job.outputs.version }}
name: Version ${{ needs.pre_job.outputs.version }}
omitBodyDuringUpdate: true
artifacts: "${{ env.PROJ_USERNAME}}.${{ env.PROJ_NAME }}.zip"
draft: true
prerelease: ${{ inputs.prerelease }}
66 changes: 66 additions & 0 deletions APITestMod/APITestMod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
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));
qsbAPI.OnChatMessage().AddListener((string message, uint from) => ModHelper.Console.WriteLine($"Chat message \"{message}\" from {from} ({(from == uint.MaxValue ? "QSB" : qsbAPI.GetPlayerName(from))})"));

qsbAPI.RegisterHandler<string>("apitest-string", MessageHandler);
qsbAPI.RegisterHandler<int>("apitest-int", MessageHandler);
qsbAPI.RegisterHandler<float>("apitest-float", MessageHandler);

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.SendMessage("apitest-string", "STRING MESSAGE", receiveLocally: true);

ModHelper.Console.WriteLine("Sending int message test...");
qsbAPI.SendMessage("apitest-int", 123, receiveLocally: true);

ModHelper.Console.WriteLine("Sending float message test...");
qsbAPI.SendMessage("apitest-float", 3.14f, receiveLocally: true);

qsbAPI.SendChatMessage("Non-system chat message", false, Color.white);
qsbAPI.SendChatMessage("System chat message", true, Color.cyan);
});
};
}

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

Check warning on line 10 in APITestMod/IMenuAPI.cs

View workflow job for this annotation

GitHub Actions / build

Cannot convert null literal to non-nullable reference type.
Button TitleScreen_MakeSimpleButton(string name, int index);
// Pause menu
GameObject PauseMenu_MakeMenuOpenButton(string name, Menu menuToOpen, Menu customMenu = null);

Check warning on line 13 in APITestMod/IMenuAPI.cs

View workflow job for this annotation

GitHub Actions / build

Cannot convert null literal to non-nullable reference type.
GameObject PauseMenu_MakeSceneLoadButton(string name, SubmitActionLoadScene.LoadableScenes sceneToLoad, PopupMenu confirmPopup = null, Menu customMenu = null);

Check warning on line 14 in APITestMod/IMenuAPI.cs

View workflow job for this annotation

GitHub Actions / build

Cannot convert null literal to non-nullable reference type.

Check warning on line 14 in APITestMod/IMenuAPI.cs

View workflow job for this annotation

GitHub Actions / build

Cannot convert null literal to non-nullable reference type.
Button PauseMenu_MakeSimpleButton(string name, Menu customMenu = null);

Check warning on line 15 in APITestMod/IMenuAPI.cs

View workflow job for this annotation

GitHub Actions / build

Cannot convert null literal to non-nullable reference type.
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);
}
119 changes: 119 additions & 0 deletions APITestMod/IQSBAPI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using System;
using OWML.Common;
using UnityEngine;
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>
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.
///
/// The first player in the list is the host.
/// </summary>
uint[] GetPlayerIDs();

/// <summary>
/// Invoked when any player (local or remote) joins the game.
/// </summary>
UnityEvent<uint> OnPlayerJoin();

/// <summary>
/// Invoked when any player (local or remote) 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. If not serializable, data will not be synced.</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);

#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>
/// <param name="data">The data to send.</param>
/// <param name="to">The player to send this message to. (0 is the host, uint.MaxValue means every player)</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, uint to = uint.MaxValue, 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);

#endregion

#region Chat

/// <summary>
/// Invoked when a chat message is received.
/// The string is the message body.
/// The uint is the player who sent the message. If it's a system message, this is uint.MaxValue.
/// </summary>
UnityEvent<string, uint> OnChatMessage();

/// <summary>
/// Sends a message in chat.
/// </summary>
/// <param name="message">The text of the message.</param>
/// <param name="systemMessage">If false, the message is sent as if the local player wrote it manually. If true, the message has no player attached to it, like the player join messages.</param>
/// <param name="color">The color of the message.</param>
void SendChatMessage(string message, bool systemMessage, Color color);

#endregion
}
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.7",
"dependencies": [ "Raicuparta.QuantumSpaceBuddies", "_nebula.MenuFramework" ]
}
Loading

0 comments on commit 105061c

Please sign in to comment.