diff --git a/EmuAPI/EmuAPI.vcproj b/EmuAPI/EmuAPI.vcproj
index 35eab8a..ba67e44 100644
--- a/EmuAPI/EmuAPI.vcproj
+++ b/EmuAPI/EmuAPI.vcproj
@@ -204,6 +204,10 @@
RelativePath=".\emu\EmuRegister.cpp"
>
+
+
+
+
#include "ZooState.h"
#include "RegZooState.h"
+#include
+#include "EmuScriptMgr.h"
bool IsConsoleRunning = false;
bool IsConsoleHiding = false;
bool HasConsoleOpenedOnce = false; // to avoid conflicts when console has not been opened yet
HWND consoleWindow; // contains console window handle
+#define fs std::filesystem
+#define B EmuBase
+#define ZS ZooState
+
DWORD WINAPI ZooConsole(LPVOID lpParameter)
{
EmuConsole console; // new console object. needed to keep token state persistent.
FILE* file_s;
+
HasConsoleOpenedOnce = true;
@@ -65,113 +72,102 @@ DWORD WINAPI ZooConsole(LPVOID lpParameter)
return 1;
}
-DWORD WINAPI RunEmu(LPVOID lpParameter)
-{
+DWORD WINAPI RunEmu(LPVOID lpParameter) {
+ //------ Variable and object initialization
bool ctrlMPressed = false;
- lua_State *lua = luaL_newstate(); // Open Lua
- int iErr = 0;
- if (!lua)
- {
- std::cerr << "Failed to create Lua state." << std::endl;
- return 0;
- }
+ //------ Timestamp for logging
+ std::time_t t = std::time(0);
+ char timestamp[80]; // timestamp buffer
+ std::strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", std::localtime(&t));
+
+ //------ Open log file in append mode
+ std::ofstream f;
+ f.open("out.log", std::ios_base::app);
- RegZooState::register_zoo_state(lua);
- luaL_openlibs (lua); // Load io library
+ //------ Find/load script file directories with script manager
+ EmuScriptMgr sm(f, timestamp);
+ sm.findScripts();
+ sm.storeScripts();
// main loop
- while (true)
- {
+
+ bool renaming_done = false;
+ while (true) {
// CTRL + J
- if (EmuBase::DoubleKey(0x11, 0x4A) == true && IsConsoleRunning == false && HasConsoleOpenedOnce == false)
- {
+ if (B::DoubleKey(0x11, 0x4A) == true && IsConsoleRunning == false && HasConsoleOpenedOnce == false) {
IsConsoleRunning = true;
HANDLE thread = CreateThread(NULL, 0, &ZooConsole, NULL, 0, NULL);
CloseHandle(thread);
- }
- else if (EmuBase::DoubleKey(0x11, 0x4A) == true && IsConsoleHiding == true && HasConsoleOpenedOnce == true)
- {
+ } else if (B::DoubleKey(0x11, 0x4A) == true && IsConsoleHiding == true && HasConsoleOpenedOnce == true) {
ShowWindow(consoleWindow, SW_SHOW);
IsConsoleHiding = false;
}
// CTRL + M
- if (EmuBase::DoubleKey(0x11, 0x4D) == true && !ctrlMPressed)
- {
+ if (B::DoubleKey(0x11, 0x4D) == true && !ctrlMPressed) {
ctrlMPressed = true; // Set the flag
float mo_money = 1000000.00f;
- ZooState::AddToZooBudget(mo_money);
+ ZS::AddToZooBudget(mo_money);
}
- else if (EmuBase::DoubleKey(0x11, 0x4D) == false)
- {
+ else if (B::DoubleKey(0x11, 0x4D) == false) {
ctrlMPressed = false; // Reset the flag when the key is released
}
+
-
- if ((((int)ZooState::object_ptr(0x0)) > 0) && (iErr = luaL_loadfile (lua, "playground.emu")) == 0)
- {
- if (ZooState::IsZooLoaded() == true)
- {
- // Call main...
- if ((iErr = lua_pcall (lua, 0, LUA_MULTRET, 0)) == 0)
- {
- lua_pcall(lua, 0, LUA_MULTRET, 0);
-
- // Push the function name onto the stack
- lua_getglobal(lua, "emu_run");
-
- lua_pcall(lua, 0, 0, 0);
-
- }
+
+ // only run scripts while zoo is loaded and not in main menu
+ if ((int)ZS::object_ptr(0x0) > 0) {
+ if (ZS::IsZooLoaded() == true) {
+ sm.executeScripts();
}
}
-
-
+
Sleep(0);
}
- lua_close (lua);
+ f.close();
return 1;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
- LPVOID lpReserved)
-{
- std::ofstream f;
- f.open("out.log");
+ LPVOID lpReserved) {
+ // std::ofstream f;
+ // f.open("out.log", std::ios_base::app);
+ // std::time_t t = std::time(0);
+ // char timestamp[80]; // timestamp buffer
+ // std::strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", std::localtime(&t));
// Get the thread ID of the current thread
- DWORD mainThreadId = GetCurrentThreadId();
- f << mainThreadId << "\nCurrent thread ID: " << std::setfill('0') << std::setw(8) << std::hex << EmuBase::base << std::endl;
+ // DWORD mainThreadId = GetCurrentThreadId();
+ // f << std::endl << std::endl << "[" << timestamp << "] " << "\nMain thread ID: " << mainThreadId << "\nCurrent thread ID: " << std::setfill('0') << std::setw(8) << std::hex << B::base << std::endl;
// dll attachment status
- f << "Status: ";
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
{
- f << "DLL attached!\n";
+ //f << "[" << timestamp << "] " << "DLL attached!\n";
HANDLE thread = CreateThread(NULL, 0, &RunEmu, NULL, 0, NULL);
CloseHandle(thread);
}
break;
case DLL_PROCESS_DETACH:
- f << "DLL detached!\n";
+ //f << "[" << timestamp << "] " << "DLL detached!\n";
break;
case DLL_THREAD_ATTACH:
- f << "Thread attached!\n";
+ //f << "[" << timestamp << "] " << "Thread attached!\n";
break;
case DLL_THREAD_DETACH:
- f << "Thread detached!\n";
+ //f << "[" << timestamp << "] " << "Thread detached!\n";
break;
default:
- f << "DLL was not attached to thread or process!\n";
+ //f << "[" << timestamp << "] " << "DLL was not attached to thread or process!\n";
return FALSE;
}
- f.close();
+ // f.close();
return TRUE;
}
\ No newline at end of file
diff --git a/EmuAPI/emu/EmuConsole.cpp b/EmuAPI/emu/EmuConsole.cpp
index b6888fd..d420a51 100644
--- a/EmuAPI/emu/EmuConsole.cpp
+++ b/EmuAPI/emu/EmuConsole.cpp
@@ -1,4 +1,3 @@
-
#include "EmuConsole.h"
#include
@@ -17,33 +16,25 @@ void EmuConsole::tokenize()
{
std::string token = "";
// TODO: fix try/catch. Crashes if error found.
- try
+ if (!std::getline(std::cin, token)) {
+ return;
+ }
+
+ if (token.size() > 100)
{
-
- std::getline(std::cin, token);
+ // this limit will be increased, it's just a pre-emptive measure
+ std::cout << "100 char limit in buffer. Please try again." << std::endl;
+ // std::cin.ignore(32767, '\n');
+ } else {
+ std::istringstream iss(token);
- if (token.size() > 100)
+ while (std::getline(iss, token, ' '))
{
- // this limit will be increased, it's just a pre-emptive measure
- std::cout << "100 char limit in buffer. Please try again." << std::endl;
- throw;
+ tokens.push_back(token);
}
}
- catch(const std::exception& e)
- {
- std::cout << e.what() << std::endl;
- token = "";
- std::cin.clear();
- std::getline(std::cin, token);
-
- }
-
- std::istringstream iss(token);
- while (std::getline(iss, token, ' '))
- {
- tokens.push_back(token);
- }
+
}
///
@@ -213,7 +204,7 @@ void EmuConsole::processInput(bool& IsConsoleRunning)
// }
else
{
- std::cout << "Err: No such command exists." << std::endl;
+ std::cout << "Err: Command <" << tokens[0] << "> does not exist." << std::endl;
}
}
else
diff --git a/EmuAPI/emu/EmuScriptMgr.cpp b/EmuAPI/emu/EmuScriptMgr.cpp
new file mode 100644
index 0000000..51f4622
--- /dev/null
+++ b/EmuAPI/emu/EmuScriptMgr.cpp
@@ -0,0 +1,154 @@
+#include "EmuScriptMgr.h"
+
+// EmuScriptMgr::EmuScriptMgr() : lua(NULL), f(std::ofstream("out.log", std::ios_base::app)), timestamp(*new char) {
+// // do not use default constructor
+// }
+
+EmuScriptMgr::EmuScriptMgr(std::ofstream& fs, char* ts) : f(fs), timestamp(ts) {
+ //------ Initializing Lua
+ lua = luaL_newstate(); // Open Lua
+ int iErr = 0;
+ if (!lua) {
+ f << "[" << timestamp << "] " << "Failed to create Lua state." << std::endl;
+ }
+
+ //------ Register API functions to Lua
+ RegZooState::register_zoo_state(lua);
+
+ //------ Load Lua libraries
+ luaL_openlibs (lua);
+}
+
+EmuScriptMgr::~EmuScriptMgr() {
+}
+
+/// @brief Executes all emu scripts in a directory.
+int EmuScriptMgr::executeScripts() {
+
+ for (int i = 0; i < scripts.size(); i++) {
+ lua = luaL_newstate(); // Open Lua
+
+ int iErr = 0;
+ if (!lua) {
+ f << "[" << timestamp << "] " << "Failed to create Lua state." << std::endl;
+ }
+ //------ Register API functions to Lua
+ RegZooState::register_zoo_state(lua);
+ luaL_openlibs (lua);
+ if (luaL_loadstring(lua, scripts[i].c_str()) == 0) {
+ if (lua_pcall(lua, 0, LUA_MULTRET, 0) == 0)
+ {
+ // script is loaded, now load specific function
+ lua_getglobal(lua, "emu_run");
+ // check if we can call function
+ if (lua_isfunction(lua, -1)) {
+ if (lua_pcall(lua, 0, LUA_MULTRET, 0) != 0) {
+ // errors if can't execute script
+ const char* error_message = lua_tostring(lua, -1);
+ f << "Error executing Lua function: " << error_message << std::endl;
+ lua_close (lua);
+ return 1;
+ }
+ } else {
+ f << "[" << timestamp << "] " << "Function 'emu_run' not found or not callable" << std::endl;
+ lua_close (lua);
+ return 1;
+ }
+ lua_pop(lua, 1);
+ } else {
+ // error handling
+ const char* error_message = lua_tostring(lua, -1);
+ f << "[" << timestamp << "] " << "Error executing Lua script " << i << ": " << error_message << std::endl;
+
+ // remove err from stack
+ lua_pop(lua, 1);
+ lua_close (lua);
+ return 1;
+ }
+ } else {
+ // error handling
+ const char* error_message = lua_tostring(lua, -1);
+ f << "[" << timestamp << "] " << "Error loading Lua script " << i << ": " << error_message << std::endl;
+
+ // remove err from stack
+ lua_pop(lua, 1);
+ lua_close (lua);
+ return 1;
+ }
+ lua_close (lua);
+ }
+
+ return 0;
+}
+
+/// @brief Stores all emu scripts in a directory in memory.
+void EmuScriptMgr::storeScripts() {
+
+ for (int i = 0; i < files.size(); i++) {
+ //------ Read script file
+ std::ifstream file(files[i].c_str());
+ std::string script;
+ char c;
+ while (file.get(c)) {
+ script += c;
+ }
+ scripts.push_back(script);
+ file.close();
+ //------ Compile script
+ if ((luaL_loadstring(lua, script.c_str())) == 0) {
+ lua_CFunction script_funct = lua_tocfunction(lua, -1);
+ compiled_scripts.push_back(script_funct);
+ lua_pop(lua, 1);
+ } else {
+ f << "[" << timestamp << "] " << "Error loading script: " << files[i].substr(0, files[i].size() - (int)(files[i].size() * 0.30)) << " [..]" << std::endl;
+ }
+ }
+ lua_close (lua);
+
+}
+
+/// @brief Finds all scripts within the /scripts directory and stores their location in memory.
+void EmuScriptMgr::findScripts() {
+
+ //------ Open log file in append mode
+ std::ofstream f;
+ f.open("out.log", std::ios_base::app);
+
+ //------ Get working directory
+ wchar_t buffer[MAX_PATH]; // wide char buffer for GetCurrentDirectory
+ DWORD len = GetCurrentDirectory(MAX_PATH, buffer); // TODO: add error handling for this
+ std::wstring wpath(buffer, len);//std::wstring(buffer.begin(), buffer.end()); // conv path to wide string (project uses multi-byte char set)
+ wpath += L"\\scripts";
+
+ //------ Convert wide string to narrow string,
+ std::string path(wpath.begin(), wpath.end());
+
+ //------ Find first .emu file in directory
+ WIN32_FIND_DATA find_emu_file;
+ HANDLE hFind = FindFirstFile((wpath + L"\\*.emu").c_str(), &find_emu_file); // wide string used here
+
+ wpath = find_emu_file.cFileName;
+ std::string file_found(wpath.begin(), wpath.end());
+
+ //------ If no .emu files found, log error
+ if (hFind == INVALID_HANDLE_VALUE) {
+ f << "[" << timestamp << "] " << "Error finding path: " << file_found << std::endl;
+ } else {
+ //------ Find the rest of the .emu files in the directory
+ do {
+ if (find_emu_file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ // skip directories (for now)
+ } else { // we only care about files (for now)
+ std::wstring nFound = find_emu_file.cFileName; // conv file found back to narrow string
+ std::string file_name(nFound.begin(), nFound.end());
+ std::string file = path + "\\" + file_name;
+
+ files.push_back(file);
+ file_names.push_back(file_name);
+ }
+ } while (FindNextFile(hFind, &find_emu_file) != 0); // find the next file
+ FindClose(hFind);
+ }
+
+}
+
diff --git a/EmuAPI/emu/EmuScriptMgr.h b/EmuAPI/emu/EmuScriptMgr.h
new file mode 100644
index 0000000..7877c9a
--- /dev/null
+++ b/EmuAPI/emu/EmuScriptMgr.h
@@ -0,0 +1,38 @@
+#ifndef EMUSCRIPTMGR_H
+#define EMUSCRIPTMGR_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "lua.hpp"
+#include
+#include
+#include "RegZooState.h"
+
+class EmuScriptMgr
+{
+public:
+ EmuScriptMgr();
+ EmuScriptMgr(std::ofstream&, char*); // overloaded constructor
+ ~EmuScriptMgr();
+ void findScripts();
+ void storeScripts();
+ int executeScripts();
+
+private:
+ std::vector files;
+ std::vector file_names;
+ std::vector compiled_scripts;
+ std::vector scripts;
+ static int writer(const void*, size_t, void*);
+
+ char* timestamp;
+ lua_State *lua;
+ std::ofstream& f;
+};
+
+#endif
\ No newline at end of file
diff --git a/EmuAPI/emu/emu_run_wrapper.emu b/EmuAPI/emu/emu_run_wrapper.emu
new file mode 100644
index 0000000..9bb7239
--- /dev/null
+++ b/EmuAPI/emu/emu_run_wrapper.emu
@@ -0,0 +1,21 @@
+-- Wrapper script
+function emu_run_wrapper()
+ -- Define a function counter
+ local counter = 1
+
+ -- Iterate through the emu_run functions
+ while true do
+ -- Generate the function name
+ local func_name = "emu_run" .. counter
+
+ -- Call the function with the generated name
+ local func = _G[func_name]
+ if func then
+ func()
+ counter = counter + 1
+ else
+ break -- Exit the loop when no more functions are found
+ end
+ end
+end
+
diff --git a/EmuAPI/emu/emu_test_script.lua b/EmuAPI/emu/emu_test_script.lua
index 604d8c6..450e424 100644
--- a/EmuAPI/emu/emu_test_script.lua
+++ b/EmuAPI/emu/emu_test_script.lua
@@ -1,4 +1,3 @@
function emu_run()
- local zs = ZooState()
- io.write(zs:GetZooBudget() + "Hello world from inside Lua running inside EMU running inside Zoo Tycoon!")
+ io.write(GetZooBudget() + "Hello world from inside Lua running inside EMU running inside Zoo Tycoon!")
end
\ No newline at end of file