Skip to content

Commit

Permalink
feat: Lua: Event Filters
Browse files Browse the repository at this point in the history
  • Loading branch information
Panakotta00 committed Oct 29, 2024
1 parent 4933810 commit 97f75ea
Show file tree
Hide file tree
Showing 4 changed files with 250 additions and 0 deletions.
73 changes: 73 additions & 0 deletions Source/FicsItNetworksLua/Private/FINEventFilter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include "FINEventFilter.h"

bool FFINEventFilter::Matches(UObject* Sender, const FFINSignalData& Signal) const {
if (!Senders.IsEmpty() && !Senders.Contains(Sender)) return false;

if (!Events.IsEmpty() && !Events.Contains(Signal.Signal->GetInternalName())) return false;

if (!ValueFilters.IsEmpty()) {
TArray<UFIRProperty*> params = Signal.Signal->GetParameters();
int num = FMath::Min(params.Num(), Signal.Data.Num());
int numEvaluated = 0;
for (int i = 0; i < num; ++i) {
UFIRProperty* param = params[i];
const FFIRAnyValue* filter = ValueFilters.Find(param->GetInternalName());
if (!filter) continue;
numEvaluated += 1;
const FFIRAnyValue& value = Signal.Data[0];

if (filter->GetType() != value.GetType()) return false;
switch (filter->GetType()) {
case FIR_BOOL:
if (filter->GetBool() != value.GetBool()) return false;
break;
case FIR_INT:
if (filter->GetInt() != value.GetInt()) return false;
break;
case FIR_FLOAT:
if (filter->GetFloat() != value.GetFloat()) return false;
break;
case FIR_STR:
if (filter->GetString() != value.GetString()) return false;
break;
case FIR_OBJ:
if (filter->GetObj() != value.GetObj()) return false;
break;
case FIR_CLASS:
if (filter->GetClass() != value.GetClass()) return false;
break;
case FIR_TRACE:
if (filter->GetTrace() != value.GetTrace()) return false;
break;
case FIR_STRUCT:
if (filter->GetStruct() != value.GetStruct()) return false;
break;
case FIR_ARRAY:
break;
default: break;
}
}
if (numEvaluated != ValueFilters.Num()) return false;
}

return true;
}

bool FFINEventFilterExpression::Matches(UObject* Sender, const FFINSignalData& Signal) const {
switch (Operator) {
case FIN_EventFilter_None:
if (Operand1.GetStruct() != FFINEventFilter::StaticStruct()) return false;
return Operand1.Get<FFINEventFilter>().Matches(Sender, Signal);
case FIN_EventFilter_AND:
if (Operand1.GetStruct() != FFINEventFilterExpression::StaticStruct() || Operand2.GetStruct() != FFINEventFilterExpression::StaticStruct()) return false;
return Operand1.Get<FFINEventFilterExpression>().Matches(Sender, Signal) && Operand2.Get<FFINEventFilterExpression>().Matches(Sender, Signal);
case FIN_EventFilter_OR:
if (Operand1.GetStruct() != FFINEventFilterExpression::StaticStruct() || Operand2.GetStruct() != FFINEventFilterExpression::StaticStruct()) return false;
return Operand1.Get<FFINEventFilterExpression>().Matches(Sender, Signal) || Operand2.Get<FFINEventFilterExpression>().Matches(Sender, Signal);
case FIN_EventFilter_NOT:
if (Operand1.GetStruct() != FFINEventFilterExpression::StaticStruct()) return false;
return !Operand1.Get<FFINEventFilterExpression>().Matches(Sender, Signal);
default:
return false;
}
}
59 changes: 59 additions & 0 deletions Source/FicsItNetworksLua/Private/FINLua/API/LuaEventAPI.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include "FicsItNetworksComputer.h"
#include "FicsItReflection.h"
#include "FINEventFilter.h"
#include "FINLua/Reflection/LuaObject.h"
#include "FINLuaProcessor.h"
#include "LuaStruct.h"
#include "FicsItKernel/Network/NetworkController.h"
#include "FINLua/FINLuaModule.h"
#include "FINLua/LuaPersistence.h"
Expand Down Expand Up @@ -155,6 +158,62 @@ namespace FINLua {
UFINLuaProcessor::luaGetProcessor(L)->GetKernel()->GetNetwork()->ClearSignals();
return 0;
}

LuaModuleTableFunction(R"(/**
* @LuaFunction EventFilter filter(...)
* @DisplayName Filter
*
* Creates an Event filter expression.
*/)", filter) {
luaL_checktype(L, 1, LUA_TTABLE);
FFINEventFilter filter;
if (lua_getfield(L, 1, "event") != LUA_TNIL) {
if (lua_istable(L, -1)) {
int len = luaL_len(L, -1);
for (int i = 0; i < len; ++i) {
lua_geti(L, -1, i);
FString event = luaFIN_toFString(L, -1);
filter.Events.Add(event);
lua_pop(L, 1);
}
} else {
FString event = luaFIN_toFString(L, -1);
filter.Events.Add(event);
}
lua_pop(L, 1);
}
if (lua_getfield(L, 1, "sender") != LUA_TNIL) {
if (lua_istable(L, -1)) {
int len = luaL_len(L, -1);
for (int i = 0; i < len; ++i) {
lua_geti(L, -1, i);
UObject* sender = luaFIN_checkObject<UObject>(L, -1);
filter.Senders.Add(sender);
lua_pop(L, 1);
}
} else {
UObject* sender = luaFIN_checkObject<UObject>(L, -1);
filter.Senders.Add(sender);
}
lua_pop(L, 1);
}
if (lua_getfield(L, 1, "values") != LUA_TNIL) {
luaL_checktype(L, -1, LUA_TTABLE);
lua_pushnil(L);
while (lua_next(L, -2)) {
FString paramName = luaFIN_toFString(L, -2);
TOptional<FFIRAnyValue> value = luaFIN_toNetworkValue(L, -1);
if (value) {
filter.ValueFilters.Add(paramName, *value);
}
lua_pop(L, 1);
}
lua_pop(L, 2);
}
FFINEventFilterExpression expression(filter);
luaFIN_pushStruct(L, expression);
return 1;
}
}

LuaModulePostSetup() {
Expand Down
55 changes: 55 additions & 0 deletions Source/FicsItNetworksLua/Private/FINLuaReflecion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include "FicsItReflection.h"
#include "FINEventFilter.h"
#include "FicsItReflection/Public/Reflection/Source/FIRSourceStaticMacros.h"

BeginStruct(FFINEventFilterExpression, "EventFilter", "Event Filter", "This struct contains filter settings so you can evaluate if a sent signal matches the filter or not.")
BeginFuncVA(matches, "Matches", "Returns true if the given signal data matches this event filter.") {
InVal(0, RString, name, "Name", "The (internal) name of the signal.")
InVal(1, RObject<UObject>, sender, "Sender", "The sender of the signal")
OutVal(2, RBool, matches, "Matches", "True if the given signal matches the filter")
Body()
if (sender.IsValid()) {
UFIRSignal* signal = FFicsItReflectionModule::Get().FindClass(sender->GetClass())->FindFIRSignal(name);
if (IsValid(signal)) {
FFINSignalData data(signal, TArray<FIRAny>(&Params[3], Params.Num()-3));
matches = self->Matches(sender.Get(), data);
return;
}
}
matches = false;
} EndFunc()
BeginOp(FIR_Operator_Mul, 0, "And", "Creates a new Event Filter with an AND expression from two Event Filters") {
InVal(0, RStruct<FFINEventFilterExpression>, operand, "Operand", "The other Operand.")
OutVal(1, RStruct<FFINEventFilterExpression>, result, "Result", "The combined Expression.")
Body()
result = static_cast<FIRStruct>(FFINEventFilterExpression::And(*self, operand));
} EndFunc()
BeginOp(FIR_Operator_BitAND, 0, "And", "Creates a new Event Filter with an AND expression from two Event Filters") {
InVal(0, RStruct<FFINEventFilterExpression>, operand, "Operand", "The other Operand.")
OutVal(1, RStruct<FFINEventFilterExpression>, result, "Result", "The combined Expression.")
Body()
result = static_cast<FIRStruct>(FFINEventFilterExpression::And(*self, operand));
} EndFunc()
BeginOp(FIR_Operator_Add, 0, "Or", "Creates a new Event Filter with an OR expression from two Event Filters") {
InVal(0, RStruct<FFINEventFilterExpression>, operand, "Operand", "The other Operand.")
OutVal(1, RStruct<FFINEventFilterExpression>, result, "Result", "The combined Expression.")
Body()
result = static_cast<FIRStruct>(FFINEventFilterExpression::Or(*self, operand));
} EndFunc()
BeginOp(FIR_Operator_BitOR, 0, "Or", "Creates a new Event Filter with an OR expression from two Event Filters") {
InVal(0, RStruct<FFINEventFilterExpression>, operand, "Operand", "The other Operand.")
OutVal(1, RStruct<FFINEventFilterExpression>, result, "Result", "The combined Expression.")
Body()
result = static_cast<FIRStruct>(FFINEventFilterExpression::Or(*self, operand));
} EndFunc()
BeginOp(FIR_Operator_Neg, 0, "Not", "Creates a new Event Filter with an NOT expression from this Event Filter") {
OutVal(1, RStruct<FFINEventFilterExpression>, result, "Result", "The output Expression.")
Body()
result = static_cast<FIRStruct>(FFINEventFilterExpression::Not(*self));
} EndFunc()
BeginOp(FIR_Operator_BitNOT, 0, "Not", "Creates a new Event Filter with an NOT expression from this Event Filter") {
OutVal(1, RStruct<FFINEventFilterExpression>, result, "Result", "The output Expression.")
Body()
result = static_cast<FIRStruct>(FFINEventFilterExpression::Not(*self));
} EndFunc()
EndStruct()
63 changes: 63 additions & 0 deletions Source/FicsItNetworksLua/Public/FINEventFilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once

#include "CoreMinimal.h"
#include "FINSignalData.h"
#include "FIRSignal.h"
#include "FINEventFilter.generated.h"

USTRUCT()
struct FFINEventFilter {
GENERATED_BODY()

UPROPERTY(SaveGame)
TArray<UObject*> Senders;

UPROPERTY(SaveGame)
TArray<FString> Events;

UPROPERTY(SaveGame)
TMap<FString, FFIRAnyValue> ValueFilters;

bool Matches(UObject* Sender, const FFINSignalData& Signal) const;
};

UENUM()
enum EFINEventFilterExpressionOperator {
FIN_EventFilter_None,
FIN_EventFilter_AND,
FIN_EventFilter_OR,
FIN_EventFilter_NOT,
};

USTRUCT()
struct FFINEventFilterExpression {
GENERATED_BODY()

UPROPERTY(SaveGame)
FFIRInstancedStruct Operand1;

UPROPERTY(SaveGame)
TEnumAsByte<EFINEventFilterExpressionOperator> Operator = FIN_EventFilter_None;

UPROPERTY(SaveGame)
FFIRInstancedStruct Operand2;

FFINEventFilterExpression() = default;
FFINEventFilterExpression(const FFINEventFilter& Filter) : Operand1(Filter) {}
FFINEventFilterExpression(const FFINEventFilterExpression& Operand1, EFINEventFilterExpressionOperator Operator) : Operand1(Operand1), Operator(Operator) {}
FFINEventFilterExpression(const FFINEventFilterExpression& Operand1, EFINEventFilterExpressionOperator Operator, const FFINEventFilterExpression& Operand2) : Operand1(Operand1), Operator(Operator), Operand2(Operand2) {}

static FFINEventFilterExpression And(const FFINEventFilterExpression& Operand1, const FFINEventFilterExpression& Operand2) {
return FFINEventFilterExpression(Operand1, FIN_EventFilter_AND, Operand2);
}

static FFINEventFilterExpression Or(const FFINEventFilterExpression& Operand1, const FFINEventFilterExpression& Operand2) {
return FFINEventFilterExpression(Operand1, FIN_EventFilter_OR, Operand2);
}

static FFINEventFilterExpression Not(const FFINEventFilterExpression& Operand1) {
return FFINEventFilterExpression(Operand1, FIN_EventFilter_NOT);
}

bool Matches(UObject* Sender, const FFINSignalData& Signal) const;
};

0 comments on commit 97f75ea

Please sign in to comment.