Fix Many API Bugs

This commit is contained in:
TheBrokenRail 2025-02-26 05:41:36 -05:00
parent 718b3e98fe
commit 800b1441a9
7 changed files with 134 additions and 58 deletions

View File

@ -4,7 +4,6 @@
#include <optional> #include <optional>
#include <sstream> #include <sstream>
#include <libreborn/log.h>
#include <libreborn/util/string.h> #include <libreborn/util/string.h>
#include <libreborn/patch.h> #include <libreborn/patch.h>
#include <libreborn/config.h> #include <libreborn/config.h>
@ -89,15 +88,15 @@ static std::string get_blocks(CommandServer *server, const Vec3 &start, const Ve
server->pos_translator.from(end_x, end_y, end_z); server->pos_translator.from(end_x, end_y, end_z);
// Swap If Needed // Swap If Needed
if (end_x < start_x) { #define swap_if_needed(axis) \
std::swap(start_x, end_x); if (end_##axis < start_##axis) { \
} std::swap(start_##axis, end_##axis); \
if (end_y < start_y) { } \
std::swap(start_y, end_y); (void) 0
} swap_if_needed(x);
if (end_z < start_z) { swap_if_needed(y);
std::swap(start_z, end_z); swap_if_needed(z);
} #undef swap_if_needed
// Get // Get
std::vector<std::string> ret; std::vector<std::string> ret;
@ -112,6 +111,42 @@ static std::string get_blocks(CommandServer *server, const Vec3 &start, const Ve
return api_join_outputs(ret, arg_separator); return api_join_outputs(ret, arg_separator);
} }
// Properly Teleport Players
static void update_player_position(const Entity *entity) {
if (entity->vtable == (Entity_vtable *) ServerPlayer_vtable::base) {
const ServerPlayer *player = (ServerPlayer *) entity;
MovePlayerPacket *packet = MovePlayerPacket::allocate();
((Packet *) packet)->constructor();
packet->vtable = MovePlayerPacket_vtable::base;
packet->x = player->x;
packet->y = player->y - player->height_offset;
packet->z = player->z;
packet->yaw = player->yaw;
packet->pitch = player->pitch;
packet->entity_id = player->id;
player->minecraft->rak_net_instance->send(*(Packet *) packet);
packet->destructor_deleting();
}
}
static void Entity_moveTo_injection(Entity *self, const float x, const float y, const float z, const float yaw, const float pitch) {
self->moveTo(x, y, z, yaw, pitch);
update_player_position(self);
}
static void ClientSideNetworkHandler_handle_MovePlayerPacket_injection(ClientSideNetworkHandler_handle_MovePlayerPacket_t original, ClientSideNetworkHandler *self, const RakNet_RakNetGUID &rak_net_guid, MovePlayerPacket *packet) {
if (self->level) {
Entity *entity = self->level->getEntity(packet->entity_id);
if (entity) {
if (entity == (Entity *) self->minecraft->player) {
// Just Teleport
entity->moveTo(packet->x, packet->y, packet->z, packet->yaw, packet->pitch);
} else {
// Call Original Method
original(self, rak_net_guid, packet);
}
}
}
}
// Set Entity Rotation From XYZ // Set Entity Rotation From XYZ
static void set_dir(Entity *entity, const float x, const float y, const float z) { static void set_dir(Entity *entity, const float x, const float y, const float z) {
// Check Rotation // Check Rotation
@ -128,6 +163,7 @@ static void set_dir(Entity *entity, const float x, const float y, const float z)
entity->yaw = std::fmod(std::atan2(-x, z), _2PI) * factor; entity->yaw = std::fmod(std::atan2(-x, z), _2PI) * factor;
const float xz = std::sqrt(x * x + z * z); const float xz = std::sqrt(x * x + z * z);
entity->pitch = std::atan(-y / xz) * factor; entity->pitch = std::atan(-y / xz) * factor;
update_player_position(entity);
} }
// Convert Entity Rotation To XYZ // Convert Entity Rotation To XYZ
static Vec3 get_dir(const Entity *entity) { static Vec3 get_dir(const Entity *entity) {
@ -173,31 +209,28 @@ void api_convert_to_mcpi_entity_type(int &type) {
// Convert Entity To String // Convert Entity To String
static std::string get_entity_message(CommandServer *server, Entity *entity) { static std::string get_entity_message(CommandServer *server, Entity *entity) {
// Offset Position std::vector<std::string> pieces;
float x = entity->x; // ID
float y = entity->y - entity->height_offset; pieces.push_back(std::to_string(entity->id));
float z = entity->z; // Type
server->pos_translator.to(x, y, z);
// Fix Type ID
int type = entity->getEntityTypeId(); int type = entity->getEntityTypeId();
if (api_compat_mode) { if (api_compat_mode) {
api_convert_to_rj_entity_type(type); api_convert_to_rj_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));
}
// XYZ
float x = entity->x;
float y = entity->y - entity->height_offset;
float z = entity->z;
server->pos_translator.to(x, y, z);
pieces.push_back(std::to_string(x));
pieces.push_back(std::to_string(y));
pieces.push_back(std::to_string(z));
// Return // Return
return api_join_outputs({ return api_join_outputs(pieces, arg_separator);
// ID
std::to_string(entity->id),
// Type
std::to_string(type),
// Name
api_get_output(misc_get_entity_type_name(entity).second, true),
// X
std::to_string(x),
// Y
std::to_string(y),
// X
std::to_string(z)
}, arg_separator);
} }
// Calculate Distance Between Entities // Calculate Distance Between Entities
@ -223,8 +256,6 @@ static SignTileEntity *get_sign(const CommandServer *server, const int x, const
// Parse API Commands // Parse API Commands
static const std::string player_namespace = "player."; static const std::string player_namespace = "player.";
#define API_WARN(format, ...) WARN("API: %s: " format, cmd.c_str(), ##__VA_ARGS__)
#define ENTITY_NOT_FOUND API_WARN("Entity Not Found: %i", id)
#define next_string(out, required) \ #define next_string(out, required) \
std::string out; \ std::string out; \
if (!std::getline(args, out, arg_separator) && (required)) { \ if (!std::getline(args, out, arg_separator) && (required)) { \
@ -263,6 +294,7 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
// And Now The Big If-Else Chain // And Now The Big If-Else Chain
std::stringstream args(args_str); std::stringstream args(args_str);
if (cmd == "world.getBlocks") { if (cmd == "world.getBlocks") {
// Parse
next_int(x0); next_int(x0);
next_int(y0); next_int(y0);
next_int(z0); next_int(z0);
@ -272,29 +304,34 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
// Get The Blocks // Get The Blocks
return get_blocks(server, Vec3{(float) x0, (float) y0, (float) z0}, Vec3{(float) x1, (float) y1, (float) z1}); return get_blocks(server, Vec3{(float) x0, (float) y0, (float) z0}, Vec3{(float) x1, (float) y1, (float) z1});
} else if (cmd == "world.getPlayerId") { } else if (cmd == "world.getPlayerId") {
// Parse
next_string(input, true); next_string(input, true);
// Search
std::string username = get_input(input); std::string username = get_input(input);
for (Player *player : server->minecraft->level->players) { for (Player *player : server->minecraft->level->players) {
if (misc_get_player_username_utf(player) == username) { if (misc_get_player_username_utf(player) == username) {
// Found
return std::to_string(player->id) + "\n"; return std::to_string(player->id) + "\n";
} }
} }
API_WARN("Player Not Found: %s", username.c_str());
return CommandServer::Fail; return CommandServer::Fail;
} else if (cmd == "entity.getName") { } else if (cmd == "entity.getName") {
// Parse
next_int(id); next_int(id);
// Return
Entity *entity = server->minecraft->level->getEntity(id); Entity *entity = server->minecraft->level->getEntity(id);
if (entity == nullptr) { if (entity == nullptr) {
ENTITY_NOT_FOUND;
return CommandServer::NullString; return CommandServer::NullString;
} else { } else {
return api_get_output(misc_get_entity_name(entity), false) + '\n'; return api_get_output(misc_get_entity_name(entity), false) + '\n';
} }
} else if (cmd == "world.getEntities") { } else if (cmd == "world.getEntities") {
// Parse
next_int(type); next_int(type);
if (api_compat_mode) { if (api_compat_mode) {
api_convert_to_mcpi_entity_type(type); api_convert_to_mcpi_entity_type(type);
} }
// Search
std::vector<std::string> result; std::vector<std::string> result;
for (Entity *entity : server->minecraft->level->entities) { for (Entity *entity : server->minecraft->level->entities) {
int i = entity->getEntityTypeId(); int i = entity->getEntityTypeId();
@ -304,7 +341,9 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
} }
return api_join_outputs(result, list_separator); return api_join_outputs(result, list_separator);
} else if (cmd == "world.removeEntity") { } else if (cmd == "world.removeEntity") {
// Parse
next_int(id); next_int(id);
// Remove
Entity *entity = server->minecraft->level->getEntity(id); Entity *entity = server->minecraft->level->getEntity(id);
int result = 0; int result = 0;
if (entity != nullptr && !entity->isPlayer()) { if (entity != nullptr && !entity->isPlayer()) {
@ -313,10 +352,12 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
} }
return std::to_string(result) + '\n'; return std::to_string(result) + '\n';
} else if (cmd == "world.removeEntities") { } else if (cmd == "world.removeEntities") {
// Parse
next_int(type); next_int(type);
if (api_compat_mode) { if (api_compat_mode) {
api_convert_to_mcpi_entity_type(type); api_convert_to_mcpi_entity_type(type);
} }
// Remove
int removed = 0; int removed = 0;
for (Entity *entity : server->minecraft->level->entities) { for (Entity *entity : server->minecraft->level->entities) {
int i = entity->getEntityTypeId(); int i = entity->getEntityTypeId();
@ -342,61 +383,66 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
next_int(id); next_int(id);
return api_get_projectile_events(server, client, id); return api_get_projectile_events(server, client, id);
} else if (cmd == "entity.setDirection") { } else if (cmd == "entity.setDirection") {
// Parse
next_int(id); next_int(id);
next_float(x); next_float(x);
next_float(y); next_float(y);
next_float(z); next_float(z);
// Set
Entity *entity = server->minecraft->level->getEntity(id); Entity *entity = server->minecraft->level->getEntity(id);
if (entity == nullptr) { if (entity != nullptr) {
ENTITY_NOT_FOUND;
} else {
set_dir(entity, x, y, z); set_dir(entity, x, y, z);
} }
return CommandServer::NullString; return CommandServer::NullString;
} else if (cmd == "entity.getDirection") { } else if (cmd == "entity.getDirection") {
// Parse
next_int(id); next_int(id);
// Get
Entity *entity = server->minecraft->level->getEntity(id); Entity *entity = server->minecraft->level->getEntity(id);
if (entity == nullptr) { if (entity == nullptr) {
ENTITY_NOT_FOUND;
return CommandServer::Fail; return CommandServer::Fail;
} else { } else {
Vec3 vec = get_dir(entity); Vec3 vec = get_dir(entity);
return api_join_outputs({std::to_string(vec.x), std::to_string(vec.y), std::to_string(vec.z)}, arg_separator); return api_join_outputs({std::to_string(vec.x), std::to_string(vec.y), std::to_string(vec.z)}, arg_separator);
} }
} else if (cmd == "entity.setRotation") { } else if (cmd == "entity.setRotation") {
// Parse
next_int(id); next_int(id);
next_float(yaw); next_float(yaw);
// Set
Entity *entity = server->minecraft->level->getEntity(id); Entity *entity = server->minecraft->level->getEntity(id);
if (entity == nullptr) { if (entity != nullptr) {
ENTITY_NOT_FOUND;
} else {
entity->yaw = yaw; entity->yaw = yaw;
update_player_position(entity);
} }
return CommandServer::NullString; return CommandServer::NullString;
} else if (cmd == "entity.setPitch") { } else if (cmd == "entity.setPitch") {
// Parse
next_int(id); next_int(id);
next_float(pitch); next_float(pitch);
// Set
Entity *entity = server->minecraft->level->getEntity(id); Entity *entity = server->minecraft->level->getEntity(id);
if (entity == nullptr) { if (entity != nullptr) {
ENTITY_NOT_FOUND;
} else {
entity->pitch = pitch; entity->pitch = pitch;
update_player_position(entity);
} }
return CommandServer::NullString; return CommandServer::NullString;
} else if (cmd == "entity.getRotation") { } else if (cmd == "entity.getRotation") {
// Parse
next_int(id); next_int(id);
// Get
Entity *entity = server->minecraft->level->getEntity(id); Entity *entity = server->minecraft->level->getEntity(id);
if (entity == nullptr) { if (entity == nullptr) {
ENTITY_NOT_FOUND;
return CommandServer::Fail; return CommandServer::Fail;
} else { } else {
return std::to_string(entity->yaw) + '\n'; return std::to_string(entity->yaw) + '\n';
} }
} else if (cmd == "entity.getPitch") { } else if (cmd == "entity.getPitch") {
// Parse
next_int(id); next_int(id);
// Get
Entity *entity = server->minecraft->level->getEntity(id); Entity *entity = server->minecraft->level->getEntity(id);
if (entity == nullptr) { if (entity == nullptr) {
ENTITY_NOT_FOUND;
return CommandServer::Fail; return CommandServer::Fail;
} else { } else {
return std::to_string(entity->pitch) + '\n'; return std::to_string(entity->pitch) + '\n';
@ -408,7 +454,6 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
next_int(type); next_int(type);
Entity *src = server->minecraft->level->getEntity(id); Entity *src = server->minecraft->level->getEntity(id);
if (src == nullptr) { if (src == nullptr) {
ENTITY_NOT_FOUND;
return CommandServer::Fail; return CommandServer::Fail;
} }
// Run // Run
@ -427,7 +472,6 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
next_int(type); next_int(type);
Entity *src = server->minecraft->level->getEntity(id); Entity *src = server->minecraft->level->getEntity(id);
if (src == nullptr) { if (src == nullptr) {
ENTITY_NOT_FOUND;
return CommandServer::Fail; return CommandServer::Fail;
} }
// Run // Run
@ -508,6 +552,7 @@ sign->lines[i] = get_input(line_##i); \
server->minecraft->level->addEntity(entity); 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
std::vector<std::string> result; std::vector<std::string> result;
for (const std::pair<const EntityType, std::pair<std::string, std::string>> &i : misc_get_entity_type_names()) { 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); int id = static_cast<int>(i.first);
@ -518,25 +563,27 @@ sign->lines[i] = get_input(line_##i); \
} }
return api_join_outputs(result, list_separator); return api_join_outputs(result, list_separator);
} else if (cmd == "entity.setAbsPos") { } else if (cmd == "entity.setAbsPos") {
// Parse
next_int(id); next_int(id);
next_float(x); next_float(x);
next_float(y); next_float(y);
next_float(z); next_float(z);
// Set
Entity *entity = server->minecraft->level->getEntity(id); Entity *entity = server->minecraft->level->getEntity(id);
if (entity == nullptr) { if (entity == nullptr) {
ENTITY_NOT_FOUND;
return CommandServer::Fail; return CommandServer::Fail;
} }
entity->moveTo(x, y, z, entity->yaw, entity->pitch); Entity_moveTo_injection(entity, x, y, z, entity->yaw, entity->pitch);
return CommandServer::NullString; return CommandServer::NullString;
} else if (cmd == "entity.getAbsPos") { } else if (cmd == "entity.getAbsPos") {
// Parse
next_int(id); next_int(id);
// Get
Entity *entity = server->minecraft->level->getEntity(id); Entity *entity = server->minecraft->level->getEntity(id);
if (entity == nullptr) { if (entity == nullptr) {
ENTITY_NOT_FOUND;
return CommandServer::Fail; return CommandServer::Fail;
} }
return api_join_outputs({std::to_string(entity->x), std::to_string(entity->y), std::to_string(entity->z)}, arg_separator); 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") { } else if (cmd == "entity.events.clear") {
next_int(id); next_int(id);
api_clear_events(client, id); api_clear_events(client, id);
@ -561,5 +608,8 @@ void init_api() {
if (feature_has("Implement RaspberryJuice API", server_enabled)) { if (feature_has("Implement RaspberryJuice API", server_enabled)) {
overwrite_calls(CommandServer_parse, CommandServer_parse_injection); overwrite_calls(CommandServer_parse, CommandServer_parse_injection);
_init_api_events(); _init_api_events();
// Fix Teleporting Players
overwrite_calls(ClientSideNetworkHandler_handle_MovePlayerPacket, ClientSideNetworkHandler_handle_MovePlayerPacket_injection);
overwrite_call((void *) 0x6b6e8, Entity_moveTo, Entity_moveTo_injection);
} }
} }

View File

@ -113,13 +113,14 @@ static bool CommandServer__updateClient_injection(CommandServer__updateClient_t
return ret; return ret;
} }
static void CommandServer__close_injection(CommandServer__close_t original, CommandServer *self) { static void CommandServer__close_injection(CommandServer__close_t original, CommandServer *self) {
// Server Shutdown
extra_client_data.clear(); extra_client_data.clear();
original(self); original(self);
} }
// Clear All Events // Clear All Events
void api_clear_events(const ConnectedClient &client) { void api_clear_events(const ConnectedClient &client) {
ExtraClientData &data = extra_client_data[client.sock]; ExtraClientData &data = extra_client_data.at(client.sock);
if (!api_compat_mode) { if (!api_compat_mode) {
// Match RJ Bug // Match RJ Bug
data.projectile_events.clear(); data.projectile_events.clear();
@ -131,12 +132,12 @@ void api_clear_events(const ConnectedClient &client) {
// Clear Events Produced By Given Entity // Clear Events Produced By Given Entity
template <typename T> template <typename T>
static void clear_events(std::vector<T> &data, const int id) { static void clear_events(std::vector<T> &data, const int id) {
std::ranges::remove_if(data, [&id](const T &e) { data.erase(std::remove_if(data.begin(), data.end(), [&id](const T &e) {
return id == e.owner_id; return id == e.owner_id;
}); }), data.end());
} }
void api_clear_events(const ConnectedClient &client, const int id) { void api_clear_events(const ConnectedClient &client, const int id) {
ExtraClientData &data = extra_client_data[client.sock]; ExtraClientData &data = extra_client_data.at(client.sock);
clear_events(data.block_hit_events, id); clear_events(data.block_hit_events, id);
clear_events(data.chat_events, id); clear_events(data.chat_events, id);
clear_events(data.projectile_events, id); clear_events(data.projectile_events, id);
@ -163,7 +164,7 @@ static std::string get_events(CommandServer *server, std::vector<T> &queue, cons
} }
#define create_get_events(name) \ #define create_get_events(name) \
std::string api_get_##name##_events(CommandServer *server, const ConnectedClient &client, const std::optional<int> id) { \ std::string api_get_##name##_events(CommandServer *server, const ConnectedClient &client, const std::optional<int> id) { \
return get_events(server, extra_client_data[client.sock].name##_events, id); \ return get_events(server, extra_client_data.at(client.sock).name##_events, id); \
} }
create_get_events(projectile) create_get_events(projectile)
create_get_events(chat) create_get_events(chat)
@ -270,14 +271,18 @@ static bool CreatorMode_useItemOn_injection(__attribute__((unused)) CreatorMode_
// Init // Init
void _init_api_events() { void _init_api_events() {
enabled = true; enabled = true;
// Track Projectile Hits
overwrite_calls(Arrow_tick, Arrow_tick_injection); overwrite_calls(Arrow_tick, Arrow_tick_injection);
overwrite_call((void *) 0x8b28c, Entity_hurt, Arrow_tick_Entity_hurt_injection); overwrite_call((void *) 0x8b28c, Entity_hurt, Arrow_tick_Entity_hurt_injection);
overwrite_call((void *) 0x8b388, Level_getTile, Arrow_tick_Level_getTile_injection); overwrite_call((void *) 0x8b388, Level_getTile, Arrow_tick_Level_getTile_injection);
overwrite_call((void *) 0x8c5a4, Throwable_onHit, Throwable_tick_Throwable_onHit_injection); overwrite_call((void *) 0x8c5a4, Throwable_onHit, Throwable_tick_Throwable_onHit_injection);
// Track GUI Messages
overwrite_calls(Gui_addMessage, Gui_addMessage_injection); overwrite_calls(Gui_addMessage, Gui_addMessage_injection);
// Track Connected Clients
overwrite_call((void *) 0x6bd78, CommandServer_setSocketBlocking, CommandServer__updateAccept_setSocketBlocking_injection); overwrite_call((void *) 0x6bd78, CommandServer_setSocketBlocking, CommandServer__updateAccept_setSocketBlocking_injection);
overwrite_calls(CommandServer__updateClient, CommandServer__updateClient_injection); overwrite_calls(CommandServer__updateClient, CommandServer__updateClient_injection);
overwrite_calls(CommandServer__close, CommandServer__close_injection); overwrite_calls(CommandServer__close, CommandServer__close_injection);
// Track Block Hits
overwrite_calls(GameMode_useItemOn, GameMode_useItemOn_injection); overwrite_calls(GameMode_useItemOn, GameMode_useItemOn_injection);
overwrite_calls(CreatorMode_useItemOn, CreatorMode_useItemOn_injection); overwrite_calls(CreatorMode_useItemOn, CreatorMode_useItemOn_injection);
} }

View File

@ -374,11 +374,12 @@ static void LocalPlayer_tick_injection(LocalPlayer_tick_t original, LocalPlayer
if (real != synced) { if (real != synced) {
// Send To Server // Send To Server
PlayerActionPacket *packet = PlayerActionPacket::allocate(); PlayerActionPacket *packet = PlayerActionPacket::allocate();
Packet_constructor->get(false)((Packet *) packet); ((Packet *) packet)->constructor();
packet->vtable = PlayerActionPacket_vtable::base; packet->vtable = PlayerActionPacket_vtable::base;
packet->entity_id = self->id; packet->entity_id = self->id;
packet->action = real ? PLAYER_ACTION_START_SNEAKING : PLAYER_ACTION_STOP_SNEAKING; packet->action = real ? PLAYER_ACTION_START_SNEAKING : PLAYER_ACTION_STOP_SNEAKING;
self->minecraft->rak_net_instance->send(*(Packet *) packet); self->minecraft->rak_net_instance->send(*(Packet *) packet);
packet->destructor_deleting();
} }
} }
} }

View File

@ -27,6 +27,7 @@ set(SRC
src/network/raknet/RakNet_RakPeer.def src/network/raknet/RakNet_RakPeer.def
src/network/raknet/RakNet_BitStream.def src/network/raknet/RakNet_BitStream.def
src/network/ServerSideNetworkHandler.def src/network/ServerSideNetworkHandler.def
src/network/ClientSideNetworkHandler.def
src/network/packet/LoginPacket.def src/network/packet/LoginPacket.def
src/network/packet/PlayerEquipmentPacket.def src/network/packet/PlayerEquipmentPacket.def
src/network/packet/SignUpdatePacket.def src/network/packet/SignUpdatePacket.def
@ -34,6 +35,7 @@ set(SRC
src/network/packet/StartGamePacket.def src/network/packet/StartGamePacket.def
src/network/packet/ChatPacket.def src/network/packet/ChatPacket.def
src/network/packet/PlayerActionPacket.def src/network/packet/PlayerActionPacket.def
src/network/packet/MovePlayerPacket.def
src/entity/EntityFactory.def src/entity/EntityFactory.def
src/entity/PrimedTnt.def src/entity/PrimedTnt.def
src/entity/CameraEntity.def src/entity/CameraEntity.def

View File

@ -0,0 +1,6 @@
extends NetEventCallback;
vtable 0x108eb8;
property Minecraft *minecraft = 0x4;
property Level *level = 0x8;

View File

@ -6,3 +6,4 @@ virtual-method void onDisconnect(const RakNet_RakNetGUID &guid) = 0x18;
virtual-method void handle_SignUpdatePacket(const RakNet_RakNetGUID &guid, SignUpdatePacket *packet) = 0xcc; virtual-method void handle_SignUpdatePacket(const RakNet_RakNetGUID &guid, SignUpdatePacket *packet) = 0xcc;
virtual-method void handle_ChatPacket(const RakNet_RakNetGUID &rak_net_guid, ChatPacket *packet) = 0xc8; virtual-method void handle_ChatPacket(const RakNet_RakNetGUID &rak_net_guid, ChatPacket *packet) = 0xc8;
virtual-method void handle_PlayerActionPacket(const RakNet_RakNetGUID &rak_net_guid, PlayerActionPacket *packet) = 0xa0; virtual-method void handle_PlayerActionPacket(const RakNet_RakNetGUID &rak_net_guid, PlayerActionPacket *packet) = 0xa0;
virtual-method void handle_MovePlayerPacket(const RakNet_RakNetGUID &rak_net_guid, MovePlayerPacket *packet) = 0x58;

View File

@ -0,0 +1,11 @@
extends Packet;
size 0x24;
vtable 0x105e50;
property int entity_id = 0xc;
property float x = 0x10;
property float y = 0x14;
property float z = 0x18;
property float pitch = 0x1c;
property float yaw = 0x20;