From f6a33158d49e0c8b1a5354d427033c8181723084 Mon Sep 17 00:00:00 2001 From: Hamunii Date: Mon, 5 Feb 2024 07:47:04 +0200 Subject: [PATCH 01/12] clarifications & additional information --- .../lethallib/custom-enemies/unity-project.md | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/dev/apis/lethallib/custom-enemies/unity-project.md b/docs/dev/apis/lethallib/custom-enemies/unity-project.md index 9c9866de315..69d6dc7018d 100644 --- a/docs/dev/apis/lethallib/custom-enemies/unity-project.md +++ b/docs/dev/apis/lethallib/custom-enemies/unity-project.md @@ -3,9 +3,13 @@ prev: true next: true description: A tutorial on configuring your Unity project for custom enemies. --- -# Unity Project +# ExampleEnemy Unity Project -You can open the Unity project included in the repository by choosing to open a project from disk, and selecting the `UnityProject` folder. When Unity has loaded the project, look into the ExampleEnemy folder for the assets that make up the asset bundle. +::: warning IMPORTANT +The Unity project this page references is in the [LC-ExampleEnemy](https://github.com/Hamunii/LC-ExampleEnemy) repository! So if you didn't already download your copy of the project, now is the time to do it! +::: + +You can open the Unity project from Unity Hub by choosing to open a project from disk, and selecting the `UnityProject` folder. When Unity has loaded the project, look into the `ExampleEnemy` folder for the assets that make up our asset bundle. ## Setting Up Our Unity Project @@ -53,7 +57,7 @@ We also depend on LethalLib by Evaisa (which is already included in the project) >- MMHOOK_Facepunch Transport for Netcode for GameObjects.dll ::: -The dll file of this mod also needs to be there so we can reference ExampleEnemyAI from a component of the ExampleEnemy prefab in Unity. We need to do this via a dll file, we cannot just copy and paste the ExampleEnemyAI.cs file in the Unity project because asset bundles cannot contain scripts, and it just doesn't get the reference otherwise. You know it doesn't get the reference in the form of a yellow warning text if you launch the game with the mod and you have unity logging enabled in the `BepInEx.cfg` file. +The dll file of our mod also needs to be there so we can reference [ExampleEnemyAI.cs](https://github.com/Hamunii/LC-ExampleEnemy/blob/main/Plugin/src/ExampleEnemyAI.cs) from a component of the ExampleEnemy prefab in Unity. We need to do this via a dll file, we cannot just copy and paste the ExampleEnemyAI.cs file in the Unity project because asset bundles cannot contain scripts, and it just doesn't get the reference otherwise. You know it doesn't get the reference in the form of a yellow warning text if you launch the game with the mod and you have unity logging enabled in the `BepInEx.cfg` file. ## Our ExampleEnemy Assets in Unity @@ -94,20 +98,28 @@ We also have these as children of the prefab itself: - Allows us to scan the enemy. Make sure the following is set: - Tag: `DoNotSet` - Layer: `ScanNode` + - It also should have the following components: + - Scan Node Properties (Script) + - **Notice:** The `Creature Scan ID` property is overridden by LethalLib, so it does not matter what we set it as. Same goes for the `Creature File ID` on the bestiary Terminal Node. + - A collider, such as: `Box Collider`. While not necessary, it's a good idea to set `isTrigger: true` in order to avoid unwanted collisions with this object. 2. MapDot - Allows us to see the enemy on map. Make sure the following is set: - Tag: `DoNotSet` - Layer: `MapRadar` + - It is also worth nothing that this object gets rendered only on the map cameras, and the size and color of the object will be what you set them as in Unity. 3. Collision - - Has the following components: + - Allows our enemy to collide with the player and other things. Make sure the following is set: + - Tag: `Enemy` ( allows certain intercations, such as opening doors) + - Layer: `Enemies` + - Must also have the following components: - Enemy AI Collision Detect (Script) - - Box Collider with `isTrigger: true` + - A collider, such as: `Box Collider` with `isTrigger: true` 4. TurnCompass - - Does nothing by itself, but we have a reference to this in the ExampleEnemyAI.cs script to make the enemy looking at player a bit easier. + - Does nothing by itself, but we have a reference to this in the [ExampleEnemyAI.cs](https://github.com/Hamunii/LC-ExampleEnemy/blob/main/Plugin/src/ExampleEnemyAI.cs) script to make the enemy looking at player a bit easier. 5. AttackArea - Does nothing by itself, but we take its position and scale and check if the player exists inside that area for the head swing attack. 6. CreatureSFX - - We play the creature sound effects through this. + - We play the creature's sound effects through this. 7. CreatureVoice - We play the creature's voice through this. From a4b4d9ddc34e796f5bb921f4ea3184d2d9791297 Mon Sep 17 00:00:00 2001 From: Hamunii Date: Mon, 5 Feb 2024 08:52:14 +0200 Subject: [PATCH 02/12] MSBuild plugin no longer used: VS issues --- docs/dev/apis/lethallib/custom-enemies/coding-ai.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/dev/apis/lethallib/custom-enemies/coding-ai.md b/docs/dev/apis/lethallib/custom-enemies/coding-ai.md index e2bb1c0df92..9f0b9f017e1 100644 --- a/docs/dev/apis/lethallib/custom-enemies/coding-ai.md +++ b/docs/dev/apis/lethallib/custom-enemies/coding-ai.md @@ -195,7 +195,7 @@ We've now converted our AI into a state machine by using an enum! This helps you ### Networking - Unity Docs ::: warning IMPORTANT -We are using [Unity Netcode Patcher](https://github.com/EvaisaDev/UnityNetcodePatcher) MSBuild plugin to make our custom Rpc methods work. +We are using [Unity Netcode Patcher](https://github.com/EvaisaDev/UnityNetcodePatcher) to make our custom Rpc methods work. ::: [ClientRpc](https://docs-multiplayer.unity3d.com/netcode/current/advanced-topics/message-system/clientrpc/) From 2ec8182a6d5a34b59d519ba145595cb3f3f7afd9 Mon Sep 17 00:00:00 2001 From: Hamunii Date: Mon, 5 Feb 2024 08:59:37 +0200 Subject: [PATCH 03/12] fix spelling mistakes --- docs/dev/apis/lethallib/custom-enemies/blender-resources.md | 2 +- docs/dev/apis/lethallib/custom-enemies/unity-project.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/dev/apis/lethallib/custom-enemies/blender-resources.md b/docs/dev/apis/lethallib/custom-enemies/blender-resources.md index cff9e20862f..34cd0e3c3ac 100644 --- a/docs/dev/apis/lethallib/custom-enemies/blender-resources.md +++ b/docs/dev/apis/lethallib/custom-enemies/blender-resources.md @@ -44,7 +44,7 @@ If you have absolutely no experience with Blender, the 5 first parts of this ser ## Materials, Texturing & UV Unwrapping ::: info -Unity does not understand Blender's shader node system. If you use it for anything other than the princibled BSDF, you will have to bake your material as a texture before it will work in Unity. Also make note of the fact that Lethal Company automatically adds its own "style" to everything, so you don't need to worry about that. However, textures are not necessary so you can basically skip this section entirely. +Unity does not understand Blender's shader node system. If you use it for anything other than the principled BSDF, you will have to bake your material as a texture before it will work in Unity. Also make note of the fact that Lethal Company automatically adds its own "style" to everything, so you don't need to worry about that. However, textures are not necessary so you can basically skip this section entirely. ::: - [Blender 4.0 - Texture Painting quick start guide](https://youtu.be/iwWoXMWzC_c) - Jamie Dunbar diff --git a/docs/dev/apis/lethallib/custom-enemies/unity-project.md b/docs/dev/apis/lethallib/custom-enemies/unity-project.md index 69d6dc7018d..75d9d81f9ad 100644 --- a/docs/dev/apis/lethallib/custom-enemies/unity-project.md +++ b/docs/dev/apis/lethallib/custom-enemies/unity-project.md @@ -109,7 +109,7 @@ We also have these as children of the prefab itself: - It is also worth nothing that this object gets rendered only on the map cameras, and the size and color of the object will be what you set them as in Unity. 3. Collision - Allows our enemy to collide with the player and other things. Make sure the following is set: - - Tag: `Enemy` ( allows certain intercations, such as opening doors) + - Tag: `Enemy` ( allows certain interactions, such as opening doors) - Layer: `Enemies` - Must also have the following components: - Enemy AI Collision Detect (Script) @@ -133,7 +133,7 @@ If an existing item in the game starts with the same word as your enemy's name, We also have a TerminalKeyword ScriptableObject, which has the word that the user needs to write in the terminal to find the page. -The enemy spinning animation on the beastiary entry background is a video file, and you can make one yourself in Blender by for example using the decimate (if you have a lot of geometry) and wireframe modifiers. +The enemy spinning animation on the bestiary entry background is a video file, and you can make one yourself in Blender by for example using the decimate (if you have a lot of geometry) and wireframe modifiers. ::: warning IMPORTANT Unity Editor on Linux has [bad support for video files](https://docs.unity3d.com/Manual/VideoSources-FileCompatibility.html), so if you are using Linux, you might want to [encode your video to VP8 using FFmpeg](https://trac.ffmpeg.org/wiki/Encode/VP8). Unfortunately, Blender does not have an option to encode to VP8. @@ -144,7 +144,7 @@ Unity Editor on Linux has [bad support for video files](https://docs.unity3d.com We need to package our assets into an Asset Bundle in order to be able to load them from our plugin. See [Asset Bundling](/dev/intermediate/asset-bundling) to find out how this is done. ::: tip -We have a `SETUP-PROJECT.py` script in our project which genereates a `csproj.user` file. This file will copy your mod DLL and Asset Bundle to the path you specified when running the setup script, each time you build your plugin. +We have a `SETUP-PROJECT.py` script in our project which generates a `csproj.user` file. This file will copy your mod DLL and Asset Bundle to the path you specified when running the setup script, each time you build your plugin. Just make sure to keep the asset bundle name the default, or you'll have to edit your `csproj.user` file to look for the new name, in which case you may also want to edit our setup script to look for this new name in the file it generates. ::: \ No newline at end of file From ddb3c21bea5f3f9b02186dbf502e10739e8dc18a Mon Sep 17 00:00:00 2001 From: Hamunii Date: Tue, 6 Feb 2024 11:13:52 +0200 Subject: [PATCH 04/12] Add more info about components --- docs/dev/apis/lethallib/custom-enemies/unity-project.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/dev/apis/lethallib/custom-enemies/unity-project.md b/docs/dev/apis/lethallib/custom-enemies/unity-project.md index 75d9d81f9ad..ebaf6fb785a 100644 --- a/docs/dev/apis/lethallib/custom-enemies/unity-project.md +++ b/docs/dev/apis/lethallib/custom-enemies/unity-project.md @@ -109,11 +109,12 @@ We also have these as children of the prefab itself: - It is also worth nothing that this object gets rendered only on the map cameras, and the size and color of the object will be what you set them as in Unity. 3. Collision - Allows our enemy to collide with the player and other things. Make sure the following is set: - - Tag: `Enemy` ( allows certain interactions, such as opening doors) + - Tag: `Enemy` (allows certain interactions, such as opening doors) - Layer: `Enemies` - Must also have the following components: - Enemy AI Collision Detect (Script) - A collider, such as: `Box Collider` with `isTrigger: true` + - `Rigidbody`, so it can interact with certain colliders. This is also needed for our enemy to be able to open doors. 4. TurnCompass - Does nothing by itself, but we have a reference to this in the [ExampleEnemyAI.cs](https://github.com/Hamunii/LC-ExampleEnemy/blob/main/Plugin/src/ExampleEnemyAI.cs) script to make the enemy looking at player a bit easier. 5. AttackArea @@ -122,6 +123,8 @@ We also have these as children of the prefab itself: - We play the creature's sound effects through this. 7. CreatureVoice - We play the creature's voice through this. +8. Eye + - The point from which the game checks for line of sight in some methods. Make sure to reference this as the `Eye` in your AI script in Unity. ### ExampleEnemy Terminal Entry From 5d485f14e4a3bfdcdb644fa6d21940755e04c34e Mon Sep 17 00:00:00 2001 From: Hamunii Date: Sat, 10 Feb 2024 17:27:55 +0200 Subject: [PATCH 05/12] DevelopmentStartup now supports automatically joining local games --- docs/dev/mod-testing-tips.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/dev/mod-testing-tips.md b/docs/dev/mod-testing-tips.md index 2b814f66255..6e4db0a7fc4 100644 --- a/docs/dev/mod-testing-tips.md +++ b/docs/dev/mod-testing-tips.md @@ -18,7 +18,7 @@ We can open multiple instances of the game when opening it directly from the exe ### Instantly Load Into a Game -For entering a game as soon as possible, we can use [DevelopmentStartup](https://thunderstore.io/c/lethal-company/p/CTNOriginals/DevelopmentStartup/). This will skip start menus and jump right into a game. *Do note that it does not support automatically joining local games on a second instance yet.* +For entering a game as soon as possible, we can use [DevelopmentStartup](https://thunderstore.io/c/lethal-company/p/CTNOriginals/DevelopmentStartup/). This will skip start menus and jump right into a game. ### Accessing The Debug/Test Menu From 7d32a731c1d405cef790f1aed925c4b5249327c7 Mon Sep 17 00:00:00 2001 From: Hamunii Date: Sun, 11 Feb 2024 17:16:49 +0200 Subject: [PATCH 06/12] Mention DevTools --- docs/dev/mod-testing-tips.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/dev/mod-testing-tips.md b/docs/dev/mod-testing-tips.md index 6e4db0a7fc4..92d6ccb6e97 100644 --- a/docs/dev/mod-testing-tips.md +++ b/docs/dev/mod-testing-tips.md @@ -22,10 +22,12 @@ For entering a game as soon as possible, we can use [DevelopmentStartup](https:/ ### Accessing The Debug/Test Menu -We can use [LethalDevMode](https://thunderstore.io/c/lethal-company/p/megumin/LethalDevMode/) to get access to the game's internal debug tools menu. This allows us to do the following: +We can use [DevTools](https://thunderstore.io/c/lethal-company/p/Hamunii/DevTools/) or [LethalDevMode](https://thunderstore.io/c/lethal-company/p/megumin/LethalDevMode/) to get access to the game's internal debug tools menu. This allows us to do the following: - Toggle a testing level without having to land your ship. - Toggle invincibility. - Spawning enemies. - Spawning items. -![Screenshot: Toggle Testing Room](/images/mod-testing-tips/DebugToggleTestRoom.png) \ No newline at end of file +![Screenshot: Toggle Testing Room](/images/mod-testing-tips/DebugToggleTestRoom.png) + +[DevTools](https://thunderstore.io/c/lethal-company/p/Hamunii/DevTools/) can also enable the testing level automatically as soon as you load into a game and even teleport you outside of the ship! You can also use it to automate spawning an enemy and giving yourself an item, and more! \ No newline at end of file From 8a710c566a44d98c2a4a2d329980851ac4fc403a Mon Sep 17 00:00:00 2001 From: Hamunii Date: Sun, 11 Feb 2024 17:50:37 +0200 Subject: [PATCH 07/12] more neutral description of DevTools --- docs/dev/mod-testing-tips.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/dev/mod-testing-tips.md b/docs/dev/mod-testing-tips.md index 92d6ccb6e97..c8712a7998e 100644 --- a/docs/dev/mod-testing-tips.md +++ b/docs/dev/mod-testing-tips.md @@ -30,4 +30,4 @@ We can use [DevTools](https://thunderstore.io/c/lethal-company/p/Hamunii/DevTool ![Screenshot: Toggle Testing Room](/images/mod-testing-tips/DebugToggleTestRoom.png) -[DevTools](https://thunderstore.io/c/lethal-company/p/Hamunii/DevTools/) can also enable the testing level automatically as soon as you load into a game and even teleport you outside of the ship! You can also use it to automate spawning an enemy and giving yourself an item, and more! \ No newline at end of file +[DevTools](https://thunderstore.io/c/lethal-company/p/Hamunii/DevTools/) can also automatically enable the testing level, teleport you outside of the ship, spawn an enemy, give yourself an item, and activate certain cheats. \ No newline at end of file From 4520828f9ec0731589cd203b13445e12a923ec23 Mon Sep 17 00:00:00 2001 From: Owen <48495634+Owen3H@users.noreply.github.com> Date: Sun, 11 Feb 2024 23:27:43 +0000 Subject: [PATCH 08/12] Add CSync page (#95) --- docs/.vitepress/config.mts | 10 +- docs/dev/apis/csync.md | 33 +++++ docs/dev/apis/csync/troubleshooting.md | 47 ++++++++ docs/dev/apis/csync/usage-guide.md | 160 +++++++++++++++++++++++++ docs/dev/apis/overview.md | 4 +- 5 files changed, 252 insertions(+), 2 deletions(-) create mode 100644 docs/dev/apis/csync.md create mode 100644 docs/dev/apis/csync/troubleshooting.md create mode 100644 docs/dev/apis/csync/usage-guide.md diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 820c987888c..438cbd5d84a 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -133,7 +133,15 @@ export default defineConfig({ { text: 'Coding Our AI', link: '/dev/apis/lethallib/custom-enemies/coding-ai'}, ] }, - + { + text: 'CSync', + link: '/dev/apis/csync', + collapsed: true, + items: [ + { text: 'Usage Guide', link: '/dev/apis/csync/usage-guide' }, + { text: 'Troubleshooting', link: '/dev/apis/csync/troubleshooting' } + ] + }, ] }, { diff --git a/docs/dev/apis/csync.md b/docs/dev/apis/csync.md new file mode 100644 index 00000000000..b74d0a82d4b --- /dev/null +++ b/docs/dev/apis/csync.md @@ -0,0 +1,33 @@ +--- +prev: false +next: false +description: A guide to synchronizing a BepInEx config file between host and clients using the CSync library. +--- + +# CSync (Config Syncing Library) + +## Setup +There are two ways to depend upon **CSync**, but I recommend using the [NuGet package](https://www.nuget.org/packages/Owen3H.BepInEx.CSync).
+This will automatically include both an assembly reference and documentation as opposed to Thunderstore. + +### NuGet (Recommended) +**1**. Open the terminal in Visual Studio.
+**2**. Run the following command. +```console +dotnet add package Owen3H.BepInEx.CSync +``` + +Alternatively, you can install it visually via the **NuGet** package manager. + +**1**. Head to `Project > Manage NuGet Packages`.
+**2**. Search and select the `Owen3H.BepInEx.CSync` package.
+**3**. Choose the latest version and hit Install. + +### Thunderstore (Manual) +**1**. Download the latest version of the library on the [Thunderstore page](https://thunderstore.io/c/lethal-company/p/Owen3H/CSync/).
+**2**. Extract the zip into your game directory root.
+**3**. In your mod's project, add an **Assembly Reference** to `../BepInEx/plugins/CSync.dll`. + +## Overview +- [Usage Guide](/dev/apis/csync/usage-guide) - The guide/tutorial to using this library. +- [Troubleshooting](/dev/apis/csync/troubleshooting) - Common issues and their solutions. \ No newline at end of file diff --git a/docs/dev/apis/csync/troubleshooting.md b/docs/dev/apis/csync/troubleshooting.md new file mode 100644 index 00000000000..6de67a2ec31 --- /dev/null +++ b/docs/dev/apis/csync/troubleshooting.md @@ -0,0 +1,47 @@ +--- +prev: true +next: false +description: Troubleshooting section for problems using CSync. +--- + +# Troubleshooting +This page is intended to answer common questions and address frequently encountered issues.
+If you encounter an issue that isn't here, please report it within the [CSync forum](https://discord.com/channels/1168655651455639582/1199756974368227439) in the modding discord. + +## Syncing doesn't work when I patch manually. + +If you're using `PatchAll()` with type parameters, make sure to patch the `Config` class like other files.
+Example: +```cs +harmony.PatchAll(typeof(StartMatchLeverPatch)); +harmony.PatchAll(typeof(GameNetworkManagerPatch)); +harmony.PatchAll(typeof(Config)); // [!code ++] +``` + +## I am not seeing any logs from the request/receiver methods? + +Harmony may refuse to patch the `InitializeLocalPlayer` method inside `Config.cs` if you have already have a dedicated patch file for `PlayerControllerB`. You can try placing the method there instead. +```cs +[HarmonyPatch(typeof(PlayerControllerB))] +internal class PlayerControllerBPatch { + [HarmonyPostfix] + [HarmonyPatch("ConnectClientToPlayerObject")] + public static void InitializeLocalPlayer() { + if (Config.IsHost) { + try { + Config.MessageManager.RegisterNamedMessageHandler($"{PluginInfo.PLUGIN_GUID}_OnRequestConfigSync", Config.OnRequestSync); + Config.Synced = true; + } + catch (Exception e) { + Plugin.Logger.LogError(e); + } + + return; + } + + Config.Synced = false; + Config.MessageManager.RegisterNamedMessageHandler($"{PluginInfo.PLUGIN_GUID}_OnReceiveConfigSync", Config.OnReceiveSync); + Config.RequestSync(); + } +} +``` \ No newline at end of file diff --git a/docs/dev/apis/csync/usage-guide.md b/docs/dev/apis/csync/usage-guide.md new file mode 100644 index 00000000000..b054c9242bb --- /dev/null +++ b/docs/dev/apis/csync/usage-guide.md @@ -0,0 +1,160 @@ +--- +prev: false +next: true +description: The main guide to using CSync. +--- + +# Guide to using CSync + +## 1. Creating a serializable config class +To begin, we will create a new class that will inherit from `SyncedInstance`.
+We must then add the `[DataContract]` attribute for this to be synced with clients. + +```cs +[DataContract] +public class Config : SyncedInstance +``` + +Within this class, we can now begin writing out our config entries that we want to sync.
+We must also mark them with the `[DataMember]` attribute for the serializer to recognize them. + +```cs +[DataContract] +public class Config : SyncedInstance { + public ConfigEntry DISPLAY_DEBUG_INFO { get; private set; } + + [DataMember] public SyncedEntry MOVEMENT_SPEED { get; private set; } + [DataMember] public SyncedEntry CLIMB_SPEED { get; private set; } +} +``` + +::: warning +When using client side and synced entries in the same class, any instance of `ConfigEntry` should **NOT** be marked with `[DataMember]` to avoid BepInEx runtime errors. +::: + +## 2. Binding config entries +Before binding, we will add the following line at the top of the constructor. +```cs +InitInstance(this); +``` + +We can now bind our entries to the **BepInEx** config file like usual, however we will use the dedicated `BindSyncedEntry` extension method provided by **CSync**. + +```cs +public Config(ConfigFile cfg) { + InitInstance(this); + + MOVEMENT_SPEED = cfg.BindSyncedEntry("Movement", "fMovementSpeed", 4.1f, + "The base speed at which the player moves. This is NOT a multiplier." + ); + + CLIMB_SPEED = cfg.BindSyncedEntry("Movement", "fClimbSpeed", 3.9f, + "The base speed at which the player climbs. This is NOT a multiplier." + ); +} +``` + +## 3. Adding synchronization methods +We will now place the following methods within the class, making sure to replace `PluginInfo.PLUGIN_GUID` if it is defined elsewhere. + +::: warning +If you specify a GUID that is not unique, your mod will conflict with other mods that use **CSync**. +::: + +```cs +internal static void RequestSync() { + if (!IsClient) return; + + using FastBufferWriter stream = new(IntSize, Allocator.Temp); + + // Method `OnRequestSync` will then get called on host. + stream.SendMessage($"{PluginInfo.PLUGIN_GUID}_OnRequestConfigSync"); +} + +internal static void OnRequestSync(ulong clientId, FastBufferReader _) { + if (!IsHost) return; + + byte[] array = SerializeToBytes(Instance); + int value = array.Length; + + using FastBufferWriter stream = new(value + IntSize, Allocator.Temp); + + try { + stream.WriteValueSafe(in value, default); + stream.WriteBytesSafe(array); + + stream.SendMessage($"{PluginInfo.PLUGIN_GUID}_OnReceiveConfigSync", clientId); + } catch(Exception e) { + Plugin.Logger.LogError($"Error occurred syncing config with client: {clientId}\n{e}"); + } +} + +internal static void OnReceiveSync(ulong _, FastBufferReader reader) { + if (!reader.TryBeginRead(IntSize)) { + Plugin.Logger.LogError("Config sync error: Could not begin reading buffer."); + return; + } + + reader.ReadValueSafe(out int val, default); + if (!reader.TryBeginRead(val)) { + Plugin.Logger.LogError("Config sync error: Host could not sync."); + return; + } + + byte[] data = new byte[val]; + reader.ReadBytesSafe(ref data, val); + + try { + SyncInstance(data); + } catch(Exception e) { + Plugin.Logger.LogError($"Error syncing config instance!\n{e}"); + } +} +``` + +## 4. Apply Harmony patches +Add in the following method and make sure the GUID is defined just like the previous step. + +```cs +[HarmonyPostfix] +[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] +public static void InitializeLocalPlayer() { + if (IsHost) { + MessageManager.RegisterNamedMessageHandler($"{PluginInfo.PLUGIN_GUID}_OnRequestConfigSync", OnRequestSync); + Synced = true; + + return; + } + + Synced = false; + MessageManager.RegisterNamedMessageHandler($"{PluginInfo.PLUGIN_GUID}_OnReceiveConfigSync", OnReceiveSync); + RequestSync(); +} +``` + +Finally, we need to make sure the client reverts back to their own config upon leaving. + +```cs +[HarmonyPostfix] +[HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")] +public static void PlayerLeave() { + Config.RevertSync(); +} +``` + +# Finalizing and Publishing +It is recommended you inform **BepInEx** that you depend upon **CSync**.
+You can do this by adding a `BepInDependency` attribute and specifying the GUID of this library. + +```cs +[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)] +[BepInDependency("io.github.CSync")] // [!code ++] +public class MyPlugin : BaseUnityPlugin +``` + +If you plan to upload your mod to **Thunderstore**, make sure you also specify the dependency within your `manifest.json` file by adding its **Thunderstore** ID to the array. +```json +"dependencies": ["BepInEx-BepInExPack-5.4.2100", "Owen3H-CSync-1.0.7"] +``` + +**NOTE**: Please ensure your manifest contains the latest version, the one seen above may be outdated! \ No newline at end of file diff --git a/docs/dev/apis/overview.md b/docs/dev/apis/overview.md index 2286fe2ae3e..b99da3c0273 100644 --- a/docs/dev/apis/overview.md +++ b/docs/dev/apis/overview.md @@ -36,7 +36,9 @@ APIs marked with a `Gold Star ⭐` have a tutorial on this wiki. ## Programming APIs ### Configuration -- [ConfigurableCompany by Ansuz/Amrv](https://thunderstore.io/c/lethal-company/p/AMRV/ConfigurableCompany/) implements an in-game menu that allows developers to create file-dependant configurations in a simple way that will automatically synchronize when needed. [Learn how to develop with mod](/dev/apis/configurable-company.md). +- [ConfigurableCompany by Ansuz/Amrv](https://thunderstore.io/c/lethal-company/p/AMRV/ConfigurableCompany/) implements an in-game menu that allows developers to create file-dependant configurations in a simple way that will automatically synchronize when needed. [Learn how to develop with mod](/dev/apis/configurable-company.md). + +- ⭐ [CSync by Owen3H](https://thunderstore.io/c/lethal-company/p/Owen3H/CSync/) is a compact library/API enabling mod authors to synchronize the host's configuration file with all other clients. [The wiki page on CSync](/dev/apis/csync) will guide you through the process of implementing this into your own mod. ### Dungeons - [LethalLib by Evaisa](https://thunderstore.io/c/lethal-company/p/Evaisa/LethalLib/) allows you to add new dungeons. From 2e19cd7cb5e13379f30a620fd0024ef9ff58b76e Mon Sep 17 00:00:00 2001 From: Owen <48495634+Owen3H@users.noreply.github.com> Date: Mon, 12 Feb 2024 15:24:25 +0000 Subject: [PATCH 09/12] FIX CSYNC SECTION (#98) * FIX CSYNC SECTION * cuppa changes --- docs/.vitepress/config.mts | 20 ++++++++++---------- docs/dev/apis/csync/usage-guide.md | 8 +++++--- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 438cbd5d84a..9557c416249 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -133,15 +133,6 @@ export default defineConfig({ { text: 'Coding Our AI', link: '/dev/apis/lethallib/custom-enemies/coding-ai'}, ] }, - { - text: 'CSync', - link: '/dev/apis/csync', - collapsed: true, - items: [ - { text: 'Usage Guide', link: '/dev/apis/csync/usage-guide' }, - { text: 'Troubleshooting', link: '/dev/apis/csync/troubleshooting' } - ] - }, ] }, { @@ -166,7 +157,16 @@ export default defineConfig({ link: '/dev/apis/configurable-company/event-listening' } ] - } + }, + { + text: 'CSync', + link: '/dev/apis/csync', + collapsed: true, + items: [ + { text: 'Usage Guide', link: '/dev/apis/csync/usage-guide' }, + { text: 'Troubleshooting', link: '/dev/apis/csync/troubleshooting' } + ] + }, ] } ] diff --git a/docs/dev/apis/csync/usage-guide.md b/docs/dev/apis/csync/usage-guide.md index b054c9242bb..89fde3563cb 100644 --- a/docs/dev/apis/csync/usage-guide.md +++ b/docs/dev/apis/csync/usage-guide.md @@ -142,7 +142,7 @@ public static void PlayerLeave() { } ``` -# Finalizing and Publishing +## Finalizing and Publishing It is recommended you inform **BepInEx** that you depend upon **CSync**.
You can do this by adding a `BepInDependency` attribute and specifying the GUID of this library. @@ -154,7 +154,9 @@ public class MyPlugin : BaseUnityPlugin If you plan to upload your mod to **Thunderstore**, make sure you also specify the dependency within your `manifest.json` file by adding its **Thunderstore** ID to the array. ```json -"dependencies": ["BepInEx-BepInExPack-5.4.2100", "Owen3H-CSync-1.0.7"] +"dependencies": ["BepInEx-BepInExPack-5.4.2100", "Owen3H-CSync-1.0.8"] ``` -**NOTE**: Please ensure your manifest contains the latest version, the one seen above may be outdated! \ No newline at end of file +::: info NOTE +Please ensure your manifest contains the latest version, the one seen above may be outdated! +::: \ No newline at end of file From 292dd5147db2252578c3210a3a822b4f93f2a7b4 Mon Sep 17 00:00:00 2001 From: Joe Clack <28568841+Lordfirespeed@users.noreply.github.com> Date: Fri, 16 Feb 2024 23:52:19 +0000 Subject: [PATCH 10/12] update recommended GitHub template (#93) --- docs/dev/starting-a-mod.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/dev/starting-a-mod.md b/docs/dev/starting-a-mod.md index 14be468816e..aa79dc010e4 100644 --- a/docs/dev/starting-a-mod.md +++ b/docs/dev/starting-a-mod.md @@ -14,8 +14,15 @@ This guide assumes you've completed all the required steps in **[initial setup]( This guide follows certain parts of the [official BepInEx guide](https://docs.bepinex.dev/articles/dev_guide/plugin_tutorial/2_plugin_start.html). ### Using the template repository {#using-template-repo} +::: danger Outdated Template +The linked GitHub template repository may be **stale**. Refer to the Lethal Company Modding Discord server if you encounter issues using it. +::: + +[Distractic's template](https://github.com/Distractic/LethalCompanyTemplate) is the current recommended GitHub template. +If you're remotely familiar with GitHub, or willing to [learn](/dev/initial-setup#creating-a-github-account), this might serve as a quick start. +It does come with some minor drawbacks such as it using "LethalCompanyTemplate" as project name in a number of files; however, it should build out-of-the-box with no edits required. -We have created a [template repository](https://github.com/LethalCompany/LethalCompanyTemplate) on GitHub. If you're remotely familiar with GitHub, or willing to [learn](/dev/initial-setup#creating-a-github-account), this might serve as a quick start. It does come with some minor drawbacks such as it using "LethalCompanyTemplate" as project name in a number of files, but you can edit this. It should build out-of-the-box with no edits required; though you may need to add BepInEx as a NuGet source (see the [relevant](#adding-nuget-source) section below). +It is important that you remove all unused template code from the project before distributing your mod. ### Creating your project {#create-project} @@ -184,4 +191,4 @@ Check our list of tips for improving your modding workflow on [Mod Testing Tips] We also recommend reading through our very short guide on [open-source & ethics](/dev/open-source-and-ethics), to help foster a healthy modding community. -Once you've finished a mod, you can [publish it](/dev/publishing-your-mod). \ No newline at end of file +Once you've finished a mod, you can [publish it](/dev/publishing-your-mod). From 1037a624b4f9046579972a6ac4733b57b6c3286e Mon Sep 17 00:00:00 2001 From: Joe Clack <28568841+Lordfirespeed@users.noreply.github.com> Date: Thu, 22 Feb 2024 00:54:58 +0000 Subject: [PATCH 11/12] tempfix the netcode patcher instructions (#102) --- docs/dev/advanced/networking.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/dev/advanced/networking.md b/docs/dev/advanced/networking.md index 259377a9cd4..17800706cce 100644 --- a/docs/dev/advanced/networking.md +++ b/docs/dev/advanced/networking.md @@ -432,7 +432,7 @@ Hooking to a ClientRpc can cause errors with code running multiple times on the Now that we've finished the networking code, all that's left is to patch the compiled mod assembly with Unity Netcode Patcher. Before we can do so, we need to prepare the mod for patching. -1. Make sure that there is a .pdb file when you build your plugin. If it is not there, make sure that Debug Symbols is set to `Portable` and not embedded. +1. Make sure that `DebugSymbols` are set to `portable` (or `pdbonly`) or `embedded`. `Full` debug symbols **will not work** and NetcodePatcher will produce an uninterpretable error message. 2. Add the following code to your main Plugin.cs file, and make sure the method only runs **once**: @@ -460,16 +460,17 @@ static void Awake() } ``` -Before you can run Unity Netcode Patcher, make sure it's set up - specifically, copy the contents of `Lethal Company/Lethal Company_Data/Managed` into `NetcodePatcher/deps`. +Before you can run Unity Netcode Patcher, make sure it's set up - specifically, run `dotnet tool install -g Evaisa.NetcodePatcher.Cli`. -Now, you just have to add the following Post-Build Event to your project: +Now, you just have to add the following `Target` element to your `.csproj`: -```cmd -cd -NetcodePatcher.dll $(TargetDir) deps/ +```xml + + + ``` -If this does not work, you can [follow the instructions on how to use Unity Netcode Patcher from the command line.](https://github.com/EvaisaDev/UnityNetcodePatcher#usage-from-command-line) +If this does not work, you can [follow the instructions on how to use Unity Netcode Patcher.](https://github.com/EvaisaDev/UnityNetcodePatcher#usage-from-command-line) ## Conclusion From edd57746cecde3ac1dcd4138bedf68b3c25fbb60 Mon Sep 17 00:00:00 2001 From: Mae Date: Mon, 26 Feb 2024 20:28:40 -0800 Subject: [PATCH 12/12] Removed the warning agaisnt netcode variables. (#103) They are needed. It is a terrible idea to not enable them when making scrap like the clown horn, because they will not sync if you don't touch the netcode variables. --- docs/dev/apis/lethallib/customscrap.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/dev/apis/lethallib/customscrap.md b/docs/dev/apis/lethallib/customscrap.md index c094d7344cc..c2cce2fcdf3 100644 --- a/docs/dev/apis/lethallib/customscrap.md +++ b/docs/dev/apis/lethallib/customscrap.md @@ -34,7 +34,9 @@ This item data lets you configure basically everything about your item. There ar - **Allow Dropping Ahead of Player**: Whether the item can be dropped in front of the player, as opposed to only dropping directly below their feet. - **Is Defensive Weapon**: For scrap that also acts as weapons; requires more special scripting, so for most cases should be left off. -Everything else is optional, has no effect on scrap, or shouldn't be modified (e.g. Netcode variables should be left alone). +Everything else is optional, has no effect on scrap, or shouldn't be modified. + +Note that you will have to enable some of the netcode variables if you want them to sync properly in multiplayer. ## Item Prefab An item prefab needs to have a specific setup to work correctly with all the Lethal Company systems. The prefab should have only the root object and a child object called "ScanNode":