diff --git a/Game.Client/C_BaseEntity.cs b/Game.Client/C_BaseEntity.cs index c1e85ea2..a8189db8 100644 --- a/Game.Client/C_BaseEntity.cs +++ b/Game.Client/C_BaseEntity.cs @@ -1474,6 +1474,7 @@ public virtual void Dispose() { double flSpawnTime; double LastMessageTime; + bool LuaEntityCreatedCalled; public void MoveToLastReceivedPosition(bool force = false) { if (force || (RenderFx)RenderFX != RenderFx.Ragdoll) { @@ -1571,6 +1572,11 @@ public virtual void PostDataUpdate(DataUpdateType updateType) { UpdateVisibility(); if (OldShouldDraw != ShouldDraw()) UpdateVisibility(); + + if (updateType == DataUpdateType.Created && GetRefEHandle().Index != Constants.INVALID_EHANDLE_INDEX && !LuaEntityCreatedCalled) { + LuaEntityCreatedCalled = true; + garrysmod.EntityCreated(this); + } } public ReadOnlySpan GetModelName() => ModelName.SliceNullTerminatedString(); public void AllocateIntermediateData() { @@ -1798,6 +1804,11 @@ public bool InitializeAsClientEntityByIndex(int index, RenderGroup renderGroup) SpawnClientEntity(); + if (!LuaEntityCreatedCalled) { + LuaEntityCreatedCalled = true; + garrysmod.EntityCreated(this); + } + return true; } diff --git a/Game.Server/MapEntities.cs b/Game.Server/MapEntities.cs index c12ddfe6..e7fe1b56 100644 --- a/Game.Server/MapEntities.cs +++ b/Game.Server/MapEntities.cs @@ -53,6 +53,8 @@ public static class MapEntities BaseEntity? entity = (BaseEntity?)network.GetBaseEntity(); Assert(entity); + if (entity != null && entity.GetRefEHandle().Index != Constants.INVALID_EHANDLE_INDEX) + garrysmod.EntityCreated(entity); return entity; } diff --git a/Game.Server/Util.cs b/Game.Server/Util.cs index 6bc3aea4..9446be76 100644 --- a/Game.Server/Util.cs +++ b/Game.Server/Util.cs @@ -537,18 +537,26 @@ public static void TransmitShakeEvent(BasePlayer player, float localAmplitude, f } public static void PrecacheOther(ReadOnlySpan className, ReadOnlySpan modelName = default) { + bool precaching = s_RemoveImmediateSemaphore == 0; + if (precaching) + Game.Client.GarrysMod.GarrysMod.g_GModPrecaching++; + if (Game.Client.GarrysMod.GarrysMod.g_GModPrecaching > 0x20) + Error("Something seems to have gone wroong"); + BaseEntity? entity = CreateEntityByName(className); - if (entity == null) { + if (entity == null) Warning("NULL Ent in Util.PrecacheOther\n"); - return; - } + else { + // If we have a specified model, set it before calling precache + if (!modelName.IsStringEmpty) + entity.SetModelName(modelName); - // If we have a specified model, set it before calling precache - if (!modelName.IsStringEmpty) - entity.SetModelName(modelName); + entity.Precache(); + Util.RemoveImmediate(entity); + } - entity.Precache(); - Util.RemoveImmediate(entity); + if (precaching) + Game.Client.GarrysMod.GarrysMod.g_GModPrecaching--; } public static void ClientPrintFilter(scoped in Filter filter, HudPrint dest, ReadOnlySpan msgName, ReadOnlySpan param1 = default, ReadOnlySpan param2 = default, ReadOnlySpan param3 = default, ReadOnlySpan param4 = default) where Filter : IRecipientFilter { diff --git a/Game.Shared/GarrysMod/GarrysMod.cs b/Game.Shared/GarrysMod/GarrysMod.cs index 9ee6a93d..21f3127b 100644 --- a/Game.Shared/GarrysMod/GarrysMod.cs +++ b/Game.Shared/GarrysMod/GarrysMod.cs @@ -576,6 +576,38 @@ public void StartVideoScale(int unk1, int unk2) { throw new NotImplementedException(); } + public static sbyte g_GModPrecaching; + + public static void ResetLuaIteratorEntityCache(BaseEntity ent) { + if (g_Lua == null || g_Lua.Global() == null) + return; + + LuaObject invalidate = new(); + g_Lua.Global().GetMember("InvalidateInternalEntityCache", invalidate); + if (invalidate.isFunction()) { + invalidate.Push(); + g_Lua.PushBool(ent.IsPlayer()); + g_Lua.CallInternalNoReturns(1); + } + invalidate.UnReference(); + } + + public void EntityCreated(BaseEntity? ent) { + if (g_Lua == null || gGM == null || ent == null || g_GModPrecaching != 0) + return; + + ResetLuaIteratorEntityCache(ent); + if (gGM == null || !gGM.CallWithArgs((int)LUA_POOLEDSTRING.OnEntityCreated)) + return; + +#if CLIENT_DLL + LuaEntity.Push_Entity(ent); +#else + Game.Server.GarrysMod.LuaEntity.Push_Entity(ent); +#endif + gGM.CallNoReturns(1); + } + public void Think() { if (g_Lua != null) { // CheckForFilesystemChanges(); diff --git a/Game.Shared/PrecacheRegister.cs b/Game.Shared/PrecacheRegister.cs index ebd1dfbc..1ec2a80b 100644 --- a/Game.Shared/PrecacheRegister.cs +++ b/Game.Shared/PrecacheRegister.cs @@ -36,8 +36,15 @@ public PrecacheRegister(PrecacheFn fn, object? userdata) { public PrecacheRegister? Next; public static void Precache() { +#if GAME_DLL || CLIENT_DLL + if (++Game.Client.GarrysMod.GarrysMod.g_GModPrecaching > 0x20) + Error("Something seems to have gone wrong"); +#endif for (PrecacheRegister? cur = PrecacheRegisters; cur != null; cur = cur.Next) cur.Fn(cur.User); +#if GAME_DLL || CLIENT_DLL + Game.Client.GarrysMod.GarrysMod.g_GModPrecaching--; +#endif } public static void PrecacheFn_Other(object? userdata) {