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)`
|
||||
* Description: Retrieve the block ID and data value at the specified location.
|
||||
* 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.
|
||||
* `world.getHeight(x,z)`
|
||||
* 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`
|
||||
|
||||
### 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.
|
||||
* Output: List of <code>block_id<ins>,data</ins></code>
|
||||
* 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)`
|
||||
* Description: Remove all entities of the specified type[^1][^2] within the given distance of the provided entity.
|
||||
* 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.
|
||||
* Output: `entity_id`
|
||||
* `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::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_decode(const std::string &input);
|
||||
|
@ -299,6 +299,7 @@ static std::string CommandServer_parse_injection(CommandServer_parse_t original,
|
||||
if (src == nullptr) {
|
||||
return CommandServer::Fail;
|
||||
}
|
||||
api_convert_to_mcpi_entity_type(type);
|
||||
// Run
|
||||
std::vector<std::string> result;
|
||||
for (Entity *entity : server->minecraft->level->entities) {
|
||||
@ -316,6 +317,7 @@ static std::string CommandServer_parse_injection(CommandServer_parse_t original,
|
||||
if (src == nullptr) {
|
||||
return CommandServer::Fail;
|
||||
}
|
||||
api_convert_to_mcpi_entity_type(type);
|
||||
// Run
|
||||
int removed = 0;
|
||||
for (Entity *entity : server->minecraft->level->entities) {
|
||||
@ -333,14 +335,17 @@ static std::string CommandServer_parse_injection(CommandServer_parse_t original,
|
||||
next_int(type);
|
||||
// Translate
|
||||
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);
|
||||
// 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) {
|
||||
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
|
||||
|
@ -82,6 +82,7 @@ static std::unordered_map<int, EntityType> modern_entity_id_mapping = {
|
||||
{7, EntityType::THROWN_EGG},
|
||||
{9, EntityType::PAINTING}
|
||||
};
|
||||
static constexpr int unknown_entity_type_id = static_cast<int>(EntityType::UNKNOWN);
|
||||
void api_convert_to_outside_entity_type(int &type) {
|
||||
if (!api_compat_mode) {
|
||||
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) {
|
||||
if (static_cast<int>(pair.second) == type) {
|
||||
type = pair.first;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
type = unknown_entity_type_id;;
|
||||
}
|
||||
void api_convert_to_mcpi_entity_type(int &type) {
|
||||
if (!api_compat_mode) {
|
||||
@ -101,5 +103,7 @@ void api_convert_to_mcpi_entity_type(int &type) {
|
||||
// Convert To Native Entity Type
|
||||
if (modern_entity_id_mapping.contains(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);
|
||||
}
|
||||
|
||||
// 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
|
||||
std::string _chat_get_prefix(const char *username) {
|
||||
return std::string("<") + username + "> ";
|
||||
@ -57,7 +65,11 @@ void chat_handle_packet_send(const Minecraft *minecraft, ChatPacket *packet) {
|
||||
// Hosting Multiplayer
|
||||
const char *message = packet->message.c_str();
|
||||
ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) minecraft->network_handler;
|
||||
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 {
|
||||
// Client
|
||||
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"
|
||||
patch((void *) 0x6b490, disable_chat_packet_loopback_patch);
|
||||
// Manually Send (And Loopback) ChatPacket
|
||||
overwrite_calls(CommandServer_parse, CommandServer_parse_injection);
|
||||
overwrite_call((void *) 0x6b518, CommandServer_dispatchPacket, CommandServer_parse_CommandServer_dispatchPacket_injection);
|
||||
// Re-Broadcast ChatPacket
|
||||
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
|
||||
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)) {
|
||||
// Spwn Mob
|
||||
return (Entity *) MobFactory::CreateMob(id, level);
|
||||
// Mob
|
||||
entity = (Entity *) MobFactory::CreateMob(id, level);
|
||||
} else {
|
||||
// Spawn Entity
|
||||
Entity *entity = EntityFactory::CreateEntity(id, level);
|
||||
// Entity
|
||||
entity = EntityFactory::CreateEntity(id, level);
|
||||
}
|
||||
// Setup
|
||||
if (entity) {
|
||||
// Position
|
||||
entity->moveTo(x, y, z, 0, 0);
|
||||
// Adjust
|
||||
switch (id) {
|
||||
case static_cast<int>(EntityType::PAINTING): {
|
||||
// Fix Crash
|
||||
((Painting *) entity)->motive = Motive::DefaultImage;
|
||||
// Find Valid Direction
|
||||
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;
|
||||
}
|
||||
case static_cast<int>(EntityType::FALLING_SAND): {
|
||||
// Sensible Default
|
||||
FallingTile *sand = (FallingTile *) entity;
|
||||
sand->tile_id = Tile::sand->id;
|
||||
sand->time = 1;
|
||||
// Use Current Tile
|
||||
FallingTile *tile = (FallingTile *) entity;
|
||||
tile->tile_id = level->getTile(int(x), int(y), int(z));
|
||||
tile->data = level->getData(int(x), int(y), int(z));
|
||||
break;
|
||||
}
|
||||
case static_cast<int>(EntityType::DROPPED_ITEM): {
|
||||
@ -231,8 +268,11 @@ Entity *misc_make_entity_from_id(Level *level, const int id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return entity;
|
||||
// Add To World
|
||||
level->addEntity(entity);
|
||||
}
|
||||
// Return
|
||||
return entity;
|
||||
}
|
||||
|
||||
// Username In Unicode
|
||||
@ -244,4 +284,8 @@ std::string misc_get_player_username_utf(const Player *player) {
|
||||
void _init_misc_api() {
|
||||
// Handle Custom Creative Inventory Setup Behavior
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
method void setRandomMotive(int direction) = 0x83420;
|
||||
|
||||
static-property Motive **default_motive = 0x836d0;
|
||||
property Motive *motive = 0xe4;
|
Loading…
x
Reference in New Issue
Block a user