{"id":16013331,"url":"https://github.com/sof3/gsp","last_synced_at":"2026-05-16T23:15:21.987Z","repository":{"id":95881544,"uuid":"312171519","full_name":"SOF3/GSP","owner":"SOF3","description":"A Generalized Subprocess Plugin (GSP) is a PocketMine plugin written in any language supporting standard IO.","archived":false,"fork":false,"pushed_at":"2020-11-12T04:55:47.000Z","size":4,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"slaveowner","last_synced_at":"2025-03-20T09:51:19.335Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SOF3.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-12T04:55:32.000Z","updated_at":"2021-01-04T01:33:41.000Z","dependencies_parsed_at":"2023-06-17T17:33:23.154Z","dependency_job_id":null,"html_url":"https://github.com/SOF3/GSP","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/SOF3/GSP","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SOF3%2FGSP","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SOF3%2FGSP/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SOF3%2FGSP/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SOF3%2FGSP/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SOF3","download_url":"https://codeload.github.com/SOF3/GSP/tar.gz/refs/heads/slaveowner","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SOF3%2FGSP/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33121882,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-16T18:38:32.183Z","status":"ssl_error","status_checked_at":"2026-05-16T18:38:29.903Z","response_time":115,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-08T14:40:51.938Z","updated_at":"2026-05-16T23:15:21.963Z","avatar_url":"https://github.com/SOF3.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# GspPluginLoader\n\nA Generalized Subprocess Plugin (GSP) is a PocketMine plugin written in any language supporting standard IO.\nThe GSP is initialized as a standalone subprocess of the PocketMine process,\nand interact with the PocketMine API using the standard IO interface.\n\n## Plugin format\nGSP is a directory in the plugins directory with a `gsp.yml` file.\nIt shares the same format as the usual `plugin.yml`,\nexcept in the `main` attribute, instead of a PHP class string,\na command line shall be provided,\nwhich is used to spawn the GSP as a subprocess.\n\nThe command line can be a string or an array.\nSee the documentation of [`proc_open`](https://php.net/proc-open) for details.\nIt can also be a mapping of strings or arrays,\nin which the key should be values of `PHP_OS` to specify the command line based on operating system.\nIf more configuration is required, the developer can create a batch/powershell/shell script\nand invoke it from the command line.\n\nThe command line is executed with cwd set to the parent directory of the `gsp.yml`.\nThe environment variable `INVOKED_FROM_GSP_RUNTIME` is set to `1`.\n\n## Protocol\nThe subprocess communicates with the parent PHP process\nusing standard IO in a binary protocol as specified below.\n\n### Messages\nPocketMine sends \"messages\" to the subprocess through the stdin,\nand the subprocess sends \"messages\" to PocketMine through the stdout.\nGspPluginLoader also forwards the stderr output to PocketMine's main logger at DEBUG level asynchronously.\n\nEach \"message\" starts with an unsigned 16-bit integer, indicating the message type.\n\n#### Startup messages\n##### Shebang message\nIn case the first two bytes are `#!` (in ASCII encoding),\nthe stream is skipped until a Line Feed byte is encountered.\n\nThe shebang message is only allowed as the first message in the stream.\nFurther occurrences will crash the plugin.\n\n##### Handshake message\n```\n00 01 \"P\" \"M\" \"G\" \"S\" \"P\" \"S\" VERSION ENABLER DISABLER\n```\n\n- `VERSION` is a 16-bit integer indicating the supported GSP protocol version.\nThe current version is `00 01`.\n- `ENABLER` is the GCBID of the callback to invoke when the plugin shall be enabled.\n- `DISABLER` is the GCBID of the callback to invoke when the plugin shall be enabled.\n\nIf the GSP protocol version is mismatched,\nGspPluginLoader sends a `SIGTERM` signal to the subprocess.\nTherefore, the GSP should not initialize anything other than basic language runtime setup\nbefore sending the handshake message.\n\n#### GOA\nAll PHP objects accessible by subprocesses are stored in the GSP Object Arena (GOA).\nEach object is identified by a GOAID,\nwhich is a 64-bit signed integer assigned by GspPluginLoader.\nAlthough the current implementation uses the `spl_object_id` as the GOAID,\nthis is subject to change in the future without affecting protocol version.\n\nAn object is added to the GOA when its ID is passed in any message to the subprocess,\nand removed when the ObjectDeallocate message is sent from the subprocess.\nThe GOA is not automatically garbage-collected,\nso it is the responsibility of the subprocess to send the ObjectDeallocate message frequently.\n\nIt is guaranteed that the same PHP object always uses the same GOAID,\nbut it is not guaranteed that the same GOAID implies the same PHP object\nif the GOAID was Objectdeallocated.\n\n##### ObjectDeallocate message\n```\n01 01\n```\n\n#### Callbacks\nCallbacks are asynchronous invocations initiated by GspPluginLoader.\nEach callback is allocated with a GCBID (totally orthogonal to GOAID),\nwhich is a 64-bit signed integer assigned by the subprocess.\nAn assigned GCBID must be positive;\na negative value is never allowed,\nand a zero value implies no-op (returns null).\n\nA callback must be invokable as long as its GCBID is passed to GspPluginLoader,\nuntil it is deallocated.\nCallbacks are deallocated when the CallbackDeallocate message is sent from GspPluginLoader,\nwhich happens when PHP garbage-collects the wrapper object for the callback.\n\n##### CallbackDeallocate message\n```\n02 01 GCBID\n```\n\n- `GCBID` is the callback to deallocate.\n\nSent from GspPluginLoader,\nallows deallocation of the callback.\n\n##### CallbackToClosure message\n```\n02 02 GCBID\n```\n\n- `GCBID` is the callback to convert to closure.\n\nSent from subprocess,\nrequests to create a PHP Closure object that invokes the callback.\nThe closure would block until the callback completes.\n\n##### CallbackInvoke message\n```\n02 03 INVOKE_ID GCBID ARG_COUNT ( PARAM )*\n```\n\n- `INVOKE_ID` is the invocation ID to pass when the callback completes\n- `GCBID` is the callback to invoke.\n- `ARG_COUNT` is the 64-bit signed integer representing the number of arguments to pass.\n- `PARAM` are the PHP values to pass as arguments.\n\nSent from GspPluginLoader,\ninvokes the callback with the passed arguments.\n\nThe callback must return or throw by sending the CallbackComplete message.\n\n##### CallbackComplete message\n```\n02 04 INVOKE_ID ERROR VALUE\n```\n\n- `INVOKE_ID` is the `INVOKE_ID` passed in the CallbackInvoke message.\n- `ERROR` is a 8-bit byte indicating whether the callback should throw (`01`) or return (`00`)\n- `VALUE` is the PHP value to return/throw\n\n#### Accessing PHP\n##### FunctionCall message\n```\n03 00 RETURN THROW FUNCTION_NAME ARG_COUNT ( PARAM )*\n```\n\n- `RETURN` is the GCBID of the callback to invoke with the function return value.\n- `THROW` is the GCBID of the callback to invoke with the function return value.\n- `FUNCTION_NAME` is the name of the function to invoke.\n- `ARG_COUNT` is the 64-bit signed integer representing the number of arguments to pass.\n- `PARAM` are the PHP values to pass as arguments.\n\n##### MethodCall message\n```\n03 01 RETURN THROW GOAID METHOD_NAME ARG_COUNT ( PARAM )*\n```\n\n- `RETURN` is the GCBID of the callback to invoke with the method return value.\n- `THROW` is the GCBID of the callback to invoke with the method return value.\n- `GOAID` is the object to call the method on.\n- `METHOD_NAME` is the name of the function to invoke.\n- `ARG_COUNT` is the 64-bit signed integer representing the number of arguments to pass.\n- `PARAM` are the PHP values to pass as arguments.\n\n##### PropertyGet message\n```\n03 02 GCBID GOAID PROPERTY_NAME\n```\n\n- `GCBID` is the callback to invoke with the property value.\n- `GOAID` is the object to get the property on.\n- `PROPERTY_NAME` is the name of the property.\n\n##### PropertySet message\n```\n03 03 GCBID GOAID PROPERTY_NAME VALUE\n```\n\n- `GCBID` is the callback to invoke with the original value of the property.\n- `GOAID` is the object to get the property on.\n- `PROPERTY_NAME` is the name of the property.\n\n#### Concurrency\n##### Batch message\n```\n04 00 ( MESSAGE )*\n```\n\n- Each `MESSAGE` encodes a message to dispatch.\n\nThis guarantees that the messages are dispatched on the main thread consecutively.\nThis has no effect on messages that are not dispatched on the main thread.\n\n##### BlockStart message\n```\n04 01 GCBID\n```\n\n- `GCBID` is the callback to invoke when the lock starts\n\nBlocks the main thread to only process messages from the subprocess until LockEnd is received.\n\n##### BlockEnd message\n```\n04 02\n```\n\nUnblocks the main thread.\n\n### PHP values\nA PHP value is encoded on the protocol by a discriminant byte followed by the data.\n\n#### Null\n```\n00\n```\n\n#### Boolean\n```\n01 VALUE\n```\n\n- `VALUE` is `01` for true, `00` for false.\n\n#### Integer\n```\n02 VALUE\n```\n\n- `VALUE` is the little-endian signed 64-bit encoding of the integer.\n\nNote that PocketMine only supports 64-bit systems,\nand all integers in PHP are signed.\n\n#### Float\n```\n03 VALUE\n```\n\n- `VALUE` is the little-endian double-precision IEEE-754 encoding of the float.\n\n#### String\n```\n04 LENGTH BUFFER\n```\n\n- `LENGTH` is a little-endian signed 64-bit encoding of the length of the string.\n- `BUFFER` is a byte array of `LENGTH` bytes, representing the contents of the string.\n\nNote that PHP strings are binary byte arrays and encoding-insensitive.\n\n#### Array\n```\n05 GOAID\n```\n\n- `GOAID` is the ArrayAdapter object allocated for the array.\n\nTo access array contents,\ninvoke the appropriate methods on the ArrayAdapter object.\n\n#### Object\n```\n06 ID\n```\n\n- `ID` is the GOAID of the object.\n\nSee the \"GOA\" section above.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsof3%2Fgsp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsof3%2Fgsp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsof3%2Fgsp/lists"}