-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
555 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
set(SOURCE2PY_PACKAGE_DIR ${BUILD_DIR}/Package/Source2Py) | ||
set(SOURCE2PY_PACKAGE_RES_DIR ${SCRIPTS_DIR}/Resources) | ||
|
||
add_custom_command(TARGET Source2Py POST_BUILD | ||
COMMAND ${CMAKE_COMMAND} -E make_directory "${SOURCE2PY_PACKAGE_DIR}" | ||
COMMAND ${CMAKE_COMMAND} -E make_directory "${SOURCE2PY_PACKAGE_DIR}/bin" | ||
COMMAND ${CMAKE_COMMAND} -E make_directory "${SOURCE2PY_PACKAGE_DIR}/plugins" | ||
|
||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:Source2Py> "${SOURCE2PY_PACKAGE_DIR}/bin" | ||
COMMAND ${CMAKE_COMMAND} -E copy "${SOURCE2PY_PACKAGE_RES_DIR}/pyplugins.ini" "${SOURCE2PY_PACKAGE_DIR}" | ||
|
||
# Copy sample plugins to package directory | ||
COMMAND ${CMAKE_COMMAND} -E copy "${SAMPLE_PLUGINS_DIR}/SamplePlugin.py" "${SOURCE2PY_PACKAGE_DIR}/plugins" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Check if Python vars have been set in CLI | ||
|
||
message(STATUS "Checking if Python paths have been set...") | ||
|
||
if (NOT DEFINED PYTHON_INCLUDE_DIR) | ||
message(FATAL_ERROR "Please provide Python include directory as CMake argument! Usage: -DPYTHON_INCLUDE_DIR=/path/to/python/include") | ||
else() | ||
message(STATUS "PYTHON_INCLUDE_DIR=${PYTHON_INCLUDE_DIR}") | ||
endif() | ||
|
||
if (NOT DEFINED PYTHON_LIB_DIR) | ||
message(FATAL_ERROR "Please provide Python lib directory as CMake argument! Usage: -DPYTHON_LIB_DIR=/path/to/python/lib") | ||
else() | ||
message(STATUS "PYTHON_LIB_DIR=${PYTHON_LIB_DIR}") | ||
endif() | ||
|
||
if (NOT DEFINED PYTHON_LIB) | ||
message(FATAL_ERROR "Please provide Python library as CMake argument! Usage -DPYTHON_LIB=python3.11") | ||
else() | ||
message(STATUS "PYTHON_LIB=${PYTHON_LIB}") | ||
endif() | ||
|
||
message(STATUS "Python OK!") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# List Python plugins to include here | ||
|
||
plugins/SamplePlugin.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import Source2Py | ||
|
||
class SamplePlugin: | ||
def Load(self): | ||
Source2Py.Print("Hello world!") | ||
|
||
def Unload(self): | ||
Source2Py.Print("Goodbye world!") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#pragma once | ||
|
||
#include <iostream> | ||
#include <string_view> | ||
#include <string> | ||
|
||
namespace Source2Py { | ||
|
||
class Log { | ||
public: | ||
|
||
static void Write(std::string_view message) { | ||
std::cout << "[ Source2Py ] " << message << "\n"; | ||
} | ||
|
||
static void Error(std::string_view message) { | ||
std::cerr << "[ Source2Py ] ERROR: " << message << "\n"; | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#include "PyAPI.h" | ||
|
||
#include <ISmmPlugin.h> | ||
|
||
namespace Source2Py { | ||
|
||
PLUGIN_GLOBALVARS(); | ||
|
||
void PyAPI::ConPrint(std::string& message) { | ||
message.append("\n"); | ||
META_CONPRINT(message.c_str()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#pragma once | ||
|
||
#include <string> | ||
|
||
namespace Source2Py { | ||
|
||
class PyAPI { | ||
public: | ||
|
||
// Print message to console | ||
static void ConPrint(std::string& message); | ||
|
||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#pragma once | ||
|
||
#include "PyAPI.h" | ||
|
||
#include <pybind11/embed.h> | ||
namespace py = pybind11; | ||
|
||
PYBIND11_EMBEDDED_MODULE(Source2Py, m) { | ||
using namespace Source2Py; | ||
|
||
m.def("Print", &PyAPI::ConPrint); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#include "PyPlugin.h" | ||
|
||
#include <filesystem> | ||
namespace fs = std::filesystem; | ||
|
||
namespace Source2Py { | ||
|
||
bool PyPlugin::LoadFromFile(std::string filepath) { | ||
std::string modulename = fs::path(filepath).stem().string(); | ||
|
||
// Format filepath into module path for Python | ||
filepath.erase(filepath.find_last_of('.'), filepath.size()); | ||
for (char& c : filepath) { | ||
if (c == '/' || c == '\\') | ||
c = '.'; | ||
} | ||
|
||
// Attempt to load Python plugin | ||
try { | ||
m_PluginObject = py::module_::import(filepath.c_str()).attr(modulename.c_str()); | ||
} | ||
catch (py::error_already_set& e) { | ||
Log::Error("Failed to load Python plugin: " + filepath + "\n" + std::string(e.what())); | ||
m_Valid = false; | ||
} | ||
|
||
return m_Valid; | ||
} | ||
|
||
void PyPlugin::Load() { | ||
PyRuntime::ExecuteObjectMethod(m_PluginObject, "Load"); | ||
} | ||
|
||
void PyPlugin::Unload() { | ||
PyRuntime::ExecuteObjectMethod(m_PluginObject, "Unload"); | ||
} | ||
|
||
void PyPlugin::GameFrame(bool simulating, bool firstTick, bool lastTick) { | ||
PyRuntime::ExecuteObjectMethod(m_PluginObject, "GameFrame", simulating, firstTick, lastTick); | ||
} | ||
|
||
void PyPlugin::ClientActive(int playerSlot, bool loadGame, const char* name, uint64_t xuid) { | ||
PyRuntime::ExecuteObjectMethod(m_PluginObject, "ClientActive", playerSlot, loadGame, name, xuid); | ||
} | ||
|
||
void PyPlugin::ClientDisconnect(int playerSlot, int reason, const char* name, uint64_t xuid, const char* networkID) { | ||
PyRuntime::ExecuteObjectMethod(m_PluginObject, "ClientDisconnect", playerSlot, reason, name, xuid, networkID); | ||
} | ||
|
||
void PyPlugin::ClientPutInServer(int playerSlot, char const* name, int type, uint64_t xuid) { | ||
PyRuntime::ExecuteObjectMethod(m_PluginObject, "ClientPutInServer", playerSlot, name, type, xuid); | ||
} | ||
|
||
void PyPlugin::ClientSettingsChanged(int playerSlot) { | ||
PyRuntime::ExecuteObjectMethod(m_PluginObject, "ClientSettingsChanged", playerSlot); | ||
} | ||
|
||
void PyPlugin::OnClientConnected(int playerSlot, const char* name, uint64_t xuid, const char* networkID, const char* address, bool fakePlayer) { | ||
PyRuntime::ExecuteObjectMethod(m_PluginObject, "OnClientConnected", playerSlot, name, xuid, networkID, address, fakePlayer); | ||
} | ||
|
||
void PyPlugin::ClientConnect(int playerSlot, const char* name, uint64_t xuid, const char* networkID) { | ||
PyRuntime::ExecuteObjectMethod(m_PluginObject, "ClientConnect", playerSlot, name, xuid, networkID); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#pragma once | ||
|
||
#include "PyRuntime.h" | ||
|
||
namespace Source2Py { | ||
|
||
class PyPlugin { | ||
public: | ||
PyPlugin() = default; | ||
PyPlugin(std::string filepath) { this->LoadFromFile(filepath); } | ||
|
||
bool LoadFromFile(std::string filepath); | ||
|
||
// Python plugin methods | ||
void Load(); | ||
void Unload(); | ||
|
||
// Python plugin hooks | ||
void GameFrame(bool simulating, bool firstTick, bool lastTick); | ||
void ClientActive(int playerSlot, bool loadGame, const char* name, uint64_t xuid); | ||
void ClientDisconnect(int playerSlot, int reason, const char* name, uint64_t xuid, const char* networkID); | ||
void ClientPutInServer(int playerSlot, char const* name, int type, uint64_t xuid); | ||
void ClientSettingsChanged(int playerSlot); | ||
void OnClientConnected(int playerSlot, const char* name, uint64_t xuid, const char* networkID, const char* address, bool fakePlayer); | ||
void ClientConnect(int playerSlot, const char* name, uint64_t xuid, const char* networkID); | ||
//void ClientCommand(int playerSlot, const CCommand& _cmd); (todo: port CCommand) | ||
|
||
bool IsValid() const { return m_Valid; } | ||
|
||
operator bool() { return m_Valid; } | ||
|
||
private: | ||
py::object m_PluginObject; | ||
bool m_Valid = true; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#include "PyRuntime.h" | ||
#include "PyModule.h" // Include this once | ||
|
||
namespace Source2Py { | ||
|
||
bool PyRuntime::s_InterpreterRunning = false; | ||
|
||
bool PyRuntime::Init() { | ||
if (s_InterpreterRunning) { | ||
Log::Error("PyRuntime is already running!"); | ||
return false; | ||
} | ||
|
||
try { | ||
py::initialize_interpreter(); | ||
s_InterpreterRunning = true; | ||
} | ||
catch (std::exception& e) { | ||
Log::Error(e.what()); | ||
return false; | ||
} | ||
|
||
Log::Write("PyRuntime started"); | ||
|
||
return true; | ||
} | ||
|
||
void PyRuntime::Close() { | ||
if (!s_InterpreterRunning) { | ||
Log::Error("PyRuntime is not running!"); | ||
return; | ||
} | ||
|
||
py::finalize_interpreter(); | ||
s_InterpreterRunning = false; | ||
|
||
Log::Write("PyRuntime stopped"); | ||
} | ||
} |
Oops, something went wrong.