2024-07-05 02:33:29 -04:00
|
|
|
#include <vector>
|
|
|
|
#include <iomanip>
|
|
|
|
#include <sstream>
|
2024-09-30 22:00:19 -04:00
|
|
|
#include <cmath>
|
2024-07-05 02:33:29 -04:00
|
|
|
|
|
|
|
#include <symbols/minecraft.h>
|
|
|
|
#include <libreborn/libreborn.h>
|
|
|
|
|
|
|
|
#include <mods/misc/misc.h>
|
|
|
|
#include <mods/feature/feature.h>
|
|
|
|
#include <mods/input/input.h>
|
|
|
|
#include <mods/version/version.h>
|
|
|
|
#include <mods/fps/fps.h>
|
|
|
|
#include <mods/init/init.h>
|
|
|
|
|
|
|
|
// Get Debug Information
|
|
|
|
static std::string to_string_with_precision(const double x, const int precision) {
|
|
|
|
std::stringstream stream;
|
|
|
|
stream << std::fixed << std::setprecision(precision) << x;
|
|
|
|
return stream.str();
|
|
|
|
}
|
2024-09-30 22:00:19 -04:00
|
|
|
static float wrap_degrees(float x) {
|
|
|
|
x = std::fmod(x, 360);
|
|
|
|
if (x >= 180) {
|
|
|
|
x -= 360;
|
|
|
|
}
|
|
|
|
if (x < -180) {
|
|
|
|
x += 360;
|
|
|
|
}
|
|
|
|
return x;
|
|
|
|
}
|
2024-07-05 02:33:29 -04:00
|
|
|
static int debug_precision = 3;
|
2024-09-30 22:00:19 -04:00
|
|
|
static std::vector<std::string> get_debug_info_left(const Minecraft *minecraft) {
|
2024-07-05 02:33:29 -04:00
|
|
|
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));
|
2024-09-30 22:00:19 -04:00
|
|
|
// Level Information
|
2024-09-30 00:45:53 -04:00
|
|
|
if (minecraft->level) {
|
|
|
|
info.push_back("");
|
|
|
|
info.push_back("Seed: " + std::to_string(minecraft->level->data.seed));
|
2024-09-30 22:00:19 -04:00
|
|
|
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()));
|
2024-09-30 00:45:53 -04:00
|
|
|
}
|
2024-09-30 22:00:19 -04:00
|
|
|
// Player Information
|
2024-07-05 02:33:29 -04:00
|
|
|
if (minecraft->player) {
|
2024-09-30 22:00:19 -04:00
|
|
|
// X/Y/Z
|
2024-07-05 02:33:29 -04:00
|
|
|
info.push_back("");
|
|
|
|
float x = minecraft->player->x;
|
|
|
|
float y = minecraft->player->y - minecraft->player->height_offset;
|
|
|
|
float z = minecraft->player->z;
|
2024-07-15 03:05:05 -04:00
|
|
|
minecraft->command_server->pos_translator.to(x, y, z);
|
2024-07-05 02:33:29 -04:00
|
|
|
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));
|
2024-09-30 22:00:19 -04:00
|
|
|
// 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());
|
2024-07-05 02:33:29 -04:00
|
|
|
}
|
|
|
|
// Return
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Render Text With Background
|
2024-09-22 19:28:51 -04:00
|
|
|
static constexpr uint32_t debug_background_color = 0x90505050;
|
|
|
|
static constexpr int debug_text_color = 0xe0e0e0;
|
2024-09-30 22:00:19 -04:00
|
|
|
static void render_debug_line(Gui *gui, const std::string &line, int x, const int y, const bool right_aligned) {
|
2024-07-05 02:33:29 -04:00
|
|
|
// Draw Background
|
2024-08-22 23:43:32 -04:00
|
|
|
const int width = gui->minecraft->font->width(line);
|
2024-07-05 02:33:29 -04:00
|
|
|
if (width == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2024-09-30 22:00:19 -04:00
|
|
|
if (right_aligned) {
|
|
|
|
const int screen_width = int(float(gui->minecraft->screen_width) * Gui::InvGuiScale);
|
|
|
|
x = screen_width - x - width + 1;
|
|
|
|
}
|
2024-09-30 13:13:02 -04:00
|
|
|
int x1 = x - 1;
|
|
|
|
int y1 = y - 1;
|
|
|
|
int x2 = x + width;
|
|
|
|
int y2 = y + line_height;
|
|
|
|
gui->fill(x1, y1, x2, y2, debug_background_color);
|
2024-07-05 02:33:29 -04:00
|
|
|
// Draw Text
|
2024-07-15 03:05:05 -04:00
|
|
|
gui->minecraft->font->draw(line, float(x), float(y), debug_text_color);
|
2024-07-05 02:33:29 -04:00
|
|
|
}
|
|
|
|
// Draw Debug Information
|
|
|
|
static bool debug_info_shown = false;
|
2024-09-22 19:28:51 -04:00
|
|
|
static constexpr int debug_margin = 2;
|
|
|
|
static constexpr int debug_line_padding = 1;
|
2024-09-30 22:00:19 -04:00
|
|
|
static void render_debug_info(Gui *self, const std::vector<std::string> &info, const bool right_aligned) {
|
|
|
|
int y = debug_margin;
|
|
|
|
for (const std::string &line : info) {
|
|
|
|
render_debug_line(self, line, debug_margin, y, right_aligned);
|
|
|
|
y += line_height;
|
|
|
|
y += debug_line_padding;
|
|
|
|
}
|
|
|
|
}
|
2024-07-05 02:33:29 -04:00
|
|
|
static void Gui_renderDebugInfo_injection(__attribute__((unused)) Gui_renderDebugInfo_t original, Gui *self) {
|
|
|
|
if (debug_info_shown) {
|
2024-09-30 22:00:19 -04:00
|
|
|
render_debug_info(self, get_debug_info_left(self->minecraft), false);
|
|
|
|
render_debug_info(self, get_debug_info_right(self->minecraft), true);
|
2024-07-05 02:33:29 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Init
|
|
|
|
void init_f3() {
|
|
|
|
if (feature_has("F3 Debug Information", server_disabled)) {
|
|
|
|
overwrite_calls(Gui_renderDebugInfo, Gui_renderDebugInfo_injection);
|
2024-09-22 21:21:53 -04:00
|
|
|
misc_run_on_game_key_press([](__attribute__((unused)) Minecraft *minecraft, const int key) {
|
2024-07-05 02:33:29 -04:00
|
|
|
if (key == MC_KEY_F3) {
|
|
|
|
debug_info_shown = !debug_info_shown;
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|