Update on this thread.
After reading the blender plugins “blend2ue” source code, mainly the pythonremoteexcution.py file, and now I know how much I lack the fundamental knowledge on OOP developing. I couldn’t figure it out just based on the implemented source code alone, and so I found the C++ source file for handling python remote execution, that’s where UE declare how the json byte should be configure, the C++ file is located on where you install your engine: engineInstallLocation\Epic Games\UE_5.1\Engine\Plugins\Experimental\PythonScriptPlugin\Source\PythonScriptPlugin\Private\PythonScriptRemoteExecution.cpp
Below is the doc string in the C++ source code describe the remote execution protocol:
/**
* Remote Execution protocol definition.
*
* Messages are a UTF-8 encoded JSON object with the following layout:
* {
* "version": 1, // Required - Integer - Protocol version number (currently 1)
* "magic": "ue_py", // Required - String - Protocol magic identifier (currently "ue_py")
* "type": "...", // Required - String - Identifier for the message type (see below)
* "source": "...", // Required - String - Unique identifier of the node that sent the message (typically a GUID)
* "dest": "...", // Optional - String - Unique identifier of the node that should receive the message (typically a GUID)
* "data": "..." // Optional - Any - Message specific payload data (see below)
* }
*
* Message types:
* "ping" (UDP) - Service discovery request
*
* "pong" (UDP) - Service discovery response
* "dest" - Required - String - The node that requested the discovery
* "data" - Required - Object - Payload data:
* {
* "user": "...", // Required - String - The name of the user that owns the engine instance
* "machine": "...", // Required - String - The name of the machine that owns the engine instance
* "engine_version": "...", // Required - String - The version number of the engine
* "engine_root": "...", // Required - String - The absolute on-disk root of the engine
* "project_root: "...", // Optional - String - The absolute on-disk root of the project (if a project is loaded)
* "project_name": "..." // Optional - String - The name of the project (if a project is loaded)
* }
*
* "open_connection" (UDP) - Open a TCP command connection with the requested server
* "dest" - Required - String - The node that should open a connection to the server
* "data" - Required - Object - Payload data:
* {
* "command_ip": "...", // Required - String - The IP address of the TCP command server
* "command_port": 0 // Required - Integer - The port of the TCP command server
* }
*
* "close_connection" (UDP) - Close any active TCP command connection
* "dest" - Required - String - The node that should close its connection to the server
*
* "command" (TCP) - Execute a remote Python command
* "dest" - Required - String - The node that should execute the command
* "data" - Required - Object - Payload data:
* {
* "command": "...", // Required - String - The command to execute
* "unattended": True, // Required - Boolean - Whether to run the command in "unattended" mode (suppressing some UI)
* "exec_mode": "..." // Required - String - The execution mode to use as a string value (see EPythonCommandExecutionMode, and LexToString, LexFromString)
* }
*
* "command_result" (TCP) - Result of executing a remote Python command
* "dest" - Required - String - The node that should receive the result
* "data" - Required - Object - Payload data:
* {
* "success": True, // Required - Boolean - Whether the command executed successfully (without raising an uncaught exception)
* "command": "...", // Required - String - The command that was executed
* "result": "...", // Required - String - The result of running the command
* "output": [{ // Required - List - The log output from running the command
* "type: "...", // Required - String - The type of output (Info, Warning, or Error)
* "output": "..." // Required - String - The actual log output
* }]
* }
*/
And now from what I gather from both side, it seems like the communication between “client” (blender using the “send2ue” plugin or maya which I’m trying to achieve the same thing ) and “server” UE5 happens at least 5 or 6 times:
- maya sending an UDP broadcast asking for every currently running UE5 instance;
- every running UE5 instance response to that broadcast and give it’s GUID, known as NODEID in the blender “send2ue” plugins?
- maya catch that response, and now sending an “open_connection” type json in UDP mode to the desire NODEID, asking UE5 to open a TCP/IP port(define by maya I suppose?) for the next move, and I guess UE5 just open a TCP/IP port waiting for data? Did UE5 just automatically broadcast it’s GUID to whoever is listening? How do I listen for that response to catch that very important GUID for all the “dest” key that’re required in later on json message?
- maya finally send a “command” type json(this time in TCP mode?) to the TCP/IP port maya told UE5 to open in previous move, the actual python command string is put into the data[‘command’] value?
- maya catch the result of UE5 executing the python script, like HOW?
- maya send a “close_connection” type json in UDP mode again to tell UE5 to close down any TCP/IP port that are open.
I got so so so many question…
I’m not good at socket programming in python, heck I’m not even good at large project developing in python, and completely new to C++, if someone can take a look at my assumption and answer whichever question in those steps it would be great, or maybe my assumption is completely wrong and to point out what it should be, just to narrow it down a little bit so I know where to start.
Thanks~