From 5777b64a1894e6e5eb79ca1fa06a06cd0caaa848 Mon Sep 17 00:00:00 2001 From: Evil Factory <36804725+evilfactory@users.noreply.github.com> Date: Sun, 1 Feb 2026 00:44:25 -0300 Subject: [PATCH] Move LuaUserData and registration into a proper service --- .../Lua/DefaultLib/LibClient.lua | 15 +- .../Lua/DefaultLib/LibServer.lua | 4 +- .../Lua/DefaultLib/LibShared.lua | 6 +- .../Lua/DefaultLib/Utils/SteamApi.lua | 2 + .../Lua/DefaultRegister/RegisterClient.lua | 150 ------ .../Lua/DefaultRegister/RegisterServer.lua | 20 - .../Lua/DefaultRegister/RegisterShared.lua | 479 ------------------ .../LuaCsForBarotrauma/Lua/LuaSetup.lua | 15 +- .../LuaCsForBarotrauma/Lua/LuaUserData.lua | 97 ---- .../LuaCsForBarotrauma/Lua/PostSetup.lua | 13 - .../SharedSource/LuaCs/LuaCsSetup.cs | 4 + .../Services/LuaScriptManagementService.cs | 68 +-- .../Services/Safe/DefaultLuaRegistrar.cs | 177 +++++++ .../Services/Safe/LuaClasses/LuaUserData.cs | 367 -------------- .../LuaCs/Services/Safe/LuaUserDataService.cs | 440 ++++++++++++++++ .../Services/Safe/SafeLuaUserDataService.cs | 234 +++++++++ .../ILuaScriptManagementService.cs | 6 - 17 files changed, 908 insertions(+), 1189 deletions(-) delete mode 100644 Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultRegister/RegisterClient.lua delete mode 100644 Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultRegister/RegisterServer.lua delete mode 100644 Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultRegister/RegisterShared.lua delete mode 100644 Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/LuaUserData.lua delete mode 100644 Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/PostSetup.lua create mode 100644 Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/DefaultLuaRegistrar.cs delete mode 100644 Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/LuaClasses/LuaUserData.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/LuaUserDataService.cs create mode 100644 Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/SafeLuaUserDataService.cs diff --git a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/LibClient.lua b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/LibClient.lua index eb94d18f5..a6a6a1562 100644 --- a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/LibClient.lua +++ b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/LibClient.lua @@ -1,8 +1,8 @@ local defaultLib = {} -local CreateStatic = LuaSetup.LuaUserData.CreateStatic -local CreateEnum = LuaSetup.LuaUserData.CreateEnumTable -local AddCallMetaTable = LuaSetup.LuaUserData.AddCallMetaTable +local CreateStatic = LuaUserData.CreateStatic +local CreateEnum = LuaUserData.CreateEnumTable +local AddCallMetaTable = LuaUserData.AddCallMetaTable local localizedStrings = { "LocalizedString", "LimitLString", "WrappedLString", "AddedPunctuationLString", "CapitalizeLString", "ConcatLString", "FallbackLString", "FormattedLString", "InputTypeLString", "JoinLString", "LowerLString", "RawLString", "ReplaceLString", "ServerMsgLString", "SplitLString", "TagLString", "TrimLString", "UpperLString", "StripRichTagsLString", @@ -79,13 +79,12 @@ defaultLib["GUI"] = { GUIStyle = CreateStatic("Barotrauma.GUIStyle", true), } +local guiFallback = defaultLib["GUI"].GUI + setmetatable(defaultLib["GUI"], { - __index = function (table, key) - return defaultLib["GUI"].GUI[key] + __index = function(_, key) + return guiFallback[key] end }) -AddCallMetaTable(defaultLib["GUI"].VideoPlayer.VideoSettings) -AddCallMetaTable(defaultLib["GUI"].VideoPlayer.TextSettings) - return defaultLib \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/LibServer.lua b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/LibServer.lua index 68bfe97ef..1076e90f6 100644 --- a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/LibServer.lua +++ b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/LibServer.lua @@ -1,7 +1,7 @@ local defaultLib = {} -local CreateStatic = LuaSetup.LuaUserData.CreateStatic -local CreateEnum = LuaSetup.LuaUserData.CreateEnumTable +local CreateStatic = LuaUserData.CreateStatic +local CreateEnum = LuaUserData.CreateEnumTable local localizedStrings = { "LocalizedString", "AddedPunctuationLString", "CapitalizeLString", "ConcatLString", "FallbackLString", "FormattedLString", "InputTypeLString", "JoinLString", "LowerLString", "RawLString", "ReplaceLString", "ServerMsgLString", "SplitLString", "TagLString", "TrimLString", "UpperLString", "StripRichTagsLString", diff --git a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/LibShared.lua b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/LibShared.lua index 1fde8456b..db8469158 100644 --- a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/LibShared.lua +++ b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/LibShared.lua @@ -1,8 +1,8 @@ local defaultLib = {} -local AddCallMetaTable = LuaSetup.LuaUserData.AddCallMetaTable -local CreateStatic = LuaSetup.LuaUserData.CreateStatic -local CreateEnum = LuaSetup.LuaUserData.CreateEnumTable +local AddCallMetaTable = LuaUserData.AddCallMetaTable +local CreateStatic = LuaUserData.CreateStatic +local CreateEnum = LuaUserData.CreateEnumTable defaultLib["SByte"] = CreateStatic("Barotrauma.LuaSByte", true) defaultLib["Byte"] = CreateStatic("Barotrauma.LuaByte", true) diff --git a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/Utils/SteamApi.lua b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/Utils/SteamApi.lua index 4e9608f60..564d39bc7 100644 --- a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/Utils/SteamApi.lua +++ b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultLib/Utils/SteamApi.lua @@ -1,3 +1,5 @@ +if true then return end + local descriptor = LuaUserData.RegisterType("Barotrauma.LuaCsSteam") LuaUserData.AddMethod(descriptor, "GetWorkshopCollection", function (id, callback) diff --git a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultRegister/RegisterClient.lua b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultRegister/RegisterClient.lua deleted file mode 100644 index 6f074747b..000000000 --- a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultRegister/RegisterClient.lua +++ /dev/null @@ -1,150 +0,0 @@ -local Register = LuaSetup.LuaUserData.RegisterType -local RegisterBarotrauma = LuaSetup.LuaUserData.RegisterTypeBarotrauma - -local localizedStrings = { - "LocalizedString", "LimitLString", "WrappedLString", "AddedPunctuationLString", "CapitalizeLString", "ConcatLString", "FallbackLString", "FormattedLString", "InputTypeLString", "JoinLString", "LowerLString", "RawLString", "ReplaceLString", "ServerMsgLString", "SplitLString", "TagLString", "TrimLString", "UpperLString", "StripRichTagsLString", -} - -for key, value in pairs(localizedStrings) do - RegisterBarotrauma(value) -end - -RegisterBarotrauma("EditorScreen") -RegisterBarotrauma("SubEditorScreen") -RegisterBarotrauma("EventEditorScreen") -RegisterBarotrauma("CharacterEditor.CharacterEditorScreen") -RegisterBarotrauma("SpriteEditorScreen") -RegisterBarotrauma("LevelEditorScreen") - -RegisterBarotrauma("Networking.ClientPeer") -RegisterBarotrauma("Networking.GameClient") -RegisterBarotrauma("Networking.VoipCapture") - -RegisterBarotrauma("Media.Video") - -RegisterBarotrauma("SoundsFile") -RegisterBarotrauma("SoundPrefab") -RegisterBarotrauma("PrefabCollection`1") -RegisterBarotrauma("PrefabSelector`1") -RegisterBarotrauma("BackgroundMusic") -RegisterBarotrauma("GUISound") -RegisterBarotrauma("DamageSound") - -RegisterBarotrauma("Sounds.SoundManager") -RegisterBarotrauma("Sounds.OggSound") -RegisterBarotrauma("Sounds.VideoSound") -RegisterBarotrauma("Sounds.VoipSound") -RegisterBarotrauma("Sounds.SoundChannel") -RegisterBarotrauma("Sounds.SoundBuffers") -RegisterBarotrauma("RoundSound") -RegisterBarotrauma("CharacterSound") -RegisterBarotrauma("SoundPlayer") -RegisterBarotrauma("Items.Components.ItemSound") - -RegisterBarotrauma("Sounds.LowpassFilter") -RegisterBarotrauma("Sounds.HighpassFilter") -RegisterBarotrauma("Sounds.BandpassFilter") -RegisterBarotrauma("Sounds.NotchFilter") -RegisterBarotrauma("Sounds.LowShelfFilter") -RegisterBarotrauma("Sounds.HighShelfFilter") -RegisterBarotrauma("Sounds.PeakFilter") - -RegisterBarotrauma("Particles.ParticleManager") -RegisterBarotrauma("Particles.Particle") -RegisterBarotrauma("Particles.ParticleEmitterProperties") -RegisterBarotrauma("Particles.ParticleEmitter") -RegisterBarotrauma("Particles.ParticlePrefab") - -RegisterBarotrauma("Lights.LightManager") -RegisterBarotrauma("Lights.LightSource") -RegisterBarotrauma("Lights.LightSourceParams") - -RegisterBarotrauma("LevelWallVertexBuffer") -RegisterBarotrauma("LevelRenderer") -RegisterBarotrauma("WaterRenderer") -RegisterBarotrauma("WaterVertexData") - -RegisterBarotrauma("ChatBox") -RegisterBarotrauma("GUICanvas") -RegisterBarotrauma("Anchor") -RegisterBarotrauma("Alignment") -RegisterBarotrauma("Pivot") -RegisterBarotrauma("Key") -RegisterBarotrauma("PlayerInput") -RegisterBarotrauma("ScalableFont") - -Register("Microsoft.Xna.Framework.Graphics.Effect") -Register("Microsoft.Xna.Framework.Graphics.EffectParameterCollection") -Register("Microsoft.Xna.Framework.Graphics.EffectParameter") - -Register("Microsoft.Xna.Framework.Graphics.SpriteBatch") -Register("Microsoft.Xna.Framework.Graphics.Texture2D") -Register("EventInput.KeyboardDispatcher") -Register("EventInput.KeyEventArgs") -Register("Microsoft.Xna.Framework.Input.Keys") -Register("Microsoft.Xna.Framework.Input.KeyboardState") - -RegisterBarotrauma("TextureLoader") -RegisterBarotrauma("Sprite") -RegisterBarotrauma("GUI") -RegisterBarotrauma("GUIStyle") -RegisterBarotrauma("GUIComponent") -RegisterBarotrauma("GUILayoutGroup") -RegisterBarotrauma("GUITextBox") -RegisterBarotrauma("GUITextBlock") -RegisterBarotrauma("GUIButton") -RegisterBarotrauma("RectTransform") -RegisterBarotrauma("GUIFrame") -RegisterBarotrauma("GUITickBox") -RegisterBarotrauma("GUIImage") -RegisterBarotrauma("GUIListBox") -RegisterBarotrauma("GUIScrollBar") -RegisterBarotrauma("GUIDropDown") -RegisterBarotrauma("GUINumberInput") -RegisterBarotrauma("GUIMessage") -RegisterBarotrauma("GUIMessageBox") -RegisterBarotrauma("GUIColorPicker") -RegisterBarotrauma("GUIProgressBar") -RegisterBarotrauma("GUICustomComponent") -RegisterBarotrauma("GUIScissorComponent") -RegisterBarotrauma("GUIComponentStyle") -RegisterBarotrauma("GUIFontPrefab") -RegisterBarotrauma("GUIFont") -RegisterBarotrauma("GUISpritePrefab") -RegisterBarotrauma("GUISprite") -RegisterBarotrauma("GUISpriteSheetPrefab") -RegisterBarotrauma("GUISpriteSheet") -RegisterBarotrauma("GUICursorPrefab") -RegisterBarotrauma("GUICursor") -RegisterBarotrauma("GUIRadioButtonGroup") -RegisterBarotrauma("GUIDragHandle") -RegisterBarotrauma("GUIContextMenu") -RegisterBarotrauma("ContextMenuOption") -RegisterBarotrauma("VideoPlayer") -RegisterBarotrauma("CreditsPlayer") -RegisterBarotrauma("SlideshowPlayer") -RegisterBarotrauma("SerializableEntityEditor") -RegisterBarotrauma("CircuitBoxWireRenderer") -RegisterBarotrauma("CircuitBoxLabel") -RegisterBarotrauma("CircuitBoxMouseDragSnapshotHandler") -RegisterBarotrauma("CircuitBoxUI") - -RegisterBarotrauma("SettingsMenu") -RegisterBarotrauma("TabMenu") -RegisterBarotrauma("Widget") -RegisterBarotrauma("UpgradeStore") -RegisterBarotrauma("VotingInterface") -RegisterBarotrauma("MedicalClinicUI") -RegisterBarotrauma("LoadingScreen") -RegisterBarotrauma("HUD") -RegisterBarotrauma("HUDLayoutSettings") -RegisterBarotrauma("HUDProgressBar") -RegisterBarotrauma("Graph") -RegisterBarotrauma("HRManagerUI") -RegisterBarotrauma("SubmarineSelection") -RegisterBarotrauma("Store") -RegisterBarotrauma("UISprite") -RegisterBarotrauma("ParamsEditor") - -RegisterBarotrauma("Inventory+SlotReference") -RegisterBarotrauma("VisualSlot") diff --git a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultRegister/RegisterServer.lua b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultRegister/RegisterServer.lua deleted file mode 100644 index 0de67a7f4..000000000 --- a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultRegister/RegisterServer.lua +++ /dev/null @@ -1,20 +0,0 @@ -local Register = LuaSetup.LuaUserData.RegisterType -local RegisterBarotrauma = LuaSetup.LuaUserData.RegisterTypeBarotrauma - - -local localizedStrings = { - "LocalizedString", "AddedPunctuationLString", "CapitalizeLString", "ConcatLString", "FallbackLString", "FormattedLString", "InputTypeLString", "JoinLString", "LowerLString", "RawLString", "ReplaceLString", "ServerMsgLString", "SplitLString", "TagLString", "TrimLString", "UpperLString", "StripRichTagsLString", -} - -for key, value in pairs(localizedStrings) do - RegisterBarotrauma(value) -end - -Register("Steamworks.SteamServer") - -RegisterBarotrauma("Character+TeamChangeEventData") - -RegisterBarotrauma("Networking.GameServer") - -RegisterBarotrauma("Networking.ServerPeer") -RegisterBarotrauma("Networking.FileSender") diff --git a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultRegister/RegisterShared.lua b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultRegister/RegisterShared.lua deleted file mode 100644 index fc5ee9b2c..000000000 --- a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/DefaultRegister/RegisterShared.lua +++ /dev/null @@ -1,479 +0,0 @@ -local Register = LuaSetup.LuaUserData.RegisterType -local RegisterExtension = LuaSetup.LuaUserData.RegisterExtensionType -local RegisterBarotrauma = LuaSetup.LuaUserData.RegisterTypeBarotrauma - -Register("System.TimeSpan") -Register("System.Exception") -Register("System.Console") -Register("System.Exception") - -RegisterBarotrauma("Success`2") -RegisterBarotrauma("Failure`2") - -RegisterBarotrauma("LuaSByte") -RegisterBarotrauma("LuaByte") -RegisterBarotrauma("LuaInt16") -RegisterBarotrauma("LuaUInt16") -RegisterBarotrauma("LuaInt32") -RegisterBarotrauma("LuaUInt32") -RegisterBarotrauma("LuaInt64") -RegisterBarotrauma("LuaUInt64") -RegisterBarotrauma("LuaSingle") -RegisterBarotrauma("LuaDouble") - -RegisterBarotrauma("GameMain") -RegisterBarotrauma("Networking.BanList") -RegisterBarotrauma("Networking.BannedPlayer") - -RegisterBarotrauma("Range`1") - -RegisterBarotrauma("RichString") -RegisterBarotrauma("Identifier") -RegisterBarotrauma("LanguageIdentifier") - -RegisterBarotrauma("Job") -RegisterBarotrauma("JobPrefab") -RegisterBarotrauma("JobVariant") - -Register("Voronoi2.DoubleVector2") -Register("Voronoi2.Site") -Register("Voronoi2.Edge") -Register("Voronoi2.Halfedge") -Register("Voronoi2.VoronoiCell") -Register("Voronoi2.GraphEdge") - -RegisterBarotrauma("WayPoint") -RegisterBarotrauma("Level") -RegisterBarotrauma("LevelData") -RegisterBarotrauma("Level+InterestingPosition") -RegisterBarotrauma("LevelGenerationParams") -RegisterBarotrauma("LevelObjectManager") -RegisterBarotrauma("LevelObject") -RegisterBarotrauma("LevelObjectPrefab") -RegisterBarotrauma("LevelTrigger") -RegisterBarotrauma("CaveGenerationParams") -RegisterBarotrauma("CaveGenerator") -RegisterBarotrauma("OutpostGenerationParams") -RegisterBarotrauma("OutpostGenerator") -RegisterBarotrauma("OutpostModuleInfo") -RegisterBarotrauma("BeaconStationInfo") -RegisterBarotrauma("NPCSet") -RegisterBarotrauma("RuinGeneration.Ruin") -RegisterBarotrauma("RuinGeneration.RuinGenerationParams") -RegisterBarotrauma("LevelWall") -RegisterBarotrauma("DestructibleLevelWall") -RegisterBarotrauma("Biome") -RegisterBarotrauma("Map") -RegisterBarotrauma("Networking.RespawnManager") -RegisterBarotrauma("Networking.RespawnManager+TeamSpecificState") - -RegisterBarotrauma("Character") -RegisterBarotrauma("CharacterPrefab") -RegisterBarotrauma("CharacterInfo") -RegisterBarotrauma("CharacterInfoPrefab") -RegisterBarotrauma("CharacterInfo+HeadPreset") -RegisterBarotrauma("CharacterInfo+HeadInfo") -RegisterBarotrauma("CharacterHealth") -RegisterBarotrauma("CharacterHealth+LimbHealth") -RegisterBarotrauma("DamageModifier") -RegisterBarotrauma("CharacterInventory") -RegisterBarotrauma("CharacterParams") -RegisterBarotrauma("CharacterParams+AIParams") -RegisterBarotrauma("CharacterParams+TargetParams") -RegisterBarotrauma("CharacterParams+InventoryParams") -RegisterBarotrauma("CharacterParams+HealthParams") -RegisterBarotrauma("CharacterParams+ParticleParams") -RegisterBarotrauma("CharacterParams+SoundParams") -RegisterBarotrauma("SteeringManager") -RegisterBarotrauma("IndoorsSteeringManager") -RegisterBarotrauma("SteeringPath") -RegisterBarotrauma("CreatureMetrics") - -RegisterBarotrauma("Item") -RegisterBarotrauma("DeconstructItem") -RegisterBarotrauma("PurchasedItem") -RegisterBarotrauma("PurchasedItemSwap") -RegisterBarotrauma("PurchasedUpgrade") -RegisterBarotrauma("SoldItem") -RegisterBarotrauma("StartItem") -RegisterBarotrauma("StartItemSet") -RegisterBarotrauma("RelatedItem") -RegisterBarotrauma("UpgradeManager") -RegisterBarotrauma("CargoManager") -RegisterBarotrauma("HireManager") -RegisterBarotrauma("FabricationRecipe") -RegisterBarotrauma("PreferredContainer") -RegisterBarotrauma("SwappableItem") -RegisterBarotrauma("FabricationRecipe+RequiredItemByIdentifier") -RegisterBarotrauma("FabricationRecipe+RequiredItemByTag") -RegisterBarotrauma("Submarine") - -RegisterBarotrauma("Networking.AccountInfo") -RegisterBarotrauma("Networking.AccountId") -RegisterBarotrauma("Networking.SteamId") -RegisterBarotrauma("Networking.EpicAccountId") -RegisterBarotrauma("Networking.Address") -RegisterBarotrauma("Networking.UnknownAddress") -RegisterBarotrauma("Networking.P2PAddress") -RegisterBarotrauma("Networking.EosP2PAddress") -RegisterBarotrauma("Networking.SteamP2PAddress") -RegisterBarotrauma("Networking.PipeAddress") -RegisterBarotrauma("Networking.LidgrenAddress") -RegisterBarotrauma("Networking.Endpoint") -RegisterBarotrauma("Networking.SteamP2PEndpoint") -RegisterBarotrauma("Networking.PipeEndpoint") -RegisterBarotrauma("Networking.LidgrenEndpoint") - -RegisterBarotrauma("INetSerializableStruct") -RegisterBarotrauma("Networking.Client") -RegisterBarotrauma("Networking.TempClient") -RegisterBarotrauma("Networking.NetworkConnection") -RegisterBarotrauma("Networking.LidgrenConnection") -RegisterBarotrauma("Networking.SteamP2PConnection") -RegisterBarotrauma("Networking.VoipQueue") -RegisterBarotrauma("Networking.ChatMessage") - -RegisterBarotrauma("AnimController") -RegisterBarotrauma("HumanoidAnimController") -RegisterBarotrauma("FishAnimController") -RegisterBarotrauma("Limb") -RegisterBarotrauma("Ragdoll") -RegisterBarotrauma("RagdollParams") - -RegisterBarotrauma("AfflictionPrefab") -RegisterBarotrauma("Affliction") -RegisterBarotrauma("AttackResult") -RegisterBarotrauma("Attack") -RegisterBarotrauma("Entity") -RegisterBarotrauma("EntityGrid") -RegisterBarotrauma("EntitySpawner") -RegisterBarotrauma("MapEntity") -RegisterBarotrauma("MapEntityPrefab") -RegisterBarotrauma("CauseOfDeath") -RegisterBarotrauma("Hull") -RegisterBarotrauma("WallSection") -RegisterBarotrauma("Structure") -RegisterBarotrauma("Gap") -RegisterBarotrauma("PhysicsBody") -RegisterBarotrauma("AbilityFlags") -RegisterBarotrauma("ItemPrefab") -RegisterBarotrauma("ItemAssemblyPrefab") -RegisterBarotrauma("InputType") - -RegisterBarotrauma("FireSource") -RegisterBarotrauma("SerializableProperty") -LuaUserData.MakeFieldAccessible(RegisterBarotrauma("StatusEffect"), "user") -RegisterBarotrauma("DurationListElement") -RegisterBarotrauma("PropertyConditional") -RegisterBarotrauma("DelayedListElement") -RegisterBarotrauma("DelayedEffect") - - -RegisterBarotrauma("ContentPackageManager") -RegisterBarotrauma("ContentPackageManager+PackageSource") -RegisterBarotrauma("ContentPackageManager+EnabledPackages") -RegisterBarotrauma("ContentPackage") -RegisterBarotrauma("RegularPackage") -RegisterBarotrauma("CorePackage") -RegisterBarotrauma("ContentXElement") -RegisterBarotrauma("ContentPath") -RegisterBarotrauma("ContentPackageId") -RegisterBarotrauma("SteamWorkshopId") -RegisterBarotrauma("Md5Hash") - -RegisterBarotrauma("AfflictionsFile") -RegisterBarotrauma("BackgroundCreaturePrefabsFile") -RegisterBarotrauma("BallastFloraFile") -RegisterBarotrauma("BeaconStationFile") -RegisterBarotrauma("CaveGenerationParametersFile") -RegisterBarotrauma("CharacterFile") -RegisterBarotrauma("ContentFile") -RegisterBarotrauma("CorpsesFile") -RegisterBarotrauma("DecalsFile") -RegisterBarotrauma("EnemySubmarineFile") -RegisterBarotrauma("EventManagerSettingsFile") -RegisterBarotrauma("FactionsFile") -RegisterBarotrauma("ItemAssemblyFile") -RegisterBarotrauma("ItemFile") -RegisterBarotrauma("JobsFile") -RegisterBarotrauma("LevelGenerationParametersFile") -RegisterBarotrauma("LevelObjectPrefabsFile") -RegisterBarotrauma("LocationTypesFile") -RegisterBarotrauma("MapGenerationParametersFile") -RegisterBarotrauma("MissionsFile") -RegisterBarotrauma("NPCConversationsFile") -RegisterBarotrauma("NPCPersonalityTraitsFile") -RegisterBarotrauma("NPCSetsFile") -RegisterBarotrauma("OrdersFile") -RegisterBarotrauma("OtherFile") -RegisterBarotrauma("OutpostConfigFile") -RegisterBarotrauma("OutpostFile") -RegisterBarotrauma("OutpostModuleFile") -RegisterBarotrauma("ParticlesFile") -RegisterBarotrauma("RandomEventsFile") -RegisterBarotrauma("RuinConfigFile") -RegisterBarotrauma("ServerExecutableFile") -RegisterBarotrauma("SkillSettingsFile") -RegisterBarotrauma("SoundsFile") -RegisterBarotrauma("StartItemsFile") -RegisterBarotrauma("StructureFile") -RegisterBarotrauma("SubmarineFile") -RegisterBarotrauma("TalentsFile") -RegisterBarotrauma("TalentTreesFile") -RegisterBarotrauma("TextFile") -RegisterBarotrauma("TutorialsFile") -RegisterBarotrauma("UIStyleFile") -RegisterBarotrauma("UpgradeModulesFile") -RegisterBarotrauma("WreckAIConfigFile") -RegisterBarotrauma("WreckFile") - -Register("System.Xml.Linq.XElement") -Register("System.Xml.Linq.XName") -Register("System.Xml.Linq.XAttribute") -Register("System.Xml.Linq.XContainer") -Register("System.Xml.Linq.XDocument") -Register("System.Xml.Linq.XNode") - - -RegisterBarotrauma("SubmarineBody") -RegisterBarotrauma("Explosion") -RegisterBarotrauma("Networking.ServerSettings") -RegisterBarotrauma("Networking.ServerSettings+SavedClientPermission") -RegisterBarotrauma("Inventory") -RegisterBarotrauma("ItemInventory") -RegisterBarotrauma("Inventory+ItemSlot") -RegisterBarotrauma("FireSource") -RegisterBarotrauma("AutoItemPlacer") -RegisterBarotrauma("CircuitBoxConnection") -RegisterBarotrauma("CircuitBoxComponent") -RegisterBarotrauma("CircuitBoxNode") -RegisterBarotrauma("CircuitBoxWire") -RegisterBarotrauma("CircuitBoxInputOutputNode") -RegisterBarotrauma("CircuitBoxSelectable") -RegisterBarotrauma("CircuitBoxSizes") - -local componentsToRegister = { "DockingPort", "Door", "GeneticMaterial", "Growable", "Holdable", "LevelResource", "ItemComponent", "ItemLabel", "LightComponent", "Controller", "Deconstructor", "Engine", "Fabricator", "OutpostTerminal", "Pump", "Reactor", "Steering", "PowerContainer", "Projectile", "Repairable", "Rope", "Scanner", "ButtonTerminal", "ConnectionPanel", "CustomInterface", "MemoryComponent", "Terminal", "WifiComponent", "Wire", "TriggerComponent", "ElectricalDischarger", "EntitySpawnerComponent", "ProducedItem", "VineTile", "GrowthSideExtension", "IdCard", "MeleeWeapon", "Pickable", "AbilityItemPickingTime", "Propulsion", "RangedWeapon", "AbilityRangedWeapon", "RepairTool", "Sprayer", "Throwable", "ItemContainer", "AbilityItemContainer", "Ladder", "LimbPos", "AbilityDeconstructedItem", "AbilityItemCreationMultiplier", "AbilityItemDeconstructedInventory", "MiniMap", "OxygenGenerator", "Sonar", "SonarTransducer", "Vent", "NameTag", "Planter", "Powered", "PowerTransfer", "Quality", "RemoteController", "AdderComponent", "AndComponent", "ArithmeticComponent", "ColorComponent", "ConcatComponent", "Connection", "CircuitBox", "DelayComponent", "DivideComponent", "EqualsComponent", "ExponentiationComponent", "FunctionComponent", "GreaterComponent", "ModuloComponent", "MotionSensor", "MultiplyComponent", "NotComponent", "OrComponent", "OscillatorComponent", "OxygenDetector", "RegExFindComponent", "RelayComponent", "SignalCheckComponent", "SmokeDetector", "StringComponent", "SubtractComponent", "TrigonometricFunctionComponent", "WaterDetector", "XorComponent", "StatusHUD", "Turret", "Wearable", -"GridInfo", "PowerSourceGroup" -} - -for key, value in pairs(componentsToRegister) do - RegisterBarotrauma("Items.Components." .. value) -end - -LuaUserData.MakeFieldAccessible(RegisterBarotrauma("Items.Components.CustomInterface"), "customInterfaceElementList") -RegisterBarotrauma("Items.Components.CustomInterface+CustomInterfaceElement") - -RegisterBarotrauma("WearableSprite") - -RegisterBarotrauma("AIController") -RegisterBarotrauma("EnemyAIController") -RegisterBarotrauma("HumanAIController") -RegisterBarotrauma("AICharacter") -RegisterBarotrauma("AITarget") -RegisterBarotrauma("AITargetMemory") -RegisterBarotrauma("AIChatMessage") -RegisterBarotrauma("AIObjectiveManager") -RegisterBarotrauma("WreckAI") -RegisterBarotrauma("WreckAIConfig") - -RegisterBarotrauma("AIObjectiveChargeBatteries") -RegisterBarotrauma("AIObjective") -RegisterBarotrauma("AIObjectiveCleanupItem") -RegisterBarotrauma("AIObjectiveCleanupItems") -RegisterBarotrauma("AIObjectiveCombat") -RegisterBarotrauma("AIObjectiveContainItem") -RegisterBarotrauma("AIObjectiveDeconstructItem") -RegisterBarotrauma("AIObjectiveDeconstructItems") -RegisterBarotrauma("AIObjectiveEscapeHandcuffs") -RegisterBarotrauma("AIObjectiveExtinguishFire") -RegisterBarotrauma("AIObjectiveExtinguishFires") -RegisterBarotrauma("AIObjectiveFightIntruders") -RegisterBarotrauma("AIObjectiveFindDivingGear") -RegisterBarotrauma("AIObjectiveFindSafety") -RegisterBarotrauma("AIObjectiveFixLeak") -RegisterBarotrauma("AIObjectiveFixLeaks") -RegisterBarotrauma("AIObjectiveGetItem") -RegisterBarotrauma("AIObjectiveGoTo") -RegisterBarotrauma("AIObjectiveIdle") -RegisterBarotrauma("AIObjectiveOperateItem") -RegisterBarotrauma("AIObjectivePumpWater") -RegisterBarotrauma("AIObjectiveRepairItem") -RegisterBarotrauma("AIObjectiveRepairItems") -RegisterBarotrauma("AIObjectiveRescue") -RegisterBarotrauma("AIObjectiveRescueAll") -RegisterBarotrauma("AIObjectiveReturn") - -RegisterBarotrauma("Order") -RegisterBarotrauma("OrderPrefab") -RegisterBarotrauma("OrderTarget") - -RegisterBarotrauma("TalentPrefab") -RegisterBarotrauma("TalentOption") -RegisterBarotrauma("TalentSubTree") -RegisterBarotrauma("TalentTree") -RegisterBarotrauma("CharacterTalent") -RegisterBarotrauma("Upgrade") -RegisterBarotrauma("UpgradeCategory") -RegisterBarotrauma("UpgradePrefab") -RegisterBarotrauma("UpgradeManager") - -RegisterBarotrauma("Screen") -RegisterBarotrauma("GameScreen") -RegisterBarotrauma("GameSession") -RegisterBarotrauma("GameSettings") -RegisterBarotrauma("CrewManager") -RegisterBarotrauma("KarmaManager") - -RegisterBarotrauma("GameMode") -RegisterBarotrauma("MissionMode") -RegisterBarotrauma("PvPMode") -RegisterBarotrauma("Mission") -RegisterBarotrauma("AbandonedOutpostMission") -RegisterBarotrauma("EliminateTargetsMission") -RegisterBarotrauma("EndMission") -RegisterBarotrauma("BeaconMission") -RegisterBarotrauma("CargoMission") -RegisterBarotrauma("CombatMission") -RegisterBarotrauma("EscortMission") -RegisterBarotrauma("GoToMission") -RegisterBarotrauma("MineralMission") -RegisterBarotrauma("MonsterMission") -RegisterBarotrauma("NestMission") -RegisterBarotrauma("PirateMission") -RegisterBarotrauma("SalvageMission") -RegisterBarotrauma("ScanMission") -RegisterBarotrauma("MissionPrefab") -RegisterBarotrauma("CampaignMode") -RegisterBarotrauma("CoOpMode") -RegisterBarotrauma("MultiPlayerCampaign") -RegisterBarotrauma("Radiation") - -RegisterBarotrauma("CampaignMetadata") -RegisterBarotrauma("Wallet") - -RegisterBarotrauma("Faction") -RegisterBarotrauma("FactionPrefab") -RegisterBarotrauma("Reputation") - -RegisterBarotrauma("Location") -RegisterBarotrauma("LocationConnection") -RegisterBarotrauma("LocationType") -RegisterBarotrauma("LocationTypeChange") - -RegisterBarotrauma("DebugConsole") -RegisterBarotrauma("DebugConsole+Command") - -RegisterBarotrauma("TextManager") -RegisterBarotrauma("TextPack") - -local descriptor = RegisterBarotrauma("NetLobbyScreen") - -if SERVER then - LuaUserData.MakeFieldAccessible(descriptor, "subs") -end - -RegisterBarotrauma("EventManager") -RegisterBarotrauma("EventManagerSettings") -RegisterBarotrauma("Event") -RegisterBarotrauma("ArtifactEvent") -RegisterBarotrauma("MonsterEvent") -RegisterBarotrauma("ScriptedEvent") -RegisterBarotrauma("MalfunctionEvent") -RegisterBarotrauma("EventSet") -RegisterBarotrauma("EventPrefab") - -RegisterBarotrauma("Networking.NetConfig") -RegisterBarotrauma("Networking.IWriteMessage") -RegisterBarotrauma("Networking.IReadMessage") -RegisterBarotrauma("Networking.NetEntityEvent") -RegisterBarotrauma("Networking.INetSerializable") -Register("Lidgren.Network.NetIncomingMessage") -Register("Lidgren.Network.NetConnection") -Register("System.Net.IPEndPoint") -Register("System.Net.IPAddress") - -RegisterBarotrauma("Skill") -RegisterBarotrauma("SkillPrefab") -RegisterBarotrauma("SkillSettings") - -RegisterBarotrauma("TraitorManager") -RegisterBarotrauma("TraitorEvent") -RegisterBarotrauma("TraitorEventPrefab") -RegisterBarotrauma("TraitorManager+TraitorResults") - -Register("FarseerPhysics.Dynamics.Body") -Register("FarseerPhysics.Dynamics.World") -Register("FarseerPhysics.Dynamics.Fixture") -Register("FarseerPhysics.ConvertUnits") -Register("FarseerPhysics.Collision.AABB") -Register("FarseerPhysics.Collision.ContactFeature") -Register("FarseerPhysics.Collision.ManifoldPoint") -Register("FarseerPhysics.Collision.ContactID") -Register("FarseerPhysics.Collision.Manifold") -Register("FarseerPhysics.Collision.RayCastInput") -Register("FarseerPhysics.Collision.ClipVertex") -Register("FarseerPhysics.Collision.RayCastOutput") -Register("FarseerPhysics.Collision.EPAxis") -Register("FarseerPhysics.Collision.ReferenceFace") -Register("FarseerPhysics.Collision.Collision") - -RegisterBarotrauma("Physics") - -local toolBox = RegisterBarotrauma("ToolBox") -if CLIENT then - LuaUserData.RemoveMember(toolBox, "OpenFileWithShell") -end - -RegisterBarotrauma("Camera") -RegisterBarotrauma("Key") - -RegisterBarotrauma("PrefabCollection`1") - -RegisterBarotrauma("PrefabSelector`1") - -RegisterBarotrauma("Pair`2") - -RegisterBarotrauma("Items.Components.Signal") -RegisterBarotrauma("SubmarineInfo") - -RegisterBarotrauma("MapCreatures.Behavior.BallastFloraBehavior") -RegisterBarotrauma("MapCreatures.Behavior.BallastFloraBranch") - -RegisterBarotrauma("PetBehavior") -RegisterBarotrauma("SwarmBehavior") -RegisterBarotrauma("LatchOntoAI") - -RegisterBarotrauma("Decal") -RegisterBarotrauma("DecalPrefab") -RegisterBarotrauma("DecalManager") - -RegisterBarotrauma("PriceInfo") - -RegisterBarotrauma("Voting") - -Register("Microsoft.Xna.Framework.Vector2") -Register("Microsoft.Xna.Framework.Vector3") -Register("Microsoft.Xna.Framework.Vector4") -Register("Microsoft.Xna.Framework.Color") -Register("Microsoft.Xna.Framework.Point") -Register("Microsoft.Xna.Framework.Rectangle") -Register("Microsoft.Xna.Framework.Matrix") - -local friend = Register("Steamworks.Friend") - -LuaUserData.RemoveMember(friend, "InviteToGame") -LuaUserData.RemoveMember(friend, "SendMessage") - -local workshopItem = Register("Steamworks.Ugc.Item") - -LuaUserData.RemoveMember(workshopItem, "Subscribe") -LuaUserData.RemoveMember(workshopItem, "DownloadAsync") -LuaUserData.RemoveMember(workshopItem, "Unsubscribe") -LuaUserData.RemoveMember(workshopItem, "AddFavorite") -LuaUserData.RemoveMember(workshopItem, "RemoveFavorite") -LuaUserData.RemoveMember(workshopItem, "Vote") -LuaUserData.RemoveMember(workshopItem, "GetUserVote") -LuaUserData.RemoveMember(workshopItem, "Edit") - -RegisterExtension("Barotrauma.MathUtils") -RegisterExtension("Barotrauma.XMLExtensions") \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/LuaSetup.lua b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/LuaSetup.lua index 4b038464e..d8c531649 100644 --- a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/LuaSetup.lua +++ b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/LuaSetup.lua @@ -6,17 +6,6 @@ package.path = {path .. "/Lua/?.lua"} setmodulepaths(package.path) --- Setup Libraries -LuaSetup.LuaUserData = LuaUserData - -require("DefaultRegister/RegisterShared") - -if SERVER then - require("DefaultRegister/RegisterServer") -else - require("DefaultRegister/RegisterClient") -end - local function AddTableToGlobal(tbl) for k, v in pairs(tbl) do _G[k] = v @@ -35,11 +24,11 @@ AddTableToGlobal(require("CompatibilityLib")) require("DefaultHook") +Descriptors = LuaSetup.LuaUserData + require("DefaultLib/Utils/Math") require("DefaultLib/Utils/String") require("DefaultLib/Utils/Util") require("DefaultLib/Utils/SteamApi") -require("PostSetup") - LuaSetup = nil \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/LuaUserData.lua b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/LuaUserData.lua deleted file mode 100644 index 387fc7f2b..000000000 --- a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/LuaUserData.lua +++ /dev/null @@ -1,97 +0,0 @@ -local clrLuaUserData = LuaUserData -local luaUserData = {} - -luaUserData.Descriptors = {} - -LuaSetup.LuaUserData = luaUserData - -luaUserData.IsRegistered = clrLuaUserData.IsRegistered -luaUserData.UnregisterType = clrLuaUserData.UnregisterType -luaUserData.RegisterGenericType = clrLuaUserData.RegisterGenericType -luaUserData.RegisterExtensionType = clrLuaUserData.RegisterExtensionType -luaUserData.UnregisterGenericType = clrLuaUserData.UnregisterGenericType -luaUserData.IsTargetType = clrLuaUserData.IsTargetType -luaUserData.TypeOf = clrLuaUserData.TypeOf -luaUserData.GetType = clrLuaUserData.GetType -luaUserData.CreateEnumTable = clrLuaUserData.CreateEnumTable -luaUserData.MakeFieldAccessible = clrLuaUserData.MakeFieldAccessible -luaUserData.MakeMethodAccessible = clrLuaUserData.MakeMethodAccessible -luaUserData.MakePropertyAccessible = clrLuaUserData.MakePropertyAccessible -luaUserData.AddMethod = clrLuaUserData.AddMethod -luaUserData.AddField = clrLuaUserData.AddField -luaUserData.RemoveMember = clrLuaUserData.RemoveMember -luaUserData.CreateUserDataFromDescriptor = clrLuaUserData.CreateUserDataFromDescriptor -luaUserData.CreateUserDataFromType = clrLuaUserData.CreateUserDataFromType -luaUserData.HasMember = clrLuaUserData.HasMember - -luaUserData.RegisterType = function(typeName) - local success, result = pcall(clrLuaUserData.RegisterType, typeName) - - if not success then - error(result, 2) - end - - luaUserData.Descriptors[typeName] = result - - return result -end - -luaUserData.RegisterTypeBarotrauma = function(typeName) - typeName = "Barotrauma." .. typeName - local success, result = pcall(luaUserData.RegisterType, typeName) - - if not success then - error(result, 2) - end - - return result -end - -luaUserData.AddCallMetaTable = function (userdata) - if userdata == nil then - error("Attempted to add a call metatable to a nil value.", 2) - end - - if not LuaUserData.HasMember(userdata, ".ctor") then - error("Attempted to add a call metatable to a userdata that does not have a constructor.", 2) - end - - debug.setmetatable(userdata, { - __call = function(obj, ...) - if userdata == nil then - error("userdata was nil.", 2) - end - - local success, result = pcall(userdata.__new, ...) - - - if not success then - error(result, 2) - end - - return result - end - }) -end - -luaUserData.CreateStatic = function(typeName) - if type(typeName) ~= "string" then - error("Expected a string for typeName, got " .. type(typeName) .. ".", 2) - end - - local success, result = pcall(clrLuaUserData.CreateStatic, typeName) - - if not success then - error(result, 2) - end - - if result == nil then - return - end - - if LuaUserData.HasMember(result, ".ctor") then - luaUserData.AddCallMetaTable(result) - end - - return result -end \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/PostSetup.lua b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/PostSetup.lua deleted file mode 100644 index d18dbc685..000000000 --- a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/Lua/PostSetup.lua +++ /dev/null @@ -1,13 +0,0 @@ -if not CSActive then - LuaUserDataIUUD = LuaUserData.RegisterType("Barotrauma.LuaSafeUserData") - LuaUserData = LuaUserData.CreateStatic("Barotrauma.LuaSafeUserData"); - - for k, v in pairs(debug) do - if k ~= "getmetatable" and k ~= "setmetatable" and k ~= "traceback" then - debug[k] = nil - end - end -end - -Descriptors = LuaUserData.__new() -LuaUserDataIUUD = nil \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs index 740e8ab89..8bb0d26ae 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs @@ -189,6 +189,10 @@ namespace Barotrauma servicesProvider.RegisterServiceType(ServiceLifetime.Transient); servicesProvider.RegisterServiceResolver(factory => factory.GetInstance()); servicesProvider.RegisterServiceType(ServiceLifetime.Singleton); + servicesProvider.RegisterServiceType(ServiceLifetime.Singleton); + servicesProvider.RegisterServiceType(ServiceLifetime.Singleton); + servicesProvider.RegisterServiceType(ServiceLifetime.Singleton); + servicesProvider.RegisterServiceType(ServiceLifetime.Transient); servicesProvider.RegisterServiceType(ServiceLifetime.Singleton); servicesProvider.RegisterServiceType(ServiceLifetime.Singleton); diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/LuaScriptManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/LuaScriptManagementService.cs index d15b0e682..97564b9be 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/LuaScriptManagementService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/LuaScriptManagementService.cs @@ -17,16 +17,10 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; -using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; -using System.Globalization; using System.IO; using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading; using System.Threading.Tasks; -using static Barotrauma.GameSettings; namespace Barotrauma.LuaCs.Services; @@ -39,20 +33,26 @@ class LuaScriptManagementService : ILuaScriptManagementService, ILuaDataService private List _resourcesInfo = new List(); private readonly AsyncReaderWriterLock _operationsLock = new (); - + + private readonly ILuaUserDataService _userDataService; + private readonly ISafeLuaUserDataService _safeUserDataService; + private readonly ILuaScriptLoader _luaScriptLoader; private readonly ILuaScriptServicesConfig _luaScriptServicesConfig; private readonly ILoggerService _loggerService; private readonly LuaGame _luaGame; private readonly ILuaCsHook _luaCsHook; private readonly ILuaCsTimer _luaCsTimer; + private readonly IDefaultLuaRegistrar _defaultLuaRegistrar; //private readonly ILuaCsNetworking _luaCsNetworking; //private readonly ILuaCsUtility _luaCsUtility; - //private readonly ILuaCsTimer _luaCsTimer; public LuaScriptManagementService( - ILoggerService loggerService, - ILuaScriptLoader loader, + ILoggerService loggerService, + ILuaScriptLoader loader, + ILuaUserDataService userDataService, + ISafeLuaUserDataService safeUserDataService, + IDefaultLuaRegistrar defaultLuaRegistrar, ILuaScriptServicesConfig luaScriptServicesConfig, LuaGame luaGame, ILuaCsHook luaCsHook, @@ -62,6 +62,9 @@ class LuaScriptManagementService : ILuaScriptManagementService, ILuaDataService ) { _luaScriptLoader = loader; + _userDataService = userDataService; + _safeUserDataService = safeUserDataService; + _defaultLuaRegistrar = defaultLuaRegistrar; _luaScriptServicesConfig = luaScriptServicesConfig; _loggerService = loggerService; @@ -168,16 +171,15 @@ class LuaScriptManagementService : ILuaScriptManagementService, ILuaDataService Script.GlobalOptions.ShouldPCallCatchException = (Exception ex) => { return true; }; - RegisterType(typeof(LuaGame)); - RegisterType(typeof(EventService)); - RegisterType(typeof(ILuaCsNetworking)); - RegisterType(typeof(ILuaCsUtility)); - RegisterType(typeof(ILuaCsTimer)); - RegisterType(typeof(LuaCsFile)); - RegisterType(typeof(ILuaScriptResourceInfo)); - RegisterType(typeof(IResourceInfo)); - RegisterType(typeof(LuaUserData)); - RegisterType(typeof(IUserDataDescriptor)); + UserData.RegisterType(typeof(LuaGame)); + UserData.RegisterType(typeof(EventService)); + UserData.RegisterType(typeof(ILuaCsNetworking)); + UserData.RegisterType(typeof(ILuaCsUtility)); + UserData.RegisterType(typeof(ILuaCsTimer)); + UserData.RegisterType(typeof(LuaCsFile)); + UserData.RegisterType(typeof(ILuaScriptResourceInfo)); + UserData.RegisterType(typeof(IResourceInfo)); + UserData.RegisterType(typeof(IUserDataDescriptor)); new LuaConverters(_script).RegisterLuaConverters(); @@ -193,20 +195,31 @@ class LuaScriptManagementService : ILuaScriptManagementService, ILuaDataService _script.Globals["dostring"] = (Func)_script.DoString; _script.Globals["load"] = (Func)_script.LoadString; - _script.Globals["Game"] = _luaGame; _script.Globals["Hook"] = _luaCsHook; _script.Globals["Timer"] = _luaCsTimer; _script.Globals["File"] = UserData.CreateStatic(); //_script.Globals["Networking"] = _luaCsNetworking; //_script.Globals["Steam"] = Steam; - _script.Globals["LuaUserData"] = UserData.CreateStatic(); + + if (GameMain.LuaCs.IsCsEnabled) + { + UserData.RegisterType(typeof(LuaUserDataService)); + _script.Globals["LuaUserData"] = _userDataService; + } + else + { + UserData.RegisterType(typeof(SafeLuaUserDataService)); + _script.Globals["LuaUserData"] = _safeUserDataService; + } _script.Globals["ExecutionNumber"] = 0; _script.Globals["CSActive"] = false; _script.Globals["SERVER"] = LuaCsSetup.IsServer; _script.Globals["CLIENT"] = LuaCsSetup.IsClient; + + _defaultLuaRegistrar.RegisterAll(); } public FluentResults.Result ExecuteLoadedScripts(ImmutableArray executionOrder) @@ -291,24 +304,17 @@ class LuaScriptManagementService : ILuaScriptManagementService, ILuaDataService public FluentResults.Result Reset() { + _userDataService.Reset(); return DisposeAllPackageResources(); } public void Dispose() { + _userDataService.Dispose(); _luaScriptLoader.Dispose(); IsDisposed = true; } - public IUserDataDescriptor RegisterType(Type type) - { - return UserData.RegisterType(type); - } - public void UnregisterType(Type type) - { - UserData.UnregisterType(type, true); - } - public object? GetGlobalTableValue(string tableName) { if (!IsRunning) { return null; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/DefaultLuaRegistrar.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/DefaultLuaRegistrar.cs new file mode 100644 index 000000000..c7bc3c518 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/DefaultLuaRegistrar.cs @@ -0,0 +1,177 @@ +using Barotrauma.Networking; +using MoonSharp.Interpreter; +using Sigil; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace Barotrauma.LuaCs.Services; + +public interface IDefaultLuaRegistrar : IService +{ + public void RegisterAll(); +} + +public class DefaultLuaRegistrar : IDefaultLuaRegistrar +{ + public bool IsDisposed { get; private set; } + + private readonly ILuaUserDataService _userDataService; + private readonly ISafeLuaUserDataService _safeUserDataService; + private readonly ILoggerService _loggerService; + + public DefaultLuaRegistrar(ILoggerService loggerService, ILuaUserDataService userDataService, ISafeLuaUserDataService safeUserDataService) + { + _userDataService = userDataService; + _safeUserDataService = safeUserDataService; + _loggerService = loggerService; + } + + private void RegisterShared() + { + _userDataService.RegisterType("System.TimeSpan"); + _userDataService.RegisterType("System.Exception"); + _userDataService.RegisterType("System.Console"); + _userDataService.RegisterType("System.Exception"); + + _userDataService.RegisterType("Barotrauma.Success`2"); + _userDataService.RegisterType("Barotrauma.Failure`2"); + _userDataService.RegisterType("Barotrauma.Range`1"); + + List assembliesToScan = [typeof(DefaultLuaRegistrar).Assembly, typeof(Identifier).Assembly, typeof(Microsoft.Xna.Framework.Vector2).Assembly]; + + foreach (var type in assembliesToScan.SelectMany(a => a.GetTypes())) + { + if (type.IsEnum || type.IsDefined(typeof(CompilerGeneratedAttribute)) || !_safeUserDataService.IsAllowed(type.FullName)) + { + continue; + } + + _loggerService.LogMessage($"Registered {type.FullName}"); + + _userDataService.RegisterType(type.FullName); + } + + + _userDataService.RegisterType("Barotrauma.LuaSByte"); + _userDataService.RegisterType("Barotrauma.LuaByte"); + _userDataService.RegisterType("Barotrauma.LuaInt16"); + _userDataService.RegisterType("Barotrauma.LuaUInt16"); + _userDataService.RegisterType("Barotrauma.LuaInt32"); + _userDataService.RegisterType("Barotrauma.LuaUInt32"); + _userDataService.RegisterType("Barotrauma.LuaInt64"); + _userDataService.RegisterType("Barotrauma.LuaUInt64"); + _userDataService.RegisterType("Barotrauma.LuaSingle"); + _userDataService.RegisterType("Barotrauma.LuaDouble"); + + _userDataService.RegisterType("Barotrauma.Level+InterestingPosition"); + _userDataService.RegisterType("Barotrauma.Networking.RespawnManager+TeamSpecificState"); + + _userDataService.RegisterType("Barotrauma.CharacterParams+AIParams"); + _userDataService.RegisterType("Barotrauma.CharacterParams+TargetParams"); + _userDataService.RegisterType("Barotrauma.CharacterParams+InventoryParams"); + _userDataService.RegisterType("Barotrauma.CharacterParams+HealthParams"); + _userDataService.RegisterType("Barotrauma.CharacterParams+ParticleParams"); + _userDataService.RegisterType("Barotrauma.CharacterParams+SoundParams"); + + _userDataService.RegisterType("Barotrauma.FabricationRecipe+RequiredItemByIdentifier"); + _userDataService.RegisterType("Barotrauma.FabricationRecipe+RequiredItemByTag"); + + _userDataService.MakeFieldAccessible(_userDataService.RegisterType("Barotrauma.StatusEffect"), "user"); + + + _userDataService.RegisterType("Barotrauma.ContentPackageManager+PackageSource"); + _userDataService.RegisterType("Barotrauma.ContentPackageManager+EnabledPackages"); + + _userDataService.RegisterType("System.Xml.Linq.XElement"); + _userDataService.RegisterType("System.Xml.Linq.XName"); + _userDataService.RegisterType("System.Xml.Linq.XAttribute"); + _userDataService.RegisterType("System.Xml.Linq.XContainer"); + _userDataService.RegisterType("System.Xml.Linq.XDocument"); + _userDataService.RegisterType("System.Xml.Linq.XNode"); + + + _userDataService.RegisterType("Barotrauma.Networking.ServerSettings+SavedClientPermission"); + _userDataService.RegisterType("Barotrauma.Inventory+ItemSlot"); + + + _userDataService.MakeFieldAccessible(_userDataService.RegisterType("Barotrauma.Items.Components.CustomInterface"), "customInterfaceElementList"); + _userDataService.RegisterType("Barotrauma.Items.Components.CustomInterface+CustomInterfaceElement"); + + _userDataService.RegisterType("Barotrauma.DebugConsole+Command"); + + { + var descriptor = _userDataService.RegisterType("Barotrauma.NetLobbyScreen"); + +#if SERVER + _userDataService.MakeFieldAccessible(descriptor, "subs"); +#endif + } + + _userDataService.RegisterType("FarseerPhysics.Dynamics.Body"); + _userDataService.RegisterType("FarseerPhysics.Dynamics.World"); + _userDataService.RegisterType("FarseerPhysics.Dynamics.Fixture"); + _userDataService.RegisterType("FarseerPhysics.ConvertUnits"); + _userDataService.RegisterType("FarseerPhysics.Collision.AABB"); + _userDataService.RegisterType("FarseerPhysics.Collision.ContactFeature"); + _userDataService.RegisterType("FarseerPhysics.Collision.ManifoldPoint"); + _userDataService.RegisterType("FarseerPhysics.Collision.ContactID"); + _userDataService.RegisterType("FarseerPhysics.Collision.Manifold"); + _userDataService.RegisterType("FarseerPhysics.Collision.RayCastInput"); + _userDataService.RegisterType("FarseerPhysics.Collision.ClipVertex"); + _userDataService.RegisterType("FarseerPhysics.Collision.RayCastOutput"); + _userDataService.RegisterType("FarseerPhysics.Collision.EPAxis"); + _userDataService.RegisterType("FarseerPhysics.Collision.ReferenceFace"); + _userDataService.RegisterType("FarseerPhysics.Collision.Collision"); + + _userDataService.RegisterType("Barotrauma.PrefabCollection`1"); + _userDataService.RegisterType("Barotrauma.PrefabSelector`1"); + _userDataService.RegisterType("Barotrauma.Pair`2"); + + var toolBox = UserData.RegisterType(typeof(ToolBox)); +#if CLIENT + _userDataService.RemoveMember(toolBox, "OpenFileWithShell"); +#endif + } + +#if CLIENT + private void RegisterClient() + { + _userDataService.RegisterType("Microsoft.Xna.Framework.Graphics.Effect"); + _userDataService.RegisterType("Microsoft.Xna.Framework.Graphics.EffectParameterCollection"); + _userDataService.RegisterType("Microsoft.Xna.Framework.Graphics.EffectParameter"); + + _userDataService.RegisterType("Microsoft.Xna.Framework.Graphics.SpriteBatch"); + _userDataService.RegisterType("Microsoft.Xna.Framework.Graphics.Texture2D"); + _userDataService.RegisterType("EventInput.KeyboardDispatcher"); + _userDataService.RegisterType("EventInput.KeyEventArgs"); + _userDataService.RegisterType("Microsoft.Xna.Framework.Input.Keys"); + _userDataService.RegisterType("Microsoft.Xna.Framework.Input.KeyboardState"); + + + _userDataService.RegisterType("Barotrauma.Inventory+SlotReference"); + } +#elif SERVER + private void RegisterServer() + { + _userDataService.RegisterType("Barotrauma.Character+TeamChangeEventData"); + } +#endif + + public void RegisterAll() + { + RegisterShared(); +#if CLIENT + RegisterClient(); +#elif SERVER + RegisterServer(); +#endif + } + + public void Dispose() + { + IsDisposed = true; + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/LuaClasses/LuaUserData.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/LuaClasses/LuaUserData.cs deleted file mode 100644 index 1cd7fccc2..000000000 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/LuaClasses/LuaUserData.cs +++ /dev/null @@ -1,367 +0,0 @@ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using MoonSharp.Interpreter; -using MoonSharp.Interpreter.Interop; - -namespace Barotrauma -{ - internal class LuaUserData - { - [Obsolete("Use IPluginManagementService::GetTypesByName()")] - public static Type GetType(string typeName) => GameMain.LuaCs.PluginManagementService.GetType(typeName, includeInterfaces: true); //LuaCsSetup.GetType(typeName); - - public static IUserDataDescriptor RegisterType(string typeName) - { - Type type = GetType(typeName); - - if (type == null) - { - throw new ScriptRuntimeException($"tried to register a type that doesn't exist: {typeName}."); - } - - return UserData.RegisterType(type); - } - - public static void RegisterExtensionType(string typeName) - { - Type type = GetType(typeName); - - if (type == null) - { - throw new ScriptRuntimeException($"tried to register a type that doesn't exist: {typeName}."); - } - - UserData.RegisterExtensionType(type); - } - - public static bool IsRegistered(string typeName) - { - Type type = GetType(typeName); - - if (type == null) - { - return false; - } - - return UserData.GetDescriptorForType(type, true) != null; - } - - public static void UnregisterType(string typeName, bool deleteHistory = false) - { - Type type = GetType(typeName); - - if (type == null) - { - throw new ScriptRuntimeException($"tried to unregister a type that doesn't exist: {typeName}."); - } - - UserData.UnregisterType(type, deleteHistory); - } - public static IUserDataDescriptor RegisterGenericType(string typeName, params string[] typeNameArguements) - { - Type type = GetType(typeName); - Type[] typeArguements = typeNameArguements.Select(x => GetType(x)).ToArray(); - Type genericType = type.MakeGenericType(typeArguements); - return UserData.RegisterType(genericType); - } - - public static void UnregisterGenericType(string typeName, params string[] typeNameArguements) - { - Type type = GetType(typeName); - Type[] typeArguements = typeNameArguements.Select(x => GetType(x)).ToArray(); - Type genericType = type.MakeGenericType(typeArguements); - UserData.UnregisterType(genericType); - } - - public static bool IsTargetType(object obj, string typeName) - { - if (obj == null) { throw new ScriptRuntimeException("userdata is nil"); } - Type targetType = GetType(typeName); - if (targetType == null) { throw new ScriptRuntimeException("target type not found"); } - - Type type = obj is Type ? (Type)obj : obj.GetType(); - return targetType.IsAssignableFrom(type); - } - - public static string TypeOf(object obj) - { - if (obj == null) { throw new ScriptRuntimeException("userdata is nil"); } - - return obj.GetType().FullName; - } - - public static object CreateStatic(string typeName) - { - Type type = GetType(typeName); - - if (type == null) - { - throw new ScriptRuntimeException($"tried to create a static userdata of a type that doesn't exist: {typeName}."); - } - - MethodInfo method = typeof(UserData).GetMethod(nameof(UserData.CreateStatic), 1, new Type[0]); - MethodInfo generic = method.MakeGenericMethod(type); - return generic.Invoke(null, null); - } - - public static object CreateEnumTable(string typeName) - { - Type type = GetType(typeName); - - if (type == null) - { - throw new ScriptRuntimeException($"tried to create an enum table with a type that doesn't exist:: {typeName}."); - } - - Dictionary result = new Dictionary(); - - foreach (var value in Enum.GetValues(type)) - { - string name = Enum.GetName(type, value); - - result[name] = value; - } - - return result; - } - - private static FieldInfo FindFieldRecursively(Type type, string fieldName) - { - var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); - - if (field == null && type.BaseType != null) - { - return FindFieldRecursively(type.BaseType, fieldName); - } - - return field; - } - - public static void MakeFieldAccessible(IUserDataDescriptor IUUD, string fieldName) - { - if (IUUD == null) - { - throw new ScriptRuntimeException($"tried to use a UserDataDescriptor that is null to make {fieldName} accessible."); - } - - var descriptor = (StandardUserDataDescriptor)IUUD; - FieldInfo field = FindFieldRecursively(IUUD.Type, fieldName); - - if (field == null) - { - throw new ScriptRuntimeException($"tried to make field '{fieldName}' accessible, but the field doesn't exist."); - } - - descriptor.RemoveMember(fieldName); - descriptor.AddMember(fieldName, new FieldMemberDescriptor(field, InteropAccessMode.Default)); - } - - private static MethodInfo FindMethodRecursively(Type type, string methodName, Type[] types = null) - { - MethodInfo method; - - if (types == null) - { - method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); - } - else - { - method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, types); - } - - if (method == null && type.BaseType != null) - { - return FindMethodRecursively(type.BaseType, methodName, types); - } - - return method; - } - - public static void MakeMethodAccessible(IUserDataDescriptor IUUD, string methodName, string[] parameters = null) - { - if (IUUD == null) - { - throw new ScriptRuntimeException($"tried to use a UserDataDescriptor that is null to make {methodName} accessible."); - } - - Type[] parameterTypes = null; - - - if (parameters != null) - { - parameterTypes = new Type[parameters.Length]; - - for (int i = 0; i < parameters.Length; i++) - { - Type type = LuaUserData.GetType(parameters[i]); - if (type == null) - { - throw new ScriptRuntimeException($"invalid parameter type '{parameters[i]}'"); - } - parameterTypes[i] = type; - } - } - - var descriptor = (StandardUserDataDescriptor)IUUD; - - MethodBase method; - - try - { - method = FindMethodRecursively(IUUD.Type, methodName, parameterTypes); - } - catch (AmbiguousMatchException ex) - { - throw new ScriptRuntimeException("ambiguous method signature."); - } - - if (method == null) - { - throw new ScriptRuntimeException($"tried to make method '{methodName}' accessible, but the method doesn't exist."); - } - - descriptor.AddMember(methodName, new MethodMemberDescriptor(method, InteropAccessMode.Default)); - } - - private static PropertyInfo FindPropertyRecursively(Type type, string propertyName) - { - var property = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); - - if (property == null && type.BaseType != null) - { - return FindPropertyRecursively(type.BaseType, propertyName); - } - - return property; - } - - public static void MakePropertyAccessible(IUserDataDescriptor IUUD, string propertyName) - { - if (IUUD == null) - { - throw new ScriptRuntimeException($"tried to use a UserDataDescriptor that is null to make {propertyName} accessible."); - } - - var descriptor = (StandardUserDataDescriptor)IUUD; - PropertyInfo property = FindPropertyRecursively(IUUD.Type, propertyName); - - if (property == null) - { - throw new ScriptRuntimeException($"tried to make property '{propertyName}' accessible, but the property doesn't exist."); - } - - descriptor.RemoveMember(propertyName); - descriptor.AddMember(propertyName, new PropertyMemberDescriptor(property, InteropAccessMode.Default, property.GetGetMethod(true), property.GetSetMethod(true))); - } - - public static void AddMethod(IUserDataDescriptor IUUD, string methodName, object function) - { - if (IUUD == null) - { - throw new ScriptRuntimeException($"tried to use a UserDataDescriptor that is null to add method {methodName}."); - } - - var descriptor = (StandardUserDataDescriptor)IUUD; - - descriptor.RemoveMember(methodName); - descriptor.AddMember(methodName, new ObjectCallbackMemberDescriptor(methodName, (object arg1, ScriptExecutionContext arg2, CallbackArguments arg3) => - { - /*if (GameMain.LuaCs != null) - return GameMain.LuaCs.CallLuaFunction(function, arg3.GetArray()); - return null;*/ - throw new NotImplementedException(); - })); - } - - public static void AddField(IUserDataDescriptor IUUD, string fieldName, DynValue value) - { - if (IUUD == null) - { - throw new ScriptRuntimeException($"tried to use a UserDataDescriptor that is null to add field {fieldName}."); - } - - var descriptor = (StandardUserDataDescriptor)IUUD; - descriptor.RemoveMember(fieldName); - descriptor.AddMember(fieldName, new DynValueMemberDescriptor(fieldName, value)); - } - - public static void RemoveMember(IUserDataDescriptor IUUD, string memberName) - { - if (IUUD == null) - { - throw new ScriptRuntimeException($"tried to use a UserDataDescriptor that is null to remove the member {memberName}."); - } - - var descriptor = (StandardUserDataDescriptor)IUUD; - descriptor.RemoveMember(memberName); - } - - public static bool HasMember(object obj, string memberName) - { - if (obj == null) { throw new ScriptRuntimeException("object is nil"); } - - Type type; - if (obj is Type) - { - type = (Type)obj; - } - else if(obj is IUserDataDescriptor descriptor) - { - type = descriptor.Type; - - if (((StandardUserDataDescriptor)descriptor).HasMember(memberName)) - { - return true; - } - } - else - { - type = obj.GetType(); - } - - if (type.GetMember(memberName).Length == 0) - { - return false; - } - - return true; - } - - - /// - /// See . - /// - /// Lua value to convert and wrap in a userdata. - /// Descriptor of the type of the object to convert the Lua value to. Uses MoonSharp ScriptToClr converters. - /// A userdata that wraps the Lua value converted to an object of the desired type as described by . - public static DynValue CreateUserDataFromDescriptor(DynValue scriptObject, IUserDataDescriptor desiredTypeDescriptor) - { - return UserData.Create(scriptObject.ToObject(desiredTypeDescriptor.Type), desiredTypeDescriptor); - } - - /// - /// Converts a Lua value to a CLR object of a desired type and wraps it in a userdata. - /// If the type is not registered, then a new will be created and used. - /// The goal of this method is to allow Lua scripts to create userdata to wrap certain data without having to register types. - /// Wrapping the value in a userdata preserves the original type during script-to-CLR conversions. - /// A Lua script needs to pass a List`1 to a CLR method expecting System.Object, MoonSharp gets - /// in the way by converting the List`1 to a MoonSharp.Interpreter.Table and breaking everything. - /// Registering the List`1 type can break other scripts relying on default converters, so instead - /// it is better to manually wrap the List`1 object into a userdata. - /// - /// - /// Lua value to convert and wrap in a userdata. - /// Type describing the CLR type of the object to convert the Lua value to. - /// A userdata that wraps the Lua value converted to an object of the desired type. - public static DynValue CreateUserDataFromType(DynValue scriptObject, Type desiredType) - { - IUserDataDescriptor descriptor = UserData.GetDescriptorForType(desiredType, true); - descriptor ??= new StandardUserDataDescriptor(desiredType, InteropAccessMode.Default); - return CreateUserDataFromDescriptor(scriptObject, descriptor); - } - } -} - diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/LuaUserDataService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/LuaUserDataService.cs new file mode 100644 index 000000000..51a20c41d --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/LuaUserDataService.cs @@ -0,0 +1,440 @@ +using MoonSharp.Interpreter; +using MoonSharp.Interpreter.Interop; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace Barotrauma.LuaCs.Services; + +public interface ILuaUserDataService : IReusableService +{ + IReadOnlyDictionary Descriptors { get; } + IUserDataDescriptor RegisterType(string typeName); + void RegisterExtensionType(string typeName); + bool IsRegistered(string typeName); + void UnregisterType(string typeName, bool deleteHistory = false); + object CreateStatic(string typeName); + bool IsTargetType(object obj, string typeName); + string TypeOf(object obj); + object CreateEnumTable(string typeName); + void MakeFieldAccessible(IUserDataDescriptor IUUD, string fieldName); + void MakeMethodAccessible(IUserDataDescriptor IUUD, string methodName, string[] parameters = null); + void MakePropertyAccessible(IUserDataDescriptor IUUD, string propertyName); + void AddMethod(IUserDataDescriptor IUUD, string methodName, object function); + void AddField(IUserDataDescriptor IUUD, string fieldName, DynValue value); + void RemoveMember(IUserDataDescriptor IUUD, string memberName); + bool HasMember(object obj, string memberName); + /// + /// See . + /// + /// Lua value to convert and wrap in a userdata. + /// Descriptor of the type of the object to convert the Lua value to. Uses MoonSharp ScriptToClr converters. + /// A userdata that wraps the Lua value converted to an object of the desired type as described by . + DynValue CreateUserDataFromDescriptor(DynValue scriptObject, IUserDataDescriptor desiredTypeDescriptor); + + /// + /// Converts a Lua value to a CLR object of a desired type and wraps it in a userdata. + /// If the type is not registered, then a new will be created and used. + /// The goal of this method is to allow Lua scripts to create userdata to wrap certain data without having to register types. + /// Wrapping the value in a userdata preserves the original type during script-to-CLR conversions. + /// A Lua script needs to pass a List`1 to a CLR method expecting System.Object, MoonSharp gets + /// in the way by converting the List`1 to a MoonSharp.Interpreter.Table and breaking everything. + /// Registering the List`1 type can break other scripts relying on default converters, so instead + /// it is better to manually wrap the List`1 object into a userdata. + /// + /// + /// Lua value to convert and wrap in a userdata. + /// Type describing the CLR type of the object to convert the Lua value to. + /// A userdata that wraps the Lua value converted to an object of the desired type. + DynValue CreateUserDataFromType(DynValue scriptObject, Type desiredType); + + void AddCallMetaTable(object userdata); +} + +public class LuaUserDataService : ILuaUserDataService +{ + public bool IsDisposed { get; private set; } + + public IReadOnlyDictionary Descriptors => descriptors; + private ConcurrentDictionary descriptors; + + private readonly IPluginManagementService _pluginManagementService; + + public LuaUserDataService(IPluginManagementService pluginManagementService) + { + descriptors = new ConcurrentDictionary(); + _pluginManagementService = pluginManagementService; + } + + public IUserDataDescriptor this[string key] + { + get + { + return descriptors.GetValueOrDefault(key); + } + } + + private Type GetType(string typeName) => _pluginManagementService.GetType(typeName, includeInterfaces: true); + + public IUserDataDescriptor RegisterType(string typeName) + { + Type type = GetType(typeName); + + if (type == null) + { + throw new ScriptRuntimeException($"tried to register a type that doesn't exist: {typeName}."); + } + + return UserData.RegisterType(type, new CallableUserDataDescriptor(type)); + } + + public void RegisterExtensionType(string typeName) + { + Type type = GetType(typeName); + + if (type == null) + { + throw new ScriptRuntimeException($"tried to register a type that doesn't exist: {typeName}."); + } + + UserData.RegisterExtensionType(type); + } + + public bool IsRegistered(string typeName) + { + Type type = GetType(typeName); + + if (type == null) + { + return false; + } + + return UserData.GetDescriptorForType(type, true) != null; + } + + public void UnregisterType(string typeName, bool deleteHistory = false) + { + Type type = GetType(typeName); + + if (type == null) + { + throw new ScriptRuntimeException($"tried to unregister a type that doesn't exist: {typeName}."); + } + + UserData.UnregisterType(type, deleteHistory); + } + + public bool IsTargetType(object obj, string typeName) + { + if (obj == null) { throw new ScriptRuntimeException("userdata is nil"); } + Type targetType = GetType(typeName); + if (targetType == null) { throw new ScriptRuntimeException("target type not found"); } + + Type type = obj is Type ? (Type)obj : obj.GetType(); + return targetType.IsAssignableFrom(type); + } + + public string TypeOf(object obj) + { + if (obj == null) { throw new ScriptRuntimeException("userdata is nil"); } + + return obj.GetType().FullName; + } + + public object CreateEnumTable(string typeName) + { + Type type = GetType(typeName); + + if (type == null) + { + throw new ScriptRuntimeException($"tried to create an enum table with a type that doesn't exist:: {typeName}."); + } + + Dictionary result = new Dictionary(); + + foreach (var value in Enum.GetValues(type)) + { + string name = Enum.GetName(type, value); + + result[name] = value; + } + + return result; + } + + public object CreateStatic(string typeName) + { + Type type = GetType(typeName); + + if (type == null) + { + throw new ScriptRuntimeException($"tried to create a static userdata of a type that doesn't exist: {typeName}."); + } + + MethodInfo method = typeof(UserData).GetMethod(nameof(UserData.CreateStatic), 1, new Type[0]); + MethodInfo generic = method.MakeGenericMethod(type); + return generic.Invoke(null, null); + } + + private FieldInfo FindFieldRecursively(Type type, string fieldName) + { + var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + + if (field == null && type.BaseType != null) + { + return FindFieldRecursively(type.BaseType, fieldName); + } + + return field; + } + + public void MakeFieldAccessible(IUserDataDescriptor IUUD, string fieldName) + { + if (IUUD == null) + { + throw new ScriptRuntimeException($"tried to use a UserDataDescriptor that is null to make {fieldName} accessible."); + } + + var descriptor = (StandardUserDataDescriptor)IUUD; + FieldInfo field = FindFieldRecursively(IUUD.Type, fieldName); + + if (field == null) + { + throw new ScriptRuntimeException($"tried to make field '{fieldName}' accessible, but the field doesn't exist."); + } + + descriptor.RemoveMember(fieldName); + descriptor.AddMember(fieldName, new FieldMemberDescriptor(field, InteropAccessMode.Default)); + } + + private MethodInfo FindMethodRecursively(Type type, string methodName, Type[] types = null) + { + MethodInfo method; + + if (types == null) + { + method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + } + else + { + method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, types); + } + + if (method == null && type.BaseType != null) + { + return FindMethodRecursively(type.BaseType, methodName, types); + } + + return method; + } + + public void MakeMethodAccessible(IUserDataDescriptor IUUD, string methodName, string[] parameters = null) + { + if (IUUD == null) + { + throw new ScriptRuntimeException($"tried to use a UserDataDescriptor that is null to make {methodName} accessible."); + } + + Type[] parameterTypes = null; + + + if (parameters != null) + { + parameterTypes = new Type[parameters.Length]; + + for (int i = 0; i < parameters.Length; i++) + { + Type type = GetType(parameters[i]); + if (type == null) + { + throw new ScriptRuntimeException($"invalid parameter type '{parameters[i]}'"); + } + parameterTypes[i] = type; + } + } + + var descriptor = (StandardUserDataDescriptor)IUUD; + + MethodBase method; + + try + { + method = FindMethodRecursively(IUUD.Type, methodName, parameterTypes); + } + catch (AmbiguousMatchException ex) + { + throw new ScriptRuntimeException("ambiguous method signature."); + } + + if (method == null) + { + throw new ScriptRuntimeException($"tried to make method '{methodName}' accessible, but the method doesn't exist."); + } + + descriptor.AddMember(methodName, new MethodMemberDescriptor(method, InteropAccessMode.Default)); + } + + private PropertyInfo FindPropertyRecursively(Type type, string propertyName) + { + var property = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + + if (property == null && type.BaseType != null) + { + return FindPropertyRecursively(type.BaseType, propertyName); + } + + return property; + } + + public void MakePropertyAccessible(IUserDataDescriptor IUUD, string propertyName) + { + if (IUUD == null) + { + throw new ScriptRuntimeException($"tried to use a UserDataDescriptor that is null to make {propertyName} accessible."); + } + + var descriptor = (StandardUserDataDescriptor)IUUD; + PropertyInfo property = FindPropertyRecursively(IUUD.Type, propertyName); + + if (property == null) + { + throw new ScriptRuntimeException($"tried to make property '{propertyName}' accessible, but the property doesn't exist."); + } + + descriptor.RemoveMember(propertyName); + descriptor.AddMember(propertyName, new PropertyMemberDescriptor(property, InteropAccessMode.Default, property.GetGetMethod(true), property.GetSetMethod(true))); + } + + public void AddMethod(IUserDataDescriptor IUUD, string methodName, object function) + { + if (IUUD == null) + { + throw new ScriptRuntimeException($"tried to use a UserDataDescriptor that is null to add method {methodName}."); + } + + var descriptor = (StandardUserDataDescriptor)IUUD; + + descriptor.RemoveMember(methodName); + descriptor.AddMember(methodName, new ObjectCallbackMemberDescriptor(methodName, (object arg1, ScriptExecutionContext arg2, CallbackArguments arg3) => + { + /*if (GameMain.LuaCs != null) + return GameMain.LuaCs.CallLuaFunction(function, arg3.GetArray()); + return null;*/ + throw new NotImplementedException(); + })); + } + + public void AddField(IUserDataDescriptor IUUD, string fieldName, DynValue value) + { + if (IUUD == null) + { + throw new ScriptRuntimeException($"tried to use a UserDataDescriptor that is null to add field {fieldName}."); + } + + var descriptor = (StandardUserDataDescriptor)IUUD; + descriptor.RemoveMember(fieldName); + descriptor.AddMember(fieldName, new DynValueMemberDescriptor(fieldName, value)); + } + + public void RemoveMember(IUserDataDescriptor IUUD, string memberName) + { + if (IUUD == null) + { + throw new ScriptRuntimeException($"tried to use a UserDataDescriptor that is null to remove the member {memberName}."); + } + + var descriptor = (StandardUserDataDescriptor)IUUD; + descriptor.RemoveMember(memberName); + } + + public bool HasMember(object obj, string memberName) + { + if (obj == null) { throw new ScriptRuntimeException("object is nil"); } + + Type type; + if (obj is Type) + { + type = (Type)obj; + } + else if (obj is IUserDataDescriptor descriptor) + { + type = descriptor.Type; + + if (((StandardUserDataDescriptor)descriptor).HasMember(memberName)) + { + return true; + } + } + else + { + type = obj.GetType(); + } + + if (type.GetMember(memberName).Length == 0) + { + return false; + } + + return true; + } + + + public DynValue CreateUserDataFromDescriptor(DynValue scriptObject, IUserDataDescriptor desiredTypeDescriptor) + { + return UserData.Create(scriptObject.ToObject(desiredTypeDescriptor.Type), desiredTypeDescriptor); + } + + public DynValue CreateUserDataFromType(DynValue scriptObject, Type desiredType) + { + IUserDataDescriptor descriptor = UserData.GetDescriptorForType(desiredType, true); + descriptor ??= new StandardUserDataDescriptor(desiredType, InteropAccessMode.Default); + return CreateUserDataFromDescriptor(scriptObject, descriptor); + } + + public void AddCallMetaTable(object userdata) { } + + public void Dispose() + { + IsDisposed = true; + descriptors.Clear(); + } + + public FluentResults.Result Reset() + { + descriptors.Clear(); + return FluentResults.Result.Ok(); + } +} + +sealed class CallableUserDataDescriptor : StandardUserDataDescriptor +{ + public CallableUserDataDescriptor(Type type) + : base(type, InteropAccessMode.Default) + { + } + + public override DynValue MetaIndex(Script script, object obj, string metaname) + { + if (metaname == "__call") + { + return DynValue.NewCallback((ctx, args) => + { + var self = args[0]; + + var ctor = base.Index(script, obj, DynValue.NewString("__new"), true); + + if (ctor == null || ctor.IsNil()) + { + throw new ScriptRuntimeException("Attempted to call userdata without __new."); + } + + var callArgs = args.GetArray().Skip(1).ToArray(); + return script.Call(ctor, callArgs); + }); + } + + return base.MetaIndex(script, obj, metaname); + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/SafeLuaUserDataService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/SafeLuaUserDataService.cs new file mode 100644 index 000000000..9f2dc0130 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Safe/SafeLuaUserDataService.cs @@ -0,0 +1,234 @@ +using Barotrauma; +using Barotrauma.LuaCs.Services; +using MoonSharp.Interpreter; +using MoonSharp.Interpreter.Interop; +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace Barotrauma.LuaCs.Services; + +public interface ISafeLuaUserDataService : IService +{ + bool IsAllowed(string typeName); + IUserDataDescriptor RegisterType(string typeName); + void RegisterExtensionType(string typeName); + bool IsRegistered(string typeName); + void UnregisterType(string typeName, bool deleteHistory = false); + object CreateStatic(string typeName); + bool IsTargetType(object obj, string typeName); + string TypeOf(object obj); + object CreateEnumTable(string typeName); + void MakeFieldAccessible(IUserDataDescriptor IUUD, string fieldName); + void MakeMethodAccessible(IUserDataDescriptor IUUD, string methodName, string[] parameters = null); + void MakePropertyAccessible(IUserDataDescriptor IUUD, string propertyName); + void AddMethod(IUserDataDescriptor IUUD, string methodName, object function); + void AddField(IUserDataDescriptor IUUD, string fieldName, DynValue value); + void RemoveMember(IUserDataDescriptor IUUD, string memberName); + bool HasMember(object obj, string memberName); + /// + /// See . + /// + /// Lua value to convert and wrap in a userdata. + /// Descriptor of the type of the object to convert the Lua value to. Uses MoonSharp ScriptToClr converters. + /// A userdata that wraps the Lua value converted to an object of the desired type as described by . + DynValue CreateUserDataFromDescriptor(DynValue scriptObject, IUserDataDescriptor desiredTypeDescriptor); + + /// + /// Converts a Lua value to a CLR object of a desired type and wraps it in a userdata. + /// If the type is not registered, then a new will be created and used. + /// The goal of this method is to allow Lua scripts to create userdata to wrap certain data without having to register types. + /// Wrapping the value in a userdata preserves the original type during script-to-CLR conversions. + /// A Lua script needs to pass a List`1 to a CLR method expecting System.Object, MoonSharp gets + /// in the way by converting the List`1 to a MoonSharp.Interpreter.Table and breaking everything. + /// Registering the List`1 type can break other scripts relying on default converters, so instead + /// it is better to manually wrap the List`1 object into a userdata. + /// + /// + /// Lua value to convert and wrap in a userdata. + /// Type describing the CLR type of the object to convert the Lua value to. + /// A userdata that wraps the Lua value converted to an object of the desired type. + DynValue CreateUserDataFromType(DynValue scriptObject, Type desiredType); + void AddCallMetaTable(object userdata); +} + +public class SafeLuaUserDataService : ISafeLuaUserDataService +{ + private readonly ILuaUserDataService _userDataService; + + public bool IsDisposed { get; private set; } + + public SafeLuaUserDataService(ILuaUserDataService userDataService) + { + _userDataService = userDataService; + } + + public IUserDataDescriptor this[string key] + { + get + { + return _userDataService.Descriptors.GetValueOrDefault(key); + } + } + + private bool CanBeRegistered(string typeName) + { + if (typeName.StartsWith("Barotrauma.Lua", StringComparison.Ordinal) || + typeName.StartsWith("Barotrauma.Cs", StringComparison.Ordinal) || + typeName.StartsWith("Barotrauma.LuaCs", StringComparison.Ordinal)) + { + return false; + } + + if (typeName == "System.Single") { return true; } + + if (typeName.StartsWith("System.Collections", StringComparison.Ordinal)) + return true; + + if (typeName.StartsWith("Microsoft.Xna", StringComparison.Ordinal)) + return true; + + if (typeName.StartsWith("Barotrauma.IO", StringComparison.Ordinal)) + return false; + + if (typeName.StartsWith("Barotrauma.ToolBox", StringComparison.Ordinal)) + return false; + + if (typeName.StartsWith("Barotrauma.SaveUtil", StringComparison.Ordinal)) + return false; + + if (typeName.StartsWith("Barotrauma.", StringComparison.Ordinal)) + return true; + + return false; + } + + private bool CanBeReRegistered(string typeName) + { + if (typeName.StartsWith("Barotrauma.Lua", StringComparison.Ordinal) || + typeName.StartsWith("Barotrauma.Cs", StringComparison.Ordinal) || + typeName.StartsWith("Barotrauma.LuaCs", StringComparison.Ordinal)) + { + return false; + } + + return true; + } + + public bool IsAllowed(string typeName) + { + if (!CanBeReRegistered(typeName) && IsRegistered(typeName)) + { + return false; + } + + if (!CanBeRegistered(typeName)) + { + return false; + } + + return true; + } + + private void CheckAllowed(string typeName) + { + if (!IsAllowed(typeName)) + { + throw new ScriptRuntimeException($"Type {typeName} can't be registered"); + } + } + + public IUserDataDescriptor RegisterType(string typeName) + { + CheckAllowed(typeName); + return _userDataService.RegisterType(typeName); + } + + public void RegisterExtensionType(string typeName) + { + CheckAllowed(typeName); + _userDataService.RegisterExtensionType(typeName); + } + + public bool IsRegistered(string typeName) + { + return _userDataService.IsRegistered(typeName); + } + + public void UnregisterType(string typeName, bool deleteHistory = false) + { + IsAllowed(typeName); + _userDataService.UnregisterType(typeName, deleteHistory); + } + public object CreateStatic(string typeName) + { + return _userDataService.CreateStatic(typeName); + } + + public bool IsTargetType(object obj, string typeName) + { + return _userDataService.IsTargetType(obj, typeName); + } + + public string TypeOf(object obj) + { + return _userDataService.TypeOf(obj); + } + + public object CreateEnumTable(string typeName) + { + return _userDataService.CreateEnumTable(typeName); + } + + public void MakeFieldAccessible(IUserDataDescriptor IUUD, string fieldName) + { + _userDataService.MakeFieldAccessible(IUUD, fieldName); + } + + public void MakeMethodAccessible(IUserDataDescriptor IUUD, string methodName, string[] parameters = null) + { + _userDataService.MakeMethodAccessible(IUUD, methodName, parameters); + } + + public void MakePropertyAccessible(IUserDataDescriptor IUUD, string propertyName) + { + _userDataService.MakePropertyAccessible(IUUD, propertyName); + } + + public void AddMethod(IUserDataDescriptor IUUD, string methodName, object function) + { + _userDataService.AddMethod(IUUD, methodName, function); + } + + public void AddField(IUserDataDescriptor IUUD, string fieldName, DynValue value) + { + _userDataService.AddField(IUUD, fieldName, value); + } + + public void RemoveMember(IUserDataDescriptor IUUD, string memberName) + { + _userDataService.RemoveMember(IUUD, memberName); + } + + public bool HasMember(object obj, string memberName) + { + return _userDataService.HasMember(obj, memberName); + } + + public DynValue CreateUserDataFromDescriptor(DynValue scriptObject, IUserDataDescriptor desiredTypeDescriptor) + { + return _userDataService.CreateUserDataFromDescriptor(scriptObject, desiredTypeDescriptor); + } + + public DynValue CreateUserDataFromType(DynValue scriptObject, Type desiredType) + { + return _userDataService.CreateUserDataFromType(scriptObject, desiredType); + } + + public void AddCallMetaTable(object userdata) { } + + public void Dispose() + { + IsDisposed = true; + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/ILuaScriptManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/ILuaScriptManagementService.cs index f53cee1ed..d05a8e046 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/ILuaScriptManagementService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/ILuaScriptManagementService.cs @@ -58,10 +58,4 @@ public interface ILuaScriptManagementService : IReusableService #endregion - #region Type_Registration - - IUserDataDescriptor RegisterType(Type type); - void UnregisterType(Type type); - - #endregion }