engine: reject mbf21 and shit24 wads. there is no way to know if it is safe to ignore...
[k8vavoom.git] / source / text.cpp
blob7c0991281d733fd3d40246110a577b53160510f6
1 //**************************************************************************
2 //**
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
9 //**
10 //** Copyright (C) 1999-2006 Jānis Legzdiņš
11 //** Copyright (C) 2018-2023 Ketmar Dark
12 //**
13 //** This program is free software: you can redistribute it and/or modify
14 //** it under the terms of the GNU General Public License as published by
15 //** the Free Software Foundation, version 3 of the License ONLY.
16 //**
17 //** This program is distributed in the hope that it will be useful,
18 //** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 //** GNU General Public License for more details.
21 //**
22 //** You should have received a copy of the GNU General Public License
23 //** along with this program. If not, see <http://www.gnu.org/licenses/>.
24 //**
25 //**************************************************************************
26 #include "gamedefs.h"
27 #include "widgets/ui.h"
28 #ifdef CLIENT
29 # include "drawer.h"
30 # include "screen.h"
31 # include "net/network.h" /* sorry */
32 # include "client/client.h"
33 #endif
34 #include "text.h"
35 #include "psim/p_player.h"
36 #include "server/server.h"
39 int NetLagChart[NETLAG_CHART_ITEMS] = {0};
40 unsigned NetLagChartPos = 0;
43 #ifdef CLIENT
44 extern VCvarB draw_lag;
47 //==========================================================================
49 // T_Init
51 //==========================================================================
52 void T_Init () {
53 VFont::StaticInit();
57 //==========================================================================
59 // T_Shutdown
61 //==========================================================================
62 void T_Shutdown () {
63 VFont::StaticShutdown();
67 //==========================================================================
69 // T_ToDrawerX
71 //==========================================================================
72 int T_ToDrawerX (int x) {
73 return GRoot->ToDrawerX(x);
77 //==========================================================================
79 // T_ToDrawerY
81 //==========================================================================
82 int T_ToDrawerY (int y) {
83 return GRoot->ToDrawerY(y);
87 //==========================================================================
89 // T_FromDrawerX
91 //==========================================================================
92 int T_FromDrawerX (int x) {
93 return GRoot->FromDrawerX(x);
97 //==========================================================================
99 // T_FromDrawerY
101 //==========================================================================
102 int T_FromDrawerY (int y) {
103 return GRoot->FromDrawerY(y);
107 //==========================================================================
109 // T_SetFont
111 //==========================================================================
112 void T_SetFont (VFont *AFont) {
113 GRoot->SetFont(AFont);
117 //==========================================================================
119 // T_SetFont
121 //==========================================================================
122 void T_SetFont (VName fontname) {
123 if (fontname == NAME_None) return;
124 VFont *f = VFont::GetFont(VStr(fontname)); // this doesn't allocate
125 if (f) T_SetFont(f);
129 //==========================================================================
131 // T_SetAlign
133 //==========================================================================
134 void T_SetAlign (halign_e NewHAlign, valign_e NewVAlign) {
135 GRoot->SetTextAlign(NewHAlign, NewVAlign);
139 //==========================================================================
141 // T_IsFontExists
143 //==========================================================================
144 bool T_IsFontExists (VName fontname) {
145 if (fontname == NAME_None) return false;
146 return !!VFont::GetFont(VStr(fontname)); // this doesn't allocate
150 //==========================================================================
152 // T_DrawText
154 //==========================================================================
155 void T_DrawText (int x, int y, VStr String, int col, float alpha) {
156 GRoot->DrawText(x, y, String, col, CR_YELLOW, alpha);
160 //==========================================================================
162 // T_TextWidth
164 //==========================================================================
165 int T_TextWidth (VStr s) {
166 return GRoot->TextWidth(s);
170 //==========================================================================
172 // T_StringWidth
174 //==========================================================================
175 int T_StringWidth (VStr s) {
176 return GRoot->StringWidth(s);
180 //==========================================================================
182 // T_TextHeight
184 //==========================================================================
185 int T_TextHeight (VStr s) {
186 return GRoot->TextHeight(s);
190 //==========================================================================
192 // T_FontHeight
194 //==========================================================================
195 int T_FontHeight () {
196 return GRoot->FontHeight();
200 //==========================================================================
202 // T_CursorWidth
204 //==========================================================================
205 int T_CursorWidth () {
206 return GRoot->CursorWidth();
210 //==========================================================================
212 // T_DrawCursor
214 //==========================================================================
215 void T_DrawCursor () {
216 GRoot->DrawCursor();
220 //==========================================================================
222 // T_DrawCursorAt
224 //==========================================================================
225 void T_DrawCursorAt (int x, int y) {
226 GRoot->DrawCursorAt(x, y, GRoot->GetCursorChar());
230 //==========================================================================
232 // T_DrawCursorAt
234 //==========================================================================
235 void T_DrawCursorAt (int x, int y, int cursorChar, int cursorColor) {
236 GRoot->DrawCursorAt(x, y, cursorChar, cursorColor);
240 //==========================================================================
242 // T_SetCursorPos
244 //==========================================================================
245 void T_SetCursorPos (int cx, int cy) {
246 GRoot->SetCursorPos(cx, cy);
250 //==========================================================================
252 // T_GetCursorX
254 //==========================================================================
255 int T_GetCursorX () {
256 return GRoot->GetCursorX();
260 //==========================================================================
262 // T_GetCursorY
264 //==========================================================================
265 int T_GetCursorY () {
266 return GRoot->GetCursorY();
270 int T_GetCursorChar () {
271 return GRoot->GetCursorChar();
273 #endif
276 //**************************************************************************
278 // loader messages and progress bar
280 //**************************************************************************
281 enum {
282 PBarHPad = 20+16,
283 PBarVPad = 20+16,
284 PBarHeight = 20,
288 static int currMsgNumber = 0;
289 static int currMsgType = OSD_MapLoading;
291 static int lastPBarWdt = -666;
292 static double pbarStartTime = 0.0;
293 static double pbarLastUpdateTime = 0.0;
294 static double pbarLastLagUpdateTime = 0.0;
295 static int pbarMaxLagWidth = 0;
297 int R_OSDMsgColorMain = CR_FIRE;
298 int R_OSDMsgColorSecondary = CR_ORANGE /*CR_PURPLE*/ /*CR_TEAL*/;
301 //==========================================================================
303 // R_IsDrawerInited
305 //==========================================================================
306 bool R_IsDrawerInited () {
307 #ifdef CLIENT
308 return (Drawer && Drawer->IsInited());
309 #else
310 return false;
311 #endif
315 //==========================================================================
317 // R_OSDMsgReset
319 //==========================================================================
320 void R_OSDMsgReset (int type, bool sendKeepalives) {
321 currMsgNumber = 0;
322 currMsgType = type;
323 if (sendKeepalives) NET_SendNetworkHeartbeat();
327 //==========================================================================
329 // R_OSDMsgShow
331 //==========================================================================
332 void R_OSDMsgShow (const char *msg, int clr, bool sendKeepalives) {
333 if (sendKeepalives) NET_SendNetworkHeartbeat();
334 #ifdef CLIENT
335 if (!msg || !msg[0]) return;
336 if (Drawer && Drawer->IsInited()) {
337 T_SetFont(SmallFont);
338 Drawer->StartUpdate();
339 T_SetAlign(hcenter, /*vcenter*/vtop);
340 // slightly off vcenter
341 int y;
342 switch (currMsgType) {
343 case OSD_MapLoading:
344 y = VirtualHeight/2+64;
345 if (clr == -666) clr = CR_TAN;
346 break;
347 case OSD_Network:
348 y = 8*T_FontHeight();
349 if (clr == -666) clr = CR_ICE;
350 //GRoot->FillRect(0, y+T_FontHeight()*currMsgNumber, VirtualWidth, T_FontHeight(), 0, 1.0f);
351 break;
352 default:
353 if (clr == -666) clr = CR_TEAL;
354 y = max2(4*T_FontHeight(), VirtualHeight/2-9*T_FontHeight());
355 //GRoot->ShadeRect(96, y+T_FontHeight()*currMsgNumber, VirtualWidth-96*2, T_FontHeight(), 0.666f);
356 break;
358 y += T_FontHeight()*currMsgNumber;
359 if (currMsgNumber == 0) {
360 GRoot->ShadeRect(96, y-T_FontHeight(), VirtualWidth-96*2, T_FontHeight()*3, 0.666f);
361 } else {
362 GRoot->ShadeRect(96, y+T_FontHeight(), VirtualWidth-96*2, T_FontHeight(), 0.666f);
364 T_DrawText(VirtualWidth/2, y, msg, clr);
365 Drawer->Update();
366 ++currMsgNumber;
368 #endif
372 //==========================================================================
374 // R_PBarReset
376 //==========================================================================
377 bool R_PBarReset (bool /*sendKeepalives*/) {
378 lastPBarWdt = -666;
379 pbarStartTime = Sys_Time();
380 pbarLastUpdateTime = 0;
381 pbarLastLagUpdateTime = 0;
382 pbarMaxLagWidth = 0;
383 #ifdef CLIENT
384 return (Drawer && Drawer->IsInited());
385 #else
386 return false;
387 #endif
391 #ifdef CLIENT
392 //==========================================================================
394 // RenderLag
396 //==========================================================================
397 static bool RenderLag () {
398 if (!cl || !cl->Net) return false;
399 double ctt = Sys_Time();
400 if (ctt-pbarLastLagUpdateTime <= 1.0) return false;
401 pbarLastLagUpdateTime = ctt;
402 const int nlag = clampval((int)((cl->Net->PrevLag+1.2*(max2(cl->Net->InLoss, cl->Net->OutLoss)*0.01))*1000), 0, 999);
403 //const int lag0 = clampval((int)(cl->Net->PrevLag*1000), 0, 999);
404 //const int lag1 = clampval((int)(cl->Net->AvgLag*1000), 0, 999);
405 T_SetFont(ConFont);
406 T_SetAlign(hleft, vtop);
407 int xpos = 4;
408 int ypos = 22;
409 VStr s0(va("NET LAG:%3d", nlag));
410 //VStr s1(va("LAGS :%3d %3d", lag0, lag1));
411 //pbarMaxLagWidth = max(pbarMaxLagWidth, max2(T_TextWidth(s0), T_TextWidth(s1))+4*2);
412 pbarMaxLagWidth = max2(pbarMaxLagWidth, T_TextWidth(s0)+4*2);
413 //GRoot->FillRect(xpos-4, ypos-4, pbarMaxLagWidth, T_FontHeight()*2+4*2, 0, 1.0f);
414 GRoot->FillRect(xpos-4, ypos-4, pbarMaxLagWidth, T_FontHeight()*1+4*2, 0, 1.0f);
415 T_DrawText(xpos, ypos, s0, CR_DARKBROWN); ypos += 9;
416 //T_DrawText(xpos, ypos, s1, CR_DARKBROWN); ypos += 9;
417 return true;
419 #endif
422 //==========================================================================
424 // R_PBarUpdate
426 //==========================================================================
427 bool R_PBarUpdate (const char *message, int cur, int max, bool forced, bool sendKeepalives) {
428 if (sendKeepalives) NET_SendNetworkHeartbeat();
430 if (forced && cur >= max && lastPBarWdt == -666) return false; // nothing was drawn at all
432 // check if we need to update pbar
433 // when we have drawer, delay first update by 800 msec, otherwise don't delay it
434 #ifdef CLIENT
435 if (!forced) {
436 if (Drawer && Drawer->IsInited()) {
437 if (lastPBarWdt == -666) {
438 if (Sys_Time()-pbarStartTime < 0.8) return false;
442 #endif
444 if (max < 1) return false; // alas
445 if (cur < 0) cur = 0;
446 if (cur > max) cur = max;
448 #ifdef CLIENT
449 if (Drawer && Drawer->IsInited()) {
450 int wdt = cur*(Drawer->getWidth()-PBarHPad*2)/max;
451 if (!forced && wdt == lastPBarWdt) {
452 if (draw_lag && cl && cl->Net) {
453 if (RenderLag()) Drawer->Update();
455 return false;
457 // delay update if it is too often
458 const double currt = Sys_Time();
459 if (!forced && currt-pbarLastUpdateTime < 1.0/30.0) return false;
460 pbarLastUpdateTime = currt;
461 lastPBarWdt = wdt;
462 Drawer->StartUpdate();
463 // load progressbar textures
464 static bool texturesLoaded = false;
465 static int left = -1, right = -1, mid = -1, fill = -1;
466 if (!texturesLoaded) {
467 texturesLoaded = true;
468 left = GTextureManager.AddFileTextureChecked("graphics/progbar/progbar_left.png", TEXTYPE_Pic);
469 if (left > 0) right = GTextureManager.AddFileTextureChecked("graphics/progbar/progbar_right.png", TEXTYPE_Pic);
470 if (right > 0) mid = GTextureManager.AddFileTextureChecked("graphics/progbar/progbar_middle.png", TEXTYPE_Pic);
471 if (mid > 0) fill = GTextureManager.AddFileTextureChecked("graphics/progbar/progbar_marker.png", TEXTYPE_Pic);
473 // which kind of progress bar to draw?
474 if (left > 0) {
475 VTexture *tex;
476 // left end
477 tex = GTextureManager(left);
478 Drawer->DrawPic(
479 PBarHPad-8, Drawer->getHeight()-PBarVPad-PBarHeight, PBarHPad, Drawer->getHeight()-PBarVPad-PBarHeight+32,
480 0, 0, tex->GetWidth(), tex->GetHeight(), tex, nullptr, 1.0f);
481 // right end
482 tex = GTextureManager(right);
483 Drawer->DrawPic(
484 Drawer->getWidth()-PBarHPad, Drawer->getHeight()-PBarVPad-PBarHeight, Drawer->getWidth()-PBarHPad+8, Drawer->getHeight()-PBarVPad-PBarHeight+32,
485 0, 0, tex->GetWidth(), tex->GetHeight(), tex, nullptr, 1.0f);
486 // middle
487 tex = GTextureManager(mid);
488 Drawer->FillRectWithFlatRepeat(
489 PBarHPad, Drawer->getHeight()-PBarVPad-PBarHeight, Drawer->getWidth()-PBarHPad, Drawer->getHeight()-PBarVPad-PBarHeight+32,
490 0, 0, /*tex->GetWidth()*/(Drawer->getWidth()-PBarHPad)*2, tex->GetHeight(), tex);
491 // fill
492 if (wdt > 0) {
493 tex = GTextureManager(fill);
494 Drawer->FillRectWithFlatRepeat(
495 PBarHPad, Drawer->getHeight()-PBarVPad-PBarHeight, PBarHPad+wdt, Drawer->getHeight()-PBarVPad-PBarHeight+32,
496 0, 0, /*tex->GetWidth()*/wdt, tex->GetHeight(), tex);
498 } else {
499 Drawer->FillRect(PBarHPad-2, Drawer->getHeight()-PBarVPad-PBarHeight-2, Drawer->getWidth()-PBarHPad+2, Drawer->getHeight()-PBarVPad+2, 0xffffffff);
500 Drawer->FillRect(PBarHPad-1, Drawer->getHeight()-PBarVPad-PBarHeight-1, Drawer->getWidth()-PBarHPad+1, Drawer->getHeight()-PBarVPad+1, 0xff000000);
501 Drawer->FillRect(PBarHPad, Drawer->getHeight()-PBarVPad-PBarHeight, Drawer->getWidth()-PBarHPad, Drawer->getHeight()-PBarVPad, 0xff8f0f00);
502 if (wdt > 0) Drawer->FillRect(PBarHPad, Drawer->getHeight()-PBarVPad-PBarHeight, PBarHPad+wdt, Drawer->getHeight()-PBarVPad, 0xffff7f00);
504 if (draw_lag && cl && cl->Net) RenderLag();
505 Drawer->Update();
506 } else
507 #endif
508 // textual
510 double currt = Sys_Time();
511 if (!forced && currt-pbarLastUpdateTime < 2.0) return false;
512 pbarLastUpdateTime = currt;
513 int prc = cur*100/max;
514 if (!message) message = "PROCESSING";
515 GCon->Logf("%s: %02d%% done (%d of %d)", message, prc, cur-1, max);
517 return true;