Merge remote-tracking branch 'upstream-teeworlds/0.6' into DDRace

Conflicts:
	bam.lua
	data/languages/index.txt
	src/engine/server/server.cpp
	src/engine/shared/network_server.cpp
	src/game/client/components/chat.cpp
	src/game/client/components/menus_settings.cpp
	src/game/server/entities/character.cpp
	src/game/server/gamecontext.cpp
	src/game/version.h
This commit is contained in:
def 2013-12-26 18:02:22 +01:00
commit 3eaad43b6b
70 changed files with 2259 additions and 1014 deletions

View file

@ -8,6 +8,8 @@ Import("other/freetype/freetype.lua")
config = NewConfig()
config:Add(OptCCompiler("compiler"))
config:Add(OptTestCompileC("stackprotector", "int main(){return 0;}", "-fstack-protector -fstack-protector-all"))
config:Add(OptTestCompileC("minmacosxsdk", "int main(){return 0;}", "-mmacosx-version-min=10.5 -isysroot /Developer/SDKs/MacOSX10.5.sdk"))
config:Add(OptTestCompileC("macosxppc", "int main(){return 0;}", "-arch ppc"))
config:Add(OptLibrary("zlib", "zlib.h", false))
config:Add(SDL.OptFind("sdl", true))
config:Add(FreeType.OptFind("freetype", true))
@ -170,6 +172,10 @@ function build(settings)
elseif platform == "macosx" then
settings.cc.flags:Add("-mmacosx-version-min=10.5")
settings.link.flags:Add("-mmacosx-version-min=10.5")
if config.minmacosxsdk.value == 1 then
settings.cc.flags:Add("-isysroot /Developer/SDKs/MacOSX10.5.sdk")
settings.link.flags:Add("-isysroot /Developer/SDKs/MacOSX10.5.sdk")
end
elseif config.stackprotector.value == 1 then
settings.cc.flags:Add("-fstack-protector", "-fstack-protector-all")
settings.link.flags:Add("-fstack-protector", "-fstack-protector-all")

View file

@ -376,6 +376,8 @@ function OptCCompiler(name, default_driver, default_c, default_cxx, desc)
SetDriversCL(settings)
elseif option.driver == "gcc" then
SetDriversGCC(settings)
elseif option.driver == "clang" then
SetDriversClang(settings)
else
error(option.driver.." is not a known c/c++ compile driver")
end
@ -393,7 +395,7 @@ function OptCCompiler(name, default_driver, default_c, default_cxx, desc)
local printhelp = function(option)
local a = ""
if option.desc then a = "for "..option.desc end
print("\t"..option.name.."=gcc|cl")
print("\t"..option.name.."=gcc|cl|clang")
print("\t\twhat c/c++ compile driver to use"..a)
print("\t"..option.name..".c=FILENAME")
print("\t\twhat c compiler executable to use"..a)

97
data/languages/index.txt Normal file
View file

@ -0,0 +1,97 @@
##### language indices #####
belarusian
== Беларуская
== 112
bosnian
== Bosanski
== 70
brazilian_portuguese
== Português brasileiro
== 76
bulgarian
== Български
== 100
czech
== Česky
== 203
danish
== Dansk
== 208
dutch
== Nederlands
== 528
finnish
== Suomi
== 246
french
== Français
== 250
german
== Deutsch
== 276
hungarian
== Magyar
== 348
italian
== Italiano
== 380
kyrgyz
== Кыргызча
== 417
norwegian
== Norsk
== 578
polish
== Polski
== 616
portuguese
== Português
== 620
romanian
== Română
== 642
russian
== Русский
== 643
serbian
== Srpski
== 688
slovak
== Slovensky
== 703
spanish
== Español
== 724
swedish
== Svenska
== 752
turkish
== Türkçe
== 792
ukrainian
== Українська
== 804

686
data/languages/kyrgyz.txt Normal file
View file

@ -0,0 +1,686 @@
##### translated strings #####
%d Bytes
== %d байт
%d of %d servers, %d players
== %d / %d сервер, %d оюнчу
%d%% loaded
== %d%% жүктөлдү
%ds left
== %d сек. калды
%i minute left
== %i минута калды!
%i minutes left
== %i минута калды!
%i second left
== %i секунда калды!
%i seconds left
== %i секунда калды!
%s wins!
== %s утту!
-Page %d-
== -Барак %d-
Abort
== Жокко чыгаруу
Add
== Кошуу
Add Friend
== Досту кошуу
Address
== Дареги
All
== Баары
Alpha
== Тунук.
Always show name plates
== Ат көрнөкчөлөрдү дайыма көрсөтүү
Are you sure that you want to delete the demo?
== Сиз чын эле демонун өчүрүлүшүн каалайсызбы?
Are you sure that you want to quit?
== Сиз чын эле оюндан чыгууну каалайсызбы?
Are you sure that you want to remove the player from your friends list?
== Сиз чын эле бул оюнчуну достор тизмеңизден өчүргүңүз келеби?
As this is the first time you launch the game, please enter your nick name below. It's recommended that you check the settings to adjust them to your liking before joining a server.
== Бул оюндун биринчи жүргүзүлүшү болгону үчүн, төмөн жакка такма атыңызды киргизиңиз. Серверге туташуу алдында ырастоолорду текшериңиз.
Automatically record demos
== Демону автоматтуу түрдө жаздыруу
Automatically take game over screenshot
== Оюн натыйжаларын сүрөткө тартуу
Blue team
== Көктөр
Blue team wins!
== Көктөр утту!
Body
== Дене
Call vote
== Добуш берүү
Change settings
== Ырастоолорду өзгөртүү
Chat
== Маек
Clan
== Кланы
Client
== Клиент
Close
== Чыгуу
Compatible version
== Батышуучу версия
Connect
== Туташуу
Connecting to
== Туташтырылууда
Connection Problems...
== Байланыш көйгөйлөрү...
Console
== Консоль
Controls
== Башкаруу
Count players only
== Оюнчуларды гана саноо
Country
== Өлкө
Crc:
== Crc:
Created:
== Жаратылганы:
Current
== Кезектегиси
Current version: %s
== Кезектеги версиясы: %s
Custom colors
== Өз түстөрүңүз
Delete
== Өчүрүү
Delete demo
== Демону өчүрүү
Demo details
== Демо деталдары
Demofile: %s
== Демофайлы: %s
Demos
== Демолор
Disconnect
== Өчүрүү
Disconnected
== Өчүрүлдү
Display Modes
== Көрсөтүү режимдери
Downloading map
== Карта жүктөөлүүдө
Draw!
== Тең!
Dynamic Camera
== Динамикалык камера
Emoticon
== Эмоциялар
Enter
== Кирүү
Error
== Ката
Error loading demo
== Демону жүктөө учурундагы ката
FSAA samples
== FSAA сэмплдери
Favorite
== Тандалма
Favorites
== Тандалмалар
Feet
== Бут
Filter
== Фильтр
Fire
== Атуу
Folder
== Папка
Force vote
== Тездетүү
Free-View
== Эркин сереп
Friends
== Достор
Fullscreen
== Толук экран
Game
== Оюн
Game info
== Оюн жөнүндө
Game over
== Оюн бүттү
Game type
== Оюн түрү
Game types:
== Оюн түрү:
General
== Негизги
Graphics
== Графика
Grenade
== Гранатомёт
Hammer
== Барскан
Has people playing
== Бош эмес сервер
High Detail
== Жогорку деталдаштыруу
Hook
== Илмек
Host address
== Сервер дареги
Hue
== Түсү
Info
== Маалымат
Internet
== Интернет
Invalid Demo
== Жарабаган демо
Join blue
== Көктөргө
Join game
== Ойноо
Join red
== Кызылдарга
Jump
== Секирүү
Kick player
== Оюнчуну чыгаруу
LAN
== LAN
Language
== Тил
Length:
== Узундугу:
Lht.
== Ач. түс.
Loading
== Жүктөлүүдө
MOTD
== Күндүн билдирүүсү
Map
== Картасы
Map:
== Картасы:
Max Screenshots
== Сүрөттөрдүн жогорку чеги
Max demos
== Демолордун жогорку чеги
Maximum ping:
== Пингдин ж. чеги:
Miscellaneous
== Кошумча
Mouse sens.
== Чычкан сезгич.
Move left
== Солго басуу
Move player to spectators
== Оюнчуну байкоочуларга ташуу
Move right
== Оңго басуу
Movement
== Аракет
Mute when not active
== Активдүү эмес кезде үндү өчүрүү
Name
== Аты
Name plates size
== Ат көрнөкчөлөрдүн өлчөмү
Netversion:
== Версиясы:
New name:
== Жаңы аты:
News
== Жаңылыктар
Next weapon
== Кийин. курал
Nickname
== Такма атыңыз
No
== Жок
No password
== Сырсөзсүз
No servers found
== Серверлер табылган жок
No servers match your filter criteria
== Сиздин фильтриңизге жарай турган серверлер жок
Ok
== ОК
Open
== Ачуу
Parent Folder
== Ата-энелик каталог
Password
== Сырсөзү
Password incorrect
== Сырсөз
Ping
== Пинги
Pistol
== Тапанча
Play
== Көрүү
Play background music
== Фон музыкасын ойнотуу
Player
== Оюнчу
Player country:
== Өлкөсү:
Player options
== Оюнчу опциялары
Players
== Оюнчулар
Please balance teams!
== Команадаларды баланстаңыз!
Prev. weapon
== Мурун. курал
Quality Textures
== Сапаттуу текстуралар
Quick search:
== Тез издөө:
Quit
== Чыгуу
Quit anyway?
== Чыгуу?
REC %3d:%02d
== ЖАЗДЫРУУ %3d:%02d
Reason:
== Себеби:
Record demo
== Демо жаздыруу
Red team
== Кызылдар
Red team wins!
== Кызылдар утту!
Refresh
== Жаңылоо
Refreshing master servers
== Мастер-серверлер тизмесин жаңылоо
Remote console
== Алыскы консоль
Remove
== Өчүрүү
Remove friend
== Досту өчүрүү
Rename
== Атын өзгөртүү
Rename demo
== Демо атын өзгөртүү
Reset filter
== Фильтрлерди түшүрүү
Reset to defaults
== Жарыяланбаска түшүрүү
Rifle
== Бластер
Round
== Раунду
Sample rate
== Жыштыгы
Sat.
== Канык.
Score
== Упайы
Score board
== Табло
Score limit
== Упай чеги
Scoreboard
== Табло
Screenshot
== Сүрөт
Server address:
== Сервер дареги:
Server details
== Сервер деталдары
Server filter
== Сервер фильтри
Server info
== Маалымат
Server not full
== Сервер толук эмес
Settings
== Ырастоолор
Shotgun
== Мылтык
Show chat
== Маекти көрсөтүү
Show friends only
== Достор менен гана
Show ingame HUD
== Оюн ичиндеги HUD'ни көрсөтүү
Show name plates
== Оюнчулардын аттарын көрсөтүү
Show only supported
== Колдолгонду гана көрсөтүү
Size:
== Өлчөмү:
Skins
== Терилер
Sound
== Үн
Sound error
== Үн катасы
Sound volume
== Үн көлөмү
Spectate
== Байкоо
Spectate next
== Кийин. байкоо
Spectate previous
== Мурун. байкоо
Spectator mode
== Байкоочу
Spectators
== Байкоочулар
Standard gametype
== Стандарттуу оюн түрү
Standard map
== Стандарттуу карта
Stop record
== Токтотуу
Strict gametype filter
== Оюн түрүнүн так фильтри
Sudden Death
== Тез өлүм
Switch weapon on pickup
== Көтөрүлгөн куралга которуу
Team
== Команда
Team chat
== Команда маеги
Teeworlds %s is out! Download it at www.teeworlds.com!
== Teeworlds %s чыкты! www.teeworlds.com сайтынан жүктөп алыңыз!
Texture Compression
== Текстура кысылышы
The audio device couldn't be initialised.
== Аудио түзмөгүн инициализациялап алууга мүмкүн эмес.
The server is running a non-standard tuning on a pure game type.
== Бул сервер стандартту эмес ырастоолор менен таза оюн түрүндө иштеп жатат.
There's an unsaved map in the editor, you might want to save it before you quit the game.
== Редактордо сакталбаган карта бар, аны оюндан чыгаар алдында сактасаңыз болот.
Time limit
== Убакыт чеги
Time limit: %d min
== Убакыт чеги: %d мин.
Try again
== ОК
Type
== Түрү
Type:
== Түрү:
UI Color
== Интерфейс түсү
Unable to delete the demo
== Демону өчүрүү мүмкүн эмес
Unable to rename the demo
== Демо атын өзгөртүү мүмкүн эмес
Use sounds
== Үндөрдү колдонуу
Use team colors for name plates
== Аттар үчүн команданын түсүн колдонуу
V-Sync
== Тик синхрондоштуруусу
Version
== Версиясы
Version:
== Версиясы:
Vote command:
== Добуш коммандасы:
Vote description:
== Добуш баяндамасы:
Vote no
== Каршы
Vote yes
== Макул
Voting
== Добуш берүү
Warmup
== Даярдануу
Weapon
== Курал
Welcome to Teeworlds
== Teeworlds'ко кош келиңиз!
Yes
== Ооба
You must restart the game for all settings to take effect.
== Өзгөртүүлөрдү колдонуу үчүн оюнду кайта жүргүзүңүз.
Your skin
== Териңиз
no limit
== чексиз
Game paused
== Оюн бир азга токтотулду
Respawn
== Кайра жаралуу
Show only chat messages from friends
== Достордун гана маек билдирүүлөрүн көрсөтүү
##### needs translation #####
##### old translations #####

View file

@ -231,7 +231,7 @@ Messages = [
NetMessage("Sv_Chat", [
NetIntRange("m_Team", 'TEAM_SPECTATORS', 'TEAM_BLUE'),
NetIntRange("m_ClientID", -1, 'MAX_CLIENTS-1'),
NetString("m_pMessage"),
NetStringStrict("m_pMessage"),
]),
NetMessage("Sv_KillMsg", [
@ -294,7 +294,7 @@ Messages = [
### Client messages
NetMessage("Cl_Say", [
NetBool("m_Team"),
NetString("m_pMessage"),
NetStringStrict("m_pMessage"),
]),
NetMessage("Cl_SetTeam", [

View file

@ -38,7 +38,7 @@ if platform == "src":
# print(valid_platforms)
# sys.exit(-1)
if platform == 'win32':
if platform == 'win32' or platform == 'win64':
exe_ext = ".exe"
use_zip = 1
use_gz = 0

View file

@ -80,7 +80,7 @@ void dbg_assert_imp(const char *filename, int line, int test, const char *msg)
void dbg_break()
{
*((unsigned*)0) = 0x0;
*((volatile unsigned*)0) = 0x0;
}
void dbg_msg(const char *sys, const char *fmt, ...)
@ -176,6 +176,8 @@ void *mem_alloc_debug(const char *filename, int line, unsigned size, unsigned al
MEMTAIL *tail;
MEMHEADER *header = (struct MEMHEADER *)malloc(size+sizeof(MEMHEADER)+sizeof(MEMTAIL));
dbg_assert(header != 0, "mem_alloc failure");
if(!header)
return NULL;
tail = (struct MEMTAIL *)(((char*)(header+1))+size);
header->size = size;
header->filename = filename;
@ -487,7 +489,7 @@ int lock_try(LOCK lock)
#if defined(CONF_FAMILY_UNIX)
return pthread_mutex_trylock((LOCKINTERNAL *)lock);
#elif defined(CONF_FAMILY_WINDOWS)
return TryEnterCriticalSection((LPCRITICAL_SECTION)lock);
return !TryEnterCriticalSection((LPCRITICAL_SECTION)lock);
#else
#error not implemented on this platform
#endif
@ -515,18 +517,20 @@ void lock_release(LOCK lock)
#endif
}
#if defined(CONF_FAMILY_UNIX)
void semaphore_init(SEMAPHORE *sem) { sem_init(sem, 0, 0); }
void semaphore_wait(SEMAPHORE *sem) { sem_wait(sem); }
void semaphore_signal(SEMAPHORE *sem) { sem_post(sem); }
void semaphore_destroy(SEMAPHORE *sem) { sem_destroy(sem); }
#elif defined(CONF_FAMILY_WINDOWS)
void semaphore_init(SEMAPHORE *sem) { *sem = CreateSemaphore(0, 0, 10000, 0); }
void semaphore_wait(SEMAPHORE *sem) { WaitForSingleObject((HANDLE)*sem, 0L); }
void semaphore_signal(SEMAPHORE *sem) { ReleaseSemaphore((HANDLE)*sem, 1, NULL); }
void semaphore_destroy(SEMAPHORE *sem) { CloseHandle((HANDLE)*sem); }
#else
#error not implemented on this platform
#if !defined(CONF_PLATFORM_MACOSX)
#if defined(CONF_FAMILY_UNIX)
void semaphore_init(SEMAPHORE *sem) { sem_init(sem, 0, 0); }
void semaphore_wait(SEMAPHORE *sem) { sem_wait(sem); }
void semaphore_signal(SEMAPHORE *sem) { sem_post(sem); }
void semaphore_destroy(SEMAPHORE *sem) { sem_destroy(sem); }
#elif defined(CONF_FAMILY_WINDOWS)
void semaphore_init(SEMAPHORE *sem) { *sem = CreateSemaphore(0, 0, 10000, 0); }
void semaphore_wait(SEMAPHORE *sem) { WaitForSingleObject((HANDLE)*sem, INFINITE); }
void semaphore_signal(SEMAPHORE *sem) { ReleaseSemaphore((HANDLE)*sem, 1, NULL); }
void semaphore_destroy(SEMAPHORE *sem) { CloseHandle((HANDLE)*sem); }
#else
#error not implemented on this platform
#endif
#endif
@ -914,6 +918,7 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
NETSOCKET sock = invalid_socket;
NETADDR tmpbindaddr = bindaddr;
int broadcast = 1;
int recvsize = 65536;
if(bindaddr.type&NETTYPE_IPV4)
{
@ -928,13 +933,13 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
{
sock.type |= NETTYPE_IPV4;
sock.ipv4sock = socket;
/* set boardcast */
setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
/* set receive buffer size */
setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char*)&recvsize, sizeof(recvsize));
}
/* set non-blocking */
net_set_non_blocking(sock);
/* set boardcast */
setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
}
if(bindaddr.type&NETTYPE_IPV6)
@ -950,15 +955,18 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
{
sock.type |= NETTYPE_IPV6;
sock.ipv6sock = socket;
/* set boardcast */
setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
/* set receive buffer size */
setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char*)&recvsize, sizeof(recvsize));
}
/* set non-blocking */
net_set_non_blocking(sock);
/* set boardcast */
setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
}
/* set non-blocking */
net_set_non_blocking(sock);
/* return */
return sock;
}
@ -1834,6 +1842,27 @@ int str_toint(const char *str) { return atoi(str); }
float str_tofloat(const char *str) { return atof(str); }
const char *str_utf8_skip_whitespaces(const char *str)
{
const char *str_old;
int code;
while(*str)
{
str_old = str;
code = str_utf8_decode(&str);
// check if unicode is not empty
if(code > 0x20 && code != 0xA0 && code != 0x034F && (code < 0x2000 || code > 0x200F) && (code < 0x2028 || code > 0x202F) &&
(code < 0x205F || code > 0x2064) && (code < 0x206A || code > 0x206F) && (code < 0xFE00 || code > 0xFE0F) &&
code != 0xFEFF && (code < 0xFFF9 || code > 0xFFFC))
{
return str_old;
}
}
return str;
}
static int str_utf8_isstart(char c)
{

View file

@ -33,6 +33,13 @@ void dbg_assert(int test, const char *msg);
#define dbg_assert(test,msg) dbg_assert_imp(__FILE__, __LINE__, test, msg)
void dbg_assert_imp(const char *filename, int line, int test, const char *msg);
#ifdef __clang_analyzer__
#include <assert.h>
#undef dbg_assert
#define dbg_assert(test,msg) assert(test)
#endif
/*
Function: dbg_break
Breaks into the debugger.
@ -403,19 +410,21 @@ void lock_release(LOCK lock);
/* Group: Semaphores */
#if defined(CONF_FAMILY_UNIX)
#include <semaphore.h>
typedef sem_t SEMAPHORE;
#elif defined(CONF_FAMILY_WINDOWS)
typedef void* SEMAPHORE;
#else
#error missing sempahore implementation
#endif
#if !defined(CONF_PLATFORM_MACOSX)
#if defined(CONF_FAMILY_UNIX)
#include <semaphore.h>
typedef sem_t SEMAPHORE;
#elif defined(CONF_FAMILY_WINDOWS)
typedef void* SEMAPHORE;
#else
#error missing sempahore implementation
#endif
void semaphore_init(SEMAPHORE *sem);
void semaphore_wait(SEMAPHORE *sem);
void semaphore_signal(SEMAPHORE *sem);
void semaphore_destroy(SEMAPHORE *sem);
void semaphore_init(SEMAPHORE *sem);
void semaphore_wait(SEMAPHORE *sem);
void semaphore_signal(SEMAPHORE *sem);
void semaphore_destroy(SEMAPHORE *sem);
#endif
/* Group: Timer */
#ifdef __GNUC__
@ -1207,6 +1216,7 @@ unsigned str_quickhash(const char *str);
*/
void gui_messagebox(const char *title, const char *message);
const char *str_utf8_skip_whitespaces(const char *str);
/*
Function: str_utf8_rewind

View file

@ -5,7 +5,7 @@
#include <base/system.h>
inline void assert(bool statement)
inline void tl_assert(bool statement)
{
dbg_assert(statement, "assert!");
}

View file

@ -150,11 +150,11 @@ public:
}
bool empty() const { return begin >= end; }
void pop_front() { assert(!empty()); begin++; }
void pop_back() { assert(!empty()); end--; }
T& front() { assert(!empty()); return *begin; }
T& back() { assert(!empty()); return *(end-1); }
T& index(unsigned i) { assert(i >= 0 && i < (unsigned)(end-begin)); return begin[i]; }
void pop_front() { tl_assert(!empty()); begin++; }
void pop_back() { tl_assert(!empty()); end--; }
T& front() { tl_assert(!empty()); return *begin; }
T& back() { tl_assert(!empty()); return *(end-1); }
T& index(unsigned i) { tl_assert(i < (unsigned)(end-begin)); return begin[i]; }
unsigned size() const { return (unsigned)(end-begin); }
plain_range slice(unsigned startindex, unsigned endindex)
{

View file

@ -7,19 +7,19 @@
atomic_inc - should return the value after increment
atomic_dec - should return the value after decrement
atomic_compswap - should return the value before the eventual swap
sync_barrier - creates a full hardware fence
*/
#if defined(__GNUC__)
inline unsigned atomic_inc(volatile unsigned *pValue)
{
return __sync_fetch_and_add(pValue, 1);
return __sync_add_and_fetch(pValue, 1);
}
inline unsigned atomic_dec(volatile unsigned *pValue)
{
return __sync_fetch_and_add(pValue, -1);
return __sync_add_and_fetch(pValue, -1);
}
inline unsigned atomic_compswap(volatile unsigned *pValue, unsigned comperand, unsigned value)
@ -35,6 +35,9 @@
#elif defined(_MSC_VER)
#include <intrin.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
inline unsigned atomic_inc(volatile unsigned *pValue)
{
return _InterlockedIncrement((volatile long *)pValue);
@ -52,21 +55,27 @@
inline void sync_barrier()
{
_ReadWriteBarrier();
MemoryBarrier();
}
#else
#error missing atomic implementation for this compiler
#endif
class semaphore
{
SEMAPHORE sem;
public:
semaphore() { semaphore_init(&sem); }
~semaphore() { semaphore_destroy(&sem); }
void wait() { semaphore_wait(&sem); }
void signal() { semaphore_signal(&sem); }
};
#if defined(CONF_PLATFORM_MACOSX)
/*
use semaphore provided by SDL on macosx
*/
#else
class semaphore
{
SEMAPHORE sem;
public:
semaphore() { semaphore_init(&sem); }
~semaphore() { semaphore_destroy(&sem); }
void wait() { semaphore_wait(&sem); }
void signal() { semaphore_signal(&sem); }
};
#endif
class lock
{

View file

@ -11,6 +11,9 @@
void CGraphicsBackend_Threaded::ThreadFunc(void *pUser)
{
#ifdef CONF_PLATFORM_MACOSX
CAutoreleasePool AutoreleasePool;
#endif
CGraphicsBackend_Threaded *pThis = (CGraphicsBackend_Threaded *)pUser;
while(!pThis->m_Shutdown)
@ -97,6 +100,41 @@ int CCommandProcessorFragment_OpenGL::TexFormatToOpenGLFormat(int TexFormat)
return GL_RGBA;
}
unsigned char CCommandProcessorFragment_OpenGL::Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp)
{
int Value = 0;
for(int x = 0; x < ScaleW; x++)
for(int y = 0; y < ScaleH; y++)
Value += pData[((v+y)*w+(u+x))*Bpp+Offset];
return Value/(ScaleW*ScaleH);
}
void *CCommandProcessorFragment_OpenGL::Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData)
{
unsigned char *pTmpData;
int ScaleW = Width/NewWidth;
int ScaleH = Height/NewHeight;
int Bpp = 3;
if(Format == CCommandBuffer::TEXFORMAT_RGBA)
Bpp = 4;
pTmpData = (unsigned char *)mem_alloc(NewWidth*NewHeight*Bpp, 1);
int c = 0;
for(int y = 0; y < NewHeight; y++)
for(int x = 0; x < NewWidth; x++, c++)
{
pTmpData[c*Bpp] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 0, ScaleW, ScaleH, Bpp);
pTmpData[c*Bpp+1] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 1, ScaleW, ScaleH, Bpp);
pTmpData[c*Bpp+2] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 2, ScaleW, ScaleH, Bpp);
if(Bpp == 4)
pTmpData[c*Bpp+3] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 3, ScaleW, ScaleH, Bpp);
}
return pTmpData;
}
void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &State)
{
// blend
@ -130,7 +168,7 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St
if(State.m_Texture >= 0 && State.m_Texture < CCommandBuffer::MAX_TEXTURES)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_aTextures[State.m_Texture]);
glBindTexture(GL_TEXTURE_2D, m_aTextures[State.m_Texture].m_Tex);
}
else
glDisable(GL_TEXTURE_2D);
@ -155,9 +193,14 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St
glOrtho(State.m_ScreenTL.x, State.m_ScreenBR.x, State.m_ScreenBR.y, State.m_ScreenTL.y, 1.0f, 10.f);
}
void CCommandProcessorFragment_OpenGL::Cmd_Init(const SCommand_Init *pCommand)
{
m_pTextureMemoryUsage = pCommand->m_pTextureMemoryUsage;
}
void CCommandProcessorFragment_OpenGL::Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand)
{
glBindTexture(GL_TEXTURE_2D, m_aTextures[pCommand->m_Slot]);
glBindTexture(GL_TEXTURE_2D, m_aTextures[pCommand->m_Slot].m_Tex);
glTexSubImage2D(GL_TEXTURE_2D, 0, pCommand->m_X, pCommand->m_Y, pCommand->m_Width, pCommand->m_Height,
TexFormatToOpenGLFormat(pCommand->m_Format), GL_UNSIGNED_BYTE, pCommand->m_pData);
mem_free(pCommand->m_pData);
@ -165,31 +208,85 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Update(const CCommandBuffer::
void CCommandProcessorFragment_OpenGL::Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand)
{
glDeleteTextures(1, &m_aTextures[pCommand->m_Slot]);
glDeleteTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex);
*m_pTextureMemoryUsage -= m_aTextures[pCommand->m_Slot].m_MemSize;
}
void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand)
{
int Width = pCommand->m_Width;
int Height = pCommand->m_Height;
void *pTexData = pCommand->m_pData;
// resample if needed
if(pCommand->m_Format == CCommandBuffer::TEXFORMAT_RGBA || pCommand->m_Format == CCommandBuffer::TEXFORMAT_RGB)
{
int MaxTexSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTexSize);
if(Width > MaxTexSize || Height > MaxTexSize)
{
do
{
Width>>=1;
Height>>=1;
}
while(Width > MaxTexSize || Height > MaxTexSize);
void *pTmpData = Rescale(pCommand->m_Width, pCommand->m_Height, Width, Height, pCommand->m_Format, static_cast<const unsigned char *>(pCommand->m_pData));
mem_free(pTexData);
pTexData = pTmpData;
}
else if(Width > 16 && Height > 16 && (pCommand->m_Flags&CCommandBuffer::TEXFLAG_QUALITY) == 0)
{
Width>>=1;
Height>>=1;
void *pTmpData = Rescale(pCommand->m_Width, pCommand->m_Height, Width, Height, pCommand->m_Format, static_cast<const unsigned char *>(pCommand->m_pData));
mem_free(pTexData);
pTexData = pTmpData;
}
}
int Oglformat = TexFormatToOpenGLFormat(pCommand->m_Format);
int StoreOglformat = TexFormatToOpenGLFormat(pCommand->m_StoreFormat);
glGenTextures(1, &m_aTextures[pCommand->m_Slot]);
glBindTexture(GL_TEXTURE_2D, m_aTextures[pCommand->m_Slot]);
if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_COMPRESSED)
{
switch(StoreOglformat)
{
case GL_RGB: StoreOglformat = GL_COMPRESSED_RGB_ARB; break;
case GL_ALPHA: StoreOglformat = GL_COMPRESSED_ALPHA_ARB; break;
case GL_RGBA: StoreOglformat = GL_COMPRESSED_RGBA_ARB; break;
default: StoreOglformat = GL_COMPRESSED_RGBA_ARB;
}
}
glGenTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex);
glBindTexture(GL_TEXTURE_2D, m_aTextures[pCommand->m_Slot].m_Tex);
if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_NOMIPMAPS)
{
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, pCommand->m_Width, pCommand->m_Height, 0, Oglformat, GL_UNSIGNED_BYTE, pCommand->m_pData);
glTexImage2D(GL_TEXTURE_2D, 0, StoreOglformat, Width, Height, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, StoreOglformat, pCommand->m_Width, pCommand->m_Height, Oglformat, GL_UNSIGNED_BYTE, pCommand->m_pData);
gluBuild2DMipmaps(GL_TEXTURE_2D, StoreOglformat, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pTexData);
}
mem_free(pCommand->m_pData);
// calculate memory usage
m_aTextures[pCommand->m_Slot].m_MemSize = Width*Height*pCommand->m_PixelSize;
while(Width > 2 && Height > 2)
{
Width>>=1;
Height>>=1;
m_aTextures[pCommand->m_Slot].m_MemSize += Width*Height*pCommand->m_PixelSize;
}
*m_pTextureMemoryUsage += m_aTextures[pCommand->m_Slot].m_MemSize;
mem_free(pTexData);
}
void CCommandProcessorFragment_OpenGL::Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand)
@ -260,12 +357,14 @@ void CCommandProcessorFragment_OpenGL::Cmd_Screenshot(const CCommandBuffer::SCom
CCommandProcessorFragment_OpenGL::CCommandProcessorFragment_OpenGL()
{
mem_zero(m_aTextures, sizeof(m_aTextures));
m_pTextureMemoryUsage = 0;
}
bool CCommandProcessorFragment_OpenGL::RunCommand(const CCommandBuffer::SCommand * pBaseCommand)
{
switch(pBaseCommand->m_Cmd)
{
case CMD_INIT: Cmd_Init(static_cast<const SCommand_Init *>(pBaseCommand)); break;
case CCommandBuffer::CMD_TEXTURE_CREATE: Cmd_Texture_Create(static_cast<const CCommandBuffer::SCommand_Texture_Create *>(pBaseCommand)); break;
case CCommandBuffer::CMD_TEXTURE_DESTROY: Cmd_Texture_Destroy(static_cast<const CCommandBuffer::SCommand_Texture_Destroy *>(pBaseCommand)); break;
case CCommandBuffer::CMD_TEXTURE_UPDATE: Cmd_Texture_Update(static_cast<const CCommandBuffer::SCommand_Texture_Update *>(pBaseCommand)); break;
@ -388,7 +487,7 @@ void CCommandProcessor_SDL_OpenGL::RunBuffer(CCommandBuffer *pBuffer)
// ------------ CGraphicsBackend_SDL_OpenGL
int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Width, int Height, int FsaaSamples, int Flags)
int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags)
{
if(!SDL_WasInit(SDL_INIT_VIDEO))
{
@ -400,13 +499,20 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Width, int Height,
#ifdef CONF_FAMILY_WINDOWS
if(!getenv("SDL_VIDEO_WINDOW_POS") && !getenv("SDL_VIDEO_CENTERED")) // ignore_convention
putenv("SDL_VIDEO_WINDOW_POS=8,27"); // ignore_convention
putenv("SDL_VIDEO_WINDOW_POS=center"); // ignore_convention
#endif
}
const SDL_VideoInfo *pInfo = SDL_GetVideoInfo();
SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); // prevent stuck mouse cursor sdl-bug when loosing fullscreen focus in windows
// use current resolution as default
if(*Width == 0 || *Height == 0)
{
*Width = pInfo->current_w;
*Height = pInfo->current_h;
}
// set flags
int SdlFlags = SDL_OPENGL;
if(Flags&IGraphicsBackend::INITFLAG_RESIZABLE)
@ -420,6 +526,13 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Width, int Height,
if(pInfo->blit_hw) // ignore_convention
SdlFlags |= SDL_HWACCEL;
dbg_assert(!(Flags&IGraphicsBackend::INITFLAG_BORDERLESS)
|| !(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN),
"only one of borderless and fullscreen may be activated at the same time");
if(Flags&IGraphicsBackend::INITFLAG_BORDERLESS)
SdlFlags |= SDL_NOFRAME;
if(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN)
SdlFlags |= SDL_FULLSCREEN;
@ -436,13 +549,13 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Width, int Height,
}
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, Flags&CCommandBuffer::INITFLAG_VSYNC ? 1 : 0);
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, Flags&IGraphicsBackend::INITFLAG_VSYNC ? 1 : 0);
// set caption
SDL_WM_SetCaption(pName, pName);
// create window
m_pScreenSurface = SDL_SetVideoMode(Width, Height, 0, SdlFlags);
m_pScreenSurface = SDL_SetVideoMode(*Width, *Height, 0, SdlFlags);
if(!m_pScreenSurface)
{
dbg_msg("gfx", "unable to set video mode: %s", SDL_GetError());
@ -460,11 +573,14 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Width, int Height,
m_pProcessor = new CCommandProcessor_SDL_OpenGL;
StartProcessor(m_pProcessor);
// issue a init command
// issue init commands for OpenGL and SDL
CCommandBuffer CmdBuffer(1024, 512);
CCommandProcessorFragment_SDL::SCommand_Init Cmd;
Cmd.m_Context = m_GLContext;
CmdBuffer.AddCommand(Cmd);
CCommandProcessorFragment_OpenGL::SCommand_Init CmdOpenGL;
CmdOpenGL.m_pTextureMemoryUsage = &m_TextureMemoryUsage;
CmdBuffer.AddCommand(CmdOpenGL);
CCommandProcessorFragment_SDL::SCommand_Init CmdSDL;
CmdSDL.m_Context = m_GLContext;
CmdBuffer.AddCommand(CmdSDL);
RunBuffer(&CmdBuffer);
WaitForIdle();
@ -490,6 +606,11 @@ int CGraphicsBackend_SDL_OpenGL::Shutdown()
return 0;
}
int CGraphicsBackend_SDL_OpenGL::MemoryUsage() const
{
return m_TextureMemoryUsage;
}
void CGraphicsBackend_SDL_OpenGL::Minimize()
{
SDL_WM_IconifyWindow();

View file

@ -28,24 +28,72 @@
static void GL_SwapBuffers(const SGLContext &Context) { SwapBuffers(Context.m_hDC); }
#elif defined(CONF_PLATFORM_MACOSX)
#include <AGL/agl.h>
#include <objc/objc-runtime.h>
class semaphore
{
SDL_sem *sem;
public:
semaphore() { sem = SDL_CreateSemaphore(0); }
~semaphore() { SDL_DestroySemaphore(sem); }
void wait() { SDL_SemWait(sem); }
void signal() { SDL_SemPost(sem); }
};
struct SGLContext
{
AGLContext m_Context;
id m_Context;
};
static SGLContext GL_GetCurrentContext()
{
SGLContext Context;
Context.m_Context = aglGetCurrentContext();
Class NSOpenGLContextClass = (Class) objc_getClass("NSOpenGLContext");
SEL selector = sel_registerName("currentContext");
Context.m_Context = objc_msgSend((objc_object*) NSOpenGLContextClass, selector);
return Context;
}
static void GL_MakeCurrent(const SGLContext &Context) { aglSetCurrentContext(Context.m_Context); }
static void GL_ReleaseContext(const SGLContext &Context) { aglSetCurrentContext(NULL); }
static void GL_SwapBuffers(const SGLContext &Context) { aglSwapBuffers(Context.m_Context); }
static void GL_MakeCurrent(const SGLContext &Context)
{
SEL selector = sel_registerName("makeCurrentContext");
objc_msgSend(Context.m_Context, selector);
}
static void GL_ReleaseContext(const SGLContext &Context)
{
Class NSOpenGLContextClass = (Class) objc_getClass("NSOpenGLContext");
SEL selector = sel_registerName("clearCurrentContext");
objc_msgSend((objc_object*) NSOpenGLContextClass, selector);
}
static void GL_SwapBuffers(const SGLContext &Context)
{
SEL selector = sel_registerName("flushBuffer");
objc_msgSend(Context.m_Context, selector);
}
class CAutoreleasePool
{
private:
id m_Pool;
public:
CAutoreleasePool()
{
Class NSAutoreleasePoolClass = (Class) objc_getClass("NSAutoreleasePool");
m_Pool = class_createInstance(NSAutoreleasePoolClass, 0);
SEL selector = sel_registerName("init");
objc_msgSend(m_Pool, selector);
}
~CAutoreleasePool()
{
SEL selector = sel_registerName("drain");
objc_msgSend(m_Pool, selector);
}
};
#elif defined(CONF_FAMILY_UNIX)
#include <GL/glx.h>
@ -119,11 +167,34 @@ public:
// takes care of opengl related rendering
class CCommandProcessorFragment_OpenGL
{
GLuint m_aTextures[CCommandBuffer::MAX_TEXTURES];
struct CTexture
{
GLuint m_Tex;
int m_MemSize;
};
CTexture m_aTextures[CCommandBuffer::MAX_TEXTURES];
volatile int *m_pTextureMemoryUsage;
public:
enum
{
CMD_INIT = CCommandBuffer::CMDGROUP_PLATFORM_OPENGL,
};
struct SCommand_Init : public CCommandBuffer::SCommand
{
SCommand_Init() : SCommand(CMD_INIT) {}
volatile int *m_pTextureMemoryUsage;
};
private:
static int TexFormatToOpenGLFormat(int TexFormat);
static unsigned char Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp);
static void *Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData);
void SetState(const CCommandBuffer::SState &State);
void Cmd_Init(const SCommand_Init *pCommand);
void Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand);
void Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand);
void Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand);
@ -145,7 +216,7 @@ class CCommandProcessorFragment_SDL
public:
enum
{
CMD_INIT = CCommandBuffer::CMDGROUP_PLATFORM,
CMD_INIT = CCommandBuffer::CMDGROUP_PLATFORM_SDL,
CMD_SHUTDOWN,
};
@ -187,10 +258,13 @@ class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded
SDL_Surface *m_pScreenSurface;
ICommandProcessor *m_pProcessor;
SGLContext m_GLContext;
volatile int m_TextureMemoryUsage;
public:
virtual int Init(const char *pName, int Width, int Height, int FsaaSamples, int Flags);
virtual int Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags);
virtual int Shutdown();
virtual int MemoryUsage() const;
virtual void Minimize();
virtual void Maximize();
virtual int WindowActive();

View file

@ -8,7 +8,6 @@
#include <base/math.h>
#include <base/vmath.h>
#include <base/system.h>
#include <base/tl/threading.h>
#include <game/client/gameclient.h>
@ -140,14 +139,16 @@ void CGraph::Render(IGraphics *pGraphics, int Font, float x, float y, float w, f
pGraphics->LinesEnd();
pGraphics->TextureSet(Font);
pGraphics->QuadsText(x+2, y+h-16, 16, 1,1,1,1, pDescription);
pGraphics->QuadsBegin();
pGraphics->QuadsText(x+2, y+h-16, 16, pDescription);
char aBuf[32];
str_format(aBuf, sizeof(aBuf), "%.2f", m_Max);
pGraphics->QuadsText(x+w-8*str_length(aBuf)-8, y+2, 16, 1,1,1,1, aBuf);
pGraphics->QuadsText(x+w-8*str_length(aBuf)-8, y+2, 16, aBuf);
str_format(aBuf, sizeof(aBuf), "%.2f", m_Min);
pGraphics->QuadsText(x+w-8*str_length(aBuf)-8, y+h-16, 16, 1,1,1,1, aBuf);
pGraphics->QuadsText(x+w-8*str_length(aBuf)-8, y+h-16, 16, aBuf);
pGraphics->QuadsEnd();
}
@ -681,6 +682,7 @@ void CClient::DebugRender()
//m_pGraphics->BlendNormal();
Graphics()->TextureSet(m_DebugFont);
Graphics()->MapScreen(0,0,Graphics()->ScreenWidth(),Graphics()->ScreenHeight());
Graphics()->QuadsBegin();
if(time_get()-LastSnap > time_freq())
{
@ -702,7 +704,7 @@ void CClient::DebugRender()
mem_stats()->total_allocations,
Graphics()->MemoryUsage()/1024,
(int)(1.0f/FrameTimeAvg + 0.5f));
Graphics()->QuadsText(2, 2, 16, 1,1,1,1, aBuffer);
Graphics()->QuadsText(2, 2, 16, aBuffer);
{
@ -718,7 +720,7 @@ void CClient::DebugRender()
str_format(aBuffer, sizeof(aBuffer), "send: %3d %5d+%4d=%5d (%3d kbps) avg: %5d\nrecv: %3d %5d+%4d=%5d (%3d kbps) avg: %5d",
SendPackets, SendBytes, SendPackets*42, SendTotal, (SendTotal*8)/1024, SendBytes/SendPackets,
RecvPackets, RecvBytes, RecvPackets*42, RecvTotal, (RecvTotal*8)/1024, RecvBytes/RecvPackets);
Graphics()->QuadsText(2, 14, 16, 1,1,1,1, aBuffer);
Graphics()->QuadsText(2, 14, 16, aBuffer);
}
// render rates
@ -731,7 +733,7 @@ void CClient::DebugRender()
{
str_format(aBuffer, sizeof(aBuffer), "%4d %20s: %8d %8d %8d", i, GameClient()->GetItemName(i), m_SnapshotDelta.GetDataRate(i)/8, m_SnapshotDelta.GetDataUpdates(i),
(m_SnapshotDelta.GetDataRate(i)/m_SnapshotDelta.GetDataUpdates(i))/8);
Graphics()->QuadsText(2, 100+y*12, 16, 1,1,1,1, aBuffer);
Graphics()->QuadsText(2, 100+y*12, 16, aBuffer);
y++;
}
}
@ -739,7 +741,8 @@ void CClient::DebugRender()
str_format(aBuffer, sizeof(aBuffer), "pred: %d ms",
(int)((m_PredictedTime.Get(Now)-m_GameTime.Get(Now))*1000/(float)time_freq()));
Graphics()->QuadsText(2, 70, 16, 1,1,1,1, aBuffer);
Graphics()->QuadsText(2, 70, 16, aBuffer);
Graphics()->QuadsEnd();
// render graphs
if(g_Config.m_DbgGraphs)
@ -1330,7 +1333,6 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
}
// unpack delta
PurgeTick = DeltaTick;
SnapSize = m_SnapshotDelta.UnpackDelta(pDeltaShot, pTmpBuffer3, pDeltaData, DeltaSize);
if(SnapSize < 0)
{
@ -1369,7 +1371,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
if(m_aSnapshots[SNAP_PREV] && m_aSnapshots[SNAP_PREV]->m_Tick < PurgeTick)
PurgeTick = m_aSnapshots[SNAP_PREV]->m_Tick;
if(m_aSnapshots[SNAP_CURRENT] && m_aSnapshots[SNAP_CURRENT]->m_Tick < PurgeTick)
PurgeTick = m_aSnapshots[SNAP_PREV]->m_Tick;
PurgeTick = m_aSnapshots[SNAP_CURRENT]->m_Tick;
m_SnapshotStorage.PurgeUntil(PurgeTick);
// add new
@ -1766,14 +1768,19 @@ void CClient::Run()
// open socket
{
NETADDR BindAddr;
if(g_Config.m_Bindaddr[0] == 0 || net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) != 0)
if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
{
// got bindaddr
BindAddr.type = NETTYPE_ALL;
}
else
{
mem_zero(&BindAddr, sizeof(BindAddr));
BindAddr.type = NETTYPE_ALL;
}
if(!m_NetClient.Open(BindAddr, 0))
{
dbg_msg("client", "couldn't start network");
dbg_msg("client", "couldn't open socket");
return;
}
}
@ -1957,10 +1964,10 @@ void CClient::Run()
break;
// beNice
if(g_Config.m_DbgStress)
if(g_Config.m_ClCpuThrottle)
thread_sleep(g_Config.m_ClCpuThrottle);
else if(g_Config.m_DbgStress || !m_pGraphics->WindowActive())
thread_sleep(5);
else if(g_Config.m_ClCpuThrottle || !m_pGraphics->WindowActive())
thread_sleep(1);
if(g_Config.m_DbgHitch)
{

View file

@ -175,8 +175,6 @@ class CClient : public IClient, public CDemoPlayer::IListner
class CHostLookup m_VersionServeraddr;
} m_VersionInfo;
semaphore m_GfxRenderSemaphore;
semaphore m_GfxStateSemaphore;
volatile int m_GfxState;
static void GraphicsThreadProxy(void *pThis) { ((CClient*)pThis)->GraphicsThread(); }
void GraphicsThread();

View file

@ -22,6 +22,20 @@
#include "graphics.h"
#if defined(CONF_PLATFORM_MACOSX)
class semaphore
{
SDL_sem *sem;
public:
semaphore() { sem = SDL_CreateSemaphore(0); }
~semaphore() { SDL_DestroySemaphore(sem); }
void wait() { SDL_SemWait(sem); }
void signal() { SDL_SemPost(sem); }
};
#endif
static CVideoMode g_aFakeModes[] = {
{320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8},
{720,400,8,8,8}, {768,576,8,8,8}, {800,600,8,8,8},
@ -686,13 +700,10 @@ void CGraphics_OpenGL::QuadsDrawFreeform(const CFreeformItem *pArray, int Num)
AddVertices(4*Num);
}
void CGraphics_OpenGL::QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText)
void CGraphics_OpenGL::QuadsText(float x, float y, float Size, const char *pText)
{
float StartX = x;
QuadsBegin();
SetColor(r,g,b,a);
while(*pText)
{
char c = *pText;
@ -716,8 +727,6 @@ void CGraphics_OpenGL::QuadsText(float x, float y, float Size, float r, float g,
x += Size/2;
}
}
QuadsEnd();
}
int CGraphics_OpenGL::Init()
@ -761,12 +770,19 @@ int CGraphics_OpenGL::Init()
int CGraphics_SDL::TryInit()
{
m_ScreenWidth = g_Config.m_GfxScreenWidth;
m_ScreenHeight = g_Config.m_GfxScreenHeight;
const SDL_VideoInfo *pInfo = SDL_GetVideoInfo();
SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); // prevent stuck mouse cursor sdl-bug when loosing fullscreen focus in windows
// use current resolution as default
if(g_Config.m_GfxScreenWidth == 0 || g_Config.m_GfxScreenHeight == 0)
{
g_Config.m_GfxScreenWidth = pInfo->current_w;
g_Config.m_GfxScreenHeight = pInfo->current_h;
}
m_ScreenWidth = g_Config.m_GfxScreenWidth;
m_ScreenHeight = g_Config.m_GfxScreenHeight;
// set flags
int Flags = SDL_OPENGL;
if(g_Config.m_DbgResizable)
@ -780,7 +796,15 @@ int CGraphics_SDL::TryInit()
if(pInfo->blit_hw) // ignore_convention
Flags |= SDL_HWACCEL;
if(g_Config.m_GfxFullscreen)
if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
{
dbg_msg("gfx", "both borderless and fullscreen activated, disabling borderless");
g_Config.m_GfxBorderless = 0;
}
if(g_Config.m_GfxBorderless)
Flags |= SDL_NOFRAME;
else if(g_Config.m_GfxFullscreen)
Flags |= SDL_FULLSCREEN;
// set gl attributes
@ -876,7 +900,7 @@ int CGraphics_SDL::Init()
#ifdef CONF_FAMILY_WINDOWS
if(!getenv("SDL_VIDEO_WINDOW_POS") && !getenv("SDL_VIDEO_CENTERED")) // ignore_convention
putenv("SDL_VIDEO_WINDOW_POS=8,27"); // ignore_convention
putenv("SDL_VIDEO_WINDOW_POS=center"); // ignore_convention
#endif
if(InitWindow() != 0)
@ -929,7 +953,8 @@ void CGraphics_SDL::Swap()
{
if(m_DoScreenshot)
{
ScreenshotDirect(m_aScreenshotName);
if(WindowActive())
ScreenshotDirect(m_aScreenshotName);
m_DoScreenshot = false;
}

View file

@ -119,7 +119,7 @@ public:
virtual void QuadsDraw(CQuadItem *pArray, int Num);
virtual void QuadsDrawTL(const CQuadItem *pArray, int Num);
virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num);
virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText);
virtual void QuadsText(float x, float y, float Size, const char *pText);
virtual int Init();
};

View file

@ -126,41 +126,6 @@ void CGraphics_Threaded::Rotate4(const CCommandBuffer::SPoint &rCenter, CCommand
}
}
unsigned char CGraphics_Threaded::Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp)
{
int Value = 0;
for(int x = 0; x < ScaleW; x++)
for(int y = 0; y < ScaleH; y++)
Value += pData[((v+y)*w+(u+x))*Bpp+Offset];
return Value/(ScaleW*ScaleH);
}
unsigned char *CGraphics_Threaded::Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData)
{
unsigned char *pTmpData;
int ScaleW = Width/NewWidth;
int ScaleH = Height/NewHeight;
int Bpp = 3;
if(Format == CImageInfo::FORMAT_RGBA)
Bpp = 4;
pTmpData = (unsigned char *)mem_alloc(NewWidth*NewHeight*Bpp, 1);
int c = 0;
for(int y = 0; y < NewHeight; y++)
for(int x = 0; x < NewWidth; x++, c++)
{
pTmpData[c*Bpp] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 0, ScaleW, ScaleH, Bpp);
pTmpData[c*Bpp+1] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 1, ScaleW, ScaleH, Bpp);
pTmpData[c*Bpp+2] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 2, ScaleW, ScaleH, Bpp);
if(Bpp == 4)
pTmpData[c*Bpp+3] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 3, ScaleW, ScaleH, Bpp);
}
return pTmpData;
}
CGraphics_Threaded::CGraphics_Threaded()
{
m_State.m_ScreenTL.x = 0;
@ -247,7 +212,7 @@ void CGraphics_Threaded::WrapClamp()
int CGraphics_Threaded::MemoryUsage() const
{
return m_TextureMemoryUsage;
return m_pBackend->MemoryUsage();
}
void CGraphics_Threaded::MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY)
@ -312,8 +277,7 @@ int CGraphics_Threaded::UnloadTexture(int Index)
Cmd.m_Slot = Index;
m_pCommandBuffer->AddCommand(Cmd);
m_aTextures[Index].m_Next = m_FirstFreeTexture;
m_TextureMemoryUsage -= m_aTextures[Index].m_MemSize;
m_aTextureIndices[Index] = m_FirstFreeTexture;
m_FirstFreeTexture = Index;
return 0;
}
@ -326,6 +290,16 @@ static int ImageFormatToTexFormat(int Format)
return CCommandBuffer::TEXFORMAT_RGBA;
}
static int ImageFormatToPixelSize(int Format)
{
switch(Format)
{
case CImageInfo::FORMAT_RGB: return 3;
case CImageInfo::FORMAT_ALPHA: return 1;
default: return 4;
}
}
int CGraphics_Threaded::LoadTextureRawSub(int TextureID, int x, int y, int Width, int Height, int Format, const void *pData)
{
@ -338,13 +312,7 @@ int CGraphics_Threaded::LoadTextureRawSub(int TextureID, int x, int y, int Width
Cmd.m_Format = ImageFormatToTexFormat(Format);
// calculate memory usage
int PixelSize = 4;
if(Format == CImageInfo::FORMAT_RGB)
PixelSize = 3;
else if(Format == CImageInfo::FORMAT_ALPHA)
PixelSize = 1;
int MemSize = Width*Height*PixelSize;
int MemSize = Width*Height*ImageFormatToPixelSize(Format);
// copy texture data
void *pTmpData = mem_alloc(MemSize, sizeof(void*));
@ -364,13 +332,14 @@ int CGraphics_Threaded::LoadTextureRaw(int Width, int Height, int Format, const
// grab texture
int Tex = m_FirstFreeTexture;
m_FirstFreeTexture = m_aTextures[Tex].m_Next;
m_aTextures[Tex].m_Next = -1;
m_FirstFreeTexture = m_aTextureIndices[Tex];
m_aTextureIndices[Tex] = -1;
CCommandBuffer::SCommand_Texture_Create Cmd;
Cmd.m_Slot = Tex;
Cmd.m_Width = Width;
Cmd.m_Height = Height;
Cmd.m_PixelSize = ImageFormatToPixelSize(Format);
Cmd.m_Format = ImageFormatToTexFormat(Format);
Cmd.m_StoreFormat = ImageFormatToTexFormat(StoreFormat);
@ -378,17 +347,13 @@ int CGraphics_Threaded::LoadTextureRaw(int Width, int Height, int Format, const
Cmd.m_Flags = 0;
if(Flags&IGraphics::TEXLOAD_NOMIPMAPS)
Cmd.m_Flags |= CCommandBuffer::TEXFLAG_NOMIPMAPS;
// calculate memory usage
int PixelSize = 4;
if(Format == CImageInfo::FORMAT_RGB)
PixelSize = 3;
else if(Format == CImageInfo::FORMAT_ALPHA)
PixelSize = 1;
int MemSize = Width*Height*PixelSize;
if(g_Config.m_GfxTextureCompression)
Cmd.m_Flags |= CCommandBuffer::TEXFLAG_COMPRESSED;
if(g_Config.m_GfxTextureQuality || Flags&TEXLOAD_NORESAMPLE)
Cmd.m_Flags |= CCommandBuffer::TEXFLAG_QUALITY;
// copy texture data
int MemSize = Width*Height*Cmd.m_PixelSize;
void *pTmpData = mem_alloc(MemSize, sizeof(void*));
mem_copy(pTmpData, pData, MemSize);
Cmd.m_pData = pTmpData;
@ -396,17 +361,6 @@ int CGraphics_Threaded::LoadTextureRaw(int Width, int Height, int Format, const
//
m_pCommandBuffer->AddCommand(Cmd);
// calculate memory usage
int MemUsage = MemSize;
while(Width > 2 && Height > 2)
{
Width>>=1;
Height>>=1;
MemUsage += Width*Height*PixelSize;
}
m_TextureMemoryUsage += MemUsage;
//mem_free(pTmpData);
return Tex;
}
@ -694,13 +648,10 @@ void CGraphics_Threaded::QuadsDrawFreeform(const CFreeformItem *pArray, int Num)
AddVertices(4*Num);
}
void CGraphics_Threaded::QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText)
void CGraphics_Threaded::QuadsText(float x, float y, float Size, const char *pText)
{
float StartX = x;
QuadsBegin();
SetColor(r,g,b,a);
while(*pText)
{
char c = *pText;
@ -724,18 +675,23 @@ void CGraphics_Threaded::QuadsText(float x, float y, float Size, float r, float
x += Size/2;
}
}
QuadsEnd();
}
int CGraphics_Threaded::IssueInit()
{
int Flags = 0;
if(g_Config.m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN;
if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
{
dbg_msg("gfx", "both borderless and fullscreen activated, disabling borderless");
g_Config.m_GfxBorderless = 0;
}
if(g_Config.m_GfxBorderless) Flags |= IGraphicsBackend::INITFLAG_BORDERLESS;
else if(g_Config.m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN;
if(g_Config.m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC;
if(g_Config.m_DbgResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE;
return m_pBackend->Init("Teeworlds", g_Config.m_GfxScreenWidth, g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags);
return m_pBackend->Init("Teeworlds", &g_Config.m_GfxScreenWidth, &g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags);
}
int CGraphics_Threaded::InitWindow()
@ -785,9 +741,9 @@ int CGraphics_Threaded::Init()
// init textures
m_FirstFreeTexture = 0;
for(int i = 0; i < MAX_TEXTURES; i++)
m_aTextures[i].m_Next = i+1;
m_aTextures[MAX_TEXTURES-1].m_Next = -1;
for(int i = 0; i < MAX_TEXTURES-1; i++)
m_aTextureIndices[i] = i+1;
m_aTextureIndices[MAX_TEXTURES-1] = -1;
m_pBackend = CreateGraphicsBackend();
if(InitWindow() != 0)
@ -862,7 +818,8 @@ void CGraphics_Threaded::Swap()
// TODO: screenshot support
if(m_DoScreenshot)
{
ScreenshotDirect(m_aScreenshotName);
if(WindowActive())
ScreenshotDirect(m_aScreenshotName);
m_DoScreenshot = false;
}

View file

@ -57,7 +57,8 @@ public:
{
// commadn groups
CMDGROUP_CORE = 0, // commands that everyone has to implement
CMDGROUP_PLATFORM = 10000, // commands specific to a platform
CMDGROUP_PLATFORM_OPENGL = 10000, // commands specific to a platform
CMDGROUP_PLATFORM_SDL = 20000,
//
CMD_NOP = CMDGROUP_CORE,
@ -94,13 +95,8 @@ public:
TEXFORMAT_ALPHA,
TEXFLAG_NOMIPMAPS = 1,
};
enum
{
INITFLAG_FULLSCREEN = 1,
INITFLAG_VSYNC = 2,
INITFLAG_RESIZABLE = 4,
TEXFLAG_COMPRESSED = 2,
TEXFLAG_QUALITY = 4,
};
enum
@ -217,6 +213,7 @@ public:
int m_Width;
int m_Height;
int m_PixelSize;
int m_Format;
int m_StoreFormat;
int m_Flags;
@ -300,11 +297,16 @@ public:
INITFLAG_FULLSCREEN = 1,
INITFLAG_VSYNC = 2,
INITFLAG_RESIZABLE = 4,
INITFLAG_BORDERLESS = 8,
};
virtual int Init(const char *pName, int Width, int Height, int FsaaSamples, int Flags) = 0;
virtual ~IGraphicsBackend() {}
virtual int Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags) = 0;
virtual int Shutdown() = 0;
virtual int MemoryUsage() const = 0;
virtual void Minimize() = 0;
virtual void Maximize() = 0;
virtual int WindowActive() = 0;
@ -354,15 +356,7 @@ class CGraphics_Threaded : public IEngineGraphics
int m_InvalidTexture;
struct CTexture
{
int m_State;
int m_MemSize;
int m_Flags;
int m_Next;
};
CTexture m_aTextures[MAX_TEXTURES];
int m_aTextureIndices[MAX_TEXTURES];
int m_FirstFreeTexture;
int m_TextureMemoryUsage;
@ -370,9 +364,6 @@ class CGraphics_Threaded : public IEngineGraphics
void AddVertices(int Count);
void Rotate4(const CCommandBuffer::SPoint &rCenter, CCommandBuffer::SVertex *pPoints);
static unsigned char Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp);
static unsigned char *Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData);
void KickCommandBuffer();
int IssueInit();
@ -428,7 +419,7 @@ public:
virtual void QuadsDraw(CQuadItem *pArray, int Num);
virtual void QuadsDrawTL(const CQuadItem *pArray, int Num);
virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num);
virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText);
virtual void QuadsText(float x, float y, float Size, const char *pText);
virtual void Minimize();
virtual void Maximize();

View file

@ -495,7 +495,7 @@ void CServerBrowser::Refresh(int Type)
/* do the broadcast version */
Packet.m_ClientID = -1;
mem_zero(&Packet, sizeof(Packet));
Packet.m_Address.type = NETTYPE_ALL|NETTYPE_LINK_BROADCAST;
Packet.m_Address.type = m_pNetClient->NetType()|NETTYPE_LINK_BROADCAST;
Packet.m_Flags = NETSENDFLAG_CONNLESS;
Packet.m_DataSize = sizeof(Buffer);
Packet.m_pData = Buffer;

View file

@ -639,7 +639,7 @@ public:
Compare.m_Y = DrawY;
Compare.m_Flags &= ~TEXTFLAG_RENDER;
Compare.m_LineWidth = -1;
TextEx(&Compare, pText, Wlen);
TextEx(&Compare, pCurrent, Wlen);
if(Compare.m_X-DrawX > pCursor->m_LineWidth)
{

View file

@ -21,6 +21,10 @@ struct CDemoHeader
char m_aType[8];
char m_aLength[4];
char m_aTimestamp[20];
};
struct CTimelineMarkers
{
char m_aNumTimelineMarkers[4];
char m_aTimelineMarkers[MAX_TIMELINE_MARKERS][4];
};

View file

@ -120,7 +120,7 @@ public:
: m_X0(x0), m_Y0(y0), m_X1(x1), m_Y1(y1), m_X2(x2), m_Y2(y2), m_X3(x3), m_Y3(y3) {}
};
virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num) = 0;
virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText) = 0;
virtual void QuadsText(float x, float y, float Size, const char *pText) = 0;
struct CColorVertex
{

View file

@ -42,7 +42,7 @@
#include <windows.h>
#endif
static const char *StrUTF8Ltrim(const char *pStr)
static const char *StrLtrim(const char *pStr)
{
while(*pStr)
{
@ -60,7 +60,7 @@ static const char *StrUTF8Ltrim(const char *pStr)
return pStr;
}
static void StrUTF8Rtrim(char *pStr)
static void StrRtrim(char *pStr)
{
const char *p = pStr;
const char *pEnd = 0;
@ -68,7 +68,7 @@ static void StrUTF8Rtrim(char *pStr)
{
const char *pStrOld = p;
int Code = str_utf8_decode(&p);
// check if unicode is not empty
if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) &&
(Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) &&
@ -173,7 +173,7 @@ void CSnapIDPool::FreeID(int ID)
}
void CServerBan::Init(IConsole *pConsole, IStorage *pStorage, CServer* pServer)
void CServerBan::InitServerBan(IConsole *pConsole, IStorage *pStorage, CServer* pServer)
{
CNetBan::Init(pConsole, pStorage);
@ -324,8 +324,12 @@ int CServer::TrySetClientName(int ClientID, const char *pName)
char aTrimmedName[64];
// trim the name
str_copy(aTrimmedName, StrUTF8Ltrim(pName), sizeof(aTrimmedName));
StrUTF8Rtrim(aTrimmedName);
str_copy(aTrimmedName, StrLtrim(pName), sizeof(aTrimmedName));
StrRtrim(aTrimmedName);
// check for empty names
if(!aTrimmedName[0])
return -1;
// check if new and old name are the same
if(m_aClients[ClientID].m_aName[0] && str_comp(m_aClients[ClientID].m_aName, aTrimmedName) == 0)
@ -336,11 +340,6 @@ int CServer::TrySetClientName(int ClientID, const char *pName)
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf);
pName = aTrimmedName;
// check for empty names
if(!pName[0])
return -1;
// make sure that two clients doesn't have the same name
for(int i = 0; i < MAX_CLIENTS; i++)
if(i != ClientID && m_aClients[i].m_State >= CClient::STATE_READY)
@ -365,13 +364,13 @@ void CServer::SetClientName(int ClientID, const char *pName)
return;
char aNameTry[MAX_NAME_LENGTH];
str_copy(aNameTry, pName, MAX_NAME_LENGTH);
str_copy(aNameTry, pName, sizeof(aNameTry));
if(TrySetClientName(ClientID, aNameTry))
{
// auto rename
for(int i = 1;; i++)
{
str_format(aNameTry, MAX_NAME_LENGTH, "(%d)%s", i, pName);
str_format(aNameTry, sizeof(aNameTry), "(%d)%s", i, pName);
if(TrySetClientName(ClientID, aNameTry) == 0)
break;
}
@ -1392,6 +1391,7 @@ int CServer::Run()
if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
{
// sweet!
BindAddr.type = NETTYPE_ALL;
BindAddr.port = g_Config.m_SvPort;
}
else
@ -1591,8 +1591,12 @@ void CServer::ConStatus(IConsole::IResult *pResult, void *pUser)
{
net_addr_str(pThis->m_NetServer.ClientAddr(i), aAddrStr, sizeof(aAddrStr), true);
if(pThis->m_aClients[i].m_State == CClient::STATE_INGAME)
str_format(aBuf, sizeof(aBuf), "id=%d addr=%s name='%s' score=%d", i, aAddrStr,
pThis->m_aClients[i].m_aName, pThis->m_aClients[i].m_Score);
{
const char *pAuthStr = pThis->m_aClients[i].m_Authed == CServer::AUTHED_ADMIN ? "(Admin)" :
pThis->m_aClients[i].m_Authed == CServer::AUTHED_MOD ? "(Mod)" : "";
str_format(aBuf, sizeof(aBuf), "id=%d addr=%s name='%s' score=%d %s", i, aAddrStr,
pThis->m_aClients[i].m_aName, pThis->m_aClients[i].m_Score, pAuthStr);
}
else
str_format(aBuf, sizeof(aBuf), "id=%d addr=%s connecting", i, aAddrStr);
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
@ -1668,6 +1672,7 @@ void CServer::ConLogout(IConsole::IResult *pResult, void *pUser)
pServer->SendMsgEx(&Msg, MSGFLAG_VITAL, pServer->m_RconClientID, true);
pServer->m_aClients[pServer->m_RconClientID].m_Authed = AUTHED_NO;
pServer->m_aClients[pServer->m_RconClientID].m_AuthTries = 0;
pServer->m_aClients[pServer->m_RconClientID].m_pRconCmdToSend = 0;
pServer->SendRconLine(pServer->m_RconClientID, "Logout successful.");
char aBuf[32];
@ -1755,7 +1760,7 @@ void CServer::RegisterCommands()
Console()->Chain("console_output_level", ConchainConsoleOutputLevelUpdate, this);
// register console commands in sub parts
m_ServerBan.Init(Console(), Storage(), this);
m_ServerBan.InitServerBan(Console(), Storage(), this);
m_pGameServer->OnConsoleInit();
}

View file

@ -61,10 +61,10 @@ class CServerBan : public CNetBan
public:
class CServer *Server() const { return m_pServer; }
void Init(class IConsole *pConsole, class IStorage *pStorage, class CServer* pServer);
void InitServerBan(class IConsole *pConsole, class IStorage *pStorage, class CServer* pServer);
int BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason);
int BanRange(const CNetRange *pRange, int Seconds, const char *pReason);
virtual int BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason);
virtual int BanRange(const CNetRange *pRange, int Seconds, const char *pReason);
static void ConBanExt(class IConsole::IResult *pResult, void *pUser);
};

View file

@ -15,7 +15,7 @@ MACRO_CONFIG_STR(Password, password, 32, "", CFGFLAG_CLIENT|CFGFLAG_SERVER, "Pas
MACRO_CONFIG_STR(Logfile, logfile, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT|CFGFLAG_SERVER, "Filename to log all output to")
MACRO_CONFIG_INT(ConsoleOutputLevel, console_output_level, 0, 0, 2, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Adjusts the amount of information in the console")
MACRO_CONFIG_INT(ClCpuThrottle, cl_cpu_throttle, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
MACRO_CONFIG_INT(ClCpuThrottle, cl_cpu_throttle, 0, 0, 100, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
MACRO_CONFIG_INT(ClEditor, cl_editor, 0, 0, 1, CFGFLAG_CLIENT, "")
MACRO_CONFIG_INT(ClLoadCountryFlags, cl_load_country_flags, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Load and show country flags")
@ -59,8 +59,9 @@ MACRO_CONFIG_INT(SndNonactiveMute, snd_nonactive_mute, 0, 0, 1, CFGFLAG_SAVE|CFG
MACRO_CONFIG_INT(SndChat, snd_chat, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
MACRO_CONFIG_INT(SndNameOnly, snd_name_only, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
MACRO_CONFIG_INT(GfxScreenWidth, gfx_screen_width, 800, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution width")
MACRO_CONFIG_INT(GfxScreenHeight, gfx_screen_height, 600, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution height")
MACRO_CONFIG_INT(GfxScreenWidth, gfx_screen_width, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution width")
MACRO_CONFIG_INT(GfxScreenHeight, gfx_screen_height, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution height")
MACRO_CONFIG_INT(GfxBorderless, gfx_borderless, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Borderless window (not to be used with fullscreen)")
MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Fullscreen")
MACRO_CONFIG_INT(GfxAlphabits, gfx_alphabits, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Alpha bits for framebuffer (fullscreen only)")
MACRO_CONFIG_INT(GfxColorDepth, gfx_color_depth, 24, 16, 24, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Colors bits for framebuffer (fullscreen only)")

View file

@ -16,21 +16,21 @@
const char *CConsole::CResult::GetString(unsigned Index)
{
if (Index < 0 || Index >= m_NumArgs)
if (Index >= m_NumArgs)
return "";
return m_apArgs[Index];
}
int CConsole::CResult::GetInteger(unsigned Index)
{
if (Index < 0 || Index >= m_NumArgs)
if (Index >= m_NumArgs)
return 0;
return str_toint(m_apArgs[Index]);
}
float CConsole::CResult::GetFloat(unsigned Index)
{
if (Index < 0 || Index >= m_NumArgs)
if (Index >= m_NumArgs)
return 0.0f;
return str_tofloat(m_apArgs[Index]);
}
@ -68,7 +68,7 @@ int CConsole::ParseStart(CResult *pResult, const char *pString, int Length)
if(Length < Len)
Len = Length;
str_copy(pResult->m_aStringStorage, pString, Length);
str_copy(pResult->m_aStringStorage, pString, Len);
pStr = pResult->m_aStringStorage;
// get command

View file

@ -98,12 +98,11 @@ class CConsole : public IConsole
if(this != &Other)
{
IResult::operator=(Other);
int Offset = m_aStringStorage - Other.m_aStringStorage;
mem_copy(m_aStringStorage, Other.m_aStringStorage, sizeof(m_aStringStorage));
m_pArgsStart = Other.m_pArgsStart + Offset;
m_pCommand = Other.m_pCommand + Offset;
m_pArgsStart = m_aStringStorage+(Other.m_pArgsStart-Other.m_aStringStorage);
m_pCommand = m_aStringStorage+(Other.m_pCommand-Other.m_aStringStorage);
for(unsigned i = 0; i < Other.m_NumArgs; ++i)
m_apArgs[i] = Other.m_apArgs[i] + Offset;
m_apArgs[i] = m_aStringStorage+(Other.m_apArgs[i]-Other.m_aStringStorage);
}
return *this;
}

View file

@ -14,6 +14,7 @@
static const unsigned char gs_aHeaderMarker[7] = {'T', 'W', 'D', 'E', 'M', 'O', 0};
static const unsigned char gs_ActVersion = 4;
static const unsigned char gs_OldVersion = 3;
static const int gs_LengthOffset = 152;
static const int gs_NumMarkersOffset = 176;
@ -29,6 +30,7 @@ CDemoRecorder::CDemoRecorder(class CSnapshotDelta *pSnapshotDelta)
int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, const char *pNetVersion, const char *pMap, unsigned Crc, const char *pType)
{
CDemoHeader Header;
CTimelineMarkers TimelineMarkers;
if(m_File)
return -1;
@ -90,9 +92,8 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con
str_copy(Header.m_aType, pType, sizeof(Header.m_aType));
// Header.m_Length - add this on stop
str_timestamp(Header.m_aTimestamp, sizeof(Header.m_aTimestamp));
// Header.m_aNumTimelineMarkers - add this on stop
// Header.m_aTimelineMarkers - add this on stop
io_write(DemoFile, &Header, sizeof(Header));
io_write(DemoFile, &TimelineMarkers, sizeof(TimelineMarkers)); // fill this on stop
// write map data
while(1)
@ -618,7 +619,7 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const
return -1;
}
if(m_Info.m_Header.m_Version < gs_ActVersion)
if(m_Info.m_Header.m_Version < gs_OldVersion)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "demo version %d is not supported", m_Info.m_Header.m_Version);
@ -627,6 +628,8 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const
m_File = 0;
return -1;
}
else if(m_Info.m_Header.m_Version > gs_OldVersion)
io_read(m_File, &m_Info.m_TimelineMarkers, sizeof(m_Info.m_TimelineMarkers));
// get demo type
if(!str_comp(m_Info.m_Header.m_aType, "client"))
@ -666,15 +669,18 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const
mem_free(pMapData);
}
// get timeline markers
int Num = ((m_Info.m_Header.m_aNumTimelineMarkers[0]<<24)&0xFF000000) | ((m_Info.m_Header.m_aNumTimelineMarkers[1]<<16)&0xFF0000) |
((m_Info.m_Header.m_aNumTimelineMarkers[2]<<8)&0xFF00) | (m_Info.m_Header.m_aNumTimelineMarkers[3]&0xFF);
m_Info.m_Info.m_NumTimelineMarkers = Num;
for(int i = 0; i < Num && i < MAX_TIMELINE_MARKERS; i++)
if(m_Info.m_Header.m_Version > gs_OldVersion)
{
char *pTimelineMarker = m_Info.m_Header.m_aTimelineMarkers[i];
m_Info.m_Info.m_aTimelineMarkers[i] = ((pTimelineMarker[0]<<24)&0xFF000000) | ((pTimelineMarker[1]<<16)&0xFF0000) |
((pTimelineMarker[2]<<8)&0xFF00) | (pTimelineMarker[3]&0xFF);
// get timeline markers
int Num = ((m_Info.m_TimelineMarkers.m_aNumTimelineMarkers[0]<<24)&0xFF000000) | ((m_Info.m_TimelineMarkers.m_aNumTimelineMarkers[1]<<16)&0xFF0000) |
((m_Info.m_TimelineMarkers.m_aNumTimelineMarkers[2]<<8)&0xFF00) | (m_Info.m_TimelineMarkers.m_aNumTimelineMarkers[3]&0xFF);
m_Info.m_Info.m_NumTimelineMarkers = Num;
for(int i = 0; i < Num && i < MAX_TIMELINE_MARKERS; i++)
{
char *pTimelineMarker = m_Info.m_TimelineMarkers.m_aTimelineMarkers[i];
m_Info.m_Info.m_aTimelineMarkers[i] = ((pTimelineMarker[0]<<24)&0xFF000000) | ((pTimelineMarker[1]<<16)&0xFF0000) |
((pTimelineMarker[2]<<8)&0xFF00) | (pTimelineMarker[3]&0xFF);
}
}
// scan the file for interessting points
@ -846,7 +852,7 @@ bool CDemoPlayer::GetDemoInfo(class IStorage *pStorage, const char *pFilename, i
return false;
io_read(File, pDemoHeader, sizeof(CDemoHeader));
if(mem_comp(pDemoHeader->m_aMarker, gs_aHeaderMarker, sizeof(gs_aHeaderMarker)) || pDemoHeader->m_Version < gs_ActVersion)
if(mem_comp(pDemoHeader->m_aMarker, gs_aHeaderMarker, sizeof(gs_aHeaderMarker)) || pDemoHeader->m_Version < gs_OldVersion)
{
io_close(File);
return false;

View file

@ -51,6 +51,7 @@ public:
struct CPlaybackInfo
{
CDemoHeader m_Header;
CTimelineMarkers m_TimelineMarkers;
IDemoPlayer::CInfo m_Info;

View file

@ -75,7 +75,11 @@ void CEcon::Init(IConsole *pConsole, CNetBan *pNetBan)
NETADDR BindAddr;
if(g_Config.m_EcBindaddr[0] && net_host_lookup(g_Config.m_EcBindaddr, &BindAddr, NETTYPE_ALL) == 0)
{
// got bindaddr
BindAddr.type = NETTYPE_ALL;
BindAddr.port = g_Config.m_EcPort;
}
else
{
mem_zero(&BindAddr, sizeof(BindAddr));

View file

@ -6,6 +6,7 @@
#include <engine/storage.h>
#include <versionsrv/versionsrv.h>
#include <versionsrv/mapversions.h>
#include "datafile.h"
#include "memheap.h"

View file

@ -45,7 +45,7 @@ public:
virtual int RefreshAddresses(int Nettype)
{
if(m_State != STATE_INIT)
if(m_State != STATE_INIT && m_State != STATE_READY)
return -1;
dbg_msg("engine/mastersrv", "refreshing master server addresses");

View file

@ -243,7 +243,7 @@ typename CNetBan::CBan<T> *CNetBan::CBanPool<T, HashCount>::Get(int Index) const
template<class T>
void CNetBan::MakeBanInfo(const CBan<T> *pBan, char *pBuf, unsigned BuffSize, int Type) const
{
if(pBan == 0)
if(pBan == 0 || pBuf == 0)
{
if(BuffSize > 0)
pBuf[0] = 0;

View file

@ -170,7 +170,7 @@ public:
class IStorage *Storage() const { return m_pStorage; }
virtual ~CNetBan() {}
virtual void Init(class IConsole *pConsole, class IStorage *pStorage);
void Init(class IConsole *pConsole, class IStorage *pStorage);
void Update();
virtual int BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason);

View file

@ -140,6 +140,7 @@ private:
int m_Token;
int m_RemoteClosed;
bool m_BlockCloseMsg;
TStaticRingBuffer<CNetChunkResend, NET_CONN_BUFFERSIZE> m_Buffer;
@ -167,7 +168,7 @@ private:
void Resend();
public:
void Init(NETSOCKET Socket);
void Init(NETSOCKET Socket, bool BlockCloseMsg);
int Connect(NETADDR *pAddr);
void Disconnect(const char *pReason);
@ -354,7 +355,7 @@ public:
int ResetErrorString();
// error and state
int NetType() { return m_Socket.type; }
int NetType() const { return m_Socket.type; }
int State();
int GotProblems();
const char *ErrorString();

View file

@ -16,7 +16,7 @@ bool CNetClient::Open(NETADDR BindAddr, int Flags)
// init
m_Socket = Socket;
m_Connection.Init(m_Socket);
m_Connection.Init(m_Socket, false);
return true;
}

View file

@ -37,12 +37,13 @@ void CNetConnection::SetError(const char *pString)
str_copy(m_ErrorString, pString, sizeof(m_ErrorString));
}
void CNetConnection::Init(NETSOCKET Socket)
void CNetConnection::Init(NETSOCKET Socket, bool BlockCloseMsg)
{
Reset();
ResetStats();
m_Socket = Socket;
m_BlockCloseMsg = BlockCloseMsg;
mem_zero(m_ErrorString, sizeof(m_ErrorString));
}
@ -212,24 +213,25 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr)
m_State = NET_CONNSTATE_ERROR;
m_RemoteClosed = 1;
if(pPacket->m_DataSize)
char Str[128] = {0};
if(pPacket->m_DataSize > 1)
{
// make sure to sanitize the error string form the other party
char Str[128];
if(pPacket->m_DataSize < 128)
str_copy(Str, (char *)pPacket->m_aChunkData, pPacket->m_DataSize);
str_copy(Str, (char *)&pPacket->m_aChunkData[1], pPacket->m_DataSize);
else
str_copy(Str, (char *)pPacket->m_aChunkData, sizeof(Str));
str_copy(Str, (char *)&pPacket->m_aChunkData[1], sizeof(Str));
str_sanitize_strong(Str);
}
if(!m_BlockCloseMsg)
{
// set the error string
SetError(Str);
}
else
SetError("No reason given");
if(g_Config.m_Debug)
dbg_msg("conn", "closed reason='%s'", ErrorString());
dbg_msg("conn", "closed reason='%s'", Str);
}
return 0;
}
@ -243,6 +245,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr)
Reset();
m_State = NET_CONNSTATE_PENDING;
m_PeerAddr = *pAddr;
mem_zero(m_ErrorString, sizeof(m_ErrorString));
m_LastSendTime = Now;
m_LastRecvTime = Now;
m_LastUpdateTime = Now;

View file

@ -30,7 +30,7 @@ bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int Ma
m_MaxClientsPerIP = MaxClientsPerIP;
for(int i = 0; i < NET_MAX_CLIENTS; i++)
m_aSlots[i].m_Connection.Init(m_Socket);
m_aSlots[i].m_Connection.Init(m_Socket, true);
return true;
}

View file

@ -136,7 +136,7 @@ const char *CUnpacker::GetString(int SanitizeType)
str_sanitize(pPtr);
else if(SanitizeType&SANITIZE_CC)
str_sanitize_cc(pPtr);
return SanitizeType&SKIP_START_WHITESPACES ? str_skip_whitespaces(pPtr) : pPtr;
return SanitizeType&SKIP_START_WHITESPACES ? str_utf8_skip_whitespaces(pPtr) : pPtr;
}
const unsigned char *CUnpacker::GetRaw(int Size)

View file

@ -195,13 +195,14 @@ int CSnapshotDelta::CreateDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pDstData
// fetch previous indices
// we do this as a separate pass because it helps the cache
for(i = 0; i < pTo->NumItems(); i++)
const int NumItems = pTo->NumItems();
for(i = 0; i < NumItems; i++)
{
pCurItem = pTo->GetItem(i); // O(1) .. O(n)
aPastIndecies[i] = GetItemIndexHashed(pCurItem->Key(), Hashlist); // O(n) .. O(n^n)
}
for(i = 0; i < pTo->NumItems(); i++)
for(i = 0; i < NumItems; i++)
{
// do delta
ItemSize = pTo->GetItemSize(i); // O(1) .. O(n)
@ -474,7 +475,7 @@ int CSnapshotStorage::Get(int Tick, int64 *pTagtime, CSnapshot **ppData, CSnapsh
if(ppData)
*ppData = pHolder->m_pSnap;
if(ppAltData)
*ppData = pHolder->m_pAltSnap;
*ppAltData = pHolder->m_pAltSnap;
return pHolder->m_SnapSize;
}

View file

@ -116,13 +116,25 @@ bool CChat::OnInput(IInput::CEvent Event)
{
if(m_Input.GetString()[0])
{
bool AddEntry = false;
if(m_LastChatSend+time_freq() < time_get())
{
Say(m_Mode == MODE_ALL ? 0 : 1, m_Input.GetString());
else
AddEntry = true;
}
else if(m_PendingChatCounter < 3)
{
++m_PendingChatCounter;
CHistoryEntry *pEntry = m_History.Allocate(sizeof(CHistoryEntry)+m_Input.GetLength());
pEntry->m_Team = m_Mode == MODE_ALL ? 0 : 1;
mem_copy(pEntry->m_aText, m_Input.GetString(), m_Input.GetLength()+1);
AddEntry = true;
}
if(AddEntry)
{
CHistoryEntry *pEntry = m_History.Allocate(sizeof(CHistoryEntry)+m_Input.GetLength());
pEntry->m_Team = m_Mode == MODE_ALL ? 0 : 1;
mem_copy(pEntry->m_aText, m_Input.GetString(), m_Input.GetLength()+1);
}
}
m_pHistoryEntry = 0x0;
m_Mode = MODE_NONE;
@ -269,11 +281,39 @@ void CChat::OnMessage(int MsgType, void *pRawMsg)
void CChat::AddLine(int ClientID, int Team, const char *pLine)
{
if(ClientID != -1 && (m_pClient->m_aClients[ClientID].m_aName[0] == '\0' || // unknown client
if(*pLine == 0 || (ClientID != -1 && (m_pClient->m_aClients[ClientID].m_aName[0] == '\0' || // unknown client
m_pClient->m_aClients[ClientID].m_ChatIgnore ||
(m_pClient->m_Snap.m_LocalClientID != ClientID && g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[ClientID].m_Friend)))
(m_pClient->m_Snap.m_LocalClientID != ClientID && g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[ClientID].m_Friend))))
return;
// trim right and set maximum length to 128 utf8-characters
int Length = 0;
const char *pStr = pLine;
const char *pEnd = 0;
while(*pStr)
{
const char *pStrOld = pStr;
int Code = str_utf8_decode(&pStr);
// check if unicode is not empty
if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) &&
(Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) &&
Code != 0xFEFF && (Code < 0xFFF9 || Code > 0xFFFC))
{
pEnd = 0;
}
else if(pEnd == 0)
pEnd = pStrOld;
if(++Length >= 127)
{
*(const_cast<char *>(pStr)) = 0;
break;
}
}
if(pEnd != 0)
*(const_cast<char *>(pEnd)) = 0;
bool Highlighted = false;
char *p = const_cast<char*>(pLine);
while(*p)
@ -347,19 +387,19 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine)
}
else if(Highlighted)
{
if(Now-m_aLastSoundPlayed[CHAT_CLIENT] >= time_freq()*3/10)
if(Now-m_aLastSoundPlayed[CHAT_HIGHLIGHT] >= time_freq()*3/10)
{
m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0);
m_aLastSoundPlayed[CHAT_CLIENT] = Now;
if (g_Config.m_SndChat)
m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0);
m_aLastSoundPlayed[CHAT_HIGHLIGHT] = Now;
}
}
else
{
if(Now-m_aLastSoundPlayed[CHAT_HIGHLIGHT] >= time_freq()*3/10)
if(Now-m_aLastSoundPlayed[CHAT_CLIENT] >= time_freq()*3/10)
{
if (g_Config.m_SndChat)
m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0);
m_aLastSoundPlayed[CHAT_HIGHLIGHT] = Now;
m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0);
m_aLastSoundPlayed[CHAT_CLIENT] = Now;
}
}
}

View file

@ -437,12 +437,6 @@ void CGameConsole::OnRender()
x = Cursor.m_X;
// render console input (wrap line)
int Lines = TextRender()->TextLineCount(0, FontSize, pConsole->m_Input.GetString(), Screen.w - 10.0f - x);
y -= (Lines - 1) * FontSize;
TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER);
Cursor.m_LineWidth = Screen.w - 10.0f - x;
//hide rcon password
char aInputString[256];
str_copy(aInputString, pConsole->m_Input.GetString(), sizeof(aInputString));
@ -452,10 +446,22 @@ void CGameConsole::OnRender()
aInputString[i] = '*';
}
// render console input (wrap line)
TextRender()->SetCursor(&Cursor, x, y, FontSize, 0);
Cursor.m_LineWidth = Screen.w - 10.0f - x;
TextRender()->TextEx(&Cursor, aInputString, pConsole->m_Input.GetCursorOffset());
TextRender()->TextEx(&Cursor, aInputString+pConsole->m_Input.GetCursorOffset(), -1);
int Lines = Cursor.m_LineCount;
y -= (Lines - 1) * FontSize;
TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER);
Cursor.m_LineWidth = Screen.w - 10.0f - x;
TextRender()->TextEx(&Cursor, aInputString, pConsole->m_Input.GetCursorOffset());
static float MarkerOffset = TextRender()->TextWidth(0, FontSize, "|", -1)/3;
CTextCursor Marker = Cursor;
Marker.m_X -= MarkerOffset;
Marker.m_LineWidth = -1;
TextRender()->TextEx(&Marker, "|", -1);
TextRender()->TextEx(&Cursor, aInputString+pConsole->m_Input.GetCursorOffset(), -1);

View file

@ -248,7 +248,8 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS
for(int i = 0; i < m_NumInputEvents; i++)
{
Len = str_length(pStr);
ReturnValue |= CLineInput::Manipulate(m_aInputEvents[i], pStr, StrSize, &Len, &s_AtIndex);
int NumChars = Len;
ReturnValue |= CLineInput::Manipulate(m_aInputEvents[i], pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars);
}
}
@ -1062,7 +1063,7 @@ int CMenus::Render()
}
// update download speed
float Diff = Client()->MapDownloadAmount()-m_DownloadLastCheckSize;
float Diff = (Client()->MapDownloadAmount()-m_DownloadLastCheckSize)/((int)((Now-m_DownloadLastCheckTime)/time_freq()));
float StartDiff = m_DownloadLastCheckSize-0.0f;
if(StartDiff+Diff > 0.0f)
m_DownloadSpeed = (Diff/(StartDiff+Diff))*(Diff/1.0f) + (StartDiff/(Diff+StartDiff))*m_DownloadSpeed;
@ -1328,6 +1329,9 @@ int CMenus::Render()
if(DoButton_Menu(&s_Button, pButtonText, 0, &Part) || m_EscapePressed || m_EnterPressed)
m_Popup = POPUP_NONE;
}
if(m_Popup == POPUP_NONE)
UI()->SetActiveItem(0);
}
return 0;

View file

@ -225,7 +225,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
{
int ItemIndex = i;
const CServerInfo *pItem = ServerBrowser()->SortedGet(ItemIndex);
NumPlayers += pItem->m_NumPlayers;
NumPlayers += g_Config.m_BrFilterSpectators ? pItem->m_NumPlayers : pItem->m_NumClients;
CUIRect Row;
CUIRect SelectHitBox;
@ -806,6 +806,8 @@ void CMenus::RenderServerbrowserFriends(CUIRect View)
// friends list(remove friend)
static float s_ScrollValue = 0;
if(m_FriendlistSelectedIndex >= m_lFriends.size())
m_FriendlistSelectedIndex = m_lFriends.size()-1;
UiDoListboxStart(&m_lFriends, &List, 30.0f, "", "", m_lFriends.size(), 1, m_FriendlistSelectedIndex, s_ScrollValue);
m_lFriends.sort_range();

View file

@ -617,11 +617,13 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
static int s_GfxScreenWidth = g_Config.m_GfxScreenWidth;
static int s_GfxScreenHeight = g_Config.m_GfxScreenHeight;
static int s_GfxColorDepth = g_Config.m_GfxColorDepth;
static int s_GfxBorderless = g_Config.m_GfxBorderless;
static int s_GfxFullscreen = g_Config.m_GfxFullscreen;
static int s_GfxVsync = g_Config.m_GfxVsync;
static int s_GfxFsaaSamples = g_Config.m_GfxFsaaSamples;
static int s_GfxTextureQuality = g_Config.m_GfxTextureQuality;
static int s_GfxTextureCompression = g_Config.m_GfxTextureCompression;
static int s_GfxThreaded = g_Config.m_GfxThreaded;
CUIRect ModeList;
MainView.VSplitLeft(300.0f, &MainView, &ModeList);
@ -671,10 +673,21 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
}
// switches
MainView.HSplitTop(20.0f, &Button, &MainView);
if(DoButton_CheckBox(&g_Config.m_GfxBorderless, Localize("Borderless window"), g_Config.m_GfxBorderless, &Button))
{
g_Config.m_GfxBorderless ^= 1;
if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
g_Config.m_GfxFullscreen = 0;
CheckSettings = true;
}
MainView.HSplitTop(20.0f, &Button, &MainView);
if(DoButton_CheckBox(&g_Config.m_GfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button))
{
g_Config.m_GfxFullscreen ^= 1;
if(g_Config.m_GfxFullscreen && g_Config.m_GfxBorderless)
g_Config.m_GfxBorderless = 0;
CheckSettings = true;
}
@ -691,8 +704,25 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
g_Config.m_GfxFsaaSamples = (g_Config.m_GfxFsaaSamples+1)%17;
CheckSettings = true;
}
MainView.HSplitTop(20.0f, &Button, &MainView);
if(DoButton_CheckBox(&g_Config.m_GfxThreaded, Localize("Threaded rendering"), g_Config.m_GfxThreaded, &Button))
{
g_Config.m_GfxThreaded ^= 1;
CheckSettings = true;
}
MainView.HSplitTop(40.0f, &Button, &MainView);
MainView.HSplitTop(20.0f, &Button, &MainView);
if(g_Config.m_GfxThreaded)
{
Button.VSplitLeft(20.0f, 0, &Button);
if(DoButton_CheckBox(&g_Config.m_GfxAsyncRender, Localize("Handle rendering async from updates"), g_Config.m_GfxAsyncRender, &Button))
{
g_Config.m_GfxAsyncRender ^= 1;
CheckSettings = true;
}
}
MainView.HSplitTop(20.0f, &Button, &MainView);
if(DoButton_CheckBox(&g_Config.m_GfxTextureQuality, Localize("Quality Textures"), g_Config.m_GfxTextureQuality, &Button))
{
@ -717,11 +747,13 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
if(s_GfxScreenWidth == g_Config.m_GfxScreenWidth &&
s_GfxScreenHeight == g_Config.m_GfxScreenHeight &&
s_GfxColorDepth == g_Config.m_GfxColorDepth &&
s_GfxBorderless == g_Config.m_GfxBorderless &&
s_GfxFullscreen == g_Config.m_GfxFullscreen &&
s_GfxVsync == g_Config.m_GfxVsync &&
s_GfxFsaaSamples == g_Config.m_GfxFsaaSamples &&
s_GfxTextureQuality == g_Config.m_GfxTextureQuality &&
s_GfxTextureCompression == g_Config.m_GfxTextureCompression)
s_GfxTextureCompression == g_Config.m_GfxTextureCompression &&
s_GfxThreaded == g_Config.m_GfxThreaded)
m_NeedRestartGraphics = false;
else
m_NeedRestartGraphics = true;
@ -785,10 +817,13 @@ void CMenus::RenderSettingsSound(CUIRect MainView)
if(DoButton_CheckBox(&g_Config.m_SndMusic, Localize("Play background music"), g_Config.m_SndMusic, &Button))
{
g_Config.m_SndMusic ^= 1;
if(g_Config.m_SndMusic)
m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f);
else
m_pClient->m_pSounds->Stop(SOUND_MENU);
if(Client()->State() == IClient::STATE_OFFLINE)
{
if(g_Config.m_SndMusic)
m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f);
else
m_pClient->m_pSounds->Stop(SOUND_MENU);
}
}
MainView.HSplitTop(20.0f, &Button, &MainView);
@ -803,6 +838,10 @@ void CMenus::RenderSettingsSound(CUIRect MainView)
if(DoButton_CheckBox(&g_Config.m_SndNameOnly, Localize("Enable sound only to highlight name"), g_Config.m_SndNameOnly, &Button))
g_Config.m_SndNameOnly ^= 1;
MainView.HSplitTop(20.0f, &Button, &MainView);
if(DoButton_CheckBox(&g_Config.m_ClThreadsoundloading, Localize("Threaded sound loading"), g_Config.m_ClThreadsoundloading, &Button))
g_Config.m_ClThreadsoundloading ^= 1;
// sample rate box
{
char aBuf[64];

View file

@ -121,7 +121,12 @@ void CVoting::Vote(int v)
CVoting::CVoting()
{
ClearOptions();
OnReset();
m_Closetime = 0;
m_aDescription[0] = 0;
m_aReason[0] = 0;
m_Yes = m_No = m_Pass = m_Total = 0;
m_Voted = 0;
}
void CVoting::AddOption(const char *pDescription)
@ -165,6 +170,9 @@ void CVoting::ClearOptions()
void CVoting::OnReset()
{
if(Client()->State() == IClient::STATE_LOADING) // do not reset active vote while connecting
return;
m_Closetime = 0;
m_aDescription[0] = 0;
m_aReason[0] = 0;

View file

@ -505,7 +505,7 @@ void CGameClient::OnRender()
m_NewPredictedTick = false;
// check if client info has to be resent
if(m_LastSendInfo && Client()->State() == IClient::STATE_ONLINE && m_Snap.m_LocalClientID >= 0 && !m_pMenus->IsActive() && m_LastSendInfo+time_freq()*5 < time_get())
if(m_LastSendInfo && Client()->State() == IClient::STATE_ONLINE && m_Snap.m_LocalClientID >= 0 && !m_pMenus->IsActive() && m_LastSendInfo+time_freq()*6 < time_get())
{
// resend if client info differs
if(str_comp(g_Config.m_PlayerName, m_aClients[m_Snap.m_LocalClientID].m_aName) ||
@ -656,7 +656,7 @@ void CGameClient::OnEnterGame() {}
void CGameClient::OnGameOver()
{
if(Client()->State() != IClient::STATE_DEMOPLAYBACK)
if(Client()->State() != IClient::STATE_DEMOPLAYBACK && g_Config.m_ClEditor == 0)
Client()->AutoScreenshot_Start();
}

View file

@ -13,6 +13,7 @@ void CLineInput::Clear()
mem_zero(m_Str, sizeof(m_Str));
m_Len = 0;
m_CursorPos = 0;
m_NumChars = 0;
}
void CLineInput::Set(const char *pString)
@ -20,10 +21,18 @@ void CLineInput::Set(const char *pString)
str_copy(m_Str, pString, sizeof(m_Str));
m_Len = str_length(m_Str);
m_CursorPos = m_Len;
m_NumChars = 0;
int Offset = 0;
while(pString[Offset])
{
Offset = str_utf8_forward(pString, Offset);
++m_NumChars;
}
}
bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *pStrLenPtr, int *pCursorPosPtr)
bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int StrMaxChars, int *pStrLenPtr, int *pCursorPosPtr, int *pNumCharsPtr)
{
int NumChars = *pNumCharsPtr;
int CursorPos = *pCursorPosPtr;
int Len = *pStrLenPtr;
bool Changes = false;
@ -40,13 +49,15 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p
char Tmp[8];
int CharSize = str_utf8_encode(Tmp, Code);
if (Len < StrMaxSize - CharSize && CursorPos < StrMaxSize - CharSize)
if (Len < StrMaxSize - CharSize && CursorPos < StrMaxSize - CharSize && NumChars < StrMaxChars)
{
mem_move(pStr + CursorPos + CharSize, pStr + CursorPos, Len-CursorPos+1); // +1 == null term
for(int i = 0; i < CharSize; i++)
pStr[CursorPos+i] = Tmp[i];
CursorPos += CharSize;
Len += CharSize;
if(CharSize > 0)
++NumChars;
Changes = true;
}
}
@ -60,6 +71,8 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p
mem_move(pStr+NewCursorPos, pStr+CursorPos, Len - NewCursorPos - CharSize + 1); // +1 == null term
CursorPos = NewCursorPos;
Len -= CharSize;
if(CharSize > 0)
--NumChars;
Changes = true;
}
else if (k == KEY_DELETE && CursorPos < Len)
@ -68,6 +81,8 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p
int CharSize = p-CursorPos;
mem_move(pStr + CursorPos, pStr + CursorPos + CharSize, Len - CursorPos - CharSize + 1); // +1 == null term
Len -= CharSize;
if(CharSize > 0)
--NumChars;
Changes = true;
}
else if (k == KEY_LEFT && CursorPos > 0)
@ -80,6 +95,7 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p
CursorPos = Len;
}
*pNumCharsPtr = NumChars;
*pCursorPosPtr = CursorPos;
*pStrLenPtr = Len;
@ -88,5 +104,5 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p
void CLineInput::ProcessInput(IInput::CEvent e)
{
Manipulate(e, m_Str, sizeof(m_Str), &m_Len, &m_CursorPos);
Manipulate(e, m_Str, MAX_SIZE, MAX_CHARS, &m_Len, &m_CursorPos, &m_NumChars);
}

View file

@ -8,11 +8,17 @@
// line input helter
class CLineInput
{
char m_Str[256];
enum
{
MAX_SIZE=512,
MAX_CHARS=MAX_SIZE/4,
};
char m_Str[MAX_SIZE];
int m_Len;
int m_CursorPos;
int m_NumChars;
public:
static bool Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *pStrLenPtr, int *pCursorPosPtr);
static bool Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int StrMaxChars, int *pStrLenPtr, int *pCursorPosPtr, int *pNumCharsPtr);
class CCallback
{

View file

@ -321,7 +321,7 @@ void CRenderTools::RenderTilemapGenerateSkip(class CLayers *pLayers)
CTile *pTiles = (CTile *)pLayers->Map()->GetData(pTmap->m_Data);
for(int y = 0; y < pTmap->m_Height; y++)
{
for(int x = 1; x < pTmap->m_Width; x++)
for(int x = 1; x < pTmap->m_Width;)
{
int sx;
for(sx = 1; x+sx < pTmap->m_Width && sx < 255; sx++)

View file

@ -107,9 +107,10 @@ void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, ENV
}
bool Opaque = false;
/* TODO: Analyze quadtexture
if(a < 0.01f || (q->m_aColors[0].a < 0.01f && q->m_aColors[1].a < 0.01f && q->m_aColors[2].a < 0.01f && q->m_aColors[3].a < 0.01f))
Opaque = true;
*/
if(Opaque && !(RenderFlags&LAYERRENDERFLAG_OPAQUE))
continue;
if(!Opaque && !(RenderFlags&LAYERRENDERFLAG_TRANSPARENT))
@ -244,7 +245,7 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4
unsigned char Flags = pTiles[c].m_Flags;
bool Render = false;
if(Flags&TILEFLAG_OPAQUE)
if(Flags&TILEFLAG_OPAQUE && Color.a*a > 254.0f/255.0f)
{
if(RenderFlags&LAYERRENDERFLAG_OPAQUE)
Render = true;

View file

@ -44,6 +44,11 @@ enum
CEditorImage::~CEditorImage()
{
m_pEditor->Graphics()->UnloadTexture(m_TexID);
if(m_pData)
{
mem_free(m_pData);
m_pData = 0;
}
}
CLayerGroup::CLayerGroup()
@ -281,7 +286,8 @@ int CEditor::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned Str
for(int i = 0; i < Input()->NumEvents(); i++)
{
Len = str_length(pStr);
ReturnValue |= CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, &Len, &s_AtIndex);
int NumChars = Len;
ReturnValue |= CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars);
}
}
@ -714,6 +720,11 @@ void CEditor::CallbackOpenMap(const char *pFileName, int StorageType, void *pUse
pEditor->m_Dialog = DIALOG_NONE;
pEditor->m_Map.m_Modified = false;
}
else
{
pEditor->Reset();
pEditor->m_aFileName[0] = 0;
}
}
void CEditor::CallbackAppendMap(const char *pFileName, int StorageType, void *pUser)
{
@ -1057,7 +1068,7 @@ void CEditor::DoToolbar(CUIRect ToolBar)
}
}
static void Rotate(CPoint *pCenter, CPoint *pPoint, float Rotation)
static void Rotate(const CPoint *pCenter, CPoint *pPoint, float Rotation)
{
int x = pPoint->x - pCenter->x;
int y = pPoint->y - pCenter->y;
@ -1447,99 +1458,126 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V)
Graphics()->QuadsDraw(&QuadItem, 1);
}
void CEditor::DoQuadEnvelopes(CQuad *pQuad, int Index, int TexID)
void CEditor::DoQuadEnvelopes(const array<CQuad> &lQuads, int TexID)
{
CEnvelope *pEnvelope = 0x0;
if(pQuad->m_PosEnv >= 0 && pQuad->m_PosEnv < m_Map.m_lEnvelopes.size())
pEnvelope = m_Map.m_lEnvelopes[pQuad->m_PosEnv];
if (!pEnvelope)
return;
//QuadParams
CPoint *pPoints = pQuad->m_aPoints;
int Num = lQuads.size();
CEnvelope **apEnvelope = new CEnvelope*[Num];
mem_zero(apEnvelope, sizeof(CEnvelope*)*Num);
for(int i = 0; i < Num; i++)
{
if((m_ShowEnvelopePreview == 1 && lQuads[i].m_PosEnv == m_SelectedEnvelope) || m_ShowEnvelopePreview == 2)
if(lQuads[i].m_PosEnv >= 0 && lQuads[i].m_PosEnv < m_Map.m_lEnvelopes.size())
apEnvelope[i] = m_Map.m_lEnvelopes[lQuads[i].m_PosEnv];
}
//Draw Lines
Graphics()->TextureSet(-1);
Graphics()->LinesBegin();
Graphics()->SetColor(80.0f/255, 150.0f/255, 230.f/255, 0.5f);
for(int i = 0; i < pEnvelope->m_lPoints.size()-1; i++)
Graphics()->SetColor(80.0f/255, 150.0f/255, 230.f/255, 0.5f);
for(int j = 0; j < Num; j++)
{
if(!apEnvelope[j])
continue;
//QuadParams
const CPoint *pPoints = lQuads[j].m_aPoints;
for(int i = 0; i < apEnvelope[j]->m_lPoints.size()-1; i++)
{
float OffsetX = fx2f(pEnvelope->m_lPoints[i].m_aValues[0]);
float OffsetY = fx2f(pEnvelope->m_lPoints[i].m_aValues[1]);
float OffsetX = fx2f(apEnvelope[j]->m_lPoints[i].m_aValues[0]);
float OffsetY = fx2f(apEnvelope[j]->m_lPoints[i].m_aValues[1]);
vec2 Pos0 = vec2(fx2f(pPoints[4].x)+OffsetX, fx2f(pPoints[4].y)+OffsetY);
OffsetX = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[0]);
OffsetY = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[1]);
OffsetX = fx2f(apEnvelope[j]->m_lPoints[i+1].m_aValues[0]);
OffsetY = fx2f(apEnvelope[j]->m_lPoints[i+1].m_aValues[1]);
vec2 Pos1 = vec2(fx2f(pPoints[4].x)+OffsetX, fx2f(pPoints[4].y)+OffsetY);
IGraphics::CLineItem Line = IGraphics::CLineItem(Pos0.x, Pos0.y, Pos1.x, Pos1.y);
Graphics()->LinesDraw(&Line, 1);
}
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
}
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
Graphics()->LinesEnd();
//Draw Quads
for(int i = 0; i < pEnvelope->m_lPoints.size(); i++)
Graphics()->TextureSet(TexID);
Graphics()->QuadsBegin();
for(int j = 0; j < Num; j++)
{
Graphics()->TextureSet(TexID);
Graphics()->QuadsBegin();
//Calc Env Position
float OffsetX = fx2f(pEnvelope->m_lPoints[i].m_aValues[0]);
float OffsetY = fx2f(pEnvelope->m_lPoints[i].m_aValues[1]);
float Rot = fx2f(pEnvelope->m_lPoints[i].m_aValues[2])/360.0f*pi*2;
if(!apEnvelope[j])
continue;
//Set Colours
float Alpha = (m_SelectedQuadEnvelope == pQuad->m_PosEnv && m_SelectedEnvelopePoint == i) ? 0.65f : 0.35f;
IGraphics::CColorVertex aArray[4] = {
IGraphics::CColorVertex(0, pQuad->m_aColors[0].r, pQuad->m_aColors[0].g, pQuad->m_aColors[0].b, Alpha),
IGraphics::CColorVertex(1, pQuad->m_aColors[1].r, pQuad->m_aColors[1].g, pQuad->m_aColors[1].b, Alpha),
IGraphics::CColorVertex(2, pQuad->m_aColors[2].r, pQuad->m_aColors[2].g, pQuad->m_aColors[2].b, Alpha),
IGraphics::CColorVertex(3, pQuad->m_aColors[3].r, pQuad->m_aColors[3].g, pQuad->m_aColors[3].b, Alpha)};
Graphics()->SetColorVertex(aArray, 4);
//QuadParams
const CPoint *pPoints = lQuads[j].m_aPoints;
//Rotation
if(Rot != 0)
for(int i = 0; i < apEnvelope[j]->m_lPoints.size(); i++)
{
static CPoint aRotated[4];
aRotated[0] = pQuad->m_aPoints[0];
aRotated[1] = pQuad->m_aPoints[1];
aRotated[2] = pQuad->m_aPoints[2];
aRotated[3] = pQuad->m_aPoints[3];
pPoints = aRotated;
//Calc Env Position
float OffsetX = fx2f(apEnvelope[j]->m_lPoints[i].m_aValues[0]);
float OffsetY = fx2f(apEnvelope[j]->m_lPoints[i].m_aValues[1]);
float Rot = fx2f(apEnvelope[j]->m_lPoints[i].m_aValues[2])/360.0f*pi*2;
Rotate(&pQuad->m_aPoints[4], &aRotated[0], Rot);
Rotate(&pQuad->m_aPoints[4], &aRotated[1], Rot);
Rotate(&pQuad->m_aPoints[4], &aRotated[2], Rot);
Rotate(&pQuad->m_aPoints[4], &aRotated[3], Rot);
//Set Colours
float Alpha = (m_SelectedQuadEnvelope == lQuads[j].m_PosEnv && m_SelectedEnvelopePoint == i) ? 0.65f : 0.35f;
IGraphics::CColorVertex aArray[4] = {
IGraphics::CColorVertex(0, lQuads[j].m_aColors[0].r, lQuads[j].m_aColors[0].g, lQuads[j].m_aColors[0].b, Alpha),
IGraphics::CColorVertex(1, lQuads[j].m_aColors[1].r, lQuads[j].m_aColors[1].g, lQuads[j].m_aColors[1].b, Alpha),
IGraphics::CColorVertex(2, lQuads[j].m_aColors[2].r, lQuads[j].m_aColors[2].g, lQuads[j].m_aColors[2].b, Alpha),
IGraphics::CColorVertex(3, lQuads[j].m_aColors[3].r, lQuads[j].m_aColors[3].g, lQuads[j].m_aColors[3].b, Alpha)};
Graphics()->SetColorVertex(aArray, 4);
//Rotation
if(Rot != 0)
{
static CPoint aRotated[4];
aRotated[0] = lQuads[j].m_aPoints[0];
aRotated[1] = lQuads[j].m_aPoints[1];
aRotated[2] = lQuads[j].m_aPoints[2];
aRotated[3] = lQuads[j].m_aPoints[3];
pPoints = aRotated;
Rotate(&lQuads[j].m_aPoints[4], &aRotated[0], Rot);
Rotate(&lQuads[j].m_aPoints[4], &aRotated[1], Rot);
Rotate(&lQuads[j].m_aPoints[4], &aRotated[2], Rot);
Rotate(&lQuads[j].m_aPoints[4], &aRotated[3], Rot);
}
//Set Texture Coords
Graphics()->QuadsSetSubsetFree(
fx2f(lQuads[j].m_aTexcoords[0].x), fx2f(lQuads[j].m_aTexcoords[0].y),
fx2f(lQuads[j].m_aTexcoords[1].x), fx2f(lQuads[j].m_aTexcoords[1].y),
fx2f(lQuads[j].m_aTexcoords[2].x), fx2f(lQuads[j].m_aTexcoords[2].y),
fx2f(lQuads[j].m_aTexcoords[3].x), fx2f(lQuads[j].m_aTexcoords[3].y)
);
//Set Quad Coords & Draw
IGraphics::CFreeformItem Freeform(
fx2f(pPoints[0].x)+OffsetX, fx2f(pPoints[0].y)+OffsetY,
fx2f(pPoints[1].x)+OffsetX, fx2f(pPoints[1].y)+OffsetY,
fx2f(pPoints[2].x)+OffsetX, fx2f(pPoints[2].y)+OffsetY,
fx2f(pPoints[3].x)+OffsetX, fx2f(pPoints[3].y)+OffsetY);
Graphics()->QuadsDrawFreeform(&Freeform, 1);
}
//Set Texture Coords
Graphics()->QuadsSetSubsetFree(
fx2f(pQuad->m_aTexcoords[0].x), fx2f(pQuad->m_aTexcoords[0].y),
fx2f(pQuad->m_aTexcoords[1].x), fx2f(pQuad->m_aTexcoords[1].y),
fx2f(pQuad->m_aTexcoords[2].x), fx2f(pQuad->m_aTexcoords[2].y),
fx2f(pQuad->m_aTexcoords[3].x), fx2f(pQuad->m_aTexcoords[3].y)
);
//Set Quad Coords & Draw
IGraphics::CFreeformItem Freeform(
fx2f(pPoints[0].x)+OffsetX, fx2f(pPoints[0].y)+OffsetY,
fx2f(pPoints[1].x)+OffsetX, fx2f(pPoints[1].y)+OffsetY,
fx2f(pPoints[2].x)+OffsetX, fx2f(pPoints[2].y)+OffsetY,
fx2f(pPoints[3].x)+OffsetX, fx2f(pPoints[3].y)+OffsetY);
Graphics()->QuadsDrawFreeform(&Freeform, 1);
Graphics()->QuadsEnd();
Graphics()->TextureSet(-1);
Graphics()->QuadsBegin();
DoQuadEnvPoint(pQuad, Index, i);
Graphics()->QuadsEnd();
}
Graphics()->QuadsEnd();
Graphics()->TextureSet(-1);
Graphics()->QuadsBegin();
// Draw QuadPoints
for(int j = 0; j < Num; j++)
{
if(!apEnvelope[j])
continue;
//QuadParams
for(int i = 0; i < apEnvelope[j]->m_lPoints.size()-1; i++)
DoQuadEnvPoint(&lQuads[j], j, i);
}
Graphics()->QuadsEnd();
delete[] apEnvelope;
}
void CEditor::DoQuadEnvPoint(CQuad *pQuad, int QIndex, int PIndex)
void CEditor::DoQuadEnvPoint(const CQuad *pQuad, int QIndex, int PIndex)
{
enum
{
@ -2153,12 +2191,7 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar)
if(pLayer->m_Image >= 0 && pLayer->m_Image < m_Map.m_lImages.size())
TexID = m_Map.m_lImages[pLayer->m_Image]->m_TexID;
for(int i = 0; i < pLayer->m_lQuads.size(); i++)
{
if((m_ShowEnvelopePreview == 1 && pLayer->m_lQuads[i].m_PosEnv == m_SelectedEnvelope) || m_ShowEnvelopePreview == 2)
DoQuadEnvelopes(&pLayer->m_lQuads[i], i, TexID);
}
DoQuadEnvelopes(pLayer->m_lQuads, TexID);
m_ShowEnvelopePreview = 0;
}
@ -2352,8 +2385,6 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
s_ScrollValue = clamp(s_ScrollValue + 1.0f/ScrollNum, 0.0f, 1.0f);
}
else
ScrollNum = 0;
}
}
@ -2488,11 +2519,17 @@ void CEditor::ReplaceImage(const char *pFileName, int StorageType, void *pUser)
CEditorImage *pImg = pEditor->m_Map.m_lImages[pEditor->m_SelectedImage];
int External = pImg->m_External;
pEditor->Graphics()->UnloadTexture(pImg->m_TexID);
if(pImg->m_pData)
{
mem_free(pImg->m_pData);
pImg->m_pData = 0;
}
*pImg = ImgInfo;
pImg->m_External = External;
pEditor->ExtractName(pFileName, pImg->m_aName, sizeof(pImg->m_aName));
pImg->m_AutoMapper.Load(pImg->m_aName);
pImg->m_TexID = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
ImgInfo.m_pData = 0;
pEditor->SortImages();
for(int i = 0; i < pEditor->m_Map.m_lImages.size(); ++i)
{
@ -2521,6 +2558,7 @@ void CEditor::AddImage(const char *pFileName, int StorageType, void *pUser)
CEditorImage *pImg = new CEditorImage(pEditor);
*pImg = ImgInfo;
pImg->m_TexID = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
ImgInfo.m_pData = 0;
pImg->m_External = 1; // external by default
str_copy(pImg->m_aName, aBuf, sizeof(pImg->m_aName));
pImg->m_AutoMapper.Load(pImg->m_aName);
@ -2668,8 +2706,6 @@ void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
s_ScrollValue = clamp(s_ScrollValue + 1.0f/ScrollNum, 0.0f, 1.0f);
}
else
ScrollNum = 0;
}
}

View file

@ -793,8 +793,8 @@ public:
vec4 ButtonColorMul(const void *pID);
void DoQuadEnvelopes(CQuad *pQuad, int Index, int TexID = -1);
void DoQuadEnvPoint(CQuad *pQuad, int QIndex, int pIndex);
void DoQuadEnvelopes(const array<CQuad> &m_lQuads, int TexID = -1);
void DoQuadEnvPoint(const CQuad *pQuad, int QIndex, int pIndex);
void DoQuadPoint(CQuad *pQuad, int QuadIndex, int v);
void DoMapEditor(CUIRect View, CUIRect Toolbar);

View file

@ -439,6 +439,7 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName)
}
df.AddItem(MAPITEMTYPE_ENVPOINTS, 0, TotalSize, pPoints);
mem_free(pPoints);
// finish the data file
df.Finish();
@ -482,6 +483,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag
editor->reset();
editor_load_old(df, this);
*/
return 0;
}
else if(pItem->m_Version == 1)
{
@ -527,6 +529,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag
{
*pImg = ImgInfo;
pImg->m_TexID = m_pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
ImgInfo.m_pData = 0;
pImg->m_External = 1;
}
}
@ -846,6 +849,8 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag
}
}
}
else
return 0;
return 1;
}

View file

@ -27,7 +27,10 @@ void CLayerQuads::Render()
if(m_Image >= 0 && m_Image < m_pEditor->m_Map.m_lImages.size())
Graphics()->TextureSet(m_pEditor->m_Map.m_lImages[m_Image]->m_TexID);
m_pEditor->RenderTools()->RenderQuads(m_lQuads.base_ptr(), m_lQuads.size(), LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT, m_pEditor->EnvelopeEval, m_pEditor);
Graphics()->BlendNone();
m_pEditor->RenderTools()->RenderQuads(m_lQuads.base_ptr(), m_lQuads.size(), LAYERRENDERFLAG_OPAQUE, m_pEditor->EnvelopeEval, m_pEditor);
Graphics()->BlendNormal();
m_pEditor->RenderTools()->RenderQuads(m_lQuads.base_ptr(), m_lQuads.size(), LAYERRENDERFLAG_TRANSPARENT, m_pEditor->EnvelopeEval, m_pEditor);
}
CQuad *CLayerQuads::NewQuad()

View file

@ -72,7 +72,11 @@ void CLayerTiles::Render()
m_TexID = m_pEditor->m_Map.m_lImages[m_Image]->m_TexID;
Graphics()->TextureSet(m_TexID);
vec4 Color = vec4(m_Color.r/255.0f, m_Color.g/255.0f, m_Color.b/255.0f, m_Color.a/255.0f);
m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, Color, LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT,
Graphics()->BlendNone();
m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, Color, LAYERRENDERFLAG_OPAQUE,
m_pEditor->EnvelopeEval, m_pEditor, m_ColorEnv, m_ColorEnvOffset);
Graphics()->BlendNormal();
m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, Color, LAYERRENDERFLAG_TRANSPARENT,
m_pEditor->EnvelopeEval, m_pEditor, m_ColorEnv, m_ColorEnvOffset);
// Render DDRace Layers
@ -476,6 +480,7 @@ void CLayerTiles::ShowInfo()
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
Graphics()->TextureSet(m_pEditor->Client()->GetDebugFont());
Graphics()->QuadsBegin();
int StartY = max(0, (int)(ScreenY0/32.0f)-1);
int StartX = max(0, (int)(ScreenX0/32.0f)-1);
@ -490,17 +495,18 @@ void CLayerTiles::ShowInfo()
{
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%i", m_pTiles[c].m_Index);
m_pEditor->Graphics()->QuadsText(x*32, y*32, 16.0f, 1,1,1,1, aBuf);
m_pEditor->Graphics()->QuadsText(x*32, y*32, 16.0f, aBuf);
char aFlags[4] = { m_pTiles[c].m_Flags&TILEFLAG_VFLIP ? 'V' : ' ',
m_pTiles[c].m_Flags&TILEFLAG_HFLIP ? 'H' : ' ',
m_pTiles[c].m_Flags&TILEFLAG_ROTATE? 'R' : ' ',
0};
m_pEditor->Graphics()->QuadsText(x*32, y*32+16, 16.0f, 1,1,1,1, aFlags);
m_pEditor->Graphics()->QuadsText(x*32, y*32+16, 16.0f, aFlags);
}
x += m_pTiles[c].m_Skip;
}
Graphics()->QuadsEnd();
Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
}

View file

@ -632,7 +632,6 @@ int CEditor::PopupPoint(CEditor *pEditor, CUIRect View)
{
if(pEditor->m_SelectedPoints&(1<<v))
{
Color = 0;
pQuad->m_aColors[v].r = (NewVal>>24)&0xff;
pQuad->m_aColors[v].g = (NewVal>>16)&0xff;
pQuad->m_aColors[v].b = (NewVal>>8)&0xff;

View file

@ -63,6 +63,7 @@ bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos)
{
m_EmoteStop = -1;
m_LastAction = -1;
m_LastNoAmmoSound = -1;
m_ActiveWeapon = WEAPON_GUN;
m_LastWeapon = WEAPON_HAMMER;
m_QueuedWeapon = -1;

View file

@ -101,6 +101,7 @@ private:
// last tick that the player took any action ie some input
int m_LastAction;
int m_LastNoAmmoSound;
// these are non-heldback inputs
CNetObj_PlayerInput m_LatestPrevInput;

File diff suppressed because it is too large Load diff

View file

@ -475,8 +475,8 @@ void IGameController::ChangeMap(const char *pToMap)
pNextMap = pMapRotation;
// cut out the next map
char aBuf[512];
for(int i = 0; i < 512; i++)
char aBuf[512] = {0};
for(int i = 0; i < 511; i++)
{
aBuf[i] = pNextMap[i];
if(IsSeparator(pNextMap[i]) || pNextMap[i] == 0)

View file

@ -99,7 +99,7 @@ bool CGameControllerCTF::CanBeMovedOnBalance(int ClientID)
for(int fi = 0; fi < 2; fi++)
{
CFlag *F = m_apFlags[fi];
if(F->m_pCarryingCharacter == Character)
if(F && F->m_pCarryingCharacter == Character)
return false;
}
}

View file

@ -18,7 +18,7 @@ int CGameControllerTDM::OnCharacterDeath(class CCharacter *pVictim, class CPlaye
IGameController::OnCharacterDeath(pVictim, pKiller, Weapon);
if(Weapon != WEAPON_GAME)
if(pKiller && Weapon != WEAPON_GAME)
{
// do team scoring
if(pKiller == pVictim->GetPlayer() || pKiller->GetTeam() == pVictim->GetPlayer()->GetTeam())

View file

@ -387,6 +387,7 @@ void CPlayer::SetTeam(int Team, bool DoChatMsg)
m_Team = Team;
m_LastSetTeam = Server()->Tick();
m_LastActionTick = Server()->Tick();
m_SpectatorID = SPEC_FREEVIEW;
// we got to wait 0.5 secs before respawning
m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' m_Team=%d", m_ClientID, Server()->ClientName(m_ClientID), m_Team);

View file

@ -3,7 +3,7 @@
#ifndef GAME_VERSION_H
#define GAME_VERSION_H
#include "generated/nethash.cpp"
#define GAME_VERSION "0.6 trunk, 1.26"
#define GAME_VERSION "0.6.2, 2.0"
#define GAME_NETVERSION "0.6 626fce9a778df4d4"
static const char GAME_RELEASE_VERSION[8] = {'0', '.', '6', '1', 0};
static const char GAME_RELEASE_VERSION[8] = {'0', '.', '6', '.', '2', 0};
#endif

View file

@ -348,7 +348,11 @@ int main(int argc, const char **argv) // ignore_convention
m_pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention
if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
{
// got bindaddr
BindAddr.type = NETTYPE_ALL;
BindAddr.port = MASTERSERVER_PORT;
}
else
{
mem_zero(&BindAddr, sizeof(BindAddr));
@ -368,6 +372,9 @@ int main(int argc, const char **argv) // ignore_convention
return -1;
}
// process pending commands
m_pConsole->StoreCommands(false);
dbg_msg("mastersrv", "started");
while(1)

View file

@ -0,0 +1,22 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#ifndef VERSIONSRV_MAPVERSIONS_H
#define VERSIONSRV_MAPVERSIONS_H
static CMapVersion s_aMapVersionList[] = {
{"ctf1", {0x06, 0xb5, 0xf1, 0x17}, {0x00, 0x00, 0x12, 0x38}},
{"ctf2", {0x27, 0xbc, 0x5e, 0xac}, {0x00, 0x00, 0x64, 0x1a}},
{"ctf3", {0xa3, 0x73, 0x9d, 0x41}, {0x00, 0x00, 0x17, 0x0f}},
{"ctf4", {0xbe, 0x7c, 0x4d, 0xb9}, {0x00, 0x00, 0x2e, 0xfe}},
{"ctf5", {0xd9, 0x21, 0x29, 0xa0}, {0x00, 0x00, 0x2f, 0x4c}},
{"ctf6", {0x28, 0xc8, 0x43, 0x51}, {0x00, 0x00, 0x69, 0x2f}},
{"ctf7", {0x1d, 0x35, 0x98, 0x72}, {0x00, 0x00, 0x15, 0x87}},
{"dm1", {0xf2, 0x15, 0x9e, 0x6e}, {0x00, 0x00, 0x16, 0xad}},
{"dm2", {0x71, 0x83, 0x98, 0x78}, {0x00, 0x00, 0x21, 0xdf}},
{"dm6", {0x47, 0x4d, 0xa2, 0x35}, {0x00, 0x00, 0x1e, 0x95}},
{"dm7", {0x42, 0x6d, 0xa1, 0x67}, {0x00, 0x00, 0x27, 0x2a}},
{"dm8", {0x85, 0xf1, 0x1e, 0xd6}, {0x00, 0x00, 0x9e, 0xbd}},
{"dm9", {0x42, 0xd4, 0x77, 0x7e}, {0x00, 0x00, 0x20, 0x11}},
};
static const int s_NumMapVersionItems = sizeof(s_aMapVersionList)/sizeof(CMapVersion);
#endif

View file

@ -7,6 +7,7 @@
#include <game/version.h>
#include "versionsrv.h"
#include "mapversions.h"
enum {
MAX_MAPS_PER_PACKET=48,

View file

@ -11,23 +11,6 @@ struct CMapVersion
unsigned char m_aSize[4];
};
static CMapVersion s_aMapVersionList[] = {
{"ctf1", {0x06, 0xb5, 0xf1, 0x17}, {0x00, 0x00, 0x12, 0x38}},
{"ctf2", {0x27, 0xbc, 0x5e, 0xac}, {0x00, 0x00, 0x64, 0x1a}},
{"ctf3", {0xa3, 0x73, 0x9d, 0x41}, {0x00, 0x00, 0x17, 0x0f}},
{"ctf4", {0xbe, 0x7c, 0x4d, 0xb9}, {0x00, 0x00, 0x2e, 0xfe}},
{"ctf5", {0xd9, 0x21, 0x29, 0xa0}, {0x00, 0x00, 0x2f, 0x4c}},
{"ctf6", {0x28, 0xc8, 0x43, 0x51}, {0x00, 0x00, 0x69, 0x2f}},
{"ctf7", {0x1d, 0x35, 0x98, 0x72}, {0x00, 0x00, 0x15, 0x87}},
{"dm1", {0xf2, 0x15, 0x9e, 0x6e}, {0x00, 0x00, 0x16, 0xad}},
{"dm2", {0x71, 0x83, 0x98, 0x78}, {0x00, 0x00, 0x21, 0xdf}},
{"dm6", {0x47, 0x4d, 0xa2, 0x35}, {0x00, 0x00, 0x1e, 0x95}},
{"dm7", {0x42, 0x6d, 0xa1, 0x67}, {0x00, 0x00, 0x27, 0x2a}},
{"dm8", {0x85, 0xf1, 0x1e, 0xd6}, {0x00, 0x00, 0x9e, 0xbd}},
{"dm9", {0x42, 0xd4, 0x77, 0x7e}, {0x00, 0x00, 0x20, 0x11}},
};
static const int s_NumMapVersionItems = sizeof(s_aMapVersionList)/sizeof(CMapVersion);
static const unsigned char VERSIONSRV_GETVERSION[] = {255, 255, 255, 255, 'v', 'e', 'r', 'g'};
static const unsigned char VERSIONSRV_VERSION[] = {255, 255, 255, 255, 'v', 'e', 'r', 's'};