Skip to content

Commit

Permalink
Refactor: Allow outside unsafe access to internal interpreter state o…
Browse files Browse the repository at this point in the history
…nly when using a wrapper type of 'Game_Interpreter_Inspector'
  • Loading branch information
florianessl committed Feb 5, 2025
1 parent 6ac81ec commit 866da7a
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 18 deletions.
3 changes: 1 addition & 2 deletions src/game_commonevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@ class Game_CommonEvent {
/** Interpreter for parallel common events. */
std::unique_ptr<Game_Interpreter_Map> interpreter;

friend class Scene_Debug;
friend class Debug::ParallelInterpreterStates;
friend class Game_Interpreter_Inspector;
};

#endif
3 changes: 1 addition & 2 deletions src/game_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,7 @@ class Game_Event : public Game_EventBase {
const lcf::rpg::EventPage* page = nullptr;
std::unique_ptr<Game_Interpreter_Map> interpreter;

friend class Scene_Debug;
friend class Debug::ParallelInterpreterStates;
friend class Game_Interpreter_Inspector;
};

inline int Game_Event::GetNumPages() const {
Expand Down
45 changes: 45 additions & 0 deletions src/game_interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5502,3 +5502,48 @@ int Game_Interpreter::ManiacBitmask(int value, int mask) const {

return value;
}

namespace {
lcf::rpg::SaveEventExecState const& empty_state = {};
}


lcf::rpg::SaveEventExecState const& Game_Interpreter_Inspector::GetForegroundExecState() {
return Game_Interpreter::GetForegroundInterpreter()._state;
}

lcf::rpg::SaveEventExecState& Game_Interpreter_Inspector::GetForegroundExecStateUnsafe() {
return Game_Interpreter::GetForegroundInterpreter()._state;
}

lcf::rpg::SaveEventExecState const& Game_Interpreter_Inspector::GetExecState(Game_Event const& ev) {
if (!ev.interpreter) {
return empty_state;
}
return ev.interpreter->GetState();
}

lcf::rpg::SaveEventExecState const& Game_Interpreter_Inspector::GetExecState(Game_CommonEvent const& ce) {
if (!ce.interpreter) {
return empty_state;
}
return ce.interpreter->GetState();
}

lcf::rpg::SaveEventExecState& Game_Interpreter_Inspector::GetExecStateUnsafe(Game_Event& ev) {
assert(ev.interpreter);
return ev.interpreter->_state;
}

lcf::rpg::SaveEventExecState& Game_Interpreter_Inspector::GetExecStateUnsafe(Game_CommonEvent& ce) {
assert(ce.interpreter);
return ce.interpreter->_state;
}

bool Game_Interpreter_Inspector::IsInActiveExcecution(Game_Event const& ev) {
return !ev.GetActivePage()->event_commands.empty() && ev.GetTrigger() == lcf::rpg::EventPage::Trigger_parallel && ev.interpreter;
}

bool Game_Interpreter_Inspector::IsInActiveExcecution(Game_CommonEvent const& ce) {
return ce.IsWaitingBackgroundExecution(false) || ce.IsWaitingForegroundExecution();
}
18 changes: 17 additions & 1 deletion src/game_interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,23 @@ class Game_Interpreter : public Game_BaseInterpreterContext
KeyInputState _keyinput;
AsyncOp _async_op = {};

friend class Scene_Debug;
friend class Game_Interpreter_Inspector;
};

class Game_Interpreter_Inspector {
public:
bool IsInActiveExcecution(Game_Event const& ev);

bool IsInActiveExcecution(Game_CommonEvent const& ce);

lcf::rpg::SaveEventExecState const& GetForegroundExecState();
lcf::rpg::SaveEventExecState& GetForegroundExecStateUnsafe();

lcf::rpg::SaveEventExecState const& GetExecState(Game_Event const& ev);
lcf::rpg::SaveEventExecState const& GetExecState(Game_CommonEvent const& ce);

lcf::rpg::SaveEventExecState& GetExecStateUnsafe(Game_Event& ev);
lcf::rpg::SaveEventExecState& GetExecStateUnsafe(Game_CommonEvent& ce);
};

inline const lcf::rpg::SaveEventExecFrame* Game_Interpreter::GetFramePtr() const {
Expand Down
19 changes: 15 additions & 4 deletions src/game_interpreter_debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <lcf/reader_util.h>

Debug::ParallelInterpreterStates Debug::ParallelInterpreterStates::GetCachedStates() {
Game_Interpreter_Inspector inspector;

std::vector<int> ev_ids;
std::vector<int> ce_ids;

Expand All @@ -33,15 +35,17 @@ Debug::ParallelInterpreterStates Debug::ParallelInterpreterStates::GetCachedStat

if (Game_Map::GetMapId() > 0) {
for (auto& ev : Game_Map::GetEvents()) {
if (ev.GetTrigger() != lcf::rpg::EventPage::Trigger_parallel || !ev.interpreter)
if (!inspector.IsInActiveExcecution(ev)) {
continue;
}

ev_ids.emplace_back(ev.GetId());
state_ev.emplace_back(ev.interpreter->GetState());
state_ev.emplace_back(inspector.GetExecState(ev));
}
for (auto& ce : Game_Map::GetCommonEvents()) {
if (ce.IsWaitingBackgroundExecution(false)) {
ce_ids.emplace_back(ce.common_event_id);
state_ce.emplace_back(ce.interpreter->GetState());
ce_ids.emplace_back(ce.GetId());
state_ce.emplace_back(inspector.GetExecState(ce));
}
}
} else if (Game_Battle::IsBattleRunning() && Player::IsPatchManiac()) {
Expand Down Expand Up @@ -135,3 +139,10 @@ std::string Debug::FormatEventName(Game_Character const& ch) {
}
return "";
}

std::string Debug::FormatEventName(Game_CommonEvent const& ce) {
if (ce.GetName().empty()) {
return fmt::format("CE{:04d}", ce.GetIndex());
}
return fmt::format("CE{:04d}: '{}'", ce.GetIndex(), ce.GetName());
}
2 changes: 2 additions & 0 deletions src/game_interpreter_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ namespace Debug {
std::vector<CallStackItem> CreateCallStack(const int owner_evt_id, const lcf::rpg::SaveEventExecState& state);

std::string FormatEventName(Game_Character const& ev);

std::string FormatEventName(Game_CommonEvent const& ce);
}

#endif
18 changes: 10 additions & 8 deletions src/scene_debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1230,15 +1230,15 @@ void Scene_Debug::UpdateInterpreterWindow(int index) {
auto tuple = bg_states.GetEventInterpreter(index - 1);
evt_id = std::get<0>(tuple);
state = std::get<1>(tuple);
first_line = fmt::format("EV{:04d}: {}", evt_id, Game_Map::GetEvent(evt_id)->GetName());
first_line = Debug::FormatEventName(*Game_Map::GetEvent(evt_id));
valid = true;
} else if ((index - bg_states.CountEventInterpreters()) <= bg_states.CountCommonEventInterpreters()) {
auto tuple = bg_states.GetCommonEventInterpreter(index - bg_states.CountEventInterpreters() - 1);
int ce_id = std::get<0>(tuple);
state = std::get<1>(tuple);
for (auto& ce : Game_Map::GetCommonEvents()) {
if (ce.common_event_id == ce_id) {
first_line = fmt::format("CE{:04d}: {}", ce_id, ce.GetName());
if (ce.GetId() == ce_id) {
first_line = Debug::FormatEventName(ce);
evt_id = ce_id;
valid = true;
break;
Expand All @@ -1255,30 +1255,32 @@ void Scene_Debug::UpdateInterpreterWindow(int index) {
}
}

lcf::rpg::SaveEventExecFrame& Scene_Debug::GetSelectedInterpreterFrameFromUiState() const {
lcf::rpg::SaveEventExecFrame const& Scene_Debug::GetSelectedInterpreterFrameFromUiState() const {
static lcf::rpg::SaveEventExecFrame empty;

if (state_interpreter.selected_state <= 0 || state_interpreter.selected_frame < 0) {
return empty;
}

Game_Interpreter_Inspector inspector;

int index = state_interpreter.selected_state;
const auto& bg_states = state_interpreter.background_states;

if (index == 1) {
auto& state = Game_Interpreter::GetForegroundInterpreter()._state;
auto const& state = inspector.GetForegroundExecState();
return state.stack[state_interpreter.selected_frame];
} else if (index <= bg_states.CountEventInterpreters()) {
int evt_id = std::get<0>(bg_states.GetEventInterpreter(index - 1));
auto ev = Game_Map::GetEvent(evt_id);

auto& state = ev->interpreter->_state;
auto const& state = inspector.GetExecState(*ev);
return state.stack[state_interpreter.selected_frame];
} else if ((index - bg_states.CountEventInterpreters()) <= bg_states.CountCommonEventInterpreters()) {
int ce_id = std::get<0>(bg_states.GetEventInterpreter(index - bg_states.CountEventInterpreters() - 1));
for (auto& ce : Game_Map::GetCommonEvents()) {
if (ce.common_event_id == ce_id) {
auto& state = ce.interpreter->_state;
if (ce.GetId() == ce_id) {
auto const& state = inspector.GetExecState(ce);
return state.stack[state_interpreter.selected_frame];
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/scene_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class Scene_Debug : public Scene {
bool interpreter_states_cached = false;

void UpdateInterpreterWindow(int index);
lcf::rpg::SaveEventExecFrame& GetSelectedInterpreterFrameFromUiState() const;
lcf::rpg::SaveEventExecFrame const& GetSelectedInterpreterFrameFromUiState() const;
struct {
Debug::ParallelInterpreterStates background_states;

Expand Down

0 comments on commit 866da7a

Please # to comment.