Expand Debug Info

This commit is contained in:
TheBrokenRail 2024-09-30 22:00:19 -04:00
parent 66f4f11a68
commit 661cfd02ad
7 changed files with 178 additions and 59 deletions

View File

@ -1,3 +1,4 @@
#pragma once
extern double fps;
extern double tps;

View File

@ -1,6 +1,7 @@
#include <vector>
#include <iomanip>
#include <sstream>
#include <cmath>
#include <symbols/minecraft.h>
#include <libreborn/libreborn.h>
@ -18,20 +19,34 @@ static std::string to_string_with_precision(const double x, const int precision)
stream << std::fixed << std::setprecision(precision) << x;
return stream.str();
}
static float wrap_degrees(float x) {
x = std::fmod(x, 360);
if (x >= 180) {
x -= 360;
}
if (x < -180) {
x += 360;
}
return x;
}
static int debug_precision = 3;
static std::vector<std::string> get_debug_info(const Minecraft *minecraft) {
static std::vector<std::string> get_debug_info_left(const Minecraft *minecraft) {
std::vector<std::string> info;
// Version
info.push_back(std::string("MCPI ") + version_get());
// FPS
info.push_back("FPS: " + to_string_with_precision(fps, debug_precision));
// Seed
// Level Information
if (minecraft->level) {
info.push_back("");
info.push_back("Seed: " + std::to_string(minecraft->level->data.seed));
info.push_back("Time: " + std::to_string(minecraft->level->data.time));
info.push_back("Entities: " + std::to_string(minecraft->level->entities.size()));
info.push_back("Players: " + std::to_string(minecraft->level->players.size()));
}
// X/Y/Z
// Player Information
if (minecraft->player) {
// X/Y/Z
info.push_back("");
float x = minecraft->player->x;
float y = minecraft->player->y - minecraft->player->height_offset;
@ -40,6 +55,93 @@ static std::vector<std::string> get_debug_info(const Minecraft *minecraft) {
info.push_back("X: " + to_string_with_precision(x, debug_precision));
info.push_back("Y: " + to_string_with_precision(y, debug_precision));
info.push_back("Z: " + to_string_with_precision(z, debug_precision));
// Rotation
info.push_back("");
const float yaw = wrap_degrees(minecraft->player->yaw);
info.push_back("Yaw: " + to_string_with_precision(yaw, debug_precision));
const float pitch = wrap_degrees(minecraft->player->pitch);
info.push_back("Pitch: " + to_string_with_precision(pitch, debug_precision));
// Facing
char axis[3] = {};
bool is_positive_on_axis;
std::string direction;
if (const float abs_yaw = std::abs(yaw); abs_yaw < 45 || abs_yaw > 135) {
// Z-Axis
axis[1] = 'Z';
is_positive_on_axis = abs_yaw < 90;
direction = is_positive_on_axis ? "South" : "North";
} else {
// X-Axis
axis[1] = 'X';
is_positive_on_axis = yaw < 0;
direction = is_positive_on_axis ? "East" : "West";
}
axis[0] = is_positive_on_axis ? '+' : '-';
info.push_back("Facing: " + direction + " (" + axis + ")");
}
// Return
return info;
}
static std::vector<std::string> get_debug_info_right(const Minecraft *minecraft) {
std::vector<std::string> info;
// TPS
info.push_back("TPS: " + to_string_with_precision(tps, debug_precision));
// Target Information
const HitResult &target = minecraft->hit_result;
if (target.type != 2) {
float x;
float y;
float z;
std::string type;
std::vector<std::string> type_info;
int xyz_precision;
if (target.type == 0) {
// Tile
x = float(target.x);
y = float(target.y);
z = float(target.z);
type = "Tile";
if (minecraft->level) {
const int id = minecraft->level->getTile(x, y, z);
std::string id_info = "ID: " + std::to_string(id);
if (Tile *tile = Tile::tiles[id]) {
const std::string description_id = tile->getDescriptionId();
std::string name = description_id + ".name";
if (I18n::_strings.contains(name)) {
name = I18n::_strings[name];
} else {
name = description_id;
}
if (!name.empty()) {
id_info += " (" + name + ')';
}
}
type_info.push_back(id_info);
type_info.push_back("Data: " + std::to_string(minecraft->level->getData(x, y, z)));
}
xyz_precision = 0;
} else {
// Entity
Entity *entity = target.entity;
x = entity->x;
y = entity->y;
z = entity->z;
type = "Entity";
type_info.push_back("Type ID: " + std::to_string(entity->getEntityTypeId())); // TODO: Specify name when RJ PR is merged
type_info.push_back("ID: " + std::to_string(entity->id));
if (entity->isMob()) {
Mob *mob = (Mob *) entity;
type_info.push_back("Health: " + std::to_string(mob->health) + '/' + std::to_string(mob->getMaxHealth()));
}
xyz_precision = debug_precision;
}
info.push_back("");
info.push_back("Target X: " + to_string_with_precision(x, xyz_precision));
info.push_back("Target Y: " + to_string_with_precision(y, xyz_precision));
info.push_back("Target Z: " + to_string_with_precision(z, xyz_precision));
info.push_back("");
info.push_back("Target Type: " + type);
info.insert(info.end(), type_info.begin(), type_info.end());
}
// Return
return info;
@ -48,12 +150,16 @@ static std::vector<std::string> get_debug_info(const Minecraft *minecraft) {
// Render Text With Background
static constexpr uint32_t debug_background_color = 0x90505050;
static constexpr int debug_text_color = 0xe0e0e0;
static void render_debug_line(Gui *gui, std::string &line, const int x, const int y) {
static void render_debug_line(Gui *gui, const std::string &line, int x, const int y, const bool right_aligned) {
// Draw Background
const int width = gui->minecraft->font->width(line);
if (width == 0) {
return;
}
if (right_aligned) {
const int screen_width = int(float(gui->minecraft->screen_width) * Gui::InvGuiScale);
x = screen_width - x - width + 1;
}
int x1 = x - 1;
int y1 = y - 1;
int x2 = x + width;
@ -66,15 +172,18 @@ static void render_debug_line(Gui *gui, std::string &line, const int x, const in
static bool debug_info_shown = false;
static constexpr int debug_margin = 2;
static constexpr int debug_line_padding = 1;
static void Gui_renderDebugInfo_injection(__attribute__((unused)) Gui_renderDebugInfo_t original, Gui *self) {
if (debug_info_shown) {
std::vector<std::string> info = get_debug_info(self->minecraft);
static void render_debug_info(Gui *self, const std::vector<std::string> &info, const bool right_aligned) {
int y = debug_margin;
for (std::string &line : info) {
render_debug_line(self, line, debug_margin, y);
for (const std::string &line : info) {
render_debug_line(self, line, debug_margin, y, right_aligned);
y += line_height;
y += debug_line_padding;
}
}
static void Gui_renderDebugInfo_injection(__attribute__((unused)) Gui_renderDebugInfo_t original, Gui *self) {
if (debug_info_shown) {
render_debug_info(self, get_debug_info_left(self->minecraft), false);
render_debug_info(self, get_debug_info_right(self->minecraft), true);
}
}

View File

@ -16,32 +16,65 @@ static long long int get_time() {
return a + b;
}
// Track FPS
static bool log_fps;
double fps = 0;
static void update_fps() {
// Track Frames
static long long int frames = 0;
frames++;
// Tracker
struct Tracker {
// State
long long int counter = 0;
long long int last_time = get_time();
// Properties
double &out;
const std::function<void()> callback;
// Constructor
Tracker(double &out_, const std::function<void()> &callback_):
out(out_),
callback(callback_) {}
// Update
void update() {
// Update Counter
counter++;
// Get Delta
const long long int time = get_time();
static long long int last_time = time;
const long long int delta = time - last_time;
const double delta_seconds = double(delta) / double(NANOSECONDS_IN_SECOND);
// Calculate FPS
if (delta_seconds >= 1) {
fps = double(frames) / delta_seconds;
frames = 0;
out = double(counter) / delta_seconds;
counter = 0;
last_time = time;
// Callback
if (callback) {
callback();
}
}
}
};
// Track FPS
static bool log_fps;
double fps = 0;
static void fps_callback() {
// Log
if (log_fps) {
INFO("FPS: %f", fps);
}
}
}
static Tracker fps_tracker(fps, fps_callback);
static void update_fps() {
fps_tracker.update();
}
// Track TPS
double tps = 0;
static Tracker tps_tracker(tps, nullptr);
static void update_tps(__attribute__((unused)) Minecraft *minecraft) {
tps_tracker.update();
}
// Init
void init_fps() {
if (!reborn_is_headless()) {
misc_run_on_swap_buffers(update_fps);
log_fps = feature_has("Log FPS", server_disabled);
}
misc_run_on_tick(update_tps);
}

View File

@ -24,8 +24,8 @@ __attribute__((constructor)) static void init() {
init_title_screen();
if (!reborn_is_headless()) {
init_skin();
init_fps();
}
init_fps();
init_touch();
init_textures();
init_creative();

View File

@ -1,6 +1,5 @@
#include <string>
#include <cstdint>
#include <ctime>
#include <cstdio>
#include <fstream>
#include <vector>
@ -21,6 +20,7 @@
#include <mods/compat/compat.h>
#include <mods/misc/misc.h>
#include <mods/game-mode/game-mode.h>
#include <mods/fps/fps.h>
// --only-generate: Ony Generate World And Then Exit
static bool only_generate = false;
@ -207,29 +207,6 @@ static void list_callback(Minecraft *minecraft, const std::string &username, Pla
INFO(" - %s (%s)", username.c_str(), get_player_ip(minecraft, player));
}
// Track TPS
#define NANOSECONDS_IN_SECOND 1000000000ll
static long long int get_time() {
timespec ts = {};
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
const long long int a = (long long int) ts.tv_nsec;
const long long int b = ((long long int) ts.tv_sec) * NANOSECONDS_IN_SECOND;
return a + b;
}
static bool is_last_tick_time_set = false;
static long long int last_tick_time;
static double tps = 0;
static void Minecraft_tick_injection(__attribute__((unused)) const Minecraft *minecraft) {
const long long int time = get_time();
if (is_last_tick_time_set) {
const long long int tick_time = time - last_tick_time;
tps = ((double) NANOSECONDS_IN_SECOND) / ((double) tick_time);
} else {
is_last_tick_time_set = true;
}
last_tick_time = time;
}
// Get ServerSideNetworkHandler From Minecraft
static ServerSideNetworkHandler *get_server_side_network_handler(const Minecraft *minecraft) {
return (ServerSideNetworkHandler *) minecraft->network_handler;
@ -612,9 +589,6 @@ static void server_init() {
// Log IPs
overwrite_call((void *) 0x75e54, (void *) ServerSideNetworkHandler_onReady_ClientGeneration_ServerSideNetworkHandler_popPendingPlayer_injection);
// Track TPS
misc_run_on_tick(Minecraft_tick_injection);
// Start Reading STDIN
pthread_create(&read_stdin_thread_obj, nullptr, read_stdin_thread, nullptr);
}

View File

@ -10,6 +10,7 @@ virtual-method ItemInstance *getCarriedItem() = 0x1ac;
virtual-method void updateAi() = 0x1cc;
virtual-method float getWalkingSpeedModifier() = 0x1e8;
virtual-method void aiStep() = 0x180;
virtual-method int getMaxHealth() = 0x168;
method bool getSharedFlag(int flag) = 0x81fd8;
method void setSharedFlag(int flag, bool value) = 0x81ef8;

View File

@ -48,6 +48,7 @@ virtual-method bool getSignal2(LevelSource *level, int x, int y, int z, int dire
// Called by Level_hasDirectSignal
virtual-method bool getDirectSignal(Level *level, int x, int y, int z, int direction) = 0xc8;
virtual-method void entityInside(Level *level, int x, int y, int z, Entity *entity) = 0xcc;
virtual-method std::string getName() = 0xd8;
virtual-method std::string getDescriptionId() = 0xdc;
virtual-method Tile *setDescriptionId(const std::string &description_id) = 0xe0;
virtual-method Tile *setSoundType(const Tile_SoundType &sound_type) = 0xe8;