Files
briaguya 6da0031295 run clang format (#448)
* add linux clang format script

* first shot at powershell

* whoops

* webrequest is slow, try webclient

* just get the one file

* simplify and maybe make it work?

* whoops again

* try a different suggestion

* why is it always windows

* again

* try again

* bit of path stuff

* chmod +x

* add action to check

* fix workflow name

* run clang format
2024-05-22 09:05:05 -05:00

394 lines
18 KiB
C++

#include "EventLog.h"
#include <iostream>
#include <iomanip>
#include <ctime>
#include <sstream>
#include "2s2h/BenGui/UIWidgets.hpp"
#include "2s2h/Enhancements/GameInteractor/GameInteractor.h"
extern "C" {
#include <z64.h>
}
typedef enum {
EVENT_LOG_ENTRY_TYPE_FLAG_SET,
EVENT_LOG_ENTRY_TYPE_FLAG_UNSET,
EVENT_LOG_ENTRY_TYPE_SCENE_FLAG_SET,
EVENT_LOG_ENTRY_TYPE_SCENE_FLAG_UNSET,
EVENT_LOG_ENTRY_TYPE_ACTOR_INIT,
EVENT_LOG_ENTRY_TYPE_ACTOR_KILL,
EVENT_LOG_ENTRY_TYPE_SCENE_INIT,
EVENT_LOG_ENTRY_TYPE_ROOM_INIT,
EVENT_LOG_ENTRY_TYPE_OPEN_TEXT,
EVENT_LOG_ENTRY_TYPE_ITEM_GIVE,
} EventLogEntryType;
const char* eventLogEntryTypeNames[] = {
"FlagSet", "FlagUnset", "SceneFlagSet", "SceneFlagUnset", "ActorInit",
"ActorKill", "SceneInit", "RoomInit", "OpenText", "ItemGive",
};
struct EventLogEntry {
std::string timestamp;
EventLogEntryType type;
std::string meta;
};
std::vector<EventLogEntry> eventLogEntries;
const char* flagTypeNames[] = {
"", "weekEventReg", "eventInf", "scenesVisible", "owlActivation",
"chest", "switch", "clearedRoom", "collectible", "unk_14",
"rooms", "chest *", "switch *", "clearedRoom *", "collectible *",
};
#define DEFINE_ACTOR(name, _enumValue, _allocType, _debugName, _humanName) { _enumValue, _debugName },
#define DEFINE_ACTOR_INTERNAL(_name, _enumValue, _allocType, _debugName, _humanName) { _enumValue, _debugName },
#define DEFINE_ACTOR_UNSET(_enumValue) { _enumValue, "Unset" },
std::unordered_map<s16, const char*> actorNames = {
#include "tables/actor_table.h"
};
#undef DEFINE_ACTOR
#undef DEFINE_ACTOR_INTERNAL
#undef DEFINE_ACTOR_UNSET
// 2S2H Added columns to scene table: entranceSceneId, betterMapSelectIndex, humanName
#define DEFINE_SCENE(_name, enumValue, _textId, _drawConfig, _restrictionFlags, _persistentCycleFlags, \
_entranceSceneId, _betterMapSelectIndex, humanName) \
{ enumValue, humanName },
#define DEFINE_SCENE_UNSET(_enumValue)
std::unordered_map<s16, const char*> sceneNames = {
#include "tables/scene_table.h"
};
#undef DEFINE_SCENE
#undef DEFINE_SCENE_UNSET
static HOOK_ID onFlagSetHookId = 0;
static HOOK_ID onFlagUnsetHookId = 0;
static HOOK_ID onSceneFlagSetHookId = 0;
static HOOK_ID onSceneFlagUnsetHookId = 0;
static HOOK_ID onActorInitHookId = 0;
static HOOK_ID onActorKillHookId = 0;
static HOOK_ID onSceneInitHookId = 0;
static HOOK_ID onRoomInitHookId = 0;
static HOOK_ID onOpenTextHookId = 0;
static HOOK_ID onItemGiveHookId = 0;
std::string CurrentTime() {
auto t = std::time(nullptr);
auto tm = *std::localtime(&t);
std::ostringstream oss;
oss << std::put_time(&tm, "%I:%M:%S");
return oss.str();
}
void TrimEventLog() {
while (eventLogEntries.size() > CVarGetInteger("gEventLog.MaxEntries", 1000)) {
eventLogEntries.pop_back();
}
}
void RegisterEventLogHooks() {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnFlagSet>(onFlagSetHookId);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnFlagUnset>(onFlagUnsetHookId);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneFlagSet>(onSceneFlagSetHookId);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneFlagUnset>(onSceneFlagUnsetHookId);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorInit>(onActorInitHookId);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorKill>(onActorKillHookId);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(onSceneInitHookId);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnRoomInit>(onRoomInitHookId);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnOpenText>(onOpenTextHookId);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnItemGive>(onItemGiveHookId);
onFlagSetHookId = 0;
onFlagUnsetHookId = 0;
onSceneFlagSetHookId = 0;
onSceneFlagUnsetHookId = 0;
onActorInitHookId = 0;
onActorKillHookId = 0;
onSceneInitHookId = 0;
onRoomInitHookId = 0;
onOpenTextHookId = 0;
onItemGiveHookId = 0;
if (!CVarGetInteger("gEventLog.Enabled", 0)) {
return;
}
onFlagSetHookId =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>([](FlagType type, u32 flag) {
if (type == FlagType::FLAG_WEEK_EVENT_REG) {
eventLogEntries.insert(eventLogEntries.begin(),
{
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_FLAG_SET,
.meta = fmt::format("WEEKEVENTREG_{:02d}_{:02x}", flag >> 8, flag & 0xFF),
});
} else if (type == FlagType::FLAG_EVENT_INF) {
eventLogEntries.insert(eventLogEntries.begin(), {
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_FLAG_SET,
.meta = fmt::format("EVENTINF_{:02x}", flag),
});
} else {
eventLogEntries.insert(
eventLogEntries.begin(),
{
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_FLAG_SET,
.meta = fmt::format("{}({:02d}) {:02x}", flagTypeNames[type], flag >> 8, flag & 0xFF),
});
}
TrimEventLog();
});
onFlagUnsetHookId =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagUnset>([](FlagType type, u32 flag) {
if (type == FlagType::FLAG_WEEK_EVENT_REG) {
eventLogEntries.insert(eventLogEntries.begin(),
{
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_FLAG_UNSET,
.meta = fmt::format("WEEKEVENTREG_{:02d}_{:02x}", flag >> 8, flag & 0xFF),
});
} else if (type == FlagType::FLAG_EVENT_INF) {
eventLogEntries.insert(eventLogEntries.begin(), {
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_FLAG_UNSET,
.meta = fmt::format("EVENTINF_{:02x}", flag),
});
} else {
eventLogEntries.insert(
eventLogEntries.begin(),
{
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_FLAG_UNSET,
.meta = fmt::format("{}({:02d}) {:02x}", flagTypeNames[type], flag >> 8, flag & 0xFF),
});
}
TrimEventLog();
});
onSceneFlagSetHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneFlagSet>(
[](s16 sceneId, FlagType type, u32 flag) {
eventLogEntries.insert(
eventLogEntries.begin(),
{
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_SCENE_FLAG_SET,
.meta = fmt::format("{}({:02d}) {:02x}", flagTypeNames[type], flag >> 8, flag & 0xFF),
});
TrimEventLog();
});
onSceneFlagUnsetHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneFlagUnset>(
[](s16 sceneId, FlagType type, u32 flag) {
eventLogEntries.insert(
eventLogEntries.begin(),
{
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_SCENE_FLAG_UNSET,
.meta = fmt::format("{}[{:02d}] {:02x}", flagTypeNames[type], flag >> 8, flag & 0xFF),
});
TrimEventLog();
});
onActorInitHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](Actor* actor) {
eventLogEntries.insert(eventLogEntries.begin(),
{
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_ACTOR_INIT,
.meta = fmt::format("{} {}", actorNames[actor->id], actor->params),
});
TrimEventLog();
});
onActorKillHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorKill>([](Actor* actor) {
eventLogEntries.insert(eventLogEntries.begin(),
{
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_ACTOR_KILL,
.meta = fmt::format("{} {}", actorNames[actor->id], actor->params),
});
TrimEventLog();
});
onSceneInitHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](s16 sceneId,
s8 spawnNum) {
eventLogEntries.insert(eventLogEntries.begin(), {
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_SCENE_INIT,
.meta = fmt::format("{} {}", sceneNames[sceneId], spawnNum),
});
TrimEventLog();
});
onRoomInitHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnRoomInit>([](s16 sceneId,
s8 roomId) {
eventLogEntries.insert(eventLogEntries.begin(), {
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_ROOM_INIT,
.meta = fmt::format("{} {}", sceneNames[sceneId], roomId),
});
TrimEventLog();
});
onOpenTextHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnOpenText>([](s16 textId) {
eventLogEntries.insert(eventLogEntries.begin(), {
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_OPEN_TEXT,
.meta = fmt::format("0x{:02x}", textId),
});
TrimEventLog();
});
onItemGiveHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemGive>([](u8 item) {
eventLogEntries.insert(eventLogEntries.begin(), {
.timestamp = CurrentTime(),
.type = EVENT_LOG_ENTRY_TYPE_ITEM_GIVE,
.meta = fmt::format("0x{:02x}", item),
});
TrimEventLog();
});
}
void EventLogWindow::DrawElement() {
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Event Log", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}
if (UIWidgets::CVarCheckbox("Enable", "gEventLog.Enabled")) {
RegisterEventLogHooks();
}
ImGui::SameLine();
if (UIWidgets::Button("Filters", { .size = UIWidgets::Sizes::Inline })) {
ImGui::OpenPopup("eventLogFiltersPopup");
}
if (ImGui::BeginPopup("eventLogFiltersPopup")) {
bool allChecked =
CVarGetInteger("gEventLog.Filter.FlagSet", 1) && CVarGetInteger("gEventLog.Filter.FlagUnset", 1) &&
CVarGetInteger("gEventLog.Filter.SceneFlagSet", 1) &&
CVarGetInteger("gEventLog.Filter.SceneFlagUnset", 1) && CVarGetInteger("gEventLog.Filter.ActorInit", 1) &&
CVarGetInteger("gEventLog.Filter.ActorKill", 1) && CVarGetInteger("gEventLog.Filter.SceneInit", 1) &&
CVarGetInteger("gEventLog.Filter.RoomInit", 1) && CVarGetInteger("gEventLog.Filter.OpenText", 1) &&
CVarGetInteger("gEventLog.Filter.ItemGive", 1);
bool someChecked =
CVarGetInteger("gEventLog.Filter.FlagSet", 1) || CVarGetInteger("gEventLog.Filter.FlagUnset", 1) ||
CVarGetInteger("gEventLog.Filter.SceneFlagSet", 1) ||
CVarGetInteger("gEventLog.Filter.SceneFlagUnset", 1) || CVarGetInteger("gEventLog.Filter.ActorInit", 1) ||
CVarGetInteger("gEventLog.Filter.ActorKill", 1) || CVarGetInteger("gEventLog.Filter.SceneInit", 1) ||
CVarGetInteger("gEventLog.Filter.RoomInit", 1) || CVarGetInteger("gEventLog.Filter.OpenText", 1) ||
CVarGetInteger("gEventLog.Filter.ItemGive", 1);
ImGuiContext* g = ImGui::GetCurrentContext();
ImGuiItemFlags backup_item_flags = g->CurrentItemFlags;
if (!allChecked && someChecked)
g->CurrentItemFlags |= ImGuiItemFlags_MixedValue;
if (UIWidgets::Checkbox("All", &allChecked)) {
if (allChecked) {
CVarSetInteger("gEventLog.Filter.FlagSet", 1);
CVarSetInteger("gEventLog.Filter.FlagUnset", 1);
CVarSetInteger("gEventLog.Filter.SceneFlagSet", 1);
CVarSetInteger("gEventLog.Filter.SceneFlagUnset", 1);
CVarSetInteger("gEventLog.Filter.ActorInit", 1);
CVarSetInteger("gEventLog.Filter.ActorKill", 1);
CVarSetInteger("gEventLog.Filter.SceneInit", 1);
CVarSetInteger("gEventLog.Filter.RoomInit", 1);
CVarSetInteger("gEventLog.Filter.OpenText", 1);
CVarSetInteger("gEventLog.Filter.ItemGive", 1);
} else {
CVarSetInteger("gEventLog.Filter.FlagSet", 0);
CVarSetInteger("gEventLog.Filter.FlagUnset", 0);
CVarSetInteger("gEventLog.Filter.SceneFlagSet", 0);
CVarSetInteger("gEventLog.Filter.SceneFlagUnset", 0);
CVarSetInteger("gEventLog.Filter.ActorInit", 0);
CVarSetInteger("gEventLog.Filter.ActorKill", 0);
CVarSetInteger("gEventLog.Filter.SceneInit", 0);
CVarSetInteger("gEventLog.Filter.RoomInit", 0);
CVarSetInteger("gEventLog.Filter.OpenText", 0);
CVarSetInteger("gEventLog.Filter.ItemGive", 0);
}
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
g->CurrentItemFlags = backup_item_flags;
UIWidgets::CVarCheckbox("FlagSet", "gEventLog.Filter.FlagSet", { .defaultValue = 1 });
UIWidgets::CVarCheckbox("FlagUnset", "gEventLog.Filter.FlagUnset", { .defaultValue = 1 });
UIWidgets::CVarCheckbox("SceneFlagSet", "gEventLog.Filter.SceneFlagSet", { .defaultValue = 1 });
UIWidgets::CVarCheckbox("SceneFlagUnset", "gEventLog.Filter.SceneFlagUnset", { .defaultValue = 1 });
UIWidgets::CVarCheckbox("ActorInit", "gEventLog.Filter.ActorInit", { .defaultValue = 1 });
UIWidgets::CVarCheckbox("ActorKill", "gEventLog.Filter.ActorKill", { .defaultValue = 1 });
UIWidgets::CVarCheckbox("SceneInit", "gEventLog.Filter.SceneInit", { .defaultValue = 1 });
UIWidgets::CVarCheckbox("RoomInit", "gEventLog.Filter.RoomInit", { .defaultValue = 1 });
UIWidgets::CVarCheckbox("OpenText", "gEventLog.Filter.OpenText", { .defaultValue = 1 });
UIWidgets::CVarCheckbox("ItemGive", "gEventLog.Filter.ItemGive", { .defaultValue = 1 });
ImGui::EndPopup();
}
ImGui::SameLine(0);
std::string maxEntriesStr = std::string("Max Entries: ") + std::to_string(eventLogEntries.size()) + "/";
ImGui::Text("%s", maxEntriesStr.c_str());
ImGui::SameLine(0);
UIWidgets::PushStyleCombobox();
ImGui::PushItemWidth(50);
s32 maxEntries = CVarGetInteger("gEventLog.MaxEntries", 1000);
if (ImGui::InputScalar("##maxEntriesInput", ImGuiDataType_S32, &maxEntries)) {
CVarSetInteger("gEventLog.MaxEntries", MAX(0, maxEntries));
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
TrimEventLog();
}
ImGui::PopItemWidth();
UIWidgets::PopStyleCombobox();
ImGui::SameLine(0);
if (UIWidgets::Button("Clear", { .color = UIWidgets::Colors::Red, .size = UIWidgets::Sizes::Inline })) {
eventLogEntries.clear();
}
if (ImGui::BeginTable("events", 3, ImGuiTableFlags_ScrollY, ImVec2(0, 0))) {
ImGui::TableSetupColumn("Timestamp", ImGuiTableColumnFlags_WidthFixed, 70);
ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, 100);
ImGui::TableSetupColumn("Meta", ImGuiTableColumnFlags_WidthStretch, 0);
ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableHeadersRow();
for (int i = 0; i < eventLogEntries.size(); i++) {
if (!CVarGetInteger(
(std::string("gEventLog.Filter.") + eventLogEntryTypeNames[eventLogEntries[i].type]).c_str(), 1)) {
continue;
}
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Text("%s", eventLogEntries[i].timestamp.c_str());
ImGui::TableSetColumnIndex(1);
ImGui::Text("%s", eventLogEntryTypeNames[eventLogEntries[i].type]);
ImGui::TableSetColumnIndex(2);
ImGui::Text("%s", eventLogEntries[i].meta.c_str());
}
ImGui::EndTable();
}
ImGui::End();
}
void EventLogWindow::InitElement() {
RegisterEventLogHooks();
}