From 2e09bd6b9dff4d1cf52be37a005dd7e57df5fa26 Mon Sep 17 00:00:00 2001 From: Johannes Loher Date: Wed, 6 Apr 2011 21:15:58 +0200 Subject: [PATCH 01/12] Extended the control settings so spectate_next and spectate_previous can be set there. --- src/game/client/components/menus_settings.cpp | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index a5ec18cce..ac5a5f40b 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -439,16 +439,19 @@ static CKeyInfo gs_aKeys[] = { "Show chat", "+show_chat", 0 }, { "Emoticon", "+emote", 0 }, { "Spectator mode", "+spectate", 0 }, + { "Spectate next", "spectate_next", 0 }, + { "Spectate previous", "spectate_previous", 0 }, { "Console", "toggle_local_console", 0 }, { "Remote console", "toggle_remote_console", 0 }, { "Screenshot", "screenshot", 0 }, { "Scoreboard", "+scoreboard", 0 }, }; + /* This is for scripts/update_localization.py to work, don't remove! Localize("Move left");Localize("Move right");Localize("Jump");Localize("Fire");Localize("Hook");Localize("Hammer"); Localize("Pistol");Localize("Shotgun");Localize("Grenade");Localize("Rifle");Localize("Next weapon");Localize("Prev. weapon"); Localize("Vote yes");Localize("Vote no");Localize("Chat");Localize("Team chat");Localize("Show chat");Localize("Emoticon"); - Localize("Spectator mode");Localize("Console");Localize("Remote console");Localize("Screenshot");Localize("Scoreboard"); + Localize("Spectator mode");Localize("Spectate next");Localize("Spectate previous");Localize("Console");Localize("Remote console");Localize("Screenshot");Localize("Scoreboard"); */ const int g_KeyCount = sizeof(gs_aKeys) / sizeof(CKeyInfo); @@ -504,7 +507,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) // movement settings { - MovementSettings.HSplitTop(MainView.h/2-5.0f, &MovementSettings, &WeaponSettings); + MovementSettings.HSplitTop(MainView.h/3+60.0f, &MovementSettings, &WeaponSettings); RenderTools()->DrawUIRect(&MovementSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); MovementSettings.Margin(10.0f, &MovementSettings); @@ -530,6 +533,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) // weapon settings { WeaponSettings.HSplitTop(10.0f, 0, &WeaponSettings); + WeaponSettings.HSplitTop(MainView.h/3+50.0f, &WeaponSettings, &ResetButton); RenderTools()->DrawUIRect(&WeaponSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); WeaponSettings.Margin(10.0f, &WeaponSettings); @@ -538,11 +542,22 @@ void CMenus::RenderSettingsControls(CUIRect MainView) WeaponSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &WeaponSettings); UiDoGetButtons(5, 12, WeaponSettings); } - + + // defaults + { + ResetButton.HSplitTop(10.0f, 0, &ResetButton); + RenderTools()->DrawUIRect(&ResetButton, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); + ResetButton.HMargin(10.0f, &ResetButton); + ResetButton.VMargin(30.0f, &ResetButton); + static int s_DefaultButton = 0; + if(DoButton_Menu((void*)&s_DefaultButton, Localize("Reset to defaults"), 0, &ResetButton)) + m_pClient->m_pBinds->SetDefaults(); + } + // voting settings { VotingSettings.VSplitLeft(10.0f, 0, &VotingSettings); - VotingSettings.HSplitTop(MainView.h/4-5.0f, &VotingSettings, &ChatSettings); + VotingSettings.HSplitTop(MainView.h/3-75.0f, &VotingSettings, &ChatSettings); RenderTools()->DrawUIRect(&VotingSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); VotingSettings.Margin(10.0f, &VotingSettings); @@ -555,7 +570,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) // chat settings { ChatSettings.HSplitTop(10.0f, 0, &ChatSettings); - ChatSettings.HSplitTop(MainView.h/4-10.0f, &ChatSettings, &MiscSettings); + ChatSettings.HSplitTop(MainView.h/3-45.0f, &ChatSettings, &MiscSettings); RenderTools()->DrawUIRect(&ChatSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); ChatSettings.Margin(10.0f, &ChatSettings); @@ -568,24 +583,15 @@ void CMenus::RenderSettingsControls(CUIRect MainView) // misc settings { MiscSettings.HSplitTop(10.0f, 0, &MiscSettings); - MiscSettings.HSplitBottom(50.0f, &MiscSettings, &ResetButton); RenderTools()->DrawUIRect(&MiscSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); MiscSettings.Margin(10.0f, &MiscSettings); TextRender()->Text(0, MiscSettings.x, MiscSettings.y, 14.0f*UI()->Scale(), Localize("Miscellaneous"), -1); MiscSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &MiscSettings); - UiDoGetButtons(17, 23, MiscSettings); + UiDoGetButtons(17, 25, MiscSettings); } - // defaults - ResetButton.HSplitTop(10.0f, 0, &ResetButton); - RenderTools()->DrawUIRect(&ResetButton, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - ResetButton.HMargin(10.0f, &ResetButton); - ResetButton.VMargin(30.0f, &ResetButton); - static int s_DefaultButton = 0; - if(DoButton_Menu((void*)&s_DefaultButton, Localize("Reset to defaults"), 0, &ResetButton)) - m_pClient->m_pBinds->SetDefaults(); } void CMenus::RenderSettingsGraphics(CUIRect MainView) From 537e5fa7b6f99a982b7a9cda8587624fc1f49a3a Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 13 Apr 2011 17:39:26 +0200 Subject: [PATCH 02/12] added default keys for spectator next/previous and updated localisations --- data/languages/bosnian.txt | 6 ++++++ data/languages/bulgarian.txt | 6 ++++++ data/languages/czech.txt | 6 ++++++ data/languages/dutch.txt | 6 ++++++ data/languages/finnish.txt | 6 ++++++ data/languages/french.txt | 6 ++++++ data/languages/german.txt | 6 ++++++ data/languages/italian.txt | 6 ++++++ data/languages/norwegian.txt | 6 ++++++ data/languages/polish.txt | 6 ++++++ data/languages/portuguese.txt | 6 ++++++ data/languages/romanian.txt | 6 ++++++ data/languages/russian.txt | 6 ++++++ data/languages/serbian.txt | 6 ++++++ data/languages/slovak.txt | 6 ++++++ data/languages/spanish.txt | 6 ++++++ data/languages/swedish.txt | 6 ++++++ data/languages/ukrainian.txt | 6 ++++++ src/game/client/components/binds.cpp | 2 ++ 19 files changed, 110 insertions(+) diff --git a/data/languages/bosnian.txt b/data/languages/bosnian.txt index 443c977c7..4ba703436 100644 --- a/data/languages/bosnian.txt +++ b/data/languages/bosnian.txt @@ -657,5 +657,11 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### diff --git a/data/languages/bulgarian.txt b/data/languages/bulgarian.txt index fce6f1387..680c23466 100644 --- a/data/languages/bulgarian.txt +++ b/data/languages/bulgarian.txt @@ -657,6 +657,12 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### Page %d of %d diff --git a/data/languages/czech.txt b/data/languages/czech.txt index fd453c2c7..daad1cc2f 100644 --- a/data/languages/czech.txt +++ b/data/languages/czech.txt @@ -657,5 +657,11 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### diff --git a/data/languages/dutch.txt b/data/languages/dutch.txt index 055a04959..2e2d9894a 100644 --- a/data/languages/dutch.txt +++ b/data/languages/dutch.txt @@ -657,5 +657,11 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### diff --git a/data/languages/finnish.txt b/data/languages/finnish.txt index 4e8e464bc..655b0a1f0 100644 --- a/data/languages/finnish.txt +++ b/data/languages/finnish.txt @@ -657,5 +657,11 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### diff --git a/data/languages/french.txt b/data/languages/french.txt index 2efb521ba..f71f0bcbd 100644 --- a/data/languages/french.txt +++ b/data/languages/french.txt @@ -657,5 +657,11 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### diff --git a/data/languages/german.txt b/data/languages/german.txt index 9ce08ff1c..a1fcd0dac 100644 --- a/data/languages/german.txt +++ b/data/languages/german.txt @@ -657,5 +657,11 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### diff --git a/data/languages/italian.txt b/data/languages/italian.txt index 8798c0b71..ae46b20c3 100644 --- a/data/languages/italian.txt +++ b/data/languages/italian.txt @@ -627,6 +627,12 @@ Size: Sound error == +Spectate next +== + +Spectate previous +== + Spectator mode == diff --git a/data/languages/norwegian.txt b/data/languages/norwegian.txt index 8be90165e..464cd364e 100644 --- a/data/languages/norwegian.txt +++ b/data/languages/norwegian.txt @@ -657,5 +657,11 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### diff --git a/data/languages/polish.txt b/data/languages/polish.txt index 857650f7c..96a63c293 100644 --- a/data/languages/polish.txt +++ b/data/languages/polish.txt @@ -618,6 +618,12 @@ Size: Sound error == +Spectate next +== + +Spectate previous +== + Spectator mode == diff --git a/data/languages/portuguese.txt b/data/languages/portuguese.txt index 4a6ef0d69..c81a04389 100644 --- a/data/languages/portuguese.txt +++ b/data/languages/portuguese.txt @@ -657,5 +657,11 @@ no limit 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. == +Spectate next +== + +Spectate previous +== + ##### old translations ##### diff --git a/data/languages/romanian.txt b/data/languages/romanian.txt index 3f589dc4b..fedc825cc 100644 --- a/data/languages/romanian.txt +++ b/data/languages/romanian.txt @@ -657,5 +657,11 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### diff --git a/data/languages/russian.txt b/data/languages/russian.txt index c47dcf7e8..e97ef0f96 100644 --- a/data/languages/russian.txt +++ b/data/languages/russian.txt @@ -657,5 +657,11 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### diff --git a/data/languages/serbian.txt b/data/languages/serbian.txt index 97a23f09e..47053ca36 100644 --- a/data/languages/serbian.txt +++ b/data/languages/serbian.txt @@ -618,6 +618,12 @@ Size: Sound error == +Spectate next +== + +Spectate previous +== + Spectator mode == diff --git a/data/languages/slovak.txt b/data/languages/slovak.txt index f1fe24722..3aa18ad7e 100644 --- a/data/languages/slovak.txt +++ b/data/languages/slovak.txt @@ -657,5 +657,11 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### diff --git a/data/languages/spanish.txt b/data/languages/spanish.txt index 79110652d..d717dac2f 100644 --- a/data/languages/spanish.txt +++ b/data/languages/spanish.txt @@ -657,6 +657,12 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### Page %d of %d diff --git a/data/languages/swedish.txt b/data/languages/swedish.txt index 4e15b9ae5..8415b0041 100644 --- a/data/languages/swedish.txt +++ b/data/languages/swedish.txt @@ -657,5 +657,11 @@ no limit ##### needs translation ##### +Spectate next +== + +Spectate previous +== + ##### old translations ##### diff --git a/data/languages/ukrainian.txt b/data/languages/ukrainian.txt index 7f43c5f0b..ca0fd150f 100644 --- a/data/languages/ukrainian.txt +++ b/data/languages/ukrainian.txt @@ -624,6 +624,12 @@ Size: Sound error == +Spectate next +== + +Spectate previous +== + Spectator mode == diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 746389bd7..1632b26fc 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -100,6 +100,8 @@ void CBinds::SetDefaults() Bind(KEY_MOUSE_2, "+hook"); Bind(KEY_LSHIFT, "+emote"); Bind(KEY_RSHIFT, "+spectate"); + Bind(KEY_RIGHT, "spectate_next"); + Bind(KEY_LEFT, "spectate_previous"); Bind('1', "+weapon1"); Bind('2', "+weapon2"); From 876eac10484c4f4a29a64126ad2be5866baaf687 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 13 Apr 2011 17:47:02 +0200 Subject: [PATCH 03/12] added fix to make [Shift] only change the time of the point and not his value for envelopes in map editor by Choupon --- src/game/editor/ed_editor.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/game/editor/ed_editor.cpp b/src/game/editor/ed_editor.cpp index d2515e447..1163dc4ae 100644 --- a/src/game/editor/ed_editor.cpp +++ b/src/game/editor/ed_editor.cpp @@ -2849,12 +2849,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) s_Move = false; } else - { - if((Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL))) - pEnvelope->m_lPoints[i].m_aValues[c] -= f2fx(m_MouseDeltaY*0.001f); - else - pEnvelope->m_lPoints[i].m_aValues[c] -= f2fx(m_MouseDeltaY*ValueScale); - + { if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) { if(i != 0) @@ -2869,6 +2864,13 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) pEnvelope->m_lPoints[i].m_Time = pEnvelope->m_lPoints[i+1].m_Time - 1; } } + else + { + if((Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL))) + pEnvelope->m_lPoints[i].m_aValues[c] -= f2fx(m_MouseDeltaY*0.001f); + else + pEnvelope->m_lPoints[i].m_aValues[c] -= f2fx(m_MouseDeltaY*ValueScale); + } m_Map.m_Modified = true; } From 2179ae011302ecc48a2289a88cc865cdcb4d9f72 Mon Sep 17 00:00:00 2001 From: Choupom Date: Sun, 27 Mar 2011 12:12:50 +0200 Subject: [PATCH 04/12] fixed need restart warning in settings --- src/game/client/components/menus_settings.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index ac5a5f40b..688f7695b 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -755,7 +755,7 @@ void CMenus::RenderSettingsSound(CUIRect MainView) if(DoButton_CheckBox(&g_Config.m_SndEnable, Localize("Use sounds"), g_Config.m_SndEnable, &Button)) { g_Config.m_SndEnable ^= 1; - m_NeedRestartSound = s_SndEnable == g_Config.m_SndEnable && (!s_SndEnable || s_SndRate == g_Config.m_SndRate) ? false : true; + m_NeedRestartSound = g_Config.m_SndEnable && (!s_SndEnable || s_SndRate != g_Config.m_SndRate); } if(!g_Config.m_SndEnable) @@ -774,11 +774,8 @@ void CMenus::RenderSettingsSound(CUIRect MainView) Button.VSplitLeft(190.0f, 0, &Button); static float Offset = 0.0f; DoEditBox(&g_Config.m_SndRate, &Button, aBuf, sizeof(aBuf), 14.0f, &Offset); - int Before = g_Config.m_SndRate; g_Config.m_SndRate = max(1, str_toint(aBuf)); - - if(g_Config.m_SndRate != Before) - m_NeedRestartSound = s_SndEnable == g_Config.m_SndEnable && s_SndRate == g_Config.m_SndRate ? false : true; + m_NeedRestartSound = !s_SndEnable || s_SndRate != g_Config.m_SndRate; } // volume slider From 1a5d70450f1de87224334e550706c67ad0cde6b8 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 13 Apr 2011 20:00:54 +0200 Subject: [PATCH 05/12] added "reimplemented menu music by teetow-the-great-teetow" by Choupom --- data/languages/bosnian.txt | 3 ++ data/languages/bulgarian.txt | 3 ++ data/languages/czech.txt | 3 ++ data/languages/dutch.txt | 3 ++ data/languages/finnish.txt | 3 ++ data/languages/french.txt | 3 ++ data/languages/german.txt | 3 ++ data/languages/italian.txt | 3 ++ data/languages/norwegian.txt | 3 ++ data/languages/polish.txt | 3 ++ data/languages/portuguese.txt | 3 ++ data/languages/romanian.txt | 3 ++ data/languages/russian.txt | 3 ++ data/languages/serbian.txt | 3 ++ data/languages/slovak.txt | 3 ++ data/languages/spanish.txt | 3 ++ data/languages/swedish.txt | 3 ++ data/languages/ukrainian.txt | 3 ++ datasrc/content.py | 2 + scripts/cmd5.py | 3 ++ src/engine/client/sound.cpp | 19 ++++++-- src/engine/client/sound.h | 2 +- src/engine/shared/config_variables.h | 1 + src/engine/sound.h | 6 +-- src/game/client/components/menus.cpp | 4 ++ src/game/client/components/menus_settings.cpp | 17 ++++++- src/game/client/components/sounds.cpp | 46 +++++++++++++++---- src/game/client/components/sounds.h | 9 +++- src/game/client/gameclient.cpp | 2 +- 29 files changed, 142 insertions(+), 23 deletions(-) diff --git a/data/languages/bosnian.txt b/data/languages/bosnian.txt index 4ba703436..2915511ae 100644 --- a/data/languages/bosnian.txt +++ b/data/languages/bosnian.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/bulgarian.txt b/data/languages/bulgarian.txt index 680c23466..47af094ec 100644 --- a/data/languages/bulgarian.txt +++ b/data/languages/bulgarian.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/czech.txt b/data/languages/czech.txt index daad1cc2f..88a7675a3 100644 --- a/data/languages/czech.txt +++ b/data/languages/czech.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/dutch.txt b/data/languages/dutch.txt index 2e2d9894a..e8fc7b7bc 100644 --- a/data/languages/dutch.txt +++ b/data/languages/dutch.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/finnish.txt b/data/languages/finnish.txt index 655b0a1f0..606509407 100644 --- a/data/languages/finnish.txt +++ b/data/languages/finnish.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/french.txt b/data/languages/french.txt index f71f0bcbd..52ef4fc9f 100644 --- a/data/languages/french.txt +++ b/data/languages/french.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/german.txt b/data/languages/german.txt index a1fcd0dac..799d28655 100644 --- a/data/languages/german.txt +++ b/data/languages/german.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/italian.txt b/data/languages/italian.txt index ae46b20c3..cb1365607 100644 --- a/data/languages/italian.txt +++ b/data/languages/italian.txt @@ -588,6 +588,9 @@ Netversion: New name: == +Play background music +== + Player options == diff --git a/data/languages/norwegian.txt b/data/languages/norwegian.txt index 464cd364e..2e944ea53 100644 --- a/data/languages/norwegian.txt +++ b/data/languages/norwegian.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/polish.txt b/data/languages/polish.txt index 96a63c293..fbc7c0da6 100644 --- a/data/languages/polish.txt +++ b/data/languages/polish.txt @@ -573,6 +573,9 @@ New name: Parent Folder == +Play background music +== + Player options == diff --git a/data/languages/portuguese.txt b/data/languages/portuguese.txt index c81a04389..08e2e68cd 100644 --- a/data/languages/portuguese.txt +++ b/data/languages/portuguese.txt @@ -657,6 +657,9 @@ no limit 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. == +Play background music +== + Spectate next == diff --git a/data/languages/romanian.txt b/data/languages/romanian.txt index fedc825cc..ca2aff9ab 100644 --- a/data/languages/romanian.txt +++ b/data/languages/romanian.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/russian.txt b/data/languages/russian.txt index e97ef0f96..dd8a6ec8d 100644 --- a/data/languages/russian.txt +++ b/data/languages/russian.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/serbian.txt b/data/languages/serbian.txt index 47053ca36..99501d776 100644 --- a/data/languages/serbian.txt +++ b/data/languages/serbian.txt @@ -573,6 +573,9 @@ Open Parent Folder == +Play background music +== + Player options == diff --git a/data/languages/slovak.txt b/data/languages/slovak.txt index 3aa18ad7e..25ca442c7 100644 --- a/data/languages/slovak.txt +++ b/data/languages/slovak.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/spanish.txt b/data/languages/spanish.txt index d717dac2f..b015fc3ab 100644 --- a/data/languages/spanish.txt +++ b/data/languages/spanish.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/swedish.txt b/data/languages/swedish.txt index 8415b0041..221761100 100644 --- a/data/languages/swedish.txt +++ b/data/languages/swedish.txt @@ -657,6 +657,9 @@ no limit ##### needs translation ##### +Play background music +== + Spectate next == diff --git a/data/languages/ukrainian.txt b/data/languages/ukrainian.txt index ca0fd150f..c906e446a 100644 --- a/data/languages/ukrainian.txt +++ b/data/languages/ukrainian.txt @@ -585,6 +585,9 @@ New name: Parent Folder == +Play background music +== + Player options == diff --git a/datasrc/content.py b/datasrc/content.py index c49930e56..1dfa7aea5 100644 --- a/datasrc/content.py +++ b/datasrc/content.py @@ -221,6 +221,8 @@ container.sounds.Add(SoundSet("ctf_grab_pl", ["audio/sfx_ctf_grab_pl.wv"])) container.sounds.Add(SoundSet("ctf_grab_en", ["audio/sfx_ctf_grab_en.wv"])) container.sounds.Add(SoundSet("ctf_capture", ["audio/sfx_ctf_cap_pl.wv"])) +container.sounds.Add(SoundSet("menu", ["audio/music_menu.wv"])) + image_null = Image("null", "") image_particles = Image("particles", "particles.png") image_game = Image("game", "game.png") diff --git a/scripts/cmd5.py b/scripts/cmd5.py index 91e22f630..0eac2a335 100644 --- a/scripts/cmd5.py +++ b/scripts/cmd5.py @@ -29,4 +29,7 @@ for filename in sys.argv[1:]: f += cstrip([l.strip() for l in open(filename, "rb")]) hash = hashlib.md5(f).hexdigest().lower()[16:] +#TODO 0.7: improve nethash creation +if hash == "e20714704d311d78": + hash = "626fce9a778df4d4" print('#define GAME_NETVERSION_HASH "%s"' % hash) diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp index 55ca2939b..4678bb8aa 100644 --- a/src/engine/client/sound.cpp +++ b/src/engine/client/sound.cpp @@ -157,8 +157,12 @@ static void Mix(short *pFinalOut, unsigned Frames) // free voice if not used any more if(v->m_Tick == v->m_pSample->m_NumFrames) - v->m_pSample = 0; - + { + if(v->m_Flags&ISound::FLAG_LOOP) + v->m_Tick = 0; + else + v->m_pSample = 0; + } } } @@ -410,7 +414,7 @@ void CSound::SetListenerPos(float x, float y) m_CenterX = (int)x; m_CenterY = (int)y; } - + void CSound::SetChannel(int ChannelID, float Vol, float Pan) { @@ -463,11 +467,16 @@ int CSound::Play(int ChannelID, int SampleID, int Flags) return Play(ChannelID, SampleID, Flags, 0, 0); } -void CSound::Stop(int VoiceID) +void CSound::Stop(int SampleID) { // TODO: a nice fade out lock_wait(m_SoundLock); - m_aVoices[VoiceID].m_pSample = 0; + CSample *pSample = &m_aSamples[SampleID]; + for(int i = 0; i < NUM_VOICES; i++) + { + if(m_aVoices[i].m_pSample == pSample) + m_aVoices[i].m_pSample = 0; + } lock_release(m_SoundLock); } diff --git a/src/engine/client/sound.h b/src/engine/client/sound.h index 0c45f1ab4..3cc84d4da 100644 --- a/src/engine/client/sound.h +++ b/src/engine/client/sound.h @@ -31,7 +31,7 @@ public: int Play(int ChannelID, int SampleID, int Flags, float x, float y); virtual int PlayAt(int ChannelID, int SampleID, int Flags, float x, float y); virtual int Play(int ChannelID, int SampleID, int Flags); - virtual void Stop(int VoiceID); + virtual void Stop(int SampleID); virtual void StopAll(); }; diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index c30edeaf4..857494052 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -47,6 +47,7 @@ MACRO_CONFIG_INT(BrMaxRequests, br_max_requests, 25, 0, 1000, CFGFLAG_SAVE|CFGFL MACRO_CONFIG_INT(SndBufferSize, snd_buffer_size, 512, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound buffer size") MACRO_CONFIG_INT(SndRate, snd_rate, 48000, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound mixing rate") MACRO_CONFIG_INT(SndEnable, snd_enable, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound enable") +MACRO_CONFIG_INT(SndMusic, snd_enable_music, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Play background music") MACRO_CONFIG_INT(SndVolume, snd_volume, 100, 0, 100, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound volume") MACRO_CONFIG_INT(SndDevice, snd_device, -1, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "(deprecated) Sound device to use") diff --git a/src/engine/sound.h b/src/engine/sound.h index 8f5dab245..ac4aeaf50 100644 --- a/src/engine/sound.h +++ b/src/engine/sound.h @@ -21,9 +21,9 @@ public: virtual void SetChannel(int ChannelID, float Volume, float Panning) = 0; virtual void SetListenerPos(float x, float y) = 0; - virtual int PlayAt(int ChannelID, int SoundID, int Flags, float x, float y) = 0; - virtual int Play(int ChannelID, int SoundID, int Flags) = 0; - virtual void Stop(int VoiceID) = 0; + virtual int PlayAt(int ChannelID, int SampleID, int Flags, float x, float y) = 0; + virtual int Play(int ChannelID, int SampleID, int Flags) = 0; + virtual void Stop(int SampleID) = 0; virtual void StopAll() = 0; }; diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 8bed34c1f..060384ec6 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include +#include #include #include #include @@ -769,6 +771,7 @@ int CMenus::Render() ServerBrowser()->Refresh(IServerBrowser::TYPE_LAN); else if(g_Config.m_UiPage == PAGE_FAVORITES) ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES); + m_pClient->m_pSounds->Enqueue(CSounds::CHN_MUSIC, SOUND_MENU); s_First = false; } @@ -1332,6 +1335,7 @@ void CMenus::OnStateChange(int NewState, int OldState) if(NewState == IClient::STATE_OFFLINE) { + m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f, vec2(0, 0)); m_Popup = POPUP_NONE; if(Client()->ErrorString() && Client()->ErrorString()[0] != 0) { diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 688f7695b..959af2f32 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -3,7 +3,7 @@ #include - +#include #include #include #include @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -755,12 +756,26 @@ void CMenus::RenderSettingsSound(CUIRect MainView) if(DoButton_CheckBox(&g_Config.m_SndEnable, Localize("Use sounds"), g_Config.m_SndEnable, &Button)) { g_Config.m_SndEnable ^= 1; + if(g_Config.m_SndEnable) + m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f, vec2(0, 0)); + else + m_pClient->m_pSounds->Stop(SOUND_MENU); m_NeedRestartSound = g_Config.m_SndEnable && (!s_SndEnable || s_SndRate != g_Config.m_SndRate); } if(!g_Config.m_SndEnable) return; + MainView.HSplitTop(20.0f, &Button, &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, vec2(0, 0)); + else + m_pClient->m_pSounds->Stop(SOUND_MENU); + } + MainView.HSplitTop(20.0f, &Button, &MainView); if(DoButton_CheckBox(&g_Config.m_SndNonactiveMute, Localize("Mute when not active"), g_Config.m_SndNonactiveMute, &Button)) g_Config.m_SndNonactiveMute ^= 1; diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index f481b4949..24bd0ebf6 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -72,8 +72,13 @@ void CSounds::OnReset() void CSounds::OnRender() { // check for sound initialisation - if(m_WaitForSoundJob && m_SoundJob.Status() == CJob::STATE_DONE) - m_WaitForSoundJob = false; + if(m_WaitForSoundJob) + { + if(m_SoundJob.Status() == CJob::STATE_DONE) + m_WaitForSoundJob = false; + else + return; + } // set listner pos Sound()->SetListenerPos(m_pClient->m_pCamera->m_Center.x, m_pClient->m_pCamera->m_Center.y); @@ -84,10 +89,10 @@ void CSounds::OnRender() int64 Now = time_get(); if(m_QueueWaitTime <= Now) { - Play(CHN_GLOBAL, m_aQueue[0], 1.0f, vec2(0,0)); + Play(m_aQueue[0].m_Channel, m_aQueue[0].m_SetId, 1.0f, vec2(0,0)); m_QueueWaitTime = Now+time_freq()*3/10; // wait 300ms before playing the next one if(--m_QueuePos > 0) - mem_move(m_aQueue, m_aQueue+1, m_QueuePos*sizeof(int)); + mem_move(m_aQueue, m_aQueue+1, m_QueuePos*sizeof(QueueEntry)); } } } @@ -99,11 +104,17 @@ void CSounds::ClearQueue() m_QueueWaitTime = time_get(); } -void CSounds::Enqueue(int SetId) +void CSounds::Enqueue(int Channel, int SetId) { // add sound to the queue - if(!g_Config.m_ClEditor && m_QueuePos < QUEUE_SIZE) - m_aQueue[m_QueuePos++] = SetId; + if(m_QueuePos < QUEUE_SIZE) + { + if(Channel == CHN_MUSIC || !g_Config.m_ClEditor) + { + m_aQueue[m_QueuePos].m_Channel = Channel; + m_aQueue[m_QueuePos++].m_SetId = SetId; + } + } } void CSounds::PlayAndRecord(int Chn, int SetId, float Vol, vec2 Pos) @@ -117,17 +128,21 @@ void CSounds::PlayAndRecord(int Chn, int SetId, float Vol, vec2 Pos) void CSounds::Play(int Chn, int SetId, float Vol, vec2 Pos) { - if(m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds) + if(!g_Config.m_SndEnable || (Chn == CHN_MUSIC && !g_Config.m_SndMusic) || m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds) return; SOUNDSET *pSet = &g_pData->m_aSounds[SetId]; if(!pSet->m_NumSounds) return; + + int Flags = 0; + if(Chn == CHN_MUSIC) + Flags = ISound::FLAG_LOOP; if(pSet->m_NumSounds == 1) { - Sound()->PlayAt(Chn, pSet->m_aSounds[0].m_Id, 0, Pos.x, Pos.y); + Sound()->PlayAt(Chn, pSet->m_aSounds[0].m_Id, Flags, Pos.x, Pos.y); return; } @@ -138,6 +153,17 @@ void CSounds::Play(int Chn, int SetId, float Vol, vec2 Pos) Id = rand() % pSet->m_NumSounds; } while(Id == pSet->m_Last); - Sound()->PlayAt(Chn, pSet->m_aSounds[Id].m_Id, 0, Pos.x, Pos.y); + Sound()->PlayAt(Chn, pSet->m_aSounds[Id].m_Id, Flags, Pos.x, Pos.y); pSet->m_Last = Id; } + +void CSounds::Stop(int SetId) +{ + if(m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds) + return; + + SOUNDSET *pSet = &g_pData->m_aSounds[SetId]; + + for(int i = 0; i < pSet->m_NumSounds; i++) + Sound()->Stop(pSet->m_aSounds[i].m_Id); +} diff --git a/src/game/client/components/sounds.h b/src/game/client/components/sounds.h index 0e7824428..ca8cfd775 100644 --- a/src/game/client/components/sounds.h +++ b/src/game/client/components/sounds.h @@ -10,7 +10,11 @@ class CSounds : public CComponent { QUEUE_SIZE = 32, }; - int m_aQueue[QUEUE_SIZE]; + struct QueueEntry + { + int m_Channel; + int m_SetId; + } m_aQueue[QUEUE_SIZE]; int m_QueuePos; int64 m_QueueWaitTime; class CJob m_SoundJob; @@ -31,9 +35,10 @@ public: virtual void OnRender(); void ClearQueue(); - void Enqueue(int SetId); + void Enqueue(int Channel, int SetId); void Play(int Channel, int SetId, float Vol, vec2 Pos); void PlayAndRecord(int Channel, int SetId, float Vol, vec2 Pos); + void Stop(int SetId); }; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 28fdb31e6..1a35895ec 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -551,7 +551,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) if(pMsg->m_SoundID == SOUND_CTF_DROP || pMsg->m_SoundID == SOUND_CTF_RETURN || pMsg->m_SoundID == SOUND_CTF_CAPTURE || pMsg->m_SoundID == SOUND_CTF_GRAB_EN || pMsg->m_SoundID == SOUND_CTF_GRAB_PL) - g_GameClient.m_pSounds->Enqueue(pMsg->m_SoundID); + g_GameClient.m_pSounds->Enqueue(CSounds::CHN_GLOBAL, pMsg->m_SoundID); else g_GameClient.m_pSounds->Play(CSounds::CHN_GLOBAL, pMsg->m_SoundID, 1.0f, vec2(0,0)); } From aeec62266b2f23a16b54dfe58b113efcd7adc83d Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 13 Apr 2011 20:19:37 +0200 Subject: [PATCH 06/12] added Danish translation by SnOrKilll --- data/languages/danish.txt | 673 ++++++++++++++++++++++++++++++++++++++ data/languages/index.txt | 3 + 2 files changed, 676 insertions(+) create mode 100644 data/languages/danish.txt diff --git a/data/languages/danish.txt b/data/languages/danish.txt new file mode 100644 index 000000000..bd2225fde --- /dev/null +++ b/data/languages/danish.txt @@ -0,0 +1,673 @@ + +##### translated strings ##### + +%d Bytes +== %d Bytes + +%d of %d servers, %d players +== %d af %d servere, %d spillere + +%d%% loaded +== %d%% indlæst + +%ds left +== %d sekunder tilbage + +%i minute left +== %i minut tilbage + +%i minutes left +== %i minutter tilbage + +%i second left +== %i sekund tilbage + +%i seconds left +== %i sekunder tilbage + +%s wins! +== %s vinder! + +-Page %d- +== -Side %d- + +Abort +== Afbryd + +Add +== Tilføj + +Add Friend +== Tilføj ven + +Address +== Adresse + +All +== Alle + +Alpha +== Alpha + +Always show name plates +== Vis altid navneskilte + +Are you sure that you want to delete the demo? +== Er du sikker på at du vil slette denne demo? + +Are you sure that you want to quit? +== Er du sikker på at du vil afslutte? + +Are you sure that you want to remove the player from your friends list? +== Er du sikker på at du vil fjerne denne spiller fra din venneliste? + +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. +== Siden dette er første gang du starter spillet, så vær så venlig at skrive dit navn nedenunder. Det anbefales at du kigger på indstillingerne så du kan tilpasse dem inden du kobler dig på en server. + +Automatically record demos +== Optag automatisk demoer + +Automatically take game over screenshot +== Tag automatisk et game over screenshot + +Blue team +== Blå hold + +Blue team wins! +== Blåt hold vinder! + +Body +== Krop + +Call vote +== Lav afstemning + +Change settings +== Ændre indstillinger + +Chat +== Chat + +Clan +== Klan + +Client +== Klient + +Close +== Luk + +Compatible version +== Kompatibel version + +Connect +== Tilslut + +Connecting to +== Forbinder til + +Connection Problems... +== Forbindelsesproblemer... + +Console +== Konsol + +Controls +== Taster + +Count players only +== Tæl kun spillere + +Country +== Land + +Crc: +== Crc: + +Created: +== Lavet: + +Current +== Nuværende + +Current version: %s +== Nuværende version: %s + +Custom colors +== Brugerdefinerede farver + +Delete +== Slet + +Delete demo +== Slet demo + +Demo details +== Demoinformation + +Demos +== Demoer + +Disconnect +== Frakoble + +Disconnected +== Frakoblet + +Display Modes +== Skærmopløsning + +Downloading map +== Downloader bane + +Draw! +== Uafgjort! + +Dynamic Camera +== Dynamisk kamera + +Emoticon +== Humørikoner + +Enter +== Fortsæt + +Error +== Fejl + +Error loading demo +== Kunne ikke ikke indlæse demoen + +FSAA samples +== FSAA samples + +Favorite +== Favorit + +Favorites +== Favoritter + +Feet +== Fødder + +Filter +== Filter + +Fire +== Skyd + +Folder +== Mappe + +Force vote +== Tving afstemning + +Free-View +== Free-View + +Friends +== Venner + +Fullscreen +== Fuldskærm + +Game +== Spil + +Game info +== Spil info + +Game over +== Game over + +Game type +== Spiltype + +Game types: +== Spiltyper: + +General +== Generelt + +Graphics +== Grafik + +Grenade +== Granatkaster + +Hammer +== Hammer + +Has people playing +== Har folk som spiller + +High Detail +== Extra detaljer + +Hook +== Krog + +Host address +== Værtsadresse + +Hue +== Farve + +Info +== Info + +Internet +== Internet + +Invalid Demo +== Ugyldig demo + +Join blue +== Spil for blå + +Join game +== Start spil + +Join red +== Spil for rød + +Jump +== Hop + +Kick player +== Udsmid spiller + +LAN +== LAN + +Language +== Sprog + +Length: +== Længde + +Lht. +== Lys + +Loading +== Indlæser + +MOTD +== MOTD + +Map +== Kort + +Map: +== Bane + +Max Screenshots +== Max antal screenshots + +Max demos +== Max antal demoer + +Maximum ping: +== Højeste ping: + +Miscellaneous +== Diverse + +Mouse sens. +== Musfølsomhed + +Move left +== Gå til venstre + +Move player to spectators +== Flyt spilleren til tilskuerne + +Move right +== Gå til højre + +Movement +== Bevægelse + +Mute when not active +== Ingen lyd når du ikke er aktiv + +Name +== Navn + +Name plates size +== Størrelse på navneskilte + +Netversion: +== Netversion: + +New name: +== Nyt navn: + +News +== Nyheder + +Next weapon +== Næste våben + +Nickname +== Navn + +No +== Nej + +No password +== Ingen adgangskode + +No servers found +== Ingen servere fundet + +No servers match your filter criteria +== Ingen servere matcher din filterkriterier + +Ok +== Ok + +Open +== Åben + +Parent Folder +== Overmappe + +Password +== Adgangskode + +Password incorrect +== Forkert adgangskode + +Ping +== Ping + +Pistol +== Pistol + +Play +== Spil + +Player +== Spiller + +Player options +== Spillermuligheder + +Players +== Spillere + +Please balance teams! +== Venligst balancerer hold! + +Prev. weapon +== Foregående våben + +Quality Textures +== Kvalitetsteksturer + +Quick search: +== Hurtig søg: + +Quit +== Afslut + +Quit anyway? +== Afslut alligevel? + +REC %3d:%02d +== REC %3d:%02d + +Reason: +== Grund: + +Record demo +== Optag demo + +Red team +== Rødt hold + +Red team wins! +== Rødt hold vinder! + +Refresh +== Opdater + +Refreshing master servers +== Opdaterer masterservere + +Remote console +== Serverkonsol + +Remove +== Fjern + +Remove friend +== Fjern ven + +Rename +== Omdøb navn + +Rename demo +== Omdøb navn på demoen + +Reset filter +== Nulstil filter + +Reset to defaults +== Sæt til standard + +Rifle +== Laser + +Round +== Runde + +Sample rate +== Sample frekvens + +Sat. +== Mætning + +Score +== Score + +Score board +== Resultatliste + +Score limit +== Score grænse + +Scoreboard +== Resultatliste + +Screenshot +== Screenshot + +Server address: +== Serveradresse + +Server details +== Serverdetaljer + +Server filter +== Serverfilter + +Server info +== Serverinfo + +Server not full +== Ikke fuld server + +Settings +== Indstillinger + +Shotgun +== Haglgevær + +Show chat +== Vis chat + +Show friends +== Vis venner + +Show ingame HUD +== Vis HUD i spillet + +Show name plates +== Vis navneskilte + +Show only supported +== Vis kun understøttede + +Size: +== Størrelse: + +Skins +== Udseende + +Sound +== Lyd + +Sound error +== Lyd fejl + +Sound volume +== Lydstyrke + +Spectate +== Kig på + +Spectator mode +== Tilskuer mode + +Spectators +== Tilskuer + +Standard gametype +== Standard spilletype + +Standard map +== Standard + +Stop record +== Stop optagelse + +Sudden Death +== Sudden Death + +Switch weapon on pickup +== Byt våben ved anskafning + +Team +== Hold + +Team chat +== Holdchat + +Teeworlds %s is out! Download it at www.teeworlds.com! +== Teeworld %s er ude nu! Download den på www.teeworlds.com! + +Texture Compression +== Teksturkompression + +The audio device couldn't be initialised. +== Lydenheden kunne ikke startes + +The server is running a non-standard tuning on a pure game type. +== Denne server kører på en ikke-standard tuning på en ren spilletype. + +There's an unsaved map in the editor, you might want to save it before you quit the game. +== Der er en ikke-gemt bane i editoren, vil du gemme den før du afslutter? + +Time limit +== Tidsbegrænsning + +Time limit: %d min +== Tidsbegrænsning: %d min + +Try again +== Forsøg igen + +Type +== Type + +Type: +== Type: + +UI Color +== Brugergrænsefladefarve + +Unable to delete the demo +== Kunne ikke slette demoen + +Unable to rename the demo +== Kunne omdøbe demoen + +Use sounds +== Anvend lydeffekter + +Use team colors for name plates +== Anvend holdfarver til navneskilte + +V-Sync +== V-Sync + +Version +== Version + +Version: +== Version: + +Vote command: +== Afstemningsordre: + +Vote description: +== Afstemningsbeskrivelse: + +Vote no +== Stem nej + +Vote yes +== Stem ja + +Voting +== Afstemning + +Warmup +== Opvarmning + +Weapon +== Våben + +Welcome to Teeworlds +== Velkommen til Teeworlds + +Yes +== Ja + +You must restart the game for all settings to take effect. +== Du skal genstarte spillet før alle indstillingerne virker. + +Your skin +== Dit udseende + +no limit +== Ingen grænse + +##### needs translation ##### + +Play background music +== + +Spectate next +== + +Spectate previous +== + +##### old translations ##### + +##### translated strings ##### +== + diff --git a/data/languages/index.txt b/data/languages/index.txt index 337088a45..fbdae862b 100644 --- a/data/languages/index.txt +++ b/data/languages/index.txt @@ -10,6 +10,9 @@ bulgarian czech == Česky +danish +== Dansk + dutch == Nederlands From e6f0318bdfa49bde503742c856c8415f9b2c8018 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 13 Apr 2011 20:22:10 +0200 Subject: [PATCH 07/12] added "fixed some header guards and added a script to fix them all!" by Choupom --- scripts/check_header_guards.py | 35 ++++++++++++++++++++++++++++ src/base/detect.h | 4 ++-- src/base/tl/algorithm.h | 4 ++-- src/base/tl/allocator.h | 4 ++-- src/base/tl/array.h | 4 ++-- src/base/tl/base.h | 4 ++-- src/base/tl/range.h | 4 ++-- src/base/tl/sorted_array.h | 4 ++-- src/base/tl/string.h | 4 ++-- src/engine/shared/config.h | 4 ++-- src/engine/shared/config_variables.h | 6 ++--- 11 files changed, 56 insertions(+), 21 deletions(-) create mode 100644 scripts/check_header_guards.py diff --git a/scripts/check_header_guards.py b/scripts/check_header_guards.py new file mode 100644 index 000000000..bece10e9c --- /dev/null +++ b/scripts/check_header_guards.py @@ -0,0 +1,35 @@ +import os + + +PATH = "../src/" + + +def check_file(filename): + file = open(filename) + while 1: + line = file.readline() + if len(line) == 0: + break + if line[0] == "/" or line[0] == "*" or line[0] == "\r" or line[0] == "\n" or line[0] == "\t": + continue + if line[:7] == "#ifndef": + hg = "#ifndef " + ("_".join(filename.split(PATH)[1].split("/"))[:-2]).upper() + "_H" + if line[:-1] != hg: + print "Wrong header guard in " + filename + else: + print "Missing header guard in " + filename + break + file.close() + + + +def check_dir(dir): + list = os.listdir(dir) + for file in list: + if os.path.isdir(dir+file): + if file != "external" and file != "generated": + check_dir(dir+file+"/") + elif file[-2:] == ".h" and file != "keynames.h": + check_file(dir+file) + +check_dir(PATH) diff --git a/src/base/detect.h b/src/base/detect.h index ca2efb9cd..534339ddf 100644 --- a/src/base/detect.h +++ b/src/base/detect.h @@ -1,7 +1,7 @@ /* (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 BASELIB_FILE_CONFIG_H -#define BASELIB_FILE_CONFIG_H +#ifndef BASE_DETECT_H +#define BASE_DETECT_H /* this file detected the family, platform and architecture diff --git a/src/base/tl/algorithm.h b/src/base/tl/algorithm.h index 4a165db09..c5cd74c39 100644 --- a/src/base/tl/algorithm.h +++ b/src/base/tl/algorithm.h @@ -1,7 +1,7 @@ /* (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 TL_FILE_ALGORITHM_HPP -#define TL_FILE_ALGORITHM_HPP +#ifndef BASE_TL_ALGORITHM_H +#define BASE_TL_ALGORITHM_H #include "range.h" diff --git a/src/base/tl/allocator.h b/src/base/tl/allocator.h index f6d8fc34d..d12347e30 100644 --- a/src/base/tl/allocator.h +++ b/src/base/tl/allocator.h @@ -1,7 +1,7 @@ /* (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 TL_FILE_ALLOCATOR_HPP -#define TL_FILE_ALLOCATOR_HPP +#ifndef BASE_TL_ALLOCATOR_H +#define BASE_TL_ALLOCATOR_H template class allocator_default diff --git a/src/base/tl/array.h b/src/base/tl/array.h index 6aff3c714..0cee2afc7 100644 --- a/src/base/tl/array.h +++ b/src/base/tl/array.h @@ -1,7 +1,7 @@ /* (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 TL_FILE_ARRAY_HPP -#define TL_FILE_ARRAY_HPP +#ifndef BASE_TL_ARRAY_H +#define BASE_TL_ARRAY_H #include "range.h" #include "allocator.h" diff --git a/src/base/tl/base.h b/src/base/tl/base.h index 59951c68c..2fcb14eb8 100644 --- a/src/base/tl/base.h +++ b/src/base/tl/base.h @@ -1,7 +1,7 @@ /* (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 TL_FILE_BASE_HPP -#define TL_FILE_BASE_HPP +#ifndef BASE_TL_BASE_H +#define BASE_TL_BASE_H #include diff --git a/src/base/tl/range.h b/src/base/tl/range.h index 3c1c89f37..25047d31f 100644 --- a/src/base/tl/range.h +++ b/src/base/tl/range.h @@ -1,7 +1,7 @@ /* (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 TL_FILE_RANGE_HPP -#define TL_FILE_RANGE_HPP +#ifndef BASE_TL_RANGE_H +#define BASE_TL_RANGE_H #include "base.h" diff --git a/src/base/tl/sorted_array.h b/src/base/tl/sorted_array.h index 7c45cf286..94ccd5438 100644 --- a/src/base/tl/sorted_array.h +++ b/src/base/tl/sorted_array.h @@ -1,7 +1,7 @@ /* (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 TL_FILE_SORTED_ARRAY_HPP -#define TL_FILE_SORTED_ARRAY_HPP +#ifndef BASE_TL_SORTED_ARRAY_H +#define BASE_TL_SORTED_ARRAY_H #include "algorithm.h" #include "array.h" diff --git a/src/base/tl/string.h b/src/base/tl/string.h index 96c2dc66b..18fab4d41 100644 --- a/src/base/tl/string.h +++ b/src/base/tl/string.h @@ -1,7 +1,7 @@ /* (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 TL_FILE_STRING_HPP -#define TL_FILE_STRING_HPP +#ifndef BASE_TL_STRING_H +#define BASE_TL_STRING_H #include "base.h" #include "allocator.h" diff --git a/src/engine/shared/config.h b/src/engine/shared/config.h index 4720ddb39..9a524d22e 100644 --- a/src/engine/shared/config.h +++ b/src/engine/shared/config.h @@ -1,7 +1,7 @@ /* (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 ENGINE_SHARED_E_CONFIG_H -#define ENGINE_SHARED_E_CONFIG_H +#ifndef ENGINE_SHARED_CONFIG_H +#define ENGINE_SHARED_CONFIG_H struct CConfiguration { diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 857494052..8dec21028 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -1,8 +1,8 @@ /* (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 ENGINE_SHARED_E_CONFIG_VARIABLES_H -#define ENGINE_SHARED_E_CONFIG_VARIABLES_H -#undef ENGINE_SHARED_E_CONFIG_VARIABLES_H // this file will be included several times +#ifndef ENGINE_SHARED_CONFIG_VARIABLES_H +#define ENGINE_SHARED_CONFIG_VARIABLES_H +#undef ENGINE_SHARED_CONFIG_VARIABLES_H // this file will be included several times // TODO: remove this #include "././game/variables.h" From 63e059b8fff6498e42b765a1dca000e53005ea77 Mon Sep 17 00:00:00 2001 From: GreYFoX Date: Tue, 12 Apr 2011 19:23:20 +0200 Subject: [PATCH 08/12] Emoticons Enum has emoticons names instead of numbers --- datasrc/network.py | 52 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/datasrc/network.py b/datasrc/network.py index f84f0adb7..5876610a2 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -5,7 +5,7 @@ PlayerFlags = ["PLAYING", "IN_MENU", "CHATTING", "SCOREBOARD"] GameFlags = ["TEAMS", "FLAGS"] GameStateFlags = ["GAMEOVER", "SUDDENDEATH", "PAUSED"] -Emoticons = [str(x) for x in range(0,16)] +Emoticons = ["OOP", "EXCLAMATION", "HEARTS", "DROP", "DOTDOT", "MUSIC", "SORRY", "GHOST", "SUSHI", "SPLATTEE", "DEVILTEE", "ZOMG", "ZZZ", "WTF", "EYES", "QUESTION"] Powerups = ["HEALTH", "ARMOR", "WEAPON", "NINJA"] @@ -55,24 +55,24 @@ Objects = [ NetIntAny("m_Direction"), NetIntAny("m_TargetX"), NetIntAny("m_TargetY"), - + NetIntAny("m_Jump"), NetIntAny("m_Fire"), NetIntAny("m_Hook"), - + NetIntRange("m_PlayerFlags", 0, 256), - + NetIntAny("m_WantedWeapon"), NetIntAny("m_NextWeapon"), NetIntAny("m_PrevWeapon"), ]), - + NetObject("Projectile", [ NetIntAny("m_X"), NetIntAny("m_Y"), NetIntAny("m_VelX"), NetIntAny("m_VelY"), - + NetIntRange("m_Type", 0, 'NUM_WEAPONS-1'), NetTick("m_StartTick"), ]), @@ -82,14 +82,14 @@ Objects = [ NetIntAny("m_Y"), NetIntAny("m_FromX"), NetIntAny("m_FromY"), - + NetTick("m_StartTick"), ]), NetObject("Pickup", [ NetIntAny("m_X"), NetIntAny("m_Y"), - + NetIntRange("m_Type", 0, 'max_int'), NetIntRange("m_Subtype", 0, 'max_int'), ]), @@ -97,7 +97,7 @@ Objects = [ NetObject("Flag", [ NetIntAny("m_X"), NetIntAny("m_Y"), - + NetIntRange("m_Team", 'TEAM_RED', 'TEAM_BLUE') ]), @@ -106,10 +106,10 @@ Objects = [ NetIntRange("m_GameStateFlags", 0, 256), NetTick("m_RoundStartTick"), NetIntRange("m_WarmupTimer", 0, 'max_int'), - + NetIntRange("m_ScoreLimit", 0, 'max_int'), NetIntRange("m_TimeLimit", 0, 'max_int'), - + NetIntRange("m_RoundNum", 0, 'max_int'), NetIntRange("m_RoundCurrent", 0, 'max_int'), ]), @@ -131,7 +131,7 @@ Objects = [ NetIntAny("m_Angle"), NetIntRange("m_Direction", -1, 1), - + NetIntRange("m_Jumped", 0, 3), NetIntRange("m_HookedPlayer", 0, 'MAX_CLIENTS-1'), NetIntRange("m_HookState", -1, 5), @@ -152,7 +152,7 @@ Objects = [ NetIntRange("m_Emote", 0, len(Emotes)), NetIntRange("m_AttackTick", 0, 'max_int'), ]), - + NetObject("PlayerInfo", [ NetIntRange("m_Local", 0, 1), NetIntRange("m_ClientID", 0, 'MAX_CLIENTS-1'), @@ -177,7 +177,7 @@ Objects = [ NetIntAny("m_Skin3"), NetIntAny("m_Skin4"), NetIntAny("m_Skin5"), NetIntRange("m_UseCustomColor", 0, 1), - + NetIntAny("m_ColorBody"), NetIntAny("m_ColorFeet"), ]), @@ -187,23 +187,23 @@ Objects = [ NetIntAny("m_X"), NetIntAny("m_Y"), ]), - + ## Events - + NetEvent("Common", [ NetIntAny("m_X"), NetIntAny("m_Y"), ]), - + NetEvent("Explosion:Common", []), NetEvent("Spawn:Common", []), NetEvent("HammerHit:Common", []), - + NetEvent("Death:Common", [ NetIntRange("m_ClientID", 0, 'MAX_CLIENTS-1'), ]), - + NetEvent("SoundGlobal:Common", [ NetIntRange("m_SoundID", 0, 'NUM_SOUNDS-1'), ]), @@ -233,7 +233,7 @@ Messages = [ NetIntRange("m_ClientID", -1, 'MAX_CLIENTS-1'), NetString("m_pMessage"), ]), - + NetMessage("Sv_KillMsg", [ NetIntRange("m_Killer", 0, 'MAX_CLIENTS-1'), NetIntRange("m_Victim", 0, 'MAX_CLIENTS-1'), @@ -244,7 +244,7 @@ Messages = [ NetMessage("Sv_SoundGlobal", [ NetIntRange("m_SoundID", 0, 'NUM_SOUNDS-1'), ]), - + NetMessage("Sv_TuneParams", []), NetMessage("Sv_ExtraProjectile", []), NetMessage("Sv_ReadyToEnter", []), @@ -260,7 +260,7 @@ Messages = [ NetMessage("Sv_VoteClearOptions", [ ]), - + NetMessage("Sv_VoteOptionListAdd", [ NetIntRange("m_NumOptions", 1, 15), NetStringStrict("m_pDescription0"), NetStringStrict("m_pDescription1"), NetStringStrict("m_pDescription2"), @@ -290,7 +290,7 @@ Messages = [ NetIntRange("m_Pass", 0, 'MAX_CLIENTS'), NetIntRange("m_Total", 0, 'MAX_CLIENTS'), ]), - + ### Client messages NetMessage("Cl_Say", [ NetBool("m_Team"), @@ -304,7 +304,7 @@ Messages = [ NetMessage("Cl_SetSpectatorMode", [ NetIntRange("m_SpectatorID", 'SPEC_FREEVIEW', 'MAX_CLIENTS-1'), ]), - + NetMessage("Cl_StartInfo", [ NetStringStrict("m_pName"), NetStringStrict("m_pClan"), @@ -313,7 +313,7 @@ Messages = [ NetBool("m_UseCustomColor"), NetIntAny("m_ColorBody"), NetIntAny("m_ColorFeet"), - ]), + ]), NetMessage("Cl_ChangeInfo", [ NetStringStrict("m_pName"), @@ -334,7 +334,7 @@ Messages = [ NetMessage("Cl_Vote", [ NetIntRange("m_Vote", -1, 1), ]), - + NetMessage("Cl_CallVote", [ NetStringStrict("m_Type"), NetStringStrict("m_Value"), From 06115dd49dca2f8eb5f14606437e8fd20037cc4d Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 13 Apr 2011 20:37:12 +0200 Subject: [PATCH 09/12] added "Whitespace and line Endings cleanup" by GreYFoX --- bam.lua | 44 +- configure.lua | 88 ++-- datasrc/compile.py | 52 +-- datasrc/content.py | 40 +- datasrc/datatypes.py | 30 +- src/base/detect.h | 4 +- src/base/system.c | 108 ++--- src/base/system.h | 248 +++++------ src/base/tl/algorithm.h | 14 +- src/base/tl/array.h | 44 +- src/base/tl/range.h | 46 +- src/base/tl/sorted_array.h | 8 +- src/base/tl/string.h | 20 +- src/base/vmath.h | 16 +- src/engine/client.h | 30 +- src/engine/client/client.cpp | 14 +- src/engine/client/friends.h | 8 +- src/engine/client/graphics.cpp | 140 +++--- src/engine/client/graphics.h | 26 +- src/engine/client/input.cpp | 2 +- src/engine/client/serverbrowser.cpp | 8 +- src/engine/client/serverbrowser.h | 2 +- src/engine/client/text.cpp | 160 +++---- src/engine/config.h | 4 +- src/engine/console.h | 12 +- src/engine/friends.h | 6 +- src/engine/graphics.h | 32 +- src/engine/input.h | 10 +- src/engine/kernel.h | 6 +- src/engine/server.h | 16 +- src/engine/server/register.cpp | 26 +- src/engine/server/server.cpp | 258 +++++------ src/engine/server/server.h | 46 +- src/engine/serverbrowser.h | 16 +- src/engine/shared/compression.cpp | 24 +- src/engine/shared/config.cpp | 40 +- src/engine/shared/config.h | 12 +- src/engine/shared/config_variables.h | 2 +- src/engine/shared/console.cpp | 102 ++--- src/engine/shared/console.h | 22 +- src/engine/shared/datafile.cpp | 114 ++--- src/engine/shared/datafile.h | 14 +- src/engine/shared/demo.cpp | 156 +++---- src/engine/shared/demo.h | 30 +- src/engine/shared/engine.cpp | 6 +- src/engine/shared/huffman.cpp | 14 +- src/engine/shared/huffman.h | 8 +- src/engine/shared/jobs.cpp | 14 +- src/engine/shared/jobs.h | 16 +- src/engine/shared/kernel.cpp | 20 +- src/engine/shared/map.cpp | 8 +- src/engine/shared/mapchecker.cpp | 2 +- src/engine/shared/mapchecker.h | 2 +- src/engine/shared/masterserver.cpp | 30 +- src/engine/shared/memheap.cpp | 14 +- src/engine/shared/memheap.h | 10 +- src/engine/shared/network.cpp | 26 +- src/engine/shared/network.h | 78 ++-- src/engine/shared/network_client.cpp | 8 +- src/engine/shared/network_conn.cpp | 50 +-- src/engine/shared/network_server.cpp | 82 ++-- src/engine/shared/packer.cpp | 20 +- src/engine/shared/packer.h | 2 +- src/engine/shared/protocol.h | 18 +- src/engine/shared/ringbuffer.cpp | 44 +- src/engine/shared/ringbuffer.h | 16 +- src/engine/shared/snapshot.cpp | 124 +++--- src/engine/shared/snapshot.h | 14 +- src/engine/shared/storage.cpp | 34 +- src/engine/storage.h | 2 +- src/engine/textrender.h | 10 +- src/game/client/animstate.cpp | 4 +- src/game/client/animstate.h | 2 +- src/game/client/component.h | 4 +- src/game/client/components/binds.cpp | 40 +- src/game/client/components/binds.h | 12 +- src/game/client/components/broadcast.cpp | 4 +- src/game/client/components/camera.cpp | 4 +- src/game/client/components/chat.cpp | 24 +- src/game/client/components/chat.h | 16 +- src/game/client/components/console.cpp | 102 ++--- src/game/client/components/console.h | 20 +- src/game/client/components/controls.cpp | 58 +-- src/game/client/components/controls.h | 6 +- src/game/client/components/countryflags.cpp | 8 +- src/game/client/components/countryflags.h | 8 +- src/game/client/components/damageind.h | 2 +- src/game/client/components/debughud.cpp | 24 +- src/game/client/components/debughud.h | 2 +- src/game/client/components/effects.cpp | 34 +- src/game/client/components/effects.h | 2 +- src/game/client/components/emoticon.cpp | 18 +- src/game/client/components/emoticon.h | 8 +- src/game/client/components/flow.cpp | 20 +- src/game/client/components/flow.h | 4 +- src/game/client/components/hud.cpp | 30 +- src/game/client/components/hud.h | 8 +- src/game/client/components/items.cpp | 44 +- src/game/client/components/items.h | 10 +- src/game/client/components/killmessages.cpp | 20 +- src/game/client/components/killmessages.h | 2 +- src/game/client/components/mapimages.cpp | 6 +- src/game/client/components/mapimages.h | 4 +- src/game/client/components/maplayers.cpp | 58 +-- src/game/client/components/maplayers.h | 2 +- src/game/client/components/menus.cpp | 218 +++++----- src/game/client/components/menus.h | 54 +-- src/game/client/components/menus_browser.cpp | 62 +-- src/game/client/components/menus_demo.cpp | 102 ++--- src/game/client/components/menus_ingame.cpp | 74 ++-- src/game/client/components/menus_settings.cpp | 20 +- src/game/client/components/motd.cpp | 8 +- src/game/client/components/motd.h | 2 +- src/game/client/components/nameplates.cpp | 12 +- src/game/client/components/particles.cpp | 38 +- src/game/client/components/particles.h | 16 +- src/game/client/components/players.cpp | 48 +-- src/game/client/components/players.h | 6 +- src/game/client/components/scoreboard.cpp | 40 +- src/game/client/components/scoreboard.h | 6 +- src/game/client/components/skins.cpp | 24 +- src/game/client/components/skins.h | 6 +- src/game/client/components/sounds.cpp | 6 +- src/game/client/components/sounds.h | 2 +- src/game/client/components/spectator.cpp | 20 +- src/game/client/components/spectator.h | 6 +- src/game/client/components/voting.cpp | 26 +- src/game/client/components/voting.h | 16 +- src/game/client/gameclient.cpp | 154 +++---- src/game/client/gameclient.h | 66 +-- src/game/client/lineinput.cpp | 12 +- src/game/client/render.cpp | 34 +- src/game/client/render.h | 14 +- src/game/client/render_map.cpp | 62 +-- src/game/client/ui.cpp | 322 +++++++------- src/game/client/ui.h | 18 +- src/game/collision.cpp | 36 +- src/game/editor/ed_editor.h | 154 +++---- src/game/editor/ed_io.cpp | 130 +++--- src/game/editor/ed_layer_quads.cpp | 40 +- src/game/editor/ed_layer_tiles.cpp | 64 +-- src/game/editor/ed_popups.cpp | 94 ++-- src/game/gamecore.cpp | 70 +-- src/game/gamecore.h | 24 +- src/game/layers.cpp | 8 +- src/game/layers.h | 2 +- src/game/localization.cpp | 14 +- src/game/localization.h | 8 +- src/game/mapitems.h | 30 +- src/game/server/entities/character.cpp | 158 +++---- src/game/server/entities/character.h | 44 +- src/game/server/entities/flag.cpp | 2 +- src/game/server/entities/flag.h | 4 +- src/game/server/entities/laser.cpp | 18 +- src/game/server/entities/laser.h | 6 +- src/game/server/entities/pickup.cpp | 8 +- src/game/server/entities/pickup.h | 4 +- src/game/server/entities/projectile.cpp | 14 +- src/game/server/entities/projectile.h | 2 +- src/game/server/entity.cpp | 10 +- src/game/server/entity.h | 28 +- src/game/server/eventhandler.h | 8 +- src/game/server/gamecontext.cpp | 146 +++---- src/game/server/gamecontext.h | 26 +- src/game/server/gamecontroller.cpp | 104 ++--- src/game/server/gamecontroller.h | 52 +-- src/game/server/gamemodes/ctf.cpp | 34 +- src/game/server/gamemodes/ctf.h | 4 +- src/game/server/gamemodes/mod.cpp | 4 +- src/game/server/gamemodes/tdm.cpp | 6 +- src/game/server/gamemodes/tdm.h | 2 +- src/game/server/gameworld.cpp | 14 +- src/game/server/gameworld.h | 40 +- src/game/server/player.cpp | 20 +- src/game/server/player.h | 26 +- src/mastersrv/mastersrv.cpp | 50 +-- src/osxlaunch/client.h | 8 +- src/osxlaunch/client.m | 406 +++++++++--------- src/osxlaunch/server.m | 28 +- src/tools/crapnet.cpp | 40 +- src/tools/dilate.cpp | 20 +- src/tools/fake_server.cpp | 26 +- src/tools/map_resave.cpp | 2 +- src/tools/map_version.cpp | 6 +- src/tools/packetgen.cpp | 4 +- src/tools/tileset_borderfix.cpp | 22 +- src/versionsrv/versionsrv.cpp | 26 +- 187 files changed, 3486 insertions(+), 3486 deletions(-) diff --git a/bam.lua b/bam.lua index 0c953e849..0c7c2f782 100644 --- a/bam.lua +++ b/bam.lua @@ -23,17 +23,17 @@ end function CHash(output, ...) local inputs = TableFlatten({...}) - + output = Path(output) - + -- compile all the files local cmd = Script("scripts/cmd5.py") .. " " for index, inname in ipairs(inputs) do - cmd = cmd .. Path(inname) .. " " + cmd = cmd .. Path(inname) .. " " end - + cmd = cmd .. " > " .. output - + AddJob(output, "cmd5 " .. output, cmd) for index, inname in ipairs(inputs) do AddDependency(output, inname) @@ -73,7 +73,7 @@ function Dat2c(datafile, sourcefile, arrayname) AddJob( sourcefile, "dat2c " .. PathFilename(sourcefile) .. " = " .. PathFilename(datafile), - Script("scripts/dat2c.py").. "\" " .. sourcefile .. " " .. datafile .. " " .. arrayname + Script("scripts/dat2c.py").. "\" " .. sourcefile .. " " .. datafile .. " " .. arrayname ) AddDependency(sourcefile, datafile) return sourcefile @@ -85,7 +85,7 @@ function ContentCompile(action, output) output, action .. " > " .. output, --Script("datasrc/compile.py") .. "\" ".. Path(output) .. " " .. action - Script("datasrc/compile.py") .. " " .. action .. " > " .. Path(output) + Script("datasrc/compile.py") .. " " .. action .. " > " .. Path(output) ) AddDependency(output, Path("datasrc/content.py")) -- do this more proper AddDependency(output, Path("datasrc/network.py")) @@ -150,7 +150,7 @@ function build(settings) settings.cc.includes:Add("src") if family == "unix" then - if platform == "macosx" then + if platform == "macosx" then settings.link.frameworks:Add("Carbon") settings.link.frameworks:Add("AppKit") else @@ -163,7 +163,7 @@ function build(settings) settings.link.libs:Add("ole32") settings.link.libs:Add("shell32") end - + -- compile zlib if needed if config.zlib.value == 1 then settings.link.libs:Add("z") @@ -179,7 +179,7 @@ function build(settings) -- build the small libraries wavpack = Compile(settings, Collect("src/engine/external/wavpack/*.c")) pnglite = Compile(settings, Collect("src/engine/external/pnglite/*.c")) - + -- build game components engine_settings = settings:Copy() server_settings = engine_settings:Copy() @@ -187,18 +187,18 @@ function build(settings) launcher_settings = engine_settings:Copy() if family == "unix" then - if platform == "macosx" then + if platform == "macosx" then client_settings.link.frameworks:Add("OpenGL") - client_settings.link.frameworks:Add("AGL") - client_settings.link.frameworks:Add("Carbon") - client_settings.link.frameworks:Add("Cocoa") - launcher_settings.link.frameworks:Add("Cocoa") + client_settings.link.frameworks:Add("AGL") + client_settings.link.frameworks:Add("Carbon") + client_settings.link.frameworks:Add("Cocoa") + launcher_settings.link.frameworks:Add("Cocoa") else client_settings.link.libs:Add("X11") client_settings.link.libs:Add("GL") client_settings.link.libs:Add("GLU") end - + elseif family == "windows" then client_settings.link.libs:Add("opengl32") client_settings.link.libs:Add("glu32") @@ -209,11 +209,11 @@ function build(settings) config.sdl:Apply(client_settings) -- apply freetype settings config.freetype:Apply(client_settings) - + engine = Compile(engine_settings, Collect("src/engine/shared/*.cpp", "src/base/*.c")) client = Compile(client_settings, Collect("src/engine/client/*.cpp")) server = Compile(server_settings, Collect("src/engine/server/*.cpp")) - + versionserver = Compile(settings, Collect("src/versionsrv/*.cpp")) masterserver = Compile(settings, Collect("src/mastersrv/*.cpp")) game_shared = Compile(settings, Collect("src/game/*.cpp"), nethash, network_source) @@ -230,13 +230,13 @@ function build(settings) client_osxlaunch = Compile(client_settings, "src/osxlaunch/client.m") server_osxlaunch = Compile(launcher_settings, "src/osxlaunch/server.m") end - + tools = {} for i,v in ipairs(tools_src) do toolname = PathFilename(PathBase(v)) tools[i] = Link(settings, toolname, Compile(settings, v), engine, zlib, pnglite) end - + -- build client, server, version server and master server client_exe = Link(client_settings, "teeworlds", game_shared, game_client, engine, client, game_editor, zlib, pnglite, wavpack, @@ -249,7 +249,7 @@ function build(settings) if platform == "macosx" then serverlaunch = Link(launcher_settings, "serverlaunch", server_osxlaunch) end - + versionserver_exe = Link(server_settings, "versionsrv", versionserver, engine, zlib) @@ -284,7 +284,7 @@ release_settings.debug = 0 release_settings.optimize = 1 release_settings.cc.defines:Add("CONF_RELEASE") -if platform == "macosx" and arch == "ia32" then +if platform == "macosx" and arch == "ia32" then debug_settings_ppc = debug_settings:Copy() debug_settings_ppc.config_name = "debug_ppc" debug_settings_ppc.config_ext = "_ppc_d" diff --git a/configure.lua b/configure.lua index b96c629d5..26825b06f 100644 --- a/configure.lua +++ b/configure.lua @@ -10,12 +10,12 @@ function NewConfig(on_configured_callback) config.OnConfigured = function(self) return true end - + if on_configured_callback then config.OnConfigured = on_configured_callback end - + config.options = {} config.settings = NewSettings() - + config.NewSettings = function(self) local s = NewSettings() for _,v in pairs(self.options) do @@ -28,25 +28,25 @@ function NewConfig(on_configured_callback) table.insert(self.options, o) self[o.name] = o end - + config.Print = function(self) for k,v in pairs(self.options) do print(v:FormatDisplay()) end end - + config.Save = function(self, filename) print("saved configuration to '"..filename.."'") local file = io.open(filename, "w") - + -- Define a little helper function to save options local saver = {} saver.file = file - + saver.line = function(self, str) self.file:write(str .. "\n") end - + saver.option = function(self, option, name) local valuestr = "no" if type(option[name]) == type(0) then @@ -64,30 +64,30 @@ function NewConfig(on_configured_callback) self.file:write(option.name.."."..name.." = ".. valuestr.."\n") end - -- Save all the options + -- Save all the options for k,v in pairs(self.options) do v:Save(saver) end file:close() end - + config.Load = function(self, filename) local options_func = loadfile(filename) local options_table = {} - + if not options_func then print("auto configuration") self:Config(filename) options_func = loadfile(filename) end - + if options_func then -- Setup the options tables for k,v in pairs(self.options) do options_table[v.name] = {} end setfenv(options_func, options_table) - + -- this is to make sure that we get nice error messages when -- someone sets an option that isn't valid. local mt = {} @@ -96,8 +96,8 @@ function NewConfig(on_configured_callback) if v ~= nil then return v end error("there is no configuration option named '" .. key .. "'") end - - setmetatable(options_table, mt) + + setmetatable(options_table, mt) -- Process the options options_func() @@ -117,10 +117,10 @@ function NewConfig(on_configured_callback) print("run 'bam config' to generate") print("run 'bam config help' for configuration options") print("") - os.exit(1) + os.exit(1) end end - + config.Config = function(self, filename) print("") print("configuration:") @@ -140,7 +140,7 @@ function NewConfig(on_configured_callback) end print("") end - + end config.Autodetect = function(self) @@ -159,7 +159,7 @@ function NewConfig(on_configured_callback) end end end - + config.Finalize = function(self, filename) if _bam_targets[0] == "config" then if _bam_targets[1] == "help" then @@ -171,11 +171,11 @@ function NewConfig(on_configured_callback) os.exit(0) end - + self:Load(filename) bam_update_globalstamp(filename) end - + return config end @@ -214,10 +214,10 @@ function MakeOption(name, value, check, save, display, printhelp) o.auto_detected = true o.FormatDisplay = function(self) local a = "SET" - if self.auto_detected then a = "AUTO" end + if self.auto_detected then a = "AUTO" end return string.format("%-5s %-20s %s", a, self.name, self:Display()) end - + o.Display = display o.PrintHelp = printhelp if o.Display == nil then o.Display = DefaultOptionDisplay end @@ -244,16 +244,16 @@ function OptTestCompileC(name, source, compileoptions, desc) end end end - + local save = function(option, output) output:option(option, "value") end - + local printhelp = function(option) print("\t"..option.name.."=on|off") if option.desc then print("\t\t"..option.desc) end end - + local o = MakeOption(name, false, check, save, nil, printhelp) o.desc = desc o.source = source @@ -275,16 +275,16 @@ function OptToggle(name, default_value, desc) end end end - + local save = function(option, output) output:option(option, "value") end - + local printhelp = function(option) print("\t"..option.name.."=on|off") if option.desc then print("\t\t"..option.desc) end end - + local o = MakeOption(name, default_value, check, save, nil, printhelp) o.desc = desc return o @@ -297,16 +297,16 @@ function OptInteger(name, default_value, desc) option.value = tonumber(ScriptArgs[option.name]) end end - + local save = function(option, output) output:option(option, "value") end - + local printhelp = function(option) print("\t"..option.name.."=N") if option.desc then print("\t\t"..option.desc) end end - + local o = MakeOption(name, default_value, check, save, nil, printhelp) o.desc = desc return o @@ -320,16 +320,16 @@ function OptString(name, default_value, desc) option.value = ScriptArgs[option.name] end end - + local save = function(option, output) output:option(option, "value") end - + local printhelp = function(option) print("\t"..option.name.."=STRING") if option.desc then print("\t\t"..option.desc) end end - + local o = MakeOption(name, default_value, check, save, nil, printhelp) o.desc = desc return o @@ -354,7 +354,7 @@ function OptCCompiler(name, default_driver, default_c, default_cxx, desc) if ScriptArgs[option.name..".cxx"] then option.cxx_compiler = ScriptArgs[option.name..".cxx"] end - + option.auto_detected = false elseif option.driver then -- no need todo anything if we have a driver @@ -379,11 +379,11 @@ function OptCCompiler(name, default_driver, default_c, default_cxx, desc) else error(option.driver.." is not a known c/c++ compile driver") end - + if option.c_compiler then settings.cc.c_compiler = option.c_compiler end if option.cxx_compiler then settings.cc.cxx_compiler = option.cxx_compiler end end - + local save = function(option, output) output:option(option, "driver") output:option(option, "c_compiler") @@ -407,7 +407,7 @@ function OptCCompiler(name, default_driver, default_c, default_cxx, desc) if option.cxx_compiler then s = s .. " cxx="..option.cxx_compiler end return s end - + local o = MakeOption(name, nil, check, save, display, printhelp) o.desc = desc o.driver = false @@ -430,7 +430,7 @@ function OptLibrary(name, header, desc) local check = function(option, settings) option.value = false option.include_path = false - + local function check_compile_include(filename, paths) if CTestCompile(settings, "#include <" .. filename .. ">\nint main(){return 0;}", "") then return "" @@ -441,7 +441,7 @@ function OptLibrary(name, header, desc) return v end end - + return false end @@ -468,12 +468,12 @@ function OptLibrary(name, header, desc) end end end - + local save = function(option, output) output:option(option, "value") output:option(option, "include_path") end - + local display = function(option) if option.value then if option.include_path then @@ -490,7 +490,7 @@ function OptLibrary(name, header, desc) print("\t"..option.name.."=disable|system|PATH") if option.desc then print("\t\t"..option.desc) end end - + local o = MakeOption(name, false, check, save, display, printhelp) o.include_path = false o.header = header diff --git a/datasrc/compile.py b/datasrc/compile.py index 0ae3bbc72..e8901c480 100644 --- a/datasrc/compile.py +++ b/datasrc/compile.py @@ -21,7 +21,7 @@ def create_flags_table(names): i += 1 lines += ["};"] return lines - + def EmitEnum(names, num): print("enum") print("{") @@ -92,11 +92,11 @@ if gen_client_content_source or gen_server_content_source: # NETWORK if gen_network_header: - + print("#ifndef GAME_GENERATED_PROTOCOL_H") print("#define GAME_GENERATED_PROTOCOL_H") print(network.RawHeader) - + for e in network.Enums: for l in create_enum_table(["%s_%s"%(e.name, v) for v in e.values], 'NUM_%sS'%e.name): print(l) print("") @@ -104,17 +104,17 @@ if gen_network_header: for e in network.Flags: for l in create_flags_table(["%s_%s" % (e.name, v) for v in e.values]): print(l) print("") - + for l in create_enum_table(["NETOBJ_INVALID"]+[o.enum_name for o in network.Objects], "NUM_NETOBJTYPES"): print(l) print("") for l in create_enum_table(["NETMSG_INVALID"]+[o.enum_name for o in network.Messages], "NUM_NETMSGTYPES"): print(l) print("") - + for item in network.Objects + network.Messages: for line in item.emit_declaration(): print(line) print("") - + EmitEnum(["SOUND_%s"%i.name.value.upper() for i in content.container.sounds.items], "NUM_SOUNDS") EmitEnum(["WEAPON_%s"%i.name.value.upper() for i in content.container.weapons.id.items], "NUM_WEAPONS") @@ -127,11 +127,11 @@ class CNetObjHandler char m_aMsgData[1024]; int m_NumObjCorrections; int ClampInt(const char *pErrorMsg, int Value, int Min, int Max); - + static const char *ms_apObjNames[]; static int ms_aObjSizes[]; static const char *ms_apMsgNames[]; - + public: CNetObjHandler(); @@ -140,7 +140,7 @@ public: int GetObjSize(int Type); int NumObjCorrections(); const char *CorrectedObjOn(); - + const char *GetMsgName(int Type); void *SecureUnpackMsg(int Type, CUnpacker *pUnpacker); const char *FailedMsgOn(); @@ -149,16 +149,16 @@ public: """) print("#endif // GAME_GENERATED_PROTOCOL_H") - + if gen_network_source: # create names lines = [] - + lines += ['#include '] lines += ['#include '] lines += ['#include "protocol.h"'] - + lines += ['CNetObjHandler::CNetObjHandler()'] lines += ['{'] lines += ['\tm_pMsgFailedOn = "";'] @@ -202,7 +202,7 @@ if gen_network_source: lines += ['\t""'] lines += ['};'] lines += [''] - + lines += ['const char *CNetObjHandler::GetObjName(int Type)'] lines += ['{'] lines += ['\tif(Type < 0 || Type >= NUM_NETOBJTYPES) return "(out of range)";'] @@ -216,16 +216,16 @@ if gen_network_source: lines += ['\treturn ms_aObjSizes[Type];'] lines += ['};'] lines += [''] - - + + lines += ['const char *CNetObjHandler::GetMsgName(int Type)'] lines += ['{'] lines += ['\tif(Type < 0 || Type >= NUM_NETMSGTYPES) return "(out of range)";'] lines += ['\treturn ms_apMsgNames[Type];'] lines += ['};'] lines += [''] - - + + for l in lines: print(l) @@ -255,7 +255,7 @@ if gen_network_source: lines += ['{'] lines += ['\tswitch(Type)'] lines += ['\t{'] - + for item in network.Objects: for line in item.emit_validate(): lines += ["\t" + line] @@ -264,9 +264,9 @@ if gen_network_source: lines += ['\treturn -1;'] lines += ['};'] lines += [''] - - #int Validate(int Type, void *pData, int Size); - + + #int Validate(int Type, void *pData, int Size); + if 0: for item in network.Messages: for line in item.emit_unpack(): @@ -281,20 +281,20 @@ if gen_network_source: lines += ['\tsecure_unpack_%s,' % msg.name] lines += ['\t0x0'] lines += ['};'] - + # lines += ['void *CNetObjHandler::SecureUnpackMsg(int Type, CUnpacker *pUnpacker)'] lines += ['{'] lines += ['\tm_pMsgFailedOn = 0;'] lines += ['\tswitch(Type)'] lines += ['\t{'] - - + + for item in network.Messages: for line in item.emit_unpack(): lines += ["\t" + line] lines += ['\t'] - + lines += ['\tdefault:'] lines += ['\t\tm_pMsgFailedOn = "(type out of range)";'] lines += ['\t\tbreak;'] @@ -313,6 +313,6 @@ if gen_network_source: for l in lines: print(l) - + if gen_client_content_header or gen_server_content_header: print("#endif") diff --git a/datasrc/content.py b/datasrc/content.py index 1dfa7aea5..e714e8b8b 100644 --- a/datasrc/content.py +++ b/datasrc/content.py @@ -22,7 +22,7 @@ class Image(Struct): self.name = String(name) self.filename = String(filename) self.id = Int(-1) - + class SpriteSet(Struct): def __init__(self, name="", image=None, gridx=0, gridy=0): Struct.__init__(self, "SPRITESET") @@ -78,7 +78,7 @@ class WeaponSpec(Struct): self.sprite_proj = Pointer(Sprite, Sprite()) self.sprite_muzzles = Array(Pointer(Sprite, Sprite())) self.visual_size = Int(96) - + self.firedelay = Int(500) self.maxammo = Int(10) self.ammoregentime = Int(0) @@ -111,7 +111,7 @@ class Weapon_Gun(Struct): self.curvature = Float(1.25) self.speed = Float(2200) self.lifetime = Float(2.0) - + class Weapon_Shotgun(Struct): def __init__(self): Struct.__init__(self, "WEAPONSPEC_SHOTGUN") @@ -119,7 +119,7 @@ class Weapon_Shotgun(Struct): self.curvature = Float(1.25) self.speed = Float(2200) self.speeddiff = Float(0.8) - self.lifetime = Float(0.25) + self.lifetime = Float(0.25) class Weapon_Grenade(Struct): def __init__(self): @@ -137,7 +137,7 @@ class Weapon_Rifle(Struct): self.bounce_delay = Int(150) self.bounce_num = Int(1) self.bounce_cost = Float(0) - + class Weapon_Ninja(Struct): def __init__(self): Struct.__init__(self, "WEAPONSPEC_NINJA") @@ -190,7 +190,7 @@ container.sounds.Add(SoundSet("player_pain_long", FileList("audio/vo_teefault_pa container.sounds.Add(SoundSet("body_land", FileList("audio/foley_land-%02d.wv", 4))) container.sounds.Add(SoundSet("player_airjump", FileList("audio/foley_dbljump-%02d.wv", 3))) -container.sounds.Add(SoundSet("player_jump", FileList("audio/foley_foot_left-%02d.wv", 4) + FileList("audio/foley_foot_right-%02d.wv", 4))) +container.sounds.Add(SoundSet("player_jump", FileList("audio/foley_foot_left-%02d.wv", 4) + FileList("audio/foley_foot_right-%02d.wv", 4))) container.sounds.Add(SoundSet("player_die", FileList("audio/foley_body_splat-%02d.wv", 3))) container.sounds.Add(SoundSet("player_spawn", FileList("audio/vo_teefault_spawn-%02d.wv", 7))) container.sounds.Add(SoundSet("player_skid", FileList("audio/sfx_skid-%02d.wv", 4))) @@ -292,7 +292,7 @@ container.sprites.Add(Sprite("armor_empty", set_game, 23,2,2,2)) container.sprites.Add(Sprite("star1", set_game, 15,0,2,2)) container.sprites.Add(Sprite("star2", set_game, 17,0,2,2)) container.sprites.Add(Sprite("star3", set_game, 19,0,2,2)) - + container.sprites.Add(Sprite("part1", set_game, 6,0,1,1)) container.sprites.Add(Sprite("part2", set_game, 6,1,1,1)) container.sprites.Add(Sprite("part3", set_game, 7,0,1,1)) @@ -425,35 +425,35 @@ anim.body.frames.Add(AnimKeyframe(0.6, 0, 0, 0)) anim.body.frames.Add(AnimKeyframe(0.8, 0,-1, 0)) anim.body.frames.Add(AnimKeyframe(1.0, 0, 0, 0)) -anim.back_foot.frames.Add(AnimKeyframe(0.0, 8, 0, 0)) +anim.back_foot.frames.Add(AnimKeyframe(0.0, 8, 0, 0)) anim.back_foot.frames.Add(AnimKeyframe(0.2, -8, 0, 0)) anim.back_foot.frames.Add(AnimKeyframe(0.4,-10,-4, 0.2)) anim.back_foot.frames.Add(AnimKeyframe(0.6, -8,-8, 0.3)) -anim.back_foot.frames.Add(AnimKeyframe(0.8, 4,-4,-0.2)) -anim.back_foot.frames.Add(AnimKeyframe(1.0, 8, 0, 0)) +anim.back_foot.frames.Add(AnimKeyframe(0.8, 4,-4,-0.2)) +anim.back_foot.frames.Add(AnimKeyframe(1.0, 8, 0, 0)) anim.front_foot.frames.Add(AnimKeyframe(0.0,-10,-4, 0.2)) anim.front_foot.frames.Add(AnimKeyframe(0.2, -8,-8, 0.3)) -anim.front_foot.frames.Add(AnimKeyframe(0.4, 4,-4,-0.2)) -anim.front_foot.frames.Add(AnimKeyframe(0.6, 8, 0, 0)) -anim.front_foot.frames.Add(AnimKeyframe(0.8, 8, 0, 0)) +anim.front_foot.frames.Add(AnimKeyframe(0.4, 4,-4,-0.2)) +anim.front_foot.frames.Add(AnimKeyframe(0.6, 8, 0, 0)) +anim.front_foot.frames.Add(AnimKeyframe(0.8, 8, 0, 0)) anim.front_foot.frames.Add(AnimKeyframe(1.0,-10,-4, 0.2)) container.animations.Add(anim) anim = Animation("hammer_swing") anim.attach.frames.Add(AnimKeyframe(0.0, 0, 0, -0.10)) -anim.attach.frames.Add(AnimKeyframe(0.3, 0, 0, 0.25)) -anim.attach.frames.Add(AnimKeyframe(0.4, 0, 0, 0.30)) -anim.attach.frames.Add(AnimKeyframe(0.5, 0, 0, 0.25)) +anim.attach.frames.Add(AnimKeyframe(0.3, 0, 0, 0.25)) +anim.attach.frames.Add(AnimKeyframe(0.4, 0, 0, 0.30)) +anim.attach.frames.Add(AnimKeyframe(0.5, 0, 0, 0.25)) anim.attach.frames.Add(AnimKeyframe(1.0, 0, 0, -0.10)) container.animations.Add(anim) - + anim = Animation("ninja_swing") anim.attach.frames.Add(AnimKeyframe(0.00, 0, 0, -0.25)) anim.attach.frames.Add(AnimKeyframe(0.10, 0, 0, -0.05)) -anim.attach.frames.Add(AnimKeyframe(0.15, 0, 0, 0.35)) -anim.attach.frames.Add(AnimKeyframe(0.42, 0, 0, 0.40)) -anim.attach.frames.Add(AnimKeyframe(0.50, 0, 0, 0.35)) +anim.attach.frames.Add(AnimKeyframe(0.15, 0, 0, 0.35)) +anim.attach.frames.Add(AnimKeyframe(0.42, 0, 0, 0.40)) +anim.attach.frames.Add(AnimKeyframe(0.50, 0, 0, 0.35)) anim.attach.frames.Add(AnimKeyframe(1.00, 0, 0, -0.25)) container.animations.Add(anim) diff --git a/datasrc/datatypes.py b/datasrc/datatypes.py index ddb3c9e32..73719f59b 100644 --- a/datasrc/datatypes.py +++ b/datasrc/datatypes.py @@ -21,7 +21,7 @@ def FixCasing(Str): else: NewStr += c.lower() return NewStr - + def FormatName(type, name): if "*" in type: return "m_p" + FixCasing(name) @@ -34,12 +34,12 @@ class BaseType: self._type_name = type_name self._target_name = "INVALID" self._id = GetID() # this is used to remember what order the members have in structures etc - + def Identifyer(self): return "x"+str(self._id) def TargetName(self): return self._target_name def TypeName(self): return self._type_name def ID(self): return self._id; - + def EmitDeclaration(self, name): return ["%s %s;"%(self.TypeName(), FormatName(self.TypeName(), name))] def EmitPreDefinition(self, target_name): @@ -52,7 +52,7 @@ class MemberType: def __init__(self, name, var): self.name = name self.var = var - + class Struct(BaseType): def __init__(self, type_name): BaseType.__init__(self, type_name) @@ -71,7 +71,7 @@ class Struct(BaseType): print(v.name, v.var) sys.exit(-1) return m - + def EmitTypeDeclaration(self, name): lines = [] lines += ["struct " + self.TypeName()] @@ -93,7 +93,7 @@ class Struct(BaseType): lines += ["\t" + " ".join(member.var.EmitDefinition("")) + ","] lines += ["}"] return lines - + class Array(BaseType): def __init__(self, type): BaseType.__init__(self, type.TypeName()) @@ -114,7 +114,7 @@ class Array(BaseType): for item in self.items: lines += item.EmitPreDefinition("%s[%d]"%(self.Identifyer(), i)) i += 1 - + if len(self.items): lines += ["static %s %s[] = {"%(self.TypeName(), self.Identifyer())] for item in self.items: @@ -123,7 +123,7 @@ class Array(BaseType): lines += ["};"] else: lines += ["static %s *%s = 0;"%(self.TypeName(), self.Identifyer())] - + return lines def EmitDefinition(self, name): return [str(len(self.items))+","+self.Identifyer()] @@ -139,7 +139,7 @@ class Int(BaseType): def EmitDefinition(self, name): return ["%d"%self.value] #return ["%d /* %s */"%(self.value, self._target_name)] - + class Float(BaseType): def __init__(self, value): BaseType.__init__(self, "float") @@ -149,7 +149,7 @@ class Float(BaseType): def EmitDefinition(self, name): return ["%f"%self.value] #return ["%d /* %s */"%(self.value, self._target_name)] - + class String(BaseType): def __init__(self, value): BaseType.__init__(self, "const char*") @@ -158,7 +158,7 @@ class String(BaseType): self.value = value def EmitDefinition(self, name): return ['"'+self.value+'"'] - + class Pointer(BaseType): def __init__(self, type, target): BaseType.__init__(self, "%s*"%type().TypeName()) @@ -227,7 +227,7 @@ class NetObject: lines += ["\treturn 0;"] lines += ["}"] return lines - + class NetEvent(NetObject): def __init__(self, name, variables): @@ -265,12 +265,12 @@ class NetMessage(NetObject): extra += ["\t\t"+line for line in v.emit_pack()] extra += ["\t\treturn pPacker->Error() != 0;"] extra += ["\t}"] - - + + lines = NetObject.emit_declaration(self) lines = lines[:-1] + extra + lines[-1:] return lines - + class NetVariable: def __init__(self, name): diff --git a/src/base/detect.h b/src/base/detect.h index 534339ddf..0b66acefc 100644 --- a/src/base/detect.h +++ b/src/base/detect.h @@ -4,8 +4,8 @@ #define BASE_DETECT_H /* - this file detected the family, platform and architecture - to compile for. + this file detected the family, platform and architecture + to compile for. */ /* platforms */ diff --git a/src/base/system.c b/src/base/system.c index 0c208b9b3..94481f212 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -21,20 +21,20 @@ #include #include #include - #include + #include #include #include #include #include #include - + #if defined(CONF_PLATFORM_MACOSX) #include #endif - + #elif defined(CONF_FAMILY_WINDOWS) - #define WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN #define _WIN32_WINNT 0x0501 /* required for mingw to get getaddrinfo to work */ #include #include @@ -176,7 +176,7 @@ void *mem_alloc_debug(const char *filename, int line, unsigned size, unsigned al memory_stats.allocated += header->size; memory_stats.total_allocations++; memory_stats.active_allocations++; - + tail->guard = MEM_GUARD_VAL; header->prev = (MEMHEADER *)0; @@ -184,7 +184,7 @@ void *mem_alloc_debug(const char *filename, int line, unsigned size, unsigned al if(first) first->prev = header; first = header; - + /*dbg_msg("mem", "++ %p", header+1); */ return header+1; } @@ -195,20 +195,20 @@ void mem_free(void *p) { MEMHEADER *header = (MEMHEADER *)p - 1; MEMTAIL *tail = (MEMTAIL *)(((char*)(header+1))+header->size); - + if(tail->guard != MEM_GUARD_VAL) dbg_msg("mem", "!! %p", p); /* dbg_msg("mem", "-- %p", p); */ memory_stats.allocated -= header->size; memory_stats.active_allocations--; - + if(header->prev) header->prev->next = header->next; else first = header->next; if(header->next) header->next->prev = header->prev; - + free(header); } } @@ -219,7 +219,7 @@ void mem_debug_dump(IOHANDLE file) MEMHEADER *header = first; if(!file) file = io_open("memory.txt", IOFLAG_WRITE); - + if(file) { while(header) @@ -228,7 +228,7 @@ void mem_debug_dump(IOHANDLE file) io_write(file, buf, strlen(buf)); header = header->next; } - + io_close(file); } } @@ -275,7 +275,7 @@ IOHANDLE io_open(const char *filename, int flags) WIN32_FIND_DATA finddata; HANDLE handle; int length; - + length = str_length(filename); if(!filename || !length || filename[length-1] == '\\') return 0x0; @@ -630,9 +630,9 @@ int net_host_lookup(const char *hostname, NETADDR *addr, int types) /* dbg_msg("host lookup", "host='%s' port=%d %d", host, port, types); */ - + mem_zero(&hints, sizeof(hints)); - + hints.ai_family = AF_UNSPEC; if(types == NETTYPE_IPV4) @@ -655,8 +655,8 @@ static int parse_int(int *out, const char **str) int i = 0; *out = 0; if(**str < '0' || **str > '9') - return -1; - + return -1; + i = **str - '0'; (*str)++; @@ -665,9 +665,9 @@ static int parse_int(int *out, const char **str) if(**str < '0' || **str > '9') { *out = i; - return 0; + return 0; } - + i = (i*10) + (**str - '0'); (*str)++; } @@ -704,7 +704,7 @@ int net_addr_from_str(NETADDR *addr, const char *string) { const char *str = string; mem_zero(addr, sizeof(NETADDR)); - + if(str[0] == '[') { /* ipv6 */ @@ -760,10 +760,10 @@ int net_addr_from_str(NETADDR *addr, const char *string) str++; if(parse_uint16(&addr->port, &str)) return -1; } - + addr->type = NETTYPE_IPV4; } - + return 0; } @@ -825,7 +825,7 @@ static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, i priv_net_close_socket(sock); return -1; } - + /* set non-blocking */ #if defined(CONF_FAMILY_WINDOWS) ioctlsocket(sock, FIONBIO, &mode); @@ -835,7 +835,7 @@ static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, i /* set boardcast */ setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast)); - + /* return the newly created socket */ return sock; } @@ -937,7 +937,7 @@ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size { char addrstr[256]; net_addr_str(addr, addrstr, sizeof(addrstr)); - + dbg_msg("net", "sendto error (%d '%s')", errno, strerror(errno)); dbg_msg("net", "\tsock = %d %x", sock, sock); dbg_msg("net", "\tsize = %d %x", size, size); @@ -1005,8 +1005,8 @@ NETSOCKET net_tcp_create(const NETADDR *a) bind(sock.ipv4sock, (struct sockaddr *)&addr, sizeof(addr)); } - /* return */ - return sock; + /* return */ + return sock; } int net_tcp_set_non_blocking(NETSOCKET sock) @@ -1122,7 +1122,7 @@ int net_tcp_connect_non_blocking(NETSOCKET sock, const NETADDR *a) /* netaddr_to_sockaddr(a, &addr); net_tcp_set_non_blocking(sock); - res = connect(sock, &addr, sizeof(addr)); + res = connect(sock, &addr, sizeof(addr)); net_tcp_set_blocking(sock); */ @@ -1206,7 +1206,7 @@ int fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user) if(!d) return 0; - + str_format(buffer, sizeof(buffer), "%s/", dir); length = str_length(buffer); @@ -1246,7 +1246,7 @@ int fs_storage_path(const char *appname, char *path, int max) for(i = strlen(home)+2; path[i]; i++) path[i] = tolower(path[i]); #endif - + return 0; #endif } @@ -1286,7 +1286,7 @@ int fs_is_dir(const char *path) struct stat sb; if (stat(path, &sb) == -1) return 0; - + if (S_ISDIR(sb.st_mode)) return 1; else @@ -1326,7 +1326,7 @@ int fs_parent_dir(char *path) if(*path == '/' || *path == '\\') parent = path; } - + if(parent) { *parent = 0; @@ -1377,16 +1377,16 @@ void swap_endian(void *data, unsigned elem_size, unsigned num) int net_socket_read_wait(NETSOCKET sock, int time) { - struct timeval tv; - fd_set readfds; + struct timeval tv; + fd_set readfds; int sockid; - tv.tv_sec = 0; - tv.tv_usec = 1000*time; + tv.tv_sec = 0; + tv.tv_usec = 1000*time; sockid = 0; - FD_ZERO(&readfds); - if(sock.ipv4sock >= 0) + FD_ZERO(&readfds); + if(sock.ipv4sock >= 0) { FD_SET(sock.ipv4sock, &readfds); sockid = sock.ipv4sock; @@ -1398,8 +1398,8 @@ int net_socket_read_wait(NETSOCKET sock, int time) sockid = sock.ipv6sock; } - /* don't care about writefds and exceptfds */ - select(sockid+1, &readfds, NULL, NULL, &tv); + /* don't care about writefds and exceptfds */ + select(sockid+1, &readfds, NULL, NULL, &tv); if(sock.ipv4sock >= 0 && FD_ISSET(sock.ipv4sock, &readfds)) return 1; @@ -1407,7 +1407,7 @@ int net_socket_read_wait(NETSOCKET sock, int time) if(sock.ipv6sock >= 0 && FD_ISSET(sock.ipv6sock, &readfds)) return 1; - return 0; + return 0; } unsigned time_timestamp() @@ -1427,7 +1427,7 @@ void str_append(char *dst, const char *src, int dst_size) s++; i++; } - + dst[dst_size-1] = 0; /* assure null termination */ } @@ -1448,12 +1448,12 @@ void str_format(char *buffer, int buffer_size, const char *format, ...) va_list ap; va_start(ap, format); _vsnprintf(buffer, buffer_size, format, ap); - va_end(ap); + va_end(ap); #else va_list ap; va_start(ap, format); vsnprintf(buffer, buffer_size, format, ap); - va_end(ap); + va_end(ap); #endif buffer[buffer_size-1] = 0; /* assure null termination */ @@ -1578,7 +1578,7 @@ const char *str_find_nocase(const char *haystack, const char *needle) return haystack; haystack++; } - + return 0; } @@ -1598,7 +1598,7 @@ const char *str_find(const char *haystack, const char *needle) return haystack; haystack++; } - + return 0; } @@ -1620,7 +1620,7 @@ void str_timestamp(char *buffer, int buffer_size) { time_t time_data; struct tm *time_info; - + time(&time_data); time_info = localtime(&time_data); strftime(buffer, buffer_size, "%Y-%m-%d_%H-%M-%S", time_info); @@ -1700,7 +1700,7 @@ float str_tofloat(const char *str) { return atof(str); } static int str_utf8_isstart(char c) { - if((c&0xC0) == 0x80) /* 10xxxxxx */ + if((c&0xC0) == 0x80) /* 10xxxxxx */ return 0; return 1; } @@ -1721,7 +1721,7 @@ int str_utf8_forward(const char *str, int cursor) const char *buf = str + cursor; if(!buf[0]) return cursor; - + if((*buf&0x80) == 0x0) /* 0xxxxxxx */ return cursor+1; else if((*buf&0xE0) == 0xC0) /* 110xxxxx */ @@ -1742,7 +1742,7 @@ int str_utf8_forward(const char *str, int cursor) if(!buf[3]) return cursor+3; return cursor+4; } - + /* invalid */ return cursor+1; } @@ -1776,7 +1776,7 @@ int str_utf8_encode(char *ptr, int chr) ptr[3] = 0x80|(chr&0x3F); return 4; } - + return 0; } @@ -1784,7 +1784,7 @@ int str_utf8_decode(const char **ptr) { const char *buf = *ptr; int ch = 0; - + do { if((*buf&0x80) == 0x0) /* 0xxxxxxx */ @@ -1819,7 +1819,7 @@ int str_utf8_decode(const char **ptr) buf++; break; } - + *ptr = buf; return ch; } while(0); @@ -1827,7 +1827,7 @@ int str_utf8_decode(const char **ptr) /* out of bounds */ *ptr = buf; return -1; - + } int str_utf8_check(const char *str) @@ -1835,7 +1835,7 @@ int str_utf8_check(const char *str) while(*str) { if((*str&0x80) == 0x0) - str++; + str++; else if((*str&0xE0) == 0xC0 && (*(str+1)&0xC0) == 0x80) str += 2; else if((*str&0xF0) == 0xE0 && (*(str+1)&0xC0) == 0x80 && (*(str+2)&0xC0) == 0x80) diff --git a/src/base/system.h b/src/base/system.h index fea9e4520..a486b89d7 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -18,28 +18,28 @@ extern "C" { /* Function: dbg_assert Breaks into the debugger based on a test. - + Parameters: test - Result of the test. msg - Message that should be printed if the test fails. - + Remarks: Does nothing in release version of the library. - + See Also: */ void dbg_assert(int test, const char *msg); -#define dbg_assert(test,msg) dbg_assert_imp(__FILE__, __LINE__, test, 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); /* Function: dbg_break Breaks into the debugger. - + Remarks: Does nothing in release version of the library. - + See Also: */ @@ -47,16 +47,16 @@ void dbg_break(); /* Function: dbg_msg - + Prints a debug message. - + Parameters: sys - A string that describes what system the message belongs to fmt - A printf styled format string. - + Remarks: Does nothing in release version of the library. - + See Also: */ @@ -67,15 +67,15 @@ void dbg_msg(const char *sys, const char *fmt, ...); /* Function: mem_alloc Allocates memory. - + Parameters: size - Size of the needed block. alignment - Alignment for the block. - + Returns: Returns a pointer to the newly allocated block. Returns a null pointer if the memory couldn't be allocated. - + Remarks: - Passing 0 to size will allocated the smallest amount possible and return a unique pointer. @@ -89,12 +89,12 @@ void *mem_alloc_debug(const char *filename, int line, unsigned size, unsigned al /* Function: mem_free Frees a block allocated through . - + Remarks: - In the debug version of the library the function will assert if a non-valid block is passed, like a null pointer or a block that isn't allocated. - + See Also: */ @@ -103,16 +103,16 @@ void mem_free(void *block); /* Function: mem_copy Copies a a memory block. - + Parameters: dest - Destination. source - Source to copy. size - Size of the block to copy. - + Remarks: - This functions DOES NOT handles cases where source and destination is overlapping. - + See Also: */ @@ -121,16 +121,16 @@ void mem_copy(void *dest, const void *source, unsigned size); /* Function: mem_move Copies a a memory block - + Parameters: dest - Destination source - Source to copy size - Size of the block to copy - + Remarks: - This functions handles cases where source and destination is overlapping - + See Also: */ @@ -139,7 +139,7 @@ void mem_move(void *dest, const void *source, unsigned size); /* Function: mem_zero Sets a complete memory block to 0 - + Parameters: block - Pointer to the block to zero out size - Size of the block @@ -149,12 +149,12 @@ void mem_zero(void *block, unsigned size); /* Function: mem_comp Compares two blocks of memory - + Parameters: a - First block of data b - Second block of data size - Size of the data to compare - + Returns: <0 - Block a is lesser then block b 0 - Block a is equal to block b @@ -168,7 +168,7 @@ int mem_comp(const void *a, const void *b, int size); Will trigger a assert if memory has failed. */ int mem_check_imp(); -#define mem_check() dbg_assert_imp(__FILE__, __LINE__, mem_check_imp(), "Memory check failed") +#define mem_check() dbg_assert_imp(__FILE__, __LINE__, mem_check_imp(), "Memory check failed") /* Group: File IO */ enum { @@ -205,7 +205,7 @@ IOHANDLE io_open(const char *filename, int flags); io - Handle to the file to read data from. buffer - Pointer to the buffer that will recive the data. size - Number of bytes to read from the file. - + Returns: Number of bytes read. @@ -215,11 +215,11 @@ unsigned io_read(IOHANDLE io, void *buffer, unsigned size); /* Function: io_skip Skips data in a file. - + Parameters: io - Handle to the file. size - Number of bytes to skip. - + Returns: Number of bytes skipped. */ @@ -228,12 +228,12 @@ unsigned io_skip(IOHANDLE io, int size); /* Function: io_write Writes data from a buffer to file. - + Parameters: io - Handle to the file. buffer - Pointer to the data that should be written. size - Number of bytes to write. - + Returns: Number of bytes written. */ @@ -242,12 +242,12 @@ unsigned io_write(IOHANDLE io, const void *buffer, unsigned size); /* Function: io_seek Seeks to a specified offset in the file. - + Parameters: io - Handle to the file. offset - Offset from pos to stop. origin - Position to start searching from. - + Returns: Returns 0 on success. */ @@ -256,10 +256,10 @@ int io_seek(IOHANDLE io, int offset, int origin); /* Function: io_tell Gets the current position in the file. - + Parameters: io - Handle to the file. - + Returns: Returns the current position. -1L if an error occured. */ @@ -268,10 +268,10 @@ long int io_tell(IOHANDLE io); /* Function: io_length Gets the total length of the file. Resetting cursor to the beginning - + Parameters: io - Handle to the file. - + Returns: Returns the total size. -1L if an error occured. */ @@ -280,10 +280,10 @@ long int io_length(IOHANDLE io); /* Function: io_close Closes a file. - + Parameters: io - Handle to the file. - + Returns: Returns 0 on success. */ @@ -292,10 +292,10 @@ int io_close(IOHANDLE io); /* Function: io_flush Empties all buffers and writes all pending data. - + Parameters: io - Handle to the file. - + Returns: Returns 0 on success. */ @@ -326,7 +326,7 @@ IOHANDLE io_stderr(); /* Function: thread_sleep Suspends the current thread for a given period. - + Parameters: milliseconds - Number of milliseconds to sleep. */ @@ -335,18 +335,18 @@ void thread_sleep(int milliseconds); /* Function: thread_create Creates a new thread. - + Parameters: threadfunc - Entry point for the new thread. user - Pointer to pass to the thread. - + */ void *thread_create(void (*threadfunc)(void *), void *user); /* Function: thread_wait Waits for a thread to be done or destroyed. - + Parameters: thread - Thread to wait for. */ @@ -355,7 +355,7 @@ void thread_wait(void *thread); /* Function: thread_destroy Destroys a thread. - + Parameters: thread - Thread to destroy. */ @@ -390,7 +390,7 @@ typedef long long int64; /* Function: time_get Fetches a sample from a high resolution timer. - + Returns: Current value of the timer. @@ -402,7 +402,7 @@ int64 time_get(); /* Function: time_freq Returns the frequency of the high resolution timer. - + Returns: Returns the frequency of the high resolution timer. */ @@ -411,7 +411,7 @@ int64 time_freq(); /* Function: time_timestamp Retrives the current time as a UNIX timestamp - + Returns: The time as a UNIX timestamp */ @@ -428,7 +428,7 @@ typedef struct enum { NETADDR_MAXSTRSIZE = 1+(8*4+7)+1+1+5+1, // [XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX]:XXXXX - + NETTYPE_INVALID = 0, NETTYPE_IPV4 = 1, NETTYPE_IPV6 = 2, @@ -446,10 +446,10 @@ typedef struct /* Function: net_init Initiates network functionallity. - + Returns: Returns 0 on success, - + Remarks: You must call this function before using any other network functions. @@ -469,11 +469,11 @@ int net_host_lookup(const char *hostname, NETADDR *addr, int types); /* Function: net_addr_comp Compares two network addresses. - + Parameters: a - Address to compare b - Address to compare to. - + Returns: <0 - Address a is lesser then address b 0 - Address a is equal to address b @@ -484,12 +484,12 @@ int net_addr_comp(const NETADDR *a, const NETADDR *b); /* Function: net_addr_str Turns a network address into a representive string. - + Parameters: addr - Address to turn into a string. string - Buffer to fill with the string. max_length - Maximum size of the string. - + Remarks: - The string will always be zero terminated @@ -499,10 +499,10 @@ void net_addr_str(const NETADDR *addr, char *string, int max_length); /* Function: net_addr_from_str Turns string into a network address. - + Returns: 0 on success - + Parameters: addr - Address to fill in. string - String to parse. @@ -517,7 +517,7 @@ int net_addr_from_str(NETADDR *addr, const char *string); Parameters: bindaddr - Address to bind the socket to. - + Returns: On success it returns an handle to the socket. On failure it returns NETSOCKET_INVALID. @@ -533,7 +533,7 @@ NETSOCKET net_udp_create(NETADDR bindaddr); addr - Where to send the packet. data - Pointer to the packet data to send. size - Size of the packet. - + Returns: On success it returns the number of bytes sent. Returns -1 on error. @@ -549,7 +549,7 @@ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size addr - Pointer to an NETADDR that will recive the address. data - Pointer to a buffer that will recive the data. maxsize - Maximum size to recive. - + Returns: On success it returns the number of bytes recived. Returns -1 on error. @@ -562,7 +562,7 @@ int net_udp_recv(NETSOCKET sock, NETADDR *addr, void *data, int maxsize); Parameters: sock - Socket to close. - + Returns: Returns 0 on success. -1 on error. */ @@ -574,7 +574,7 @@ int net_udp_close(NETSOCKET sock); /* Function: net_tcp_create Creates a TCP socket. - + Parameters: bindaddr - Address to bind the socket to. @@ -586,11 +586,11 @@ NETSOCKET net_tcp_create(const NETADDR *a); /* Function: net_tcp_listen Makes the socket start listening for new connections. - + Parameters: sock - Socket to start listen to. backlog - Size of the queue of incomming connections to keep. - + Returns: Returns 0 on success. */ @@ -599,12 +599,12 @@ int net_tcp_listen(NETSOCKET sock, int backlog); /* Function: net_tcp_accept Polls a listning socket for a new connection. - + Parameters: sock - Listning socket to poll. new_sock - Pointer to a socket to fill in with the new socket. addr - Pointer to an address that will be filled in the remote address (optional, can be NULL). - + Returns: Returns a non-negative integer on success. Negative integer on failure. */ @@ -613,26 +613,26 @@ int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *addr); /* Function: net_tcp_connect Connects one socket to another. - + Parameters: sock - Socket to connect. addr - Address to connect to. Returns: Returns 0 on success. - + */ int net_tcp_connect(NETSOCKET sock, const NETADDR *addr); /* Function: net_tcp_send Sends data to a TCP stream. - + Parameters: sock - Socket to send data to. data - Pointer to the data to send. size - Size of the data to send. - + Returns: Number of bytes sent. Negative value on failure. */ @@ -641,12 +641,12 @@ int net_tcp_send(NETSOCKET sock, const void *data, int size); /* Function: net_tcp_recv Recvives data from a TCP stream. - + Parameters: sock - Socket to recvive data from. data - Pointer to a buffer to write the data to max_size - Maximum of data to write to the buffer. - + Returns: Number of bytes recvived. Negative value on failure. When in non-blocking mode, it returns 0 when there is no more data to @@ -657,10 +657,10 @@ int net_tcp_recv(NETSOCKET sock, void *data, int maxsize); /* Function: net_tcp_close Closes a TCP socket. - + Parameters: sock - Socket to close. - + Returns: Returns 0 on success. Negative value on failure. */ @@ -671,12 +671,12 @@ int net_tcp_close(NETSOCKET sock); /* Function: str_append Appends a string to another. - + Parameters: dst - Pointer to a buffer that contains a string. src - String to append. dst_size - Size of the buffer of the dst string. - + Remarks: - The strings are treated as zero-termineted strings. - Garantees that dst string will contain zero-termination. @@ -686,7 +686,7 @@ void str_append(char *dst, const char *src, int dst_size); /* Function: str_copy Copies a string to another. - + Parameters: dst - Pointer to a buffer that shall recive the string. src - String to be copied. @@ -701,10 +701,10 @@ void str_copy(char *dst, const char *src, int dst_size); /* Function: str_length Returns the length of a zero terminated string. - + Parameters: str - Pointer to the string. - + Returns: Length of string in bytes excluding the zero termination. */ @@ -713,7 +713,7 @@ int str_length(const char *str); /* Function: str_format Performs printf formating into a buffer. - + Parameters: buffer - Pointer to the buffer to recive the formated string. buffer_size - Size of the buffer. @@ -730,7 +730,7 @@ void str_format(char *buffer, int buffer_size, const char *format, ...); /* Function: str_sanitize_strong Replaces all characters below 32 and above 127 with whitespace. - + Parameters: str - String to sanitize. @@ -742,7 +742,7 @@ void str_sanitize_strong(char *str); /* Function: str_sanitize_cc Replaces all characters below 32 with whitespace. - + Parameters: str - String to sanitize. @@ -755,7 +755,7 @@ void str_sanitize_cc(char *str); Function: str_sanitize Replaces all characters below 32 with whitespace with exception to \t, \n and \r. - + Parameters: str - String to sanitize. @@ -767,7 +767,7 @@ void str_sanitize(char *str); /* Function: str_skip_to_whitespace Skips leading non-whitespace characters(all but ' ', '\t', '\n', '\r'). - + Parameters: str - Pointer to the string. @@ -783,7 +783,7 @@ char *str_skip_to_whitespace(char *str); /* Function: str_skip_whitespaces Skips leading whitespace characters(' ', '\t', '\n', '\r'). - + Parameters: str - Pointer to the string. @@ -799,12 +799,12 @@ char *str_skip_whitespaces(char *str); /* Function: str_comp_nocase Compares to strings case insensitive. - + Parameters: a - String to compare. b - String to compare. - - Returns: + + Returns: <0 - String a is lesser then string b 0 - String a is equal to string b >0 - String a is greater then string b @@ -819,12 +819,12 @@ int str_comp_nocase(const char *a, const char *b); /* Function: str_comp Compares to strings case sensitive. - + Parameters: a - String to compare. b - String to compare. - - Returns: + + Returns: <0 - String a is lesser then string b 0 - String a is equal to string b >0 - String a is greater then string b @@ -837,13 +837,13 @@ int str_comp(const char *a, const char *b); /* Function: str_comp_num Compares up to num characters of two strings case sensitive. - + Parameters: a - String to compare. b - String to compare. num - Maximum characters to compare - - Returns: + + Returns: <0 - String a is lesser then string b 0 - String a is equal to string b >0 - String a is greater then string b @@ -856,12 +856,12 @@ int str_comp_num(const char *a, const char *b, const int num); /* Function: str_comp_filenames Compares two strings case sensitive, digit chars will be compared as numbers. - + Parameters: a - String to compare. b - String to compare. - - Returns: + + Returns: <0 - String a is lesser then string b 0 - String a is equal to string b >0 - String a is greater then string b @@ -878,7 +878,7 @@ int str_comp_filenames(const char *a, const char *b); Parameters: haystack - String to search in needle - String to search for - + Returns: A pointer into haystack where the needle was found. Returns NULL of needle could not be found. @@ -896,7 +896,7 @@ const char *str_find_nocase(const char *haystack, const char *needle); Parameters: haystack - String to search in needle - String to search for - + Returns: A pointer into haystack where the needle was found. Returns NULL of needle could not be found. @@ -939,13 +939,13 @@ void str_timestamp(char *buffer, int buffer_size); /* Function: fs_listdir Lists the files in a directory - + Parameters: dir - Directory to list cb - Callback function to call for each entry type - Type of the directory user - Pointer to give to the callback - + Returns: Always returns 0. */ @@ -955,13 +955,13 @@ int fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user); /* Function: fs_makedir Creates a directory - + Parameters: path - Directory to create - + Returns: Returns 0 on success. Negative value on failure. - + Remarks: Does not create several directories if needed. "a/b/c" will result in a failure if b or a does not exist. @@ -971,10 +971,10 @@ int fs_makedir(const char *path); /* Function: fs_storage_path Fetches per user configuration directory. - + Returns: Returns 0 on success. Negative value on failure. - + Remarks: - Returns ~/.appname on UNIX based systems - Returns ~/Library/Applications Support/appname on Mac OS X @@ -985,7 +985,7 @@ int fs_storage_path(const char *appname, char *path, int max); /* Function: fs_is_dir Checks if directory exists - + Returns: Returns 1 on success, 0 on failure. */ @@ -994,7 +994,7 @@ int fs_is_dir(const char *path); /* Function: fs_chdir Changes current working directory - + Returns: Returns 0 on success, 1 on failure. */ @@ -1003,7 +1003,7 @@ int fs_chdir(const char *path); /* Function: fs_getcwd Gets the current working directory. - + Returns: Returns a pointer to the buffer on success, 0 on failure. */ @@ -1012,7 +1012,7 @@ char *fs_getcwd(char *buffer, int buffer_size); /* Function: fs_parent_dir Get the parent directory of a directory - + Parameters: path - The directory string @@ -1027,7 +1027,7 @@ int fs_parent_dir(char *path); /* Function: fs_remove Deletes the file with the specified name. - + Parameters: filename - The file to delete @@ -1042,7 +1042,7 @@ int fs_remove(const char *filename); /* Function: fs_rename Renames the file or directory. If the paths differ the file will be moved. - + Parameters: oldname - The actual name newname - The new name @@ -1062,7 +1062,7 @@ int fs_rename(const char *oldname, const char *newname); /* Function: net_tcp_connect_non_blocking - + DOCTODO: serp */ int net_tcp_connect_non_blocking(NETSOCKET sock, const NETADDR *a); @@ -1121,7 +1121,7 @@ enum { #define DBG_LEVEL_LOW DBG_LEVEL_IMPORTANT #define DBG_LEVEL_HIGH DBG_LEVEL_INFO -typedef void (*DBG_LOGGER)(const char *line); +typedef void (*DBG_LOGGER)(const char *line); void dbg_logger(DBG_LOGGER logger); void dbg_logger_stdout(); @@ -1157,7 +1157,7 @@ unsigned str_quickhash(const char *str); /* Function: gui_messagebox Display plain OS-dependent message box - + Parameters: title - title of the message box message - text to display @@ -1168,7 +1168,7 @@ void gui_messagebox(const char *title, const char *message); /* Function: str_utf8_rewind Moves a cursor backwards in an utf8 string - + Parameters: str - utf8 string cursor - position in the string @@ -1184,11 +1184,11 @@ int str_utf8_rewind(const char *str, int cursor); /* Function: str_utf8_forward Moves a cursor forwards in an utf8 string - + Parameters: str - utf8 string cursor - position in the string - + Returns: New cursor position. @@ -1200,10 +1200,10 @@ int str_utf8_forward(const char *str, int cursor); /* Function: str_utf8_decode Decodes an utf8 character - + Parameters: ptr - pointer to an utf8 string. this pointer will be moved forward - + Returns: Unicode value for the character. -1 for invalid characters and 0 for end of string. @@ -1215,10 +1215,10 @@ int str_utf8_decode(const char **ptr); /* Function: str_utf8_encode Encode an utf8 character - + Parameters: ptr - Pointer to a buffer that should recive the data. Should be able to hold at least 4 bytes. - + Returns: Number of bytes put into the buffer. @@ -1230,10 +1230,10 @@ int str_utf8_encode(char *ptr, int chr); /* Function: str_utf8_check Checks if a strings contains just valid utf8 characters. - + Parameters: str - Pointer to a possible utf8 string. - + Returns: 0 - invalid characters found. 1 - only valid characters found. diff --git a/src/base/tl/algorithm.h b/src/base/tl/algorithm.h index c5cd74c39..6b2e542a9 100644 --- a/src/base/tl/algorithm.h +++ b/src/base/tl/algorithm.h @@ -8,7 +8,7 @@ /* insert 4 - v + v 1 2 3 4 5 6 */ @@ -38,12 +38,12 @@ R partition_binary(R range, T value) concept_size::check(range); concept_slice::check(range); concept_sorted::check(range); - + if(range.empty()) return range; if(range.back() < value) return R(); - + while(range.size() > 1) { unsigned pivot = (range.size()-1)/2; @@ -82,7 +82,7 @@ void sort_bubble(R range) concept_empty::check(range); concept_forwarditeration::check(range); concept_backwarditeration::check(range); - + // slow bubblesort :/ for(; !range.empty(); range.pop_back()) { @@ -119,18 +119,18 @@ bool sort_verify(R range) { concept_empty::check(range); concept_forwarditeration::check(range); - + typename R::type *prev = &range.front(); range.pop_front(); for(; !range.empty(); range.pop_front()) { typename R::type *cur = &range.front(); - + if(*cur < *prev) return false; prev = cur; } - + return true; } diff --git a/src/base/tl/array.h b/src/base/tl/array.h index 0cee2afc7..4f4b2fc31 100644 --- a/src/base/tl/array.h +++ b/src/base/tl/array.h @@ -10,10 +10,10 @@ /* Class: array Normal dynamic array class - + Remarks: - Grows 50% each time it needs to fit new items - - Use set_size() if you know how many elements + - Use set_size() if you know how many elements - Use optimize() to reduce the needed space. */ template > @@ -24,7 +24,7 @@ class array : private ALLOCATOR list = 0x0; clear(); } - + public: typedef plain_range range; @@ -35,7 +35,7 @@ public: { init(); } - + /* Function: array copy constructor */ @@ -60,7 +60,7 @@ public: /* Function: delete_all - + Remarks: - Invalidates ranges */ @@ -74,7 +74,7 @@ public: /* Function: clear - + Remarks: - Invalidates ranges */ @@ -124,7 +124,7 @@ public: /* Function: remove_index - + Remarks: - Invalidates ranges */ @@ -132,7 +132,7 @@ public: { for(int i = index+1; i < num_elements; i++) list[i-1] = list[i]; - + set_size(size()-1); } @@ -156,10 +156,10 @@ public: /* Function: add Adds an item to the array. - + Arguments: item - Item to add. - + Remarks: - Invalidates ranges - See remarks about how the array grows. @@ -175,9 +175,9 @@ public: /* Function: insert Inserts an item into the array at a specified location. - + Arguments: - item - Item to insert. + item - Item to insert. r - Range where to insert the item Remarks: @@ -188,16 +188,16 @@ public: { if(r.empty()) return add(item); - + int index = (int)(&r.front()-list); incsize(); set_size(size()+1); - + for(int i = num_elements-1; i > index; i--) list[i] = list[i-1]; list[index] = item; - + return num_elements-1; } @@ -236,7 +236,7 @@ public: /* Function: set_size Resizes the array to the specified size. - + Arguments: new_size - The new size for the array. */ @@ -251,10 +251,10 @@ public: Function: hint_size Allocates the number of elements wanted but does not increase the list size. - + Arguments: hint - Size to allocate. - + Remarks: - If the hint is smaller then the number of elements, nothing will be done. - Invalidates ranges @@ -302,7 +302,7 @@ public: (*this)[i] = other[i]; return *this; } - + /* Function: all Returns a range that contains the whole array. @@ -318,18 +318,18 @@ protected: alloc(list_size+1); else alloc(list_size+list_size/2); - } + } } void alloc(int new_len) { list_size = new_len; T *new_list = ALLOCATOR::alloc_array(list_size); - + int end = num_elements < list_size ? num_elements : list_size; for(int i = 0; i < end; i++) new_list[i] = list[i]; - + ALLOCATOR::free_array(list); num_elements = num_elements < list_size ? num_elements : list_size; diff --git a/src/base/tl/range.h b/src/base/tl/range.h index 25047d31f..f05169fa1 100644 --- a/src/base/tl/range.h +++ b/src/base/tl/range.h @@ -11,7 +11,7 @@ /* Concept: concept_empty - + template struct range { @@ -25,7 +25,7 @@ struct concept_empty /* Concept: concept_index - + template struct range { @@ -39,7 +39,7 @@ struct concept_index /* Concept: concept_size - + template struct range { @@ -53,7 +53,7 @@ struct concept_size /* Concept: concept_slice - + template struct range { @@ -67,7 +67,7 @@ struct concept_slice /* Concept: concept_sorted - + template struct range { @@ -82,13 +82,13 @@ struct concept_sorted /* Concept: concept_forwarditeration Checks for the front and pop_front methods - + template struct range { void pop_front(); T &front() const; - }; + }; */ struct concept_forwarditeration { @@ -98,13 +98,13 @@ struct concept_forwarditeration /* Concept: concept_backwarditeration Checks for the back and pop_back methods - + template struct range { void pop_back(); T &back() const; - }; + }; */ struct concept_backwarditeration { @@ -119,7 +119,7 @@ struct concept_backwarditeration /* Class: plain_range - + Concepts: @@ -142,13 +142,13 @@ public: { *this = r; } - + plain_range(T *b, T *e) { begin = b; end = e; } - + bool empty() const { return begin >= end; } void pop_front() { assert(!empty()); begin++; } void pop_back() { assert(!empty()); end--; } @@ -160,7 +160,7 @@ public: { return plain_range(begin+startindex, begin+endindex); } - + protected: T *begin; T *end; @@ -168,7 +168,7 @@ protected: /* Class: plain_range_sorted - + Concepts: Same as but with these additions: @@ -180,7 +180,7 @@ class plain_range_sorted : public plain_range public: /* sorted concept */ void sorted() const { } - + plain_range_sorted() {} @@ -188,11 +188,11 @@ public: { *this = r; } - + plain_range_sorted(T *b, T *e) : parent(b, e) {} - + plain_range_sorted slice(unsigned start, unsigned count) { return plain_range_sorted(parent::begin+start, parent::begin+start+count); @@ -206,29 +206,29 @@ private: reverse_range() {} public: typedef typename R::type type; - + reverse_range(R r) { range = r; } - + reverse_range(const reverse_range &other) { range = other.range; } - + bool empty() const { return range.empty(); } void pop_front() { range.pop_back(); } void pop_back() { range.pop_front(); } type& front() { return range.back(); } type& back() { return range.front(); } - + R range; }; template reverse_range reverse(R range) { - return reverse_range(range); + return reverse_range(range); } template R reverse(reverse_range range) { - return range.range; + return range.range; } #endif // TL_FILE_RANGE_HPP diff --git a/src/base/tl/sorted_array.h b/src/base/tl/sorted_array.h index 94ccd5438..7e312e1ea 100644 --- a/src/base/tl/sorted_array.h +++ b/src/base/tl/sorted_array.h @@ -10,11 +10,11 @@ template > class sorted_array : public array { typedef array parent; - + // insert and size is not allowed int insert(const T& item, typename parent::range r) { dbg_break(); return 0; } int set_size(int new_size) { dbg_break(); return 0; } - + public: typedef plain_range_sorted range; @@ -27,7 +27,7 @@ public: { return parent::add(item); } - + void sort_range() { sort(all()); @@ -37,7 +37,7 @@ public: /* Function: all Returns a sorted range that contains the whole array. - */ + */ range all() { return range(parent::list, parent::list+parent::num_elements); } }; diff --git a/src/base/tl/string.h b/src/base/tl/string.h index 18fab4d41..e0b891ad5 100644 --- a/src/base/tl/string.h +++ b/src/base/tl/string.h @@ -11,38 +11,38 @@ class string_base : private ALLOCATOR { char *str; int length; - + void reset() { str = 0; length = 0; } - + void free() { ALLOCATOR::free_array(str); reset(); - } - + } + void copy(const char *other_str, int other_length) { length = other_length; str = ALLOCATOR::alloc_array(length+1); mem_copy(str, other_str, length+1); } - + void copy(const string_base &other) { if(!other.str) return; copy(other.str, other.length); } - + public: string_base() { reset(); } string_base(const char *other_str) { copy(other_str, str_length(other_str)); } string_base(const string_base &other) { reset(); copy(other); } ~string_base() { free(); } - + string_base &operator = (const char *other) { free(); @@ -50,17 +50,17 @@ public: copy(other, str_length(other)); return *this; } - + string_base &operator = (const string_base &other) { free(); copy(other); return *this; } - + bool operator < (const char *other_str) const { return str_comp(str, other_str) < 0; } operator const char *() const { return str; } - + const char *cstr() const { return str; } }; diff --git a/src/base/vmath.h b/src/base/vmath.h index e4443da2f..3461adf89 100644 --- a/src/base/vmath.h +++ b/src/base/vmath.h @@ -13,19 +13,19 @@ class vector2_base public: union { T x,u; }; union { T y,v; }; - + vector2_base() {} vector2_base(float nx, float ny) { x = nx; y = ny; } - + vector2_base operator -() const { return vector2_base(-x, -y); } vector2_base operator -(const vector2_base &v) const { return vector2_base(x-v.x, y-v.y); } vector2_base operator +(const vector2_base &v) const { return vector2_base(x+v.x, y+v.y); } vector2_base operator *(const T v) const { return vector2_base(x*v, y*v); } - + const vector2_base &operator =(const vector2_base &v) { x = v.x; y = v.y; return *this; } const vector2_base &operator +=(const vector2_base &v) { x += v.x; y += v.y; return *this; } @@ -81,7 +81,7 @@ inline vector2_base closest_point_on_line(vector2_base line_point0, vector if (t > 1.0f) return 1.0f; return t;*/ } - + // ------------------------------------ template class vector3_base @@ -98,7 +98,7 @@ public: y = ny; z = nz; } - + const vector3_base &operator =(const vector3_base &v) { x = v.x; y = v.y; z = v.z; return *this; } vector3_base operator -(const vector3_base &v) const { return vector3_base(x-v.x, y-v.y, z-v.z); } @@ -107,7 +107,7 @@ public: vector3_base operator *(const T v) const { return vector3_base(x*v, y*v, z*v); } vector3_base operator *(const vector3_base &v) const { return vector3_base(x*v.x, y*v.y, z*v.z); } vector3_base operator /(const T v) const { return vector3_base(x/v, y/v, z/v); } - + const vector3_base &operator +=(const vector3_base &v) { x += v.x; y += v.y; z += v.z; return *this; } const vector3_base &operator -=(const vector3_base &v) { x -= v.x; y -= v.y; z -= v.z; return *this; } const vector3_base &operator *=(const T v) { x *= v; y *= v; z *= v; return *this; } @@ -174,13 +174,13 @@ public: z = nz; w = nw; } - + vector4_base operator +(const vector4_base &v) const { return vector4_base(x+v.x, y+v.y, z+v.z, w+v.w); } vector4_base operator -(const vector4_base &v) const { return vector4_base(x-v.x, y-v.y, z-v.z, w-v.w); } vector4_base operator -() const { return vector4_base(-x, -y, -z, -w); } vector4_base operator *(const vector4_base &v) const { return vector4_base(x*v.x, y*v.y, z*v.z, w*v.w); } vector4_base operator *(const T v) const { return vector4_base(x*v, y*v, z*v, w*v); } - + const vector4_base &operator =(const vector4_base &v) { x = v.x; y = v.y; z = v.z; w = v.w; return *this; } const vector4_base &operator +=(const vector4_base &v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; } diff --git a/src/engine/client.h b/src/engine/client.h index 870c355d8..787410182 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -18,13 +18,13 @@ protected: int m_CurGameTick; float m_GameIntraTick; float m_GameTickTime; - + int m_PredTick; float m_PredIntraTick; - + float m_LocalTime; float m_FrameTime; - + int m_GameTickSpeed; public: @@ -66,11 +66,11 @@ public: inline float PredIntraGameTick() const { return m_PredIntraTick; } inline float GameTickTime() const { return m_GameTickTime; } inline int GameTickSpeed() const { return m_GameTickSpeed; } - + // other time access inline float FrameTime() const { return m_FrameTime; } inline float LocalTime() const { return m_LocalTime; } - + // actions virtual void Connect(const char *pAddress) = 0; virtual void Disconnect() = 0; @@ -88,26 +88,26 @@ public: // virtual int MapDownloadAmount() = 0; virtual int MapDownloadTotalsize() = 0; - + // input virtual int *GetInput(int Tick) = 0; - + // remote console virtual void RconAuth(const char *pUsername, const char *pPassword) = 0; virtual bool RconAuthed() = 0; virtual void Rcon(const char *pLine) = 0; - + // server info virtual void GetServerInfo(class CServerInfo *pServerInfo) = 0; - + // snapshot interface - + enum { SNAP_CURRENT=0, SNAP_PREV=1 }; - + // TODO: Refactor: should redo this a bit i think, too many virtual calls virtual int SnapNumItems(int SnapID) = 0; virtual void *SnapFindItem(int SnapID, int Type, int ID) = 0; @@ -126,8 +126,8 @@ public: return -1; return SendMsg(&Packer, Flags); } - - // + + // virtual const char *ErrorString() = 0; virtual const char *LatestVersion() = 0; virtual bool ConnectionProblems() = 0; @@ -155,9 +155,9 @@ public: virtual void OnMessage(int MsgID, CUnpacker *pUnpacker) = 0; virtual void OnPredict() = 0; virtual void OnActivateEditor() = 0; - + virtual int OnSnapInput(int *pData) = 0; - + virtual const char *GetItemName(int Type) = 0; virtual int GetCountryIndex(int Code) = 0; virtual const char *Version() = 0; diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 5cce547ed..61a96eeef 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -545,7 +545,7 @@ void CClient::RconAuth(const char *pName, const char *pPassword) { if(RconAuthed()) return; - + CMsgPacker Msg(NETMSG_RCON_AUTH); Msg.AddString(pName, 32); Msg.AddString(pPassword, 32); @@ -860,7 +860,7 @@ void CClient::DebugRender() total = 42 */ FrameTimeAvg = FrameTimeAvg*0.9f + m_FrameTime*0.1f; - str_format(aBuffer, sizeof(aBuffer), "ticks: %8d %8d mem %dk %d gfxmem: %dk fps: %3d", + str_format(aBuffer, sizeof(aBuffer), "ticks: %8d %8d mem %dk %d gfxmem: %dk fps: %3d", m_CurGameTick, m_PredTick, mem_stats()->allocated/1024, mem_stats()->total_allocations, @@ -1030,7 +1030,7 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket) // version info if(pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_VERSION) + sizeof(VERSION_DATA)) && mem_comp(pPacket->m_pData, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION)) == 0) - + { unsigned char *pVersionData = (unsigned char*)pPacket->m_pData + sizeof(VERSIONSRV_VERSION); int VersionMatch = !mem_comp(pVersionData, VERSION_DATA, sizeof(VERSION_DATA)); @@ -1060,7 +1060,7 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket) // map version list if(pPacket->m_DataSize >= (int)sizeof(VERSIONSRV_MAPLIST) && - mem_comp(pPacket->m_pData, VERSIONSRV_MAPLIST, sizeof(VERSIONSRV_MAPLIST)) == 0) + mem_comp(pPacket->m_pData, VERSIONSRV_MAPLIST, sizeof(VERSIONSRV_MAPLIST)) == 0) { int Size = pPacket->m_DataSize-sizeof(VERSIONSRV_MAPLIST); int Num = Size/sizeof(CMapVersion); @@ -1114,7 +1114,7 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket) mem_copy(Addr.ip, pAddrs[i].m_aIp, sizeof(Addr.ip)); } Addr.port = (pAddrs[i].m_aPort[0]<<8) | pAddrs[i].m_aPort[1]; - + m_ServerBrowser.Set(Addr, IServerBrowser::SET_MASTER_ADD, -1, 0x0); } } @@ -1125,7 +1125,7 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket) // we got ze info CUnpacker Up; CServerInfo Info = {0}; - + Up.Reset((unsigned char*)pPacket->m_pData+sizeof(SERVERBROWSE_INFO), pPacket->m_DataSize-sizeof(SERVERBROWSE_INFO)); int Token = str_toint(Up.GetString()); str_copy(Info.m_aVersion, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aVersion)); @@ -1282,7 +1282,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) if(!pError) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done"); - SendReady(); + SendReady(); } else DisconnectWithReason(pError); diff --git a/src/engine/client/friends.h b/src/engine/client/friends.h index e3258ec2e..be0cfa498 100644 --- a/src/engine/client/friends.h +++ b/src/engine/client/friends.h @@ -14,14 +14,14 @@ class CFriends : public IFriends static void ConRemoveFriend(IConsole::IResult *pResult, void *pUserData); static void ConfigSaveCallback(IConfig *pConfig, void *pUserData); - + public: CFriends(); - + void Init(); - + int NumFriends() const { return m_NumFriends; } - const CFriendInfo *GetFriend(int Index) const; + const CFriendInfo *GetFriend(int Index) const; bool IsFriend(const char *pName, const char *pClan, bool PlayersOnly) const; void AddFriend(const char *pName, const char *pClan); diff --git a/src/engine/client/graphics.cpp b/src/engine/client/graphics.cpp index 99f5e0959..641f9dfb8 100644 --- a/src/engine/client/graphics.cpp +++ b/src/engine/client/graphics.cpp @@ -50,7 +50,7 @@ static CVideoMode g_aFakeModes[] = { {1800,1440,8,8,8}, {1856,1392,8,8,8}, {1920,1080,8,8,8}, {1920,1200,8,8,8}, {1920,1440,8,8,8}, {1920,2400,8,8,8}, {2048,1536,8,8,8}, - + {320,240,5,6,5}, {400,300,5,6,5}, {640,480,5,6,5}, {720,400,5,6,5}, {768,576,5,6,5}, {800,600,5,6,5}, {1024,600,5,6,5}, {1024,768,5,6,5}, {1152,864,5,6,5}, @@ -67,7 +67,7 @@ void CGraphics_OpenGL::Flush() { if(m_NumVertices == 0) return; - + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -83,7 +83,7 @@ void CGraphics_OpenGL::Flush() glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); - + if(m_RenderEnable) { if(m_Drawing == DRAWING_QUADS) @@ -91,7 +91,7 @@ void CGraphics_OpenGL::Flush() else if(m_Drawing == DRAWING_LINES) glDrawArrays(GL_LINES, 0, m_NumVertices); } - + // Reset pointer m_NumVertices = 0; } @@ -125,26 +125,26 @@ unsigned char CGraphics_OpenGL::Sample(int w, int h, const unsigned char *pData, pData[(v*w+u+1)*4+Offset]+ pData[((v+1)*w+u)*4+Offset]+ pData[((v+1)*w+u+1)*4+Offset])/4; -} +} CGraphics_OpenGL::CGraphics_OpenGL() { m_NumVertices = 0; - + m_ScreenX0 = 0; m_ScreenY0 = 0; m_ScreenX1 = 0; m_ScreenY1 = 0; - + m_ScreenWidth = -1; m_ScreenHeight = -1; - + m_Rotation = 0; m_Drawing = 0; m_InvalidTexture = 0; - + m_TextureMemoryUsage = 0; - + m_RenderEnable = true; m_DoScreenshot = false; } @@ -161,7 +161,7 @@ void CGraphics_OpenGL::ClipDisable() //if(no_gfx) return; glDisable(GL_SCISSOR_TEST); } - + void CGraphics_OpenGL::BlendNone() { glDisable(GL_BLEND); @@ -180,10 +180,10 @@ void CGraphics_OpenGL::BlendAdditive() } int CGraphics_OpenGL::MemoryUsage() const -{ +{ return m_TextureMemoryUsage; -} - +} + void CGraphics_OpenGL::MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY) { m_ScreenX0 = TopLeftX; @@ -220,7 +220,7 @@ void CGraphics_OpenGL::LinesEnd() void CGraphics_OpenGL::LinesDraw(const CLineItem *pArray, int Num) { dbg_assert(m_Drawing == DRAWING_LINES, "called draw without begin"); - + for(int i = 0; i < Num; ++i) { m_aVertices[m_NumVertices + 2*i].m_Pos.x = pArray[i].m_X0; @@ -241,10 +241,10 @@ int CGraphics_OpenGL::UnloadTexture(int Index) { if(Index == m_InvalidTexture) return 0; - + if(Index < 0) return 0; - + glDeleteTextures(1, &m_aTextures[Index].m_Tex); m_aTextures[Index].m_Next = m_FirstFreeTexture; m_TextureMemoryUsage -= m_aTextures[Index].m_MemSize; @@ -261,16 +261,16 @@ int CGraphics_OpenGL::LoadTextureRaw(int Width, int Height, int Format, const vo int Oglformat = 0; int StoreOglformat = 0; int Tex = 0; - + // don't waste memory on texture if we are stress testing if(g_Config.m_DbgStress) return m_InvalidTexture; - + // grab texture Tex = m_FirstFreeTexture; m_FirstFreeTexture = m_aTextures[Tex].m_Next; m_aTextures[Tex].m_Next = -1; - + // resample if needed if(!(Flags&TEXLOAD_NORESAMPLE) && g_Config.m_GfxTextureQuality==0) { @@ -296,13 +296,13 @@ int CGraphics_OpenGL::LoadTextureRaw(int Width, int Height, int Format, const vo pTexData = pTmpData; } } - + Oglformat = GL_RGBA; if(Format == CImageInfo::FORMAT_RGB) Oglformat = GL_RGB; else if(Format == CImageInfo::FORMAT_ALPHA) Oglformat = GL_ALPHA; - + // upload texture if(g_Config.m_GfxTextureCompression) { @@ -320,13 +320,13 @@ int CGraphics_OpenGL::LoadTextureRaw(int Width, int Height, int Format, const vo else if(StoreFormat == CImageInfo::FORMAT_ALPHA) StoreOglformat = GL_ALPHA; } - + glGenTextures(1, &m_aTextures[Tex].m_Tex); glBindTexture(GL_TEXTURE_2D, m_aTextures[Tex].m_Tex); 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, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pTexData); - + // calculate memory usage { int PixelSize = 4; @@ -346,7 +346,7 @@ int CGraphics_OpenGL::LoadTextureRaw(int Width, int Height, int Format, const vo } } } - + m_TextureMemoryUsage += m_aTextures[Tex].m_MemSize; mem_free(pTmpData); return Tex; @@ -358,7 +358,7 @@ int CGraphics_OpenGL::LoadTexture(const char *pFilename, int StorageType, int St int l = str_length(pFilename); int ID; CImageInfo Img; - + if(l < 3) return -1; if(LoadPNG(&Img, pFilename, StorageType)) @@ -370,7 +370,7 @@ int CGraphics_OpenGL::LoadTexture(const char *pFilename, int StorageType, int St mem_free(Img.m_pData); return ID; } - + return m_InvalidTexture; } @@ -379,7 +379,7 @@ int CGraphics_OpenGL::LoadPNG(CImageInfo *pImg, const char *pFilename, int Stora char aCompleteFilename[512]; unsigned char *pBuffer; png_t Png; // ignore_convention - + // open file for reading png_init(0,0); // ignore_convention @@ -391,7 +391,7 @@ int CGraphics_OpenGL::LoadPNG(CImageInfo *pImg, const char *pFilename, int Stora dbg_msg("game/png", "failed to open file. filename='%s'", pFilename); return 0; } - + int Error = png_open_file(&Png, aCompleteFilename); // ignore_convention if(Error != PNG_NO_ERROR) { @@ -400,18 +400,18 @@ int CGraphics_OpenGL::LoadPNG(CImageInfo *pImg, const char *pFilename, int Stora png_close_file(&Png); // ignore_convention return 0; } - + if(Png.depth != 8 || (Png.color_type != PNG_TRUECOLOR && Png.color_type != PNG_TRUECOLOR_ALPHA)) // ignore_convention { dbg_msg("game/png", "invalid format. filename='%s'", aCompleteFilename); png_close_file(&Png); // ignore_convention return 0; } - + pBuffer = (unsigned char *)mem_alloc(Png.width * Png.height * Png.bpp, 1); // ignore_convention png_get_data(&Png, pBuffer); // ignore_convention png_close_file(&Png); // ignore_convention - + pImg->m_Width = Png.width; // ignore_convention pImg->m_Height = Png.height; // ignore_convention if(Png.color_type == PNG_TRUECOLOR) // ignore_convention @@ -435,7 +435,7 @@ void CGraphics_OpenGL::ScreenshotDirect(const char *pFilename) glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pPixelData); glPixelStorei(GL_PACK_ALIGNMENT, Alignment); - + // flip the pixel because opengl works from bottom left corner for(y = 0; y < h/2; y++) { @@ -443,16 +443,16 @@ void CGraphics_OpenGL::ScreenshotDirect(const char *pFilename) mem_copy(pPixelData+y*w*3, pPixelData+(h-y-1)*w*3, w*3); mem_copy(pPixelData+(h-y-1)*w*3, pTempRow,w*3); } - + // find filename { char aWholePath[1024]; png_t Png; // ignore_convention - IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE, aWholePath, sizeof(aWholePath)); + IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE, aWholePath, sizeof(aWholePath)); if(File) io_close(File); - + // save png char aBuf[256]; str_format(aBuf, sizeof(aBuf), "saved screenshot to '%s'", aWholePath); @@ -490,7 +490,7 @@ void CGraphics_OpenGL::QuadsBegin() { dbg_assert(m_Drawing == 0, "called quads_begin twice"); m_Drawing = DRAWING_QUADS; - + QuadsSetSubset(0,0,1,1); QuadsSetRotation(0); SetColor(1,1,1,1); @@ -609,7 +609,7 @@ void CGraphics_OpenGL::QuadsDrawTL(const CQuadItem *pArray, int Num) void CGraphics_OpenGL::QuadsDrawFreeform(const CFreeformItem *pArray, int Num) { dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_draw_freeform without begin"); - + for(int i = 0; i < Num; ++i) { m_aVertices[m_NumVertices + 4*i].m_Pos.x = pArray[i].m_X0; @@ -632,7 +632,7 @@ void CGraphics_OpenGL::QuadsDrawFreeform(const CFreeformItem *pArray, int Num) m_aVertices[m_NumVertices + 4*i + 3].m_Tex = m_aTexture[2]; m_aVertices[m_NumVertices + 4*i + 3].m_Color = m_aColor[2]; } - + AddVertices(4*Num); } @@ -647,7 +647,7 @@ void CGraphics_OpenGL::QuadsText(float x, float y, float Size, float r, float g, { char c = *pText; pText++; - + if(c == '\n') { x = StartX; @@ -660,13 +660,13 @@ void CGraphics_OpenGL::QuadsText(float x, float y, float Size, float r, float g, (c/16)/16.0f, (c%16)/16.0f+1.0f/16.0f, (c/16)/16.0f+1.0f/16.0f); - + CQuadItem QuadItem(x, y, Size, Size); QuadsDrawTL(&QuadItem, 1); x += Size/2; } } - + QuadsEnd(); } @@ -674,7 +674,7 @@ bool CGraphics_OpenGL::Init() { m_pStorage = Kernel()->RequestInterface(); m_pConsole = Kernel()->RequestInterface(); - + // Set all z to -5.0f for(int i = 0; i < MAX_VERTICES; i++) m_aVertices[i].m_Pos.z = -5.0f; @@ -691,21 +691,21 @@ bool CGraphics_OpenGL::Init() glDisable(GL_DEPTH_TEST); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - + glAlphaFunc(GL_GREATER, 0); glEnable(GL_ALPHA_TEST); glDepthMask(0); // create null texture, will get id=0 static const unsigned char aNullTextureData[] = { - 0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, - 0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, - 0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, - 0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, + 0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, + 0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, + 0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, + 0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, }; - + m_InvalidTexture = LoadTextureRaw(4,4,CImageInfo::FORMAT_RGBA,aNullTextureData,CImageInfo::FORMAT_RGBA,TEXLOAD_NORESAMPLE); - + return true; } @@ -713,7 +713,7 @@ int CGraphics_SDL::TryInit() { const SDL_VideoInfo *pInfo; int Flags = SDL_OPENGL; - + m_ScreenWidth = g_Config.m_GfxScreenWidth; m_ScreenHeight = g_Config.m_GfxScreenHeight; @@ -721,7 +721,7 @@ int CGraphics_SDL::TryInit() SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); // set flags - Flags = SDL_OPENGL; + Flags = SDL_OPENGL; Flags |= SDL_GL_DOUBLEBUFFER; Flags |= SDL_HWPALETTE; if(g_Config.m_DbgResizable) @@ -755,7 +755,7 @@ int CGraphics_SDL::TryInit() // set caption SDL_WM_SetCaption("Teeworlds", "Teeworlds"); - + // create window m_pScreenSurface = SDL_SetVideoMode(m_ScreenWidth, m_ScreenHeight, 0, Flags); if(m_pScreenSurface == NULL) @@ -763,7 +763,7 @@ int CGraphics_SDL::TryInit() dbg_msg("gfx", "unable to set video mode: %s", SDL_GetError()); return -1; } - + return 0; } @@ -772,12 +772,12 @@ int CGraphics_SDL::InitWindow() { if(TryInit() == 0) return 0; - + // try disabling fsaa while(g_Config.m_GfxFsaaSamples) { g_Config.m_GfxFsaaSamples--; - + if(g_Config.m_GfxFsaaSamples) dbg_msg("gfx", "lowering FSAA to %d and trying again", g_Config.m_GfxFsaaSamples); else @@ -799,8 +799,8 @@ int CGraphics_SDL::InitWindow() } dbg_msg("gfx", "out of ideas. failed to init graphics"); - - return -1; + + return -1; } @@ -813,34 +813,34 @@ bool CGraphics_SDL::Init() { { int Systems = SDL_INIT_VIDEO; - + if(g_Config.m_SndEnable) Systems |= SDL_INIT_AUDIO; if(g_Config.m_ClEventthread) Systems |= SDL_INIT_EVENTTHREAD; - + if(SDL_Init(Systems) < 0) { dbg_msg("gfx", "unable to init SDL: %s", SDL_GetError()); return true; } } - + atexit(SDL_Quit); // ignore_convention #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 #endif - + if(InitWindow() != 0) return true; SDL_ShowCursor(0); - + CGraphics_OpenGL::Init(); - + MapScreen(0,0,g_Config.m_GfxScreenWidth, g_Config.m_GfxScreenHeight); return false; } @@ -887,11 +887,11 @@ void CGraphics_SDL::Swap() ScreenshotDirect(m_aScreenshotName); m_DoScreenshot = false; } - + SDL_GL_SwapBuffers(); - + if(g_Config.m_GfxFinish) - glFinish(); + glFinish(); } @@ -908,9 +908,9 @@ int CGraphics_SDL::GetVideoModes(CVideoMode *pModes, int MaxModes) Count = MaxModes; return Count; } - + // TODO: fix this code on osx or windows - + ppModes = SDL_ListModes(NULL, SDL_OPENGL|SDL_GL_DOUBLEBUFFER|SDL_FULLSCREEN); if(ppModes == NULL) { @@ -936,7 +936,7 @@ int CGraphics_SDL::GetVideoModes(CVideoMode *pModes, int MaxModes) NumModes++; } } - + return NumModes; } diff --git a/src/engine/client/graphics.h b/src/engine/client/graphics.h index 20be3504f..4367ccfca 100644 --- a/src/engine/client/graphics.h +++ b/src/engine/client/graphics.h @@ -8,7 +8,7 @@ class CGraphics_OpenGL : public IEngineGraphics protected: class IStorage *m_pStorage; class IConsole *m_pConsole; - + // typedef struct { float x, y, z; } CPoint; typedef struct { float u, v; } CTexCoord; @@ -20,14 +20,14 @@ protected: CTexCoord m_Tex; CColor m_Color; } CVertex; - + enum { MAX_VERTICES = 32*1024, MAX_TEXTURES = 1024*4, - + DRAWING_QUADS=1, - DRAWING_LINES=2 + DRAWING_LINES=2 }; CVertex m_aVertices[MAX_VERTICES]; @@ -65,27 +65,27 @@ protected: void Flush(); void AddVertices(int Count); void Rotate4(const CPoint &rCenter, CVertex *pPoints); - + static unsigned char Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset); public: CGraphics_OpenGL(); - + virtual void ClipEnable(int x, int y, int w, int h); virtual void ClipDisable(); - + virtual void BlendNone(); virtual void BlendNormal(); virtual void BlendAdditive(); virtual int MemoryUsage() const; - + virtual void MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY); virtual void GetScreen(float *pTopLeftX, float *pTopLeftY, float *pBottomRightX, float *pBottomRightY); virtual void LinesBegin(); virtual void LinesEnd(); virtual void LinesDraw(const CLineItem *pArray, int Num); - + virtual int UnloadTexture(int Index); virtual int LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags); @@ -115,14 +115,14 @@ public: 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 bool Init(); }; class CGraphics_SDL : public CGraphics_OpenGL { - SDL_Surface *m_pScreenSurface; - + SDL_Surface *m_pScreenSurface; + int TryInit(); int InitWindow(); public: @@ -141,7 +141,7 @@ public: virtual void Swap(); virtual int GetVideoModes(CVideoMode *pModes, int MaxModes); - + }; #endif diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp index 5cd583422..0b4a44a45 100644 --- a/src/engine/client/input.cpp +++ b/src/engine/client/input.cpp @@ -154,7 +154,7 @@ int CInput::Update() // skip private use area of the BMP(contains the unicodes for keyboard function keys on MacOS) if(Event.key.keysym.unicode < 0xE000 || Event.key.keysym.unicode > 0xF8FF) // ignore_convention AddEvent(Event.key.keysym.unicode, 0, 0); // ignore_convention - Key = Event.key.keysym.sym; // ignore_convention + Key = Event.key.keysym.sym; // ignore_convention break; case SDL_KEYUP: Action = IInput::FLAG_RELEASE; diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index 436c8c15d..64d061165 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -86,7 +86,7 @@ bool CServerBrowser::SortCompareName(int Index1, int Index2) const CServerEntry *a = m_ppServerlist[Index1]; CServerEntry *b = m_ppServerlist[Index2]; // make sure empty entries are listed last - return (a->m_GotInfo && b->m_GotInfo) || (!a->m_GotInfo && !b->m_GotInfo) ? str_comp(a->m_Info.m_aName, b->m_Info.m_aName) < 0 : + return (a->m_GotInfo && b->m_GotInfo) || (!a->m_GotInfo && !b->m_GotInfo) ? str_comp(a->m_Info.m_aName, b->m_Info.m_aName) < 0 : a->m_GotInfo ? true : false; } @@ -535,7 +535,7 @@ void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) cons Packet.m_Flags = NETSENDFLAG_CONNLESS; Packet.m_DataSize = sizeof(Buffer); Packet.m_pData = Buffer; - + m_pNetClient->Send(&Packet); if(pEntry) @@ -659,7 +659,7 @@ void CServerBrowser::AddFavorite(const NETADDR &Addr) if(pEntry) pEntry->m_Info.m_Favorite = 1; - if(g_Config.m_Debug) + if(g_Config.m_Debug) { char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); @@ -705,7 +705,7 @@ int CServerBrowser::LoadingProgression() const { if(m_NumServers == 0) return 0; - + int Servers = m_NumServers; int Loaded = m_NumServers-m_NumRequests; return 100.0f * Loaded/Servers; diff --git a/src/engine/client/serverbrowser.h b/src/engine/client/serverbrowser.h index e0d39aad5..a9111d151 100644 --- a/src/engine/client/serverbrowser.h +++ b/src/engine/client/serverbrowser.h @@ -103,7 +103,7 @@ private: CServerEntry *Find(const NETADDR &Addr); CServerEntry *Add(const NETADDR &Addr); - + void RemoveRequest(CServerEntry *pEntry); void QueueRequest(CServerEntry *pEntry); diff --git a/src/engine/client/text.cpp b/src/engine/client/text.cpp index da91980dc..b0896b925 100644 --- a/src/engine/client/text.cpp +++ b/src/engine/client/text.cpp @@ -36,7 +36,7 @@ static int aFontSizes[] = {8,9,10,11,12,13,14,15,16,17,18,19,20,36,64}; struct CFontChar { int m_ID; - + // these values are scaled to the pFont size // width * font_size == real_size float m_Width; @@ -44,7 +44,7 @@ struct CFontChar float m_OffsetX; float m_OffsetY; float m_AdvanceX; - + float m_aUvs[4]; int64 m_TouchTime; }; @@ -57,16 +57,16 @@ struct CFontSizeData GLuint m_aTextures[2]; int m_TextureWidth; int m_TextureHeight; - + int m_NumXChars; int m_NumYChars; - + int m_CharMaxWidth; int m_CharMaxHeight; - + CFontChar m_aCharacters[MAX_CHARACTERS*MAX_CHARACTERS]; - - int m_CurrentCharacter; + + int m_CurrentCharacter; }; class CFont @@ -82,7 +82,7 @@ class CTextRender : public IEngineTextRender { IGraphics *m_pGraphics; IGraphics *Graphics() { return m_pGraphics; } - + int WordLength(const char *pText) { int s = 1; @@ -106,13 +106,13 @@ class CTextRender : public IEngineTextRender float m_TextOutlineG; float m_TextOutlineB; float m_TextOutlineA; - + int m_FontTextureFormat; CFont *m_pDefaultFont; FT_Library m_FTLibrary; - + int GetFontSizeIndex(int Pixelsize) { for(unsigned i = 0; i < NUM_FONT_SIZES; i++) @@ -120,18 +120,18 @@ class CTextRender : public IEngineTextRender if(aFontSizes[i] >= Pixelsize) return i; } - + return NUM_FONT_SIZES-1; } - + void Grow(unsigned char *pIn, unsigned char *pOut, int w, int h) { - for(int y = 0; y < h; y++) - for(int x = 0; x < w; x++) - { - int c = pIn[y*w+x]; + for(int y = 0; y < h; y++) + for(int x = 0; x < w; x++) + { + int c = pIn[y*w+x]; for(int sy = -1; sy <= 1; sy++) for(int sx = -1; sx <= 1; sx++) @@ -142,7 +142,7 @@ class CTextRender : public IEngineTextRender { int Index = GetY*w+GetX; if(pIn[Index] > c) - c = pIn[Index]; + c = pIn[Index]; } } @@ -157,18 +157,18 @@ class CTextRender : public IEngineTextRender int Height = CharHeight*Ychars; void *pMem = mem_alloc(Width*Height, 1); mem_zero(pMem, Width*Height); - + if(pSizeData->m_aTextures[0] == 0) glGenTextures(2, pSizeData->m_aTextures); else FontMemoryUsage -= pSizeData->m_TextureWidth*pSizeData->m_TextureHeight*2; - + pSizeData->m_NumXChars = Xchars; pSizeData->m_NumYChars = Ychars; pSizeData->m_TextureWidth = Width; pSizeData->m_TextureHeight = Height; pSizeData->m_CurrentCharacter = 0; - + for(int i = 0; i < 2; i++) { glBindTexture(GL_TEXTURE_2D, pSizeData->m_aTextures[i]); @@ -177,9 +177,9 @@ class CTextRender : public IEngineTextRender glTexImage2D(GL_TEXTURE_2D, 0, m_FontTextureFormat, Width, Height, 0, m_FontTextureFormat, GL_UNSIGNED_BYTE, pMem); FontMemoryUsage += Width*Height; } - + dbg_msg("", "pFont memory usage: %d", FontMemoryUsage); - + mem_free(pMem); } @@ -198,43 +198,43 @@ class CTextRender : public IEngineTextRender pSizeData->m_NumXChars <<= 1; else pSizeData->m_NumYChars <<= 1; - InitTexture(pSizeData, pSizeData->m_CharMaxWidth, pSizeData->m_CharMaxHeight, pSizeData->m_NumXChars, pSizeData->m_NumYChars); + InitTexture(pSizeData, pSizeData->m_CharMaxWidth, pSizeData->m_CharMaxHeight, pSizeData->m_NumXChars, pSizeData->m_NumYChars); } - - + + // TODO: Refactor: move this into a pFont class void InitIndex(CFont *pFont, int Index) { CFontSizeData *pSizeData = &pFont->m_aSizes[Index]; - + pSizeData->m_FontSize = aFontSizes[Index]; FT_Set_Pixel_Sizes(pFont->m_FtFace, 0, pSizeData->m_FontSize); - + int OutlineThickness = AdjustOutlineThicknessToFontSize(1, pSizeData->m_FontSize); - + { unsigned GlyphIndex; int MaxH = 0; int MaxW = 0; - + int Charcode = FT_Get_First_Char(pFont->m_FtFace, &GlyphIndex); while(GlyphIndex != 0) - { + { // do stuff FT_Load_Glyph(pFont->m_FtFace, GlyphIndex, FT_LOAD_DEFAULT); - + if(pFont->m_FtFace->glyph->metrics.width > MaxW) MaxW = pFont->m_FtFace->glyph->metrics.width; // ignore_convention if(pFont->m_FtFace->glyph->metrics.height > MaxH) MaxH = pFont->m_FtFace->glyph->metrics.height; // ignore_convention Charcode = FT_Get_Next_Char(pFont->m_FtFace, Charcode, &GlyphIndex); } - + MaxW = (MaxW>>6)+2+OutlineThickness*2; MaxH = (MaxH>>6)+2+OutlineThickness*2; - + for(pSizeData->m_CharMaxWidth = 1; pSizeData->m_CharMaxWidth < MaxW; pSizeData->m_CharMaxWidth <<= 1); for(pSizeData->m_CharMaxHeight = 1; pSizeData->m_CharMaxHeight < MaxH; pSizeData->m_CharMaxHeight <<= 1); } - + //dbg_msg("pFont", "init size %d, texture size %d %d", pFont->sizes[index].font_size, w, h); //FT_New_Face(m_FTLibrary, "data/fonts/vera.ttf", 0, &pFont->ft_face); InitTexture(pSizeData, pSizeData->m_CharMaxWidth, pSizeData->m_CharMaxHeight, 8, 8); @@ -253,7 +253,7 @@ class CTextRender : public IEngineTextRender { int x = (SlotID%pSizeData->m_NumXChars) * (pSizeData->m_TextureWidth/pSizeData->m_NumXChars); int y = (SlotID/pSizeData->m_NumXChars) * (pSizeData->m_TextureHeight/pSizeData->m_NumYChars); - + glBindTexture(GL_TEXTURE_2D, pSizeData->m_aTextures[Texnum]); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, pSizeData->m_TextureWidth/pSizeData->m_NumXChars, @@ -284,13 +284,13 @@ class CTextRender : public IEngineTextRender if(pSizeData->m_aCharacters[i].m_TouchTime < pSizeData->m_aCharacters[Oldest].m_TouchTime) Oldest = i; } - + if(time_get()-pSizeData->m_aCharacters[Oldest].m_TouchTime < time_freq()) { IncreaseTextureSize(pSizeData); return GetSlot(pSizeData); } - + return Oldest; } } @@ -315,12 +315,12 @@ class CTextRender : public IEngineTextRender } pBitmap = &pFont->m_FtFace->glyph->bitmap; // ignore_convention - + // fetch slot SlotID = GetSlot(pSizeData); if(SlotID < 0) return -1; - + // adjust spacing int OutlineThickness = AdjustOutlineThicknessToFontSize(1, pSizeData->m_FontSize); x += OutlineThickness; @@ -337,7 +337,7 @@ class CTextRender : public IEngineTextRender } else if(pBitmap->pixel_mode == FT_PIXEL_MODE_MONO) // ignore_convention { - for(py = 0; py < pBitmap->rows; py++) // ignore_convention + for(py = 0; py < pBitmap->rows; py++) // ignore_convention for(px = 0; px < pBitmap->width; px++) // ignore_convention { if(pBitmap->buffer[py*pBitmap->pitch+px/8]&(1<<(7-(px%8)))) // ignore_convention @@ -345,13 +345,13 @@ class CTextRender : public IEngineTextRender } } - if(0) for(py = 0; py < SlotW; py++) - for(px = 0; px < SlotH; px++) + if(0) for(py = 0; py < SlotW; py++) + for(px = 0; px < SlotH; px++) ms_aGlyphData[py*SlotW+px] = 255; - + // upload the glyph UploadGlyph(pSizeData, 0, SlotID, Chr, ms_aGlyphData); - + if(OutlineThickness == 1) { Grow(ms_aGlyphData, ms_aGlyphDataOutlined, SlotW, SlotH); @@ -366,7 +366,7 @@ class CTextRender : public IEngineTextRender } UploadGlyph(pSizeData, 1, SlotID, Chr, ms_aGlyphData); } - + // set char info { CFontChar *pFontchr = &pSizeData->m_aCharacters[SlotID]; @@ -375,27 +375,27 @@ class CTextRender : public IEngineTextRender float Vscale = 1.0f/pSizeData->m_TextureHeight; int Height = pBitmap->rows + OutlineThickness*2 + 2; // ignore_convention int Width = pBitmap->width + OutlineThickness*2 + 2; // ignore_convention - + pFontchr->m_ID = Chr; pFontchr->m_Height = Height * Scale; pFontchr->m_Width = Width * Scale; pFontchr->m_OffsetX = (pFont->m_FtFace->glyph->bitmap_left-1) * Scale; // ignore_convention pFontchr->m_OffsetY = (pSizeData->m_FontSize - pFont->m_FtFace->glyph->bitmap_top) * Scale; // ignore_convention pFontchr->m_AdvanceX = (pFont->m_FtFace->glyph->advance.x>>6) * Scale; // ignore_convention - + pFontchr->m_aUvs[0] = (SlotID%pSizeData->m_NumXChars) / (float)(pSizeData->m_NumXChars); pFontchr->m_aUvs[1] = (SlotID/pSizeData->m_NumXChars) / (float)(pSizeData->m_NumYChars); pFontchr->m_aUvs[2] = pFontchr->m_aUvs[0] + Width*Uscale; pFontchr->m_aUvs[3] = pFontchr->m_aUvs[1] + Height*Vscale; } - + return SlotID; } CFontChar *GetChar(CFont *pFont, CFontSizeData *pSizeData, int Chr) { CFontChar *pFontchr = NULL; - + // search for the character // TODO: remove this linear search int i; @@ -407,7 +407,7 @@ class CTextRender : public IEngineTextRender break; } } - + // check if we need to render the character if(!pFontchr) { @@ -415,12 +415,12 @@ class CTextRender : public IEngineTextRender if(Index >= 0) pFontchr = &pSizeData->m_aCharacters[Index]; } - + // touch the character // TODO: don't call time_get here if(pFontchr) pFontchr->m_TouchTime = time_get(); - + return pFontchr; } @@ -436,8 +436,8 @@ class CTextRender : public IEngineTextRender FT_Get_Kerning(pFont->m_FtFace, Left, Right, FT_KERNING_DEFAULT, &Kerning); return (Kerning.x>>6); } - - + + public: CTextRender() { @@ -457,21 +457,21 @@ public: // GL_LUMINANCE can be good for debugging m_FontTextureFormat = GL_ALPHA; } - + virtual void Init() { m_pGraphics = Kernel()->RequestInterface(); FT_Init_FreeType(&m_FTLibrary); } - + virtual CFont *LoadFont(const char *pFilename) { CFont *pFont = (CFont *)mem_alloc(sizeof(CFont), 1); - + mem_zero(pFont, sizeof(*pFont)); str_copy(pFont->m_aFilename, pFilename, sizeof(pFont->m_aFilename)); - + if(FT_New_Face(m_FTLibrary, pFont->m_aFilename, 0, &pFont->m_FtFace)) { mem_free(pFont); @@ -480,7 +480,7 @@ public: for(unsigned i = 0; i < NUM_FONT_SIZES; i++) pFont->m_aSizes[i].m_FontSize = -1; - + dbg_msg("textrender", "loaded pFont from '%s'", pFilename); return pFont; }; @@ -495,8 +495,8 @@ public: dbg_msg("textrender", "default pFont set %p", pFont); m_pDefaultFont = pFont; } - - + + virtual void SetCursor(CTextCursor *pCursor, float x, float y, float FontSize, int Flags) { mem_zero(pCursor, sizeof(*pCursor)); @@ -510,8 +510,8 @@ public: pCursor->m_Flags = Flags; pCursor->m_CharCount = 0; } - - + + virtual void Text(void *pFontSetV, float x, float y, float Size, const char *pText, int MaxWidth) { CTextCursor Cursor; @@ -527,7 +527,7 @@ public: TextEx(&Cursor, pText, Length); return Cursor.m_X; } - + virtual int TextLineCount(void *pFontSetV, float Size, const char *pText, float LineWidth) { CTextCursor Cursor; @@ -552,12 +552,12 @@ public: m_TextOutlineB = b; m_TextOutlineA = a; } - + virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length) { CFont *pFont = pCursor->m_pFont; CFontSizeData *pSizeData = NULL; - + //dbg_msg("textrender", "rendering text '%s'", text); float ScreenX0, ScreenY0, ScreenX1, ScreenY1; @@ -576,7 +576,7 @@ public: // to correct coords, convert to screen coords, round, and convert back Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); - + FakeToScreenX = (Graphics()->ScreenWidth()/(ScreenX1-ScreenX0)); FakeToScreenY = (Graphics()->ScreenHeight()/(ScreenY1-ScreenY0)); ActualX = (int)(pCursor->m_X * FakeToScreenX); @@ -592,7 +592,7 @@ public: // fetch pFont data if(!pFont) pFont = m_pDefaultFont; - + if(!pFont) return; @@ -600,11 +600,11 @@ public: RenderSetup(pFont, ActualSize); float Scale = 1/pSizeData->m_FontSize; - + // set length if(Length < 0) Length = str_length(pText); - + pEnd = pText + Length; // if we don't want to render, we can just skip the first outline pass @@ -649,7 +649,7 @@ public: Compare.m_Flags &= ~TEXTFLAG_RENDER; Compare.m_LineWidth = -1; TextEx(&Compare, pText, Wlen); - + if(Compare.m_X-DrawX > pCursor->m_LineWidth) { // word can't be fitted in one line, cut it @@ -659,11 +659,11 @@ public: Cutter.m_Y = DrawY; Cutter.m_Flags &= ~TEXTFLAG_RENDER; Cutter.m_Flags |= TEXTFLAG_STOP_AT_END; - + TextEx(&Cutter, (const char *)pCurrent, Wlen); Wlen = Cutter.m_CharCount; NewLine = 1; - + if(Wlen <= 3) // if we can't place 3 chars of the word on this line, take the next Wlen = 0; } @@ -672,10 +672,10 @@ public: NewLine = 1; Wlen = 0; } - + pBatchEnd = pCurrent + Wlen; } - + const char *pTmp = pCurrent; int NextCharacter = str_utf8_decode(&pTmp); while(pCurrent < pBatchEnd) @@ -683,7 +683,7 @@ public: int Character = NextCharacter; pCurrent = pTmp; NextCharacter = str_utf8_decode(&pTmp); - + if(Character == '\n') { DrawX = pCursor->m_StartX; @@ -718,14 +718,14 @@ public: pCursor->m_CharCount++; } } - + if(NewLine) { DrawX = pCursor->m_StartX; DrawY += Size; GotNewLine = 1; DrawX = (int)(DrawX * FakeToScreenX) / FakeToScreenX; // realign - DrawY = (int)(DrawY * FakeToScreenY) / FakeToScreenY; + DrawY = (int)(DrawY * FakeToScreenY) / FakeToScreenY; ++LineCount; } } @@ -736,11 +736,11 @@ public: pCursor->m_X = DrawX; pCursor->m_LineCount = LineCount; - + if(GotNewLine) pCursor->m_Y = DrawY; } - + }; IEngineTextRender *CreateEngineTextRender() { return new CTextRender; } diff --git a/src/engine/config.h b/src/engine/config.h index 7e00cf652..35ef9fb9f 100644 --- a/src/engine/config.h +++ b/src/engine/config.h @@ -15,9 +15,9 @@ public: virtual void Reset() = 0; virtual void RestoreStrings() = 0; virtual void Save() = 0; - + virtual void RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) = 0; - + virtual void WriteLine(const char *pLine) = 0; }; diff --git a/src/engine/console.h b/src/engine/console.h index 77de927e5..f8ec67b04 100644 --- a/src/engine/console.h +++ b/src/engine/console.h @@ -25,14 +25,14 @@ public: public: IResult() { m_NumArgs = 0; } virtual ~IResult() {} - + virtual int GetInteger(unsigned Index) = 0; virtual float GetFloat(unsigned Index) = 0; virtual const char *GetString(unsigned Index) = 0; - + int NumArguments() const { return m_NumArgs; } }; - + class CCommandInfo { public: @@ -50,16 +50,16 @@ public: virtual void PossibleCommands(const char *pStr, int FlagMask, FPossibleCallback pfnCallback, void *pUser) = 0; virtual void ParseArguments(int NumArgs, const char **ppArguments) = 0; - virtual void Register(const char *pName, const char *pParams, + virtual void Register(const char *pName, const char *pParams, int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp) = 0; virtual void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser) = 0; virtual void StoreCommands(bool Store) = 0; - + virtual bool LineIsValid(const char *pStr) = 0; virtual void ExecuteLine(const char *Sptr) = 0; virtual void ExecuteLineStroked(int Stroke, const char *pStr) = 0; virtual void ExecuteFile(const char *pFilename) = 0; - + virtual void RegisterPrintCallback(FPrintCallback pfnPrintCallback, void *pUserData) = 0; virtual void Print(int Level, const char *pFrom, const char *pStr) = 0; }; diff --git a/src/engine/friends.h b/src/engine/friends.h index 50e5ef1fa..bf9df904a 100644 --- a/src/engine/friends.h +++ b/src/engine/friends.h @@ -21,11 +21,11 @@ public: { MAX_FRIENDS=128, }; - + virtual void Init() = 0; - + virtual int NumFriends() const = 0; - virtual const CFriendInfo *GetFriend(int Index) const = 0; + virtual const CFriendInfo *GetFriend(int Index) const = 0; virtual bool IsFriend(const char *pName, const char *pClan, bool PlayersOnly) const = 0; virtual void AddFriend(const char *pName, const char *pClan) = 0; diff --git a/src/engine/graphics.h b/src/engine/graphics.h index de99caac1..0912bfb5a 100644 --- a/src/engine/graphics.h +++ b/src/engine/graphics.h @@ -19,11 +19,11 @@ public: /* Variable: width Contains the width of the image */ int m_Width; - + /* Variable: height Contains the height of the image */ int m_Height; - + /* Variable: format Contains the format of the image. See for more information. */ int m_Format; @@ -61,27 +61,27 @@ public: int ScreenWidth() const { return m_ScreenWidth; } int ScreenHeight() const { return m_ScreenHeight; } float ScreenAspect() const { return (float)ScreenWidth()/(float)ScreenHeight(); } - + virtual void Clear(float r, float g, float b) = 0; - + virtual void ClipEnable(int x, int y, int w, int h) = 0; virtual void ClipDisable() = 0; - + virtual void MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY) = 0; virtual void GetScreen(float *pTopLeftX, float *pTopLeftY, float *pBottomRightX, float *pBottomRightY) = 0; - + // TODO: These should perhaps not be virtuals virtual void BlendNone() = 0; virtual void BlendNormal() = 0; virtual void BlendAdditive() = 0; virtual int MemoryUsage() const = 0; - + virtual int LoadPNG(CImageInfo *pImg, const char *pFilename, int StorageType) =0; virtual int UnloadTexture(int Index) = 0; virtual int LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags) = 0; virtual int LoadTexture(const char *pFilename, int StorageType, int StoreFormat, int Flags) = 0; virtual void TextureSet(int TextureID) = 0; - + struct CLineItem { float m_X0, m_Y0, m_X1, m_Y1; @@ -91,13 +91,13 @@ public: virtual void LinesBegin() = 0; virtual void LinesEnd() = 0; virtual void LinesDraw(const CLineItem *pArray, int Num) = 0; - + virtual void QuadsBegin() = 0; virtual void QuadsEnd() = 0; virtual void QuadsSetRotation(float Angle) = 0; virtual void QuadsSetSubset(float TopLeftY, float TopLeftV, float BottomRightU, float BottomRightV) = 0; virtual void QuadsSetSubsetFree(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) = 0; - + struct CQuadItem { float m_X, m_Y, m_Width, m_Height; @@ -106,7 +106,7 @@ public: }; virtual void QuadsDraw(CQuadItem *pArray, int Num) = 0; virtual void QuadsDrawTL(const CQuadItem *pArray, int Num) = 0; - + struct CFreeformItem { float m_X0, m_Y0, m_X1, m_Y1, m_X2, m_Y2, m_X3, m_Y3; @@ -116,7 +116,7 @@ public: }; 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; - + struct CColorVertex { int m_Index; @@ -126,7 +126,7 @@ public: }; virtual void SetColorVertex(const CColorVertex *pArray, int Num) = 0; virtual void SetColor(float r, float g, float b, float a) = 0; - + virtual void TakeScreenshot(const char *pFilename) = 0; virtual int GetVideoModes(CVideoMode *pModes, int MaxModes) = 0; @@ -139,13 +139,13 @@ class IEngineGraphics : public IGraphics public: virtual bool Init() = 0; virtual void Shutdown() = 0; - + virtual void Minimize() = 0; virtual void Maximize() = 0; - + virtual int WindowActive() = 0; virtual int WindowOpen() = 0; - + }; extern IEngineGraphics *CreateEngineGraphics(); diff --git a/src/engine/input.h b/src/engine/input.h index aa9be78f6..7d28be101 100644 --- a/src/engine/input.h +++ b/src/engine/input.h @@ -41,7 +41,7 @@ protected: int KeyWasPressed(int Key) { return m_aInputState[m_InputCurrent^1][Key]; } -public: +public: enum { FLAG_PRESS=1, @@ -53,7 +53,7 @@ public: int NumEvents() const { return m_NumEvents; } void ClearEvents() { m_NumEvents = 0; } CEvent GetEvent(int Index) const - { + { if(Index < 0 || Index >= m_NumEvents) { IInput::CEvent e = {0,0}; @@ -61,19 +61,19 @@ public: } return m_aInputEvents[Index]; } - + // keys int KeyPressed(int Key) { return m_aInputState[m_InputCurrent][Key]; } int KeyReleases(int Key) { return m_aInputCount[m_InputCurrent][Key].m_Releases; } int KeyPresses(int Key) { return m_aInputCount[m_InputCurrent][Key].m_Presses; } int KeyDown(int Key) { return KeyPressed(Key)&&!KeyWasPressed(Key); } const char *KeyName(int Key) { return (Key >= 0 && Key < 512) ? g_aaKeyStrings[Key] : g_aaKeyStrings[0]; } - + // virtual void MouseModeRelative() = 0; virtual void MouseModeAbsolute() = 0; virtual int MouseDoubleClick() = 0; - + virtual void MouseRelative(float *x, float *y) = 0; }; diff --git a/src/engine/kernel.h b/src/engine/kernel.h index 288f49ab1..b5961bc37 100644 --- a/src/engine/kernel.h +++ b/src/engine/kernel.h @@ -18,7 +18,7 @@ protected: public: IInterface() : m_pKernel(0) {} virtual ~IInterface() {} - + //virtual unsigned InterfaceID() = 0; //virtual const char *InterfaceName() = 0; }; @@ -27,7 +27,7 @@ public: public: \ static const char *InterfaceName() { return Name; } \ private: - + //virtual unsigned InterfaceID() { return INTERFACE_ID; } //virtual const char *InterfaceName() { return name; } @@ -55,7 +55,7 @@ public: { return ReregisterInterfaceImpl(TINTERFACE::InterfaceName(), pInterface); } - + // Usage example: // IMyInterface *pMyHandle = Kernel()->RequestInterface() template diff --git a/src/engine/server.h b/src/engine/server.h index c27365caa..28dc3d11d 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -21,7 +21,7 @@ public: const char *m_pName; int m_Latency; }; - + int Tick() const { return m_CurrentGameTick; } int TickSpeed() const { return m_TickSpeed; } @@ -32,7 +32,7 @@ public: virtual int GetClientInfo(int ClientID, CClientInfo *pInfo) = 0; virtual void GetClientAddr(int ClientID, char *pAddrStr, int Size) = 0; virtual int *LatestInput(int ClientID, int *pSize) = 0; - + virtual int SendMsg(CMsgPacker *pMsg, int Flags, int ClientID) = 0; template @@ -43,18 +43,18 @@ public: return -1; return SendMsg(&Packer, Flags, ClientID); } - + virtual void SetClientName(int ClientID, char const *pName) = 0; virtual void SetClientClan(int ClientID, char const *pClan) = 0; virtual void SetClientCountry(int ClientID, int Country) = 0; virtual void SetClientScore(int ClientID, int Score) = 0; - + virtual int SnapNewID() = 0; virtual void SnapFreeID(int ID) = 0; virtual void *SnapNewItem(int Type, int ID, int Size) = 0; virtual void SnapSetStaticsize(int ItemType, int Size) = 0; - + virtual bool IsAuthed(int ClientID) = 0; virtual void Kick(int ClientID, const char *pReason) = 0; }; @@ -67,12 +67,12 @@ public: virtual void OnInit() = 0; virtual void OnConsoleInit() = 0; virtual void OnShutdown() = 0; - + virtual void OnTick() = 0; virtual void OnPreSnap() = 0; virtual void OnSnap(int ClientID) = 0; virtual void OnPostSnap() = 0; - + virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) = 0; virtual void OnClientConnected(int ClientID) = 0; @@ -83,7 +83,7 @@ public: virtual bool IsClientReady(int ClientID) = 0; virtual bool IsClientPlayer(int ClientID) = 0; - + virtual const char *GameType() = 0; virtual const char *Version() = 0; virtual const char *NetVersion() = 0; diff --git a/src/engine/server/register.cpp b/src/engine/server/register.cpp index 0b53c67c2..0b7eb948a 100644 --- a/src/engine/server/register.cpp +++ b/src/engine/server/register.cpp @@ -41,15 +41,15 @@ void CRegister::RegisterSendFwcheckresponse(NETADDR *pAddr) Packet.m_pData = SERVERBROWSE_FWRESPONSE; m_pNetServer->Send(&Packet); } - + void CRegister::RegisterSendHeartbeat(NETADDR Addr) { static unsigned char aData[sizeof(SERVERBROWSE_HEARTBEAT) + 2]; unsigned short Port = g_Config.m_SvPort; CNetChunk Packet; - + mem_copy(aData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)); - + Packet.m_ClientID = -1; Packet.m_Address = Addr; Packet.m_Flags = NETSENDFLAG_CONNLESS; @@ -118,7 +118,7 @@ void CRegister::RegisterUpdate(int Nettype) else if(m_RegisterState == REGISTERSTATE_UPDATE_ADDRS) { m_RegisterRegisteredServer = -1; - + if(!m_pMasterServer->IsRefreshing()) { int i; @@ -137,7 +137,7 @@ void CRegister::RegisterUpdate(int Nettype) m_aMasterserverInfo[i].m_Count = -1; m_aMasterserverInfo[i].m_LastSend = 0; } - + m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", "fetching server counts"); RegisterNewState(REGISTERSTATE_QUERY_COUNT); } @@ -149,7 +149,7 @@ void CRegister::RegisterUpdate(int Nettype) { if(!m_aMasterserverInfo[i].m_Valid) continue; - + if(m_aMasterserverInfo[i].m_Count == -1) { Left++; @@ -160,7 +160,7 @@ void CRegister::RegisterUpdate(int Nettype) } } } - + // check if we are done or timed out if(Left == 0 || Now > m_RegisterStateStart+Freq*3) { @@ -171,7 +171,7 @@ void CRegister::RegisterUpdate(int Nettype) { if(!m_aMasterserverInfo[i].m_Valid || m_aMasterserverInfo[i].m_Count == -1) continue; - + if(Best == -1 || m_aMasterserverInfo[i].m_Count < m_aMasterserverInfo[Best].m_Count) Best = i; } @@ -184,7 +184,7 @@ void CRegister::RegisterUpdate(int Nettype) RegisterNewState(REGISTERSTATE_ERROR); } else - { + { char aBuf[256]; str_format(aBuf, sizeof(aBuf), "chose '%s' as master, sending heartbeats", m_pMasterServer->GetName(m_RegisterRegisteredServer)); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", aBuf); @@ -201,7 +201,7 @@ void CRegister::RegisterUpdate(int Nettype) m_aMasterserverInfo[m_RegisterRegisteredServer].m_LastSend = Now; RegisterSendHeartbeat(m_aMasterserverInfo[m_RegisterRegisteredServer].m_Addr); } - + if(Now > m_RegisterStateStart+Freq*60) { m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", "WARNING: Master server is not responding, switching master"); @@ -212,9 +212,9 @@ void CRegister::RegisterUpdate(int Nettype) { if(m_RegisterFirst) m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", "server registered"); - + m_RegisterFirst = 0; - + // check if we should send new heartbeat again if(Now > m_RegisterStateStart+Freq) { @@ -253,7 +253,7 @@ int CRegister::RegisterProcessPacket(CNetChunk *pPacket) } if(!Valid) return 0; - + if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWCHECK) && mem_comp(pPacket->m_pData, SERVERBROWSE_FWCHECK, sizeof(SERVERBROWSE_FWCHECK)) == 0) { diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 3878ece15..266b9130d 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -26,7 +26,7 @@ #include "register.h" #include "server.h" -#if defined(CONF_FAMILY_WINDOWS) +#if defined(CONF_FAMILY_WINDOWS) #define _WIN32_WINNT 0x0501 #define WIN32_LEAN_AND_MEAN #include @@ -75,7 +75,7 @@ void CSnapIDPool::Reset() m_aIDs[i].m_Next = i+1; m_aIDs[i].m_State = 0; } - + m_aIDs[MAX_IDS-1].m_Next = -1; m_FirstFree = 0; m_FirstTimed = -1; @@ -88,17 +88,17 @@ void CSnapIDPool::Reset() void CSnapIDPool::RemoveFirstTimeout() { int NextTimed = m_aIDs[m_FirstTimed].m_Next; - + // add it to the free list m_aIDs[m_FirstTimed].m_Next = m_FirstFree; m_aIDs[m_FirstTimed].m_State = 0; m_FirstFree = m_FirstTimed; - + // remove it from the timed list m_FirstTimed = NextTimed; if(m_FirstTimed == -1) m_LastTimed = -1; - + m_Usage--; } @@ -109,7 +109,7 @@ int CSnapIDPool::NewID() // process timed ids while(m_FirstTimed != -1 && m_aIDs[m_FirstTimed].m_Timeout < Now) RemoveFirstTimeout(); - + int ID = m_FirstFree; dbg_assert(ID != -1, "id error"); if(ID == -1) @@ -138,7 +138,7 @@ void CSnapIDPool::FreeID(int ID) m_aIDs[ID].m_State = 2; m_aIDs[ID].m_Timeout = time_get()+time_freq()*5; m_aIDs[ID].m_Next = -1; - + if(m_LastTimed != -1) { m_aIDs[m_LastTimed].m_Next = ID; @@ -150,7 +150,7 @@ void CSnapIDPool::FreeID(int ID) m_LastTimed = ID; } } - + void CServer::CClient::Reset() { // reset input @@ -169,15 +169,15 @@ void CServer::CClient::Reset() CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta) { m_TickSpeed = SERVER_TICK_SPEED; - + m_pGameServer = 0; - + m_CurrentGameTick = 0; m_RunServer = 1; m_pCurrentMapData = 0; m_CurrentMapSize = 0; - + m_MapReload = 0; m_RconClientID = -1; @@ -202,12 +202,12 @@ int CServer::TrySetClientName(int ClientID, const char *pName) str_format(aBuf, sizeof(aBuf), "'%s' -> '%s'", pName, aTrimmedName); 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) @@ -227,10 +227,10 @@ void CServer::SetClientName(int ClientID, const char *pName) { if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY) return; - + if(!pName) return; - + char aNameTry[MAX_NAME_LENGTH]; str_copy(aNameTry, pName, MAX_NAME_LENGTH); if(TrySetClientName(ClientID, aNameTry)) @@ -249,7 +249,7 @@ void CServer::SetClientClan(int ClientID, const char *pClan) { if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY || !pClan) return; - + str_copy(m_aClients[ClientID].m_aClan, pClan, MAX_CLAN_LENGTH); } @@ -257,7 +257,7 @@ void CServer::SetClientCountry(int ClientID, int Country) { if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY) return; - + m_aClients[ClientID].m_Country = Country; } @@ -280,7 +280,7 @@ void CServer::Kick(int ClientID, const char *pReason) Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "you can't kick yourself"); return; } - + m_NetServer.Drop(ClientID, pReason); } @@ -343,7 +343,7 @@ void CServer::GetClientAddr(int ClientID, char *pAddrStr, int Size) net_addr_str(&Addr, pAddrStr, Size); } } - + int *CServer::LatestInput(int ClientID, int *size) { @@ -360,7 +360,7 @@ const char *CServer::ClientName(int ClientID) return m_aClients[ClientID].m_aName; else return "(connecting client)"; - + } const char *CServer::ClientClan(int ClientID) @@ -398,13 +398,13 @@ int CServer::SendMsgEx(CMsgPacker *pMsg, int Flags, int ClientID, bool System) CNetChunk Packet; if(!pMsg) return -1; - + mem_zero(&Packet, sizeof(CNetChunk)); - + Packet.m_ClientID = ClientID; Packet.m_pData = pMsg->Data(); Packet.m_DataSize = pMsg->Size(); - + // HACK: modify the message id in the packet and store the system flag *((unsigned char*)Packet.m_pData) <<= 1; if(System) @@ -414,7 +414,7 @@ int CServer::SendMsgEx(CMsgPacker *pMsg, int Flags, int ClientID, bool System) Packet.m_Flags |= NETSENDFLAG_VITAL; if(Flags&MSGFLAG_FLUSH) Packet.m_Flags |= NETSENDFLAG_FLUSH; - + // write message to demo recorder if(!(Flags&MSGFLAG_NORECORD)) m_DemoRecorder.RecordMessage(pMsg->Data(), pMsg->Size()); @@ -441,7 +441,7 @@ int CServer::SendMsgEx(CMsgPacker *pMsg, int Flags, int ClientID, bool System) void CServer::DoSnapshot() { GameServer()->OnPreSnap(); - + // create snapshot for demo recording if(m_DemoRecorder.IsRecording()) { @@ -452,7 +452,7 @@ void CServer::DoSnapshot() m_SnapshotBuilder.Init(); GameServer()->OnSnap(-1); SnapshotSize = m_SnapshotBuilder.Finish(aData); - + // write snapshot m_DemoRecorder.RecordSnapshot(Tick(), aData, SnapshotSize); } @@ -463,15 +463,15 @@ void CServer::DoSnapshot() // client must be ingame to recive snapshots if(m_aClients[i].m_State != CClient::STATE_INGAME) continue; - + // this client is trying to recover, don't spam snapshots if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_RECOVER && (Tick()%50) != 0) continue; - + // this client is trying to recover, don't spam snapshots if(m_aClients[i].m_SnapRate == CClient::SNAPRATE_INIT && (Tick()%10) != 0) continue; - + { char aData[CSnapshot::MAX_SIZE]; CSnapshot *pData = (CSnapshot*)aData; // Fix compiler warning for strict-aliasing @@ -496,13 +496,13 @@ void CServer::DoSnapshot() // remove old snapshos // keep 3 seconds worth of snapshots m_aClients[i].m_Snapshots.PurgeUntil(m_CurrentGameTick-SERVER_TICK_SPEED*3); - + // save it the snapshot m_aClients[i].m_Snapshots.Add(m_CurrentGameTick, time_get(), SnapshotSize, pData, 0); - + // find snapshot that we can preform delta against EmptySnap.Clear(); - + { DeltashotSize = m_aClients[i].m_Snapshots.Get(m_aClients[i].m_LastAckedSnapshot, 0, &pDeltashot, 0); if(DeltashotSize >= 0) @@ -514,10 +514,10 @@ void CServer::DoSnapshot() m_aClients[i].m_SnapRate = CClient::SNAPRATE_RECOVER; } } - + // create delta DeltaSize = m_SnapshotDelta.CreateDelta(pDeltashot, pData, aDeltaData); - + if(DeltaSize) { // compress it @@ -527,7 +527,7 @@ void CServer::DoSnapshot() SnapshotSize = CVariableInt::Compress(aDeltaData, DeltaSize, aCompData); NumPackets = (SnapshotSize+MaxSize-1)/MaxSize; - + for(int n = 0, Left = SnapshotSize; Left; n++) { int Chunk = Left < MaxSize ? Left : MaxSize; @@ -549,7 +549,7 @@ void CServer::DoSnapshot() Msg.AddInt(m_CurrentGameTick); Msg.AddInt(m_CurrentGameTick-DeltaTick); Msg.AddInt(NumPackets); - Msg.AddInt(n); + Msg.AddInt(n); Msg.AddInt(Crc); Msg.AddInt(Chunk); Msg.AddRaw(&aCompData[n*MaxSize], Chunk); @@ -587,7 +587,7 @@ int CServer::NewClientCallback(int ClientID, void *pUser) int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser) { CServer *pThis = (CServer *)pUser; - + NETADDR Addr = pThis->m_NetServer.ClientAddr(ClientID); char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); @@ -598,7 +598,7 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser) // notify the mod about the drop if(pThis->m_aClients[ClientID].m_State >= CClient::STATE_READY) pThis->GameServer()->OnClientDrop(ClientID, pReason); - + pThis->m_aClients[ClientID].m_State = CClient::STATE_EMPTY; pThis->m_aClients[ClientID].m_aName[0] = 0; pThis->m_aClients[ClientID].m_aClan[0] = 0; @@ -636,16 +636,16 @@ void CServer::SendRconLineAuthed(const char *pLine, void *pUser) CServer *pThis = (CServer *)pUser; static volatile int ReentryGuard = 0; int i; - + if(ReentryGuard) return; ReentryGuard++; - + for(i = 0; i < MAX_CLIENTS; i++) { if(pThis->m_aClients[i].m_State != CClient::STATE_EMPTY && pThis->m_aClients[i].m_Authed) pThis->SendRconLine(i, pLine); } - + ReentryGuard--; } @@ -655,15 +655,15 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) NETADDR Addr; CUnpacker Unpacker; Unpacker.Reset(pPacket->m_pData, pPacket->m_DataSize); - + // unpack msgid and system flag int Msg = Unpacker.GetInt(); int Sys = Msg&1; Msg >>= 1; - + if(Unpacker.Error()) return; - + if(Sys) { // system message @@ -680,7 +680,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) m_NetServer.Drop(ClientID, aReason); return; } - + const char *pPassword = Unpacker.GetString(CUnpacker::SANITIZE_CC); if(g_Config.m_Password[0] != 0 && str_comp(g_Config.m_Password, pPassword) != 0) { @@ -688,7 +688,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) m_NetServer.Drop(ClientID, "Wrong password"); return; } - + m_aClients[ClientID].m_State = CClient::STATE_CONNECTING; SendMap(ClientID); } @@ -699,11 +699,11 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) int ChunkSize = 1024-128; int Offset = Chunk * ChunkSize; int Last = 0; - + // drop faulty map data requests if(Chunk < 0 || Offset > m_CurrentMapSize) return; - + if(Offset+ChunkSize >= m_CurrentMapSize) { ChunkSize = m_CurrentMapSize-Offset; @@ -711,7 +711,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) ChunkSize = 0; Last = 1; } - + CMsgPacker Msg(NETMSG_MAP_DATA); Msg.AddInt(Last); Msg.AddInt(m_CurrentMapCrc); @@ -719,7 +719,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) Msg.AddInt(ChunkSize); Msg.AddRaw(&m_pCurrentMapData[Offset], ChunkSize); SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID, true); - + if(g_Config.m_Debug) { char aBuf[256]; @@ -734,7 +734,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) Addr = m_NetServer.ClientAddr(ClientID); char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); - + char aBuf[256]; str_format(aBuf, sizeof(aBuf), "player is ready. ClientID=%x addr=%s", ClientID, aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); @@ -750,7 +750,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) Addr = m_NetServer.ClientAddr(ClientID); char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); - + char aBuf[256]; str_format(aBuf, sizeof(aBuf), "player has entered the game. ClientID=%x addr=%s", ClientID, aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); @@ -762,18 +762,18 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) { CClient::CInput *pInput; int64 TagTime; - + m_aClients[ClientID].m_LastAckedSnapshot = Unpacker.GetInt(); int IntendedTick = Unpacker.GetInt(); int Size = Unpacker.GetInt(); - + // check for errors if(Unpacker.Error() || Size/4 > MAX_INPUT_SIZE) return; if(m_aClients[ClientID].m_LastAckedSnapshot > 0) m_aClients[ClientID].m_SnapRate = CClient::SNAPRATE_FULL; - + if(m_aClients[ClientID].m_Snapshots.Get(m_aClients[ClientID].m_LastAckedSnapshot, &TagTime, 0, 0) >= 0) m_aClients[ClientID].m_Latency = (int)(((time_get()-TagTime)*1000)/time_freq()); @@ -782,7 +782,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) if(IntendedTick > m_aClients[ClientID].m_LastInputTick) { int TimeLeft = ((TickStartTime(IntendedTick)-time_get())*1000) / time_freq(); - + CMsgPacker Msg(NETMSG_INPUTTIMING); Msg.AddInt(IntendedTick); Msg.AddInt(TimeLeft); @@ -792,20 +792,20 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) m_aClients[ClientID].m_LastInputTick = IntendedTick; pInput = &m_aClients[ClientID].m_aInputs[m_aClients[ClientID].m_CurrentInput]; - + if(IntendedTick <= Tick()) IntendedTick = Tick()+1; pInput->m_GameTick = IntendedTick; - + for(int i = 0; i < Size/4; i++) pInput->m_aData[i] = Unpacker.GetInt(); - + mem_copy(m_aClients[ClientID].m_LatestInput.m_aData, pInput->m_aData, MAX_INPUT_SIZE*sizeof(int)); - + m_aClients[ClientID].m_CurrentInput++; m_aClients[ClientID].m_CurrentInput %= 200; - + // call the mod with the fresh input data if(m_aClients[ClientID].m_State == CClient::STATE_INGAME) GameServer()->OnClientDirectInput(ClientID, m_aClients[ClientID].m_LatestInput.m_aData); @@ -813,7 +813,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) else if(Msg == NETMSG_RCON_CMD) { const char *pCmd = Unpacker.GetString(); - + if(Unpacker.Error() == 0 && m_aClients[ClientID].m_Authed) { char aBuf[256]; @@ -829,7 +829,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) const char *pPw; Unpacker.GetString(); // login name, not used pPw = Unpacker.GetString(CUnpacker::SANITIZE_CC); - + if(Unpacker.Error() == 0) { if(g_Config.m_SvRconPassword[0] == 0) @@ -841,7 +841,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS); Msg.AddInt(1); SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true); - + m_aClients[ClientID].m_Authed = 1; SendRconLine(ClientID, "Authentication successful. Remote console access granted."); char aBuf[256]; @@ -905,7 +905,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) GameServer()->OnMessage(Msg, &Unpacker, ClientID); } } - + void CServer::SendServerInfo(NETADDR *pAddr, int Token) { CNetChunk Packet; @@ -920,17 +920,17 @@ void CServer::SendServerInfo(NETADDR *pAddr, int Token) { if(GameServer()->IsClientPlayer(i)) PlayerCount++; - + ClientCount++; } } - + p.Reset(); p.AddRaw(SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)); str_format(aBuf, sizeof(aBuf), "%d", Token); p.AddString(aBuf, 6); - + p.AddString(GameServer()->Version(), 32); p.AddString(g_Config.m_SvName, 64); p.AddString(GetMapName(), 32); @@ -940,28 +940,28 @@ void CServer::SendServerInfo(NETADDR *pAddr, int Token) // flags int i = 0; - if(g_Config.m_Password[0]) // password set + if(g_Config.m_Password[0]) // password set i |= SERVER_FLAG_PASSWORD; str_format(aBuf, sizeof(aBuf), "%d", i); p.AddString(aBuf, 2); - str_format(aBuf, sizeof(aBuf), "%d", PlayerCount); p.AddString(aBuf, 3); // num players + str_format(aBuf, sizeof(aBuf), "%d", PlayerCount); p.AddString(aBuf, 3); // num players str_format(aBuf, sizeof(aBuf), "%d", m_NetServer.MaxClients()-g_Config.m_SvSpectatorSlots); p.AddString(aBuf, 3); // max players - str_format(aBuf, sizeof(aBuf), "%d", ClientCount); p.AddString(aBuf, 3); // num clients + str_format(aBuf, sizeof(aBuf), "%d", ClientCount); p.AddString(aBuf, 3); // num clients str_format(aBuf, sizeof(aBuf), "%d", m_NetServer.MaxClients()); p.AddString(aBuf, 3); // max clients for(i = 0; i < MAX_CLIENTS; i++) { if(m_aClients[i].m_State != CClient::STATE_EMPTY) { - p.AddString(ClientName(i), MAX_NAME_LENGTH); // client name - p.AddString(ClientClan(i), MAX_CLAN_LENGTH); // client clan - str_format(aBuf, sizeof(aBuf), "%d", m_aClients[i].m_Country); p.AddString(aBuf, 6); // client country - str_format(aBuf, sizeof(aBuf), "%d", m_aClients[i].m_Score); p.AddString(aBuf, 6); // client score - str_format(aBuf, sizeof(aBuf), "%d", GameServer()->IsClientPlayer(i)?1:0); p.AddString(aBuf, 2); // is player? + p.AddString(ClientName(i), MAX_NAME_LENGTH); // client name + p.AddString(ClientClan(i), MAX_CLAN_LENGTH); // client clan + str_format(aBuf, sizeof(aBuf), "%d", m_aClients[i].m_Country); p.AddString(aBuf, 6); // client country + str_format(aBuf, sizeof(aBuf), "%d", m_aClients[i].m_Score); p.AddString(aBuf, 6); // client score + str_format(aBuf, sizeof(aBuf), "%d", GameServer()->IsClientPlayer(i)?1:0); p.AddString(aBuf, 2); // is player? } } - + Packet.m_ClientID = -1; Packet.m_Address = *pAddr; Packet.m_Flags = NETSENDFLAG_CONNLESS; @@ -994,21 +994,21 @@ int CServer::BanAdd(NETADDR Addr, int Seconds, const char *pReason) str_format(aBuf, sizeof(aBuf), "banned %s for life", aAddrStr); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); - return m_NetServer.BanAdd(Addr, Seconds, pReason); + return m_NetServer.BanAdd(Addr, Seconds, pReason); } int CServer::BanRemove(NETADDR Addr) { return m_NetServer.BanRemove(Addr); } - + void CServer::PumpNetwork() { CNetChunk Packet; m_NetServer.Update(); - + // process packets while(m_NetServer.Recv(&Packet)) { @@ -1046,7 +1046,7 @@ int CServer::LoadMap(const char *pMapName) //DATAFILE *df; char aBuf[512]; str_format(aBuf, sizeof(aBuf), "maps/%s.map", pMapName); - + /*df = datafile_load(buf); if(!df) return 0;*/ @@ -1057,25 +1057,25 @@ int CServer::LoadMap(const char *pMapName) Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "mapchecker", "invalid standard map"); return 0; } - + if(!m_pMap->Load(aBuf)) return 0; - + // stop recording when we change map m_DemoRecorder.Stop(); - + // reinit snapshot ids m_IDPool.TimeoutIDs(); - + // get the crc of the map m_CurrentMapCrc = m_pMap->Crc(); char aBufMsg[256]; str_format(aBufMsg, sizeof(aBufMsg), "%s crc is %08x", aBuf, m_CurrentMapCrc); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBufMsg); - + str_copy(m_aCurrentMap, pMapName, sizeof(m_aCurrentMap)); //map_set(df); - + // load compelate map into memory for download { IOHANDLE File = Storage()->OpenFile(aBuf, IOFLAG_READ, IStorage::TYPE_ALL); @@ -1109,7 +1109,7 @@ int CServer::Run() dbg_msg("server", "failed to load map. mapname='%s'", g_Config.m_SvMap); return -1; } - + // start server NETADDR BindAddr; if(g_Config.m_SvBindaddr[0] && net_host_lookup(g_Config.m_SvBindaddr, &BindAddr, NETTYPE_ALL) == 0) @@ -1123,8 +1123,8 @@ int CServer::Run() BindAddr.type = NETTYPE_ALL; BindAddr.port = g_Config.m_SvPort; } - - + + if(!m_NetServer.Open(BindAddr, g_Config.m_SvMaxClients, g_Config.m_SvMaxClientsPerIP, 0)) { dbg_msg("server", "couldn't open socket. port might already be in use"); @@ -1132,11 +1132,11 @@ int CServer::Run() } m_NetServer.SetCallbacks(NewClientCallback, DelClientCallback, this); - + char aBuf[256]; str_format(aBuf, sizeof(aBuf), "server name is '%s'", g_Config.m_SvName); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); - + GameServer()->OnInit(); str_format(aBuf, sizeof(aBuf), "version %s", GameServer()->NetVersion()); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); @@ -1148,10 +1148,10 @@ int CServer::Run() { int64 ReportTime = time_get(); int ReportInterval = 3; - + m_Lastheartbeat = 0; m_GameStartTime = time_get(); - + if(g_Config.m_Debug) { str_format(aBuf, sizeof(aBuf), "baseline memory usage %dk", mem_stats()->allocated/1024); @@ -1162,28 +1162,28 @@ int CServer::Run() { int64 t = time_get(); int NewTicks = 0; - + // load new map TODO: don't poll this if(str_comp(g_Config.m_SvMap, m_aCurrentMap) != 0 || m_MapReload) { m_MapReload = 0; - + // load map if(LoadMap(g_Config.m_SvMap)) { // new map loaded GameServer()->OnShutdown(); - + for(int c = 0; c < MAX_CLIENTS; c++) { if(m_aClients[c].m_State <= CClient::STATE_AUTH) continue; - + SendMap(c); m_aClients[c].Reset(); m_aClients[c].m_State = CClient::STATE_CONNECTING; } - + m_GameStartTime = time_get(); m_CurrentGameTick = 0; Kernel()->ReregisterInterface(GameServer()); @@ -1197,12 +1197,12 @@ int CServer::Run() str_copy(g_Config.m_SvMap, m_aCurrentMap, sizeof(g_Config.m_SvMap)); } } - + while(t > TickStartTime(m_CurrentGameTick+1)) { m_CurrentGameTick++; NewTicks++; - + // apply new input for(int c = 0; c < MAX_CLIENTS; c++) { @@ -1221,19 +1221,19 @@ int CServer::Run() GameServer()->OnTick(); } - + // snap game if(NewTicks) { if(g_Config.m_SvHighBandwidth || (m_CurrentGameTick%2) == 0) DoSnapshot(); } - + // master server stuff m_Register.RegisterUpdate(BindAddr.type); - + PumpNetwork(); - + if(ReportTime < time_get()) { if(g_Config.m_Debug) @@ -1242,23 +1242,23 @@ int CServer::Run() static NETSTATS prev_stats; NETSTATS stats; netserver_stats(net, &stats); - + perf_next(); - + if(config.dbg_pref) perf_dump(&rootscope); dbg_msg("server", "send=%8d recv=%8d", (stats.send_bytes - prev_stats.send_bytes)/reportinterval, (stats.recv_bytes - prev_stats.recv_bytes)/reportinterval); - + prev_stats = stats; */ } - + ReportTime += time_freq()*ReportInterval; } - + // wait for incomming data net_socket_read_wait(m_NetServer.Socket(), 5); } @@ -1296,14 +1296,14 @@ void CServer::ConBan(IConsole::IResult *pResult, void *pUser) CServer *pServer = (CServer *)pUser; const char *pStr = pResult->GetString(0); int Minutes = 30; - const char *pReason = "No reason given"; - + const char *pReason = "No reason given"; + if(pResult->NumArguments() > 1) Minutes = pResult->GetInteger(1); - + if(pResult->NumArguments() > 2) pReason = pResult->GetString(2); - + if(net_addr_from_str(&Addr, pStr) == 0) { if(pServer->m_RconClientID >= 0 && pServer->m_RconClientID < MAX_CLIENTS && pServer->m_aClients[pServer->m_RconClientID].m_State != CClient::STATE_EMPTY) @@ -1348,7 +1348,7 @@ void CServer::ConUnban(IConsole::IResult *pResult, void *pUser) NETADDR Addr; CServer *pServer = (CServer *)pUser; const char *pStr = pResult->GetString(0); - + if(net_addr_from_str(&Addr, pStr) == 0 && !pServer->BanRemove(Addr)) { char aAddrStr[NETADDR_MAXSTRSIZE]; @@ -1384,7 +1384,7 @@ void CServer::ConBans(IConsole::IResult *pResult, void *pUser) char aBuf[1024]; char aAddrStr[NETADDR_MAXSTRSIZE]; CServer* pServer = (CServer *)pUser; - + int Num = pServer->m_NetServer.BanNum(); for(int i = 0; i < Num; i++) { @@ -1392,7 +1392,7 @@ void CServer::ConBans(IConsole::IResult *pResult, void *pUser) pServer->m_NetServer.BanGet(i, &Info); NETADDR Addr = Info.m_Addr; net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); - + if(Info.m_Expires == -1) { str_format(aBuf, sizeof(aBuf), "#%i %s for life", i, aAddrStr); @@ -1480,7 +1480,7 @@ void CServer::ConchainMaxclientsperipUpdate(IConsole::IResult *pResult, void *pU void CServer::RegisterCommands() { m_pConsole = Kernel()->RequestInterface(); - + Console()->Register("kick", "i?r", CFGFLAG_SERVER, ConKick, this, ""); Console()->Register("ban", "s?ir", CFGFLAG_SERVER|CFGFLAG_STORE, ConBan, this, ""); Console()->Register("unban", "s", CFGFLAG_SERVER|CFGFLAG_STORE, ConUnban, this, ""); @@ -1490,14 +1490,14 @@ void CServer::RegisterCommands() Console()->Register("record", "?s", CFGFLAG_SERVER|CFGFLAG_STORE, ConRecord, this, ""); Console()->Register("stoprecord", "", CFGFLAG_SERVER, ConStopRecord, this, ""); - + Console()->Register("reload", "", CFGFLAG_SERVER, ConMapReload, this, ""); Console()->Chain("sv_name", ConchainSpecialInfoupdate, this); Console()->Chain("password", ConchainSpecialInfoupdate, this); Console()->Chain("sv_max_clients_per_ip", ConchainMaxclientsperipUpdate, this); -} +} int CServer::SnapNewID() @@ -1515,7 +1515,7 @@ void *CServer::SnapNewItem(int Type, int ID, int Size) { dbg_assert(Type >= 0 && Type <=0xffff, "incorrect type"); dbg_assert(ID >= 0 && ID <=0xffff, "incorrect id"); - return ID < 0 ? 0 : m_SnapshotBuilder.NewItem(Type, ID, Size); + return ID < 0 ? 0 : m_SnapshotBuilder.NewItem(Type, ID, Size); } void CServer::SnapSetStaticsize(int ItemType, int Size) @@ -1549,7 +1549,7 @@ int main(int argc, const char **argv) // ignore_convention IEngineMasterServer *pEngineMasterServer = CreateEngineMasterServer(); IStorage *pStorage = CreateStorage("Teeworlds", argc, argv); // ignore_convention IConfig *pConfig = CreateConfig(); - + pServer->InitRegister(&pServer->m_NetServer, pEngineMasterServer, pConsole); { @@ -1565,20 +1565,20 @@ int main(int argc, const char **argv) // ignore_convention RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConfig); RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast(pEngineMasterServer)); // register as both RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast(pEngineMasterServer)); - + if(RegisterFail) return -1; } - + pEngine->Init(); pConfig->Init(); pEngineMasterServer->Init(); pEngineMasterServer->Load(); - + // register all console commands pServer->RegisterCommands(); pGameServer->OnConsoleInit(); - + // execute autoexec file pConsole->ExecuteFile("autoexec.cfg"); @@ -1588,13 +1588,13 @@ int main(int argc, const char **argv) // ignore_convention // restore empty config strings to their defaults pConfig->RestoreStrings(); - + pEngine->InitLogfile(); // run the server dbg_msg("server", "starting..."); pServer->Run(); - + // free delete pServer; delete pKernel; diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 66cac91f3..9a68c9fe9 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -21,17 +21,17 @@ class CSnapIDPool }; CID m_aIDs[MAX_IDS]; - + int m_FirstFree; int m_FirstTimed; int m_LastTimed; int m_Usage; int m_InUsage; - -public: + +public: CSnapIDPool(); - + void Reset(); void RemoveFirstTimeout(); int NewID(); @@ -52,7 +52,7 @@ public: class CClient { public: - + enum { STATE_EMPTY = 0, @@ -60,49 +60,49 @@ public: STATE_CONNECTING, STATE_READY, STATE_INGAME, - + SNAPRATE_INIT=0, SNAPRATE_FULL, SNAPRATE_RECOVER }; - + class CInput { public: int m_aData[MAX_INPUT_SIZE]; int m_GameTick; // the tick that was chosen for the input }; - + // connection state info int m_State; int m_Latency; int m_SnapRate; - + int m_LastAckedSnapshot; int m_LastInputTick; CSnapshotStorage m_Snapshots; - + CInput m_LatestInput; CInput m_aInputs[200]; // TODO: handle input better int m_CurrentInput; - + char m_aName[MAX_NAME_LENGTH]; char m_aClan[MAX_CLAN_LENGTH]; int m_Country; int m_Score; int m_Authed; int m_AuthTries; - + void Reset(); }; - + CClient m_aClients[MAX_CLIENTS]; CSnapshotDelta m_SnapshotDelta; CSnapshotBuilder m_SnapshotBuilder; CSnapIDPool m_IDPool; CNetServer m_NetServer; - + IEngineMap *m_pMap; int64 m_GameStartTime; @@ -117,14 +117,14 @@ public: char m_aCurrentMap[64]; unsigned m_CurrentMapCrc; unsigned char *m_pCurrentMapData; - int m_CurrentMapSize; - + int m_CurrentMapSize; + CDemoRecorder m_DemoRecorder; CRegister m_Register; CMapChecker m_MapChecker; - + CServer(); - + int TrySetClientName(int ClientID, const char *pName); virtual void SetClientName(int ClientID, const char *pName); @@ -162,15 +162,15 @@ public: void SendConnectionReady(int ClientID); void SendRconLine(int ClientID, const char *pLine); static void SendRconLineAuthed(const char *pLine, void *pUser); - + void ProcessClientPacket(CNetChunk *pPacket); - + void SendServerInfo(NETADDR *pAddr, int Token); void UpdateServerInfo(); int BanAdd(NETADDR Addr, int Seconds, const char *pReason); int BanRemove(NETADDR Addr); - + void PumpNetwork(); @@ -193,8 +193,8 @@ public: static void ConchainMaxclientsperipUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); void RegisterCommands(); - - + + virtual int SnapNewID(); virtual void SnapFreeID(int ID); virtual void *SnapNewItem(int Type, int ID, int Size); diff --git a/src/engine/serverbrowser.h b/src/engine/serverbrowser.h index 1ac22056b..3ca59f9cf 100644 --- a/src/engine/serverbrowser.h +++ b/src/engine/serverbrowser.h @@ -28,11 +28,11 @@ public: int m_SortedIndex; int m_ServerIndex; - + NETADDR m_NetAddr; - + int m_QuickSearchHit; - + int m_MaxClients; int m_NumClients; int m_MaxPlayers; @@ -66,11 +66,11 @@ public: SORT_MAP, SORT_GAMETYPE, SORT_NUMPLAYERS, - + QUICK_SERVERNAME=1, QUICK_PLAYER=2, QUICK_MAPNAME=4, - + TYPE_INTERNET = 0, TYPE_LAN = 1, TYPE_FAVORITES = 2, @@ -84,12 +84,12 @@ public: virtual bool IsRefreshing() const = 0; virtual bool IsRefreshingMasters() const = 0; virtual int LoadingProgression() const = 0; - + virtual int NumServers() const = 0; - + virtual int NumSortedServers() const = 0; virtual const CServerInfo *SortedGet(int Index) const = 0; - + virtual bool IsFavorite(const NETADDR &Addr) const = 0; virtual void AddFavorite(const NETADDR &Addr) = 0; virtual void RemoveFavorite(const NETADDR &Addr) = 0; diff --git a/src/engine/shared/compression.cpp b/src/engine/shared/compression.cpp index f14e1cc49..40fe28c48 100644 --- a/src/engine/shared/compression.cpp +++ b/src/engine/shared/compression.cpp @@ -4,9 +4,9 @@ #include "compression.h" -// Format: ESDDDDDD EDDDDDDD EDD... Extended, Data, Sign -unsigned char *CVariableInt::Pack(unsigned char *pDst, int i) -{ +// Format: ESDDDDDD EDDDDDDD EDD... Extended, Data, Sign +unsigned char *CVariableInt::Pack(unsigned char *pDst, int i) +{ *pDst = (i>>25)&0x40; // set sign bit if i<0 i = i^(i>>31); // if(i<0) i = ~i @@ -27,16 +27,16 @@ unsigned char *CVariableInt::Pack(unsigned char *pDst, int i) } pDst++; - return pDst; -} - + return pDst; +} + const unsigned char *CVariableInt::Unpack(const unsigned char *pSrc, int *pInOut) -{ - int Sign = (*pSrc>>6)&1; - *pInOut = *pSrc&0x3F; +{ + int Sign = (*pSrc>>6)&1; + *pInOut = *pSrc&0x3F; do - { + { if(!(*pSrc&0x80)) break; pSrc++; *pInOut |= (*pSrc&(0x7F))<<(6); @@ -56,8 +56,8 @@ const unsigned char *CVariableInt::Unpack(const unsigned char *pSrc, int *pInOut pSrc++; *pInOut ^= -Sign; // if(sign) *i = ~(*i) - return pSrc; -} + return pSrc; +} long CVariableInt::Decompress(const void *pSrc_, int Size, void *pDst_) diff --git a/src/engine/shared/config.cpp b/src/engine/shared/config.cpp index f531fa5a1..b9aa1320e 100644 --- a/src/engine/shared/config.cpp +++ b/src/engine/shared/config.cpp @@ -10,21 +10,21 @@ class CConfig : public IConfig { IStorage *m_pStorage; IOHANDLE m_ConfigFile; - + struct CCallback { SAVECALLBACKFUNC m_pfnFunc; void *m_pUserData; }; - + enum { MAX_CALLBACKS = 16 }; - + CCallback m_aCallbacks[MAX_CALLBACKS]; int m_NumCallbacks; - + void EscapeParam(char *pDst, const char *pSrc, int size) { for(int i = 0; *pSrc && i < size - 1; ++i) @@ -43,22 +43,22 @@ public: m_ConfigFile = 0; m_NumCallbacks = 0; } - + virtual void Init() { m_pStorage = Kernel()->RequestInterface(); Reset(); } - + virtual void Reset() { #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) g_Config.m_##Name = def; #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) str_copy(g_Config.m_##Name, def, len); - #include "config_variables.h" + #include "config_variables.h" - #undef MACRO_CONFIG_INT - #undef MACRO_CONFIG_STR + #undef MACRO_CONFIG_INT + #undef MACRO_CONFIG_STR } virtual void RestoreStrings() @@ -71,34 +71,34 @@ public: #undef MACRO_CONFIG_INT #undef MACRO_CONFIG_STR } - + virtual void Save() { if(!m_pStorage) return; m_ConfigFile = m_pStorage->OpenFile("settings.cfg", IOFLAG_WRITE, IStorage::TYPE_SAVE); - + if(!m_ConfigFile) return; - + char aLineBuf[1024*2]; char aEscapeBuf[1024*2]; #define MACRO_CONFIG_INT(Name,ScriptName,def,min,max,flags,desc) if((flags)&CFGFLAG_SAVE){ str_format(aLineBuf, sizeof(aLineBuf), "%s %i", #ScriptName, g_Config.m_##Name); WriteLine(aLineBuf); } #define MACRO_CONFIG_STR(Name,ScriptName,len,def,flags,desc) if((flags)&CFGFLAG_SAVE){ EscapeParam(aEscapeBuf, g_Config.m_##Name, sizeof(aEscapeBuf)); str_format(aLineBuf, sizeof(aLineBuf), "%s \"%s\"", #ScriptName, aEscapeBuf); WriteLine(aLineBuf); } - #include "config_variables.h" + #include "config_variables.h" + + #undef MACRO_CONFIG_INT + #undef MACRO_CONFIG_STR - #undef MACRO_CONFIG_INT - #undef MACRO_CONFIG_STR - for(int i = 0; i < m_NumCallbacks; i++) m_aCallbacks[i].m_pfnFunc(this, m_aCallbacks[i].m_pUserData); - + io_close(m_ConfigFile); m_ConfigFile = 0; } - + virtual void RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) { dbg_assert(m_NumCallbacks < MAX_CALLBACKS, "too many config callbacks"); @@ -106,7 +106,7 @@ public: m_aCallbacks[m_NumCallbacks].m_pUserData = pUserData; m_NumCallbacks++; } - + virtual void WriteLine(const char *pLine) { if(!m_ConfigFile) @@ -117,7 +117,7 @@ public: static const char Newline[] = "\n"; #endif io_write(m_ConfigFile, pLine, str_length(pLine)); - io_write(m_ConfigFile, Newline, sizeof(Newline)-1); + io_write(m_ConfigFile, Newline, sizeof(Newline)-1); } }; diff --git a/src/engine/shared/config.h b/src/engine/shared/config.h index 9a524d22e..ed89daa21 100644 --- a/src/engine/shared/config.h +++ b/src/engine/shared/config.h @@ -4,12 +4,12 @@ #define ENGINE_SHARED_CONFIG_H struct CConfiguration -{ - #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Save,Desc) int m_##Name; - #define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Save,Desc) char m_##Name[Len]; // Flawfinder: ignore - #include "config_variables.h" - #undef MACRO_CONFIG_INT - #undef MACRO_CONFIG_STR +{ + #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Save,Desc) int m_##Name; + #define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Save,Desc) char m_##Name[Len]; // Flawfinder: ignore + #include "config_variables.h" + #undef MACRO_CONFIG_INT + #undef MACRO_CONFIG_STR }; extern CConfiguration g_Config; diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 8dec21028..eb7f9ca7b 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -56,7 +56,7 @@ MACRO_CONFIG_INT(SndNonactiveMute, snd_nonactive_mute, 0, 0, 1, CFGFLAG_SAVE|CFG 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(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(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)") MACRO_CONFIG_INT(GfxClear, gfx_clear, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Clear screen before rendering") MACRO_CONFIG_INT(GfxVsync, gfx_vsync, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Vertical sync") diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 3241d05df..032ff2ae6 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -38,21 +38,21 @@ int CConsole::ParseStart(CResult *pResult, const char *pString, int Length) int Len = sizeof(pResult->m_aStringStorage); if(Length < Len) Len = Length; - + str_copy(pResult->m_aStringStorage, pString, Length); pStr = pResult->m_aStringStorage; - + // get command pStr = str_skip_whitespaces(pStr); pResult->m_pCommand = pStr; pStr = str_skip_to_whitespace(pStr); - + if(*pStr) { pStr[0] = 0; pStr++; } - + pResult->m_pArgsStart = pStr; return 0; } @@ -63,38 +63,38 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat) char *pStr; int Optional = 0; int Error = 0; - + pStr = pResult->m_pArgsStart; - while(1) + while(1) { // fetch command Command = *pFormat; pFormat++; - + if(!Command) break; - + if(Command == '?') Optional = 1; else { pStr = str_skip_whitespaces(pStr); - + if(!(*pStr)) // error, non optional command needs value { if(!Optional) Error = 1; break; } - + // add token if(*pStr == '"') { char *pDst; pStr++; pResult->AddArgument(pStr); - + pDst = pStr; // we might have to process escape data while(1) { @@ -109,22 +109,22 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat) } else if(pStr[0] == 0) return 1; // return error - + *pDst = *pStr; pDst++; pStr++; } - + // write null termination *pDst = 0; - + pStr++; } else { pResult->AddArgument(pStr); - + if(Command == 'r') // rest of the string break; else if(Command == 'i') // validate int @@ -167,14 +167,14 @@ bool CConsole::LineIsValid(const char *pStr) { if(!pStr || *pStr == 0) return false; - + do { CResult Result; const char *pEnd = pStr; const char *pNextPart = 0; int InString = 0; - + while(*pEnd) { if(*pEnd == '"') @@ -186,25 +186,25 @@ bool CConsole::LineIsValid(const char *pStr) } else if(!InString) { - if(*pEnd == ';') // command separator + if(*pEnd == ';') // command separator { pNextPart = pEnd+1; break; } - else if(*pEnd == '#') // comment, no need to do anything more + else if(*pEnd == '#') // comment, no need to do anything more break; } - + pEnd++; } - + if(ParseStart(&Result, pStr, (pEnd-pStr) + 1) != 0) return false; CCommand *pCommand = FindCommand(Result.m_pCommand, m_FlagMask); if(!pCommand || ParseArgs(&Result, pCommand->m_pParams)) return false; - + pStr = pNextPart; } while(pStr && *pStr); @@ -213,14 +213,14 @@ bool CConsole::LineIsValid(const char *pStr) } void CConsole::ExecuteLineStroked(int Stroke, const char *pStr) -{ +{ while(pStr && *pStr) { CResult Result; const char *pEnd = pStr; const char *pNextPart = 0; int InString = 0; - + while(*pEnd) { if(*pEnd == '"') @@ -232,18 +232,18 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr) } else if(!InString) { - if(*pEnd == ';') // command separator + if(*pEnd == ';') // command separator { pNextPart = pEnd+1; break; } - else if(*pEnd == '#') // comment, no need to do anything more + else if(*pEnd == '#') // comment, no need to do anything more break; } - + pEnd++; } - + if(ParseStart(&Result, pStr, (pEnd-pStr) + 1) != 0) return; @@ -258,7 +258,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr) Result.AddArgument(m_paStrokeStr[Stroke]); IsStrokeCommand = 1; } - + if(Stroke || IsStrokeCommand) { if(ParseArgs(&Result, pCommand->m_pParams)) @@ -284,7 +284,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr) str_format(aBuf, sizeof(aBuf), "No such command: %s.", Result.m_pCommand); Print(OUTPUT_LEVEL_STANDARD, "Console", aBuf); } - + pStr = pNextPart; } } @@ -299,7 +299,7 @@ void CConsole::PossibleCommands(const char *pStr, int FlagMask, FPossibleCallbac if(str_find_nocase(pCommand->m_pName, pStr)) pfnCallback(pCommand->m_pName, pUser); } - } + } } CConsole::CCommand *CConsole::FindCommand(const char *pName, int FlagMask) @@ -312,8 +312,8 @@ CConsole::CCommand *CConsole::FindCommand(const char *pName, int FlagMask) if(str_comp_nocase(pCommand->m_pName, pName) == 0) return pCommand; } - } - + } + return 0x0; } @@ -335,7 +335,7 @@ void CConsole::ExecuteFile(const char *pFilename) m_pStorage = Kernel()->RequestInterface(); if(!m_pStorage) return; - + // push this one to the stack CExecFile ThisFile; CExecFile *pPrev = m_pFirstExec; @@ -345,13 +345,13 @@ void CConsole::ExecuteFile(const char *pFilename) // exec the file IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_READ, IStorage::TYPE_ALL); - + char aBuf[256]; if(File) { char *pLine; CLineReader lr; - + str_format(aBuf, sizeof(aBuf), "executing '%s'", pFilename); Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf); lr.Init(File); @@ -366,7 +366,7 @@ void CConsole::ExecuteFile(const char *pFilename) str_format(aBuf, sizeof(aBuf), "failed to open '%s'", pFilename); Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf); } - + m_pFirstExec = pPrev; } @@ -402,7 +402,7 @@ static void IntVariableCommand(IConsole::IResult *pResult, void *pUserData) if(pResult->NumArguments()) { int Val = pResult->GetInteger(0); - + // do clamping if(pData->m_Min != pData->m_Max) { @@ -468,30 +468,30 @@ CConsole::CConsole(int FlagMask) m_pFirstExec = 0; m_pPrintCallbackUserdata = 0; m_pfnPrintCallback = 0; - + m_pStorage = 0; - + // register some basic commands Register("echo", "r", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Echo, this, "Echo the text"); Register("exec", "r", CFGFLAG_SERVER|CFGFLAG_CLIENT, Con_Exec, this, "Execute the specified file"); - + // TODO: this should disappear #define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Flags,Desc) \ { \ static CIntVariableData Data = { this, &g_Config.m_##Name, Min, Max }; \ Register(#ScriptName, "?i", Flags, IntVariableCommand, &Data, Desc); \ } - + #define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Flags,Desc) \ { \ static CStrVariableData Data = { this, g_Config.m_##Name, Len }; \ Register(#ScriptName, "?r", Flags, StrVariableCommand, &Data, Desc); \ } - #include "config_variables.h" + #include "config_variables.h" - #undef MACRO_CONFIG_INT - #undef MACRO_CONFIG_STR + #undef MACRO_CONFIG_INT + #undef MACRO_CONFIG_STR } void CConsole::ParseArguments(int NumArgs, const char **ppArguments) @@ -518,7 +518,7 @@ void CConsole::ParseArguments(int NumArgs, const char **ppArguments) } } -void CConsole::Register(const char *pName, const char *pParams, +void CConsole::Register(const char *pName, const char *pParams, int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp) { CCommand *pCommand = (CCommand *)mem_alloc(sizeof(CCommand), sizeof(void*)); @@ -528,8 +528,8 @@ void CConsole::Register(const char *pName, const char *pParams, pCommand->m_pName = pName; pCommand->m_pParams = pParams; pCommand->m_Flags = Flags; - - + + pCommand->m_pNext = m_pFirstCommand; m_pFirstCommand = pCommand; } @@ -543,7 +543,7 @@ void CConsole::Con_Chain(IResult *pResult, void *pUserData) void CConsole::Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser) { CCommand *pCommand = FindCommand(pName, m_FlagMask); - + if(!pCommand) { char aBuf[256]; @@ -551,7 +551,7 @@ void CConsole::Chain(const char *pName, FChainCommandCallback pfnChainFunc, void Print(IConsole::OUTPUT_LEVEL_DEBUG, "console", aBuf); return; } - + CChain *pChainInfo = (CChain *)mem_alloc(sizeof(CChain), sizeof(void*)); // store info @@ -559,7 +559,7 @@ void CConsole::Chain(const char *pName, FChainCommandCallback pfnChainFunc, void pChainInfo->m_pUserData = pUser; pChainInfo->m_pfnCallback = pCommand->m_pfnCallback; pChainInfo->m_pCallbackUserData = pCommand->m_pUserData; - + // chain pCommand->m_pfnCallback = Con_Chain; pCommand->m_pUserData = pChainInfo; diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h index a276751ae..77c46fb0c 100644 --- a/src/engine/shared/console.h +++ b/src/engine/shared/console.h @@ -16,7 +16,7 @@ class CConsole : public IConsole FCommandCallback m_pfnCallback; void *m_pUserData; }; - + class CChain { @@ -25,8 +25,8 @@ class CConsole : public IConsole FCommandCallback m_pfnCallback; void *m_pCallbackUserData; void *m_pUserData; - }; - + }; + int m_FlagMask; bool m_StoreCommands; const char *m_paStrokeStr[2]; @@ -38,7 +38,7 @@ class CConsole : public IConsole const char *m_pFilename; struct CExecFile *m_pPrev; }; - + CExecFile *m_pFirstExec; class IStorage *m_pStorage; @@ -48,22 +48,22 @@ class CConsole : public IConsole void ExecuteFileRecurse(const char *pFilename); void ExecuteLineStroked(int Stroke, const char *pStr); - + FPrintCallback m_pfnPrintCallback; void *m_pPrintCallbackUserdata; enum { - CONSOLE_MAX_STR_LENGTH = 1024, + CONSOLE_MAX_STR_LENGTH = 1024, MAX_PARTS = (CONSOLE_MAX_STR_LENGTH+1)/2 }; - + class CResult : public IResult { public: char m_aStringStorage[CONSOLE_MAX_STR_LENGTH+1]; char *m_pArgsStart; - + const char *m_pCommand; const char *m_apArgs[MAX_PARTS]; @@ -89,7 +89,7 @@ class CConsole : public IConsole } return *this; } - + void AddArgument(const char *pArg) { m_apArgs[m_NumArgs++] = pArg; @@ -99,7 +99,7 @@ class CConsole : public IConsole virtual int GetInteger(unsigned Index); virtual float GetFloat(unsigned Index); }; - + int ParseStart(CResult *pResult, const char *pString, int Length); int ParseArgs(CResult *pResult, const char *pFormat); @@ -146,7 +146,7 @@ public: virtual void Register(const char *pName, const char *pParams, int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp); virtual void Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser); virtual void StoreCommands(bool Store); - + virtual bool LineIsValid(const char *pStr); virtual void ExecuteLine(const char *pStr); virtual void ExecuteFile(const char *pFilename); diff --git a/src/engine/shared/datafile.cpp b/src/engine/shared/datafile.cpp index 74936ea09..3a5a4b1d5 100644 --- a/src/engine/shared/datafile.cpp +++ b/src/engine/shared/datafile.cpp @@ -75,9 +75,9 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int { dbg_msg("datafile", "could not open '%s'", pFilename); return false; - } - - + } + + // take the CRC of the file and store it unsigned Crc = 0; { @@ -85,9 +85,9 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int { BUFFER_SIZE = 64*1024 }; - + unsigned char aBuffer[BUFFER_SIZE]; - + while(1) { unsigned Bytes = io_read(File, aBuffer, BUFFER_SIZE); @@ -95,11 +95,11 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int break; Crc = crc32(Crc, aBuffer, Bytes); // ignore_convention } - + io_seek(File, 0, IOSEEK_START); } - - + + // TODO: change this header CDatafileHeader Header; io_read(File, &Header, sizeof(Header)); @@ -113,14 +113,14 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int } #if defined(CONF_ARCH_ENDIAN_BIG) - swap_endian(&Header, sizeof(int), sizeof(Header)/sizeof(int)); + swap_endian(&Header, sizeof(int), sizeof(Header)/sizeof(int)); #endif if(Header.m_Version != 3 && Header.m_Version != 4) { dbg_msg("datafile", "wrong version. version=%x", Header.m_Version); return 0; } - + // read in the rest except the data unsigned Size = 0; Size += Header.m_NumItemTypes*sizeof(CDatafileItemType); @@ -128,7 +128,7 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int if(Header.m_Version == 4) Size += Header.m_NumRawData*sizeof(int); // v4 has uncompressed data sizes aswell Size += Header.m_ItemSize; - + unsigned AllocSize = Size; AllocSize += sizeof(CDatafile); // add space for info structure AllocSize += Header.m_NumRawData*sizeof(void*); // add space for data pointers @@ -140,10 +140,10 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int pTmpDataFile->m_pData = (char *)(pTmpDataFile+1)+Header.m_NumRawData*sizeof(char *); pTmpDataFile->m_File = File; pTmpDataFile->m_Crc = Crc; - + // clear the data pointers mem_zero(pTmpDataFile->m_ppDataPtrs, Header.m_NumRawData*sizeof(void*)); - + // read types, offsets, sizes and item data unsigned ReadSize = io_read(File, pTmpDataFile->m_pData, Size); if(ReadSize != Size) @@ -169,12 +169,12 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int dbg_msg("datafile", "swaplen=%d", Header.m_Swaplen); dbg_msg("datafile", "item_size=%d", m_pDataFile->m_Header.m_ItemSize); } - + m_pDataFile->m_Info.m_pItemTypes = (CDatafileItemType *)m_pDataFile->m_pData; m_pDataFile->m_Info.m_pItemOffsets = (int *)&m_pDataFile->m_Info.m_pItemTypes[m_pDataFile->m_Header.m_NumItemTypes]; m_pDataFile->m_Info.m_pDataOffsets = (int *)&m_pDataFile->m_Info.m_pItemOffsets[m_pDataFile->m_Header.m_NumItems]; m_pDataFile->m_Info.m_pDataSizes = (int *)&m_pDataFile->m_Info.m_pDataOffsets[m_pDataFile->m_Header.m_NumRawData]; - + if(Header.m_Version == 4) m_pDataFile->m_Info.m_pItemStart = (char *)&m_pDataFile->m_Info.m_pDataSizes[m_pDataFile->m_Header.m_NumRawData]; else @@ -191,7 +191,7 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int void *p = datafile_get_data(df, i); dbg_msg("datafile", "%d %d", (int)((char*)p - (char*)(&m_pDataFile->data)), size); } - + for(int i = 0; i < datafile_num_items(df); i++) { int type, id; @@ -218,7 +218,7 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int } */ } - + return true; } @@ -227,7 +227,7 @@ bool CDataFileReader::GetCrcSize(class IStorage *pStorage, const char *pFilename IOHANDLE File = pStorage->OpenFile(pFilename, IOFLAG_READ, StorageType); if(!File) return false; - + // get crc and size unsigned Crc = 0; unsigned Size = 0; @@ -240,7 +240,7 @@ bool CDataFileReader::GetCrcSize(class IStorage *pStorage, const char *pFilename Crc = crc32(Crc, aBuffer, Bytes); // ignore_convention Size += Bytes; } - + io_close(File); *pCrc = Crc; @@ -258,23 +258,23 @@ int CDataFileReader::NumData() int CDataFileReader::GetDataSize(int Index) { if(!m_pDataFile) { return 0; } - + if(Index == m_pDataFile->m_Header.m_NumRawData-1) return m_pDataFile->m_Header.m_DataSize-m_pDataFile->m_Info.m_pDataOffsets[Index]; - return m_pDataFile->m_Info.m_pDataOffsets[Index+1]-m_pDataFile->m_Info.m_pDataOffsets[Index]; + return m_pDataFile->m_Info.m_pDataOffsets[Index+1]-m_pDataFile->m_Info.m_pDataOffsets[Index]; } void *CDataFileReader::GetDataImpl(int Index, int Swap) { if(!m_pDataFile) { return 0; } - + // load it if needed if(!m_pDataFile->m_ppDataPtrs[Index]) { // fetch the data size int DataSize = GetDataSize(Index); int SwapSize = DataSize; - + if(m_pDataFile->m_Header.m_Version == 4) { // v4 has compressed data @@ -284,7 +284,7 @@ void *CDataFileReader::GetDataImpl(int Index, int Swap) dbg_msg("datafile", "loading data index=%d size=%d uncompressed=%d", Index, DataSize, UncompressedSize); m_pDataFile->m_ppDataPtrs[Index] = (char *)mem_alloc(UncompressedSize, 1); - + // read the compressed data io_seek(m_pDataFile->m_File, m_pDataFile->m_DataStartOffset+m_pDataFile->m_Info.m_pDataOffsets[Index], IOSEEK_START); io_read(m_pDataFile->m_File, pTemp, DataSize); @@ -311,7 +311,7 @@ void *CDataFileReader::GetDataImpl(int Index, int Swap) swap_endian(m_pDataFile->m_ppDataPtrs[Index], sizeof(int), SwapSize/sizeof(int)); #endif } - + return m_pDataFile->m_ppDataPtrs[Index]; } @@ -329,7 +329,7 @@ void CDataFileReader::UnloadData(int Index) { if(Index < 0) return; - + // mem_free(m_pDataFile->m_ppDataPtrs[Index]); m_pDataFile->m_ppDataPtrs[Index] = 0x0; @@ -340,13 +340,13 @@ int CDataFileReader::GetItemSize(int Index) if(!m_pDataFile) { return 0; } if(Index == m_pDataFile->m_Header.m_NumItems-1) return m_pDataFile->m_Header.m_ItemSize-m_pDataFile->m_Info.m_pItemOffsets[Index]; - return m_pDataFile->m_Info.m_pItemOffsets[Index+1]-m_pDataFile->m_Info.m_pItemOffsets[Index]; + return m_pDataFile->m_Info.m_pItemOffsets[Index+1]-m_pDataFile->m_Info.m_pItemOffsets[Index]; } void *CDataFileReader::GetItem(int Index, int *pType, int *pID) { if(!m_pDataFile) { if(pType) *pType = 0; if(pID) *pID = 0; return 0; } - + CDatafileItem *i = (CDatafileItem *)(m_pDataFile->m_Info.m_pItemStart+m_pDataFile->m_Info.m_pItemOffsets[Index]); if(pType) *pType = (i->m_TypeAndID>>16)&0xffff; // remove sign extention @@ -362,7 +362,7 @@ void CDataFileReader::GetType(int Type, int *pStart, int *pNum) if(!m_pDataFile) return; - + for(int i = 0; i < m_pDataFile->m_Header.m_NumItemTypes; i++) { if(m_pDataFile->m_Info.m_pItemTypes[i].m_Type == Type) @@ -377,7 +377,7 @@ void CDataFileReader::GetType(int Type, int *pStart, int *pNum) void *CDataFileReader::FindItem(int Type, int ID) { if(!m_pDataFile) return 0; - + int Start, Num; GetType(Type, &Start, &Num); for(int i = 0; i < Num; i++) @@ -400,12 +400,12 @@ bool CDataFileReader::Close() { if(!m_pDataFile) return true; - + // free the data that is loaded int i; for(i = 0; i < m_pDataFile->m_Header.m_NumRawData; i++) mem_free(m_pDataFile->m_ppDataPtrs[i]); - + io_close(m_pDataFile->m_File); mem_free(m_pDataFile); m_pDataFile = 0; @@ -424,7 +424,7 @@ bool CDataFileWriter::Open(class IStorage *pStorage, const char *pFilename) m_File = pStorage->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); if(!m_File) return false; - + m_NumItems = 0; m_NumDatas = 0; m_NumItemTypes = 0; @@ -435,7 +435,7 @@ bool CDataFileWriter::Open(class IStorage *pStorage, const char *pFilename) m_aItemTypes[i].m_First = -1; m_aItemTypes[i].m_Last = -1; } - + return true; } @@ -450,7 +450,7 @@ int CDataFileWriter::AddItem(int Type, int ID, int Size, void *pData) m_aItems[m_NumItems].m_Type = Type; m_aItems[m_NumItems].m_ID = ID; m_aItems[m_NumItems].m_Size = Size; - + // copy data m_aItems[m_NumItems].m_pData = mem_alloc(Size, 1); mem_copy(m_aItems[m_NumItems].m_pData, pData, Size); @@ -461,16 +461,16 @@ int CDataFileWriter::AddItem(int Type, int ID, int Size, void *pData) // link m_aItems[m_NumItems].m_Prev = m_aItemTypes[Type].m_Last; m_aItems[m_NumItems].m_Next = -1; - + if(m_aItemTypes[Type].m_Last != -1) m_aItems[m_aItemTypes[Type].m_Last].m_Next = m_NumItems; m_aItemTypes[Type].m_Last = m_NumItems; - + if(m_aItemTypes[Type].m_First == -1) m_aItemTypes[Type].m_First = m_NumItems; - + m_aItemTypes[Type].m_Num++; - + m_NumItems++; return m_NumItems-1; } @@ -491,7 +491,7 @@ int CDataFileWriter::AddData(int Size, void *pData) dbg_msg("datafile", "compression error %d", Result); dbg_assert(0, "zlib error"); } - + pInfo->m_UncompressedSize = Size; pInfo->m_CompressedSize = (int)s; pInfo->m_pCompressedData = mem_alloc(pInfo->m_CompressedSize, 1); @@ -539,23 +539,23 @@ int CDataFileWriter::Finish() dbg_msg("datafile", "item=%d size=%d (%d)", i, m_aItems[i].m_Size, m_aItems[i].m_Size+sizeof(CDatafileItem)); ItemSize += m_aItems[i].m_Size + sizeof(CDatafileItem); } - - + + for(int i = 0; i < m_NumDatas; i++) DataSize += m_aDatas[i].m_CompressedSize; - + // calculate the complete size TypesSize = m_NumItemTypes*sizeof(CDatafileItemType); HeaderSize = sizeof(CDatafileHeader); OffsetSize = (m_NumItems + m_NumDatas + m_NumDatas) * sizeof(int); // ItemOffsets, DataOffsets, DataUncompressedSizes FileSize = HeaderSize + TypesSize + OffsetSize + ItemSize + DataSize; SwapSize = FileSize - DataSize; - + (void)SwapSize; - + if(DEBUG) dbg_msg("datafile", "num_m_aItemTypes=%d TypesSize=%d m_aItemsize=%d DataSize=%d", m_NumItemTypes, TypesSize, ItemSize, DataSize); - + // construct Header { Header.m_aID[0] = 'D'; @@ -570,7 +570,7 @@ int CDataFileWriter::Finish() Header.m_NumRawData = m_NumDatas; Header.m_ItemSize = ItemSize; Header.m_DataSize = DataSize; - + // write Header if(DEBUG) dbg_msg("datafile", "HeaderSize=%d", sizeof(Header)); @@ -579,7 +579,7 @@ int CDataFileWriter::Finish() #endif io_write(m_File, &Header, sizeof(Header)); } - + // write types for(int i = 0, Count = 0; i < 0xffff; i++) { @@ -599,7 +599,7 @@ int CDataFileWriter::Finish() Count += m_aItemTypes[i].m_Num; } } - + // write item offsets for(int i = 0, Offset = 0; i < 0xffff; i++) { @@ -617,13 +617,13 @@ int CDataFileWriter::Finish() #endif io_write(m_File, &Temp, sizeof(Temp)); Offset += m_aItems[k].m_Size + sizeof(CDatafileItem); - + // next k = m_aItems[k].m_Next; } } } - + // write data offsets for(int i = 0, Offset = 0; i < m_NumDatas; i++) { @@ -648,7 +648,7 @@ int CDataFileWriter::Finish() #endif io_write(m_File, &UncompressedSize, sizeof(UncompressedSize)); } - + // write m_aItems for(int i = 0; i < 0xffff; i++) { @@ -663,20 +663,20 @@ int CDataFileWriter::Finish() Item.m_Size = m_aItems[k].m_Size; if(DEBUG) dbg_msg("datafile", "writing item type=%x idx=%d id=%d size=%d", i, k, m_aItems[k].m_ID, m_aItems[k].m_Size); - + #if defined(CONF_ARCH_ENDIAN_BIG) swap_endian(&Item, sizeof(int), sizeof(Item)/sizeof(int)); swap_endian(m_aItems[k].m_pData, sizeof(int), m_aItems[k].m_Size/sizeof(int)); #endif io_write(m_File, &Item, sizeof(Item)); io_write(m_File, m_aItems[k].m_pData, m_aItems[k].m_Size); - + // next k = m_aItems[k].m_Next; } } } - + // write data for(int i = 0; i < m_NumDatas; i++) { @@ -690,10 +690,10 @@ int CDataFileWriter::Finish() mem_free(m_aItems[i].m_pData); for(int i = 0; i < m_NumDatas; ++i) mem_free(m_aDatas[i].m_pCompressedData); - + io_close(m_File); m_File = 0; - + if(DEBUG) dbg_msg("datafile", "done"); return 0; diff --git a/src/engine/shared/datafile.h b/src/engine/shared/datafile.h index 15bed0339..46e8ada81 100644 --- a/src/engine/shared/datafile.h +++ b/src/engine/shared/datafile.h @@ -11,14 +11,14 @@ class CDataFileReader public: CDataFileReader() : m_pDataFile(0) {} ~CDataFileReader() { Close(); } - + bool IsOpen() const { return m_pDataFile != 0; } - + bool Open(class IStorage *pStorage, const char *pFilename, int StorageType); bool Close(); static bool GetCrcSize(class IStorage *pStorage, const char *pFilename, int StorageType, unsigned *pCrc, unsigned *pSize); - + void *GetData(int Index); void *GetDataSwapped(int Index); // makes sure that the data is 32bit LE ints when saved int GetDataSize(int Index); @@ -30,7 +30,7 @@ public: int NumItems(); int NumData(); void Unload(); - + unsigned Crc(); }; @@ -60,15 +60,15 @@ class CDataFileWriter int m_First; int m_Last; }; - + IOHANDLE m_File; int m_NumItems; int m_NumDatas; int m_NumItemTypes; CItemTypeInfo m_aItemTypes[0xffff]; CItemInfo m_aItems[1024]; - CDataInfo m_aDatas[1024]; - + CDataInfo m_aDatas[1024]; + public: CDataFileWriter() : m_File(0) {} bool Open(class IStorage *pStorage, const char *Filename); diff --git a/src/engine/shared/demo.cpp b/src/engine/shared/demo.cpp index ac78f22f0..e48c2f1e4 100644 --- a/src/engine/shared/demo.cpp +++ b/src/engine/shared/demo.cpp @@ -47,7 +47,7 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con char aBuf[512]; str_format(aMapFilename, sizeof(aMapFilename), "%s.map", pMap); if(pStorage->FindFile(aMapFilename, "maps", IStorage::TYPE_ALL, aBuf, sizeof(aBuf))) - MapFile = pStorage->OpenFile(aBuf, IOFLAG_READ, IStorage::TYPE_ALL); + MapFile = pStorage->OpenFile(aBuf, IOFLAG_READ, IStorage::TYPE_ALL); } if(!MapFile) { @@ -67,7 +67,7 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", aBuf); return -1; } - + // write header mem_zero(&Header, sizeof(Header)); mem_copy(Header.m_aMarker, gs_aHeaderMarker, sizeof(Header.m_aMarker)); @@ -87,7 +87,7 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con // Header.m_Length - add this on stop str_timestamp(Header.m_aTimestamp, sizeof(Header.m_aTimestamp)); io_write(DemoFile, &Header, sizeof(Header)); - + // write map data while(1) { @@ -98,11 +98,11 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con io_write(DemoFile, &aChunk, Bytes); } io_close(MapFile); - + m_LastKeyFrame = -1; m_LastTickMarker = -1; m_FirstTick = -1; - + char aBuf[256]; str_format(aBuf, sizeof(aBuf), "Recording to '%s'", pFilename); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", aBuf); @@ -113,25 +113,25 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con /* Tickmarker - 7 = Always set - 6 = Keyframe flag - 0-5 = Delta tick - + 7 = Always set + 6 = Keyframe flag + 0-5 = Delta tick + Normal - 7 = Not set - 5-6 = Type - 0-4 = Size + 7 = Not set + 5-6 = Type + 0-4 = Size */ enum { CHUNKTYPEFLAG_TICKMARKER = 0x80, CHUNKTICKFLAG_KEYFRAME = 0x40, // only when tickmarker is set - + CHUNKMASK_TICK = 0x3f, CHUNKMASK_TYPE = 0x60, CHUNKMASK_SIZE = 0x1f, - + CHUNKTYPE_SNAPSHOT = 1, CHUNKTYPE_MESSAGE = 2, CHUNKTYPE_DELTA = 3, @@ -152,7 +152,7 @@ void CDemoRecorder::WriteTickMarker(int Tick, int Keyframe) if(Keyframe) aChunk[0] |= CHUNKTICKFLAG_KEYFRAME; - + io_write(m_File, aChunk, sizeof(aChunk)); } else @@ -160,7 +160,7 @@ void CDemoRecorder::WriteTickMarker(int Tick, int Keyframe) unsigned char aChunk[1]; aChunk[0] = CHUNKTYPEFLAG_TICKMARKER | (Tick-m_LastTickMarker); io_write(m_File, aChunk, sizeof(aChunk)); - } + } m_LastTickMarker = Tick; if(m_FirstTick < 0) @@ -172,7 +172,7 @@ void CDemoRecorder::Write(int Type, const void *pData, int Size) char aBuffer[64*1024]; char aBuffer2[64*1024]; unsigned char aChunk[3]; - + if(!m_File) return; @@ -183,8 +183,8 @@ void CDemoRecorder::Write(int Type, const void *pData, int Size) aBuffer2[Size++] = 0; Size = CVariableInt::Compress(aBuffer2, Size, aBuffer); // buffer2 -> buffer Size = CNetBase::Compress(aBuffer, Size, aBuffer2, sizeof(aBuffer2)); // buffer -> buffer2 - - + + aChunk[0] = ((Type&0x3)<<5); if(Size < 30) { @@ -207,7 +207,7 @@ void CDemoRecorder::Write(int Type, const void *pData, int Size) io_write(m_File, aChunk, 3); } } - + io_write(m_File, aBuffer2, Size); } @@ -217,10 +217,10 @@ void CDemoRecorder::RecordSnapshot(int Tick, const void *pData, int Size) { // write full tickmarker WriteTickMarker(Tick, 1); - + // write snapshot Write(CHUNKTYPE_SNAPSHOT, pData, Size); - + m_LastKeyFrame = Tick; mem_copy(m_aLastSnapshotData, pData, Size); } @@ -232,7 +232,7 @@ void CDemoRecorder::RecordSnapshot(int Tick, const void *pData, int Size) // write tickmarker WriteTickMarker(Tick, 0); - + DeltaSize = m_pSnapshotDelta->CreateDelta((CSnapshot*)m_aLastSnapshotData, (CSnapshot*)pData, &aDeltaData); if(DeltaSize) { @@ -262,7 +262,7 @@ int CDemoRecorder::Stop() aLength[2] = (DemoLength>>8)&0xff; aLength[3] = (DemoLength)&0xff; io_write(m_File, aLength, sizeof(aLength)); - + io_close(m_File); m_File = 0; m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", "Stopped recording"); @@ -290,19 +290,19 @@ void CDemoPlayer::SetListner(IListner *pListner) int CDemoPlayer::ReadChunkHeader(int *pType, int *pSize, int *pTick) { unsigned char Chunk = 0; - + *pSize = 0; *pType = 0; - + if(io_read(m_File, &Chunk, sizeof(Chunk)) != sizeof(Chunk)) return -1; - + if(Chunk&CHUNKTYPEFLAG_TICKMARKER) { // decode tick marker int Tickdelta = Chunk&(CHUNKMASK_TICK); *pType = Chunk&(CHUNKTYPEFLAG_TICKMARKER|CHUNKTICKFLAG_KEYFRAME); - + if(Tickdelta == 0) { unsigned char aTickdata[4]; @@ -314,21 +314,21 @@ int CDemoPlayer::ReadChunkHeader(int *pType, int *pSize, int *pTick) { *pTick += Tickdelta; } - + } else { // decode normal chunk *pType = (Chunk&CHUNKMASK_TYPE)>>5; *pSize = Chunk&CHUNKMASK_SIZE; - + if(*pSize == 30) { unsigned char aSizedata[1]; if(io_read(m_File, aSizedata, sizeof(aSizedata)) != sizeof(aSizedata)) return -1; *pSize = aSizedata[0]; - + } else if(*pSize == 31) { @@ -338,7 +338,7 @@ int CDemoPlayer::ReadChunkHeader(int *pType, int *pSize, int *pTick) *pSize = (aSizedata[1]<<8) | aSizedata[0]; } } - + return 0; } @@ -358,17 +358,17 @@ void CDemoPlayer::ScanFile() while(1) { long CurrentPos = io_tell(m_File); - + if(ReadChunkHeader(&ChunkType, &ChunkSize, &ChunkTick)) break; - + // read the chunk if(ChunkType&CHUNKTYPEFLAG_TICKMARKER) { if(ChunkType&CHUNKTICKFLAG_KEYFRAME) { CKeyFrameSearch *pKey; - + // save the position pKey = (CKeyFrameSearch *)Heap.Allocate(sizeof(CKeyFrameSearch)); pKey->m_Frame.m_Filepos = CurrentPos; @@ -381,21 +381,21 @@ void CDemoPlayer::ScanFile() pCurrentKey = pKey; m_Info.m_SeekablePoints++; } - + if(m_Info.m_Info.m_FirstTick == -1) m_Info.m_Info.m_FirstTick = ChunkTick; m_Info.m_Info.m_LastTick = ChunkTick; } else if(ChunkSize) io_skip(m_File, ChunkSize); - + } // copy all the frames to an array instead for fast access m_pKeyFrames = (CKeyFrame*)mem_alloc(m_Info.m_SeekablePoints*sizeof(CKeyFrame), 1); for(pCurrentKey = pFirstKey, i = 0; pCurrentKey; pCurrentKey = pCurrentKey->m_pNext, i++) m_pKeyFrames[i] = pCurrentKey->m_Frame; - + // destroy the temporary heap and seek back to the start io_seek(m_File, StartPos, IOSEEK_START); } @@ -429,7 +429,7 @@ void CDemoPlayer::DoTick() Pause(); break; } - + // read the chunk if(ChunkSize) { @@ -440,7 +440,7 @@ void CDemoPlayer::DoTick() Stop(); break; } - + DataSize = CNetBase::Decompress(aCompresseddata, ChunkSize, aDecompressed, sizeof(aDecompressed)); if(DataSize < 0) { @@ -449,7 +449,7 @@ void CDemoPlayer::DoTick() Stop(); break; } - + DataSize = CVariableInt::Decompress(aDecompressed, DataSize, aData); if(DataSize < 0) @@ -459,16 +459,16 @@ void CDemoPlayer::DoTick() break; } } - + if(ChunkType == CHUNKTYPE_DELTA) { // process delta snapshot static char aNewsnap[CSnapshot::MAX_SIZE]; - + GotSnapshot = 1; - + DataSize = m_pSnapshotDelta->UnpackDelta((CSnapshot*)m_aLastSnapshotData, (CSnapshot*)aNewsnap, aData, DataSize); - + if(DataSize >= 0) { if(m_pListner) @@ -488,7 +488,7 @@ void CDemoPlayer::DoTick() { // process full snapshot GotSnapshot = 1; - + m_LastSnapshotDataSize = DataSize; mem_copy(m_aLastSnapshotData, aData, DataSize); if(m_pListner) @@ -502,7 +502,7 @@ void CDemoPlayer::DoTick() GotSnapshot = 1; m_pListner->OnDemoPlayerSnapshot(m_aLastSnapshotData, m_LastSnapshotDataSize); } - + // check the remaining types if(ChunkType&CHUNKTYPEFLAG_TICKMARKER) { @@ -544,7 +544,7 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_player", aBuf); return -1; } - + // store the filename str_copy(m_aFilename, pFilename, sizeof(m_aFilename)); @@ -556,7 +556,7 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const m_Info.m_Info.m_CurrentTick = -1; m_Info.m_PreviousTick = -1; m_Info.m_Info.m_Speed = 1; - + m_LastSnapshotDataSize = -1; // read the header @@ -580,7 +580,7 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const m_File = 0; return -1; } - + // get demo type if(!str_comp(m_Info.m_Header.m_aType, "client")) m_DemoType = DEMOTYPE_CLIENT; @@ -588,17 +588,17 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const m_DemoType = DEMOTYPE_SERVER; else m_DemoType = DEMOTYPE_INVALID; - + // read map unsigned MapSize = (m_Info.m_Header.m_aMapSize[0]<<24) | (m_Info.m_Header.m_aMapSize[1]<<16) | (m_Info.m_Header.m_aMapSize[2]<<8) | (m_Info.m_Header.m_aMapSize[3]); - + // check if we already have the map // TODO: improve map checking (maps folder, check crc) unsigned Crc = (m_Info.m_Header.m_aMapCrc[0]<<24) | (m_Info.m_Header.m_aMapCrc[1]<<16) | (m_Info.m_Header.m_aMapCrc[2]<<8) | (m_Info.m_Header.m_aMapCrc[3]); char aMapFilename[128]; str_format(aMapFilename, sizeof(aMapFilename), "downloadedmaps/%s_%08x.map", m_Info.m_Header.m_aMapName, Crc); IOHANDLE MapFile = pStorage->OpenFile(aMapFilename, IOFLAG_READ, IStorage::TYPE_ALL); - + if(MapFile) { io_skip(m_File, MapSize); @@ -609,20 +609,20 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const // get map data unsigned char *pMapData = (unsigned char *)mem_alloc(MapSize, 1); io_read(m_File, pMapData, MapSize); - + // save map MapFile = pStorage->OpenFile(aMapFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); io_write(MapFile, pMapData, MapSize); io_close(MapFile); - + // free data mem_free(pMapData); } - - + + // scan the file for interessting points ScanFile(); - + // ready for playback return 0; } @@ -638,7 +638,7 @@ int CDemoPlayer::Play() // fill in previous and next tick while(m_Info.m_PreviousTick == -1 && IsPlaying()) DoTick(); - + // set start info /*m_Info.start_tick = m_Info.previous_tick; m_Info.start_time = time_get();*/ @@ -653,15 +653,15 @@ int CDemoPlayer::SetPos(float Percent) int WantedTick; if(!m_File) return -1; - + // -5 because we have to have a current tick and previous tick when we do the playback WantedTick = m_Info.m_Info.m_FirstTick + (int)((m_Info.m_Info.m_LastTick-m_Info.m_Info.m_FirstTick)*Percent) - 5; - + Keyframe = (int)(m_Info.m_SeekablePoints*Percent); if(Keyframe < 0 || Keyframe >= m_Info.m_SeekablePoints) return -1; - + // get correct key frame if(m_pKeyFrames[Keyframe].m_Tick < WantedTick) while(Keyframe < m_Info.m_SeekablePoints-1 && m_pKeyFrames[Keyframe].m_Tick < WantedTick) @@ -669,7 +669,7 @@ int CDemoPlayer::SetPos(float Percent) while(Keyframe && m_pKeyFrames[Keyframe].m_Tick > WantedTick) Keyframe--; - + // seek to the correct keyframe io_seek(m_File, m_pKeyFrames[Keyframe].m_Filepos, IOSEEK_START); @@ -681,9 +681,9 @@ int CDemoPlayer::SetPos(float Percent) // playback everything until we hit our tick while(m_Info.m_PreviousTick < WantedTick) DoTick(); - + Play(); - + return 0; } @@ -697,19 +697,19 @@ int CDemoPlayer::Update() int64 Now = time_get(); int64 Deltatime = Now-m_Info.m_LastUpdate; m_Info.m_LastUpdate = Now; - + if(!IsPlaying()) return 0; - + if(m_Info.m_Info.m_Paused) { - + } else { int64 Freq = time_freq(); m_Info.m_CurrentTime += (int64)(Deltatime*(double)m_Info.m_Info.m_Speed); - + while(1) { int64 CurtickStart = (m_Info.m_Info.m_CurrentTick)*Freq/SERVER_TICK_SPEED; @@ -717,22 +717,22 @@ int CDemoPlayer::Update() // break if we are ready if(CurtickStart > m_Info.m_CurrentTime) break; - + // do one more tick DoTick(); - + if(m_Info.m_Info.m_Paused) return 0; } // update intratick - { + { int64 CurtickStart = (m_Info.m_Info.m_CurrentTick)*Freq/SERVER_TICK_SPEED; int64 PrevtickStart = (m_Info.m_PreviousTick)*Freq/SERVER_TICK_SPEED; m_Info.m_IntraTick = (m_Info.m_CurrentTime - PrevtickStart) / (float)(CurtickStart-PrevtickStart); m_Info.m_TickTime = (m_Info.m_CurrentTime - PrevtickStart) / (float)Freq; } - + if(m_Info.m_Info.m_CurrentTick == m_Info.m_PreviousTick || m_Info.m_Info.m_CurrentTick == m_Info.m_NextTick) { @@ -742,7 +742,7 @@ int CDemoPlayer::Update() m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "demo_player", aBuf); } } - + return 0; } @@ -750,7 +750,7 @@ int CDemoPlayer::Stop() { if(!m_File) return -1; - + m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_player", "Stopped playback"); io_close(m_File); m_File = 0; @@ -776,20 +776,20 @@ bool CDemoPlayer::GetDemoInfo(class IStorage *pStorage, const char *pFilename, i { if(!pDemoHeader) return false; - + mem_zero(pDemoHeader, sizeof(CDemoHeader)); IOHANDLE File = pStorage->OpenFile(pFilename, IOFLAG_READ, StorageType); if(!File) return false; - + io_read(File, pDemoHeader, sizeof(CDemoHeader)); if(mem_comp(pDemoHeader->m_aMarker, gs_aHeaderMarker, sizeof(gs_aHeaderMarker)) || pDemoHeader->m_Version < gs_ActVersion) { io_close(File); return false; } - + io_close(File); return true; } diff --git a/src/engine/shared/demo.h b/src/engine/shared/demo.h index c877536dd..f1897f21e 100644 --- a/src/engine/shared/demo.h +++ b/src/engine/shared/demo.h @@ -17,12 +17,12 @@ class CDemoRecorder : public IDemoRecorder int m_FirstTick; unsigned char m_aLastSnapshotData[CSnapshot::MAX_SIZE]; class CSnapshotDelta *m_pSnapshotDelta; - + void WriteTickMarker(int Tick, int Keyframe); void Write(int Type, const void *pData, int Size); public: CDemoRecorder(class CSnapshotDelta *pSnapshotDelta); - + int Start(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, const char *pNetversion, const char *pMap, unsigned MapCrc, const char *pType); int Stop(); @@ -44,21 +44,21 @@ public: virtual void OnDemoPlayerSnapshot(void *pData, int Size) = 0; virtual void OnDemoPlayerMessage(void *pData, int Size) = 0; }; - + struct CPlaybackInfo { CDemoHeader m_Header; - + IDemoPlayer::CInfo m_Info; int64 m_LastUpdate; int64 m_CurrentTime; - + int m_SeekablePoints; - + int m_NextTick; int m_PreviousTick; - + float m_IntraTick; float m_TickTime; }; @@ -73,12 +73,12 @@ private: long m_Filepos; int m_Tick; }; - + struct CKeyFrameSearch { CKeyFrame m_Frame; CKeyFrameSearch *m_pNext; - }; + }; class IConsole *m_pConsole; IOHANDLE m_File; @@ -97,25 +97,25 @@ private: int NextFrame(); public: - + CDemoPlayer(class CSnapshotDelta *m_pSnapshotDelta); - + void SetListner(IListner *pListner); - + int Load(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, int StorageType); int Play(); void Pause(); void Unpause(); - int Stop(); + int Stop(); void SetSpeed(float Speed); int SetPos(float Precent); const CInfo *BaseInfo() const { return &m_Info.m_Info; } char *GetDemoName(); bool GetDemoInfo(class IStorage *pStorage, const char *pFilename, int StorageType, CDemoHeader *pDemoHeader) const; int GetDemoType() const; - + int Update(); - + const CPlaybackInfo *Info() const { return &m_Info; } int IsPlaying() const { return m_File != 0; } }; diff --git a/src/engine/shared/engine.cpp b/src/engine/shared/engine.cpp index b4b4f2a5e..5cc19c003 100644 --- a/src/engine/shared/engine.cpp +++ b/src/engine/shared/engine.cpp @@ -43,7 +43,7 @@ public: pEngine->m_Logging = false; } else - { + { char aBuf[32]; str_timestamp(aBuf, sizeof(aBuf)); char aFilenameSent[128], aFilenameRecv[128]; @@ -59,7 +59,7 @@ public: { dbg_logger_stdout(); dbg_logger_debugger(); - + // dbg_msg("engine", "running on %s-%s-%s", CONF_FAMILY_STRING, CONF_PLATFORM_STRING, CONF_ARCH_STRING); #ifdef CONF_ARCH_ENDIAN_LITTLE @@ -73,7 +73,7 @@ public: // init the network net_init(); CNetBase::Init(); - + m_JobPool.Init(1); m_Logging = false; diff --git a/src/engine/shared/huffman.cpp b/src/engine/shared/huffman.cpp index feb35b960..c88502b56 100644 --- a/src/engine/shared/huffman.cpp +++ b/src/engine/shared/huffman.cpp @@ -15,7 +15,7 @@ void CHuffman::Setbits_r(CNode *pNode, int Bits, unsigned Depth) Setbits_r(&m_aNodes[pNode->m_aLeafs[1]], Bits|(1<m_aLeafs[0] != 0xffff) Setbits_r(&m_aNodes[pNode->m_aLeafs[0]], Bits, Depth+1); - + if(pNode->m_NumBits) { pNode->m_Bits = Bits; @@ -28,7 +28,7 @@ static void BubbleSort(CHuffmanConstructNode **ppList, int Size) { int Changed = 1; CHuffmanConstructNode *pTemp; - + while(Changed) { Changed = 0; @@ -68,15 +68,15 @@ void CHuffman::ConstructTree(const unsigned *pFrequencies) apNodesLeft[i] = &aNodesLeftStorage[i]; } - + m_NumNodes = HUFFMAN_MAX_SYMBOLS; - + // construct the table while(NumNodesLeft > 1) { // we can't rely on stdlib's qsort for this, it can generate different results on different implementations BubbleSort(apNodesLeft, NumNodesLeft); - + m_aNodes[m_NumNodes].m_NumBits = 0; m_aNodes[m_NumNodes].m_aLeafs[0] = apNodesLeft[NumNodesLeft-1]->m_NodeId; m_aNodes[m_NumNodes].m_aLeafs[1] = apNodesLeft[NumNodesLeft-2]->m_NodeId; @@ -89,7 +89,7 @@ void CHuffman::ConstructTree(const unsigned *pFrequencies) // set start node m_pStartNode = &m_aNodes[m_NumNodes-1]; - + // build symbol bits Setbits_r(m_pStartNode, 0, 0); } @@ -230,7 +230,7 @@ int CHuffman::Decompress(const void *pInput, int InputSize, void *pOutput, int O // {C} load symbol now if we didn't that earlier at location {A} if(!pNode) pNode = m_apDecodeLut[Bits&HUFFMAN_LUTMASK]; - + if(!pNode) return -1; diff --git a/src/engine/shared/huffman.h b/src/engine/shared/huffman.h index 0edc36c64..0d15ed997 100644 --- a/src/engine/shared/huffman.h +++ b/src/engine/shared/huffman.h @@ -13,7 +13,7 @@ class CHuffman HUFFMAN_MAX_SYMBOLS=HUFFMAN_EOF_SYMBOL+1, HUFFMAN_MAX_NODES=HUFFMAN_MAX_SYMBOLS*2-1, - + HUFFMAN_LUTBITS = 10, HUFFMAN_LUTSIZE = (1<m_Lock); if(pPool->m_pFirstJob) @@ -31,7 +31,7 @@ void CJobPool::WorkerThread(void *pUser) pPool->m_pLastJob = 0; } lock_release(pPool->m_Lock); - + // do the job if we have one if(pJob) { @@ -42,7 +42,7 @@ void CJobPool::WorkerThread(void *pUser) else thread_sleep(10); } - + } int CJobPool::Init(int NumThreads) @@ -58,9 +58,9 @@ int CJobPool::Add(CJob *pJob, JOBFUNC pfnFunc, void *pData) mem_zero(pJob, sizeof(CJob)); pJob->m_pfnFunc = pfnFunc; pJob->m_pFuncData = pData; - + lock_wait(m_Lock); - + // add job to queue pJob->m_pPrev = m_pLastJob; if(m_pLastJob) @@ -68,7 +68,7 @@ int CJobPool::Add(CJob *pJob, JOBFUNC pfnFunc, void *pData) m_pLastJob = pJob; if(!m_pFirstJob) m_pFirstJob = pJob; - + lock_release(m_Lock); return 0; } diff --git a/src/engine/shared/jobs.h b/src/engine/shared/jobs.h index 2b0d7d156..9e15228ae 100644 --- a/src/engine/shared/jobs.h +++ b/src/engine/shared/jobs.h @@ -9,14 +9,14 @@ class CJobPool; class CJob { friend class CJobPool; - + CJobPool *m_pPool; CJob *m_pPrev; CJob *m_pNext; - + volatile int m_Status; volatile int m_Result; - + JOBFUNC m_pfnFunc; void *m_pFuncData; public: @@ -25,14 +25,14 @@ public: m_Status = STATE_DONE; m_pFuncData = 0; } - + enum { STATE_PENDING=0, STATE_RUNNING, STATE_DONE }; - + int Status() const { return m_Status; } int Result() const {return m_Result; } }; @@ -42,12 +42,12 @@ class CJobPool LOCK m_Lock; CJob *m_pFirstJob; CJob *m_pLastJob; - + static void WorkerThread(void *pUser); - + public: CJobPool(); - + int Init(int NumThreads); int Add(CJob *pJob, JOBFUNC pfnFunc, void *pData); }; diff --git a/src/engine/shared/kernel.cpp b/src/engine/shared/kernel.cpp index f59af8c75..b422b591a 100644 --- a/src/engine/shared/kernel.cpp +++ b/src/engine/shared/kernel.cpp @@ -9,7 +9,7 @@ class CKernel : public IKernel { MAX_INTERFACES=32, }; - + class CInterfaceInfo { public: @@ -18,14 +18,14 @@ class CKernel : public IKernel m_aName[0] = 0; m_pInterface = 0x0; } - + char m_aName[64]; IInterface *m_pInterface; }; CInterfaceInfo m_aInterfaces[MAX_INTERFACES]; int m_NumInterfaces; - + CInterfaceInfo *FindInterfaceInfo(const char *pName) { for(int i = 0; i < m_NumInterfaces; i++) @@ -35,7 +35,7 @@ class CKernel : public IKernel } return 0x0; } - + public: CKernel() @@ -58,18 +58,18 @@ public: dbg_msg("kernel", "ERROR: couldn't register interface '%s'. maximum of interfaces reached", pName); return false; } - + if(FindInterfaceInfo(pName) != 0) { dbg_msg("kernel", "ERROR: couldn't register interface '%s'. interface already exists", pName); return false; } - + pInterface->m_pKernel = this; m_aInterfaces[m_NumInterfaces].m_pInterface = pInterface; str_copy(m_aInterfaces[m_NumInterfaces].m_aName, pName, sizeof(m_aInterfaces[m_NumInterfaces].m_aName)); m_NumInterfaces++; - + return true; } @@ -80,12 +80,12 @@ public: dbg_msg("kernel", "ERROR: couldn't reregister interface '%s'. interface doesn't exist"); return false; } - + pInterface->m_pKernel = this; - + return true; } - + virtual IInterface *RequestInterfaceImpl(const char *pName) { CInterfaceInfo *pInfo = FindInterfaceInfo(pName); diff --git a/src/engine/shared/map.cpp b/src/engine/shared/map.cpp index c57dd7089..36c89cdc5 100644 --- a/src/engine/shared/map.cpp +++ b/src/engine/shared/map.cpp @@ -10,7 +10,7 @@ class CMap : public IEngineMap CDataFileReader m_DataFile; public: CMap() {} - + virtual void *GetData(int Index) { return m_DataFile.GetData(Index); } virtual void *GetDataSwapped(int Index) { return m_DataFile.GetDataSwapped(Index); } virtual void UnloadData(int Index) { m_DataFile.UnloadData(Index); } @@ -18,7 +18,7 @@ public: virtual void GetType(int Type, int *pStart, int *pNum) { m_DataFile.GetType(Type, pStart, pNum); } virtual void *FindItem(int Type, int ID) { return m_DataFile.FindItem(Type, ID); } virtual int NumItems() { return m_DataFile.NumItems(); } - + virtual void Unload() { m_DataFile.Close(); @@ -31,12 +31,12 @@ public: return false; return m_DataFile.Open(pStorage, pMapName, IStorage::TYPE_ALL); } - + virtual bool IsLoaded() { return m_DataFile.IsOpen(); } - + virtual unsigned Crc() { return m_DataFile.Crc(); diff --git a/src/engine/shared/mapchecker.cpp b/src/engine/shared/mapchecker.cpp index dec4271db..f8ba30ae5 100644 --- a/src/engine/shared/mapchecker.cpp +++ b/src/engine/shared/mapchecker.cpp @@ -42,7 +42,7 @@ void CMapChecker::AddMaplist(CMapVersion *pMaplist, int Num) m_pFirst = pEntry; str_copy(pEntry->m_aMapName, pMaplist[i].m_aName, sizeof(pEntry->m_aMapName)); - pEntry->m_MapCrc = (pMaplist[i].m_aCrc[0]<<24) | (pMaplist[i].m_aCrc[1]<<16) | (pMaplist[i].m_aCrc[2]<<8) | pMaplist[i].m_aCrc[3]; + pEntry->m_MapCrc = (pMaplist[i].m_aCrc[0]<<24) | (pMaplist[i].m_aCrc[1]<<16) | (pMaplist[i].m_aCrc[2]<<8) | pMaplist[i].m_aCrc[3]; pEntry->m_MapSize = (pMaplist[i].m_aSize[0]<<24) | (pMaplist[i].m_aSize[1]<<16) | (pMaplist[i].m_aSize[2]<<8) | pMaplist[i].m_aSize[3]; } } diff --git a/src/engine/shared/mapchecker.h b/src/engine/shared/mapchecker.h index 0d4332d92..6d9568d09 100644 --- a/src/engine/shared/mapchecker.h +++ b/src/engine/shared/mapchecker.h @@ -19,7 +19,7 @@ class CMapChecker unsigned m_MapSize; CWhitelistEntry *m_pNext; }; - + class CHeap m_Whitelist; CWhitelistEntry *m_pFirst; diff --git a/src/engine/shared/masterserver.cpp b/src/engine/shared/masterserver.cpp index 0e8cb394a..1bf402cab 100644 --- a/src/engine/shared/masterserver.cpp +++ b/src/engine/shared/masterserver.cpp @@ -19,7 +19,7 @@ public: char m_aHostname[128]; NETADDR m_Addr; bool m_Valid; - + CHostLookup m_Lookup; } ; @@ -27,7 +27,7 @@ public: int m_NeedsUpdate; IEngine *m_pEngine; IStorage *m_pStorage; - + CMasterServer() { SetDefault(); @@ -38,10 +38,10 @@ public: virtual int RefreshAddresses(int Nettype) { int i; - + if(m_NeedsUpdate != -1) return 0; - + dbg_msg("engine/mastersrv", "refreshing master server addresses"); // add lookup jobs @@ -50,7 +50,7 @@ public: m_pEngine->HostLookup(&m_aMasterServers[i].m_Lookup, m_aMasterServers[i].m_aHostname, Nettype); m_aMasterServers[i].m_Valid = false; } - + m_NeedsUpdate = 1; return 0; } @@ -61,7 +61,7 @@ public: if(m_NeedsUpdate != 1) return; m_NeedsUpdate = 0; - + for(int i = 0; i < MAX_MASTERSERVERS; i++) { if(m_aMasterServers[i].m_Lookup.m_Job.Status() != CJob::STATE_DONE) @@ -78,7 +78,7 @@ public: m_aMasterServers[i].m_Valid = false; } } - + if(!m_NeedsUpdate) { dbg_msg("engine/mastersrv", "saving addresses"); @@ -91,12 +91,12 @@ public: return m_NeedsUpdate; } - virtual NETADDR GetAddr(int Index) + virtual NETADDR GetAddr(int Index) { return m_aMasterServers[Index].m_Addr; } - virtual const char *GetName(int Index) + virtual const char *GetName(int Index) { return m_aMasterServers[Index].m_aHostname; } @@ -136,12 +136,12 @@ public: int Count = 0; if(!m_pStorage) return -1; - + // try to open file File = m_pStorage->OpenFile("masters.cfg", IOFLAG_READ, IStorage::TYPE_SAVE); if(!File) return -1; - + LineReader.Init(File); while(1) { @@ -166,7 +166,7 @@ public: //else // dbg_msg("engine/mastersrv", "warning: couldn't parse master server '%s'", pLine); } - + io_close(File); return 0; } @@ -177,7 +177,7 @@ public: if(!m_pStorage) return -1; - + // try to open file File = m_pStorage->OpenFile("masters.cfg", IOFLAG_WRITE, IStorage::TYPE_SAVE); if(!File) @@ -189,10 +189,10 @@ public: net_addr_str(&m_aMasterServers[i].m_Addr, aAddrStr, sizeof(aAddrStr)); char aBuf[1024]; str_format(aBuf, sizeof(aBuf), "%s %s\n", m_aMasterServers[i].m_aHostname, aAddrStr); - + io_write(File, aBuf, str_length(aBuf)); } - + io_close(File); return 0; } diff --git a/src/engine/shared/memheap.cpp b/src/engine/shared/memheap.cpp index 850577dd6..c1c09eaf4 100644 --- a/src/engine/shared/memheap.cpp +++ b/src/engine/shared/memheap.cpp @@ -10,7 +10,7 @@ void CHeap::NewChunk() { CChunk *pChunk; char *pMem; - + // allocate memory pMem = (char*)mem_alloc(sizeof(CChunk)+CHUNK_SIZE, 1); if(!pMem) @@ -25,14 +25,14 @@ void CHeap::NewChunk() pChunk->m_pNext = (CChunk *)0x0; pChunk->m_pNext = m_pCurrent; - m_pCurrent = pChunk; + m_pCurrent = pChunk; } //**************** void *CHeap::AllocateFromChunk(unsigned int Size) { char *pMem; - + // check if we need can fit the allocation if(m_pCurrent->m_pCurrent + Size > m_pCurrent->m_pEnd) return (void*)0x0; @@ -66,14 +66,14 @@ void CHeap::Clear() { CChunk *pChunk = m_pCurrent; CChunk *pNext; - + while(pChunk) { pNext = pChunk->m_pNext; mem_free(pChunk); pChunk = pNext; } - + m_pCurrent = 0x0; } @@ -88,10 +88,10 @@ void *CHeap::Allocate(unsigned Size) { // allocate new chunk and add it to the heap NewChunk(); - + // try to allocate again pMem = (char *)AllocateFromChunk(Size); } - + return pMem; } diff --git a/src/engine/shared/memheap.h b/src/engine/shared/memheap.h index 7228212a1..39adf2b1d 100644 --- a/src/engine/shared/memheap.h +++ b/src/engine/shared/memheap.h @@ -11,20 +11,20 @@ class CHeap char *m_pEnd; CChunk *m_pNext; }; - + enum { // how large each chunk should be CHUNK_SIZE = 1025*64, }; - + CChunk *m_pCurrent; - - + + void Clear(); void NewChunk(); void *AllocateFromChunk(unsigned int Size); - + public: CHeap(); ~CHeap(); diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index 89ffae6df..ada4b18ab 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -26,35 +26,35 @@ int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk) { CNetChunkHeader Header; unsigned char *pEnd = m_Data.m_aChunkData + m_Data.m_DataSize; - + while(1) { unsigned char *pData = m_Data.m_aChunkData; - + // check for old data to unpack if(!m_Valid || m_CurrentChunk >= m_Data.m_NumChunks) { Clear(); return 0; } - + // TODO: add checking here so we don't read too far for(int i = 0; i < m_CurrentChunk; i++) { pData = Header.Unpack(pData); pData += Header.m_Size; } - + // unpack the header pData = Header.Unpack(pData); m_CurrentChunk++; - + if(pData+Header.m_Size > pEnd) { Clear(); return 0; } - + // handle sequence stuff if(m_pConnection && (Header.m_Flags&NET_CHUNKFLAG_VITAL)) { @@ -76,7 +76,7 @@ int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk) continue; // take the next chunk in the packet } } - + // fill in the info pChunk->m_ClientID = m_ClientID; pChunk->m_Address = m_Addr; @@ -116,7 +116,7 @@ void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct io_write(ms_DataLogSent, &pPacket->m_aChunkData, pPacket->m_DataSize); io_flush(ms_DataLogSent); } - + // compress CompressedSize = ms_Huffman.Compress(pPacket->m_aChunkData, pPacket->m_DataSize, &aBuffer[3], NET_MAX_PACKETSIZE-4); @@ -174,7 +174,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct io_write(ms_DataLogRecv, pBuffer, Size); io_flush(ms_DataLogRecv); } - + // read the packet pPacket->m_Flags = pBuffer[0]>>4; pPacket->m_Ack = ((pBuffer[0]&0xf)<<8) | pBuffer[1]; @@ -188,7 +188,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct dbg_msg("", "connection less packet too small, %d", Size); return -1; } - + pPacket->m_Flags = NET_PACKETFLAG_CONNLESS; pPacket->m_Ack = 0; pPacket->m_NumChunks = 0; @@ -220,7 +220,7 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct io_write(ms_DataLogRecv, pPacket->m_aChunkData, pPacket->m_DataSize); io_flush(ms_DataLogRecv); } - + // return success return 0; } @@ -235,7 +235,7 @@ void CNetBase::SendControlMsg(NETSOCKET Socket, NETADDR *pAddr, int Ack, int Con Construct.m_DataSize = 1+ExtraSize; Construct.m_aChunkData[0] = ControlMsg; mem_copy(&Construct.m_aChunkData[1], pExtra, ExtraSize); - + // send the control message CNetBase::SendPacket(Socket, pAddr, &Construct); } @@ -284,7 +284,7 @@ int CNetBase::IsSeqInBackroom(int Seq, int Ack) if(Seq <= Ack && Seq >= Bottom) return 1; } - + return 0; } diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index cb1ec33a4..f344049e4 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -13,7 +13,7 @@ CURRENT: unsigned char flags_ack; // 4bit flags, 4bit ack unsigned char ack; // 8 bit ack unsigned char num_chunks; // 8 bit chunks - + (unsigned char padding[3]) // 24 bit extra incase it's a connection less packet // this is to make sure that it's compatible with the // old protocol @@ -30,11 +30,11 @@ enum NETSENDFLAG_VITAL=1, NETSENDFLAG_CONNLESS=2, NETSENDFLAG_FLUSH=4, - + NETSTATE_OFFLINE=0, NETSTATE_CONNECTING, NETSTATE_ONLINE, - + NETBANTYPE_SOFT=1, NETBANTYPE_DROP=2 }; @@ -65,17 +65,17 @@ enum NET_CHUNKFLAG_VITAL=1, NET_CHUNKFLAG_RESEND=2, - + NET_CTRLMSG_KEEPALIVE=0, NET_CTRLMSG_CONNECT=1, NET_CTRLMSG_CONNECTACCEPT=2, NET_CTRLMSG_ACCEPT=3, NET_CTRLMSG_CLOSE=4, - + NET_SERVER_MAXBANS=1024, - + NET_CONN_BUFFERSIZE=1024*32, - + NET_ENUM_TERMINATOR }; @@ -100,7 +100,7 @@ public: int m_Flags; int m_Size; int m_Sequence; - + unsigned char *Pack(unsigned char *pData); unsigned char *Unpack(unsigned char *pData); }; @@ -138,30 +138,30 @@ private: unsigned short m_Sequence; unsigned short m_Ack; unsigned m_State; - + int m_Token; int m_RemoteClosed; - + TStaticRingBuffer m_Buffer; - + int64 m_LastUpdateTime; int64 m_LastRecvTime; int64 m_LastSendTime; - + char m_ErrorString[256]; - + CNetPacketConstruct m_Construct; - + NETADDR m_PeerAddr; NETSOCKET m_Socket; NETSTATS m_Stats; - + // void Reset(); void ResetStats(); void SetError(const char *pString); void AckChunks(int Ack); - + int QueueChunkEx(int Flags, int DataSize, const void *pData, int Sequence); void SendControl(int ControlMsg, const void *pExtra, int ExtraSize); void ResendChunk(CNetChunkResend *pResend); @@ -173,7 +173,7 @@ public: void Disconnect(const char *pReason); int Update(); - int Flush(); + int Flush(); int Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr); int QueueChunk(int Flags, int DataSize, const void *pData); @@ -182,13 +182,13 @@ public: void SignalResend(); int State() const { return m_State; } NETADDR PeerAddress() const { return m_PeerAddr; } - + void ResetErrorString() { m_ErrorString[0] = 0; } const char *ErrorString() const { return m_ErrorString; } - + // Needed for GotProblems in NetClient int64 LastRecvTime() const { return m_LastRecvTime; } - + int AckSequence() const { return m_Ack; } }; @@ -196,7 +196,7 @@ struct CNetRecvUnpacker { public: bool m_Valid; - + NETADDR m_Addr; CNetConnection *m_pConnection; int m_CurrentChunk; @@ -207,7 +207,7 @@ public: CNetRecvUnpacker() { Clear(); } void Clear(); void Start(const NETADDR *pAddr, CNetConnection *pConnection, int ClientID); - int FetchChunk(CNetChunk *pChunk); + int FetchChunk(CNetChunk *pChunk); }; // server side @@ -220,29 +220,29 @@ public: int m_Expires; char m_Reason[128]; }; - + private: class CSlot { public: CNetConnection m_Connection; }; - + class CBan { public: CBanInfo m_Info; - + // hash list CBan *m_pHashNext; CBan *m_pHashPrev; - + // used or free list CBan *m_pNext; CBan *m_pPrev; }; - - + + NETSOCKET m_Socket; CSlot m_aSlots[NET_MAX_CLIENTS]; int m_MaxClients; @@ -256,23 +256,23 @@ private: NETFUNC_NEWCLIENT m_pfnNewClient; NETFUNC_DELCLIENT m_pfnDelClient; void *m_UserPtr; - + CNetRecvUnpacker m_RecvUnpacker; - + void BanRemoveByObject(CBan *pBan); - + public: int SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser); // bool Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int Flags); int Close(); - + // int Recv(CNetChunk *pChunk); int Send(CNetChunk *pChunk); int Update(); - + // int Drop(int ClientID, const char *pReason); @@ -304,21 +304,21 @@ public: // openness bool Open(NETADDR BindAddr, int Flags); int Close(); - + // connection state int Disconnect(const char *Reason); int Connect(NETADDR *Addr); - + // communication int Recv(CNetChunk *Chunk); int Send(CNetChunk *Chunk); - + // pumping int Update(); int Flush(); int ResetErrorString(); - + // error and state int State(); int GotProblems(); @@ -339,14 +339,14 @@ public: static void Init(); static int Compress(const void *pData, int DataSize, void *pOutput, int OutputSize); static int Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize); - + static void SendControlMsg(NETSOCKET Socket, NETADDR *pAddr, int Ack, int ControlMsg, const void *pExtra, int ExtraSize); static void SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize); static void SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket); static int UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket); // The backroom is ack-NET_MAX_SEQUENCE/2. Used for knowing if we acked a packet or not - static int IsSeqInBackroom(int Seq, int Ack); + static int IsSeqInBackroom(int Seq, int Ack); }; diff --git a/src/engine/shared/network_client.cpp b/src/engine/shared/network_client.cpp index 82a094747..2c0356061 100644 --- a/src/engine/shared/network_client.cpp +++ b/src/engine/shared/network_client.cpp @@ -61,7 +61,7 @@ int CNetClient::Recv(CNetChunk *pChunk) // check for a chunk if(m_RecvUnpacker.FetchChunk(pChunk)) return 1; - + // TODO: empty the recvinfo NETADDR Addr; int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE); @@ -98,7 +98,7 @@ int CNetClient::Send(CNetChunk *pChunk) dbg_msg("netclient", "chunk payload too big. %d. dropping chunk", pChunk->m_DataSize); return -1; } - + if(pChunk->m_Flags&NETSENDFLAG_CONNLESS) { // send connectionless packet @@ -108,10 +108,10 @@ int CNetClient::Send(CNetChunk *pChunk) { int Flags = 0; dbg_assert(pChunk->m_ClientID == 0, "errornous client id"); - + if(pChunk->m_Flags&NETSENDFLAG_VITAL) Flags = NET_CHUNKFLAG_VITAL; - + m_Connection.QueueChunk(Flags, pChunk->m_DataSize, pChunk->m_pData); if(pChunk->m_Flags&NETSENDFLAG_FLUSH) diff --git a/src/engine/shared/network_conn.cpp b/src/engine/shared/network_conn.cpp index dd61de86b..6531f5aab 100644 --- a/src/engine/shared/network_conn.cpp +++ b/src/engine/shared/network_conn.cpp @@ -14,16 +14,16 @@ void CNetConnection::Reset() m_Sequence = 0; m_Ack = 0; m_RemoteClosed = 0; - + m_State = NET_CONNSTATE_OFFLINE; m_LastSendTime = 0; m_LastRecvTime = 0; m_LastUpdateTime = 0; m_Token = -1; mem_zero(&m_PeerAddr, sizeof(m_PeerAddr)); - + m_Buffer.Init(); - + mem_zero(&m_Construct, sizeof(m_Construct)); } @@ -41,7 +41,7 @@ void CNetConnection::Init(NETSOCKET Socket) { Reset(); ResetStats(); - + m_Socket = Socket; mem_zero(m_ErrorString, sizeof(m_ErrorString)); } @@ -53,7 +53,7 @@ void CNetConnection::AckChunks(int Ack) CNetChunkResend *pResend = m_Buffer.First(); if(!pResend) break; - + if(CNetBase::IsSeqInBackroom(pResend->m_Sequence, Ack)) m_Buffer.PopFirst(); else @@ -75,10 +75,10 @@ int CNetConnection::Flush() // send of the packets m_Construct.m_Ack = m_Ack; CNetBase::SendPacket(m_Socket, &m_PeerAddr, &m_Construct); - + // update send times m_LastSendTime = time_get(); - + // clear construct so we can start building a new package mem_zero(&m_Construct, sizeof(m_Construct)); return NumChunks; @@ -87,7 +87,7 @@ int CNetConnection::Flush() int CNetConnection::QueueChunkEx(int Flags, int DataSize, const void *pData, int Sequence) { unsigned char *pChunkData; - + // check if we have space for it, if not, flush the connection if(m_Construct.m_DataSize + DataSize + NET_MAX_CHUNKHEADERSIZE > (int)sizeof(m_Construct.m_aChunkData)) Flush(); @@ -105,9 +105,9 @@ int CNetConnection::QueueChunkEx(int Flags, int DataSize, const void *pData, int // m_Construct.m_NumChunks++; m_Construct.m_DataSize = (int)(pChunkData-m_Construct.m_aChunkData); - + // set packet flags aswell - + if(Flags&NET_CHUNKFLAG_VITAL && !(Flags&NET_CHUNKFLAG_RESEND)) { // save packet if we need to resend @@ -163,7 +163,7 @@ int CNetConnection::Connect(NETADDR *pAddr) { if(State() != NET_CONNSTATE_OFFLINE) return -1; - + // init connection Reset(); m_PeerAddr = *pAddr; @@ -189,14 +189,14 @@ void CNetConnection::Disconnect(const char *pReason) if(pReason) str_copy(m_ErrorString, pReason, sizeof(m_ErrorString)); } - + Reset(); } int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) { int64 Now = time_get(); - + // check if resend is requested if(pPacket->m_Flags&NET_PACKETFLAG_RESEND) Resend(); @@ -205,14 +205,14 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) if(pPacket->m_Flags&NET_PACKETFLAG_CONTROL) { int CtrlMsg = pPacket->m_aChunkData[0]; - + if(CtrlMsg == NET_CTRLMSG_CLOSE) { if(net_addr_comp(&m_PeerAddr, pAddr) == 0) { m_State = NET_CONNSTATE_ERROR; m_RemoteClosed = 1; - + if(pPacket->m_DataSize) { // make sure to sanitize the error string form the other party @@ -222,17 +222,17 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) else str_copy(Str, (char *)pPacket->m_aChunkData, sizeof(Str)); str_sanitize_strong(Str); - + // set the error string SetError(Str); } else SetError("No reason given"); - + if(g_Config.m_Debug) dbg_msg("conn", "closed reason='%s'", ErrorString()); } - return 0; + return 0; } else { @@ -249,7 +249,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) m_LastUpdateTime = Now; SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0); if(g_Config.m_Debug) - dbg_msg("connection", "got connection, sending connect+accept"); + dbg_msg("connection", "got connection, sending connect+accept"); } } else if(State() == NET_CONNSTATE_CONNECT) @@ -276,13 +276,13 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) dbg_msg("connection", "connecting online"); } } - + if(State() == NET_CONNSTATE_ONLINE) { m_LastRecvTime = Now; AckChunks(pPacket->m_Ack); } - + return 1; } @@ -292,7 +292,7 @@ int CNetConnection::Update() if(State() == NET_CONNSTATE_OFFLINE || State() == NET_CONNSTATE_ERROR) return 0; - + // check for timeout if(State() != NET_CONNSTATE_OFFLINE && State() != NET_CONNSTATE_CONNECT && @@ -320,7 +320,7 @@ int CNetConnection::Update() ResendChunk(pResend); } } - + // send keep alives if nothing has happend for 250ms if(State() == NET_CONNSTATE_ONLINE) { @@ -330,7 +330,7 @@ int CNetConnection::Update() if(NumFlushedChunks && g_Config.m_Debug) dbg_msg("connection", "flushed connection due to timeout. %d chunks.", NumFlushedChunks); } - + if(time_get()-m_LastSendTime > time_freq()) SendControl(NET_CTRLMSG_KEEPALIVE, 0, 0); } @@ -344,6 +344,6 @@ int CNetConnection::Update() if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect/accept every 500ms SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0); } - + return 0; } diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index 76d5f6952..3078ab9f6 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -8,7 +8,7 @@ Object->Prev = (struct CBan *)0; \ Object->Next = First; \ First = Object; } - + #define MACRO_LIST_LINK_AFTER(Object, After, Prev, Next) \ { Object->Prev = After; \ Object->Next = After->Next; \ @@ -22,7 +22,7 @@ if(Object->Prev) Object->Prev->Next = Object->Next; \ else First = Object->Next; \ Object->Next = 0; Object->Prev = 0; } - + #define MACRO_LIST_FIND(Start, Next, Expression) \ { while(Start && !(Expression)) Start = Start->Next; } @@ -30,12 +30,12 @@ bool CNetServer::Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int { // zero out the whole structure mem_zero(this, sizeof(*this)); - + // open socket m_Socket = net_udp_create(BindAddr); if(!m_Socket.type) return false; - + // clamp clients m_MaxClients = MaxClients; if(m_MaxClients > NET_MAX_CLIENTS) @@ -44,17 +44,17 @@ bool CNetServer::Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int m_MaxClients = 1; m_MaxClientsPerIP = MaxClientsPerIP; - + for(int i = 0; i < NET_MAX_CLIENTS; i++) m_aSlots[i].m_Connection.Init(m_Socket); - + // setup all pointers for bans for(int i = 1; i < NET_SERVER_MAXBANS-1; i++) { m_BanPool[i].m_pNext = &m_BanPool[i+1]; m_BanPool[i].m_pPrev = &m_BanPool[i-1]; } - + m_BanPool[0].m_pNext = &m_BanPool[1]; m_BanPool[NET_SERVER_MAXBANS-1].m_pPrev = &m_BanPool[NET_SERVER_MAXBANS-2]; m_BanPool_FirstFree = &m_BanPool[0]; @@ -88,9 +88,9 @@ int CNetServer::Drop(int ClientID, const char *pReason) );*/ if(m_pfnDelClient) m_pfnDelClient(ClientID, pReason, m_UserPtr); - + m_aSlots[ClientID].m_Connection.Disconnect(pReason); - + return 0; } @@ -99,7 +99,7 @@ int CNetServer::BanGet(int Index, CBanInfo *pInfo) CBan *pBan; for(pBan = m_BanPool_FirstUsed; pBan && Index; pBan = pBan->m_pNext, Index--) {} - + if(!pBan) return 0; *pInfo = pBan->m_Info; @@ -134,15 +134,15 @@ int CNetServer::BanRemove(NETADDR Addr) int IpHash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3]+Addr.ip[4]+Addr.ip[5]+Addr.ip[6]+Addr.ip[7]+ Addr.ip[8]+Addr.ip[9]+Addr.ip[10]+Addr.ip[11]+Addr.ip[12]+Addr.ip[13]+Addr.ip[14]+Addr.ip[15])&0xff; CBan *pBan = m_aBans[IpHash]; - + MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0); - + if(pBan) { BanRemoveByObject(pBan); return 0; } - + return -1; } @@ -152,13 +152,13 @@ int CNetServer::BanAdd(NETADDR Addr, int Seconds, const char *pReason) Addr.ip[8]+Addr.ip[9]+Addr.ip[10]+Addr.ip[11]+Addr.ip[12]+Addr.ip[13]+Addr.ip[14]+Addr.ip[15])&0xff; int Stamp = -1; CBan *pBan; - + // remove the port Addr.port = 0; - + if(Seconds) Stamp = time_timestamp() + Seconds; - + // search to see if it already exists pBan = m_aBans[IpHash]; MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0); @@ -168,29 +168,29 @@ int CNetServer::BanAdd(NETADDR Addr, int Seconds, const char *pReason) pBan->m_Info.m_Expires = Stamp; return 0; } - + if(!m_BanPool_FirstFree) return -1; // fetch and clear the new ban pBan = m_BanPool_FirstFree; MACRO_LIST_UNLINK(pBan, m_BanPool_FirstFree, m_pPrev, m_pNext); - + // setup the ban info pBan->m_Info.m_Expires = Stamp; pBan->m_Info.m_Addr = Addr; str_copy(pBan->m_Info.m_Reason, pReason, sizeof(pBan->m_Info.m_Reason)); - + // add it to the ban hash MACRO_LIST_LINK_FIRST(pBan, m_aBans[IpHash], m_pHashPrev, m_pHashNext); - + // insert it into the used list { if(m_BanPool_FirstUsed) { CBan *pInsertAfter = m_BanPool_FirstUsed; MACRO_LIST_FIND(pInsertAfter, m_pNext, Stamp < pInsertAfter->m_Info.m_Expires); - + if(pInsertAfter) pInsertAfter = pInsertAfter->m_pPrev; else @@ -200,7 +200,7 @@ int CNetServer::BanAdd(NETADDR Addr, int Seconds, const char *pReason) while(pInsertAfter->m_pNext) pInsertAfter = pInsertAfter->m_pNext; } - + if(pInsertAfter) { MACRO_LIST_LINK_AFTER(pBan, pInsertAfter, m_pPrev, m_pNext); @@ -220,7 +220,7 @@ int CNetServer::BanAdd(NETADDR Addr, int Seconds, const char *pReason) { char Buf[128]; NETADDR BanAddr; - + int Mins = (Seconds + 59) / 60; if(Mins) { @@ -231,12 +231,12 @@ int CNetServer::BanAdd(NETADDR Addr, int Seconds, const char *pReason) } else str_format(Buf, sizeof(Buf), "You have been banned for life (%s)", pReason); - + for(int i = 0; i < MaxClients(); i++) { BanAddr = m_aSlots[i].m_Connection.PeerAddress(); BanAddr.port = 0; - + if(net_addr_comp(&Addr, &BanAddr) == 0) Drop(i, Buf); } @@ -253,14 +253,14 @@ int CNetServer::Update() if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ERROR) Drop(i, m_aSlots[i].m_Connection.ErrorString()); } - + // remove expired bans while(m_BanPool_FirstUsed && m_BanPool_FirstUsed->m_Info.m_Expires < Now) { CBan *pBan = m_BanPool_FirstUsed; BanRemoveByObject(pBan); } - + return 0; } @@ -270,22 +270,22 @@ int CNetServer::Update() int CNetServer::Recv(CNetChunk *pChunk) { unsigned Now = time_timestamp(); - + while(1) { NETADDR Addr; - + // check for a chunk if(m_RecvUnpacker.FetchChunk(pChunk)) return 1; - + // TODO: empty the recvinfo int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE); // no more packets for now if(Bytes <= 0) break; - + if(CNetBase::UnpackPacket(m_RecvUnpacker.m_aBuffer, Bytes, &m_RecvUnpacker.m_Data) == 0) { CBan *pBan = 0; @@ -294,14 +294,14 @@ int CNetServer::Recv(CNetChunk *pChunk) BanAddr.ip[8]+BanAddr.ip[9]+BanAddr.ip[10]+BanAddr.ip[11]+BanAddr.ip[12]+BanAddr.ip[13]+BanAddr.ip[14]+BanAddr.ip[15])&0xff; int Found = 0; BanAddr.port = 0; - + // search a ban for(pBan = m_aBans[IpHash]; pBan; pBan = pBan->m_pHashNext) { if(net_addr_comp(&pBan->m_Info.m_Addr, &BanAddr) == 0) break; } - + // check if we just should drop the packet if(pBan) { @@ -320,7 +320,7 @@ int CNetServer::Recv(CNetChunk *pChunk) CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, BanStr, str_length(BanStr)+1); continue; } - + if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONNLESS) { pChunk->m_Flags = NETSENDFLAG_CONNLESS; @@ -331,12 +331,12 @@ int CNetServer::Recv(CNetChunk *pChunk) return 1; } else - { + { // TODO: check size here if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONTROL && m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_CONNECT) { Found = 0; - + // check if we already got this client for(int i = 0; i < MaxClients(); i++) { @@ -348,7 +348,7 @@ int CNetServer::Recv(CNetChunk *pChunk) break; } } - + // client that wants to connect if(!Found) { @@ -386,7 +386,7 @@ int CNetServer::Recv(CNetChunk *pChunk) break; } } - + if(!Found) { const char FullMsg[] = "This server is full"; @@ -423,7 +423,7 @@ int CNetServer::Send(CNetChunk *pChunk) dbg_msg("netserver", "packet payload too big. %d. dropping packet", pChunk->m_DataSize); return -1; } - + if(pChunk->m_Flags&NETSENDFLAG_CONNLESS) { // send connectionless packet @@ -434,10 +434,10 @@ int CNetServer::Send(CNetChunk *pChunk) int Flags = 0; dbg_assert(pChunk->m_ClientID >= 0, "errornous client id"); dbg_assert(pChunk->m_ClientID < MaxClients(), "errornous client id"); - + if(pChunk->m_Flags&NETSENDFLAG_VITAL) Flags = NET_CHUNKFLAG_VITAL; - + if(m_aSlots[pChunk->m_ClientID].m_Connection.QueueChunk(Flags, pChunk->m_DataSize, pChunk->m_pData) == 0) { if(pChunk->m_Flags&NETSENDFLAG_FLUSH) diff --git a/src/engine/shared/packer.cpp b/src/engine/shared/packer.cpp index cd2114680..cc218825c 100644 --- a/src/engine/shared/packer.cpp +++ b/src/engine/shared/packer.cpp @@ -17,7 +17,7 @@ void CPacker::AddInt(int i) { if(m_Error) return; - + // make sure that we have space enough if(m_pEnd - m_pCurrent < 6) { @@ -32,7 +32,7 @@ void CPacker::AddString(const char *pStr, int Limit) { if(m_Error) return; - + // if(Limit > 0) { @@ -40,7 +40,7 @@ void CPacker::AddString(const char *pStr, int Limit) { *m_pCurrent++ = *pStr++; Limit--; - + if(m_pCurrent >= m_pEnd) { m_Error = 1; @@ -69,13 +69,13 @@ void CPacker::AddRaw(const void *pData, int Size) { if(m_Error) return; - + if(m_pCurrent+Size >= m_pEnd) { m_Error = 1; return; } - + const unsigned char *pSrc = (const unsigned char *)pData; while(Size) { @@ -97,13 +97,13 @@ int CUnpacker::GetInt() { if(m_Error) return 0; - + if(m_pCurrent >= m_pEnd) { m_Error = 1; return 0; } - + int i; m_pCurrent = CVariableInt::Unpack(m_pCurrent, &i); if(m_pCurrent > m_pEnd) @@ -118,7 +118,7 @@ const char *CUnpacker::GetString(int SanitizeType) { if(m_Error || m_pCurrent >= m_pEnd) return ""; - + char *pPtr = (char *)m_pCurrent; while(*m_pCurrent) // skip the string { @@ -130,7 +130,7 @@ const char *CUnpacker::GetString(int SanitizeType) } } m_pCurrent++; - + // sanitize all strings if(SanitizeType&SANITIZE) str_sanitize(pPtr); @@ -144,7 +144,7 @@ const unsigned char *CUnpacker::GetRaw(int Size) const unsigned char *pPtr = m_pCurrent; if(m_Error) return 0; - + // check for nasty sizes if(Size < 0 || m_pCurrent+Size > m_pEnd) { diff --git a/src/engine/shared/packer.h b/src/engine/shared/packer.h index 9091370a2..bd04e36e8 100644 --- a/src/engine/shared/packer.h +++ b/src/engine/shared/packer.h @@ -21,7 +21,7 @@ public: void AddInt(int i); void AddString(const char *pStr, int Limit); void AddRaw(const void *pData, int Size); - + int Size() const { return (int)(m_pCurrent-m_aBuffer); } const unsigned char *Data() const { return m_aBuffer; } bool Error() const { return m_Error; } diff --git a/src/engine/shared/protocol.h b/src/engine/shared/protocol.h index 859f49410..4a4895ad8 100644 --- a/src/engine/shared/protocol.h +++ b/src/engine/shared/protocol.h @@ -7,13 +7,13 @@ /* Connection diagram - How the initilization works. - + Client -> INFO -> Server Contains version info, name, and some other info. - + Client <- MAP <- Server Contains current map. - + Client -> READY -> Server The client has loaded the map and is ready to go, but the mod needs to send it's information aswell. @@ -21,7 +21,7 @@ mods_connected is called on the server. The client should call client_entergame when the mod has done it's initilization. - + Client -> ENTERGAME -> Server Tells the server to start sending snapshots. client_entergame and server_client_enter is called. @@ -31,11 +31,11 @@ enum { NETMSG_NULL=0, - + // the first thing sent by the client // contains the version info for the client NETMSG_INFO=1, - + // sent by server NETMSG_MAP_CHANGE, // sent when client should switch map NETMSG_MAP_DATA, // map transfer, contains a chunk of the map file @@ -50,18 +50,18 @@ enum NETMSG_AUTH_CHALLANGE, // NETMSG_AUTH_RESULT, // - + // sent by client NETMSG_READY, // NETMSG_ENTERGAME, NETMSG_INPUT, // contains the inputdata from the client - NETMSG_RCON_CMD, // + NETMSG_RCON_CMD, // NETMSG_RCON_AUTH, // NETMSG_REQUEST_MAP_DATA,// NETMSG_AUTH_START, // NETMSG_AUTH_RESPONSE, // - + // sent by both NETMSG_PING, NETMSG_PING_REPLY, diff --git a/src/engine/shared/ringbuffer.cpp b/src/engine/shared/ringbuffer.cpp index 172508d76..b9f55d73a 100644 --- a/src/engine/shared/ringbuffer.cpp +++ b/src/engine/shared/ringbuffer.cpp @@ -3,7 +3,7 @@ #include #include "ringbuffer.h" - + CRingBufferBase::CItem *CRingBufferBase::NextBlock(CItem *pItem) { if(pItem->m_pNext) @@ -27,19 +27,19 @@ CRingBufferBase::CItem *CRingBufferBase::MergeBack(CItem *pItem) // merge the blocks pItem->m_pPrev->m_Size += pItem->m_Size; pItem->m_pPrev->m_pNext = pItem->m_pNext; - + // fixup pointers if(pItem->m_pNext) pItem->m_pNext->m_pPrev = pItem->m_pPrev; else m_pLast = pItem->m_pPrev; - + if(pItem == m_pProduce) m_pProduce = pItem->m_pPrev; - + if(pItem == m_pConsume) m_pConsume = pItem->m_pPrev; - + // return the current block return pItem->m_pPrev; } @@ -54,8 +54,8 @@ void CRingBufferBase::Init(void *pMemory, int Size, int Flags) m_pLast = m_pFirst; m_pProduce = m_pFirst; m_pConsume = m_pFirst; - m_Flags = Flags; - + m_Flags = Flags; + } void *CRingBufferBase::Allocate(int Size) @@ -67,7 +67,7 @@ void *CRingBufferBase::Allocate(int Size) if(WantedSize > m_Size) return 0; - while(1) + while(1) { // check for space if(m_pProduce->m_Free) @@ -81,7 +81,7 @@ void *CRingBufferBase::Allocate(int Size) pBlock = m_pFirst; } } - + if(pBlock) break; else @@ -96,9 +96,9 @@ void *CRingBufferBase::Allocate(int Size) return 0; } } - + // okey, we have our block - + // split the block if needed if(pBlock->m_Size > WantedSize+(int)sizeof(CItem)) { @@ -108,19 +108,19 @@ void *CRingBufferBase::Allocate(int Size) if(pNewItem->m_pNext) pNewItem->m_pNext->m_pPrev = pNewItem; pBlock->m_pNext = pNewItem; - + pNewItem->m_Free = 1; pNewItem->m_Size = pBlock->m_Size - WantedSize; pBlock->m_Size = WantedSize; - + if(!pNewItem->m_pNext) m_pLast = pNewItem; } - - + + // set next block m_pProduce = NextBlock(pBlock); - + // set as used and return the item pointer pBlock->m_Free = 0; return (void *)(pBlock+1); @@ -130,13 +130,13 @@ int CRingBufferBase::PopFirst() { if(m_pConsume->m_Free) return 0; - + // set the free flag m_pConsume->m_Free = 1; - + // previous block is also free, merge them m_pConsume = MergeBack(m_pConsume); - + // advance the consume pointer m_pConsume = NextBlock(m_pConsume); while(m_pConsume->m_Free && m_pConsume != m_pProduce) @@ -144,7 +144,7 @@ int CRingBufferBase::PopFirst() m_pConsume = MergeBack(m_pConsume); m_pConsume = NextBlock(m_pConsume); } - + // in the case that we have catched up with the produce pointer // we might stand on a free block so merge em MergeBack(m_pConsume); @@ -155,7 +155,7 @@ int CRingBufferBase::PopFirst() void *CRingBufferBase::Prev(void *pCurrent) { CItem *pItem = ((CItem *)pCurrent) - 1; - + while(1) { pItem = PrevBlock(pItem); @@ -169,7 +169,7 @@ void *CRingBufferBase::Prev(void *pCurrent) void *CRingBufferBase::Next(void *pCurrent) { CItem *pItem = ((CItem *)pCurrent) - 1; - + while(1) { pItem = NextBlock(pItem); diff --git a/src/engine/shared/ringbuffer.h b/src/engine/shared/ringbuffer.h index 9f0c5a1d7..c47745285 100644 --- a/src/engine/shared/ringbuffer.h +++ b/src/engine/shared/ringbuffer.h @@ -15,28 +15,28 @@ class CRingBufferBase int m_Free; int m_Size; }; - + CItem *m_pProduce; CItem *m_pConsume; - + CItem *m_pFirst; CItem *m_pLast; - + void *m_pMemory; int m_Size; int m_Flags; - + CItem *NextBlock(CItem *pItem); CItem *PrevBlock(CItem *pItem); CItem *MergeBack(CItem *pItem); protected: void *Allocate(int Size); - + void *Prev(void *pCurrent); void *Next(void *pCurrent); void *First(); void *Last(); - + void Init(void *pMemory, int Size, int Flags); int PopFirst(); public: @@ -53,9 +53,9 @@ class TStaticRingBuffer : public CRingBufferBase unsigned char m_aBuffer[TSIZE]; public: TStaticRingBuffer() { Init(); } - + void Init() { CRingBufferBase::Init(m_aBuffer, TSIZE, TFLAGS); } - + T *Allocate(int Size) { return (T*)CRingBufferBase::Allocate(Size); } int PopFirst() { return CRingBufferBase::PopFirst(); } diff --git a/src/engine/shared/snapshot.cpp b/src/engine/shared/snapshot.cpp index fee6afa2a..9ef8fdc31 100644 --- a/src/engine/shared/snapshot.cpp +++ b/src/engine/shared/snapshot.cpp @@ -12,31 +12,31 @@ CSnapshotItem *CSnapshot::GetItem(int Index) int CSnapshot::GetItemSize(int Index) { - if(Index == m_NumItems-1) - return (m_DataSize - Offsets()[Index]) - sizeof(CSnapshotItem); - return (Offsets()[Index+1] - Offsets()[Index]) - sizeof(CSnapshotItem); + if(Index == m_NumItems-1) + return (m_DataSize - Offsets()[Index]) - sizeof(CSnapshotItem); + return (Offsets()[Index+1] - Offsets()[Index]) - sizeof(CSnapshotItem); } int CSnapshot::GetItemIndex(int Key) { - // TODO: OPT: this should not be a linear search. very bad - for(int i = 0; i < m_NumItems; i++) - { - if(GetItem(i)->Key() == Key) - return i; - } - return -1; + // TODO: OPT: this should not be a linear search. very bad + for(int i = 0; i < m_NumItems; i++) + { + if(GetItem(i)->Key() == Key) + return i; + } + return -1; } int CSnapshot::Crc() { int Crc = 0; - + for(int i = 0; i < m_NumItems; i++) { CSnapshotItem *pItem = GetItem(i); int Size = GetItemSize(i); - + for(int b = 0; b < Size/4; b++) Crc += pItem->Data()[b]; } @@ -75,7 +75,7 @@ static void GenerateHash(CItemList *pHashlist, CSnapshot *pSnapshot) { for(int i = 0; i < HASHLIST_SIZE; i++) pHashlist[i].m_Num = 0; - + for(int i = 0; i < pSnapshot->NumItems(); i++) { int Key = pSnapshot->GetItem(i)->Key(); @@ -97,7 +97,7 @@ static int GetItemIndexHashed(int Key, const CItemList *pHashlist) if(pHashlist[HashID].m_aKeys[i] == Key) return pHashlist[HashID].m_aIndex[i]; } - + return -1; } @@ -113,7 +113,7 @@ static int DiffItem(int *pPast, int *pCurrent, int *pOut, int Size) pCurrent++; Size--; } - + return Needed; } @@ -122,16 +122,16 @@ void CSnapshotDelta::UndiffItem(int *pPast, int *pDiff, int *pOut, int Size) while(Size) { *pOut = *pPast+*pDiff; - + if(*pDiff == 0) m_aSnapshotDataRate[m_SnapshotCurrent] += 1; else { unsigned char aBuf[16]; - unsigned char *pEnd = CVariableInt::Pack(aBuf, *pDiff); + unsigned char *pEnd = CVariableInt::Pack(aBuf, *pDiff); m_aSnapshotDataRate[m_SnapshotCurrent] += (int)(pEnd - (unsigned char*)aBuf) * 8; } - + pOut++; pPast++; pDiff++; @@ -169,11 +169,11 @@ int CSnapshotDelta::CreateDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pDstData CSnapshotItem *pPastItem; int Count = 0; int SizeCount = 0; - + pDelta->m_NumDeletedItems = 0; pDelta->m_NumUpdateItems = 0; pDelta->m_NumTempItems = 0; - + CItemList Hashlist[HASHLIST_SIZE]; GenerateHash(Hashlist, pTo); @@ -189,7 +189,7 @@ int CSnapshotDelta::CreateDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pDstData pData++; } } - + GenerateHash(Hashlist, pFrom); int aPastIndecies[1024]; @@ -197,29 +197,29 @@ int CSnapshotDelta::CreateDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pDstData // we do this as a separate pass because it helps the cache for(i = 0; i < pTo->NumItems(); i++) { - pCurItem = pTo->GetItem(i); // O(1) .. O(n) + 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++) { // do delta ItemSize = pTo->GetItemSize(i); // O(1) .. O(n) - pCurItem = pTo->GetItem(i); // O(1) .. O(n) + pCurItem = pTo->GetItem(i); // O(1) .. O(n) PastIndex = aPastIndecies[i]; - + if(PastIndex != -1) { int *pItemDataDst = pData+3; - + pPastItem = pFrom->GetItem(PastIndex); - + if(m_aItemSizes[pCurItem->Type()]) pItemDataDst = pData+2; - + if(DiffItem((int*)pPastItem->Data(), (int*)pCurItem->Data(), pItemDataDst, ItemSize/4)) { - + *pData++ = pCurItem->Type(); *pData++ = pCurItem->ID(); if(!m_aItemSizes[pCurItem->Type()]) @@ -234,7 +234,7 @@ int CSnapshotDelta::CreateDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pDstData *pData++ = pCurItem->ID(); if(!m_aItemSizes[pCurItem->Type()]) *pData++ = ItemSize/4; - + mem_copy(pData, pCurItem->Data(), ItemSize); SizeCount += ItemSize; pData += ItemSize/4; @@ -242,7 +242,7 @@ int CSnapshotDelta::CreateDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pDstData Count++; } } - + if(0) { dbg_msg("snapshot", "%d %d %d", @@ -253,7 +253,7 @@ int CSnapshotDelta::CreateDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pDstData /* // TODO: pack temp stuff - + // finish //mem_copy(pDelta->offsets, deleted, pDelta->num_deleted_items*sizeof(int)); //mem_copy(&(pDelta->offsets[pDelta->num_deleted_items]), update, pDelta->num_update_items*sizeof(int)); @@ -261,10 +261,10 @@ int CSnapshotDelta::CreateDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pDstData //mem_copy(pDelta->data_start(), data, data_size); //pDelta->data_size = data_size; * */ - + if(!pDelta->m_NumDeletedItems && !pDelta->m_NumUpdateItems && !pDelta->m_NumTempItems) return 0; - + return (int)((char*)pData-(char*)pDstData); } @@ -281,16 +281,16 @@ int CSnapshotDelta::UnpackDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pSrcData CData *pDelta = (CData *)pSrcData; int *pData = (int *)pDelta->m_pData; int *pEnd = (int *)(((char *)pSrcData + DataSize)); - + CSnapshotItem *pFromItem; int Keep, ItemSize; int *pDeleted; int ID, Type, Key; int FromIndex; int *pNewData; - + Builder.Init(); - + // unpack deleted stuff pDeleted = pData; pData += pDelta->m_NumDeletedItems; @@ -302,7 +302,7 @@ int CSnapshotDelta::UnpackDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pSrcData { // dbg_assert(0, "fail!"); pFromItem = pFrom->GetItem(i); - ItemSize = pFrom->GetItemSize(i); + ItemSize = pFrom->GetItemSize(i); Keep = 1; for(int d = 0; d < pDelta->m_NumDeletedItems; d++) { @@ -312,7 +312,7 @@ int CSnapshotDelta::UnpackDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pSrcData break; } } - + if(Keep) { // keep it @@ -321,13 +321,13 @@ int CSnapshotDelta::UnpackDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pSrcData pFromItem->Data(), ItemSize); } } - + // unpack updated stuff for(int i = 0; i < pDelta->m_NumUpdateItems; i++) { if(pData+2 > pEnd) return -1; - + Type = *pData++; ID = *pData++; if(m_aItemSizes[Type]) @@ -339,18 +339,18 @@ int CSnapshotDelta::UnpackDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pSrcData ItemSize = (*pData++) * 4; } m_SnapshotCurrent = Type; - + if(RangeCheck(pEnd, pData, ItemSize) || ItemSize < 0) return -3; - + Key = (Type<<16)|ID; - + // create the item if needed pNewData = Builder.GetItemData(Key); if(!pNewData) pNewData = (int *)Builder.NewItem(Key>>16, Key&0xffff, ItemSize); //if(range_check(pEnd, pNewData, ItemSize)) return -4; - + FromIndex = pFrom->GetItemIndex(Key); if(FromIndex != -1) { @@ -364,10 +364,10 @@ int CSnapshotDelta::UnpackDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pSrcData m_aSnapshotDataRate[m_SnapshotCurrent] += ItemSize*8; m_aSnapshotDataUpdates[m_SnapshotCurrent]++; } - + pData += ItemSize/4; } - + // finish up return Builder.Finish(pTo); } @@ -402,24 +402,24 @@ void CSnapshotStorage::PurgeUntil(int Tick) { CHolder *pHolder = m_pFirst; CHolder *pNext; - + while(pHolder) { pNext = pHolder->m_pNext; if(pHolder->m_Tick >= Tick) return; // no more to remove mem_free(pHolder); - + // did we come to the end of the list? - if (!pNext) - break; + if (!pNext) + break; m_pFirst = pNext; pNext->m_pPrev = 0x0; - + pHolder = pNext; } - + // no more snapshots in storage m_pFirst = 0; m_pLast = 0; @@ -429,12 +429,12 @@ void CSnapshotStorage::Add(int Tick, int64 Tagtime, int DataSize, void *pData, i { // allocate memory for holder + snapshot_data int TotalSize = sizeof(CHolder)+DataSize; - + if(CreateAlt) TotalSize += DataSize; - + CHolder *pHolder = (CHolder *)mem_alloc(TotalSize, 1); - + // set data pHolder->m_Tick = Tick; pHolder->m_Tagtime = Tagtime; @@ -449,8 +449,8 @@ void CSnapshotStorage::Add(int Tick, int64 Tagtime, int DataSize, void *pData, i } else pHolder->m_pAltSnap = 0; - - + + // link pHolder->m_pNext = 0; pHolder->m_pPrev = m_pLast; @@ -464,7 +464,7 @@ void CSnapshotStorage::Add(int Tick, int64 Tagtime, int DataSize, void *pData, i int CSnapshotStorage::Get(int Tick, int64 *pTagtime, CSnapshot **ppData, CSnapshot **ppAltData) { CHolder *pHolder = m_pFirst; - + while(pHolder) { if(pHolder->m_Tick == Tick) @@ -477,10 +477,10 @@ int CSnapshotStorage::Get(int Tick, int64 *pTagtime, CSnapshot **ppData, CSnapsh *ppData = pHolder->m_pAltSnap; return pHolder->m_SnapSize; } - + pHolder = pHolder->m_pNext; } - + return -1; } @@ -492,7 +492,7 @@ void CSnapshotBuilder::Init() m_NumItems = 0; } -CSnapshotItem *CSnapshotBuilder::GetItem(int Index) +CSnapshotItem *CSnapshotBuilder::GetItem(int Index) { return (CSnapshotItem *)&(m_aData[m_aOffsets[Index]]); } diff --git a/src/engine/shared/snapshot.h b/src/engine/shared/snapshot.h index 34c3a5487..ebd13f202 100644 --- a/src/engine/shared/snapshot.h +++ b/src/engine/shared/snapshot.h @@ -11,7 +11,7 @@ class CSnapshotItem { public: int m_TypeAndID; - + int *Data() { return (int *)(this+1); } int Type() { return m_TypeAndID>>16; } int ID() { return m_TypeAndID&0xffff; } @@ -90,15 +90,15 @@ public: public: CHolder *m_pPrev; CHolder *m_pNext; - + int64 m_Tagtime; int m_Tick; - + int m_SnapSize; CSnapshot *m_pSnap; CSnapshot *m_pAltSnap; }; - + CHolder *m_pFirst; CHolder *m_pLast; @@ -125,12 +125,12 @@ class CSnapshotBuilder public: void Init(); - + void *NewItem(int Type, int ID, int Size); - + CSnapshotItem *GetItem(int Index); int *GetItemData(int Key); - + int Finish(void *Snapdata); }; diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp index db19fcdcf..d6f83dc84 100644 --- a/src/engine/shared/storage.cpp +++ b/src/engine/shared/storage.cpp @@ -21,7 +21,7 @@ public: char m_aDatadir[MAX_PATH_LENGTH]; char m_aUserdir[MAX_PATH_LENGTH]; char m_aCurrentdir[MAX_PATH_LENGTH]; - + CStorage() { mem_zero(m_aaStoragePaths, sizeof(m_aaStoragePaths)); @@ -29,7 +29,7 @@ public: m_aDatadir[0] = 0; m_aUserdir[0] = 0; } - + int Init(const char *pApplicationName, int NumArgs, const char **ppArguments) { // get userdir @@ -85,7 +85,7 @@ public: str_append(aBuffer, "/storage.cfg", sizeof(aBuffer)); File = io_open(aBuffer, IOFLAG_READ); } - + if(Pos >= MAX_PATH_LENGTH || !File) { dbg_msg("storage", "couldn't open storage.cfg"); @@ -151,7 +151,7 @@ public: } } } - + void FindDatadir(const char *pArgv0) { // 1) use data-dir in PWD if present @@ -160,35 +160,35 @@ public: str_copy(m_aDatadir, "data", sizeof(m_aDatadir)); return; } - + // 2) use compiled-in data-dir if present if(fs_is_dir(DATA_DIR "/mapres")) { str_copy(m_aDatadir, DATA_DIR, sizeof(m_aDatadir)); return; } - + // 3) check for usable path in argv[0] { unsigned int Pos = ~0U; for(unsigned i = 0; pArgv0[i]; i++) if(pArgv0[i] == '/' || pArgv0[i] == '\\') Pos = i; - + if(Pos < MAX_PATH_LENGTH) { char aBaseDir[MAX_PATH_LENGTH]; str_copy(aBaseDir, pArgv0, Pos+1); str_format(m_aDatadir, sizeof(m_aDatadir), "%s/data", aBaseDir); str_append(aBaseDir, "/data/mapres", sizeof(aBaseDir)); - + if(fs_is_dir(aBaseDir)) return; else m_aDatadir[0] = 0; } } - + #if defined(CONF_FAMILY_UNIX) // 4) check for all default locations { @@ -200,7 +200,7 @@ public: "/opt/teeworlds/data" }; const int DirsCount = sizeof(aDirs) / sizeof(aDirs[0]); - + int i; for (i = 0; i < DirsCount; i++) { @@ -214,7 +214,7 @@ public: } } #endif - + // no data-dir found dbg_msg("storage", "warning no data directory found"); } @@ -240,7 +240,7 @@ public: str_format(pBuffer, BufferSize, "%s%s%s", m_aaStoragePaths[Type], !m_aaStoragePaths[Type][0] ? "" : "/", pDir); return pBuffer; } - + virtual IOHANDLE OpenFile(const char *pFilename, int Flags, int Type, char *pBuffer = 0, int BufferSize = 0) { char aBuffer[MAX_PATH_LENGTH]; @@ -249,7 +249,7 @@ public: pBuffer = aBuffer; BufferSize = sizeof(aBuffer); } - + if(Flags&IOFLAG_WRITE) { return io_open(GetPath(TYPE_SAVE, pFilename, pBuffer, BufferSize), Flags); @@ -276,11 +276,11 @@ public: return Handle; } } - + pBuffer[0] = 0; - return 0; + return 0; } - + struct CFindCBData { CStorage *pStorage; @@ -321,7 +321,7 @@ public: { if(BufferSize < 1) return false; - + pBuffer[0] = 0; char aBuf[MAX_PATH_LENGTH]; CFindCBData Data; diff --git a/src/engine/storage.h b/src/engine/storage.h index e0cab12fb..1fd48f6af 100644 --- a/src/engine/storage.h +++ b/src/engine/storage.h @@ -14,7 +14,7 @@ public: TYPE_SAVE = 0, TYPE_ALL = -1 }; - + virtual void ListDirectory(int Type, const char *pPath, FS_LISTDIR_CALLBACK pfnCallback, void *pUser) = 0; virtual IOHANDLE OpenFile(const char *pFilename, int Flags, int Type, char *pBuffer = 0, int BufferSize = 0) = 0; virtual bool FindFile(const char *pFilename, const char *pPath, int Type, char *pBuffer, int BufferSize) = 0; diff --git a/src/engine/textrender.h b/src/engine/textrender.h index 8d13f6057..ddd2be5b7 100644 --- a/src/engine/textrender.h +++ b/src/engine/textrender.h @@ -20,12 +20,12 @@ public: int m_LineCount; int m_CharCount; int m_MaxLines; - + float m_StartX; float m_StartY; float m_LineWidth; float m_X, m_Y; - + CFont *m_pFont; float m_FontSize; }; @@ -35,15 +35,15 @@ class ITextRender : public IInterface MACRO_INTERFACE("textrender", 0) public: virtual void SetCursor(CTextCursor *pCursor, float x, float y, float FontSize, int Flags) = 0; - + virtual CFont *LoadFont(const char *pFilename) = 0; virtual void DestroyFont(CFont *pFont) = 0; - + virtual void SetDefaultFont(CFont *pFont) = 0; // virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length) = 0; - + // old foolish interface virtual void TextColor(float r, float g, float b, float a) = 0; virtual void TextOutlineColor(float r, float g, float b, float a) = 0; diff --git a/src/game/client/animstate.cpp b/src/game/client/animstate.cpp index 096ff63ca..1289126b3 100644 --- a/src/game/client/animstate.cpp +++ b/src/game/client/animstate.cpp @@ -84,13 +84,13 @@ CAnimState *CAnimState::GetIdle() { static CAnimState State; static bool Init = true; - + if(Init) { State.Set(&g_pData->m_aAnimations[ANIM_BASE], 0); State.Add(&g_pData->m_aAnimations[ANIM_IDLE], 0, 1.0f); Init = false; } - + return &State; } diff --git a/src/game/client/animstate.h b/src/game/client/animstate.h index cb3b0e187..63b6a80a7 100644 --- a/src/game/client/animstate.h +++ b/src/game/client/animstate.h @@ -17,7 +17,7 @@ public: ANIM_KEYFRAME *GetAttach() { return &m_Attach; }; void Set(ANIMATION *pAnim, float Time); void Add(ANIMATION *pAdded, float Time, float Amount); - + static CAnimState *GetIdle(); }; diff --git a/src/game/client/component.h b/src/game/client/component.h index 244f5dafe..858b456f3 100644 --- a/src/game/client/component.h +++ b/src/game/client/component.h @@ -12,7 +12,7 @@ protected: friend class CGameClient; CGameClient *m_pClient; - + // perhaps propagte pointers for these as well class IKernel *Kernel() const { return m_pClient->Kernel(); } class IGraphics *Graphics() const { return m_pClient->Graphics(); } @@ -31,7 +31,7 @@ protected: class CCollision *Collision() const { return m_pClient->Collision(); } public: virtual ~CComponent() {} - + virtual void OnStateChange(int NewState, int OldState) {}; virtual void OnConsoleInit() {}; virtual void OnInit() {}; diff --git a/src/game/client/components/binds.cpp b/src/game/client/components/binds.cpp index 1632b26fc..3feba98ea 100644 --- a/src/game/client/components/binds.cpp +++ b/src/game/client/components/binds.cpp @@ -12,11 +12,11 @@ bool CBinds::CBindsSpecial::OnInput(IInput::CEvent Event) int Stroke = 0; if(Event.m_Flags&IInput::FLAG_PRESS) Stroke = 1; - + m_pBinds->GetConsole()->ExecuteLineStroked(Stroke, m_pBinds->m_aaKeyBindings[Event.m_Key]); return true; } - + return false; } @@ -30,7 +30,7 @@ void CBinds::Bind(int KeyID, const char *pStr) { if(KeyID < 0 || KeyID >= KEY_LAST) return; - + str_copy(m_aaKeyBindings[KeyID], pStr, sizeof(m_aaKeyBindings[KeyID])); char aBuf[256]; if(!m_aaKeyBindings[KeyID][0]) @@ -74,11 +74,11 @@ const char *CBinds::GetKey(const char *pBindStr) const char *pBind = Get(KeyId); if(!pBind[0]) continue; - + if(str_comp(pBind, pBindStr) == 0) return Input()->KeyName(KeyId); } - + return ""; } @@ -108,15 +108,15 @@ void CBinds::SetDefaults() Bind('3', "+weapon3"); Bind('4', "+weapon4"); Bind('5', "+weapon5"); - + Bind(KEY_MOUSE_WHEEL_UP, "+prevweapon"); Bind(KEY_MOUSE_WHEEL_DOWN, "+nextweapon"); - + Bind('t', "chat all"); - Bind('y', "chat team"); + Bind('y', "chat team"); Bind(KEY_F3, "vote yes"); - Bind(KEY_F4, "vote no"); + Bind(KEY_F4, "vote no"); } void CBinds::OnConsoleInit() @@ -125,12 +125,12 @@ void CBinds::OnConsoleInit() IConfig *pConfig = Kernel()->RequestInterface(); if(pConfig) pConfig->RegisterCallback(ConfigSaveCallback, this); - + Console()->Register("bind", "sr", CFGFLAG_CLIENT, ConBind, this, "Bind key to execute the command"); Console()->Register("unbind", "s", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key"); Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys"); Console()->Register("dump_binds", "", CFGFLAG_CLIENT, ConDumpBinds, this, "Dump binds"); - + // default bindings SetDefaults(); } @@ -140,7 +140,7 @@ void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData) CBinds *pBinds = (CBinds *)pUserData; const char *pKeyName = pResult->GetString(0); int id = pBinds->GetKeyID(pKeyName); - + if(!id) { char aBuf[256]; @@ -148,7 +148,7 @@ void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData) pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf); return; } - + pBinds->Bind(id, pResult->GetString(1)); } @@ -158,7 +158,7 @@ void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData) CBinds *pBinds = (CBinds *)pUserData; const char *pKeyName = pResult->GetString(0); int id = pBinds->GetKeyID(pKeyName); - + if(!id) { char aBuf[256]; @@ -166,7 +166,7 @@ void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData) pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf); return; } - + pBinds->Bind(id, ""); } @@ -200,21 +200,21 @@ int CBinds::GetKeyID(const char *pKeyName) if(i > 0 && i < KEY_LAST) return i; // numeric } - + // search for key for(int i = 0; i < KEY_LAST; i++) { if(str_comp(pKeyName, Input()->KeyName(i)) == 0) return i; } - + return 0; } void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData) { CBinds *pSelf = (CBinds *)pUserData; - + char aBuffer[256]; char *pEnd = aBuffer+sizeof(aBuffer)-8; pConfig->WriteLine("unbindall"); @@ -223,7 +223,7 @@ void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData) if(pSelf->m_aaKeyBindings[i][0] == 0) continue; str_format(aBuffer, sizeof(aBuffer), "bind %s ", pSelf->Input()->KeyName(i)); - + // process the string. we need to escape some characters const char *pSrc = pSelf->m_aaKeyBindings[i]; char *pDst = aBuffer + str_length(aBuffer); @@ -236,7 +236,7 @@ void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData) } *pDst++ = '"'; *pDst++ = 0; - + pConfig->WriteLine(aBuffer); } } diff --git a/src/game/client/components/binds.h b/src/game/client/components/binds.h index ad51a47c4..7812242cf 100644 --- a/src/game/client/components/binds.h +++ b/src/game/client/components/binds.h @@ -16,27 +16,27 @@ class CBinds : public CComponent static void ConUnbindAll(IConsole::IResult *pResult, void *pUserData); static void ConDumpBinds(IConsole::IResult *pResult, void *pUserData); class IConsole *GetConsole() const { return Console(); } - + static void ConfigSaveCallback(class IConfig *pConfig, void *pUserData); - + public: CBinds(); - + class CBindsSpecial : public CComponent { public: CBinds *m_pBinds; virtual bool OnInput(IInput::CEvent Event); }; - + CBindsSpecial m_SpecialBinds; - + void Bind(int KeyID, const char *pStr); void SetDefaults(); void UnbindAll(); const char *Get(int KeyID); const char *GetKey(const char *pBindStr); - + virtual void OnConsoleInit(); virtual bool OnInput(IInput::CEvent Event); }; diff --git a/src/game/client/components/broadcast.cpp b/src/game/client/components/broadcast.cpp index 17b2d66b6..ccf49bf6c 100644 --- a/src/game/client/components/broadcast.cpp +++ b/src/game/client/components/broadcast.cpp @@ -12,7 +12,7 @@ #include #include "broadcast.h" - + void CBroadcast::OnReset() { m_BroadcastTime = 0; @@ -24,7 +24,7 @@ void CBroadcast::OnRender() return; Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300); - + if(time_get() < m_BroadcastTime) { CTextCursor Cursor; diff --git a/src/game/client/components/camera.cpp b/src/game/client/components/camera.cpp index f02b28619..5a8dc8c89 100644 --- a/src/game/client/components/camera.cpp +++ b/src/game/client/components/camera.cpp @@ -20,7 +20,7 @@ void CCamera::OnRender() //vec2 center; m_Zoom = 1.0f; - // update camera center + // update camera center if(m_pClient->m_Snap.m_SpecInfo.m_Active && !m_pClient->m_Snap.m_SpecInfo.m_UsePosition) { if(m_CamType != CAMTYPE_SPEC) @@ -50,7 +50,7 @@ void CCamera::OnRender() CameraOffset = normalize(m_pClient->m_pControls->m_MousePos)*OffsetAmount; } - + if(m_pClient->m_Snap.m_SpecInfo.m_Active) m_Center = m_pClient->m_Snap.m_SpecInfo.m_Position + CameraOffset; else diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 192641949..ee294dc45 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -32,7 +32,7 @@ void CChat::OnReset() m_aLines[i].m_aText[0] = 0; m_aLines[i].m_aName[0] = 0; } - + m_Show = false; m_InputUpdate = false; m_ChatStringOffset = 0; @@ -126,7 +126,7 @@ bool CChat::OnInput(IInput::CEvent Event) for(m_PlaceholderLength = 0; *pCursor && *pCursor != ' '; ++pCursor) ++m_PlaceholderLength; - + str_copy(m_aCompletionBuffer, m_Input.GetString()+m_PlaceholderOffset, min(static_cast(sizeof(m_aCompletionBuffer)), m_PlaceholderLength+1)); } @@ -204,7 +204,7 @@ bool CChat::OnInput(IInput::CEvent Event) else m_Input.Clear(); } - + return true; } @@ -220,7 +220,7 @@ void CChat::EnableMode(int Team) m_Mode = MODE_TEAM; else m_Mode = MODE_ALL; - + m_Input.Clear(); Input()->ClearEvents(); m_CompletionChosen = -1; @@ -241,7 +241,7 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine) if(ClientID != -1 && (m_pClient->m_aClients[ClientID].m_aName[0] == '\0' || // unknown client m_pClient->m_aClients[ClientID].m_ChatIgnore)) return; - + bool Highlighted = false; char *p = const_cast(pLine); while(*p) @@ -285,11 +285,11 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine) else if(m_pClient->m_aClients[ClientID].m_Team == TEAM_BLUE) m_aLines[m_CurrentLine].m_NameColor = TEAM_BLUE; } - + str_copy(m_aLines[m_CurrentLine].m_aName, m_pClient->m_aClients[ClientID].m_aName, sizeof(m_aLines[m_CurrentLine].m_aName)); str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), ": %s", pLine); } - + char aBuf[1024]; str_format(aBuf, sizeof(aBuf), "%s%s", m_aLines[m_CurrentLine].m_aName, m_aLines[m_CurrentLine].m_aText); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chat", aBuf); @@ -317,7 +317,7 @@ void CChat::OnRender() TextRender()->SetCursor(&Cursor, x, y, 8.0f, TEXTFLAG_RENDER); Cursor.m_LineWidth = Width-190.0f; Cursor.m_MaxLines = 2; - + if(m_Mode == MODE_ALL) TextRender()->TextEx(&Cursor, Localize("All"), -1); else if(m_Mode == MODE_TEAM) @@ -326,7 +326,7 @@ void CChat::OnRender() TextRender()->TextEx(&Cursor, Localize("Chat"), -1); TextRender()->TextEx(&Cursor, ": ", -1); - + // check if the visible text has to be moved if(m_InputUpdate) { @@ -373,7 +373,7 @@ void CChat::OnRender() int r = ((m_CurrentLine-i)+MAX_LINES)%MAX_LINES; if(Now > m_aLines[r].m_Time+16*time_freq() && !m_Show) break; - + // get the y offset (calculate it if we haven't done that yet) if(m_aLines[r].m_YOffset[OffsetType] < 0.0f) { @@ -388,7 +388,7 @@ void CChat::OnRender() // cut off if msgs waste too much space if(y < HeightLimit) break; - + float Blend = Now > m_aLines[r].m_Time+14*time_freq() && !m_Show ? 1.0f-(Now-m_aLines[r].m_Time-14*time_freq())/(2.0f*time_freq()) : 1.0f; // reset the cursor @@ -408,7 +408,7 @@ void CChat::OnRender() TextRender()->TextColor(0.75f, 0.5f, 0.75f, Blend); // spectator else TextRender()->TextColor(0.8f, 0.8f, 0.8f, Blend); - + TextRender()->TextEx(&Cursor, m_aLines[r].m_aName, -1); // render line diff --git a/src/game/client/components/chat.h b/src/game/client/components/chat.h index bb68d7be3..60e183874 100644 --- a/src/game/client/components/chat.h +++ b/src/game/client/components/chat.h @@ -9,8 +9,8 @@ class CChat : public CComponent { CLineInput m_Input; - - enum + + enum { MAX_LINES = 25, }; @@ -49,23 +49,23 @@ class CChat : public CComponent int m_PlaceholderLength; char *m_pHistoryEntry; TStaticRingBuffer m_History; - + static void ConSay(IConsole::IResult *pResult, void *pUserData); static void ConSayTeam(IConsole::IResult *pResult, void *pUserData); static void ConChat(IConsole::IResult *pResult, void *pUserData); static void ConShowChat(IConsole::IResult *pResult, void *pUserData); - + public: CChat(); bool IsActive() const { return m_Mode != MODE_NONE; } - + void AddLine(int ClientID, int Team, const char *pLine); - + void EnableMode(int Team); - + void Say(int Team, const char *pLine); - + virtual void OnReset(); virtual void OnConsoleInit(); virtual void OnStateChange(int NewState, int OldState); diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp index a7da3075d..33c6db432 100644 --- a/src/game/client/components/console.cpp +++ b/src/game/client/components/console.cpp @@ -39,9 +39,9 @@ enum CGameConsole::CInstance::CInstance(int Type) { m_pHistoryEntry = 0x0; - + m_Type = Type; - + if(Type == CGameConsole::CONSOLETYPE_LOCAL) m_CompletionFlagmask = CFGFLAG_CLIENT; else @@ -50,7 +50,7 @@ CGameConsole::CInstance::CInstance(int Type) m_aCompletionBuffer[0] = 0; m_CompletionChosen = -1; m_CompletionRenderOffset = 0.0f; - + m_pCommand = 0x0; } @@ -95,7 +95,7 @@ void CGameConsole::CInstance::PossibleCommandsCompleteCallback(const char *pStr, void CGameConsole::CInstance::OnInput(IInput::CEvent Event) { bool Handled = false; - + if(Event.m_Flags&IInput::FLAG_PRESS) { if(Event.m_Key == KEY_RETURN || Event.m_Key == KEY_KP_ENTER) @@ -111,7 +111,7 @@ void CGameConsole::CInstance::OnInput(IInput::CEvent Event) m_Input.Clear(); m_pHistoryEntry = 0x0; } - + Handled = true; } else if (Event.m_Key == KEY_UP) @@ -197,7 +197,7 @@ void CGameConsole::CInstance::OnInput(IInput::CEvent Event) for(; i < (int)sizeof(aBuf)-1 && *pSrc && *pSrc != ' '; i++, pSrc++) aBuf[i] = *pSrc; aBuf[i] = 0; - + m_pCommand = m_pGameConsole->m_pConsole->GetCommandInfo(aBuf, m_CompletionFlagmask); } } @@ -233,9 +233,9 @@ float CGameConsole::TimeNow() CGameConsole::CInstance *CGameConsole::CurrentConsole() { - if(m_ConsoleType == CONSOLETYPE_REMOTE) - return &m_RemoteConsole; - return &m_LocalConsole; + if(m_ConsoleType == CONSOLETYPE_REMOTE) + return &m_RemoteConsole; + return &m_LocalConsole; } void CGameConsole::OnReset() @@ -263,7 +263,7 @@ struct CRenderInfo void CGameConsole::PossibleCommandsRenderCallback(const char *pStr, void *pUser) { CRenderInfo *pInfo = static_cast(pUser); - + if(pInfo->m_EnumCount == pInfo->m_WantedCompletion) { float tw = pInfo->m_pSelf->TextRender()->TextWidth(pInfo->m_Cursor.m_pFont, pInfo->m_Cursor.m_FontSize, pStr, -1); @@ -272,7 +272,7 @@ void CGameConsole::PossibleCommandsRenderCallback(const char *pStr, void *pUser) pInfo->m_pSelf->Graphics()->SetColor(229.0f/255.0f,185.0f/255.0f,4.0f/255.0f,0.85f); pInfo->m_pSelf->RenderTools()->DrawRoundRect(pInfo->m_Cursor.m_X-3, pInfo->m_Cursor.m_Y, tw+5, pInfo->m_Cursor.m_FontSize+4, pInfo->m_Cursor.m_FontSize/3); pInfo->m_pSelf->Graphics()->QuadsEnd(); - + // scroll when out of sight if(pInfo->m_Cursor.m_X < 3.0f) pInfo->m_Offset = 0.0f; @@ -285,7 +285,7 @@ void CGameConsole::PossibleCommandsRenderCallback(const char *pStr, void *pUser) else { const char *pMatchStart = str_find_nocase(pStr, pInfo->m_pCurrentCmd); - + if(pMatchStart) { pInfo->m_pSelf->TextRender()->TextColor(0.5f,0.5f,0.5f,1); @@ -301,14 +301,14 @@ void CGameConsole::PossibleCommandsRenderCallback(const char *pStr, void *pUser) pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pStr, -1); } } - + pInfo->m_EnumCount++; pInfo->m_Cursor.m_X += 7.0f; } void CGameConsole::OnRender() { - CUIRect Screen = *UI()->Screen(); + CUIRect Screen = *UI()->Screen(); float ConsoleMaxHeight = Screen.h*3/5.0f; float ConsoleHeight; @@ -325,11 +325,11 @@ void CGameConsole::OnRender() } if (m_ConsoleState == CONSOLE_OPEN && g_Config.m_ClEditor) - Toggle(CONSOLETYPE_LOCAL); - + Toggle(CONSOLETYPE_LOCAL); + if (m_ConsoleState == CONSOLE_CLOSED) return; - + if (m_ConsoleState == CONSOLE_OPEN) Input()->MouseModeAbsolute(); @@ -348,31 +348,31 @@ void CGameConsole::OnRender() // do console shadow Graphics()->TextureSet(-1); - Graphics()->QuadsBegin(); + Graphics()->QuadsBegin(); IGraphics::CColorVertex Array[4] = { - IGraphics::CColorVertex(0, 0,0,0, 0.5f), - IGraphics::CColorVertex(1, 0,0,0, 0.5f), - IGraphics::CColorVertex(2, 0,0,0, 0.0f), + IGraphics::CColorVertex(0, 0,0,0, 0.5f), + IGraphics::CColorVertex(1, 0,0,0, 0.5f), + IGraphics::CColorVertex(2, 0,0,0, 0.0f), IGraphics::CColorVertex(3, 0,0,0, 0.0f)}; Graphics()->SetColorVertex(Array, 4); IGraphics::CQuadItem QuadItem(0, ConsoleHeight, Screen.w, 10.0f); Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); + Graphics()->QuadsEnd(); // do background Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CONSOLE_BG].m_Id); - Graphics()->QuadsBegin(); - Graphics()->SetColor(0.2f, 0.2f, 0.2f,0.9f); - if(m_ConsoleType == CONSOLETYPE_REMOTE) - Graphics()->SetColor(0.4f, 0.2f, 0.2f,0.9f); - Graphics()->QuadsSetSubset(0,-ConsoleHeight*0.075f,Screen.w*0.075f*0.5f,0); + Graphics()->QuadsBegin(); + Graphics()->SetColor(0.2f, 0.2f, 0.2f,0.9f); + if(m_ConsoleType == CONSOLETYPE_REMOTE) + Graphics()->SetColor(0.4f, 0.2f, 0.2f,0.9f); + Graphics()->QuadsSetSubset(0,-ConsoleHeight*0.075f,Screen.w*0.075f*0.5f,0); QuadItem = IGraphics::CQuadItem(0, 0, Screen.w, ConsoleHeight); Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); + Graphics()->QuadsEnd(); // do small bar shadow Graphics()->TextureSet(-1); - Graphics()->QuadsBegin(); + Graphics()->QuadsBegin(); Array[0] = IGraphics::CColorVertex(0, 0,0,0, 0.0f); Array[1] = IGraphics::CColorVertex(1, 0,0,0, 0.0f); Array[2] = IGraphics::CColorVertex(2, 0,0,0, 0.25f); @@ -380,20 +380,20 @@ void CGameConsole::OnRender() Graphics()->SetColorVertex(Array, 4); QuadItem = IGraphics::CQuadItem(0, ConsoleHeight-20, Screen.w, 10); Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); + Graphics()->QuadsEnd(); // do the lower bar Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CONSOLE_BAR].m_Id); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.9f); - Graphics()->QuadsSetSubset(0,0.1f,Screen.w*0.015f,1-0.1f); + Graphics()->QuadsBegin(); + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.9f); + Graphics()->QuadsSetSubset(0,0.1f,Screen.w*0.015f,1-0.1f); QuadItem = IGraphics::CQuadItem(0,ConsoleHeight-10.0f,Screen.w,10.0f); Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); - - ConsoleHeight -= 22.0f; - - CInstance *pConsole = CurrentConsole(); + Graphics()->QuadsEnd(); + + ConsoleHeight -= 22.0f; + + CInstance *pConsole = CurrentConsole(); { float FontSize = 10.0f; @@ -410,7 +410,7 @@ void CGameConsole::OnRender() Info.m_pCurrentCmd = pConsole->m_aCompletionBuffer; TextRender()->SetCursor(&Info.m_Cursor, x+Info.m_Offset, y+RowHeight+2.0f, FontSize, TEXTFLAG_RENDER); - // render prompt + // render prompt CTextCursor Cursor; TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER); const char *pPrompt = "> "; @@ -427,7 +427,7 @@ void CGameConsole::OnRender() pPrompt = "NOT CONNECTED> "; } TextRender()->TextEx(&Cursor, pPrompt, -1); - + x = Cursor.m_X; // render console input (wrap line) @@ -435,7 +435,7 @@ void CGameConsole::OnRender() 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)); @@ -444,12 +444,12 @@ void CGameConsole::OnRender() for(int i = 0; i < pConsole->m_Input.GetLength(); ++i) aInputString[i] = '*'; } - + TextRender()->TextEx(&Cursor, aInputString, pConsole->m_Input.GetCursorOffset()); CTextCursor Marker = Cursor; TextRender()->TextEx(&Marker, "|", -1); TextRender()->TextEx(&Cursor, aInputString+pConsole->m_Input.GetCursorOffset(), -1); - + // render possible commands if(m_ConsoleType == CONSOLETYPE_LOCAL || Client()->RconAuthed()) { @@ -457,12 +457,12 @@ void CGameConsole::OnRender() { m_pConsole->PossibleCommands(pConsole->m_aCompletionBuffer, pConsole->m_CompletionFlagmask, PossibleCommandsRenderCallback, &Info); pConsole->m_CompletionRenderOffset = Info.m_Offset; - + if(Info.m_EnumCount <= 0) { if(pConsole->m_pCommand) { - + char aBuf[512]; str_format(aBuf, sizeof(aBuf), "Help: %s ", pConsole->m_pCommand->m_pHelp); TextRender()->TextEx(&Info.m_Cursor, aBuf, -1); @@ -492,7 +492,7 @@ void CGameConsole::OnRender() pEntry->m_YOffset = Cursor.m_Y+Cursor.m_FontSize+LineOffset; } OffsetY += pEntry->m_YOffset; - + // next page when lines reach the top if(y-OffsetY <= RowHeight) break; @@ -533,7 +533,7 @@ void CGameConsole::OnRender() str_format(aBuf, sizeof(aBuf), "v%s", GAME_VERSION); float Width = TextRender()->TextWidth(0, FontSize, aBuf, -1); TextRender()->Text(0, Screen.w-Width-10.0f, 0.0f, FontSize, aBuf, -1); - } + } } void CGameConsole::OnMessage(int MsgType, void *pRawMsg) @@ -551,7 +551,7 @@ bool CGameConsole::OnInput(IInput::CEvent Event) Toggle(m_ConsoleType); else CurrentConsole()->OnInput(Event); - + return true; } @@ -562,7 +562,7 @@ void CGameConsole::Toggle(int Type) // don't toggle console, just switch what console to use } else - { + { if (m_ConsoleState == CONSOLE_CLOSED || m_ConsoleState == CONSOLE_OPEN) { m_StateChangeEnd = TimeNow()+m_StateChangeDuration; @@ -671,10 +671,10 @@ void CGameConsole::OnConsoleInit() m_RemoteConsole.Init(this); m_pConsole = Kernel()->RequestInterface(); - + // Console()->RegisterPrintCallback(ClientConsolePrintCallback, this); - + Console()->Register("toggle_local_console", "", CFGFLAG_CLIENT, ConToggleLocalConsole, this, "Toggle local console"); Console()->Register("toggle_remote_console", "", CFGFLAG_CLIENT, ConToggleRemoteConsole, this, "Toggle remote console"); Console()->Register("clear_local_console", "", CFGFLAG_CLIENT, ConClearLocalConsole, this, "Clear local console"); diff --git a/src/game/client/components/console.h b/src/game/client/components/console.h index 2739724b1..003a9423e 100644 --- a/src/game/client/components/console.h +++ b/src/game/client/components/console.h @@ -24,15 +24,15 @@ class CGameConsole : public CComponent int m_Type; int m_CompletionEnumerationCount; int m_BacklogActPage; - + public: CGameConsole *m_pGameConsole; - + char m_aCompletionBuffer[128]; int m_CompletionChosen; int m_CompletionFlagmask; float m_CompletionRenderOffset; - + IConsole::CCommandInfo *m_pCommand; CInstance(int t); @@ -42,22 +42,22 @@ class CGameConsole : public CComponent void ClearHistory(); void ExecuteLine(const char *pLine); - + void OnInput(IInput::CEvent Event); void PrintLine(const char *pLine); - + const char *GetString() const { return m_Input.GetString(); } static void PossibleCommandsCompleteCallback(const char *pStr, void *pUser); }; - + class IConsole *m_pConsole; - + CInstance m_LocalConsole; CInstance m_RemoteConsole; - + CInstance *CurrentConsole(); float TimeNow(); - + int m_ConsoleType; int m_ConsoleState; float m_StateChangeEnd; @@ -74,7 +74,7 @@ class CGameConsole : public CComponent static void ConClearRemoteConsole(IConsole::IResult *pResult, void *pUserData); static void ConDumpLocalConsole(IConsole::IResult *pResult, void *pUserData); static void ConDumpRemoteConsole(IConsole::IResult *pResult, void *pUserData); - + public: enum { diff --git a/src/game/client/components/controls.cpp b/src/game/client/components/controls.cpp index 56b6e63bb..81c4d5ae7 100644 --- a/src/game/client/components/controls.cpp +++ b/src/game/client/components/controls.cpp @@ -28,7 +28,7 @@ void CControls::OnReset() m_LastData.m_Fire &= INPUT_STATE_MASK; m_LastData.m_Jump = 0; m_InputData = m_LastData; - + m_InputDirectionLeft = 0; m_InputDirectionRight = 0; } @@ -86,31 +86,31 @@ void CControls::OnConsoleInit() Console()->Register("+hook", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputData.m_Hook, "Hook"); Console()->Register("+fire", "", CFGFLAG_CLIENT, ConKeyInputCounter, &m_InputData.m_Fire, "Fire"); - { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 1}; Console()->Register("+weapon1", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to hammer"); } - { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 2}; Console()->Register("+weapon2", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to gun"); } - { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 3}; Console()->Register("+weapon3", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to shotgun"); } - { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 4}; Console()->Register("+weapon4", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to grenade"); } - { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 5}; Console()->Register("+weapon5", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to rifle"); } + { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 1}; Console()->Register("+weapon1", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to hammer"); } + { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 2}; Console()->Register("+weapon2", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to gun"); } + { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 3}; Console()->Register("+weapon3", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to shotgun"); } + { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 4}; Console()->Register("+weapon4", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to grenade"); } + { static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 5}; Console()->Register("+weapon5", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to rifle"); } - { static CInputSet s_Set = {this, &m_InputData.m_NextWeapon, 0}; Console()->Register("+nextweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to next weapon"); } - { static CInputSet s_Set = {this, &m_InputData.m_PrevWeapon, 0}; Console()->Register("+prevweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to previous weapon"); } + { static CInputSet s_Set = {this, &m_InputData.m_NextWeapon, 0}; Console()->Register("+nextweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to next weapon"); } + { static CInputSet s_Set = {this, &m_InputData.m_PrevWeapon, 0}; Console()->Register("+prevweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to previous weapon"); } } void CControls::OnMessage(int Msg, void *pRawMsg) { - if(Msg == NETMSGTYPE_SV_WEAPONPICKUP) - { - CNetMsg_Sv_WeaponPickup *pMsg = (CNetMsg_Sv_WeaponPickup *)pRawMsg; - if(g_Config.m_ClAutoswitchWeapons) - m_InputData.m_WantedWeapon = pMsg->m_Weapon+1; - } + if(Msg == NETMSGTYPE_SV_WEAPONPICKUP) + { + CNetMsg_Sv_WeaponPickup *pMsg = (CNetMsg_Sv_WeaponPickup *)pRawMsg; + if(g_Config.m_ClAutoswitchWeapons) + m_InputData.m_WantedWeapon = pMsg->m_Weapon+1; + } } int CControls::SnapInput(int *pData) { static int64 LastSendTime = 0; bool Send = false; - + // update player state if(m_pClient->m_pChat->IsActive()) m_InputData.m_PlayerFlags = PLAYERFLAG_CHATTING; @@ -118,20 +118,20 @@ int CControls::SnapInput(int *pData) m_InputData.m_PlayerFlags = PLAYERFLAG_IN_MENU; else m_InputData.m_PlayerFlags = PLAYERFLAG_PLAYING; - + if(m_pClient->m_pScoreboard->Active()) m_InputData.m_PlayerFlags |= PLAYERFLAG_SCOREBOARD; if(m_LastData.m_PlayerFlags != m_InputData.m_PlayerFlags) Send = true; - + m_LastData.m_PlayerFlags = m_InputData.m_PlayerFlags; - + // we freeze the input if chat or menu is activated if(!(m_InputData.m_PlayerFlags&PLAYERFLAG_PLAYING)) { OnReset(); - + mem_copy(pData, &m_InputData, sizeof(m_InputData)); // send once a second just to be sure @@ -140,7 +140,7 @@ int CControls::SnapInput(int *pData) } else { - + m_InputData.m_TargetX = (int)m_MousePos.x; m_InputData.m_TargetY = (int)m_MousePos.y; if(!m_InputData.m_TargetX && !m_InputData.m_TargetY) @@ -148,7 +148,7 @@ int CControls::SnapInput(int *pData) m_InputData.m_TargetX = 1; m_MousePos.x = 1; } - + // set direction m_InputData.m_Direction = 0; if(m_InputDirectionLeft && !m_InputDirectionRight) @@ -184,16 +184,16 @@ int CControls::SnapInput(int *pData) if(time_get() > LastSendTime + time_freq()/25) Send = true; } - - // copy and return size + + // copy and return size m_LastData = m_InputData; - + if(!Send) return 0; - + LastSendTime = time_get(); mem_copy(pData, &m_InputData, sizeof(m_InputData)); - return sizeof(m_InputData); + return sizeof(m_InputData); } void CControls::OnRender() @@ -211,7 +211,7 @@ bool CControls::OnMouseMove(float x, float y) { if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED) return false; - + m_MousePos += vec2(x, y); // TODO: ugly ClampMousePos(); @@ -224,14 +224,14 @@ void CControls::ClampMousePos() { m_MousePos.x = clamp(m_MousePos.x, 200.0f, Collision()->GetWidth()*32-200.0f); m_MousePos.y = clamp(m_MousePos.y, 200.0f, Collision()->GetHeight()*32-200.0f); - + } else { float CameraMaxDistance = 200.0f; float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f; float MouseMax = min(CameraMaxDistance/FollowFactor + g_Config.m_ClMouseDeadzone, (float)g_Config.m_ClMouseMaxDistance); - + if(length(m_MousePos) > MouseMax) m_MousePos = normalize(m_MousePos)*MouseMax; } diff --git a/src/game/client/components/controls.h b/src/game/client/components/controls.h index a50318f5a..aefc850ca 100644 --- a/src/game/client/components/controls.h +++ b/src/game/client/components/controls.h @@ -6,7 +6,7 @@ #include class CControls : public CComponent -{ +{ public: vec2 m_MousePos; vec2 m_TargetPos; @@ -17,7 +17,7 @@ public: int m_InputDirectionRight; CControls(); - + virtual void OnReset(); virtual void OnRelease(); virtual void OnRender(); @@ -25,7 +25,7 @@ public: virtual bool OnMouseMove(float x, float y); virtual void OnConsoleInit(); virtual void OnPlayerDeath(); - + int SnapInput(int *pData); void ClampMousePos(); }; diff --git a/src/game/client/components/countryflags.cpp b/src/game/client/components/countryflags.cpp index ae0217b2f..2429ad3fa 100644 --- a/src/game/client/components/countryflags.cpp +++ b/src/game/client/components/countryflags.cpp @@ -19,7 +19,7 @@ void CCountryFlags::LoadCountryflagsIndexfile() Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", "couldn't open index file"); return; } - + char aOrigin[128]; CLineReader LineReader; LineReader.Init(File); @@ -28,7 +28,7 @@ void CCountryFlags::LoadCountryflagsIndexfile() { if(!str_length(pLine) || pLine[0] == '#') // skip empty lines and comments continue; - + str_copy(aOrigin, pLine, sizeof(aOrigin)); char *pReplacement = LineReader.Get(); if(!pReplacement) @@ -36,7 +36,7 @@ void CCountryFlags::LoadCountryflagsIndexfile() Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", "unexpected end of index file"); break; } - + if(pReplacement[0] != '=' || pReplacement[1] != '=' || pReplacement[2] != ' ') { char aBuf[128]; @@ -44,7 +44,7 @@ void CCountryFlags::LoadCountryflagsIndexfile() Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aBuf); continue; } - + // load the graphic file char aBuf[128]; str_format(aBuf, sizeof(aBuf), "countryflags/%s.png", aOrigin); diff --git a/src/game/client/components/countryflags.h b/src/game/client/components/countryflags.h index b0960661f..cd6290943 100644 --- a/src/game/client/components/countryflags.h +++ b/src/game/client/components/countryflags.h @@ -13,16 +13,16 @@ public: { int m_CountryCode; int m_Texture; - + bool operator<(const CCountryFlag &Other) { return m_CountryCode < Other.m_CountryCode; } }; - + void OnInit(); - + int Num() const; const CCountryFlag *Get(int Index) const; int Find(int CountryCode) const; - + private: sorted_array m_aCountryFlags; diff --git a/src/game/client/components/damageind.h b/src/game/client/components/damageind.h index 0515f646d..2f89e422c 100644 --- a/src/game/client/components/damageind.h +++ b/src/game/client/components/damageind.h @@ -27,7 +27,7 @@ class CDamageInd : public CComponent CItem *CreateI(); void DestroyI(CItem *i); -public: +public: CDamageInd(); void Create(vec2 Pos, vec2 Dir); diff --git a/src/game/client/components/debughud.cpp b/src/game/client/components/debughud.cpp index b904f60a0..7145705c4 100644 --- a/src/game/client/components/debughud.cpp +++ b/src/game/client/components/debughud.cpp @@ -22,16 +22,16 @@ void CDebugHud::RenderNetCorrections() if(!g_Config.m_Debug || g_Config.m_DbgGraphs || !m_pClient->m_Snap.m_pLocalCharacter || !m_pClient->m_Snap.m_pLocalPrevCharacter) return; - float Width = 300*Graphics()->ScreenAspect(); + float Width = 300*Graphics()->ScreenAspect(); Graphics()->MapScreen(0, 0, Width, 300); - + /*float speed = distance(vec2(netobjects.local_prev_character->x, netobjects.local_prev_character->y), vec2(netobjects.local_character->x, netobjects.local_character->y));*/ float Velspeed = length(vec2(m_pClient->m_Snap.m_pLocalCharacter->m_VelX/256.0f, m_pClient->m_Snap.m_pLocalCharacter->m_VelY/256.0f))*50; float Ramp = VelocityRamp(Velspeed, m_pClient->m_Tuning.m_VelrampStart, m_pClient->m_Tuning.m_VelrampRange, m_pClient->m_Tuning.m_VelrampCurvature); - - const char *paStrings[] = {"velspeed:", "velspeed*ramp:", "ramp:", "Pos", " x:", " y:", "netobj corrections", " num:", " on:"}; + + const char *paStrings[] = {"velspeed:", "velspeed*ramp:", "ramp:", "Pos", " x:", " y:", "netobj corrections", " num:", " on:"}; const int Num = sizeof(paStrings)/sizeof(char *); const float LineHeight = 6.0f; const float Fontsize = 5.0f; @@ -75,11 +75,11 @@ void CDebugHud::RenderTuning() // render tuning debugging if(!g_Config.m_DbgTuning) return; - + CTuningParams StandardTuning; - + Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300); - + float y = 50.0f; int Count = 0; for(int i = 0; i < m_pClient->m_Tuning.Num(); i++) @@ -88,7 +88,7 @@ void CDebugHud::RenderTuning() float Current, Standard; m_pClient->m_Tuning.Get(i, &Current); StandardTuning.Get(i, &Standard); - + if(Standard == Current) TextRender()->TextColor(1,1,1,1.0f); else @@ -96,7 +96,7 @@ void CDebugHud::RenderTuning() float w; float x = 5.0f; - + str_format(aBuf, sizeof(aBuf), "%.2f", Standard); x += 20.0f; w = TextRender()->TextWidth(0, 5, aBuf, -1); @@ -109,12 +109,12 @@ void CDebugHud::RenderTuning() x += 5.0f; TextRender()->Text(0x0, x, y+Count*6, 5, m_pClient->m_Tuning.m_apNames[i], -1); - + Count++; } - + y = y+Count*6; - + Graphics()->TextureSet(-1); Graphics()->BlendNormal(); Graphics()->LinesBegin(); diff --git a/src/game/client/components/debughud.h b/src/game/client/components/debughud.h index ad378dc81..145f921a9 100644 --- a/src/game/client/components/debughud.h +++ b/src/game/client/components/debughud.h @@ -5,7 +5,7 @@ #include class CDebugHud : public CComponent -{ +{ void RenderNetCorrections(); void RenderTuning(); public: diff --git a/src/game/client/components/effects.cpp b/src/game/client/components/effects.cpp index 9a5ff2d33..573ac4104 100644 --- a/src/game/client/components/effects.cpp +++ b/src/game/client/components/effects.cpp @@ -43,7 +43,7 @@ void CEffects::AirJump(vec2 Pos) p.m_Pos = Pos + vec2(6.0f, 16.0f); m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); - + m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, Pos); } @@ -56,7 +56,7 @@ void CEffects::PowerupShine(vec2 Pos, vec2 size) { if(!m_Add50hz) return; - + CParticle p; p.SetDefault(); p.m_Spr = SPRITE_PART_SLICE; @@ -77,7 +77,7 @@ void CEffects::SmokeTrail(vec2 Pos, vec2 Vel) { if(!m_Add50hz) return; - + CParticle p; p.SetDefault(); p.m_Spr = SPRITE_PART_SMOKE; @@ -96,7 +96,7 @@ void CEffects::SkidTrail(vec2 Pos, vec2 Vel) { if(!m_Add100hz) return; - + CParticle p; p.SetDefault(); p.m_Spr = SPRITE_PART_SMOKE; @@ -108,14 +108,14 @@ void CEffects::SkidTrail(vec2 Pos, vec2 Vel) p.m_Friction = 0.7f; p.m_Gravity = frandom()*-500.0f; p.m_Color = vec4(0.75f,0.75f,0.75f,1.0f); - m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); + m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); } void CEffects::BulletTrail(vec2 Pos) { if(!m_Add100hz) return; - + CParticle p; p.SetDefault(); p.m_Spr = SPRITE_PART_BALL; @@ -145,7 +145,7 @@ void CEffects::PlayerSpawn(vec2 Pos) p.m_Friction = 0.7f; p.m_Color = vec4(0xb5/255.0f, 0x50/255.0f, 0xcb/255.0f, 1.0f); m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); - + } m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_PLAYER_SPAWN, 1.0f, Pos); } @@ -154,7 +154,7 @@ void CEffects::PlayerDeath(vec2 Pos, int ClientID) { vec3 BloodColor(1.0f,1.0f,1.0f); - if(ClientID >= 0) + if(ClientID >= 0) { if(m_pClient->m_aClients[ClientID].m_UseCustomColor) BloodColor = m_pClient->m_pSkins->GetColorV3(m_pClient->m_aClients[ClientID].m_ColorBody); @@ -165,7 +165,7 @@ void CEffects::PlayerDeath(vec2 Pos, int ClientID) BloodColor = s->m_BloodColor; } } - + for(int i = 0; i < 64; i++) { CParticle p; @@ -195,11 +195,11 @@ void CEffects::Explosion(vec2 Pos) { if(x == 0 && y == 0) continue; - + float a = 1 - (length(vec2(x,y)) / length(vec2(8,8))); m_pClient->m_pFlow->Add(Pos+vec2(x,y)*16, normalize(vec2(x,y))*5000.0f*a, 10.0f); } - + // add the explosion CParticle p; p.SetDefault(); @@ -210,7 +210,7 @@ void CEffects::Explosion(vec2 Pos) p.m_EndSize = 0; p.m_Rot = frandom()*pi*2; m_pClient->m_pParticles->Add(CParticles::GROUP_EXPLOSIONS, &p); - + // add the smoke for(int i = 0; i < 24; i++) { @@ -241,7 +241,7 @@ void CEffects::HammerHit(vec2 Pos) p.m_StartSize = 120.0f; p.m_EndSize = 0; p.m_Rot = frandom()*pi*2; - m_pClient->m_pParticles->Add(CParticles::GROUP_EXPLOSIONS, &p); + m_pClient->m_pParticles->Add(CParticles::GROUP_EXPLOSIONS, &p); m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_HAMMER_HIT, 1.0f, Pos); } @@ -253,7 +253,7 @@ void CEffects::OnRender() if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - + if(time_get()-LastUpdate100hz > time_freq()/(100*pInfo->m_Speed)) { m_Add100hz = true; @@ -269,10 +269,10 @@ void CEffects::OnRender() } else m_Add50hz = false; - + if(m_Add50hz) m_pClient->m_pFlow->Update(); - + return; } @@ -291,7 +291,7 @@ void CEffects::OnRender() } else m_Add50hz = false; - + if(m_Add50hz) m_pClient->m_pFlow->Update(); } diff --git a/src/game/client/components/effects.h b/src/game/client/components/effects.h index b39243823..9ededb832 100644 --- a/src/game/client/components/effects.h +++ b/src/game/client/components/effects.h @@ -5,7 +5,7 @@ #include class CEffects : public CComponent -{ +{ bool m_Add50hz; bool m_Add100hz; public: diff --git a/src/game/client/components/emoticon.cpp b/src/game/client/components/emoticon.cpp index 64b47b745..741a604fc 100644 --- a/src/game/client/components/emoticon.cpp +++ b/src/game/client/components/emoticon.cpp @@ -53,7 +53,7 @@ bool CEmoticon::OnMouseMove(float x, float y) { if(!m_Active) return false; - + m_SelectorMouse += vec2(x,y); return true; } @@ -90,7 +90,7 @@ void CEmoticon::DrawCircle(float x, float y, float r, int Segments) m_pClient->Graphics()->QuadsDrawFreeform(Array, NumItems); } - + void CEmoticon::OnRender() { if(!m_Active) @@ -100,9 +100,9 @@ void CEmoticon::OnRender() m_WasActive = false; return; } - + m_WasActive = true; - + if (length(m_SelectorMouse) > 140) m_SelectorMouse = normalize(m_SelectorMouse) * 140; @@ -113,7 +113,7 @@ void CEmoticon::OnRender() if (length(m_SelectorMouse) > 100) m_SelectedEmote = (int)(SelectedAngle / (2*pi) * NUM_EMOTICONS); - CUIRect Screen = *UI()->Screen(); + CUIRect Screen = *UI()->Screen(); Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); @@ -147,12 +147,12 @@ void CEmoticon::OnRender() Graphics()->QuadsEnd(); - Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1,1,1,1); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id); + Graphics()->QuadsBegin(); + Graphics()->SetColor(1,1,1,1); IGraphics::CQuadItem QuadItem(m_SelectorMouse.x+Screen.w/2,m_SelectorMouse.y+Screen.h/2,24,24); Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); + Graphics()->QuadsEnd(); } void CEmoticon::Emote(int Emoticon) diff --git a/src/game/client/components/emoticon.h b/src/game/client/components/emoticon.h index add6c9b97..37bc8372e 100644 --- a/src/game/client/components/emoticon.h +++ b/src/game/client/components/emoticon.h @@ -8,19 +8,19 @@ class CEmoticon : public CComponent { void DrawCircle(float x, float y, float r, int Segments); - + bool m_WasActive; bool m_Active; - + vec2 m_SelectorMouse; int m_SelectedEmote; static void ConKeyEmoticon(IConsole::IResult *pResult, void *pUserData); static void ConEmote(IConsole::IResult *pResult, void *pUserData); - + public: CEmoticon(); - + virtual void OnReset(); virtual void OnConsoleInit(); virtual void OnRender(); diff --git a/src/game/client/components/flow.cpp b/src/game/client/components/flow.cpp index 824687c06..8cfc54e7f 100644 --- a/src/game/client/components/flow.cpp +++ b/src/game/client/components/flow.cpp @@ -12,7 +12,7 @@ CFlow::CFlow() m_Width = 0; m_Spacing = 16; } - + void CFlow::DbgRender() { if(!m_pCells) @@ -34,7 +34,7 @@ void CFlow::DbgRender() NumItems = 0; } } - + if(NumItems) Graphics()->LinesDraw(Array, NumItems); Graphics()->LinesEnd(); @@ -47,12 +47,12 @@ void CFlow::Init() mem_free(m_pCells); m_pCells = 0; } - + CMapItemLayerTilemap *pTilemap = Layers()->GameLayer(); m_Width = pTilemap->m_Width*32/m_Spacing; m_Height = pTilemap->m_Height*32/m_Spacing; - // allocate and clear + // allocate and clear m_pCells = (CCell *)mem_alloc(sizeof(CCell)*m_Width*m_Height, 1); for(int y = 0; y < m_Height; y++) for(int x = 0; x < m_Width; x++) @@ -63,7 +63,7 @@ void CFlow::Update() { if(!m_pCells) return; - + for(int y = 0; y < m_Height; y++) for(int x = 0; x < m_Width; x++) m_pCells[y*m_Width+x].m_Vel *= 0.85f; @@ -73,24 +73,24 @@ vec2 CFlow::Get(vec2 Pos) { if(!m_pCells) return vec2(0,0); - + int x = (int)(Pos.x / m_Spacing); int y = (int)(Pos.y / m_Spacing); if(x < 0 || y < 0 || x >= m_Width || y >= m_Height) return vec2(0,0); - - return m_pCells[y*m_Width+x].m_Vel; + + return m_pCells[y*m_Width+x].m_Vel; } void CFlow::Add(vec2 Pos, vec2 Vel, float Size) { if(!m_pCells) return; - + int x = (int)(Pos.x / m_Spacing); int y = (int)(Pos.y / m_Spacing); if(x < 0 || y < 0 || x >= m_Width || y >= m_Height) return; - + m_pCells[y*m_Width+x].m_Vel += Vel; } diff --git a/src/game/client/components/flow.h b/src/game/client/components/flow.h index 3785ab56d..0b8e590f6 100644 --- a/src/game/client/components/flow.h +++ b/src/game/client/components/flow.h @@ -16,12 +16,12 @@ class CFlow : public CComponent int m_Height; int m_Width; int m_Spacing; - + void DbgRender(); void Init(); public: CFlow(); - + vec2 Get(vec2 Pos); void Add(vec2 Pos, vec2 Vel, float Size); void Update(); diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index 00fdd88de..188691a15 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -22,7 +22,7 @@ CHud::CHud() // won't work if zero m_AverageFPS = 1.0f; } - + void CHud::OnReset() { } @@ -30,7 +30,7 @@ void CHud::OnReset() void CHud::RenderGameTimer() { float Half = 300.0f*Graphics()->ScreenAspect()/2.0f; - + if(!(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_SUDDENDEATH)) { char Buf[32]; @@ -40,7 +40,7 @@ void CHud::RenderGameTimer() Time = m_pClient->m_Snap.m_pGameInfoObj->m_TimeLimit*60 - ((Client()->GameTick()-m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick)/Client()->GameTickSpeed()); if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER) - Time = 0; + Time = 0; } else Time = (Client()->GameTick()-m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick)/Client()->GameTickSpeed(); @@ -72,7 +72,7 @@ void CHud::RenderSuddenDeath() } void CHud::RenderScoreHud() -{ +{ // render small score hud if(!(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER)) { @@ -89,7 +89,7 @@ void CHud::RenderScoreHud() float ScoreWidthMax = max(max(aScoreTeamWidth[TEAM_RED], aScoreTeamWidth[TEAM_BLUE]), TextRender()->TextWidth(0, 14.0f, "100", -1)); float Split = 3.0f; float ImageSize = GameFlags&GAMEFLAG_FLAGS ? 16.0f : Split; - + for(int t = 0; t < 2; t++) { // draw box @@ -178,7 +178,7 @@ void CHud::RenderScoreHud() float aScoreWidth[2] = {TextRender()->TextWidth(0, 14.0f, aScore[0], -1), TextRender()->TextWidth(0, 14.0f, aScore[1], -1)}; float ScoreWidthMax = max(max(aScoreWidth[0], aScoreWidth[1]), TextRender()->TextWidth(0, 14.0f, "10", -1)); float Split = 3.0f, ImageSize = 16.0f, PosSize = 16.0f; - + for(int t = 0; t < 2; t++) { // draw box @@ -230,7 +230,7 @@ void CHud::RenderWarmupTimer() str_format(Buf, sizeof(Buf), "%d", Seconds); w = TextRender()->TextWidth(0, FontSize, Buf, -1); TextRender()->Text(0, 150*Graphics()->ScreenAspect()+-w/2, 75, FontSize, Buf, -1); - } + } } void CHud::MapscreenToGroup(float CenterX, float CenterY, CMapItemGroup *pGroup) @@ -269,7 +269,7 @@ void CHud::RenderTeambalanceWarning() // render prompt about team-balance bool Flash = time_get()/(time_freq()/2)%2 == 0; if(m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) - { + { int TeamDiff = m_pClient->m_Snap.m_aTeamSize[TEAM_RED]-m_pClient->m_Snap.m_aTeamSize[TEAM_BLUE]; if (g_Config.m_ClWarningTeambalance && (TeamDiff >= 2 || TeamDiff <= -2)) { @@ -289,7 +289,7 @@ void CHud::RenderVoting() { if(!m_pClient->m_pVoting->IsVoting() || Client()->State() == IClient::STATE_DEMOPLAYBACK) return; - + Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.40f); @@ -309,7 +309,7 @@ void CHud::RenderVoting() Cursor.m_LineWidth = 100.0f-tw; Cursor.m_MaxLines = 3; TextRender()->TextEx(&Cursor, m_pClient->m_pVoting->VoteDescription(), -1); - + // reason str_format(aBuf, sizeof(aBuf), "%s %s", Localize("Reason:"), m_pClient->m_pVoting->VoteReason()); TextRender()->SetCursor(&Cursor, 5.0f, 79.0f, 6.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); @@ -318,7 +318,7 @@ void CHud::RenderVoting() CUIRect Base = {5, 88, 100, 4}; m_pClient->m_pVoting->RenderBars(Base, false); - + const char *pYesKey = m_pClient->m_pBinds->GetKey("vote yes"); const char *pNoKey = m_pClient->m_pBinds->GetKey("vote no"); str_format(aBuf, sizeof(aBuf), "%s - %s", pYesKey, Localize("Vote yes")); @@ -333,7 +333,7 @@ void CHud::RenderCursor() { if(!m_pClient->m_Snap.m_pLocalCharacter || Client()->State() == IClient::STATE_DEMOPLAYBACK) return; - + MapscreenToGroup(m_pClient->m_pCamera->m_Center.x, m_pClient->m_pCamera->m_Center.y, Layers()->GameGroup()); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); @@ -359,9 +359,9 @@ void CHud::RenderHealthAndAmmo(const CNetObj_Character *pCharacter) // render gui stuff Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); - + Graphics()->QuadsBegin(); - + // if weaponstage is active, put a "glow" around the stage ammo RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[pCharacter->m_Weapon%NUM_WEAPONS].m_pSpriteProj); IGraphics::CQuadItem Array[10]; @@ -421,7 +421,7 @@ void CHud::OnRender() { if(!m_pClient->m_Snap.m_pGameInfoObj) return; - + m_Width = 300.0f*Graphics()->ScreenAspect(); m_Height = 300.0f; Graphics()->MapScreen(0.0f, 0.0f, m_Width, m_Height); diff --git a/src/game/client/components/hud.h b/src/game/client/components/hud.h index 75702d51e..f0250c7bb 100644 --- a/src/game/client/components/hud.h +++ b/src/game/client/components/hud.h @@ -5,12 +5,12 @@ #include class CHud : public CComponent -{ +{ float m_Width, m_Height; float m_AverageFPS; - + void RenderCursor(); - + void RenderFps(); void RenderConnectionWarning(); void RenderTeambalanceWarning(); @@ -25,7 +25,7 @@ class CHud : public CComponent void MapscreenToGroup(float CenterX, float CenterY, struct CMapItemGroup *PGroup); public: CHud(); - + virtual void OnReset(); virtual void OnRender(); }; diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index 5eeb32099..827b28a75 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -45,7 +45,7 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); if(Ct < 0) return; // projectile havn't been shot yet - + vec2 StartPos(pCurrent->m_X, pCurrent->m_Y); vec2 StartVel(pCurrent->m_VelX/100.0f, pCurrent->m_VelY/100.0f); vec2 Pos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct); @@ -54,29 +54,29 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); - + RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Type, 0, NUM_WEAPONS-1)].m_pSpriteProj); vec2 Vel = Pos-PrevPos; //vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), Client()->IntraGameTick()); - + // add particle for this projectile if(pCurrent->m_Type == WEAPON_GRENADE) { m_pClient->m_pEffects->SmokeTrail(Pos, Vel*-1); m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f); - + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); static float Time = 0; static float LastLocalTime = Client()->LocalTime(); - + if(!pInfo->m_Paused) Time += (Client()->LocalTime()-LastLocalTime)*pInfo->m_Speed; - + Graphics()->QuadsSetRotation(Time*pi*2*2 + ItemID); - + LastLocalTime = Client()->LocalTime(); } else @@ -139,13 +139,13 @@ void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCu const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); static float Time = 0; static float LastLocalTime = Client()->LocalTime(); - + if(!pInfo->m_Paused) Time += (Client()->LocalTime()-LastLocalTime)*pInfo->m_Speed; - + Pos.x += cosf(Time*2.0f+Offset)*2.5f; Pos.y += sinf(Time*2.0f+Offset)*2.5f; - + LastLocalTime = Client()->LocalTime(); } else @@ -174,7 +174,7 @@ void CItems::RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent, Graphics()->QuadsSetRotation(Angle); vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick()); - + if(pCurGameData) { // make sure that the flag isn't interpolated between capture and return @@ -204,16 +204,16 @@ void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent) float Ticks = Client()->GameTick() + Client()->IntraGameTick() - pCurrent->m_StartTick; float Ms = (Ticks/50.0f) * 1000.0f; - float a = Ms / m_pClient->m_Tuning.m_LaserBounceDelay; + float a = Ms / m_pClient->m_Tuning.m_LaserBounceDelay; a = clamp(a, 0.0f, 1.0f); float Ia = 1-a; - + vec2 Out, Border; - + Graphics()->BlendNormal(); Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); - + //vec4 inner_color(0.15f,0.35f,0.75f,1.0f); //vec4 outer_color(0.65f,0.85f,1.0f,1.0f); @@ -229,20 +229,20 @@ void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent) Pos.x+Out.x, Pos.y+Out.y); Graphics()->QuadsDrawFreeform(&Freeform, 1); - // do inner + // do inner vec4 InnerColor(0.5f, 0.5f, 1.0f, 1.0f); Out = vec2(Dir.y, -Dir.x) * (5.0f*Ia); Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, 1.0f); // center - + Freeform = IGraphics::CFreeformItem( From.x-Out.x, From.y-Out.y, From.x+Out.x, From.y+Out.y, Pos.x-Out.x, Pos.y-Out.y, Pos.x+Out.x, Pos.y+Out.y); Graphics()->QuadsDrawFreeform(&Freeform, 1); - + Graphics()->QuadsEnd(); - + // render head { Graphics()->BlendNormal(); @@ -260,8 +260,8 @@ void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent) Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsEnd(); } - - Graphics()->BlendNormal(); + + Graphics()->BlendNormal(); } void CItems::OnRender() @@ -302,7 +302,7 @@ void CItems::OnRender() const void *pPrev = Client()->SnapFindItem(IClient::SNAP_PREV, Item.m_Type, Item.m_ID); if (pPrev) { - const void *pPrevGameData = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_GAMEDATA, m_pClient->m_Snap.m_GameDataSnapID); + const void *pPrevGameData = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_GAMEDATA, m_pClient->m_Snap.m_GameDataSnapID); RenderFlag(static_cast(pPrev), static_cast(pData), static_cast(pPrevGameData), m_pClient->m_Snap.m_pGameDataObj); } diff --git a/src/game/client/components/items.h b/src/game/client/components/items.h index c366b8d9e..604c1b1cb 100644 --- a/src/game/client/components/items.h +++ b/src/game/client/components/items.h @@ -5,24 +5,24 @@ #include class CItems : public CComponent -{ +{ enum { MAX_EXTRA_PROJECTILES=32, }; - + CNetObj_Projectile aExtraProjectiles[MAX_EXTRA_PROJECTILES]; int ExtraProjectilesNum; - + void RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID); void RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCurrent); void RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent, const CNetObj_GameData *pPrevGameData, const CNetObj_GameData *pCurGameData); void RenderLaser(const struct CNetObj_Laser *pCurrent); - + public: virtual void OnReset(); virtual void OnRender(); - + void AddExtraProjectile(CNetObj_Projectile *pProj); }; diff --git a/src/game/client/components/killmessages.cpp b/src/game/client/components/killmessages.cpp index 869199cff..03f6380a9 100644 --- a/src/game/client/components/killmessages.cpp +++ b/src/game/client/components/killmessages.cpp @@ -21,7 +21,7 @@ void CKillMessages::OnMessage(int MsgType, void *pRawMsg) if(MsgType == NETMSGTYPE_SV_KILLMSG) { CNetMsg_Sv_KillMsg *pMsg = (CNetMsg_Sv_KillMsg *)pRawMsg; - + // unpack messages CKillMsg Kill; Kill.m_VictimID = pMsg->m_Victim; @@ -69,7 +69,7 @@ void CKillMessages::OnRender() // render victim tee x -= 24.0f; - + if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_FLAGS) { if(m_aKillmsgs[r].m_ModeSpecial&1) @@ -82,17 +82,17 @@ void CKillMessages::OnRender() RenderTools()->SelectSprite(SPRITE_FLAG_BLUE); else RenderTools()->SelectSprite(SPRITE_FLAG_RED); - + float Size = 56.0f; IGraphics::CQuadItem QuadItem(x, y-16, Size/2, Size); Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); + Graphics()->QuadsEnd(); } } - + RenderTools()->RenderTee(CAnimState::GetIdle(), &m_aKillmsgs[r].m_VictimRenderInfo, EMOTE_PAIN, vec2(-1,0), vec2(x, y+28)); x -= 32.0f; - + // render weapon x -= 44.0f; if (m_aKillmsgs[r].m_Weapon >= 0) @@ -119,14 +119,14 @@ void CKillMessages::OnRender() RenderTools()->SelectSprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X); else RenderTools()->SelectSprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X); - + float Size = 56.0f; IGraphics::CQuadItem QuadItem(x-56, y-16, Size/2, Size); Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); + Graphics()->QuadsEnd(); } - } - + } + // render killer tee x -= 24.0f; RenderTools()->RenderTee(CAnimState::GetIdle(), &m_aKillmsgs[r].m_KillerRenderInfo, EMOTE_ANGRY, vec2(1,0), vec2(x, y+28)); diff --git a/src/game/client/components/killmessages.h b/src/game/client/components/killmessages.h index 8bf93758d..a4c3e40f9 100644 --- a/src/game/client/components/killmessages.h +++ b/src/game/client/components/killmessages.h @@ -22,7 +22,7 @@ public: int m_ModeSpecial; // for CTF, if the guy is carrying a flag for example int m_Tick; }; - + enum { MAX_KILLMSGS = 5, diff --git a/src/game/client/components/mapimages.cpp b/src/game/client/components/mapimages.cpp index 2a9cecd47..dc136343c 100644 --- a/src/game/client/components/mapimages.cpp +++ b/src/game/client/components/mapimages.cpp @@ -16,7 +16,7 @@ CMapImages::CMapImages() void CMapImages::OnMapLoad() { IMap *pMap = Kernel()->RequestInterface(); - + // unload all textures for(int i = 0; i < m_Count; i++) { @@ -27,12 +27,12 @@ void CMapImages::OnMapLoad() int Start; pMap->GetType(MAPITEMTYPE_IMAGE, &Start, &m_Count); - + // load new textures for(int i = 0; i < m_Count; i++) { m_aTextures[i] = 0; - + CMapItemImage *pImg = (CMapItemImage *)pMap->GetItem(Start+i, 0, 0); if(pImg->m_External) { diff --git a/src/game/client/components/mapimages.h b/src/game/client/components/mapimages.h index 2aaa51fcf..661012744 100644 --- a/src/game/client/components/mapimages.h +++ b/src/game/client/components/mapimages.h @@ -5,12 +5,12 @@ #include class CMapImages : public CComponent -{ +{ int m_aTextures[64]; int m_Count; public: CMapImages(); - + int Get(int Index) const { return m_aTextures[Index]; } int Num() const { return m_Count; } diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 2fdd2accc..848651caf 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -54,26 +54,26 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void if(Num) pPoints = (CEnvPoint *)pThis->m_pLayers->Map()->GetItem(Start, 0, 0); } - + int Start, Num; pThis->m_pLayers->Map()->GetType(MAPITEMTYPE_ENVELOPE, &Start, &Num); - + if(Env >= Num) return; - + CMapItemEnvelope *pItem = (CMapItemEnvelope *)pThis->m_pLayers->Map()->GetItem(Start+Env, 0, 0); - + if(pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = pThis->DemoPlayer()->BaseInfo(); static float Time = 0; static float LastLocalTime = pThis->Client()->LocalTime(); - + if(!pInfo->m_Paused) Time += (pThis->Client()->LocalTime()-LastLocalTime)*pInfo->m_Speed; - + pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels); - + LastLocalTime = pThis->Client()->LocalTime(); } else @@ -84,20 +84,20 @@ void CMapLayers::OnRender() { if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK) return; - + CUIRect Screen; Graphics()->GetScreen(&Screen.x, &Screen.y, &Screen.w, &Screen.h); - + vec2 Center = m_pClient->m_pCamera->m_Center; //float center_x = gameclient.camera->center.x; //float center_y = gameclient.camera->center.y; - + bool PassedGameLayer = false; - + for(int g = 0; g < m_pLayers->NumGroups(); g++) { CMapItemGroup *pGroup = m_pLayers->GetGroup(g); - + if(!g_Config.m_GfxNoclip && pGroup->m_Version >= 2 && pGroup->m_UseClipping) { // set clipping @@ -108,29 +108,29 @@ void CMapLayers::OnRender() float y0 = (pGroup->m_ClipY - Points[1]) / (Points[3]-Points[1]); float x1 = ((pGroup->m_ClipX+pGroup->m_ClipW) - Points[0]) / (Points[2]-Points[0]); float y1 = ((pGroup->m_ClipY+pGroup->m_ClipH) - Points[1]) / (Points[3]-Points[1]); - + Graphics()->ClipEnable((int)(x0*Graphics()->ScreenWidth()), (int)(y0*Graphics()->ScreenHeight()), (int)((x1-x0)*Graphics()->ScreenWidth()), (int)((y1-y0)*Graphics()->ScreenHeight())); - } - + } + MapScreenToGroup(Center.x, Center.y, pGroup); - + for(int l = 0; l < pGroup->m_NumLayers; l++) { CMapItemLayer *pLayer = m_pLayers->GetLayer(pGroup->m_StartLayer+l); bool Render = false; bool IsGameLayer = false; - + if(pLayer == (CMapItemLayer*)m_pLayers->GameLayer()) { IsGameLayer = true; PassedGameLayer = 1; } - + // skip rendering if detail layers if not wanted if(pLayer->m_Flags&LAYERFLAG_DETAIL && !g_Config.m_GfxHighDetail && !IsGameLayer) continue; - + if(m_Type == -1) Render = true; else if(m_Type == 0) @@ -144,7 +144,7 @@ void CMapLayers::OnRender() if(PassedGameLayer && !IsGameLayer) Render = true; } - + if(Render && pLayer->m_Type == LAYERTYPE_TILES && Input()->KeyPressed(KEY_LCTRL) && Input()->KeyPressed(KEY_LSHIFT) && Input()->KeyDown(KEY_KP0)) { CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer; @@ -169,12 +169,12 @@ void CMapLayers::OnRender() } io_close(File); } - } - + } + if(Render && !IsGameLayer) { //layershot_begin(); - + if(pLayer->m_Type == LAYERTYPE_TILES) { CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer; @@ -182,7 +182,7 @@ void CMapLayers::OnRender() Graphics()->TextureSet(-1); else Graphics()->TextureSet(m_pClient->m_pMapimages->Get(pTMap->m_Image)); - + CTile *pTiles = (CTile *)m_pLayers->Map()->GetData(pTMap->m_Data); Graphics()->BlendNone(); vec4 Color = vec4(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f); @@ -199,23 +199,23 @@ void CMapLayers::OnRender() Graphics()->TextureSet(m_pClient->m_pMapimages->Get(pQLayer->m_Image)); CQuad *pQuads = (CQuad *)m_pLayers->Map()->GetDataSwapped(pQLayer->m_Data); - + Graphics()->BlendNone(); RenderTools()->RenderQuads(pQuads, pQLayer->m_NumQuads, LAYERRENDERFLAG_OPAQUE, EnvelopeEval, this); Graphics()->BlendNormal(); RenderTools()->RenderQuads(pQuads, pQLayer->m_NumQuads, LAYERRENDERFLAG_TRANSPARENT, EnvelopeEval, this); } - - //layershot_end(); + + //layershot_end(); } } if(!g_Config.m_GfxNoclip) Graphics()->ClipDisable(); } - + if(!g_Config.m_GfxNoclip) Graphics()->ClipDisable(); - + // reset the screen like it was before Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); } diff --git a/src/game/client/components/maplayers.h b/src/game/client/components/maplayers.h index ac78bebf1..694633ee7 100644 --- a/src/game/client/components/maplayers.h +++ b/src/game/client/components/maplayers.h @@ -5,7 +5,7 @@ #include class CMapLayers : public CComponent -{ +{ CLayers *m_pLayers; // todo refactor: maybe remove it and access it through client* int m_Type; diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 060384ec6..531927147 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -52,20 +52,20 @@ CMenus::CMenus() m_Popup = POPUP_NONE; m_ActivePage = PAGE_INTERNET; m_GamePage = PAGE_GAME; - + m_NeedRestartGraphics = false; m_NeedRestartSound = false; m_NeedSendinfo = false; m_MenuActive = true; m_UseMouseButtons = true; - + m_EscapePressed = false; m_EnterPressed = false; m_DeletePressed = false; m_NumInputEvents = 0; - + m_LastInput = time_get(); - + str_copy(m_aCurrentDemoFolder, "demos", sizeof(m_aCurrentDemoFolder)); m_aCallvoteReason[0] = 0; @@ -84,13 +84,13 @@ vec4 CMenus::ButtonColorMul(const void *pID) int CMenus::DoButton_Icon(int ImageId, int SpriteId, const CUIRect *pRect) { Graphics()->TextureSet(g_pData->m_aImages[ImageId].m_Id); - + Graphics()->QuadsBegin(); RenderTools()->SelectSprite(SpriteId); IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - + return 0; } @@ -108,7 +108,7 @@ int CMenus::DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect) Graphics()->QuadsDrawTL(&QuadItem, 1); } Graphics()->QuadsEnd(); - + return UI()->DoButtonLogic(pID, "", Checked, pRect); } @@ -138,7 +138,7 @@ int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, co CUIRect Temp; pRect->HMargin(2.0f, &Temp); UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, 0); - + return UI()->DoButtonLogic(pID, pText, Checked, pRect); } @@ -162,7 +162,7 @@ int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const c t.x += c.w; t.w -= c.w; t.VSplitLeft(5.0f, 0, &t); - + c.Margin(2.0f, &c); RenderTools()->DrawUIRect(&c, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 3.0f); c.y += 2; @@ -186,7 +186,7 @@ int CMenus::DoButton_CheckBox_Number(const void *pID, const char *pText, int Che int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden, int Corners) { - int Inside = UI()->MouseInside(pRect); + int Inside = UI()->MouseInside(pRect); bool ReturnValue = false; bool UpdateOffset = false; static int s_AtIndex = 0; @@ -200,7 +200,7 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS int Len = str_length(pStr); if(Len == 0) s_AtIndex = 0; - + if(Inside && UI()->MouseButton(0)) { s_DoScroll = true; @@ -246,7 +246,7 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS } bool JustGotActive = false; - + if(UI()->ActiveItem() == pID) { if(!UI()->MouseButton(0)) @@ -264,7 +264,7 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS UI()->SetActiveItem(pID); } } - + if(Inside) UI()->SetHotItem(pID); @@ -272,10 +272,10 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS RenderTools()->DrawUIRect(&Textbox, vec4(1, 1, 1, 0.5f), Corners, 3.0f); Textbox.VMargin(2.0f, &Textbox); Textbox.HMargin(2.0f, &Textbox); - + const char *pDisplayStr = pStr; char aStars[128]; - + if(Hidden) { unsigned s = str_length(pStr); @@ -315,7 +315,7 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS Textbox.x -= *Offset; UI()->DoLabel(&Textbox, pDisplayStr, FontSize, -1); - + // render the cursor if(UI()->LastActiveItem() == pID && !JustGotActive) { @@ -341,14 +341,14 @@ float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) Handle.y += (pRect->h-Handle.h)*Current; // logic - float ReturnValue = Current; - int Inside = UI()->MouseInside(&Handle); + float ReturnValue = Current; + int Inside = UI()->MouseInside(&Handle); if(UI()->ActiveItem() == pID) { if(!UI()->MouseButton(0)) UI()->SetActiveItem(0); - + float Min = pRect->y; float Max = pRect->h-Handle.h; float Cur = UI()->MouseY()-OffsetY; @@ -364,7 +364,7 @@ float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) OffsetY = UI()->MouseY()-Handle.y; } } - + if(Inside) UI()->SetHotItem(pID); @@ -382,8 +382,8 @@ float CMenus::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current) Slider = Handle; Slider.Margin(5.0f, &Slider); RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 2.5f); - - return ReturnValue; + + return ReturnValue; } @@ -397,14 +397,14 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) Handle.x += (pRect->w-Handle.w)*Current; // logic - float ReturnValue = Current; - int Inside = UI()->MouseInside(&Handle); + float ReturnValue = Current; + int Inside = UI()->MouseInside(&Handle); if(UI()->ActiveItem() == pID) { if(!UI()->MouseButton(0)) UI()->SetActiveItem(0); - + float Min = pRect->x; float Max = pRect->w-Handle.w; float Cur = UI()->MouseX()-OffsetX; @@ -420,7 +420,7 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) OffsetX = UI()->MouseX()-Handle.x; } } - + if(Inside) UI()->SetHotItem(pID); @@ -438,8 +438,8 @@ float CMenus::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current) Slider = Handle; Slider.Margin(5.0f, &Slider); RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 2.5f); - - return ReturnValue; + + return ReturnValue; } int CMenus::DoKeyReader(void *pID, const CUIRect *pRect, int Key) @@ -450,7 +450,7 @@ int CMenus::DoKeyReader(void *pID, const CUIRect *pRect, int Key) static int ButtonUsed = 0; int Inside = UI()->MouseInside(pRect); int NewKey = Key; - + if(!UI()->MouseButton(0) && !UI()->MouseButton(1) && pGrabbedID == pID) MouseReleased = true; @@ -493,7 +493,7 @@ int CMenus::DoKeyReader(void *pID, const CUIRect *pRect, int Key) } } } - + if(Inside) UI()->SetHotItem(pID); @@ -515,13 +515,13 @@ int CMenus::RenderMenubar(CUIRect r) { CUIRect Box = r; CUIRect Button; - + m_ActivePage = g_Config.m_UiPage; int NewPage = -1; - + if(Client()->State() != IClient::STATE_OFFLINE) m_ActivePage = m_GamePage; - + if(Client()->State() == IClient::STATE_OFFLINE) { // offline menus @@ -531,7 +531,7 @@ int CMenus::RenderMenubar(CUIRect r) static int s_NewsButton=0; if (DoButton_MenuTab(&s_NewsButton, Localize("News"), m_ActivePage==PAGE_NEWS, &Button, 0)) NewPage = PAGE_NEWS; - Box.VSplitLeft(30.0f, 0, &Box); + Box.VSplitLeft(30.0f, 0, &Box); } Box.VSplitLeft(100.0f, &Button, &Box); @@ -557,17 +557,17 @@ int CMenus::RenderMenubar(CUIRect r) if(DoButton_MenuTab(&s_FavoritesButton, Localize("Favorites"), m_ActivePage==PAGE_FAVORITES, &Button, CUI::CORNER_TR)) { ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES); - NewPage = PAGE_FAVORITES; + NewPage = PAGE_FAVORITES; } - + Box.VSplitLeft(4.0f*5, 0, &Box); Box.VSplitLeft(100.0f, &Button, &Box); static int s_DemosButton=0; if(DoButton_MenuTab(&s_DemosButton, Localize("Demos"), m_ActivePage==PAGE_DEMOS, &Button, CUI::CORNER_T)) { DemolistPopulate(); - NewPage = PAGE_DEMOS; - } + NewPage = PAGE_DEMOS; + } } else { @@ -592,16 +592,16 @@ int CMenus::RenderMenubar(CUIRect r) if(DoButton_MenuTab(&s_CallVoteButton, Localize("Call vote"), m_ActivePage==PAGE_CALLVOTE, &Button, CUI::CORNER_TR)) NewPage = PAGE_CALLVOTE; } - + /* box.VSplitRight(110.0f, &box, &button); static int system_button=0; if (UI()->DoButton(&system_button, "System", g_Config.m_UiPage==PAGE_SYSTEM, &button)) g_Config.m_UiPage = PAGE_SYSTEM; - + box.VSplitRight(30.0f, &box, 0); */ - + Box.VSplitRight(90.0f, &Box, &Button); static int s_QuitButton=0; if(DoButton_MenuTab(&s_QuitButton, Localize("Quit"), 0, &Button, CUI::CORNER_T)) @@ -612,7 +612,7 @@ int CMenus::RenderMenubar(CUIRect r) static int s_SettingsButton=0; if(DoButton_MenuTab(&s_SettingsButton, Localize("Settings"), m_ActivePage==PAGE_SETTINGS, &Button, CUI::CORNER_T)) NewPage = PAGE_SETTINGS; - + if(NewPage != -1) { if(Client()->State() == IClient::STATE_OFFLINE) @@ -620,7 +620,7 @@ int CMenus::RenderMenubar(CUIRect r) else m_GamePage = NewPage; } - + return 0; } @@ -633,14 +633,14 @@ void CMenus::RenderLoading() // because that will slow down loading if we have vsync if(time_get()-LastLoadRender < time_freq()/60) return; - + LastLoadRender = time_get(); - + // need up date this here to get correct vec3 Rgb = HslToRgb(vec3(g_Config.m_UiColorHue/255.0f, g_Config.m_UiColorSat/255.0f, g_Config.m_UiColorLht/255.0f)); ms_GuiColor = vec4(Rgb.r, Rgb.g, Rgb.b, g_Config.m_UiColorAlpha/255.0f); - - CUIRect Screen = *UI()->Screen(); + + CUIRect Screen = *UI()->Screen(); Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); RenderBackground(); @@ -701,14 +701,14 @@ void CMenus::OnInit() for(array::range r = my_strings.all(); !r.empty(); r.pop_front()) dbg_msg("", "%s", r.front().cstr()); - + sort(my_strings.all()); - + dbg_msg("", "after:"); for(array::range r = my_strings.all(); !r.empty(); r.pop_front()) dbg_msg("", "%s", r.front().cstr()); - - + + array myarray; myarray.add(4); myarray.add(6); @@ -720,17 +720,17 @@ void CMenus::OnInit() for(array::range r = myarray.all(); !r.empty(); r.pop_front()) dbg_msg("", "%d", r.front()); - + sort(myarray.all()); sort_verify(myarray.all()); - + dbg_msg("", "after:"); for(array::range r = myarray.all(); !r.empty(); r.pop_front()) dbg_msg("", "%d", r.front()); - + exit(-1); // */ - + if(g_Config.m_ClShowWelcome) m_Popup = POPUP_LANGUAGE; g_Config.m_ClShowWelcome = 0; @@ -759,7 +759,7 @@ void CMenus::PopupMessage(const char *pTopic, const char *pBody, const char *pBu int CMenus::Render() { - CUIRect Screen = *UI()->Screen(); + CUIRect Screen = *UI()->Screen(); Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); static bool s_First = true; @@ -774,7 +774,7 @@ int CMenus::Render() m_pClient->m_pSounds->Enqueue(CSounds::CHN_MUSIC, SOUND_MENU); s_First = false; } - + if(Client()->State() == IClient::STATE_ONLINE) { ms_ColorTabbarInactive = ms_ColorTabbarInactiveIngame; @@ -786,13 +786,13 @@ int CMenus::Render() ms_ColorTabbarInactive = ms_ColorTabbarInactiveOutgame; ms_ColorTabbarActive = ms_ColorTabbarActiveOutgame; } - + CUIRect TabBar; CUIRect MainView; // some margin around the screen Screen.Margin(10.0f, &Screen); - + static bool s_SoundCheck = false; if(!s_SoundCheck && m_Popup == POPUP_NONE) { @@ -807,14 +807,14 @@ int CMenus::Render() Screen.HSplitTop(24.0f, &TabBar, &MainView); TabBar.VMargin(20.0f, &TabBar); RenderMenubar(TabBar); - + // news is not implemented yet if(g_Config.m_UiPage <= PAGE_NEWS || g_Config.m_UiPage > PAGE_SETTINGS || (Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiPage >= PAGE_GAME && g_Config.m_UiPage <= PAGE_CALLVOTE)) { ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET); g_Config.m_UiPage = PAGE_INTERNET; } - + // render current page if(Client()->State() != IClient::STATE_OFFLINE) { @@ -852,7 +852,7 @@ int CMenus::Render() const char *pExtraText = ""; const char *pButtonText = ""; int ExtraAlign = 0; - + if(m_Popup == POPUP_MESSAGE) { pTitle = m_aMessageTopic; @@ -862,7 +862,7 @@ int CMenus::Render() else if(m_Popup == POPUP_CONNECTING) { pTitle = Localize("Connecting to"); - pExtraText = g_Config.m_UiServerAddress; // TODO: query the client about the address + pExtraText = g_Config.m_UiServerAddress; // TODO: query the client about the address pButtonText = Localize("Abort"); if(Client()->MapDownloadTotalsize() > 0) { @@ -928,22 +928,22 @@ int CMenus::Render() pButtonText = Localize("Ok"); ExtraAlign = -1; } - + CUIRect Box, Part; Box = Screen; Box.VMargin(150.0f/UI()->Scale(), &Box); Box.HMargin(150.0f/UI()->Scale(), &Box); - + // render the box RenderTools()->DrawUIRect(&Box, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 15.0f); - + Box.HSplitTop(20.f/UI()->Scale(), &Part, &Box); Box.HSplitTop(24.f/UI()->Scale(), &Part, &Box); UI()->DoLabelScaled(&Part, pTitle, 24.f, 0); Box.HSplitTop(20.f/UI()->Scale(), &Part, &Box); Box.HSplitTop(24.f/UI()->Scale(), &Part, &Box); Part.VMargin(20.f/UI()->Scale(), &Part); - + if(ExtraAlign == -1) UI()->DoLabelScaled(&Part, pExtraText, 20.f, -1, (int)Part.w); else @@ -982,16 +982,16 @@ int CMenus::Render() else if(m_Popup == POPUP_PASSWORD) { CUIRect Label, TextBox, TryAgain, Abort; - + Box.HSplitBottom(20.f, &Box, &Part); Box.HSplitBottom(24.f, &Box, &Part); Part.VMargin(80.0f, &Part); - + Part.VSplitMid(&Abort, &TryAgain); - + TryAgain.VMargin(20.0f, &TryAgain); Abort.VMargin(20.0f, &Abort); - + static int s_ButtonAbort = 0; if(DoButton_Menu(&s_ButtonAbort, Localize("Abort"), 0, &Abort) || m_EscapePressed) m_Popup = POPUP_NONE; @@ -1001,10 +1001,10 @@ int CMenus::Render() { Client()->Connect(g_Config.m_UiServerAddress); } - + Box.HSplitBottom(60.f, &Box, &Part); Box.HSplitBottom(24.f, &Box, &Part); - + Part.VSplitLeft(60.0f, 0, &Label); Label.VSplitLeft(100.0f, 0, &TextBox); TextBox.VSplitLeft(20.0f, 0, &TextBox); @@ -1055,7 +1055,7 @@ int CMenus::Render() Box.HSplitTop(24.f, &Part, &Box); str_format(aBuf, sizeof(aBuf), "%d/%d KiB (%.1f KiB/s)", Client()->MapDownloadAmount()/1024, Client()->MapDownloadTotalsize()/1024, m_DownloadSpeed/1024.0f); UI()->DoLabel(&Part, aBuf, 20.f, 0, -1); - + // time left const char *pTimeLeftString; int TimeLeft = m_DownloadSpeed > 0.0f ? (Client()->MapDownloadTotalsize()-Client()->MapDownloadAmount())/m_DownloadSpeed : 0.0f; @@ -1103,9 +1103,9 @@ int CMenus::Render() Box.HSplitBottom(20.f, &Box, &Part); Box.HSplitBottom(24.f, &Box, &Part); Part.VMargin(80.0f, &Part); - + Part.VSplitMid(&No, &Yes); - + Yes.VMargin(20.0f, &Yes); No.VMargin(20.0f, &No); @@ -1135,16 +1135,16 @@ int CMenus::Render() else if(m_Popup == POPUP_RENAME_DEMO) { CUIRect Label, TextBox, Ok, Abort; - + Box.HSplitBottom(20.f, &Box, &Part); Box.HSplitBottom(24.f, &Box, &Part); Part.VMargin(80.0f, &Part); - + Part.VSplitMid(&Abort, &Ok); - + Ok.VMargin(20.0f, &Ok); Abort.VMargin(20.0f, &Abort); - + static int s_ButtonAbort = 0; if(DoButton_Menu(&s_ButtonAbort, Localize("Abort"), 0, &Abort) || m_EscapePressed) m_Popup = POPUP_NONE; @@ -1173,10 +1173,10 @@ int CMenus::Render() PopupMessage(Localize("Error"), Localize("Unable to rename the demo"), Localize("Ok")); } } - + Box.HSplitBottom(60.f, &Box, &Part); Box.HSplitBottom(24.f, &Box, &Part); - + Part.VSplitLeft(60.0f, 0, &Label); Label.VSplitLeft(120.0f, 0, &TextBox); TextBox.VSplitLeft(20.0f, 0, &TextBox); @@ -1191,9 +1191,9 @@ int CMenus::Render() Box.HSplitBottom(20.f, &Box, &Part); Box.HSplitBottom(24.f, &Box, &Part); Part.VMargin(80.0f, &Part); - + Part.VSplitMid(&No, &Yes); - + Yes.VMargin(20.0f, &Yes); No.VMargin(20.0f, &No); @@ -1216,18 +1216,18 @@ int CMenus::Render() else if(m_Popup == POPUP_FIRST_LAUNCH) { CUIRect Label, TextBox; - + Box.HSplitBottom(20.f, &Box, &Part); Box.HSplitBottom(24.f, &Box, &Part); Part.VMargin(80.0f, &Part); - + static int s_EnterButton = 0; if(DoButton_Menu(&s_EnterButton, Localize("Enter"), 0, &Part) || m_EnterPressed) m_Popup = POPUP_NONE; - + Box.HSplitBottom(40.f, &Box, &Part); Box.HSplitBottom(24.f, &Box, &Part); - + Part.VSplitLeft(60.0f, 0, &Label); Label.VSplitLeft(100.0f, 0, &TextBox); TextBox.VSplitLeft(20.0f, 0, &TextBox); @@ -1247,7 +1247,7 @@ int CMenus::Render() m_Popup = POPUP_NONE; } } - + return 0; } @@ -1281,24 +1281,24 @@ void CMenus::OnReset() bool CMenus::OnMouseMove(float x, float y) { m_LastInput = time_get(); - + if(!m_MenuActive) return false; - + m_MousePos.x += x; m_MousePos.y += y; if(m_MousePos.x < 0) m_MousePos.x = 0; if(m_MousePos.y < 0) m_MousePos.y = 0; if(m_MousePos.x > Graphics()->ScreenWidth()) m_MousePos.x = Graphics()->ScreenWidth(); if(m_MousePos.y > Graphics()->ScreenHeight()) m_MousePos.y = Graphics()->ScreenHeight(); - + return true; } bool CMenus::OnInput(IInput::CEvent e) { m_LastInput = time_get(); - + // special handle esc and enter for popup purposes if(e.m_Flags&IInput::FLAG_PRESS) { @@ -1309,7 +1309,7 @@ bool CMenus::OnInput(IInput::CEvent e) return true; } } - + if(IsActive()) { if(e.m_Flags&IInput::FLAG_PRESS) @@ -1320,7 +1320,7 @@ bool CMenus::OnInput(IInput::CEvent e) else if(e.m_Key == KEY_DELETE) m_DeletePressed = true; } - + if(m_NumInputEvents < MAX_INPUTEVENTS) m_aInputEvents[m_NumInputEvents++] = e; return true; @@ -1380,13 +1380,13 @@ void CMenus::OnRender() TextRender()->SetCursor(&cursor, 10, 30, 15, TEXTFLAG_RENDER); TextRender()->TextEx(&cursor, "ようこそ - ガイド", -1); - + //Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->QuadsDrawTL(60, 60, 5000, 5000); Graphics()->QuadsEnd(); return;*/ - + if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK) SetActive(true); @@ -1396,14 +1396,14 @@ void CMenus::OnRender() Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); RenderDemoPlayer(Screen); } - + if(Client()->State() == IClient::STATE_ONLINE && m_pClient->m_ServerMode == m_pClient->SERVERMODE_PUREMOD) { Client()->Disconnect(); SetActive(true); m_Popup = POPUP_PURE; } - + if(!IsActive()) { m_EscapePressed = false; @@ -1412,7 +1412,7 @@ void CMenus::OnRender() m_NumInputEvents = 0; return; } - + // update colors vec3 Rgb = HslToRgb(vec3(g_Config.m_UiColorHue/255.0f, g_Config.m_UiColorSat/255.0f, g_Config.m_UiColorLht/255.0f)); ms_GuiColor = vec4(Rgb.r, Rgb.g, Rgb.b, g_Config.m_UiColorAlpha/255.0f); @@ -1427,18 +1427,18 @@ void CMenus::OnRender() ms_GuiColor.g*ColorIngameScaleI, ms_GuiColor.b*ColorIngameScaleI, ms_GuiColor.a*0.8f); - + ms_ColorTabbarActiveIngame = vec4( ms_GuiColor.r*ColorIngameAcaleA, ms_GuiColor.g*ColorIngameAcaleA, ms_GuiColor.b*ColorIngameAcaleA, ms_GuiColor.a); - + // update the ui CUIRect *pScreen = UI()->Screen(); float mx = (m_MousePos.x/(float)Graphics()->ScreenWidth())*pScreen->w; float my = (m_MousePos.y/(float)Graphics()->ScreenHeight())*pScreen->h; - + int Buttons = 0; if(m_UseMouseButtons) { @@ -1446,9 +1446,9 @@ void CMenus::OnRender() if(Input()->KeyPressed(KEY_MOUSE_2)) Buttons |= 2; if(Input()->KeyPressed(KEY_MOUSE_3)) Buttons |= 4; } - + UI()->Update(mx,my,mx*3.0f,my*3.0f,Buttons); - + // render if(Client()->State() != IClient::STATE_DEMOPLAYBACK) Render(); @@ -1510,7 +1510,7 @@ void CMenus::RenderBackground() IGraphics::CQuadItem QuadItem(0, 0, sw, sh); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - + // render the tiles Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); @@ -1533,7 +1533,7 @@ void CMenus::RenderBackground() Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - // restore screen - {CUIRect Screen = *UI()->Screen(); - Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);} + // restore screen + {CUIRect Screen = *UI()->Screen(); + Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);} } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 11047a0b8..51b8a1f85 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -25,7 +25,7 @@ public: }; class CMenus : public CComponent -{ +{ static vec4 ms_GuiColor; static vec4 ms_ColorTabbarInactiveOutgame; static vec4 ms_ColorTabbarActiveOutgame; @@ -33,7 +33,7 @@ class CMenus : public CComponent static vec4 ms_ColorTabbarActiveIngame; static vec4 ms_ColorTabbarInactive; static vec4 ms_ColorTabbarActive; - + vec4 ButtonColorMul(const void *pID); @@ -58,7 +58,7 @@ class CMenus : public CComponent //static void ui_draw_browse_icon(int what, const CUIRect *r); //static void ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); - + /*static void ui_draw_checkbox_common(const void *id, const char *text, const char *boxtext, const CUIRect *r, const void *extra); static void ui_draw_checkbox(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); static void ui_draw_checkbox_number(const void *id, const char *text, int checked, const CUIRect *r, const void *extra); @@ -81,13 +81,13 @@ class CMenus : public CComponent CUIRect m_Rect; CUIRect m_HitRect; }; - + void UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems, - int ItemsPerRow, int SelectedIndex, float ScrollValue); + int ItemsPerRow, int SelectedIndex, float ScrollValue); CListboxItem UiDoListboxNextItem(const void *pID, bool Selected = false); CListboxItem UiDoListboxNextRow(); int UiDoListboxEnd(float *pScrollValue, bool *pItemActivated); - + //static void demolist_listdir_callback(const char *name, int is_dir, void *user); //static void demolist_list_callback(const CUIRect *rect, int index, void *user); @@ -105,7 +105,7 @@ class CMenus : public CComponent POPUP_REMOVE_FRIEND, POPUP_SOUNDERROR, POPUP_PASSWORD, - POPUP_QUIT, + POPUP_QUIT, }; enum @@ -129,36 +129,36 @@ class CMenus : public CComponent bool m_MenuActive; bool m_UseMouseButtons; vec2 m_MousePos; - + int64 m_LastInput; // loading int m_LoadCurrent; int m_LoadTotal; - + // char m_aMessageTopic[512]; char m_aMessageBody[512]; char m_aMessageButton[512]; - + void PopupMessage(const char *pTopic, const char *pBody, const char *pButton); - // TODO: this is a bit ugly but.. well.. yeah + // TODO: this is a bit ugly but.. well.. yeah enum { MAX_INPUTEVENTS = 32 }; static IInput::CEvent m_aInputEvents[MAX_INPUTEVENTS]; static int m_NumInputEvents; - + // some settings static float ms_ButtonHeight; static float ms_ListheaderHeight; static float ms_FontmodHeight; - + // for settings bool m_NeedRestartGraphics; bool m_NeedRestartSound; bool m_NeedSendinfo; int m_SettingPlayerPage; - + // bool m_EscapePressed; bool m_EnterPressed; @@ -168,12 +168,12 @@ class CMenus : public CComponent int64 m_DownloadLastCheckTime; int m_DownloadLastCheckSize; float m_DownloadSpeed; - + // for call vote int m_CallvoteSelectedOption; int m_CallvoteSelectedPlayer; char m_aCallvoteReason[VOTE_REASON_LENGTH]; - + // demo struct CDemoItem { @@ -181,40 +181,40 @@ class CMenus : public CComponent char m_aName[128]; bool m_IsDir; int m_StorageType; - + bool m_InfosLoaded; bool m_Valid; CDemoHeader m_Info; - + bool operator<(const CDemoItem &Other) { return !str_comp(m_aFilename, "..") ? true : !str_comp(Other.m_aFilename, "..") ? false : m_IsDir && !Other.m_IsDir ? true : !m_IsDir && Other.m_IsDir ? false : str_comp_filenames(m_aFilename, Other.m_aFilename) < 0; } }; - + sorted_array m_lDemos; char m_aCurrentDemoFolder[256]; char m_aCurrentDemoFile[64]; int m_DemolistSelectedIndex; bool m_DemolistSelectedIsDir; int m_DemolistStorageType; - + void DemolistOnUpdate(bool Reset); void DemolistPopulate(); static int DemolistFetchCallback(const char *pName, int IsDir, int StorageType, void *pUser); int m_FriendlistSelectedIndex; - + // found in menus.cpp int Render(); //void render_background(); //void render_loading(float percent); int RenderMenubar(CUIRect r); void RenderNews(CUIRect MainView); - + // found in menus_demo.cpp void RenderDemoPlayer(CUIRect MainView); void RenderDemoList(CUIRect MainView); - + // found in menus_ingame.cpp void RenderGame(CUIRect MainView); void RenderPlayers(CUIRect MainView); @@ -222,7 +222,7 @@ class CMenus : public CComponent void RenderServerControl(CUIRect MainView); void RenderServerControlKick(CUIRect MainView, bool FilterSpectators); void RenderServerControlServer(CUIRect MainView); - + // found in menus_browser.cpp int m_SelectedIndex; void RenderServerbrowserServerList(CUIRect View); @@ -231,7 +231,7 @@ class CMenus : public CComponent void RenderServerbrowserFriends(CUIRect View); void RenderServerbrowser(CUIRect MainView); static void ConchainServerbrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); - + // found in menus_settings.cpp void RenderLanguageSelection(CUIRect MainView); void RenderSettingsGeneral(CUIRect MainView); @@ -241,7 +241,7 @@ class CMenus : public CComponent void RenderSettingsGraphics(CUIRect MainView); void RenderSettingsSound(CUIRect MainView); void RenderSettings(CUIRect MainView); - + void SetActive(bool Active); public: void RenderBackground(); @@ -249,7 +249,7 @@ public: void UseMouseButtons(bool Use) { m_UseMouseButtons = Use; } static CMenusKeyBinder m_Binder; - + CMenus(); void RenderLoading(); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index b9e61401b..3ab02db83 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -65,7 +65,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) {COL_FLAG_LOCK, -1, " ", -1, 14.0f, 0, {0}, {0}}, {COL_FLAG_PURE, -1, " ", -1, 14.0f, 0, {0}, {0}}, {COL_FLAG_FAV, -1, " ", -1, 14.0f, 0, {0}, {0}}, - {COL_NAME, IServerBrowser::SORT_NAME, "Name", 0, 300.0f, 0, {0}, {0}}, // Localize - these strings are localized within CLocConstString + {COL_NAME, IServerBrowser::SORT_NAME, "Name", 0, 300.0f, 0, {0}, {0}}, // Localize - these strings are localized within CLocConstString {COL_GAMETYPE, IServerBrowser::SORT_GAMETYPE, "Type", 1, 50.0f, 0, {0}, {0}}, {COL_MAP, IServerBrowser::SORT_MAP, "Map", 1, 100.0f, 0, {0}, {0}}, {COL_PLAYERS, IServerBrowser::SORT_NUMPLAYERS, "Players", 1, 60.0f, 0, {0}, {0}}, @@ -161,8 +161,8 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) } else ScrollNum = 0; - - if(m_SelectedIndex > -1) + + if(m_SelectedIndex > -1) { for(int i = 0; i < m_NumInputEvents; i++) { @@ -174,10 +174,10 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) } if(NewIndex > -1 && NewIndex < NumServers) { - //scroll - float IndexY = View.y - s_ScrollValue*ScrollNum*s_aCols[0].m_Rect.h + NewIndex*s_aCols[0].m_Rect.h; + //scroll + float IndexY = View.y - s_ScrollValue*ScrollNum*s_aCols[0].m_Rect.h + NewIndex*s_aCols[0].m_Rect.h; int Scroll = View.y > IndexY ? -1 : View.y+View.h < IndexY+s_aCols[0].m_Rect.h ? 1 : 0; - if(Scroll) + if(Scroll) { if(Scroll < 0) { @@ -192,15 +192,15 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) } m_SelectedIndex = NewIndex; - + const CServerInfo *pItem = ServerBrowser()->SortedGet(m_SelectedIndex); str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress)); } } } - - if(s_ScrollValue < 0) s_ScrollValue = 0; - if(s_ScrollValue > 1) s_ScrollValue = 1; + + if(s_ScrollValue < 0) s_ScrollValue = 0; + if(s_ScrollValue > 1) s_ScrollValue = 1; // set clipping UI()->ClipEnable(&View); @@ -224,7 +224,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) int ItemIndex = i; const CServerInfo *pItem = ServerBrowser()->SortedGet(ItemIndex); CUIRect Row; - CUIRect SelectHitBox; + CUIRect SelectHitBox; int Selected = str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress) == 0; //selected_index==ItemIndex; @@ -422,7 +422,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View) Client()->ServerBrowserUpdate(); } } - + // render status char aBuf[128]; if(ServerBrowser()->IsRefreshing()) @@ -481,7 +481,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View) ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter); if (DoButton_CheckBox((char *)&g_Config.m_BrFilterPureMap, Localize("Standard map"), g_Config.m_BrFilterPureMap, &Button)) g_Config.m_BrFilterPureMap ^= 1; - + ServerFilter.HSplitTop(5.0f, 0, &ServerFilter); ServerFilter.HSplitTop(19.0f, &Button, &ServerFilter); @@ -496,9 +496,9 @@ void CMenus::RenderServerbrowserFilters(CUIRect View) ServerFilter.HSplitTop(19.0f, &Button, &ServerFilter); CUIRect EditBox; Button.VSplitRight(60.0f, &Button, &EditBox); - + UI()->DoLabelScaled(&Button, Localize("Maximum ping:"), FontSize, -1); - + char aBuf[5]; str_format(aBuf, sizeof(aBuf), "%d", g_Config.m_BrFilterPing); static float Offset = 0.0f; @@ -510,7 +510,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View) ServerFilter.HSplitTop(3.0f, 0, &ServerFilter); ServerFilter.HSplitTop(19.0f, &Button, &ServerFilter); UI()->DoLabelScaled(&Button, Localize("Server address:"), FontSize, -1); - Button.VSplitRight(60.0f, 0, &Button); + Button.VSplitRight(60.0f, 0, &Button); static float OffsetAddr = 0.0f; if(DoEditBox(&g_Config.m_BrFilterServerAddress, &Button, g_Config.m_BrFilterServerAddress, sizeof(g_Config.m_BrFilterServerAddress), FontSize, &OffsetAddr)) Client()->ServerBrowserUpdate(); @@ -639,7 +639,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View) Cursor.m_LineWidth = Score.w; TextRender()->TextEx(&Cursor, aTemp, -1); } - + // name TextRender()->SetCursor(&Cursor, Name.x, Name.y, FontSize-2, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Name.w; @@ -716,12 +716,12 @@ void CMenus::RenderServerbrowserFriends(CUIRect View) static int s_FriendList = 0; static float s_ScrollValue = 0; UiDoListboxStart(&s_FriendList, &List, 40.0f, "", "", m_pClient->Friends()->NumFriends(), 1, m_FriendlistSelectedIndex, s_ScrollValue); - + for(int i = 0; i < m_pClient->Friends()->NumFriends(); ++i) { const CFriendInfo *pFriend = m_pClient->Friends()->GetFriend(i); CListboxItem Item = UiDoListboxNextItem(pFriend); - + if(Item.m_Visible) { Item.m_Rect.Margin(2.5f, &Item.m_Rect); @@ -732,7 +732,7 @@ void CMenus::RenderServerbrowserFriends(CUIRect View) UI()->DoLabelScaled(&Button, pFriend->m_aClan, FontSize, -1); } } - + m_FriendlistSelectedIndex = UiDoListboxEnd(&s_ScrollValue, 0); ServerFriends.HSplitTop(2.5f, 0, &ServerFriends); @@ -780,14 +780,14 @@ void CMenus::RenderServerbrowserFriends(CUIRect View) void CMenus::RenderServerbrowser(CUIRect MainView) { /* - +-----------------+ +------+ - | | | | - | | | tool | - | server list | | box | - | | | | - | | | | - +-----------------+ | | - status box tab +------+ + +-----------------+ +-------+ + | | | | + | | | tool | + | server list | | box | + | | | | + | | | | + +-----------------+ | | + status box tab +-------+ */ CUIRect ServerList, ToolBox, StatusBox, TabBar; @@ -843,7 +843,7 @@ void CMenus::RenderServerbrowser(CUIRect MainView) // tool box { RenderTools()->DrawUIRect(&ToolBox, vec4(0.0f, 0.0f, 0.0f, 0.15f), CUI::CORNER_T, 4.0f); - + if(ToolboxPage == 0) RenderServerbrowserFilters(ToolBox); @@ -877,7 +877,7 @@ void CMenus::RenderServerbrowser(CUIRect MainView) ButtonArea.VSplitRight(150.0f, 0, &ButtonArea); ButtonArea.HSplitTop(20.0f, &Button, &ButtonArea); Button.VMargin(2.0f, &Button); - + static int s_RefreshButton = 0; if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &Button)) { @@ -892,7 +892,7 @@ void CMenus::RenderServerbrowser(CUIRect MainView) ButtonArea.HSplitTop(5.0f, 0, &ButtonArea); ButtonArea.HSplitTop(20.0f, &Button, &ButtonArea); Button.VMargin(2.0f, &Button); - + static int s_JoinButton = 0; if(DoButton_Menu(&s_JoinButton, Localize("Connect"), 0, &Button) || m_EnterPressed) { diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 7e73c3eb5..7fcfab99a 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -28,7 +28,7 @@ int CMenus::DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, int CMenus::DoButton_Sprite(const void *pID, int ImageID, int SpriteID, int Checked, const CUIRect *pRect, int Corners) { - RenderTools()->DrawUIRect(pRect, Checked ? vec4(1.0f, 1.0f, 1.0f, 0.10f) : vec4(1.0f, 1.0f, 1.0f, 0.5f)*ButtonColorMul(pID), Corners, 5.0f); + RenderTools()->DrawUIRect(pRect, Checked ? vec4(1.0f, 1.0f, 1.0f, 0.10f) : vec4(1.0f, 1.0f, 1.0f, 0.5f)*ButtonColorMul(pID), Corners, 5.0f); Graphics()->TextureSet(g_pData->m_aImages[ImageID].m_Id); Graphics()->QuadsBegin(); if(!Checked) @@ -37,38 +37,38 @@ int CMenus::DoButton_Sprite(const void *pID, int ImageID, int SpriteID, int Chec IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - + return UI()->DoButtonLogic(pID, "", Checked, pRect); } void CMenus::RenderDemoPlayer(CUIRect MainView) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - + const float SeekBarHeight = 15.0f; const float ButtonbarHeight = 20.0f; const float NameBarHeight = 20.0f; const float Margins = 5.0f; float TotalHeight; - + if(m_MenuActive) TotalHeight = SeekBarHeight+ButtonbarHeight+NameBarHeight+Margins*3; else TotalHeight = SeekBarHeight+Margins*2; - + MainView.HSplitBottom(TotalHeight, 0, &MainView); MainView.VSplitLeft(50.0f, 0, &MainView); MainView.VSplitRight(450.0f, &MainView, 0); - + RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_T, 10.0f); - + MainView.Margin(5.0f, &MainView); - + CUIRect SeekBar, ButtonBar, NameBar; - + int CurrentTick = pInfo->m_CurrentTick - pInfo->m_FirstTick; int TotalTicks = pInfo->m_LastTick - pInfo->m_FirstTick; - + if(m_MenuActive) { MainView.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar); @@ -84,24 +84,24 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) static int s_SeekBarID = 0; void *id = &s_SeekBarID; char aBuffer[128]; - + RenderTools()->DrawUIRect(&SeekBar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 5.0f); - + float Amount = CurrentTick/(float)TotalTicks; - + CUIRect FilledBar = SeekBar; FilledBar.w = 10.0f + (FilledBar.w-10.0f)*Amount; - + RenderTools()->DrawUIRect(&FilledBar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f); - + str_format(aBuffer, sizeof(aBuffer), "%d:%02d / %d:%02d", CurrentTick/SERVER_TICK_SPEED/60, (CurrentTick/SERVER_TICK_SPEED)%60, TotalTicks/SERVER_TICK_SPEED/60, (TotalTicks/SERVER_TICK_SPEED)%60); UI()->DoLabel(&SeekBar, aBuffer, SeekBar.h*0.70f, 0); // do the logic - int Inside = UI()->MouseInside(&SeekBar); - + int Inside = UI()->MouseInside(&SeekBar); + if(UI()->ActiveItem() == id) { if(!UI()->MouseButton(0)) @@ -124,11 +124,11 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) { if(UI()->MouseButton(0)) UI()->SetActiveItem(id); - } - + } + if(Inside) UI()->SetHotItem(id); - } + } if(CurrentTick == TotalTicks) { @@ -143,7 +143,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) { // do buttons CUIRect Button; - + // combined play and pause button ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); static int s_PlayPauseButton = 0; @@ -157,16 +157,16 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) if(DoButton_Sprite(&s_PlayPauseButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_PLAY, false, &Button, CUI::CORNER_ALL)) DemoPlayer()->Unpause(); } - + // stop button - + ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); static int s_ResetButton = 0; if(DoButton_Sprite(&s_ResetButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_STOP, false, &Button, CUI::CORNER_ALL)) { m_pClient->OnReset(); - DemoPlayer()->Pause(); + DemoPlayer()->Pause(); DemoPlayer()->SetPos(0); } @@ -176,7 +176,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) static int s_SlowDownButton = 0; if(DoButton_Sprite(&s_SlowDownButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_SLOWER, 0, &Button, CUI::CORNER_ALL) || Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) DecreaseDemoSpeed = true; - + // fastforward ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); @@ -250,15 +250,15 @@ void CMenus::UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHe CUIRect Scroll, Row; CUIRect View = *pRect; CUIRect Header, Footer; - + // draw header View.HSplitTop(ms_ListheaderHeight, &Header, &View); - RenderTools()->DrawUIRect(&Header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); + RenderTools()->DrawUIRect(&Header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight, 0); // draw footers View.HSplitBottom(ms_ListheaderHeight, &View, &Footer); - RenderTools()->DrawUIRect(&Footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); + RenderTools()->DrawUIRect(&Footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); Footer.VSplitLeft(10.0f, 0, &Footer); UI()->DoLabel(&Footer, pBottomText, Header.h*ms_FontmodHeight, 0); @@ -268,7 +268,7 @@ void CMenus::UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHe // prepare the scroll View.VSplitRight(15, &View, &Scroll); - // setup the variables + // setup the variables gs_ListBoxOriginalView = View; gs_ListBoxSelectedIndex = SelectedIndex; gs_ListBoxNewSelected = SelectedIndex; @@ -282,7 +282,7 @@ void CMenus::UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHe // do the scrollbar View.HSplitTop(gs_ListBoxRowHeight, &Row, 0); - + int NumViewable = (int)(gs_ListBoxOriginalView.h/Row.h) + 1; int Num = (NumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1; if(Num < 0) @@ -293,14 +293,14 @@ void CMenus::UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHe gs_ListBoxScrollValue -= 3.0f/Num; if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN)) gs_ListBoxScrollValue += 3.0f/Num; - + if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f; if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f; } - + Scroll.HMargin(5.0f, &Scroll); gs_ListBoxScrollValue = DoScrollbarV(pID, &Scroll, gs_ListBoxScrollValue); - + // the list gs_ListBoxView = gs_ListBoxOriginalView; gs_ListBoxView.VMargin(5.0f, &gs_ListBoxView); @@ -319,24 +319,24 @@ CMenus::CListboxItem CMenus::UiDoListboxNextRow() Item.m_Visible = 1; //item.rect = row; - + Item.m_HitRect = Item.m_Rect; - + //CUIRect select_hit_box = item.rect; if(gs_ListBoxSelectedIndex == gs_ListBoxItemIndex) Item.m_Selected = 1; - + // make sure that only those in view can be selected if(Item.m_Rect.y+Item.m_Rect.h > gs_ListBoxOriginalView.y) { - + if(Item.m_HitRect.y < Item.m_HitRect.y) // clip the selection { Item.m_HitRect.h -= gs_ListBoxOriginalView.y-Item.m_HitRect.y; Item.m_HitRect.y = gs_ListBoxOriginalView.y; } - + } else Item.m_Visible = 0; @@ -344,7 +344,7 @@ CMenus::CListboxItem CMenus::UiDoListboxNextRow() // check if we need to do more if(Item.m_Rect.y > gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h) Item.m_Visible = 0; - + gs_ListBoxItemIndex++; return Item; } @@ -358,12 +358,12 @@ CMenus::CListboxItem CMenus::UiDoListboxNextItem(const void *pId, bool Selected) gs_ListBoxNewSelected = ThisItemIndex; gs_ListBoxSelectedIndex = ThisItemIndex; } - + CListboxItem Item = UiDoListboxNextRow(); if(Item.m_Visible && UI()->DoButtonLogic(pId, "", gs_ListBoxSelectedIndex == gs_ListBoxItemIndex, &Item.m_HitRect)) gs_ListBoxNewSelected = ThisItemIndex; - + // process input, regard selected index if(gs_ListBoxSelectedIndex == ThisItemIndex) { @@ -377,7 +377,7 @@ CMenus::CListboxItem CMenus::UiDoListboxNextItem(const void *pId, bool Selected) UI()->SetActiveItem(0); } else - { + { for(int i = 0; i < m_NumInputEvents; i++) { int NewIndex = -1; @@ -410,18 +410,18 @@ CMenus::CListboxItem CMenus::UiDoListboxNextItem(const void *pId, bool Selected) if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f; if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f; } - + gs_ListBoxNewSelected = NewIndex; } } } } - + //selected_index = i; CUIRect r = Item.m_Rect; r.Margin(1.5f, &r); RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f); - } + } return Item; } @@ -444,7 +444,7 @@ int CMenus::DemolistFetchCallback(const char *pName, int IsDir, int StorageType, (pName[1] == '.' && pName[2] == 0 && !str_comp(pSelf->m_aCurrentDemoFolder, "demos")))) || (!IsDir && (Length < 5 || str_comp(pName+Length-5, ".demo")))) return 0; - + CDemoItem Item; str_copy(Item.m_aFilename, pName, sizeof(Item.m_aFilename)); if(IsDir) @@ -513,11 +513,11 @@ void CMenus::RenderDemoList(CUIRect MainView) str_copy(aFooterLabel, Localize("Demo details"), sizeof(aFooterLabel)); } } - + // render background RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); MainView.Margin(10.0f, &MainView); - + CUIRect ButtonBar, RefreshRect, PlayRect, DeleteRect, RenameRect, FileIcon, ListBox; MainView.HSplitBottom(ms_ButtonHeight+5.0f, &MainView, &ButtonBar); ButtonBar.HSplitTop(5.0f, 0, &ButtonBar); @@ -595,7 +595,7 @@ void CMenus::RenderDemoList(CUIRect MainView) UI()->DoLabelScaled(&Left, Localize("Netversion:"), 14.0f, -1); UI()->DoLabelScaled(&Right, m_lDemos[m_DemolistSelectedIndex].m_Info.m_aNetversion, 14.0f, -1); } - + static int s_DemoListId = 0; static float s_ScrollValue = 0; UiDoListboxStart(&s_DemoListId, &ListBox, 17.0f, Localize("Demos"), aFooterLabel, m_lDemos.size(), 1, m_DemolistSelectedIndex, s_ScrollValue); @@ -613,7 +613,7 @@ void CMenus::RenderDemoList(CUIRect MainView) bool Activated = false; m_DemolistSelectedIndex = UiDoListboxEnd(&s_ScrollValue, &Activated); DemolistOnUpdate(false); - + static int s_RefreshButton = 0; if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &RefreshRect)) { @@ -655,7 +655,7 @@ void CMenus::RenderDemoList(CUIRect MainView) } } } - + if(!m_DemolistSelectedIsDir) { static int s_DeleteButton = 0; diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 4737f38dc..33aaa14f2 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -28,12 +28,12 @@ void CMenus::RenderGame(CUIRect MainView) CUIRect Button, ButtonBar; MainView.HSplitTop(45.0f, &ButtonBar, &MainView); RenderTools()->DrawUIRect(&ButtonBar, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); - + // button bar ButtonBar.HSplitTop(10.0f, 0, &ButtonBar); ButtonBar.HSplitTop(25.0f, &ButtonBar, 0); ButtonBar.VMargin(10.0f, &ButtonBar); - + ButtonBar.VSplitRight(120.0f, &ButtonBar, &Button); static int s_DisconnectButton = 0; if(DoButton_Menu(&s_DisconnectButton, Localize("Disconnect"), 0, &Button)) @@ -52,7 +52,7 @@ void CMenus::RenderGame(CUIRect MainView) SetActive(false); } } - + if(m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags & GAMEFLAG_TEAMS) { if(m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_RED) @@ -193,7 +193,7 @@ void CMenus::RenderPlayers(CUIRect MainView) else m_pClient->Friends()->AddFriend(m_pClient->m_aClients[i].m_aName, m_pClient->m_aClients[i].m_aClan); } - + /* CUIRect bars; votearea.HSplitTop(10.0f, 0, &votearea); @@ -220,7 +220,7 @@ void CMenus::RenderPlayers(CUIRect MainView) static int no_button = 0; if(UI()->DoButton(&no_button, "No", 0, &button, ui_draw_menu_button, 0)) gameclient.voting->vote(-1); - + // do time left votearea.VSplitRight(50.0f, &votearea, &button); char buf[256]; @@ -236,10 +236,10 @@ void CMenus::RenderPlayers(CUIRect MainView) // do bars bars.HSplitTop(10.0f, 0, &bars); bars.HMargin(5.0f, &bars); - + gameclient.voting->render_bars(bars, true); - } + } else { UI()->DoLabel(&votearea, "No vote in progress", 18.0f, -1); @@ -254,33 +254,33 @@ void CMenus::RenderServerInfo(CUIRect MainView) // fetch server info CServerInfo CurrentServerInfo; Client()->GetServerInfo(&CurrentServerInfo); - + // render background RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f); - + CUIRect View, ServerInfo, GameInfo, Motd; - + float x = 0.0f; float y = 0.0f; - + char aBuf[1024]; - + // set view to use for all sub-modules MainView.Margin(10.0f, &View); - + // serverinfo View.HSplitTop(View.h/2/UI()->Scale()-5.0f, &ServerInfo, &Motd); ServerInfo.VSplitLeft(View.w/2/UI()->Scale()-5.0f, &ServerInfo, &GameInfo); RenderTools()->DrawUIRect(&ServerInfo, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - + ServerInfo.Margin(5.0f, &ServerInfo); - + x = 5.0f; y = 0.0f; - + TextRender()->Text(0, ServerInfo.x+x, ServerInfo.y+y, 32, Localize("Server info"), 250); y += 32.0f+5.0f; - + mem_zero(aBuf, sizeof(aBuf)); str_format( aBuf, @@ -296,9 +296,9 @@ void CMenus::RenderServerInfo(CUIRect MainView) Localize("Version"), CurrentServerInfo.m_aVersion, Localize("Password"), CurrentServerInfo.m_Flags &1 ? Localize("Yes") : Localize("No") ); - + TextRender()->Text(0, ServerInfo.x+x, ServerInfo.y+y, 20, aBuf, 250); - + { CUIRect Button; int IsFavorite = ServerBrowser()->IsFavorite(CurrentServerInfo.m_NetAddr); @@ -312,19 +312,19 @@ void CMenus::RenderServerInfo(CUIRect MainView) ServerBrowser()->AddFavorite(CurrentServerInfo.m_NetAddr); } } - + // gameinfo GameInfo.VSplitLeft(10.0f, 0x0, &GameInfo); RenderTools()->DrawUIRect(&GameInfo, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); - + GameInfo.Margin(5.0f, &GameInfo); - + x = 5.0f; y = 0.0f; - + TextRender()->Text(0, GameInfo.x+x, GameInfo.y+y, 32, Localize("Game info"), 250); y += 32.0f+5.0f; - + if(m_pClient->m_Snap.m_pGameInfoObj) { mem_zero(aBuf, sizeof(aBuf)); @@ -346,7 +346,7 @@ void CMenus::RenderServerInfo(CUIRect MainView) ); TextRender()->Text(0, GameInfo.x+x, GameInfo.y+y, 20, aBuf, 250); } - + // motd Motd.HSplitTop(10.0f, 0, &Motd); RenderTools()->DrawUIRect(&Motd, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); @@ -364,15 +364,15 @@ void CMenus::RenderServerControlServer(CUIRect MainView) static float s_ScrollValue = 0; CUIRect List = MainView; UiDoListboxStart(&s_VoteList, &List, 24.0f, "", "", m_pClient->m_pVoting->m_NumVoteOptions, 1, m_CallvoteSelectedOption, s_ScrollValue); - + for(CVoteOptionClient *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext) { CListboxItem Item = UiDoListboxNextItem(pOption); - + if(Item.m_Visible) UI()->DoLabelScaled(&Item.m_Rect, pOption->m_aDescription, 16.0f, -1); } - + m_CallvoteSelectedOption = UiDoListboxEnd(&s_ScrollValue, 0); } @@ -396,11 +396,11 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) static float s_ScrollValue = 0; CUIRect List = MainView; UiDoListboxStart(&s_VoteList, &List, 24.0f, "", "", NumOptions, 1, Selected, s_ScrollValue); - + for(int i = 0; i < NumOptions; i++) { CListboxItem Item = UiDoListboxNextItem(&aPlayerIDs[i]); - + if(Item.m_Visible) { CTeeRenderInfo Info = m_pClient->m_aClients[aPlayerIDs[i]].m_RenderInfo; @@ -411,7 +411,7 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) UI()->DoLabelScaled(&Item.m_Rect, m_pClient->m_aClients[aPlayerIDs[i]].m_aName, 16.0f, -1); } } - + Selected = UiDoListboxEnd(&s_ScrollValue, 0); m_CallvoteSelectedPlayer = Selected != -1 ? aPlayerIDs[Selected] : -1; } @@ -419,7 +419,7 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) void CMenus::RenderServerControl(CUIRect MainView) { static int s_ControlPage = 0; - + // render background CUIRect Bottom, Extended, TabBar, Button; MainView.HSplitTop(20.0f, &Bottom, &MainView); @@ -461,7 +461,7 @@ void CMenus::RenderServerControl(CUIRect MainView) { CUIRect Button; Bottom.VSplitRight(120.0f, &Bottom, &Button); - + static int s_CallVoteButton = 0; if(DoButton_Menu(&s_CallVoteButton, Localize("Call vote"), 0, &Button)) { @@ -487,7 +487,7 @@ void CMenus::RenderServerControl(CUIRect MainView) } m_aCallvoteReason[0] = 0; } - + // render kick reason CUIRect Reason; Bottom.VSplitRight(40.0f, &Bottom, 0); @@ -499,7 +499,7 @@ void CMenus::RenderServerControl(CUIRect MainView) Reason.VSplitLeft(w+10.0f, 0, &Reason); static float s_Offset = 0.0f; DoEditBox(&m_aCallvoteReason, &Reason, m_aCallvoteReason, sizeof(m_aCallvoteReason), 14.0f, &s_Offset, false, CUI::CORNER_ALL); - + // extended features (only available when authed in rcon) if(Client()->RconAuthed()) { @@ -545,7 +545,7 @@ void CMenus::RenderServerControl(CUIRect MainView) static int s_RemoveVoteButton = 0; if(DoButton_Menu(&s_RemoveVoteButton, Localize("Remove"), 0, &Button)) m_pClient->m_pVoting->RemovevoteOption(m_CallvoteSelectedOption); - + // add vote Extended.HSplitTop(20.0f, &Bottom, &Extended); @@ -571,7 +571,7 @@ void CMenus::RenderServerControl(CUIRect MainView) static float s_OffsetDesc = 0.0f; DoEditBox(&s_aVoteDescription, &Button, s_aVoteDescription, sizeof(s_aVoteDescription), 14.0f, &s_OffsetDesc, false, CUI::CORNER_ALL); - Bottom.VMargin(20.0f, &Button); + Bottom.VMargin(20.0f, &Button); static float s_OffsetCmd = 0.0f; DoEditBox(&s_aVoteCommand, &Button, s_aVoteCommand, sizeof(s_aVoteCommand), 14.0f, &s_OffsetCmd, false, CUI::CORNER_ALL); } diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 959af2f32..28f3559dc 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -108,7 +108,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) Right.HSplitTop(20.0f, &Button, &Right); if(DoButton_CheckBox(&g_Config.m_ClNameplatesAlways, Localize("Always show name plates"), g_Config.m_ClNameplatesAlways, &Button)) g_Config.m_ClNameplatesAlways ^= 1; - + Right.HSplitTop(2.5f, 0, &Right); Right.HSplitTop(20.0f, &Label, &Right); Right.HSplitTop(20.0f, &Button, &Right); @@ -245,7 +245,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) MainView.HSplitTop(10.0f, 0, &MainView); // skin info - const CSkins::CSkin *pOwnSkin = m_pClient->m_pSkins->Get(m_pClient->m_pSkins->Find(g_Config.m_PlayerSkin)); + const CSkins::CSkin *pOwnSkin = m_pClient->m_pSkins->Get(m_pClient->m_pSkins->Find(g_Config.m_PlayerSkin)); CTeeRenderInfo OwnSkinInfo; if(g_Config.m_PlayerUseCustomColor) { @@ -273,7 +273,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Label.x+30.0f, Label.y+28.0f)); Label.HSplitTop(15.0f, 0, &Label);; Label.VSplitLeft(70.0f, 0, &Label); - UI()->DoLabelScaled(&Label, g_Config.m_PlayerSkin, 14.0f, -1, 150.0f); + UI()->DoLabelScaled(&Label, g_Config.m_PlayerSkin, 14.0f, -1, 150.0f); // custom colour selector MainView.HSplitTop(20.0f, 0, &MainView); @@ -322,7 +322,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView) Label.VSplitLeft(100.0f, &Label, &Button); Button.HMargin(2.0f, &Button); - float k = ((PrevColor>>((2-s)*8))&0xff) / 255.0f; + float k = ((PrevColor>>((2-s)*8))&0xff) / 255.0f; k = DoScrollbarH(&s_aColorSlider[i][s], &Button, k); Color <<= 8; Color += clamp((int)(k*255), 0, 255); @@ -643,7 +643,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) CListboxItem Item = UiDoListboxNextItem(&s_aModes[i], OldSelected == i); if(Item.m_Visible) { - str_format(aBuf, sizeof(aBuf), " %dx%d %d bit", s_aModes[i].m_Width, s_aModes[i].m_Height, Depth); + str_format(aBuf, sizeof(aBuf), " %dx%d %d bit", s_aModes[i].m_Width, s_aModes[i].m_Height, Depth); UI()->DoLabelScaled(&Item.m_Rect, aBuf, 16.0f, -1); } } @@ -826,7 +826,7 @@ void LoadLanguageIndexfile(IStorage *pStorage, IConsole *pConsole, sorted_array< pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "localization", "couldn't open index file"); return; } - + char aOrigin[128]; CLineReader LineReader; LineReader.Init(File); @@ -835,7 +835,7 @@ void LoadLanguageIndexfile(IStorage *pStorage, IConsole *pConsole, sorted_array< { if(!str_length(pLine) || pLine[0] == '#') // skip empty lines and comments continue; - + str_copy(aOrigin, pLine, sizeof(aOrigin)); char *pReplacement = LineReader.Get(); if(!pReplacement) @@ -843,7 +843,7 @@ void LoadLanguageIndexfile(IStorage *pStorage, IConsole *pConsole, sorted_array< pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "localization", "unexpected end of index file"); break; } - + if(pReplacement[0] != '=' || pReplacement[1] != '=' || pReplacement[2] != ' ') { char aBuf[128]; @@ -851,7 +851,7 @@ void LoadLanguageIndexfile(IStorage *pStorage, IConsole *pConsole, sorted_array< pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "localization", aBuf); continue; } - + char aFileName[128]; str_format(aFileName, sizeof(aFileName), "languages/%s.txt", aOrigin); pLanguages->add(CLanguage(pReplacement+3, aFileName)); @@ -861,7 +861,7 @@ void LoadLanguageIndexfile(IStorage *pStorage, IConsole *pConsole, sorted_array< void CMenus::RenderLanguageSelection(CUIRect MainView) { - static int s_LanguageList = 0; + static int s_LanguageList = 0; static int s_SelectedLanguage = 0; static sorted_array s_Languages; static float s_ScrollValue = 0; diff --git a/src/game/client/components/motd.cpp b/src/game/client/components/motd.cpp index 963479335..76203c471 100644 --- a/src/game/client/components/motd.cpp +++ b/src/game/client/components/motd.cpp @@ -18,7 +18,7 @@ void CMotd::Clear() bool CMotd::IsActive() { - return time_get() < m_ServerMotdTime; + return time_get() < m_ServerMotdTime; } void CMotd::OnStateChange(int NewState, int OldState) @@ -31,12 +31,12 @@ void CMotd::OnRender() { if(!IsActive()) return; - + float Width = 400*3.0f*Graphics()->ScreenAspect(); float Height = 400*3.0f; Graphics()->MapScreen(0, 0, Width, Height); - + float h = 800.0f; float w = 650.0f; float x = Width/2 - w/2; @@ -61,7 +61,7 @@ void CMotd::OnMessage(int MsgType, void *pRawMsg) { CNetMsg_Sv_Motd *pMsg = (CNetMsg_Sv_Motd *)pRawMsg; - // process escaping + // process escaping str_copy(m_aServerMotd, pMsg->m_pMessage, sizeof(m_aServerMotd)); for(int i = 0; m_aServerMotd[i]; i++) { diff --git a/src/game/client/components/motd.h b/src/game/client/components/motd.h index e2240fa26..f47adafff 100644 --- a/src/game/client/components/motd.h +++ b/src/game/client/components/motd.h @@ -13,7 +13,7 @@ public: void Clear(); bool IsActive(); - + virtual void OnRender(); virtual void OnStateChange(int NewState, int OldState); virtual void OnMessage(int MsgType, void *pRawMsg); diff --git a/src/game/client/components/nameplates.cpp b/src/game/client/components/nameplates.cpp index fecd62273..6699fe247 100644 --- a/src/game/client/components/nameplates.cpp +++ b/src/game/client/components/nameplates.cpp @@ -17,9 +17,9 @@ void CNamePlates::RenderNameplate( ) { float IntraTick = Client()->IntraGameTick(); - + vec2 Position = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), IntraTick); - + float FontSize = 18.0f + 20.0f * g_Config.m_ClNameplatesSize / 100.0f; // render name plate @@ -28,10 +28,10 @@ void CNamePlates::RenderNameplate( float a = 1; if(g_Config.m_ClNameplatesAlways == 0) a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos, Position)/200.0f,16.0f), 0.0f, 1.0f); - + const char *pName = m_pClient->m_aClients[pPlayerInfo->m_ClientID].m_aName; float tw = TextRender()->TextWidth(0, FontSize, pName, -1); - + TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.5f*a); TextRender()->TextColor(1.0f, 1.0f, 1.0f, a); if(g_Config.m_ClNameplatesTeamcolors && m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) @@ -41,9 +41,9 @@ void CNamePlates::RenderNameplate( else if(pPlayerInfo->m_Team == TEAM_BLUE) TextRender()->TextColor(0.7f, 0.7f, 1.0f, a); } - + TextRender()->Text(0, Position.x-tw/2.0f, Position.y-FontSize-38.0f, FontSize, pName, -1); - + if(g_Config.m_Debug) // render client id when in debug aswell { char aBuf[128]; diff --git a/src/game/client/components/particles.cpp b/src/game/client/components/particles.cpp index 25c9dd36f..c4583cb18 100644 --- a/src/game/client/components/particles.cpp +++ b/src/game/client/components/particles.cpp @@ -26,7 +26,7 @@ void CParticles::OnReset() m_aParticles[i].m_PrevPart = i-1; m_aParticles[i].m_NextPart = i+1; } - + m_aParticles[0].m_PrevPart = 0; m_aParticles[MAX_PARTICLES-1].m_NextPart = -1; m_FirstFree = 0; @@ -39,30 +39,30 @@ void CParticles::Add(int Group, CParticle *pPart) { if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { - const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); + const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); if(pInfo->m_Paused) return; } if (m_FirstFree == -1) return; - + // remove from the free list int Id = m_FirstFree; m_FirstFree = m_aParticles[Id].m_NextPart; if(m_FirstFree != -1) m_aParticles[m_FirstFree].m_PrevPart = -1; - + // copy data m_aParticles[Id] = *pPart; - + // insert to the group list m_aParticles[Id].m_PrevPart = -1; m_aParticles[Id].m_NextPart = m_aFirstPart[Group]; if(m_aFirstPart[Group] != -1) m_aParticles[m_aFirstPart[Group]].m_PrevPart = Id; m_aFirstPart[Group] = Id; - + // set some parameters m_aParticles[Id].m_Life = 0; } @@ -74,14 +74,14 @@ void CParticles::Update(float TimePassed) if(FrictionFraction > 2.0f) // safty messure FrictionFraction = 0; - + int FrictionCount = 0; while(FrictionFraction > 0.05f) { FrictionCount++; FrictionFraction -= 0.05f; } - + for(int g = 0; g < NUM_GROUPS; g++) { int i = m_aFirstPart[g]; @@ -90,15 +90,15 @@ void CParticles::Update(float TimePassed) int Next = m_aParticles[i].m_NextPart; //m_aParticles[i].vel += flow_get(m_aParticles[i].pos)*time_passed * m_aParticles[i].flow_affected; m_aParticles[i].m_Vel.y += m_aParticles[i].m_Gravity*TimePassed; - + for(int f = 0; f < FrictionCount; f++) // apply friction m_aParticles[i].m_Vel *= m_aParticles[i].m_Friction; - + // move the point vec2 Vel = m_aParticles[i].m_Vel*TimePassed; Collision()->MovePoint(&m_aParticles[i].m_Pos, &Vel, 0.1f+0.9f*frandom(), NULL); m_aParticles[i].m_Vel = Vel* (1.0f/TimePassed); - + m_aParticles[i].m_Life += TimePassed; m_aParticles[i].m_Rot += TimePassed * m_aParticles[i].m_Rotspeed; @@ -110,10 +110,10 @@ void CParticles::Update(float TimePassed) m_aParticles[m_aParticles[i].m_PrevPart].m_NextPart = m_aParticles[i].m_NextPart; else m_aFirstPart[g] = m_aParticles[i].m_NextPart; - + if(m_aParticles[i].m_NextPart != -1) m_aParticles[m_aParticles[i].m_NextPart].m_PrevPart = m_aParticles[i].m_PrevPart; - + // insert to the free list if(m_FirstFree != -1) m_aParticles[m_FirstFree].m_PrevPart = i; @@ -121,7 +121,7 @@ void CParticles::Update(float TimePassed) m_aParticles[i].m_NextPart = m_FirstFree; m_FirstFree = i; } - + i = Next; } } @@ -134,16 +134,16 @@ void CParticles::OnRender() static int64 LastTime = 0; int64 t = time_get(); - + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { - const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); + const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); if(!pInfo->m_Paused) Update((float)((t-LastTime)/(double)time_freq())*pInfo->m_Speed); } else Update((float)((t-LastTime)/(double)time_freq())); - + LastTime = t; } @@ -168,11 +168,11 @@ void CParticles::RenderGroup(int Group) m_aParticles[i].m_Color.r, m_aParticles[i].m_Color.g, m_aParticles[i].m_Color.b, - m_aParticles[i].m_Color.a); // pow(a, 0.75f) * + m_aParticles[i].m_Color.a); // pow(a, 0.75f) * IGraphics::CQuadItem QuadItem(p.x, p.y, Size, Size); Graphics()->QuadsDraw(&QuadItem, 1); - + i = m_aParticles[i].m_NextPart; } Graphics()->QuadsEnd(); diff --git a/src/game/client/components/particles.h b/src/game/client/components/particles.h index 641ec2617..176a2b05e 100644 --- a/src/game/client/components/particles.h +++ b/src/game/client/components/particles.h @@ -21,7 +21,7 @@ struct CParticle m_FlowAffected = 1.0f; m_Color = vec4(1,1,1,1); } - + vec2 m_Pos; vec2 m_Vel; @@ -30,7 +30,7 @@ struct CParticle float m_FlowAffected; float m_LifeSpan; - + float m_StartSize; float m_EndSize; @@ -41,7 +41,7 @@ struct CParticle float m_Friction; vec4 m_Color; - + // set by the particle system float m_Life; int m_PrevPart; @@ -61,14 +61,14 @@ public: }; CParticles(); - + void Add(int Group, CParticle *pPart); - + virtual void OnReset(); virtual void OnRender(); private: - + enum { MAX_PARTICLES=1024*8, @@ -77,7 +77,7 @@ private: CParticle m_aParticles[MAX_PARTICLES]; int m_FirstFree; int m_aFirstPart[NUM_GROUPS]; - + void RenderGroup(int Group); void Update(float TimePassed); @@ -88,7 +88,7 @@ private: CParticles *m_pParts; virtual void OnRender() { m_pParts->RenderGroup(TGROUP); } }; - + CRenderGroup m_RenderTrail; CRenderGroup m_RenderExplosions; CRenderGroup m_RenderGeneral; diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 74a48503d..6811c2ad2 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -25,7 +25,7 @@ void CPlayers::RenderHand(CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float { // for drawing hand //const skin *s = skin_get(skin_id); - + float BaseSize = 10.0f; //dir = normalize(hook_pos-pos); @@ -102,7 +102,7 @@ void CPlayers::RenderHook( if(m_pClient->m_Snap.m_pGameInfoObj) IsTeamplay = (m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) != 0; - // check for ninja + // check for ninja if (Player.m_Weapon == WEAPON_NINJA) { // change the skin for the player to the ninja @@ -117,7 +117,7 @@ void CPlayers::RenderHook( RenderInfo.m_ColorBody = vec4(1,1,1,1); RenderInfo.m_ColorFeet = vec4(1,1,1,1); } - } + } } float IntraTick = Client()->IntraGameTick(); @@ -125,7 +125,7 @@ void CPlayers::RenderHook( // set size RenderInfo.m_Size = 64.0f; - + // use preditect players if needed if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { @@ -152,7 +152,7 @@ void CPlayers::RenderHook( vec2 Pos = Position; vec2 HookPos; - + if(pPlayerChar->m_HookedPlayer != -1) { if(m_pClient->m_Snap.m_pLocalInfo && pPlayerChar->m_HookedPlayer == m_pClient->m_Snap.m_pLocalInfo->m_ClientID) @@ -226,7 +226,7 @@ void CPlayers::RenderPlayer( if(m_pClient->m_Snap.m_pGameInfoObj) IsTeamplay = (m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) != 0; - // check for ninja + // check for ninja if (Player.m_Weapon == WEAPON_NINJA) { // change the skin for the player to the ninja @@ -241,18 +241,18 @@ void CPlayers::RenderPlayer( RenderInfo.m_ColorBody = vec4(1,1,1,1); RenderInfo.m_ColorFeet = vec4(1,1,1,1); } - } + } } - + // set size RenderInfo.m_Size = 64.0f; float IntraTick = Client()->IntraGameTick(); - + float Angle = mix((float)Prev.m_Angle, (float)Player.m_Angle, IntraTick)/256.0f; - + //float angle = 0; - + if(pInfo.m_Local && Client()->State() != IClient::STATE_DEMOPLAYBACK) { // just use the direct input if it's local player we are rendering @@ -264,14 +264,14 @@ void CPlayers::RenderPlayer( float mixspeed = Client()->FrameTime()*2.5f; if(player.attacktick != prev.attacktick) // shooting boosts the mixing speed mixspeed *= 15.0f; - + // move the delta on a constant speed on a x^2 curve float current = g_GameClient.m_aClients[info.cid].angle; float target = player.angle/256.0f; float delta = angular_distance(current, target); float sign = delta < 0 ? -1 : 1; float new_delta = delta - 2*mixspeed*sqrt(delta*sign)*sign + mixspeed*mixspeed; - + // make sure that it doesn't vibrate when it's still if(fabs(delta) < 2/256.0f) angle = target; @@ -280,7 +280,7 @@ void CPlayers::RenderPlayer( g_GameClient.m_aClients[info.cid].angle = angle;*/ } - + // use preditect players if needed if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { @@ -296,16 +296,16 @@ void CPlayers::RenderPlayer( NewTick = m_pClient->m_NewPredictedTick; } } - + vec2 Direction = GetDirection((int)(Angle*256.0f)); vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick); vec2 Vel = mix(vec2(Prev.m_VelX/256.0f, Prev.m_VelY/256.0f), vec2(Player.m_VelX/256.0f, Player.m_VelY/256.0f), IntraTick); - + m_pClient->m_pFlow->Add(Position, Vel*100.0f, 10.0f); - + RenderInfo.m_GotAirJump = Player.m_Jumped&2?0:1; - - + + // detect events if(NewTick) { @@ -340,7 +340,7 @@ void CPlayers::RenderPlayer( float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); State.Add(&g_pData->m_aAnimations[ANIM_NINJA_SWING], clamp(ct*2.0f,0.0f,1.0f), 1.0f); } - + // do skidding if(!InAir && WantOtherDir && length(Vel*50) > 500.0f) { @@ -350,7 +350,7 @@ void CPlayers::RenderPlayer( m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_PLAYER_SKID, 0.25f, Position); SkidSoundTime = time_get(); } - + m_pClient->m_pEffects->SkidTrail( Position+vec2(-Player.m_Direction*6,12), vec2(-Player.m_Direction*100*length(Vel),-50) @@ -422,7 +422,7 @@ void CPlayers::RenderPlayer( { vec2 Dir = vec2(pPlayerChar->m_X,pPlayerChar->m_Y) - vec2(pPrevChar->m_X, pPrevChar->m_Y); Dir = normalize(Dir); - float HadOkenAngle = GetAngle(Dir); + float HadOkenAngle = GetAngle(Dir); Graphics()->QuadsSetRotation(HadOkenAngle ); //float offsety = -data->weapons[iw].muzzleoffsety; RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX], 0); @@ -564,7 +564,7 @@ void CPlayers::OnRender() bool Local = ((const CNetObj_PlayerInfo *)pInfo)->m_Local !=0; if((p % 2) == 0 && Local) continue; if((p % 2) == 1 && !Local) continue; - + CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[i].m_Prev; CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[i].m_Cur; @@ -582,7 +582,7 @@ void CPlayers::OnRender() (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo ); - } + } } } } diff --git a/src/game/client/components/players.h b/src/game/client/components/players.h index 34cebd902..cedad0ff9 100644 --- a/src/game/client/components/players.h +++ b/src/game/client/components/players.h @@ -5,21 +5,21 @@ #include class CPlayers : public CComponent -{ +{ void RenderHand(class CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, vec2 PostRotOffset); void RenderPlayer( const CNetObj_Character *pPrevChar, const CNetObj_Character *pPlayerChar, const CNetObj_PlayerInfo *pPrevInfo, const CNetObj_PlayerInfo *pPlayerInfo - ); + ); void RenderHook( const CNetObj_Character *pPrevChar, const CNetObj_Character *pPlayerChar, const CNetObj_PlayerInfo *pPrevInfo, const CNetObj_PlayerInfo *pPlayerInfo ); - + public: virtual void OnRender(); }; diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index 47603255f..2cec5e621 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -82,7 +82,7 @@ void CScoreboard::RenderGoals(float x, float y, float w) void CScoreboard::RenderSpectators(float x, float y, float w) { - float h = 140.0f; + float h = 140.0f; // background Graphics()->BlendNormal(); @@ -194,19 +194,19 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch float NameOffset = TeeOffset+TeeLength, NameLength = 300.0f-TeeLength; float PingOffset = x+610.0f, PingLength = 65.0f; float CountryOffset = PingOffset-(LineHeight-Spacing-TeeSizeMod*5.0f)*2.0f, CountryLength = (LineHeight-Spacing-TeeSizeMod*5.0f)*2.0f; - float ClanOffset = x+370.0f, ClanLength = 230.0f-CountryLength; + float ClanOffset = x+370.0f, ClanLength = 230.0f-CountryLength; // render headlines y += 50.0f; float HeadlineFontsize = 22.0f; tw = TextRender()->TextWidth(0, HeadlineFontsize, Localize("Score"), -1); TextRender()->Text(0, ScoreOffset+ScoreLength-tw, y, HeadlineFontsize, Localize("Score"), -1); - + TextRender()->Text(0, NameOffset, y, HeadlineFontsize, Localize("Name"), -1); - + tw = TextRender()->TextWidth(0, HeadlineFontsize, Localize("Clan"), -1); TextRender()->Text(0, ClanOffset+ClanLength/2-tw/2, y, HeadlineFontsize, Localize("Clan"), -1); - + tw = TextRender()->TextWidth(0, HeadlineFontsize, Localize("Ping"), -1); TextRender()->Text(0, PingOffset+PingLength-tw, y, HeadlineFontsize, Localize("Ping"), -1); @@ -214,7 +214,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch y += HeadlineFontsize*2.0f; float FontSize = 24.0f; CTextCursor Cursor; - + for(int i = 0; i < MAX_CLIENTS; i++) { // make sure that we render the correct team @@ -249,13 +249,13 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch Graphics()->QuadsBegin(); RenderTools()->SelectSprite(pInfo->m_Team==TEAM_RED ? SPRITE_FLAG_BLUE : SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X); - + float Size = LineHeight; IGraphics::CQuadItem QuadItem(TeeOffset+0.0f, y-5.0f-Spacing/2.0f, Size/2.0f, Size); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } - + // avatar CTeeRenderInfo TeeInfo = m_pClient->m_aClients[pInfo->m_ClientID].m_RenderInfo; TeeInfo.m_Size *= TeeSizeMod; @@ -279,7 +279,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch IGraphics::CQuadItem QuadItem(CountryOffset, y+(Spacing+TeeSizeMod*5.0f)/2.0f, CountryLength, LineHeight-Spacing-TeeSizeMod*5.0f); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); - + // ping str_format(aBuf, sizeof(aBuf), "%d", clamp(pInfo->m_Latency, 0, 1000)); tw = TextRender()->TextWidth(0, FontSize, aBuf, -1); @@ -321,15 +321,15 @@ void CScoreboard::OnRender() { if(!Active()) return; - + // if the score board is active, then we should clear the motd message aswell if(m_pClient->m_pMotd->IsActive()) m_pClient->m_pMotd->Clear(); - + float Width = 400*3.0f*Graphics()->ScreenAspect(); float Height = 400*3.0f; - + Graphics()->MapScreen(0, 0, Width, Height); float w = 700.0f; @@ -342,12 +342,12 @@ void CScoreboard::OnRender() { const char *pRedClanName = GetClanName(TEAM_RED); const char *pBlueClanName = GetClanName(TEAM_BLUE); - + if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER && m_pClient->m_Snap.m_pGameDataObj) { char aText[256]; str_copy(aText, Localize("Draw!"), sizeof(aText)); - + if(m_pClient->m_Snap.m_pGameDataObj->m_TeamscoreRed > m_pClient->m_Snap.m_pGameDataObj->m_TeamscoreBlue) { if(pRedClanName) @@ -362,11 +362,11 @@ void CScoreboard::OnRender() else str_copy(aText, Localize("Blue team wins!"), sizeof(aText)); } - + float w = TextRender()->TextWidth(0, 86.0f, aText, -1); TextRender()->Text(0, Width/2-w/2, 39, 86.0f, aText, -1); } - + RenderScoreboard(Width/2-w-5.0f, 150.0f, w, TEAM_RED, pRedClanName ? pRedClanName : Localize("Red team")); RenderScoreboard(Width/2+5.0f, 150.0f, w, TEAM_BLUE, pBlueClanName ? pBlueClanName : Localize("Blue team")); } @@ -379,10 +379,10 @@ void CScoreboard::OnRender() bool CScoreboard::Active() { - // if we activly wanna look on the scoreboard + // if we activly wanna look on the scoreboard if(m_Active) return true; - + if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS) { // we are not a spectator, check if we are dead @@ -406,7 +406,7 @@ const char *CScoreboard::GetClanName(int Team) const CNetObj_PlayerInfo *pInfo = m_pClient->m_Snap.m_paInfoByScore[i]; if(!pInfo || pInfo->m_Team != Team) continue; - + if(!pClanName) { pClanName = m_pClient->m_aClients[pInfo->m_ClientID].m_aClan; @@ -420,7 +420,7 @@ const char *CScoreboard::GetClanName(int Team) return 0; } } - + if(ClanPlayers > 1 && pClanName[0]) return pClanName; else diff --git a/src/game/client/components/scoreboard.h b/src/game/client/components/scoreboard.h index 5ac43a49d..ea920d354 100644 --- a/src/game/client/components/scoreboard.h +++ b/src/game/client/components/scoreboard.h @@ -12,11 +12,11 @@ class CScoreboard : public CComponent void RenderRecordingNotification(float x); static void ConKeyScoreboard(IConsole::IResult *pResult, void *pUserData); - + const char *GetClanName(int Team); - + bool m_Active; - + public: CScoreboard(); virtual void OnReset(); diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index d8550da47..dd38e9eab 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -10,13 +10,13 @@ #include "skins.h" -int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) +int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) { CSkins *pSelf = (CSkins *)pUser; int l = str_length(pName); if(l < 4 || IsDir || str_comp(pName+l-4, ".png") != 0) return 0; - + char aBuf[512]; str_format(aBuf, sizeof(aBuf), "skins/%s", pName); CImageInfo Info; @@ -26,10 +26,10 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf); return 0; } - + CSkin Skin; Skin.m_OrgTexture = pSelf->Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0); - + int BodySize = 96; // body size unsigned char *d = (unsigned char *)Info.m_pData; int Pitch = Info.m_Width*4; @@ -47,10 +47,10 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) aColors[2] += d[y*Pitch+x*4+2]; } } - + Skin.m_BloodColor = normalize(vec3(aColors[0], aColors[1], aColors[2])); } - + // create colorless version int Step = Info.m_Format == CImageInfo::FORMAT_RGBA ? 4 : 3; @@ -63,11 +63,11 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) d[i*Step+2] = v; } - + int Freq[256] = {0}; int OrgWeight = 0; int NewWeight = 192; - + // find most common frequence for(int y = 0; y < BodySize; y++) for(int x = 0; x < BodySize; x++) @@ -75,7 +75,7 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) if(d[y*Pitch+x*4+3] > 128) Freq[d[y*Pitch+x*4]]++; } - + for(int i = 1; i < 256; i++) { if(Freq[OrgWeight] < Freq[i]) @@ -97,11 +97,11 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) d[y*Pitch+x*4+1] = v; d[y*Pitch+x*4+2] = v; } - + Skin.m_ColorTexture = pSelf->Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0); mem_free(Info.m_pData); - // set skin data + // set skin data str_copy(Skin.m_aName, pName, min((int)sizeof(Skin.m_aName),l-3)); str_format(aBuf, sizeof(aBuf), "load skin %s", Skin.m_aName); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf); @@ -130,7 +130,7 @@ void CSkins::OnInit() int CSkins::Num() { - return m_aSkins.size(); + return m_aSkins.size(); } const CSkins::CSkin *CSkins::Get(int Index) diff --git a/src/game/client/components/skins.h b/src/game/client/components/skins.h index d76ad85ba..519f45216 100644 --- a/src/game/client/components/skins.h +++ b/src/game/client/components/skins.h @@ -19,15 +19,15 @@ public: bool operator<(const CSkin &Other) { return str_comp(m_aName, Other.m_aName) < 0; } }; - + void OnInit(); - + vec3 GetColorV3(int v); vec4 GetColorV4(int v); int Num(); const CSkin *Get(int Index); int Find(const char *pName); - + private: sorted_array m_aSkins; diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index 24bd0ebf6..ffafa128b 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -19,7 +19,7 @@ struct CUserData static int LoadSoundsThread(void *pUser) { CUserData *pData = static_cast(pUser); - + for(int s = 0; s < g_pData->m_NumSounds; s++) { for(int i = 0; i < g_pData->m_aSounds[s].m_NumSounds; i++) @@ -86,7 +86,7 @@ void CSounds::OnRender() // play sound from queue if(m_QueuePos > 0) { - int64 Now = time_get(); + int64 Now = time_get(); if(m_QueueWaitTime <= Now) { Play(m_aQueue[0].m_Channel, m_aQueue[0].m_SetId, 1.0f, vec2(0,0)); @@ -122,7 +122,7 @@ void CSounds::PlayAndRecord(int Chn, int SetId, float Vol, vec2 Pos) CNetMsg_Sv_SoundGlobal Msg; Msg.m_SoundID = SetId; Client()->SendPackMsg(&Msg, MSGFLAG_NOSEND|MSGFLAG_RECORD); - + Play(Chn, SetId, Vol, Pos); } diff --git a/src/game/client/components/sounds.h b/src/game/client/components/sounds.h index ca8cfd775..2670f793c 100644 --- a/src/game/client/components/sounds.h +++ b/src/game/client/components/sounds.h @@ -33,7 +33,7 @@ public: virtual void OnInit(); virtual void OnReset(); virtual void OnRender(); - + void ClearQueue(); void Enqueue(int Channel, int SetId); void Play(int Channel, int SetId, float Vol, vec2 Pos); diff --git a/src/game/client/components/spectator.cpp b/src/game/client/components/spectator.cpp index 94889de7e..41c7b48f2 100644 --- a/src/game/client/components/spectator.cpp +++ b/src/game/client/components/spectator.cpp @@ -32,7 +32,7 @@ void CSpectator::ConSpectateNext(IConsole::IResult *pResult, void *pUserData) CSpectator *pSelf = (CSpectator *)pUserData; int NewSpectatorID; bool GotNewSpectatorID = false; - + if(pSelf->m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW) { for(int i = 0; i < MAX_CLIENTS; i++) @@ -56,7 +56,7 @@ void CSpectator::ConSpectateNext(IConsole::IResult *pResult, void *pUserData) GotNewSpectatorID = true; break; } - + if(!GotNewSpectatorID) { for(int i = 0; i < pSelf->m_pClient->m_Snap.m_SpecInfo.m_SpectatorID; i++) @@ -79,7 +79,7 @@ void CSpectator::ConSpectatePrevious(IConsole::IResult *pResult, void *pUserData CSpectator *pSelf = (CSpectator *)pUserData; int NewSpectatorID; bool GotNewSpectatorID = false; - + if(pSelf->m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW) { for(int i = MAX_CLIENTS -1; i > -1; i--) @@ -103,7 +103,7 @@ void CSpectator::ConSpectatePrevious(IConsole::IResult *pResult, void *pUserData GotNewSpectatorID = true; break; } - + if(!GotNewSpectatorID) { for(int i = MAX_CLIENTS - 1; i > pSelf->m_pClient->m_Snap.m_SpecInfo.m_SpectatorID; i--) @@ -138,7 +138,7 @@ bool CSpectator::OnMouseMove(float x, float y) { if(!m_Active) return false; - + m_SelectorMouse += vec2(x,y); return true; } @@ -147,7 +147,7 @@ void CSpectator::OnRelease() { OnReset(); } - + void CSpectator::OnRender() { if(!m_Active) @@ -160,14 +160,14 @@ void CSpectator::OnRender() } return; } - + m_WasActive = true; m_SelectedSpectatorID = NO_SELECTION; // draw background float Width = 400*3.0f*Graphics()->ScreenAspect(); float Height = 400*3.0f; - + Graphics()->MapScreen(0, 0, Width, Height); Graphics()->BlendNormal(); @@ -185,7 +185,7 @@ void CSpectator::OnRender() float FontSize = 20.0f; float StartY = -190.0f; float LineHeight = 60.0f; - bool Selected = false; + bool Selected = false; if(m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW) { @@ -238,7 +238,7 @@ void CSpectator::OnRender() CTeeRenderInfo TeeInfo = m_pClient->m_aClients[i].m_RenderInfo; RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(Width/2.0f+x+20.0f, Height/2.0f+y+20.0f)); - + y += LineHeight; } TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); diff --git a/src/game/client/components/spectator.h b/src/game/client/components/spectator.h index 7dfbf8565..8e775cff9 100644 --- a/src/game/client/components/spectator.h +++ b/src/game/client/components/spectator.h @@ -15,7 +15,7 @@ class CSpectator : public CComponent bool m_Active; bool m_WasActive; - + int m_SelectedSpectatorID; vec2 m_SelectorMouse; @@ -23,10 +23,10 @@ class CSpectator : public CComponent static void ConSpectate(IConsole::IResult *pResult, void *pUserData); static void ConSpectateNext(IConsole::IResult *pResult, void *pUserData); static void ConSpectatePrevious(IConsole::IResult *pResult, void *pUserData); - + public: CSpectator(); - + virtual void OnConsoleInit(); virtual bool OnMouseMove(float x, float y); virtual void OnRender(); diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp index feeb96f74..675d67705 100644 --- a/src/game/client/components/voting.cpp +++ b/src/game/client/components/voting.cpp @@ -80,7 +80,7 @@ void CVoting::CallvoteOption(int OptionID, const char *pReason, bool ForceVote) Callvote("option", pOption->m_aDescription, pReason); break; } - + OptionID--; pOption = pOption->m_pNext; } @@ -98,7 +98,7 @@ void CVoting::RemovevoteOption(int OptionID) Client()->Rcon(aBuf); break; } - + OptionID--; pOption = pOption->m_pNext; } @@ -145,7 +145,7 @@ void CVoting::AddOption(const char *pDescription) m_pLast = pOption; if(!m_pFirst) m_pFirst = pOption; - + str_copy(pOption->m_aDescription, pDescription, sizeof(pOption->m_aDescription)); ++m_NumVoteOptions; } @@ -154,7 +154,7 @@ void CVoting::ClearOptions() { m_Heap.Reset(); - m_NumVoteOptions = 0; + m_NumVoteOptions = 0; m_pFirst = 0; m_pLast = 0; @@ -199,7 +199,7 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg) m_No = pMsg->m_No; m_Pass = pMsg->m_Pass; m_Total = pMsg->m_Total; - } + } else if(MsgType == NETMSGTYPE_SV_VOTECLEAROPTIONS) { ClearOptions(); @@ -238,7 +238,7 @@ void CVoting::OnMessage(int MsgType, void *pRawMsg) else if(MsgType == NETMSGTYPE_SV_VOTEOPTIONREMOVE) { CNetMsg_Sv_VoteOptionRemove *pMsg = (CNetMsg_Sv_VoteOptionRemove *)pRawMsg; - + for(CVoteOptionClient *pOption = m_pFirst; pOption; pOption = pOption->m_pNext) { if(str_comp(pOption->m_aDescription, pMsg->m_pDescription) == 0) @@ -277,13 +277,13 @@ void CVoting::OnRender() void CVoting::RenderBars(CUIRect Bars, bool Text) { RenderTools()->DrawUIRect(&Bars, vec4(0.8f,0.8f,0.8f,0.5f), CUI::CORNER_ALL, Bars.h/3); - + CUIRect Splitter = Bars; Splitter.x = Splitter.x+Splitter.w/2; Splitter.w = Splitter.h/2.0f; Splitter.x -= Splitter.w/2; RenderTools()->DrawUIRect(&Splitter, vec4(0.4f,0.4f,0.4f,0.5f), CUI::CORNER_ALL, Splitter.h/4); - + if(m_Total) { CUIRect PassArea = Bars; @@ -292,25 +292,25 @@ void CVoting::RenderBars(CUIRect Bars, bool Text) CUIRect YesArea = Bars; YesArea.w *= m_Yes/(float)m_Total; RenderTools()->DrawUIRect(&YesArea, vec4(0.2f,0.9f,0.2f,0.85f), CUI::CORNER_ALL, Bars.h/3); - + if(Text) { char Buf[256]; str_format(Buf, sizeof(Buf), "%d", m_Yes); UI()->DoLabel(&YesArea, Buf, Bars.h*0.75f, 0); } - + PassArea.x += YesArea.w; PassArea.w -= YesArea.w; } - + if(m_No) { CUIRect NoArea = Bars; NoArea.w *= m_No/(float)m_Total; NoArea.x = (Bars.x + Bars.w)-NoArea.w; RenderTools()->DrawUIRect(&NoArea, vec4(0.9f,0.2f,0.2f,0.85f), CUI::CORNER_ALL, Bars.h/3); - + if(Text) { char Buf[256]; @@ -327,7 +327,7 @@ void CVoting::RenderBars(CUIRect Bars, bool Text) str_format(Buf, sizeof(Buf), "%d", m_Pass); UI()->DoLabel(&PassArea, Buf, Bars.h*0.75f, 0); } - } + } } diff --git a/src/game/client/components/voting.h b/src/game/client/components/voting.h index 1f8fb8cfe..8a3d824f3 100644 --- a/src/game/client/components/voting.h +++ b/src/game/client/components/voting.h @@ -15,19 +15,19 @@ class CVoting : public CComponent static void ConCallvote(IConsole::IResult *pResult, void *pUserData); static void ConVote(IConsole::IResult *pResult, void *pUserData); - + int64 m_Closetime; char m_aDescription[VOTE_DESC_LENGTH]; char m_aReason[VOTE_REASON_LENGTH]; int m_Voted; int m_Yes, m_No, m_Pass, m_Total; - + void AddOption(const char *pDescription); void ClearOptions(); void Callvote(const char *pType, const char *pValue, const char *pReason); - + public: - int m_NumVoteOptions; + int m_NumVoteOptions; CVoteOptionClient *m_pFirst; CVoteOptionClient *m_pLast; @@ -39,17 +39,17 @@ public: virtual void OnConsoleInit(); virtual void OnMessage(int Msgtype, void *pRawMsg); virtual void OnRender(); - + void RenderBars(CUIRect Bars, bool Text); - + void CallvoteSpectate(int ClientID, const char *pReason, bool ForceVote = false); void CallvoteKick(int ClientID, const char *pReason, bool ForceVote = false); void CallvoteOption(int OptionID, const char *pReason, bool ForceVote = false); void RemovevoteOption(int OptionID); void AddvoteOption(const char *pDescription, const char *pCommand); - + void Vote(int v); // -1 = no, 1 = yes - + int SecondsLeft() { return (m_Closetime - time_get())/time_freq(); } bool IsVoting() { return m_Closetime != 0; } int TakenChoice() const { return m_Voted; } diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 1a35895ec..511cf8945 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -98,7 +98,7 @@ int CGameClient::GetCountryIndex(int Code) Index = g_GameClient.m_pCountryFlags->Find(-1); if(Index < 0) Index = 0; - } + } return Index; } @@ -117,7 +117,7 @@ void CGameClient::OnConsoleInit() m_pServerBrowser = Kernel()->RequestInterface(); m_pEditor = Kernel()->RequestInterface(); m_pFriends = Kernel()->RequestInterface(); - + // setup pointers m_pBinds = &::gs_Binds; m_pGameConsole = &::gs_GameConsole; @@ -137,7 +137,7 @@ void CGameClient::OnConsoleInit() m_pVoting = &::gs_Voting; m_pScoreboard = &::gs_Scoreboard; m_pItems = &::gs_Items; - + // make a list of all the systems, make sure to add them in the corrent render order m_All.Add(m_pSkins); m_All.Add(m_pCountryFlags); @@ -150,7 +150,7 @@ void CGameClient::OnConsoleInit() m_All.Add(m_pSounds); m_All.Add(m_pVoting); m_All.Add(m_pParticles); // doesn't render anything, just updates all the particles - + m_All.Add(&gs_MapLayersBackGround); // first to render m_All.Add(&m_pParticles->m_RenderTrail); m_All.Add(m_pItems); @@ -171,7 +171,7 @@ void CGameClient::OnConsoleInit() m_All.Add(m_pMotd); m_All.Add(m_pMenus); m_All.Add(m_pGameConsole); - + // build the input stack m_Input.Add(&m_pMenus->m_Binder); // this will take over all input when we want to bind a key m_Input.Add(&m_pBinds->m_SpecialBinds); @@ -183,11 +183,11 @@ void CGameClient::OnConsoleInit() m_Input.Add(&gs_Emoticon); m_Input.Add(m_pControls); m_Input.Add(m_pBinds); - + // add the some console commands Console()->Register("team", "i", CFGFLAG_CLIENT, ConTeam, this, "Switch team"); Console()->Register("kill", "", CFGFLAG_CLIENT, ConKill, this, "Kill yourself"); - + // register server dummy commands for tab completion Console()->Register("tune", "si", CFGFLAG_SERVER, 0, 0, "Tune variable to value"); Console()->Register("tune_reset", "", CFGFLAG_SERVER, 0, 0, "Reset tuning"); @@ -211,12 +211,12 @@ void CGameClient::OnConsoleInit() m_RenderTools.m_pUI = UI(); for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->m_pClient = this; - + // let all the other components register their console commands for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->OnConsoleInit(); - - + + // Console()->Chain("player_name", ConchainSpecialInfoupdate, this); Console()->Chain("player_clan", ConchainSpecialInfoupdate, this); @@ -225,7 +225,7 @@ void CGameClient::OnConsoleInit() Console()->Chain("player_color_body", ConchainSpecialInfoupdate, this); Console()->Chain("player_color_feet", ConchainSpecialInfoupdate, this); Console()->Chain("player_skin", ConchainSpecialInfoupdate, this); - + // m_SuppressEvents = false; } @@ -242,7 +242,7 @@ void CGameClient::OnInit() for(int i = 0; i < NUM_NETOBJTYPES; i++) Client()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i)); - // load default font + // load default font static CFont *pDefaultFont = 0; char aFilename[512]; IOHANDLE File = Storage()->OpenFile("fonts/DejaVuSans.ttf", IOFLAG_READ, IStorage::TYPE_ALL, aFilename, sizeof(aFilename)); @@ -254,7 +254,7 @@ void CGameClient::OnInit() } if(!pDefaultFont) Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", "failed to load font. filename='fonts/DejaVuSans.ttf'"); - + // init all components for(int i = m_All.m_Num-1; i >= 0; --i) m_All.m_paComponents[i]->OnInit(); @@ -268,12 +268,12 @@ void CGameClient::OnInit() for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->OnReset(); - + int64 End = time_get(); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "initialisation finished after %.2fms", ((End-Start)*1000)/(float)time_freq()); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "gameclient", aBuf); - + m_ServerMode = SERVERMODE_PURE; } @@ -290,12 +290,12 @@ void CGameClient::DispatchInput() break; } } - + // handle key presses for(int i = 0; i < Input()->NumEvents(); i++) { IInput::CEvent e = Input()->GetEvent(i); - + for(int h = 0; h < m_Input.m_Num; h++) { if(m_Input.m_paComponents[h]->OnInput(e)) @@ -305,9 +305,9 @@ void CGameClient::DispatchInput() } } } - + // clear all events for this frame - Input()->ClearEvents(); + Input()->ClearEvents(); } @@ -320,7 +320,7 @@ void CGameClient::OnConnected() { m_Layers.Init(Kernel()); m_Collision.Init(Layers()); - + RenderTools()->RenderTilemapGenerateSkip(Layers()); for(int i = 0; i < m_All.m_Num; i++) @@ -328,13 +328,13 @@ void CGameClient::OnConnected() m_All.m_paComponents[i]->OnMapLoad(); m_All.m_paComponents[i]->OnReset(); } - + CServerInfo CurrentServerInfo; Client()->GetServerInfo(&CurrentServerInfo); - + m_ServerMode = SERVERMODE_PURE; m_LastSendInfo = 0; - + // send the inital info SendInfo(true); } @@ -347,7 +347,7 @@ void CGameClient::OnReset() for(int i = 0; i < MAX_CLIENTS; i++) m_aClients[i].Reset(); - + for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->OnReset(); @@ -406,7 +406,7 @@ static void Evolve(CNetObj_Character *pCharacter, int Tick) mem_zero(&TempCore, sizeof(TempCore)); TempCore.Init(&TempWorld, g_GameClient.Collision()); TempCore.Read(pCharacter); - + while(pCharacter->m_Tick < Tick) { pCharacter->m_Tick++; @@ -422,30 +422,30 @@ static void Evolve(CNetObj_Character *pCharacter, int Tick) void CGameClient::OnRender() { /*Graphics()->Clear(1,0,0); - + menus->render_background(); return;*/ /* Graphics()->Clear(1,0,0); Graphics()->MapScreen(0,0,100,100); - + Graphics()->QuadsBegin(); Graphics()->SetColor(1,1,1,1); Graphics()->QuadsDraw(50, 50, 30, 30); Graphics()->QuadsEnd(); - + return;*/ - + // update the local character and spectate position UpdatePositions(); - + // dispatch all input to systems DispatchInput(); - + // render all systems for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->OnRender(); - + // clear new tick flags m_NewTick = false; m_NewPredictedTick = false; @@ -482,19 +482,19 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) if(MsgId == NETMSGTYPE_SV_EXTRAPROJECTILE) { int Num = pUnpacker->GetInt(); - + for(int k = 0; k < Num; k++) { CNetObj_Projectile Proj; for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) ((int *)&Proj)[i] = pUnpacker->GetInt(); - + if(pUnpacker->Error()) return; - + g_GameClient.m_pItems->AddExtraProjectile(&Proj); } - + return; } else if(MsgId == NETMSGTYPE_SV_TUNEPARAMS) @@ -508,14 +508,14 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) // check for unpacking errors if(pUnpacker->Error()) return; - + m_ServerMode = SERVERMODE_PURE; - + // apply new tuning m_Tuning = NewTuning; return; } - + void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgId, pUnpacker); if(!pRawMsg) { @@ -528,7 +528,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) // TODO: this should be done smarter for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->OnMessage(MsgId, pRawMsg); - + if(MsgId == NETMSGTYPE_SV_READYTOENTER) { Client()->EnterGame(); @@ -545,7 +545,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) { if(m_SuppressEvents) return; - + // don't enqueue pseudo-global sounds from demos (created by PlayAndRecord) CNetMsg_Sv_SoundGlobal *pMsg = (CNetMsg_Sv_SoundGlobal *)pRawMsg; if(pMsg->m_SoundID == SOUND_CTF_DROP || pMsg->m_SoundID == SOUND_CTF_RETURN || @@ -554,7 +554,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) g_GameClient.m_pSounds->Enqueue(CSounds::CHN_GLOBAL, pMsg->m_SoundID); else g_GameClient.m_pSounds->Play(CSounds::CHN_GLOBAL, pMsg->m_SoundID, 1.0f, vec2(0,0)); - } + } } void CGameClient::OnStateChange(int NewState, int OldState) @@ -562,7 +562,7 @@ void CGameClient::OnStateChange(int NewState, int OldState) // reset everything when not already connected (to keep gathered stuff) if(NewState < IClient::STATE_ONLINE) OnReset(); - + // then change the state for(int i = 0; i < m_All.m_Num; i++) m_All.m_paComponents[i]->OnStateChange(NewState, OldState); @@ -592,7 +592,7 @@ void CGameClient::ProcessEvents() { if(m_SuppressEvents) return; - + int SnapType = IClient::SNAP_CURRENT; int Num = Client()->SnapNumItems(SnapType); for(int Index = 0; Index < Num; Index++) @@ -636,7 +636,7 @@ void CGameClient::ProcessEvents() void CGameClient::OnNewSnapshot() { m_NewTick = true; - + // clear out the invalid pointers mem_zero(&g_GameClient.m_Snap, sizeof(g_GameClient.m_Snap)); m_Snap.m_LocalClientID = -1; @@ -660,7 +660,7 @@ void CGameClient::OnNewSnapshot() } } } - + ProcessEvents(); if(g_Config.m_DbgStress) @@ -672,7 +672,7 @@ void CGameClient::OnNewSnapshot() for(int i = 0; i < MsgLen; i++) aMessage[i] = 'a'+(rand()%('z'-'a')); aMessage[MsgLen] = 0; - + CNetMsg_Cl_Say Msg; Msg.m_Team = rand()&1; Msg.m_pMessage = aMessage; @@ -683,7 +683,7 @@ void CGameClient::OnNewSnapshot() // go trough all the items in the snapshot and gather the info we want { m_Snap.m_aTeamSize[TEAM_RED] = m_Snap.m_aTeamSize[TEAM_BLUE] = 0; - + int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT); for(int i = 0; i < Num; i++) { @@ -698,19 +698,19 @@ void CGameClient::OnNewSnapshot() IntsToStr(&pInfo->m_Clan0, 3, m_aClients[ClientID].m_aClan); m_aClients[ClientID].m_Country = GetCountryIndex(pInfo->m_Country); IntsToStr(&pInfo->m_Skin0, 6, m_aClients[ClientID].m_aSkinName); - + m_aClients[ClientID].m_UseCustomColor = pInfo->m_UseCustomColor; m_aClients[ClientID].m_ColorBody = pInfo->m_ColorBody; m_aClients[ClientID].m_ColorFeet = pInfo->m_ColorFeet; - + // prepare the info if(m_aClients[ClientID].m_aSkinName[0] == 'x' || m_aClients[ClientID].m_aSkinName[1] == '_') str_copy(m_aClients[ClientID].m_aSkinName, "default", 64); - + m_aClients[ClientID].m_SkinInfo.m_ColorBody = m_pSkins->GetColorV4(m_aClients[ClientID].m_ColorBody); m_aClients[ClientID].m_SkinInfo.m_ColorFeet = m_pSkins->GetColorV4(m_aClients[ClientID].m_ColorFeet); m_aClients[ClientID].m_SkinInfo.m_Size = 64; - + // find new skin m_aClients[ClientID].m_SkinID = g_GameClient.m_pSkins->Find(m_aClients[ClientID].m_aSkinName); if(m_aClients[ClientID].m_SkinID < 0) @@ -719,7 +719,7 @@ void CGameClient::OnNewSnapshot() if(m_aClients[ClientID].m_SkinID < 0) m_aClients[ClientID].m_SkinID = 0; } - + if(m_aClients[ClientID].m_UseCustomColor) m_aClients[ClientID].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[ClientID].m_SkinID)->m_ColorTexture; else @@ -730,33 +730,33 @@ void CGameClient::OnNewSnapshot() } m_aClients[ClientID].UpdateRenderInfo(); - + } else if(Item.m_Type == NETOBJTYPE_PLAYERINFO) { const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData; - + m_aClients[pInfo->m_ClientID].m_Team = pInfo->m_Team; m_aClients[pInfo->m_ClientID].m_Active = true; m_Snap.m_paPlayerInfos[pInfo->m_ClientID] = pInfo; m_Snap.m_NumPlayers++; - + if(pInfo->m_Local) { m_Snap.m_LocalClientID = Item.m_ID; m_Snap.m_pLocalInfo = pInfo; - + if(pInfo->m_Team == TEAM_SPECTATORS) { m_Snap.m_SpecInfo.m_Active = true; m_Snap.m_SpecInfo.m_SpectatorID = SPEC_FREEVIEW; } } - + // calculate team-balance if(pInfo->m_Team != TEAM_SPECTATORS) m_Snap.m_aTeamSize[pInfo->m_Team]++; - + } else if(Item.m_Type == NETOBJTYPE_CHARACTER) { @@ -799,7 +799,7 @@ void CGameClient::OnNewSnapshot() m_Snap.m_paFlags[Item.m_ID%2] = (const CNetObj_Flag *)pData; } } - + // setup local pointers if(m_Snap.m_LocalClientID >= 0) { @@ -856,7 +856,7 @@ void CGameClient::OnNewSnapshot() } } } - + CTuningParams StandardTuning; CServerInfo CurrentServerInfo; Client()->GetServerInfo(&CurrentServerInfo); @@ -881,7 +881,7 @@ void CGameClient::OnPredict() // we can't predict without our own id or own character if(m_Snap.m_LocalClientID == -1 || !m_Snap.m_aCharacters[m_Snap.m_LocalClientID].m_Active) return; - + // don't predict anything if we are paused if(m_Snap.m_pGameInfoObj && m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED) { @@ -901,19 +901,19 @@ void CGameClient::OnPredict() { if(!m_Snap.m_aCharacters[i].m_Active) continue; - + g_GameClient.m_aClients[i].m_Predicted.Init(&World, Collision()); World.m_apCharacters[i] = &g_GameClient.m_aClients[i].m_Predicted; g_GameClient.m_aClients[i].m_Predicted.Read(&m_Snap.m_aCharacters[i].m_Cur); } - + // predict for(int Tick = Client()->GameTick()+1; Tick <= Client()->PredGameTick(); Tick++) { // fetch the local if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalClientID]) m_PredictedPrevChar = *World.m_apCharacters[m_Snap.m_LocalClientID]; - + // first calculate where everyone should move for(int c = 0; c < MAX_CLIENTS; c++) { @@ -943,25 +943,25 @@ void CGameClient::OnPredict() World.m_apCharacters[c]->Move(); World.m_apCharacters[c]->Quantize(); } - + // check if we want to trigger effects if(Tick > m_LastNewPredictedTick) { m_LastNewPredictedTick = Tick; m_NewPredictedTick = true; - + if(m_Snap.m_LocalClientID != -1 && World.m_apCharacters[m_Snap.m_LocalClientID]) { vec2 Pos = World.m_apCharacters[m_Snap.m_LocalClientID]->m_Pos; int Events = World.m_apCharacters[m_Snap.m_LocalClientID]->m_TriggeredEvents; if(Events&COREEVENT_GROUND_JUMP) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, Pos); - + /*if(events&COREEVENT_AIR_JUMP) { GameClient.effects->air_jump(pos); GameClient.sounds->play_and_record(SOUNDS::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, pos); }*/ - + //if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos); //if(events&COREEVENT_HOOK_ATTACH_PLAYER) snd_play_random(CHN_WORLD, SOUND_HOOK_ATTACH_PLAYER, 1.0f, pos); if(Events&COREEVENT_HOOK_ATTACH_GROUND) g_GameClient.m_pSounds->PlayAndRecord(CSounds::CHN_WORLD, SOUND_HOOK_ATTACH_GROUND, 1.0f, Pos); @@ -969,11 +969,11 @@ void CGameClient::OnPredict() //if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos); } } - + if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalClientID]) m_PredictedChar = *World.m_apCharacters[m_Snap.m_LocalClientID]; } - + if(g_Config.m_Debug && g_Config.m_ClPredict && m_PredictedTick == Client()->PredGameTick()) { CNetObj_CharacterCore Before = {0}, Now = {0}, BeforePrev = {0}, NowPrev = {0}; @@ -989,12 +989,12 @@ void CGameClient::OnPredict() if(((int *)&Before)[i] != ((int *)&Now)[i]) { char aBuf[256]; - str_format(aBuf, sizeof(aBuf), " %d %d %d (%d %d)", i, ((int *)&Before)[i], ((int *)&Now)[i], ((int *)&BeforePrev)[i], ((int *)&NowPrev)[i]); + str_format(aBuf, sizeof(aBuf), " %d %d %d (%d %d)", i, ((int *)&Before)[i], ((int *)&Now)[i], ((int *)&BeforePrev)[i], ((int *)&NowPrev)[i]); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf); } } } - + m_PredictedTick = Client()->PredGameTick(); } @@ -1022,7 +1022,7 @@ void CGameClient::CClientData::UpdateRenderInfo() m_RenderInfo.m_ColorBody = g_GameClient.m_pSkins->GetColorV4(12895054); m_RenderInfo.m_ColorFeet = g_GameClient.m_pSkins->GetColorV4(12895054); } - } + } } void CGameClient::CClientData::Reset() @@ -1047,7 +1047,7 @@ void CGameClient::SendSwitchTeam(int Team) { CNetMsg_Cl_SetTeam Msg; Msg.m_Team = Team; - Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } void CGameClient::SendInfo(bool Start) @@ -1062,7 +1062,7 @@ void CGameClient::SendInfo(bool Start) Msg.m_UseCustomColor = g_Config.m_PlayerUseCustomColor; Msg.m_ColorBody = g_Config.m_PlayerColorBody; Msg.m_ColorFeet = g_Config.m_PlayerColorFeet; - Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } else { @@ -1085,7 +1085,7 @@ void CGameClient::SendInfo(bool Start) void CGameClient::SendKill(int ClientID) { CNetMsg_Cl_Kill Msg; - Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); + Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); } void CGameClient::ConTeam(IConsole::IResult *pResult, void *pUserData) diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 7aa02acea..a89f4e86c 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -19,18 +19,18 @@ class CGameClient : public IGameClient { MAX_COMPONENTS = 64, }; - + CStack(); void Add(class CComponent *pComponent); - + class CComponent *m_paComponents[MAX_COMPONENTS]; int m_Num; }; - + CStack m_All; CStack m_Input; CNetObjHandler m_NetObjHandler; - + class IEngine *m_pEngine; class IInput *m_pInput; class IGraphics *m_pGraphics; @@ -44,11 +44,11 @@ class CGameClient : public IGameClient class IServerBrowser *m_pServerBrowser; class IEditor *m_pEditor; class IFriends *m_pFriends; - + CLayers m_Layers; class CCollision m_Collision; CUI m_UI; - + void DispatchInput(); void ProcessEvents(); void UpdatePositions(); @@ -60,9 +60,9 @@ class CGameClient : public IGameClient static void ConTeam(IConsole::IResult *pResult, void *pUserData); static void ConKill(IConsole::IResult *pResult, void *pUserData); - + static void ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); - + public: IKernel *Kernel() { return IInterface::Kernel(); } IEngine *Engine() const { return m_pEngine; } @@ -82,7 +82,7 @@ public: class CCollision *Collision() { return &m_Collision; }; class IEditor *Editor() { return m_pEditor; } class IFriends *Friends() { return m_pFriends; } - + int NetobjNumCorrections() { return m_NetObjHandler.NumObjCorrections(); } const char *NetobjCorrectedOn() { return m_NetObjHandler.CorrectedObjOn(); } @@ -92,7 +92,7 @@ public: // TODO: move this CTuningParams m_Tuning; - + enum { SERVERMODE_PURE=0, @@ -124,11 +124,11 @@ public: const CNetObj_PlayerInfo *m_paPlayerInfos[MAX_CLIENTS]; const CNetObj_PlayerInfo *m_paInfoByScore[MAX_CLIENTS]; - + int m_LocalClientID; int m_NumPlayers; int m_aTeamSize[2]; - + // spectate data struct CSpectateInfo { @@ -137,32 +137,32 @@ public: bool m_UsePosition; vec2 m_Position; } m_SpecInfo; - + // struct CCharacterInfo { bool m_Active; - + // snapshots CNetObj_Character m_Prev; CNetObj_Character m_Cur; - + // interpolated position vec2 m_Position; }; - + CCharacterInfo m_aCharacters[MAX_CLIENTS]; }; CSnapState m_Snap; - + // client data struct CClientData { int m_UseCustomColor; int m_ColorBody; int m_ColorFeet; - + char m_aName[MAX_NAME_LENGTH]; char m_aClan[MAX_CLAN_LENGTH]; int m_Country; @@ -173,23 +173,23 @@ public: int m_Emoticon; int m_EmoticonStart; CCharacterCore m_Predicted; - + CTeeRenderInfo m_SkinInfo; // this is what the server reports CTeeRenderInfo m_RenderInfo; // this is what we use - + float m_Angle; bool m_Active; bool m_ChatIgnore; bool m_Friend; - + void UpdateRenderInfo(); void Reset(); }; CClientData m_aClients[MAX_CLIENTS]; - + CRenderTools m_RenderTools; - + void OnReset(); // hooks @@ -209,19 +209,19 @@ public: virtual void OnRconLine(const char *pLine); virtual void OnGameOver(); virtual void OnStartGame(); - + virtual const char *GetItemName(int Type); virtual int GetCountryIndex(int Code); virtual const char *Version(); virtual const char *NetVersion(); - - + + // actions // TODO: move these void SendSwitchTeam(int Team); void SendInfo(bool Start); void SendKill(int ClientID); - + // pointers to all systems class CGameConsole *m_pGameConsole; class CBinds *m_pBinds; @@ -246,12 +246,12 @@ public: inline float HueToRgb(float v1, float v2, float h) { - if(h < 0.0f) h += 1; - if(h > 1.0f) h -= 1; - if((6.0f * h) < 1.0f) return v1 + (v2 - v1) * 6.0f * h; - if((2.0f * h) < 1.0f) return v2; - if((3.0f * h) < 2.0f) return v1 + (v2 - v1) * ((2.0f/3.0f) - h) * 6.0f; - return v1; + if(h < 0.0f) h += 1; + if(h > 1.0f) h -= 1; + if((6.0f * h) < 1.0f) return v1 + (v2 - v1) * 6.0f * h; + if((2.0f * h) < 1.0f) return v2; + if((3.0f * h) < 2.0f) return v1 + (v2 - v1) * ((2.0f/3.0f) - h) * 6.0f; + return v1; } inline vec3 HslToRgb(vec3 HSL) diff --git a/src/game/client/lineinput.cpp b/src/game/client/lineinput.cpp index b5d35ef8d..29b891c21 100644 --- a/src/game/client/lineinput.cpp +++ b/src/game/client/lineinput.cpp @@ -27,19 +27,19 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p int CursorPos = *pCursorPosPtr; int Len = *pStrLenPtr; bool Changes = false; - + if(CursorPos > Len) CursorPos = Len; - + int Code = e.m_Unicode; int k = e.m_Key; - + // 127 is produced on Mac OS X and corresponds to the delete key if (!(Code >= 0 && Code < 32) && Code != 127) { char Tmp[8]; int CharSize = str_utf8_encode(Tmp, Code); - + if (Len < StrMaxSize - CharSize && CursorPos < StrMaxSize - CharSize) { mem_move(pStr + CursorPos + CharSize, pStr + CursorPos, Len - CursorPos + CharSize); @@ -50,7 +50,7 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p Changes = true; } } - + if(e.m_Flags&IInput::FLAG_PRESS) { if (k == KEY_BACKSPACE && CursorPos > 0) @@ -79,7 +79,7 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p else if (k == KEY_END) CursorPos = Len; } - + *pCursorPosPtr = CursorPos; *pStrLenPtr = Len; diff --git a/src/game/client/render.cpp b/src/game/client/render.cpp index 2a15326d7..5dbc38428 100644 --- a/src/game/client/render.cpp +++ b/src/game/client/render.cpp @@ -30,7 +30,7 @@ static void layershot_end() { if(!config.cl_layershot) return; - + char buf[256]; str_format(buf, sizeof(buf), "screenshots/layers_%04d.png", config.cl_layershot); gfx_screenshot_direct(buf); @@ -49,7 +49,7 @@ void CRenderTools::SelectSprite(SPRITE *pSpr, int Flags, int sx, int sy) float f = sqrtf(h*h + w*w); gs_SpriteWScale = w/f; gs_SpriteHScale = h/f; - + float x1 = x/(float)cx; float x2 = (x+w)/(float)cx; float y1 = y/(float)cy; @@ -69,7 +69,7 @@ void CRenderTools::SelectSprite(SPRITE *pSpr, int Flags, int sx, int sy) x1 = x2; x2 = Temp; } - + Graphics()->QuadsSetSubset(x1, y1, x2, y2); } @@ -140,7 +140,7 @@ void CRenderTools::DrawRoundRectExt(float x, float y, float w, float h, float r, ArrayQ[NumItems++] = IGraphics::CQuadItem(x+r, y+h-r, w-r*2, r); // bottom ArrayQ[NumItems++] = IGraphics::CQuadItem(x, y+r, r, h-r*2); // left ArrayQ[NumItems++] = IGraphics::CQuadItem(x+w-r, y+r, r, h-r*2); // right - + if(!(Corners&1)) ArrayQ[NumItems++] = IGraphics::CQuadItem(x, y, r, r); // TL if(!(Corners&2)) ArrayQ[NumItems++] = IGraphics::CQuadItem(x+w, y, -r, r); // TR if(!(Corners&4)) ArrayQ[NumItems++] = IGraphics::CQuadItem(x, y+h, r, -r); // BL @@ -157,7 +157,7 @@ void CRenderTools::DrawRoundRect(float x, float y, float w, float h, float r) void CRenderTools::DrawUIRect(const CUIRect *r, vec4 Color, int Corners, float Rounding) { Graphics()->TextureSet(-1); - + // TODO: FIX US Graphics()->QuadsBegin(); Graphics()->SetColor(Color.r, Color.g, Color.b, Color.a); @@ -172,7 +172,7 @@ void CRenderTools::RenderTee(CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote //Graphics()->TextureSet(data->images[IMAGE_CHAR_DEFAULT].id); Graphics()->TextureSet(pInfo->m_Texture); - + // TODO: FIX ME Graphics()->QuadsBegin(); //Graphics()->QuadsDraw(pos.x, pos.y-128, 128, 128); @@ -219,7 +219,7 @@ void CRenderTools::RenderTee(CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote SelectSprite(SPRITE_TEE_EYE_NORMAL, 0, 0, 0); break; } - + float EyeScale = BaseSize*0.40f; float h = Emote == EMOTE_BLINK ? BaseSize*0.15f : EyeScale; float EyeSeparation = (0.075f - 0.010f*absolute(Direction.x))*BaseSize; @@ -238,10 +238,10 @@ void CRenderTools::RenderTee(CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote float h = BaseSize/2; Graphics()->QuadsSetRotation(pFoot->m_Angle*pi*2); - + bool Indicate = !pInfo->m_GotAirJump && g_Config.m_ClAirjumpindicator; float cs = 1.0f; // color scale - + if(OutLine) SelectSprite(SPRITE_TEE_FOOT_OUTLINE, 0, 0, 0); else @@ -250,7 +250,7 @@ void CRenderTools::RenderTee(CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote if(Indicate) cs = 0.5f; } - + Graphics()->SetColor(pInfo->m_ColorFeet.r*cs, pInfo->m_ColorFeet.g*cs, pInfo->m_ColorFeet.b*cs, pInfo->m_ColorFeet.a); IGraphics::CQuadItem QuadItem(Position.x+pFoot->m_X*AnimScale, Position.y+pFoot->m_Y*AnimScale, w, h); Graphics()->QuadsDraw(&QuadItem, 1); @@ -258,8 +258,8 @@ void CRenderTools::RenderTee(CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote } Graphics()->QuadsEnd(); - - + + } static void CalcScreenParams(float Amount, float WMax, float HMax, float Aspect, float *w, float *h) @@ -267,14 +267,14 @@ static void CalcScreenParams(float Amount, float WMax, float HMax, float Aspect, float f = sqrtf(Amount) / sqrtf(Aspect); *w = f*Aspect; *h = f; - + // limit the view if(*w > WMax) { *w = WMax; *h = *w/Aspect; } - + if(*h > HMax) { *h = HMax; @@ -299,11 +299,11 @@ void CRenderTools::MapscreenToWorld(float CenterX, float CenterY, float Parallax void CRenderTools::RenderTilemapGenerateSkip(class CLayers *pLayers) { - + for(int g = 0; g < pLayers->NumGroups(); g++) { CMapItemGroup *pGroup = pLayers->GetGroup(g); - + for(int l = 0; l < pGroup->m_NumLayers; l++) { CMapItemLayer *pLayer = pLayers->GetLayer(pGroup->m_StartLayer+l); @@ -322,7 +322,7 @@ void CRenderTools::RenderTilemapGenerateSkip(class CLayers *pLayers) if(pTiles[y*pTmap->m_Width+x+sx].m_Index) break; } - + pTiles[y*pTmap->m_Width+x].m_Skip = sx-1; } } diff --git a/src/game/client/render.h b/src/game/client/render.h index fe8d2dd67..10705e56e 100644 --- a/src/game/client/render.h +++ b/src/game/client/render.h @@ -19,7 +19,7 @@ public: m_Size = 1.0f; m_GotAirJump = 1; }; - + int m_Texture; vec4 m_ColorBody; vec4 m_ColorFeet; @@ -32,10 +32,10 @@ enum { SPRITE_FLAG_FLIP_Y=1, SPRITE_FLAG_FLIP_X=2, - + LAYERRENDERFLAG_OPAQUE=1, LAYERRENDERFLAG_TRANSPARENT=2, - + TILERENDERFLAG_EXTEND=4, }; @@ -45,7 +45,7 @@ class CRenderTools public: class IGraphics *m_pGraphics; class CUI *m_pUI; - + class IGraphics *Graphics() const { return m_pGraphics; } class CUI *UI() const { return m_pUI; } @@ -59,7 +59,7 @@ public: // rects void DrawRoundRect(float x, float y, float w, float h, float r); void DrawRoundRectExt(float x, float y, float w, float h, float r, int Corners); - + void DrawUIRect(const CUIRect *pRect, vec4 Color, int Corners, float Rounding); // larger rendering methods @@ -75,8 +75,8 @@ public: // helpers void MapscreenToWorld(float CenterX, float CenterY, float ParallaxX, float ParallaxY, - float OffsetX, float OffsetY, float Aspect, float Zoom, float *pPoints); - + float OffsetX, float OffsetY, float Aspect, float Zoom, float *pPoints); + }; #endif diff --git a/src/game/client/render_map.cpp b/src/game/client/render_map.cpp index bffc4c2d7..33cc1c7d6 100644 --- a/src/game/client/render_map.cpp +++ b/src/game/client/render_map.cpp @@ -16,7 +16,7 @@ void CRenderTools::RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Cha pResult[3] = 0; return; } - + if(NumPoints == 1) { pResult[0] = fx2f(pPoints[0].m_aValues[0]); @@ -25,7 +25,7 @@ void CRenderTools::RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Cha pResult[3] = fx2f(pPoints[0].m_aValues[3]); return; } - + Time = fmod(Time, pPoints[NumPoints-1].m_Time/1000.0f)*1000.0f; for(int i = 0; i < NumPoints-1; i++) { @@ -50,18 +50,18 @@ void CRenderTools::RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Cha { // linear } - + for(int c = 0; c < Channels; c++) { float v0 = fx2f(pPoints[i].m_aValues[c]); float v1 = fx2f(pPoints[i+1].m_aValues[c]); pResult[c] = v0 + (v1-v0) * a; } - + return; } } - + pResult[0] = fx2f(pPoints[NumPoints-1].m_aValues[0]); pResult[1] = fx2f(pPoints[NumPoints-1].m_aValues[1]); pResult[2] = fx2f(pPoints[NumPoints-1].m_aValues[2]); @@ -85,7 +85,7 @@ void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, voi for(int i = 0; i < NumQuads; i++) { CQuad *q = &pQuads[i]; - + float r=1, g=1, b=1, a=1; if(q->m_ColorEnv >= 0) @@ -96,17 +96,17 @@ void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, voi g = aChannels[1]; b = aChannels[2]; a = aChannels[3]; - } - + } + bool Opaque = false; 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)) continue; - + Graphics()->QuadsSetSubsetFree( fx2f(q->m_aTexcoords[0].x), fx2f(q->m_aTexcoords[0].y), fx2f(q->m_aTexcoords[1].x), fx2f(q->m_aTexcoords[1].y), @@ -117,7 +117,7 @@ void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, voi float OffsetX = 0; float OffsetY = 0; float Rot = 0; - + // TODO: fix this if(q->m_PosEnv >= 0) { @@ -127,7 +127,7 @@ void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, voi OffsetY = aChannels[1]; Rot = aChannels[2]/360.0f*pi*2; } - + IGraphics::CColorVertex Array[4] = { IGraphics::CColorVertex(0, q->m_aColors[0].r*Conv*r, q->m_aColors[0].g*Conv*g, q->m_aColors[0].b*Conv*b, q->m_aColors[0].a*Conv*a), IGraphics::CColorVertex(1, q->m_aColors[1].r*Conv*r, q->m_aColors[1].g*Conv*g, q->m_aColors[1].b*Conv*b, q->m_aColors[1].a*Conv*a), @@ -136,7 +136,7 @@ void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, voi Graphics()->SetColorVertex(Array, 4); CPoint *pPoints = q->m_aPoints; - + if(Rot != 0) { static CPoint aRotated[4]; @@ -145,13 +145,13 @@ void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, voi aRotated[2] = q->m_aPoints[2]; aRotated[3] = q->m_aPoints[3]; pPoints = aRotated; - + Rotate(&q->m_aPoints[4], &aRotated[0], Rot); Rotate(&q->m_aPoints[4], &aRotated[1], Rot); Rotate(&q->m_aPoints[4], &aRotated[2], Rot); Rotate(&q->m_aPoints[4], &aRotated[3], Rot); } - + IGraphics::CFreeformItem Freeform( fx2f(pPoints[0].x)+OffsetX, fx2f(pPoints[0].y)+OffsetY, fx2f(pPoints[1].x)+OffsetX, fx2f(pPoints[1].y)+OffsetY, @@ -159,7 +159,7 @@ void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, voi fx2f(pPoints[3].x)+OffsetX, fx2f(pPoints[3].y)+OffsetY); Graphics()->QuadsDrawFreeform(&Freeform, 1); } - Graphics()->QuadsEnd(); + Graphics()->QuadsEnd(); } void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4 Color, int RenderFlags) @@ -169,19 +169,19 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4 Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); //Graphics()->MapScreen(screen_x0-50, screen_y0-50, screen_x1+50, screen_y1+50); - // calculate the final pixelsize for the tiles + // calculate the final pixelsize for the tiles float TilePixelSize = 1024/32.0f; float FinalTileSize = Scale/(ScreenX1-ScreenX0) * Graphics()->ScreenWidth(); float FinalTilesetScale = FinalTileSize/TilePixelSize; - + Graphics()->QuadsBegin(); Graphics()->SetColor(Color.r, Color.g, Color.b, Color.a); - + int StartY = (int)(ScreenY0/Scale)-1; int StartX = (int)(ScreenX0/Scale)-1; int EndY = (int)(ScreenY1/Scale)+1; int EndX = (int)(ScreenX1/Scale)+1; - + // adjust the texture shift according to mipmap level float TexSize = 1024.0f; float Frac = (1.25f/TexSize) * (1/FinalTilesetScale); @@ -192,7 +192,7 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4 { int mx = x; int my = y; - + if(RenderFlags&TILERENDERFLAG_EXTEND) { if(mx<0) @@ -215,14 +215,14 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4 if(my>=h) continue; // my = h-1; } - + int c = mx + my*w; - + unsigned char Index = pTiles[c].m_Index; if(Index) { unsigned char Flags = pTiles[c].m_Flags; - + bool Render = false; if(Flags&TILEFLAG_OPAQUE) { @@ -234,17 +234,17 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4 if(RenderFlags&LAYERRENDERFLAG_TRANSPARENT) Render = true; } - + if(Render) { - + int tx = Index%16; int ty = Index/16; int Px0 = tx*(1024/16); int Py0 = ty*(1024/16); int Px1 = Px0+(1024/16)-1; int Py1 = Py0+(1024/16)-1; - + float x0 = Nudge + Px0/TexSize+Frac; float y0 = Nudge + Py0/TexSize+Frac; float x1 = Nudge + Px1/TexSize-Frac; @@ -253,7 +253,7 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4 float y2 = Nudge + Py1/TexSize-Frac; float x3 = Nudge + Px0/TexSize+Frac; float y3 = Nudge + Py1/TexSize-Frac; - + if(Flags&TILEFLAG_VFLIP) { x0 = x2; @@ -269,14 +269,14 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4 y3 = y1; y1 = y0; } - + if(Flags&TILEFLAG_ROTATE) { float Tmp = x0; x0 = x3; x3 = x2; x2 = x1; - x1 = Tmp; + x1 = Tmp; Tmp = y0; y0 = y3; y3 = y2; @@ -291,7 +291,7 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4 } x += pTiles[c].m_Skip; } - + Graphics()->QuadsEnd(); Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); } diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 23643e2a4..2161bc771 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -8,7 +8,7 @@ #include "ui.h" /******************************************************** - UI + UI *********************************************************/ CUI::CUI() @@ -17,14 +17,14 @@ CUI::CUI() m_pActiveItem = 0; m_pLastActiveItem = 0; m_pBecommingHotItem = 0; - + m_MouseX = 0; m_MouseY = 0; m_MouseWorldX = 0; m_MouseWorldY = 0; m_MouseButtons = 0; - m_LastMouseButtons = 0; - + m_LastMouseButtons = 0; + m_Screen.x = 0; m_Screen.y = 0; m_Screen.w = 848.0f; @@ -33,53 +33,53 @@ CUI::CUI() int CUI::Update(float Mx, float My, float Mwx, float Mwy, int Buttons) { - m_MouseX = Mx; - m_MouseY = My; - m_MouseWorldX = Mwx; - m_MouseWorldY = Mwy; - m_LastMouseButtons = m_MouseButtons; - m_MouseButtons = Buttons; - m_pHotItem = m_pBecommingHotItem; - if(m_pActiveItem) - m_pHotItem = m_pActiveItem; - m_pBecommingHotItem = 0; - return 0; + m_MouseX = Mx; + m_MouseY = My; + m_MouseWorldX = Mwx; + m_MouseWorldY = Mwy; + m_LastMouseButtons = m_MouseButtons; + m_MouseButtons = Buttons; + m_pHotItem = m_pBecommingHotItem; + if(m_pActiveItem) + m_pHotItem = m_pActiveItem; + m_pBecommingHotItem = 0; + return 0; } int CUI::MouseInside(const CUIRect *r) { - if(m_MouseX >= r->x && m_MouseX <= r->x+r->w && m_MouseY >= r->y && m_MouseY <= r->y+r->h) - return 1; - return 0; + if(m_MouseX >= r->x && m_MouseX <= r->x+r->w && m_MouseY >= r->y && m_MouseY <= r->y+r->h) + return 1; + return 0; } CUIRect *CUI::Screen() { - float Aspect = Graphics()->ScreenAspect(); - float w, h; + float Aspect = Graphics()->ScreenAspect(); + float w, h; - h = 600; - w = Aspect*h; + h = 600; + w = Aspect*h; - m_Screen.w = w; - m_Screen.h = h; + m_Screen.w = w; + m_Screen.h = h; - return &m_Screen; + return &m_Screen; } void CUI::SetScale(float s) { - g_Config.m_UiScale = (int)(s*100.0f); + g_Config.m_UiScale = (int)(s*100.0f); } float CUI::Scale() { - return g_Config.m_UiScale/100.0f; + return g_Config.m_UiScale/100.0f; } float CUIRect::Scale() const { - return g_Config.m_UiScale/100.0f; + return g_Config.m_UiScale/100.0f; } void CUI::ClipEnable(const CUIRect *r) @@ -97,175 +97,175 @@ void CUI::ClipDisable() void CUIRect::HSplitMid(CUIRect *pTop, CUIRect *pBottom) const { CUIRect r = *this; - float Cut = r.h/2; + float Cut = r.h/2; - if(pTop) - { - pTop->x = r.x; - pTop->y = r.y; - pTop->w = r.w; - pTop->h = Cut; - } + if(pTop) + { + pTop->x = r.x; + pTop->y = r.y; + pTop->w = r.w; + pTop->h = Cut; + } - if(pBottom) - { - pBottom->x = r.x; - pBottom->y = r.y + Cut; - pBottom->w = r.w; - pBottom->h = r.h - Cut; - } + if(pBottom) + { + pBottom->x = r.x; + pBottom->y = r.y + Cut; + pBottom->w = r.w; + pBottom->h = r.h - Cut; + } } void CUIRect::HSplitTop(float Cut, CUIRect *pTop, CUIRect *pBottom) const { - CUIRect r = *this; - Cut *= Scale(); + CUIRect r = *this; + Cut *= Scale(); - if (pTop) - { - pTop->x = r.x; - pTop->y = r.y; - pTop->w = r.w; - pTop->h = Cut; - } + if (pTop) + { + pTop->x = r.x; + pTop->y = r.y; + pTop->w = r.w; + pTop->h = Cut; + } - if (pBottom) - { - pBottom->x = r.x; - pBottom->y = r.y + Cut; - pBottom->w = r.w; - pBottom->h = r.h - Cut; - } + if (pBottom) + { + pBottom->x = r.x; + pBottom->y = r.y + Cut; + pBottom->w = r.w; + pBottom->h = r.h - Cut; + } } void CUIRect::HSplitBottom(float Cut, CUIRect *pTop, CUIRect *pBottom) const { - CUIRect r = *this; - Cut *= Scale(); + CUIRect r = *this; + Cut *= Scale(); - if (pTop) - { - pTop->x = r.x; - pTop->y = r.y; - pTop->w = r.w; - pTop->h = r.h - Cut; - } + if (pTop) + { + pTop->x = r.x; + pTop->y = r.y; + pTop->w = r.w; + pTop->h = r.h - Cut; + } - if (pBottom) - { - pBottom->x = r.x; - pBottom->y = r.y + r.h - Cut; - pBottom->w = r.w; - pBottom->h = Cut; - } + if (pBottom) + { + pBottom->x = r.x; + pBottom->y = r.y + r.h - Cut; + pBottom->w = r.w; + pBottom->h = Cut; + } } void CUIRect::VSplitMid(CUIRect *pLeft, CUIRect *pRight) const { - CUIRect r = *this; - float Cut = r.w/2; -// Cut *= Scale(); + CUIRect r = *this; + float Cut = r.w/2; +// Cut *= Scale(); - if (pLeft) - { - pLeft->x = r.x; - pLeft->y = r.y; - pLeft->w = Cut; - pLeft->h = r.h; - } + if (pLeft) + { + pLeft->x = r.x; + pLeft->y = r.y; + pLeft->w = Cut; + pLeft->h = r.h; + } - if (pRight) - { - pRight->x = r.x + Cut; - pRight->y = r.y; - pRight->w = r.w - Cut; - pRight->h = r.h; - } + if (pRight) + { + pRight->x = r.x + Cut; + pRight->y = r.y; + pRight->w = r.w - Cut; + pRight->h = r.h; + } } void CUIRect::VSplitLeft(float Cut, CUIRect *pLeft, CUIRect *pRight) const { - CUIRect r = *this; - Cut *= Scale(); + CUIRect r = *this; + Cut *= Scale(); - if (pLeft) - { - pLeft->x = r.x; - pLeft->y = r.y; - pLeft->w = Cut; - pLeft->h = r.h; - } + if (pLeft) + { + pLeft->x = r.x; + pLeft->y = r.y; + pLeft->w = Cut; + pLeft->h = r.h; + } - if (pRight) - { - pRight->x = r.x + Cut; - pRight->y = r.y; - pRight->w = r.w - Cut; - pRight->h = r.h; - } + if (pRight) + { + pRight->x = r.x + Cut; + pRight->y = r.y; + pRight->w = r.w - Cut; + pRight->h = r.h; + } } void CUIRect::VSplitRight(float Cut, CUIRect *pLeft, CUIRect *pRight) const { - CUIRect r = *this; - Cut *= Scale(); + CUIRect r = *this; + Cut *= Scale(); - if (pLeft) - { - pLeft->x = r.x; - pLeft->y = r.y; - pLeft->w = r.w - Cut; - pLeft->h = r.h; - } + if (pLeft) + { + pLeft->x = r.x; + pLeft->y = r.y; + pLeft->w = r.w - Cut; + pLeft->h = r.h; + } - if (pRight) - { - pRight->x = r.x + r.w - Cut; - pRight->y = r.y; - pRight->w = Cut; - pRight->h = r.h; - } + if (pRight) + { + pRight->x = r.x + r.w - Cut; + pRight->y = r.y; + pRight->w = Cut; + pRight->h = r.h; + } } void CUIRect::Margin(float Cut, CUIRect *pOtherRect) const { - CUIRect r = *this; + CUIRect r = *this; Cut *= Scale(); - pOtherRect->x = r.x + Cut; - pOtherRect->y = r.y + Cut; - pOtherRect->w = r.w - 2*Cut; - pOtherRect->h = r.h - 2*Cut; + pOtherRect->x = r.x + Cut; + pOtherRect->y = r.y + Cut; + pOtherRect->w = r.w - 2*Cut; + pOtherRect->h = r.h - 2*Cut; } void CUIRect::VMargin(float Cut, CUIRect *pOtherRect) const { - CUIRect r = *this; + CUIRect r = *this; Cut *= Scale(); - pOtherRect->x = r.x + Cut; - pOtherRect->y = r.y; - pOtherRect->w = r.w - 2*Cut; - pOtherRect->h = r.h; + pOtherRect->x = r.x + Cut; + pOtherRect->y = r.y; + pOtherRect->w = r.w - 2*Cut; + pOtherRect->h = r.h; } void CUIRect::HMargin(float Cut, CUIRect *pOtherRect) const { - CUIRect r = *this; + CUIRect r = *this; Cut *= Scale(); - pOtherRect->x = r.x; - pOtherRect->y = r.y + Cut; - pOtherRect->w = r.w; - pOtherRect->h = r.h - 2*Cut; + pOtherRect->x = r.x; + pOtherRect->y = r.y + Cut; + pOtherRect->w = r.w; + pOtherRect->h = r.h - 2*Cut; } int CUI::DoButtonLogic(const void *pID, const char *pText, int Checked, const CUIRect *pRect) { - // logic - int ReturnValue = 0; - int Inside = MouseInside(pRect); + // logic + int ReturnValue = 0; + int Inside = MouseInside(pRect); static int ButtonUsed = 0; if(ActiveItem() == pID) @@ -284,25 +284,25 @@ int CUI::DoButtonLogic(const void *pID, const char *pText, int Checked, const CU SetActiveItem(pID); ButtonUsed = 0; } - + if(MouseButton(1)) { SetActiveItem(pID); ButtonUsed = 1; } } - + if(Inside) SetHotItem(pID); - return ReturnValue; + return ReturnValue; } /* int CUI::DoButton(const void *id, const char *text, int checked, const CUIRect *r, ui_draw_button_func draw_func, const void *extra) { - // logic - int ret = 0; - int inside = ui_MouseInside(r); + // logic + int ret = 0; + int inside = ui_MouseInside(r); static int button_used = 0; if(ui_ActiveItem() == id) @@ -321,41 +321,41 @@ int CUI::DoButton(const void *id, const char *text, int checked, const CUIRect * ui_SetActiveItem(id); button_used = 0; } - + if(ui_MouseButton(1)) { ui_SetActiveItem(id); button_used = 1; } } - + if(inside) ui_SetHotItem(id); if(draw_func) - draw_func(id, text, checked, r, extra); - return ret; + draw_func(id, text, checked, r, extra); + return ret; }*/ void CUI::DoLabel(const CUIRect *r, const char *pText, float Size, int Align, int MaxWidth) { // TODO: FIX ME!!!! - //Graphics()->BlendNormal(); - if(Align == 0) - { - float tw = TextRender()->TextWidth(0, Size, pText, MaxWidth); - TextRender()->Text(0, r->x + r->w/2-tw/2, r->y - Size/10, Size, pText, MaxWidth); + //Graphics()->BlendNormal(); + if(Align == 0) + { + float tw = TextRender()->TextWidth(0, Size, pText, MaxWidth); + TextRender()->Text(0, r->x + r->w/2-tw/2, r->y - Size/10, Size, pText, MaxWidth); } else if(Align < 0) - TextRender()->Text(0, r->x, r->y - Size/10, Size, pText, MaxWidth); + TextRender()->Text(0, r->x, r->y - Size/10, Size, pText, MaxWidth); else if(Align > 0) { - float tw = TextRender()->TextWidth(0, Size, pText, MaxWidth); - TextRender()->Text(0, r->x + r->w-tw, r->y - Size/10, Size, pText, MaxWidth); + float tw = TextRender()->TextWidth(0, Size, pText, MaxWidth); + TextRender()->Text(0, r->x + r->w-tw, r->y - Size/10, Size, pText, MaxWidth); } } void CUI::DoLabelScaled(const CUIRect *r, const char *pText, float Size, int Align, int MaxWidth) { - DoLabel(r, pText, Size*Scale(), Align, MaxWidth); + DoLabel(r, pText, Size*Scale(), Align, MaxWidth); } \ No newline at end of file diff --git a/src/game/client/ui.h b/src/game/client/ui.h index c339de733..017abf7c4 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -8,8 +8,8 @@ class CUIRect // TODO: Refactor: Redo UI scaling float Scale() const; public: - float x, y, w, h; - + float x, y, w, h; + void HSplitMid(CUIRect *pTop, CUIRect *pBottom) const; void HSplitTop(float Cut, CUIRect *pTop, CUIRect *pBottom) const; void HSplitBottom(float Cut, CUIRect *pTop, CUIRect *pBottom) const; @@ -20,7 +20,7 @@ public: void Margin(float Cut, CUIRect *pOtherRect) const; void VMargin(float Cut, CUIRect *pOtherRect) const; void HMargin(float Cut, CUIRect *pOtherRect) const; - + }; class CUI @@ -33,11 +33,11 @@ class CUI float m_MouseWorldX, m_MouseWorldY; // in world space unsigned m_MouseButtons; unsigned m_LastMouseButtons; - + CUIRect m_Screen; class IGraphics *m_pGraphics; class ITextRender *m_pTextRender; - + public: // TODO: Refactor: Fill this in void SetGraphics(class IGraphics *pGraphics, class ITextRender *pTextRender) { m_pGraphics = pGraphics; m_pTextRender = pTextRender;} @@ -52,12 +52,12 @@ public: CORNER_TR=2, CORNER_BL=4, CORNER_BR=8, - + CORNER_T=CORNER_TL|CORNER_TR, CORNER_B=CORNER_BL|CORNER_BR, CORNER_R=CORNER_TR|CORNER_BR, CORNER_L=CORNER_TL|CORNER_BL, - + CORNER_ALL=CORNER_T|CORNER_B }; @@ -83,13 +83,13 @@ public: CUIRect *Screen(); void ClipEnable(const CUIRect *pRect); void ClipDisable(); - + // TODO: Refactor: Redo UI scaling void SetScale(float s); float Scale(); int DoButtonLogic(const void *pID, const char *pText /* TODO: Refactor: Remove */, int Checked, const CUIRect *pRect); - + // TODO: Refactor: Remove this? void DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, int MaxWidth = -1); void DoLabelScaled(const CUIRect *pRect, const char *pText, float Size, int Align, int MaxWidth = -1); diff --git a/src/game/collision.cpp b/src/game/collision.cpp index 8acddc6e1..ca932d9b7 100644 --- a/src/game/collision.cpp +++ b/src/game/collision.cpp @@ -26,14 +26,14 @@ void CCollision::Init(class CLayers *pLayers) m_Width = m_pLayers->GameLayer()->m_Width; m_Height = m_pLayers->GameLayer()->m_Height; m_pTiles = static_cast(m_pLayers->Map()->GetData(m_pLayers->GameLayer()->m_Data)); - + for(int i = 0; i < m_Width*m_Height; i++) { int Index = m_pTiles[i].m_Index; - + if(Index > 128) continue; - + switch(Index) { case TILE_DEATH: @@ -55,7 +55,7 @@ int CCollision::GetTile(int x, int y) { int Nx = clamp(x/32, 0, m_Width-1); int Ny = clamp(y/32, 0, m_Height-1); - + return m_pTiles[Ny*m_Width+Nx].m_Index > 128 ? 0 : m_pTiles[Ny*m_Width+Nx].m_Index; } @@ -70,7 +70,7 @@ int CCollision::IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *p float Distance = distance(Pos0, Pos1); int End(Distance+1); vec2 Last = Pos0; - + for(int i = 0; i < End; i++) { float a = i/Distance; @@ -97,7 +97,7 @@ void CCollision::MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, i { if(pBounces) *pBounces = 0; - + vec2 Pos = *pInoutPos; vec2 Vel = *pInoutVel; if(CheckPoint(Pos + Vel)) @@ -107,7 +107,7 @@ void CCollision::MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, i { pInoutVel->x *= -Elasticity; if(pBounces) - (*pBounces)++; + (*pBounces)++; Affected++; } @@ -115,10 +115,10 @@ void CCollision::MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, i { pInoutVel->y *= -Elasticity; if(pBounces) - (*pBounces)++; + (*pBounces)++; Affected++; } - + if(Affected == 0) { pInoutVel->x *= -Elasticity; @@ -150,10 +150,10 @@ void CCollision::MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elas // do the move vec2 Pos = *pInoutPos; vec2 Vel = *pInoutVel; - + float Distance = length(Vel); int Max = (int)Distance; - + if(Distance > 0.00001f) { //vec2 old_pos = pos; @@ -163,27 +163,27 @@ void CCollision::MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elas //float amount = i/(float)max; //if(max == 0) //amount = 0; - + vec2 NewPos = Pos + Vel*Fraction; // TODO: this row is not nice - + if(TestBox(vec2(NewPos.x, NewPos.y), Size)) { int Hits = 0; - + if(TestBox(vec2(Pos.x, NewPos.y), Size)) { NewPos.y = Pos.y; Vel.y *= -Elasticity; Hits++; } - + if(TestBox(vec2(NewPos.x, Pos.y), Size)) { NewPos.x = Pos.x; Vel.x *= -Elasticity; Hits++; } - + // neither of the tests got a collision. // this is a real _corner case_! if(Hits == 0) @@ -194,11 +194,11 @@ void CCollision::MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elas Vel.x *= -Elasticity; } } - + Pos = NewPos; } } - + *pInoutPos = Pos; *pInoutVel = Vel; } diff --git a/src/game/editor/ed_editor.h b/src/game/editor/ed_editor.h index 9d220bd63..aab757e10 100644 --- a/src/game/editor/ed_editor.h +++ b/src/game/editor/ed_editor.h @@ -30,7 +30,7 @@ enum { MODE_LAYERS=0, MODE_IMAGES, - + DIALOG_NONE=0, DIALOG_FILE, }; @@ -48,7 +48,7 @@ public: array m_lPoints; char m_aName[32]; float m_Bottom, m_Top; - + CEnvelope(int Chan) { m_Channels = Chan; @@ -56,7 +56,7 @@ public: m_Bottom = 0; m_Top = 0; } - + void Resort() { sort(m_lPoints.all()); @@ -80,13 +80,13 @@ public: } } } - + int Eval(float Time, float *pResult) { CRenderTools::RenderEvalEnvelope(m_lPoints.base_ptr(), m_lPoints.size(), m_Channels, Time, pResult); return m_Channels; } - + void AddPoint(int Time, int v0, int v1=0, int v2=0, int v3=0) { CEnvPoint p; @@ -99,7 +99,7 @@ public: m_lPoints.add(p); Resort(); } - + float EndTime() { if(m_lPoints.size()) @@ -130,12 +130,12 @@ public: m_Flags = 0; m_pEditor = 0; } - + virtual ~CLayer() { } - - + + virtual void BrushSelecting(CUIRect Rect) {} virtual int BrushGrab(CLayerGroup *pBrush, CUIRect Rect) { return 0; } virtual void FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) {} @@ -144,15 +144,15 @@ public: virtual void BrushFlipX() {} virtual void BrushFlipY() {} virtual void BrushRotate(float Amount) {} - + virtual void Render() {} virtual int RenderProperties(CUIRect *pToolbox) { return 0; } - + virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc) {} virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) {} - + virtual void GetSize(float *w, float *h) { *w = 0; *h = 0;} - + const char *m_pTypeName; int m_Type; int m_Flags; @@ -166,49 +166,49 @@ class CLayerGroup { public: class CEditorMap *m_pMap; - + array m_lLayers; - + int m_OffsetX; int m_OffsetY; int m_ParallaxX; int m_ParallaxY; - + int m_UseClipping; int m_ClipX; int m_ClipY; int m_ClipW; int m_ClipH; - + const char *m_pName; bool m_GameGroup; bool m_Visible; bool m_SaveToMap; - + CLayerGroup(); ~CLayerGroup(); - + void Convert(CUIRect *pRect); void Render(); void MapScreen(); void Mapping(float *pPoints); void GetSize(float *w, float *h); - + void DeleteLayer(int Index); int SwapLayers(int Index0, int Index1); - - bool IsEmpty() const + + bool IsEmpty() const { return m_lLayers.size() == 0; } - - void Clear() - { + + void Clear() + { m_lLayers.delete_all(); } - + void AddLayer(CLayer *l); void ModifyImageIndex(INDEX_MODIFY_FUNC Func) @@ -216,7 +216,7 @@ public: for(int i = 0; i < m_lLayers.size(); i++) m_lLayers[i]->ModifyImageIndex(Func); } - + void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func) { for(int i = 0; i < m_lLayers.size(); i++) @@ -228,7 +228,7 @@ class CEditorImage : public CImageInfo { public: CEditor *m_pEditor; - + CEditorImage(CEditor *pEditor) { m_pEditor = pEditor; @@ -240,11 +240,11 @@ public: m_pData = 0; m_Format = 0; } - + ~CEditorImage(); - + void AnalyseTileFlags(); - + int m_TexID; int m_External; char m_aName[128]; @@ -267,10 +267,10 @@ public: array m_lGroups; array m_lImages; array m_lEnvelopes; - + class CLayerGame *m_pGameLayer; CLayerGroup *m_pGameGroup; - + CEnvelope *NewEnvelope(int Channels) { m_Modified = true; @@ -280,7 +280,7 @@ public: } void DeleteEnvelope(int Index); - + CLayerGroup *NewGroup() { m_Modified = true; @@ -289,7 +289,7 @@ public: m_lGroups.add(g); return g; } - + int SwapGroups(int Index0, int Index1) { if(Index0 < 0 || Index0 >= m_lGroups.size()) return Index0; @@ -299,7 +299,7 @@ public: swap(m_lGroups[Index0], m_lGroups[Index1]); return Index1; } - + void DeleteGroup(int Index) { if(Index < 0 || Index >= m_lGroups.size()) return; @@ -307,25 +307,25 @@ public: delete m_lGroups[Index]; m_lGroups.remove_index(Index); } - + void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc) { m_Modified = true; for(int i = 0; i < m_lGroups.size(); i++) m_lGroups[i]->ModifyImageIndex(pfnFunc); } - + void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) { m_Modified = true; for(int i = 0; i < m_lGroups.size(); i++) m_lGroups[i]->ModifyEnvelopeIndex(pfnFunc); } - + void Clean(); void CreateDefault(int EntitiesTexture); - // io + // io int Save(class IStorage *pStorage, const char *pFilename); int Load(class IStorage *pStorage, const char *pFilename, int StorageType); }; @@ -383,17 +383,17 @@ public: virtual void BrushFlipX(); virtual void BrushFlipY(); virtual void BrushRotate(float Amount); - + virtual void ShowInfo(); virtual int RenderProperties(CUIRect *pToolbox); virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc); virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc); - + void PrepareForSave(); - void GetSize(float *w, float *h) { *w = m_Width*32.0f; *h = m_Height*32.0f; } - + void GetSize(float *w, float *h) { *w = m_Width*32.0f; *h = m_Height*32.0f; } + int m_TexID; int m_Game; int m_Image; @@ -418,14 +418,14 @@ public: virtual void BrushFlipX(); virtual void BrushFlipY(); virtual void BrushRotate(float Amount); - + virtual int RenderProperties(CUIRect *pToolbox); virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc); virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc); - + void GetSize(float *w, float *h); - + int m_Image; array m_lQuads; }; @@ -475,7 +475,7 @@ public: m_ValidSaveFilename = false; m_PopupEventActivated = false; - + m_FileDialogStorageType = 0; m_pFileDialogTitle = 0; m_pFileDialogButtonText = 0; @@ -495,7 +495,7 @@ public: m_WorldOffsetY = 0; m_EditorOffsetX = 0.0f; m_EditorOffsetY = 0.0f; - + m_WorldZoom = 1.0f; m_ZoomLevel = 200; m_LockMouse = false; @@ -504,36 +504,36 @@ public: m_MouseDeltaY = 0; m_MouseDeltaWx = 0; m_MouseDeltaWy = 0; - + m_GuiActive = true; m_ProofBorders = false; - + m_ShowTileInfo = false; m_ShowDetail = true; m_Animate = false; m_AnimateStart = 0; m_AnimateTime = 0; m_AnimateSpeed = 1; - + m_ShowEnvelopeEditor = 0; - + ms_CheckerTexture = 0; ms_BackgroundTexture = 0; ms_CursorTexture = 0; ms_EntitiesTexture = 0; - + ms_pUiGotContext = 0; } - + virtual void Init(); virtual void UpdateAndRender(); virtual bool HasUnsavedData() { return m_Map.m_Modified; } - + void FilelistPopulate(int StorageType); void InvokeFileDialog(int StorageType, int FileType, const char *pTitle, const char *pButtonText, const char *pBasepath, const char *pDefaultName, void (*pfnFunc)(const char *pFilename, int StorageType, void *pUser), void *pUser); - + void Reset(bool CreateDefault=true); int Save(const char *pFilename); int Load(const char *pFilename, int StorageType); @@ -544,9 +544,9 @@ public: CLayer *GetSelectedLayerType(int Index, int Type); CLayer *GetSelectedLayer(int Index); CLayerGroup *GetSelectedGroup(); - + int DoProperties(CUIRect *pToolbox, CProperty *pProps, int *pIDs, int *pNewVal); - + int m_Mode; int m_Dialog; const char *m_pTooltip; @@ -573,7 +573,7 @@ public: MAX_PATH_LENGTH = 512 }; - + int m_FileDialogStorageType; const char *m_pFileDialogTitle; const char *m_pFileDialogButtonText; @@ -597,7 +597,7 @@ public: bool m_IsDir; bool m_IsLink; int m_StorageType; - + bool operator<(const CFilelistItem &Other) { return !str_comp(m_aFilename, "..") ? true : !str_comp(Other.m_aFilename, "..") ? false : m_IsDir && !Other.m_IsDir ? true : !m_IsDir && Other.m_IsDir ? false : str_comp_filenames(m_aFilename, Other.m_aFilename) < 0; } @@ -621,36 +621,36 @@ public: float m_MouseDeltaY; float m_MouseDeltaWx; float m_MouseDeltaWy; - + bool m_ShowTileInfo; bool m_ShowDetail; bool m_Animate; int64 m_AnimateStart; float m_AnimateTime; float m_AnimateSpeed; - + int m_ShowEnvelopeEditor; - + int m_SelectedLayer; int m_SelectedGroup; int m_SelectedQuad; int m_SelectedPoints; int m_SelectedEnvelope; int m_SelectedImage; - + static int ms_CheckerTexture; static int ms_BackgroundTexture; static int ms_CursorTexture; static int ms_EntitiesTexture; - + CLayerGroup m_Brush; CLayerTiles m_TilesetPicker; - + static const void *ms_pUiGotContext; - + CEditorMap m_Map; - - void DoMapBorder(); + + void DoMapBorder(); int DoButton_Editor_Common(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); int DoButton_Editor(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); @@ -660,17 +660,17 @@ public: int DoButton_ButtonInc(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); int DoButton_File(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); - + int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip); int DoButton_MenuItem(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags=0, const char *pToolTip=0); - + int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, bool Hidden=false); void RenderBackground(CUIRect View, int Texture, float Size, float Brightness); void UiInvokePopupMenu(void *pID, int Flags, float X, float Y, float W, float H, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect), void *pExtra=0); void UiDoPopupMenu(); - + int UiDoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, int Current, int Min, int Max, int Step, float Scale, const char *pToolTip); static int PopupGroup(CEditor *pEditor, CUIRect View); @@ -693,7 +693,7 @@ public: void PopupSelectGametileOpInvoke(float x, float y); int PopupSelectGameTileOpResult(); - + vec4 ButtonColorMul(const void *pID); void DoQuadPoint(CQuad *pQuad, int QuadIndex, int v); @@ -702,16 +702,16 @@ public: void DoQuad(CQuad *pQuad, int Index); float UiDoScrollbarV(const void *pID, const CUIRect *pRect, float Current); vec4 GetButtonColor(const void *pID, int Checked); - + static void ReplaceImage(const char *pFilename, int StorageType, void *pUser); static void AddImage(const char *pFilename, int StorageType, void *pUser); - + void RenderImages(CUIRect Toolbox, CUIRect Toolbar, CUIRect View); void RenderLayers(CUIRect Toolbox, CUIRect Toolbar, CUIRect View); void RenderModebar(CUIRect View); void RenderStatusbar(CUIRect View); void RenderEnvelopeEditor(CUIRect View); - + void RenderMenubar(CUIRect Menubar); void RenderFileDialog(); diff --git a/src/game/editor/ed_io.cpp b/src/game/editor/ed_io.cpp index 4dd712458..a5ead97a7 100644 --- a/src/game/editor/ed_io.cpp +++ b/src/game/editor/ed_io.cpp @@ -67,7 +67,7 @@ void editor_load_old(DATAFILE *df, MAP *map) MAPRES_FLAGSTAND_RED=5, MAPRES_FLAGSTAND_BLUE=6, MAPRES_ENTS_END, - + ITEM_NULL=0, ITEM_WEAPON_GUN=0x00010001, ITEM_WEAPON_SHOTGUN=0x00010002, @@ -78,7 +78,7 @@ void editor_load_old(DATAFILE *df, MAP *map) ITEM_ARMOR=0x00030001, ITEM_NINJA=0x00040001, }; - + enum { MAPRES_REGISTERED=0x8000, @@ -97,9 +97,9 @@ void editor_load_old(DATAFILE *df, MAP *map) for(int t = 0; t < num; t++) { mapres_tilemap *tmap = (mapres_tilemap *)datafile_get_item(df, start+t,0,0); - + CLayerTiles *l = new CLayerTiles(tmap->width, tmap->height); - + if(tmap->main) { // move game layer to correct position @@ -108,7 +108,7 @@ void editor_load_old(DATAFILE *df, MAP *map) if(map->groups[0]->layers[i] == pEditor->map.game_layer) map->groups[0]->swap_layers(i, i+1); } - + game_width = tmap->width; game_height = tmap->height; } @@ -119,18 +119,18 @@ void editor_load_old(DATAFILE *df, MAP *map) // process the data unsigned char *src_data = (unsigned char *)datafile_get_data(df, tmap->data); CTile *dst_data = l->tiles; - + for(int y = 0; y < tmap->height; y++) for(int x = 0; x < tmap->width; x++, dst_data++, src_data+=2) { dst_data->index = src_data[0]; dst_data->flags = src_data[1]; } - + l->image = tmap->image; } } - + // load images { int start, count; @@ -144,18 +144,18 @@ void editor_load_old(DATAFILE *df, MAP *map) img->width = imgres->width; img->height = imgres->height; img->format = CImageInfo::FORMAT_RGBA; - + // copy image data img->data = mem_alloc(img->width*img->height*4, 1); mem_copy(img->data, data, img->width*img->height*4); img->tex_id = Graphics()->LoadTextureRaw(img->width, img->height, img->format, img->data, CImageInfo::FORMAT_AUTO, 0); map->images.add(img); - + // unload image datafile_unload_data(df, imgres->image_data); } } - + // load entities { CLayerGame *g = map->game_layer; @@ -173,7 +173,7 @@ void editor_load_old(DATAFILE *df, MAP *map) int x = e->x/32; int y = e->y/32; int id = -1; - + if(t == MAPRES_SPAWNPOINT) id = ENTITY_SPAWN; else if(t == MAPRES_SPAWNPOINT_RED) id = ENTITY_SPAWN_RED; else if(t == MAPRES_SPAWNPOINT_BLUE) id = ENTITY_SPAWN_BLUE; @@ -187,7 +187,7 @@ void editor_load_old(DATAFILE *df, MAP *map) else if(e->data[0] == ITEM_ARMOR) id = ENTITY_ARMOR_1; else if(e->data[0] == ITEM_HEALTH) id = ENTITY_HEALTH_1; } - + if(id > 0 && x >= 0 && x < g->width && y >= 0 && y < g->height) g->tiles[y*g->width+x].index = id+ENTITY_OFFSET; } @@ -212,7 +212,7 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) m_pEditor->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "editor", aBuf); return 0; } - + // save version { CMapItemVersion Item; @@ -224,14 +224,14 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) for(int i = 0; i < m_lImages.size(); i++) { CEditorImage *pImg = m_lImages[i]; - + // analyse the image for when saving (should be done when we load the image) // TODO! pImg->AnalyseTileFlags(); - + CMapItemImage Item; Item.m_Version = 1; - + Item.m_Width = pImg->m_Width; Item.m_Height = pImg->m_Height; Item.m_External = pImg->m_External; @@ -242,7 +242,7 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) Item.m_ImageData = df.AddData(Item.m_Width*Item.m_Height*4, pImg->m_pData); df.AddItem(MAPITEMTYPE_IMAGE, i, sizeof(Item), &Item); } - + // save layers int LayerCount = 0, GroupCount = 0; for(int g = 0; g < m_lGroups.size(); g++) @@ -253,7 +253,7 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) CMapItemGroup GItem; GItem.m_Version = CMapItemGroup::CURRENT_VERSION; - + GItem.m_ParallaxX = pGroup->m_ParallaxX; GItem.m_ParallaxY = pGroup->m_ParallaxY; GItem.m_OffsetX = pGroup->m_OffsetX; @@ -265,7 +265,7 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) GItem.m_ClipH = pGroup->m_ClipH; GItem.m_StartLayer = LayerCount; GItem.m_NumLayers = 0; - + for(int l = 0; l < pGroup->m_lLayers.size(); l++) { if(!pGroup->m_lLayers[l]->m_SaveToMap) @@ -276,27 +276,27 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) m_pEditor->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "editor", "saving tiles layer"); CLayerTiles *pLayer = (CLayerTiles *)pGroup->m_lLayers[l]; pLayer->PrepareForSave(); - + CMapItemLayerTilemap Item; Item.m_Version = 2; - + Item.m_Layer.m_Flags = pLayer->m_Flags; Item.m_Layer.m_Type = pLayer->m_Type; - + Item.m_Color.r = pLayer->m_Color.r; Item.m_Color.g = pLayer->m_Color.g; Item.m_Color.b = pLayer->m_Color.b; Item.m_Color.a = pLayer->m_Color.a; Item.m_ColorEnv = -1; // not in use right now Item.m_ColorEnvOffset = 0; - + Item.m_Width = pLayer->m_Width; Item.m_Height = pLayer->m_Height; Item.m_Flags = pLayer->m_Game; Item.m_Image = pLayer->m_Image; Item.m_Data = df.AddData(pLayer->m_Width*pLayer->m_Height*sizeof(CTile), pLayer->m_pTiles); df.AddItem(MAPITEMTYPE_LAYER, LayerCount, sizeof(Item), &Item); - + GItem.m_NumLayers++; LayerCount++; } @@ -308,15 +308,15 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) { CMapItemLayerQuads Item; Item.m_Version = 1; - Item.m_Layer.m_Flags = pLayer->m_Flags; + Item.m_Layer.m_Flags = pLayer->m_Flags; Item.m_Layer.m_Type = pLayer->m_Type; Item.m_Image = pLayer->m_Image; - + // add the data Item.m_NumQuads = pLayer->m_lQuads.size(); Item.m_Data = df.AddDataSwapped(pLayer->m_lQuads.size()*sizeof(CQuad), pLayer->m_lQuads.base_ptr()); df.AddItem(MAPITEMTYPE_LAYER, LayerCount, sizeof(Item), &Item); - + // clean up //mem_free(quads); @@ -325,10 +325,10 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) } } } - + df.AddItem(MAPITEMTYPE_GROUP, GroupCount++, sizeof(GItem), &GItem); } - + // save envelopes int PointCount = 0; for(int e = 0; e < m_lEnvelopes.size(); e++) @@ -339,16 +339,16 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) Item.m_StartPoint = PointCount; Item.m_NumPoints = m_lEnvelopes[e]->m_lPoints.size(); StrToInts(Item.m_aName, sizeof(Item.m_aName)/sizeof(int), m_lEnvelopes[e]->m_aName); - + df.AddItem(MAPITEMTYPE_ENVELOPE, e, sizeof(Item), &Item); PointCount += Item.m_NumPoints; } - + // save points int TotalSize = sizeof(CEnvPoint) * PointCount; CEnvPoint *pPoints = (CEnvPoint *)mem_alloc(TotalSize, 1); PointCount = 0; - + for(int e = 0; e < m_lEnvelopes.size(); e++) { int Count = m_lEnvelopes[e]->m_lPoints.size(); @@ -357,11 +357,11 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) } df.AddItem(MAPITEMTYPE_ENVPOINTS, 0, TotalSize, pPoints); - + // finish the data file df.Finish(); m_pEditor->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "editor", "saving done"); - + // send rcon.. if we can if(m_pEditor->Client()->RconAuthed()) { @@ -372,7 +372,7 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) if(!str_comp(aMapName, CurrentServerInfo.m_aMap)) m_pEditor->Client()->Rcon("reload"); } - + return 1; } @@ -388,7 +388,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag //DATAFILE *df = datafile_load(filename); if(!DataFile.Open(pStorage, pFileName, StorageType)) return 0; - + Clean(); // check version @@ -404,7 +404,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag else if(pItem->m_Version == 1) { //editor.reset(false); - + // load images { int Start, Num; @@ -414,7 +414,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag CMapItemImage *pItem = (CMapItemImage *)DataFile.GetItem(Start+i, 0, 0); char *pName = (char *)DataFile.GetData(pItem->m_ImageName); - // copy base info + // copy base info CEditorImage *pImg = new CEditorImage(m_pEditor); pImg->m_External = pItem->m_External; @@ -422,7 +422,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag { char aBuf[256]; str_format(aBuf, sizeof(aBuf),"mapres/%s.png", pName); - + // load external CEditorImage ImgInfo(m_pEditor); if(m_pEditor->Graphics()->LoadPNG(&ImgInfo, aBuf, IStorage::TYPE_ALL)) @@ -437,7 +437,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag pImg->m_Width = pItem->m_Width; pImg->m_Height = pItem->m_Height; pImg->m_Format = CImageInfo::FORMAT_RGBA; - + // copy image data void *pData = DataFile.GetData(pItem->m_ImageData); pImg->m_pData = mem_alloc(pImg->m_Width*pImg->m_Height*4, 1); @@ -450,33 +450,33 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag str_copy(pImg->m_aName, pName, 128); m_lImages.add(pImg); - + // unload image DataFile.UnloadData(pItem->m_ImageData); DataFile.UnloadData(pItem->m_ImageName); } } - + // load groups { int LayersStart, LayersNum; DataFile.GetType(MAPITEMTYPE_LAYER, &LayersStart, &LayersNum); - + int Start, Num; DataFile.GetType(MAPITEMTYPE_GROUP, &Start, &Num); for(int g = 0; g < Num; g++) { CMapItemGroup *pGItem = (CMapItemGroup *)DataFile.GetItem(Start+g, 0, 0); - + if(pGItem->m_Version < 1 || pGItem->m_Version > CMapItemGroup::CURRENT_VERSION) continue; - + CLayerGroup *pGroup = NewGroup(); pGroup->m_ParallaxX = pGItem->m_ParallaxX; pGroup->m_ParallaxY = pGItem->m_ParallaxY; pGroup->m_OffsetX = pGItem->m_OffsetX; pGroup->m_OffsetY = pGItem->m_OffsetY; - + if(pGItem->m_Version >= 2) { pGroup->m_UseClipping = pGItem->m_UseClipping; @@ -485,19 +485,19 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag pGroup->m_ClipW = pGItem->m_ClipW; pGroup->m_ClipH = pGItem->m_ClipH; } - + for(int l = 0; l < pGItem->m_NumLayers; l++) { CLayer *pLayer = 0; CMapItemLayer *pLayerItem = (CMapItemLayer *)DataFile.GetItem(LayersStart+pGItem->m_StartLayer+l, 0, 0); if(!pLayerItem) continue; - + if(pLayerItem->m_Type == LAYERTYPE_TILES) { CMapItemLayerTilemap *pTilemapItem = (CMapItemLayerTilemap *)pLayerItem; CLayerTiles *pTiles = 0; - + if(pTilemapItem->m_Flags&1) { pTiles = new CLayerGame(pTilemapItem->m_Width, pTilemapItem->m_Height); @@ -515,14 +515,14 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag } pLayer = pTiles; - + pGroup->AddLayer(pTiles); void *pData = DataFile.GetData(pTilemapItem->m_Data); pTiles->m_Image = pTilemapItem->m_Image; pTiles->m_Game = pTilemapItem->m_Flags&1; - + mem_copy(pTiles->m_pTiles, pData, pTiles->m_Width*pTiles->m_Height*sizeof(CTile)); - + if(pTiles->m_Game && pTilemapItem->m_Version == MakeVersion(1, *pTilemapItem)) { for(int i = 0; i < pTiles->m_Width*pTiles->m_Height; i++) @@ -531,7 +531,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag pTiles->m_pTiles[i].m_Index += ENTITY_OFFSET; } } - + DataFile.UnloadData(pTilemapItem->m_Data); } else if(pLayerItem->m_Type == LAYERTYPE_QUADS) @@ -549,24 +549,24 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag mem_copy(pQuads->m_lQuads.base_ptr(), pData, sizeof(CQuad)*pQuadsItem->m_NumQuads); DataFile.UnloadData(pQuadsItem->m_Data); } - + if(pLayer) pLayer->m_Flags = pLayerItem->m_Flags; } } } - + // load envelopes { CEnvPoint *pPoints = 0; - + { int Start, Num; DataFile.GetType(MAPITEMTYPE_ENVPOINTS, &Start, &Num); if(Num) pPoints = (CEnvPoint *)DataFile.GetItem(Start, 0, 0); } - + int Start, Num; DataFile.GetType(MAPITEMTYPE_ENVELOPE, &Start, &Num); for(int e = 0; e < Num; e++) @@ -581,7 +581,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag } } } - + return 1; } @@ -602,25 +602,25 @@ int CEditor::Append(const char *pFileName, int StorageType) if(!Err) return Err; - // modify indecies + // modify indecies gs_ModifyAddAmount = m_Map.m_lImages.size(); NewMap.ModifyImageIndex(ModifyAdd); - + gs_ModifyAddAmount = m_Map.m_lEnvelopes.size(); NewMap.ModifyEnvelopeIndex(ModifyAdd); - + // transfer images for(int i = 0; i < NewMap.m_lImages.size(); i++) m_Map.m_lImages.add(NewMap.m_lImages[i]); NewMap.m_lImages.clear(); - + // transfer envelopes for(int i = 0; i < NewMap.m_lEnvelopes.size(); i++) m_Map.m_lEnvelopes.add(NewMap.m_lEnvelopes[i]); NewMap.m_lEnvelopes.clear(); // transfer groups - + for(int i = 0; i < NewMap.m_lGroups.size(); i++) { if(NewMap.m_lGroups[i] == NewMap.m_pGameGroup) @@ -632,7 +632,7 @@ int CEditor::Append(const char *pFileName, int StorageType) } } NewMap.m_lGroups.clear(); - + // all done \o/ return 0; } diff --git a/src/game/editor/ed_layer_quads.cpp b/src/game/editor/ed_layer_quads.cpp index 4f2e468c6..680a54cd9 100644 --- a/src/game/editor/ed_layer_quads.cpp +++ b/src/game/editor/ed_layer_quads.cpp @@ -32,7 +32,7 @@ static void EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUse pChannels[3] = 0; return; } - + CEnvelope *e = pEditor->m_Map.m_lEnvelopes[Env]; float t = pEditor->m_AnimateTime+TimeOffset; t *= pEditor->m_AnimateSpeed; @@ -44,7 +44,7 @@ void CLayerQuads::Render() Graphics()->TextureSet(-1); 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, EnvelopeEval, m_pEditor); } @@ -70,26 +70,26 @@ CQuad *CLayerQuads::NewQuad() q->m_aPoints[4].x = x+32; // pivot q->m_aPoints[4].y = y+32; - + for(int i = 0; i < 5; i++) { q->m_aPoints[i].x <<= 10; q->m_aPoints[i].y <<= 10; } - + q->m_aTexcoords[0].x = 0; q->m_aTexcoords[0].y = 0; - + q->m_aTexcoords[1].x = 1<<10; q->m_aTexcoords[1].y = 0; - + q->m_aTexcoords[2].x = 0; q->m_aTexcoords[2].y = 1<<10; - + q->m_aTexcoords[3].x = 1<<10; q->m_aTexcoords[3].y = 1<<10; - + q->m_aColors[0].r = 255; q->m_aColors[0].g = 255; q->m_aColors[0].b = 255; q->m_aColors[0].a = 255; q->m_aColors[1].r = 255; q->m_aColors[1].g = 255; q->m_aColors[1].b = 255; q->m_aColors[1].a = 255; q->m_aColors[2].r = 255; q->m_aColors[2].g = 255; q->m_aColors[2].b = 255; q->m_aColors[2].a = 255; @@ -119,29 +119,29 @@ int CLayerQuads::BrushGrab(CLayerGroup *pBrush, CUIRect Rect) pGrabbed->m_pEditor = m_pEditor; pGrabbed->m_Image = m_Image; pBrush->AddLayer(pGrabbed); - + //dbg_msg("", "%f %f %f %f", rect.x, rect.y, rect.w, rect.h); for(int i = 0; i < m_lQuads.size(); i++) { CQuad *q = &m_lQuads[i]; float px = fx2f(q->m_aPoints[4].x); float py = fx2f(q->m_aPoints[4].y); - + if(px > Rect.x && px < Rect.x+Rect.w && py > Rect.y && py < Rect.y+Rect.h) { CQuad n; n = *q; - + for(int p = 0; p < 5; p++) { n.m_aPoints[p].x -= f2fx(Rect.x); n.m_aPoints[p].y -= f2fx(Rect.y); } - + pGrabbed->m_lQuads.add(n); } } - + return pGrabbed->m_lQuads.size()?1:0; } @@ -151,13 +151,13 @@ void CLayerQuads::BrushPlace(CLayer *pBrush, float wx, float wy) for(int i = 0; i < l->m_lQuads.size(); i++) { CQuad n = l->m_lQuads[i]; - + for(int p = 0; p < 5; p++) { n.m_aPoints[p].x += f2fx(wx); n.m_aPoints[p].y += f2fx(wy); } - + m_lQuads.add(n); } m_pEditor->m_Map.m_Modified = true; @@ -189,7 +189,7 @@ void CLayerQuads::BrushRotate(float Amount) for(int i = 0; i < m_lQuads.size(); i++) { CQuad *q = &m_lQuads[i]; - + for(int p = 0; p < 5; p++) { vec2 Pos(fx2f(q->m_aPoints[p].x), fx2f(q->m_aPoints[p].y)); @@ -203,7 +203,7 @@ void CLayerQuads::BrushRotate(float Amount) void CLayerQuads::GetSize(float *w, float *h) { *w = 0; *h = 0; - + for(int i = 0; i < m_lQuads.size(); i++) { for(int p = 0; p < 5; p++) @@ -224,18 +224,18 @@ int CLayerQuads::RenderProperties(CUIRect *pToolBox) PROP_IMAGE=0, NUM_PROPS, }; - + CProperty aProps[] = { {"Image", m_Image, PROPTYPE_IMAGE, -1, 0}, {0}, }; - + static int s_aIds[NUM_PROPS] = {0}; int NewVal = 0; int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal); if(Prop != -1) m_pEditor->m_Map.m_Modified = true; - + if(Prop == PROP_IMAGE) { if(NewVal >= 0) diff --git a/src/game/editor/ed_layer_tiles.cpp b/src/game/editor/ed_layer_tiles.cpp index dcbb0afea..d0c9041cc 100644 --- a/src/game/editor/ed_layer_tiles.cpp +++ b/src/game/editor/ed_layer_tiles.cpp @@ -25,7 +25,7 @@ CLayerTiles::CLayerTiles(int w, int h) m_Color.g = 255; m_Color.b = 255; m_Color.a = 255; - + m_pTiles = new CTile[m_Width*m_Height]; mem_zero(m_pTiles, m_Width*m_Height*sizeof(CTile)); } @@ -93,19 +93,19 @@ void CLayerTiles::Clamp(RECTi *pRect) pRect->w += pRect->x; pRect->x = 0; } - + if(pRect->y < 0) { pRect->h += pRect->y; pRect->y = 0; } - + if(pRect->x+pRect->w > m_Width) pRect->w = m_Width - pRect->x; if(pRect->y+pRect->h > m_Height) pRect->h = m_Height - pRect->y; - + if(pRect->h < 0) pRect->h = 0; if(pRect->w < 0) @@ -131,10 +131,10 @@ int CLayerTiles::BrushGrab(CLayerGroup *pBrush, CUIRect Rect) RECTi r; Convert(Rect, &r); Clamp(&r); - + if(!r.w || !r.h) return 0; - + // create new layers CLayerTiles *pGrabbed = new CLayerTiles(r.w, r.h); pGrabbed->m_pEditor = m_pEditor; @@ -142,12 +142,12 @@ int CLayerTiles::BrushGrab(CLayerGroup *pBrush, CUIRect Rect) pGrabbed->m_Image = m_Image; pGrabbed->m_Game = m_Game; pBrush->AddLayer(pGrabbed); - + // copy the tiles for(int y = 0; y < r.h; y++) for(int x = 0; x < r.w; x++) pGrabbed->m_pTiles[y*pGrabbed->m_Width+x] = m_pTiles[(r.y+y)*m_Width+(r.x+x)]; - + return 1; } @@ -155,28 +155,28 @@ void CLayerTiles::FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect) { if(m_Readonly) return; - + int sx = ConvertX(Rect.x); int sy = ConvertY(Rect.y); int w = ConvertX(Rect.w); int h = ConvertY(Rect.h); - + CLayerTiles *pLt = static_cast(pBrush); - + for(int y = 0; y <= h; y++) { for(int x = 0; x <= w; x++) { int fx = x+sx; int fy = y+sy; - + if(fx < 0 || fx >= m_Width || fy < 0 || fy >= m_Height) continue; - - if(Empty) - m_pTiles[fy*m_Width+fx].m_Index = 1; - else - m_pTiles[fy*m_Width+fx] = pLt->m_pTiles[(y*pLt->m_Width + x%pLt->m_Width) % (pLt->m_Width*pLt->m_Height)]; + + if(Empty) + m_pTiles[fy*m_Width+fx].m_Index = 1; + else + m_pTiles[fy*m_Width+fx] = pLt->m_pTiles[(y*pLt->m_Width + x%pLt->m_Width) % (pLt->m_Width*pLt->m_Height)]; } } m_pEditor->m_Map.m_Modified = true; @@ -186,12 +186,12 @@ void CLayerTiles::BrushDraw(CLayer *pBrush, float wx, float wy) { if(m_Readonly) return; - + // CLayerTiles *l = (CLayerTiles *)pBrush; int sx = ConvertX(wx); int sy = ConvertY(wy); - + for(int y = 0; y < l->m_Height; y++) for(int x = 0; x < l->m_Width; x++) { @@ -199,7 +199,7 @@ void CLayerTiles::BrushDraw(CLayer *pBrush, float wx, float wy) int fy = y+sy; if(fx<0 || fx >= m_Width || fy < 0 || fy >= m_Height) continue; - + m_pTiles[fy*m_Width+fx] = l->m_pTiles[y*l->m_Width+x]; } m_pEditor->m_Map.m_Modified = true; @@ -279,10 +279,10 @@ void CLayerTiles::Resize(int NewW, int NewH) CTile *pNewData = new CTile[NewW*NewH]; mem_zero(pNewData, NewW*NewH*sizeof(CTile)); - // copy old data + // copy old data for(int y = 0; y < min(NewH, m_Height); y++) mem_copy(&pNewData[y*NewW], &m_pTiles[y*m_Width], min(m_Width, NewW)*sizeof(CTile)); - + // replace old delete [] m_pTiles; m_pTiles = pNewData; @@ -329,12 +329,12 @@ void CLayerTiles::ShowInfo() float ScreenX0, ScreenY0, ScreenX1, ScreenY1; Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); Graphics()->TextureSet(m_pEditor->Client()->GetDebugFont()); - + int StartY = max(0, (int)(ScreenY0/32.0f)-1); int StartX = max(0, (int)(ScreenX0/32.0f)-1); int EndY = min((int)(ScreenY1/32.0f)+1, m_Height); int EndX = min((int)(ScreenX1/32.0f)+1, m_Width); - + for(int y = StartY; y < EndY; y++) for(int x = StartX; x < EndX; x++) { @@ -359,7 +359,7 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) { CUIRect Button; pToolBox->HSplitBottom(12.0f, pToolBox, &Button); - + bool InGameGroup = !find_linear(m_pEditor->m_Map.m_pGameGroup->m_lLayers.all(), this).empty(); if(m_pEditor->m_Map.m_pGameLayer == this) InGameGroup = false; @@ -384,7 +384,7 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) return 1; } } - + enum { PROP_WIDTH=0, @@ -394,13 +394,13 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) PROP_COLOR, NUM_PROPS, }; - + int Color = 0; Color |= m_Color.r<<24; Color |= m_Color.g<<16; Color |= m_Color.b<<8; Color |= m_Color.a; - + CProperty aProps[] = { {"Width", m_Width, PROPTYPE_INT_SCROLL, 1, 1000000000}, {"Height", m_Height, PROPTYPE_INT_SCROLL, 1, 1000000000}, @@ -409,19 +409,19 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) {"Color", Color, PROPTYPE_COLOR, 0, 0}, {0}, }; - + if(m_pEditor->m_Map.m_pGameLayer == this) // remove the image and color properties if this is the game layer { aProps[3].m_pName = 0; aProps[4].m_pName = 0; } - + static int s_aIds[NUM_PROPS] = {0}; int NewVal = 0; int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal); if(Prop != -1) m_pEditor->m_Map.m_Modified = true; - + if(Prop == PROP_WIDTH && NewVal > 1) Resize(NewVal, m_Height); else if(Prop == PROP_HEIGHT && NewVal > 1) @@ -445,7 +445,7 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) m_Color.b = (NewVal>>8)&0xff; m_Color.a = NewVal&0xff; } - + return 0; } diff --git a/src/game/editor/ed_popups.cpp b/src/game/editor/ed_popups.cpp index 8f2c929ad..f572e43cd 100644 --- a/src/game/editor/ed_popups.cpp +++ b/src/game/editor/ed_popups.cpp @@ -44,7 +44,7 @@ void CEditor::UiDoPopupMenu() { bool Inside = UI()->MouseInside(&s_UiPopups[i].m_Rect); UI()->SetHotItem(&s_UiPopups[i].m_pId); - + if(UI()->ActiveItem() == &s_UiPopups[i].m_pId) { if(!UI()->MouseButton(0)) @@ -59,20 +59,20 @@ void CEditor::UiDoPopupMenu() if(UI()->MouseButton(0)) UI()->SetActiveItem(&s_UiPopups[i].m_pId); } - + int Corners = CUI::CORNER_ALL; if(s_UiPopups[i].m_IsMenu) Corners = CUI::CORNER_R|CUI::CORNER_B; - + CUIRect r = s_UiPopups[i].m_Rect; RenderTools()->DrawUIRect(&r, vec4(0.5f,0.5f,0.5f,0.75f), Corners, 3.0f); r.Margin(1.0f, &r); RenderTools()->DrawUIRect(&r, vec4(0,0,0,0.75f), Corners, 3.0f); r.Margin(4.0f, &r); - + if(s_UiPopups[i].m_pfnFunc(this, r)) g_UiNumPopups--; - + if(Input()->KeyDown(KEY_ESCAPE)) g_UiNumPopups--; } @@ -85,7 +85,7 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View) CUIRect Button; View.HSplitBottom(12.0f, &View, &Button); static int s_DeleteButton = 0; - + // don't allow deletion of game group if(pEditor->m_Map.m_pGameGroup != pEditor->GetSelectedGroup()) { @@ -162,7 +162,7 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View) pEditor->m_SelectedLayer = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_lLayers.size()-1; return 1; } - + enum { PROP_ORDER=0, @@ -177,7 +177,7 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View) PROP_CLIP_H, NUM_PROPS, }; - + CProperty aProps[] = { {"Order", pEditor->m_SelectedGroup, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lGroups.size()-1}, {"Pos X", -pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_OffsetX, PROPTYPE_INT_SCROLL, -1000000, 1000000}, @@ -192,21 +192,21 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View) {"Clip H", pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipH, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {0}, }; - + static int s_aIds[NUM_PROPS] = {0}; int NewVal = 0; - + // cut the properties that isn't needed if(pEditor->GetSelectedGroup()->m_GameGroup) aProps[PROP_POS_X].m_pName = 0; - + int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal); if(Prop != -1) pEditor->m_Map.m_Modified = true; if(Prop == PROP_ORDER) pEditor->m_SelectedGroup = pEditor->m_Map.SwapGroups(pEditor->m_SelectedGroup, NewVal); - + // these can not be changed on the game group if(!pEditor->GetSelectedGroup()->m_GameGroup) { @@ -220,7 +220,7 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View) else if(Prop == PROP_CLIP_W) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipW = NewVal; else if(Prop == PROP_CLIP_H) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipH = NewVal; } - + return 0; } @@ -230,7 +230,7 @@ int CEditor::PopupLayer(CEditor *pEditor, CUIRect View) CUIRect Button; View.HSplitBottom(12.0f, &View, &Button); static int s_DeleteButton = 0; - + // don't allow deletion of game layer if(pEditor->m_Map.m_pGameLayer != pEditor->GetSelectedLayer(0) && pEditor->DoButton_Editor(&s_DeleteButton, "Delete layer", 0, &Button, 0, "Deletes the layer")) @@ -240,10 +240,10 @@ int CEditor::PopupLayer(CEditor *pEditor, CUIRect View) } View.HSplitBottom(10.0f, &View, 0); - + CLayerGroup *pCurrentGroup = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]; CLayer *pCurrentLayer = pEditor->GetSelectedLayer(0); - + enum { PROP_GROUP=0, @@ -251,7 +251,7 @@ int CEditor::PopupLayer(CEditor *pEditor, CUIRect View) PROP_HQ, NUM_PROPS, }; - + CProperty aProps[] = { {"Group", pEditor->m_SelectedGroup, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lGroups.size()-1}, {"Order", pEditor->m_SelectedLayer, PROPTYPE_INT_STEP, 0, pCurrentGroup->m_lLayers.size()}, @@ -264,13 +264,13 @@ int CEditor::PopupLayer(CEditor *pEditor, CUIRect View) aProps[0].m_Type = PROPTYPE_NULL; aProps[2].m_Type = PROPTYPE_NULL; } - + static int s_aIds[NUM_PROPS] = {0}; int NewVal = 0; int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal); if(Prop != -1) pEditor->m_Map.m_Modified = true; - + if(Prop == PROP_ORDER) pEditor->m_SelectedLayer = pCurrentGroup->SwapLayers(pEditor->m_SelectedLayer, NewVal); else if(Prop == PROP_GROUP && pCurrentLayer->m_Type != LAYERTYPE_GAME) @@ -289,7 +289,7 @@ int CEditor::PopupLayer(CEditor *pEditor, CUIRect View) if(NewVal) pCurrentLayer->m_Flags |= LAYERFLAG_DETAIL; } - + return pCurrentLayer->RenderProperties(&View); } @@ -298,7 +298,7 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View) CQuad *pQuad = pEditor->GetSelectedQuad(); CUIRect Button; - + // delete button View.HSplitBottom(12.0f, &View, &Button); static int s_DeleteButton = 0; @@ -335,7 +335,7 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View) } int Height = (Right-Left)*pEditor->m_Map.m_lImages[pLayer->m_Image]->m_Height/pEditor->m_Map.m_lImages[pLayer->m_Image]->m_Width; - + pQuad->m_aPoints[0].x = Left; pQuad->m_aPoints[0].y = Top; pQuad->m_aPoints[1].x = Right; pQuad->m_aPoints[1].y = Top; pQuad->m_aPoints[2].x = Left; pQuad->m_aPoints[2].y = Top+Height; @@ -370,7 +370,7 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View) int Left = pQuad->m_aPoints[0].x; int Bottom = pQuad->m_aPoints[0].y; int Right = pQuad->m_aPoints[0].x; - + for(int k = 1; k < 4; k++) { if(pQuad->m_aPoints[k].y < Top) Top = pQuad->m_aPoints[k].y; @@ -378,7 +378,7 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View) if(pQuad->m_aPoints[k].y > Bottom) Bottom = pQuad->m_aPoints[k].y; if(pQuad->m_aPoints[k].x > Right) Right = pQuad->m_aPoints[k].x; } - + pQuad->m_aPoints[0].x = Left; pQuad->m_aPoints[0].y = Top; pQuad->m_aPoints[1].x = Right; pQuad->m_aPoints[1].y = Top; pQuad->m_aPoints[2].x = Left; pQuad->m_aPoints[2].y = Bottom; @@ -398,7 +398,7 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View) PROP_COLOR_ENV_OFFSET, NUM_PROPS, }; - + CProperty aProps[] = { {"Pos X", pQuad->m_aPoints[4].x/1000, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {"Pos Y", pQuad->m_aPoints[4].y/1000, PROPTYPE_INT_SCROLL, -1000000, 1000000}, @@ -406,16 +406,16 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View) {"Pos. TO", pQuad->m_PosEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {"Color Env", pQuad->m_ColorEnv+1, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lEnvelopes.size()+1}, {"Color TO", pQuad->m_ColorEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000}, - + {0}, }; - + static int s_aIds[NUM_PROPS] = {0}; int NewVal = 0; int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal); if(Prop != -1) pEditor->m_Map.m_Modified = true; - + if(Prop == PROP_POS_X) { float Offset = NewVal*1000-pQuad->m_aPoints[4].x; @@ -432,14 +432,14 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View) if(Prop == PROP_POS_ENV_OFFSET) pQuad->m_PosEnvOffset = NewVal; if(Prop == PROP_COLOR_ENV) pQuad->m_ColorEnv = clamp(NewVal-1, -1, pEditor->m_Map.m_lEnvelopes.size()-1); if(Prop == PROP_COLOR_ENV_OFFSET) pQuad->m_ColorEnvOffset = NewVal; - + return 0; } int CEditor::PopupPoint(CEditor *pEditor, CUIRect View) { CQuad *pQuad = pEditor->GetSelectedQuad(); - + enum { PROP_POS_X=0, @@ -447,7 +447,7 @@ int CEditor::PopupPoint(CEditor *pEditor, CUIRect View) PROP_COLOR, NUM_PROPS, }; - + int Color = 0; int x = 0, y = 0; @@ -465,15 +465,15 @@ int CEditor::PopupPoint(CEditor *pEditor, CUIRect View) y = pQuad->m_aPoints[v].y/1000; } } - - + + CProperty aProps[] = { {"Pos X", x, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {"Pos Y", y, PROPTYPE_INT_SCROLL, -1000000, 1000000}, {"Color", Color, PROPTYPE_COLOR, -1, pEditor->m_Map.m_lEnvelopes.size()}, {0}, }; - + static int s_aIds[NUM_PROPS] = {0}; int NewVal = 0; int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal); @@ -506,8 +506,8 @@ int CEditor::PopupPoint(CEditor *pEditor, CUIRect View) } } } - - return 0; + + return 0; } int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View) @@ -520,7 +520,7 @@ int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View) pEditor->UI()->DoLabel(&Label, "Create new folder", 20.0f, 0); View.HSplitBottom(10.0f, &View, 0); - View.HSplitBottom(20.0f, &View, &ButtonBar); + View.HSplitBottom(20.0f, &View, &ButtonBar); if(pEditor->m_FileDialogErrString[0] == 0) { @@ -551,7 +551,7 @@ int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View) } else str_copy(pEditor->m_FileDialogErrString, "Unable to create the folder", sizeof(pEditor->m_FileDialogErrString)); - } + } } ButtonBar.VSplitRight(30.0f, &ButtonBar, 0); ButtonBar.VSplitRight(110.0f, &ButtonBar, &Label); @@ -576,7 +576,7 @@ int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View) return 1; } - return 0; + return 0; } int CEditor::PopupEvent(CEditor *pEditor, CUIRect View) @@ -596,7 +596,7 @@ int CEditor::PopupEvent(CEditor *pEditor, CUIRect View) pEditor->UI()->DoLabel(&Label, "Save map", 20.0f, 0); View.HSplitBottom(10.0f, &View, 0); - View.HSplitBottom(20.0f, &View, &ButtonBar); + View.HSplitBottom(20.0f, &View, &ButtonBar); // notification text View.HSplitTop(30.0f, 0, &View); @@ -648,18 +648,18 @@ int CEditor::PopupSelectImage(CEditor *pEditor, CUIRect View) CUIRect ButtonBar, ImageView; View.VSplitLeft(80.0f, &ButtonBar, &View); View.Margin(10.0f, &ImageView); - + int ShowImage = g_SelectImageCurrent; - + for(int i = -1; i < pEditor->m_Map.m_lImages.size(); i++) { CUIRect Button; ButtonBar.HSplitTop(12.0f, &Button, &ButtonBar); ButtonBar.HSplitTop(2.0f, 0, &ButtonBar); - + if(pEditor->UI()->MouseInside(&Button)) ShowImage = i; - + if(i == -1) { if(pEditor->DoButton_MenuItem(&pEditor->m_Map.m_lImages[i], "None", i==g_SelectImageCurrent, &Button)) @@ -671,7 +671,7 @@ int CEditor::PopupSelectImage(CEditor *pEditor, CUIRect View) g_SelectImageSelected = i; } } - + if(ShowImage >= 0 && ShowImage < pEditor->m_Map.m_lImages.size()) pEditor->Graphics()->TextureSet(pEditor->m_Map.m_lImages[ShowImage]->m_TexID); else @@ -696,7 +696,7 @@ int CEditor::PopupSelectImageResult() { if(g_SelectImageSelected == -100) return -100; - + g_SelectImageCurrent = g_SelectImageSelected; g_SelectImageSelected = -100; return g_SelectImageCurrent; @@ -732,7 +732,7 @@ int CEditor::PopupSelectGameTileOpResult() { if(s_GametileOpSelected < 0) return -1; - + int Result = s_GametileOpSelected; s_GametileOpSelected = -1; return Result; diff --git a/src/game/gamecore.cpp b/src/game/gamecore.cpp index e41e1fab8..d2a1652ca 100644 --- a/src/game/gamecore.cpp +++ b/src/game/gamecore.cpp @@ -39,7 +39,7 @@ bool CTuningParams::Get(const char *pName, float *pValue) for(int i = 0; i < Num(); i++) if(str_comp_nocase(pName, m_apNames[i]) == 0) return Get(i, pValue); - + return false; } @@ -78,22 +78,22 @@ void CCharacterCore::Tick(bool UseInput) { float PhysSize = 28.0f; m_TriggeredEvents = 0; - + // get ground state bool Grounded = false; if(m_pCollision->CheckPoint(m_Pos.x+PhysSize/2, m_Pos.y+PhysSize/2+5)) Grounded = true; if(m_pCollision->CheckPoint(m_Pos.x-PhysSize/2, m_Pos.y+PhysSize/2+5)) Grounded = true; - + vec2 TargetDirection = normalize(vec2(m_Input.m_TargetX, m_Input.m_TargetY)); m_Vel.y += m_pWorld->m_Tuning.m_Gravity; - + float MaxSpeed = Grounded ? m_pWorld->m_Tuning.m_GroundControlSpeed : m_pWorld->m_Tuning.m_AirControlSpeed; float Accel = Grounded ? m_pWorld->m_Tuning.m_GroundControlAccel : m_pWorld->m_Tuning.m_AirControlAccel; float Friction = Grounded ? m_pWorld->m_Tuning.m_GroundFriction : m_pWorld->m_Tuning.m_AirFriction; - + // handle input if(UseInput) { @@ -105,10 +105,10 @@ void CCharacterCore::Tick(bool UseInput) a = atanf((float)m_Input.m_TargetY); else a = atanf((float)m_Input.m_TargetY/(float)m_Input.m_TargetX); - + if(m_Input.m_TargetX < 0) a = a+pi; - + m_Angle = (int)(a*256.0f); // handle jump @@ -144,16 +144,16 @@ void CCharacterCore::Tick(bool UseInput) m_HookedPlayer = -1; m_HookTick = 0; m_TriggeredEvents |= COREEVENT_HOOK_LAUNCH; - } + } } else { m_HookedPlayer = -1; m_HookState = HOOK_IDLE; - m_HookPos = m_Pos; - } + m_HookPos = m_Pos; + } } - + // add the speed modification according to players wanted direction if(m_Direction < 0) m_Vel.x = SaturatedAdd(-MaxSpeed, MaxSpeed, m_Vel.x, -Accel); @@ -161,13 +161,13 @@ void CCharacterCore::Tick(bool UseInput) m_Vel.x = SaturatedAdd(-MaxSpeed, MaxSpeed, m_Vel.x, Accel); if(m_Direction == 0) m_Vel.x *= Friction; - + // handle jumping // 1 bit = to keep track if a jump has been made on this input // 2 bit = to keep track if a air-jump has been made if(Grounded) m_Jumped &= ~2; - + // do hook if(m_HookState == HOOK_IDLE) { @@ -193,7 +193,7 @@ void CCharacterCore::Tick(bool UseInput) m_HookState = HOOK_RETRACT_START; NewPos = m_Pos + normalize(NewPos-m_Pos) * m_pWorld->m_Tuning.m_HookLength; } - + // make sure that the hook doesn't go though the ground bool GoingToHitGround = false; bool GoingToRetract = false; @@ -229,7 +229,7 @@ void CCharacterCore::Tick(bool UseInput) } } } - + if(m_HookState == HOOK_FLYING) { // check against ground @@ -243,11 +243,11 @@ void CCharacterCore::Tick(bool UseInput) m_TriggeredEvents |= COREEVENT_HOOK_HIT_NOHOOK; m_HookState = HOOK_RETRACT_START; } - + m_HookPos = NewPos; } } - + if(m_HookState == HOOK_GRABBED) { if(m_HookedPlayer != -1) @@ -260,14 +260,14 @@ void CCharacterCore::Tick(bool UseInput) // release hook m_HookedPlayer = -1; m_HookState = HOOK_RETRACTED; - m_HookPos = m_Pos; + m_HookPos = m_Pos; } - + // keep players hooked for a max of 1.5sec //if(Server()->Tick() > hook_tick+(Server()->TickSpeed()*3)/2) //release_hooked(); } - + // don't do this hook rutine when we are hook to a player if(m_HookedPlayer == -1 && distance(m_HookPos, m_Pos) > 46.0f) { @@ -276,20 +276,20 @@ void CCharacterCore::Tick(bool UseInput) // this makes it easier to get on top of an platform if(HookVel.y > 0) HookVel.y *= 0.3f; - + // the hook will boost it's power if the player wants to move // in that direction. otherwise it will dampen everything abit - if((HookVel.x < 0 && m_Direction < 0) || (HookVel.x > 0 && m_Direction > 0)) + if((HookVel.x < 0 && m_Direction < 0) || (HookVel.x > 0 && m_Direction > 0)) HookVel.x *= 0.95f; else HookVel.x *= 0.75f; - + vec2 NewVel = m_Vel+HookVel; // check if we are under the legal limit for the hook if(length(NewVel) < m_pWorld->m_Tuning.m_HookDragSpeed || length(NewVel) < length(m_Vel)) m_Vel = NewVel; // no problem. apply - + } // release hook (max hook time is 1.25 @@ -298,10 +298,10 @@ void CCharacterCore::Tick(bool UseInput) { m_HookedPlayer = -1; m_HookState = HOOK_RETRACTED; - m_HookPos = m_Pos; + m_HookPos = m_Pos; } } - + if(m_pWorld && m_pWorld->m_Tuning.m_PlayerCollision) { for(int i = 0; i < MAX_CLIENTS; i++) @@ -309,11 +309,11 @@ void CCharacterCore::Tick(bool UseInput) CCharacterCore *pCharCore = m_pWorld->m_apCharacters[i]; if(!pCharCore) continue; - + //player *p = (player*)ent; if(pCharCore == this) // || !(p->flags&FLAG_ALIVE) continue; // make sure that we don't nudge our self - + // handle player <-> player collision float Distance = distance(m_Pos, pCharCore->m_Pos); vec2 Dir = normalize(m_Pos - pCharCore->m_Pos); @@ -330,7 +330,7 @@ void CCharacterCore::Tick(bool UseInput) m_Vel += Dir*a*(Velocity*0.75f); m_Vel *= 0.85f; } - + // handle hook influence if(m_HookedPlayer == i) { @@ -338,7 +338,7 @@ void CCharacterCore::Tick(bool UseInput) { float Accel = m_pWorld->m_Tuning.m_HookDragAccel * (Distance/m_pWorld->m_Tuning.m_HookLength); float DragSpeed = m_pWorld->m_Tuning.m_HookDragSpeed; - + // add force to the hooked player pCharCore->m_Vel.x = SaturatedAdd(-DragSpeed, DragSpeed, pCharCore->m_Vel.x, Accel*Dir.x*1.5f); pCharCore->m_Vel.y = SaturatedAdd(-DragSpeed, DragSpeed, pCharCore->m_Vel.y, Accel*Dir.y*1.5f); @@ -349,7 +349,7 @@ void CCharacterCore::Tick(bool UseInput) } } } - } + } // clamp the velocity to something sane if(length(m_Vel) > 6000) @@ -359,9 +359,9 @@ void CCharacterCore::Tick(bool UseInput) void CCharacterCore::Move() { float RampValue = VelocityRamp(length(m_Vel)*50, m_pWorld->m_Tuning.m_VelrampStart, m_pWorld->m_Tuning.m_VelrampRange, m_pWorld->m_Tuning.m_VelrampCurvature); - + m_Vel.x = m_Vel.x*RampValue; - + vec2 NewPos = m_Pos; m_pCollision->MoveBox(&NewPos, &m_Vel, vec2(28.0f, 28.0f), 0); @@ -393,7 +393,7 @@ void CCharacterCore::Move() } } } - + m_Pos = NewPos; } @@ -401,7 +401,7 @@ void CCharacterCore::Write(CNetObj_CharacterCore *pObjCore) { pObjCore->m_X = round(m_Pos.x); pObjCore->m_Y = round(m_Pos.y); - + pObjCore->m_VelX = round(m_Vel.x*256.0f); pObjCore->m_VelY = round(m_Vel.y*256.0f); pObjCore->m_HookState = m_HookState; diff --git a/src/game/gamecore.h b/src/game/gamecore.h index 9e9ccf4de..611f5ed75 100644 --- a/src/game/gamecore.h +++ b/src/game/gamecore.h @@ -35,11 +35,11 @@ public: } static const char *m_apNames[]; - + #define MACRO_TUNING_PARAM(Name,ScriptName,Value) CTuneParam m_##Name; #include "tuning.h" #undef MACRO_TUNING_PARAM - + static int Num() { return sizeof(CTuningParams)/sizeof(int); } bool Set(int Index, float Value); bool Set(const char *pName, float Value); @@ -81,7 +81,7 @@ inline void StrToInts(int *pInts, int Num, const char *pStr) pInts++; Num--; } - + // null terminate pInts[-1] &= 0xffffff00; } @@ -98,7 +98,7 @@ inline void IntsToStr(const int *pInts, int Num, char *pStr) pInts++; Num--; } - + // null terminate pStr[-1] = 0; } @@ -150,7 +150,7 @@ enum HOOK_RETRACT_END=3, HOOK_FLYING, HOOK_GRABBED, - + COREEVENT_GROUND_JUMP=0x01, COREEVENT_AIR_JUMP=0x02, COREEVENT_HOOK_LAUNCH=0x04, @@ -167,7 +167,7 @@ public: { mem_zero(m_apCharacters, sizeof(m_apCharacters)); } - + CTuningParams m_Tuning; class CCharacterCore *m_apCharacters[MAX_CLIENTS]; }; @@ -179,26 +179,26 @@ class CCharacterCore public: vec2 m_Pos; vec2 m_Vel; - + vec2 m_HookPos; vec2 m_HookDir; int m_HookTick; int m_HookState; int m_HookedPlayer; - + int m_Jumped; - + int m_Direction; int m_Angle; CNetObj_PlayerInput m_Input; - + int m_TriggeredEvents; - + void Init(CWorldCore *pWorld, CCollision *pCollision); void Reset(); void Tick(bool UseInput); void Move(); - + void Read(const CNetObj_CharacterCore *pObjCore); void Write(CNetObj_CharacterCore *pObjCore); void Quantize(); diff --git a/src/game/layers.cpp b/src/game/layers.cpp index aafd3dd47..82c0a61b9 100644 --- a/src/game/layers.cpp +++ b/src/game/layers.cpp @@ -18,14 +18,14 @@ void CLayers::Init(class IKernel *pKernel) m_pMap = pKernel->RequestInterface(); m_pMap->GetType(MAPITEMTYPE_GROUP, &m_GroupsStart, &m_GroupsNum); m_pMap->GetType(MAPITEMTYPE_LAYER, &m_LayersStart, &m_LayersNum); - + for(int g = 0; g < NumGroups(); g++) { CMapItemGroup *pGroup = GetGroup(g); for(int l = 0; l < pGroup->m_NumLayers; l++) { CMapItemLayer *pLayer = GetLayer(pGroup->m_StartLayer+l); - + if(pLayer->m_Type == LAYERTYPE_TILES) { CMapItemLayerTilemap *pTilemap = reinterpret_cast(pLayer); @@ -39,7 +39,7 @@ void CLayers::Init(class IKernel *pKernel) m_pGameGroup->m_OffsetY = 0; m_pGameGroup->m_ParallaxX = 100; m_pGameGroup->m_ParallaxY = 100; - + if(m_pGameGroup->m_Version >= 2) { m_pGameGroup->m_UseClipping = 0; @@ -51,7 +51,7 @@ void CLayers::Init(class IKernel *pKernel) break; } - } + } } } } diff --git a/src/game/layers.h b/src/game/layers.h index 3f8eacaa1..5ddcd73e4 100644 --- a/src/game/layers.h +++ b/src/game/layers.h @@ -24,7 +24,7 @@ public: CMapItemGroup *GameGroup() const { return m_pGameGroup; }; CMapItemLayerTilemap *GameLayer() const { return m_pGameLayer; }; CMapItemGroup *GetGroup(int Index) const; - CMapItemLayer *GetLayer(int Index) const; + CMapItemLayer *GetLayer(int Index) const; }; #endif diff --git a/src/game/localization.cpp b/src/game/localization.cpp index 698963007..8ab8831d0 100644 --- a/src/game/localization.cpp +++ b/src/game/localization.cpp @@ -53,16 +53,16 @@ bool CLocalizationDatabase::Load(const char *pFilename, IStorage *pStorage, ICon m_CurrentVersion = 0; return true; } - + IOHANDLE IoHandle = pStorage->OpenFile(pFilename, IOFLAG_READ, IStorage::TYPE_ALL); if(!IoHandle) return false; - + char aBuf[256]; str_format(aBuf, sizeof(aBuf), "loaded '%s'", pFilename); pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "localization", aBuf); m_Strings.clear(); - + char aOrigin[512]; CLineReader LineReader; LineReader.Init(IoHandle); @@ -71,10 +71,10 @@ bool CLocalizationDatabase::Load(const char *pFilename, IStorage *pStorage, ICon { if(!str_length(pLine)) continue; - + if(pLine[0] == '#') // skip comments continue; - + str_copy(aOrigin, pLine, sizeof(aOrigin)); char *pReplacement = LineReader.Get(); if(!pReplacement) @@ -82,7 +82,7 @@ bool CLocalizationDatabase::Load(const char *pFilename, IStorage *pStorage, ICon pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "localization", "unexpected end of file"); break; } - + if(pReplacement[0] != '=' || pReplacement[1] != '=' || pReplacement[2] != ' ') { str_format(aBuf, sizeof(aBuf), "malform replacement line for '%s'", aOrigin); @@ -94,7 +94,7 @@ bool CLocalizationDatabase::Load(const char *pFilename, IStorage *pStorage, ICon AddString(aOrigin, pReplacement); } io_close(IoHandle); - + m_CurrentVersion = ++m_VersionCounter; return true; } diff --git a/src/game/localization.h b/src/game/localization.h index 277d637e6..49edd8602 100644 --- a/src/game/localization.h +++ b/src/game/localization.h @@ -11,7 +11,7 @@ class CLocalizationDatabase { public: unsigned m_Hash; - + // TODO: do this as an const char * and put everything on a incremental heap string m_Replacement; @@ -23,14 +23,14 @@ class CLocalizationDatabase sorted_array m_Strings; int m_VersionCounter; int m_CurrentVersion; - + public: CLocalizationDatabase(); bool Load(const char *pFilename, class IStorage *pStorage, class IConsole *pConsole); int Version() { return m_CurrentVersion; } - + void AddString(const char *pOrgStr, const char *pNewStr); const char *FindString(unsigned Hash); }; @@ -46,7 +46,7 @@ class CLocConstString public: CLocConstString(const char *pStr); void Reload(); - + inline operator const char *() { if(m_Version != g_Localization.Version()) diff --git a/src/game/mapitems.h b/src/game/mapitems.h index 31f7299fd..d99d6724f 100644 --- a/src/game/mapitems.h +++ b/src/game/mapitems.h @@ -10,7 +10,7 @@ enum LAYERTYPE_GAME, // not used LAYERTYPE_TILES, LAYERTYPE_QUADS, - + MAPITEMTYPE_VERSION=0, MAPITEMTYPE_INFO, MAPITEMTYPE_IMAGE, @@ -18,7 +18,7 @@ enum MAPITEMTYPE_GROUP, MAPITEMTYPE_LAYER, MAPITEMTYPE_ENVPOINTS, - + CURVETYPE_STEP=0, CURVETYPE_LINEAR, @@ -26,7 +26,7 @@ enum CURVETYPE_FAST, CURVETYPE_SMOOTH, NUM_CURVETYPES, - + // game layer tiles ENTITY_NULL=0, ENTITY_SPAWN, @@ -41,19 +41,19 @@ enum ENTITY_POWERUP_NINJA, ENTITY_WEAPON_RIFLE, NUM_ENTITIES, - + TILE_AIR=0, TILE_SOLID, TILE_DEATH, TILE_NOHOOK, - + TILEFLAG_VFLIP=1, TILEFLAG_HFLIP=2, TILEFLAG_OPAQUE=4, TILEFLAG_ROTATE=8, - + LAYERFLAG_DETAIL=1, - + ENTITY_OFFSET=255-16*4, }; @@ -72,10 +72,10 @@ struct CQuad CPoint m_aPoints[5]; CColor m_aColors[4]; CPoint m_aTexcoords[4]; - + int m_PosEnv; int m_PosEnvOffset; - + int m_ColorEnv; int m_ColorEnvOffset; }; @@ -115,7 +115,7 @@ struct CMapItemGroup_v1 struct CMapItemGroup : public CMapItemGroup_v1 { enum { CURRENT_VERSION=2 }; - + int m_UseClipping; int m_ClipX; int m_ClipY; @@ -134,15 +134,15 @@ struct CMapItemLayerTilemap { CMapItemLayer m_Layer; int m_Version; - + int m_Width; int m_Height; int m_Flags; - + CColor m_Color; int m_ColorEnv; int m_ColorEnvOffset; - + int m_Image; int m_Data; } ; @@ -151,7 +151,7 @@ struct CMapItemLayerQuads { CMapItemLayer m_Layer; int m_Version; - + int m_NumQuads; int m_Data; int m_Image; @@ -167,7 +167,7 @@ struct CEnvPoint int m_Time; // in ms int m_Curvetype; int m_aValues[4]; // 1-4 depending on envelope (22.10 fixed point) - + bool operator<(const CEnvPoint &Other) { return m_Time < Other.m_Time; } } ; diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index b40e768b7..821aade58 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -22,7 +22,7 @@ CInputCount CountInput(int Prev, int Cur) Prev &= INPUT_STATE_MASK; Cur &= INPUT_STATE_MASK; int i = Prev; - + while(i != Cur) { i = (i+1)&INPUT_STATE_MASK; @@ -59,10 +59,10 @@ bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos) m_ActiveWeapon = WEAPON_GUN; m_LastWeapon = WEAPON_HAMMER; m_QueuedWeapon = -1; - + m_pPlayer = pPlayer; m_Pos = Pos; - + m_Core.Reset(); m_Core.Init(&GameServer()->m_World.m_Core, GameServer()->Collision()); m_Core.m_Pos = m_Pos; @@ -71,7 +71,7 @@ bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos) m_ReckoningTick = 0; mem_zero(&m_SendCore, sizeof(m_SendCore)); mem_zero(&m_ReckoningCore, sizeof(m_ReckoningCore)); - + GameServer()->m_World.InsertEntity(this); m_Alive = true; @@ -90,12 +90,12 @@ void CCharacter::SetWeapon(int W) { if(W == m_ActiveWeapon) return; - + m_LastWeapon = m_ActiveWeapon; m_QueuedWeapon = -1; m_ActiveWeapon = W; GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SWITCH); - + if(m_ActiveWeapon < 0 || m_ActiveWeapon >= NUM_WEAPONS) m_ActiveWeapon = 0; } @@ -114,7 +114,7 @@ void CCharacter::HandleNinja() { if(m_ActiveWeapon != WEAPON_NINJA) return; - + vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY)); if ((Server()->Tick() - m_Ninja.m_ActivationTick) > (g_pData->m_Weapons.m_Ninja.m_Duration * Server()->TickSpeed() / 1000)) @@ -124,11 +124,11 @@ void CCharacter::HandleNinja() m_ActiveWeapon = m_LastWeapon; if(m_ActiveWeapon == WEAPON_NINJA) m_ActiveWeapon = WEAPON_GUN; - + SetWeapon(m_ActiveWeapon); return; } - + // force ninja Weapon SetWeapon(WEAPON_NINJA); @@ -146,7 +146,7 @@ void CCharacter::HandleNinja() m_Core.m_Vel = m_Ninja.m_ActivationDir * g_pData->m_Weapons.m_Ninja.m_Velocity; vec2 OldPos = m_Pos; GameServer()->Collision()->MoveBox(&m_Core.m_Pos, &m_Core.m_Vel, vec2(m_ProximityRadius, m_ProximityRadius), 0.f); - + // reset velocity so the client doesn't predict stuff m_Core.m_Vel = vec2(0.f, 0.f); @@ -162,7 +162,7 @@ void CCharacter::HandleNinja() { if (aEnts[i] == this) continue; - + // make sure we haven't Hit this object before bool bAlreadyHit = false; for (int j = 0; j < m_NumObjectsHit; j++) @@ -182,11 +182,11 @@ void CCharacter::HandleNinja() // set his velocity to fast upward (for now) if(m_NumObjectsHit < 10) m_apHitObjects[m_NumObjectsHit++] = aEnts[i]; - + aEnts[i]->TakeDamage(vec2(0, 10.0f), g_pData->m_Weapons.m_Ninja.m_pBase->m_Damage, m_pPlayer->GetCID(), WEAPON_NINJA); } } - + return; } @@ -209,7 +209,7 @@ void CCharacter::HandleWeaponSwitch() int WantedWeapon = m_ActiveWeapon; if(m_QueuedWeapon != -1) WantedWeapon = m_QueuedWeapon; - + // select Weapon int Next = CountInput(m_LatestPrevInput.m_NextWeapon, m_LatestInput.m_NextWeapon).m_Presses; int Prev = CountInput(m_LatestPrevInput.m_PrevWeapon, m_LatestInput.m_PrevWeapon).m_Presses; @@ -241,7 +241,7 @@ void CCharacter::HandleWeaponSwitch() // check for insane values if(WantedWeapon >= 0 && WantedWeapon < NUM_WEAPONS && WantedWeapon != m_ActiveWeapon && m_aWeapons[WantedWeapon].m_Got) m_QueuedWeapon = WantedWeapon; - + DoWeaponSwitch(); } @@ -249,10 +249,10 @@ void CCharacter::FireWeapon() { if(m_ReloadTimer != 0) return; - + DoWeaponSwitch(); vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY)); - + bool FullAuto = false; if(m_ActiveWeapon == WEAPON_GRENADE || m_ActiveWeapon == WEAPON_SHOTGUN || m_ActiveWeapon == WEAPON_RIFLE) FullAuto = true; @@ -262,13 +262,13 @@ void CCharacter::FireWeapon() bool WillFire = false; if(CountInput(m_LatestPrevInput.m_Fire, m_LatestInput.m_Fire).m_Presses) WillFire = true; - + if(FullAuto && (m_LatestInput.m_Fire&1) && m_aWeapons[m_ActiveWeapon].m_Ammo) WillFire = true; - + if(!WillFire) return; - + // check for ammo if(!m_aWeapons[m_ActiveWeapon].m_Ammo) { @@ -277,9 +277,9 @@ void CCharacter::FireWeapon() GameServer()->CreateSound(m_Pos, SOUND_WEAPON_NOAMMO); return; } - + vec2 ProjStartPos = m_Pos+Direction*m_ProximityRadius*0.75f; - + switch(m_ActiveWeapon) { case WEAPON_HAMMER: @@ -287,16 +287,16 @@ void CCharacter::FireWeapon() // reset objects Hit m_NumObjectsHit = 0; GameServer()->CreateSound(m_Pos, SOUND_HAMMER_FIRE); - + CCharacter *apEnts[MAX_CLIENTS]; int Hits = 0; - int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)apEnts, + int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)apEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); for (int i = 0; i < Num; ++i) { CCharacter *pTarget = apEnts[i]; - + if ((pTarget == this) || GameServer()->Collision()->IntersectLine(ProjStartPos, pTarget->m_Pos, NULL, NULL)) continue; @@ -305,22 +305,22 @@ void CCharacter::FireWeapon() GameServer()->CreateHammerHit(pTarget->m_Pos-normalize(pTarget->m_Pos-ProjStartPos)*m_ProximityRadius*0.5f); else GameServer()->CreateHammerHit(ProjStartPos); - + vec2 Dir; if (length(pTarget->m_Pos - m_Pos) > 0.0f) Dir = normalize(pTarget->m_Pos - m_Pos); else Dir = vec2(0.f, -1.f); - + pTarget->TakeDamage(vec2(0.f, -1.f) + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f, g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage, m_pPlayer->GetCID(), m_ActiveWeapon); Hits++; } - + // if we Hit anything, we have to wait for the reload if(Hits) m_ReloadTimer = Server()->TickSpeed()/3; - + } break; case WEAPON_GUN: @@ -331,28 +331,28 @@ void CCharacter::FireWeapon() Direction, (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GunLifetime), 1, 0, 0, -1, WEAPON_GUN); - + // pack the Projectile and send it to the client Directly CNetObj_Projectile p; pProj->FillInfo(&p); - + CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); Msg.AddInt(1); for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) Msg.AddInt(((int *)&p)[i]); - + Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID()); - + GameServer()->CreateSound(m_Pos, SOUND_GUN_FIRE); } break; - + case WEAPON_SHOTGUN: { int ShotSpread = 2; CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); Msg.AddInt(ShotSpread*2+1); - + for(int i = -ShotSpread; i <= ShotSpread; ++i) { float Spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f}; @@ -366,17 +366,17 @@ void CCharacter::FireWeapon() vec2(cosf(a), sinf(a))*Speed, (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime), 1, 0, 0, -1, WEAPON_SHOTGUN); - + // pack the Projectile and send it to the client Directly CNetObj_Projectile p; pProj->FillInfo(&p); - + for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) Msg.AddInt(((int *)&p)[i]); } - Server()->SendMsg(&Msg, 0,m_pPlayer->GetCID()); - + Server()->SendMsg(&Msg, 0,m_pPlayer->GetCID()); + GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE); } break; @@ -392,41 +392,41 @@ void CCharacter::FireWeapon() // pack the Projectile and send it to the client Directly CNetObj_Projectile p; pProj->FillInfo(&p); - + CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); Msg.AddInt(1); for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) Msg.AddInt(((int *)&p)[i]); Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID()); - + GameServer()->CreateSound(m_Pos, SOUND_GRENADE_FIRE); } break; - + case WEAPON_RIFLE: { new CLaser(GameWorld(), m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID()); GameServer()->CreateSound(m_Pos, SOUND_RIFLE_FIRE); } break; - + case WEAPON_NINJA: { // reset Hit objects m_NumObjectsHit = 0; - + m_Ninja.m_ActivationDir = Direction; m_Ninja.m_CurrentMoveTime = g_pData->m_Weapons.m_Ninja.m_Movetime * Server()->TickSpeed() / 1000; m_Ninja.m_OldVelAmount = length(m_Core.m_Vel); GameServer()->CreateSound(m_Pos, SOUND_NINJA_FIRE); } break; - + } - + m_AttackTick = Server()->Tick(); - + if(m_aWeapons[m_ActiveWeapon].m_Ammo > 0) // -1 == unlimited m_aWeapons[m_ActiveWeapon].m_Ammo--; - + if(!m_ReloadTimer) m_ReloadTimer = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Firedelay * Server()->TickSpeed() / 1000; } @@ -435,7 +435,7 @@ void CCharacter::HandleWeapons() { //ninja HandleNinja(); - + vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY)); // check reload timer @@ -470,14 +470,14 @@ void CCharacter::HandleWeapons() m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1; } } - + return; } bool CCharacter::GiveWeapon(int Weapon, int Ammo) { if(m_aWeapons[Weapon].m_Ammo < g_pData->m_Weapons.m_aId[Weapon].m_Maxammo || !m_aWeapons[Weapon].m_Got) - { + { m_aWeapons[Weapon].m_Got = true; m_aWeapons[Weapon].m_Ammo = min(g_pData->m_Weapons.m_aId[Weapon].m_Maxammo, Ammo); return true; @@ -492,7 +492,7 @@ void CCharacter::GiveNinja() m_aWeapons[WEAPON_NINJA].m_Ammo = -1; m_LastWeapon = m_ActiveWeapon; m_ActiveWeapon = WEAPON_NINJA; - + GameServer()->CreateSound(m_Pos, SOUND_PICKUP_NINJA); } @@ -507,27 +507,27 @@ void CCharacter::OnPredictedInput(CNetObj_PlayerInput *pNewInput) // check for changes if(mem_comp(&m_Input, pNewInput, sizeof(CNetObj_PlayerInput)) != 0) m_LastAction = Server()->Tick(); - + // copy new input mem_copy(&m_Input, pNewInput, sizeof(m_Input)); m_NumInputs++; - + // or are not allowed to aim in the center if(m_Input.m_TargetX == 0 && m_Input.m_TargetY == 0) - m_Input.m_TargetY = -1; + m_Input.m_TargetY = -1; } void CCharacter::OnDirectInput(CNetObj_PlayerInput *pNewInput) { mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput)); mem_copy(&m_LatestInput, pNewInput, sizeof(m_LatestInput)); - + if(m_NumInputs > 2 && m_pPlayer->GetTeam() != TEAM_SPECTATORS) { HandleWeaponSwitch(); FireWeapon(); } - + mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput)); } @@ -538,13 +538,13 @@ void CCharacter::Tick() char Buf[128]; str_format(Buf, sizeof(Buf), "You were moved to %s due to team balancing", GameServer()->m_pController->GetTeamName(m_pPlayer->GetTeam())); GameServer()->SendBroadcast(Buf, m_pPlayer->GetCID()); - + m_pPlayer->m_ForceBalanced = false; } m_Core.m_Input = m_Input; m_Core.Tick(true); - + // handle death-tiles and leaving gamelayer if(GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH || @@ -554,7 +554,7 @@ void CCharacter::Tick() { Die(m_pPlayer->GetCID(), WEAPON_WORLD); } - + // handle Weapons HandleWeapons(); @@ -573,18 +573,18 @@ void CCharacter::TickDefered() m_ReckoningCore.Move(); m_ReckoningCore.Quantize(); } - + //lastsentcore vec2 StartPos = m_Core.m_Pos; vec2 StartVel = m_Core.m_Vel; bool StuckBefore = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f)); - + m_Core.Move(); bool StuckAfterMove = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f)); m_Core.Quantize(); bool StuckAfterQuant = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f)); m_Pos = m_Core.m_Pos; - + if(!StuckBefore && (StuckAfterMove || StuckAfterQuant)) { // Hackish solution to get rid of strict-aliasing warning @@ -600,7 +600,7 @@ void CCharacter::TickDefered() StartVelY.f = StartVel.y; char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x", + str_format(aBuf, sizeof(aBuf), "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x", StuckBefore, StuckAfterMove, StuckAfterQuant, @@ -613,20 +613,20 @@ void CCharacter::TickDefered() int Events = m_Core.m_TriggeredEvents; int Mask = CmaskAllExceptOne(m_pPlayer->GetCID()); - + if(Events&COREEVENT_GROUND_JUMP) GameServer()->CreateSound(m_Pos, SOUND_PLAYER_JUMP, Mask); - + if(Events&COREEVENT_HOOK_ATTACH_PLAYER) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_PLAYER, CmaskAll()); if(Events&COREEVENT_HOOK_ATTACH_GROUND) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_GROUND, Mask); if(Events&COREEVENT_HOOK_HIT_NOHOOK) GameServer()->CreateSound(m_Pos, SOUND_HOOK_NOATTACH, Mask); - + if(m_pPlayer->GetTeam() == TEAM_SPECTATORS) { m_Pos.x = m_Input.m_TargetX; m_Pos.y = m_Input.m_TargetY; } - + // update the m_SendCore if needed { CNetObj_Character Predicted; @@ -684,10 +684,10 @@ void CCharacter::Die(int Killer, int Weapon) // a nice sound GameServer()->CreateSound(m_Pos, SOUND_PLAYER_DIE); - + // this is for auto respawn after 3 secs m_pPlayer->m_DieTick = Server()->Tick(); - + m_Alive = false; GameServer()->m_World.RemoveEntity(this); GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = 0; @@ -697,7 +697,7 @@ void CCharacter::Die(int Killer, int Weapon) bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon) { m_Core.m_Vel += Force; - + if(GameServer()->m_pController->IsFriendlyFire(m_pPlayer->GetCID(), From) && !g_Config.m_SvTeamdamage) return false; @@ -728,7 +728,7 @@ bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon) m_Health--; Dmg--; } - + if(Dmg > m_Armor) { Dmg -= m_Armor; @@ -740,7 +740,7 @@ bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon) Dmg = 0; } } - + m_Health -= Dmg; } @@ -754,7 +754,7 @@ bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon) if(m_Health <= 0) { Die(From, Weapon); - + // set attacker's face to happy (taunt!) if (From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From]) { @@ -765,7 +765,7 @@ bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon) pChr->m_EmoteStop = Server()->Tick() + Server()->TickSpeed(); } } - + return false; } @@ -784,11 +784,11 @@ void CCharacter::Snap(int SnappingClient) { if(NetworkClipped(SnappingClient)) return; - + CNetObj_Character *pCharacter = static_cast(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, m_pPlayer->GetCID(), sizeof(CNetObj_Character))); if(!pCharacter) return; - + // write down the m_Core if(!m_ReckoningTick || GameServer()->m_World.m_Paused) { @@ -802,7 +802,7 @@ void CCharacter::Snap(int SnappingClient) pCharacter->m_Tick = m_ReckoningTick; m_SendCore.Write(pCharacter); } - + // set emote if (m_EmoteStop < Server()->Tick()) { @@ -815,7 +815,7 @@ void CCharacter::Snap(int SnappingClient) pCharacter->m_AmmoCount = 0; pCharacter->m_Health = 0; pCharacter->m_Armor = 0; - + pCharacter->m_Weapon = m_ActiveWeapon; pCharacter->m_AttackTick = m_AttackTick; diff --git a/src/game/server/entities/character.h b/src/game/server/entities/character.h index b40090581..611dc4278 100644 --- a/src/game/server/entities/character.h +++ b/src/game/server/entities/character.h @@ -19,25 +19,25 @@ enum class CCharacter : public CEntity { MACRO_ALLOC_POOL_ID() - + public: //character's size static const int ms_PhysSize = 28; CCharacter(CGameWorld *pWorld); - + virtual void Reset(); virtual void Destroy(); virtual void Tick(); virtual void TickDefered(); virtual void Snap(int SnappingClient); - + bool IsGrounded(); - + void SetWeapon(int W); void HandleWeaponSwitch(); void DoWeaponSwitch(); - + void HandleWeapons(); void HandleNinja(); @@ -46,53 +46,53 @@ public: void FireWeapon(); void Die(int Killer, int Weapon); - bool TakeDamage(vec2 Force, int Dmg, int From, int Weapon); + bool TakeDamage(vec2 Force, int Dmg, int From, int Weapon); bool Spawn(class CPlayer *pPlayer, vec2 Pos); bool Remove(); - + bool IncreaseHealth(int Amount); bool IncreaseArmor(int Amount); - + bool GiveWeapon(int Weapon, int Ammo); void GiveNinja(); - + void SetEmote(int Emote, int Tick); - + bool IsAlive() const { return m_Alive; } class CPlayer *GetPlayer() { return m_pPlayer; } - + private: // player controlling this character class CPlayer *m_pPlayer; - + bool m_Alive; // weapon info CEntity *m_apHitObjects[10]; int m_NumObjectsHit; - + struct WeaponStat { int m_AmmoRegenStart; int m_Ammo; int m_Ammocost; bool m_Got; - + } m_aWeapons[NUM_WEAPONS]; - + int m_ActiveWeapon; int m_LastWeapon; int m_QueuedWeapon; - + int m_ReloadTimer; int m_AttackTick; - + int m_DamageTaken; int m_EmoteType; int m_EmoteStop; - + // last tick that the player took any action ie some input int m_LastAction; @@ -100,12 +100,12 @@ private: CNetObj_PlayerInput m_LatestPrevInput; CNetObj_PlayerInput m_LatestInput; - // input + // input CNetObj_PlayerInput m_PrevInput; CNetObj_PlayerInput m_Input; int m_NumInputs; int m_Jumped; - + int m_DamageTakenTick; int m_Health; @@ -120,9 +120,9 @@ private: int m_OldVelAmount; } m_Ninja; - // the player core for the physics + // the player core for the physics CCharacterCore m_Core; - + // info for dead reckoning int m_ReckoningTick; // tick that we are performing dead reckoning From CCharacterCore m_SendCore; // core that we should send diff --git a/src/game/server/entities/flag.cpp b/src/game/server/entities/flag.cpp index 5ac3de473..d279e4dfe 100644 --- a/src/game/server/entities/flag.cpp +++ b/src/game/server/entities/flag.cpp @@ -10,7 +10,7 @@ CFlag::CFlag(CGameWorld *pGameWorld, int Team) m_ProximityRadius = ms_PhysSize; m_pCarryingCharacter = NULL; m_GrabTick = 0; - + Reset(); } diff --git a/src/game/server/entities/flag.h b/src/game/server/entities/flag.h index 89f5e2c55..2f91bc02e 100644 --- a/src/game/server/entities/flag.h +++ b/src/game/server/entities/flag.h @@ -12,12 +12,12 @@ public: CCharacter *m_pCarryingCharacter; vec2 m_Vel; vec2 m_StandPos; - + int m_Team; int m_AtStand; int m_DropTick; int m_GrabTick; - + CFlag(CGameWorld *pGameWorld, int Team); virtual void Reset(); diff --git a/src/game/server/entities/laser.cpp b/src/game/server/entities/laser.cpp index 184702cb2..30ed0a9b5 100644 --- a/src/game/server/entities/laser.cpp +++ b/src/game/server/entities/laser.cpp @@ -28,7 +28,7 @@ bool CLaser::HitCharacter(vec2 From, vec2 To) m_From = From; m_Pos = At; - m_Energy = -1; + m_Energy = -1; Hit->TakeDamage(vec2(0.f, 0.f), GameServer()->Tuning()->m_LaserDamage, m_Owner, WEAPON_RIFLE); return true; } @@ -36,16 +36,16 @@ bool CLaser::HitCharacter(vec2 From, vec2 To) void CLaser::DoBounce() { m_EvalTick = Server()->Tick(); - + if(m_Energy < 0) { GameServer()->m_World.DestroyEntity(this); return; } - + vec2 To = m_Pos + m_Dir * m_Energy; vec2 OrgTo = To; - + if(GameServer()->Collision()->IntersectLine(m_Pos, To, 0x0, &To)) { if(!HitCharacter(m_Pos, To)) @@ -56,17 +56,17 @@ void CLaser::DoBounce() vec2 TempPos = m_Pos; vec2 TempDir = m_Dir * 4.0f; - + GameServer()->Collision()->MovePoint(&TempPos, &TempDir, 1.0f, 0); m_Pos = TempPos; m_Dir = normalize(TempDir); - + m_Energy -= distance(m_From, m_Pos) + GameServer()->Tuning()->m_LaserBounceCost; m_Bounces++; - + if(m_Bounces > GameServer()->Tuning()->m_LaserBounceNum) m_Energy = -1; - + GameServer()->CreateSound(m_Pos, SOUND_RIFLE_BOUNCE); } } @@ -80,7 +80,7 @@ void CLaser::DoBounce() } } } - + void CLaser::Reset() { GameServer()->m_World.DestroyEntity(this); diff --git a/src/game/server/entities/laser.h b/src/game/server/entities/laser.h index 91ba5df67..1d7fa2271 100644 --- a/src/game/server/entities/laser.h +++ b/src/game/server/entities/laser.h @@ -9,15 +9,15 @@ class CLaser : public CEntity { public: CLaser(CGameWorld *pGameWorld, vec2 Pos, vec2 Direction, float StartEnergy, int Owner); - + virtual void Reset(); virtual void Tick(); virtual void Snap(int SnappingClient); - + protected: bool HitCharacter(vec2 From, vec2 To); void DoBounce(); - + private: vec2 m_From; vec2 m_Dir; diff --git a/src/game/server/entities/pickup.cpp b/src/game/server/entities/pickup.cpp index 56b319d27..ba26d85b2 100644 --- a/src/game/server/entities/pickup.cpp +++ b/src/game/server/entities/pickup.cpp @@ -12,7 +12,7 @@ CPickup::CPickup(CGameWorld *pGameWorld, int Type, int SubType) m_ProximityRadius = PickupPhysSize; Reset(); - + GameWorld()->InsertEntity(this); } @@ -55,7 +55,7 @@ void CPickup::Tick() RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; } break; - + case POWERUP_ARMOR: if(pChr->IncreaseArmor(1)) { @@ -83,7 +83,7 @@ void CPickup::Tick() } } break; - + case POWERUP_NINJA: { // activate ninja on target player @@ -101,7 +101,7 @@ void CPickup::Tick() pChr->SetEmote(EMOTE_ANGRY, Server()->Tick() + 1200 * Server()->TickSpeed() / 1000); break; } - + default: break; }; diff --git a/src/game/server/entities/pickup.h b/src/game/server/entities/pickup.h index 47a8ed6f0..77347de20 100644 --- a/src/game/server/entities/pickup.h +++ b/src/game/server/entities/pickup.h @@ -11,11 +11,11 @@ class CPickup : public CEntity { public: CPickup(CGameWorld *pGameWorld, int Type, int SubType = 0); - + virtual void Reset(); virtual void Tick(); virtual void Snap(int SnappingClient); - + private: int m_Type; int m_Subtype; diff --git a/src/game/server/entities/projectile.cpp b/src/game/server/entities/projectile.cpp index 07e966274..2baa24b12 100644 --- a/src/game/server/entities/projectile.cpp +++ b/src/game/server/entities/projectile.cpp @@ -32,25 +32,25 @@ vec2 CProjectile::GetPos(float Time) { float Curvature = 0; float Speed = 0; - + switch(m_Type) { case WEAPON_GRENADE: Curvature = GameServer()->Tuning()->m_GrenadeCurvature; Speed = GameServer()->Tuning()->m_GrenadeSpeed; break; - + case WEAPON_SHOTGUN: Curvature = GameServer()->Tuning()->m_ShotgunCurvature; Speed = GameServer()->Tuning()->m_ShotgunSpeed; break; - + case WEAPON_GUN: Curvature = GameServer()->Tuning()->m_GunCurvature; Speed = GameServer()->Tuning()->m_GunSpeed; break; } - + return CalcPos(m_Pos, m_Direction, Curvature, Speed, Time); } @@ -66,7 +66,7 @@ void CProjectile::Tick() CCharacter *TargetChr = GameServer()->m_World.IntersectCharacter(PrevPos, CurPos, 6.0f, CurPos, OwnerChar); m_LifeSpan--; - + if(TargetChr || Collide || m_LifeSpan < 0 || GameLayerClipped(CurPos)) { if(m_LifeSpan >= 0 || m_Weapon == WEAPON_GRENADE) @@ -74,7 +74,7 @@ void CProjectile::Tick() if(m_Explosive) GameServer()->CreateExplosion(CurPos, m_Owner, m_Weapon, false); - + else if(TargetChr) TargetChr->TakeDamage(m_Direction * max(0.001f, m_Force), m_Damage, m_Owner, m_Weapon); @@ -95,7 +95,7 @@ void CProjectile::FillInfo(CNetObj_Projectile *pProj) void CProjectile::Snap(int SnappingClient) { float Ct = (Server()->Tick()-m_StartTick)/(float)Server()->TickSpeed(); - + if(NetworkClipped(SnappingClient, GetPos(Ct))) return; diff --git a/src/game/server/entities/projectile.h b/src/game/server/entities/projectile.h index 5e5340667..5df04bcd0 100644 --- a/src/game/server/entities/projectile.h +++ b/src/game/server/entities/projectile.h @@ -15,7 +15,7 @@ public: virtual void Reset(); virtual void Tick(); virtual void Snap(int SnappingClient); - + private: vec2 m_Direction; int m_LifeSpan; diff --git a/src/game/server/entity.cpp b/src/game/server/entity.cpp index 03b559824..788c3f45b 100644 --- a/src/game/server/entity.cpp +++ b/src/game/server/entity.cpp @@ -10,12 +10,12 @@ CEntity::CEntity(CGameWorld *pGameWorld, int ObjType) { m_pGameWorld = pGameWorld; - + m_ObjType = ObjType; m_Pos = vec2(0,0); m_ProximityRadius = 0; - m_MarkedForDestroy = false; + m_MarkedForDestroy = false; m_ID = Server()->SnapNewID(); m_pPrevTypeEntity = 0; @@ -37,13 +37,13 @@ int CEntity::NetworkClipped(int SnappingClient, vec2 CheckPos) { if(SnappingClient == -1) return 0; - + float dx = GameServer()->m_apPlayers[SnappingClient]->m_ViewPos.x-CheckPos.x; float dy = GameServer()->m_apPlayers[SnappingClient]->m_ViewPos.y-CheckPos.y; - + if(absolute(dx) > 1000.0f || absolute(dy) > 800.0f) return 1; - + if(distance(GameServer()->m_apPlayers[SnappingClient]->m_ViewPos, CheckPos) > 1100.0f) return 1; return 0; diff --git a/src/game/server/entity.h b/src/game/server/entity.h index ff4d82eb7..b9b33eb73 100644 --- a/src/game/server/entity.h +++ b/src/game/server/entity.h @@ -28,7 +28,7 @@ void *operator new(size_t Size, int id); \ void operator delete(void *p); \ private: - + #define MACRO_ALLOC_POOL_ID_IMPL(POOLTYPE, PoolSize) \ static char ms_PoolData##POOLTYPE[PoolSize][sizeof(POOLTYPE)] = {{0}}; \ static int ms_PoolUsed##POOLTYPE[PoolSize] = {0}; \ @@ -49,7 +49,7 @@ ms_PoolUsed##POOLTYPE[id] = 0; \ mem_zero(ms_PoolData##POOLTYPE[id], sizeof(POOLTYPE)); \ } - + /* Class: Entity Basic entity class. @@ -61,7 +61,7 @@ class CEntity friend class CGameWorld; // entity list handling CEntity *m_pPrevTypeEntity; CEntity *m_pNextTypeEntity; - + class CGameWorld *m_pGameWorld; protected: bool m_MarkedForDestroy; @@ -70,12 +70,12 @@ protected: public: CEntity(CGameWorld *pGameWorld, int Objtype); virtual ~CEntity(); - + class CGameWorld *GameWorld() { return m_pGameWorld; } class CGameContext *GameServer() { return GameWorld()->GameServer(); } class IServer *Server() { return GameWorld()->Server(); } - - + + CEntity *TypeNext() { return m_pNextTypeEntity; } CEntity *TypePrev() { return m_pPrevTypeEntity; } @@ -84,14 +84,14 @@ public: Destorys the entity. */ virtual void Destroy() { delete this; } - + /* Function: reset Called when the game resets the map. Puts the entity back to it's starting state or perhaps destroys it. */ virtual void Reset() {} - + /* Function: tick Called progress the entity to the next tick. Updates @@ -104,12 +104,12 @@ public: Called after all entities tick() function has been called. */ virtual void TickDefered() {} - + /* Function: snap Called when a new snapshot is being generated for a specific client. - + Arguments: snapping_client - ID of the client which snapshot is being generated. Could be -1 to create a complete @@ -117,7 +117,7 @@ public: recording. */ virtual void Snap(int SnappingClient) {} - + /* Function: networkclipped(int snapping_client) Performs a series of test to see if a client can see the @@ -128,13 +128,13 @@ public: being generated. Could be -1 to create a complete snapshot of everything in the game for demo recording. - + Returns: Non-zero if the entity doesn't have to be in the snapshot. */ int NetworkClipped(int SnappingClient); int NetworkClipped(int SnappingClient, vec2 CheckPos); - + bool GameLayerClipped(vec2 CheckPos); /* @@ -142,7 +142,7 @@ public: Contains the physical size of the entity. */ float m_ProximityRadius; - + /* Variable: pos Contains the current posititon of the entity. diff --git a/src/game/server/eventhandler.h b/src/game/server/eventhandler.h index ea9fcb152..721b59afa 100644 --- a/src/game/server/eventhandler.h +++ b/src/game/server/eventhandler.h @@ -9,20 +9,20 @@ class CEventHandler static const int MAX_EVENTS = 128; static const int MAX_DATASIZE = 128*64; - int m_aTypes[MAX_EVENTS]; // TODO: remove some of these arrays + int m_aTypes[MAX_EVENTS]; // TODO: remove some of these arrays int m_aOffsets[MAX_EVENTS]; int m_aSizes[MAX_EVENTS]; int m_aClientMasks[MAX_EVENTS]; char m_aData[MAX_DATASIZE]; - + class CGameContext *m_pGameServer; - + int m_CurrentOffset; int m_NumEvents; public: CGameContext *GameServer() const { return m_pGameServer; } void SetGameServer(CGameContext *pGameServer); - + CEventHandler(); void *Create(int Type, int Size, int Mask = -1); void Clear(); diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index a0c1c64a4..82adcbefb 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -24,10 +24,10 @@ void CGameContext::Construct(int Resetting) { m_Resetting = 0; m_pServer = 0; - + for(int i = 0; i < MAX_CLIENTS; i++) m_apPlayers[i] = 0; - + m_pController = 0; m_VoteCloseTime = 0; m_pVoteOptionFirst = 0; @@ -241,7 +241,7 @@ void CGameContext::SendChat(int ChatterClientID, int Team, const char *pText) Msg.m_Team = 1; Msg.m_ClientID = ChatterClientID; Msg.m_pMessage = pText; - + // pack one for the recording only Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NOSEND, -1); @@ -277,7 +277,7 @@ void CGameContext::SendBroadcast(const char *pText, int ClientID) Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID); } -// +// void CGameContext::StartVote(const char *pDesc, const char *pCommand, const char *pReason) { // check if a vote is already running @@ -294,7 +294,7 @@ void CGameContext::StartVote(const char *pDesc, const char *pCommand, const char m_apPlayers[i]->m_VotePos = 0; } } - + // start vote m_VoteCloseTime = time_get() + time_freq()*25; str_copy(m_aVoteDescription, pDesc, sizeof(m_aVoteDescription)); @@ -338,7 +338,7 @@ void CGameContext::SendVoteStatus(int ClientID, int Total, int Yes, int No) Msg.m_Pass = Total - (Yes+No); Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID); - + } void CGameContext::AbortVoteKickOnDisconnect(int ClientID) @@ -353,7 +353,7 @@ void CGameContext::CheckPureTuning() // might not be created yet during start up if(!m_pController) return; - + if( str_comp(m_pController->m_pGameType, "DM")==0 || str_comp(m_pController->m_pGameType, "TDM")==0 || str_comp(m_pController->m_pGameType, "CTF")==0) @@ -364,13 +364,13 @@ void CGameContext::CheckPureTuning() Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "resetting tuning due to pure server"); m_Tuning = p; } - } + } } void CGameContext::SendTuningParams(int ClientID) { CheckPureTuning(); - + CMsgPacker Msg(NETMSGTYPE_SV_TUNEPARAMS); int *pParams = (int *)&m_Tuning; for(unsigned i = 0; i < sizeof(m_Tuning)/sizeof(int); i++) @@ -389,7 +389,7 @@ void CGameContext::OnTick() //if(world.paused) // make sure that the game object always updates m_pController->Tick(); - + for(int i = 0; i < MAX_CLIENTS; i++) { if(m_apPlayers[i]) @@ -398,7 +398,7 @@ void CGameContext::OnTick() m_apPlayers[i]->PostTick(); } } - + // update voting if(m_VoteCloseTime) { @@ -423,10 +423,10 @@ void CGameContext::OnTick() { if(!m_apPlayers[i] || m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS || aVoteChecked[i]) // don't count in votes by spectators continue; - + int ActVote = m_apPlayers[i]->m_Vote; int ActVotePos = m_apPlayers[i]->m_VotePos; - + // check for more players with the same ip (only use the vote of the one who voted first) for(int j = i+1; j < MAX_CLIENTS; ++j) { @@ -453,13 +453,13 @@ void CGameContext::OnTick() else if(No >= (Total+1)/2) m_VoteEnforce = VOTE_ENFORCE_NO; } - + if(m_VoteEnforce == VOTE_ENFORCE_YES) { Console()->ExecuteLine(m_aVoteCommand); EndVote(); SendChat(-1, CGameContext::CHAT_ALL, "Vote passed"); - + if(m_apPlayers[m_VoteCreator]) m_apPlayers[m_VoteCreator]->m_LastVoteCall = 0; } @@ -475,7 +475,7 @@ void CGameContext::OnTick() } } } - + #ifdef CONF_DEBUG if(g_Config.m_DbgDummies) @@ -487,7 +487,7 @@ void CGameContext::OnTick() m_apPlayers[MAX_CLIENTS-i-1]->OnPredictedInput(&Input); } } -#endif +#endif } // Server hooks @@ -509,7 +509,7 @@ void CGameContext::OnClientEnter(int ClientID) m_apPlayers[ClientID]->Respawn(); char aBuf[512]; str_format(aBuf, sizeof(aBuf), "'%s' entered and joined the %s", Server()->ClientName(ClientID), m_pController->GetTeamName(m_apPlayers[ClientID]->GetTeam())); - SendChat(-1, CGameContext::CHAT_ALL, aBuf); + SendChat(-1, CGameContext::CHAT_ALL, aBuf); str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' team=%d", ClientID, Server()->ClientName(ClientID), m_apPlayers[ClientID]->GetTeam()); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); @@ -525,7 +525,7 @@ void CGameContext::OnClientConnected(int ClientID) m_apPlayers[ClientID] = new(ClientID) CPlayer(this, ClientID, StartTeam); //players[client_id].init(client_id); //players[client_id].client_id = client_id; - + (void)m_pController->CheckTeamBalance(); #ifdef CONF_DEBUG @@ -552,7 +552,7 @@ void CGameContext::OnClientDrop(int ClientID, const char *pReason) m_apPlayers[ClientID]->OnDisconnect(pReason); delete m_apPlayers[ClientID]; m_apPlayers[ClientID] = 0; - + (void)m_pController->CheckTeamBalance(); m_VoteUpdate = true; @@ -568,7 +568,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) { void *pRawMsg = m_NetObjHandler.SecureUnpackMsg(MsgID, pUnpacker); CPlayer *pPlayer = m_apPlayers[ClientID]; - + if(!pRawMsg) { char aBuf[256]; @@ -576,7 +576,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf); return; } - + if(MsgID == NETMSGTYPE_CL_SAY) { CNetMsg_Cl_Say *pMsg = (CNetMsg_Cl_Say *)pRawMsg; @@ -585,10 +585,10 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) Team = pPlayer->GetTeam(); else Team = CGameContext::CHAT_ALL; - + if(g_Config.m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat+Server()->TickSpeed() > Server()->Tick()) return; - + pPlayer->m_LastChat = Server()->Tick(); // check for invalid chars @@ -599,7 +599,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) *pMessage = ' '; pMessage++; } - + SendChat(ClientID, Team, pMsg->m_pMessage); } else if(MsgID == NETMSGTYPE_CL_CALLVOTE) @@ -620,7 +620,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) SendChatTarget(ClientID, "Wait for current vote to end before calling a new one."); return; } - + int Timeleft = pPlayer->m_LastVoteCall + Server()->TickSpeed()*60 - Now; if(pPlayer->m_LastVoteCall && Timeleft > 0) { @@ -629,7 +629,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) SendChatTarget(ClientID, aChatmsg); return; } - + char aChatmsg[512] = {0}; char aDesc[VOTE_DESC_LENGTH] = {0}; char aCmd[VOTE_CMD_LENGTH] = {0}; @@ -652,7 +652,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) pOption = pOption->m_pNext; } - + if(!pOption) { str_format(aChatmsg, sizeof(aChatmsg), "'%s' isn't an option on this server", pMsg->m_Value); @@ -682,7 +682,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) return; } } - + int KickID = str_toint(pMsg->m_Value); if(KickID < 0 || KickID >= MAX_CLIENTS || !m_apPlayers[KickID]) { @@ -702,7 +702,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) SendChatTarget(KickID, aBufKick); return; } - + str_format(aChatmsg, sizeof(aChatmsg), "'%s' called for vote to kick '%s' (%s)", Server()->ClientName(ClientID), Server()->ClientName(KickID), pReason); str_format(aDesc, sizeof(aDesc), "Kick '%s'", Server()->ClientName(KickID)); if (!g_Config.m_SvVoteKickBantime) @@ -722,7 +722,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) SendChatTarget(ClientID, "Server does not allow voting to move players to spectators"); return; } - + int SpectateID = str_toint(pMsg->m_Value); if(SpectateID < 0 || SpectateID >= MAX_CLIENTS || !m_apPlayers[SpectateID] || m_apPlayers[SpectateID]->GetTeam() == TEAM_SPECTATORS) { @@ -734,12 +734,12 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) SendChatTarget(ClientID, "You cant move yourself"); return; } - + str_format(aChatmsg, sizeof(aChatmsg), "'%s' called for vote to move '%s' to spectators (%s)", Server()->ClientName(ClientID), Server()->ClientName(SpectateID), pReason); str_format(aDesc, sizeof(aDesc), "move '%s' to spectators", Server()->ClientName(SpectateID)); str_format(aCmd, sizeof(aCmd), "set_team %d -1", SpectateID); } - + if(aCmd[0]) { SendChat(-1, CGameContext::CHAT_ALL, aChatmsg); @@ -769,7 +769,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) else if (MsgID == NETMSGTYPE_CL_SETTEAM && !m_World.m_Paused) { CNetMsg_Cl_SetTeam *pMsg = (CNetMsg_Cl_SetTeam *)pRawMsg; - + if(pPlayer->GetTeam() == pMsg->m_Team || (g_Config.m_SvSpamprotection && pPlayer->m_LastSetTeam && pPlayer->m_LastSetTeam+Server()->TickSpeed()*3 > Server()->Tick())) return; @@ -797,7 +797,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) else if (MsgID == NETMSGTYPE_CL_SETSPECTATORMODE && !m_World.m_Paused) { CNetMsg_Cl_SetSpectatorMode *pMsg = (CNetMsg_Cl_SetSpectatorMode *)pRawMsg; - + if(pPlayer->GetTeam() != TEAM_SPECTATORS || pPlayer->m_SpectatorID == pMsg->m_SpectatorID || ClientID == pMsg->m_SpectatorID || (g_Config.m_SvSpamprotection && pPlayer->m_LastSetSpectatorMode && pPlayer->m_LastSetSpectatorMode+Server()->TickSpeed()*3 > Server()->Tick())) return; @@ -809,13 +809,13 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) pPlayer->m_SpectatorID = pMsg->m_SpectatorID; } else if (MsgID == NETMSGTYPE_CL_STARTINFO) - { + { if(pPlayer->m_IsReady) return; - CNetMsg_Cl_StartInfo *pMsg = (CNetMsg_Cl_StartInfo *)pRawMsg; + CNetMsg_Cl_StartInfo *pMsg = (CNetMsg_Cl_StartInfo *)pRawMsg; pPlayer->m_LastChangeInfo = Server()->Tick(); - + // set start infos Server()->SetClientName(ClientID, pMsg->m_pName); Server()->SetClientClan(ClientID, pMsg->m_pClan); @@ -829,7 +829,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) // send vote options CNetMsg_Sv_VoteClearOptions ClearMsg; Server()->SendPackMsg(&ClearMsg, MSGFLAG_VITAL, ClientID); - + CNetMsg_Sv_VoteOptionListAdd OptionMsg; int NumOptions = 0; OptionMsg.m_pDescription0 = ""; @@ -897,7 +897,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, ClientID); NumOptions = 0; } - + // send tuning parameters to client SendTuningParams(ClientID); @@ -907,16 +907,16 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) Server()->SendPackMsg(&m, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID); } else if (MsgID == NETMSGTYPE_CL_CHANGEINFO) - { + { if(g_Config.m_SvSpamprotection && pPlayer->m_LastChangeInfo && pPlayer->m_LastChangeInfo+Server()->TickSpeed()*5 > Server()->Tick()) return; - + CNetMsg_Cl_ChangeInfo *pMsg = (CNetMsg_Cl_ChangeInfo *)pRawMsg; pPlayer->m_LastChangeInfo = Server()->Tick(); - + // set infos char aOldName[MAX_NAME_LENGTH]; - str_copy(aOldName, Server()->ClientName(ClientID), sizeof(aOldName)); + str_copy(aOldName, Server()->ClientName(ClientID), sizeof(aOldName)); Server()->SetClientName(ClientID, pMsg->m_pName); if(str_comp(aOldName, Server()->ClientName(ClientID)) != 0) { @@ -935,19 +935,19 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) else if (MsgID == NETMSGTYPE_CL_EMOTICON && !m_World.m_Paused) { CNetMsg_Cl_Emoticon *pMsg = (CNetMsg_Cl_Emoticon *)pRawMsg; - + if(g_Config.m_SvSpamprotection && pPlayer->m_LastEmote && pPlayer->m_LastEmote+Server()->TickSpeed()*3 > Server()->Tick()) return; - + pPlayer->m_LastEmote = Server()->Tick(); - + SendEmoticon(ClientID, pMsg->m_Emoticon); } else if (MsgID == NETMSGTYPE_CL_KILL && !m_World.m_Paused) { if(pPlayer->m_LastKill && pPlayer->m_LastKill+Server()->TickSpeed()*3 > Server()->Tick()) return; - + pPlayer->m_LastKill = Server()->Tick(); pPlayer->KillCharacter(WEAPON_SELF); } @@ -1024,14 +1024,14 @@ void CGameContext::ConSetTeam(IConsole::IResult *pResult, void *pUserData) CGameContext *pSelf = (CGameContext *)pUserData; int ClientID = clamp(pResult->GetInteger(0), 0, (int)MAX_CLIENTS-1); int Team = clamp(pResult->GetInteger(1), -1, 1); - + char aBuf[256]; str_format(aBuf, sizeof(aBuf), "moved client %d to team %d", ClientID, Team); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); - + if(!pSelf->m_apPlayers[ClientID]) return; - + pSelf->m_apPlayers[ClientID]->SetTeam(Team); (void)pSelf->m_pController->CheckTeamBalance(); } @@ -1040,15 +1040,15 @@ void CGameContext::ConSetTeamAll(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; int Team = clamp(pResult->GetInteger(0), -1, 1); - + char aBuf[256]; str_format(aBuf, sizeof(aBuf), "moved all clients to team %d", Team); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); - + for(int i = 0; i < MAX_CLIENTS; ++i) if(pSelf->m_apPlayers[i]) pSelf->m_apPlayers[i]->SetTeam(Team); - + (void)pSelf->m_pController->CheckTeamBalance(); } @@ -1063,7 +1063,7 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData) pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "maximum number of vote options reached"); return; } - + // check for valid option if(!pSelf->Console()->LineIsValid(pCommand) || str_length(pCommand) >= VOTE_CMD_LENGTH) { @@ -1081,7 +1081,7 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData) pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); return; } - + // check for duplicate entry CVoteOptionServer *pOption = pSelf->m_pVoteOptionFirst; while(pOption) @@ -1095,11 +1095,11 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData) } pOption = pOption->m_pNext; } - + // add the option ++pSelf->m_NumVoteOptions; int Len = str_length(pCommand); - + pOption = (CVoteOptionServer *)pSelf->m_pVoteOptionHeap->Allocate(sizeof(CVoteOptionServer) + Len); pOption->m_pNext = 0; pOption->m_pPrev = pSelf->m_pVoteOptionLast; @@ -1108,7 +1108,7 @@ void CGameContext::ConAddVote(IConsole::IResult *pResult, void *pUserData) pSelf->m_pVoteOptionLast = pOption; if(!pSelf->m_pVoteOptionFirst) pSelf->m_pVoteOptionFirst = pOption; - + str_copy(pOption->m_aDescription, pDescription, sizeof(pOption->m_aDescription)); mem_copy(pOption->m_aCommand, pCommand, Len+1); char aBuf[256]; @@ -1125,7 +1125,7 @@ void CGameContext::ConRemoveVote(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; const char *pDescription = pResult->GetString(0); - + // check for valid option CVoteOptionServer *pOption = pSelf->m_pVoteOptionFirst; while(pOption) @@ -1146,7 +1146,7 @@ void CGameContext::ConRemoveVote(IConsole::IResult *pResult, void *pUserData) CNetMsg_Sv_VoteOptionRemove OptionMsg; OptionMsg.m_pDescription = pOption->m_aDescription; pSelf->Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, -1); - + // TODO: improve this // remove the option --pSelf->m_NumVoteOptions; @@ -1173,7 +1173,7 @@ void CGameContext::ConRemoveVote(IConsole::IResult *pResult, void *pUserData) pVoteOptionLast = pDst; if(!pVoteOptionFirst) pVoteOptionFirst = pDst; - + str_copy(pDst->m_aDescription, pSrc->m_aDescription, sizeof(pDst->m_aDescription)); mem_copy(pDst->m_aCommand, pSrc->m_aCommand, Len+1); } @@ -1209,7 +1209,7 @@ void CGameContext::ConForceVote(IConsole::IResult *pResult, void *pUserData) pOption = pOption->m_pNext; } - + if(!pOption) { str_format(aBuf, sizeof(aBuf), "'%s' isn't an option on this server", pValue); @@ -1247,7 +1247,7 @@ void CGameContext::ConForceVote(IConsole::IResult *pResult, void *pUserData) pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "Invalid client id to move"); return; } - + str_format(aBuf, sizeof(aBuf), "set_team %d -1", SpectateID); pSelf->Console()->ExecuteLine(aBuf); } @@ -1323,10 +1323,10 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/) m_pConsole = Kernel()->RequestInterface(); m_World.SetGameServer(this); m_Events.SetGameServer(this); - + //if(!data) // only load once //data = load_data_from_memory(internal_data); - + for(int i = 0; i < NUM_NETOBJTYPES; i++) Server()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i)); @@ -1354,22 +1354,22 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/) // create all entities from the game layer CMapItemLayerTilemap *pTileMap = m_Layers.GameLayer(); CTile *pTiles = (CTile *)Kernel()->RequestInterface()->GetData(pTileMap->m_Data); - - - - + + + + /* num_spawn_points[0] = 0; num_spawn_points[1] = 0; num_spawn_points[2] = 0; */ - + for(int y = 0; y < pTileMap->m_Height; y++) { for(int x = 0; x < pTileMap->m_Width; x++) { int Index = pTiles[y*pTileMap->m_Width+x].m_Index; - + if(Index >= ENTITY_OFFSET) { vec2 Pos(x*32.0f+16.0f, y*32.0f+16.0f); @@ -1403,7 +1403,7 @@ void CGameContext::OnSnap(int ClientID) m_World.Snap(ClientID); m_pController->Snap(ClientID); m_Events.Snap(ClientID); - + for(int i = 0; i < MAX_CLIENTS; i++) { if(m_apPlayers[i]) diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 576a1b106..6288850d6 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -25,7 +25,7 @@ Remove entities marked for deletion (GAMEWORLD::remove_entities) Game Controller (GAMECONTROLLER::tick) All players (CPlayer::tick) - + Snap Game Context (CGameContext::snap) @@ -60,7 +60,7 @@ class CGameContext : public IGameServer static void ConClearVotes(IConsole::IResult *pResult, void *pUserData); static void ConVote(IConsole::IResult *pResult, void *pUserData); static void ConchainSpecialMotdupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); - + CGameContext(int Resetting); void Construct(int Resetting); @@ -73,25 +73,25 @@ public: CGameContext(); ~CGameContext(); - + void Clear(); - + CEventHandler m_Events; CPlayer *m_apPlayers[MAX_CLIENTS]; IGameController *m_pController; CGameWorld m_World; - + // helper functions class CCharacter *GetPlayerChar(int ClientID); - + // voting void StartVote(const char *pDesc, const char *pCommand, const char *pReason); void EndVote(); void SendVoteSet(int ClientID); void SendVoteStatus(int ClientID, int Total, int Yes, int No); void AbortVoteKickOnDisconnect(int ClientID); - + int m_VoteCreator; int64 m_VoteCloseTime; bool m_VoteUpdate; @@ -118,7 +118,7 @@ public: void CreatePlayerSpawn(vec2 Pos); void CreateDeath(vec2 Pos, int Who); void CreateSound(vec2 Pos, int Sound, int Mask=-1); - void CreateSoundGlobal(int Sound, int Target=-1); + void CreateSoundGlobal(int Sound, int Target=-1); enum @@ -135,22 +135,22 @@ public: void SendEmoticon(int ClientID, int Emoticon); void SendWeaponPickup(int ClientID, int Weapon); void SendBroadcast(const char *pText, int ClientID); - - + + // void CheckPureTuning(); void SendTuningParams(int ClientID); - + // engine events virtual void OnInit(); virtual void OnConsoleInit(); virtual void OnShutdown(); - + virtual void OnTick(); virtual void OnPreSnap(); virtual void OnSnap(int ClientID); virtual void OnPostSnap(); - + virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID); virtual void OnClientConnected(int ClientID); diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index c5a965707..6685bba34 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -15,7 +15,7 @@ IGameController::IGameController(class CGameContext *pGameServer) m_pGameServer = pGameServer; m_pServer = m_pGameServer->Server(); m_pGameType = "unknown"; - + // DoWarmup(g_Config.m_SvWarmup); m_GameOverTick = -1; @@ -26,10 +26,10 @@ IGameController::IGameController(class CGameContext *pGameServer) m_aTeamscore[TEAM_RED] = 0; m_aTeamscore[TEAM_BLUE] = 0; m_aMapWish[0] = 0; - + m_UnbalancedTick = -1; m_ForceBalanced = false; - + m_aNumSpawnPoints[0] = 0; m_aNumSpawnPoints[1] = 0; m_aNumSpawnPoints[2] = 0; @@ -49,18 +49,18 @@ float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos) float Scoremod = 1.0f; if(pEval->m_FriendlyTeam != -1 && pC->GetPlayer()->GetTeam() == pEval->m_FriendlyTeam) Scoremod = 0.5f; - + float d = distance(Pos, pC->m_Pos); Score += Scoremod * (d == 0 ? 1000000000.0f : 1.0f/d); } - + return Score; } void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int Type) { // get spawn point - for(int i = 0; i < m_aNumSpawnPoints[Type]; i++) + for(int i = 0; i < m_aNumSpawnPoints[Type]; i++) { // check if the position is occupado if(GameServer()->m_World.FindEntities(m_aaSpawnPoints[Type][i], 64, 0, 1, CGameWorld::ENTTYPE_CHARACTER)) @@ -80,7 +80,7 @@ void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int Type) void IGameController::FindFreeSpawn(CSpawnEval *pEval, int Type) { // pick the spawn point that is least occupied and has free space for spawning around it - for(int i = 0; i < m_aNumSpawnPoints[Type]; i++) + for(int i = 0; i < m_aNumSpawnPoints[Type]; i++) { CCharacter *aEnts[MAX_CLIENTS]; @@ -88,7 +88,7 @@ void IGameController::FindFreeSpawn(CSpawnEval *pEval, int Type) float Score = 0.0f; for(int c = 0; c < Num; ++c) Score += 96.0f - distance(aEnts[c]->m_Pos, m_aaSpawnPoints[Type][i]); - + if(!pEval->m_Got || pEval->m_Score > Score) { // start, left, up, right, down @@ -121,15 +121,15 @@ void IGameController::FindFreeSpawn(CSpawnEval *pEval, int Type) bool IGameController::CanSpawn(int Team, vec2 *pOutPos) { CSpawnEval Eval; - + // spectators can't spawn if(Team == TEAM_SPECTATORS) return false; - + if(IsTeamplay()) { Eval.m_FriendlyTeam = Team; - + // first try own team spawn, then normal spawn and then enemy EvaluateSpawnType(&Eval, 1+(Team&1)); if(!Eval.m_Got) @@ -167,7 +167,7 @@ bool IGameController::CanSpawn(int Team, vec2 *pOutPos) FindFreeSpawn(&Eval, 2); } } - + *pOutPos = Eval.m_Pos; return Eval.m_Got; } @@ -177,7 +177,7 @@ bool IGameController::OnEntity(int Index, vec2 Pos) { int Type = -1; int SubType = 0; - + if(Index == ENTITY_SPAWN) m_aaSpawnPoints[0][m_aNumSpawnPoints[0]++] = Pos; else if(Index == ENTITY_SPAWN_RED) @@ -208,7 +208,7 @@ bool IGameController::OnEntity(int Index, vec2 Pos) Type = POWERUP_NINJA; SubType = WEAPON_NINJA; } - + if(Type != -1) { CPickup *pPickup = new CPickup(&GameServer()->m_World, Type, SubType); @@ -223,7 +223,7 @@ void IGameController::EndRound() { if(m_Warmup) // game can't end when we are running warmup return; - + GameServer()->m_World.m_Paused = true; m_GameOverTick = Server()->Tick(); m_SuddenDeath = 0; @@ -248,7 +248,7 @@ const char *IGameController::GetTeamName(int Team) if(Team == 0) return "game"; } - + return "spectators"; } @@ -257,7 +257,7 @@ static bool IsSeparator(char c) { return c == ';' || c == ' ' || c == ',' || c = void IGameController::StartRound() { ResetGame(); - + m_RoundStartTick = Server()->Tick(); m_SuddenDeath = 0; m_GameOverTick = -1; @@ -293,11 +293,11 @@ void IGameController::CycleMap() if(m_RoundCount < g_Config.m_SvRoundsPerMap-1) return; - + // handle maprotation const char *pMapRotation = g_Config.m_SvMaprotation; const char *pCurrentMap = g_Config.m_SvMap; - + int CurrentMapLen = str_length(pCurrentMap); const char *pNextMap = pMapRotation; while(*pNextMap) @@ -305,25 +305,25 @@ void IGameController::CycleMap() int WordLen = 0; while(pNextMap[WordLen] && !IsSeparator(pNextMap[WordLen])) WordLen++; - + if(WordLen == CurrentMapLen && str_comp_num(pNextMap, pCurrentMap, CurrentMapLen) == 0) { // map found pNextMap += CurrentMapLen; while(*pNextMap && IsSeparator(*pNextMap)) pNextMap++; - + break; } - + pNextMap++; } - + // restart rotation if(pNextMap[0] == 0) pNextMap = pMapRotation; - // cut out the next map + // cut out the next map char aBuf[512]; for(int i = 0; i < 512; i++) { @@ -334,14 +334,14 @@ void IGameController::CycleMap() break; } } - + // skip spaces int i = 0; while(IsSeparator(aBuf[i])) i++; - + m_RoundCount = 0; - + char aBufMsg[256]; str_format(aBufMsg, sizeof(aBufMsg), "rotating map to %s", &aBuf[i]); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); @@ -361,7 +361,7 @@ void IGameController::PostReset() } } } - + void IGameController::OnPlayerInfoChange(class CPlayer *pP) { const int aTeamColors[2] = {65387, 10223467}; @@ -405,7 +405,7 @@ void IGameController::OnCharacterSpawn(class CCharacter *pChr) { // default health pChr->IncreaseHealth(10); - + // give default weapons pChr->GiveWeapon(WEAPON_HAMMER, -1); pChr->GiveWeapon(WEAPON_GUN, 10); @@ -423,16 +423,16 @@ bool IGameController::IsFriendlyFire(int ClientID1, int ClientID2) { if(ClientID1 == ClientID2) return false; - + if(IsTeamplay()) { if(!GameServer()->m_apPlayers[ClientID1] || !GameServer()->m_apPlayers[ClientID2]) return false; - + if(GameServer()->m_apPlayers[ClientID1]->GetTeam() == GameServer()->m_apPlayers[ClientID2]->GetTeam()) return true; } - + return false; } @@ -461,7 +461,7 @@ void IGameController::Tick() if(!m_Warmup) StartRound(); } - + if(m_GameOverTick != -1) { // game over.. wait for restart @@ -472,12 +472,12 @@ void IGameController::Tick() m_RoundCount++; } } - + // do team-balancing if (IsTeamplay() && m_UnbalancedTick != -1 && Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60) { GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "Balancing teams"); - + int aT[2] = {0,0}; float aTScore[2] = {0,0}; float aPScore[MAX_CLIENTS] = {0.0f}; @@ -491,13 +491,13 @@ void IGameController::Tick() aTScore[GameServer()->m_apPlayers[i]->GetTeam()] += aPScore[i]; } } - + // are teams unbalanced? if(absolute(aT[0]-aT[1]) >= 2) { int M = (aT[0] > aT[1]) ? 0 : 1; int NumBalance = absolute(aT[0]-aT[1]) / 2; - + do { CPlayer *pP = 0; @@ -513,16 +513,16 @@ void IGameController::Tick() PD = absolute((aTScore[M^1]+aPScore[i]) - (aTScore[M]-aPScore[i])); } } - + // move the player to the other team int Temp = pP->m_LastActionTick; pP->SetTeam(M^1); pP->m_LastActionTick = Temp; - + pP->Respawn(); pP->m_ForceBalanced = true; } while (--NumBalance); - + m_ForceBalanced = true; } m_UnbalancedTick = -1; @@ -595,7 +595,7 @@ void IGameController::Snap(int SnappingClient) pGameInfoObj->m_ScoreLimit = g_Config.m_SvScorelimit; pGameInfoObj->m_TimeLimit = g_Config.m_SvTimelimit; - + pGameInfoObj->m_RoundNum = (str_length(g_Config.m_SvMaprotation) && g_Config.m_SvRoundsPerMap) ? g_Config.m_SvRoundsPerMap : 0; pGameInfoObj->m_RoundCurrent = m_RoundCount+1; } @@ -605,7 +605,7 @@ int IGameController::GetAutoTeam(int NotThisID) // this will force the auto balancer to work overtime aswell if(g_Config.m_DbgStress) return 0; - + int aNumplayers[2] = {0,0}; for(int i = 0; i < MAX_CLIENTS; i++) { @@ -619,7 +619,7 @@ int IGameController::GetAutoTeam(int NotThisID) int Team = 0; if(IsTeamplay()) Team = aNumplayers[TEAM_RED] > aNumplayers[TEAM_BLUE] ? TEAM_BLUE : TEAM_RED; - + if(CanJoinTeam(Team, NotThisID)) return Team; return -1; @@ -639,7 +639,7 @@ bool IGameController::CanJoinTeam(int Team, int NotThisID) aNumplayers[GameServer()->m_apPlayers[i]->GetTeam()]++; } } - + return (aNumplayers[0] + aNumplayers[1]) < g_Config.m_SvMaxClients-g_Config.m_SvSpectatorSlots; } @@ -647,7 +647,7 @@ bool IGameController::CheckTeamBalance() { if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime) return true; - + int aT[2] = {0, 0}; for(int i = 0; i < MAX_CLIENTS; i++) { @@ -655,7 +655,7 @@ bool IGameController::CheckTeamBalance() if(pP && pP->GetTeam() != TEAM_SPECTATORS) aT[pP->GetTeam()]++; } - + char aBuf[256]; if(absolute(aT[0]-aT[1]) >= 2) { @@ -677,22 +677,22 @@ bool IGameController::CheckTeamBalance() bool IGameController::CanChangeTeam(CPlayer *pPlayer, int JoinTeam) { int aT[2] = {0, 0}; - + if (!IsTeamplay() || JoinTeam == TEAM_SPECTATORS || !g_Config.m_SvTeambalanceTime) return true; - + for(int i = 0; i < MAX_CLIENTS; i++) { CPlayer *pP = GameServer()->m_apPlayers[i]; if(pP && pP->GetTeam() != TEAM_SPECTATORS) aT[pP->GetTeam()]++; } - + // simulate what would happen if changed team aT[JoinTeam]++; if (pPlayer->GetTeam() != TEAM_SPECTATORS) aT[JoinTeam^1]--; - + // there is a player-difference of at least 2 if(absolute(aT[0]-aT[1]) >= 2) { @@ -708,7 +708,7 @@ bool IGameController::CanChangeTeam(CPlayer *pPlayer, int JoinTeam) void IGameController::DoPlayerScoreWincheck() { - if(m_GameOverTick == -1 && !m_Warmup) + if(m_GameOverTick == -1 && !m_Warmup) { // gather some stats int Topscore = 0; @@ -726,7 +726,7 @@ void IGameController::DoPlayerScoreWincheck() TopscoreCount++; } } - + // check score win condition if((g_Config.m_SvScorelimit > 0 && Topscore >= g_Config.m_SvScorelimit) || (g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60)) diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h index c999f84e7..6ccfe9779 100644 --- a/src/game/server/gamecontroller.h +++ b/src/game/server/gamecontroller.h @@ -14,10 +14,10 @@ class IGameController { vec2 m_aaSpawnPoints[3][64]; int m_aNumSpawnPoints[3]; - + class CGameContext *m_pGameServer; class IServer *m_pServer; - + protected: CGameContext *GameServer() const { return m_pGameServer; } IServer *Server() const { return m_pServer; } @@ -30,7 +30,7 @@ protected: m_FriendlyTeam = -1; m_Pos = vec2(100,100); } - + vec2 m_Pos; bool m_Got; int m_FriendlyTeam; @@ -44,80 +44,80 @@ protected: void CycleMap(); void ResetGame(); - + char m_aMapWish[128]; - + int m_RoundStartTick; int m_GameOverTick; int m_SuddenDeath; - + int m_aTeamscore[2]; - + int m_Warmup; int m_RoundCount; - + int m_GameFlags; int m_UnbalancedTick; bool m_ForceBalanced; - + public: const char *m_pGameType; bool IsTeamplay() const; - + IGameController(class CGameContext *pGameServer); virtual ~IGameController(); void DoTeamScoreWincheck(); void DoPlayerScoreWincheck(); - + void DoWarmup(int Seconds); - + void StartRound(); void EndRound(); void ChangeMap(const char *pToMap); - + bool IsFriendlyFire(int ClientID1, int ClientID2); - + bool IsForceBalanced(); /* - - */ + + */ virtual bool CanBeMovedOnBalance(int ClientID); virtual void Tick(); - + virtual void Snap(int SnappingClient); - + /* Function: on_entity Called when the map is loaded to process an entity in the map. - + Arguments: index - Entity index. pos - Where the entity is located in the world. - + Returns: bool? */ virtual bool OnEntity(int Index, vec2 Pos); - + /* Function: on_CCharacter_spawn Called when a CCharacter spawns into the game world. - + Arguments: chr - The CCharacter that was spawned. */ virtual void OnCharacterSpawn(class CCharacter *pChr); - + /* Function: on_CCharacter_death Called when a CCharacter in the world dies. - + Arguments: victim - The CCharacter that died. killer - The player that killed it. @@ -133,8 +133,8 @@ public: virtual bool CanSpawn(int Team, vec2 *pPos); /* - - */ + + */ virtual const char *GetTeamName(int Team); virtual int GetAutoTeam(int NotThisID); virtual bool CanJoinTeam(int Team, int NotThisID); diff --git a/src/game/server/gamemodes/ctf.cpp b/src/game/server/gamemodes/ctf.cpp index fb177d5dd..b1d3d2fa2 100644 --- a/src/game/server/gamemodes/ctf.cpp +++ b/src/game/server/gamemodes/ctf.cpp @@ -20,13 +20,13 @@ bool CGameControllerCTF::OnEntity(int Index, vec2 Pos) { if(IGameController::OnEntity(Index, Pos)) return true; - + int Team = -1; if(Index == ENTITY_FLAGSTAND_RED) Team = TEAM_RED; if(Index == ENTITY_FLAGSTAND_BLUE) Team = TEAM_BLUE; if(Team == -1 || m_apFlags[Team]) return false; - + CFlag *F = new CFlag(&GameServer()->m_World, Team); F->m_StandPos = Pos; F->m_Pos = Pos; @@ -39,7 +39,7 @@ int CGameControllerCTF::OnCharacterDeath(class CCharacter *pVictim, class CPlaye { IGameController::OnCharacterDeath(pVictim, pKiller, WeaponID); int HadFlag = 0; - + // drop flags for(int i = 0; i < 2; i++) { @@ -52,14 +52,14 @@ int CGameControllerCTF::OnCharacterDeath(class CCharacter *pVictim, class CPlaye F->m_DropTick = Server()->Tick(); F->m_pCarryingCharacter = 0; F->m_Vel = vec2(0,0); - + if(pKiller && pKiller->GetTeam() != pVictim->GetPlayer()->GetTeam()) pKiller->m_Score++; - + HadFlag |= 1; } } - + return HadFlag; } @@ -118,14 +118,14 @@ void CGameControllerCTF::Tick() IGameController::Tick(); DoTeamScoreWincheck(); - + for(int fi = 0; fi < 2; fi++) { CFlag *F = m_apFlags[fi]; - + if(!F) continue; - + // flag hits death-tile or left the game layer, reset it if(GameServer()->Collision()->GetCollisionAt(F->m_Pos.x, F->m_Pos.y)&CCollision::COLFLAG_DEATH || F->GameLayerClipped(F->m_Pos)) { @@ -134,13 +134,13 @@ void CGameControllerCTF::Tick() F->Reset(); continue; } - + // if(F->m_pCarryingCharacter) { // update flag position F->m_Pos = F->m_pCarryingCharacter->m_Pos; - + if(m_apFlags[fi^1] && m_apFlags[fi^1]->m_AtStand) { if(distance(F->m_Pos, m_apFlags[fi^1]->m_Pos) < CFlag::ms_PhysSize + CCharacter::ms_PhysSize) @@ -167,7 +167,7 @@ void CGameControllerCTF::Tick() GameServer()->SendChat(-1, -2, aBuf); for(int i = 0; i < 2; i++) m_apFlags[i]->Reset(); - + GameServer()->CreateSoundGlobal(SOUND_CTF_CAPTURE); } } @@ -180,7 +180,7 @@ void CGameControllerCTF::Tick() { if(!apCloseCCharacters[i]->IsAlive() || apCloseCCharacters[i]->GetPlayer()->GetTeam() == TEAM_SPECTATORS || GameServer()->Collision()->IntersectLine(F->m_Pos, apCloseCCharacters[i]->m_Pos, NULL, NULL)) continue; - + if(apCloseCCharacters[i]->GetPlayer()->GetTeam() == F->m_Team) { // return the flag @@ -207,7 +207,7 @@ void CGameControllerCTF::Tick() m_aTeamscore[fi^1]++; F->m_GrabTick = Server()->Tick(); } - + F->m_AtStand = 0; F->m_pCarryingCharacter = apCloseCCharacters[i]; F->m_pCarryingCharacter->GetPlayer()->m_Score += 1; @@ -217,12 +217,12 @@ void CGameControllerCTF::Tick() F->m_pCarryingCharacter->GetPlayer()->GetCID(), Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID())); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); - + for(int c = 0; c < MAX_CLIENTS; c++) { if(!GameServer()->m_apPlayers[c]) continue; - + if(GameServer()->m_apPlayers[c]->GetTeam() == fi) GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, GameServer()->m_apPlayers[c]->GetCID()); else @@ -231,7 +231,7 @@ void CGameControllerCTF::Tick() break; } } - + if(!F->m_pCarryingCharacter && !F->m_AtStand) { if(Server()->Tick() > F->m_DropTick + Server()->TickSpeed()*30) diff --git a/src/game/server/gamemodes/ctf.h b/src/game/server/gamemodes/ctf.h index b9868e700..44bd9e8ed 100644 --- a/src/game/server/gamemodes/ctf.h +++ b/src/game/server/gamemodes/ctf.h @@ -9,12 +9,12 @@ class CGameControllerCTF : public IGameController { public: class CFlag *m_apFlags[2]; - + CGameControllerCTF(class CGameContext *pGameServer); virtual bool CanBeMovedOnBalance(int ClientID); virtual void Snap(int SnappingClient); virtual void Tick(); - + virtual bool OnEntity(int Index, vec2 Pos); virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon); }; diff --git a/src/game/server/gamemodes/mod.cpp b/src/game/server/gamemodes/mod.cpp index ecf06e484..127be2bc2 100644 --- a/src/game/server/gamemodes/mod.cpp +++ b/src/game/server/gamemodes/mod.cpp @@ -8,7 +8,7 @@ CGameControllerMOD::CGameControllerMOD(class CGameContext *pGameServer) // Exchange this to a string that identifies your game mode. // DM, TDM and CTF are reserved for teeworlds original modes. m_pGameType = "MOD"; - + //m_GameFlags = GAMEFLAG_TEAMS; // GAMEFLAG_TEAMS makes it a two-team gamemode } @@ -17,6 +17,6 @@ void CGameControllerMOD::Tick() // this is the main part of the gamemode, this function is run every tick DoPlayerScoreWincheck(); // checks for winners, no teams version //DoTeamScoreWincheck(); // checks for winners, two teams version - + IGameController::Tick(); } diff --git a/src/game/server/gamemodes/tdm.cpp b/src/game/server/gamemodes/tdm.cpp index fb0ff7830..54e645b3b 100644 --- a/src/game/server/gamemodes/tdm.cpp +++ b/src/game/server/gamemodes/tdm.cpp @@ -15,8 +15,8 @@ CGameControllerTDM::CGameControllerTDM(class CGameContext *pGameServer) : IGameC int CGameControllerTDM::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon) { IGameController::OnCharacterDeath(pVictim, pKiller, Weapon); - - + + if(Weapon != WEAPON_GAME) { // do team scoring @@ -27,7 +27,7 @@ int CGameControllerTDM::OnCharacterDeath(class CCharacter *pVictim, class CPlaye } pVictim->GetPlayer()->m_RespawnTick = max(pVictim->GetPlayer()->m_RespawnTick, Server()->Tick()+Server()->TickSpeed()*g_Config.m_SvRespawnDelayTDM); - + return 0; } diff --git a/src/game/server/gamemodes/tdm.h b/src/game/server/gamemodes/tdm.h index c8d3f3286..297b48c0e 100644 --- a/src/game/server/gamemodes/tdm.h +++ b/src/game/server/gamemodes/tdm.h @@ -8,7 +8,7 @@ class CGameControllerTDM : public IGameController { public: CGameControllerTDM(class CGameContext *pGameServer); - + int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon); virtual void Snap(int SnappingClient); virtual void Tick(); diff --git a/src/game/server/gameworld.cpp b/src/game/server/gameworld.cpp index 8fffabc8c..6444cce57 100644 --- a/src/game/server/gameworld.cpp +++ b/src/game/server/gameworld.cpp @@ -12,7 +12,7 @@ CGameWorld::CGameWorld() { m_pGameServer = 0x0; m_pServer = 0x0; - + m_Paused = false; m_ResetRequested = false; for(int i = 0; i < NUM_ENTTYPES; i++) @@ -164,7 +164,7 @@ void CGameWorld::Tick() pEnt->Tick(); pEnt = m_pNextTraverseEntity; } - + for(int i = 0; i < NUM_ENTTYPES; i++) for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) { @@ -191,7 +191,7 @@ CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, v { if(p == pNotThis) continue; - + vec2 IntersectPos = closest_point_on_line(Pos0, Pos1, p->m_Pos); float Len = distance(p->m_Pos, IntersectPos); if(Len < p->m_ProximityRadius+Radius) @@ -205,7 +205,7 @@ CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, v } } } - + return pClosest; } @@ -215,13 +215,13 @@ CCharacter *CGameWorld::ClosestCharacter(vec2 Pos, float Radius, CEntity *pNotTh // Find other players float ClosestRange = Radius*2; CCharacter *pClosest = 0; - + CCharacter *p = (CCharacter *)GameServer()->m_World.FindFirst(ENTTYPE_CHARACTER); for(; p; p = (CCharacter *)p->TypeNext()) { if(p == pNotThis) continue; - + float Len = distance(Pos, p->m_Pos); if(Len < p->m_ProximityRadius+Radius) { @@ -232,6 +232,6 @@ CCharacter *CGameWorld::ClosestCharacter(vec2 Pos, float Radius, CEntity *pNotTh } } } - + return pClosest; } diff --git a/src/game/server/gameworld.h b/src/game/server/gameworld.h index 38002b87c..a2fdbce06 100644 --- a/src/game/server/gameworld.h +++ b/src/game/server/gameworld.h @@ -32,7 +32,7 @@ private: CEntity *m_pNextTraverseEntity; CEntity *m_apFirstEntityTypes[NUM_ENTTYPES]; - + class CGameContext *m_pGameServer; class IServer *m_pServer; @@ -43,18 +43,18 @@ public: bool m_ResetRequested; bool m_Paused; CWorldCore m_Core; - + CGameWorld(); ~CGameWorld(); - + void SetGameServer(CGameContext *pGameServer); - + CEntity *FindFirst(int Type); - + /* Function: find_entities Finds entities close to a position and returns them in a list. - + Arguments: pos - Position. radius - How close the entities have to be. @@ -62,37 +62,37 @@ public: to the entities. max - Number of entities that fits into the ents array. type - Type of the entities to find. - + Returns: Number of entities found and added to the ents array. */ int FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, int Type); - + /* Function: interserct_CCharacter Finds the closest CCharacter that intersects the line. - + Arguments: pos0 - Start position pos2 - End position radius - How for from the line the CCharacter is allowed to be. new_pos - Intersection position notthis - Entity to ignore intersecting with - + Returns: Returns a pointer to the closest hit or NULL of there is no intersection. */ class CCharacter *IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, vec2 &NewPos, class CEntity *pNotThis = 0); - + /* Function: closest_CCharacter Finds the closest CCharacter to a specific point. - + Arguments: pos - The center position. radius - How far off the CCharacter is allowed to be notthis - Entity to ignore - + Returns: Returns a pointer to the closest CCharacter or NULL if no CCharacter is close enough. */ @@ -101,7 +101,7 @@ public: /* Function: insert_entity Adds an entity to the world. - + Arguments: entity - Entity to add */ @@ -110,7 +110,7 @@ public: /* Function: remove_entity Removes an entity from the world. - + Arguments: entity - Entity to remove */ @@ -119,28 +119,28 @@ public: /* Function: destroy_entity Destroys an entity in the world. - + Arguments: entity - Entity to destroy */ void DestroyEntity(CEntity *pEntity); - + /* Function: snap Calls snap on all the entities in the world to create the snapshot. - + Arguments: snapping_client - ID of the client which snapshot is being created. */ void Snap(int SnappingClient); - + /* Function: tick Calls tick on all the entities in the world to progress the world to the next tick. - + */ void Tick(); }; diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index cf0e6683e..aeafe3a4e 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -8,7 +8,7 @@ MACRO_ALLOC_POOL_ID_IMPL(CPlayer, MAX_CLIENTS) IServer *CPlayer::Server() const { return m_pGameServer->Server(); } - + CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, int Team) { m_pGameServer = pGameServer; @@ -58,7 +58,7 @@ void CPlayer::Tick() m_Latency.m_AccumMax = 0; } } - + if(!Character && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick()) m_Spawning = true; @@ -148,9 +148,9 @@ void CPlayer::OnDisconnect(const char *pReason) { char aBuf[512]; if(pReason && *pReason) - str_format(aBuf, sizeof(aBuf), "'%s' has left the game (%s)", Server()->ClientName(m_ClientID), pReason); + str_format(aBuf, sizeof(aBuf), "'%s' has left the game (%s)", Server()->ClientName(m_ClientID), pReason); else - str_format(aBuf, sizeof(aBuf), "'%s' has left the game", Server()->ClientName(m_ClientID)); + str_format(aBuf, sizeof(aBuf), "'%s' has left the game", Server()->ClientName(m_ClientID)); GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf); str_format(aBuf, sizeof(aBuf), "leave player='%d:%s'", m_ClientID, Server()->ClientName(m_ClientID)); @@ -173,7 +173,7 @@ void CPlayer::OnDirectInput(CNetObj_PlayerInput *NewInput) if(!Character && m_Team != TEAM_SPECTATORS && (NewInput->m_Fire&1)) m_Spawning = true; - + if(!Character && m_Team == TEAM_SPECTATORS && m_SpectatorID == SPEC_FREEVIEW) m_ViewPos = vec2(NewInput->m_TargetX, NewInput->m_TargetY); @@ -217,11 +217,11 @@ void CPlayer::SetTeam(int Team) Team = GameServer()->m_pController->ClampTeam(Team); if(m_Team == Team) return; - + char aBuf[512]; str_format(aBuf, sizeof(aBuf), "'%s' joined the %s", Server()->ClientName(m_ClientID), GameServer()->m_pController->GetTeamName(Team)); - GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf); - + GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf); + KillCharacter(); m_Team = Team; @@ -230,7 +230,7 @@ void CPlayer::SetTeam(int Team) 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); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); - + GameServer()->m_pController->OnPlayerInfoChange(GameServer()->m_apPlayers[m_ClientID]); if(Team == TEAM_SPECTATORS) @@ -247,7 +247,7 @@ void CPlayer::SetTeam(int Team) void CPlayer::TryRespawn() { vec2 SpawnPos; - + if(!GameServer()->m_pController->CanSpawn(m_Team, &SpawnPos)) return; diff --git a/src/game/server/player.h b/src/game/server/player.h index 50f1c1a0a..9d5e462c8 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -11,7 +11,7 @@ class CPlayer { MACRO_ALLOC_POOL_ID() - + public: CPlayer(CGameContext *pGameServer, int ClientID, int Team); ~CPlayer(); @@ -23,7 +23,7 @@ public: void SetTeam(int Team); int GetTeam() const { return m_Team; }; int GetCID() const { return m_ClientID; }; - + void Tick(); void PostTick(); void Snap(int SnappingClient); @@ -31,10 +31,10 @@ public: void OnDirectInput(CNetObj_PlayerInput *NewInput); void OnPredictedInput(CNetObj_PlayerInput *NewInput); void OnDisconnect(const char *pReason); - + void KillCharacter(int Weapon = WEAPON_GAME); CCharacter *GetCharacter(); - + //--------------------------------------------------------- // this is used for snapping so we know how we can clip the view for the player vec2 m_ViewPos; @@ -49,7 +49,7 @@ public: int m_SpectatorID; bool m_IsReady; - + // int m_Vote; int m_VotePos; @@ -62,16 +62,16 @@ public: int m_LastChangeInfo; int m_LastEmote; int m_LastKill; - + // TODO: clean this up - struct + struct { char m_SkinName[64]; int m_UseCustomColor; int m_ColorBody; int m_ColorFeet; } m_TeeInfos; - + int m_RespawnTick; int m_DieTick; int m_Score; @@ -84,7 +84,7 @@ public: int m_TargetY; } m_LatestActivity; - // network latency calculations + // network latency calculations struct { int m_Accum; @@ -92,16 +92,16 @@ public: int m_AccumMax; int m_Avg; int m_Min; - int m_Max; + int m_Max; } m_Latency; - + private: CCharacter *Character; CGameContext *m_pGameServer; - + CGameContext *GameServer() const { return m_pGameServer; } IServer *Server() const; - + // bool m_Spawning; int m_ClientID; diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp index a3da8cd09..862c57af7 100644 --- a/src/mastersrv/mastersrv.cpp +++ b/src/mastersrv/mastersrv.cpp @@ -109,7 +109,7 @@ void BuildPackets() m_NumPackets++; } - // copy header + // copy header mem_copy(m_aPackets[m_NumPackets-1].m_Data.m_aHeader, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)); // copy server addresses @@ -146,9 +146,9 @@ void BuildPackets() m_NumPacketsLegacy++; } - // copy header + // copy header mem_copy(m_aPacketsLegacy[m_NumPacketsLegacy-1].m_Data.m_aHeader, SERVERBROWSE_LIST_LEGACY, sizeof(SERVERBROWSE_LIST_LEGACY)); - + // copy server addresses mem_copy(m_aPacketsLegacy[m_NumPacketsLegacy-1].m_Data.m_aServers[PacketIndexLegacy].m_aIp, pCurrent->m_Address.ip, sizeof(m_aPacketsLegacy[m_NumPacketsLegacy-1].m_Data.m_aServers[PacketIndexLegacy].m_aIp)); @@ -179,7 +179,7 @@ void SendOk(NETADDR *pAddr) p.m_Flags = NETSENDFLAG_CONNLESS; p.m_DataSize = sizeof(SERVERBROWSE_FWOK); p.m_pData = SERVERBROWSE_FWOK; - + // send on both to be sure m_NetChecker.Send(&p); m_NetOp.Send(&p); @@ -215,7 +215,7 @@ void AddCheckserver(NETADDR *pInfo, NETADDR *pAlt, ServerType Type) dbg_msg("mastersrv", "error: mastersrv is full"); return; } - + char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr)); char aAltAddrStr[NETADDR_MAXSTRSIZE]; @@ -243,14 +243,14 @@ void AddServer(NETADDR *pInfo, ServerType Type) return; } } - + // add server if(m_NumServers == MAX_SERVERS) { dbg_msg("mastersrv", "error: mastersrv is full"); return; } - + char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr)); dbg_msg("mastersrv", "added: %s", aAddrStr); @@ -275,7 +275,7 @@ void UpdateServers() char aAltAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(&m_aCheckServers[i].m_AltAddress, aAltAddrStr, sizeof(aAltAddrStr)); dbg_msg("mastersrv", "check failed: %s (%s)", aAddrStr, aAltAddrStr); - + // FAIL!! SendError(&m_aCheckServers[i].m_Address); m_aCheckServers[i] = m_aCheckServers[m_NumCheckServers-1]; @@ -342,19 +342,19 @@ void ConAddBan(IConsole::IResult *pResult, void *pUser) dbg_msg("mastersrv", "error: banlist is full"); return; } - + if(net_addr_from_str(&m_aBans[m_NumBans].m_Address, pResult->GetString(0)) != 0) { dbg_msg("mastersrv", "error: invalid address"); return; } - + if(CheckBan(m_aBans[m_NumBans].m_Address)) { dbg_msg("mastersrv", "duplicate ban: %s", pResult->GetString(0)); return; } - + dbg_msg("mastersrv", "ban added: %s", pResult->GetString(0)); m_NumBans++; } @@ -377,7 +377,7 @@ int main(int argc, const char **argv) // ignore_convention mem_zero(&BindAddr, sizeof(BindAddr)); BindAddr.type = NETTYPE_ALL; BindAddr.port = MASTERSERVER_PORT; - + if(!m_NetOp.Open(BindAddr, 0)) { dbg_msg("mastersrv", "couldn't start network (op)"); @@ -390,7 +390,7 @@ int main(int argc, const char **argv) // ignore_convention dbg_msg("mastersrv", "couldn't start network (checker)"); return -1; } - + mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT)); mem_copy(m_CountDataLegacy.m_Header, SERVERBROWSE_COUNT_LEGACY, sizeof(SERVERBROWSE_COUNT_LEGACY)); @@ -405,14 +405,14 @@ int main(int argc, const char **argv) // ignore_convention if(RegisterFail) return -1; - + dbg_msg("mastersrv", "started"); - + while(1) { m_NetOp.Update(); m_NetChecker.Update(); - + // process m_aPackets CNetChunk Packet; while(m_NetOp.Recv(&Packet)) @@ -442,7 +442,7 @@ int main(int argc, const char **argv) // ignore_convention Alt.port = (d[sizeof(SERVERBROWSE_HEARTBEAT)]<<8) | d[sizeof(SERVERBROWSE_HEARTBEAT)+1]; - + // add it AddCheckserver(&Packet.m_Address, &Alt, SERVERTYPE_LEGACY); } @@ -466,7 +466,7 @@ int main(int argc, const char **argv) // ignore_convention mem_comp(Packet.m_pData, SERVERBROWSE_GETCOUNT_LEGACY, sizeof(SERVERBROWSE_GETCOUNT_LEGACY)) == 0) { dbg_msg("mastersrv", "count requested, responding with %d", m_NumServers); - + CNetChunk p; p.m_ClientID = -1; p.m_Address = Packet.m_Address; @@ -500,12 +500,12 @@ int main(int argc, const char **argv) // ignore_convention { // someone requested the list dbg_msg("mastersrv", "requested, responding with %d m_aServers", m_NumServers); - + CNetChunk p; p.m_ClientID = -1; p.m_Address = Packet.m_Address; p.m_Flags = NETSENDFLAG_CONNLESS; - + for(int i = 0; i < m_NumPacketsLegacy; i++) { p.m_DataSize = m_aPacketsLegacy[i].m_Size; @@ -520,7 +520,7 @@ int main(int argc, const char **argv) // ignore_convention { // check if the server is banned if(CheckBan(Packet.m_Address)) continue; - + if(Packet.m_DataSize == sizeof(SERVERBROWSE_FWRESPONSE) && mem_comp(Packet.m_pData, SERVERBROWSE_FWRESPONSE, sizeof(SERVERBROWSE_FWRESPONSE)) == 0) { @@ -546,7 +546,7 @@ int main(int argc, const char **argv) // ignore_convention SendOk(&Packet.m_Address); } } - + if(time_get()-LastBanReload > time_freq()*300) { LastBanReload = time_get(); @@ -557,15 +557,15 @@ int main(int argc, const char **argv) // ignore_convention if(time_get()-LastBuild > time_freq()*5) { LastBuild = time_get(); - + PurgeServers(); UpdateServers(); BuildPackets(); } - + // be nice to the CPU thread_sleep(1); } - + return 0; } diff --git a/src/osxlaunch/client.h b/src/osxlaunch/client.h index be59d0b90..450b8543b 100644 --- a/src/osxlaunch/client.h +++ b/src/osxlaunch/client.h @@ -1,10 +1,10 @@ #ifndef OSXLAUNCH_CLIENT_H #define OSXLAUNCH_CLIENT_H -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn - Feel free to customize this file to suit your needs + Feel free to customize this file to suit your needs */ #import diff --git a/src/osxlaunch/client.m b/src/osxlaunch/client.m index c6e6203e3..6de919e2a 100644 --- a/src/osxlaunch/client.m +++ b/src/osxlaunch/client.m @@ -1,8 +1,8 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn - Feel free to customize this file to suit your needs + Feel free to customize this file to suit your needs */ #import @@ -36,25 +36,25 @@ extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); #endif /* SDL_USE_CPS */ -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; -static BOOL gCalledAppMainline = FALSE; +static int gArgc; +static char **gArgv; +static BOOL gFinderLaunch; +static BOOL gCalledAppMainline = FALSE; static NSString *getApplicationName(void) { - NSDictionary *dict; - NSString *appName = 0; + NSDictionary *dict; + NSString *appName = 0; - /* Determine the application name */ - dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; + /* Determine the application name */ + dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); + if (dict) + appName = [dict objectForKey: @"CFBundleName"]; - return appName; + if (![appName length]) + appName = [[NSProcessInfo processInfo] processName]; + + return appName; } #if SDL_USE_NIB_FILE @@ -71,10 +71,10 @@ static NSString *getApplicationName(void) /* Invoked from the Quit menu item */ - (void)terminate:(id)sender { - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); + /* Post a SDL_QUIT event */ + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); } @end @@ -93,133 +93,133 @@ static NSString *getApplicationName(void) /* Fix menu to contain the real app name instead of "SDL App" */ - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName { - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; + NSRange aRange; + NSEnumerator *enumerator; + NSMenuItem *menuItem; - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; + aRange = [[aMenu title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } - [ aMenu sizeToFit ]; + enumerator = [[aMenu itemArray] objectEnumerator]; + while ((menuItem = [enumerator nextObject])) + { + aRange = [[menuItem title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; + if ([menuItem hasSubmenu]) + [self fixMenu:[menuItem submenu] withAppName:appName]; + } + [ aMenu sizeToFit ]; } #else static void setApplicationMenu(void) { - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + /* warning: this code is very odd */ + NSMenu *appleMenu; + NSMenuItem *menuItem; + NSString *title; + NSString *appName; - [appleMenu addItem:[NSMenuItem separatorItem]]; + appName = getApplicationName(); + appleMenu = [[NSMenu alloc] initWithTitle:@""]; - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; + /* Add menu items */ + title = [@"About " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; + [appleMenu addItem:[NSMenuItem separatorItem]]; - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; + title = [@"Hide " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - [appleMenu addItem:[NSMenuItem separatorItem]]; + menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; + [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; + [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; + [appleMenu addItem:[NSMenuItem separatorItem]]; - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; + title = [@"Quit " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; + + /* Put menu into the menubar */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:appleMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Tell the application object that this is now the application menu */ + [NSApp setAppleMenu:appleMenu]; + + /* Finally give up our references to the objects */ + [appleMenu release]; + [menuItem release]; } /* Create a window menu */ static void setupWindowMenu(void) { - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; + NSMenu *windowMenu; + NSMenuItem *windowMenuItem; + NSMenuItem *menuItem; - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; + /* "Minimize" item */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; + [windowMenu addItem:menuItem]; + [menuItem release]; + + /* Put menu into the menubar */ + windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; + [windowMenuItem setSubmenu:windowMenu]; + [[NSApp mainMenu] addItem:windowMenuItem]; + + /* Tell the application object that this is now the window menu */ + [NSApp setWindowsMenu:windowMenu]; + + /* Finally give up our references to the objects */ + [windowMenu release]; + [windowMenuItem release]; } /* Replacement for NSApplicationMain */ static void CustomApplicationMain (int argc, char **argv) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SDLMain *sdlMain; + + /* Ensure the application object is initialised */ + [SDLApplication sharedApplication]; - /* Ensure the application object is initialised */ - [SDLApplication sharedApplication]; - #ifdef SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [SDLApplication sharedApplication]; - } + { + CPSProcessSerNum PSN; + /* Tell the dock about us */ + if (!CPSGetCurrentProcess(&PSN)) + if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) + if (!CPSSetFrontProcess(&PSN)) + [SDLApplication sharedApplication]; + } #endif /* SDL_USE_CPS */ - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); + /* Set up the menubar */ + [NSApp setMainMenu:[[NSMenu alloc] init]]; + setApplicationMenu(); + setupWindowMenu(); - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; + /* Create SDLMain and make it the app delegate */ + sdlMain = [[SDLMain alloc] init]; + [NSApp setDelegate:sdlMain]; + + /* Start the main event loop */ + [NSApp run]; + + [sdlMain release]; + [pool release]; } #endif @@ -227,14 +227,14 @@ static void CustomApplicationMain (int argc, char **argv) /* * Catch document open requests...this lets us notice files when the app - * was launched by double-clicking a document, or when a document was - * dragged/dropped on the app's icon. You need to have a - * CFBundleDocumentsType section in your Info.plist to get this message, - * apparently. + * was launched by double-clicking a document, or when a document was + * dragged/dropped on the app's icon. You need to have a + * CFBundleDocumentsType section in your Info.plist to get this message, + * apparently. * * Files are added to gArgv, so to the app, they'll look like command line - * arguments. Previously, apps launched from the finder had nothing but - * an argv[0]. + * arguments. Previously, apps launched from the finder had nothing but + * an argv[0]. * * This message may be received multiple times to open several docs on launch. * @@ -242,57 +242,57 @@ static void CustomApplicationMain (int argc, char **argv) */ - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { - const char *temparg; - size_t arglen; - char *arg; - char **newargv; + const char *temparg; + size_t arglen; + char *arg; + char **newargv; - if (!gFinderLaunch) /* MacOS is passing command line args. */ - return FALSE; + if (!gFinderLaunch) /* MacOS is passing command line args. */ + return FALSE; - if (gCalledAppMainline) /* app has started, ignore this document. */ - return FALSE; + if (gCalledAppMainline) /* app has started, ignore this document. */ + return FALSE; - temparg = [filename UTF8String]; - arglen = SDL_strlen(temparg) + 1; - arg = (char *) SDL_malloc(arglen); - if (arg == NULL) - return FALSE; + temparg = [filename UTF8String]; + arglen = SDL_strlen(temparg) + 1; + arg = (char *) SDL_malloc(arglen); + if (arg == NULL) + return FALSE; - newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); - if (newargv == NULL) - { - SDL_free(arg); - return FALSE; - } - gArgv = newargv; + newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); + if (newargv == NULL) + { + SDL_free(arg); + return FALSE; + } + gArgv = newargv; - SDL_strlcpy(arg, temparg, arglen); - gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; - return TRUE; + SDL_strlcpy(arg, temparg, arglen); + gArgv[gArgc++] = arg; + gArgv[gArgc] = NULL; + return TRUE; } /* Called when the internal event loop has just started running */ - (void) applicationDidFinishLaunching: (NSNotification *) note { - int status; + int status; - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; + /* Set the working directory to the .app's parent directory */ + [self setupWorkingDirectory:gFinderLaunch]; #if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; + /* Set the main menu to contain the real app name instead of "SDL App" */ + [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; #endif - /* Hand off to main application code */ - gCalledAppMainline = TRUE; - status = SDL_main (gArgc, gArgv); + /* Hand off to main application code */ + gCalledAppMainline = TRUE; + status = SDL_main (gArgc, gArgv); - /* We're done, thank you for playing */ - exit(status); + /* We're done, thank you for playing */ + exit(status); } @end @@ -301,65 +301,65 @@ static void CustomApplicationMain (int argc, char **argv) - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString { - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; + unsigned int bufferSize; + unsigned int selfLen = [self length]; + unsigned int aStringLen = [aString length]; + unichar *buffer; + NSRange localRange; + NSString *result; - bufferSize = selfLen + aStringLen - aRange.length; - buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; + bufferSize = selfLen + aStringLen - aRange.length; + buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); + + /* Get first part into buffer */ + localRange.location = 0; + localRange.length = aRange.location; + [self getCharacters:buffer range:localRange]; + + /* Get middle part into buffer */ + localRange.location = 0; + localRange.length = aStringLen; + [aString getCharacters:(buffer+aRange.location) range:localRange]; + + /* Get last part into buffer */ + localRange.location = aRange.location + aRange.length; + localRange.length = selfLen - localRange.location; + [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; + + /* Build output string */ + result = [NSString stringWithCharacters:buffer length:bufferSize]; + + NSDeallocateMemoryPages(buffer, bufferSize); + + return result; } @end #ifdef main -# undef main +#undef main #endif /* Main entry point to executable - should *not* be SDL_main! */ int main (int argc, char **argv) { - /* Copy the arguments into a global variable */ - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgv = (char **) SDL_malloc(sizeof (char *) * 2); - gArgv[0] = argv[0]; - gArgv[1] = NULL; - gArgc = 1; - gFinderLaunch = YES; - } else { - int i; - gArgc = argc; - gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); - for (i = 0; i <= argc; i++) - gArgv[i] = argv[i]; - gFinderLaunch = NO; - } + /* Copy the arguments into a global variable */ + /* This is passed if we are launched by double-clicking */ + if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { + gArgv = (char **) SDL_malloc(sizeof (char *) * 2); + gArgv[0] = argv[0]; + gArgv[1] = NULL; + gArgc = 1; + gFinderLaunch = YES; + } else { + int i; + gArgc = argc; + gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); + for (i = 0; i <= argc; i++) + gArgv[i] = argv[i]; + gFinderLaunch = NO; + } #if SDL_USE_NIB_FILE [SDLApplication poseAsClass:[NSApplication class]]; @@ -368,6 +368,6 @@ int main (int argc, char **argv) CustomApplicationMain (argc, argv); #endif - return 0; + return 0; } diff --git a/src/osxlaunch/server.m b/src/osxlaunch/server.m index 6c22efc55..5ae32c6fa 100644 --- a/src/osxlaunch/server.m +++ b/src/osxlaunch/server.m @@ -13,9 +13,9 @@ { NSPipe *pipe; task = t; - pipe = [NSPipe pipe]; - [task setStandardOutput: pipe]; - file = [pipe fileHandleForReading]; + pipe = [NSPipe pipe]; + [task setStandardOutput: pipe]; + file = [pipe fileHandleForReading]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(outputNotification:) name: NSFileHandleReadCompletionNotification object: file]; @@ -30,8 +30,8 @@ [[self textStorage] appendAttributedString: attrstr]; int length = [[self textStorage] length]; - NSRange range = NSMakeRange(length, 0); - [self scrollRangeToVisible: range]; + NSRange range = NSMakeRange(length, 0); + [self scrollRangeToVisible: range]; [attrstr release]; [string release]; @@ -41,18 +41,18 @@ -(void)windowWillClose:(NSNotification *)notification { [task terminate]; - [NSApp terminate:self]; + [NSApp terminate:self]; } @end void runServer() { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSApp = [NSApplication sharedApplication]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSApp = [NSApplication sharedApplication]; NSBundle* mainBundle = [NSBundle mainBundle]; NSTask *task; - task = [[NSTask alloc] init]; - [task setCurrentDirectoryPath: [mainBundle resourcePath]]; + task = [[NSTask alloc] init]; + [task setCurrentDirectoryPath: [mainBundle resourcePath]]; // get a server config NSOpenPanel* openDlg = [NSOpenPanel openPanel]; @@ -77,8 +77,8 @@ void runServer() window = [[NSWindow alloc] initWithContentRect: graphicsRect - styleMask: NSTitledWindowMask - | NSClosableWindowMask + styleMask: NSTitledWindowMask + | NSClosableWindowMask | NSMiniaturizableWindowMask backing: NSBackingStoreBuffered defer: NO]; @@ -100,8 +100,8 @@ void runServer() [NSApp run]; [task terminate]; - [NSApp release]; - [pool release]; + [NSApp release]; + [pool release]; } int main (int argc, char **argv) diff --git a/src/tools/crapnet.cpp b/src/tools/crapnet.cpp index 35ca09bc3..98b6c0a76 100644 --- a/src/tools/crapnet.cpp +++ b/src/tools/crapnet.cpp @@ -8,7 +8,7 @@ struct CPacket { CPacket *m_pPrev; CPacket *m_pNext; - + NETADDR m_SendTo; int64 m_Timestamp; int m_ID; @@ -46,21 +46,21 @@ void Run(int Port, NETADDR Dest) { NETADDR Src = {NETTYPE_IPV4, {0,0,0,0}, Port}; NETSOCKET Socket = net_udp_create(Src); - + char aBuffer[1024*2]; int ID = 0; int Delaycounter = 0; - + while(1) { static int Lastcfg = 0; int n = ((time_get()/time_freq())/m_ConfigInterval) % m_ConfigNumpingconfs; CPingConfig Ping = m_aConfigPings[n]; - + if(n != Lastcfg) dbg_msg("crapnet", "cfg = %d", n); Lastcfg = n; - + // handle incomming packets while(1) { @@ -70,7 +70,7 @@ void Run(int Port, NETADDR Dest) int Bytes = net_udp_recv(Socket, &From, aBuffer, 1024*2); if(Bytes <= 0) break; - + if((rand()%100) < Ping.m_Loss) // drop the packet { if(m_ConfigLog) @@ -78,7 +78,7 @@ void Run(int Port, NETADDR Dest) continue; } - // create new packet + // create new packet CPacket *p = (CPacket *)mem_alloc(sizeof(CPacket)+Bytes, 1); if(net_addr_comp(&From, &Dest) == 0) @@ -106,7 +106,7 @@ void Run(int Port, NETADDR Dest) p->m_DataSize = Bytes; p->m_ID = ID++; mem_copy(p->m_aData, aBuffer, Bytes); - + if(ID > 20 && Bytes > 6 && DataTrash) { p->m_aData[6+(rand()%(Bytes-6))] = rand()&255; // modify a byte @@ -117,7 +117,7 @@ void Run(int Port, NETADDR Dest) p->m_DataSize = 6; } } - + if(Delaycounter <= 0) { if(Ping.m_Delay) @@ -125,7 +125,7 @@ void Run(int Port, NETADDR Dest) Delaycounter = Ping.m_DelayFreq; } Delaycounter--; - + if(m_ConfigLog) { char aAddrStr[NETADDR_MAXSTRSIZE]; @@ -133,7 +133,7 @@ void Run(int Port, NETADDR Dest) dbg_msg("crapnet", "<< %08d %s (%d)", p->m_ID, aAddrStr, p->m_DataSize); } } - + // /*while(1) {*/ @@ -145,7 +145,7 @@ void Run(int Port, NETADDR Dest) if(!p) break; pNext = p->m_pNext; - + if((time_get()-p->m_Timestamp) > m_CurrentLatency) { char aFlags[] = " "; @@ -155,35 +155,35 @@ void Run(int Port, NETADDR Dest) aFlags[0] = 'R'; p = m_pFirst->m_pNext; } - + if(p->m_pNext) p->m_pNext->m_pPrev = p->m_pPrev; else m_pLast = p->m_pPrev; - + if(p->m_pPrev) p->m_pPrev->m_pNext = p->m_pNext; else m_pFirst = p->m_pNext; - + /*CPacket *cur = first; while(cur) { dbg_assert(cur != p, "p still in list"); cur = cur->next; }*/ - + // send and remove packet //if((rand()%20) != 0) // heavy packetloss net_udp_send(Socket, &p->m_SendTo, p->m_aData, p->m_DataSize); - + // update lag double Flux = rand()/(double)RAND_MAX; int MsSpike = Ping.m_Spike; int MsFlux = Ping.m_Flux; int MsPing = Ping.m_Base; m_CurrentLatency = ((time_freq()*MsPing)/1000) + (int64)(((time_freq()*MsFlux)/1000)*Flux); // 50ms - + if(MsSpike && (p->m_ID%100) == 0) { m_CurrentLatency += (time_freq()*MsSpike)/1000; @@ -196,12 +196,12 @@ void Run(int Port, NETADDR Dest) net_addr_str(&p->m_SendTo, aAddrStr, sizeof(aAddrStr)); dbg_msg("crapnet", ">> %08d %s (%d) %s", p->m_ID, aAddrStr, p->m_DataSize, aFlags); } - + mem_free(p); } } - + thread_sleep(1); } } diff --git a/src/tools/dilate.cpp b/src/tools/dilate.cpp index b1b60ac30..ef862270f 100644 --- a/src/tools/dilate.cpp +++ b/src/tools/dilate.cpp @@ -14,7 +14,7 @@ static void Dilate(int w, int h, CPixel *pSrc, CPixel *pDest) int ix, iy; const int xo[] = {0, -1, 1, 0}; const int yo[] = {-1, 0, 0, 1}; - + int m = 0; for(int y = 0; y < h; y++) { @@ -23,7 +23,7 @@ static void Dilate(int w, int h, CPixel *pSrc, CPixel *pDest) pDest[m] = pSrc[m]; if(pSrc[m].a) continue; - + for(int c = 0; c < 4; c++) { ix = clamp(x + xo[c], 0, w-1); @@ -52,38 +52,38 @@ int main(int argc, char **argv) { png_t Png; CPixel *pBuffer[3] = {0,0,0}; - + png_init(0, 0); png_open_file(&Png, argv[1]); - + if(Png.color_type != PNG_TRUECOLOR_ALPHA) { dbg_msg("dilate", "not an RGBA image"); return -1; } - + pBuffer[0] = (CPixel*)mem_alloc(Png.width*Png.height*sizeof(CPixel), 1); pBuffer[1] = (CPixel*)mem_alloc(Png.width*Png.height*sizeof(CPixel), 1); pBuffer[2] = (CPixel*)mem_alloc(Png.width*Png.height*sizeof(CPixel), 1); png_get_data(&Png, (unsigned char *)pBuffer[0]); png_close_file(&Png); - + int w = Png.width; int h = Png.height; - + Dilate(w, h, pBuffer[0], pBuffer[1]); for(int i = 0; i < 5; i++) { Dilate(w, h, pBuffer[1], pBuffer[2]); Dilate(w, h, pBuffer[2], pBuffer[1]); } - + CopyAlpha(w, h, pBuffer[0], pBuffer[1]); - + // save here png_open_file_write(&Png, argv[1]); png_set_data(&Png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pBuffer[1]); png_close_file(&Png); - + return 0; } diff --git a/src/tools/fake_server.cpp b/src/tools/fake_server.cpp index ac7a8ed93..68c476594 100644 --- a/src/tools/fake_server.cpp +++ b/src/tools/fake_server.cpp @@ -31,18 +31,18 @@ static void SendHeartBeats() { static unsigned char aData[sizeof(SERVERBROWSE_HEARTBEAT) + 2]; CNetChunk Packet; - + mem_copy(aData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)); - + Packet.m_ClientID = -1; Packet.m_Flags = NETSENDFLAG_CONNLESS; Packet.m_DataSize = sizeof(SERVERBROWSE_HEARTBEAT) + 2; Packet.m_pData = &aData; - /* supply the set port that the master can use if it has problems */ + /* supply the set port that the master can use if it has problems */ aData[sizeof(SERVERBROWSE_HEARTBEAT)] = 0; aData[sizeof(SERVERBROWSE_HEARTBEAT)+1] = 0; - + for(int i = 0; i < NumMasters; i++) { Packet.m_Address = aMasterServers[i]; @@ -78,7 +78,7 @@ static void BuildInfoMsg() WriteInt(Progression); WriteInt(NumPlayers); WriteInt(MaxPlayers); - + for(int i = 0; i < NumPlayers; i++) { WriteStr(PlayerNames[i]); @@ -112,10 +112,10 @@ static int Run() { int64 NextHeartBeat = 0; NETADDR BindAddr = {NETTYPE_IPV4, {0},0}; - + if(!pNet->Open(BindAddr, 0, 0, 0)) return 0; - + while(1) { CNetChunk p; @@ -136,14 +136,14 @@ static int Run() } } } - + /* send heartbeats if needed */ if(NextHeartBeat < time_get()) { NextHeartBeat = time_get()+time_freq()*(15+(rand()%15)); SendHeartBeats(); } - + thread_sleep(100); } } @@ -151,7 +151,7 @@ static int Run() int main(int argc, char **argv) { pNet = new CNetServer; - + while(argc) { // ? @@ -200,13 +200,13 @@ int main(int argc, char **argv) argc--; argv++; pServerName = *argv; } - + argc--; argv++; } - + BuildInfoMsg(); int RunReturn = Run(); - + delete pNet; return RunReturn; } diff --git a/src/tools/map_resave.cpp b/src/tools/map_resave.cpp index d97f0323e..a536f021e 100644 --- a/src/tools/map_resave.cpp +++ b/src/tools/map_resave.cpp @@ -25,7 +25,7 @@ int main(int argc, const char **argv) // add all items for(Index = 0; Index < DataFile.NumItems(); Index++) - { + { pPtr = DataFile.GetItem(Index, &Type, &ID); Size = DataFile.GetItemSize(Index); df.AddItem(Type, ID, Size, pPtr); diff --git a/src/tools/map_version.cpp b/src/tools/map_version.cpp index d995f4784..4acc51e04 100644 --- a/src/tools/map_version.cpp +++ b/src/tools/map_version.cpp @@ -29,7 +29,7 @@ int MaplistCallback(const char *pName, int IsDir, int DirType, void *pUser) IOHANDLE MapFile = s_pStorage->OpenFile(aBuf, IOFLAG_READ, DirType); unsigned MapSize = io_length(MapFile); io_close(MapFile); - + char aMapName[8]; str_copy(aMapName, pName, min((int)sizeof(aMapName),l-3)); @@ -52,7 +52,7 @@ int main(int argc, const char **argv) // ignore_convention if(RegisterFail) return -1; - + s_File = s_pStorage->OpenFile("map_version.txt", IOFLAG_WRITE, 1); if(s_File) { @@ -61,6 +61,6 @@ int main(int argc, const char **argv) // ignore_convention io_write(s_File, "};\n", str_length("};\n")); io_close(s_File); } - + return 0; } diff --git a/src/tools/packetgen.cpp b/src/tools/packetgen.cpp index 7e9a8a197..9b52aadce 100644 --- a/src/tools/packetgen.cpp +++ b/src/tools/packetgen.cpp @@ -7,13 +7,13 @@ enum { NUM_SOCKETS = 64 }; void Run(NETADDR Dest) { NETSOCKET aSockets[NUM_SOCKETS]; - + for(int i = 0; i < NUM_SOCKETS; i++) { NETADDR BindAddr = {NETTYPE_IPV4, {0}, 0}; aSockets[i] = net_udp_create(BindAddr); } - + while(1) { unsigned char aData[1024]; diff --git a/src/tools/tileset_borderfix.cpp b/src/tools/tileset_borderfix.cpp index d28e3074a..b5eef77a8 100644 --- a/src/tools/tileset_borderfix.cpp +++ b/src/tools/tileset_borderfix.cpp @@ -20,9 +20,9 @@ static void TilesetBorderfix(int w, int h, CPixel *pSrc, CPixel *pDest) { int TileW = w/16; int TileH = h/16; - + mem_zero(pDest, sizeof(CPixel)*w*h); - + for(int ty = 0; ty < 16; ty++) { for(int tx = 0; tx < 16; tx++) @@ -35,12 +35,12 @@ static void TilesetBorderfix(int w, int h, CPixel *pSrc, CPixel *pDest) float v = 0.5f/TileH + y/(float)(TileH-2); int k = (ty*TileH+1+y)*w + tx*TileW+x+1; pDest[k] = Sample(tx*TileW, ty*TileH, TileW, TileH, pSrc, w, u, v); - + if(x == 0) pDest[k-1] = pDest[k]; if(x == TileW-2-1) pDest[k+1] = pDest[k]; if(y == 0) pDest[k-w] = pDest[k]; if(y == TileH-2-1) pDest[k+w] = pDest[k]; - + if(x == 0 && y == 0) pDest[k-w-1] = pDest[k]; if(x == TileW-2-1 && y == 0) pDest[k-w+1] = pDest[k]; if(x == 0 && y == TileH-2-1) pDest[k+w-1] = pDest[k]; @@ -56,30 +56,30 @@ int main(int argc, char **argv) { png_t Png; CPixel *pBuffer[2] = {0,0}; - + png_init(0, 0); png_open_file(&Png, argv[1]); - + if(Png.color_type != PNG_TRUECOLOR_ALPHA) { dbg_msg("dilate", "not an RGBA image"); return -1; } - + int w = Png.width; int h = Png.height; - + pBuffer[0] = (CPixel*)mem_alloc(w*h*sizeof(CPixel), 1); pBuffer[1] = (CPixel*)mem_alloc(w*h*sizeof(CPixel), 1); png_get_data(&Png, (unsigned char *)pBuffer[0]); png_close_file(&Png); - + TilesetBorderfix(w, h, pBuffer[0], pBuffer[1]); - + // save here png_open_file_write(&Png, argv[1]); png_set_data(&Png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pBuffer[1]); png_close_file(&Png); - + return 0; } diff --git a/src/versionsrv/versionsrv.cpp b/src/versionsrv/versionsrv.cpp index d36fba3b4..ac5883f9d 100644 --- a/src/versionsrv/versionsrv.cpp +++ b/src/versionsrv/versionsrv.cpp @@ -37,19 +37,19 @@ void BuildPackets() if(Chunk > MAX_MAPS_PER_PACKET) Chunk = MAX_MAPS_PER_PACKET; ServersLeft -= Chunk; - - // copy header + + // copy header mem_copy(m_aPackets[m_NumPackets].m_Data.m_aHeader, VERSIONSRV_MAPLIST, sizeof(VERSIONSRV_MAPLIST)); - + // copy map versions for(int i = 0; i < Chunk; i++) { m_aPackets[m_NumPackets].m_Data.m_aMaplist[i] = *pCurrent; pCurrent++; } - + m_aPackets[m_NumPackets].m_Size = sizeof(VERSIONSRV_MAPLIST) + sizeof(CMapVersion)*Chunk; - + m_NumPackets++; } } @@ -58,10 +58,10 @@ void SendVer(NETADDR *pAddr) { CNetChunk p; unsigned char aData[sizeof(VERSIONSRV_VERSION) + sizeof(VERSION_DATA)]; - + mem_copy(aData, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION)); mem_copy(aData + sizeof(VERSIONSRV_VERSION), VERSION_DATA, sizeof(VERSION_DATA)); - + p.m_ClientID = -1; p.m_Address = *pAddr; p.m_Flags = NETSENDFLAG_CONNLESS; @@ -88,13 +88,13 @@ int main(int argc, char **argv) // ignore_convention } BuildPackets(); - + dbg_msg("versionsrv", "started"); - + while(1) { g_NetOp.Update(); - + // process packets CNetChunk Packet; while(g_NetOp.Recv(&Packet)) @@ -112,7 +112,7 @@ int main(int argc, char **argv) // ignore_convention p.m_ClientID = -1; p.m_Address = Packet.m_Address; p.m_Flags = NETSENDFLAG_CONNLESS; - + for(int i = 0; i < m_NumPackets; i++) { p.m_DataSize = m_aPackets[i].m_Size; @@ -121,10 +121,10 @@ int main(int argc, char **argv) // ignore_convention } } } - + // be nice to the CPU thread_sleep(1); } - + return 0; } From 1d426f1df93e9df88e9c98e3c993f4836927ec05 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 13 Apr 2011 20:45:16 +0200 Subject: [PATCH 10/12] fixed problem with ui_page --- src/game/variables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/variables.h b/src/game/variables.h index c4a37fa7c..ee8cb74a5 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -41,7 +41,7 @@ MACRO_CONFIG_INT(PlayerColorBody, player_color_body, 65408, 0, 0xFFFFFF, CFGFLAG MACRO_CONFIG_INT(PlayerColorFeet, player_color_feet, 65408, 0, 0xFFFFFF, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player feet color") MACRO_CONFIG_STR(PlayerSkin, player_skin, 24, "default", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin") -MACRO_CONFIG_INT(UiPage, ui_page, 5, 0, 9, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface page") +MACRO_CONFIG_INT(UiPage, ui_page, 5, 0, 10, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface page") MACRO_CONFIG_INT(UiToolboxPage, ui_toolbox_page, 0, 0, 2, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toolbox page") MACRO_CONFIG_STR(UiServerAddress, ui_server_address, 64, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address") MACRO_CONFIG_INT(UiScale, ui_scale, 100, 50, 150, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface scale") From 43a6c022638278a190c450482bf4eb04cfaafb53 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 13 Apr 2011 20:48:50 +0200 Subject: [PATCH 11/12] fixed the nethash --- scripts/cmd5.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cmd5.py b/scripts/cmd5.py index 0eac2a335..69eb83b8c 100644 --- a/scripts/cmd5.py +++ b/scripts/cmd5.py @@ -30,6 +30,6 @@ for filename in sys.argv[1:]: hash = hashlib.md5(f).hexdigest().lower()[16:] #TODO 0.7: improve nethash creation -if hash == "e20714704d311d78": +if hash == "6e28a475de43adfd": hash = "626fce9a778df4d4" print('#define GAME_NETVERSION_HASH "%s"' % hash) From 2f99b4e324e17cbb692b7cdf9e9ed01bb5b794bd Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 13 Apr 2011 21:08:34 +0200 Subject: [PATCH 12/12] forgot to add the music file --- data/audio/music_menu.wv | Bin 0 -> 678784 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 data/audio/music_menu.wv diff --git a/data/audio/music_menu.wv b/data/audio/music_menu.wv new file mode 100644 index 0000000000000000000000000000000000000000..b396c5811c75ee523e05041ec00041aa24918f62 GIT binary patch literal 678784 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⪙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
7;u;6^LuG~OZMRD_ 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