using Barotrauma.Items.Components; using Barotrauma.LuaCs.Data; using Barotrauma.Networking; using FarseerPhysics.Dynamics; using Microsoft.Xna.Framework; using MoonSharp.Interpreter; using Steamworks.Ugc; using System; using System.Collections.Generic; using System.Reflection; namespace Barotrauma.LuaCs.Events; /* * The following is a collection of interfaces that types can implement to be registered events. * Note: Internally-marked interfaces should be consumed using a publicizer. This is due to the Barotrauma source * types being internal by default. */ public interface IEvent { bool IsLuaRunner() => false; public abstract class LuaWrapperBase : IEvent { protected readonly IDictionary LuaFuncs; protected LuaWrapperBase(IDictionary luaFuncs) => LuaFuncs = luaFuncs; public bool IsLuaRunner() => true; } } public interface IEvent : IEvent where T : class, IEvent { static virtual T GetLuaRunner(IDictionary luaFunc) { throw new InvalidOperationException($"Lua runners forbidden for {typeof(T).Name}"); } } #region RuntimeServiceEvents /// /// Called when the current (game state) changes. Upstream Type 'Screen' is internal. /// internal interface IEventScreenSelected : IEvent { void OnScreenSelected(Screen screen); } /// /// Called whenever the list of all (enabled and disabled) on disk has changed. /// internal interface IEventAllPackageListChanged : IEvent { void OnAllPackageListChanged(IEnumerable corePackages, IEnumerable regularPackages); } /// /// Called whenever the list of enabled has changed. /// internal interface IEventEnabledPackageListChanged : IEvent { void OnEnabledPackageListChanged(CorePackage package, IEnumerable regularPackages); } internal interface IEventReloadAllPackages : IEvent { void OnReloadAllPackages(); } internal interface IEventSettingInstanceLifetime : IEvent { void OnSettingInstanceCreated(T configInstance) where T : ISettingBase; void OnSettingInstanceDisposed(T configInstance) where T : ISettingBase; } #endregion #region GameEvents internal interface IEventAfflictionUpdate : IEvent { void OnAfflictionUpdate(Affliction affliction, CharacterHealth characterHealth, Limb targetLimb, float deltaTime); static IEventAfflictionUpdate IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventAfflictionUpdate { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnAfflictionUpdate(Affliction affliction, CharacterHealth characterHealth, Limb targetLimb, float deltaTime) { LuaFuncs[nameof(OnAfflictionUpdate)](affliction, characterHealth, targetLimb, deltaTime); } } } internal interface IEventGiveCharacterJobItems : IEvent { void OnGiveCharacterJobItems(Character character, WayPoint spawnPoint, bool isPvPMode); static IEventGiveCharacterJobItems IEvent.GetLuaRunner( IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventGiveCharacterJobItems { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnGiveCharacterJobItems(Character character, WayPoint spawnPoint, bool isPvPMode) { LuaFuncs[nameof(OnGiveCharacterJobItems)](character, spawnPoint, isPvPMode); } } } internal interface IEventCharacterCreated : IEvent { void OnCharacterCreated(Character character); static IEventCharacterCreated IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventCharacterCreated { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnCharacterCreated(Character character) { LuaFuncs[nameof(OnCharacterCreated)](character); } } } // TODO: harmony-fy internal interface IEventHumanCPRSuccess : IEvent { void OnCharacterCPRSuccess(HumanoidAnimController animController); static IEventHumanCPRSuccess IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventHumanCPRSuccess { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnCharacterCPRSuccess(HumanoidAnimController animController) { LuaFuncs[nameof(OnCharacterCPRSuccess)](animController); } } } // TODO: harmony-fy internal interface IEventHumanCPRFailed : IEvent { void OnCharacterCPRFailed(HumanoidAnimController animController); static IEventHumanCPRFailed IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventHumanCPRFailed { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnCharacterCPRFailed(HumanoidAnimController animController) { LuaFuncs[nameof(OnCharacterCPRFailed)](animController); } } } // TODO: harmony-fy internal interface IEventClientControlHusk : IEvent { void OnClientControlHusk(Client client, Character husk); static IEventClientControlHusk IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventClientControlHusk { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnClientControlHusk(Client client, Character husk) { LuaFuncs[nameof(OnClientControlHusk)](client, husk); } } } // TODO: harmony-fy internal interface IEventMeleeWeaponHandleImpact : IEvent { void OnMeleeWeaponHandleImpact(MeleeWeapon meleeWeapon, Body target); static IEventMeleeWeaponHandleImpact IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventMeleeWeaponHandleImpact { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnMeleeWeaponHandleImpact(MeleeWeapon meleeWeapon, Body target) { LuaFuncs[nameof(OnMeleeWeaponHandleImpact)](meleeWeapon, target); } } } // TODO: harmony-fy internal interface IEventServerLog : IEvent { void OnServerLog(string line, ServerLog.MessageType messageType); static IEventServerLog IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventServerLog { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnServerLog(string line, ServerLog.MessageType messageType) { LuaFuncs[nameof(OnServerLog)](line, messageType); } } } // TODO: harmony-fy internal interface IEventChatMessage : IEvent { bool? OnChatMessage(string messageText, Client sender, ChatMessageType type, ChatMessage message); static IEventChatMessage IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventChatMessage { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnChatMessage(string messageText, Client sender, ChatMessageType type, ChatMessage message) { object result = LuaFuncs[nameof(OnChatMessage)](messageText, sender, type, message); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } // TODO: harmony-fy internal interface IEventTryClientChangeName : IEvent { bool? OnTryClienChangeName(Client client, string newName, Identifier newJob, CharacterTeamType newTeam); static IEventTryClientChangeName IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventTryClientChangeName { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnTryClienChangeName(Client client, string newName, Identifier newJob, CharacterTeamType newTeam) { var result = LuaFuncs[nameof(OnTryClienChangeName)](client, newName, newJob, newTeam); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } // TODO: harmony-fy internal interface IEventChangeFallDamage : IEvent { float? OnChangeFallDamage(float impactDamage, Character character, Vector2 impactPos, Vector2 velocity); static IEventChangeFallDamage IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventChangeFallDamage { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public float? OnChangeFallDamage(float impactDamage, Character character, Vector2 impactPos, Vector2 velocity) { var result = LuaFuncs[nameof(OnChangeFallDamage)](impactDamage, character, impactPos, velocity); if (result is DynValue dynValue && dynValue.Type == DataType.Number) { return (float)dynValue.Number; } return null; } } } // TODO: harmony-fy internal interface IEventGapOxygenUpdate : IEvent { bool? OnGapOxygenUpdate(Gap gap, Hull hull1, Hull hull2); static IEventGapOxygenUpdate IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventGapOxygenUpdate { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnGapOxygenUpdate(Gap gap, Hull hull1, Hull hull2) { var result = LuaFuncs[nameof(OnGapOxygenUpdate)](gap, hull1, hull2); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } // TODO: harmony-fy internal interface IEventCharacterApplyDamage : IEvent { bool? OnCharacterApplyDamage(CharacterHealth characterHealth, AttackResult attackResult, Limb hitLimb, bool allowStacking); static IEventCharacterApplyDamage IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventCharacterApplyDamage { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnCharacterApplyDamage(CharacterHealth characterHealth, AttackResult attackResult, Limb hitLimb, bool allowStacking) { var result = LuaFuncs[nameof(OnCharacterApplyDamage)](characterHealth, attackResult, hitLimb, allowStacking); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } // TODO: harmony-fy internal interface IEventCharacterApplyAffliction : IEvent { bool? OnCharacterApplyAffliction(CharacterHealth characterHealth, CharacterHealth.LimbHealth limbHealth, Affliction newAffliction, bool allowStacking); static IEventCharacterApplyAffliction IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventCharacterApplyAffliction { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnCharacterApplyAffliction(CharacterHealth characterHealth, CharacterHealth.LimbHealth limbHealth, Affliction newAffliction, bool allowStacking) { var result = LuaFuncs[nameof(OnCharacterApplyAffliction)](characterHealth, limbHealth, newAffliction, allowStacking); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } // TODO: harmony-fy internal interface IEventItemReadPropertyChange : IEvent { bool? OnItemReadPropertyChange(Item item, SerializableProperty property, object parentObject, bool allowEditing, Client sender); static IEventItemReadPropertyChange IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventItemReadPropertyChange { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnItemReadPropertyChange(Item item, SerializableProperty property, object parentObject, bool allowEditing, Client sender) { var result = LuaFuncs[nameof(OnItemReadPropertyChange)](item, property, parentObject, allowEditing, sender); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } // TODO: harmony-fy internal interface IEventCanUseVoiceRadio : IEvent { bool? OnCanUseVoiceRadio(Client sender, Client recipient); static IEventCanUseVoiceRadio IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventCanUseVoiceRadio { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnCanUseVoiceRadio(Client sender, Client recipient) { var result = LuaFuncs[nameof(OnCanUseVoiceRadio)](sender, recipient); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } // TODO: harmony-fy internal interface IEventChangeLocalVoiceRange : IEvent { float? OnChangeLocalVoiceRange(Client sender, Client recipient); static IEventChangeLocalVoiceRange IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventChangeLocalVoiceRange { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public float? OnChangeLocalVoiceRange(Client sender, Client recipient) { var result = LuaFuncs[nameof(OnChangeLocalVoiceRange)](sender, recipient); if (result is DynValue dynValue && dynValue.Type == DataType.Number) { return (float)dynValue.Number; } return null; } } } // TODO: harmony-fy internal interface IEventItemDeconstructed : IEvent { bool? OnItemDeconstructed(Item item, Deconstructor deconstructor, Character user, bool allowRemove); static IEventItemDeconstructed IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventItemDeconstructed { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnItemDeconstructed(Item item, Deconstructor deconstructor, Character user, bool allowRemove) { var result = LuaFuncs[nameof(OnItemDeconstructed)](item, deconstructor, user, allowRemove); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } // TODO: harmony-fy internal interface IEventWifiSignalTransmitted : IEvent { bool? OnWifiSignalTransmitted(WifiComponent wifiComponent, Signal signal, bool sentFromChat); static IEventWifiSignalTransmitted IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventWifiSignalTransmitted { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnWifiSignalTransmitted(WifiComponent wifiComponent, Signal signal, bool sentFromChat) { var result = LuaFuncs[nameof(OnWifiSignalTransmitted)](wifiComponent, signal, sentFromChat); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } internal interface IEventCharacterDeath : IEvent { void OnCharacterDeath(Character character, Affliction causeOfDeathAffliction, CauseOfDeathType causeOfDeathType); static IEventCharacterDeath IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventCharacterDeath { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnCharacterDeath(Character character, Affliction causeOfDeathAffliction, CauseOfDeathType causeOfDeathType) { LuaFuncs[nameof(OnCharacterDeath)](character, causeOfDeathAffliction, causeOfDeathType); } } } public interface IEventKeyUpdate : IEvent { void OnKeyUpdate(double deltaTime); static IEventKeyUpdate IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventKeyUpdate { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnKeyUpdate(double deltaTime) { LuaFuncs[nameof(OnKeyUpdate)](deltaTime); } } } /// /// Called as soon as round begins to load before any loading takes place. /// public interface IEventRoundStarting : IEvent { void OnRoundStarting(); static IEventRoundStarting IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventRoundStarting { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnRoundStarting() { LuaFuncs[nameof(OnRoundStarting)](); } } } /// /// Called when a round has started and fully loaded. /// public interface IEventRoundStarted : IEvent { void OnRoundStart(); static IEventRoundStarted IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventRoundStarted { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnRoundStart() { LuaFuncs[nameof(OnRoundStart)](); } } } /// /// Called when a round has ended. /// public interface IEventRoundEnded : IEvent { void OnRoundEnd(); static IEventRoundEnded IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventRoundEnded { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnRoundEnd() { LuaFuncs[nameof(OnRoundEnd)](); } } } internal interface IEventMissionsEnded : IEvent { void OnMissionsEnded(IReadOnlyList missions); static IEventMissionsEnded IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventMissionsEnded { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnMissionsEnded(IReadOnlyList missions) { LuaFuncs[nameof(OnMissionsEnded)](missions); } } } /// /// Called on game loop normal update. /// public interface IEventUpdate : IEvent { void OnUpdate(double fixedDeltaTime); static IEventUpdate IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventUpdate { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnUpdate(double deltaTime) { LuaFuncs[nameof(OnUpdate)](deltaTime); } } } /// /// Called on game loop draw update. /// public interface IEventDrawUpdate : IEvent { void OnDrawUpdate(double deltaTime); static IEventDrawUpdate IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventDrawUpdate { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnDrawUpdate(double deltaTime) { LuaFuncs[nameof(OnDrawUpdate)](deltaTime); } } } interface IEventSignalReceived : IEvent { void OnSignalReceived(Signal signal, Connection connection); static IEventSignalReceived IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventSignalReceived { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnSignalReceived(Signal signal, Connection connection) { LuaFuncs[nameof(OnSignalReceived)](signal, connection); } } } interface IEventItemCreated : IEvent { void OnItemCreated(Item item); static IEventItemCreated IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventItemCreated { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnItemCreated(Item item) { LuaFuncs[nameof(OnItemCreated)](item); } } } interface IEventItemRemoved : IEvent { void OnItemRemoved(Item item); static IEventItemRemoved IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventItemRemoved { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnItemRemoved(Item item) { LuaFuncs[nameof(OnItemRemoved)](item); } } } interface IEventItemUse : IEvent { bool? OnItemUsed(Item item, Character user, Limb targetLimb, Entity useTarget); static IEventItemUse IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventItemUse { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnItemUsed(Item item, Character user, Limb targetLimb, Entity useTarget) { var result = LuaFuncs[nameof(OnItemUsed)](item, user, targetLimb, useTarget); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } interface IEventItemSecondaryUse : IEvent { bool? OnItemSecondaryUsed(Item item, Character user); static IEventItemSecondaryUse IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventItemSecondaryUse { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnItemSecondaryUsed(Item item, Character user) { var result = LuaFuncs[nameof(OnItemSecondaryUsed)](item, user); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } interface IEventCharacterDamageLimb : IEvent { AttackResult? OnCharacterDamageLimb(Character character, Vector2 worldPosition, Limb hitLimb, IEnumerable afflictions, float stun, bool playSound, Vector2 attackImpulse, Character attacker = null, float damageMultiplier = 1, bool allowStacking = true, float penetration = 0f, bool shouldImplode = false); static IEventCharacterDamageLimb IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventCharacterDamageLimb { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public AttackResult? OnCharacterDamageLimb(Character character, Vector2 worldPosition, Limb hitLimb, IEnumerable afflictions, float stun, bool playSound, Vector2 attackImpulse, Character attacker = null, float damageMultiplier = 1, bool allowStacking = true, float penetration = 0f, bool shouldImplode = false) { object result = LuaFuncs[nameof(OnCharacterDamageLimb)](character, worldPosition, hitLimb, afflictions, stun, playSound, attackImpulse, attacker, damageMultiplier, allowStacking, penetration, shouldImplode); if (result is DynValue dynValue) { result = dynValue.ToObject(); } if (result is AttackResult attackResult) { return attackResult; } return null; } } } interface IEventInventoryPutItem : IEvent { bool? OnInventoryPutItem(Inventory inventory, Item item, Character user, int i, bool removeItem); static IEventInventoryPutItem IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventInventoryPutItem { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnInventoryPutItem(Inventory inventory, Item item, Character user, int i, bool removeItem) { var result = LuaFuncs[nameof(OnInventoryPutItem)](inventory, item, user, i, removeItem); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } interface IEventInventoryItemSwap : IEvent { bool? OnInventoryItemSwap(Inventory inventory, Item item, Character user, int i, bool swapWholeStack); static IEventInventoryItemSwap IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventInventoryItemSwap { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public bool? OnInventoryItemSwap(Inventory inventory, Item item, Character user, int i, bool swapWholeStack) { var result = LuaFuncs[nameof(OnInventoryItemSwap)](inventory, item, user, i, swapWholeStack); if (result is DynValue dynValue && dynValue.Type == DataType.Boolean) { return dynValue.Boolean; } return null; } } } #endregion #region Networking #region Networking-Server #if SERVER public interface IEventClientRawNetMessageReceived : IEvent { void OnReceivedClientNetMessage(IReadMessage netMessage, ClientPacketHeader serverPacketHeader, NetworkConnection sender); } /// /// Called when a client connects to the server. /// interface IEventClientConnected : IEvent { /// /// Called when a client connects to the server. /// /// The connecting client. void OnClientConnected(Client client); static IEventClientConnected IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventClientConnected { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnClientConnected(Client client) { LuaFuncs[nameof(OnClientConnected)](client); } } } /// /// Called when a client disconnects from the server. /// interface IEventClientDisconnected : IEvent { /// /// Called when a client connects to the server. /// /// The connecting client. void OnClientDisconnected(Client client); static IEventClientDisconnected IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventClientDisconnected { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnClientDisconnected(Client client) { LuaFuncs[nameof(OnClientDisconnected)](client); } } } interface IEventJobsAssigned : IEvent { /// /// Called when a client connects to the server. /// /// The connecting client. void OnJobsAssigned(IReadOnlyList unassignedClients); static IEventJobsAssigned IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventJobsAssigned { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnJobsAssigned(IReadOnlyList unassignedClients) { LuaFuncs[nameof(OnJobsAssigned)](unassignedClients); } } } #endif #endregion #region Networking-Client #if CLIENT public interface IEventServerRawNetMessageReceived : IEvent { void OnReceivedServerNetMessage(IReadMessage netMessage, ServerPacketHeader serverPacketHeader); } /// /// Called when the client has connected to the server and loaded to the lobby. /// public interface IEventServerConnected : IEvent { void OnServerConnected(); static IEventServerConnected IEvent.GetLuaRunner(IDictionary luaFunc) => new LuaWrapper(luaFunc); public sealed class LuaWrapper : LuaWrapperBase, IEventServerConnected { public LuaWrapper(IDictionary luaFuncs) : base(luaFuncs) { } public void OnServerConnected() { LuaFuncs[nameof(OnServerConnected)](); } } } #endif #endregion #endregion #region Assembly_PluginEvents /// /// Called on plugin normal, use this for basic/core loading that does not rely on any other modded content. /// public interface IEventPluginInitialize : IEvent { void Initialize(); } /// /// Called once all plugins have been loaded. if you have integrations with any other mod, put that code here. /// public interface IEventPluginLoadCompleted : IEvent { void OnLoadCompleted(); } /// /// Called before Barotrauma initializes plugins. Use if you want to patch another plugin's behaviour 'unofficially'. /// WARNING: This method is called before Initialize()! /// public interface IEventPluginPreInitialize : IEvent { void PreInitPatching(); } /// /// Called whenever a new assembly is loaded. /// public interface IEventAssemblyLoaded : IEvent { void OnAssemblyLoaded(Assembly assembly); } /// /// Called whenever an is instanced. /// public interface IEventAssemblyContextCreated : IEvent { void OnAssemblyCreated(IAssemblyLoaderService loaderService); } /// /// Called whenever an begins unloading. /// public interface IEventAssemblyContextUnloading : IEvent { void OnAssemblyUnloading(WeakReference loaderService); } public interface IEventAssemblyUnloading : IEvent { void OnAssemblyUnloading(Assembly assembly); } #endregion