starting playing the wherigo
Signed-off-by: Peter Siegmund <mars3142@noreply.mars3142.dev>
This commit is contained in:
275
main/src/app.cpp
Normal file
275
main/src/app.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
#include "app.h"
|
||||
#include "lua/game_engine.h"
|
||||
#include "lua/media_manager.h"
|
||||
#include "lua/persistence.h"
|
||||
#include "lua/wherigo.h"
|
||||
#include "lua/wherigo_completion.h"
|
||||
#include "ui/start_screen.h"
|
||||
|
||||
#include <cartridge/parser.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/stdpaths.h>
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
}
|
||||
|
||||
bool cApp::OnInit()
|
||||
{
|
||||
|
||||
// Initialize image handlers for JPEG, PNG, GIF, etc.
|
||||
wxInitAllImageHandlers();
|
||||
|
||||
// Show start frame
|
||||
auto *startFrame = new cStartScreen();
|
||||
startFrame->Show(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cApp::loadCartridge(const std::string &filePath) {
|
||||
// Unload previous cartridge if any
|
||||
unloadCartridge();
|
||||
|
||||
m_cartridgePath = filePath;
|
||||
|
||||
// Parse cartridge
|
||||
m_cartridge = cartridge::parseFile(filePath);
|
||||
if (!m_cartridge) {
|
||||
wxLogError("Failed to parse cartridge: %s", filePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
return initLuaState();
|
||||
}
|
||||
|
||||
bool cApp::initLuaState() {
|
||||
auto luac = m_cartridge->luac();
|
||||
if (!luac) {
|
||||
wxLogError("No Lua bytecode in cartridge");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_luaState = luaL_newstate();
|
||||
if (!m_luaState) {
|
||||
wxLogError("Failed to create Lua state");
|
||||
return false;
|
||||
}
|
||||
|
||||
luaL_openlibs(m_luaState);
|
||||
|
||||
// Reset media counter before loading cartridge
|
||||
wherigo::resetMediaCounter();
|
||||
|
||||
// Register Wherigo module
|
||||
wherigo::luaopen_Wherigo(m_luaState);
|
||||
lua_pop(m_luaState, 1);
|
||||
|
||||
const auto &bytecode = luac->getData();
|
||||
int result = luaL_loadbuffer(m_luaState,
|
||||
reinterpret_cast<const char *>(bytecode.data()),
|
||||
bytecode.size(),
|
||||
"cartridge");
|
||||
|
||||
if (result != 0) {
|
||||
const char *err = lua_tostring(m_luaState, -1);
|
||||
wxLogError("Lua load error: %s", err);
|
||||
lua_close(m_luaState);
|
||||
m_luaState = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Execute the loaded chunk
|
||||
if (lua_pcall(m_luaState, 0, 0, 0) != 0) {
|
||||
const char *err = lua_tostring(m_luaState, -1);
|
||||
wxLogError("Lua exec error: %s", err);
|
||||
lua_close(m_luaState);
|
||||
m_luaState = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the cartridge object by searching for ClassName = "ZCartridge"
|
||||
m_cartridgeRef = LUA_NOREF;
|
||||
lua_getglobal(m_luaState, "_G");
|
||||
lua_pushnil(m_luaState);
|
||||
while (lua_next(m_luaState, -2) != 0) {
|
||||
if (lua_istable(m_luaState, -1)) {
|
||||
lua_getfield(m_luaState, -1, "ClassName");
|
||||
if (lua_isstring(m_luaState, -1)) {
|
||||
const char *className = lua_tostring(m_luaState, -1);
|
||||
if (strcmp(className, "ZCartridge") == 0) {
|
||||
lua_pop(m_luaState, 1); // pop ClassName
|
||||
m_cartridgeRef = luaL_ref(m_luaState, LUA_REGISTRYINDEX); // store reference, pops table
|
||||
lua_pop(m_luaState, 1); // pop key
|
||||
break;
|
||||
}
|
||||
}
|
||||
lua_pop(m_luaState, 1); // pop ClassName
|
||||
}
|
||||
lua_pop(m_luaState, 1); // pop value
|
||||
}
|
||||
lua_pop(m_luaState, 1); // pop _G
|
||||
|
||||
// Initialize media manager
|
||||
wherigo::MediaManager::getInstance().init(m_luaState, m_cartridge.get());
|
||||
|
||||
if (m_cartridgeRef == LUA_NOREF) {
|
||||
wxLogError("No ZCartridge object found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the game engine (but don't start yet)
|
||||
wherigo::GameEngine::getInstance().init(m_luaState, m_cartridgeRef);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cApp::startGame() {
|
||||
if (!m_luaState || m_cartridgeRef == LUA_NOREF) {
|
||||
wxLogError("No cartridge loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
// Call OnStart callback
|
||||
lua_rawgeti(m_luaState, LUA_REGISTRYINDEX, m_cartridgeRef);
|
||||
lua_getfield(m_luaState, -1, "OnStart");
|
||||
if (lua_isfunction(m_luaState, -1)) {
|
||||
lua_pushvalue(m_luaState, -2); // push cartridge as self
|
||||
if (lua_pcall(m_luaState, 1, 0, 0) != 0) {
|
||||
const char *err = lua_tostring(m_luaState, -1);
|
||||
wxLogError("OnStart error: %s", err);
|
||||
lua_pop(m_luaState, 1);
|
||||
}
|
||||
} else {
|
||||
lua_pop(m_luaState, 1);
|
||||
}
|
||||
lua_pop(m_luaState, 1); // pop cartridge
|
||||
|
||||
// Start the game engine
|
||||
wherigo::GameEngine::getInstance().start();
|
||||
}
|
||||
|
||||
void cApp::unloadCartridge() {
|
||||
// Shutdown the game engine
|
||||
wherigo::GameEngine::getInstance().shutdown();
|
||||
|
||||
if (m_cartridgeRef != LUA_NOREF && m_luaState) {
|
||||
luaL_unref(m_luaState, LUA_REGISTRYINDEX, m_cartridgeRef);
|
||||
m_cartridgeRef = LUA_NOREF;
|
||||
}
|
||||
|
||||
if (m_luaState) {
|
||||
lua_close(m_luaState);
|
||||
m_luaState = nullptr;
|
||||
}
|
||||
|
||||
m_cartridge.reset();
|
||||
m_cartridgePath.clear();
|
||||
}
|
||||
|
||||
std::string cApp::getAutoSavePath() const {
|
||||
if (m_cartridge) {
|
||||
wxStandardPaths& stdPaths = wxStandardPaths::Get();
|
||||
wxString userDataDir = stdPaths.GetUserDataDir();
|
||||
|
||||
// Create save directory if it doesn't exist
|
||||
if (!wxDir::Exists(userDataDir)) {
|
||||
wxFileName::Mkdir(userDataDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
|
||||
}
|
||||
|
||||
// Generate save filename from cartridge name
|
||||
wxString cartName = wxString::FromUTF8(m_cartridge->cartridgeName());
|
||||
cartName.Replace(" ", "_");
|
||||
cartName.Replace("/", "_");
|
||||
|
||||
wxString savePath = userDataDir + wxFileName::GetPathSeparator() + cartName + ".save";
|
||||
return savePath.ToStdString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool cApp::saveGameState(const std::string &saveFilePath) {
|
||||
if (!m_luaState) {
|
||||
wxLogError("No Lua state to save");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string savePath = saveFilePath.empty() ? getAutoSavePath() : saveFilePath;
|
||||
if (savePath.empty()) {
|
||||
wxLogError("No save path available");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = wherigo::LuaPersistence::saveState(m_luaState, savePath);
|
||||
if (success) {
|
||||
wxLogMessage("Game saved to: %s", savePath);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool cApp::loadGameState(const std::string &saveFilePath) {
|
||||
if (!m_luaState) {
|
||||
wxLogError("No Lua state to load into");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string loadPath = saveFilePath.empty() ? getAutoSavePath() : saveFilePath;
|
||||
if (loadPath.empty() || !wxFileExists(loadPath)) {
|
||||
wxLogError("Save file not found: %s", loadPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = wherigo::LuaPersistence::loadState(m_luaState, loadPath);
|
||||
if (success) {
|
||||
wxLogMessage("Game loaded from: %s", loadPath);
|
||||
// Notify game engine of state change
|
||||
wherigo::GameEngine::getInstance().notifyStateChanged();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
std::string cApp::getCompletionLogPath() const {
|
||||
if (m_cartridge && !m_cartridgePath.empty()) {
|
||||
// Use the same directory as the GWC file
|
||||
wxFileName gwcFile(m_cartridgePath);
|
||||
wxString directory = gwcFile.GetPath();
|
||||
|
||||
// Generate completion log filename from cartridge name
|
||||
wxString cartName = wxString::FromUTF8(m_cartridge->cartridgeName());
|
||||
cartName.Replace(" ", "_");
|
||||
cartName.Replace("/", "_");
|
||||
|
||||
wxString logPath = directory + wxFileName::GetPathSeparator() + cartName + ".gwl";
|
||||
return logPath.ToStdString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool cApp::generateCompletionLog(const std::string &logFilePath) {
|
||||
if (!m_luaState) {
|
||||
wxLogError("No Lua state for completion log");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string logPath = logFilePath.empty() ? getCompletionLogPath() : logFilePath;
|
||||
if (logPath.empty()) {
|
||||
wxLogError("No completion log path available");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = wherigo::WherigoCompletion::generateCompletionLog(m_luaState, logPath, "Player");
|
||||
if (success) {
|
||||
wxLogMessage("Completion log generated: %s", logPath);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
int cApp::OnExit()
|
||||
{
|
||||
unloadCartridge();
|
||||
return wxApp::OnExit();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user