Command Parsing & Execution
Relevant source files
The following files were used as context for generating this wiki page:
The Command Parsing & Execution system provides the foundational infrastructure for the Minecraft: Pi Edition programming interface. It enables external applications to interact with the game engine via a custom line-based protocol over TCP port 4711. The system is responsible for listening for incoming network connections, buffering and splitting raw bytes into discrete command strings, and parsing those strings into structured data for execution.
This module is central to the project's goal of preserving compatibility with the original MCPI API while providing a native port for modern systems. It consists of a multi-threaded TCP server (ApiServer) and a specialized string parser designed to handle the specific function-call syntax used by the original protocol.
Sources: README.md:1-15, src/main.cpp:8-10, src/api/ApiServer.hpp:20-22
Architecture Overview
The system is split into two primary layers: the Network Transport layer and the Command Logic layer. The ApiServer handles low-level socket operations and thread management, while the Command module handles the transformation of strings into actionable objects.
System Components
| Component | Responsibility | Relevant Files |
|---|---|---|
| ApiServer | Manages TCP lifecycle, client connections, and worker threads. | ApiServer.cpp, ApiServer.hpp |
| Command | Defines the internal structure of a command (name and arguments). | Command.hpp |
| Parser | A set of utilities to validate and decompose strings into Command objects. | Command.cpp |
| Handler | A user-defined callback function that processes parsed commands. | ApiServer.hpp |
Sources: src/api/ApiServer.hpp:16-36, src/api/Command.hpp:10-16
Component Interaction
The following diagram illustrates the relationship between the server implementation and the command data structures.
Network Communication
The ApiServer implements a TCP listener that accepts connections from external scripts. It utilizes a dedicated worker thread to handle client interactions asynchronously, ensuring the main game loop remains responsive.
Socket Management
The server supports cross-platform socket operations, handling differences between Winsock on Windows and standard Berkeley sockets on Linux. It includes logic for:
- Port Selection: Defaults to
4711but can be initialized with port0to request an available ephemeral port from the OS. - Address Reuse: Sets
SO_REUSEADDRto allow immediate restart of the server. - Timeouts: Configures
SO_RCVTIMEO(200ms) to allow the worker thread to periodically check if the server is stillrunning()during blockingrecvcalls.
Sources: src/api/ApiServer.cpp:45-77, src/api/ApiServer.cpp:160-200, tests/api_server_tests.cpp:110-120
Client Lifecycle
The following sequence diagram represents the lifecycle of a single command request from a client connection to the return of a response.
Command Parsing Logic
The parser transforms a raw string into a Command structure. The protocol follows a standard function-call syntax: method.name(arg1,arg2,...).
The Command Structure
struct Command {
std::string name;
std::vector<std::string> arguments;
};
Sources: src/api/Command.hpp:10-13
Parsing Algorithm
The parse_command function in src/api/Command.cpp performs the following steps:
- Trimming: Removes leading and trailing whitespace from the input line.
- Validation: Ensures the string contains matching parentheses
(and)and that the closing parenthesis is at the end of the string. - Name Extraction: Extracts the text before the first
(as the command name. - Argument Splitting: The text inside the parentheses is split by commas.
- Empty arguments (e.g.,
func(,,)) result in empty strings in the vector. - Leading/trailing whitespace for each individual argument is trimmed.
- Empty arguments (e.g.,
Sources: src/api/Command.cpp:25-63
Parsing Examples
The behavior of the parser is validated through various test cases in tests/protocol_tests.cpp.
| Input String | Parsed Name | Parsed Arguments | Result |
|---|---|---|---|
world.setBlock(1,2,3,57)\n | world.setBlock | ["1", "2", "3", "57"] | Success |
player.getPos()\r\n | player.getPos | [] | Success |
chat.post(Hello World) | chat.post | ["Hello World"] | Success |
malformed-input | N/A | N/A | Failure |
Sources: tests/protocol_tests.cpp:23-45
Implementation Details
Server Configuration
The ApiServer class provides methods to control the execution environment.
// src/api/ApiServer.hpp:16-36
class ApiServer {
public:
using Handler = std::function<std::optional<std::string>(const Command&)>;
explicit ApiServer(std::uint16_t port = 4711);
bool start(Handler handler);
void stop();
std::uint16_t port() const noexcept;
};
Response Handling
Handlers are provided as functional callbacks. If a handler returns a std::string, the ApiServer automatically appends a newline \n before transmitting it back to the client. If the handler returns std::nullopt, no response is sent to the client for that specific command.
Sources: src/api/ApiServer.cpp:143-146, tests/api_server_tests.cpp:108-112
Summary
The Command Parsing & Execution system provides a robust, thread-safe gateway for external control of the MCPI-recompiled game engine. By implementing the original TCP 4711 protocol and providing a flexible handler interface, it ensures that existing Minecraft: Pi Edition scripts and tools can function without modification. The modular separation of networking logic and string parsing allows for easy expansion as more game systems are reconstructed.
Sources: README.md:17-25, src/main.cpp:8-15