[submodule "deps/endian.h"]
path = deps/endian.h
url = https://github.com/mikepb/endian.h
+[submodule "deps/dragonport"]
+ path = deps/dragonport
+ url = https://github.com/dragonblocks/dragonport
--- /dev/null
+Subproject commit a6c5dd9faf12ac38b1868c7ad742947a7dbeb905
signal_handlers.c
util.c
"${DEPS_DIR}/dragontype/implementation.c"
+ "${DEPS_DIR}/dragonport/asprintf.c"
"${DEPS_DIR}/perlin/perlin.c"
)
#include "day.h"
#include "environment.h"
#include "perlin.h"
+#include "util.h"
#include "version.h"
typedef enum
.scale = {1.0f, 1.0f},
.scale_type = GST_TEXT,
.affect_parent_scale = false,
- .text = "",
+ .text = strdup(""),
.image = NULL,
.text_color = (v4f32) {1.0f, 1.0f, 1.0f, 1.0f},
.bg_color = (v4f32) {0.0f, 0.0f, 0.0f, 0.0f},
void debug_menu_update_version()
{
- char text[BUFSIZ];
- sprintf(text, "Dragonblocks Alpha %s", VERSION);
- gui_set_text(gui_elements[DME_VERSION], text);
+ gui_set_text(gui_elements[DME_VERSION], format_string("Dragonblocks Alpha %s", VERSION));
}
void debug_menu_update_fps(int fps)
{
- char text[BUFSIZ];
- sprintf(text, "%d FPS", fps);
- gui_set_text(gui_elements[DME_FPS], text);
+ gui_set_text(gui_elements[DME_FPS], format_string("%d FPS", fps));
}
void debug_menu_update_pos()
{
- char text[BUFSIZ];
- sprintf(text, "(%.1f %.1f %.1f)", client_player.pos.x, client_player.pos.y, client_player.pos.z);
- gui_set_text(gui_elements[DME_POS], text);
+ gui_set_text(gui_elements[DME_POS], format_string("(%.1f %.1f %.1f)", client_player.pos.x, client_player.pos.y, client_player.pos.z));
}
void debug_menu_update_yaw()
{
- char text[BUFSIZ];
- sprintf(text, "yaw = %.1f", client_player.yaw / M_PI * 180.0);
- gui_set_text(gui_elements[DME_YAW], text);
+ gui_set_text(gui_elements[DME_YAW], format_string("yaw = %.1f", client_player.yaw / M_PI * 180.0));
}
void debug_menu_update_pitch()
{
- char text[BUFSIZ];
- sprintf(text, "pitch = %.1f", client_player.pitch / M_PI * 180.0);
- gui_set_text(gui_elements[DME_PITCH], text);
+ gui_set_text(gui_elements[DME_PITCH], format_string("pitch = %.1f", client_player.pitch / M_PI * 180.0));
}
void debug_menu_update_time()
{
int hours, minutes;
split_time_of_day(&hours, &minutes);
-
- char text[BUFSIZ];
- sprintf(text, "%02d:%02d", hours, minutes);
- gui_set_text(gui_elements[DME_TIME], text);
+ gui_set_text(gui_elements[DME_TIME], format_string("%02d:%02d", hours, minutes));
}
void debug_menu_update_daylight()
{
- char text[BUFSIZ];
- sprintf(text, "daylight = %.2f", get_daylight());
- gui_set_text(gui_elements[DME_DAYLIGHT], text);
+ gui_set_text(gui_elements[DME_DAYLIGHT], format_string("daylight = %.2f", get_daylight()));
}
void debug_menu_update_sun_angle()
{
- char text[BUFSIZ];
- sprintf(text, "sun angle = %.1f", fmod(get_sun_angle() / M_PI * 180.0, 360.0));
- gui_set_text(gui_elements[DME_SUN_ANGLE], text);
+ gui_set_text(gui_elements[DME_SUN_ANGLE], format_string("sun angle = %.1f", fmod(get_sun_angle() / M_PI * 180.0, 360.0)));
}
void debug_menu_update_humidity()
{
- char text[BUFSIZ];
- sprintf(text, "humidity = %.2f", get_humidity((v3s32) {client_player.pos.x, client_player.pos.y, client_player.pos.z}));
- gui_set_text(gui_elements[DME_HUMIDITY], text);
+ gui_set_text(gui_elements[DME_HUMIDITY], format_string("humidity = %.2f", get_humidity((v3s32) {client_player.pos.x, client_player.pos.y, client_player.pos.z})));
}
void debug_menu_update_temperature()
{
- char text[BUFSIZ];
- sprintf(text, "temperature = %.2f", get_temperature((v3s32) {client_player.pos.x, client_player.pos.y, client_player.pos.z}));
- gui_set_text(gui_elements[DME_TEMPERATURE], text);
+ gui_set_text(gui_elements[DME_TEMPERATURE], format_string("temperature = %.2f", get_temperature((v3s32) {client_player.pos.x, client_player.pos.y, client_player.pos.z})));
}
void debug_menu_update_seed()
{
- char text[BUFSIZ];
- sprintf(text, "seed = %d", seed);
- gui_set_text(gui_elements[DME_SEED], text);
+ gui_set_text(gui_elements[DME_SEED], format_string("seed = %d", seed));
}
void debug_menu_update_flight()
{
- char text[BUFSIZ];
- sprintf(text, "flight: %s", client_player.fly ? "enabled" : "disabled");
- gui_set_text(gui_elements[DME_FLIGHT], text);
+ gui_set_text(gui_elements[DME_FLIGHT], format_string("flight: %s", client_player.fly ? "enabled" : "disabled"));
}
void debug_menu_update_collision()
{
- char text[BUFSIZ];
- sprintf(text, "collision: %s", client_player.collision ? "enabled" : "disabled");
- gui_set_text(gui_elements[DME_COLLISION], text);
+ gui_set_text(gui_elements[DME_COLLISION], format_string("collision: %s", client_player.collision ? "enabled" : "disabled"));
}
void debug_menu_update_timelapse()
{
- char text[BUFSIZ];
- sprintf(text, "timelapse: %s", timelapse ? "enabled" : "disabled");
- gui_set_text(gui_elements[DME_TIMELAPSE], text);
+ gui_set_text(gui_elements[DME_TIMELAPSE], format_string("timelapse: %s", timelapse ? "enabled" : "disabled"));
}
void debug_menu_update_fullscreen()
{
- char text[BUFSIZ];
- sprintf(text, "fullscreen: %s", window.fullscreen ? "enabled" : "disabled");
- gui_set_text(gui_elements[DME_FULLSCREEN], text);
+ gui_set_text(gui_elements[DME_FULLSCREEN], format_string("fullscreen: %s", window.fullscreen ? "enabled" : "disabled"));
}
void debug_menu_update_opengl()
{
- char text[BUFSIZ];
- sprintf(text, "OpenGL %s", glGetString(GL_VERSION));
- gui_set_text(gui_elements[DME_OPENGL], text);
+ gui_set_text(gui_elements[DME_OPENGL], format_string("OpenGL %s", glGetString(GL_VERSION)));
}
void debug_menu_update_gpu()
{
- char text[BUFSIZ];
- sprintf(text, "%s", glGetString(GL_RENDERER));
- gui_set_text(gui_elements[DME_GPU], text);
+ gui_set_text(gui_elements[DME_GPU], format_string("%s", glGetString(GL_RENDERER)));
}
frames++;
- input_tick();
+ input_tick(dtime);
client_player_tick(dtime);
debug_menu_update_time();
return true;
}
-void take_screenshot()
+char *take_screenshot()
{
// renderbuffer for depth & stencil buffer
GLuint RBO;
glDeleteRenderbuffers(1, &RBO);
glDeleteTextures(2, textures);
glDeleteFramebuffers(2, FBOs);
+
+ return strdup(filename);
}
void game_on_resize(int width, int height)
#include "client/client.h"
bool game(Client *client);
-void take_screenshot();
+char *take_screenshot();
void game_on_resize(int width, int height);
#endif
if (element->def.text) {
element->def.text = strdup(element->def.text);
element->text = font_create(element->def.text);
+ } else {
+ element->text = NULL;
}
bintree_insert(&parent->children, &element->def.z_index, element);
return element;
}
-void gui_set_text(GUIElement *element, const char *text)
+void gui_set_text(GUIElement *element, char *text)
{
- if (! element->def.text || strcmp(element->def.text, text)) {
- element->def.text = strdup(text);
- font_delete(element->text);
- element->text = font_create(text);
- gui_update_transform(element);
- }
+ if (element->def.text)
+ free(element->def.text);
+
+ element->def.text = text;
+ font_delete(element->text);
+ element->text = font_create(text);
+ gui_update_transform(element);
}
// transform code
switch (element->def.scale_type) {
case GST_IMAGE:
- assert(element->def.image);
element->scale.x *= element->def.image->width;
element->scale.y *= element->def.image->height;
break;
case GST_TEXT:
- assert(element->text);
element->scale.x *= element->text->size.x;
element->scale.y *= element->text->size.y;
break;
static void calculate_element_transform(GUIElement *element)
{
element->pos = (v2f32) {
- element->parent->pos.x + element->def.offset.x + element->def.pos.x * element->parent->scale.x - element->def.align.x * element->scale.x,
- element->parent->pos.y + element->def.offset.y + element->def.pos.y * element->parent->scale.y - element->def.align.y * element->scale.y,
+ floor(element->parent->pos.x + element->def.offset.x + element->def.pos.x * element->parent->scale.x - element->def.align.x * element->scale.x),
+ floor(element->parent->pos.y + element->def.offset.y + element->def.pos.y * element->parent->scale.y - element->def.align.y * element->scale.y),
};
mat4x4_translate(element->transform, element->pos.x - element->def.margin.x, element->pos.y - element->def.margin.y, 0.0f);
void gui_on_resize(int width, int height);
void gui_render();
GUIElement *gui_add(GUIElement *parent, GUIElementDefinition def);
-void gui_set_text(GUIElement *element, const char *text);
+void gui_set_text(GUIElement *element, char *text);
void gui_update_transform(GUIElement *element);
extern GUIElement gui_root;
#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "client/camera.h"
#include "client/client.h"
#include "client/client_player.h"
#include "client/input.h"
#include "client/window.h"
#include "day.h"
+#include "util.h"
typedef struct
{
static struct
{
GUIElement *pause_menu;
+ GUIElement *status_message;
bool paused;
KeyListener pause_listener;
KeyListener fullscreen_listener;
};
}
-void input_tick()
+static void set_status_message(char *message)
{
+ gui_set_text(input.status_message, message);
+ input.status_message->def.text_color.w = 2.0f;
+}
+
+void input_tick(f64 dtime)
+{
+ if (input.status_message->def.text_color.w > 1.0f)
+ input.status_message->def.text_color.w -= dtime * 1.0f;
+ else if (input.status_message->def.text_color.w > 0.0f)
+ input.status_message->def.text_color.w -= dtime * 1.0f;
+
do_key_listener(&input.pause_listener);
do_key_listener(&input.fullscreen_listener);
if (input.fly_listener.fired) {
client_player.fly = ! client_player.fly;
debug_menu_update_flight();
+ set_status_message(format_string("Flight %s", client_player.fly ? "Enabled" : "Disabled"));
}
if (input.collision_listener.fired) {
client_player.collision = ! client_player.collision;
debug_menu_update_collision();
+ set_status_message(format_string("Collision %s", client_player.collision ? "Enabled" : "Disabled"));
}
if (input.timelapse_listener.fired) {
timelapse = ! timelapse;
set_time_of_day(current_time);
debug_menu_update_timelapse();
+ set_status_message(format_string("Timelapse %s", timelapse ? "Enabled" : "Disabled"));
}
if (input.debug_menu_listener.fired)
debug_menu_toggle();
- if (input.screenshot_listener.fired)
- take_screenshot();
+ if (input.screenshot_listener.fired) {
+ char *screenshot_filename = take_screenshot();
+ set_status_message(format_string("Screenshot saved to %s", screenshot_filename));
+ free(screenshot_filename);
+ }
}
client_player.velocity.x = 0.0f;
.bg_color = {0.0f, 0.0f, 0.0f, 0.4f},
});
+ input.status_message = gui_add(&gui_root, (GUIElementDefinition) {
+ .pos = {0.5f, 0.25f},
+ .z_index = 0.1f,
+ .offset = {0, 0},
+ .margin = {0, 0},
+ .align = {0.5f, 0.5f},
+ .scale = {1.0f, 1.0f},
+ .scale_type = GST_TEXT,
+ .affect_parent_scale = false,
+ .text = strdup(""),
+ .image = NULL,
+ .text_color = {1.0f, 0.91f, 0.13f, 0.0f},
+ .bg_color = {0.0f, 0.0f, 0.0f, 0.0f},
+ });
+
glfwSetInputMode(window.handle, GLFW_STICKY_KEYS, GL_TRUE);
enter_game();
#ifndef _INPUT_H_
#define _INPUT_H_
-void input_tick();
+#include <dragontype/number.h>
+
+void input_tick(f64 dtime);
void input_init();
void input_on_cursor_pos(double current_x, double current_y);
#include <unistd.h>
#include <string.h>
#include <zlib.h>
+#include <dragonport/asprintf.h>
#include "map.h"
#include "util.h"
return result;
}
-// convert #RRGGBB color to v3f32
-v3f32 html_to_v3f32(const char *html)
-{
- unsigned int r, g, b;
- sscanf(html, "#%2x%2x%2x", &r, &g, &b);
- return (v3f32) {(f32) r / 255.0f, (f32) g / 255.0f, (f32) b / 255.0f};
-}
-
// compress data using ZLib and store result(buffer allocated by malloc) in compressed
void my_compress(const void *uncompressed, size_t uncompressed_size, char **compressed, size_t *compressed_size)
{
{
return v < min ? min : v > max ? max : v;
}
+
+char *format_string(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ char *ptr;
+ vasprintf(&ptr, format, args);
+ va_end(args);
+ return ptr;
+}
void internal_error(const char *err); // print general error message and exit
char *read_string(int fd, size_t bufsiz); // read from fd until \0 or EOF terminator
char *address_string(struct sockaddr_in6 *addr); // convert IPv6 address to human readable, return allocated buffer
-v3f32 html_to_v3f32(const char *html); // convert #RRGGBB color to v3f32
void my_compress(const void *uncompressed, size_t uncompressed_size, char **compressed, size_t *compressed_size); // compress data using ZLib and store result(buffer allocated by malloc) in compressed
bool my_decompress(const char *compressed, size_t compressed_size, void *decompressed, size_t expected_decompressed_size); // decompress data and put result into decompressed, return false if decompressed size does not match expected_decompressed_size
bool within_simulation_distance(v3f64 player_pos, v3s32 block_pos, u32 simulation_distance); // return true if a player is close enough to a block to access it
f64 clamp(f64 v, f64 min, f64 max);
+char *format_string(const char *format, ...);
#endif