From a3557242bf6e67612463b5297336b0d117d25700 Mon Sep 17 00:00:00 2001 From: Igor Stepanov Date: Fri, 25 Jul 2025 04:14:55 +0300 Subject: [PATCH 1/3] event save/load implementation --- src/libs/core/include/core.h | 3 +- src/libs/core/include/message.h | 26 +- src/libs/core/src/compiler.cpp | 399 ++++++++-- src/libs/core/src/compiler.h | 23 +- src/libs/core/src/core_impl.cpp | 7 +- src/libs/core/src/core_impl.h | 3 +- src/libs/core/src/data.cpp | 22 + src/libs/core/src/data.h | 3 + src/libs/core/src/internal_functions.cpp | 339 ++++++-- src/libs/core/src/message.cpp | 733 +++++++++++++++++- src/libs/core/src/s_eventmsg.h | 67 ++ src/libs/core/src/s_eventtab.cpp | 488 +++++++++--- src/libs/core/src/s_eventtab.h | 27 +- src/libs/core/src/s_postevents.h | 64 ++ src/libs/location/src/fader.cpp | 8 +- src/libs/ship/src/ship.cpp | 3 +- .../xinterface/src/aviplayer/aviplayer.cpp | 2 +- .../xinterface/src/back_scene/back_scene.cpp | 2 +- .../xinterface/src/nodes/xi_slide_line.cpp | 2 +- src/libs/xinterface/src/xinterface.cpp | 2 +- 20 files changed, 1959 insertions(+), 264 deletions(-) diff --git a/src/libs/core/include/core.h b/src/libs/core/include/core.h index 1118c56b5..df2b75147 100644 --- a/src/libs/core/include/core.h +++ b/src/libs/core/include/core.h @@ -70,7 +70,6 @@ class Core virtual void Entity_SetAttributePointer(entid_t id_PTR, ATTRIBUTES *pA) = 0; virtual uint32_t Entity_AttributeChanged(entid_t id_PTR, ATTRIBUTES *) = 0; virtual ATTRIBUTES *Entity_GetAttributePointer(entid_t id_PTR) = 0; - // send message to an object virtual uint64_t Send_Message(entid_t Destination, const char *Format, ...) = 0; @@ -95,7 +94,7 @@ class Core return Event(event_name, message); } virtual VDATA *Event(const std::string_view &event_name, MESSAGE &message) = 0; - virtual uint32_t PostEvent(const char *Event_name, uint32_t post_time, const char *Format, ...) = 0; + virtual uint32_t PostEvent(ATTRIBUTES * pObject, const char *Event_name, uint32_t post_time, const char *Format, ...) = 0; virtual void *GetSaveData(const char *file_name, int32_t &data_size) = 0; diff --git a/src/libs/core/include/message.h b/src/libs/core/include/message.h index 1cfc54099..ba0c96aa4 100644 --- a/src/libs/core/include/message.h +++ b/src/libs/core/include/message.h @@ -3,11 +3,14 @@ #include #include #include +#include #include "c_vector.h" #include "entity.h" class VDATA; +class DATA; +class VarTable; namespace storm { @@ -57,13 +60,19 @@ class MESSAGE final CVECTOR CVector(); const std::string &String(); + + bool Set(uint8_t value); + bool Set(uint16_t value); bool Set(int32_t value); + bool Set(uint32_t value); bool Set(uintptr_t value); bool Set(float value); + bool Set(double value); bool Set(std::string value); bool SetEntity(entid_t value); bool Set(VDATA *value); bool Set(ATTRIBUTES *value); + bool Set(CVECTOR value); void ValidateFormat(char c); void Reset(const std::string_view &format); @@ -84,10 +93,25 @@ class MESSAGE final [[nodiscard]] std::string_view GetFormat() const; [[nodiscard]] bool ParamValid() const; -private: + size_t GetParametersCount() const; + void GetData(DATA *vd, COMPILER *comp); + void StoreData(ATTRIBUTES *attr, std::unordered_map>> &varIndex) const; + static MESSAGE *LoadData(ATTRIBUTES *attr, VarTable &VarTab); + void FixEnitiyIDs(); + + ATTRIBUTES *GetThisObject(); + void SetThisObject(ATTRIBUTES *); + private: static storm::MessageParam GetParamValue(const char c, va_list &args); std::string format_; std::vector params_; int32_t index{}; + bool hasThisObject_{false}; }; + +ATTRIBUTES *LoadAttributesRef(ATTRIBUTES *attr, VarTable &VarTab); + +//false - local variable reference; otherwise - true +bool StoreAttributesRef(ATTRIBUTES *attr, const ATTRIBUTES *val, + std::unordered_map>> &varIndex); diff --git a/src/libs/core/src/compiler.cpp b/src/libs/core/src/compiler.cpp index 3ffe29702..00799316b 100644 --- a/src/libs/core/src/compiler.cpp +++ b/src/libs/core/src/compiler.cpp @@ -19,6 +19,7 @@ #include #include + #define SKIP_COMMENT_TRACING #define TRACE_OFF #define INVALID_SEGMENT_INDEX 0xffffffff @@ -30,6 +31,8 @@ #define SBUPDATE 4 #define DEF_COMPILE_EXPRESSIONS +constexpr auto MAGIC_VAR_CODE = 0xffffffaa; + #ifdef _WIN32 // S_DEBUG namespace { @@ -605,7 +608,7 @@ void COMPILER::FindErrorSource() } while (Token_type != END_OF_PROGRAMM); } -void COMPILER::SetEventHandler(const char *event_name, const char *func_name, int32_t flag, bool bStatic) +void COMPILER::SetEventHandler(ATTRIBUTES * pObject, const char *event_name, const char *func_name, int32_t flag, bool bStatic) { FuncInfo fi; @@ -629,14 +632,24 @@ void COMPILER::SetEventHandler(const char *event_name, const char *func_name, in if (!FuncTab.GetFunc(fi, func_code)) { - SetError("func not found eror"); + SetError("func not found error"); return; } - EventTab.AddEventHandler(event_name, func_code, fi.segment_id, flag, bStatic); + auto format = EventTab.GetEventFormat(event_name); + if (format.has_value()) + { + if (fi.arguments != format.value().size()) + { + SetError("Function handler (%s) has %u arguments, but '%s' event expects %u", func_name, + (unsigned)fi.arguments, event_name, format.value().size()); + } + } + + EventTab.AddEventHandler(pObject, event_name, func_code, fi.segment_id, flag, bStatic); } -void COMPILER::DelEventHandler(const char *event_name, const char *func_name) +void COMPILER::DelEventHandler(ATTRIBUTES *pObject, const char *event_name, const char *func_name) { if (event_name == nullptr) { @@ -657,23 +670,28 @@ void COMPILER::DelEventHandler(const char *event_name, const char *func_name) return; } - EventTab.SetStatus(event_name, func_code, FSTATUS_DELETED); + EventTab.SetStatus(pObject, event_name, func_code, FSTATUS_DELETED); - for (int32_t n = 0; n < static_cast(EventMsg.GetClassesNum()); n++) + if constexpr (false) { - S_EVENTMSG *pM = EventMsg.Read(n); - if (!pM->pEventName) - continue; - if (pM->ProcessTime(0)) - continue; // skip events, possible executed on this frame - if (storm::iEquals(pM->pEventName, event_name)) + for (int32_t n = 0; n < static_cast(EventMsg.GetClassesNum()); n++) { - EventMsg.Del(n); - n--; + S_EVENTMSG *pM = EventMsg.Read(n); + if (!pM->pEventName) + continue; + if (pM->ProcessTime(0)) + continue; // skip events, possible executed on this frame + if (storm::iEquals(pM->pEventName, event_name)) + { + EventMsg.Del(n); + n--; + } } } + } + VDATA *COMPILER::ProcessEvent(const char *event_name) { // TODO: only do if stack debug if enabled (should be runtime configurable) @@ -684,8 +702,6 @@ VDATA *COMPILER::ProcessEvent(const char *event_name) uint32_t event_code; uint32_t func_code; VDATA *pVD; - DATA *pResult; - MESSAGE *pMem; EVENTINFO ei; #ifdef _WIN32 // S_DEBUG uint32_t current_debug_mode; @@ -713,58 +729,20 @@ VDATA *COMPILER::ProcessEvent(const char *event_name) if (event_code == INVALID_EVENT_CODE) return nullptr; // no handlers EventTab.GetEvent(ei, event_code); - for (uint32_t n = 0; n < ei.elements; n++) - { - func_code = ei.pFuncInfo[n].func_code; - if (ei.pFuncInfo[n].status != FSTATUS_NORMAL) - continue; - pMem = pEventMessage; - if (pMem) - { - pMem->Move2Start(); - } - - const uint32_t nStackVars = SStack.GetDataNum(); // remember stack elements num - RDTSC_B(nTicks); - BC_Execute(ei.pFuncInfo[n].func_code, pResult); - RDTSC_E(nTicks); - FuncInfo fi; - // if(FuncTab.GetFuncX(fi,ei.pFuncInfo[n].func_code)) - if (FuncTab.GetFuncX(fi, func_code)) - { - if (fi.return_type != TVOID) - { - fi.return_type = TVOID; - } - } //*/ + pVD = ProcessEventFunctions(ei.pFuncInfo, event_code, pEventMessage, nTicks); - if (EventTab.GetEvent(ei, event_code)) // to be sure event still exist + if (pEventMessage) + { + auto objPtr = pEventMessage->GetThisObject(); + if (objPtr) { - if (n < ei.elements) + auto it = ei.pFuncInfoForObjects.find(objPtr); + if (it != ei.pFuncInfoForObjects.end()) { - if (!FuncTab.AddTime(ei.pFuncInfo[n].func_code, nTicks)) - { - core_internal.Trace("Invalid func_code = %u for AddTime", ei.pFuncInfo[n].func_code); - } + pVD = ProcessEventFunctions(it->second, event_code, pEventMessage, nTicks); } } - - pEventMessage = pMem; - if (pResult) - pVD = pResult->GetVarPointer(); - if (pResult) - SStack.Pop(); - - if (nStackVars != SStack.GetDataNum()) - { - SStack.InvalidateFrom(nStackVars); // restore stack state - crash situation - pVD = nullptr; - SetError("process event stack error"); - } - - if (bEventsBreak) - break; } nTimeOnEvent = SDL_GetTicks() - nTimeOnEvent; @@ -791,6 +769,95 @@ VDATA *COMPILER::ProcessEvent(const char *event_name) return pVD; } +VDATA *COMPILER::ProcessEventFunctions(std::vector &eventFuncVec, uint32_t event_code, MESSAGE *pMem, + uint64_t &nTicks) +{ + VDATA *pVD = nullptr; + for (uint32_t n = 0; n < eventFuncVec.size(); n++) + { + if (eventFuncVec[n].status != FSTATUS_NORMAL) + continue; + pVD = ProcessEventFunc(eventFuncVec, n, event_code, pMem, nTicks); + if (bEventsBreak) + break; + } + return pVD; +} + +VDATA *COMPILER::ProcessEventFunc(std::vector &eventFuncVec, uint32_t func_idx, uint32_t event_code, MESSAGE *pMem, + uint64_t &nTicks) +{ + DATA *pResult = nullptr; + VDATA *pVD = nullptr; + if (pMem) + { + pMem->Move2Start(); + } + + FuncInfo fi; + // if(FuncTab.GetFuncX(fi,ei.pFuncInfo[n].func_code)) + if (FuncTab.GetFuncX(fi, eventFuncVec[func_idx].func_code)) + { + if (fi.return_type != TVOID) + { + fi.return_type = TVOID; + } + } //*/ + + const uint32_t nStackVars = SStack.GetDataNum(); // remember stack elements num + + EVENTINFO ei; + if (!EventTab.GetEvent(ei, event_code)) // to be sure event still exist + { + return nullptr; + } + + if (pMem && fi.arguments > 0) + { + auto msgParamCount = pMem->GetParametersCount(); + if (fi.arguments > msgParamCount) + { + SetError("Too many parameters in function '%s' for handle event '%s'", fi.name.c_str(), ei.name); + return nullptr; + } + for (size_t i = 0; i < msgParamCount; i++) + { + auto pD = SStack.Push(); + pMem->GetData(pD, this); + } + } + RDTSC_B(nTicks); + BC_Execute(eventFuncVec[func_idx].func_code, pResult); + RDTSC_E(nTicks); + + + if (EventTab.GetEvent(ei, event_code)) // to be sure event still exist + { + if (1 < eventFuncVec.size()) + { + if (!FuncTab.AddTime(eventFuncVec[func_idx].func_code, nTicks)) + { + core_internal.Trace("Invalid func_code = %u for AddTime", eventFuncVec[func_idx].func_code); + } + } + } + + pEventMessage = pMem; + if (pResult) + pVD = pResult->GetVarPointer(); + if (pResult) + SStack.Pop(); + + if (nStackVars != SStack.GetDataNum()) + { + SStack.InvalidateFrom(nStackVars); // restore stack state - crash situation + pVD = nullptr; + SetError("process event stack error"); + } + + return pVD; +} + void COMPILER::ProcessEvent(const char *event_name, MESSAGE *pMs) { pEventMessage = pMs; @@ -2239,7 +2306,7 @@ bool COMPILER::CompileBlock(SEGMENT_DESC &Segment, bool &bFunctionBlock, uint32_ return false; } // SetEventHandler(gs,Token.GetData(),1,true); - SetEventHandler(gs, Token.GetData(), 0, true); + SetEventHandler(nullptr, gs, Token.GetData(), 0, true); if (script_cache_mode_ != kCacheDisabled) { script_cache_.event_handlers.emplace_back(storm::script_cache::EventHandler{gs, Token.GetData()}); @@ -6400,14 +6467,34 @@ bool COMPILER::ReadVariable(char *name, /* DWORD code,*/ bool bDim, uint32_t a_i ReadAttributesData(pTA, nullptr); delete pTA; } + break; case VAR_REFERENCE: var_index = ReadVDword(); if (var_index == 0xffffffff) break; // uninitialized ref + array_index = ReadVDword(); + + + if (var_index == MAGIC_VAR_CODE) // new format + { + pString = ReadString(); + var_index = VarTab.FindVar(pString); + if (var_index == INVALID_VAR_CODE) + { + SetError("Load - unknown variable '%s'", pString); + delete[] pString; + return false; + } + if (bSkipVariable) + delete[] pString; + pString = nullptr; + } + if (bSkipVariable) break; + real_var_ref = VarTab.GetVarX(var_index); if (real_var_ref == nullptr) { @@ -6428,6 +6515,23 @@ bool COMPILER::ReadVariable(char *name, /* DWORD code,*/ bool bDim, uint32_t a_i if (var_index == 0xffffffff) break; array_index = ReadVDword(); + + + if (var_index == MAGIC_VAR_CODE) // new format + { + pString = ReadString(); + var_index = VarTab.FindVar(pString); + if (var_index == INVALID_VAR_CODE) + { + SetError("Load - unknown variable '%s'", pString); + delete[] pString; + return false; + } + if (bSkipVariable) + delete[] pString; + pString = nullptr; + } + pString = ReadString(); if (bSkipVariable) { @@ -6551,9 +6655,26 @@ void COMPILER::SaveVariable(DATA *pV, bool bdim) WriteVDword(0xffffffff); return; } + + if constexpr (true) + { + auto pvi = VarTab.GetVarX(var_index); + if (!pvi) + { + SetError("Unknown variable %u", var_index); + return; + } - WriteVDword(var_index); - WriteVDword(array_index); + //write magic code to differ from the old format + WriteVDword(MAGIC_VAR_CODE); + WriteVDword(array_index); + SaveString(pvi->name.c_str()); + } + else + { + WriteVDword(var_index); + WriteVDword(array_index); + } break; case VAR_AREFERENCE: @@ -6585,8 +6706,25 @@ void COMPILER::SaveVariable(DATA *pV, bool bdim) delete[] pString; break; } - WriteVDword(var_index); - WriteVDword(array_index); + if constexpr (true) + { + auto pvi = VarTab.GetVarX(var_index); + if (!pvi) + { + SetError("Unknown variable %u", var_index); + return; + } + + // write magic code to differ from the old format + WriteVDword(MAGIC_VAR_CODE); + WriteVDword(array_index); + SaveString(pvi->name.c_str()); + } + else + { + WriteVDword(var_index); + WriteVDword(array_index); + } SaveString(pString); delete[] pString; break; @@ -6601,6 +6739,114 @@ bool COMPILER::OnLoad() return true; } +void COMPILER::PrepareEventsToSaving() +{ + VarIndex varIndex = CollectAttributeIndex(); + + VarInfo vi; + vi.name = "__eventsData"; + vi.type = S_TOKEN_TYPE::VAR_OBJECT; + vi.segment_id = 0; + vi.elements = 1; + + size_t idx = VarTab.FindVar(vi.name); + if (idx == INVALID_VAR_CODE) + { + idx = VarTab.AddVar(vi); + } + + auto pvi = VarTab.GetVarX(idx); + if (!pvi) + { + spdlog::error("error during writting event record"); + return; + } + auto oldAtt = pvi->value->AttributesClass; + if (oldAtt) + { + delete oldAtt; + } + pvi->value->AttributesClass = new ATTRIBUTES(GetVSC()); + EventTab.StoreEventsData(pvi->value->AttributesClass, FuncTab, varIndex); + EventMsg.StoreEventsData(pvi->value->AttributesClass, varIndex); + return; +} + +void COMPILER::PrepareEventsBeforeLoading() +{ + VarInfo vi; + vi.name = "__eventsData"; + vi.type = S_TOKEN_TYPE::VAR_OBJECT; + vi.segment_id = 0; + vi.elements = 1; + VarTab.AddVar(vi); +} + +void COMPILER::PrepareEventsAfterLoading() +{ + auto idx = VarTab.FindVar("__eventsData"); + if (idx == INVALID_VAR_CODE) + { + spdlog::error("no event data available"); + return; + } + auto info = VarTab.GetVar(idx); + + if (!info->value->AttributesClass) + { + spdlog::error("wrong event record"); + return; + } + + EventTab.LoadEventsData(info->value->AttributesClass, FuncTab, VarTab); + EventMsg.LoadEventsData(info->value->AttributesClass, VarTab); +} + +VarIndex COMPILER::CollectAttributeIndex() const +{ + std::unordered_map>> result; + const uint32_t nVarNum = VarTab.GetVarNum(); + + for (size_t n = 0; n < nVarNum; n++) + { + const VarInfo *real_var = VarTab.GetVar(n); + if (real_var == nullptr) + { + continue; + } + + std::vector indexVector; + CollectAttributeIndexStep(real_var->value.get(), real_var->name, indexVector, result); + } + + return result; +} +void COMPILER::CollectAttributeIndexStep(DATA *pV, const std::string &varName, std::vector &indexVector, VarIndex &result) const +{ + if (pV == nullptr) + { + return; + } + + if (pV->IsArray()) + { + for (size_t n = 0; n < pV->GetElementsNum(); n++) + { + // Потенциальная потеря производительности, если упремся - заменим на стек + std::vector curIndexVector = indexVector; + curIndexVector.push_back(n); + CollectAttributeIndexStep(pV->GetArrayElement(n), varName, curIndexVector, result); + } + return; + } + + if (pV->GetType() == VAR_OBJECT) + { + result[pV->AttributesClass] = std::pair>(varName, indexVector); + } +} + + bool COMPILER::SaveState(std::fstream &fileS) { uint32_t n; @@ -6615,6 +6861,8 @@ bool COMPILER::SaveState(std::fstream &fileS) if (function_code != INVALID_FUNC_CODE) BC_Execute(function_code, pResult); + PrepareEventsToSaving(); + EXTDATA_HEADER edh; auto *pVDat = static_cast(core_internal.GetScriptVariable("savefile_info")); if (pVDat && pVDat->GetString()) @@ -6764,7 +7012,7 @@ bool COMPILER::LoadState(std::fstream &fileS) return false; delete[] pSegmentName; } - + PrepareEventsBeforeLoading(); // 5. Variables table, all variables created during previous step, just read value const uint32_t nVarNum = ReadVDword(); for (n = 0; n < nVarNum; n++) @@ -6776,13 +7024,13 @@ bool COMPILER::LoadState(std::fstream &fileS) return false; } ReadVariable(pString /*,n*/); - + delete[] pString; } - + PrepareEventsAfterLoading(); // call to script function "OnLoad()" OnLoad(); - + EventMsg.FixEnitiyIDs(); delete[] pBuffer; pBuffer = nullptr; @@ -6819,7 +7067,7 @@ void COMPILER::ReadAttributesData(ATTRIBUTES *pRoot, ATTRIBUTES *pParent) nNameCode = ReadVDword(); pValue = ReadString(); // pRoot->SetAttribute(nNameCode,pValue); - + pRoot->SetNameCode(nNameCode); pRoot->SetValue(pValue); @@ -7411,7 +7659,7 @@ void COMPILER::LoadEventHandlersFromCache(storm::script_cache::BufferReader &rea auto event = std::string(reader.ReadArray()); auto name = std::string(reader.ReadArray()); - SetEventHandler(event.c_str(), name.c_str(), 0, true); + SetEventHandler(nullptr, event.c_str(), name.c_str(), 0, true); } } @@ -8022,3 +8270,8 @@ void STRING_CODEC::VariableChanged() CDebug->SetTraceMode(TMODE_MAKESTEP); #endif } + +void COMPILER::SetEventFormat(const char *eventName, std::string format) +{ + EventTab.SetEventFormat(eventName, format); +} diff --git a/src/libs/core/src/compiler.h b/src/libs/core/src/compiler.h index 63eab800f..b9b991739 100644 --- a/src/libs/core/src/compiler.h +++ b/src/libs/core/src/compiler.h @@ -90,6 +90,7 @@ enum COMPILER_STAGE class CoreImpl; +typedef std::unordered_map>> VarIndex; class COMPILER : public VIRTUAL_COMPILER { friend CoreImpl; @@ -127,8 +128,9 @@ class COMPILER : public VIRTUAL_COMPILER void SetProgramDirectory(const char *dir_name); VDATA *ProcessEvent(const char *event_name, MESSAGE message); VDATA *ProcessEvent(const char *event_name); - void SetEventHandler(const char *event_name, const char *func_name, int32_t flag, bool bStatic = false); - void DelEventHandler(const char *event_name, const char *func_name); + void SetEventHandler(ATTRIBUTES *pObject, const char *event_name, const char *func_name, int32_t flag, + bool bStatic = false); + void DelEventHandler(ATTRIBUTES *pObject, const char *event_name, const char *func_name); bool Completed() { @@ -267,6 +269,14 @@ class COMPILER : public VIRTUAL_COMPILER // printout script functions usage void PrintoutUsage(); + void PrepareEventsToSaving(); + void PrepareEventsBeforeLoading(); + void PrepareEventsAfterLoading(); + + void StoreEventsData(ATTRIBUTES *, + std::unordered_map>> &varIndex); + void LoadEventsData(ATTRIBUTES *, VarTable &VarTab); + private: [[nodiscard]] std::filesystem::path GetSegmentCachePath(const SEGMENT_DESC &segment) const; @@ -288,6 +298,15 @@ class COMPILER : public VIRTUAL_COMPILER void SaveEventHandlersToCache(storm::script_cache::BufferWriter &writer); void SaveByteCodeToCache(storm::script_cache::BufferWriter &writer, const SEGMENT_DESC &segment); + VarIndex CollectAttributeIndex() const; + void CollectAttributeIndexStep(DATA *pV, const std::string &varName, std::vector &indexVector, VarIndex &result) const; + VDATA *ProcessEventFunctions(std::vector &eventFuncVec, uint32_t event_code, MESSAGE *pMem, + uint64_t &nTicks); + VDATA *ProcessEventFunc(std::vector &eventFuncVec, uint32_t func_idx, uint32_t event_code, + MESSAGE *pMem, uint64_t &nTicks); + + void SetEventFormat(const char *eventName, std::string format); + COMPILER_STAGE CompilerStage; STRINGS_LIST LabelTable; // STRINGS_LIST EventTable; diff --git a/src/libs/core/src/core_impl.cpp b/src/libs/core/src/core_impl.cpp index a6938239a..a2c6eaa53 100644 --- a/src/libs/core/src/core_impl.cpp +++ b/src/libs/core/src/core_impl.cpp @@ -365,7 +365,7 @@ uint64_t CoreImpl::Send_Message(entid_t Destination, const char *Format, ...) return rc; } -uint32_t CoreImpl::PostEvent(const char *Event_name, uint32_t post_time, const char *Format, ...) +uint32_t CoreImpl::PostEvent(ATTRIBUTES *pObject, const char *Event_name, uint32_t post_time, const char *Format, ...) { MESSAGE *pMS; MESSAGE message; @@ -378,6 +378,11 @@ uint32_t CoreImpl::PostEvent(const char *Event_name, uint32_t post_time, const c va_list args; va_start(args, Format); message.ResetVA(Format, args); + + if (pObject) + { + pMS->SetThisObject(pObject); + } pMS->Reset(Format); auto bAction = true; diff --git a/src/libs/core/src/core_impl.h b/src/libs/core/src/core_impl.h index a83bf2af8..600fcbda1 100644 --- a/src/libs/core/src/core_impl.h +++ b/src/libs/core/src/core_impl.h @@ -97,7 +97,8 @@ class CoreImpl final : public CorePrivate // VDATA *Event(const std::string_view &event_name) override; VDATA *Event(const std::string_view &event_name, MESSAGE& message) override; - uint32_t PostEvent(const char *Event_name, uint32_t post_time, const char *Format, ...) override; + uint32_t PostEvent(ATTRIBUTES *pObject, const char *Event_name, uint32_t post_time, const char *Format, + ...) override; void *GetSaveData(const char *file_name, int32_t &data_size) override; diff --git a/src/libs/core/src/data.cpp b/src/libs/core/src/data.cpp index 533d065bd..9f0f23c39 100644 --- a/src/libs/core/src/data.cpp +++ b/src/libs/core/src/data.cpp @@ -113,6 +113,28 @@ DATA::DATA(S_TOKEN_TYPE _element_type) nGlobalVarTableIndex = 0xffffffff; } +DATA::DATA(entid_t eid, ATTRIBUTES *pARef) : pValue(0) +{ + Data_type = VAR_OBJECT; + Number_of_elements = 0; + lValue = 0; + fValue = 0; + bArray = false; + bEntity = false; + pVCompiler = nullptr; + Segment_id = 0; + object_id = eid; + pReference = nullptr; + AttributesClass = nullptr; + nGlobalVarTableIndex = 0xffffffff; + + if (pARef) + { + auto attrCopy = pARef->Copy(); + AttributesClass = new ATTRIBUTES(std::move(attrCopy)); + } +} + DATA::DATA(uint32_t _num_of_elements, S_TOKEN_TYPE _element_type) : pValue(0), object_id(0) { diff --git a/src/libs/core/src/data.h b/src/libs/core/src/data.h index abe3b9e40..25b65df1c 100644 --- a/src/libs/core/src/data.h +++ b/src/libs/core/src/data.h @@ -72,7 +72,10 @@ class DATA : public VDATA DATA &operator=(const DATA &); DATA(S_TOKEN_TYPE _element_type); DATA(uint32_t num_of_elements, S_TOKEN_TYPE _element_type); + + DATA(entid_t eid, ATTRIBUTES *pARef); ~DATA() override; + void Set(int32_t value) override; void SetPtr(uintptr_t value) override; bool GetPtr(uintptr_t &value) override; diff --git a/src/libs/core/src/internal_functions.cpp b/src/libs/core/src/internal_functions.cpp index 8a5df1cd1..6481db019 100644 --- a/src/libs/core/src/internal_functions.cpp +++ b/src/libs/core/src/internal_functions.cpp @@ -113,6 +113,11 @@ enum FUNCTION_CODE FUNC_CHECKFUNCTION, FUNC_GETENGINEVERSION, FUNC_SORT, + FUNC_SET_EVENT_HANDLER_FOR_OBJECT, + FUNC_DEL_EVENT_HANDLER_FOR_OBJECT, + FUNC_EVENT_FOR_OBJECT, + FUNC_POSTEVENT_FOR_OBJECT, + FUNC_SET_EVENT_FORMAT }; INTFUNCDESC IntFuncTable[] = { @@ -145,7 +150,12 @@ INTFUNCDESC IntFuncTable[] = { VAR_INTEGER, 1, "FindEntityNext", VAR_INTEGER, 2, "GetSymbol", VAR_STRING, 2, "IsDigit", VAR_INTEGER, 2, "SaveVariable", VAR_INTEGER, 2, "LoadVariable", VAR_INTEGER, 2, "SetControlTreshold", TVOID, 2, "LockControl", TVOID, 1, "TestRef", VAR_INTEGER, 1, "SetTimeScale", TVOID, 1, "CheckFunction", VAR_INTEGER, 0, "GetEngineVersion", - VAR_INTEGER, 1, "sort", TVOID}; + VAR_INTEGER, 1, "sort", TVOID, + 4, "SetEventHandlerForObject", TVOID, + 3, "DelEventHandlerForObject", TVOID, + 0, "EventForObject", TVOID, + 0, "PostEventForObject", TVOID, + 2, "SetEventFormat", TVOID}; /* char * FuncNameTable[]= @@ -367,6 +377,8 @@ bool COMPILER::IsIntFuncVarArgsNum(uint32_t code) case FUNC_SEND_MESSAGE: case FUNC_EVENT: case FUNC_POSTEVENT: + case FUNC_EVENT_FOR_OBJECT: + case FUNC_POSTEVENT_FOR_OBJECT: return true; } @@ -425,9 +437,11 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t Entity *pE; MESSAGE ms; uint32_t s_off; - + int shift; static std::remove_reference_t::const_iterator entity_iterator; static std::remove_reference_t::const_iterator entity_iterator_end; + std::optional format = std::nullopt; + std::string currentFormat; pResult = nullptr; TempFloat1 = 0; @@ -438,7 +452,7 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t int32_t slen, slen2; char sVarName[64]; std::string utf8_character; - + bool variadicHasAnError = false; switch (func_code) { case FUNC_GETENGINEVERSION: @@ -1628,6 +1642,7 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t core.EraseEntity(ent); break; // + case FUNC_DEL_EVENT_HANDLER_FOR_OBJECT: case FUNC_DEL_EVENT_HANDLER: pV2 = SStack.Pop(); if (!pV2) @@ -1643,8 +1658,34 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t } pV->Get(pChar); pV2->Get(pChar2); - DelEventHandler(pChar, pChar2); + + pA = nullptr; + if (func_code == FUNC_DEL_EVENT_HANDLER_FOR_OBJECT) + { + pV3 = SStack.Pop(); + if (!pV3) + { + SetError(INVALID_FA); + break; + } + pV3 = pV3->GetVarPointer(); + if (pV3->GetType() != VAR_OBJECT) + { + SetError(BAD_FA); + break; + } + pA = pV3->GetAClass(); + if (pA == nullptr) + { + SetError("AClass ERROR n1"); + break; + } + } + + + DelEventHandler(nullptr, pChar, pChar2); break; + case FUNC_SET_EVENT_HANDLER_FOR_OBJECT: case FUNC_SET_EVENT_HANDLER: pV3 = SStack.Pop(); if (!pV3) @@ -1667,7 +1708,30 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t pV->Get(pChar); pV2->Get(pChar2); pV3->Get(TempLong1); - SetEventHandler(pChar, pChar2, TempLong1); + pA = nullptr; + if (func_code == FUNC_SET_EVENT_HANDLER_FOR_OBJECT) + { + pV4 = SStack.Pop(); + if (!pV4) + { + SetError(INVALID_FA); + break; + } + pV4 = pV4->GetVarPointer(); + if (pV4->GetType() != VAR_OBJECT) + { + SetError(BAD_FA); + break; + } + pA = pV4->GetAClass(); + if (pA == nullptr) + { + SetError("AClass ERROR n1"); + break; + } + } + + SetEventHandler(pA, pChar, pChar2, TempLong1); break; // case FUNC_EXIT_PROGRAM: @@ -1681,58 +1745,10 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t SetError("No data on this event"); return nullptr; } - char format_sym; - format_sym = pEventMessage->GetCurrentFormatType(); - if (format_sym == 0) - { - SetError("No (more) data on this event"); - return nullptr; - } - switch (format_sym) - { - case 'a': - pResult = SStack.Push(); - pResult->SetType(VAR_AREFERENCE); - pResult->SetAReference(pEventMessage->AttributePointer()); - pVResult = pResult; - return pResult; - case 'l': - pResult = SStack.Push(); - pResult->Set(pEventMessage->Long()); - pVResult = pResult; - return pResult; - case 'f': - pResult = SStack.Push(); - pResult->Set(pEventMessage->Float()); - pVResult = pResult; - return pResult; - case 's': - pResult = SStack.Push(); - Message_string = pEventMessage->String(); - pResult->Set(Message_string.c_str()); - pVResult = pResult; - return pResult; - case 'i': - pResult = SStack.Push(); - pResult->SetType(VAR_AREFERENCE); - ent = pEventMessage->EntityID(); - pResult->Set(ent); - pResult->SetAReference(core_internal.Entity_GetAttributePointer(ent)); - - pVResult = pResult; - return pResult; - case 'e': - pResult = SStack.Push(); - DATA *pE; - pE = static_cast(pEventMessage->ScriptVariablePointer()); - pResult->SetReference(pE); - pVResult = pResult; - return pResult; - default: - SetError("Invalid data type in event message: '%c'", format_sym); - return nullptr; - } - break; + pResult = SStack.Push(); + pEventMessage->GetData(pResult, this); + pVResult = pResult; + return pResult; /*case FUNC_EXECUTE: pV = SStack.Pop(); if(!pV){SetError(INVALID_FA);break;}; pV->Get(pChar); @@ -1787,56 +1803,217 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t bCompleted = true; break; // - + + case FUNC_EVENT_FOR_OBJECT: case FUNC_EVENT: s_off = SStack.GetDataNum() - arguments; // set stack offset - pV = SStack.Read(s_off, 0); + + shift = 0; + if (func_code == FUNC_EVENT_FOR_OBJECT) + { + shift = 1; + pV = SStack.Read(s_off, 0); + if (!pV) + { + SetError(INVALID_FA); + variadicHasAnError = true; + break; + } + pV = pV->GetVarPointer(); + if (pV->GetType() != VAR_OBJECT) + { + SetError(BAD_FA); + variadicHasAnError = true; + break; + } + pA = pV->GetAClass(); + if (pA == nullptr) + { + SetError("AClass ERROR n1"); + variadicHasAnError = true; + break; + } + + ms.SetThisObject(pA); + } + + pV = SStack.Read(s_off, 0 + shift); if (!pV) { SetError(INVALID_FA); + variadicHasAnError = true; break; } pV->Get(pChar); - if (arguments > 1) + + + if (arguments > 1 + shift) + { + pV = SStack.Read(s_off, 1 + shift); + if (!pV) + { + SetError(INVALID_FA); + variadicHasAnError = true; + break; + } + pV->Get(pChar2); //format + + format = EventTab.GetEventFormat(pChar); + if (format.has_value()) + { + currentFormat = pChar2; + if (func_code == FUNC_EVENT_FOR_OBJECT) + { + currentFormat = "a" + currentFormat; + } + if (currentFormat != format.value()) + { + SetError("'%s' event expects '%s' format instead of '%s'", pChar, format.value().c_str(), currentFormat.c_str()); + variadicHasAnError = true; + break; + } + } + + CreateMessage(&ms, s_off, 1 + shift); + ms.Move2Start(); + ProcessEvent(pChar, &ms); + } + else if (func_code == FUNC_EVENT_FOR_OBJECT) { - CreateMessage(&ms, s_off, 1); + format = EventTab.GetEventFormat(pChar); + if (format.has_value()) + { + if (strcmp("a", format.value().c_str())) + { + SetError("'%s' event expects '%s' format instead of '%s'", pChar, format.value().c_str(), "a"); + variadicHasAnError = true; + break; + } + } ms.Move2Start(); ProcessEvent(pChar, &ms); } else + { ProcessEvent(pChar); + } + for (n = 0; n < arguments; n++) { SStack.Pop(); } // set stack pointer to correct position (vars in stack remain valid) break; + case FUNC_POSTEVENT_FOR_OBJECT: case FUNC_POSTEVENT: MESSAGE *pMS; S_EVENTMSG *pEM; s_off = SStack.GetDataNum() - arguments; // set stack offset - pV = SStack.Read(s_off, 0); + + shift = 0; + pA = nullptr; + if (func_code == FUNC_POSTEVENT_FOR_OBJECT) + { + shift = 1; + pV = SStack.Read(s_off, 0); + if (!pV) + { + SetError(INVALID_FA); + variadicHasAnError = true; + break; + } + pV = pV->GetVarPointer(); + if (pV->GetType() != VAR_OBJECT) + { + SetError(BAD_FA); + variadicHasAnError = true; + break; + } + pA = pV->GetAClass(); + if (pA == nullptr) + { + SetError("AClass ERROR n1"); + variadicHasAnError = true; + break; + } + } + + pV = SStack.Read(s_off, 0 + shift); if (!pV) { SetError(INVALID_FA); + variadicHasAnError = true; break; } pV->Get(pChar); - pV = SStack.Read(s_off, 1); + pV = SStack.Read(s_off, 1 + shift); if (!pV) { SetError(INVALID_FA); + variadicHasAnError = true; break; } pV->Get(TempLong1); - if (arguments >= 4) // event w/o message + + + + if (arguments >= 4 + shift) // event w/o message + { + pV = SStack.Read(s_off, 2 + shift); + if (!pV) + { + SetError(INVALID_FA); + variadicHasAnError = true; + break; + } + pV->Get(pChar2); // format + + format = EventTab.GetEventFormat(pChar); + if (format.has_value()) + { + currentFormat = pChar2; + if (func_code == FUNC_POSTEVENT_FOR_OBJECT) + { + currentFormat = "a" + currentFormat; + } + if (currentFormat != format.value()) + { + SetError("'%s' event expects '%s' format instead of '%s'", pChar, format.value().c_str(), + currentFormat.c_str()); + variadicHasAnError = true; + break; + } + } + + pMS = new MESSAGE(); + if (pA) + { + pMS->SetThisObject(pA); + } + CreateMessage(pMS, s_off, 2 + shift); + pMS->Move2Start(); + } + else if (pA) { + if (format.has_value()) + { + if (strcmp("a", format.value().c_str())) + { + SetError("'%s' event expects '%s' format instead of '%s'", pChar, format.value().c_str(), "a"); + variadicHasAnError = true; + break; + } + + } pMS = new MESSAGE(); - CreateMessage(pMS, s_off, 2); + pMS->SetThisObject(pA); pMS->Move2Start(); } else + { pMS = nullptr; + } + pEM = new S_EVENTMSG(pChar, pMS, TempLong1); EventMsg.Add(pEM); @@ -1852,6 +2029,7 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t if (!pV) { SetError(INVALID_FA); + variadicHasAnError = true; break; } pV->Get(ent); @@ -2570,7 +2748,38 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t }); break; + + case FUNC_SET_EVENT_FORMAT: + pV2 = SStack.Pop(); + if (!pV2) + { + SetError(INVALID_FA); + break; + } + + pV = SStack.Pop(); + if (!pV) + { + SetError(INVALID_FA); + break; + } + + pV->Get(pChar); + pV2->Get(pChar2); + + + SetEventFormat(pChar, pChar2); + break; } + + if (variadicHasAnError) + { + for (n = 0; n < arguments; n++) + { + SStack.Pop(); + } + } + return nullptr; } diff --git a/src/libs/core/src/message.cpp b/src/libs/core/src/message.cpp index e06537730..39d383ebb 100644 --- a/src/libs/core/src/message.cpp +++ b/src/libs/core/src/message.cpp @@ -5,6 +5,11 @@ #include #include +#include +#include +#include +#include "s_vartab.h" +#include "core_impl.h" void MESSAGE::Move2Start() { @@ -83,6 +88,20 @@ const std::string & MESSAGE::String() return get(params_[index - 1]); } +bool MESSAGE::Set(uint8_t value) +{ + ValidateFormat('b'); + params_[index - 1] = value; + return true; +} + +bool MESSAGE::Set(uint16_t value) +{ + ValidateFormat('w'); + params_[index - 1] = value; + return true; +} + bool MESSAGE::Set(int32_t value) { ValidateFormat('l'); @@ -90,6 +109,13 @@ bool MESSAGE::Set(int32_t value) return true; } +bool MESSAGE::Set(uint32_t value) +{ + ValidateFormat('u'); + params_[index - 1] = value; + return true; +} + bool MESSAGE::Set(uintptr_t value) { ValidateFormat('p'); @@ -104,6 +130,13 @@ bool MESSAGE::Set(float value) return true; } +bool MESSAGE::Set(double value) +{ + ValidateFormat('d'); + params_[index - 1] = value; + return true; +} + bool MESSAGE::Set(std::string value) { ValidateFormat('s'); @@ -132,6 +165,13 @@ bool MESSAGE::Set(ATTRIBUTES *value) return true; } +bool MESSAGE::Set(CVECTOR value) +{ + ValidateFormat('c'); + params_[index - 1] = value; + return true; +} + void MESSAGE::ValidateFormat(char c) { if (format_.empty()) @@ -143,15 +183,31 @@ void MESSAGE::ValidateFormat(char c) void MESSAGE::Reset(const std::string_view &format) { - format_ = format; + if (hasThisObject_ && index == 1 && format_ == "a") + { + format_ += format; + } + else + { + index = 0; + format_ = format; + } + params_.resize(format_.size()); - index = 0; } void MESSAGE::ResetVA(const std::string_view &format, va_list&args) { - index = 0; - format_ = format; + if (hasThisObject_ && index == 1 && format_ == "a") + { + format_ += format; + } + else + { + index = 0; + format_ = format; + } + params_.resize(format_.size()); std::transform(format_.begin(), format_.end(), params_.begin(), [&](const char c) { return GetParamValue(c, args); }); @@ -172,6 +228,11 @@ std::string_view MESSAGE::GetFormat() const return format_; } +size_t MESSAGE::GetParametersCount() const +{ + return format_.size(); +} + bool MESSAGE::ParamValid() const { return index < format_.length(); @@ -211,3 +272,667 @@ storm::MessageParam MESSAGE::GetParamValue(const char c, va_list&args) throw std::runtime_error(fmt::format("Unknown message format: '{}'", c)); } } + +void MESSAGE::GetData(DATA *vd, COMPILER *comp) +{ + char format_sym; + format_sym = GetCurrentFormatType(); + if (format_sym == 0) + { + comp->SetError("No (more) data on this event"); + return; + } + entid_t ent; + std::string str; + switch (format_sym) + { + case 'a': + vd->SetType(VAR_AREFERENCE); + vd->SetAReference(AttributePointer()); + return; + case 'l': + vd->Set(Long()); + return; + case 'f': + vd->Set(Float()); + return; + case 's': + str = String(); + vd->Set(str.c_str()); + return; + case 'i': + vd->SetType(VAR_AREFERENCE); + ent = EntityID(); + vd->Set(ent); + vd->SetAReference(core_internal.Entity_GetAttributePointer(ent)); + return; + case 'e': + DATA *pE; + pE = static_cast(ScriptVariablePointer()); + vd->SetType(VAR_REFERENCE); + vd->SetReference(pE); + return; + default: + comp->SetError("Invalid data type in event message: '%c'", format_sym); + return; + } +} + +ATTRIBUTES *MESSAGE::GetThisObject() +{ + if (!hasThisObject_) + { + return nullptr; + } + + if (!format_.size() || format_[0] != 'a') + { + throw std::runtime_error(fmt::format("Wrong message format: '{}'; First elem should be an aref", format_)); + } + + return std::get(params_[0]); +} +void MESSAGE::SetThisObject(ATTRIBUTES *attr) +{ + if (format_.size()) + { + throw std::runtime_error(fmt::format("Should be called for an empty object", format_)); + } + format_ = "a"; + hasThisObject_ = true; + index = 1; + params_.push_back(attr); +} + + +bool StoreAttributesRef(ATTRIBUTES *attr, const ATTRIBUTES *val, + std::unordered_map>> &varIndex) +{ + if (!val) + { + return true; + } + + std::vector attributes; + const ATTRIBUTES *curAttr = val; + while (true) + { + if (curAttr->GetParent() == nullptr) + { + break; + } + attributes.push_back(curAttr->GetThisName()); + curAttr = curAttr->GetParent(); + } + + auto globalVarData = varIndex.find((void *)curAttr); + + if (globalVarData == varIndex.end()) + { + return false; + } + + attr->CreateAttribute(std::string("varName"), globalVarData->second.first.c_str()); + auto indexes = globalVarData->second.second; + + if (indexes.size()) + { + auto &indexesRec = attr->CreateAttribute(std::string("indexes")); + for (size_t i = 0; i < indexes.size(); i++) + { + indexesRec.CreateAttribute(fmt::format("{}", i), fmt::format("{}", indexes[i]).c_str()); + } + } + + if (attributes.size()) + { + auto &attributesRec = attr->CreateAttribute(std::string("attributes")); + for (size_t i = 0; i < attributes.size(); i++) + { + attributesRec.CreateAttribute(fmt::format("{}", i), attributes[i].c_str()); + } + } + return true; +} + +static void StoreParam(ATTRIBUTES *attr, const uint8_t &val) +{ + attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); +} + +static void StoreParam(ATTRIBUTES *attr, const uint16_t &val) +{ + attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); +} + +static void StoreParam(ATTRIBUTES *attr, const uint32_t &val) +{ + attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); +} + +static void StoreParam(ATTRIBUTES *attr, const int32_t &val) +{ + attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); +} + +static void StoreParam(ATTRIBUTES *attr, const float &val) +{ + attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); +} + +static void StoreParam(ATTRIBUTES *attr, const double &val) +{ + attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); +} + +static void StoreParam(ATTRIBUTES *attr, const uintptr_t &val) +{ + attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); +} + +static void StoreParam(ATTRIBUTES *attr, const ATTRIBUTES *val, + std::unordered_map>> &varIndex) +{ + if (!StoreAttributesRef(attr, val, varIndex)) + { + auto &data = attr->CreateAttribute(std::string("value")); + data = val->Copy(); + } +} + +static void StoreParamEntity(ATTRIBUTES *attr, const entid_t &val, + std::unordered_map>> &varIndex) +{ + auto data = core_internal.Entity_GetAttributePointer(val); + StoreParam(attr, data, varIndex); +} + +static void StoreParam(ATTRIBUTES *attr, VDATA *val, + std::unordered_map>> &varIndex) +{ + entid_t eid = val->GetEntityID(); + attr->CreateAttribute(std::string("objectId"), fmt::format("{}", eid).c_str()); + auto attributes = val->GetAClass(); + StoreParam(attr, attributes, varIndex); + +} + +static void StoreParam(ATTRIBUTES *attr, const CVECTOR &val) +{ + attr->CreateAttribute(std::string("x"), fmt::format("{}", val.x).c_str()); + attr->CreateAttribute(std::string("y"), fmt::format("{}", val.y).c_str()); + attr->CreateAttribute(std::string("z"), fmt::format("{}", val.z).c_str()); +} + +static void StoreParam(ATTRIBUTES *attr, const std::string &val) +{ + attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); +} + + +void MESSAGE::StoreData(ATTRIBUTES *attr, std::unordered_map>> &varIndex) const +{ + attr->CreateAttribute(std::string("format"), format_.c_str()); + int ito = hasThisObject_; + + attr->CreateAttribute(std::string("isThisObject"), fmt::format("{}", ito).c_str()); + + auto ¶msRecord = attr->CreateAttribute(std::string("params")); + + assert(format_.size() == params_.size()); + for (uint32_t i = 0; i < format_.size(); i++) + { + auto &curParamRecord = paramsRecord.CreateAttribute(fmt::format("{}", i)); + switch (format_[i]) + { + case 'b': + StoreParam(&curParamRecord, std::get(params_[i])); + continue; + case 'w': + StoreParam(&curParamRecord, std::get(params_[i])); + continue; + case 'l': + StoreParam(&curParamRecord, std::get(params_[i])); + continue; + case 'u': + StoreParam(&curParamRecord, std::get(params_[i])); + continue; + case 'f': + StoreParam(&curParamRecord, std::get(params_[i])); + continue; + case 'd': + StoreParam(&curParamRecord, std::get(params_[i])); + continue; + case 'p': + StoreParam(&curParamRecord, std::get(params_[i])); + continue; + case 'a': + StoreParam(&curParamRecord, std::get(params_[i]), varIndex); + continue; + case 'i': + StoreParamEntity(&curParamRecord, std::get(params_[i]), varIndex); + continue; + case 'e': + StoreParam(&curParamRecord, std::get(params_[i]), varIndex); + continue; + case 'c': + StoreParam(&curParamRecord, std::get(params_[i])); + continue; + case 's': { + StoreParam(&curParamRecord, std::get(params_[i])); + continue; + } + default: + throw std::runtime_error(fmt::format("Unknown message format: '{}'", format_[i])); + } + } +} + +template T LoadParam(ATTRIBUTES *attr) +{ + static_assert(false, "Not implemented"); +} + +template T LoadParam(ATTRIBUTES *attr, VarTable &VarTab) +{ + static_assert(false, "Not implemented"); +} + + +template <> uint8_t LoadParam(ATTRIBUTES *attr) +{ + auto valueAttr = attr->GetAttributeClass(std::string("value")); + if (!valueAttr) + { + spdlog::error("value not found"); + return 0; + } + + auto str = valueAttr->GetValue(); + return std::stoll(str.c_str()); +} + +template <> uint16_t LoadParam(ATTRIBUTES *attr) +{ + auto valueAttr = attr->GetAttributeClass(std::string("value")); + if (!valueAttr) + { + spdlog::error("value not found"); + return 0; + } + + auto str = valueAttr->GetValue(); + return std::stoll(str.c_str()); +} + +template <> uint32_t LoadParam(ATTRIBUTES *attr) +{ + auto valueAttr = attr->GetAttributeClass(std::string("value")); + if (!valueAttr) + { + spdlog::error("value not found"); + return 0; + } + + auto str = valueAttr->GetValue(); + return std::stoll(str.c_str()); +} + +template <> int32_t LoadParam(ATTRIBUTES *attr) +{ + auto valueAttr = attr->GetAttributeClass(std::string("value")); + if (!valueAttr) + { + spdlog::error("value not found"); + return 0; + } + + auto str = valueAttr->GetValue(); + return std::stoll(str.c_str()); +} + +template <> float LoadParam(ATTRIBUTES *attr) +{ + auto valueAttr = attr->GetAttributeClass(std::string("value")); + if (!valueAttr) + { + spdlog::error("value not found"); + return 0; + } + + auto str = valueAttr->GetValue(); + return std::stold(str.c_str()); +} + +template <> double LoadParam(ATTRIBUTES *attr) +{ + auto valueAttr = attr->GetAttributeClass(std::string("value")); + if (!valueAttr) + { + spdlog::error("value not found"); + return 0; + } + + auto str = valueAttr->GetValue(); + return std::stold(str.c_str()); +} + +template <> uintptr_t LoadParam(ATTRIBUTES *attr) +{ + spdlog::warn("'p' parameter is not supproted for messages"); + auto valueAttr = attr->GetAttributeClass(std::string("value")); + if (!valueAttr) + { + spdlog::error("value not found"); + return 0; + } + + auto str = valueAttr->GetValue(); + return std::stoll(str.c_str()); +} + +static DATA *FindVariable(std::string name, std::vector indexes, VarTable &VarTab) +{ + auto varCode = VarTab.FindVar(name); + const VarInfo *realVar; + DATA *dt; + if (varCode == INVALID_VAR_CODE) + { + spdlog::error("Load warning - variable: '{}' not found", name); + return nullptr; + } + else + { + realVar = VarTab.GetVarX(varCode); + if (realVar == nullptr) + { + spdlog::error("Load warning - variable: '{}' has invalid var code", name); + return nullptr; + } + else + { + dt = realVar->value.get(); + } + } + + for (auto idx : indexes) + { + dt = dt->GetArrayElement(idx); + if (!dt) + { + spdlog::error("Load warning - variable: '{}' has not index {}", name, idx); + return nullptr; + } + } + + return dt; +} + +static DATA *LoadVariable(ATTRIBUTES *attr, VarTable &VarTab) +{ + auto varNameAttr = attr->GetAttributeClass(std::string("varName")); + if (!varNameAttr) + { + spdlog::error("varName not found"); + return nullptr; + } + + auto varName = varNameAttr->GetValue(); + + std::vector indexes; + auto indexesRec = attr->GetAttributeClass(std::string("indexes")); + if (indexesRec) + { + auto indexCount = indexesRec->GetAttributesNum(); + for (size_t i = 0; i < indexCount; i++) + { + auto curIndexRecord = indexesRec->GetAttributeClass(fmt::format("{}", i)); + if (!curIndexRecord) + { + spdlog::error("indexes.{} not found", i); + return nullptr; + } + + indexes.push_back(std::stoll(curIndexRecord->GetValue().c_str())); + } + } + + return FindVariable(varName, indexes, VarTab); +} + +ATTRIBUTES *LoadAttributesRef(ATTRIBUTES *attr, VarTable &VarTab) +{ + auto var = LoadVariable(attr, VarTab); + if (!var) + { + return nullptr; + } + auto attributes = var->GetAClass(); + if (!attributes) + { + return nullptr; + } + + auto attributesRec = attr->GetAttributeClass(std::string("attributes")); + if (attributesRec) + { + auto attributesCount = attributesRec->GetAttributesNum(); + for (size_t i = 0; i < attributesCount; i++) + { + auto curAttributeRecord = attributesRec->GetAttributeClass(fmt::format("{}", i)); + if (!curAttributeRecord) + { + spdlog::error("attributes.{} not found", i); + return nullptr; + } + + attributes = attributes->GetAttributeClass(curAttributeRecord->GetValue()); + if (!attributes) + { + spdlog::error("missing attribute '{}'", curAttributeRecord->GetValue()); + return nullptr; + } + } + } + return attributes; +} + + +template <> ATTRIBUTES *LoadParam(ATTRIBUTES *attr, VarTable &VarTab) +{ + auto valueAttr = attr->GetAttributeClass(std::string("value")); + if (valueAttr) + { + return valueAttr; + } + + + return LoadAttributesRef(attr, VarTab); +} + +static DATA *LoadParamEntity(ATTRIBUTES *attr, VarTable &VarTab) +{ + DATA *dt = LoadVariable(attr, VarTab); + if (!dt) + { + return nullptr; + } + return dt; +} + +template <> VDATA *LoadParam(ATTRIBUTES *attr, VarTable &VarTab) +{ + auto valueAttr = attr->GetAttributeClass(std::string("value")); + if (valueAttr) + { + auto objectIdAttr = attr->GetAttributeClass(std::string("objectId")); + if (!objectIdAttr) + { + spdlog::error("objectId not found"); + return nullptr; + } + + entid_t objectId = std::stoll(objectIdAttr->GetValue()); + return new DATA(objectId, valueAttr); + } + + DATA *dt = LoadVariable(attr, VarTab); + if (!dt) + { + return nullptr; + } + + return dt; +} + +template <> CVECTOR LoadParam(ATTRIBUTES *attr) +{ + CVECTOR ret; + + auto xAttr = attr->GetAttributeClass(std::string("x")); + if (!xAttr) + { + spdlog::error("x not found"); + return ret; + } + + auto yAttr = attr->GetAttributeClass(std::string("y")); + if (!yAttr) + { + spdlog::error("y not found"); + return ret; + } + + auto zAttr = attr->GetAttributeClass(std::string("z")); + if (!zAttr) + { + spdlog::error("z not found"); + return ret; + } + ret.x = std::stold(xAttr->GetValue().c_str()); + ret.y = std::stold(yAttr->GetValue().c_str()); + ret.z = std::stold(zAttr->GetValue().c_str()); + return ret; +} + +template <> std::string LoadParam(ATTRIBUTES *attr) +{ + auto valueAttr = attr->GetAttributeClass(std::string("value")); + if (!valueAttr) + { + spdlog::error("value not found"); + return "error"; + } + + return valueAttr->GetValue(); +} + +MESSAGE *MESSAGE::LoadData(ATTRIBUTES *attr, VarTable &VarTab) +{ + + auto formatAttr = attr->GetAttributeClass(std::string("format")); + if (!formatAttr) + { + spdlog::error("format not found"); + return nullptr; + } + + auto formatStr = formatAttr->GetValue(); + + + auto isThisObjectAttr = attr->GetAttributeClass(std::string("isThisObject")); + if (!isThisObjectAttr) + { + spdlog::error("isThisObject not found"); + return nullptr; + } + + auto ito = stoll(isThisObjectAttr->GetValue()); + + auto paramsAttr = attr->GetAttributeClass(std::string("params")); + if (!paramsAttr) + { + spdlog::error("params not found"); + return nullptr; + } + + auto paramsCount = paramsAttr->GetAttributesNum(); + if (paramsCount != formatStr.size()) + { + spdlog::error("params count != format length"); + return nullptr; + } + + MESSAGE msg; + msg.Reset(formatStr); + msg.hasThisObject_ = (bool)ito; + for (size_t i = 0; i < paramsCount; i++) + { + auto curParamRecord = paramsAttr->GetAttributeClass(fmt::format("{}", i)); + if (!curParamRecord) + { + spdlog::error("params.{} not found", i); + return nullptr; + } + DATA *ent = nullptr; + switch (formatStr[i]) + { + case 'b': + msg.Set(LoadParam(curParamRecord)); + break; + case 'w': + msg.Set(LoadParam(curParamRecord)); + break; + case 'l': + msg.Set(LoadParam(curParamRecord)); + break; + case 'u': + msg.Set(LoadParam(curParamRecord)); + break; + case 'f': + msg.Set(LoadParam(curParamRecord)); + break; + case 'd': + msg.Set(LoadParam(curParamRecord)); + break; + case 'p': + msg.Set(LoadParam(curParamRecord)); + break; + case 'a': + msg.Set(LoadParam(curParamRecord, VarTab)); + break; + case 'i': + ent = LoadParamEntity(curParamRecord, VarTab); + msg.SetEntity(ent->GetEntityID()); + // Впоследсвии будет перезаписана новым GetEntityID(), после обновления сущностей + msg.params_[i] = ent; + break; + case 'e': + msg.Set(LoadParam(curParamRecord, VarTab)); + break; + case 'c': + msg.Set(LoadParam(curParamRecord)); + break; + case 's': { + msg.Set(LoadParam(curParamRecord)); + break; + } + default: + throw std::runtime_error(fmt::format("Unknown message format: '{}'", formatStr[i])); + } + } + + return new MESSAGE(std::move(msg)); +} + + +void MESSAGE::FixEnitiyIDs() +{ + for (uint32_t i = 0; i < format_.size(); i++) + { + if (format_[i] == 'i') + { + params_[i] = std::get(params_[i])->GetEntityID(); + } + } +} diff --git a/src/libs/core/src/s_eventmsg.h b/src/libs/core/src/s_eventmsg.h index 564af860e..7c1717078 100644 --- a/src/libs/core/src/s_eventmsg.h +++ b/src/libs/core/src/s_eventmsg.h @@ -2,6 +2,8 @@ #include "message.h" #include "platform/platform.hpp" +#include "s_vartab.h" +#include class S_EVENTMSG { @@ -61,4 +63,69 @@ class S_EVENTMSG { bInvalide = true; }; + + bool IsValid() const + { + return !bInvalide && pEventName; + } + + void StoreData(ATTRIBUTES *attr, + std::unordered_map>> &varIndex) const + { + + auto period = 0; + if (nTime < nPeriod) + { + period = nPeriod - nTime; + } + + attr->CreateAttribute(std::string("nPeriod"), fmt::format("{}", period).c_str()); + attr->CreateAttribute(std::string("pEventName"), pEventName); + + if (pMessageClass) + { + pMessageClass->StoreData(&attr->CreateAttribute(std::string("pEventMsg")), varIndex); + } + + } + + static S_EVENTMSG *LoadData(ATTRIBUTES *attr, VarTable &VarTab) + { + auto nPeriodRec = attr->GetAttributeClass(std::string("nPeriod")); + if (!nPeriodRec) + { + spdlog::error("nPeriod not found"); + return nullptr; + } + + auto nPeriodSVal = nPeriodRec->GetValue(); + uint32_t period = std::stoll(nPeriodSVal); + + auto pEventNameRec = attr->GetAttributeClass(std::string("pEventName")); + if (!pEventNameRec) + { + spdlog::error("pEventName not found"); + return nullptr; + } + + auto pEventNameVal = pEventNameRec->GetValue(); + + MESSAGE *msg = nullptr; + + auto MessageRec = attr->GetAttributeClass(std::string("pEventMsg")); + if (MessageRec) + { + msg = MESSAGE::LoadData(MessageRec, VarTab); + } + + return new S_EVENTMSG(pEventNameVal.c_str(), msg, period); + } + + void FixEnitiyIDs() + { + if (pMessageClass) + { + pMessageClass->FixEnitiyIDs(); + } + } }; diff --git a/src/libs/core/src/s_eventtab.cpp b/src/libs/core/src/s_eventtab.cpp index 2ea193693..fe26b306c 100644 --- a/src/libs/core/src/s_eventtab.cpp +++ b/src/libs/core/src/s_eventtab.cpp @@ -1,6 +1,9 @@ #include "s_eventtab.h" #include "string_compare.hpp" +#include +#include "message.h" + #define HASHT_INDEX(x) (uint8_t)(x >> 24) #define HASHT_CODE(x) (x & 0xffffff) #define HASH2INDEX(x) (uint8_t)(x & 0x2f) @@ -25,12 +28,22 @@ void S_EVENTTAB::Clear() { for (uint32_t n = 0; n < Event_num[i]; n++) { - for (uint32_t m = 0; m < pTable[i][n].elements; m++) + for (uint32_t m = 0; m < pTable[i][n].pFuncInfo.size(); m++) { if (!pTable[i][n].pFuncInfo[m].bStatic) pTable[i][n].pFuncInfo[m].status = FSTATUS_DELETED; } + + for (auto &elem : pTable[i][n].pFuncInfoForObjects) + { + for (auto &handler : elem.second) + { + handler.status = FSTATUS_DELETED; + } + } + + // if(pTable[n].pFuncInfo) delete pTable[n].pFuncInfo; // if(pTable[n].name) delete pTable[n].name; } @@ -65,86 +78,59 @@ bool S_EVENTTAB::GetEvent(EVENTINFO &ei, uint32_t event_code) return true; } -uint32_t S_EVENTTAB::AddEventHandler(const char *event_name, uint32_t func_code, uint32_t func_segment_id, int32_t flag, + +uint32_t S_EVENTTAB::AddEventHandler(ATTRIBUTES *pObject, const char *event_name, uint32_t func_code, uint32_t func_segment_id, int32_t flag, bool bStatic) { uint32_t i; - + uint32_t eventPos = 0; const auto hash = MakeHashValue(event_name); const auto ti = HASH2INDEX(hash); - for (uint32_t n = 0; n < Event_num[ti]; n++) - { - if (pTable[ti][n].hash == hash) - { - if (!storm::iEquals(event_name, pTable[ti][n].name)) - continue; - // event already in list - for (i = 0; i < pTable[ti][n].elements; i++) - { - // event handler function already set - if (pTable[ti][n].pFuncInfo[i].func_code == func_code) - { - /*if(pTable[ti][n].pFuncInfo[i].status == FSTATUS_DELETED) - { - trace("pTable[ti][n].pFuncInfo[i].status == FSTATUS_DELETED : %s",pTable[ti][n].name); - }*/ - // return n; - pTable[ti][n].pFuncInfo[i].status = FSTATUS_NORMAL; + EVENTINFO *ei = FindEventByName(event_name, true, &eventPos); - return (((ti << 24) & 0xff000000) | (n & 0xffffff)); - } - } - // add function - i = pTable[ti][n].elements; - pTable[ti][n].elements++; - pTable[ti][n].pFuncInfo.resize(pTable[ti][n].elements); - - pTable[ti][n].pFuncInfo[i].func_code = func_code; - pTable[ti][n].pFuncInfo[i].segment_id = func_segment_id; - if (flag) - pTable[ti][n].pFuncInfo[i].status = FSTATUS_NEW; - else - pTable[ti][n].pFuncInfo[i].status = FSTATUS_NORMAL; - pTable[ti][n].pFuncInfo[i].bStatic = bStatic; - // return n; - return (((ti << 24) & 0xff000000) | (n & 0xffffff)); - } - } + auto funcInfoVecP = &ei->pFuncInfo; - // add new event - if (Event_num[ti] >= Buffer_size[ti]) + if (pObject) { - Buffer_size[ti] += BUFFER_BLOCK_SIZE; - pTable[ti].resize(Buffer_size[ti]); + auto it = ei->pFuncInfoForObjects.find(pObject); + if (it == ei->pFuncInfoForObjects.end()) + { + ei->pFuncInfoForObjects[pObject] = std::vector(); + funcInfoVecP = &ei->pFuncInfoForObjects[pObject]; + } + else + { + funcInfoVecP = &it->second; + } } - pTable[ti][Event_num[ti]].elements = 1; - pTable[ti][Event_num[ti]].hash = hash; - pTable[ti][Event_num[ti]].name = nullptr; - - pTable[ti][Event_num[ti]].pFuncInfo.push_back(EVENT_FUNC_INFO{}); - pTable[ti][Event_num[ti]].pFuncInfo[0].func_code = func_code; - pTable[ti][Event_num[ti]].pFuncInfo[0].segment_id = func_segment_id; - if (flag) - pTable[ti][Event_num[ti]].pFuncInfo[0].status = FSTATUS_NEW; - else - pTable[ti][Event_num[ti]].pFuncInfo[0].status = FSTATUS_NORMAL; - pTable[ti][Event_num[ti]].pFuncInfo[0].bStatic = bStatic; + auto &funcInfoVec = *funcInfoVecP; - if constexpr (true) // bKeepName) + for (i = 0; i < funcInfoVec.size(); i++) { - if (event_name) + // event handler function already set + if (funcInfoVec[i].func_code == func_code) { - const auto len = strlen(event_name) + 1; - pTable[ti][Event_num[ti]].name = new char[len]; - memcpy(pTable[ti][Event_num[ti]].name, event_name, len); + funcInfoVec[i].status = FSTATUS_NORMAL; + return (((ti << 24) & 0xff000000) | (eventPos & 0xffffff)); } } - Event_num[ti]++; - // return (Event_num[ti] - 1); - return (((ti << 24) & 0xff000000) | ((Event_num[ti] - 1) & 0xffffff)); + // add function + i = funcInfoVec.size(); + + funcInfoVec.resize(i + 1); + + funcInfoVec[i].func_code = func_code; + funcInfoVec[i].segment_id = func_segment_id; + if (flag) + funcInfoVec[i].status = FSTATUS_NEW; + else + funcInfoVec[i].status = FSTATUS_NORMAL; + funcInfoVec[i].bStatic = bStatic; + // return n; + return (((ti << 24) & 0xff000000) | (eventPos & 0xffffff)); } uint32_t S_EVENTTAB::MakeHashValue(const char *string) @@ -166,27 +152,7 @@ uint32_t S_EVENTTAB::MakeHashValue(const char *string) return hval; } -bool S_EVENTTAB::DelEventHandler(const char *event_name, uint32_t func_code) -{ - if (event_name == nullptr) - return false; - const auto hash = MakeHashValue(event_name); - - const auto ti = HASH2INDEX(hash); - - for (uint32_t n = 0; n < Event_num[ti]; n++) - { - if (pTable[ti][n].hash == hash) - if (storm::iEquals(pTable[ti][n].name, event_name)) - { - return DelEventHandler(ti, n, func_code); - // return; - } - } - return false; -} - -void S_EVENTTAB::SetStatus(const char *event_name, uint32_t func_code, uint32_t status) +void S_EVENTTAB::SetStatus(ATTRIBUTES *pObject, const char *event_name, uint32_t func_code, uint32_t status) { if (event_name == nullptr) return; @@ -199,34 +165,54 @@ void S_EVENTTAB::SetStatus(const char *event_name, uint32_t func_code, uint32_t if (pTable[ti][n].hash == hash) if (storm::iEquals(pTable[ti][n].name, event_name)) { - for (uint32_t i = 0; i < pTable[ti][n].elements; i++) + if (!pObject) { - if (pTable[ti][n].pFuncInfo[i].func_code == func_code) + for (uint32_t i = 0; i < pTable[ti][n].pFuncInfo.size(); i++) { - pTable[ti][n].pFuncInfo[i].status = status; + if (pTable[ti][n].pFuncInfo[i].func_code == func_code) + { + pTable[ti][n].pFuncInfo[i].status = status; + return; + } + } + } + else + { + auto it = pTable[ti][n].pFuncInfoForObjects.find(pObject); + if (it == pTable[ti][n].pFuncInfoForObjects.end()) return; + + for (auto &handler : it->second) + { + if (handler.func_code == func_code) + { + handler.status = status; + return; + } } } + } } } -bool S_EVENTTAB::DelEventHandler(uint8_t ti, uint32_t event_code, uint32_t func_code, bool bDelStatic) +bool S_EVENTTAB::DelEventHandler(std::vector &funcInfo, uint32_t func_code, + bool bDelStatic) { + if (!bDelStatic) { - if (pTable[ti][event_code].pFuncInfo[func_code].bStatic) + if (funcInfo[func_code].bStatic) { return false; } } - for (auto n = func_code; n < (pTable[ti][event_code].elements - 1); n++) + for (auto n = func_code; n < funcInfo.size() - 1; n++) { - pTable[ti][event_code].pFuncInfo[n] = pTable[ti][event_code].pFuncInfo[n + 1]; + funcInfo[n] = funcInfo[n + 1]; } - pTable[ti][event_code].elements--; - pTable[ti][event_code].pFuncInfo.resize(pTable[ti][event_code].elements); + funcInfo.resize(funcInfo.size() - 1); return true; } @@ -236,14 +222,27 @@ void S_EVENTTAB::InvalidateBySegmentID(uint32_t segment_id) { for (uint32_t n = 0; n < Event_num[ti]; n++) { - for (uint32_t i = 0; i < pTable[ti][n].elements; i++) + for (uint32_t i = 0; i < pTable[ti][n].pFuncInfo.size(); i++) { if (pTable[ti][n].pFuncInfo[i].segment_id == segment_id) { - if (DelEventHandler(static_cast(ti), n, i, true)) + if (DelEventHandler(pTable[ti][n].pFuncInfo, i, true)) i = 0; } } + + for (auto &elem : pTable[ti][n].pFuncInfoForObjects) + { + for (uint32_t i = 0; i < elem.second.size(); i++) + { + if (elem.second[i].segment_id == segment_id) + { + if (DelEventHandler(elem.second, i, true)) + i--; + } + } + } + } } } @@ -269,15 +268,308 @@ void S_EVENTTAB::ProcessFrame() for (uint32_t n = 0; n < Event_num[ti]; n++) { // delete old handlers - for (uint32_t i = 0; i < pTable[ti][n].elements; i++) + for (uint32_t i = 0; i < pTable[ti][n].pFuncInfo.size(); i++) { if (pTable[ti][n].pFuncInfo[i].status == FSTATUS_DELETED) { - DelEventHandler(static_cast(ti), n, i); + DelEventHandler(pTable[ti][n].pFuncInfo, i); i = 0; } else + { pTable[ti][n].pFuncInfo[i].status = FSTATUS_NORMAL; + } + } + + for (auto &elem : pTable[ti][n].pFuncInfoForObjects) + { + for (uint32_t i = 0; i < elem.second.size(); i++) + { + if (elem.second[i].status == FSTATUS_DELETED) + { + if (DelEventHandler(elem.second, i, true)) + i--; + } + else + { + elem.second[i].status = FSTATUS_NORMAL; + } + } } } } + +void S_EVENTTAB::StoreEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, + std::unordered_map>> &varIndex) +{ + auto &eventTable = attr->CreateAttribute(std::string("eventTable")); + + for (size_t ti = 0; ti < HASHTABLE_SIZE; ti++) + { + for (size_t n = 0; n < pTable[ti].size(); n++) + { + auto &curEvent = pTable[ti][n]; + + auto eventName = curEvent.name; + if (!eventName) + { + continue; + } + + auto &curEventRecord = eventTable.CreateAttribute(std::string(curEvent.name)); + + if (curEvent.format != std::nullopt) + { + curEventRecord.CreateAttribute(std::string("format"), curEvent.format.value().c_str()); + } + + auto &commonEventTable = curEventRecord.CreateAttribute(std::string("common")); + for (size_t i = 0; i < curEvent.pFuncInfo.size(); i++) + { + auto &curFunInfo = curEvent.pFuncInfo[i]; + if (curFunInfo.status == FSTATUS_DELETED) + continue; + + FuncInfo fi; + FuncTab.GetFunc(fi, curFunInfo.func_code); + const char *isStatic = curFunInfo.bStatic ? "1" : "0"; + commonEventTable.CreateAttribute(fi.name, isStatic); + } + + auto &objectEventTable = curEventRecord.CreateAttribute(std::string("object")); + size_t counter = 0; + for (auto& cur : curEvent.pFuncInfoForObjects) + { + auto &curObjectEventTable = objectEventTable.CreateAttribute(fmt::format("{}", counter)); + counter++; + + + if (!StoreAttributesRef(&curObjectEventTable, cur.first, varIndex)) + { + throw std::runtime_error(fmt::format("Attempting to save handler for local object")); + } + + auto &curObjectHandlerTable = curObjectEventTable.CreateAttribute(std::string("handlers")); + for (size_t i = 0; i < cur.second.size(); i++) + { + auto &curFunInfo = cur.second[i]; + if (curFunInfo.status == FSTATUS_DELETED) + continue; + + FuncInfo fi; + FuncTab.GetFunc(fi, curFunInfo.func_code); + const char *isStatic = curFunInfo.bStatic ? "1" : "0"; + curObjectHandlerTable.CreateAttribute(fi.name, isStatic); + } + } + } + } +} +void S_EVENTTAB::LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable &VarTab) +{ + auto eventTable = attr->GetAttributeClass(std::string("eventTable")); + if (!eventTable) + { + spdlog::error("eventTable not found"); + return; + } + + + auto eventCount = eventTable->GetAttributesNum(); + for (size_t i = 0; i < eventCount; i++) + { + auto curEventRecord = eventTable->GetAttributeClass(i); + if (!curEventRecord) + { + spdlog::error("eventTable[{}] not found", i); + return; + } + + auto eventName = curEventRecord->GetThisName(); + + auto formatEventRecord = curEventRecord->GetAttributeClass(std::string("format")); + if (formatEventRecord) + { + SetEventFormat(eventName, formatEventRecord->GetValue()); + } + + auto commonEventTable = curEventRecord->GetAttributeClass(std::string("common")); + + if (!commonEventTable) + { + spdlog::error("eventTable[{}].common not found", i); + return; + } + auto eventFuncCount = commonEventTable->GetAttributesNum(); + + for (size_t j = 0; j < eventFuncCount; j++) + { + auto curFuncRecord = commonEventTable->GetAttributeClass(j); + if (!curFuncRecord) + { + spdlog::error("eventTable.common.{}[{}] not found", eventName, j); + return; + } + auto funcName = curFuncRecord->GetThisName(); + + + FuncInfo fi; + const uint32_t func_code = FuncTab.FindFunc(funcName); + if (func_code == INVALID_FUNC_CODE) + { + spdlog::error("Invalid function code douring event loading"); + return; + } + + if (!FuncTab.GetFunc(fi, func_code)) + { + spdlog::error("func not found error"); + return; + } + + bool isStatic = curFuncRecord->GetValue() == std::string("1"); + AddEventHandler(nullptr, eventName, func_code, fi.segment_id, 1, isStatic); + } + + auto objectEventTable = curEventRecord->GetAttributeClass(std::string("object")); + + if (!objectEventTable) + { + spdlog::error("eventTable[{}].object not found", i); + return; + } + + auto objectHandlersCount = objectEventTable->GetAttributesNum(); + + for (size_t k = 0; k < objectHandlersCount; k++) + { + auto curObjectHandlerRecord = objectEventTable->GetAttributeClass(fmt::format("{}", k)); + if (!curObjectHandlerRecord) + { + spdlog::error("eventTable[{}].object[{}] not found", i, k); + return; + } + + ATTRIBUTES *objectPointer = LoadAttributesRef(curObjectHandlerRecord, VarTab); + if (!objectPointer) + { + spdlog::error("stored attribute reference not found", i, k); + return; + } + + auto curObjectHandlerListRecord = curObjectHandlerRecord->GetAttributeClass("handlers"); + if (!curObjectHandlerListRecord) + { + spdlog::error("eventTable[{}].object[{}].handlers not found", i, k); + return; + } + + auto eventFuncCount = curObjectHandlerListRecord->GetAttributesNum(); + + for (size_t j = 0; j < eventFuncCount; j++) + { + auto curFuncRecord = curObjectHandlerListRecord->GetAttributeClass(j); + if (!curFuncRecord) + { + spdlog::error("eventTable.common.{}[{}] not found", eventName, j); + return; + } + auto funcName = curFuncRecord->GetThisName(); + + FuncInfo fi; + const uint32_t func_code = FuncTab.FindFunc(funcName); + if (func_code == INVALID_FUNC_CODE) + { + spdlog::error("Invalid function code douring event loading"); + return; + } + + if (!FuncTab.GetFunc(fi, func_code)) + { + spdlog::error("func not found error"); + return; + } + + bool isStatic = curFuncRecord->GetValue() == std::string("1"); + AddEventHandler(objectPointer, eventName, func_code, fi.segment_id, 1, isStatic); + } + } + + } +} + + +EVENTINFO *S_EVENTTAB::FindEventByName(const char *eventName, bool createIsNotFound, uint32_t *pEventPos) +{ + uint32_t i; + uint32_t eventPos = 0; + const auto hash = MakeHashValue(eventName); + + const auto ti = HASH2INDEX(hash); + + EVENTINFO *ei = nullptr; + for (; eventPos < Event_num[ti]; eventPos++) + { + if (pTable[ti][eventPos].hash == hash) + { + if (storm::iEquals(eventName, pTable[ti][eventPos].name)) + { + // event already in list + ei = &pTable[ti][eventPos]; + break; + } + } + } + + if (!ei && !createIsNotFound) + { + return nullptr; + } + else if (!ei) + { + if (Event_num[ti] >= Buffer_size[ti]) + { + Buffer_size[ti] += BUFFER_BLOCK_SIZE; + pTable[ti].resize(Buffer_size[ti]); + } + + pTable[ti][Event_num[ti]].hash = hash; + pTable[ti][Event_num[ti]].name = nullptr; + + if constexpr (true) // bKeepName) + { + if (eventName) + { + const auto len = strlen(eventName) + 1; + pTable[ti][Event_num[ti]].name = new char[len]; + memcpy(pTable[ti][Event_num[ti]].name, eventName, len); + } + } + ei = &pTable[ti][Event_num[ti]]; + eventPos = Event_num[ti]; + Event_num[ti]++; + } + if (pEventPos) + { + *pEventPos = eventPos; + } + return ei; +} + +void S_EVENTTAB::SetEventFormat(const char *eventName, std::string format) +{ + auto ei = FindEventByName(eventName, true); + ei->format = format; +} + +std::optional S_EVENTTAB::GetEventFormat(const char *eventName) +{ + auto ei = FindEventByName(eventName, false); + + if (!ei) + { + return std::nullopt; + } + + return ei->format; +} diff --git a/src/libs/core/src/s_eventtab.h b/src/libs/core/src/s_eventtab.h index 6dda3c55e..188f5e6ff 100644 --- a/src/libs/core/src/s_eventtab.h +++ b/src/libs/core/src/s_eventtab.h @@ -1,6 +1,8 @@ #pragma once #include "data.h" +#include "s_functab.h" +#include #define BUFFER_BLOCK_SIZE 4 #define INVALID_EVENT_CODE 0xffffffff @@ -22,8 +24,9 @@ struct EVENTINFO { uint32_t hash; std::vector pFuncInfo; + std::unordered_map> pFuncInfoForObjects; char *name; - uint32_t elements; + std::optional format{std::nullopt}; }; #define HASHTABLE_SIZE 64 @@ -33,16 +36,18 @@ class S_EVENTTAB uint32_t Buffer_size[HASHTABLE_SIZE]; uint32_t Event_num[HASHTABLE_SIZE]; std::vector pTable[HASHTABLE_SIZE]; - // bool bKeepName; + + bool DelEventHandler(std::vector &funcInfo, uint32_t func_code, bool bDelStatic = false); + EVENTINFO *FindEventByName(const char *eventName, bool createIsNotFound, uint32_t *pEventPos = nullptr); public: S_EVENTTAB(); ~S_EVENTTAB(); - // uint32_t GetEventNum(){return Event_num;}; - void SetStatus(const char *event_name, uint32_t func_code, uint32_t status); - uint32_t AddEventHandler(const char *event_name, uint32_t func_code, uint32_t func_segment_id, int32_t flag, - bool bStatic = false); - bool DelEventHandler(const char *event_name, uint32_t func_code); - bool DelEventHandler(uint8_t ti, uint32_t event_code, uint32_t func_code, bool bDelStatic = false); + + void SetStatus(ATTRIBUTES *pObject, const char *event_name, uint32_t func_code, uint32_t status); + uint32_t AddEventHandler(ATTRIBUTES *objectPtr, const char *event_name, uint32_t func_code, + uint32_t func_segment_id, int32_t flag, bool bStatic = false); + + bool GetEvent(EVENTINFO &ei, uint32_t event_code); // return true if var registred and loaded uint32_t MakeHashValue(const char *string); // void KeepNameMode(bool on){bKeepName = on;}; @@ -51,4 +56,10 @@ class S_EVENTTAB void InvalidateBySegmentID(uint32_t segment_id); uint32_t FindEvent(const char *event_name); void ProcessFrame(); + void StoreEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, + std::unordered_map>> &varIndex); + void LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable &VarTab); + + void SetEventFormat(const char *event_name, std::string format); + std::optional GetEventFormat(const char *event_name); }; diff --git a/src/libs/core/src/s_postevents.h b/src/libs/core/src/s_postevents.h index 5b25a5ad2..b6a9ff806 100644 --- a/src/libs/core/src/s_postevents.h +++ b/src/libs/core/src/s_postevents.h @@ -1,6 +1,8 @@ #pragma once #include "s_eventmsg.h" +#include "s_vartab.h" +#include class POSTEVENTS_LIST { @@ -84,4 +86,66 @@ class POSTEVENTS_LIST } } } + + void StoreEventsData(ATTRIBUTES *attr, + std::unordered_map>> &varIndex) + { + auto &eventTable = attr->CreateAttribute(std::string("postEventTable")); + + if (pTable) + { + uint32_t count = 0; + for (uint32_t n = 0; n < nClassesNum; n++) + { + if (!pTable[n]->IsValid()) + continue; + auto &curPostEvent = eventTable.CreateAttribute(fmt::format("{}", count)); + pTable[n]->StoreData(&curPostEvent, varIndex); + count++; + } + } + } + void LoadEventsData(ATTRIBUTES *attr, VarTable &VarTab) + { + auto eventTable = attr->GetAttributeClass(std::string("postEventTable")); + if (!eventTable) + { + spdlog::error("postEventTable not found"); + return; + } + + + auto eventCount = eventTable->GetAttributesNum(); + for (size_t i = 0; i < eventCount; i++) + { + auto curEventRecord = eventTable->GetAttributeClass(fmt::format("{}", i)); + if (!curEventRecord) + { + spdlog::error("postEventTable.{} not found", i); + return; + } + + auto msg = S_EVENTMSG::LoadData(curEventRecord, VarTab); + if (!msg) + { + spdlog::error("unable to load event message"); + return; + } + Add(msg); + } + } + + void FixEnitiyIDs() + { + if (pTable) + { + uint32_t count = 0; + for (uint32_t n = 0; n < nClassesNum; n++) + { + if (!pTable[n]->IsValid()) + continue; + pTable[n]->FixEnitiyIDs(); + } + } + } }; diff --git a/src/libs/location/src/fader.cpp b/src/libs/location/src/fader.cpp index cdcc45bc7..442db330f 100644 --- a/src/libs/location/src/fader.cpp +++ b/src/libs/location/src/fader.cpp @@ -270,12 +270,12 @@ void Fader::Execute(uint32_t delta_time) eventStart = false; if (!fadeIn) { - core.PostEvent("FaderEvent_StartFade", 0, "li", fadeIn, GetId()); + core.PostEvent(nullptr, "FaderEvent_StartFade", 0, "li", fadeIn, GetId()); // core.Trace("FaderEvent_StartFade"); } else { - core.PostEvent("FaderEvent_StartFadeIn", 0, "li", fadeIn, GetId()); + core.PostEvent(nullptr, "FaderEvent_StartFadeIn", 0, "li", fadeIn, GetId()); // core.Trace("FaderEvent_StartFadeIn"); } } @@ -285,12 +285,12 @@ void Fader::Execute(uint32_t delta_time) deleteMe = isAutodelete; if (!fadeIn) { - core.PostEvent("FaderEvent_EndFade", 0, "li", fadeIn, GetId()); + core.PostEvent(nullptr, "FaderEvent_EndFade", 0, "li", fadeIn, GetId()); // core.Trace("FaderEvent_EndFade"); } else { - core.PostEvent("FaderEvent_EndFadeIn", 0, "li", fadeIn, GetId()); + core.PostEvent(nullptr, "FaderEvent_EndFadeIn", 0, "li", fadeIn, GetId()); // core.Trace("FaderEvent_EndFadeIn"); } } diff --git a/src/libs/ship/src/ship.cpp b/src/libs/ship/src/ship.cpp index d2edaed7d..4ed14403f 100644 --- a/src/libs/ship/src/ship.cpp +++ b/src/libs/ship/src/ship.cpp @@ -1404,7 +1404,8 @@ void SHIP::FakeFire(const char *sBort, float fRandTime) CVECTOR vDirTemp = mRot * vDir; float fDir = NormalizeAngle(atan2f(vDirTemp.x, vDirTemp.z)); - core.PostEvent("Ship_FakeFire", (uint32_t)(1000 * fRandTime * rand() / RAND_MAX), "ffff", vCurPos.x, + core.PostEvent(nullptr, "Ship_FakeFire", (uint32_t)(1000 * fRandTime * rand() / RAND_MAX), "ffff", + vCurPos.x, vCurPos.y, vCurPos.z, fDir); } } diff --git a/src/libs/xinterface/src/aviplayer/aviplayer.cpp b/src/libs/xinterface/src/aviplayer/aviplayer.cpp index d44d3753d..4e74d63b8 100644 --- a/src/libs/xinterface/src/aviplayer/aviplayer.cpp +++ b/src/libs/xinterface/src/aviplayer/aviplayer.cpp @@ -168,7 +168,7 @@ uint64_t CAviPlayer::ProcessMessage(MESSAGE &message) if (!PlayMedia(vidName.c_str())) { CleanupInterfaces(); - core.PostEvent("ievntEndVideo", 1, nullptr); + core.PostEvent(nullptr, "ievntEndVideo", 1, nullptr); } break; } diff --git a/src/libs/xinterface/src/back_scene/back_scene.cpp b/src/libs/xinterface/src/back_scene/back_scene.cpp index 08328a80a..1a86a4bd6 100644 --- a/src/libs/xinterface/src/back_scene/back_scene.cpp +++ b/src/libs/xinterface/src/back_scene/back_scene.cpp @@ -622,7 +622,7 @@ void InterfaceBackScene::ExecuteMenu(int32_t nMenuIndex) { if (nMenuIndex < 0 || nMenuIndex >= m_aMenuDescr.size()) return; - core.PostEvent("backgroundcommand", 1, "s", m_aMenuDescr[nMenuIndex]->sEventName.c_str()); + core.PostEvent(nullptr, "backgroundcommand", 1, "s", m_aMenuDescr[nMenuIndex]->sEventName.c_str()); } int32_t InterfaceBackScene::CheckMousePos(float fX, float fY) diff --git a/src/libs/xinterface/src/nodes/xi_slide_line.cpp b/src/libs/xinterface/src/nodes/xi_slide_line.cpp index ca317f1f0..ec96eb3a9 100644 --- a/src/libs/xinterface/src/nodes/xi_slide_line.cpp +++ b/src/libs/xinterface/src/nodes/xi_slide_line.cpp @@ -336,6 +336,6 @@ void CXI_SLIDELINE::SetNewValue(int32_t newValue) pA = pA->GetAttributeClass(m_nodeName); if (pA != nullptr) pA->SetAttributeUseFloat("value", static_cast(m_nCurValue) / m_nGrateQuantity); - core.PostEvent("eSlideChange", 0, "slf", m_nodeName, m_nCurValue, + core.PostEvent(nullptr, "eSlideChange", 0, "slf", m_nodeName, m_nCurValue, static_cast(m_nCurValue) / m_nGrateQuantity); } diff --git a/src/libs/xinterface/src/xinterface.cpp b/src/libs/xinterface/src/xinterface.cpp index 58667b3a8..8d2a1229d 100644 --- a/src/libs/xinterface/src/xinterface.cpp +++ b/src/libs/xinterface/src/xinterface.cpp @@ -1203,7 +1203,7 @@ void XINTERFACE::LoadDialog(const char *sFileName) if (!ini) { core.Trace("ini file %s not found!", sFileName); - core.PostEvent("exitCancel", 1, nullptr); + core.PostEvent(nullptr, "exitCancel", 1, nullptr); return; } auto ownerIni = fio->OpenIniFile("RESOURCE\\INI\\INTERFACES\\defaultnode.ini"); From f2e33e5329c3bbeea435eaa72cd5adcb51f208c8 Mon Sep 17 00:00:00 2001 From: Igor Stepanov Date: Sun, 27 Jul 2025 16:42:11 +0300 Subject: [PATCH 2/3] add static handler capability for scripts --- docs/syntax.txt | 16 ++++++++++++++++ src/libs/core/src/compiler.cpp | 3 ++- src/libs/core/src/compiler.h | 2 +- src/libs/core/src/internal_functions.cpp | 18 ++++++++++++++---- src/libs/core/src/s_eventtab.cpp | 4 +++- 5 files changed, 36 insertions(+), 7 deletions(-) diff --git a/docs/syntax.txt b/docs/syntax.txt index cb6ca73d6..fc9f5c5f4 100644 --- a/docs/syntax.txt +++ b/docs/syntax.txt @@ -133,6 +133,22 @@ int argb(int a,int r,int g,int b); void DeleteEntities(); void ClearEvents(); + +SetEventHandlerForObject(object &object_ref, string event_name, string function_name, int post); +DelEventHandlerForObject(object &object_ref, string event_name, string function_name); + +Event(string event_name, string format, ...); +EventForObject(object &object_ref, string event_name, string format, ...); + +PostEvent(string event_name, int time, string format, ...); // post deffered event. time in ms +PostEventForObject(object &object_ref, string event_name, int time, string format, ...); +SetEventFormat(string event_name, string format); + +// Will not be reset by ClearEvents() +SetEventStaticHandler(string event_name, string function_name, int post); +SetEventStaticHandlerForObject(object &object_ref, string event_name, string function_name, int post); + + // COMMENTS . Code send entity id "i" to script and it cames as aref variable into script (GetEventData()) \ No newline at end of file diff --git a/src/libs/core/src/compiler.cpp b/src/libs/core/src/compiler.cpp index 00799316b..da1f6a70d 100644 --- a/src/libs/core/src/compiler.cpp +++ b/src/libs/core/src/compiler.cpp @@ -777,7 +777,8 @@ VDATA *COMPILER::ProcessEventFunctions(std::vector &eventFuncVe { if (eventFuncVec[n].status != FSTATUS_NORMAL) continue; - pVD = ProcessEventFunc(eventFuncVec, n, event_code, pMem, nTicks); + auto pVD2 = ProcessEventFunc(eventFuncVec, n, event_code, pMem, nTicks); + pVD = pVD2 ? pVD2 : pVD; if (bEventsBreak) break; } diff --git a/src/libs/core/src/compiler.h b/src/libs/core/src/compiler.h index b9b991739..27bda1307 100644 --- a/src/libs/core/src/compiler.h +++ b/src/libs/core/src/compiler.h @@ -129,7 +129,7 @@ class COMPILER : public VIRTUAL_COMPILER VDATA *ProcessEvent(const char *event_name, MESSAGE message); VDATA *ProcessEvent(const char *event_name); void SetEventHandler(ATTRIBUTES *pObject, const char *event_name, const char *func_name, int32_t flag, - bool bStatic = false); + bool bStatic); void DelEventHandler(ATTRIBUTES *pObject, const char *event_name, const char *func_name); bool Completed() diff --git a/src/libs/core/src/internal_functions.cpp b/src/libs/core/src/internal_functions.cpp index 6481db019..6461a257f 100644 --- a/src/libs/core/src/internal_functions.cpp +++ b/src/libs/core/src/internal_functions.cpp @@ -117,7 +117,9 @@ enum FUNCTION_CODE FUNC_DEL_EVENT_HANDLER_FOR_OBJECT, FUNC_EVENT_FOR_OBJECT, FUNC_POSTEVENT_FOR_OBJECT, - FUNC_SET_EVENT_FORMAT + FUNC_SET_EVENT_FORMAT, + FUNC_SET_EVENT_STATIC_HANDLER, + FUNC_SET_EVENT_STATIC_HANDLER_FOR_OBJECT }; INTFUNCDESC IntFuncTable[] = { @@ -155,7 +157,10 @@ INTFUNCDESC IntFuncTable[] = { 3, "DelEventHandlerForObject", TVOID, 0, "EventForObject", TVOID, 0, "PostEventForObject", TVOID, - 2, "SetEventFormat", TVOID}; + 2, "SetEventFormat", TVOID, + 3, "SetEventStaticHandler", TVOID, + 4, "SetEventStaticHandlerForObject", TVOID +}; /* char * FuncNameTable[]= @@ -438,6 +443,7 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t MESSAGE ms; uint32_t s_off; int shift; + bool bStatic = false; static std::remove_reference_t::const_iterator entity_iterator; static std::remove_reference_t::const_iterator entity_iterator_end; std::optional format = std::nullopt; @@ -1687,6 +1693,8 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t break; case FUNC_SET_EVENT_HANDLER_FOR_OBJECT: case FUNC_SET_EVENT_HANDLER: + case FUNC_SET_EVENT_STATIC_HANDLER_FOR_OBJECT: + case FUNC_SET_EVENT_STATIC_HANDLER: pV3 = SStack.Pop(); if (!pV3) { @@ -1709,7 +1717,9 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t pV2->Get(pChar2); pV3->Get(TempLong1); pA = nullptr; - if (func_code == FUNC_SET_EVENT_HANDLER_FOR_OBJECT) + + bStatic = (func_code == FUNC_SET_EVENT_STATIC_HANDLER || func_code == FUNC_SET_EVENT_STATIC_HANDLER_FOR_OBJECT); + if (func_code == FUNC_SET_EVENT_HANDLER_FOR_OBJECT || func_code == FUNC_SET_EVENT_STATIC_HANDLER_FOR_OBJECT) { pV4 = SStack.Pop(); if (!pV4) @@ -1731,7 +1741,7 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t } } - SetEventHandler(pA, pChar, pChar2, TempLong1); + SetEventHandler(pA, pChar, pChar2, TempLong1, bStatic); break; // case FUNC_EXIT_PROGRAM: diff --git a/src/libs/core/src/s_eventtab.cpp b/src/libs/core/src/s_eventtab.cpp index fe26b306c..939320ea0 100644 --- a/src/libs/core/src/s_eventtab.cpp +++ b/src/libs/core/src/s_eventtab.cpp @@ -39,7 +39,8 @@ void S_EVENTTAB::Clear() { for (auto &handler : elem.second) { - handler.status = FSTATUS_DELETED; + if (!handler.bStatic) + handler.status = FSTATUS_DELETED; } } @@ -114,6 +115,7 @@ uint32_t S_EVENTTAB::AddEventHandler(ATTRIBUTES *pObject, const char *event_name if (funcInfoVec[i].func_code == func_code) { funcInfoVec[i].status = FSTATUS_NORMAL; + funcInfoVec[i].bStatic = bStatic; return (((ti << 24) & 0xff000000) | (eventPos & 0xffffff)); } } From 10de0bc9d50a62cb85c8a4f01614424cc9007caf Mon Sep 17 00:00:00 2001 From: Igor Stepanov Date: Sat, 2 Aug 2025 21:36:05 +0300 Subject: [PATCH 3/3] error handling and recovery save with file --- src/libs/core/include/message.h | 11 +- src/libs/core/src/compiler.cpp | 239 ++++++++++++++-- src/libs/core/src/compiler.h | 13 +- src/libs/core/src/internal_functions.cpp | 10 +- src/libs/core/src/message.cpp | 349 +++++++++++++++-------- src/libs/core/src/s_eventmsg.h | 27 +- src/libs/core/src/s_eventtab.cpp | 69 ++--- src/libs/core/src/s_eventtab.h | 7 +- src/libs/core/src/s_postevents.h | 30 +- 9 files changed, 540 insertions(+), 215 deletions(-) diff --git a/src/libs/core/include/message.h b/src/libs/core/include/message.h index ba0c96aa4..96023236e 100644 --- a/src/libs/core/include/message.h +++ b/src/libs/core/include/message.h @@ -10,6 +10,7 @@ class VDATA; class DATA; +class VIRTUAL_COMPILER; class VarTable; namespace storm @@ -95,8 +96,9 @@ class MESSAGE final size_t GetParametersCount() const; void GetData(DATA *vd, COMPILER *comp); - void StoreData(ATTRIBUTES *attr, std::unordered_map>> &varIndex) const; - static MESSAGE *LoadData(ATTRIBUTES *attr, VarTable &VarTab); + bool StoreData(ATTRIBUTES *attr, std::unordered_map>> &varIndex, + VIRTUAL_COMPILER *compiler) const; + static MESSAGE *LoadData(ATTRIBUTES *attr, VarTable &VarTab, VIRTUAL_COMPILER *compiler); void FixEnitiyIDs(); ATTRIBUTES *GetThisObject(); @@ -110,8 +112,9 @@ class MESSAGE final bool hasThisObject_{false}; }; -ATTRIBUTES *LoadAttributesRef(ATTRIBUTES *attr, VarTable &VarTab); +ATTRIBUTES *LoadAttributesRef(ATTRIBUTES *attr, VarTable &VarTab, VIRTUAL_COMPILER *compiler); //false - local variable reference; otherwise - true bool StoreAttributesRef(ATTRIBUTES *attr, const ATTRIBUTES *val, - std::unordered_map>> &varIndex); + std::unordered_map>> &varIndex, + VIRTUAL_COMPILER *compiler); diff --git a/src/libs/core/src/compiler.cpp b/src/libs/core/src/compiler.cpp index da1f6a70d..08bb24b29 100644 --- a/src/libs/core/src/compiler.cpp +++ b/src/libs/core/src/compiler.cpp @@ -18,6 +18,7 @@ #include #include +#include #define SKIP_COMMENT_TRACING @@ -32,6 +33,10 @@ #define DEF_COMPILE_EXPRESSIONS constexpr auto MAGIC_VAR_CODE = 0xffffffaa; +constexpr auto RECOVERY_FILE_PREFIX_INT = 0xaa4af7ab; +constexpr auto RECOVERY_FILE_PREFIX_STRING = "RECOVERY"; +constexpr auto RECOVERY_FILE_PATH = "recovery.bin"; + #ifdef _WIN32 // S_DEBUG namespace @@ -6316,7 +6321,7 @@ char *COMPILER::ReadString() return pBuffer; } -bool COMPILER::ReadVariable(char *name, /* DWORD code,*/ bool bDim, uint32_t a_index) +bool COMPILER::ReadVariable(char *name, std::vector *pRecoveryNameTable, bool bDim, uint32_t a_index) { int32_t nLongValue; uintptr_t ptrValue; @@ -6417,7 +6422,7 @@ bool COMPILER::ReadVariable(char *name, /* DWORD code,*/ bool bDim, uint32_t a_i continue; } - if (!ReadVariable(name, /*code,*/ true, n)) + if (!ReadVariable(name, pRecoveryNameTable, true, n)) return false; } return true; @@ -6476,7 +6481,6 @@ bool COMPILER::ReadVariable(char *name, /* DWORD code,*/ bool bDim, uint32_t a_i break; // uninitialized ref array_index = ReadVDword(); - if (var_index == MAGIC_VAR_CODE) // new format { @@ -6492,6 +6496,22 @@ bool COMPILER::ReadVariable(char *name, /* DWORD code,*/ bool bDim, uint32_t a_i delete[] pString; pString = nullptr; } + else if (pRecoveryNameTable) // old format, but we may recover it + { + auto &varName = (*pRecoveryNameTable)[var_index]; + if (!varName.size()) + { + SetError("Reference '%s' initialized with unknown variable", name); + break; + } + var_index = VarTab.FindVar(varName.c_str()); + if (var_index == INVALID_VAR_CODE) + { + SetError("Load - unknown variable '%s'", varName); + return false; + } + } + if (bSkipVariable) break; @@ -6532,6 +6552,21 @@ bool COMPILER::ReadVariable(char *name, /* DWORD code,*/ bool bDim, uint32_t a_i delete[] pString; pString = nullptr; } + else if (pRecoveryNameTable) // old format, but we may recover it + { + auto &varName = (*pRecoveryNameTable)[var_index]; + if (!varName.size()) + { + SetError("Reference '%s' initialized with unknown variable", name); + break; + } + var_index = VarTab.FindVar(varName.c_str()); + if (var_index == INVALID_VAR_CODE) + { + SetError("Load - unknown variable '%s'", varName); + return false; + } + } pString = ReadString(); if (bSkipVariable) @@ -6740,7 +6775,98 @@ bool COMPILER::OnLoad() return true; } -void COMPILER::PrepareEventsToSaving() + +void COMPILER::CreateRecoveryFile() const +{ + std::ofstream file(RECOVERY_FILE_PATH, std::ios::binary); + + uint64_t intBuff = RECOVERY_FILE_PREFIX_INT; + auto charPrefix = RECOVERY_FILE_PREFIX_STRING; + file.write((const char*) & intBuff, sizeof(uint64_t)); + file.write(charPrefix, strlen(charPrefix)); + + auto nVarNum = VarTab.GetVarNum(); + intBuff = nVarNum; + file.write(reinterpret_cast(&intBuff), sizeof(uint64_t)); + + + const VarInfo *last_var{nullptr}; + for (size_t n = 0; n < nVarNum; n++) + { + const VarInfo *real_var = VarTab.GetVar(n); + if (real_var == nullptr) + { + intBuff = 0; + file.write(reinterpret_cast(&intBuff), sizeof(uint64_t)); + continue; + } + + intBuff = real_var->name.size(); + file.write(reinterpret_cast(&intBuff), sizeof(uint64_t)); + file.write(real_var->name.c_str(), real_var->name.size()); + } +} + +bool COMPILER::LoadRecoveryFile(std::vector &varNameTable) +{ + std::ifstream fl(RECOVERY_FILE_PATH, std::ios::binary | std::ios::in); + uint64_t intBuff = 0; + + fl.exceptions(std::fstream::failbit | std::fstream::badbit); + try + { + fl.read(reinterpret_cast(&intBuff), sizeof(uint64_t)); + + if (intBuff != RECOVERY_FILE_PREFIX_INT) + { + SetError("Recovery file is corrupted"); + return false; + } + + char strPrefix[sizeof(RECOVERY_FILE_PREFIX_STRING) + 1] = {0}; + + fl.read(&strPrefix[0], sizeof(RECOVERY_FILE_PREFIX_STRING)); + + if (strcmp(strPrefix, RECOVERY_FILE_PREFIX_STRING)) + { + SetError("Recovery file is corrupted"); + return false; + } + + fl.read(reinterpret_cast(&intBuff), sizeof(uint64_t)); + size_t nVarNum = intBuff; + + varNameTable.resize(nVarNum); + + + for (size_t n = 0; n < nVarNum; n++) + { + fl.read(reinterpret_cast(&intBuff), sizeof(uint64_t)); + size_t nameSize = intBuff; + + if (nameSize == 0) + { + varNameTable[n] = ""; + continue; + } + + std::string buff; + buff.resize(nameSize + 1); + fl.read(&buff[0], nameSize); + varNameTable[n] = std::move(buff); + } + + return true; + } + catch (const std::fstream::failure &e) + { + SetError("Failed to read recovery file: %s", e.what()); + return false; + } +} + + +bool COMPILER::PrepareEventsToSaving() { VarIndex varIndex = CollectAttributeIndex(); @@ -6759,8 +6885,8 @@ void COMPILER::PrepareEventsToSaving() auto pvi = VarTab.GetVarX(idx); if (!pvi) { - spdlog::error("error during writting event record"); - return; + SetError("error during writting event record"); + return false; } auto oldAtt = pvi->value->AttributesClass; if (oldAtt) @@ -6768,39 +6894,63 @@ void COMPILER::PrepareEventsToSaving() delete oldAtt; } pvi->value->AttributesClass = new ATTRIBUTES(GetVSC()); - EventTab.StoreEventsData(pvi->value->AttributesClass, FuncTab, varIndex); - EventMsg.StoreEventsData(pvi->value->AttributesClass, varIndex); - return; + bool ret = + EventTab.StoreEventsData(pvi->value->AttributesClass, FuncTab, varIndex, this); + if (!ret) + { + return false; + } + ret = EventMsg.StoreEventsData(pvi->value->AttributesClass, varIndex, this); + if (!ret) + { + return false; + } + return true; } -void COMPILER::PrepareEventsBeforeLoading() +bool COMPILER::PrepareEventsBeforeLoading() { VarInfo vi; vi.name = "__eventsData"; vi.type = S_TOKEN_TYPE::VAR_OBJECT; vi.segment_id = 0; vi.elements = 1; - VarTab.AddVar(vi); + auto idx = VarTab.AddVar(vi); + if (idx == INVALID_VAR_CODE) + { + SetError("unable to create '__eventsData' variable"); + return false; + } + return true; } -void COMPILER::PrepareEventsAfterLoading() +bool COMPILER::PrepareEventsAfterLoading() { auto idx = VarTab.FindVar("__eventsData"); if (idx == INVALID_VAR_CODE) { - spdlog::error("no event data available"); - return; + SetWarning("no event data available"); + return true; } auto info = VarTab.GetVar(idx); if (!info->value->AttributesClass) { - spdlog::error("wrong event record"); - return; + SetWarning("no event data available"); + return true; } - EventTab.LoadEventsData(info->value->AttributesClass, FuncTab, VarTab); - EventMsg.LoadEventsData(info->value->AttributesClass, VarTab); + bool ret = EventTab.LoadEventsData(info->value->AttributesClass, FuncTab, VarTab, this); + if (!ret) + { + return false; + } + ret = EventMsg.LoadEventsData(info->value->AttributesClass, VarTab, this); + if (!ret) + { + return false; + } + return true; } VarIndex COMPILER::CollectAttributeIndex() const @@ -6862,7 +7012,11 @@ bool COMPILER::SaveState(std::fstream &fileS) if (function_code != INVALID_FUNC_CODE) BC_Execute(function_code, pResult); - PrepareEventsToSaving(); + auto ret = PrepareEventsToSaving(); + if (!ret) + { + return false; + } EXTDATA_HEADER edh; auto *pVDat = static_cast(core_internal.GetScriptVariable("savefile_info")); @@ -6903,22 +7057,30 @@ bool COMPILER::SaveState(std::fstream &fileS) // 5. Variables table const uint32_t nVarNum = VarTab.GetVarNum(); - WriteVDword(nVarNum); - const VarInfo *last_var{nullptr}; + uint32_t nVarCountForSaving = 0; + for (n = 0; n < nVarNum; n++) { const VarInfo *real_var = VarTab.GetVar(n); - if (real_var == nullptr) + if (real_var) { - real_var = last_var; // preserve old semanthics + nVarCountForSaving++; } - else + } + + WriteVDword(nVarCountForSaving); + + + for (n = 0; n < nVarNum; n++) + { + const VarInfo *real_var = VarTab.GetVar(n); + if (real_var == nullptr) { - last_var = real_var; + continue; } - SaveString(real_var->name.c_str()); // *** + SaveString(real_var->name.c_str()); SaveVariable(real_var->value.get()); } @@ -6947,6 +7109,17 @@ bool COMPILER::SaveState(std::fstream &fileS) bool COMPILER::LoadState(std::fstream &fileS) { + std::vector recoveryVarTable; + std::vector *pRrecoveryVarTable = nullptr; + if (std::filesystem::exists(RECOVERY_FILE_PATH)) + { + if (!LoadRecoveryFile(recoveryVarTable)) + { + return false; + } + pRrecoveryVarTable = &recoveryVarTable; + } + uint32_t n; char *pString; @@ -7013,7 +7186,11 @@ bool COMPILER::LoadState(std::fstream &fileS) return false; delete[] pSegmentName; } - PrepareEventsBeforeLoading(); + auto ret = PrepareEventsBeforeLoading(); + if (!ret) + { + return false; + } // 5. Variables table, all variables created during previous step, just read value const uint32_t nVarNum = ReadVDword(); for (n = 0; n < nVarNum; n++) @@ -7024,11 +7201,15 @@ bool COMPILER::LoadState(std::fstream &fileS) SetError("missing variable name"); return false; } - ReadVariable(pString /*,n*/); + ReadVariable(pString, pRrecoveryVarTable /*,n*/); delete[] pString; } - PrepareEventsAfterLoading(); + ret = PrepareEventsAfterLoading(); + if (!ret) + { + return false; + } // call to script function "OnLoad()" OnLoad(); EventMsg.FixEnitiyIDs(); diff --git a/src/libs/core/src/compiler.h b/src/libs/core/src/compiler.h index 27bda1307..ed670c2e0 100644 --- a/src/libs/core/src/compiler.h +++ b/src/libs/core/src/compiler.h @@ -221,7 +221,7 @@ class COMPILER : public VIRTUAL_COMPILER char *ReadString(); void SaveVariable(DATA *pV, bool bdim = false); - bool ReadVariable(char *name, /*DWORD code,*/ bool bdim = false, uint32_t a_index = 0); + bool ReadVariable(char *name, std::vector *pRecoveryNameTable, bool bdim = false, uint32_t a_index = 0); bool FindReferencedVariable(DATA *pRef, uint32_t &var_index, uint32_t &array_index); bool FindReferencedVariableByRootA(ATTRIBUTES *pA, uint32_t &var_index, uint32_t &array_index); ATTRIBUTES *TraceARoot(ATTRIBUTES *pA, const char *&pAccess); @@ -269,13 +269,12 @@ class COMPILER : public VIRTUAL_COMPILER // printout script functions usage void PrintoutUsage(); - void PrepareEventsToSaving(); - void PrepareEventsBeforeLoading(); - void PrepareEventsAfterLoading(); + bool PrepareEventsToSaving(); + bool PrepareEventsBeforeLoading(); + bool PrepareEventsAfterLoading(); - void StoreEventsData(ATTRIBUTES *, - std::unordered_map>> &varIndex); - void LoadEventsData(ATTRIBUTES *, VarTable &VarTab); + void CreateRecoveryFile() const; + bool LoadRecoveryFile(std::vector &v); private: [[nodiscard]] std::filesystem::path GetSegmentCachePath(const SEGMENT_DESC &segment) const; diff --git a/src/libs/core/src/internal_functions.cpp b/src/libs/core/src/internal_functions.cpp index 6461a257f..45677ff70 100644 --- a/src/libs/core/src/internal_functions.cpp +++ b/src/libs/core/src/internal_functions.cpp @@ -119,7 +119,8 @@ enum FUNCTION_CODE FUNC_POSTEVENT_FOR_OBJECT, FUNC_SET_EVENT_FORMAT, FUNC_SET_EVENT_STATIC_HANDLER, - FUNC_SET_EVENT_STATIC_HANDLER_FOR_OBJECT + FUNC_SET_EVENT_STATIC_HANDLER_FOR_OBJECT, + FUNC_CREATE_RECOVERY_FILE }; INTFUNCDESC IntFuncTable[] = { @@ -159,7 +160,8 @@ INTFUNCDESC IntFuncTable[] = { 0, "PostEventForObject", TVOID, 2, "SetEventFormat", TVOID, 3, "SetEventStaticHandler", TVOID, - 4, "SetEventStaticHandlerForObject", TVOID + 4, "SetEventStaticHandlerForObject", TVOID, + 0, "__CreateRecoveryFile", TVOID }; /* @@ -2780,6 +2782,10 @@ DATA *COMPILER::BC_CallIntFunction(uint32_t func_code, DATA *&pVResult, uint32_t SetEventFormat(pChar, pChar2); break; + + case FUNC_CREATE_RECOVERY_FILE: + CreateRecoveryFile(); + break; } if (variadicHasAnError) diff --git a/src/libs/core/src/message.cpp b/src/libs/core/src/message.cpp index 39d383ebb..8f3927ef3 100644 --- a/src/libs/core/src/message.cpp +++ b/src/libs/core/src/message.cpp @@ -6,10 +6,10 @@ #include #include -#include #include #include "s_vartab.h" #include "core_impl.h" +#include "data.h" void MESSAGE::Move2Start() { @@ -346,7 +346,8 @@ void MESSAGE::SetThisObject(ATTRIBUTES *attr) bool StoreAttributesRef(ATTRIBUTES *attr, const ATTRIBUTES *val, - std::unordered_map>> &varIndex) + std::unordered_map>> &varIndex, + VIRTUAL_COMPILER *compiler) { if (!val) { @@ -395,82 +396,96 @@ bool StoreAttributesRef(ATTRIBUTES *attr, const ATTRIBUTES *val, return true; } -static void StoreParam(ATTRIBUTES *attr, const uint8_t &val) +static bool StoreParam(ATTRIBUTES *attr, const uint8_t &val) { attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); + return true; } -static void StoreParam(ATTRIBUTES *attr, const uint16_t &val) +static bool StoreParam(ATTRIBUTES *attr, const uint16_t &val) { attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); + return true; } -static void StoreParam(ATTRIBUTES *attr, const uint32_t &val) +static bool StoreParam(ATTRIBUTES *attr, const uint32_t &val) { attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); + return true; } -static void StoreParam(ATTRIBUTES *attr, const int32_t &val) +static bool StoreParam(ATTRIBUTES *attr, const int32_t &val) { attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); + return true; } -static void StoreParam(ATTRIBUTES *attr, const float &val) +static bool StoreParam(ATTRIBUTES *attr, const float &val) { attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); + return true; } -static void StoreParam(ATTRIBUTES *attr, const double &val) +static bool StoreParam(ATTRIBUTES *attr, const double &val) { attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); + return true; } -static void StoreParam(ATTRIBUTES *attr, const uintptr_t &val) +static bool StoreParam(ATTRIBUTES *attr, const uintptr_t &val) { attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); + return true; } -static void StoreParam(ATTRIBUTES *attr, const ATTRIBUTES *val, - std::unordered_map>> &varIndex) +static bool StoreParam(ATTRIBUTES *attr, const ATTRIBUTES *val, + std::unordered_map>> &varIndex, + VIRTUAL_COMPILER *compiler) { - if (!StoreAttributesRef(attr, val, varIndex)) + if (!StoreAttributesRef(attr, val, varIndex, compiler)) { auto &data = attr->CreateAttribute(std::string("value")); data = val->Copy(); } + return true; } -static void StoreParamEntity(ATTRIBUTES *attr, const entid_t &val, - std::unordered_map>> &varIndex) +static bool StoreParamEntity(ATTRIBUTES *attr, const entid_t &val, + std::unordered_map>> &varIndex, + VIRTUAL_COMPILER *compiler) { auto data = core_internal.Entity_GetAttributePointer(val); - StoreParam(attr, data, varIndex); + return StoreParam(attr, data, varIndex, compiler); } -static void StoreParam(ATTRIBUTES *attr, VDATA *val, - std::unordered_map>> &varIndex) +static bool StoreParam(ATTRIBUTES *attr, VDATA *val, + std::unordered_map>> &varIndex, + VIRTUAL_COMPILER *compiler) { entid_t eid = val->GetEntityID(); attr->CreateAttribute(std::string("objectId"), fmt::format("{}", eid).c_str()); auto attributes = val->GetAClass(); - StoreParam(attr, attributes, varIndex); - + return StoreParam(attr, attributes, varIndex, compiler); } -static void StoreParam(ATTRIBUTES *attr, const CVECTOR &val) +static bool StoreParam(ATTRIBUTES *attr, const CVECTOR &val) { attr->CreateAttribute(std::string("x"), fmt::format("{}", val.x).c_str()); attr->CreateAttribute(std::string("y"), fmt::format("{}", val.y).c_str()); attr->CreateAttribute(std::string("z"), fmt::format("{}", val.z).c_str()); + return true; } -static void StoreParam(ATTRIBUTES *attr, const std::string &val) +static bool StoreParam(ATTRIBUTES *attr, const std::string &val) { attr->CreateAttribute(std::string("value"), fmt::format("{}", val).c_str()); + return true; } -void MESSAGE::StoreData(ATTRIBUTES *attr, std::unordered_map>> &varIndex) const +bool MESSAGE::StoreData(ATTRIBUTES *attr, + std::unordered_map>> &varIndex, + VIRTUAL_COMPILER *compiler) const { attr->CreateAttribute(std::string("format"), format_.c_str()); int ito = hasThisObject_; @@ -507,13 +522,13 @@ void MESSAGE::StoreData(ATTRIBUTES *attr, std::unordered_map(params_[i])); continue; case 'a': - StoreParam(&curParamRecord, std::get(params_[i]), varIndex); + StoreParam(&curParamRecord, std::get(params_[i]), varIndex, compiler); continue; case 'i': - StoreParamEntity(&curParamRecord, std::get(params_[i]), varIndex); + StoreParamEntity(&curParamRecord, std::get(params_[i]), varIndex, compiler); continue; case 'e': - StoreParam(&curParamRecord, std::get(params_[i]), varIndex); + StoreParam(&curParamRecord, std::get(params_[i]), varIndex, compiler); continue; case 'c': StoreParam(&curParamRecord, std::get(params_[i])); @@ -523,122 +538,138 @@ void MESSAGE::StoreData(ATTRIBUTES *attr, std::unordered_mapSetError("Unknown message format: '%c'", format_[i]); + return false; } } + return true; } -template T LoadParam(ATTRIBUTES *attr) +template T LoadParam(ATTRIBUTES *attr, VIRTUAL_COMPILER *compiler, bool &status) { static_assert(false, "Not implemented"); } -template T LoadParam(ATTRIBUTES *attr, VarTable &VarTab) +template T LoadParam(ATTRIBUTES *attr, VarTable &VarTab, VIRTUAL_COMPILER *compiler, bool &status) { static_assert(false, "Not implemented"); } -template <> uint8_t LoadParam(ATTRIBUTES *attr) +template <> uint8_t LoadParam(ATTRIBUTES *attr, VIRTUAL_COMPILER *compiler, bool &status) { auto valueAttr = attr->GetAttributeClass(std::string("value")); if (!valueAttr) { - spdlog::error("value not found"); + compiler->SetError("value not found"); + status = false; return 0; } - auto str = valueAttr->GetValue(); + auto &str = valueAttr->GetValue(); + status = true; return std::stoll(str.c_str()); } -template <> uint16_t LoadParam(ATTRIBUTES *attr) +template <> uint16_t LoadParam(ATTRIBUTES *attr, VIRTUAL_COMPILER *compiler, bool &status) { auto valueAttr = attr->GetAttributeClass(std::string("value")); if (!valueAttr) { - spdlog::error("value not found"); + compiler->SetError("value not found"); + status = false; return 0; } - auto str = valueAttr->GetValue(); + auto &str = valueAttr->GetValue(); + status = true; return std::stoll(str.c_str()); } -template <> uint32_t LoadParam(ATTRIBUTES *attr) +template <> uint32_t LoadParam(ATTRIBUTES *attr, VIRTUAL_COMPILER *compiler, bool &status) { auto valueAttr = attr->GetAttributeClass(std::string("value")); if (!valueAttr) { - spdlog::error("value not found"); + compiler->SetError("value not found"); + status = false; return 0; } - auto str = valueAttr->GetValue(); + auto &str = valueAttr->GetValue(); + status = true; return std::stoll(str.c_str()); } -template <> int32_t LoadParam(ATTRIBUTES *attr) +template <> int32_t LoadParam(ATTRIBUTES *attr, VIRTUAL_COMPILER *compiler, bool &status) { auto valueAttr = attr->GetAttributeClass(std::string("value")); if (!valueAttr) { - spdlog::error("value not found"); + compiler->SetError("value not found"); + status = false; return 0; } - auto str = valueAttr->GetValue(); + auto &str = valueAttr->GetValue(); + status = true; return std::stoll(str.c_str()); } -template <> float LoadParam(ATTRIBUTES *attr) +template <> float LoadParam(ATTRIBUTES *attr, VIRTUAL_COMPILER *compiler, bool &status) { auto valueAttr = attr->GetAttributeClass(std::string("value")); if (!valueAttr) { - spdlog::error("value not found"); + compiler->SetError("value not found"); + status = false; return 0; } - auto str = valueAttr->GetValue(); + auto &str = valueAttr->GetValue(); + status = true; return std::stold(str.c_str()); } -template <> double LoadParam(ATTRIBUTES *attr) +template <> double LoadParam(ATTRIBUTES *attr, VIRTUAL_COMPILER *compiler, bool &status) { auto valueAttr = attr->GetAttributeClass(std::string("value")); if (!valueAttr) { - spdlog::error("value not found"); + compiler->SetError("value not found"); + status = false; return 0; } - auto str = valueAttr->GetValue(); + auto &str = valueAttr->GetValue(); + status = true; return std::stold(str.c_str()); } -template <> uintptr_t LoadParam(ATTRIBUTES *attr) +template <> uintptr_t LoadParam(ATTRIBUTES *attr, VIRTUAL_COMPILER *compiler, bool &status) { - spdlog::warn("'p' parameter is not supproted for messages"); + compiler->SetWarning("'p' parameter is not supproted for messages"); auto valueAttr = attr->GetAttributeClass(std::string("value")); if (!valueAttr) { - spdlog::error("value not found"); + compiler->SetError("value not found"); + status = false; return 0; } - auto str = valueAttr->GetValue(); + auto &str = valueAttr->GetValue(); + status = true; return std::stoll(str.c_str()); } -static DATA *FindVariable(std::string name, std::vector indexes, VarTable &VarTab) +static DATA *FindVariable(std::string name, std::vector indexes, VarTable &VarTab, VIRTUAL_COMPILER *compiler) { auto varCode = VarTab.FindVar(name); const VarInfo *realVar; DATA *dt; if (varCode == INVALID_VAR_CODE) { - spdlog::error("Load warning - variable: '{}' not found", name); + compiler->SetError("Load warning - variable: '%s' not found", name.c_str()); return nullptr; } else @@ -646,7 +677,7 @@ static DATA *FindVariable(std::string name, std::vector indexes, VarTabl realVar = VarTab.GetVarX(varCode); if (realVar == nullptr) { - spdlog::error("Load warning - variable: '{}' has invalid var code", name); + compiler->SetError("Load warning - variable: '%s' has invalid var code", name.c_str()); return nullptr; } else @@ -660,7 +691,7 @@ static DATA *FindVariable(std::string name, std::vector indexes, VarTabl dt = dt->GetArrayElement(idx); if (!dt) { - spdlog::error("Load warning - variable: '{}' has not index {}", name, idx); + compiler->SetError("Load warning - variable: '%s' has not index %u", name.c_str(), (unsigned)idx); return nullptr; } } @@ -668,16 +699,16 @@ static DATA *FindVariable(std::string name, std::vector indexes, VarTabl return dt; } -static DATA *LoadVariable(ATTRIBUTES *attr, VarTable &VarTab) +static DATA *LoadVariable(ATTRIBUTES *attr, VarTable &VarTab, VIRTUAL_COMPILER *compiler) { auto varNameAttr = attr->GetAttributeClass(std::string("varName")); if (!varNameAttr) { - spdlog::error("varName not found"); + compiler->SetError("varName not found"); return nullptr; } - auto varName = varNameAttr->GetValue(); + auto &varName = varNameAttr->GetValue(); std::vector indexes; auto indexesRec = attr->GetAttributeClass(std::string("indexes")); @@ -689,7 +720,7 @@ static DATA *LoadVariable(ATTRIBUTES *attr, VarTable &VarTab) auto curIndexRecord = indexesRec->GetAttributeClass(fmt::format("{}", i)); if (!curIndexRecord) { - spdlog::error("indexes.{} not found", i); + compiler->SetError("indexes.%u not found", (unsigned)i); return nullptr; } @@ -697,12 +728,12 @@ static DATA *LoadVariable(ATTRIBUTES *attr, VarTable &VarTab) } } - return FindVariable(varName, indexes, VarTab); + return FindVariable(varName, indexes, VarTab, compiler); } -ATTRIBUTES *LoadAttributesRef(ATTRIBUTES *attr, VarTable &VarTab) +ATTRIBUTES *LoadAttributesRef(ATTRIBUTES *attr, VarTable &VarTab, VIRTUAL_COMPILER *compiler) { - auto var = LoadVariable(attr, VarTab); + auto var = LoadVariable(attr, VarTab, compiler); if (!var) { return nullptr; @@ -722,14 +753,14 @@ ATTRIBUTES *LoadAttributesRef(ATTRIBUTES *attr, VarTable &VarTab) auto curAttributeRecord = attributesRec->GetAttributeClass(fmt::format("{}", i)); if (!curAttributeRecord) { - spdlog::error("attributes.{} not found", i); + compiler->SetError("attributes.%u not found", (unsigned)i); return nullptr; } attributes = attributes->GetAttributeClass(curAttributeRecord->GetValue()); if (!attributes) { - spdlog::error("missing attribute '{}'", curAttributeRecord->GetValue()); + compiler->SetError("missing attribute '%s'", curAttributeRecord->GetValue().c_str()); return nullptr; } } @@ -738,7 +769,8 @@ ATTRIBUTES *LoadAttributesRef(ATTRIBUTES *attr, VarTable &VarTab) } -template <> ATTRIBUTES *LoadParam(ATTRIBUTES *attr, VarTable &VarTab) +template <> +ATTRIBUTES *LoadParam(ATTRIBUTES *attr, VarTable &VarTab, VIRTUAL_COMPILER *compiler, bool &status) { auto valueAttr = attr->GetAttributeClass(std::string("value")); if (valueAttr) @@ -747,20 +779,19 @@ template <> ATTRIBUTES *LoadParam(ATTRIBUTES *attr, VarTable &VarT } - return LoadAttributesRef(attr, VarTab); + auto ret = LoadAttributesRef(attr, VarTab, compiler); + status = ret != nullptr; + return ret; } -static DATA *LoadParamEntity(ATTRIBUTES *attr, VarTable &VarTab) +static DATA *LoadParamEntity(ATTRIBUTES *attr, VarTable &VarTab, VIRTUAL_COMPILER *compiler, bool &status) { - DATA *dt = LoadVariable(attr, VarTab); - if (!dt) - { - return nullptr; - } + DATA *dt = LoadVariable(attr, VarTab, compiler); + status = dt != nullptr; return dt; } -template <> VDATA *LoadParam(ATTRIBUTES *attr, VarTable &VarTab) +template <> VDATA *LoadParam(ATTRIBUTES *attr, VarTable &VarTab, VIRTUAL_COMPILER *compiler, bool &status) { auto valueAttr = attr->GetAttributeClass(std::string("value")); if (valueAttr) @@ -768,82 +799,86 @@ template <> VDATA *LoadParam(ATTRIBUTES *attr, VarTable &VarTab) auto objectIdAttr = attr->GetAttributeClass(std::string("objectId")); if (!objectIdAttr) { - spdlog::error("objectId not found"); + compiler->SetError("objectId not found"); + status = false; return nullptr; } entid_t objectId = std::stoll(objectIdAttr->GetValue()); + status = true; return new DATA(objectId, valueAttr); } - DATA *dt = LoadVariable(attr, VarTab); - if (!dt) - { - return nullptr; - } - + DATA *dt = LoadVariable(attr, VarTab, compiler); + status = dt != nullptr; return dt; } -template <> CVECTOR LoadParam(ATTRIBUTES *attr) +template <> CVECTOR LoadParam(ATTRIBUTES *attr, VIRTUAL_COMPILER *compiler, bool &status) { CVECTOR ret; auto xAttr = attr->GetAttributeClass(std::string("x")); if (!xAttr) { - spdlog::error("x not found"); + compiler->SetError("x not found"); + status = false; return ret; } auto yAttr = attr->GetAttributeClass(std::string("y")); if (!yAttr) { - spdlog::error("y not found"); + compiler->SetError("y not found"); + status = false; return ret; } auto zAttr = attr->GetAttributeClass(std::string("z")); if (!zAttr) { - spdlog::error("z not found"); + compiler->SetError("z not found"); + status = false; return ret; } ret.x = std::stold(xAttr->GetValue().c_str()); ret.y = std::stold(yAttr->GetValue().c_str()); ret.z = std::stold(zAttr->GetValue().c_str()); + status = true; return ret; } -template <> std::string LoadParam(ATTRIBUTES *attr) +template <> std::string LoadParam(ATTRIBUTES *attr, VIRTUAL_COMPILER *compiler, bool &status) { auto valueAttr = attr->GetAttributeClass(std::string("value")); if (!valueAttr) { - spdlog::error("value not found"); + compiler->SetError("value not found"); + status = false; return "error"; } + status = true; return valueAttr->GetValue(); } -MESSAGE *MESSAGE::LoadData(ATTRIBUTES *attr, VarTable &VarTab) +MESSAGE *MESSAGE::LoadData(ATTRIBUTES *attr, VarTable &VarTab, VIRTUAL_COMPILER *compiler) { auto formatAttr = attr->GetAttributeClass(std::string("format")); if (!formatAttr) { - spdlog::error("format not found"); + compiler->SetError("format not found"); return nullptr; } - auto formatStr = formatAttr->GetValue(); + auto &formatStr = formatAttr->GetValue(); auto isThisObjectAttr = attr->GetAttributeClass(std::string("isThisObject")); if (!isThisObjectAttr) { - spdlog::error("isThisObject not found"); + compiler->SetError("isThisObject not found"); return nullptr; } @@ -852,14 +887,14 @@ MESSAGE *MESSAGE::LoadData(ATTRIBUTES *attr, VarTable &VarTab) auto paramsAttr = attr->GetAttributeClass(std::string("params")); if (!paramsAttr) { - spdlog::error("params not found"); + compiler->SetError("params not found"); return nullptr; } auto paramsCount = paramsAttr->GetAttributesNum(); if (paramsCount != formatStr.size()) { - spdlog::error("params count != format length"); + compiler->SetError("params count != format length"); return nullptr; } @@ -871,54 +906,138 @@ MESSAGE *MESSAGE::LoadData(ATTRIBUTES *attr, VarTable &VarTab) auto curParamRecord = paramsAttr->GetAttributeClass(fmt::format("{}", i)); if (!curParamRecord) { - spdlog::error("params.{} not found", i); + compiler->SetError("params.%u not found", (unsigned)i); return nullptr; } DATA *ent = nullptr; + bool status = false; switch (formatStr[i]) { case 'b': - msg.Set(LoadParam(curParamRecord)); + { + auto ret = LoadParam(curParamRecord, compiler, status); + if (!status) + { + return nullptr; + } + msg.Set(ret); break; - case 'w': - msg.Set(LoadParam(curParamRecord)); + } + case 'w': + { + auto ret = LoadParam(curParamRecord, compiler, status); + if (!status) + { + return nullptr; + } + msg.Set(ret); break; - case 'l': - msg.Set(LoadParam(curParamRecord)); + } + case 'l': + { + auto ret = LoadParam(curParamRecord, compiler, status); + if (!status) + { + return nullptr; + } + msg.Set(ret); break; - case 'u': - msg.Set(LoadParam(curParamRecord)); + } + case 'u': + { + auto ret = LoadParam(curParamRecord, compiler, status); + if (!status) + { + return nullptr; + } + msg.Set(ret); break; - case 'f': - msg.Set(LoadParam(curParamRecord)); + } + case 'f': + { + auto ret = LoadParam(curParamRecord, compiler, status); + if (!status) + { + return nullptr; + } + msg.Set(ret); break; - case 'd': - msg.Set(LoadParam(curParamRecord)); + } + case 'd': + { + auto ret = LoadParam(curParamRecord, compiler, status); + if (!status) + { + return nullptr; + } + msg.Set(ret); break; - case 'p': - msg.Set(LoadParam(curParamRecord)); + } + case 'p': + { + auto ret = LoadParam(curParamRecord, compiler, status); + if (!status) + { + return nullptr; + } + msg.Set(ret); break; - case 'a': - msg.Set(LoadParam(curParamRecord, VarTab)); + } + case 'a': + { + auto ret = LoadParam(curParamRecord, VarTab, compiler, status); + if (!status) + { + return nullptr; + } + msg.Set(ret); break; + } case 'i': - ent = LoadParamEntity(curParamRecord, VarTab); + { + ent = LoadParamEntity(curParamRecord, VarTab, compiler, status); + if (!status) + { + return nullptr; + } msg.SetEntity(ent->GetEntityID()); // Впоследсвии будет перезаписана новым GetEntityID(), после обновления сущностей msg.params_[i] = ent; break; - case 'e': - msg.Set(LoadParam(curParamRecord, VarTab)); + } + case 'e': + { + auto ret = LoadParam(curParamRecord, VarTab, compiler, status); + if (!status) + { + return nullptr; + } + msg.Set(ret); break; - case 'c': - msg.Set(LoadParam(curParamRecord)); + } + case 'c': + { + auto ret = LoadParam(curParamRecord, compiler, status); + if (!status) + { + return nullptr; + } + msg.Set(ret); break; - case 's': { - msg.Set(LoadParam(curParamRecord)); + } + case 's': + { + auto ret = LoadParam(curParamRecord, compiler, status); + if (!status) + { + return nullptr; + } + msg.Set(ret); break; } default: - throw std::runtime_error(fmt::format("Unknown message format: '{}'", formatStr[i])); + compiler->SetError("Unknown message format: '%c'", formatStr[i]); + return nullptr; } } diff --git a/src/libs/core/src/s_eventmsg.h b/src/libs/core/src/s_eventmsg.h index 7c1717078..190e8a58a 100644 --- a/src/libs/core/src/s_eventmsg.h +++ b/src/libs/core/src/s_eventmsg.h @@ -3,7 +3,6 @@ #include "message.h" #include "platform/platform.hpp" #include "s_vartab.h" -#include class S_EVENTMSG { @@ -69,8 +68,8 @@ class S_EVENTMSG return !bInvalide && pEventName; } - void StoreData(ATTRIBUTES *attr, - std::unordered_map>> &varIndex) const + bool StoreData(ATTRIBUTES *attr, std::unordered_map>> &varIndex, + VIRTUAL_COMPILER *compiler) const { auto period = 0; @@ -84,17 +83,21 @@ class S_EVENTMSG if (pMessageClass) { - pMessageClass->StoreData(&attr->CreateAttribute(std::string("pEventMsg")), varIndex); + auto ret = pMessageClass->StoreData(&attr->CreateAttribute(std::string("pEventMsg")), varIndex, compiler); + if (!ret) + { + return false; + } } - + return true; } - static S_EVENTMSG *LoadData(ATTRIBUTES *attr, VarTable &VarTab) + static S_EVENTMSG *LoadData(ATTRIBUTES *attr, VarTable &VarTab, VIRTUAL_COMPILER *compiler) { auto nPeriodRec = attr->GetAttributeClass(std::string("nPeriod")); if (!nPeriodRec) { - spdlog::error("nPeriod not found"); + compiler->SetError("nPeriod not found"); return nullptr; } @@ -104,18 +107,22 @@ class S_EVENTMSG auto pEventNameRec = attr->GetAttributeClass(std::string("pEventName")); if (!pEventNameRec) { - spdlog::error("pEventName not found"); + compiler->SetError("pEventName not found"); return nullptr; } - auto pEventNameVal = pEventNameRec->GetValue(); + auto &pEventNameVal = pEventNameRec->GetValue(); MESSAGE *msg = nullptr; auto MessageRec = attr->GetAttributeClass(std::string("pEventMsg")); if (MessageRec) { - msg = MESSAGE::LoadData(MessageRec, VarTab); + msg = MESSAGE::LoadData(MessageRec, VarTab, compiler); + if (!msg) + { + return nullptr; + } } return new S_EVENTMSG(pEventNameVal.c_str(), msg, period); diff --git a/src/libs/core/src/s_eventtab.cpp b/src/libs/core/src/s_eventtab.cpp index 939320ea0..479a5a870 100644 --- a/src/libs/core/src/s_eventtab.cpp +++ b/src/libs/core/src/s_eventtab.cpp @@ -1,7 +1,6 @@ #include "s_eventtab.h" #include "string_compare.hpp" -#include #include "message.h" #define HASHT_INDEX(x) (uint8_t)(x >> 24) @@ -301,8 +300,9 @@ void S_EVENTTAB::ProcessFrame() } } -void S_EVENTTAB::StoreEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, - std::unordered_map>> &varIndex) +bool S_EVENTTAB::StoreEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, + std::unordered_map>> &varIndex, + VIRTUAL_COMPILER *compiler) { auto &eventTable = attr->CreateAttribute(std::string("eventTable")); @@ -346,9 +346,10 @@ void S_EVENTTAB::StoreEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, counter++; - if (!StoreAttributesRef(&curObjectEventTable, cur.first, varIndex)) + if (!StoreAttributesRef(&curObjectEventTable, cur.first, varIndex, compiler)) { - throw std::runtime_error(fmt::format("Attempting to save handler for local object")); + compiler->SetError("Attempting to save handler for local object"); + return false; } auto &curObjectHandlerTable = curObjectEventTable.CreateAttribute(std::string("handlers")); @@ -366,14 +367,15 @@ void S_EVENTTAB::StoreEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, } } } + return true; } -void S_EVENTTAB::LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable &VarTab) +bool S_EVENTTAB::LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable &VarTab, VIRTUAL_COMPILER *compiler) { auto eventTable = attr->GetAttributeClass(std::string("eventTable")); if (!eventTable) { - spdlog::error("eventTable not found"); - return; + compiler->SetError("eventTable not found"); + return false; } @@ -383,8 +385,8 @@ void S_EVENTTAB::LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable & auto curEventRecord = eventTable->GetAttributeClass(i); if (!curEventRecord) { - spdlog::error("eventTable[{}] not found", i); - return; + compiler->SetError("eventTable[%u] not found", (unsigned)i); + return false; } auto eventName = curEventRecord->GetThisName(); @@ -399,8 +401,8 @@ void S_EVENTTAB::LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable & if (!commonEventTable) { - spdlog::error("eventTable[{}].common not found", i); - return; + compiler->SetError("eventTable[%u].common not found", (unsigned)i); + return false; } auto eventFuncCount = commonEventTable->GetAttributesNum(); @@ -409,8 +411,8 @@ void S_EVENTTAB::LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable & auto curFuncRecord = commonEventTable->GetAttributeClass(j); if (!curFuncRecord) { - spdlog::error("eventTable.common.{}[{}] not found", eventName, j); - return; + compiler->SetError("eventTable.common.%s[%u] not found", eventName, (unsigned)j); + return false; } auto funcName = curFuncRecord->GetThisName(); @@ -419,14 +421,14 @@ void S_EVENTTAB::LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable & const uint32_t func_code = FuncTab.FindFunc(funcName); if (func_code == INVALID_FUNC_CODE) { - spdlog::error("Invalid function code douring event loading"); - return; + compiler->SetError("Invalid function code douring event loading"); + return false; } if (!FuncTab.GetFunc(fi, func_code)) { - spdlog::error("func not found error"); - return; + compiler->SetError("funcion not found error"); + return false; } bool isStatic = curFuncRecord->GetValue() == std::string("1"); @@ -437,8 +439,8 @@ void S_EVENTTAB::LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable & if (!objectEventTable) { - spdlog::error("eventTable[{}].object not found", i); - return; + compiler->SetError("eventTable[%u].object not found", (unsigned)i); + return false; } auto objectHandlersCount = objectEventTable->GetAttributesNum(); @@ -448,22 +450,22 @@ void S_EVENTTAB::LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable & auto curObjectHandlerRecord = objectEventTable->GetAttributeClass(fmt::format("{}", k)); if (!curObjectHandlerRecord) { - spdlog::error("eventTable[{}].object[{}] not found", i, k); - return; + compiler->SetError("eventTable[%u].object[%u] not found", (unsigned)i, (unsigned)k); + return false; } - ATTRIBUTES *objectPointer = LoadAttributesRef(curObjectHandlerRecord, VarTab); + ATTRIBUTES *objectPointer = LoadAttributesRef(curObjectHandlerRecord, VarTab, compiler); if (!objectPointer) { - spdlog::error("stored attribute reference not found", i, k); - return; + compiler->SetError("stored attribute reference not found"); + return false; } auto curObjectHandlerListRecord = curObjectHandlerRecord->GetAttributeClass("handlers"); if (!curObjectHandlerListRecord) { - spdlog::error("eventTable[{}].object[{}].handlers not found", i, k); - return; + compiler->SetError("eventTable[%u].object[%u].handlers not found", (unsigned)i, (unsigned)k); + return false; } auto eventFuncCount = curObjectHandlerListRecord->GetAttributesNum(); @@ -473,8 +475,8 @@ void S_EVENTTAB::LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable & auto curFuncRecord = curObjectHandlerListRecord->GetAttributeClass(j); if (!curFuncRecord) { - spdlog::error("eventTable.common.{}[{}] not found", eventName, j); - return; + compiler->SetError("eventTable.common.%s[%u] not found", eventName, (unsigned)j); + return false; } auto funcName = curFuncRecord->GetThisName(); @@ -482,14 +484,14 @@ void S_EVENTTAB::LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable & const uint32_t func_code = FuncTab.FindFunc(funcName); if (func_code == INVALID_FUNC_CODE) { - spdlog::error("Invalid function code douring event loading"); - return; + compiler->SetError("Invalid function code douring event loading"); + return false; } if (!FuncTab.GetFunc(fi, func_code)) { - spdlog::error("func not found error"); - return; + compiler->SetError("function not found error"); + return false; } bool isStatic = curFuncRecord->GetValue() == std::string("1"); @@ -498,6 +500,7 @@ void S_EVENTTAB::LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable & } } + return true; } diff --git a/src/libs/core/src/s_eventtab.h b/src/libs/core/src/s_eventtab.h index 188f5e6ff..7a5fb8280 100644 --- a/src/libs/core/src/s_eventtab.h +++ b/src/libs/core/src/s_eventtab.h @@ -56,9 +56,10 @@ class S_EVENTTAB void InvalidateBySegmentID(uint32_t segment_id); uint32_t FindEvent(const char *event_name); void ProcessFrame(); - void StoreEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, - std::unordered_map>> &varIndex); - void LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable &VarTab); + bool StoreEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, + std::unordered_map>> &varIndex, + VIRTUAL_COMPILER *compiler); + bool LoadEventsData(ATTRIBUTES *attr, FuncTable &FuncTab, VarTable &VarTab, VIRTUAL_COMPILER* compiler); void SetEventFormat(const char *event_name, std::string format); std::optional GetEventFormat(const char *event_name); diff --git a/src/libs/core/src/s_postevents.h b/src/libs/core/src/s_postevents.h index b6a9ff806..2a5fad6a2 100644 --- a/src/libs/core/src/s_postevents.h +++ b/src/libs/core/src/s_postevents.h @@ -2,7 +2,6 @@ #include "s_eventmsg.h" #include "s_vartab.h" -#include class POSTEVENTS_LIST { @@ -87,8 +86,9 @@ class POSTEVENTS_LIST } } - void StoreEventsData(ATTRIBUTES *attr, - std::unordered_map>> &varIndex) + bool StoreEventsData(ATTRIBUTES *attr, + std::unordered_map>> &varIndex, + VIRTUAL_COMPILER *compiler) { auto &eventTable = attr->CreateAttribute(std::string("postEventTable")); @@ -100,18 +100,23 @@ class POSTEVENTS_LIST if (!pTable[n]->IsValid()) continue; auto &curPostEvent = eventTable.CreateAttribute(fmt::format("{}", count)); - pTable[n]->StoreData(&curPostEvent, varIndex); + auto ret = pTable[n]->StoreData(&curPostEvent, varIndex, compiler); + if (!ret) + { + return false; + } count++; } } + return true; } - void LoadEventsData(ATTRIBUTES *attr, VarTable &VarTab) + bool LoadEventsData(ATTRIBUTES *attr, VarTable &VarTab, VIRTUAL_COMPILER *compiler) { auto eventTable = attr->GetAttributeClass(std::string("postEventTable")); if (!eventTable) { - spdlog::error("postEventTable not found"); - return; + compiler->SetError("postEventTable not found"); + return false; } @@ -121,18 +126,19 @@ class POSTEVENTS_LIST auto curEventRecord = eventTable->GetAttributeClass(fmt::format("{}", i)); if (!curEventRecord) { - spdlog::error("postEventTable.{} not found", i); - return; + compiler->SetError("postEventTable.%u not found", (unsigned)i); + return false; } - auto msg = S_EVENTMSG::LoadData(curEventRecord, VarTab); + auto msg = S_EVENTMSG::LoadData(curEventRecord, VarTab, compiler); if (!msg) { - spdlog::error("unable to load event message"); - return; + compiler->SetError("unable to load event message"); + return false; } Add(msg); } + return true; } void FixEnitiyIDs()