47 changes: 26 additions & 21 deletions data/languages/polish.txt
Expand Up @@ -149,9 +149,6 @@ Favorites
Feet
== Stopy

Filter
== Filtr

Fire
== Strzał

Expand All @@ -164,9 +161,6 @@ Force vote
Free-View
== Wolna kamera

Friends
== Znajomi

Fullscreen
== Pełny ekran

Expand Down Expand Up @@ -360,12 +354,6 @@ Screenshot
Server address:
== Adres serwera:

Server details
== Szczegóły serwera

Server filter
== Filtr serwerów

Server info
== Info serwera

Expand Down Expand Up @@ -551,9 +539,6 @@ Netversion:
Map:
== Mapa:

Info
== Info

Hue
== Kolor

Expand Down Expand Up @@ -1465,12 +1450,35 @@ Pause the current demo
Stop the current demo
==

Go back the specified duration
==

[Demo player duration]
%d min.
==

[Demo player duration]
%d sec.
==

Change the skip duration
==

Go forward the specified duration
==

Go back one tick
==

Go forward one tick
==

Go back one marker
==

Go forward one marker
==

Slow down the demo
==

Expand All @@ -1486,12 +1494,6 @@ Mark the end of a cut (right click to reset)
Export cut as a separate demo
==

Go back one marker
==

Go forward one marker
==

Close the demo player
==

Expand All @@ -1507,6 +1509,9 @@ Cut interval
Cut length
==

Render cut to video
==

Loading demo files
==

Expand Down
67 changes: 36 additions & 31 deletions data/languages/portuguese.txt
Expand Up @@ -152,9 +152,6 @@ Favorites
Feet
== Pés

Filter
== Filtro

Fire
== Disparar

Expand All @@ -167,9 +164,6 @@ Force vote
Free-View
== Vista Livre

Friends
== Amigos

Fullscreen
== Ecrã inteiro

Expand Down Expand Up @@ -375,12 +369,6 @@ Screenshot
Server address:
== Endereço do servidor:

Server details
== Detalhes do servidor

Server filter
== Filtro de servidores

Server info
== Info de servidor

Expand Down Expand Up @@ -549,9 +537,6 @@ Map:
FSAA samples
== Amostras FSAA

Info
== Info

Miscellaneous
== Diversos

Expand Down Expand Up @@ -1183,12 +1168,35 @@ Pause the current demo
Stop the current demo
==

Go back the specified duration
==

[Demo player duration]
%d min.
==

[Demo player duration]
%d sec.
==

Change the skip duration
==

Go forward the specified duration
==

Go back one tick
==

Go forward one tick
==

Go back one marker
==

Go forward one marker
==

Slow down the demo
==

Expand All @@ -1204,12 +1212,6 @@ Mark the end of a cut (right click to reset)
Export cut as a separate demo
==

Go back one marker
==

Go forward one marker
==

Close the demo player
==

Expand All @@ -1225,6 +1227,9 @@ Cut interval
Cut length
==

Render cut to video
==

Loading demo files
==

Expand Down Expand Up @@ -1309,10 +1314,10 @@ Open the directory that contains the configuration and user files
Open the directory to add custom themes
==

Loading skin files
Toggle to edit your dummy settings
==

Toggle to edit your dummy settings
Loading skin files
==

Download skins
Expand Down Expand Up @@ -1357,19 +1362,22 @@ Show all
Toggle dyncam
==

Toggle dummy
Toggle ghost
==

Toggle ghost
Converse
==

Dummy copy
Chat command
==

Hammerfly dummy
Toggle dummy
==

Converse
Dummy copy
==

Hammerfly dummy
==

Statboard
Expand All @@ -1384,9 +1392,6 @@ Show entities
Show HUD
==

Chat command
==

Enable controller
==

Expand Down
67 changes: 36 additions & 31 deletions data/languages/romanian.txt
Expand Up @@ -151,9 +151,6 @@ Favorites
Feet
== Picioare

Filter
== Filtre

Fire
== Foc

Expand All @@ -166,9 +163,6 @@ Force vote
Free-View
== Vizualizare liberă

Friends
== Prieteni

Fullscreen
== Ecrat complet

Expand Down Expand Up @@ -365,12 +359,6 @@ Screenshot
Server address:
== Adresă server:

Server details
== Detalii server

Server filter
== Filtru servere:

Server info
== Info. server

Expand Down Expand Up @@ -544,9 +532,6 @@ Netversion:
Map:
== Harta:

Info
== Informații

Hue
== Tentă

Expand Down Expand Up @@ -920,12 +905,35 @@ Pause the current demo
Stop the current demo
==

Go back the specified duration
==

[Demo player duration]
%d min.
==

[Demo player duration]
%d sec.
==

Change the skip duration
==

Go forward the specified duration
==

Go back one tick
==

Go forward one tick
==

Go back one marker
==

Go forward one marker
==

Slow down the demo
==

Expand All @@ -941,12 +949,6 @@ Mark the end of a cut (right click to reset)
Export cut as a separate demo
==

Go back one marker
==

Go forward one marker
==

Close the demo player
==

Expand All @@ -965,6 +967,9 @@ Cut length
Remove chat
==

Render cut to video
==

Please use a different name
==

Expand Down Expand Up @@ -1115,10 +1120,10 @@ Max CSVs
Dummy settings
==

Loading skin files
Toggle to edit your dummy settings
==

Toggle to edit your dummy settings
Loading skin files
==

Download skins
Expand Down Expand Up @@ -1172,19 +1177,22 @@ Show all
Toggle dyncam
==

Toggle dummy
Toggle ghost
==

Toggle ghost
Converse
==

Dummy copy
Chat command
==

Hammerfly dummy
Toggle dummy
==

Converse
Dummy copy
==

Hammerfly dummy
==

Statboard
Expand All @@ -1199,9 +1207,6 @@ Show entities
Show HUD
==

Chat command
==

Enable controller
==

Expand Down
69 changes: 38 additions & 31 deletions data/languages/russian.txt
Expand Up @@ -16,6 +16,8 @@
# banan 2022-06-12 11:36:50
# ban 2023-01-5 10:22:50
# unban 2023-03-10 21:50:50
# eblan 2023-08-07 14:27:00
# kaban 2023-9-21 19:00:00
##### /authors #####

##### translated strings #####
Expand Down Expand Up @@ -158,9 +160,6 @@ Favorites
Feet
== Ноги

Filter
== Фильтр

Fire
== Стрелять

Expand All @@ -173,9 +172,6 @@ Force vote
Free-View
== Свободный обзор

Friends
== Друзья

Fullscreen
== Полноэкранный(настр.)

Expand Down Expand Up @@ -369,12 +365,6 @@ Screenshot
Server address:
== Адрес сервера:

Server details
== Сведения сервера

Server filter
== Фильтр серверов

Server info
== Информация

Expand Down Expand Up @@ -606,9 +596,6 @@ Netversion:
Map:
== Карта:

Info
== Инфо

Hue
== Оттен.

Expand Down Expand Up @@ -769,7 +756,7 @@ Please enter your nickname below.
== Пожалуйста, ниже укажите ваш псевдоним.

Video name:
== Название видео:
== Название:

Show DDNet map finishes in server browser
== Показывать в браузере статус завершения карты
Expand Down Expand Up @@ -1694,10 +1681,10 @@ No server selected
== Не выбран сервер

Mark the beginning of a cut (right click to reset)
== Отметить начало отрезка (щелкните правой кнопкой мыши, чтобы сбросить)
== Отметить начало отрезка (нажмите ПКМ, чтобы сбросить)

Mark the end of a cut (right click to reset)
== Отметить конец отрезка (щелкните правой кнопкой мыши, чтобы сбросить)
== Отметить конец отрезка (нажмите ПКМ, чтобы сбросить)

Close the demo player
== Закрыть проигрыватель демок
Expand All @@ -1718,40 +1705,60 @@ Graphics card
== Видеокарта

Quitting. Please wait…
==
== Выход из игры. Пожалуйста, подождите...

Restarting. Please wait…
==
== Перезапуск игры. Пожалуйста, подождите...

Multi-View
==
== Мульти-Просмотр

Rename folder
==
== Переименовать папку

A folder with this name already exists
==
== Папка с таким именем уже существует

Unable to rename the folder
==
== Невозможно переименовать папку

(paused)
==
== (приостановленно)

All combined
==
== Все вместе

Folder Link
==
== Ссылка на папку

Are you sure that you want to delete the folder '%s'?
==
== Вы уверены, что хотите удалить папку '%s'?

Delete folder
==
== Удалить папку

Unable to delete the folder '%s'. Make sure it's empty first.
==
== Невозможно удалить папку '%s'. Сначала убедитесь, что она пуста.

Moved ingame
==
== Перемещены в игре

Go back the specified duration
== Отмотать назад на заданное время

[Demo player duration]
%d min.
== %d мин.

[Demo player duration]
%d sec.
== %d сек.

Change the skip duration
== Изменение времени перехода

Go forward the specified duration
== Отмотать вперед заданное время

Render cut to video
== Рендеринг отрезка в видео
216 changes: 110 additions & 106 deletions data/languages/serbian.txt

Large diffs are not rendered by default.

47 changes: 26 additions & 21 deletions data/languages/serbian_cyrillic.txt
Expand Up @@ -145,9 +145,6 @@ Favorites
Feet
== Стопала

Filter
== Филтер

Fire
== Пуцај

Expand All @@ -160,9 +157,6 @@ Force vote
Free-View
== Слободан преглед

Friends
== Пријатељи

Fullscreen
== Преко целог екрана

Expand Down Expand Up @@ -352,12 +346,6 @@ Screenshot
Server address:
== Адреса сервера:

Server details
== Детаљи о серверу

Server filter
== Филтер сервера

Server info
== О серверу

Expand Down Expand Up @@ -558,9 +546,6 @@ Netversion:
Map:
== Мапа

Info
== Инфо

Hue
== Нијанса

Expand Down Expand Up @@ -1601,12 +1586,35 @@ Pause the current demo
Stop the current demo
==

Go back the specified duration
==

[Demo player duration]
%d min.
==

[Demo player duration]
%d sec.
==

Change the skip duration
==

Go forward the specified duration
==

Go back one tick
==

Go forward one tick
==

Go back one marker
==

Go forward one marker
==

Slow down the demo
==

Expand All @@ -1622,12 +1630,6 @@ Mark the end of a cut (right click to reset)
Export cut as a separate demo
==

Go back one marker
==

Go forward one marker
==

Close the demo player
==

Expand All @@ -1643,6 +1645,9 @@ Cut interval
Cut length
==

Render cut to video
==

All combined
==

Expand Down
64 changes: 35 additions & 29 deletions data/languages/simplified_chinese.txt
Expand Up @@ -34,6 +34,7 @@
# 2023-04-01 cheeser0613
# 2023-05-21 RemakePower
# 2023-07-20 By
# 2023-08-11 By
##### /authors #####

##### translated strings #####
Expand Down Expand Up @@ -176,9 +177,6 @@ Favorites
Feet
== 脚

Filter
== 筛选

Fire
== 开火

Expand All @@ -189,10 +187,7 @@ Force vote
== 强制投票

Free-View
== 自由视野

Friends
== 好友
== 自由视角

Fullscreen
== 独占全屏
Expand Down Expand Up @@ -414,12 +409,6 @@ Screenshot
Server address:
== 服务器地址:

Server details
== 服务器详情

Server filter
== 服务器筛选

Server info
== 服务器信息

Expand Down Expand Up @@ -615,9 +604,6 @@ Netversion:
Map:
== 地图:

Info
== 信息

Hue
== 色调

Expand Down Expand Up @@ -1724,7 +1710,7 @@ Mark the end of a cut (right click to reset)
== 标记裁剪终点 (右键重置)

Close the demo player
== 关闭回放播放器
== 关闭回放

Export demo cut
== 另存裁剪部分
Expand All @@ -1742,40 +1728,60 @@ Graphics card
== 显卡

Quitting. Please wait…
==
== 正在退出,请稍等

Restarting. Please wait…
==
== 正在重启,请稍等

Multi-View
==
== 多人同框视角

Rename folder
==
== 重命名文件夹

A folder with this name already exists
==
== 已经存在同名文件夹

Unable to rename the folder
==
== 无法重命名这个文件夹

(paused)
==
== (暂停)

All combined
==
== 全部文件

Folder Link
==
== 文件夹链接

Are you sure that you want to delete the folder '%s'?
==
== 你确定要删除文件夹 "%s" ?

Delete folder
==
== 删除文件夹

Unable to delete the folder '%s'. Make sure it's empty first.
==
== 无法删除 "%s" ,请确保你已清空该文件夹

Moved ingame
== 游戏内移动

Go back the specified duration
==

[Demo player duration]
%d min.
==

[Demo player duration]
%d sec.
==

Change the skip duration
==

Go forward the specified duration
==

Render cut to video
==
67 changes: 36 additions & 31 deletions data/languages/slovak.txt
Expand Up @@ -145,9 +145,6 @@ Favorites
Feet
== Nohy

Filter
== Filter

Fire
== Streľba

Expand All @@ -160,9 +157,6 @@ Force vote
Free-View
== Voľná Kamera

Friends
== Priatelia

Fullscreen
== Celá obrazovka

Expand Down Expand Up @@ -356,12 +350,6 @@ Screenshot
Server address:
== Adresa servera:

Server details
== Detaily servera

Server filter
== Filter serverov

Server info
== Informácie

Expand Down Expand Up @@ -532,9 +520,6 @@ Netversion:
Map:
== Mapa:

Info
== Info

Hue
== Hue

Expand Down Expand Up @@ -911,12 +896,35 @@ Pause the current demo
Stop the current demo
==

Go back the specified duration
==

[Demo player duration]
%d min.
==

[Demo player duration]
%d sec.
==

Change the skip duration
==

Go forward the specified duration
==

Go back one tick
==

Go forward one tick
==

Go back one marker
==

Go forward one marker
==

Slow down the demo
==

Expand All @@ -932,12 +940,6 @@ Mark the end of a cut (right click to reset)
Export cut as a separate demo
==

Go back one marker
==

Go forward one marker
==

Close the demo player
==

Expand All @@ -956,6 +958,9 @@ Cut length
Remove chat
==

Render cut to video
==

Please use a different name
==

Expand Down Expand Up @@ -1106,10 +1111,10 @@ Max CSVs
Dummy settings
==

Loading skin files
Toggle to edit your dummy settings
==

Toggle to edit your dummy settings
Loading skin files
==

Download skins
Expand Down Expand Up @@ -1163,19 +1168,22 @@ Show all
Toggle dyncam
==

Toggle dummy
Toggle ghost
==

Toggle ghost
Converse
==

Dummy copy
Chat command
==

Hammerfly dummy
Toggle dummy
==

Converse
Dummy copy
==

Hammerfly dummy
==

Statboard
Expand All @@ -1190,9 +1198,6 @@ Show entities
Show HUD
==

Chat command
==

Enable controller
==

Expand Down
61 changes: 33 additions & 28 deletions data/languages/spanish.txt
Expand Up @@ -164,9 +164,6 @@ Favorites
Feet
== Pies

Filter
== Filtro

Fire
== Disparar

Expand All @@ -179,9 +176,6 @@ Force vote
Free-View
== Vista libre

Friends
== Amigos

Fullscreen
== Pantalla completa

Expand Down Expand Up @@ -378,12 +372,6 @@ Screenshot
Server address:
== IP del servidor:

Server details
== Detalles del servidor

Server filter
== Filtro del servidor

Server info
== Servidor

Expand Down Expand Up @@ -557,9 +545,6 @@ Netversion:
Map:
== Mapa:

Info
== Información

Hue
== Matiz

Expand Down Expand Up @@ -1726,40 +1711,60 @@ Graphics card
== Tarjeta gráfica

Quitting. Please wait…
==
== Saliendo. Por favor, espera…

Restarting. Please wait…
==
== Reiniciando. Por favor, espera…

Multi-View
==
== Vista Múltiple

Rename folder
==
== Renombrar carpeta

A folder with this name already exists
==
== Ya existe una carpeta con este nombre

Unable to rename the folder
==
== No se pudo renombrar la carpeta

(paused)
==
== (en pausa)

All combined
==
== Todo combinado

Folder Link
==
== Enlace de la carpeta

Are you sure that you want to delete the folder '%s'?
==
== ¿Seguro que quieres eliminar la carpeta '%s'?

Delete folder
==
== Eliminar carpeta

Unable to delete the folder '%s'. Make sure it's empty first.
==
== No se pudo eliminar la carpeta '%s'. Asegúrate de que esté vacía primero.

Moved ingame
==
== Movido dentro del juego

Go back the specified duration
== Retroceder el tiempo especificado

[Demo player duration]
%d min.
== %d min.

[Demo player duration]
%d sec.
== %d seg.

Change the skip duration
== Cambiar duración del salto

Go forward the specified duration
== Adelantar el tiempo especificado

Render cut to video
== Renderizar corte a vídeo
408 changes: 207 additions & 201 deletions data/languages/swedish.txt

Large diffs are not rendered by default.

62 changes: 34 additions & 28 deletions data/languages/traditional_chinese.txt
Expand Up @@ -23,6 +23,7 @@
# 2023-04-01 cheeser0613
# 2023-05-25 cheeser0613
# 2023-07-20 By
# 2023-08-11 By
##### /authors #####

##### translated strings #####
Expand Down Expand Up @@ -165,9 +166,6 @@ Favorites
Feet
== 腳

Filter
== 過濾器

Fire
== 開火

Expand All @@ -180,9 +178,6 @@ Force vote
Free-View
== 自由視角

Friends
== 好友

Fullscreen
== 獨占全螢幕

Expand Down Expand Up @@ -403,12 +398,6 @@ Screenshot
Server address:
== 伺服器地址:

Server details
== 伺服器詳細資訊

Server filter
== 伺服器過濾器

Server info
== 伺服器資訊

Expand Down Expand Up @@ -604,9 +593,6 @@ Netversion:
Map:
== 地圖:

Info
== 資訊

Hue
== 色調

Expand Down Expand Up @@ -1713,7 +1699,7 @@ Mark the end of a cut (right click to reset)
== 標記裁剪終點 (右鍵重置)

Close the demo player
== 關閉回放播放器
== 關閉回放

Export demo cut
== 另存裁剪部分
Expand All @@ -1731,40 +1717,60 @@ Graphics card
== 顯示卡

Quitting. Please wait…
==
== 正在退出,請稍等

Restarting. Please wait…
==
== 正在重啟,請稍等

Multi-View
==
== 多人同框視角

Rename folder
==
== 重新命名資料夾

A folder with this name already exists
==
== 已經存在同名資料夾

Unable to rename the folder
==
== 無法重新命名這個資料夾

(paused)
==
== (暫停)

All combined
==
== 全部檔案

Folder Link
==
== 資料夾連結

Are you sure that you want to delete the folder '%s'?
==
== 你確定要刪除資料夾 "%s" ?

Delete folder
==
== 刪除資料夾

Unable to delete the folder '%s'. Make sure it's empty first.
==
== 無法刪除 "%s" ,請確保你已清空該資料夾

Moved ingame
== 遊戲內移動

Go back the specified duration
==

[Demo player duration]
%d min.
==

[Demo player duration]
%d sec.
==

Change the skip duration
==

Go forward the specified duration
==

Render cut to video
==
512 changes: 260 additions & 252 deletions data/languages/turkish.txt

Large diffs are not rendered by default.

105 changes: 55 additions & 50 deletions data/languages/ukrainian.txt
Expand Up @@ -94,14 +94,11 @@ Favorites
Feet
== Ноги

Filter
== Фільтр

Fire
== Постріл

Folder
== Папка
== Папку

Force vote
== Форсувати
Expand Down Expand Up @@ -188,7 +185,7 @@ Nickname
== Нік

No
== Ні
== Немає

No password
== Без пароля
Expand Down Expand Up @@ -266,9 +263,6 @@ Scoreboard
Screenshot
== Скріншот

Server details
== Деталі сервера

Server info
== Інформація

Expand Down Expand Up @@ -379,9 +373,6 @@ FSAA samples
Your skin
== Ваш скін

Info
== Інформація

Hue
== Відтінок

Expand Down Expand Up @@ -473,7 +464,7 @@ Are you sure that you want to disconnect?
== Ви впевнені, що хочете відключитися?

Disconnect Dummy
== Відключити Dummy
== Відключити даммі

Are you sure that you want to disconnect your dummy?
== Ви впевнені, що хочете відключити свого даммі?
Expand Down Expand Up @@ -532,9 +523,6 @@ Search
Exclude
== Виключити

Server filter
== Фільтр серверів

Count players only
== Рахувати тільки гравців

Expand Down Expand Up @@ -565,9 +553,6 @@ Countries
Types
== Типи

Friends
== Друзі

Remove
== Видалити

Expand Down Expand Up @@ -656,7 +641,7 @@ Fetch Info
== Отримати інформацію

Rename
== Перейменуватися
== Перейменувати

Render
== Почати рендер
Expand Down Expand Up @@ -746,7 +731,7 @@ Max CSVs
== Максимум CSV

Dummy settings
== Налаштування dummy
== Налаштування даммі

Vanilla skins only
== Тільки базові скіни
Expand Down Expand Up @@ -1094,7 +1079,7 @@ Getting server list from master server
== %d З %d сервера

%d players
== %dГравців
== %d Гравців

%d player
== %d Гравець
Expand All @@ -1112,7 +1097,7 @@ Smooth Dynamic Camera
== Гладка динамічна камера

Skip the main menu
== пропускати головне меняю
== Пропускати головне меню

Themes directory
== Каталог тем
Expand All @@ -1124,10 +1109,10 @@ Skin Database
== Бази даних скінів

Skins directory
== Каталог скінав
== Каталог скінів

Chat command
== командний чат
== Чат для команд

Dummy
== Даммі
Expand Down Expand Up @@ -1169,10 +1154,10 @@ Background
== Задній фон

Entities Background color
== колір текстури заднього фону
== Колір текстури заднього фону

Use current map as background
== використовувати поточну карту як задній фон
== Використовувати поточну карту як задній фон

Regular Background Color
== Звичайний колір заднього фону
Expand All @@ -1184,7 +1169,7 @@ Emoticons
== Емоції

Particles
== частинки
== Частинки

Assets directory
== Каталог текстур
Expand Down Expand Up @@ -1677,70 +1662,90 @@ Loading sound files
== Завантаження звукових файлів

Quitting. Please wait…
==
== Припинення гри. Зачекайте будь ласка...

Restarting. Please wait…
==
== Перезавантаження. Зачекайте будь ласка...

Multi-View
==
== Дінамічний перегляд

Rename folder
==
== Перейменувати папку

A demo with this name already exists
==
== Демо з такою назвою вже існує

A folder with this name already exists
==
== Папка с такою назвою вже існує

Unable to rename the folder
==
== Неможливо перейменувати папку

(paused)
==
== (пауза)

No server selected
==
== Жоден сервер не вибран

Mark the beginning of a cut (right click to reset)
==
== Позначте початок відрізка (натисніть праву кнопку миші, щоб скинути позначку)

Mark the end of a cut (right click to reset)
==
== Позначте кінець відрізка (натисніть праву кнопку миші, щоб скинути позначку)

Close the demo player
==
== Закрити програвач демо

Export demo cut
==
== Експорт відрізку з демо

Cut interval
==
== Інтервал відрізку

Cut length
==
== Довжина відрізку

All combined
==
== Все разом

Folder Link
==
== Посилання папки

Are you sure that you want to delete the folder '%s'?
==
== Ви впевнені, що хочете видалити папку '%s'?

Delete folder
==
== Видалити папку

Unable to delete the folder '%s'. Make sure it's empty first.
==
== Неможливо видалити папку '%s'. Спочатку переконайтеся, що вона порожня.

Axis
==
== Вісь

Graphics card
==
== Відеокарта

Moved ingame
==
== Перемістився в грі

Go back the specified duration
== Повернутися на вказаний проміжок часу

[Demo player duration]
%d min.
== %d хв.

[Demo player duration]
%d sec.
== %d сек.

Change the skip duration
== Змінити тривалість пропуску

Go forward the specified duration
== Перейти вперед на вказаний проміжок часу

Render cut to video
== Відтворити вирізку відео
Binary file modified data/skins/default.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 13 additions & 4 deletions datasrc/network.py
Expand Up @@ -26,7 +26,7 @@
]
GameInfoFlags2 = [
"ALLOW_X_SKINS", "GAMETYPE_CITY", "GAMETYPE_FDDRACE", "ENTITIES_FDDRACE", "HUD_HEALTH_ARMOR", "HUD_AMMO",
"HUD_DDRACE", "NO_WEAK_HOOK"
"HUD_DDRACE", "NO_WEAK_HOOK", "NO_SKIN_CHANGE_FOR_FROZEN"
]
ExPlayerFlags = ["AFK", "PAUSED", "SPEC"]
LegacyProjectileFlags = [f"CLIENTID_BIT{i}" for i in range(8)] + [
Expand All @@ -36,6 +36,9 @@
ProjectileFlags = [
"BOUNCE_HORIZONTAL", "BOUNCE_VERTICAL", "EXPLOSIVE", "FREEZE", "NORMALIZE_VEL",
]
LaserFlags = [
"NO_PREDICT",
]

LaserTypes = ["RIFLE", "SHOTGUN", "DOOR", "FREEZE", "DRAGGER", "GUN", "PLASMA"]
DraggerTypes = ["WEAK", "WEAK_NW", "NORMAL", "NORMAL_NW", "STRONG", "STRONG_NW"]
Expand Down Expand Up @@ -71,7 +74,7 @@
enum
{
GAMEINFO_CURVERSION=8,
GAMEINFO_CURVERSION=9,
};
'''

Expand Down Expand Up @@ -100,6 +103,7 @@
Flags("EXPLAYERFLAG", ExPlayerFlags),
Flags("LEGACYPROJECTILEFLAG", LegacyProjectileFlags),
Flags("PROJECTILEFLAG", ProjectileFlags),
Flags("LASERFLAG", LaserFlags),
]

Objects = [
Expand Down Expand Up @@ -294,6 +298,7 @@
NetIntAny("m_Type"),
NetIntAny("m_SwitchNumber", -1),
NetIntAny("m_Subtype", -1),
NetIntAny("m_Flags", 0),
]),

NetObjectEx("DDNetProjectile", "ddnet-projectile@netobj.ddnet.tw", [
Expand Down Expand Up @@ -401,7 +406,7 @@
]),

NetMessage("Sv_TuneParams", []),
NetMessage("Sv_ExtraProjectile", []),
NetMessage("Unused", []),
NetMessage("Sv_ReadyToEnter", []),

NetMessage("Sv_WeaponPickup", [
Expand Down Expand Up @@ -509,7 +514,7 @@
NetIntAny("m_PlayerTimeBest"),
]),

NetMessage("Unused", []),
NetMessage("Unused2", []),

NetMessage("Sv_TeamsStateLegacy", []),

Expand Down Expand Up @@ -549,4 +554,8 @@
NetIntRange("m_Team", 0, 'MAX_CLIENTS-1'),
NetIntRange("m_First", -1, 'MAX_CLIENTS-1'),
]),

NetMessageEx("Sv_YourVote", "yourvote@netmsg.ddnet.org", [
NetIntRange("m_Voted", -1, 1),
]),
]
2 changes: 1 addition & 1 deletion datasrc/seven/network.py
Expand Up @@ -294,7 +294,7 @@
]),

NetMessage("Sv_TuneParams", []),
NetMessage("Sv_ExtraProjectile", []),
NetMessage("Unused", []),
NetMessage("Sv_ReadyToEnter", []),

NetMessage("Sv_WeaponPickup", [
Expand Down
4 changes: 2 additions & 2 deletions other/bundle/client/Info.plist.in
Expand Up @@ -5,9 +5,9 @@
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${TARGET_CLIENT}</string>
<string>${CLIENT_EXECUTABLE}</string>
<key>CFBundleIconFile</key>
<string>${TARGET_CLIENT}</string>
<string>${CLIENT_EXECUTABLE}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
Expand Down
4 changes: 2 additions & 2 deletions other/bundle/server/Info.plist.in
Expand Up @@ -5,9 +5,9 @@
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${TARGET_SERVER_LAUNCHER}</string>
<string>${SERVER_EXECUTABLE}-Launcher</string>
<key>CFBundleIconFile</key>
<string>${TARGET_SERVER}</string>
<string>${SERVER_EXECUTABLE}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
Expand Down
3 changes: 3 additions & 0 deletions other/vscode/README.md
Expand Up @@ -10,5 +10,8 @@ Optional:
- mold (linker), needs to be in PATH
- ninja

Linux (x11):
- xdotool, for automatic mouse release

Inside vscode press `Ctrl+Shift+P` and type `Scan for kits`, press enter.
Now press press `Ctrl+Shift+P` and type `Select a kit`, choose one with `[DDNet]` as prefix for best defaults.
1 change: 1 addition & 0 deletions other/vscode/ddnet.code-workspace
Expand Up @@ -79,6 +79,7 @@
// https://aur.archlinux.org/packages/clang-format-static-bin
"clang-format.executable": "clang-format-10",
"lldb.launch.expressions": "native",
"lldb.launch.initCommands": ["target stop-hook add --one-liner \"command script import ${workspaceFolder}/other/vscode/lldbinit.py\""],
"editor.defaultFormatter": "xaver.clang-format",
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer",
Expand Down
15 changes: 15 additions & 0 deletions other/vscode/lldbinit.py
@@ -0,0 +1,15 @@
#!/usr/bin/python
import os
import shutil

# make sure to have the x11 package xdotool installed on your system
def check_global_executable_exists(executable_name):
return shutil.which(executable_name) is not None

def is_x11_session():
return "DISPLAY" in os.environ and "WAYLAND_DISPLAY" not in os.environ

if is_x11_session() and check_global_executable_exists("xdotool"):
print("Breakpoint hit, releasing mouse!")
os.system("setxkbmap -option grab:break_actions")
os.system("xdotool key XF86Ungrab")
34 changes: 21 additions & 13 deletions scripts/send_named_pipe.ps1
Expand Up @@ -4,7 +4,7 @@
# The second argument is the message to send.
if ($args.length -lt 2) {
Write-Output "Usage: ./send_named_pipe.ps1 <pipename> <message> [message] ... [message]"
return
exit -1
}

$Wrapper = [pscustomobject]@{
Expand All @@ -18,16 +18,24 @@ $Wrapper = [pscustomobject]@{
Reader = $null
Writer = $null
}
$Wrapper.Pipe.Connect(5000)
if (!$?) {
return
try {
$Wrapper.Pipe.Connect(5000)
$Wrapper.Reader = New-Object System.IO.StreamReader($Wrapper.Pipe)
$Wrapper.Writer = New-Object System.IO.StreamWriter($Wrapper.Pipe)
$Wrapper.Writer.AutoFlush = $true
for ($i = 1; $i -lt $args.length; $i++) {
$Wrapper.Writer.WriteLine($args[$i])
}
# Wait for pipe contents to be read.
$Wrapper.Pipe.WaitForPipeDrain()
# Dispose the pipe, which also calls Flush and Close.
$Wrapper.Pipe.Dispose()
# Explicity set error level 0 for success, as otherwise the current error level is kept.
exit 0
} catch [TimeoutException] {
Write-Output "Timeout connecting to pipe"
exit 1
} catch [System.IO.IOException] {
Write-Output "Broken pipe"
exit 2
}
$Wrapper.Reader = New-Object System.IO.StreamReader($Wrapper.Pipe)
$Wrapper.Writer = New-Object System.IO.StreamWriter($Wrapper.Pipe)
$Wrapper.Writer.AutoFlush = $true
for ($i = 1; $i -lt $args.length; $i++) {
$Wrapper.Writer.WriteLine($args[$i])
}
# We need to wait because the lines will not be written if we close the pipe immediately
Start-Sleep -Seconds 1.5
$Wrapper.Pipe.Close()
3 changes: 2 additions & 1 deletion src/antibot/antibot_data.h
Expand Up @@ -6,7 +6,7 @@

enum
{
ANTIBOT_ABI_VERSION = 6,
ANTIBOT_ABI_VERSION = 7,

ANTIBOT_MSGFLAG_NONVITAL = 1,
ANTIBOT_MSGFLAG_FLUSH = 2,
Expand Down Expand Up @@ -91,6 +91,7 @@ struct CAntibotData
void (*m_pfnLog)(const char *pMessage, void *pUser);
void (*m_pfnReport)(int ClientID, const char *pMessage, void *pUser);
void (*m_pfnSend)(int ClientID, const void *pData, int DataSize, int Flags, void *pUser);
void (*m_pfnTeehistorian)(const void *pData, int DataSize, void *pUser);
void *m_pUser;
};
struct CAntibotRoundData
Expand Down
7 changes: 7 additions & 0 deletions src/base/color.h
Expand Up @@ -130,6 +130,13 @@ class color4_base
return col;
}

DerivedT WithMultipliedAlpha(float alpha) const
{
DerivedT col(static_cast<const DerivedT &>(*this));
col.a *= alpha;
return col;
}

template<typename UnpackT>
static UnpackT UnpackAlphaLast(unsigned Color, bool Alpha = true)
{
Expand Down
2 changes: 1 addition & 1 deletion src/base/logger.h
Expand Up @@ -103,7 +103,7 @@ class ILogger
*/
virtual void GlobalFinish() {}
/**
* Notifies thte logger of a changed `m_Filter`.
* Notifies the logger of a changed `m_Filter`.
*/
virtual void OnFilterChange() {}
};
Expand Down
2 changes: 1 addition & 1 deletion src/base/rust.rs
Expand Up @@ -11,7 +11,7 @@ use std::str;
///
/// Callbacks in C are usually represented by a function pointer and some
/// "userdata" pointer that is also passed to the function pointer. This allows
/// to hand data to the callback. This type represents such a userdata poiner.
/// to hand data to the callback. This type represents such a userdata pointer.
///
/// It is `unsafe` to convert the `UserPtr` back to its original pointer using
/// [`UserPtr::cast`] because its lifetime and type information was lost.
Expand Down
48 changes: 40 additions & 8 deletions src/base/system.cpp
Expand Up @@ -2,6 +2,7 @@
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <atomic>
#include <cctype>
#include <charconv>
#include <cmath>
#include <cstdarg>
#include <cstdio>
Expand Down Expand Up @@ -2208,16 +2209,12 @@ int net_would_block()
#endif
}

int net_init()
void net_init()
{
#if defined(CONF_FAMILY_WINDOWS)
WSADATA wsaData;
int err = WSAStartup(MAKEWORD(1, 1), &wsaData);
dbg_assert(err == 0, "network initialization failed.");
return err == 0 ? 0 : 1;
WSADATA wsa_data;
dbg_assert(WSAStartup(MAKEWORD(1, 1), &wsa_data) == 0, "network initialization failed.");
#endif

return 0;
}

#if defined(CONF_FAMILY_UNIX)
Expand Down Expand Up @@ -3640,6 +3637,13 @@ float str_tofloat(const char *str)
return strtod(str, nullptr);
}

void str_from_int(int value, char *buffer, size_t buffer_size)
{
buffer[0] = '\0'; // Fix false positive clang-analyzer-core.UndefinedBinaryOperatorResult when using result
auto result = std::to_chars(buffer, buffer + buffer_size - 1, value);
result.ptr[0] = '\0';
}

int str_utf8_comp_nocase(const char *a, const char *b)
{
int code_a;
Expand Down Expand Up @@ -3953,6 +3957,34 @@ void str_utf8_stats(const char *str, size_t max_size, size_t max_count, size_t *
}
}

size_t str_utf8_offset_bytes_to_chars(const char *str, size_t byte_offset)
{
size_t char_offset = 0;
size_t current_offset = 0;
while(current_offset < byte_offset)
{
const size_t prev_byte_offset = current_offset;
current_offset = str_utf8_forward(str, current_offset);
if(current_offset == prev_byte_offset)
break;
char_offset++;
}
return char_offset;
}

size_t str_utf8_offset_chars_to_bytes(const char *str, size_t char_offset)
{
size_t byte_offset = 0;
for(size_t i = 0; i < char_offset; i++)
{
const size_t prev_byte_offset = byte_offset;
byte_offset = str_utf8_forward(str, byte_offset);
if(byte_offset == prev_byte_offset)
break;
}
return byte_offset;
}

unsigned str_quickhash(const char *str)
{
unsigned hash = 5381;
Expand Down Expand Up @@ -4125,7 +4157,7 @@ int kill_process(PROCESS process)
#elif defined(CONF_FAMILY_UNIX)
int status;
kill(process, SIGTERM);
return !waitpid(process, &status, 0);
return waitpid(process, &status, 0) != -1;
#endif
}

Expand Down
38 changes: 35 additions & 3 deletions src/base/system.h
Expand Up @@ -879,11 +879,9 @@ typedef struct sockaddr_un UNIXSOCKETADDR;
*
* @ingroup Network-General
*
* @return 0 on success.
*
* @remark You must call this function before using any other network functions.
*/
int net_init();
void net_init();

/*
Function: net_host_lookup
Expand Down Expand Up @@ -2230,6 +2228,14 @@ unsigned long str_toulong_base(const char *str, int base);
int64_t str_toint64_base(const char *str, int base = 10);
float str_tofloat(const char *str);

void str_from_int(int value, char *buffer, size_t buffer_size);

template<size_t N>
void str_from_int(int value, char (&dst)[N])
{
str_from_int(value, dst, N);
}

/**
* Determines whether a character is whitespace.
*
Expand Down Expand Up @@ -2491,6 +2497,32 @@ int str_utf8_check(const char *str);
*/
void str_utf8_stats(const char *str, size_t max_size, size_t max_count, size_t *size, size_t *count);

/**
* Converts a byte offset of a utf8 string to the utf8 character offset.
*
* @param text Pointer to the string.
* @param byte_offset Offset in bytes.
*
* @return Offset in utf8 characters. Clamped to the maximum length of the string in utf8 characters.
*
* @remark The string is treated as a zero-terminated utf8 string.
* @remark It's the user's responsibility to make sure the bounds are aligned.
*/
size_t str_utf8_offset_bytes_to_chars(const char *str, size_t byte_offset);

/**
* Converts a utf8 character offset of a utf8 string to the byte offset.
*
* @param text Pointer to the string.
* @param char_offset Offset in utf8 characters.
*
* @return Offset in bytes. Clamped to the maximum length of the string in bytes.
*
* @remark The string is treated as a zero-terminated utf8 string.
* @remark It's the user's responsibility to make sure the bounds are aligned.
*/
size_t str_utf8_offset_chars_to_bytes(const char *str, size_t char_offset);

/*
Function: str_next_token
Writes the next token after str into buf, returns the rest of the string.
Expand Down
6 changes: 4 additions & 2 deletions src/engine/client.h
Expand Up @@ -165,9 +165,9 @@ class IClient : public IInterface
virtual void Quit() = 0;
virtual const char *DemoPlayer_Play(const char *pFilename, int StorageType) = 0;
#if defined(CONF_VIDEORECORDER)
virtual const char *DemoPlayer_Render(const char *pFilename, int StorageType, const char *pVideoName, int SpeedIndex) = 0;
virtual const char *DemoPlayer_Render(const char *pFilename, int StorageType, const char *pVideoName, int SpeedIndex, bool StartPaused = false) = 0;
#endif
virtual void DemoRecorder_Start(const char *pFilename, bool WithTimestamp, int Recorder) = 0;
virtual void DemoRecorder_Start(const char *pFilename, bool WithTimestamp, int Recorder, bool Verbose = false) = 0;
virtual void DemoRecorder_HandleAutoStart() = 0;
virtual void DemoRecorder_Stop(int Recorder, bool RemoveFile = false) = 0;
virtual class IDemoRecorder *DemoRecorder(int Recorder) = 0;
Expand All @@ -181,6 +181,7 @@ class IClient : public IInterface
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) = 0;
virtual void ToggleWindowVSync() = 0;
virtual void Notify(const char *pTitle, const char *pMessage) = 0;
virtual void OnWindowResize() = 0;

virtual void UpdateAndSwap() = 0;

Expand Down Expand Up @@ -316,6 +317,7 @@ class IGameClient : public IInterface
virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, int Conn, bool Dummy) = 0;
virtual void OnPredict() = 0;
virtual void OnActivateEditor() = 0;
virtual void OnWindowResize() = 0;

virtual int OnSnapInput(int *pData, bool Dummy, bool Force) = 0;
virtual void OnDummySwap() = 0;
Expand Down
13 changes: 3 additions & 10 deletions src/engine/client/backend/backend_base.cpp
@@ -1,24 +1,17 @@
#include "backend_base.h"
#include <engine/gfx/image_manipulation.h>

size_t CCommandProcessorFragment_GLBase::TexFormatToImageColorChannelCount(int TexFormat)
{
if(TexFormat == CCommandBuffer::TEXFORMAT_RGBA)
return 4;
return 4;
}

void *CCommandProcessorFragment_GLBase::Resize(const unsigned char *pData, int Width, int Height, int NewWidth, int NewHeight, int BPP)
{
return ResizeImage((const uint8_t *)pData, Width, Height, NewWidth, NewHeight, BPP);
}

bool CCommandProcessorFragment_GLBase::Texture2DTo3D(void *pImageBuffer, int ImageWidth, int ImageHeight, int ImageColorChannelCount, int SplitCountWidth, int SplitCountHeight, void *pTarget3DImageData, int &Target3DImageWidth, int &Target3DImageHeight)
bool CCommandProcessorFragment_GLBase::Texture2DTo3D(void *pImageBuffer, int ImageWidth, int ImageHeight, size_t PixelSize, int SplitCountWidth, int SplitCountHeight, void *pTarget3DImageData, int &Target3DImageWidth, int &Target3DImageHeight)
{
Target3DImageWidth = ImageWidth / SplitCountWidth;
Target3DImageHeight = ImageHeight / SplitCountHeight;

size_t FullImageWidth = (size_t)ImageWidth * ImageColorChannelCount;
const size_t FullImageWidth = (size_t)ImageWidth * PixelSize;

for(int Y = 0; Y < SplitCountHeight; ++Y)
{
Expand All @@ -28,7 +21,7 @@ bool CCommandProcessorFragment_GLBase::Texture2DTo3D(void *pImageBuffer, int Ima
{
int DepthIndex = X + Y * SplitCountWidth;

size_t TargetImageFullWidth = (size_t)Target3DImageWidth * ImageColorChannelCount;
size_t TargetImageFullWidth = (size_t)Target3DImageWidth * PixelSize;
size_t TargetImageFullSize = (size_t)TargetImageFullWidth * Target3DImageHeight;
ptrdiff_t ImageOffset = (ptrdiff_t)(((size_t)Y * FullImageWidth * (size_t)Target3DImageHeight) + ((size_t)Y3D * FullImageWidth) + ((size_t)X * TargetImageFullWidth));
ptrdiff_t TargetImageOffset = (ptrdiff_t)(TargetImageFullSize * (size_t)DepthIndex + ((size_t)Y3D * TargetImageFullWidth));
Expand Down
5 changes: 2 additions & 3 deletions src/engine/client/backend/backend_base.h
Expand Up @@ -84,12 +84,11 @@ class CCommandProcessorFragment_GLBase
SGFXErrorContainer m_Error;
SGFXWarningContainer m_Warning;

static size_t TexFormatToImageColorChannelCount(int TexFormat);
static void *Resize(const unsigned char *pData, int Width, int Height, int NewWidth, int NewHeight, int BPP);

static bool Texture2DTo3D(void *pImageBuffer, int ImageWidth, int ImageHeight, int ImageColorChannelCount, int SplitCountWidth, int SplitCountHeight, void *pTarget3DImageData, int &Target3DImageWidth, int &Target3DImageHeight);
static bool Texture2DTo3D(void *pImageBuffer, int ImageWidth, int ImageHeight, size_t PixelSize, int SplitCountWidth, int SplitCountHeight, void *pTarget3DImageData, int &Target3DImageWidth, int &Target3DImageHeight);

virtual bool GetPresentedImageData(uint32_t &Width, uint32_t &Height, uint32_t &Format, std::vector<uint8_t> &vDstData) = 0;
virtual bool GetPresentedImageData(uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector<uint8_t> &vDstData) = 0;

public:
virtual ~CCommandProcessorFragment_GLBase() = default;
Expand Down
2 changes: 1 addition & 1 deletion src/engine/client/backend/null/backend_null.h
Expand Up @@ -5,7 +5,7 @@

class CCommandProcessorFragment_Null : public CCommandProcessorFragment_GLBase
{
bool GetPresentedImageData(uint32_t &Width, uint32_t &Height, uint32_t &Format, std::vector<uint8_t> &vDstData) override { return false; };
bool GetPresentedImageData(uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector<uint8_t> &vDstData) override { return false; };
ERunCommandReturnTypes RunCommand(const CCommandBuffer::SCommand *pBaseCommand) override;
bool Cmd_Init(const SCommand_Init *pCommand);
virtual void Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand);
Expand Down
65 changes: 31 additions & 34 deletions src/engine/client/backend/opengl/backend_opengl.cpp
Expand Up @@ -42,19 +42,14 @@ void CCommandProcessorFragment_OpenGL::Cmd_Update_Viewport(const CCommandBuffer:
glViewport(pCommand->m_X, pCommand->m_Y, pCommand->m_Width, pCommand->m_Height);
}

void CCommandProcessorFragment_OpenGL::Cmd_Finish(const CCommandBuffer::SCommand_Finish *pCommand)
{
glFinish();
}

int CCommandProcessorFragment_OpenGL::TexFormatToOpenGLFormat(int TexFormat)
{
if(TexFormat == CCommandBuffer::TEXFORMAT_RGBA)
return GL_RGBA;
return GL_RGBA;
}

size_t CCommandProcessorFragment_OpenGL::GLFormatToImageColorChannelCount(int GLFormat)
size_t CCommandProcessorFragment_OpenGL::GLFormatToPixelSize(int GLFormat)
{
switch(GLFormat)
{
Expand Down Expand Up @@ -283,7 +278,7 @@ GfxOpenGLMessageCallback(GLenum Source,
}
#endif

bool CCommandProcessorFragment_OpenGL::GetPresentedImageData(uint32_t &Width, uint32_t &Height, uint32_t &Format, std::vector<uint8_t> &vDstData)
bool CCommandProcessorFragment_OpenGL::GetPresentedImageData(uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector<uint8_t> &vDstData)
{
if(m_CanvasWidth == 0 || m_CanvasHeight == 0)
{
Expand Down Expand Up @@ -319,7 +314,7 @@ bool CCommandProcessorFragment_OpenGL::InitOpenGL(const SCommand_Init *pCommand)
m_IsOpenGLES = pCommand->m_RequestedBackend == BACKEND_TYPE_OPENGL_ES;

TGLBackendReadPresentedImageData &ReadPresentedImgDataFunc = *pCommand->m_pReadPresentedImageDataFunc;
ReadPresentedImgDataFunc = [this](uint32_t &Width, uint32_t &Height, uint32_t &Format, std::vector<uint8_t> &vDstData) { return GetPresentedImageData(Width, Height, Format, vDstData); };
ReadPresentedImgDataFunc = [this](uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector<uint8_t> &vDstData) { return GetPresentedImageData(Width, Height, Format, vDstData); };

const char *pVendorString = (const char *)glGetString(GL_VENDOR);
dbg_msg("opengl", "Vendor string: %s", pVendorString);
Expand Down Expand Up @@ -649,7 +644,7 @@ void CCommandProcessorFragment_OpenGL::TextureUpdate(int Slot, int X, int Y, int
int ResizedW = (int)(Width * ResizeW);
int ResizedH = (int)(Height * ResizeH);

void *pTmpData = Resize(static_cast<const unsigned char *>(pTexData), Width, Height, ResizedW, ResizedH, GLFormatToImageColorChannelCount(GLFormat));
void *pTmpData = Resize(static_cast<const unsigned char *>(pTexData), Width, Height, ResizedW, ResizedH, GLFormatToPixelSize(GLFormat));
free(pTexData);
pTexData = pTmpData;

Expand All @@ -671,7 +666,7 @@ void CCommandProcessorFragment_OpenGL::TextureUpdate(int Slot, int X, int Y, int
Y /= 2;
}

void *pTmpData = Resize(static_cast<const unsigned char *>(pTexData), OldWidth, OldHeight, Width, Height, GLFormatToImageColorChannelCount(GLFormat));
void *pTmpData = Resize(static_cast<const unsigned char *>(pTexData), OldWidth, OldHeight, Width, Height, GLFormatToPixelSize(GLFormat));
free(pTexData);
pTexData = pTmpData;
}
Expand Down Expand Up @@ -723,7 +718,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Destroy(const CCommandBuffer:
DestroyTexture(pCommand->m_Slot);
}

void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int Height, int PixelSize, int GLFormat, int GLStoreFormat, int Flags, void *pTexData)
void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, void *pTexData)
{
#ifndef BACKEND_GL_MODERN_API

Expand All @@ -746,7 +741,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
int PowerOfTwoHeight = HighestBit(Height);
if(Width != PowerOfTwoWidth || Height != PowerOfTwoHeight)
{
void *pTmpData = Resize(static_cast<const unsigned char *>(pTexData), Width, Height, PowerOfTwoWidth, PowerOfTwoHeight, GLFormatToImageColorChannelCount(GLFormat));
void *pTmpData = Resize(static_cast<const unsigned char *>(pTexData), Width, Height, PowerOfTwoWidth, PowerOfTwoHeight, GLFormatToPixelSize(GLFormat));
free(pTexData);
pTexData = pTmpData;

Expand Down Expand Up @@ -778,7 +773,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He

if(NeedsResize)
{
void *pTmpData = Resize(static_cast<const unsigned char *>(pTexData), OldWidth, OldHeight, Width, Height, GLFormatToImageColorChannelCount(GLFormat));
void *pTmpData = Resize(static_cast<const unsigned char *>(pTexData), OldWidth, OldHeight, Width, Height, GLFormatToPixelSize(GLFormat));
free(pTexData);
pTexData = pTmpData;
}
Expand All @@ -787,8 +782,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
m_vTextures[Slot].m_Height = Height;
m_vTextures[Slot].m_RescaleCount = RescaleCount;

int Oglformat = GLFormat;
int StoreOglformat = GLStoreFormat;
const size_t PixelSize = GLFormatToPixelSize(GLFormat);

if((Flags & CCommandBuffer::TEXFLAG_NO_2D_TEXTURE) == 0)
{
Expand All @@ -802,7 +796,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, StoreOglformat, Width, Height, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
glTexImage2D(GL_TEXTURE_2D, 0, GLStoreFormat, Width, Height, 0, GLFormat, GL_UNSIGNED_BYTE, pTexData);
}
}
else
Expand All @@ -818,7 +812,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, ((GLfloat)m_OpenGLTextureLodBIAS / 1000.0f));
#endif

glTexImage2D(GL_TEXTURE_2D, 0, StoreOglformat, Width, Height, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
glTexImage2D(GL_TEXTURE_2D, 0, GLStoreFormat, Width, Height, 0, GLFormat, GL_UNSIGNED_BYTE, pTexData);
}

int Flag2DArrayTexture = (CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE | CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER);
Expand Down Expand Up @@ -886,14 +880,12 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
glBindSampler(0, 0);
}

int ImageColorChannels = GLFormatToImageColorChannelCount(GLFormat);

uint8_t *p3DImageData = NULL;

bool IsSingleLayer = (Flags & (CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER | CCommandBuffer::TEXFLAG_TO_3D_TEXTURE_SINGLE_LAYER)) != 0;

if(!IsSingleLayer)
p3DImageData = (uint8_t *)malloc((size_t)ImageColorChannels * Width * Height);
p3DImageData = (uint8_t *)malloc((size_t)Width * Height * PixelSize);
int Image3DWidth, Image3DHeight;

int ConvertWidth = Width;
Expand All @@ -906,7 +898,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
dbg_msg("gfx", "3D/2D array texture was resized");
int NewWidth = maximum<int>(HighestBit(ConvertWidth), 16);
int NewHeight = maximum<int>(HighestBit(ConvertHeight), 16);
uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pTexData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, GLFormatToImageColorChannelCount(GLFormat));
uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pTexData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, GLFormatToPixelSize(GLFormat));

ConvertWidth = NewWidth;
ConvertHeight = NewHeight;
Expand All @@ -916,15 +908,15 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
}
}

if(IsSingleLayer || (Texture2DTo3D(pTexData, ConvertWidth, ConvertHeight, ImageColorChannels, 16, 16, p3DImageData, Image3DWidth, Image3DHeight)))
if(IsSingleLayer || (Texture2DTo3D(pTexData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DImageData, Image3DWidth, Image3DHeight)))
{
if(IsSingleLayer)
{
glTexImage3D(Target, 0, StoreOglformat, ConvertWidth, ConvertHeight, 1, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
glTexImage3D(Target, 0, GLStoreFormat, ConvertWidth, ConvertHeight, 1, 0, GLFormat, GL_UNSIGNED_BYTE, pTexData);
}
else
{
glTexImage3D(Target, 0, StoreOglformat, Image3DWidth, Image3DHeight, 256, 0, Oglformat, GL_UNSIGNED_BYTE, p3DImageData);
glTexImage3D(Target, 0, GLStoreFormat, Image3DWidth, Image3DHeight, 256, 0, GLFormat, GL_UNSIGNED_BYTE, p3DImageData);
}
}

Expand All @@ -937,12 +929,12 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He
m_vTextures[Slot].m_LastWrapMode = CCommandBuffer::WRAP_REPEAT;

// calculate memory usage
m_vTextures[Slot].m_MemSize = Width * Height * PixelSize;
m_vTextures[Slot].m_MemSize = (size_t)Width * Height * PixelSize;
while(Width > 2 && Height > 2)
{
Width >>= 1;
Height >>= 1;
m_vTextures[Slot].m_MemSize += Width * Height * PixelSize;
m_vTextures[Slot].m_MemSize += (size_t)Width * Height * PixelSize;
}
m_pTextureMemoryUsage->store(m_pTextureMemoryUsage->load(std::memory_order_relaxed) + m_vTextures[Slot].m_MemSize, std::memory_order_relaxed);

Expand All @@ -952,7 +944,7 @@ void CCommandProcessorFragment_OpenGL::TextureCreate(int Slot, int Width, int He

void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand)
{
TextureCreate(pCommand->m_Slot, pCommand->m_Width, pCommand->m_Height, pCommand->m_PixelSize, TexFormatToOpenGLFormat(pCommand->m_Format), TexFormatToOpenGLFormat(pCommand->m_StoreFormat), pCommand->m_Flags, pCommand->m_pData);
TextureCreate(pCommand->m_Slot, pCommand->m_Width, pCommand->m_Height, TexFormatToOpenGLFormat(pCommand->m_Format), TexFormatToOpenGLFormat(pCommand->m_StoreFormat), pCommand->m_Flags, pCommand->m_pData);
}

void CCommandProcessorFragment_OpenGL::Cmd_TextTexture_Update(const CCommandBuffer::SCommand_TextTexture_Update *pCommand)
Expand All @@ -968,16 +960,24 @@ void CCommandProcessorFragment_OpenGL::Cmd_TextTextures_Destroy(const CCommandBu

void CCommandProcessorFragment_OpenGL::Cmd_TextTextures_Create(const CCommandBuffer::SCommand_TextTextures_Create *pCommand)
{
void *pTextData = pCommand->m_pTextData;
void *pTextOutlineData = pCommand->m_pTextOutlineData;
TextureCreate(pCommand->m_Slot, pCommand->m_Width, pCommand->m_Height, 1, GL_ALPHA, GL_ALPHA, CCommandBuffer::TEXFLAG_NOMIPMAPS, pTextData);
TextureCreate(pCommand->m_SlotOutline, pCommand->m_Width, pCommand->m_Height, 1, GL_ALPHA, GL_ALPHA, CCommandBuffer::TEXFLAG_NOMIPMAPS, pTextOutlineData);
TextureCreate(pCommand->m_Slot, pCommand->m_Width, pCommand->m_Height, GL_ALPHA, GL_ALPHA, CCommandBuffer::TEXFLAG_NOMIPMAPS, pCommand->m_pTextData);
TextureCreate(pCommand->m_SlotOutline, pCommand->m_Width, pCommand->m_Height, GL_ALPHA, GL_ALPHA, CCommandBuffer::TEXFLAG_NOMIPMAPS, pCommand->m_pTextOutlineData);
}

void CCommandProcessorFragment_OpenGL::Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand)
{
// if clip is still active, force disable it for clearing, enable it again afterwards
bool ClipWasEnabled = m_LastClipEnable;
if(ClipWasEnabled)
{
glDisable(GL_SCISSOR_TEST);
}
glClearColor(pCommand->m_Color.r, pCommand->m_Color.g, pCommand->m_Color.b, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(ClipWasEnabled)
{
glEnable(GL_SCISSOR_TEST);
}
}

void CCommandProcessorFragment_OpenGL::Cmd_Render(const CCommandBuffer::SCommand_Render *pCommand)
Expand Down Expand Up @@ -1102,9 +1102,6 @@ ERunCommandReturnTypes CCommandProcessorFragment_OpenGL::RunCommand(const CComma
case CCommandBuffer::CMD_UPDATE_VIEWPORT:
Cmd_Update_Viewport(static_cast<const CCommandBuffer::SCommand_Update_Viewport *>(pBaseCommand));
break;
case CCommandBuffer::CMD_FINISH:
Cmd_Finish(static_cast<const CCommandBuffer::SCommand_Finish *>(pBaseCommand));
break;

case CCommandBuffer::CMD_CREATE_BUFFER_OBJECT: Cmd_CreateBufferObject(static_cast<const CCommandBuffer::SCommand_CreateBufferObject *>(pBaseCommand)); break;
case CCommandBuffer::CMD_UPDATE_BUFFER_OBJECT: Cmd_UpdateBufferObject(static_cast<const CCommandBuffer::SCommand_UpdateBufferObject *>(pBaseCommand)); break;
Expand Down
7 changes: 3 additions & 4 deletions src/engine/client/backend/opengl/backend_opengl.h
Expand Up @@ -80,13 +80,13 @@ class CCommandProcessorFragment_OpenGL : public CCommandProcessorFragment_GLBase
virtual bool IsNewApi() { return false; }
void DestroyTexture(int Slot);

bool GetPresentedImageData(uint32_t &Width, uint32_t &Height, uint32_t &Format, std::vector<uint8_t> &vDstData) override;
bool GetPresentedImageData(uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector<uint8_t> &vDstData) override;

static int TexFormatToOpenGLFormat(int TexFormat);
static size_t GLFormatToImageColorChannelCount(int GLFormat);
static size_t GLFormatToPixelSize(int GLFormat);

void TextureUpdate(int Slot, int X, int Y, int Width, int Height, int GLFormat, void *pTexData);
void TextureCreate(int Slot, int Width, int Height, int PixelSize, int GLFormat, int GLStoreFormat, int Flags, void *pTexData);
void TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, void *pTexData);

virtual bool Cmd_Init(const SCommand_Init *pCommand);
virtual void Cmd_Shutdown(const SCommand_Shutdown *pCommand) {}
Expand All @@ -102,7 +102,6 @@ class CCommandProcessorFragment_OpenGL : public CCommandProcessorFragment_GLBase
virtual void Cmd_Screenshot(const CCommandBuffer::SCommand_TrySwapAndScreenshot *pCommand);

virtual void Cmd_Update_Viewport(const CCommandBuffer::SCommand_Update_Viewport *pCommand);
virtual void Cmd_Finish(const CCommandBuffer::SCommand_Finish *pCommand);

virtual void Cmd_CreateBufferObject(const CCommandBuffer::SCommand_CreateBufferObject *pCommand) { dbg_assert(false, "Call of unsupported Cmd_CreateBufferObject"); }
virtual void Cmd_RecreateBufferObject(const CCommandBuffer::SCommand_RecreateBufferObject *pCommand) { dbg_assert(false, "Call of unsupported Cmd_RecreateBufferObject"); }
Expand Down
51 changes: 28 additions & 23 deletions src/engine/client/backend/opengl/backend_opengl3.cpp
Expand Up @@ -555,7 +555,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureUpdate(int Slot, int X, int Y,
Y /= 2;
}

void *pTmpData = Resize(static_cast<const unsigned char *>(pTexData), Width, Height, Width, Height, GLFormatToImageColorChannelCount(GLFormat));
void *pTmpData = Resize(static_cast<const unsigned char *>(pTexData), Width, Height, Width, Height, GLFormatToPixelSize(GLFormat));
free(pTexData);
pTexData = pTmpData;
}
Expand All @@ -577,7 +577,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Texture_Destroy(const CCommandBuff
DestroyTexture(pCommand->m_Slot);
}

void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int Height, int PixelSize, int GLFormat, int GLStoreFormat, int Flags, void *pTexData)
void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, void *pTexData)
{
if(Slot >= (int)m_vTextures.size())
m_vTextures.resize(m_vTextures.size() * 2);
Expand All @@ -595,7 +595,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
++RescaleCount;
} while(Width > m_MaxTexSize || Height > m_MaxTexSize);

void *pTmpData = Resize(static_cast<const unsigned char *>(pTexData), Width, Height, Width, Height, GLFormatToImageColorChannelCount(GLFormat));
void *pTmpData = Resize(static_cast<const unsigned char *>(pTexData), Width, Height, Width, Height, GLFormatToPixelSize(GLFormat));
free(pTexData);
pTexData = pTmpData;
}
Expand All @@ -604,10 +604,9 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
m_vTextures[Slot].m_Height = Height;
m_vTextures[Slot].m_RescaleCount = RescaleCount;

int Oglformat = GLFormat;
int StoreOglformat = GLStoreFormat;
if(StoreOglformat == GL_RED)
StoreOglformat = GL_R8;
if(GLStoreFormat == GL_RED)
GLStoreFormat = GL_R8;
const size_t PixelSize = GLFormatToPixelSize(GLFormat);

int SamplerSlot = 0;

Expand All @@ -628,7 +627,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glSamplerParameteri(m_vTextures[Slot].m_Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(m_vTextures[Slot].m_Sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, StoreOglformat, Width, Height, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
glTexImage2D(GL_TEXTURE_2D, 0, GLStoreFormat, Width, Height, 0, GLFormat, GL_UNSIGNED_BYTE, pTexData);
}
}
else
Expand All @@ -649,7 +648,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5.f);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5);
}
glTexImage2D(GL_TEXTURE_2D, 0, StoreOglformat, Width, Height, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
glTexImage2D(GL_TEXTURE_2D, 0, GLStoreFormat, Width, Height, 0, GLFormat, GL_UNSIGNED_BYTE, pTexData);
glGenerateMipmap(GL_TEXTURE_2D);
}

Expand All @@ -671,14 +670,12 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
glSamplerParameterf(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_LOD_BIAS, ((GLfloat)m_OpenGLTextureLodBIAS / 1000.0f));
#endif

int ImageColorChannels = GLFormatToImageColorChannelCount(GLFormat);

uint8_t *p3DImageData = NULL;

bool IsSingleLayer = (Flags & CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER) != 0;

if(!IsSingleLayer)
p3DImageData = (uint8_t *)malloc((size_t)ImageColorChannels * Width * Height);
p3DImageData = (uint8_t *)malloc((size_t)Width * Height * PixelSize);
int Image3DWidth, Image3DHeight;

int ConvertWidth = Width;
Expand All @@ -691,7 +688,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
dbg_msg("gfx", "3D/2D array texture was resized");
int NewWidth = maximum<int>(HighestBit(ConvertWidth), 16);
int NewHeight = maximum<int>(HighestBit(ConvertHeight), 16);
uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pTexData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, GLFormatToImageColorChannelCount(GLFormat));
uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pTexData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, GLFormatToPixelSize(GLFormat));

ConvertWidth = NewWidth;
ConvertHeight = NewHeight;
Expand All @@ -701,15 +698,15 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
}
}

if(IsSingleLayer || (Texture2DTo3D(pTexData, ConvertWidth, ConvertHeight, ImageColorChannels, 16, 16, p3DImageData, Image3DWidth, Image3DHeight)))
if(IsSingleLayer || (Texture2DTo3D(pTexData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DImageData, Image3DWidth, Image3DHeight)))
{
if(IsSingleLayer)
{
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, StoreOglformat, ConvertWidth, ConvertHeight, 1, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GLStoreFormat, ConvertWidth, ConvertHeight, 1, 0, GLFormat, GL_UNSIGNED_BYTE, pTexData);
}
else
{
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, StoreOglformat, Image3DWidth, Image3DHeight, 256, 0, Oglformat, GL_UNSIGNED_BYTE, p3DImageData);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GLStoreFormat, Image3DWidth, Image3DHeight, 256, 0, GLFormat, GL_UNSIGNED_BYTE, p3DImageData);
}
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
}
Expand All @@ -723,12 +720,12 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int
m_vTextures[Slot].m_LastWrapMode = CCommandBuffer::WRAP_REPEAT;

// calculate memory usage
m_vTextures[Slot].m_MemSize = Width * Height * PixelSize;
m_vTextures[Slot].m_MemSize = (size_t)Width * Height * PixelSize;
while(Width > 2 && Height > 2)
{
Width >>= 1;
Height >>= 1;
m_vTextures[Slot].m_MemSize += Width * Height * PixelSize;
m_vTextures[Slot].m_MemSize += (size_t)Width * Height * PixelSize;
}
m_pTextureMemoryUsage->store(m_pTextureMemoryUsage->load(std::memory_order_relaxed) + m_vTextures[Slot].m_MemSize, std::memory_order_relaxed);

Expand All @@ -737,7 +734,7 @@ void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int

void CCommandProcessorFragment_OpenGL3_3::Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand)
{
TextureCreate(pCommand->m_Slot, pCommand->m_Width, pCommand->m_Height, pCommand->m_PixelSize, TexFormatToOpenGLFormat(pCommand->m_Format), TexFormatToOpenGLFormat(pCommand->m_StoreFormat), pCommand->m_Flags, pCommand->m_pData);
TextureCreate(pCommand->m_Slot, pCommand->m_Width, pCommand->m_Height, TexFormatToOpenGLFormat(pCommand->m_Format), TexFormatToOpenGLFormat(pCommand->m_StoreFormat), pCommand->m_Flags, pCommand->m_pData);
}

void CCommandProcessorFragment_OpenGL3_3::Cmd_TextTexture_Update(const CCommandBuffer::SCommand_TextTexture_Update *pCommand)
Expand All @@ -753,20 +750,28 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_TextTextures_Destroy(const CComman

void CCommandProcessorFragment_OpenGL3_3::Cmd_TextTextures_Create(const CCommandBuffer::SCommand_TextTextures_Create *pCommand)
{
void *pTextData = pCommand->m_pTextData;
void *pTextOutlineData = pCommand->m_pTextOutlineData;
TextureCreate(pCommand->m_Slot, pCommand->m_Width, pCommand->m_Height, 1, GL_RED, GL_RED, CCommandBuffer::TEXFLAG_NOMIPMAPS, pTextData);
TextureCreate(pCommand->m_SlotOutline, pCommand->m_Width, pCommand->m_Height, 1, GL_RED, GL_RED, CCommandBuffer::TEXFLAG_NOMIPMAPS, pTextOutlineData);
TextureCreate(pCommand->m_Slot, pCommand->m_Width, pCommand->m_Height, GL_RED, GL_RED, CCommandBuffer::TEXFLAG_NOMIPMAPS, pCommand->m_pTextData);
TextureCreate(pCommand->m_SlotOutline, pCommand->m_Width, pCommand->m_Height, GL_RED, GL_RED, CCommandBuffer::TEXFLAG_NOMIPMAPS, pCommand->m_pTextOutlineData);
}

void CCommandProcessorFragment_OpenGL3_3::Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand)
{
// if clip is still active, force disable it for clearing, enable it again afterwards
bool ClipWasEnabled = m_LastClipEnable;
if(ClipWasEnabled)
{
glDisable(GL_SCISSOR_TEST);
}
if(pCommand->m_Color.r != m_ClearColor.r || pCommand->m_Color.g != m_ClearColor.g || pCommand->m_Color.b != m_ClearColor.b)
{
glClearColor(pCommand->m_Color.r, pCommand->m_Color.g, pCommand->m_Color.b, 0.0f);
m_ClearColor = pCommand->m_Color;
}
glClear(GL_COLOR_BUFFER_BIT);
if(ClipWasEnabled)
{
glEnable(GL_SCISSOR_TEST);
}
}

void CCommandProcessorFragment_OpenGL3_3::UploadStreamBufferData(unsigned int PrimitiveType, const void *pVertices, size_t VertSize, unsigned int PrimitiveCount, bool AsTex3D)
Expand Down
2 changes: 1 addition & 1 deletion src/engine/client/backend/opengl/backend_opengl3.h
Expand Up @@ -83,7 +83,7 @@ class CCommandProcessorFragment_OpenGL3_3 : public CCommandProcessorFragment_Ope
void RenderText(const CCommandBuffer::SState &State, int DrawNum, int TextTextureIndex, int TextOutlineTextureIndex, int TextureSize, const ColorRGBA &TextColor, const ColorRGBA &TextOutlineColor);

void TextureUpdate(int Slot, int X, int Y, int Width, int Height, int GLFormat, void *pTexData);
void TextureCreate(int Slot, int Width, int Height, int PixelSize, int GLFormat, int GLStoreFormat, int Flags, void *pTexData);
void TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, void *pTexData);

bool Cmd_Init(const SCommand_Init *pCommand) override;
void Cmd_Shutdown(const SCommand_Shutdown *pCommand) override;
Expand Down
57 changes: 24 additions & 33 deletions src/engine/client/backend/vulkan/backend_vulkan.cpp
Expand Up @@ -1102,7 +1102,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
bool m_CanAssert = false;

/**
* After an error occured, the rendering stop as soon as possible
* After an error occurred, the rendering stop as soon as possible
* Always stop the current code execution after a call to this function (e.g. return false)
*/
void SetError(EGFXErrorType ErrType, const char *pErr, const char *pErrStrExtra = nullptr)
Expand Down Expand Up @@ -1282,7 +1282,6 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
m_aCommandCallbacks[CommandBufferCMDOff(CCommandBuffer::CMD_RENDER_QUAD_CONTAINER_SPRITE_MULTIPLE)] = {true, [this](SRenderCommandExecuteBuffer &ExecBuffer, const CCommandBuffer::SCommand *pBaseCommand) { Cmd_RenderQuadContainerAsSpriteMultiple_FillExecuteBuffer(ExecBuffer, static_cast<const CCommandBuffer::SCommand_RenderQuadContainerAsSpriteMultiple *>(pBaseCommand)); }, [this](const CCommandBuffer::SCommand *pBaseCommand, SRenderCommandExecuteBuffer &ExecBuffer) { return Cmd_RenderQuadContainerAsSpriteMultiple(static_cast<const CCommandBuffer::SCommand_RenderQuadContainerAsSpriteMultiple *>(pBaseCommand), ExecBuffer); }};

m_aCommandCallbacks[CommandBufferCMDOff(CCommandBuffer::CMD_SWAP)] = {false, [](SRenderCommandExecuteBuffer &ExecBuffer, const CCommandBuffer::SCommand *pBaseCommand) {}, [this](const CCommandBuffer::SCommand *pBaseCommand, SRenderCommandExecuteBuffer &ExecBuffer) { return Cmd_Swap(static_cast<const CCommandBuffer::SCommand_Swap *>(pBaseCommand)); }};
m_aCommandCallbacks[CommandBufferCMDOff(CCommandBuffer::CMD_FINISH)] = {false, [](SRenderCommandExecuteBuffer &ExecBuffer, const CCommandBuffer::SCommand *pBaseCommand) {}, [this](const CCommandBuffer::SCommand *pBaseCommand, SRenderCommandExecuteBuffer &ExecBuffer) { return Cmd_Finish(static_cast<const CCommandBuffer::SCommand_Finish *>(pBaseCommand)); }};

m_aCommandCallbacks[CommandBufferCMDOff(CCommandBuffer::CMD_VSYNC)] = {false, [](SRenderCommandExecuteBuffer &ExecBuffer, const CCommandBuffer::SCommand *pBaseCommand) {}, [this](const CCommandBuffer::SCommand *pBaseCommand, SRenderCommandExecuteBuffer &ExecBuffer) { return Cmd_VSync(static_cast<const CCommandBuffer::SCommand_VSync *>(pBaseCommand)); }};
m_aCommandCallbacks[CommandBufferCMDOff(CCommandBuffer::CMD_MULTISAMPLING)] = {false, [](SRenderCommandExecuteBuffer &ExecBuffer, const CCommandBuffer::SCommand *pBaseCommand) {}, [this](const CCommandBuffer::SCommand *pBaseCommand, SRenderCommandExecuteBuffer &ExecBuffer) { return Cmd_MultiSampling(static_cast<const CCommandBuffer::SCommand_MultiSampling *>(pBaseCommand)); }};
Expand Down Expand Up @@ -1386,7 +1385,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
}
}

[[nodiscard]] bool GetPresentedImageDataImpl(uint32_t &Width, uint32_t &Height, uint32_t &Format, std::vector<uint8_t> &vDstData, bool FlipImgData, bool ResetAlpha)
[[nodiscard]] bool GetPresentedImageDataImpl(uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector<uint8_t> &vDstData, bool FlipImgData, bool ResetAlpha)
{
bool IsB8G8R8A8 = m_VKSurfFormat.format == VK_FORMAT_B8G8R8A8_UNORM;
bool UsesRGBALikeFormat = m_VKSurfFormat.format == VK_FORMAT_R8G8B8A8_UNORM || IsB8G8R8A8;
Expand All @@ -1397,7 +1396,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
Height = Viewport.height;
Format = CImageInfo::FORMAT_RGBA;

size_t ImageTotalSize = (size_t)Width * Height * 4;
const size_t ImageTotalSize = (size_t)Width * Height * CImageInfo::PixelSize(Format);

uint8_t *pResImageData;
if(!PreparePresentedImageDataImage(pResImageData, Width, Height))
Expand Down Expand Up @@ -1553,7 +1552,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
}
}

[[nodiscard]] bool GetPresentedImageData(uint32_t &Width, uint32_t &Height, uint32_t &Format, std::vector<uint8_t> &vDstData) override
[[nodiscard]] bool GetPresentedImageData(uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector<uint8_t> &vDstData) override
{
return GetPresentedImageDataImpl(Width, Height, Format, vDstData, false, false);
}
Expand Down Expand Up @@ -2510,7 +2509,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
* TEXTURES
************************/

size_t VulkanFormatToImageColorChannelCount(VkFormat Format)
size_t VulkanFormatToPixelSize(VkFormat Format)
{
if(Format == VK_FORMAT_R8G8B8_UNORM)
return 3;
Expand All @@ -2521,9 +2520,9 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
return 4;
}

[[nodiscard]] bool UpdateTexture(size_t TextureSlot, VkFormat Format, void *&pData, int64_t XOff, int64_t YOff, size_t Width, size_t Height, size_t ColorChannelCount)
[[nodiscard]] bool UpdateTexture(size_t TextureSlot, VkFormat Format, void *&pData, int64_t XOff, int64_t YOff, size_t Width, size_t Height)
{
size_t ImageSize = Width * Height * ColorChannelCount;
const size_t ImageSize = Width * Height * VulkanFormatToPixelSize(Format);
SMemoryBlock<s_StagingBufferImageCacheID> StagingBuffer;
if(!GetStagingBufferImage(StagingBuffer, pData, ImageSize))
return false;
Expand All @@ -2541,7 +2540,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
YOff /= 2;
}

void *pTmpData = Resize((const uint8_t *)pData, Width, Height, Width, Height, VulkanFormatToImageColorChannelCount(Format));
void *pTmpData = Resize((const uint8_t *)pData, Width, Height, Width, Height, VulkanFormatToPixelSize(Format));
free(pData);
pData = pTmpData;
}
Expand Down Expand Up @@ -2571,14 +2570,13 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
int Slot,
int Width,
int Height,
int PixelSize,
VkFormat Format,
VkFormat StoreFormat,
int Flags,
void *&pData)
{
size_t ImageIndex = (size_t)Slot;
int ImageColorChannels = VulkanFormatToImageColorChannelCount(Format);
const size_t PixelSize = VulkanFormatToPixelSize(Format);

while(ImageIndex >= m_vTextures.size())
{
Expand All @@ -2596,7 +2594,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
++RescaleCount;
} while((size_t)Width > m_MaxTextureSize || (size_t)Height > m_MaxTextureSize);

void *pTmpData = Resize((const uint8_t *)(pData), Width, Height, Width, Height, ImageColorChannels);
void *pTmpData = Resize((const uint8_t *)(pData), Width, Height, Width, Height, PixelSize);
free(pData);
pData = pTmpData;
}
Expand Down Expand Up @@ -2654,7 +2652,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
dbg_msg("vulkan", "3D/2D array texture was resized");
int NewWidth = maximum<int>(HighestBit(ConvertWidth), 16);
int NewHeight = maximum<int>(HighestBit(ConvertHeight), 16);
uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, ImageColorChannels);
uint8_t *pNewTexData = (uint8_t *)Resize((const uint8_t *)pData, ConvertWidth, ConvertHeight, NewWidth, NewHeight, PixelSize);

ConvertWidth = NewWidth;
ConvertHeight = NewHeight;
Expand All @@ -2668,8 +2666,8 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
bool Needs3DTexDel = false;
if(!Is2DTextureSingleLayer)
{
p3DTexData = malloc((size_t)ImageColorChannels * ConvertWidth * ConvertHeight);
if(!Texture2DTo3D(pData, ConvertWidth, ConvertHeight, ImageColorChannels, 16, 16, p3DTexData, Image3DWidth, Image3DHeight))
p3DTexData = malloc((size_t)PixelSize * ConvertWidth * ConvertHeight);
if(!Texture2DTo3D(pData, ConvertWidth, ConvertHeight, PixelSize, 16, 16, p3DTexData, Image3DWidth, Image3DHeight))
{
free(p3DTexData);
p3DTexData = nullptr;
Expand Down Expand Up @@ -6467,7 +6465,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
Buffer.m_pRawCommand = pBaseCommand;
Buffer.m_ThreadIndex = 0;

if(m_CurCommandInPipe + 1 == m_CommandsInPipe && Buffer.m_Command != CCommandBuffer::CMD_FINISH)
if(m_CurCommandInPipe + 1 == m_CommandsInPipe)
{
m_LastCommandsInPipeThreadIndex = std::numeric_limits<decltype(m_LastCommandsInPipeThreadIndex)>::max();
}
Expand All @@ -6493,7 +6491,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
Ret = CallbackObj.m_CMDIsHandled;
if(!CallbackObj.m_CommandCB(pBaseCommand, Buffer))
{
// an error occured, stop this command and ignore all further commands
// an error occurred, stop this command and ignore all further commands
return ERunCommandReturnTypes::RUN_COMMAND_COMMAND_ERROR;
}
}
Expand Down Expand Up @@ -6582,7 +6580,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
m_MultiSamplingCount = (g_Config.m_GfxFsaaSamples & 0xFFFFFFFE); // ignore the uneven bit, only even multi sampling works

TGLBackendReadPresentedImageData &ReadPresentedImgDataFunc = *pCommand->m_pReadPresentedImageDataFunc;
ReadPresentedImgDataFunc = [this](uint32_t &Width, uint32_t &Height, uint32_t &Format, std::vector<uint8_t> &vDstData) { return GetPresentedImageData(Width, Height, Format, vDstData); };
ReadPresentedImgDataFunc = [this](uint32_t &Width, uint32_t &Height, CImageInfo::EImageFormat &Format, std::vector<uint8_t> &vDstData) { return GetPresentedImageData(Width, Height, Format, vDstData); };

m_pWindow = pCommand->m_pWindow;

Expand Down Expand Up @@ -6657,7 +6655,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase

void *pData = pCommand->m_pData;

if(!UpdateTexture(IndexTex, VK_FORMAT_B8G8R8A8_UNORM, pData, pCommand->m_X, pCommand->m_Y, pCommand->m_Width, pCommand->m_Height, TexFormatToImageColorChannelCount(pCommand->m_Format)))
if(!UpdateTexture(IndexTex, VK_FORMAT_B8G8R8A8_UNORM, pData, pCommand->m_X, pCommand->m_Y, pCommand->m_Width, pCommand->m_Height))
return false;

free(pData);
Expand All @@ -6682,13 +6680,12 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
int Slot = pCommand->m_Slot;
int Width = pCommand->m_Width;
int Height = pCommand->m_Height;
int PixelSize = pCommand->m_PixelSize;
int Format = pCommand->m_Format;
int StoreFormat = pCommand->m_StoreFormat;
int Flags = pCommand->m_Flags;
void *pData = pCommand->m_pData;

if(!CreateTextureCMD(Slot, Width, Height, PixelSize, TextureFormatToVulkanFormat(Format), TextureFormatToVulkanFormat(StoreFormat), Flags, pData))
if(!CreateTextureCMD(Slot, Width, Height, TextureFormatToVulkanFormat(Format), TextureFormatToVulkanFormat(StoreFormat), Flags, pData))
return false;

free(pData);
Expand All @@ -6706,9 +6703,9 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
void *pTmpData = pCommand->m_pTextData;
void *pTmpData2 = pCommand->m_pTextOutlineData;

if(!CreateTextureCMD(Slot, Width, Height, 1, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, CCommandBuffer::TEXFLAG_NOMIPMAPS, pTmpData))
if(!CreateTextureCMD(Slot, Width, Height, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, CCommandBuffer::TEXFLAG_NOMIPMAPS, pTmpData))
return false;
if(!CreateTextureCMD(SlotOutline, Width, Height, 1, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, CCommandBuffer::TEXFLAG_NOMIPMAPS, pTmpData2))
if(!CreateTextureCMD(SlotOutline, Width, Height, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, CCommandBuffer::TEXFLAG_NOMIPMAPS, pTmpData2))
return false;

if(!CreateNewTextDescriptorSets(Slot, SlotOutline))
Expand Down Expand Up @@ -6741,7 +6738,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase

void *pData = pCommand->m_pData;

if(!UpdateTexture(IndexTex, VK_FORMAT_R8_UNORM, pData, pCommand->m_X, pCommand->m_Y, pCommand->m_Width, pCommand->m_Height, 1))
if(!UpdateTexture(IndexTex, VK_FORMAT_R8_UNORM, pData, pCommand->m_X, pCommand->m_Y, pCommand->m_Width, pCommand->m_Height))
return false;

free(pData);
Expand Down Expand Up @@ -6815,7 +6812,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase

uint32_t Width;
uint32_t Height;
uint32_t Format;
CImageInfo::EImageFormat Format;
if(GetPresentedImageDataImpl(Width, Height, Format, m_vScreenshotHelper, false, true))
{
size_t ImgSize = (size_t)Width * (size_t)Height * (size_t)4;
Expand All @@ -6828,7 +6825,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
}
pCommand->m_pImage->m_Width = (int)Width;
pCommand->m_pImage->m_Height = (int)Height;
pCommand->m_pImage->m_Format = (int)Format;
pCommand->m_pImage->m_Format = Format;

return true;
}
Expand Down Expand Up @@ -6921,12 +6918,6 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
return true;
}

[[nodiscard]] bool Cmd_Finish(const CCommandBuffer::SCommand_Finish *pCommand)
{
// just ignore it with vulkan
return true;
}

[[nodiscard]] bool Cmd_Swap(const CCommandBuffer::SCommand_Swap *pCommand)
{
return NextFrame();
Expand Down Expand Up @@ -7659,7 +7650,7 @@ class CCommandProcessorFragment_Vulkan : public CCommandProcessorFragment_GLBase
{
if(!m_aCommandCallbacks[CommandBufferCMDOff(NextCmd.m_Command)].m_CommandCB(NextCmd.m_pRawCommand, NextCmd))
{
// an error occured, the thread will not continue execution
// an error occurred, the thread will not continue execution
HasErrorFromCmd = true;
break;
}
Expand Down
115 changes: 54 additions & 61 deletions src/engine/client/client.cpp
Expand Up @@ -123,27 +123,25 @@ void CGraph::InsertAt(size_t Index, float v, float r, float g, float b)
m_aColors[Index][2] = b;
}

void CGraph::Render(IGraphics *pGraphics, IGraphics::CTextureHandle FontTexture, float x, float y, float w, float h, const char *pDescription)
void CGraph::Render(IGraphics *pGraphics, ITextRender *pTextRender, float x, float y, float w, float h, const char *pDescription)
{
//m_pGraphics->BlendNormal();

pGraphics->TextureClear();

pGraphics->QuadsBegin();
pGraphics->SetColor(0, 0, 0, 0.75f);
pGraphics->SetColor(0.0f, 0.0f, 0.0f, 0.75f);
IGraphics::CQuadItem QuadItem(x, y, w, h);
pGraphics->QuadsDrawTL(&QuadItem, 1);
pGraphics->QuadsEnd();

pGraphics->LinesBegin();
pGraphics->SetColor(0.95f, 0.95f, 0.95f, 1.00f);
pGraphics->SetColor(0.95f, 0.95f, 0.95f, 1.0f);
IGraphics::CLineItem LineItem(x, y + h / 2, x + w, y + h / 2);
pGraphics->LinesDraw(&LineItem, 1);
pGraphics->SetColor(0.5f, 0.5f, 0.5f, 0.75f);
IGraphics::CLineItem aLineItems[2] = {
IGraphics::CLineItem(x, y + (h * 3) / 4, x + w, y + (h * 3) / 4),
IGraphics::CLineItem(x, y + h / 4, x + w, y + h / 4)};
pGraphics->LinesDraw(aLineItems, 2);
pGraphics->LinesDraw(aLineItems, std::size(aLineItems));
for(int i = 1; i < MAX_VALUES; i++)
{
float a0 = (i - 1) / (float)MAX_VALUES;
Expand All @@ -157,23 +155,23 @@ void CGraph::Render(IGraphics *pGraphics, IGraphics::CTextureHandle FontTexture,
IGraphics::CColorVertex aColorVertices[2] = {
IGraphics::CColorVertex(0, m_aColors[i0][0], m_aColors[i0][1], m_aColors[i0][2], 0.75f),
IGraphics::CColorVertex(1, m_aColors[i1][0], m_aColors[i1][1], m_aColors[i1][2], 0.75f)};
pGraphics->SetColorVertex(aColorVertices, 2);
pGraphics->SetColorVertex(aColorVertices, std::size(aColorVertices));
IGraphics::CLineItem LineItem2(x + a0 * w, y + h - v0 * h, x + a1 * w, y + h - v1 * h);
pGraphics->LinesDraw(&LineItem2, 1);
}
pGraphics->LinesEnd();

pGraphics->TextureSet(FontTexture);
pGraphics->QuadsBegin();
pGraphics->QuadsText(x + 2, y + h - 16, 16, pDescription);
const float FontSize = 12.0f;
const float Spacing = 2.0f;

pTextRender->Text(x + Spacing, y + h - FontSize - Spacing, FontSize, pDescription);

char aBuf[32];
str_format(aBuf, sizeof(aBuf), "%.2f", m_Max);
pGraphics->QuadsText(x + w - 8 * str_length(aBuf) - 8, y + 2, 16, aBuf);
pTextRender->Text(x + w - pTextRender->TextWidth(FontSize, aBuf) - Spacing, y + Spacing, FontSize, aBuf);

str_format(aBuf, sizeof(aBuf), "%.2f", m_Min);
pGraphics->QuadsText(x + w - 8 * str_length(aBuf) - 8, y + h - 16, 16, aBuf);
pGraphics->QuadsEnd();
pTextRender->Text(x + w - pTextRender->TextWidth(FontSize, aBuf) - Spacing, y + h - FontSize - Spacing, FontSize, aBuf);
}

void CSmoothTime::Init(int64_t Target)
Expand Down Expand Up @@ -294,16 +292,6 @@ CClient::CClient() :
for(auto &DemoRecorder : m_aDemoRecorder)
DemoRecorder = CDemoRecorder(&m_SnapshotDelta);

m_pEditor = 0;
m_pInput = 0;
m_pGraphics = 0;
m_pSound = 0;
m_pGameClient = 0;
m_pMap = 0;
m_pConfigManager = 0;
m_pConfig = 0;
m_pConsole = 0;

m_RenderFrameTime = 0.0001f;
m_RenderFrameTimeLow = 1.0f;
m_RenderFrameTimeHigh = 0.0f;
Expand Down Expand Up @@ -986,7 +974,7 @@ void CClient::ServerInfoRequest()

void CClient::LoadDebugFont()
{
m_DebugFont = Graphics()->LoadTexture("debug_font.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0);
m_DebugFont = Graphics()->LoadTexture("debug_font.png", IStorage::TYPE_ALL);
}

// ---
Expand Down Expand Up @@ -1030,24 +1018,23 @@ void CClient::SnapSetStaticsize(int ItemType, int Size)

void CClient::DebugRender()
{
static NETSTATS Prev, Current;
static int64_t LastSnap = 0;
static float FrameTimeAvg = 0;
char aBuffer[512];

if(!g_Config.m_Debug)
return;

//m_pGraphics->BlendNormal();
static NETSTATS s_Prev, s_Current;
static int64_t s_LastSnapTime = 0;
static float s_FrameTimeAvg = 0;
char aBuffer[512];

Graphics()->TextureSet(m_DebugFont);
Graphics()->MapScreen(0, 0, Graphics()->ScreenWidth(), Graphics()->ScreenHeight());
Graphics()->QuadsBegin();

if(time_get() - LastSnap > time_freq())
if(time_get() - s_LastSnapTime > time_freq())
{
LastSnap = time_get();
Prev = Current;
net_stats(&Current);
s_LastSnapTime = time_get();
s_Prev = s_Current;
net_stats(&s_Current);
}

/*
Expand All @@ -1056,22 +1043,22 @@ void CClient::DebugRender()
udp = 8
total = 42
*/
FrameTimeAvg = FrameTimeAvg * 0.9f + m_RenderFrameTime * 0.1f;
s_FrameTimeAvg = s_FrameTimeAvg * 0.9f + m_RenderFrameTime * 0.1f;
str_format(aBuffer, sizeof(aBuffer), "ticks: %8d %8d gfx mem(tex/buff/stream/staging): (%" PRIu64 "k/%" PRIu64 "k/%" PRIu64 "k/%" PRIu64 "k) fps: %3d",
m_aCurGameTick[g_Config.m_ClDummy], m_aPredTick[g_Config.m_ClDummy],
(Graphics()->TextureMemoryUsage() / 1024),
(Graphics()->BufferMemoryUsage() / 1024),
(Graphics()->StreamedMemoryUsage() / 1024),
(Graphics()->StagingMemoryUsage() / 1024),
(int)(1.0f / FrameTimeAvg + 0.5f));
(int)(1.0f / s_FrameTimeAvg + 0.5f));
Graphics()->QuadsText(2, 2, 16, aBuffer);

{
uint64_t SendPackets = (Current.sent_packets - Prev.sent_packets);
uint64_t SendBytes = (Current.sent_bytes - Prev.sent_bytes);
uint64_t SendPackets = (s_Current.sent_packets - s_Prev.sent_packets);
uint64_t SendBytes = (s_Current.sent_bytes - s_Prev.sent_bytes);
uint64_t SendTotal = SendBytes + SendPackets * 42;
uint64_t RecvPackets = (Current.recv_packets - Prev.recv_packets);
uint64_t RecvBytes = (Current.recv_bytes - Prev.recv_bytes);
uint64_t RecvPackets = (s_Current.recv_packets - s_Prev.recv_packets);
uint64_t RecvBytes = (s_Current.recv_bytes - s_Prev.recv_bytes);
uint64_t RecvTotal = RecvBytes + RecvPackets * 42;

if(!SendPackets)
Expand Down Expand Up @@ -1130,18 +1117,17 @@ void CClient::DebugRender()
// render graphs
if(g_Config.m_DbgGraphs)
{
//Graphics()->MapScreen(0,0,400.0f,300.0f);
float w = Graphics()->ScreenWidth() / 4.0f;
float h = Graphics()->ScreenHeight() / 6.0f;
float sp = Graphics()->ScreenWidth() / 100.0f;
float x = Graphics()->ScreenWidth() - w - sp;

m_FpsGraph.Scale();
m_FpsGraph.Render(Graphics(), m_DebugFont, x, sp * 5, w, h, "FPS");
m_FpsGraph.Render(Graphics(), TextRender(), x, sp * 5, w, h, "FPS");
m_InputtimeMarginGraph.Scale();
m_InputtimeMarginGraph.Render(Graphics(), m_DebugFont, x, sp * 5 + h + sp, w, h, "Prediction Margin");
m_InputtimeMarginGraph.Render(Graphics(), TextRender(), x, sp * 6 + h, w, h, "Prediction Margin");
m_GametimeMarginGraph.Scale();
m_GametimeMarginGraph.Render(Graphics(), m_DebugFont, x, sp * 5 + h + sp + h + sp, w, h, "Gametime Margin");
m_GametimeMarginGraph.Render(Graphics(), TextRender(), x, sp * 7 + h * 2, w, h, "Gametime Margin");
}
}

Expand Down Expand Up @@ -3051,8 +3037,8 @@ void CClient::Run()
#endif

// init text render
IEngineTextRender *pTextRender = Kernel()->RequestInterface<IEngineTextRender>();
pTextRender->Init();
m_pTextRender = Kernel()->RequestInterface<IEngineTextRender>();
m_pTextRender->Init();

// init the input
Input()->Init();
Expand All @@ -3071,6 +3057,8 @@ void CClient::Run()
str_copy(g_Config.m_SteamName, Steam()->GetPlayerName());
}

Graphics()->AddWindowResizeListener([this] { OnWindowResize(); });

GameClient()->OnInit();

m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", "version " GAME_RELEASE_VERSION " on " CONF_PLATFORM_STRING " " CONF_ARCH_STRING, ColorRGBA(0.7f, 0.7f, 1.0f, 1.0f));
Expand Down Expand Up @@ -3132,7 +3120,7 @@ void CClient::Run()
// handle pending map edits
if(m_aCmdEditMap[0])
{
int Result = m_pEditor->Load(m_aCmdEditMap, IStorage::TYPE_ALL_OR_ABSOLUTE);
int Result = m_pEditor->HandleMapDrop(m_aCmdEditMap, IStorage::TYPE_ALL_OR_ABSOLUTE);
if(Result)
g_Config.m_ClEditor = true;
else
Expand Down Expand Up @@ -3388,12 +3376,6 @@ void CClient::Run()
else
LastTime = Now;

if(g_Config.m_DbgHitch)
{
std::this_thread::sleep_for(g_Config.m_DbgHitch * 1ms);
g_Config.m_DbgHitch = 0;
}

// update local and global time
m_LocalTime = (time_get() - m_LocalStartTime) / (float)time_freq();
m_GlobalTime = (time_get() - m_GlobalStartTime) / (float)time_freq();
Expand All @@ -3411,7 +3393,7 @@ void CClient::Run()
delete m_pEditor;

// shutdown text render while graphics are still available
pTextRender->Shutdown();
m_pTextRender->Shutdown();
}

bool CClient::InitNetworkClient(char *pError, size_t ErrorSize)
Expand Down Expand Up @@ -3922,7 +3904,7 @@ const char *CClient::DemoPlayer_Play(const char *pFilename, int StorageType)
}

#if defined(CONF_VIDEORECORDER)
const char *CClient::DemoPlayer_Render(const char *pFilename, int StorageType, const char *pVideoName, int SpeedIndex)
const char *CClient::DemoPlayer_Render(const char *pFilename, int StorageType, const char *pVideoName, int SpeedIndex, bool StartPaused)
{
const char *pError = DemoPlayer_Play(pFilename, StorageType);
if(pError)
Expand All @@ -3932,7 +3914,7 @@ const char *CClient::DemoPlayer_Render(const char *pFilename, int StorageType, c
this->CClient::StartVideo(NULL, this, pVideoName);
m_DemoPlayer.Play();
m_DemoPlayer.SetSpeedIndex(SpeedIndex);
if(Config()->m_ClVideoPauseOnStart)
if(StartPaused)
{
m_DemoPlayer.Pause();
}
Expand Down Expand Up @@ -3969,10 +3951,13 @@ void CClient::Con_DemoSpeed(IConsole::IResult *pResult, void *pUserData)
pSelf->m_DemoPlayer.SetSpeed(pResult->GetFloat(0));
}

void CClient::DemoRecorder_Start(const char *pFilename, bool WithTimestamp, int Recorder)
void CClient::DemoRecorder_Start(const char *pFilename, bool WithTimestamp, int Recorder, bool Verbose)
{
if(State() != IClient::STATE_ONLINE)
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demorec/record", "client is not online");
{
if(Verbose)
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demorec/record", "client is not online");
}
else
{
char aFilename[IO_MAX_PATH_LENGTH];
Expand Down Expand Up @@ -4050,9 +4035,9 @@ void CClient::Con_Record(IConsole::IResult *pResult, void *pUserData)
{
CClient *pSelf = (CClient *)pUserData;
if(pResult->NumArguments())
pSelf->DemoRecorder_Start(pResult->GetString(0), false, RECORDER_MANUAL);
pSelf->DemoRecorder_Start(pResult->GetString(0), false, RECORDER_MANUAL, true);
else
pSelf->DemoRecorder_Start(pSelf->m_aCurrentMap, true, RECORDER_MANUAL);
pSelf->DemoRecorder_Start(pSelf->m_aCurrentMap, true, RECORDER_MANUAL, true);
}

void CClient::Con_StopRecord(IConsole::IResult *pResult, void *pUserData)
Expand Down Expand Up @@ -4300,6 +4285,14 @@ void CClient::Notify(const char *pTitle, const char *pMessage)
Graphics()->NotifyWindow();
}

void CClient::OnWindowResize()
{
TextRender()->OnPreWindowResize();
GameClient()->OnWindowResize();
m_pEditor->OnWindowResize();
TextRender()->OnWindowResize();
}

void CClient::ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
CClient *pSelf = (CClient *)pUserData;
Expand Down Expand Up @@ -4633,7 +4626,7 @@ int main(int argc, const char **argv)
pClient->GetGPUInfoString(aGPUInfo);
char aMessage[768];
str_format(aMessage, sizeof(aMessage),
"An assertion error occured. Please write down or take a screenshot of the following information and report this error.\n"
"An assertion error occurred. Please write down or take a screenshot of the following information and report this error.\n"
"Please also share the assert log which you should find in the 'dumps' folder in your config directory.\n\n"
"%s\n\n"
"Platform: %s\n"
Expand Down
50 changes: 26 additions & 24 deletions src/engine/client/client.h
Expand Up @@ -63,7 +63,7 @@ class CGraph
void Scale();
void Add(float v, float r, float g, float b);
void InsertAt(size_t Index, float v, float r, float g, float b);
void Render(IGraphics *pGraphics, IGraphics::CTextureHandle FontTexture, float x, float y, float w, float h, const char *pDescription);
void Render(IGraphics *pGraphics, ITextRender *pTextRender, float x, float y, float w, float h, const char *pDescription);
};

class CSmoothTime
Expand Down Expand Up @@ -107,21 +107,22 @@ class CServerCapabilities
class CClient : public IClient, public CDemoPlayer::IListener
{
// needed interfaces
IEngine *m_pEngine;
IEditor *m_pEditor;
IEngineInput *m_pInput;
IEngineGraphics *m_pGraphics;
IEngineSound *m_pSound;
IFavorites *m_pFavorites;
IGameClient *m_pGameClient;
IEngineMap *m_pMap;
IConfigManager *m_pConfigManager;
CConfig *m_pConfig;
IConsole *m_pConsole;
IStorage *m_pStorage;
IUpdater *m_pUpdater;
IDiscord *m_pDiscord;
ISteam *m_pSteam;
IConfigManager *m_pConfigManager = nullptr;
CConfig *m_pConfig = nullptr;
IConsole *m_pConsole = nullptr;
IDiscord *m_pDiscord = nullptr;
IEditor *m_pEditor = nullptr;
IEngine *m_pEngine = nullptr;
IFavorites *m_pFavorites = nullptr;
IGameClient *m_pGameClient = nullptr;
IEngineGraphics *m_pGraphics = nullptr;
IEngineInput *m_pInput = nullptr;
IEngineMap *m_pMap = nullptr;
IEngineSound *m_pSound = nullptr;
ISteam *m_pSteam = nullptr;
IStorage *m_pStorage = nullptr;
IEngineTextRender *m_pTextRender = nullptr;
IUpdater *m_pUpdater = nullptr;

CNetClient m_aNetClient[NUM_CONNS];
CDemoPlayer m_DemoPlayer;
Expand All @@ -146,7 +147,6 @@ class CClient : public IClient, public CDemoPlayer::IListener
int64_t m_GlobalStartTime;

IGraphics::CTextureHandle m_DebugFont;
int m_DebugSoundIndex = 0;

int64_t m_LastRenderTime;
float m_RenderFrameTimeLow;
Expand Down Expand Up @@ -302,17 +302,18 @@ class CClient : public IClient, public CDemoPlayer::IListener
std::shared_ptr<ILogger> m_pStdoutLogger = nullptr;

public:
IConfigManager *ConfigManager() { return m_pConfigManager; }
CConfig *Config() { return m_pConfig; }
IDiscord *Discord() { return m_pDiscord; }
IEngine *Engine() { return m_pEngine; }
IGameClient *GameClient() { return m_pGameClient; }
IEngineGraphics *Graphics() { return m_pGraphics; }
IEngineInput *Input() { return m_pInput; }
IEngineSound *Sound() { return m_pSound; }
IGameClient *GameClient() { return m_pGameClient; }
IConfigManager *ConfigManager() { return m_pConfigManager; }
CConfig *Config() { return m_pConfig; }
ISteam *Steam() { return m_pSteam; }
IStorage *Storage() { return m_pStorage; }
IEngineTextRender *TextRender() { return m_pTextRender; }
IUpdater *Updater() { return m_pUpdater; }
IDiscord *Discord() { return m_pDiscord; }
ISteam *Steam() { return m_pSteam; }

CClient();

Expand Down Expand Up @@ -447,7 +448,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
static void StartVideo(IConsole::IResult *pResult, void *pUserData, const char *pVideoName);
static void Con_StartVideo(IConsole::IResult *pResult, void *pUserData);
static void Con_StopVideo(IConsole::IResult *pResult, void *pUserData);
const char *DemoPlayer_Render(const char *pFilename, int StorageType, const char *pVideoName, int SpeedIndex) override;
const char *DemoPlayer_Render(const char *pFilename, int StorageType, const char *pVideoName, int SpeedIndex, bool StartPaused = false) override;
#endif

static void Con_Rcon(IConsole::IResult *pResult, void *pUserData);
Expand Down Expand Up @@ -481,7 +482,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
void RegisterCommands();

const char *DemoPlayer_Play(const char *pFilename, int StorageType) override;
void DemoRecorder_Start(const char *pFilename, bool WithTimestamp, int Recorder) override;
void DemoRecorder_Start(const char *pFilename, bool WithTimestamp, int Recorder, bool Verbose = false) override;
void DemoRecorder_HandleAutoStart() override;
void DemoRecorder_StartReplayRecorder();
void DemoRecorder_Stop(int Recorder, bool RemoveFile = false) override;
Expand Down Expand Up @@ -511,6 +512,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) override;
void ToggleWindowVSync() override;
void Notify(const char *pTitle, const char *pMessage) override;
void OnWindowResize() override;
void BenchmarkQuit(int Seconds, const char *pFilename);

void UpdateAndSwap() override;
Expand Down