Finish API Doc
This commit is contained in:
parent
d4525f407e
commit
9d88f28595
125
docs/API.md
125
docs/API.md
@ -14,16 +14,16 @@ It is typically hosted on port `4711`, but this can be configured.
|
||||
By default, MCPI-Reborn runs in a "compatibility mode." This makes it completely compatible with RaspberryJuice, but limits functionality.
|
||||
|
||||
* **Bold** text only applies to the compatibility mode.
|
||||
* <u>Underlined</u> text only applies when it is disabled.
|
||||
* Text enclosed in curly braces (`{}`) is meant to be [Base64-URL](https://base64.guru/standards/base64url) encoded when the compatibility mode is disabled.
|
||||
* In compatibility mode, entity type IDs are automatically translated to/from their MC Java equivalents.
|
||||
* <ins>Underlined</ins> text only applies when it is disabled.
|
||||
* Text enclosed in curly braces (for instance `{text}`) is meant to be [Base64-URL](https://base64.guru/standards/base64url)-encoded when the compatibility mode is disabled.
|
||||
* In compatibility mode, entity type IDs are automatically translated to/from their [MC Java equivalents](https://mcreator.net/wiki/entity-ids#toc-index-2).
|
||||
|
||||
## Commands
|
||||
* Commands are formatted like `<command>(<args>)` and may return a response. The response `Fail` indicates an error.
|
||||
* All commands are responses end with a newline.
|
||||
* Arguments surrounded by square brackets (for instance `[abc]`) are optional.
|
||||
* Numbers surrounded by colons (for instance `:a:`) are floating-point, all other numbers are integers.
|
||||
* Lists are delimited by `|`. For instance: `A|B|C`.
|
||||
* Lists are delimited by pipes (`|`). For instance: `A|B|C`.
|
||||
* Unless otherwise noted, all `player.*(...)` commands are equivalent to `entity.*(local_player_id,...)`.
|
||||
|
||||
### Vanilla
|
||||
@ -40,26 +40,6 @@ By default, MCPI-Reborn runs in a "compatibility mode." This makes it completely
|
||||
* `world.getHeight(x,z)`
|
||||
* Description: Get the last (from the top-down) non-solid block's Y-coordinate at the given location.
|
||||
* Output: `max_y`
|
||||
* `entity.setTile(entity_id,x,y,z)`
|
||||
* Description: Move the specified entity to the given position.
|
||||
* `entity.setPos(entity_id,:x:,:y:,:z:)`
|
||||
* Description: Same as above.
|
||||
* `entity.getTile(entity_id)`
|
||||
* Description: Retrieve the given entity's position.
|
||||
* Output: `x,y,z`
|
||||
* `entity.getPos(entity_id)`
|
||||
* Description: Same as above.
|
||||
* Output: `:x:,:y:,:z:`
|
||||
* `chat.post(message)`
|
||||
* Description: Post the specified message to chat.
|
||||
* `camera.mode.setFixed()`
|
||||
* Description: Set the camera to fixed-position mode.
|
||||
* `camera.mode.setNormal([entity_id])`
|
||||
* Description: Set the camera to normal mode. The camera will be the specified entity (or the local player if none is provided).
|
||||
* `camera.mode.setFollow([entity_id])`
|
||||
* Description: Set the camera to follow mode. The camera will follow the specified entity (or the local player if none is provided).
|
||||
* `camera.setPos(:x:,:y:,:z:)`
|
||||
* Description: Move the camera to the given position. The XZ-coordinates are automatically offset by `0.5`.
|
||||
* `world.getPlayerIds()`
|
||||
* Description: Retrieve the entity IDs of all players.
|
||||
* Output: List of `entity_id`
|
||||
@ -72,6 +52,26 @@ By default, MCPI-Reborn runs in a "compatibility mode." This makes it completely
|
||||
* `autojump`
|
||||
* `nametags_visible`
|
||||
* `world_immutable`
|
||||
* `entity.setTile(entity_id,x,y,z)`
|
||||
* Description: Move the specified entity to the given position.
|
||||
* `entity.setPos(entity_id,:x:,:y:,:z:)`
|
||||
* Description: See above.
|
||||
* `entity.getTile(entity_id)`
|
||||
* Description: Retrieve the given entity's position.
|
||||
* Output: `x,y,z`
|
||||
* `entity.getPos(entity_id)`
|
||||
* Description: See above.
|
||||
* Output: `:x:,:y:,:z:`
|
||||
* `chat.post(message)`
|
||||
* Description: Post the specified message to chat.
|
||||
* `camera.mode.setFixed()`
|
||||
* Description: Set the camera to fixed-position mode.
|
||||
* `camera.mode.setNormal([entity_id])`
|
||||
* Description: Set the camera to normal mode. The camera will be the specified entity (or the local player if none is provided).
|
||||
* `camera.mode.setFollow([entity_id])`
|
||||
* Description: Set the camera to follow mode. The camera will follow the specified entity (or the local player if none is provided).
|
||||
* `camera.setPos(:x:,:y:,:z:)`
|
||||
* Description: Move the camera to the given position. The XZ-coordinates are automatically offset by `0.5`.
|
||||
* `events.clear()`
|
||||
* Description: Clear all queued events.
|
||||
* Note: On RaspberryJuice, this *does not* clear projectile events. This behavior is maintained only in compatibility mode.
|
||||
@ -80,6 +80,78 @@ By default, MCPI-Reborn runs in a "compatibility mode." This makes it completely
|
||||
* Output: List of `x,y,z,face,entity_id`
|
||||
|
||||
### RaspberryJuice
|
||||
* `world.getBlocks(x0,y0,z0,x1,y1,x1)`
|
||||
* Description: Retrieve the blocks in the specified region.
|
||||
* Output: List of <code>block_id<ins>,data</ins></code>
|
||||
* In compatibility mode, this list is delimited with commas (`,`).
|
||||
* `world.getPlayerId({username})`
|
||||
* Description: Retrieve the entity ID of the specified player.
|
||||
* Output: `entity_id`
|
||||
* `world.getEntities(entity_type_id)`
|
||||
* Description: Retrieve all entities of the specified type[^1].
|
||||
* Output: List <code>entity_id,entity_type_id<b>,entity_type_name</b>,:x:,:y:,:z:</code>
|
||||
* `entity.getEntities(entity_id,distance,entity_type_id)`
|
||||
* Description: Retrieve all entities of the specified type[^1] within the given distance of the provided entity.
|
||||
* Output: See above.
|
||||
* `world.removeEntity(entity_id)`
|
||||
* Description: Remove the specified entity.
|
||||
* Output: `number_of_entities_removed`
|
||||
* `world.removeEntities(entity_type_id)`
|
||||
* Description: Remove all entities of the specified type[^1].
|
||||
* Output: See above.
|
||||
* `entity.removeEntities(entity_id,distance,entity_type_id)`
|
||||
* Description: Remove all entities of the specified type[^1] within the given distance of the provided entity.
|
||||
* Output: See above.
|
||||
* `world.spawnEntity(x,y,x,entity_type_id)`
|
||||
* Description: Spawn the specified entity at the given position.
|
||||
* Output: `entity_id`
|
||||
* `world.getEntityTypes()`
|
||||
* Description: Retrieve all supported entity types.
|
||||
* Output: List of `entity_type_id,entity_type_name`
|
||||
* `world.setSign(x,y,z,id,data[,{line_1}][,{line_2}][,{line_3}][,{line_4}])`
|
||||
* Description: Set the specified block at the given location. If the block is a sign, then also set its contents.
|
||||
* `entity.getName(entity_id)`
|
||||
* Description: Retrieve the name of the specified entity.
|
||||
* Output: `{entity_name}`
|
||||
* `entity.setDirection(entity_id,:x:,:y:,:z:)`
|
||||
* Description: Set the specified entity's rotation using a unit vector.
|
||||
* `entity.getDirection(entity_id)`
|
||||
* Description: Retrieve the specified entity's rotation as a unit vector.
|
||||
* Output: `:x:,:y:,:z:`
|
||||
* `entity.setRotation(entity_id,:yaw:)`
|
||||
* Description: Set the specified entity's yaw.
|
||||
* `entity.getRotation(entity_id)`
|
||||
* Description: Retrieve the specified entity's yaw.
|
||||
* Output: `:yaw:`
|
||||
* `entity.setPitch(entity_id,:pitch:)`
|
||||
* Description: Set the specified entity's pitch.
|
||||
* `entity.getPitch(entity_id)`
|
||||
* Description: Retrieve the specified entity's pitch.
|
||||
* Output: `:pitch:`
|
||||
* `entity.setAbsPos(entity_id,:x:,:y:,:z:)`
|
||||
* Description: Move the specified entity to the given absolute[^2] position.
|
||||
* `entity.getAbsPos(entity_id)`
|
||||
* Description: Retrieve the given entity's absolute[^2] position.
|
||||
* Output: `:x:,:y:,:z:`
|
||||
* `entity.events.block.hits(entity_id)`
|
||||
* Description: Retrieve all queued block hit events produced by the specified entity.
|
||||
* Output: See `events.block.hits`.
|
||||
* `events.chat.posts()`
|
||||
* Description: Retrieve all queued chat events.
|
||||
* Output: List of `entity_id,{message}`
|
||||
* When compatibility mode is disabled, this will also include non-chat messages denoted with an entity ID of `-1`.
|
||||
* `entity.events.chat.posts(entity_id)`
|
||||
* Description: Retrieve all queued chat events produced by the specified entity.
|
||||
* Output: See above.
|
||||
* `events.projectile.hits()`
|
||||
* Description: Retrieve all queued projectile hit events.
|
||||
* Output: List of <code>x,y,z<b>,1,shooter_entity_name,\[target_entity_name\]</b><ins>,shooter_entity_id,target_entity_id</ins></code>
|
||||
* If the projectile hit a block, `target_entity_id` will be `-1` and `target_entity_name` will be blank.
|
||||
* `entity.events.projectile.hits(entity_id)`
|
||||
* Description: Retrieve all queued projectile hit events produced by the specified entity.
|
||||
* Output: See above.
|
||||
* `entity.events.clear(entity_id)`
|
||||
* Description: Clear all queued events produced by the specified entity.
|
||||
|
||||
### Reborn-Specific
|
||||
* `reborn.disableCompatMode()`
|
||||
@ -92,4 +164,7 @@ By default, MCPI-Reborn runs in a "compatibility mode." This makes it completely
|
||||
* Output: List of `{line}`
|
||||
* `entity.getType(entity_id)`
|
||||
* Description: Check the type of the given entity.
|
||||
* Output: `entity_type`
|
||||
* Output: `entity_type_id`
|
||||
|
||||
[^1]: If the ID is `-1`, it will match all entities.
|
||||
[^2]: The API normally applies an offset to all coordinates, these commands use the raw data.
|
@ -199,7 +199,11 @@ static std::unordered_map<int, EntityType> modern_entity_id_mapping = {
|
||||
{7, EntityType::THROWN_EGG},
|
||||
{9, EntityType::PAINTING}
|
||||
};
|
||||
void api_convert_to_rj_entity_type(int &type) {
|
||||
void api_convert_to_outside_entity_type(int &type) {
|
||||
if (!api_compat_mode) {
|
||||
return;
|
||||
}
|
||||
// Convert To RJ-Compatible Entity Type
|
||||
for (const std::pair<const int, EntityType> &pair : modern_entity_id_mapping) {
|
||||
if (static_cast<int>(pair.second) == type) {
|
||||
type = pair.first;
|
||||
@ -207,6 +211,10 @@ void api_convert_to_rj_entity_type(int &type) {
|
||||
}
|
||||
}
|
||||
void api_convert_to_mcpi_entity_type(int &type) {
|
||||
if (!api_compat_mode) {
|
||||
return;
|
||||
}
|
||||
// Convert To Native Entity Type
|
||||
if (modern_entity_id_mapping.contains(type)) {
|
||||
type = static_cast<int>(modern_entity_id_mapping[type]);
|
||||
}
|
||||
@ -219,9 +227,7 @@ static std::string get_entity_message(CommandServer *server, Entity *entity) {
|
||||
pieces.push_back(std::to_string(entity->id));
|
||||
// Type
|
||||
int type = entity->getEntityTypeId();
|
||||
if (api_compat_mode) {
|
||||
api_convert_to_rj_entity_type(type);
|
||||
}
|
||||
api_convert_to_outside_entity_type(type);
|
||||
pieces.push_back(std::to_string(type));
|
||||
if (api_compat_mode) {
|
||||
pieces.push_back(api_get_output(misc_get_entity_type_name(entity).second, true));
|
||||
@ -345,17 +351,13 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
|
||||
return CommandServer::NullString;
|
||||
} else {
|
||||
int type = entity->getEntityTypeId();
|
||||
if (api_compat_mode) {
|
||||
api_convert_to_rj_entity_type(type);
|
||||
}
|
||||
api_convert_to_outside_entity_type(type);
|
||||
return std::to_string(type) + '\n';
|
||||
}
|
||||
} else if (cmd == "world.getEntities") {
|
||||
// Parse
|
||||
next_int(type);
|
||||
if (api_compat_mode) {
|
||||
api_convert_to_mcpi_entity_type(type);
|
||||
}
|
||||
api_convert_to_mcpi_entity_type(type);
|
||||
// Search
|
||||
std::vector<std::string> result;
|
||||
for (Entity *entity : server->minecraft->level->entities) {
|
||||
@ -378,9 +380,7 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
|
||||
} else if (cmd == "world.removeEntities") {
|
||||
// Parse
|
||||
next_int(type);
|
||||
if (api_compat_mode) {
|
||||
api_convert_to_mcpi_entity_type(type);
|
||||
}
|
||||
api_convert_to_mcpi_entity_type(type);
|
||||
// Remove
|
||||
int removed = 0;
|
||||
for (Entity *entity : server->minecraft->level->entities) {
|
||||
@ -390,6 +390,67 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
|
||||
}
|
||||
}
|
||||
return std::to_string(removed) + '\n';
|
||||
} else if (cmd == "entity.getEntities") {
|
||||
// Parse
|
||||
next_int(id);
|
||||
next_int(dist);
|
||||
next_int(type);
|
||||
Entity *src = server->minecraft->level->getEntity(id);
|
||||
if (src == nullptr) {
|
||||
return CommandServer::Fail;
|
||||
}
|
||||
// Run
|
||||
std::vector<std::string> result;
|
||||
for (Entity *entity : server->minecraft->level->entities) {
|
||||
if (is_entity_selected(entity, type) && distance_between(src, entity) < dist) {
|
||||
result.push_back(get_entity_message(server, entity));
|
||||
}
|
||||
}
|
||||
return api_join_outputs(result, list_separator);
|
||||
} else if (cmd == "entity.removeEntities") {
|
||||
// Parse
|
||||
next_int(id);
|
||||
next_int(dist);
|
||||
next_int(type);
|
||||
Entity *src = server->minecraft->level->getEntity(id);
|
||||
if (src == nullptr) {
|
||||
return CommandServer::Fail;
|
||||
}
|
||||
// Run
|
||||
int removed = 0;
|
||||
for (Entity *entity : server->minecraft->level->entities) {
|
||||
if (is_entity_selected(entity, type) && distance_between(src, entity) < dist) {
|
||||
entity->remove();
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
return std::to_string(removed) + '\n';
|
||||
} else if (cmd == "world.spawnEntity") {
|
||||
// Parse
|
||||
next_float(x);
|
||||
next_float(y);
|
||||
next_float(z);
|
||||
next_int(type);
|
||||
// Translate
|
||||
server->pos_translator.from_float(x, y, z);
|
||||
api_convert_to_mcpi_entity_type(type);
|
||||
// Spawn
|
||||
Entity *entity = misc_make_entity_from_id(server->minecraft->level, type);
|
||||
if (entity == nullptr) {
|
||||
return CommandServer::Fail;
|
||||
}
|
||||
entity->moveTo(x, y, z, 0, 0);
|
||||
server->minecraft->level->addEntity(entity);
|
||||
return std::to_string(entity->id) + '\n';
|
||||
} else if (cmd == "world.getEntityTypes") {
|
||||
// Get All Valid Entity Types
|
||||
std::vector<std::string> result;
|
||||
for (const std::pair<const EntityType, std::pair<std::string, std::string>> &i : misc_get_entity_type_names()) {
|
||||
int id = static_cast<int>(i.first);
|
||||
api_convert_to_outside_entity_type(id);
|
||||
result.push_back(api_join_outputs({std::to_string(id), api_get_output(i.second.second, true)}, arg_separator));
|
||||
}
|
||||
return api_join_outputs(result, list_separator);
|
||||
} else if (cmd == "events.chat.posts") {
|
||||
return api_get_chat_events(server, client, std::nullopt);
|
||||
} else if (cmd == "entity.events.chat.posts") {
|
||||
@ -405,6 +466,13 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
|
||||
} else if (cmd == "entity.events.projectile.hits") {
|
||||
next_int(id);
|
||||
return api_get_projectile_events(server, client, id);
|
||||
} else if (cmd == "entity.events.clear") {
|
||||
next_int(id);
|
||||
api_clear_events(client, id);
|
||||
return CommandServer::NullString;
|
||||
} else if (cmd == "events.clear") {
|
||||
api_clear_events(client);
|
||||
return CommandServer::NullString;
|
||||
} else if (cmd == "entity.setDirection") {
|
||||
// Parse
|
||||
next_int(id);
|
||||
@ -470,41 +538,6 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
|
||||
} else {
|
||||
return std::to_string(entity->pitch) + '\n';
|
||||
}
|
||||
} else if (cmd == "entity.getEntities") {
|
||||
// Parse
|
||||
next_int(id);
|
||||
next_int(dist);
|
||||
next_int(type);
|
||||
Entity *src = server->minecraft->level->getEntity(id);
|
||||
if (src == nullptr) {
|
||||
return CommandServer::Fail;
|
||||
}
|
||||
// Run
|
||||
std::vector<std::string> result;
|
||||
for (Entity *entity : server->minecraft->level->entities) {
|
||||
if (is_entity_selected(entity, type) && distance_between(src, entity) < dist) {
|
||||
result.push_back(get_entity_message(server, entity));
|
||||
}
|
||||
}
|
||||
return api_join_outputs(result, list_separator);
|
||||
} else if (cmd == "entity.removeEntities") {
|
||||
// Parse
|
||||
next_int(id);
|
||||
next_int(dist);
|
||||
next_int(type);
|
||||
Entity *src = server->minecraft->level->getEntity(id);
|
||||
if (src == nullptr) {
|
||||
return CommandServer::Fail;
|
||||
}
|
||||
// Run
|
||||
int removed = 0;
|
||||
for (Entity *entity : server->minecraft->level->entities) {
|
||||
if (is_entity_selected(entity, type) && distance_between(src, entity) < dist) {
|
||||
entity->remove();
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
return std::to_string(removed) + '\n';
|
||||
} else if (cmd == "world.setSign") {
|
||||
// Parse
|
||||
next_int(x);
|
||||
@ -551,36 +584,6 @@ sign->lines[i] = get_input(line_##i); \
|
||||
pieces.push_back(api_get_output(line, false));
|
||||
}
|
||||
return api_join_outputs(pieces, list_separator);
|
||||
} else if (cmd == "world.spawnEntity") {
|
||||
// Parse
|
||||
next_float(x);
|
||||
next_float(y);
|
||||
next_float(z);
|
||||
next_int(type);
|
||||
// Translate
|
||||
server->pos_translator.from_float(x, y, z);
|
||||
if (api_compat_mode) {
|
||||
api_convert_to_mcpi_entity_type(type);
|
||||
}
|
||||
// Spawn
|
||||
Entity *entity = misc_make_entity_from_id(server->minecraft->level, type);
|
||||
if (entity == nullptr) {
|
||||
return CommandServer::Fail;
|
||||
}
|
||||
entity->moveTo(x, y, z, 0, 0);
|
||||
server->minecraft->level->addEntity(entity);
|
||||
return std::to_string(entity->id) + '\n';
|
||||
} else if (cmd == "world.getEntityTypes") {
|
||||
// Get All Valid Entity Types
|
||||
std::vector<std::string> result;
|
||||
for (const std::pair<const EntityType, std::pair<std::string, std::string>> &i : misc_get_entity_type_names()) {
|
||||
int id = static_cast<int>(i.first);
|
||||
if (api_compat_mode) {
|
||||
api_convert_to_rj_entity_type(id);
|
||||
}
|
||||
result.push_back(api_join_outputs({std::to_string(id), api_get_output(i.second.second, true)}, arg_separator));
|
||||
}
|
||||
return api_join_outputs(result, list_separator);
|
||||
} else if (cmd == "entity.setAbsPos") {
|
||||
// Parse
|
||||
next_int(id);
|
||||
@ -603,13 +606,6 @@ sign->lines[i] = get_input(line_##i); \
|
||||
return CommandServer::Fail;
|
||||
}
|
||||
return api_join_outputs({std::to_string(entity->x), std::to_string(entity->y - entity->height_offset), std::to_string(entity->z)}, arg_separator);
|
||||
} else if (cmd == "entity.events.clear") {
|
||||
next_int(id);
|
||||
api_clear_events(client, id);
|
||||
return CommandServer::NullString;
|
||||
} else if (cmd == "events.clear") {
|
||||
api_clear_events(client);
|
||||
return CommandServer::NullString;
|
||||
} else if (cmd == "reborn.disableCompatMode") {
|
||||
api_compat_mode = false;
|
||||
return std::string(reborn_get_version()) + '\n';
|
||||
|
@ -29,9 +29,9 @@ static std::string event_to_string(CommandServer *server, const ProjectileHitEve
|
||||
// Get Outputs
|
||||
std::vector pieces = {
|
||||
// Position
|
||||
std::to_string(int(nx)),
|
||||
std::to_string(int(ny)),
|
||||
std::to_string(int(nz))
|
||||
std::to_string(nx),
|
||||
std::to_string(ny),
|
||||
std::to_string(nz)
|
||||
};
|
||||
// Needed For Compatibility
|
||||
if (api_compat_mode) {
|
||||
|
@ -9,7 +9,7 @@ static constexpr char list_separator = '|';
|
||||
__attribute__((visibility("internal"))) std::string api_get_output(std::string message, bool replace_comma);
|
||||
__attribute__((visibility("internal"))) std::string api_join_outputs(const std::vector<std::string> &pieces, char separator);
|
||||
|
||||
__attribute__((visibility("internal"))) void api_convert_to_rj_entity_type(int &type);
|
||||
__attribute__((visibility("internal"))) void api_convert_to_outside_entity_type(int &type);
|
||||
__attribute__((visibility("internal"))) void api_convert_to_mcpi_entity_type(int &type);
|
||||
|
||||
__attribute__((visibility("internal"))) void _init_api_events();
|
||||
|
Loading…
x
Reference in New Issue
Block a user