public CorpseBloomPlusPlus() { var miniRpc = MiniRpc.CreateInstance(modGuid); updateReserveCommand = miniRpc.RegisterAction(Target.Client, (NetworkUser user, CorpseReserve cr) => { if (cr != null) { currentReserve = cr.currentReserve; reserveMax = cr.maxReserve; //Debug.Log($"CR: {currentReserve}; MR: {reserveMax};"); } }); //This is to fix severe desync when a modded server communicates with a vanilla client. Ping the client and check for response before we send updates. clientPingCheck = miniRpc.RegisterFunc <bool, bool>(Target.Client, (user, x) => { Debug.Log($"[Client] HOST sent us: {x}, returning true"); return(true); //return $"Hello from the server, received {x}!"; }); }
public MiniRpcDemo() { // Create a MiniRpcInstance that automatically registers all commands to our ModGuid // This lets us support multiple mods using the same command ID // We could also just generate new command ID's without "isolating" them by mod as well, so it would break if mod load order was different for different clients // I opted for the ModGuid instead of an arbitrary number or GUID to encourage mods not to set the same ID var miniRpc = MiniRpc.CreateInstance(ModGuid); // Define two commands, both transmitting a single string ExampleCommandHost = miniRpc.RegisterAction(Target.Server, (NetworkUser user, string x) => Debug.Log($"[Host] {user?.userName} sent us: {x}")); ExampleCommandClient = miniRpc.RegisterAction(Target.Client, (NetworkUser user, string x) => Debug.Log($"[Client] Host sent us: {x}")); // Define two commands, both deserializing the data themselves // This command will be called by a client (including the host), and executed on the server (host) ExampleCommandHostCustom = miniRpc.RegisterAction(Target.Server, (user, x) => { // This is what the server will execute when a client invokes the IRpcAction var str = x.ReadString(); var int32 = x.ReadInt32(); Debug.Log($"[Host] {user?.userName} sent us: {str} {int32}"); }); // This command will be called by the host, and executed on all clients ExampleCommandClientCustom = miniRpc.RegisterAction(Target.Client, (user, x) => { // This is what all clients will execute when the server invokes the IRpcAction var str = x.ReadString(); var int32 = x.ReadInt32(); Debug.Log($"[Client] Host sent us: {str} {int32}"); }); // Here's three examples of RegisterFunc, where you also need to return a value to the caller ExampleFuncHost = miniRpc.RegisterFunc <bool, string>(Target.Server, (user, x) => { Debug.Log($"[Host] {user?.userName} sent us: {x}"); return($"Hello from the server, received {x}!"); }); ExampleFuncClient = miniRpc.RegisterFunc <bool, string>(Target.Client, (user, x) => { Debug.Log($"[Client] Host sent us: {x}"); return($"Hello from the client, received {x}!"); }); ExampleFuncClientObject = miniRpc.RegisterFunc(Target.Client, (NetworkUser user, ExampleObject obj) => { Debug.Log($"[Client] Host sent us: {obj}"); obj.StringExample = "Edited client-side!"; return(obj); }); // By default, MiniRpcLib will create an ID based on the registration order (first command is ID 0, second command is ID 1, and so on // If you want to specify an ID manually, you can choose to do so by doing either of these: // // RpcActions and RpcFuncs have separate IDs, so both an RpcFunc and an RpcAction can have the same ID without collisions. // That said, there's nothing stopping you from using the same Enum for both, as all ID values are valid. // (1, 2, 3 being Actions, 4 being a Func, 5 being an action again and so on is okay and valid) _ = miniRpc.RegisterFunc(Target.Client, (NetworkUser user, ExampleObject obj) => { Debug.Log($"[Client] Host sent us: {obj}"); obj.StringExample = "Edited client-side!"; return(obj); }, 1234); // <-- Optional ID _ = miniRpc.RegisterFunc(Target.Client, (NetworkUser user, ExampleObject obj) => { Debug.Log($"[Client] Host sent us: {obj}"); obj.StringExample = "Edited client-side!"; return(obj); }, CommandId.SomeCommandName); // <-- Optional ID // The "_ ="'s above mean that the return value will be ignored. In your code you should assign the return value to something to be able to call the function. }
private void RegisterMiniRpcCMDs(MiniRpcInstance miniRpc) { // This command will be called by a client (including the host), and executed on the server (host) ExampleCommandHostCustom = miniRpc.RegisterAction(Target.Server, (user, x) => { // This is what the server will execute when a client invokes the IRpcAction var str = x.ReadString(); Debug.Log($"[Host] {user?.userName} sent us: {str}"); if (str == "Buymenu") { //Get a user id, starts from 0 List <NetworkUser> instancesList = typeof(NetworkUser).GetFieldValue <List <NetworkUser> >("instancesList"); int id = instancesList.IndexOf(user); if (id < 0) { return; } //When the id is bigger than the count add items, with a default value of false if (AllBuyMenuStates.Count - 1 < id) { for (int i = AllBuyMenuStates.Count - 1; i < id; i++) { AllBuyMenuStates.Add(false); } } //Didnt work with Boolean ... var doubleVal = x.ReadDouble(); //Workaround bool state = doubleVal == 0.0 ? false : true; AllBuyMenuStates[id] = state; //Check if any one has the select menu open int check = AllBuyMenuStates.FindAll(a => a == true).Count; Debug.Log(check); //If at least one has it opened set the Timescale to the config one //Else set it back to 1.0 if (check > 0) { ExampleCommandClientCustom.Invoke(y => { y.Write("Timescale"); //Convert to double y.Write((double)config.TimeScale); }); } else { ExampleCommandClientCustom.Invoke(y => { y.Write("Timescale"); y.Write(1.0); }); } } if (str == "CreatePickupDroplet_Item") { ItemIndex item = x.ReadItemIndex(); PickupIndex pickupIndex = new PickupIndex(item); Transform chestTransform = x.ReadTransform(); Vector3 pos = chestTransform.position; Vector3 forward = chestTransform.position; RoR2.PickupDropletController.CreatePickupDroplet(pickupIndex, pos + Vector3.up * 1.5f, Vector3.up * 20f + forward * 2f); } if (str == "CreatePickupDroplet_Equipment") { EquipmentIndex item = x.ReadEquipmentIndex(); PickupIndex pickupIndex = new PickupIndex(item); Transform chestTransform = x.ReadTransform(); Vector3 pos = chestTransform.position; Vector3 forward = chestTransform.position; RoR2.PickupDropletController.CreatePickupDroplet(pickupIndex, pos + Vector3.up * 1.5f, Vector3.up * 20f + forward * 2f); } }); // This command will be called by the host, and executed on all clients ExampleCommandClientCustom = miniRpc.RegisterAction(Target.Client, (user, x) => { // This is what all clients will execute when the server invokes the IRpcAction var str = x.ReadString(); Debug.Log($"[Client] Host sent us: {str}"); if (str == "Reset") { bool everything_Avaiable = x.ReadBoolean(); Debug.Log("BOOL TEST:" + everything_Avaiable); playerCharacterMaster = null; //Get the local player if (this.playerCharacterMaster == null) { this.playerCharacterMaster = LocalUserManager.GetFirstLocalUser().cachedMasterController; } //If the local player isnt setup yet, set him up if (this.playerCharacterMaster.GetComponent <CA_PlayerScript>() == null) { this.playerCharacterMaster.gameObject.AddComponent <CA_PlayerScript>(); this.playerCharacterMaster.gameObject.GetComponent <CA_PlayerScript>().ExampleCommandHostCustom = this.ExampleCommandHostCustom; this.playerCharacterMaster.gameObject.GetComponent <CA_PlayerScript>().config = config; this.playerCharacterMaster.gameObject.GetComponent <CA_PlayerScript>().Everything_Avaiable = everything_Avaiable; this.playerCharacterMaster.gameObject.GetComponent <CA_PlayerScript>().AwakeManual(); } } if (str == "Chest") { //Get transfered variables GameObject interactor = x.ReadGameObject(); Transform transform = x.ReadTransform(); double tier = x.ReadDouble(); CA_PlayerScript playerScript = this.playerCharacterMaster.gameObject.GetComponent <CA_PlayerScript>(); //Check the player that opened the chest is correctly setup if (!playerScript) { return; } GameObject activator = interactor.GetComponent <CharacterBody>().gameObject; GameObject thisGO = this.playerCharacterMaster.master.GetBody().gameObject; //Check if this local player is the one that opened the chest if (activator != thisGO) { return; } // RNG Value was above specified percantage values // Cancel the drop if ((int)tier == 0) { Chat.AddMessage("Mhh Unlucky you found nothing in this Chest."); return; } //Add the items to the UI and Unhide the SelectMenu playerScript.AddTierToGUI((int)tier, transform); playerScript.SetBuyMenu(true); return; } if (str == "Timescale") { var floatVal = (float)x.ReadDouble(); Time.timeScale = floatVal; } }); // -1 = Error/Not Same || 1 = Same but not idling || 0 = Same and idling ExampleFuncClient = miniRpc.RegisterFunc <GameObject, int>(Target.Client, (user, activator) => { CA_PlayerScript playerScript = this.playerCharacterMaster.gameObject.GetComponent <CA_PlayerScript>(); Debug.Log(playerScript != null); if (!playerScript) { return(-1); } GameObject activatorGO = activator.GetComponent <CharacterBody>().gameObject; GameObject thisGO = this.playerCharacterMaster.master.GetBody().gameObject; Debug.Log(activatorGO == thisGO); if (activatorGO != thisGO) { return(-1); } Debug.Log(playerScript.isChestOpening); if (playerScript.isChestOpening) { return(1); } return(0); }); }
private void SetUpMiniRPC() { // Fix the damn in-game console stealing our not-in-game consoles output. // Not related to the demo, just very useful. //On.RoR2.RoR2Application.UnitySystemConsoleRedirector.Redirect += orig => { }; // Create a MiniRpcInstance that automatically registers all commands to our ModGuid // This lets us support multiple mods using the same command ID // We could also just generate new command ID's without "isolating" them by mod as well, so it would break if mod load order was different for different clients // I opted for the ModGuid instead of an arbitrary number or GUID to encourage mods not to set the same ID var miniRpc = MiniRpc.CreateInstance(ModGuid); AddGainedItemsToPlayers = miniRpc.RegisterFunc(Target.Client, (NetworkUser user, string QueueGainedItemSpriteToString) => //--------------------HierSTuffMachen!! { if (!ArtifactOfDoomConfig.disableSideBars.Value) { string[] QueueGainedItemSprite = QueueGainedItemSpriteToString.Split(' '); int i = 0; foreach (var element in QueueGainedItemSprite) { if (element != "") { if (ArtifactOfDoomUI.listGainedImages[i].GetComponent <Image>() == null) { ArtifactOfDoomUI.listGainedImages[i].AddComponent <Image>(); } ArtifactOfDoomUI.listGainedImages[i].GetComponent <Image>().sprite = ItemCatalog.GetItemDef(ItemCatalog.FindItemIndex(element)).pickupIconSprite; i++; } } } return("dummie"); }); AddLostItemsOfPlayers = miniRpc.RegisterFunc(Target.Client, (NetworkUser user, string QueueLostItemSpriteToString) => //--------------------HierSTuffMachen!! { if (!ArtifactOfDoomConfig.disableSideBars.Value) { string[] QueueLostItemSprite = QueueLostItemSpriteToString.Split(' '); int i = 0; foreach (var element in QueueLostItemSprite) { if (element != "") { if (ArtifactOfDoomUI.listLostImages[i].GetComponent <Image>() == null) { ArtifactOfDoomUI.listLostImages[i].AddComponent <Image>(); } ArtifactOfDoomUI.listLostImages[i].GetComponent <Image>().sprite = ItemCatalog.GetItemDef(ItemCatalog.FindItemIndex(element)).pickupIconSprite; i++; } } } return("dummie"); }); UpdateProgressBar = miniRpc.RegisterFunc(Target.Client, (NetworkUser user, string killedNeededEnemies) => //--------------------HierSTuffMachen!! { //Debug.LogWarning("in UpdateProgressBar"); //Debug.LogError("ArtifactOfDoomConfig.disableItemProgressBar.Value"+ ArtifactOfDoomConfig.disableItemProgressBar.Value); //Debug.LogError("ArtifactOfDoomConfig.useArtifactOfSacreficeCalculation.Value"+ ArtifactOfDoomConfig.useArtifactOfSacreficeCalculation.Value); if (ArtifactOfDoomConfig.disableItemProgressBar.Value || calculationSacrifice) { return("Disabled Progress Bar"); } if (killedNeededEnemies == null) { Debug.Log("killedNeededEnemies == null"); return("error"); } //Debug.LogWarning("string killedNeededEnemies für rpc: " + killedNeededEnemies); string[] stringkilledNeededEnemies = killedNeededEnemies.Split(','); //Debug.LogError("in line 276"); if (stringkilledNeededEnemies == null) { Debug.LogError("stringkilledneededEnemies=null"); } int enemiesKilled = Convert.ToInt32(stringkilledNeededEnemies[0]); int enemiesNeeded = Convert.ToInt32(stringkilledNeededEnemies[1]) + 2; //Debug.LogError("in line 279"); if (itemGainBar == null) { return("error"); } double progress = (double)enemiesKilled / ((double)enemiesNeeded); // Debug.LogError("in line 2282"); if (itemGainBar.GetComponent <RectTransform>() == null) { return("Error while excecuting Update progress bar"); } if ((0.35f + (float)(progress * 0.3)) > 0.65f) { if (itemGainBar.GetComponent <RectTransform>().anchorMax == null) { Debug.LogError("itemGainBar.GetComponent<RectTransform>().anchorMax==null"); } itemGainBar.GetComponent <RectTransform>().anchorMax = new Vector2(0.65f, 0.06f); } else { itemGainBar.GetComponent <RectTransform>().anchorMin = new Vector2(0.35f, 0.05f); // Debug.LogError("in line 288"); itemGainBar.GetComponent <RectTransform>().anchorMax = new Vector2(0.35f + (float)(progress * 0.3), 0.06f); } return("dummie"); }); IsArtifactActive = miniRpc.RegisterFunc(Target.Client, (NetworkUser user, bool isActive) => //--------------------HierSTuffMachen!! { ArtifactIsActive = isActive; return(""); }); IsCalculationSacrifice = miniRpc.RegisterFunc(Target.Client, (NetworkUser user, bool isActive) => //--------------------HierSTuffMachen!! { //Debug.LogError("Set CalculationSacrifice to " + isActive); calculationSacrifice = isActive; return(""); }); Debug.LogWarning("minirpc succsessfull set up"); // The "_ ="'s above mean that the return value will be ignored. In your code you should assign the return value to something to be able to call the function. }