Skip to content

Commit

Permalink
Add AddLuaNetListener/RemoveLuaNetListener API for lua net property m…
Browse files Browse the repository at this point in the history
…onitoring.
  • Loading branch information
zjhongxian committed Jun 19, 2023
1 parent e6af6fa commit 11a4722
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 6 deletions.
8 changes: 7 additions & 1 deletion Content/Lua/LuaGameState.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ function LuaGameState:ctor(selfType)
self.Name = "LuaGameStateTestName"
end

function LuaGameState:_PostConstruct()
self:AddLuaNetListener("Position", function (Value)
print("LuaGameState On Position Assign:", Value.X, Value.Y, Value.Z)
end)
end

function LuaGameState:TestServerRPC(ArgInt, ArgStr, ArgBool)
print("LuaGameState:TestServerRPC", ArgInt, ArgStr, ArgBool)
end
Expand Down Expand Up @@ -76,7 +82,7 @@ function LuaGameState:ReceiveBeginPlay()
self.bCanEverTick = true
-- set bCanBeDamaged property in parent
self.bCanBeDamaged = false
print("actor:ReceiveBeginPlay")
print("LuaGameState:ReceiveBeginPlay")

local KismetSystemLibrary = import("KismetSystemLibrary")
if KismetSystemLibrary.IsDedicatedServer(self) then
Expand Down
150 changes: 149 additions & 1 deletion Plugins/slua_unreal/Source/slua_unreal/Private/LuaNet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

namespace NS_SLUA
{
const char* LuaNet::ADD_LISTENER_FUNC = "AddLuaNetListener";
const char* LuaNet::REMOVE_LISTENER_FUNC = "RemoveLuaNetListener";
LuaNet::ClassLuaReplicatedMap LuaNet::classLuaReplicatedMap;
LuaNet::LuaNetSerializationMap LuaNet::luaNetSerializationMap;
LuaNet::ObjectToLuaNetAddressMap LuaNet::objectToLuaNetAddressMap;
Expand Down Expand Up @@ -765,7 +767,6 @@ namespace NS_SLUA

int LuaNet::__newindex(lua_State* L, UObject* obj, const char* keyName)
{

// Try to assign net replicated prop first.
if (LuaNet::isLuaReplicateObject(obj))
{
Expand Down Expand Up @@ -794,6 +795,7 @@ namespace NS_SLUA
checker(L, p, data + propOffset, 3, true);
proxy->dirtyMark.Add(luaReplicatedIndex);
proxy->assignTimes++;
onPropModify(L, proxy, luaReplicatedIndex, nullptr);
}
}
}
Expand All @@ -806,5 +808,151 @@ namespace NS_SLUA

return 0;
}

int LuaNet::setupFunctions(lua_State* L)
{
lua_pushstring(L, LuaNet::ADD_LISTENER_FUNC);
lua_pushcfunction(L, LuaNet::addListener);
lua_rawset(L, -3);

lua_pushstring(L, LuaNet::REMOVE_LISTENER_FUNC);
lua_pushcfunction(L, LuaNet::removeListener);
lua_rawset(L, -3);
return 0;
}

int LuaNet::addListener(lua_State* L)
{
lua_pushstring(L, SLUA_CPPINST);
lua_rawget(L, 1);
void* ud = lua_touserdata(L, -1);
lua_pop(L, 1);

auto obj = (UObject*)ud;

if (!NS_SLUA::LuaObject::isUObjectValid(obj))
{
return 0;
}

if (NS_SLUA::LuaNet::isLuaReplicateObject(obj))
{
auto classLuaReplciated = LuaNet::getClassReplicatedProps(obj);
if (classLuaReplciated)
{
auto prop = classLuaReplciated->ownerProperty.Get();
if (prop && classLuaReplciated->replicatedNameToIndexMap.Num())
{
const char* keyName = lua_tostring(L, 2);
auto luaReplicatedIndex = classLuaReplciated->replicatedNameToIndexMap.Find(UTF8_TO_TCHAR(keyName));

if (luaReplicatedIndex)
{
FLuaNetSerialization* luaNetSerialization = prop->ContainerPtrToValuePtr<FLuaNetSerialization>(obj);
auto proxy = LuaNet::getLuaNetSerializationProxy(luaNetSerialization);
if (proxy)
{
int index = *luaReplicatedIndex;
{
auto &listeners = proxy->propListeners.FindOrAdd(index);
listeners.Add(new LuaVar(L, 3));
return 1;
}
}
}
}
}
}

return 0;
}

int LuaNet::removeListener(lua_State* L)
{
lua_pushstring(L, SLUA_CPPINST);
lua_rawget(L, 1);
void* ud = lua_touserdata(L, -1);
lua_pop(L, 1);

auto obj = (UObject*)ud;

if (!NS_SLUA::LuaObject::isUObjectValid(obj))
{
return 0;
}

if (NS_SLUA::LuaNet::isLuaReplicateObject(obj))
{
auto classLuaReplciated = LuaNet::getClassReplicatedProps(obj);
if (classLuaReplciated)
{
auto prop = classLuaReplciated->ownerProperty.Get();
if (prop && classLuaReplciated->replicatedNameToIndexMap.Num())
{
const char* keyName = lua_tostring(L, 2);
auto luaReplicatedIndex = classLuaReplciated->replicatedNameToIndexMap.Find(UTF8_TO_TCHAR(keyName));

if (luaReplicatedIndex)
{
FLuaNetSerialization* luaNetSerialization = prop->ContainerPtrToValuePtr<FLuaNetSerialization>(obj);
auto proxy = LuaNet::getLuaNetSerializationProxy(luaNetSerialization);
if (proxy)
{
int index = *luaReplicatedIndex;
{
auto &listeners = proxy->propListeners.FindOrAdd(index);
auto funcToRemove = LuaVar(L, 3);
auto indexToRemove = listeners.IndexOfByPredicate([&](const LuaVar* Item)
{
if (*Item == funcToRemove)
{
delete Item;
return true;
}

return false;
});
if (indexToRemove >= 0)
{
listeners.RemoveAt(indexToRemove);
return 1;
}
}
}
}
}
}
}

return 0;
}

void LuaNet::onPropModify(lua_State* L, FLuaNetSerializationProxy* proxy, ClassLuaReplicated::ReplicateIndexType index, PrepareParamCallback callback)
{
auto *listeners = proxy->propListeners.Find(index);
if (listeners)
{
if (listeners->Num() <= 0)
{
return;
}

if (callback)
{
callback();
}

auto listenersCopy = *listeners;
auto fillParam = [L]()
{
lua_pushvalue(L, -3);
return 1;
};
for (auto listener : listenersCopy)
{
listener->callWithNArg(fillParam);
}
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ void FLuaNetSerializationProxy::AddReferencedObjects(FReferenceCollector& Collec
NS_SLUA::LuaReference::addRefByStruct(Collector, contentStruct.Get(), values.GetData());
}

FLuaNetSerializationProxy::~FLuaNetSerializationProxy()
{
for (auto Iter : propListeners)
{
for (auto funcIter : Iter.Value)
{
delete funcIter;
}
}

propListeners.Empty();
}

bool NetSerializeItem(NS_SLUA::FProperty* Prop, FArchive& Ar, UPackageMap* Map, void* Data)
{
if (auto StructProp = CastField<NS_SLUA::FStructProperty>(Prop))
Expand Down Expand Up @@ -275,6 +288,13 @@ bool FLuaNetSerialization::NetDeltaSerialize(FNetDeltaSerializeInfo& deltaParms)
auto& prop = properties[index];
CallOnRep(L, luaTable, propName, prop, oldData + prop->GetOffset_ForInternal());
}

NS_SLUA::AutoStack as(L);
NS_SLUA::LuaNet::onPropModify(L, proxy, index, [&]()
{
auto& prop = properties[index];
NS_SLUA::LuaObject::push(L, prop, data + prop->GetOffset_ForInternal(), nullptr);
});
}
}

Expand Down Expand Up @@ -466,6 +486,13 @@ bool FLuaNetSerialization::Read(FNetDeltaSerializeInfo& deltaParms, FLuaNetSeria
auto& prop = properties[index];
CallOnRep(L, luaTable, propName, prop, oldData + prop->GetOffset_ForInternal());
}

NS_SLUA::AutoStack as(L);
NS_SLUA::LuaNet::onPropModify(L, proxy, index, [&]()
{
auto& prop = properties[index];
NS_SLUA::LuaObject::push(L, prop, data + prop->GetOffset_ForInternal(), nullptr);
});
}
}
}
Expand Down
11 changes: 9 additions & 2 deletions Plugins/slua_unreal/Source/slua_unreal/Private/LuaOverrider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1196,12 +1196,14 @@ namespace NS_SLUA
classHookedFuncNames.Add(cls, funcNames);
}

bool bNetReplicated = false;
if (auto classReplicated = LuaNet::addClassReplicatedProps(L, obj, luaModule))
{
LuaNet::initLuaReplicatedProps(L, obj, *classReplicated, luaSelfTable);
bNetReplicated = true;
}

setmetatable(luaSelfTable, (void*)obj);
setmetatable(luaSelfTable, (void*)obj, bNetReplicated);
ULuaOverrider::addObjectTable(L, obj, luaSelfTable, bHookInstancedObj);

if (auto luaInterface = Cast<ILuaOverriderInterface>(obj))
Expand All @@ -1212,7 +1214,7 @@ namespace NS_SLUA
return true;
}

void LuaOverrider::setmetatable(const LuaVar& luaSelfTable, void* objPtr)
void LuaOverrider::setmetatable(const LuaVar& luaSelfTable, void* objPtr, bool bNetReplicated)
{
lua_State* L = sluaState->getLuaState();
// setup __cppinst
Expand All @@ -1222,6 +1224,11 @@ namespace NS_SLUA
lua_pushlightuserdata(L, objPtr);
lua_rawset(L, -3);

if (bNetReplicated)
{
LuaNet::setupFunctions(L);
}

lua_pushstring(L, SUPER_NAME);
LuaObject::pushType(L, new LuaSuperCall((UObject*)objPtr), "LuaSuperCall", LuaSuperCall::setupMetatable, LuaSuperCall::genericGC);
lua_rawset(L, -3);
Expand Down
10 changes: 10 additions & 0 deletions Plugins/slua_unreal/Source/slua_unreal/Public/LuaNet.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ namespace NS_SLUA
class SLUA_UNREAL_API LuaNet
{
public:
typedef TFunction<void ()> PrepareParamCallback;

// Only support c++ native UClass
static void addLuaRepilcateClass(const UClass* someBase);
static bool isLuaReplicateObject(UObject* obj);
Expand All @@ -37,8 +39,12 @@ namespace NS_SLUA
static void removeObjectTable(UObject* obj);
static void onObjectDeleted(UClass* cls);

static void onPropModify(lua_State* L, FLuaNetSerializationProxy* proxy, ClassLuaReplicated::ReplicateIndexType index, PrepareParamCallback callback);

protected:
friend class LuaOverrider;
static const char* ADD_LISTENER_FUNC;
static const char* REMOVE_LISTENER_FUNC;

void addClassRPC(lua_State* L, UClass* cls, const FString& luaFilePath);
bool addClassRPCRecursive(lua_State* L, UClass* cls, const FString& luaFilePath, LuaVar& cppSuperModule);
Expand All @@ -51,6 +57,10 @@ namespace NS_SLUA

static int __index(lua_State* L, UObject* obj, const char* keyName);
static int __newindex(lua_State* L, UObject* obj, const char* keyName);

static int setupFunctions(lua_State* L);
static int addListener(lua_State* L);
static int removeListener(lua_State* L);

typedef TMap<TWeakObjectPtr<UClass>, ClassLuaReplicated, FDefaultSetAllocator, TWeakObjectPtrMapKeyFuncs<TWeakObjectPtr<UClass>, ClassLuaReplicated>> ClassLuaReplicatedMap;
static ClassLuaReplicatedMap classLuaReplicatedMap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ struct FLuaNetSerializationProxy : public FGCObject

LuaBitArray flatDirtyMark;
TMap<int32, LuaBitArray> arrayDirtyMark;
TMap<ClassLuaReplicated::ReplicateIndexType, TArray<NS_SLUA::LuaVar*>> propListeners;

TWeakObjectPtr<UStruct> contentStruct;

Expand All @@ -187,7 +188,7 @@ struct FLuaNetSerializationProxy : public FGCObject
#endif

virtual void AddReferencedObjects( FReferenceCollector& Collector );

~FLuaNetSerializationProxy();
};

USTRUCT()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ namespace NS_SLUA
void onEngineGC();

bool bindOverrideFuncs(const UObjectBase* objBase, UClass* cls);
void setmetatable(const LuaVar& luaSelfTable, void* objPtr);
void setmetatable(const LuaVar& luaSelfTable, void* objPtr, bool bNetReplicated);

bool hookBpScript(UFunction* func, UClass* cls, FNativeFuncPtr hookFunc);

Expand Down

0 comments on commit 11a4722

Please sign in to comment.