diff --git a/.github/scripts/thunderstore_bundle.js b/.github/scripts/thunderstore_bundle.js
index 962981e2d..14e4a7334 100644
--- a/.github/scripts/thunderstore_bundle.js
+++ b/.github/scripts/thunderstore_bundle.js
@@ -11,33 +11,39 @@ import {
statSync,
} from "fs";
import { join } from "path";
-import fgrpkg from "@terascope/fetch-github-release";
-const downloadRelease = fgrpkg;
-import json2toml from "json2toml";
import child_process from "child_process";
import { zip } from "zip-a-folder";
-import fsepkg from "fs-extra";
-const move = fsepkg.move;
+import fsepkg, { copy } from "fs-extra";
const remove = fsepkg.remove;
import * as core from "@actions/core";
// Setting it so that it's consistent with installs from thunderstore
const NEBULA_RELEASE_FOLDER_NAME = "nebula-NebulaMultiplayerMod";
+const NEBULA_API_RELEASE_FOLDER_NAME = "nebula-NebulaMultiplayerModApi";
const DIST_FOLDER = "dist";
const DIST_RELEASE_FOLDER = join(DIST_FOLDER, "release");
-const DIST_NEBULA_FOLDER = join(DIST_RELEASE_FOLDER, "nebula");
-const DIST_TSTORE_CLI_FOLDER = join(DIST_RELEASE_FOLDER, "tstore-cli");
-const DIST_TSTORE_CLI_EXE_PATH = join(DIST_TSTORE_CLI_FOLDER, "tstore-cli.exe");
-const DIST_TSTORE_CLI_CONFIG_PATH = join(
- DIST_TSTORE_CLI_FOLDER,
- "publish.toml"
+const DIST_NEBULA_FOLDER = join(
+ DIST_RELEASE_FOLDER,
+ NEBULA_RELEASE_FOLDER_NAME
+);
+const DIST_NEBULA_API_FOLDER = join(
+ DIST_RELEASE_FOLDER,
+ NEBULA_API_RELEASE_FOLDER_NAME
);
+const DIST_TSTORE_CLI_FOLDER = join("Libs", "tcli");
+const DIST_TSTORE_CLI_EXE_PATH = join(DIST_TSTORE_CLI_FOLDER, "tcli.exe");
const PLUGIN_INFO_PATH = "NebulaPatcher\\PluginInfo.cs";
+const API_PLUGIN_INFO_PATH = "NebulaAPI\\NebulaModAPI.cs";
const pluginInfo = getPluginInfo();
+const apiPluginInfo = getApiPluginInfo();
const TSTORE_ARCHIVE_PATH = join(
DIST_RELEASE_FOLDER,
"nebula-thunderstore.zip"
);
+const TSTORE_API_ARCHIVE_PATH = join(
+ DIST_RELEASE_FOLDER,
+ "nebula-api-thunderstore.zip"
+);
const GH_ARCHIVE_PATH = join(
DIST_RELEASE_FOLDER,
"Nebula_" + pluginInfo.version + ".zip"
@@ -48,29 +54,40 @@ const CHANGELOG_PATH = "CHANGELOG.md";
async function main() {
if (!existsSync(DIST_NEBULA_FOLDER)) {
- throw DIST_NEBULA_FOLDER + " does not exist";
+ let err = DIST_NEBULA_FOLDER + " does not exist";
+ core.setFailed(err);
+ throw err;
}
- if (!existsSync(DIST_TSTORE_CLI_FOLDER)) {
- mkdirSync(DIST_TSTORE_CLI_FOLDER, { recursive: true });
+ if (!existsSync(DIST_NEBULA_API_FOLDER)) {
+ let err = DIST_NEBUDIST_NEBULA_API_FOLDERLA_FOLDER + " does not exist";
+ core.setFailed(err);
+ throw err;
}
try {
generateReleaseBody();
} catch (err) {
core.setFailed(err);
+ throw err;
}
generateManifest();
+ generateApiManifest();
copyIcon();
+ copyApiIcon();
copyReadme();
+ copyApiReadme();
appendChangelog();
+ appendApiChangelog();
copyLicenses();
+ copyApiLicense();
await createTStoreArchive();
+ await createTStoreApiArchive();
await createGHArchive();
- await doTStoreRelease();
+ uploadToTStore();
}
function getPluginInfo() {
@@ -83,13 +100,29 @@ function getPluginInfo() {
};
}
+function getApiPluginInfo() {
+ const pluginInfoRaw = readFileSync(API_PLUGIN_INFO_PATH).toString("utf-8");
+ const versionInfoRaw = readFileSync(
+ join("NebulaAPI", "version.json")
+ ).toString("utf-8");
+ return {
+ name: pluginInfoRaw.match(/API_NAME = "(.*)";/)[1],
+ id: pluginInfoRaw.match(/API_GUID = "(.*)";/)[1],
+ version: JSON.parse(versionInfoRaw).version,
+ };
+}
+
function generateManifest() {
const manifest = {
name: pluginInfo.name,
description:
"With this mod you will be able to play with your friends in the same game!",
version_number: pluginInfo.version,
- dependencies: ["xiaoye97-BepInEx-5.4.11", "PhantomGamers-IlLine-1.0.0"],
+ dependencies: [
+ "xiaoye97-BepInEx-5.4.11",
+ `nebula-${apiPluginInfo.name}-${apiPluginInfo.version}`,
+ "PhantomGamers-IlLine-1.0.0",
+ ],
website_url: "https://github.com/hubastard/nebula",
};
writeFileSync(
@@ -98,14 +131,41 @@ function generateManifest() {
);
}
+function generateApiManifest() {
+ const manifest = {
+ name: apiPluginInfo.name,
+ description: "API for other mods to work with the Nebula Multiplayer Mod",
+ version_number: apiPluginInfo.version,
+ website_url: "https://github.com/hubastard/nebula",
+ };
+ writeFileSync(
+ join(DIST_NEBULA_API_FOLDER, "manifest.json"),
+ JSON.stringify(manifest, null, 2)
+ );
+}
+
function copyIcon() {
copyFileSync(MOD_ICON_PATH, join(DIST_NEBULA_FOLDER, "icon.png"));
}
+function copyApiIcon() {
+ copyFileSync(
+ join("NebulaAPI", "icon.png"),
+ join(DIST_NEBULA_API_FOLDER, "icon.png")
+ );
+}
+
function copyReadme() {
copyFileSync(README_PATH, join(DIST_NEBULA_FOLDER, README_PATH));
}
+function copyApiReadme() {
+ copyFileSync(
+ join("NebulaAPI", README_PATH),
+ join(DIST_NEBULA_API_FOLDER, README_PATH)
+ );
+}
+
function appendChangelog() {
appendFileSync(
join(DIST_NEBULA_FOLDER, README_PATH),
@@ -113,11 +173,22 @@ function appendChangelog() {
);
}
+function appendApiChangelog() {
+ appendFileSync(
+ join(DIST_NEBULA_API_FOLDER, README_PATH),
+ "\n" + readFileSync(join("NebulaAPI", CHANGELOG_PATH))
+ );
+}
+
function copyLicenses() {
copyFileSync("LICENSE", join(DIST_NEBULA_FOLDER, "nebula.LICENSE"));
copyFolderContent("Licenses", DIST_NEBULA_FOLDER);
}
+function copyApiLicense() {
+ copyFileSync("LICENSE", join(DIST_NEBULA_API_FOLDER, "nebula.LICENSE"));
+}
+
function copyFolderContent(src, dst, excludedExts) {
readdirSync(src).forEach((file) => {
const srcPath = join(src, file);
@@ -138,54 +209,6 @@ function copyFolderContent(src, dst, excludedExts) {
});
}
-async function doTStoreRelease() {
- const user = "Windows10CE";
- const repo = "tstore-cli";
- const outputdir = DIST_TSTORE_CLI_FOLDER;
- const leaveZipped = false;
- const disableLogging = false;
-
- // Define a function to filter releases.
- function filterRelease(release) {
- // Filter out prereleases.
- return release.prerelease === false;
- }
-
- // Define a function to filter assets.
- function filterAsset(asset) {
- // Select assets that contain the string 'windows'.
- return asset.name.includes("tstore-cli.exe");
- }
-
- try {
- await downloadRelease(
- user,
- repo,
- outputdir,
- filterRelease,
- filterAsset,
- leaveZipped,
- disableLogging
- );
- console.log("Successfully downloaded tstore-cli.exe");
- await new Promise((r) => setTimeout(r, 2000));
- generateTStoreConfig();
- uploadToTStore();
- } catch (err) {
- console.error(err.message);
- }
-}
-
-function generateTStoreConfig() {
- const config = {
- author: "nebula",
- communities: ["dyson-sphere-program"],
- nsfw: false,
- zip: TSTORE_ARCHIVE_PATH,
- };
- writeFileSync(DIST_TSTORE_CLI_CONFIG_PATH, json2toml(config));
-}
-
function generateReleaseBody() {
const changelog = readFileSync(CHANGELOG_PATH, "utf-8");
const versionRegExp = new RegExp(
@@ -215,37 +238,46 @@ function generateReleaseBody() {
join(DIST_RELEASE_FOLDER, "BODY.md"),
"# Alpha Version " + currentVersion + "\n\n### Changes\n" + body
);
-
- console.log(body);
}
async function createTStoreArchive() {
await zip(DIST_NEBULA_FOLDER, TSTORE_ARCHIVE_PATH);
}
+async function createTStoreApiArchive() {
+ await zip(DIST_NEBULA_API_FOLDER, TSTORE_API_ARCHIVE_PATH);
+}
+
async function createGHArchive() {
// Ensure contents are within subfolder in zip
- await move(
+ await copy(
DIST_NEBULA_FOLDER,
join(DIST_FOLDER, "tmp", NEBULA_RELEASE_FOLDER_NAME)
);
- await zip(join(DIST_FOLDER, "tmp"), GH_ARCHIVE_PATH);
- await move(
- join(DIST_FOLDER, "tmp", NEBULA_RELEASE_FOLDER_NAME),
- DIST_NEBULA_FOLDER
+ await copy(
+ DIST_NEBULA_API_FOLDER,
+ join(DIST_FOLDER, "tmp", NEBULA_API_RELEASE_FOLDER_NAME)
);
+ await zip(join(DIST_FOLDER, "tmp"), GH_ARCHIVE_PATH);
await remove(join(DIST_FOLDER, "tmp"));
}
function uploadToTStore() {
- child_process.execSync(
- DIST_TSTORE_CLI_EXE_PATH +
- " publish --config " +
- DIST_TSTORE_CLI_CONFIG_PATH,
- function (err) {
- console.error(err);
- }
- );
+ try {
+ child_process.execSync(
+ `"${DIST_TSTORE_CLI_EXE_PATH}" publish --file "${TSTORE_ARCHIVE_PATH}" --token "${process.env.TSTORE_TOKEN}" --use-session-auth`
+ );
+ } catch (error) {
+ console.error(`Thunderstore upload failed for ${TSTORE_ARCHIVE_PATH}`);
+ }
+
+ try {
+ child_process.execSync(
+ `"${DIST_TSTORE_CLI_EXE_PATH}" publish --file "${TSTORE_API_ARCHIVE_PATH}" --token "${process.env.TSTORE_TOKEN}" --use-session-auth`
+ );
+ } catch (error) {
+ console.error(`Thunderstore upload failed for ${TSTORE_API_ARCHIVE_PATH}`);
+ }
}
main();
diff --git a/.github/workflows/build-winx64.yml b/.github/workflows/build-winx64.yml
index a549645f4..2806b4264 100644
--- a/.github/workflows/build-winx64.yml
+++ b/.github/workflows/build-winx64.yml
@@ -29,7 +29,7 @@ jobs:
- name: Clear output directory in DSP files
# We use SilentlyContinue here because it errors out if the folder does not exist otherwise
- run: rm -R -ErrorAction SilentlyContinue "dist\release\nebula"
+ run: rm -R -ErrorAction SilentlyContinue "dist"
- name: Add remote build identifier
run: New-Item -Name .remoteBuild -ItemType File -force
@@ -50,4 +50,4 @@ jobs:
with:
# Artifact name
name: build-artifacts-${{ matrix.configuration }}
- path: dist\release\nebula
+ path: dist\release
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
index 4a7960cf6..f7d9664bd 100644
--- a/.github/workflows/publish-release.yml
+++ b/.github/workflows/publish-release.yml
@@ -46,10 +46,10 @@ jobs:
- name: Clear output directory in DSP files
# We use SilentlyContinue here because it errors out if the folder does not exist otherwise
- run : rm -R -ErrorAction SilentlyContinue "${{ env.NEBULA_FOLDER }}"
+ run : rm -R -ErrorAction SilentlyContinue "dist"
- name: Add remote build identifier
- run: copy /b /Y NUL .remoteBuild
+ run: New-Item -Name .remoteBuild -ItemType File -force
# Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
- name: Setup MSBuild.exe
@@ -91,7 +91,13 @@ jobs:
- uses: actions/upload-artifact@v2.2.4
with:
name: nebula-thunderstore
- path: ${{ env.DIST_RELEASE_FOLDER }}nebula
+ path: ${{ env.DIST_RELEASE_FOLDER }}nebula-NebulaMultiplayerMod
+
+ # Upload the API thunderstore artifact (in case automatic upload fails)
+ - uses: actions/upload-artifact@v2.2.4
+ with:
+ name: nebula-api-thunderstore
+ path: ${{ env.DIST_RELEASE_FOLDER }}nebula-NebulaMultiplayerModApi
# Create release
- uses: hubastard/release-action@v1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4804171de..06eeb8775 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
## Changelog
+0.5.0:
+
+- Added API that enables other mods to sync over multiplayer! (Big thanks to @kremnev8!)
+- Fixed a bug that caused sorters to break when a client built a belt under preexisting sorters.
+- Fixed a bug that resulted in the client getting an error after disconnecting from a game that the host left.
+- Refactored session architecture (big changes to codebase but should be seamless to users)
+
0.4.0:
- Nebula now supports DSP version 0.8.20.7962+
@@ -20,4 +27,4 @@
0.2.0:
-- initial release on thunderstore
\ No newline at end of file
+- initial release on thunderstore
diff --git a/Directory.Build.props b/Directory.Build.props
index e37af8085..e15a63ce0 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -10,9 +10,9 @@
C:\Program Files (x86)\Steam\steamapps\common\Dyson Sphere Program\
$([MSBuild]::EnsureTrailingSlash('$(DSPGameDir)'))
- $(DSPGameDir)BepInEx\plugins\Nebula\
+ $(DSPGameDir)BepInEx\plugins\nebula-NebulaMultiplayerMod\
$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)'))
- $(PropSheetPath)dist\release\nebula
+ $(PropSheetPath)dist\release\nebula-NebulaMultiplayerMod\
@@ -21,7 +21,6 @@
true
$(PluginOutputDirectory)
- $(OutputPath)
net472
7.3
true
@@ -31,15 +30,21 @@
portable
true
+
+
+ $(OutputPath)..\nebula-NebulaMultiplayerModApi
+
-
-
+
+
+
+
diff --git a/Libs/tcli/CommandLine.dll b/Libs/tcli/CommandLine.dll
new file mode 100644
index 000000000..af18229e9
Binary files /dev/null and b/Libs/tcli/CommandLine.dll differ
diff --git a/Libs/tcli/Crayon.dll b/Libs/tcli/Crayon.dll
new file mode 100644
index 000000000..a2a3e4b04
Binary files /dev/null and b/Libs/tcli/Crayon.dll differ
diff --git a/Libs/tcli/Tommy.dll b/Libs/tcli/Tommy.dll
new file mode 100644
index 000000000..3e50217d8
Binary files /dev/null and b/Libs/tcli/Tommy.dll differ
diff --git a/Libs/tcli/tcli.deps.json b/Libs/tcli/tcli.deps.json
new file mode 100644
index 000000000..c678feb01
--- /dev/null
+++ b/Libs/tcli/tcli.deps.json
@@ -0,0 +1,74 @@
+{
+ "runtimeTarget": {
+ "name": ".NETCoreApp,Version=v5.0/win-x64",
+ "signature": ""
+ },
+ "compilationOptions": {},
+ "targets": {
+ ".NETCoreApp,Version=v5.0": {},
+ ".NETCoreApp,Version=v5.0/win-x64": {
+ "tcli/0.0.1": {
+ "dependencies": {
+ "CommandLineParser": "2.8.0",
+ "Crayon": "2.0.60",
+ "Tommy": "2.0.0"
+ },
+ "runtime": {
+ "tcli.dll": {}
+ }
+ },
+ "CommandLineParser/2.8.0": {
+ "runtime": {
+ "lib/netstandard2.0/CommandLine.dll": {
+ "assemblyVersion": "2.8.0.0",
+ "fileVersion": "2.8.0.0"
+ }
+ }
+ },
+ "Crayon/2.0.60": {
+ "runtime": {
+ "lib/netstandard2.0/Crayon.dll": {
+ "assemblyVersion": "2.0.60.0",
+ "fileVersion": "2.0.60.0"
+ }
+ }
+ },
+ "Tommy/2.0.0": {
+ "runtime": {
+ "lib/netstandard2.0/Tommy.dll": {
+ "assemblyVersion": "2.0.0.0",
+ "fileVersion": "2.0.0.0"
+ }
+ }
+ }
+ }
+ },
+ "libraries": {
+ "tcli/0.0.1": {
+ "type": "project",
+ "serviceable": false,
+ "sha512": ""
+ },
+ "CommandLineParser/2.8.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-eco2HlKQBY4Joz9odHigzGpVzv6pjsXnY5lziioMveQxr+i2Z7xYcIOMeZTgYiqnMtMAbXMXsVhrNfWO5vJS8Q==",
+ "path": "commandlineparser/2.8.0",
+ "hashPath": "commandlineparser.2.8.0.nupkg.sha512"
+ },
+ "Crayon/2.0.60": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-pqARvOP7vsCdTa/nMB115Ci0eSbkhKDqBbWxsVgLUoJUejgFE9qJ+N5j44nmqHCRP2ohuGgFQnCD9Iodhm+DSA==",
+ "path": "crayon/2.0.60",
+ "hashPath": "crayon.2.0.60.nupkg.sha512"
+ },
+ "Tommy/2.0.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-5XBermvZiJPubbS6njoNRcq8+hy+iKQ21xArDznKoc/nvSLyF/va4PCwHHMLESf2SVFUbadP9zl0KqQzHHhVPg==",
+ "path": "tommy/2.0.0",
+ "hashPath": "tommy.2.0.0.nupkg.sha512"
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/tcli/tcli.dll b/Libs/tcli/tcli.dll
new file mode 100644
index 000000000..3c5b587aa
Binary files /dev/null and b/Libs/tcli/tcli.dll differ
diff --git a/Libs/tcli/tcli.exe b/Libs/tcli/tcli.exe
new file mode 100644
index 000000000..32adcf551
Binary files /dev/null and b/Libs/tcli/tcli.exe differ
diff --git a/Libs/tcli/tcli.runtimeconfig.json b/Libs/tcli/tcli.runtimeconfig.json
new file mode 100644
index 000000000..d54914baf
--- /dev/null
+++ b/Libs/tcli/tcli.runtimeconfig.json
@@ -0,0 +1,12 @@
+{
+ "runtimeOptions": {
+ "tfm": "net5.0",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "5.0.0"
+ },
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/Nebula.sln b/Nebula.sln
index 56bb35da9..afe0d2be1 100644
--- a/Nebula.sln
+++ b/Nebula.sln
@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "websocket-sharp", "dep\webs
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NebulaNetwork", "NebulaNetwork\NebulaNetwork.csproj", "{36A3D8AE-2A0A-4A1F-8A65-4FB61B01F779}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NebulaAPI", "NebulaAPI\NebulaAPI.csproj", "{B59DB3BB-DBA2-42AF-B4F1-32A9A6A273D2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -49,6 +51,10 @@ Global
{47B9362C-E91B-4AE4-979B-7D811AB4D1EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{47B9362C-E91B-4AE4-979B-7D811AB4D1EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{47B9362C-E91B-4AE4-979B-7D811AB4D1EA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B59DB3BB-DBA2-42AF-B4F1-32A9A6A273D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B59DB3BB-DBA2-42AF-B4F1-32A9A6A273D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B59DB3BB-DBA2-42AF-B4F1-32A9A6A273D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B59DB3BB-DBA2-42AF-B4F1-32A9A6A273D2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/NebulaAPI/CHANGELOG.md b/NebulaAPI/CHANGELOG.md
new file mode 100644
index 000000000..0a520df56
--- /dev/null
+++ b/NebulaAPI/CHANGELOG.md
@@ -0,0 +1,5 @@
+## Changelog
+
+1.0.0:
+
+- initial release on thunderstore
diff --git a/NebulaModel/DataStructures/CollectionExtensions.cs b/NebulaAPI/DataStructures/CollectionExtensions.cs
similarity index 95%
rename from NebulaModel/DataStructures/CollectionExtensions.cs
rename to NebulaAPI/DataStructures/CollectionExtensions.cs
index 96a664193..ca540eeeb 100644
--- a/NebulaModel/DataStructures/CollectionExtensions.cs
+++ b/NebulaAPI/DataStructures/CollectionExtensions.cs
@@ -2,7 +2,7 @@
using System.Collections;
using System.Threading;
-namespace NebulaModel.DataStructures
+namespace NebulaAPI
{
public static class CollectionExtensions
{
diff --git a/NebulaAPI/DataStructures/DataStructureExtenstions.cs b/NebulaAPI/DataStructures/DataStructureExtenstions.cs
new file mode 100644
index 000000000..9d8d5c7e1
--- /dev/null
+++ b/NebulaAPI/DataStructures/DataStructureExtenstions.cs
@@ -0,0 +1,32 @@
+using UnityEngine;
+
+namespace NebulaAPI
+{
+ public static class DataStructureExtenstions
+ {
+ public static Vector3 ToVector3(this Float3 value)
+ {
+ return new Vector3(value.x, value.y, value.z);
+ }
+
+ public static VectorLF3 ToVectorLF3(this Double3 value)
+ {
+ return new VectorLF3(value.x, value.y, value.z);
+ }
+
+ public static Float3 ToFloat3(this Vector3 value)
+ {
+ return new Float3(value.x, value.y, value.z);
+ }
+
+ public static Quaternion ToQuaternion(this Float4 value)
+ {
+ return new Quaternion(value.x, value.y, value.z, value.w);
+ }
+
+ public static Float4 ToFloat4(this Quaternion value)
+ {
+ return new Float4(value.x, value.y, value.z, value.w);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NebulaModel/DataStructures/Double3.cs b/NebulaAPI/DataStructures/Double3.cs
similarity index 74%
rename from NebulaModel/DataStructures/Double3.cs
rename to NebulaAPI/DataStructures/Double3.cs
index c720d22a2..7706ece86 100644
--- a/NebulaModel/DataStructures/Double3.cs
+++ b/NebulaAPI/DataStructures/Double3.cs
@@ -1,7 +1,5 @@
-using NebulaModel.Attributes;
-using NebulaModel.Networking.Serialization;
-
-namespace NebulaModel.DataStructures
+
+namespace NebulaAPI
{
[RegisterNestedType]
public struct Double3 : INetSerializable
@@ -17,14 +15,14 @@ public Double3(double x, double y, double z)
this.z = z;
}
- public void Serialize(NetDataWriter writer)
+ public void Serialize(INetDataWriter writer)
{
writer.Put(x);
writer.Put(y);
writer.Put(z);
}
- public void Deserialize(NetDataReader reader)
+ public void Deserialize(INetDataReader reader)
{
x = reader.GetDouble();
y = reader.GetDouble();
diff --git a/NebulaModel/DataStructures/Float3.cs b/NebulaAPI/DataStructures/Float3.cs
similarity index 78%
rename from NebulaModel/DataStructures/Float3.cs
rename to NebulaAPI/DataStructures/Float3.cs
index 7db2c58dc..6a3abb723 100644
--- a/NebulaModel/DataStructures/Float3.cs
+++ b/NebulaAPI/DataStructures/Float3.cs
@@ -1,8 +1,6 @@
-using NebulaModel.Attributes;
-using NebulaModel.Networking.Serialization;
-using UnityEngine;
+using UnityEngine;
-namespace NebulaModel.DataStructures
+namespace NebulaAPI
{
[RegisterNestedType]
public struct Float3 : INetSerializable
@@ -29,14 +27,14 @@ public Color ToColor()
return new Color(x, y, z);
}
- public void Serialize(NetDataWriter writer)
+ public void Serialize(INetDataWriter writer)
{
writer.Put(x);
writer.Put(y);
writer.Put(z);
}
- public void Deserialize(NetDataReader reader)
+ public void Deserialize(INetDataReader reader)
{
x = reader.GetFloat();
y = reader.GetFloat();
diff --git a/NebulaModel/DataStructures/Float4.cs b/NebulaAPI/DataStructures/Float4.cs
similarity index 79%
rename from NebulaModel/DataStructures/Float4.cs
rename to NebulaAPI/DataStructures/Float4.cs
index 5db7098ad..e99753e33 100644
--- a/NebulaModel/DataStructures/Float4.cs
+++ b/NebulaAPI/DataStructures/Float4.cs
@@ -1,8 +1,6 @@
-using NebulaModel.Attributes;
-using NebulaModel.Networking.Serialization;
-using UnityEngine;
+using UnityEngine;
-namespace NebulaModel.DataStructures
+namespace NebulaAPI
{
[RegisterNestedType]
public struct Float4 : INetSerializable
@@ -28,7 +26,7 @@ public Float4(Quaternion value)
w = value.w;
}
- public void Serialize(NetDataWriter writer)
+ public void Serialize(INetDataWriter writer)
{
writer.Put(x);
writer.Put(y);
@@ -36,7 +34,7 @@ public void Serialize(NetDataWriter writer)
writer.Put(w);
}
- public void Deserialize(NetDataReader reader)
+ public void Deserialize(INetDataReader reader)
{
x = reader.GetFloat();
y = reader.GetFloat();
diff --git a/NebulaAPI/DataStructures/IMechaData.cs b/NebulaAPI/DataStructures/IMechaData.cs
new file mode 100644
index 000000000..274267311
--- /dev/null
+++ b/NebulaAPI/DataStructures/IMechaData.cs
@@ -0,0 +1,15 @@
+// unset
+
+namespace NebulaAPI
+{
+ public interface IMechaData : INetSerializable
+ {
+ int SandCount { get; set; }
+ double CoreEnergy { get; set; }
+ double ReactorEnergy { get; set; }
+ StorageComponent Inventory { get; set; }
+ StorageComponent ReactorStorage { get; set; }
+ StorageComponent WarpStorage { get; set; }
+ MechaForge Forge { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/NebulaAPI/DataStructures/IPlayerTechBonuses.cs b/NebulaAPI/DataStructures/IPlayerTechBonuses.cs
new file mode 100644
index 000000000..e58fa887e
--- /dev/null
+++ b/NebulaAPI/DataStructures/IPlayerTechBonuses.cs
@@ -0,0 +1,34 @@
+// unset
+
+namespace NebulaAPI
+{
+ public interface IPlayerTechBonuses : INetSerializable
+ {
+ double coreEnergyCap { get; }
+ double corePowerGen { get; }
+ double reactorPowerGen { get; }
+ double walkPower { get; }
+ double jumpEnergy { get; }
+ double thrustPowerPerAcc { get; }
+ double warpKeepingPowerPerSpeed { get; }
+ double warpStartPowerPerSpeed { get; }
+ double miningPower { get; }
+ double replicatePower { get; }
+ double researchPower { get; }
+ double droneEjectEnergy { get; }
+ double droneEnergyPerMeter { get; }
+ int coreLevel { get; }
+ int thrusterLevel { get; }
+ float miningSpeed { get; }
+ float replicateSpeed { get; }
+ float walkSpeed { get; }
+ float jumpSpeed { get; }
+ float maxSailSpeed { get; }
+ float maxWarpSpeed { get; }
+ float buildArea { get; }
+ int droneCount { get; }
+ float droneSpeed { get; }
+ int droneMovement { get; }
+ int inventorySize { get; }
+ }
+}
\ No newline at end of file
diff --git a/NebulaAPI/GameState/IFactoryManager.cs b/NebulaAPI/GameState/IFactoryManager.cs
new file mode 100644
index 000000000..a977cf22b
--- /dev/null
+++ b/NebulaAPI/GameState/IFactoryManager.cs
@@ -0,0 +1,47 @@
+using System;
+using UnityEngine;
+
+namespace NebulaAPI
+{
+ ///
+ /// Represents data about factory
+ ///
+ public interface IFactoryManager : IDisposable
+ {
+ ///
+ /// Did we receive a packet?
+ ///
+ IToggle IsIncomingRequest { get; }
+
+ int PacketAuthor { get; set; }
+
+ int TargetPlanet { get; set; }
+
+ PlanetFactory EventFactory { get; set; }
+
+ ///
+ /// Request to load planet
+ ///
+ void AddPlanetTimer(int planetId);
+
+ void LoadPlanetData(int planetId);
+
+ void UnloadPlanetData(int planetId);
+
+ void InitializePrebuildRequests();
+
+ void SetPrebuildRequest(int planetId, int prebuildId, ushort playerId);
+
+ bool RemovePrebuildRequest(int planetId, int prebuildId);
+
+ bool ContainsPrebuildRequest(int planetId, int prebuildId);
+
+ int GetNextPrebuildId(int planetId);
+
+ int GetNextPrebuildId(PlanetFactory factory);
+
+ void OnNewSetInserterPickTarget(int objId, int otherObjId, int inserterId, int offset, Vector3 pointPos);
+
+ void OnNewSetInserterInsertTarget(int objId, int otherObjId, int inserterId, int offset, Vector3 pointPos);
+ }
+}
\ No newline at end of file
diff --git a/NebulaAPI/GameState/ILocalPlayer.cs b/NebulaAPI/GameState/ILocalPlayer.cs
new file mode 100644
index 000000000..008d98459
--- /dev/null
+++ b/NebulaAPI/GameState/ILocalPlayer.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace NebulaAPI
+{
+ ///
+ /// Represents local player. Allows to send packets.
+ ///
+ public interface ILocalPlayer : IDisposable
+ {
+ bool IsInitialDataReceived { get; }
+ bool IsHost { get; }
+ bool IsClient { get; }
+ bool IsNewPlayer { get; }
+ ushort Id { get; }
+ IPlayerData Data { get; }
+ }
+}
\ No newline at end of file
diff --git a/NebulaAPI/GameState/IMultiplayerSession.cs b/NebulaAPI/GameState/IMultiplayerSession.cs
new file mode 100644
index 000000000..b66a55784
--- /dev/null
+++ b/NebulaAPI/GameState/IMultiplayerSession.cs
@@ -0,0 +1,11 @@
+namespace NebulaAPI
+{
+ public interface IMultiplayerSession
+ {
+ INetworkProvider Network { get; }
+ ILocalPlayer LocalPlayer { get; }
+ IFactoryManager Factories { get; }
+
+ bool IsGameLoaded { get; }
+ }
+}
\ No newline at end of file
diff --git a/NebulaAPI/GameState/INebulaPlayer.cs b/NebulaAPI/GameState/INebulaPlayer.cs
new file mode 100644
index 000000000..78506f47d
--- /dev/null
+++ b/NebulaAPI/GameState/INebulaPlayer.cs
@@ -0,0 +1,13 @@
+namespace NebulaAPI
+{
+ public interface INebulaPlayer
+ {
+ INebulaConnection Connection { get; }
+ IPlayerData Data { get; }
+ ushort Id{ get; }
+ int CurrentResearchId { get; }
+ long TechProgressContributed { get; }
+ void SendPacket(T packet) where T : class, new();
+ void LoadUserData(IPlayerData data);
+ }
+}
\ No newline at end of file
diff --git a/NebulaAPI/GameState/INetworkProvider.cs b/NebulaAPI/GameState/INetworkProvider.cs
new file mode 100644
index 000000000..f9392e5aa
--- /dev/null
+++ b/NebulaAPI/GameState/INetworkProvider.cs
@@ -0,0 +1,35 @@
+using System;
+
+namespace NebulaAPI
+{
+ public interface INetworkProvider : IDisposable
+ {
+ ///
+ /// Send packet to Host (If ran on Client) or all Clients (If ran on Host)
+ ///
+ void SendPacket(T packet) where T : class, new();
+ ///
+ /// Send packet to all Clients within current star system
+ ///
+ void SendPacketToLocalStar(T packet) where T : class, new();
+ ///
+ /// Send packet to all Clients within current planet
+ ///
+ void SendPacketToLocalPlanet(T packet) where T : class, new();
+
+ ///
+ /// Send packet to all Clients on a planet
+ ///
+ void SendPacketToPlanet(T packet, int planetId) where T : class, new();
+ ///
+ /// Send packet to all Clients within star system
+ ///
+ void SendPacketToStar(T packet, int starId) where T : class, new();
+
+ void SendPacketToStarExclude(T packet, int starId, INebulaConnection exclude) where T : class, new();
+
+ IPlayerManager PlayerManager { get; }
+
+ void Update();
+ }
+}
\ No newline at end of file
diff --git a/NebulaAPI/GameState/IPlayerData.cs b/NebulaAPI/GameState/IPlayerData.cs
new file mode 100644
index 000000000..d3d526820
--- /dev/null
+++ b/NebulaAPI/GameState/IPlayerData.cs
@@ -0,0 +1,19 @@
+namespace NebulaAPI
+{
+ public interface IPlayerData : INetSerializable
+ {
+ string Username { get; set; }
+ ushort PlayerId { get; set; }
+ int LocalPlanetId { get; set; }
+ Float3 MechaColor { get; set; }
+ Float3 LocalPlanetPosition { get; set; }
+ Double3 UPosition { get; set; }
+ Float3 Rotation { get; set; }
+ Float3 BodyRotation { get; set; }
+ int LocalStarId { get; set; }
+
+ IMechaData Mecha { get; set; }
+
+ IPlayerData CreateCopyWithoutMechaData();
+ }
+}
\ No newline at end of file
diff --git a/NebulaAPI/GameState/IPlayerManager.cs b/NebulaAPI/GameState/IPlayerManager.cs
new file mode 100644
index 000000000..82611174b
--- /dev/null
+++ b/NebulaAPI/GameState/IPlayerManager.cs
@@ -0,0 +1,50 @@
+using NebulaAPI;
+using System.Collections.Generic;
+
+namespace NebulaAPI
+{
+ public interface IPlayerManager
+ {
+ Locker GetPendingPlayers(out Dictionary pendingPlayers);
+
+ Locker GetSyncingPlayers(out Dictionary syncingPlayers);
+
+ Locker GetConnectedPlayers(out Dictionary connectedPlayers);
+
+ Locker GetSavedPlayerData(out Dictionary savedPlayerData);
+
+ IPlayerData[] GetAllPlayerDataIncludingHost();
+
+ INebulaPlayer GetPlayer(INebulaConnection conn);
+
+ INebulaPlayer GetSyncingPlayer(INebulaConnection conn);
+
+ void SendPacketToAllPlayers(T packet) where T : class, new();
+
+ void SendPacketToLocalStar(T packet) where T : class, new();
+
+ void SendPacketToLocalPlanet(T packet) where T : class, new();
+
+ void SendPacketToPlanet(T packet, int planetId) where T : class, new();
+
+ void SendPacketToStar(T packet, int starId) where T : class, new();
+
+ void SendPacketToStarExcept(T packet, int starId, INebulaConnection exclude) where T : class, new();
+
+ void SendRawPacketToStar(byte[] rawPacket, int starId, INebulaConnection sender);
+
+ void SendRawPacketToPlanet(byte[] rawPacket, int planetId, INebulaConnection sender);
+
+ void SendPacketToOtherPlayers(T packet, INebulaPlayer sender) where T : class, new();
+
+ INebulaPlayer PlayerConnected(INebulaConnection conn);
+
+ void PlayerDisconnected(INebulaConnection conn);
+
+ ushort GetNextAvailablePlayerId();
+
+ void SendTechRefundPackagesToClients(int techId);
+
+ void UpdateMechaData(IMechaData mechaData, INebulaConnection conn);
+ }
+}
diff --git a/NebulaAPI/Interfaces/BinaryInterfaces.cs b/NebulaAPI/Interfaces/BinaryInterfaces.cs
new file mode 100644
index 000000000..73b0cca44
--- /dev/null
+++ b/NebulaAPI/Interfaces/BinaryInterfaces.cs
@@ -0,0 +1,22 @@
+using System;
+using System.IO;
+
+namespace NebulaAPI
+{
+ ///
+ /// Provides access to BinaryWriter with LZ4 compression
+ ///
+ public interface IWriterProvider : IDisposable
+ {
+ BinaryWriter BinaryWriter { get; }
+ byte[] CloseAndGetBytes();
+ }
+
+ ///
+ /// Provides access to BinaryReader with LZ4 compression
+ ///
+ public interface IReaderProvider : IDisposable
+ {
+ BinaryReader BinaryReader { get; }
+ }
+}
\ No newline at end of file
diff --git a/NebulaAPI/Interfaces/IMultiplayerMod.cs b/NebulaAPI/Interfaces/IMultiplayerMod.cs
new file mode 100644
index 000000000..56109c543
--- /dev/null
+++ b/NebulaAPI/Interfaces/IMultiplayerMod.cs
@@ -0,0 +1,22 @@
+using System.IO;
+
+namespace NebulaAPI
+{
+ ///
+ /// Implement this interface to make sure your mod will be the same version on the host
+ ///
+ public interface IMultiplayerMod
+ {
+ string Version { get; }
+ bool CheckVersion(string hostVersion, string clientVersion);
+ }
+
+ ///
+ /// Implement this interface if you have important settings that clients need to know
+ ///
+ public interface IMultiplayerModWithSettings : IMultiplayerMod
+ {
+ void Export (BinaryWriter w);
+ void Import (BinaryReader r);
+ }
+}
diff --git a/NebulaAPI/Interfaces/INetSerializable.cs b/NebulaAPI/Interfaces/INetSerializable.cs
new file mode 100644
index 000000000..2ae55c1ff
--- /dev/null
+++ b/NebulaAPI/Interfaces/INetSerializable.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Net;
+using System.Text;
+
+namespace NebulaAPI
+{
+ public interface INetSerializable
+ {
+ void Serialize(INetDataWriter writer);
+ void Deserialize(INetDataReader reader);
+ }
+
+ public interface INetDataWriter
+ {
+ void Put(float value);
+
+ void Put(double value);
+
+ void Put(long value);
+
+ void Put(ulong value);
+
+ void Put(int value);
+
+ void Put(uint value);
+
+ void Put(char value);
+
+ void Put(ushort value);
+
+ void Put(short value);
+
+ void Put(sbyte value);
+
+ void Put(byte value);
+
+ void Put(byte[] data, int offset, int length);
+
+ void Put(byte[] data);
+
+ void PutSBytesWithLength(sbyte[] data, int offset, int length);
+
+ void PutSBytesWithLength(sbyte[] data);
+
+ void PutBytesWithLength(byte[] data, int offset, int length);
+
+ void PutBytesWithLength(byte[] data);
+
+ void Put(bool value);
+
+ void PutArray(float[] value);
+
+ void PutArray(double[] value);
+
+ void PutArray(long[] value);
+
+ void PutArray(ulong[] value);
+
+ void PutArray(int[] value);
+
+ void PutArray(uint[] value);
+
+ void PutArray(ushort[] value);
+
+ void PutArray(short[] value);
+
+ void PutArray(bool[] value);
+
+ void PutArray(string[] value);
+
+ void PutArray(string[] value, int maxLength);
+
+ void Put(IPEndPoint endPoint);
+
+ void Put(string value);
+
+ void Put(string value, int maxLength);
+
+ void Put(T obj) where T : INetSerializable;
+ }
+
+ public interface INetDataReader
+ {
+ IPEndPoint GetNetEndPoint();
+
+ byte GetByte();
+
+ sbyte GetSByte();
+
+ bool[] GetBoolArray();
+
+ ushort[] GetUShortArray();
+
+ short[] GetShortArray();
+
+ long[] GetLongArray();
+
+ ulong[] GetULongArray();
+
+ int[] GetIntArray();
+
+ uint[] GetUIntArray();
+
+ float[] GetFloatArray();
+
+ double[] GetDoubleArray();
+
+ string[] GetStringArray();
+
+ string[] GetStringArray(int maxStringLength);
+
+ bool GetBool();
+
+ char GetChar();
+
+ ushort GetUShort();
+
+ short GetShort();
+
+ long GetLong();
+
+ ulong GetULong();
+
+ int GetInt();
+
+ uint GetUInt();
+
+ float GetFloat();
+
+ double GetDouble();
+
+ string GetString(int maxLength);
+
+ string GetString();
+
+ ArraySegment GetRemainingBytesSegment();
+
+ T Get() where T : INetSerializable, new();
+
+ byte[] GetRemainingBytes();
+
+ void GetBytes(byte[] destination, int start, int count);
+
+ void GetBytes(byte[] destination, int count);
+
+ sbyte[] GetSBytesWithLength();
+
+ byte[] GetBytesWithLength();
+ }
+}
diff --git a/NebulaAPI/Interfaces/IToggle.cs b/NebulaAPI/Interfaces/IToggle.cs
new file mode 100644
index 000000000..35f757294
--- /dev/null
+++ b/NebulaAPI/Interfaces/IToggle.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace NebulaAPI
+{
+ public interface IToggle
+ {
+ bool Value { get; }
+ IDisposable On();
+ }
+}
\ No newline at end of file
diff --git a/NebulaAPI/NebulaAPI.csproj b/NebulaAPI/NebulaAPI.csproj
new file mode 100644
index 000000000..13a6b34c9
--- /dev/null
+++ b/NebulaAPI/NebulaAPI.csproj
@@ -0,0 +1,2 @@
+
+
diff --git a/NebulaAPI/NebulaModAPI.cs b/NebulaAPI/NebulaModAPI.cs
new file mode 100644
index 000000000..998828091
--- /dev/null
+++ b/NebulaAPI/NebulaModAPI.cs
@@ -0,0 +1,141 @@
+using BepInEx;
+using HarmonyLib;
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace NebulaAPI
+{
+ [BepInPlugin(API_GUID, API_NAME, ThisAssembly.AssemblyFileVersion)]
+ [BepInDependency(NEBULA_MODID, BepInDependency.DependencyFlags.SoftDependency)]
+ public class NebulaModAPI : BaseUnityPlugin
+ {
+ private static bool nebulaIsInstalled;
+
+ private static Type multiplayer;
+
+ private static Type binaryWriter;
+ private static Type binaryReader;
+
+ public static readonly List TargetAssemblies = new List();
+
+ public const string NEBULA_MODID = "dsp.nebula-multiplayer";
+
+ public const string API_GUID = "dsp.nebula-multiplayer-api";
+ public const string API_NAME = "NebulaMultiplayerModApi";
+
+ public static bool NebulaIsInstalled => nebulaIsInstalled;
+
+ ///
+ /// Is this session in multiplayer
+ ///
+ public static bool IsMultiplayerActive
+ {
+ get
+ {
+ if (!NebulaIsInstalled) return false;
+
+ return (bool)multiplayer.GetProperty("IsActive").GetValue(null);
+ }
+ }
+
+ ///
+ /// Provides access to MultiplayerSession class
+ ///
+ public static IMultiplayerSession MultiplayerSession
+ {
+ get
+ {
+ if (!NebulaIsInstalled) return null;
+
+ return (IMultiplayerSession) multiplayer.GetProperty("Session").GetValue(null);
+ }
+ }
+
+ ///
+ /// Subscribe to receive event when new multiplayer game is started
+ ///
+ public static Action OnMultiplayerGameStarted;
+
+ ///
+ /// Subscribe to receive event when multiplayer game end
+ ///
+ public static Action OnMultiplayerGameEnded;
+
+ ///
+ /// Subscribe to receive event when a new star starts loaded
+ /// int starIndex - index of star to load
+ ///
+ public static Action OnStarLoadRequest;
+
+ ///
+ /// Subscribe to receive event when a new planet starts loaded
+ /// int planetId - id of planet to load
+ ///
+ public static Action OnPlanetLoadRequest;
+
+ ///
+ /// Subscribe to receive event when a new planet is finished loading
+ /// int planetId - id of planet to load
+ ///
+ public static Action OnPlanetLoadFinished;
+
+ private void Awake()
+ {
+ nebulaIsInstalled = false;
+
+ foreach (var pluginInfo in BepInEx.Bootstrap.Chainloader.PluginInfos)
+ {
+ if (pluginInfo.Value.Metadata.GUID == NEBULA_MODID)
+ {
+ nebulaIsInstalled = true;
+ break;
+ }
+ }
+
+ if (!nebulaIsInstalled) return;
+
+ multiplayer = AccessTools.TypeByName("NebulaWorld.Multiplayer");
+
+ Type binaryUtils = AccessTools.TypeByName("NebulaModel.Networking.BinaryUtils");
+
+ binaryWriter = binaryUtils.GetNestedType("Writer");
+ binaryReader = binaryUtils.GetNestedType("Reader");
+
+ Logger.LogInfo("Nebula API is ready!");
+ }
+
+ public const int PLANET_NONE = -2;
+ public const int AUTHOR_NONE = -1;
+ public const int STAR_NONE = -1;
+
+ ///
+ /// Register all packets within assembly
+ ///
+ /// Target assembly
+ public static void RegisterPackets(Assembly assembly)
+ {
+ TargetAssemblies.Add(assembly);
+ }
+
+ ///
+ /// Provides access to BinaryWriter with LZ4 compression
+ ///
+ public static IWriterProvider GetBinaryWriter()
+ {
+ if (!NebulaIsInstalled) return null;
+
+ return (IWriterProvider) binaryWriter.GetConstructor(new Type[0]).Invoke(new object[0]);
+ }
+
+ ///
+ /// Provides access to BinaryReader with LZ4 compression
+ ///
+ public static IReaderProvider GetBinaryReader(byte[] bytes)
+ {
+ if (!NebulaIsInstalled) return null;
+
+ return (IReaderProvider) binaryReader.GetConstructor(new[]{typeof(byte[])}).Invoke(new object[]{bytes});
+ }
+ }
+}
\ No newline at end of file
diff --git a/NebulaAPI/Packets/BasePacketProcessor.cs b/NebulaAPI/Packets/BasePacketProcessor.cs
new file mode 100644
index 000000000..066232bcb
--- /dev/null
+++ b/NebulaAPI/Packets/BasePacketProcessor.cs
@@ -0,0 +1,30 @@
+namespace NebulaAPI
+{
+ ///
+ /// Describes how to process received packets of type T
+ ///
+ /// Packet class
+ public abstract class BasePacketProcessor
+ {
+ ///
+ /// Is code running on Host
+ ///
+ protected bool IsHost;
+ ///
+ /// Is code running on Client
+ ///
+ protected bool IsClient => !IsHost;
+
+ internal void Initialize(bool isHost)
+ {
+ IsHost = isHost;
+ }
+
+ ///
+ /// Process packets here
+ ///
+ /// Received packet
+ /// Connection that sent the packet
+ public abstract void ProcessPacket(T packet, INebulaConnection conn);
+ }
+}
\ No newline at end of file
diff --git a/NebulaModel/Attributes/HidePacketInDebugLogsAttribute.cs b/NebulaAPI/Packets/HidePacketInDebugLogsAttribute.cs
similarity index 84%
rename from NebulaModel/Attributes/HidePacketInDebugLogsAttribute.cs
rename to NebulaAPI/Packets/HidePacketInDebugLogsAttribute.cs
index 7b37910e8..b3a3a3415 100644
--- a/NebulaModel/Attributes/HidePacketInDebugLogsAttribute.cs
+++ b/NebulaAPI/Packets/HidePacketInDebugLogsAttribute.cs
@@ -1,6 +1,6 @@
using System;
-namespace NebulaModel.Attributes
+namespace NebulaAPI
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
public class HidePacketInDebugLogsAttribute : Attribute { }
diff --git a/NebulaAPI/Packets/INebulaConnection.cs b/NebulaAPI/Packets/INebulaConnection.cs
new file mode 100644
index 000000000..94c7a1d5b
--- /dev/null
+++ b/NebulaAPI/Packets/INebulaConnection.cs
@@ -0,0 +1,7 @@
+namespace NebulaAPI
+{
+ public interface INebulaConnection
+ {
+ void SendPacket(T packet) where T : class, new();
+ }
+}
\ No newline at end of file
diff --git a/NebulaAPI/Packets/RegisterNestedTypeAttribute.cs b/NebulaAPI/Packets/RegisterNestedTypeAttribute.cs
new file mode 100644
index 000000000..ed1cf53f8
--- /dev/null
+++ b/NebulaAPI/Packets/RegisterNestedTypeAttribute.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace NebulaAPI
+{
+ ///
+ /// Registers custom data structure serializer. Make sure to register your assembly using NebulaModAPI.RegisterPackets
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
+ public class RegisterNestedTypeAttribute : Attribute { }
+}
diff --git a/NebulaAPI/Packets/RegisterPacketProcessorAttribute.cs b/NebulaAPI/Packets/RegisterPacketProcessorAttribute.cs
new file mode 100644
index 000000000..c229a7f12
--- /dev/null
+++ b/NebulaAPI/Packets/RegisterPacketProcessorAttribute.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace NebulaAPI
+{
+ ///
+ /// Registers packet processors. Make sure to register your assembly using NebulaModAPI.RegisterPackets
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+ public class RegisterPacketProcessorAttribute : Attribute { }
+}
diff --git a/NebulaAPI/README.md b/NebulaAPI/README.md
new file mode 100644
index 000000000..928e4c700
--- /dev/null
+++ b/NebulaAPI/README.md
@@ -0,0 +1,17 @@
+# Nebula Multiplayer API
+
+API for [Nebula multiplayer mod](https://dsp.thunderstore.io/package/nebula/NebulaMultiplayerMod/). This API allows mod developers to support Nebula. You can find setting up guide, examples and documentation [here](https://github.com/hubastard/nebula/wiki)
+
+# FAQ
+
+## Where can I get help using the API?
+
+Please join our [Discord Server](https://discord.gg/UHeB2QvgDa) and ask your question in the `General` channel. We have a really nice community that will be able to answer your questions.
+
+## How can I contribute?
+
+Please join our [Discord Server](https://discord.gg/UHeB2QvgDa) to ask if someone is already working on the task that you want to do. Once, you are done with your modification, simply submit a pull request. Contribution documentation can be found here: [Wiki](https://github.com/hubastard/nebula/wiki/Setting-up-a-development-environment).
+
+## How can I support the team?
+
+If you like what we do and would like to support us, you can donate through our [Patreon](https://www.patreon.com/nebula_mod_team). Thanks for the support <3
\ No newline at end of file
diff --git a/NebulaAPI/icon.png b/NebulaAPI/icon.png
new file mode 100644
index 000000000..63056101e
Binary files /dev/null and b/NebulaAPI/icon.png differ
diff --git a/NebulaAPI/version.json b/NebulaAPI/version.json
new file mode 100644
index 000000000..c2143a858
--- /dev/null
+++ b/NebulaAPI/version.json
@@ -0,0 +1,15 @@
+{
+ "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
+ "version": "1.0.0",
+ "assemblyVersion": {
+ "precision": "build"
+ },
+ "gitCommitIdShortFixedLength": 7,
+ "publicReleaseRefSpec": [
+ "^refs/tags/v\\d+\\.\\d+"
+ ],
+ "release": {
+ "versionIncrement": "build",
+ "firstUnstableTag": ""
+ }
+}
diff --git a/NebulaModel/Attributes/RegisterNestedTypeAttribute.cs b/NebulaModel/Attributes/RegisterNestedTypeAttribute.cs
deleted file mode 100644
index 4fdc41a21..000000000
--- a/NebulaModel/Attributes/RegisterNestedTypeAttribute.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-using System;
-
-namespace NebulaModel.Attributes
-{
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
- public class RegisterNestedTypeAttribute : Attribute { }
-}
diff --git a/NebulaModel/Attributes/RegisterPacketProcessorAttribute.cs b/NebulaModel/Attributes/RegisterPacketProcessorAttribute.cs
deleted file mode 100644
index 729568d8e..000000000
--- a/NebulaModel/Attributes/RegisterPacketProcessorAttribute.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-using System;
-
-namespace NebulaModel.Attributes
-{
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
- public class RegisterPacketProcessorAttribute : Attribute { }
-}
diff --git a/NebulaModel/DataStructures/DataStructureExtensions.cs b/NebulaModel/DataStructures/DataStructureExtensions.cs
index 2f170ca24..2552f8104 100644
--- a/NebulaModel/DataStructures/DataStructureExtensions.cs
+++ b/NebulaModel/DataStructures/DataStructureExtensions.cs
@@ -2,33 +2,8 @@
namespace NebulaModel.DataStructures
{
- public static class DataStructureExtensions
+ public static class AnimationStateExtensions
{
- public static Vector3 ToVector3(this Float3 value)
- {
- return new Vector3(value.x, value.y, value.z);
- }
-
- public static VectorLF3 ToVectorLF3(this Double3 value)
- {
- return new VectorLF3(value.x, value.y, value.z);
- }
-
- public static Float3 ToFloat3(this Vector3 value)
- {
- return new Float3(value.x, value.y, value.z);
- }
-
- public static Quaternion ToQuaternion(this Float4 value)
- {
- return new Quaternion(value.x, value.y, value.z, value.w);
- }
-
- public static Float4 ToFloat4(this Quaternion value)
- {
- return new Float4(value.x, value.y, value.z, value.w);
- }
-
public static NebulaAnimationState ToNebula(this AnimationState state)
{
return new NebulaAnimationState()
diff --git a/NebulaModel/DataStructures/GameState.cs b/NebulaModel/DataStructures/GameState.cs
index b001c8f66..2d2e549e5 100644
--- a/NebulaModel/DataStructures/GameState.cs
+++ b/NebulaModel/DataStructures/GameState.cs
@@ -1,4 +1,4 @@
-using NebulaModel.Attributes;
+using NebulaAPI;
using NebulaModel.Networking.Serialization;
namespace NebulaModel.DataStructures
@@ -15,13 +15,13 @@ public GameState(long timestamp, long gameTick)
this.gameTick = gameTick;
}
- public void Serialize(NetDataWriter writer)
+ public void Serialize(INetDataWriter writer)
{
writer.Put(timestamp);
writer.Put(gameTick);
}
- public void Deserialize(NetDataReader reader)
+ public void Deserialize(INetDataReader reader)
{
timestamp = reader.GetLong();
gameTick = reader.GetLong();
diff --git a/NebulaModel/DataStructures/MechaData.cs b/NebulaModel/DataStructures/MechaData.cs
index f607eece8..74e5f6fa0 100644
--- a/NebulaModel/DataStructures/MechaData.cs
+++ b/NebulaModel/DataStructures/MechaData.cs
@@ -1,5 +1,4 @@
-using NebulaModel.Attributes;
-using NebulaModel.Networking.Serialization;
+using NebulaAPI;
using NebulaModel.Packets.Players;
using System.Collections.Generic;
using System.IO;
@@ -7,7 +6,7 @@
namespace NebulaModel.DataStructures
{
[RegisterNestedType]
- public class MechaData : INetSerializable
+ public class MechaData : IMechaData
{
public int SandCount { get; set; }
public double CoreEnergy { get; set; }
@@ -40,7 +39,7 @@ public MechaData(int sandCount, double coreEnergy, double reactorEnergy, Storage
this.TechBonuses = new PlayerTechBonuses();
}
- public void Serialize(NetDataWriter writer)
+ public void Serialize(INetDataWriter writer)
{
TechBonuses.Serialize(writer);
writer.Put(SandCount);
@@ -65,7 +64,7 @@ public void Serialize(NetDataWriter writer)
}
}
- public void Deserialize(NetDataReader reader)
+ public void Deserialize(INetDataReader reader)
{
TechBonuses = new PlayerTechBonuses();
Inventory = new StorageComponent(4);
diff --git a/NebulaModel/DataStructures/NebulaAnimationState.cs b/NebulaModel/DataStructures/NebulaAnimationState.cs
index a3d90d623..7db917c02 100644
--- a/NebulaModel/DataStructures/NebulaAnimationState.cs
+++ b/NebulaModel/DataStructures/NebulaAnimationState.cs
@@ -1,4 +1,4 @@
-using NebulaModel.Attributes;
+using NebulaAPI;
using NebulaModel.Networking.Serialization;
namespace NebulaModel.DataStructures
@@ -10,14 +10,14 @@ public struct NebulaAnimationState : INetSerializable
public float Speed { get; set; }
public bool Enabled { get; set; }
- public void Serialize(NetDataWriter writer)
+ public void Serialize(INetDataWriter writer)
{
writer.Put(Weight);
writer.Put(Speed);
writer.Put(Enabled);
}
- public void Deserialize(NetDataReader reader)
+ public void Deserialize(INetDataReader reader)
{
Weight = reader.GetFloat();
Speed = reader.GetFloat();
diff --git a/NebulaModel/DataStructures/NetDataReaderExtensions.cs b/NebulaModel/DataStructures/NetDataReaderExtensions.cs
index f817873a8..8d99f78e1 100644
--- a/NebulaModel/DataStructures/NetDataReaderExtensions.cs
+++ b/NebulaModel/DataStructures/NetDataReaderExtensions.cs
@@ -1,24 +1,25 @@
-using NebulaModel.Networking.Serialization;
+using NebulaAPI;
+using NebulaModel.Networking.Serialization;
namespace NebulaModel.DataStructures
{
public static class NetDataReaderExtensions
{
- public static Float3 GetFloat3(this NetDataReader reader)
+ public static Float3 GetFloat3(this INetDataReader reader)
{
Float3 value = new Float3();
value.Deserialize(reader);
return value;
}
- public static Float4 GetFloat4(this NetDataReader reader)
+ public static Float4 GetFloat4(this INetDataReader reader)
{
Float4 value = new Float4();
value.Deserialize(reader);
return value;
}
- public static Double3 GetDouble3(this NetDataReader reader)
+ public static Double3 GetDouble3(this INetDataReader reader)
{
Double3 value = new Double3();
value.Deserialize(reader);
diff --git a/NebulaModel/DataStructures/PlayerData.cs b/NebulaModel/DataStructures/PlayerData.cs
index 1f8943cfb..453541c31 100644
--- a/NebulaModel/DataStructures/PlayerData.cs
+++ b/NebulaModel/DataStructures/PlayerData.cs
@@ -1,10 +1,10 @@
-using NebulaModel.Attributes;
+using NebulaAPI;
using NebulaModel.Networking.Serialization;
namespace NebulaModel.DataStructures
{
[RegisterNestedType]
- public class PlayerData : INetSerializable
+ public class PlayerData : IPlayerData
{
public string Username { get; set; }
public ushort PlayerId { get; set; }
@@ -14,7 +14,7 @@ public class PlayerData : INetSerializable
public Double3 UPosition { get; set; }
public Float3 Rotation { get; set; }
public Float3 BodyRotation { get; set; }
- public MechaData Mecha { get; set; }
+ public IMechaData Mecha { get; set; }
public int LocalStarId { get; set; }
public PlayerData() { }
@@ -31,7 +31,7 @@ public PlayerData() { }
Mecha = new MechaData();
}
- public void Serialize(NetDataWriter writer)
+ public void Serialize(INetDataWriter writer)
{
writer.Put(Username);
writer.Put(PlayerId);
@@ -44,7 +44,7 @@ public void Serialize(NetDataWriter writer)
Mecha.Serialize(writer);
}
- public void Deserialize(NetDataReader reader)
+ public void Deserialize(INetDataReader reader)
{
Username = reader.GetString();
PlayerId = reader.GetUShort();
@@ -58,7 +58,7 @@ public void Deserialize(NetDataReader reader)
Mecha.Deserialize(reader);
}
- public PlayerData CreateCopyWithoutMechaData()
+ public IPlayerData CreateCopyWithoutMechaData()
{
return new PlayerData(PlayerId, LocalPlanetId, MechaColor, Username, LocalPlanetPosition, UPosition, Rotation, BodyRotation);
}
diff --git a/NebulaModel/DataStructures/ToggleSwitch.cs b/NebulaModel/DataStructures/ToggleSwitch.cs
index dd4966f7e..cfb9422fd 100644
--- a/NebulaModel/DataStructures/ToggleSwitch.cs
+++ b/NebulaModel/DataStructures/ToggleSwitch.cs
@@ -1,9 +1,10 @@
-using System;
+using NebulaAPI;
+using System;
using System.Threading;
namespace NebulaModel.DataStructures
{
- public sealed class ToggleSwitch
+ public sealed class ToggleSwitch : IToggle
{
int onCount;
@@ -12,7 +13,7 @@ public sealed class ToggleSwitch
public static implicit operator bool(ToggleSwitch toggle) => toggle.Value;
public Toggle On(bool conditional) => new Toggle(this, conditional ? 1 : 0);
- public Toggle On() => new Toggle(this, 1);
+ public IDisposable On() => new Toggle(this, 1);
public readonly struct Toggle : IDisposable
{
diff --git a/NebulaModel/IPlayerManager.cs b/NebulaModel/IPlayerManager.cs
deleted file mode 100644
index f820bc186..000000000
--- a/NebulaModel/IPlayerManager.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using NebulaModel.DataStructures;
-using NebulaModel.Networking;
-using System.Collections.Generic;
-
-namespace NebulaModel
-{
- public interface IPlayerManager
- {
- Locker GetPendingPlayers(out Dictionary pendingPlayers);
-
- Locker GetSyncingPlayers(out Dictionary syncingPlayers);
-
- Locker GetConnectedPlayers(out Dictionary connectedPlayers);
-
- Locker GetSavedPlayerData(out Dictionary savedPlayerData);
-
- PlayerData[] GetAllPlayerDataIncludingHost();
-
- NebulaPlayer GetPlayer(NebulaConnection conn);
-
- NebulaPlayer GetSyncingPlayer(NebulaConnection conn);
-
- void SendPacketToAllPlayers(T packet) where T : class, new();
-
- void SendPacketToLocalStar(T packet) where T : class, new();
-
- void SendPacketToLocalPlanet(T packet) where T : class, new();
-
- void SendPacketToPlanet(T packet, int planetId) where T : class, new();
-
- void SendPacketToStar(T packet, int starId) where T : class, new();
-
- void SendPacketToStarExcept(T packet, int starId, NebulaConnection exclude) where T : class, new();
-
- void SendRawPacketToStar(byte[] rawPacket, int starId, NebulaConnection sender);
-
- void SendRawPacketToPlanet(byte[] rawPacket, int planetId, NebulaConnection sender);
-
- void SendPacketToOtherPlayers(T packet, NebulaPlayer sender) where T : class, new();
-
- NebulaPlayer PlayerConnected(NebulaConnection conn);
-
- void PlayerDisconnected(NebulaConnection conn);
-
- ushort GetNextAvailablePlayerId();
-
- void UpdateMechaData(MechaData mechaData, NebulaConnection conn);
-
- void SendTechRefundPackagesToClients(int techId);
- }
-}
diff --git a/NebulaModel/MultiplayerOptions.cs b/NebulaModel/MultiplayerOptions.cs
index 982438c32..28827ae54 100644
--- a/NebulaModel/MultiplayerOptions.cs
+++ b/NebulaModel/MultiplayerOptions.cs
@@ -1,4 +1,5 @@
-using NebulaModel.Attributes;
+using NebulaAPI;
+using NebulaModel.Attributes;
using System;
using System.ComponentModel;
diff --git a/NebulaModel/NebulaModel.csproj b/NebulaModel/NebulaModel.csproj
index 4f0f72709..60069a787 100644
--- a/NebulaModel/NebulaModel.csproj
+++ b/NebulaModel/NebulaModel.csproj
@@ -2,6 +2,7 @@
+
diff --git a/NebulaModel/NetworkProvider.cs b/NebulaModel/NetworkProvider.cs
index f2b859ba7..6d3a913f3 100644
--- a/NebulaModel/NetworkProvider.cs
+++ b/NebulaModel/NetworkProvider.cs
@@ -1,14 +1,15 @@
-using NebulaModel.Networking;
+using NebulaAPI;
+using NebulaModel.Networking;
using NebulaModel.Networking.Serialization;
using System;
namespace NebulaModel
{
- public abstract class NetworkProvider : IDisposable
+ public abstract class NetworkProvider : IDisposable, INetworkProvider
{
public NetPacketProcessor PacketProcessor { get; protected set; }
- public readonly IPlayerManager PlayerManager;
+ public IPlayerManager PlayerManager { get; }
protected NetworkProvider(IPlayerManager playerManager)
{
@@ -32,7 +33,7 @@ protected NetworkProvider(IPlayerManager playerManager)
public abstract void SendPacketToStar(T packet, int starId) where T : class, new();
- public abstract void SendPacketToStarExclude(T packet, int starId, NebulaConnection exclude)
+ public abstract void SendPacketToStarExclude(T packet, int starId, INebulaConnection exclude)
where T : class, new();
public abstract void Update();
diff --git a/NebulaModel/Networking/BinaryUtils.cs b/NebulaModel/Networking/BinaryUtils.cs
index 354615ee4..6e830c821 100644
--- a/NebulaModel/Networking/BinaryUtils.cs
+++ b/NebulaModel/Networking/BinaryUtils.cs
@@ -1,4 +1,5 @@
using K4os.Compression.LZ4.Streams;
+using NebulaAPI;
using System;
using System.IO;
@@ -8,7 +9,7 @@ public static class BinaryUtils
{
const int BUFFER_SIZE = 8192;
- public class Writer : IDisposable
+ public class Writer : IWriterProvider
{
readonly MemoryStream ms;
readonly LZ4EncoderStream ls;
@@ -41,7 +42,7 @@ public byte[] CloseAndGetBytes()
}
}
- public class Reader : IDisposable
+ public class Reader : IReaderProvider
{
readonly MemoryStream ms;
readonly LZ4DecoderStream ls;
diff --git a/NebulaModel/Networking/DisconnectionReason.cs b/NebulaModel/Networking/DisconnectionReason.cs
index 7eb3cf0ad..0f4398dfc 100644
--- a/NebulaModel/Networking/DisconnectionReason.cs
+++ b/NebulaModel/Networking/DisconnectionReason.cs
@@ -12,8 +12,10 @@ public enum DisconnectionReason
ClientRequestedDisconnect = 2001,
ModVersionMismatch = 2002,
GameVersionMismatch = 2003,
-
+
+
// Mod Specific Error Codes
- GalacticScaleMissmatch = 3000,
+ ModIsMissing = 2500,
+ ModIsMissingOnServer = 2501
}
}
diff --git a/NebulaModel/Networking/NebulaConnection.cs b/NebulaModel/Networking/NebulaConnection.cs
index c211d9e29..9841d4b31 100644
--- a/NebulaModel/Networking/NebulaConnection.cs
+++ b/NebulaModel/Networking/NebulaConnection.cs
@@ -1,4 +1,5 @@
-using NebulaModel.Logger;
+using NebulaAPI;
+using NebulaModel.Logger;
using NebulaModel.Networking.Serialization;
using System;
using System.Net;
@@ -6,7 +7,7 @@
namespace NebulaModel.Networking
{
- public class NebulaConnection
+ public class NebulaConnection : INebulaConnection
{
private readonly EndPoint peerEndpoint;
private readonly WebSocket peerSocket;
diff --git a/NebulaModel/Networking/PacketUtils.cs b/NebulaModel/Networking/PacketUtils.cs
index 468a10315..cfde8fc97 100644
--- a/NebulaModel/Networking/PacketUtils.cs
+++ b/NebulaModel/Networking/PacketUtils.cs
@@ -1,7 +1,6 @@
-using NebulaModel.Attributes;
+using NebulaAPI;
using NebulaModel.Logger;
using NebulaModel.Networking.Serialization;
-using NebulaModel.Packets;
using NebulaModel.Utils;
using System;
using System.Linq;
@@ -11,19 +10,18 @@ namespace NebulaModel.Networking
{
public static class PacketUtils
{
- public static void RegisterAllPacketNestedTypes(NetPacketProcessor packetProcessor)
+
+ public static void RegisterAllPacketNestedTypesInAssembly(Assembly assembly, NetPacketProcessor packetProcessor)
{
- var nestedTypes = AssembliesUtils.GetTypesWithAttribute();
+ var nestedTypes = AssembliesUtils.GetTypesWithAttributeInAssembly(assembly);
foreach (Type type in nestedTypes)
{
Log.Info($"Registering Nested Type: {type.Name}");
if (type.IsClass)
{
- // TODO: Find a better way to get the "NetPacketProcessor.RegisterNestedType" that as the Func param instead of by index.
- MethodInfo registerMethod = packetProcessor.GetType()
- .GetMethods()
+ MethodInfo registerMethod = packetProcessor.GetType().GetMethods()
.Where(m => m.Name == nameof(NetPacketProcessor.RegisterNestedType))
- .ToArray()[2]
+ .FirstOrDefault(m => m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType.Name.Equals(typeof(Func<>).Name))
.MakeGenericMethod(type);
MethodInfo delegateMethod = packetProcessor.GetType().GetMethod(nameof(NetPacketProcessor.CreateNestedClassInstance)).MakeGenericMethod(type);
@@ -44,9 +42,23 @@ public static void RegisterAllPacketNestedTypes(NetPacketProcessor packetProcess
}
}
- public static void RegisterAllPacketProcessorsInCallingAssembly(NetPacketProcessor packetProcessor, bool isMasterClient)
+ private static bool IsSubclassOfRawGeneric(Type generic, Type toCheck)
{
- var processors = Assembly.GetCallingAssembly().GetTypes()
+ while (toCheck != null && toCheck != typeof(object))
+ {
+ var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
+ if (generic == cur)
+ {
+ return true;
+ }
+ toCheck = toCheck.BaseType;
+ }
+ return false;
+ }
+
+ public static void RegisterAllPacketProcessorsInAssembly(Assembly assembly, NetPacketProcessor packetProcessor, bool isMasterClient)
+ {
+ var processors = assembly.GetTypes()
.Where(t => t.GetCustomAttributes(typeof(RegisterPacketProcessorAttribute), true).Length > 0);
MethodInfo method = packetProcessor.GetType().GetMethods()
@@ -56,29 +68,34 @@ public static void RegisterAllPacketProcessorsInCallingAssembly(NetPacketProcess
foreach (Type type in processors)
{
- if (type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(PacketProcessor<>))
+ if (IsSubclassOfRawGeneric(typeof(BasePacketProcessor<>), type))
{
Type packetType = type.BaseType.GetGenericArguments().FirstOrDefault();
Log.Info($"Registering {type.Name} to process packet of type: {packetType.Name}");
// Create instance of the processor
- Type delegateType = typeof(Action<,>).MakeGenericType(packetType, typeof(NebulaConnection));
+ Type delegateType = typeof(Action<,>).MakeGenericType(packetType, typeof(INebulaConnection));
object processor = Activator.CreateInstance(type);
- Delegate callback = Delegate.CreateDelegate(delegateType, processor, type.GetMethod(nameof(PacketProcessor