2024-04-02 19:22:01 -04:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <cmath>
|
2020-12-02 18:18:49 -05:00
|
|
|
#include <string>
|
|
|
|
#include <fstream>
|
|
|
|
#include <streambuf>
|
|
|
|
|
2024-04-02 19:22:01 -04:00
|
|
|
#include <GLES/gl.h>
|
2024-08-25 17:06:12 -04:00
|
|
|
#include <SDL/SDL.h>
|
|
|
|
#include <media-layer/core.h>
|
2020-12-02 18:18:49 -05:00
|
|
|
|
2021-01-27 16:26:19 -05:00
|
|
|
#include <libreborn/libreborn.h>
|
2021-09-11 23:18:12 -04:00
|
|
|
#include <symbols/minecraft.h>
|
2020-12-02 18:18:49 -05:00
|
|
|
|
2024-04-02 19:22:01 -04:00
|
|
|
#include <mods/init/init.h>
|
2022-06-25 17:30:08 -04:00
|
|
|
#include <mods/feature/feature.h>
|
2024-06-21 01:19:37 -04:00
|
|
|
#include <mods/input/input.h>
|
2022-06-25 17:30:08 -04:00
|
|
|
#include <mods/misc/misc.h>
|
2020-12-02 18:18:49 -05:00
|
|
|
|
2024-06-21 01:19:37 -04:00
|
|
|
#include "misc-internal.h"
|
|
|
|
|
2024-04-02 19:22:01 -04:00
|
|
|
// Sanitize Username
|
|
|
|
#define MAX_USERNAME_LENGTH 16
|
2024-04-03 03:19:12 -04:00
|
|
|
static void LoginPacket_read_injection(LoginPacket_read_t original, LoginPacket *packet, RakNet_BitStream *bit_stream) {
|
2024-04-02 19:22:01 -04:00
|
|
|
// Call Original Method
|
2024-04-03 03:19:12 -04:00
|
|
|
original(packet, bit_stream);
|
2024-04-02 19:22:01 -04:00
|
|
|
|
|
|
|
// Prepare
|
|
|
|
RakNet_RakString *rak_string = &packet->username;
|
|
|
|
// Get Original Username
|
2024-08-25 17:06:12 -04:00
|
|
|
const RakNet_RakString_SharedString *shared_string = rak_string->sharedString;
|
|
|
|
const char *c_str = shared_string->c_str;
|
2024-04-02 19:22:01 -04:00
|
|
|
// Sanitize
|
|
|
|
char *new_username = strdup(c_str);
|
|
|
|
ALLOC_CHECK(new_username);
|
2024-06-16 00:47:36 -04:00
|
|
|
sanitize_string(new_username, MAX_USERNAME_LENGTH, 0);
|
2024-04-02 19:22:01 -04:00
|
|
|
// Set New Username
|
2024-05-15 05:02:19 -04:00
|
|
|
rak_string->Assign(new_username);
|
2024-04-02 19:22:01 -04:00
|
|
|
// Free
|
|
|
|
free(new_username);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix RakNet::RakString Security Bug
|
|
|
|
//
|
|
|
|
// RakNet::RakString's format constructor is often given unsanitized user input and is never used for formatting,
|
|
|
|
// this is a massive security risk, allowing clients to run arbitrary format specifiers, this disables the
|
|
|
|
// formatting functionality.
|
2024-07-14 05:06:27 -04:00
|
|
|
RakNet_RakString_constructor_t RakNet_RakString_constructor = (RakNet_RakString_constructor_t) 0xea5cc;
|
2024-04-02 19:22:01 -04:00
|
|
|
static RakNet_RakString *RakNet_RakString_injection(RakNet_RakString *rak_string, const char *format, ...) {
|
|
|
|
// Call Original Method
|
2024-05-15 05:08:39 -04:00
|
|
|
return RakNet_RakString_constructor(rak_string, "%s", format);
|
2024-04-02 19:22:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Print Error Message If RakNet Startup Fails
|
|
|
|
static const char *RAKNET_ERROR_NAMES[] = {
|
|
|
|
"Success",
|
|
|
|
"Already Started",
|
|
|
|
"Invalid Socket Descriptors",
|
|
|
|
"Invalid Max Connections",
|
|
|
|
"Socket Family Not Supported",
|
|
|
|
"Part Already In Use",
|
|
|
|
"Failed To Bind Port",
|
|
|
|
"Failed Test Send",
|
|
|
|
"Port Cannot Be 0",
|
|
|
|
"Failed To Create Network Thread",
|
|
|
|
"Unknown"
|
|
|
|
};
|
|
|
|
static RakNet_StartupResult RakNetInstance_host_RakNet_RakPeer_Startup_injection(RakNet_RakPeer *rak_peer, unsigned short maxConnections, unsigned char *socketDescriptors, uint32_t socketDescriptorCount, int32_t threadPriority) {
|
|
|
|
// Call Original Method
|
2024-08-25 17:06:12 -04:00
|
|
|
const RakNet_StartupResult result = rak_peer->Startup(maxConnections, socketDescriptors, socketDescriptorCount, threadPriority);
|
2024-04-02 19:22:01 -04:00
|
|
|
|
|
|
|
// Print Error
|
|
|
|
if (result != RAKNET_STARTED) {
|
2024-06-15 08:52:15 -04:00
|
|
|
CONDITIONAL_ERR(reborn_is_server(), "Failed To Start RakNet: %s", RAKNET_ERROR_NAMES[result]);
|
2024-04-02 19:22:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix Furnace Not Checking Item Auxiliary When Inserting New Item
|
2024-07-15 03:05:05 -04:00
|
|
|
static int32_t FurnaceScreen_handleAddItem_injection(FurnaceScreen_handleAddItem_t original, FurnaceScreen *furnace_screen, int32_t slot, const ItemInstance *item) {
|
2024-04-02 19:22:01 -04:00
|
|
|
// Get Existing Item
|
|
|
|
FurnaceTileEntity *tile_entity = furnace_screen->tile_entity;
|
2024-08-25 17:06:12 -04:00
|
|
|
const ItemInstance *existing_item = tile_entity->getItem(slot);
|
2024-04-02 19:22:01 -04:00
|
|
|
|
|
|
|
// Check Item
|
|
|
|
int valid;
|
|
|
|
if (item->id == existing_item->id && item->auxiliary == existing_item->auxiliary) {
|
|
|
|
// Item Matches, Is Valid
|
|
|
|
valid = 1;
|
|
|
|
} else {
|
|
|
|
// Item Doesn't Match, Check If Existing Item Is Empty
|
|
|
|
if ((existing_item->id | existing_item->count | existing_item->auxiliary) == 0) {
|
|
|
|
// Existing Item Is Empty, Is Valid
|
|
|
|
valid = 1;
|
|
|
|
} else {
|
|
|
|
// Existing Item Isn't Empty, Isn't Valid
|
|
|
|
valid = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call Original Method
|
|
|
|
if (valid) {
|
|
|
|
// Valid
|
2024-04-03 03:19:12 -04:00
|
|
|
return original(furnace_screen, slot, item);
|
2024-04-02 19:22:01 -04:00
|
|
|
} else {
|
|
|
|
// Invalid
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get Real Selected Slot
|
|
|
|
int32_t misc_get_real_selected_slot(Player *player) {
|
|
|
|
// Get Selected Slot
|
2024-08-25 17:06:12 -04:00
|
|
|
const Inventory *inventory = player->inventory;
|
2024-04-02 19:22:01 -04:00
|
|
|
int32_t selected_slot = inventory->selectedSlot;
|
|
|
|
|
|
|
|
// Linked Slots
|
2024-08-25 17:06:12 -04:00
|
|
|
const int32_t linked_slots_length = inventory->linked_slots_length;
|
2024-04-02 19:22:01 -04:00
|
|
|
if (selected_slot < linked_slots_length) {
|
2024-08-25 17:06:12 -04:00
|
|
|
const int32_t *linked_slots = inventory->linked_slots;
|
2024-04-02 19:22:01 -04:00
|
|
|
selected_slot = linked_slots[selected_slot];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return
|
|
|
|
return selected_slot;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Custom API Port
|
|
|
|
HOOK(bind, int, (int sockfd, const struct sockaddr *addr, socklen_t addrlen)) {
|
|
|
|
const sockaddr *new_addr = addr;
|
|
|
|
sockaddr_in in_addr = {};
|
|
|
|
if (addr->sa_family == AF_INET) {
|
2024-08-25 17:06:12 -04:00
|
|
|
in_addr = *(const sockaddr_in *) new_addr;
|
2024-04-02 19:22:01 -04:00
|
|
|
if (in_addr.sin_port == ntohs(4711)) {
|
2024-06-17 18:09:30 -04:00
|
|
|
const char *new_port_str = getenv(MCPI_API_PORT_ENV);
|
2024-04-02 19:22:01 -04:00
|
|
|
long int new_port;
|
|
|
|
if (new_port_str != nullptr && (new_port = strtol(new_port_str, nullptr, 0)) != 0L) {
|
|
|
|
in_addr.sin_port = htons(new_port);
|
|
|
|
}
|
|
|
|
}
|
2024-08-25 17:06:12 -04:00
|
|
|
new_addr = (const sockaddr *) &in_addr;
|
2024-04-02 19:22:01 -04:00
|
|
|
}
|
|
|
|
ensure_bind();
|
|
|
|
return real_bind(sockfd, new_addr, addrlen);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate Caves
|
2024-04-03 03:19:12 -04:00
|
|
|
static void RandomLevelSource_buildSurface_injection(RandomLevelSource_buildSurface_t original, RandomLevelSource *random_level_source, int32_t chunk_x, int32_t chunk_y, unsigned char *chunk_data, Biome **biomes) {
|
2024-04-02 19:22:01 -04:00
|
|
|
// Call Original Method
|
2024-04-03 03:19:12 -04:00
|
|
|
original(random_level_source, chunk_x, chunk_y, chunk_data, biomes);
|
2024-04-02 19:22:01 -04:00
|
|
|
|
|
|
|
// Get Level
|
|
|
|
Level *level = random_level_source->level;
|
|
|
|
|
|
|
|
// Get Cave Feature
|
|
|
|
LargeCaveFeature *cave_feature = &random_level_source->cave_feature;
|
|
|
|
|
|
|
|
// Generate
|
2024-05-15 05:02:19 -04:00
|
|
|
cave_feature->apply((ChunkSource *) random_level_source, level, chunk_x, chunk_y, chunk_data, 0);
|
2024-04-02 19:22:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Disable Hostile AI In Creative Mode
|
|
|
|
static Entity *PathfinderMob_findAttackTarget_injection(PathfinderMob *mob) {
|
|
|
|
// Call Original Method
|
2024-05-15 05:02:19 -04:00
|
|
|
Entity *target = mob->findAttackTarget();
|
2024-04-02 19:22:01 -04:00
|
|
|
|
|
|
|
// Only modify the AI of monsters
|
2024-05-15 05:02:19 -04:00
|
|
|
if (mob->getCreatureBaseType() != 1) {
|
2024-04-02 19:22:01 -04:00
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check If Creative Mode
|
2024-05-15 05:02:19 -04:00
|
|
|
if (target != nullptr && target->isPlayer()) {
|
2024-08-25 17:06:12 -04:00
|
|
|
const Player *player = (Player *) target;
|
|
|
|
const Inventory *inventory = player->inventory;
|
|
|
|
const bool is_creative = inventory->is_creative;
|
2024-04-02 19:22:01 -04:00
|
|
|
if (is_creative) {
|
|
|
|
target = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix used items transferring durability
|
|
|
|
static int selected_slot = -1;
|
2024-08-25 17:06:12 -04:00
|
|
|
static void Player_startUsingItem_injection(Player_startUsingItem_t original, Player *self, ItemInstance *item_instance, const int time) {
|
2024-04-02 19:22:01 -04:00
|
|
|
selected_slot = self->inventory->selectedSlot;
|
2024-04-03 03:19:12 -04:00
|
|
|
original(self, item_instance, time);
|
2024-04-02 19:22:01 -04:00
|
|
|
}
|
2024-04-03 03:19:12 -04:00
|
|
|
static void Player_stopUsingItem_injection(Player_stopUsingItem_t original, Player *self) {
|
2024-04-02 19:22:01 -04:00
|
|
|
if (selected_slot != self->inventory->selectedSlot) {
|
|
|
|
self->itemBeingUsed.id = 0;
|
|
|
|
}
|
2024-04-03 03:19:12 -04:00
|
|
|
original(self);
|
2024-04-02 19:22:01 -04:00
|
|
|
}
|
|
|
|
|
2020-12-02 18:18:49 -05:00
|
|
|
// Read Asset File
|
2024-07-15 03:05:05 -04:00
|
|
|
static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injection(__attribute__((unused)) AppPlatform_readAssetFile_t original, __attribute__((unused)) AppPlatform *app_platform, const std::string &path) {
|
2023-11-11 00:44:26 -05:00
|
|
|
// Open File
|
2024-07-15 03:05:05 -04:00
|
|
|
std::ifstream stream("data/" + path, std::ios_base::binary | std::ios_base::ate);
|
2023-11-11 00:44:26 -05:00
|
|
|
if (!stream) {
|
|
|
|
// Does Not Exist
|
|
|
|
AppPlatform_readAssetFile_return_value ret;
|
|
|
|
ret.length = -1;
|
2024-04-02 19:22:01 -04:00
|
|
|
ret.data = nullptr;
|
2023-11-11 00:44:26 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
// Read File
|
2024-04-02 19:22:01 -04:00
|
|
|
std::streamoff len = stream.tellg();
|
2023-09-24 23:06:23 -04:00
|
|
|
char *buf = new char[len];
|
2024-04-02 19:22:01 -04:00
|
|
|
ALLOC_CHECK(buf);
|
|
|
|
stream.seekg(0, std::ifstream::beg);
|
2023-09-24 23:06:23 -04:00
|
|
|
stream.read(buf, len);
|
2023-11-11 00:44:26 -05:00
|
|
|
stream.close();
|
2020-12-04 12:17:51 -05:00
|
|
|
// Return String
|
|
|
|
AppPlatform_readAssetFile_return_value ret;
|
2024-08-25 17:06:12 -04:00
|
|
|
ret.length = int(len);
|
2023-09-24 23:07:30 -04:00
|
|
|
ret.data = strdup(buf);
|
2020-12-04 12:17:51 -05:00
|
|
|
return ret;
|
2020-12-02 18:18:49 -05:00
|
|
|
}
|
|
|
|
|
2024-02-07 06:47:46 +00:00
|
|
|
// Implement crafting remainders
|
2024-07-17 03:44:41 -04:00
|
|
|
static void PaneCraftingScreen_craftSelectedItem_PaneCraftingScreen_recheckRecipes_injection(PaneCraftingScreen *self) {
|
2024-02-07 06:47:46 +00:00
|
|
|
// Check for crafting remainders
|
2024-08-25 17:06:12 -04:00
|
|
|
const CItem *item = self->item;
|
2024-02-07 06:47:46 +00:00
|
|
|
for (size_t i = 0; i < item->ingredients.size(); i++) {
|
|
|
|
ItemInstance requested_item_instance = item->ingredients[i].requested_item;
|
2024-05-17 02:52:55 -04:00
|
|
|
Item *requested_item = Item::items[requested_item_instance.id];
|
2024-05-15 05:02:19 -04:00
|
|
|
ItemInstance *craftingRemainingItem = requested_item->getCraftingRemainingItem(&requested_item_instance);
|
2024-04-02 19:22:01 -04:00
|
|
|
if (craftingRemainingItem != nullptr) {
|
2024-02-07 06:47:46 +00:00
|
|
|
// Add or drop remainder
|
|
|
|
LocalPlayer *player = self->minecraft->player;
|
2024-05-15 05:02:19 -04:00
|
|
|
if (!player->inventory->add(craftingRemainingItem)) {
|
2024-02-07 06:47:46 +00:00
|
|
|
// Drop
|
2024-05-15 05:02:19 -04:00
|
|
|
player->drop(craftingRemainingItem, false);
|
2024-02-07 06:47:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Call Original Method
|
2024-05-15 05:02:19 -04:00
|
|
|
self->recheckRecipes();
|
2024-02-07 06:47:46 +00:00
|
|
|
}
|
2024-08-25 17:06:12 -04:00
|
|
|
static ItemInstance *Item_getCraftingRemainingItem_injection(__attribute__((unused)) Item_getCraftingRemainingItem_t original, const Item *self, const ItemInstance *item_instance) {
|
2024-04-02 19:22:01 -04:00
|
|
|
if (self->craftingRemainingItem != nullptr) {
|
2024-05-17 00:36:28 -04:00
|
|
|
ItemInstance *ret = new ItemInstance;
|
2024-02-07 06:47:46 +00:00
|
|
|
ret->id = self->craftingRemainingItem->id;
|
|
|
|
ret->count = item_instance->count;
|
|
|
|
ret->auxiliary = 0;
|
|
|
|
return ret;
|
|
|
|
}
|
2024-04-02 19:22:01 -04:00
|
|
|
return nullptr;
|
2024-02-07 06:47:46 +00:00
|
|
|
}
|
|
|
|
|
2024-02-11 20:35:41 -05:00
|
|
|
// Display Date In Select World Screen
|
2024-08-25 17:06:12 -04:00
|
|
|
static std::string AppPlatform_linux_getDateString_injection(__attribute__((unused)) AppPlatform_linux *app_platform, const int time) {
|
2024-02-11 20:35:41 -05:00
|
|
|
// From https://github.com/ReMinecraftPE/mcpe/blob/56e51027b1c2e67fe5a0e8a091cefe51d4d11926/platforms/sdl/base/AppPlatform_sdl_base.cpp#L68-L84
|
2024-07-10 23:15:58 -04:00
|
|
|
const time_t tt = time;
|
2024-04-02 19:22:01 -04:00
|
|
|
tm t = {};
|
2024-02-11 20:35:41 -05:00
|
|
|
gmtime_r(&tt, &t);
|
|
|
|
char buf[2048];
|
|
|
|
strftime(buf, sizeof buf, "%b %d %Y %H:%M:%S", &t);
|
|
|
|
return std::string(buf);
|
|
|
|
}
|
|
|
|
|
2024-07-17 03:44:41 -04:00
|
|
|
// Missing Strings
|
|
|
|
static void add_missing_string(const std::string &key, const std::string &value) {
|
|
|
|
if (!I18n::_strings.contains(key)) {
|
|
|
|
I18n::_strings[key] = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void Language_injection() {
|
|
|
|
// Fix Language Strings
|
|
|
|
add_missing_string("tile.waterStill.name", "Still Water");
|
|
|
|
add_missing_string("tile.lavaStill.name", "Still Lava");
|
|
|
|
add_missing_string("tile.grassCarried.name", "Carried Grass");
|
|
|
|
add_missing_string("tile.leavesCarried.name", "Carried Leaves");
|
|
|
|
add_missing_string("tile.invBedrock.name", "Invisible Bedrock");
|
|
|
|
// Missing Language Strings
|
|
|
|
add_missing_string("item.camera.name", "Camera");
|
|
|
|
add_missing_string("item.seedsMelon.name", "Melon Seeds");
|
|
|
|
add_missing_string("tile.pumpkinStem.name", "Pumpkin Stem");
|
|
|
|
add_missing_string("tile.stoneSlab.name", "Double Stone Slab");
|
|
|
|
}
|
|
|
|
// Invisible Bedrock
|
|
|
|
static Tile *Tile_initTiles_Tile_init_invBedrock_injection(Tile *t) {
|
|
|
|
Tile *ret = t->init();
|
|
|
|
t->setDescriptionId("invBedrock");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
// Append "Still" Suffix To Liquid Description Keys
|
|
|
|
static std::string *Tile_initTiles_std_string_constructor(std::string *self, const char *from, const std::string::allocator_type &alloc) {
|
|
|
|
new (self) std::string(from, alloc);
|
|
|
|
self->append("Still");
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix Pigmen Burning In The Sun
|
2024-08-24 00:30:06 -04:00
|
|
|
static bool fix_pigmen_burning = false;
|
2024-07-17 03:44:41 -04:00
|
|
|
static float Zombie_aiStep_getBrightness_injection(Entity *self, float param_1) {
|
2024-08-24 00:30:06 -04:00
|
|
|
if (fix_pigmen_burning && self->getEntityTypeId() == 36) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return self->getBrightness(param_1);
|
|
|
|
}
|
2024-07-17 03:44:41 -04:00
|
|
|
}
|
|
|
|
|
2024-08-22 23:43:32 -04:00
|
|
|
// Fix Door Item Dropping
|
|
|
|
static void DoorTile_neighborChanged_Tile_spawnResources_injection(DoorTile *self, Level *level, int x, int y, int z, int data2, __attribute__((unused)) float chance) {
|
|
|
|
self->spawnResources(level, x, y, z, data2, 1);
|
|
|
|
}
|
|
|
|
|
2024-08-23 05:18:20 -04:00
|
|
|
// Fix Cobweb Lighting
|
|
|
|
static Tile *Tile_initTiles_WebTile_setLightBlock_injection(Tile *self, __attribute__((unused)) int strength) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2024-08-24 00:30:06 -04:00
|
|
|
// Fix Fire Immunity
|
|
|
|
static void Mob_baseTick_injection_fire_immunity(Mob_baseTick_t original, Mob *self) {
|
|
|
|
// Fix Fire Timer
|
|
|
|
if (self->fire_immune) {
|
|
|
|
self->fire_timer = 0;
|
|
|
|
}
|
|
|
|
// Call Original Method
|
|
|
|
original(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix Fire Syncing
|
|
|
|
#define FLAG_ONFIRE 0
|
|
|
|
static void Mob_baseTick_injection_fire_syncing(Mob_baseTick_t original, Mob *self) {
|
|
|
|
// Fix Fire Timer
|
|
|
|
if (self->level->is_client_side) {
|
|
|
|
self->fire_timer = 0;
|
|
|
|
}
|
|
|
|
// Call Original Method
|
|
|
|
original(self);
|
|
|
|
// Sync Data
|
|
|
|
if (!self->level->is_client_side) {
|
|
|
|
self->setSharedFlag(FLAG_ONFIRE, self->fire_timer > 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static bool Entity_isOnFire_injection(Entity_isOnFire_t original, Entity *self) {
|
|
|
|
// Call Original Method
|
|
|
|
bool ret = original(self);
|
|
|
|
|
|
|
|
// Check Shared Data
|
|
|
|
bool shared_data = false;
|
|
|
|
if (self->isMob()) {
|
|
|
|
shared_data = ((Mob *) self)->getSharedFlag(FLAG_ONFIRE);
|
|
|
|
}
|
|
|
|
if (shared_data) {
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix Sneaking Syncing
|
|
|
|
#define FLAG_SNEAKING 1
|
|
|
|
#define PLAYER_ACTION_STOP_SNEAKING 100
|
|
|
|
#define PLAYER_ACTION_START_SNEAKING 101
|
|
|
|
static void LocalPlayer_tick_injection(LocalPlayer_tick_t original, LocalPlayer *self) {
|
|
|
|
// Call Original Method
|
|
|
|
original(self);
|
|
|
|
// Sync Data
|
|
|
|
if (!self->level->is_client_side) {
|
|
|
|
self->setSharedFlag(FLAG_SNEAKING, self->isSneaking());
|
|
|
|
} else {
|
|
|
|
const bool real = self->isSneaking();
|
|
|
|
const bool synced = self->getSharedFlag(FLAG_SNEAKING);
|
|
|
|
if (real != synced) {
|
|
|
|
// Send To Server
|
|
|
|
PlayerActionPacket *packet = new PlayerActionPacket;
|
|
|
|
Packet_constructor->get(false)((Packet *) packet);
|
|
|
|
packet->vtable = PlayerActionPacket_vtable_base;
|
|
|
|
packet->entity_id = self->id;
|
|
|
|
packet->action = real ? PLAYER_ACTION_START_SNEAKING : PLAYER_ACTION_STOP_SNEAKING;
|
|
|
|
self->minecraft->rak_net_instance->send(*(Packet *) packet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void ServerSideNetworkHandler_handle_PlayerActionPacket_injection(ServerSideNetworkHandler_handle_PlayerActionPacket_t original, ServerSideNetworkHandler *self, const RakNet_RakNetGUID &rak_net_guid, PlayerActionPacket *packet) {
|
|
|
|
// Call Original Method
|
|
|
|
original(self, rak_net_guid, packet);
|
|
|
|
|
|
|
|
// Handle Sneaking
|
|
|
|
const bool is_sneaking = packet->action == PLAYER_ACTION_START_SNEAKING;
|
|
|
|
if (self->level != nullptr && (is_sneaking || packet->action == PLAYER_ACTION_STOP_SNEAKING)) {
|
|
|
|
Entity *entity = self->level->getEntity(packet->entity_id);
|
|
|
|
if (entity != nullptr && entity->isPlayer()) {
|
|
|
|
((Player *) entity)->setSharedFlag(FLAG_SNEAKING, is_sneaking);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make Mobs Actually Catch On Fire
|
|
|
|
static void set_on_fire(Mob *mob, const int seconds) {
|
|
|
|
const int value = seconds * 20;
|
|
|
|
if (value > mob->fire_timer) {
|
|
|
|
mob->fire_timer = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template <typename Self>
|
|
|
|
static void Monster_aiStep_injection(__attribute__((unused)) std::function<void(Self *)> original, Self *self) {
|
|
|
|
// Fire!
|
|
|
|
Level *level = self->level;
|
|
|
|
if (level->isDay() && !level->is_client_side) {
|
|
|
|
const float brightness = Zombie_aiStep_getBrightness_injection((Entity *) self, 1);
|
|
|
|
if (brightness > 0.5f) {
|
|
|
|
Random *random = &self->random;
|
|
|
|
if (level->canSeeSky(Mth::floor(self->x), Mth::floor(self->y), Mth::floor(self->z)) && random->nextFloat() * 3.5f < (brightness - 0.4f)) {
|
|
|
|
set_on_fire((Mob *) self, 8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call Parent Method
|
|
|
|
Monster_aiStep->get(false)((Monster *) self);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear Fire For Creative Players
|
|
|
|
static void Player_tick_injection(Player_tick_t original, Player *self) {
|
|
|
|
// Fix Value
|
|
|
|
if (self->inventory->is_creative && !self->level->is_client_side && self->isOnFire()) {
|
|
|
|
self->fire_timer = 0;
|
|
|
|
}
|
|
|
|
// Call Original Method
|
|
|
|
original(self);
|
|
|
|
}
|
|
|
|
|
2021-06-21 21:50:26 -04:00
|
|
|
// Init
|
2024-04-02 19:22:01 -04:00
|
|
|
void init_misc() {
|
|
|
|
// Sanitize Username
|
2024-08-25 17:06:12 -04:00
|
|
|
if (feature_has("Sanitize Usernames", server_enabled)) {
|
|
|
|
overwrite_calls(LoginPacket_read, LoginPacket_read_injection);
|
|
|
|
}
|
2024-04-02 19:22:01 -04:00
|
|
|
|
|
|
|
// Fix RakNet::RakString Security Bug
|
2024-08-25 17:06:12 -04:00
|
|
|
if (feature_has("Patch RakNet Security Bug", server_enabled)) {
|
|
|
|
overwrite_calls_manual((void *) RakNet_RakString_constructor, (void *) RakNet_RakString_injection);
|
|
|
|
}
|
2024-04-02 19:22:01 -04:00
|
|
|
|
|
|
|
// Print Error Message If RakNet Startup Fails
|
2024-08-25 17:06:12 -04:00
|
|
|
if (feature_has("Log RakNet Startup Errors", server_enabled)) {
|
|
|
|
overwrite_call((void *) 0x73778, (void *) RakNetInstance_host_RakNet_RakPeer_Startup_injection);
|
|
|
|
}
|
2024-04-02 19:22:01 -04:00
|
|
|
|
|
|
|
// Fix Furnace Not Checking Item Auxiliary When Inserting New Item
|
|
|
|
if (feature_has("Fix Furnace Not Checking Item Auxiliary", server_disabled)) {
|
2024-04-03 03:19:12 -04:00
|
|
|
overwrite_calls(FurnaceScreen_handleAddItem, FurnaceScreen_handleAddItem_injection);
|
2024-04-02 19:22:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Disable Speed Bridging
|
|
|
|
if (feature_has("Disable Speed Bridging", server_disabled)) {
|
|
|
|
unsigned char disable_speed_bridging_patch[4] = {0x03, 0x00, 0x53, 0xe1}; // "cmp r3, r3"
|
|
|
|
patch((void *) 0x494b4, disable_speed_bridging_patch);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disable Creative Mode Mining Delay
|
|
|
|
if (feature_has("Disable Creative Mode Mining Delay", server_disabled)) {
|
|
|
|
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
|
|
|
patch((void *) 0x19fa0, nop_patch);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate Caves
|
|
|
|
if (feature_has("Generate Caves", server_auto)) {
|
2024-04-03 03:19:12 -04:00
|
|
|
overwrite_calls(RandomLevelSource_buildSurface, RandomLevelSource_buildSurface_injection);
|
2024-04-02 19:22:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Disable Hostile AI In Creative Mode
|
|
|
|
if (feature_has("Disable Hostile AI In Creative Mode", server_enabled)) {
|
|
|
|
overwrite_call((void *) 0x83b8c, (void *) PathfinderMob_findAttackTarget_injection);
|
|
|
|
}
|
|
|
|
|
2024-08-25 17:06:12 -04:00
|
|
|
// Send The Full Level, Not Only Changed Chunks
|
2024-04-02 19:22:01 -04:00
|
|
|
if (feature_has("Send Full Level When Hosting Game", server_enabled)) {
|
|
|
|
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
|
|
|
patch((void *) 0x717c4, nop_patch);
|
|
|
|
unsigned char mov_r3_ff[4] = {0xff, 0x30, 0xa0, 0xe3}; // "mov r3, #0xff"
|
|
|
|
patch((void *) 0x7178c, mov_r3_ff);
|
|
|
|
}
|
|
|
|
|
2024-08-25 17:06:12 -04:00
|
|
|
// Fix Used Items Transferring Durability
|
|
|
|
if (feature_has("Fix Transferring Durability When Using Items", server_disabled)) {
|
|
|
|
overwrite_calls(Player_startUsingItem, Player_startUsingItem_injection);
|
|
|
|
overwrite_calls(Player_stopUsingItem, Player_stopUsingItem_injection);
|
2024-04-02 19:22:01 -04:00
|
|
|
}
|
|
|
|
|
2020-12-02 18:18:49 -05:00
|
|
|
// Implement AppPlatform::readAssetFile So Translations Work
|
2022-04-09 20:01:16 -04:00
|
|
|
if (feature_has("Load Language Files", server_enabled)) {
|
2024-05-24 04:44:53 -04:00
|
|
|
overwrite_calls(AppPlatform_readAssetFile, AppPlatform_readAssetFile_injection);
|
2021-07-04 19:02:45 -04:00
|
|
|
}
|
2020-12-02 18:18:49 -05:00
|
|
|
|
2024-02-11 20:35:41 -05:00
|
|
|
// Implement Crafting Remainders
|
2024-07-17 03:44:41 -04:00
|
|
|
if (feature_has("Implement Crafting Remainders", server_enabled)) {
|
|
|
|
overwrite_call((void *) 0x2e230, (void *) PaneCraftingScreen_craftSelectedItem_PaneCraftingScreen_recheckRecipes_injection);
|
|
|
|
overwrite_calls(Item_getCraftingRemainingItem, Item_getCraftingRemainingItem_injection);
|
|
|
|
}
|
2024-02-08 00:34:43 -05:00
|
|
|
|
2024-02-11 20:35:41 -05:00
|
|
|
// Display Date In Select World Screen
|
|
|
|
if (feature_has("Display Date In Select World Screen", server_disabled)) {
|
2024-05-04 20:46:15 -04:00
|
|
|
patch_vtable(AppPlatform_linux_getDateString, AppPlatform_linux_getDateString_injection);
|
2024-02-11 20:35:41 -05:00
|
|
|
}
|
2024-04-02 19:22:01 -04:00
|
|
|
|
2024-06-21 01:19:37 -04:00
|
|
|
// Fullscreen
|
2024-08-25 17:06:12 -04:00
|
|
|
if (feature_has("Fullscreen Support", server_disabled)) {
|
|
|
|
misc_run_on_key_press([](__attribute__((unused)) Minecraft *mc, int key) {
|
|
|
|
if (key == MC_KEY_F11) {
|
|
|
|
media_toggle_fullscreen();
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2024-06-21 01:19:37 -04:00
|
|
|
|
2024-07-17 03:44:41 -04:00
|
|
|
// Fix/Update Language Strings
|
|
|
|
if (feature_has("Add Missing Language Strings", server_disabled)) {
|
|
|
|
misc_run_on_language_setup(Language_injection);
|
|
|
|
// Water/Lava Language Strings
|
|
|
|
overwrite_call((void *) 0xc3b54, (void *) Tile_initTiles_std_string_constructor);
|
|
|
|
overwrite_call((void *) 0xc3c7c, (void *) Tile_initTiles_std_string_constructor);
|
|
|
|
// Carried Tile Language Strings
|
|
|
|
patch_address((void *) 0xc6674, (void *) "grassCarried");
|
|
|
|
patch_address((void *) 0xc6684, (void *) "leavesCarried");
|
|
|
|
// Invisible Bedrock Language String
|
|
|
|
overwrite_call((void *) 0xc5f04, (void *) Tile_initTiles_Tile_init_invBedrock_injection);
|
|
|
|
}
|
|
|
|
|
2024-08-25 17:06:12 -04:00
|
|
|
// Prevent Pigmen From Burning In The Sun
|
2024-07-17 03:44:41 -04:00
|
|
|
if (feature_has("Fix Pigmen Burning In The Sun", server_enabled)) {
|
2024-08-24 00:30:06 -04:00
|
|
|
fix_pigmen_burning = true;
|
2024-07-17 03:44:41 -04:00
|
|
|
overwrite_call((void *) 0x89a1c, (void *) Zombie_aiStep_getBrightness_injection);
|
|
|
|
}
|
|
|
|
|
2024-08-22 23:43:32 -04:00
|
|
|
// Fix Door Duplication
|
|
|
|
if (feature_has("Fix Door Duplication", server_enabled)) {
|
|
|
|
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
|
|
|
patch((void *) 0xbe230, nop_patch);
|
|
|
|
overwrite_call((void *) 0xbe110, (void *) DoorTile_neighborChanged_Tile_spawnResources_injection);
|
|
|
|
}
|
|
|
|
|
2024-08-23 05:18:20 -04:00
|
|
|
// Fix Cobweb Lighting
|
|
|
|
if (feature_has("Fix Cobweb Lighting", server_enabled)) {
|
|
|
|
overwrite_call((void *) 0xc444c, (void *) Tile_initTiles_WebTile_setLightBlock_injection);
|
|
|
|
}
|
|
|
|
|
2024-08-24 00:30:06 -04:00
|
|
|
// Fix Fire Immunity
|
|
|
|
if (feature_has("Fix Fire Immunity", server_enabled)) {
|
|
|
|
overwrite_calls(Mob_baseTick, Mob_baseTick_injection_fire_immunity);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix Fire Syncing
|
|
|
|
if (feature_has("Fix Fire Syncing", server_enabled)) {
|
|
|
|
overwrite_calls(Mob_baseTick, Mob_baseTick_injection_fire_syncing);
|
|
|
|
overwrite_calls(Entity_isOnFire, Entity_isOnFire_injection);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix Sneaking Syncing
|
|
|
|
if (feature_has("Fix Sneaking Syncing", server_enabled)) {
|
|
|
|
overwrite_calls(LocalPlayer_tick, LocalPlayer_tick_injection);
|
|
|
|
overwrite_calls(ServerSideNetworkHandler_handle_PlayerActionPacket, ServerSideNetworkHandler_handle_PlayerActionPacket_injection);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make Skeletons/Zombies Actually Catch On Fire
|
|
|
|
if (feature_has("Fix Sunlight Not Properly Setting Mobs On Fire", server_enabled)) {
|
|
|
|
overwrite_calls(Zombie_aiStep, Monster_aiStep_injection<Zombie>);
|
|
|
|
overwrite_calls(Skeleton_aiStep, Monster_aiStep_injection<Skeleton>);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear Fire For Creative Players
|
|
|
|
if (feature_has("Stop Creative Players From Burning", server_enabled)) {
|
|
|
|
overwrite_calls(Player_tick, Player_tick_injection);
|
|
|
|
}
|
|
|
|
|
2024-08-25 17:06:12 -04:00
|
|
|
// Init Other Components
|
|
|
|
_init_misc_tinting();
|
|
|
|
_init_misc_ui();
|
2024-04-02 19:22:01 -04:00
|
|
|
_init_misc_logging();
|
|
|
|
_init_misc_api();
|
2024-08-25 17:06:12 -04:00
|
|
|
_init_misc_graphics();
|
2021-06-21 21:50:26 -04:00
|
|
|
}
|