# 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