diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index 599fc34..358e161 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -102,6 +102,8 @@ else() # text-input-box src/text-input-box/TextInputBox.cpp src/text-input-box/TextInputScreen.cpp + # fps + src/fps/fps.cpp ) # Install Splashes install( diff --git a/mods/include/mods/fps/fps.h b/mods/include/mods/fps/fps.h new file mode 100644 index 0000000..237871a --- /dev/null +++ b/mods/include/mods/fps/fps.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +extern double fps; + +#ifdef __cplusplus +} +#endif diff --git a/mods/include/mods/init/init.h b/mods/include/mods/init/init.h index 46e85cf..6dce44d 100644 --- a/mods/include/mods/init/init.h +++ b/mods/include/mods/init/init.h @@ -24,6 +24,7 @@ void init_touch(); void init_atlas(); void init_title_screen(); void init_skin(); +void init_fps(); #endif void init_textures(); void init_creative(); diff --git a/mods/src/fps/README.md b/mods/src/fps/README.md new file mode 100644 index 0000000..a522b2e --- /dev/null +++ b/mods/src/fps/README.md @@ -0,0 +1,2 @@ +# `fps` Mod +This mod tracks the game's FPS. diff --git a/mods/src/fps/fps.cpp b/mods/src/fps/fps.cpp new file mode 100644 index 0000000..3e2ec78 --- /dev/null +++ b/mods/src/fps/fps.cpp @@ -0,0 +1,54 @@ +#include +#include + +#include +#include +#include +#include + +// Track FPS +#define NANOSECONDS_IN_SECOND 1000000000ll +static long long int get_time() { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + long long int a = (long long int) ts.tv_nsec; + long long int b = ((long long int) ts.tv_sec) * NANOSECONDS_IN_SECOND; + return a + b; +} +double fps = 0; +static void update_fps(__attribute__((unused)) Minecraft *minecraft) { + static bool is_last_update_time_set = false; + static long long int last_update_time; + long long int time = get_time(); + if (is_last_update_time_set) { + long long int update_time = time - last_update_time; + fps = ((double) NANOSECONDS_IN_SECOND) / ((double) update_time); + } else { + is_last_update_time_set = true; + } + last_update_time = time; +} + +// Print FPS +static void print_fps(__attribute__((unused)) Minecraft *minecraft) { + // Track Ticks + static int ticks = 0; + ticks++; + if (ticks == 20) { + // One Second Has Passed, Reset + ticks = 0; + } + + // Print + if (ticks == 0) { + INFO("FPS: %f", fps); + } +} + +// Init +void init_fps() { + if (feature_has("Track FPS", server_disabled)) { + misc_run_on_update(update_fps); + misc_run_on_tick(print_fps); + } +} diff --git a/mods/src/init/init.c b/mods/src/init/init.c index b92629a..94b5491 100644 --- a/mods/src/init/init.c +++ b/mods/src/init/init.c @@ -23,6 +23,7 @@ __attribute__((constructor)) static void init(int argc, char *argv[]) { init_atlas(); init_title_screen(); init_skin(); + init_fps(); #endif init_textures(); init_creative(); diff --git a/mods/src/misc/misc.cpp b/mods/src/misc/misc.cpp index 410760e..bc15a27 100644 --- a/mods/src/misc/misc.cpp +++ b/mods/src/misc/misc.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -90,6 +91,38 @@ ItemInstance *Item_getCraftingRemainingItem_injection(Item *self, ItemInstance * return NULL; } +// Sort Chunks +struct chunk_data { + Chunk *chunk; + float distance; +}; +#define MAX_CHUNKS_SIZE 24336 +chunk_data data[MAX_CHUNKS_SIZE]; +static void sort_chunks(Chunk **chunks_begin, Chunk **chunks_end, DistanceChunkSorter sorter) { + // Calculate Distances + int chunks_size = chunks_end - chunks_begin; + if (chunks_size > MAX_CHUNKS_SIZE) { + IMPOSSIBLE(); + } + for (int i = 0; i < chunks_size; i++) { + Chunk *chunk = chunks_begin[i]; + float distance = Chunk_distanceToSqr(chunk, (Entity *) sorter.mob); + if ((1024.0 <= distance) && chunk->y < 0x40) { + distance = distance * 10.0; + } + data[i].chunk = chunk; + data[i].distance = distance; + } + + // Sort + std::sort(data, data + chunks_size, [](chunk_data &a, chunk_data &b) { + return a.distance < b.distance; + }); + for (int i = 0; i < chunks_size; i++) { + chunks_begin[i] = data[i].chunk; + } +} + // Init void _init_misc_cpp() { // Implement AppPlatform::readAssetFile So Translations Work @@ -106,4 +139,7 @@ void _init_misc_cpp() { // Implement crafting remainders overwrite_call((void *) 0x2e230, (void *) PaneCraftingScreen_craftSelectedItem_PaneCraftingScreen_recheckRecipes_injection); overwrite((void *) Item_getCraftingRemainingItem_non_virtual, (void *) Item_getCraftingRemainingItem_injection); + + // Replace 2011 std::sort With Optimized(TM) Code + overwrite((void *) 0x51fac, (void *) sort_chunks); } diff --git a/mods/src/title-screen/splashes.txt b/mods/src/title-screen/splashes.txt index 5d69cc3..f512cb5 100644 --- a/mods/src/title-screen/splashes.txt +++ b/mods/src/title-screen/splashes.txt @@ -51,3 +51,11 @@ Who is StevePi? Why must you hurt me? Wow! Modded MCPI! mcpi-revival.github.io! +discord.gg/aDqejQGMMy! +Buckets! +Caves! +Multiplayer! +Where's my sound? +Animated Lava! +Made with Ghidra! +Python API! diff --git a/symbols/CMakeLists.txt b/symbols/CMakeLists.txt index 3eb63fb..93360c2 100644 --- a/symbols/CMakeLists.txt +++ b/symbols/CMakeLists.txt @@ -78,6 +78,8 @@ set(SRC src/level/Dimension.def src/level/MultiPlayerLevel.def src/level/LevelSummary.def + src/level/DistanceChunkSorter.def + src/level/Chunk.def src/item/ItemRenderer.def src/item/ItemInHandRenderer.def src/item/AuxDataTileItem.def diff --git a/symbols/src/level/Chunk.def b/symbols/src/level/Chunk.def new file mode 100644 index 0000000..9614e85 --- /dev/null +++ b/symbols/src/level/Chunk.def @@ -0,0 +1,5 @@ +property int x = 0x4; +property int y = 0x8; +property int z = 0xc; + +method float distanceToSqr(Entity *entity) = 0x47ba0; diff --git a/symbols/src/level/DistanceChunkSorter.def b/symbols/src/level/DistanceChunkSorter.def new file mode 100644 index 0000000..b1b5eb5 --- /dev/null +++ b/symbols/src/level/DistanceChunkSorter.def @@ -0,0 +1,5 @@ +size 0x4; + +property Mob *mob = 0x0; + +method bool compare(Chunk *param_1, Chunk *param_2) = 0x5118c; // Actually Called _ZN19DistanceChunkSorterclEPK5ChunkS2_