From 650853043a5ffe8596af648c2fad9acb62799297 Mon Sep 17 00:00:00 2001 From: Aly Date: Wed, 1 Jun 2022 19:24:50 -0700 Subject: [PATCH 1/4] Initial CelesteNet support --- Module/SkinModHelperCelesteNet.cs | 92 +++++++++++++++++++++++++++++ Module/SkinModHelperModule.cs | 56 ++++++++++++++++++ SkinModHelper.csproj | 6 ++ everest.yaml | 4 +- lib-stripped/CelesteNet.Client.dll | Bin 0 -> 84480 bytes lib-stripped/CelesteNet.Shared.dll | Bin 0 -> 60928 bytes 6 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 Module/SkinModHelperCelesteNet.cs create mode 100644 lib-stripped/CelesteNet.Client.dll create mode 100644 lib-stripped/CelesteNet.Shared.dll diff --git a/Module/SkinModHelperCelesteNet.cs b/Module/SkinModHelperCelesteNet.cs new file mode 100644 index 00000000..eb629d60 --- /dev/null +++ b/Module/SkinModHelperCelesteNet.cs @@ -0,0 +1,92 @@ +using Celeste.Mod.CelesteNet; +using Celeste.Mod.CelesteNet.Client; +using Celeste.Mod.CelesteNet.Client.Entities; +using Celeste.Mod.CelesteNet.DataTypes; +using MonoMod.RuntimeDetour; +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace SkinModHelper.Module +{ + + public class SkinModHelperCelesteNet + { + public static void HandleDataReady(CelesteNetConnection con, DataReady data) + { + con.Send(new SkinModHelperChange {SkinID = SkinModHelperModule.Settings.SelectedSkinMod}); + } + + private static DataHandler handleDataReady; + + public static void HandleSkinModHelperChange(CelesteNetConnection con, SkinModHelperChange data) + { + SkinModHelperModule.PlayerIDSkinMap.Add(data.ChangePlayer.ID, data.SkinID); + } + + private static DataHandler handleSkinModHelperChange; + + public static void Load() + { + CelesteNetClientContext.OnInit += clientContext => + { + CelesteNetClient client = clientContext.Client; + handleDataReady = client.Data.RegisterHandler(HandleDataReady); + handleSkinModHelperChange = client.Data.RegisterHandler(HandleSkinModHelperChange); + }; + } + + public static void Unload() + { + CelesteNetClient client = CelesteNetClientModule.Instance.Client; + if (client != null) + { + if (handleDataReady != null) + { + client.Data.UnregisterHandler(typeof(DataReady), handleDataReady); + handleDataReady = null; + } + + if (handleSkinModHelperChange != null) + { + client.Data.UnregisterHandler(typeof(SkinModHelperChange), handleSkinModHelperChange); + handleSkinModHelperChange = null; + } + } + } + } + + public class SkinModHelperChange : DataType + { + static SkinModHelperChange() + { + DataID = "skinmodhelperChange"; + } + + public DataPlayerInfo ChangePlayer; + public string SkinID; + + public override MetaType[] GenerateMeta(DataContext ctx) + { + return new MetaType[] + { + new MetaPlayerPrivateState(ChangePlayer) + }; + } + + public override void FixupMeta(DataContext ctx) + { + ChangePlayer = Get(ctx).Player; + } + + protected override void Read(CelesteNetBinaryReader reader) + { + SkinID = reader.ReadNetString(); + } + + protected override void Write(CelesteNetBinaryWriter writer) + { + writer.WriteNetString(SkinID); + } + } +} \ No newline at end of file diff --git a/Module/SkinModHelperModule.cs b/Module/SkinModHelperModule.cs index 2786f12b..ae24915c 100644 --- a/Module/SkinModHelperModule.cs +++ b/Module/SkinModHelperModule.cs @@ -1,5 +1,8 @@ using Celeste; using Celeste.Mod; +using Celeste.Mod.CelesteNet; +using Celeste.Mod.CelesteNet.Client; +using Celeste.Mod.CelesteNet.Client.Entities; using FMOD.Studio; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -10,8 +13,12 @@ using MonoMod.Utils; using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; +using System.Runtime.CompilerServices; using System.Text.RegularExpressions; +using Logger = Celeste.Mod.Logger; +using LogLevel = Celeste.Mod.LogLevel; namespace SkinModHelper.Module { @@ -33,11 +40,15 @@ public class SkinModHelperModule : EverestModule "player", "player_no_backpack", "badeline", "player_badeline", "player_playback" }; + public static Dictionary PlayerIDSkinMap; + public SkinModHelperModule() { Instance = this; UI = new SkinModHelperUI(); skinConfigs = new Dictionary(); + + PlayerIDSkinMap = new Dictionary(); } public override void Load() @@ -55,6 +66,7 @@ public override void Load() On.Celeste.Player.UpdateHair += PlayerUpdateHairHook; On.Celeste.PlayerDeadBody.Render += PlayerDeadBodyRenderHook; On.Celeste.PlayerHair.GetHairTexture += PlayerHairGetHairTextureHook; + On.Celeste.PlayerSprite.Render += PlayerSpriteRenderHook; IL.Celeste.CS06_Campfire.Question.ctor += CampfireQuestionHook; IL.Celeste.DreamBlock.ctor_Vector2_float_float_Nullable1_bool_bool_bool += DreamBlockHook; @@ -64,6 +76,8 @@ public override void Load() TextboxRunRoutineHook = new ILHook( typeof(Textbox).GetMethod("RunRoutine", BindingFlags.NonPublic | BindingFlags.Instance).GetStateMachineTarget(), SwapTextboxHook); + + SkinModHelperCelesteNet.Load(); } public override void LoadContent(bool firstLoad) @@ -95,6 +109,8 @@ public override void Unload() On.Celeste.Player.UpdateHair -= PlayerUpdateHairHook; On.Celeste.PlayerHair.GetHairTexture -= PlayerHairGetHairTextureHook; + + SkinModHelperCelesteNet.Unload(); } public override void CreateModMenuSection(TextMenu menu, bool inGame, EventInstance snapshot) @@ -270,9 +286,49 @@ private void PlayerUpdateHairHook(On.Celeste.Player.orig_UpdateHair orig, Player } } + private void PlayerSpriteRenderHook(On.Celeste.PlayerSprite.orig_Render orig, PlayerSprite self) + { + DynamicData dd = new DynamicData(self); + + if (!dd.TryGet("patchedBySkinModHelper", out object _)) + { + string spriteName = dd.Get("spriteName"); + + if (self.Entity is Ghost ghost) + { + // If the current PlayerSprite belongs to a CelesteNet Ghost, use their selected skin + if (PlayerIDSkinMap.ContainsKey(ghost.PlayerInfo.ID)) + { + string suffix = PlayerIDSkinMap[ghost.PlayerInfo.ID]; + + if (suffix != null && suffix != DEFAULT) + GFX.SpriteBank.CreateOn(self, spriteName + '_' + suffix); + else + GFX.SpriteBank.CreateOn(self, spriteName); + } + } + else + { + // Otherwise, we're (most likely) the player, + string suffix = Settings.SelectedSkinMod; + + if (suffix != null && suffix != DEFAULT) + GFX.SpriteBank.CreateOn(self, spriteName + '_' + suffix); + else + GFX.SpriteBank.CreateOn(self, spriteName); + } + + dd.Add("patchedBySkinModHelper", null); + } + orig(self); + } + // If our current skinmod has an overridden sprite bank, use that sprite data instead private Sprite SpriteBankCreateOnHook(On.Monocle.SpriteBank.orig_CreateOn orig, SpriteBank self, Sprite sprite, string id) { + if (sprite is PlayerSprite) + return orig(self, sprite, id); // We handle PlayerSprites separately + String newId = id + "_" + Settings.SelectedSkinMod; if (self.SpriteData.ContainsKey(newId)) { diff --git a/SkinModHelper.csproj b/SkinModHelper.csproj index 26f14c7e..f024d865 100644 --- a/SkinModHelper.csproj +++ b/SkinModHelper.csproj @@ -24,6 +24,12 @@ + + False + + + False + \ No newline at end of file diff --git a/everest.yaml b/everest.yaml index 51254a92..1da238fb 100644 --- a/everest.yaml +++ b/everest.yaml @@ -3,4 +3,6 @@ DLL: bin/Debug/SkinModHelper.dll Dependencies: - Name: Everest - Version: 1.2742.0 \ No newline at end of file + Version: 1.2742.0 + - Name: CelesteNet.Client + Version: 2.0.0 diff --git a/lib-stripped/CelesteNet.Client.dll b/lib-stripped/CelesteNet.Client.dll new file mode 100644 index 0000000000000000000000000000000000000000..797dd78e0925cfe1bfbba34fa6bdd9b2818a94f7 GIT binary patch literal 84480 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%0Dl8QX()MHMuhpC<=9;UXvw40}wtq?sw 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 LJMG1PYXAOU_8`Ru literal 0 HcmV?d00001 diff --git a/lib-stripped/CelesteNet.Shared.dll b/lib-stripped/CelesteNet.Shared.dll new file mode 100644 index 0000000000000000000000000000000000000000..80aa44c5c55d14df686895154ec687f2cb3a1978 GIT binary patch literal 60928 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�(XihU!Z-j}-9FFnBLRy^aB4${(h%hUtt)tx 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 literal 0 HcmV?d00001 From afa751043eec471bdc1da8694550c0f746ea288d Mon Sep 17 00:00:00 2001 From: Aly Date: Wed, 1 Jun 2022 20:51:52 -0700 Subject: [PATCH 2/4] Properly send change packets --- Module/SkinModHelperCelesteNet.cs | 3 +- Module/SkinModHelperModule.cs | 63 +++++++++++++++++++------------ 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/Module/SkinModHelperCelesteNet.cs b/Module/SkinModHelperCelesteNet.cs index eb629d60..c389f30b 100644 --- a/Module/SkinModHelperCelesteNet.cs +++ b/Module/SkinModHelperCelesteNet.cs @@ -21,7 +21,8 @@ public static void HandleDataReady(CelesteNetConnection con, DataReady data) public static void HandleSkinModHelperChange(CelesteNetConnection con, SkinModHelperChange data) { - SkinModHelperModule.PlayerIDSkinMap.Add(data.ChangePlayer.ID, data.SkinID); + SkinModHelperModule.GhostIDSkinMap.Add(data.ChangePlayer.ID, data.SkinID); + SkinModHelperModule.GhostIDRefreshSet.Add(data.ChangePlayer.ID); } private static DataHandler handleSkinModHelperChange; diff --git a/Module/SkinModHelperModule.cs b/Module/SkinModHelperModule.cs index ae24915c..4e438d47 100644 --- a/Module/SkinModHelperModule.cs +++ b/Module/SkinModHelperModule.cs @@ -40,7 +40,8 @@ public class SkinModHelperModule : EverestModule "player", "player_no_backpack", "badeline", "player_badeline", "player_playback" }; - public static Dictionary PlayerIDSkinMap; + public static Dictionary GhostIDSkinMap; + public static HashSet GhostIDRefreshSet; public SkinModHelperModule() { @@ -48,7 +49,8 @@ public SkinModHelperModule() UI = new SkinModHelperUI(); skinConfigs = new Dictionary(); - PlayerIDSkinMap = new Dictionary(); + GhostIDSkinMap = new Dictionary(); + GhostIDRefreshSet = new HashSet(); } public override void Load() @@ -289,40 +291,54 @@ private void PlayerUpdateHairHook(On.Celeste.Player.orig_UpdateHair orig, Player private void PlayerSpriteRenderHook(On.Celeste.PlayerSprite.orig_Render orig, PlayerSprite self) { DynamicData dd = new DynamicData(self); + + if (self.Entity is Ghost g && GhostIDRefreshSet.Contains(g.PlayerInfo.ID)) + { + dd.Set("patchedBySkinModHelper", false); + GhostIDRefreshSet.Remove(g.PlayerInfo.ID); + } - if (!dd.TryGet("patchedBySkinModHelper", out object _)) + if (!(dd.TryGet("patchedBySkinModHelper", out object patched) && (bool) patched)) { string spriteName = dd.Get("spriteName"); if (self.Entity is Ghost ghost) { // If the current PlayerSprite belongs to a CelesteNet Ghost, use their selected skin - if (PlayerIDSkinMap.ContainsKey(ghost.PlayerInfo.ID)) + if (GhostIDSkinMap.ContainsKey(ghost.PlayerInfo.ID)) { - string suffix = PlayerIDSkinMap[ghost.PlayerInfo.ID]; - - if (suffix != null && suffix != DEFAULT) - GFX.SpriteBank.CreateOn(self, spriteName + '_' + suffix); - else - GFX.SpriteBank.CreateOn(self, spriteName); + string suffix = GhostIDSkinMap[ghost.PlayerInfo.ID]; + ReplacePlayerSprite(self, spriteName, suffix); } } else { // Otherwise, we're (most likely) the player, string suffix = Settings.SelectedSkinMod; - - if (suffix != null && suffix != DEFAULT) - GFX.SpriteBank.CreateOn(self, spriteName + '_' + suffix); - else - GFX.SpriteBank.CreateOn(self, spriteName); + ReplacePlayerSprite(self, spriteName, suffix); } - dd.Add("patchedBySkinModHelper", null); + dd.Add("patchedBySkinModHelper", true); } orig(self); } + private void ReplacePlayerSprite(PlayerSprite self, string spriteName, string suffix) + { + if (suffix != null && suffix != DEFAULT) + { + string newId = spriteName + '_' + suffix; + if (GFX.SpriteBank.SpriteData.ContainsKey(newId)) + GFX.SpriteBank.CreateOn(self, newId); + else + GFX.SpriteBank.CreateOn(self, spriteName); + } + else + { + GFX.SpriteBank.CreateOn(self, spriteName); + } + } + // If our current skinmod has an overridden sprite bank, use that sprite data instead private Sprite SpriteBankCreateOnHook(On.Monocle.SpriteBank.orig_CreateOn orig, SpriteBank self, Sprite sprite, string id) { @@ -625,19 +641,18 @@ private void PatchSprite(Sprite origSprite, Sprite newSprite) public static void UpdateSkin(string newSkinId) { Settings.SelectedSkinMod = newSkinId; + + CelesteNetClient client = CelesteNetClientModule.Instance.Client; + client?.Con?.Send(new SkinModHelperChange{SkinID = newSkinId}); + UpdateParticles(); Player player = (Engine.Scene)?.Tracker.GetEntity(); if (player != null) { - if (player.Active) - { - player.ResetSpriteNextFrame(player.Sprite.Mode); - } - else - { - player.ResetSprite(player.Sprite.Mode); - } + DynamicData dd = new DynamicData(player.Sprite); + + dd.Add("patchedBySkinModHelper", false); } } From c01e461516f3fd9ddeb7f53d4a6dcaf95a1cd43f Mon Sep 17 00:00:00 2001 From: Aly Date: Wed, 1 Jun 2022 21:02:24 -0700 Subject: [PATCH 3/4] Don't except when an existing player changes skin _Why_ is Add not an upsert by default? Why do I have to use the syntax sugar? --- Module/SkinModHelperCelesteNet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Module/SkinModHelperCelesteNet.cs b/Module/SkinModHelperCelesteNet.cs index c389f30b..922b383f 100644 --- a/Module/SkinModHelperCelesteNet.cs +++ b/Module/SkinModHelperCelesteNet.cs @@ -21,7 +21,7 @@ public static void HandleDataReady(CelesteNetConnection con, DataReady data) public static void HandleSkinModHelperChange(CelesteNetConnection con, SkinModHelperChange data) { - SkinModHelperModule.GhostIDSkinMap.Add(data.ChangePlayer.ID, data.SkinID); + SkinModHelperModule.GhostIDSkinMap[data.ChangePlayer.ID] = data.SkinID; SkinModHelperModule.GhostIDRefreshSet.Add(data.ChangePlayer.ID); } From 99daf4332f08d0640b2d0fe396c5ef6e6ef7dfb7 Mon Sep 17 00:00:00 2001 From: Aly Date: Thu, 2 Jun 2022 22:53:16 -0700 Subject: [PATCH 4/4] Remove custom HashMap --- Module/SkinModHelperCelesteNet.cs | 5 +++-- Module/SkinModHelperModule.cs | 14 ++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Module/SkinModHelperCelesteNet.cs b/Module/SkinModHelperCelesteNet.cs index 922b383f..ac54c1e5 100644 --- a/Module/SkinModHelperCelesteNet.cs +++ b/Module/SkinModHelperCelesteNet.cs @@ -21,7 +21,6 @@ public static void HandleDataReady(CelesteNetConnection con, DataReady data) public static void HandleSkinModHelperChange(CelesteNetConnection con, SkinModHelperChange data) { - SkinModHelperModule.GhostIDSkinMap[data.ChangePlayer.ID] = data.SkinID; SkinModHelperModule.GhostIDRefreshSet.Add(data.ChangePlayer.ID); } @@ -71,13 +70,15 @@ public override MetaType[] GenerateMeta(DataContext ctx) { return new MetaType[] { - new MetaPlayerPrivateState(ChangePlayer) + new MetaPlayerPrivateState(ChangePlayer), + new MetaBoundRef(DataType.DataID, ChangePlayer?.ID ?? uint.MaxValue, true) }; } public override void FixupMeta(DataContext ctx) { ChangePlayer = Get(ctx).Player; + Get(ctx).ID = ChangePlayer?.ID ?? uint.MaxValue; } protected override void Read(CelesteNetBinaryReader reader) diff --git a/Module/SkinModHelperModule.cs b/Module/SkinModHelperModule.cs index 4e438d47..1b4db4a1 100644 --- a/Module/SkinModHelperModule.cs +++ b/Module/SkinModHelperModule.cs @@ -3,6 +3,7 @@ using Celeste.Mod.CelesteNet; using Celeste.Mod.CelesteNet.Client; using Celeste.Mod.CelesteNet.Client.Entities; +using Celeste.Mod.CelesteNet.DataTypes; using FMOD.Studio; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -40,7 +41,6 @@ public class SkinModHelperModule : EverestModule "player", "player_no_backpack", "badeline", "player_badeline", "player_playback" }; - public static Dictionary GhostIDSkinMap; public static HashSet GhostIDRefreshSet; public SkinModHelperModule() @@ -49,7 +49,6 @@ public SkinModHelperModule() UI = new SkinModHelperUI(); skinConfigs = new Dictionary(); - GhostIDSkinMap = new Dictionary(); GhostIDRefreshSet = new HashSet(); } @@ -305,9 +304,16 @@ private void PlayerSpriteRenderHook(On.Celeste.PlayerSprite.orig_Render orig, Pl if (self.Entity is Ghost ghost) { // If the current PlayerSprite belongs to a CelesteNet Ghost, use their selected skin - if (GhostIDSkinMap.ContainsKey(ghost.PlayerInfo.ID)) + CelesteNetClient client = CelesteNetClientModule.Instance.Client; + if ( + client.Data.TryGetBoundRef( + ghost.PlayerInfo.ID, + out SkinModHelperChange recentChange + ) && + recentChange != null + ) { - string suffix = GhostIDSkinMap[ghost.PlayerInfo.ID]; + string suffix = recentChange.SkinID; ReplacePlayerSprite(self, spriteName, suffix); } }