More Accurate Painting/Falling Sand Spawning + Some Fixes
Some checks failed
CI / Test (AMD64, Client) (push) Blocked by required conditions
CI / Test (AMD64, Server) (push) Blocked by required conditions
CI / Test (ARM64, Client) (push) Blocked by required conditions
CI / Test (ARM64, Server) (push) Blocked by required conditions
CI / Test (ARMHF, Client) (push) Blocked by required conditions
CI / Test (ARMHF, Server) (push) Blocked by required conditions
CI / Build Example Mods (push) Blocked by required conditions
CI / Release (push) Blocked by required conditions
CI / Build (AMD64) (push) Successful in 22m34s
CI / Build (ARM64) (push) Successful in 24m56s
CI / Build (ARMHF) (push) Has been cancelled
Some checks failed
CI / Test (AMD64, Client) (push) Blocked by required conditions
CI / Test (AMD64, Server) (push) Blocked by required conditions
CI / Test (ARM64, Client) (push) Blocked by required conditions
CI / Test (ARM64, Server) (push) Blocked by required conditions
CI / Test (ARMHF, Client) (push) Blocked by required conditions
CI / Test (ARMHF, Server) (push) Blocked by required conditions
CI / Build Example Mods (push) Blocked by required conditions
CI / Release (push) Blocked by required conditions
CI / Build (AMD64) (push) Successful in 22m34s
CI / Build (ARM64) (push) Successful in 24m56s
CI / Build (ARMHF) (push) Has been cancelled
This commit is contained in:
parent
adf92124c3
commit
426a35882f
@ -35,7 +35,7 @@ By default, MCPI-Reborn runs in a "compatibility mode." This makes it completely
|
|||||||
* `world.getBlockWithData(x,y,z)`
|
* `world.getBlockWithData(x,y,z)`
|
||||||
* Description: Retrieve the block ID and data value at the specified location.
|
* Description: Retrieve the block ID and data value at the specified location.
|
||||||
* Output: `block_id,data`
|
* Output: `block_id,data`
|
||||||
* `world.setBlocks(x0,y0,z0,x1,y1,x1,block_id[,data])`
|
* `world.setBlocks(x0,y0,z0,x1,y1,z1,block_id[,data])`
|
||||||
* Description: Fill the given region with the specified block.
|
* Description: Fill the given region with the specified block.
|
||||||
* `world.getHeight(x,z)`
|
* `world.getHeight(x,z)`
|
||||||
* Description: Get the last (from the top-down) non-solid block's Y-coordinate at the given location.
|
* Description: Get the last (from the top-down) non-solid block's Y-coordinate at the given location.
|
||||||
@ -80,7 +80,7 @@ By default, MCPI-Reborn runs in a "compatibility mode." This makes it completely
|
|||||||
* Output: List of `x,y,z,face,entity_id`
|
* Output: List of `x,y,z,face,entity_id`
|
||||||
|
|
||||||
### RaspberryJuice
|
### RaspberryJuice
|
||||||
* `world.getBlocks(x0,y0,z0,x1,y1,x1)`
|
* `world.getBlocks(x0,y0,z0,x1,y1,z1)`
|
||||||
* Description: Retrieve the blocks in the specified region.
|
* Description: Retrieve the blocks in the specified region.
|
||||||
* Output: List of <code>block_id<ins>,data</ins></code>
|
* Output: List of <code>block_id<ins>,data</ins></code>
|
||||||
* In compatibility mode, this list is delimited with commas (`,`).
|
* In compatibility mode, this list is delimited with commas (`,`).
|
||||||
@ -102,7 +102,7 @@ By default, MCPI-Reborn runs in a "compatibility mode." This makes it completely
|
|||||||
* `entity.removeEntities(entity_id,distance,entity_type_id)`
|
* `entity.removeEntities(entity_id,distance,entity_type_id)`
|
||||||
* Description: Remove all entities of the specified type[^1][^2] within the given distance of the provided entity.
|
* Description: Remove all entities of the specified type[^1][^2] within the given distance of the provided entity.
|
||||||
* Output: See above.
|
* Output: See above.
|
||||||
* `world.spawnEntity(x,y,x,entity_type_id)`
|
* <code>world.spawnEntity(<ins>:</ins>x<ins>:</ins>,<ins>:</ins>y<ins>:</ins>,<ins>:</ins>z<ins>:</ins>,entity_type_id)</code>
|
||||||
* Description: Spawn the specified entity at the given position.
|
* Description: Spawn the specified entity at the given position.
|
||||||
* Output: `entity_id`
|
* Output: `entity_id`
|
||||||
* `world.getEntityTypes()`
|
* `world.getEntityTypes()`
|
||||||
|
@ -57,7 +57,7 @@ std::map<EntityType, std::pair<std::string, std::string>> &misc_get_entity_type_
|
|||||||
std::pair<std::string, std::string> misc_get_entity_type_name(Entity *entity);
|
std::pair<std::string, std::string> misc_get_entity_type_name(Entity *entity);
|
||||||
std::string misc_get_entity_name(Entity *entity);
|
std::string misc_get_entity_name(Entity *entity);
|
||||||
|
|
||||||
Entity *misc_make_entity_from_id(Level *level, int id);
|
Entity *misc_make_entity_from_id(Level *level, int id, float x, float y, float z);
|
||||||
|
|
||||||
std::string misc_base64_encode(const std::string &data);
|
std::string misc_base64_encode(const std::string &data);
|
||||||
std::string misc_base64_decode(const std::string &input);
|
std::string misc_base64_decode(const std::string &input);
|
||||||
|
@ -299,6 +299,7 @@ static std::string CommandServer_parse_injection(CommandServer_parse_t original,
|
|||||||
if (src == nullptr) {
|
if (src == nullptr) {
|
||||||
return CommandServer::Fail;
|
return CommandServer::Fail;
|
||||||
}
|
}
|
||||||
|
api_convert_to_mcpi_entity_type(type);
|
||||||
// Run
|
// Run
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
for (Entity *entity : server->minecraft->level->entities) {
|
for (Entity *entity : server->minecraft->level->entities) {
|
||||||
@ -316,6 +317,7 @@ static std::string CommandServer_parse_injection(CommandServer_parse_t original,
|
|||||||
if (src == nullptr) {
|
if (src == nullptr) {
|
||||||
return CommandServer::Fail;
|
return CommandServer::Fail;
|
||||||
}
|
}
|
||||||
|
api_convert_to_mcpi_entity_type(type);
|
||||||
// Run
|
// Run
|
||||||
int removed = 0;
|
int removed = 0;
|
||||||
for (Entity *entity : server->minecraft->level->entities) {
|
for (Entity *entity : server->minecraft->level->entities) {
|
||||||
@ -333,14 +335,17 @@ static std::string CommandServer_parse_injection(CommandServer_parse_t original,
|
|||||||
next_int(type);
|
next_int(type);
|
||||||
// Translate
|
// Translate
|
||||||
server->pos_translator.from_float(x, y, z);
|
server->pos_translator.from_float(x, y, z);
|
||||||
|
if (api_compat_mode) {
|
||||||
|
x = float(int(x));
|
||||||
|
y = float(int(y));
|
||||||
|
z = float(int(z));
|
||||||
|
}
|
||||||
api_convert_to_mcpi_entity_type(type);
|
api_convert_to_mcpi_entity_type(type);
|
||||||
// Spawn
|
// Spawn
|
||||||
Entity *entity = misc_make_entity_from_id(server->minecraft->level, type);
|
Entity *entity = misc_make_entity_from_id(server->minecraft->level, type, x, y, z);
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
return CommandServer::Fail;
|
return CommandServer::Fail;
|
||||||
}
|
}
|
||||||
entity->moveTo(x, y, z, 0, 0);
|
|
||||||
server->minecraft->level->addEntity(entity);
|
|
||||||
return std::to_string(entity->id) + '\n';
|
return std::to_string(entity->id) + '\n';
|
||||||
} else if (cmd == "world.getEntityTypes") {
|
} else if (cmd == "world.getEntityTypes") {
|
||||||
// Get All Valid Entity Types
|
// Get All Valid Entity Types
|
||||||
|
@ -82,6 +82,7 @@ static std::unordered_map<int, EntityType> modern_entity_id_mapping = {
|
|||||||
{7, EntityType::THROWN_EGG},
|
{7, EntityType::THROWN_EGG},
|
||||||
{9, EntityType::PAINTING}
|
{9, EntityType::PAINTING}
|
||||||
};
|
};
|
||||||
|
static constexpr int unknown_entity_type_id = static_cast<int>(EntityType::UNKNOWN);
|
||||||
void api_convert_to_outside_entity_type(int &type) {
|
void api_convert_to_outside_entity_type(int &type) {
|
||||||
if (!api_compat_mode) {
|
if (!api_compat_mode) {
|
||||||
return;
|
return;
|
||||||
@ -90,9 +91,10 @@ void api_convert_to_outside_entity_type(int &type) {
|
|||||||
for (const std::pair<const int, EntityType> &pair : modern_entity_id_mapping) {
|
for (const std::pair<const int, EntityType> &pair : modern_entity_id_mapping) {
|
||||||
if (static_cast<int>(pair.second) == type) {
|
if (static_cast<int>(pair.second) == type) {
|
||||||
type = pair.first;
|
type = pair.first;
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
type = unknown_entity_type_id;;
|
||||||
}
|
}
|
||||||
void api_convert_to_mcpi_entity_type(int &type) {
|
void api_convert_to_mcpi_entity_type(int &type) {
|
||||||
if (!api_compat_mode) {
|
if (!api_compat_mode) {
|
||||||
@ -101,5 +103,7 @@ void api_convert_to_mcpi_entity_type(int &type) {
|
|||||||
// Convert To Native Entity Type
|
// Convert To Native Entity Type
|
||||||
if (modern_entity_id_mapping.contains(type)) {
|
if (modern_entity_id_mapping.contains(type)) {
|
||||||
type = static_cast<int>(modern_entity_id_mapping[type]);
|
type = static_cast<int>(modern_entity_id_mapping[type]);
|
||||||
|
} else {
|
||||||
|
type = unknown_entity_type_id;;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,6 +30,14 @@ static void send_api_chat_command(const Minecraft *minecraft, const char *str) {
|
|||||||
chat_send_api_command(minecraft, command);
|
chat_send_api_command(minecraft, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track "Real" API Clients
|
||||||
|
static bool is_real_api_client;
|
||||||
|
static std::string CommandServer_parse_injection(CommandServer_parse_t original, CommandServer *self, ConnectedClient &client, const std::string &input) {
|
||||||
|
is_real_api_client = client.sock >= 0;
|
||||||
|
// Call Original Method
|
||||||
|
return original(self, client, input);
|
||||||
|
}
|
||||||
|
|
||||||
// Send Message To Players
|
// Send Message To Players
|
||||||
std::string _chat_get_prefix(const char *username) {
|
std::string _chat_get_prefix(const char *username) {
|
||||||
return std::string("<") + username + "> ";
|
return std::string("<") + username + "> ";
|
||||||
@ -57,7 +65,11 @@ void chat_handle_packet_send(const Minecraft *minecraft, ChatPacket *packet) {
|
|||||||
// Hosting Multiplayer
|
// Hosting Multiplayer
|
||||||
const char *message = packet->message.c_str();
|
const char *message = packet->message.c_str();
|
||||||
ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) minecraft->network_handler;
|
ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) minecraft->network_handler;
|
||||||
chat_send_message_to_clients(server_side_network_handler, (Player *) minecraft->player, message);
|
if (is_real_api_client) {
|
||||||
|
server_side_network_handler->displayGameMessage(packet->message);
|
||||||
|
} else {
|
||||||
|
chat_send_message_to_clients(server_side_network_handler, (Player *) minecraft->player, message);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Client
|
// Client
|
||||||
rak_net_instance->send(*(Packet *) packet);
|
rak_net_instance->send(*(Packet *) packet);
|
||||||
@ -103,6 +115,7 @@ void init_chat() {
|
|||||||
unsigned char disable_chat_packet_loopback_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
unsigned char disable_chat_packet_loopback_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||||
patch((void *) 0x6b490, disable_chat_packet_loopback_patch);
|
patch((void *) 0x6b490, disable_chat_packet_loopback_patch);
|
||||||
// Manually Send (And Loopback) ChatPacket
|
// Manually Send (And Loopback) ChatPacket
|
||||||
|
overwrite_calls(CommandServer_parse, CommandServer_parse_injection);
|
||||||
overwrite_call((void *) 0x6b518, CommandServer_dispatchPacket, CommandServer_parse_CommandServer_dispatchPacket_injection);
|
overwrite_call((void *) 0x6b518, CommandServer_dispatchPacket, CommandServer_parse_CommandServer_dispatchPacket_injection);
|
||||||
// Re-Broadcast ChatPacket
|
// Re-Broadcast ChatPacket
|
||||||
patch_vtable(ServerSideNetworkHandler_handle_ChatPacket, ServerSideNetworkHandler_handle_ChatPacket_injection);
|
patch_vtable(ServerSideNetworkHandler_handle_ChatPacket, ServerSideNetworkHandler_handle_ChatPacket_injection);
|
||||||
|
@ -205,24 +205,61 @@ std::map<EntityType, std::pair<std::string, std::string>> &misc_get_entity_type_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Spawn Entities
|
// Spawn Entities
|
||||||
Entity *misc_make_entity_from_id(Level *level, const int id) {
|
static bool painting_direction_is_valid;
|
||||||
|
static void Painting_setRandomMotive_HangingEntity_setDir_injection(HangingEntity *self, const int direction) {
|
||||||
|
Painting *painting = (Painting *) self;
|
||||||
|
painting_direction_is_valid = painting->motive != nullptr;
|
||||||
|
if (!painting_direction_is_valid) {
|
||||||
|
painting->motive = *Painting::default_motive;
|
||||||
|
}
|
||||||
|
// Call Original Method
|
||||||
|
self->setDir(direction);
|
||||||
|
}
|
||||||
|
Entity *misc_make_entity_from_id(Level *level, const int id, const float x, const float y, const float z) {
|
||||||
|
// Create
|
||||||
|
Entity *entity;
|
||||||
if (id < static_cast<int>(EntityType::DROPPED_ITEM)) {
|
if (id < static_cast<int>(EntityType::DROPPED_ITEM)) {
|
||||||
// Spwn Mob
|
// Mob
|
||||||
return (Entity *) MobFactory::CreateMob(id, level);
|
entity = (Entity *) MobFactory::CreateMob(id, level);
|
||||||
} else {
|
} else {
|
||||||
// Spawn Entity
|
// Entity
|
||||||
Entity *entity = EntityFactory::CreateEntity(id, level);
|
entity = EntityFactory::CreateEntity(id, level);
|
||||||
|
}
|
||||||
|
// Setup
|
||||||
|
if (entity) {
|
||||||
|
// Position
|
||||||
|
entity->moveTo(x, y, z, 0, 0);
|
||||||
|
// Adjust
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case static_cast<int>(EntityType::PAINTING): {
|
case static_cast<int>(EntityType::PAINTING): {
|
||||||
// Fix Crash
|
// Find Valid Direction
|
||||||
((Painting *) entity)->motive = Motive::DefaultImage;
|
Painting *painting = (Painting *) entity;
|
||||||
|
const std::vector<std::pair<int, std::pair<int, int>>> directions = {
|
||||||
|
{1, {-1, 0}}, // West
|
||||||
|
{0, {0, 1}}, // South
|
||||||
|
{3, {1, 0}}, // East
|
||||||
|
{2, {0, -1}} // North
|
||||||
|
};
|
||||||
|
for (const std::pair<int, std::pair<int, int>> &info : directions) {
|
||||||
|
// Select Motive
|
||||||
|
int direction = info.first;
|
||||||
|
int new_x = int(x) - info.second.first;
|
||||||
|
int new_y = int(y);
|
||||||
|
int new_z = int(z) - info.second.second;
|
||||||
|
painting->setPosition(new_x, new_y, new_z);
|
||||||
|
painting->setRandomMotive(direction);
|
||||||
|
// Check
|
||||||
|
if (painting_direction_is_valid) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case static_cast<int>(EntityType::FALLING_SAND): {
|
case static_cast<int>(EntityType::FALLING_SAND): {
|
||||||
// Sensible Default
|
// Use Current Tile
|
||||||
FallingTile *sand = (FallingTile *) entity;
|
FallingTile *tile = (FallingTile *) entity;
|
||||||
sand->tile_id = Tile::sand->id;
|
tile->tile_id = level->getTile(int(x), int(y), int(z));
|
||||||
sand->time = 1;
|
tile->data = level->getData(int(x), int(y), int(z));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case static_cast<int>(EntityType::DROPPED_ITEM): {
|
case static_cast<int>(EntityType::DROPPED_ITEM): {
|
||||||
@ -231,8 +268,11 @@ Entity *misc_make_entity_from_id(Level *level, const int id) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return entity;
|
// Add To World
|
||||||
|
level->addEntity(entity);
|
||||||
}
|
}
|
||||||
|
// Return
|
||||||
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Username In Unicode
|
// Username In Unicode
|
||||||
@ -244,4 +284,8 @@ std::string misc_get_player_username_utf(const Player *player) {
|
|||||||
void _init_misc_api() {
|
void _init_misc_api() {
|
||||||
// Handle Custom Creative Inventory Setup Behavior
|
// Handle Custom Creative Inventory Setup Behavior
|
||||||
overwrite_call((void *) 0x8e0fc, FillingContainer_addItem, Inventory_setupDefault_FillingContainer_addItem_call_injection);
|
overwrite_call((void *) 0x8e0fc, FillingContainer_addItem, Inventory_setupDefault_FillingContainer_addItem_call_injection);
|
||||||
|
// Easy Way To Check Painting Orientation
|
||||||
|
unsigned char set_null_as_motive_patch[4] = {0x00, 0x30, 0xa0, 0x03}; // "moveq r3, #0x0"
|
||||||
|
patch((void *) 0x834e0, set_null_as_motive_patch);
|
||||||
|
overwrite_call((void *) 0x8367c, HangingEntity_setDir, Painting_setRandomMotive_HangingEntity_setDir_injection);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
extends Entity;
|
extends Entity;
|
||||||
|
|
||||||
vtable 0x10aba8;
|
vtable 0x10aba8;
|
||||||
|
|
||||||
|
method void setPosition(int x, int y, int z) = 0x7e888;
|
||||||
|
method void setDir(int direction) = 0x7e950;
|
@ -2,4 +2,7 @@ extends HangingEntity;
|
|||||||
|
|
||||||
vtable 0x10b0b0;
|
vtable 0x10b0b0;
|
||||||
|
|
||||||
|
method void setRandomMotive(int direction) = 0x83420;
|
||||||
|
|
||||||
|
static-property Motive **default_motive = 0x836d0;
|
||||||
property Motive *motive = 0xe4;
|
property Motive *motive = 0xe4;
|
Loading…
x
Reference in New Issue
Block a user