# MAPI Documentation //Someone add a brief description of the MAPI and links to it here. -Swept [Precompiled 0MultiplayerAPI.dll](https://www.nuget.org/packages/RimWorld.MultiplayerAPI/) ### A Small Example In this section, we're going to focus on the basics of the api. Specifically, we're going to enable a mod for Multiplayer. #### The boilerplate By the time RimWorld reaches your mod the API is ready to use, you can call it wherever you see fit. See basic C# mod tutorials. The easiest place is `[StaticConstructorOnStartup]` The following is the most basic boilerplate code. ```csharp= using Multiplayer.API; using Verse; namespace MyExampleMod { [StaticConstructorOnStartup] public static class MyExampleModCompat { static MyExampleModCompat() { if (!MP.enabled) return; // This is where the magic happens and your attributes // auto register, similar to Harmony's PatchAll. MP.RegisterAll(); // You can choose to not auto register and do it manually // with the MP.Register* methods. // Use MP.IsInMultiplayer to act upon it in other places // user can have it enabled and not be in session } } } ``` That's all! You are done. ### More Examples The [Multiplayer Compatibility Project](https://github.com/notfood/RimWorld-Multiplayer-Compatibility) ### Fields Well... sometimes you aren't that lucky. Sometimes you want to change a specific Field. For those scenarios there is the `MP.Watch*` methods. Basically, at the beginning of the operation you take a snapshot of the Field value and then compare it later. MPAPI checks them if they need to broadcast it and then spreads the change accordingly. ```csharp= ... [HarmonyPatch(typeof(RimWorldWindowClass), nameof(DoWindowContents))] static class RimWorldWindowClass_DoWindowContents_Patch { // Draw a 160x16 slider in RimWorldWindowClass static void Postfix(Rect inRect) { if (MP.IsInMultiplayer) { MP.WatchBegin(); // Let's being watching // This is here to set the variable if it changed on other clients // It will update the variable and the logic will stay the same. MP.Watch(instance, nameof(instance.weight)); } Rect sliderRect = new Rect(inRect.x, inRect.y, 160f, 16f); instance.weight = GUI.HorizontalSlider(sliderRect, instance.weight, -10f, 10f); if (MP.IsInMultiplayer) { MP.WatchEnd(); // We are done watching! } } static MyObject instance = new MyObject(); class MyObject { [SyncField] public float weight; } } ... ``` That's all! So easy! Is it? ### Gizmos Oh dear! Oh deity no no--- NO- Pray you aren't dealing with them with Reflection. See the Examples for dark magic. But if it's your own code, just move the Action delegate to a method anywhere and tag it with `[SyncMethod]`. ### Sync Workers Sometimes, when you use [SyncMethod], you will encounter... ``` Error writing type: MyType, ... Multiplayer.Client.SerializationException: No writer for type MyType ``` MPAPI needs to know how to reference your type to send it to the other clients. Basically if you have... ```csharp= [SyncMethod] static MyReturnType MyMethod(MyArgumentType arg1, MyArgumentType2 arg2, int arg3, float arg4) { ... } ``` You need to teach MPApi to handle your types, so they can send them over the wire to the other players. For our example, we will need to write a SyncWorker for `MyReturnType`, `MyArgumentType` and `MyArgumentType2`, most of RimWorld types are already handled so don't be afraid to use them. Assuming `MyReturnType` is made of `aString`, `anInt` and `aFloat`, here is how you write a SyncWorker for it: ```csharp= [SyncWorker(shouldConstruct = true)] static void SyncMyReturnType(SyncWorker sync, ref MyReturnType type) { sync.Bind(type.aString); sync.Bind(type.anInt); sync.Bind(type.aFloat); } ``` Bind does the writing and reading for you, `shouldConstruct` makes it so type is constructed before being passed to the SyncWorker (not needed for structs). But if you need more complex situations, you can use Write and Read. Assuming `MyArgumentType` requires an argument `Pawn` to construct, you'd write it this way: ```csharp= [SyncWorker] static void SyncMyArgumentType(SyncWorker sync, ref MyArgumentType type) { if (sync.isWriting) { sync.Write(type.Pawn); } else { Pawn pawn = sync.Read<Pawn>(); type = new MyArgumentType(pawn); } } ``` *Todo migrate the rest of the API doc https://github.com/Parexy/Multiplayer/wiki/API#mp