summaryrefslogtreecommitdiffstats
path: root/src/menu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/menu.cpp')
-rw-r--r--src/menu.cpp49
1 files changed, 40 insertions, 9 deletions
diff --git a/src/menu.cpp b/src/menu.cpp
index 5fc325e..2021218 100644
--- a/src/menu.cpp
+++ b/src/menu.cpp
@@ -116,12 +116,14 @@ void register_bundled_font() {
116 } 116 }
117 if (path.empty()) { 117 if (path.empty()) {
118 logf("font: bundled LiberationSans-Regular.ttf not found"); 118 logf("font: bundled LiberationSans-Regular.ttf not found");
119 toastf(TOAST_WARN, "Bundled font missing; overlay may not render");
119 return; 120 return;
120 } 121 }
121 122
122 void *fc = dlopen("libfontconfig.so.1", RTLD_LAZY | RTLD_GLOBAL); 123 void *fc = dlopen("libfontconfig.so.1", RTLD_LAZY | RTLD_GLOBAL);
123 if (!fc) { 124 if (!fc) {
124 logf("font: libfontconfig.so.1 not available"); 125 logf("font: libfontconfig.so.1 not available");
126 toastf(TOAST_WARN, "fontconfig unavailable; overlay font not registered");
125 return; 127 return;
126 } 128 }
127 using InitFn = int (*)(); 129 using InitFn = int (*)();
@@ -132,20 +134,27 @@ void register_bundled_font() {
132 auto add = (AddFileFn)dlsym(fc, "FcConfigAppFontAddFile"); 134 auto add = (AddFileFn)dlsym(fc, "FcConfigAppFontAddFile");
133 if (!init || !get || !add) { 135 if (!init || !get || !add) {
134 logf("font: fontconfig symbols missing"); 136 logf("font: fontconfig symbols missing");
137 toastf(TOAST_WARN, "fontconfig symbols missing; overlay font not registered");
135 return; 138 return;
136 } 139 }
137 init(); 140 init();
138 void *cfg = get(); 141 void *cfg = get();
139 if (cfg && add(cfg, path.c_str())) 142 if (cfg && add(cfg, path.c_str()))
140 logf("font: registered %s", path.c_str()); 143 logf("font: registered %s", path.c_str());
141 else 144 else {
142 logf("font: failed to register %s", path.c_str()); 145 logf("font: failed to register %s", path.c_str());
146 toastf(TOAST_WARN, "Could not register the overlay font");
147 }
143} 148}
144 149
145void config_save() { 150void config_save() {
146 FILE *f = fopen(config_path().c_str(), "w"); 151 std::string path = config_path();
147 if (!f) 152 std::string tmp = path + ".tmp";
153 FILE *f = fopen(tmp.c_str(), "w");
154 if (!f) {
155 toastf(TOAST_ERROR, "Config save failed: %s", path.c_str());
148 return; 156 return;
157 }
149 fprintf(f, "[bhop]\nactive=%d\nbind=%d\nautostrafe=%d\n", g_bhop.active, 158 fprintf(f, "[bhop]\nactive=%d\nbind=%d\nautostrafe=%d\n", g_bhop.active,
150 g_bhop.bind, g_bhop_autostrafe); 159 g_bhop.bind, g_bhop_autostrafe);
151 fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind); 160 fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind);
@@ -175,13 +184,23 @@ void config_save() {
175 g_esp_opt[ESP_OPT_SHOW_SKELETON], g_esp_opt[ESP_OPT_SHOW_BOX], 184 g_esp_opt[ESP_OPT_SHOW_SKELETON], g_esp_opt[ESP_OPT_SHOW_BOX],
176 g_esp_opt[ESP_OPT_SHOW_SPEEDGRAPH]); 185 g_esp_opt[ESP_OPT_SHOW_SPEEDGRAPH]);
177 gui_config_write(f); 186 gui_config_write(f);
178 fclose(f); 187 bool ok = ferror(f) == 0;
188 if (fflush(f) != 0)
189 ok = false;
190 if (ok)
191 (void)fsync(fileno(f)); // best effort; the rename is what matters
192 if (fclose(f) != 0)
193 ok = false;
194 if (!ok || rename(tmp.c_str(), path.c_str()) != 0) {
195 remove(tmp.c_str());
196 toastf(TOAST_ERROR, "Config save failed: %s", path.c_str());
197 }
179} 198}
180 199
181static void config_load() { 200static bool config_load() {
182 FILE *f = fopen(config_path().c_str(), "r"); 201 FILE *f = fopen(config_path().c_str(), "r");
183 if (!f) 202 if (!f)
184 return; 203 return false;
185 char line[256]; 204 char line[256];
186 FeatureState *cur = nullptr; 205 FeatureState *cur = nullptr;
187 bool in_esp = false, in_bhop = false, in_aim = false, in_silent = false, 206 bool in_esp = false, in_bhop = false, in_aim = false, in_silent = false,
@@ -288,9 +307,15 @@ static void config_load() {
288 } 307 }
289 } 308 }
290 fclose(f); 309 fclose(f);
310 return true;
291} 311}
292 312
293void config_reload() { config_load(); } 313void config_reload() {
314 if (config_load())
315 toastf(TOAST_INFO, "Config reloaded");
316 else
317 toastf(TOAST_WARN, "Config not found; kept current settings");
318}
294 319
295const char *config_path_cstr() { 320const char *config_path_cstr() {
296 static std::string path; 321 static std::string path;
@@ -583,7 +608,8 @@ void outer_draw() {
583 // HL2H_DRAW_TEST=1 draws a probe rect without needing the GUI open 608 // HL2H_DRAW_TEST=1 draws a probe rect without needing the GUI open
584 static bool draw_test = getenv("HL2H_DRAW_TEST") != nullptr; 609 static bool draw_test = getenv("HL2H_DRAW_TEST") != nullptr;
585 bool esp_on = feature_active(FEAT_ESP); 610 bool esp_on = feature_active(FEAT_ESP);
586 if (!g_surface || (!gui_is_open() && !draw_test && !esp_on)) 611 bool toasts = gui_toasts_active();
612 if (!g_surface || (!gui_is_open() && !draw_test && !esp_on && !toasts))
587 return; 613 return;
588 614
589 // Level/menu -> game transitions can invalidate the VGUI font handle. 615 // Level/menu -> game transitions can invalidate the VGUI font handle.
@@ -622,6 +648,7 @@ void outer_draw() {
622 } 648 }
623 if (!font_ok) { 649 if (!font_ok) {
624 logf("outer_draw: no usable font"); 650 logf("outer_draw: no usable font");
651 toastf(TOAST_ERROR, "No usable overlay font");
625 return; 652 return;
626 } 653 }
627 } 654 }
@@ -639,6 +666,8 @@ void outer_draw() {
639 } 666 }
640 if (gui_is_open()) 667 if (gui_is_open())
641 gui_draw(); 668 gui_draw();
669 if (toasts)
670 gui_draw_toasts();
642 surf_pop_make_current(panel); 671 surf_pop_make_current(panel);
643} 672}
644 673
@@ -697,13 +726,15 @@ static ISurface *find_surface_interface() {
697void install_menu() { 726void install_menu() {
698 register_bundled_font(); 727 register_bundled_font();
699 logf("config: %s", config_path().c_str()); 728 logf("config: %s", config_path().c_str());
700 config_load(); 729 if (!config_load())
730 toastf(TOAST_INFO, "No config found; using defaults");
701 gui_config_init(); 731 gui_config_init();
702 // resolve ISurface once (used by the DrawPrintText hook in hl2h.cpp and 732 // resolve ISurface once (used by the DrawPrintText hook in hl2h.cpp and
703 // by outer_draw). DrawPrintText hook is installed from hkdCreateMove. 733 // by outer_draw). DrawPrintText hook is installed from hkdCreateMove.
704 g_surface = find_surface_interface(); 734 g_surface = find_surface_interface();
705 if (!g_surface) { 735 if (!g_surface) {
706 logf("ISurface not found; menu disabled"); 736 logf("ISurface not found; menu disabled");
737 toastf(TOAST_ERROR, "Overlay unavailable: ISurface not found");
707 return; 738 return;
708 } 739 }
709 logf("ISurface = %p", g_surface); 740 logf("ISurface = %p", g_surface);