mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
commit
77f5826146
14
.github/workflows/build.yaml
vendored
14
.github/workflows/build.yaml
vendored
|
@ -80,11 +80,11 @@ jobs:
|
|||
cd debug
|
||||
${{ matrix.cmake-path }}cmake --version
|
||||
${{ matrix.cmake-path }}cmake ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=Debug -Werror=dev -DDOWNLOAD_GTEST=ON -DDEV=ON -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG=. ..
|
||||
${{ matrix.cmake-path }}cmake --build . --config Debug ${{ matrix.build-args }} --target everything
|
||||
${{ matrix.cmake-path }}cmake --build . --config Debug --target everything ${{ matrix.build-args }}
|
||||
- name: Test debug
|
||||
run: |
|
||||
cd debug
|
||||
${{ matrix.cmake-path }}cmake --build . --config Debug ${{ matrix.build-args }} --target run_tests
|
||||
${{ matrix.cmake-path }}cmake --build . --config Debug --target run_tests ${{ matrix.build-args }}
|
||||
./DDNet-Server shutdown
|
||||
|
||||
- name: Build in release mode
|
||||
|
@ -93,11 +93,11 @@ jobs:
|
|||
mkdir release
|
||||
cd release
|
||||
${{ matrix.cmake-path }}cmake ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=Release -Werror=dev -DDOWNLOAD_GTEST=ON -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=. ..
|
||||
${{ matrix.cmake-path }}cmake --build . --config Release ${{ matrix.build-args }} --target everything
|
||||
${{ matrix.cmake-path }}cmake --build . --config Release --target everything ${{ matrix.build-args }}
|
||||
- name: Test release
|
||||
run: |
|
||||
cd release
|
||||
${{ matrix.cmake-path }}cmake --build . --config Release ${{ matrix.build-args }} --target run_tests
|
||||
${{ matrix.cmake-path }}cmake --build . --config Release --target run_tests ${{ matrix.build-args }}
|
||||
./DDNet-Server shutdown
|
||||
|
||||
- name: Build in release mode with debug info and all features on
|
||||
|
@ -107,18 +107,18 @@ jobs:
|
|||
mkdir fancy
|
||||
cd fancy
|
||||
${{ matrix.cmake-path }}cmake ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DANTIBOT=ON -DMYSQL=ON -DWEBSOCKETS=ON ..
|
||||
${{ matrix.cmake-path }}cmake --build . --config RelWithDebInfo ${{ matrix.build-args }} --target everything
|
||||
${{ matrix.cmake-path }}cmake --build . --config RelWithDebInfo --target everything ${{ matrix.build-args }}
|
||||
- name: Test fancy
|
||||
if: matrix.fancy
|
||||
run: |
|
||||
cd release
|
||||
${{ matrix.cmake-path }}cmake --build . --config RelWithDebInfo ${{ matrix.build-args }} --target run_tests
|
||||
${{ matrix.cmake-path }}cmake --build . --config RelWithDebInfo --target run_tests ${{ matrix.build-args }}
|
||||
./DDNet-Server shutdown
|
||||
|
||||
- name: Package
|
||||
run: |
|
||||
cd release
|
||||
${{ matrix.cmake-path }}cmake --build . --config Release ${{ matrix.build-args }} --target package_default
|
||||
${{ matrix.cmake-path }}cmake --build . --config Release --target package_default ${{ matrix.build-args }}
|
||||
mkdir artifacts
|
||||
mv ${{ matrix.package-file }} artifacts
|
||||
|
||||
|
|
|
@ -2336,7 +2336,6 @@ set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION
|
|||
set(CPACK_SOURCE_FILES
|
||||
CMakeLists.txt
|
||||
README.md
|
||||
autoexec_server.cfg
|
||||
cmake/
|
||||
data/
|
||||
datasrc/
|
||||
|
@ -2380,7 +2379,6 @@ set(CPACK_DIRS data)
|
|||
set(CPACK_FILES
|
||||
license.txt
|
||||
storage.cfg
|
||||
autoexec_server.cfg
|
||||
${COPY_FILES}
|
||||
)
|
||||
if(TARGET_OS STREQUAL "windows")
|
||||
|
|
|
@ -30,11 +30,11 @@ Dependencies on Linux
|
|||
|
||||
You can install the required libraries on your system, `touch CMakeLists.txt` and CMake will use the system-wide libraries by default. You can install all required dependencies and CMake on Debian or Ubuntu like this:
|
||||
|
||||
sudo apt install build-essential cmake git libcurl4-openssl-dev libssl-dev libfreetype6-dev libglew-dev libnotify-dev libogg-dev libopus-dev libopusfile-dev libpnglite-dev libsdl2-dev libsqlite3-dev libwavpack-dev python
|
||||
sudo apt install build-essential cmake git libcurl4-openssl-dev libssl-dev libfreetype6-dev libglew-dev libnotify-dev libogg-dev libopus-dev libopusfile-dev libpnglite-dev libsdl2-dev libsqlite3-dev libwavpack-dev python google-mock
|
||||
|
||||
Or on Arch Linux like this:
|
||||
|
||||
sudo pacman -S --needed base-devel cmake curl freetype2 git glew libnotify opusfile python sdl2 sqlite wavpack
|
||||
sudo pacman -S --needed base-devel cmake curl freetype2 git glew libnotify opusfile python sdl2 sqlite wavpack gmock
|
||||
|
||||
There is an [AUR package for pnglite](https://aur.archlinux.org/packages/pnglite/). For instructions on installing it, see [AUR packages installation instructions on ArchWiki](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages).
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ if(NOT CMAKE_CROSSCOMPILING)
|
|||
pkg_check_modules(PC_SWSCALE libswscale)
|
||||
pkg_check_modules(PC_SWRESAMPLE libswresample)
|
||||
if(TARGET_OS STREQUAL "linux")
|
||||
pkg_check_modules(PC_X264 libx264)
|
||||
pkg_search_module(PC_X264 libx264 x264)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
</content_rating>
|
||||
<releases>
|
||||
<release date="2021-03-25" version="15.4"/>
|
||||
<release date="2021-02-20" version="15.3.2"/>
|
||||
<release date="2021-02-12" version="15.3.1"/>
|
||||
<release date="2021-02-11" version="15.3"/>
|
||||
|
|
|
@ -4,6 +4,7 @@ import os
|
|||
import shlex
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
ConfigDmgtools = namedtuple('Config', 'dmg hfsplus newfs_hfs verbose')
|
||||
ConfigHdiutil = namedtuple('Config', 'hdiutil verbose')
|
||||
|
@ -72,7 +73,16 @@ class Hdiutil(Dmg):
|
|||
def create(self, dmg, volume_name, directory, symlinks):
|
||||
if symlinks:
|
||||
raise NotImplementedError("symlinks are not yet implemented")
|
||||
self._hdiutil('create', '-volname', volume_name, '-srcdir', directory, dmg)
|
||||
for i in range(5):
|
||||
try:
|
||||
self._hdiutil('create', '-volname', volume_name, '-srcdir', directory, dmg)
|
||||
except subprocess.CalledProcessError as e:
|
||||
if i == 4:
|
||||
raise e
|
||||
print("Retrying hdiutil create")
|
||||
time.sleep(5)
|
||||
else:
|
||||
break
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description="Manipulate dmg archives")
|
||||
|
|
|
@ -3017,8 +3017,8 @@ const char *str_utf8_find_nocase(const char *haystack, const char *needle)
|
|||
|
||||
int str_utf8_isspace(int code)
|
||||
{
|
||||
return code <= 0x0020 || code == 0x0085 || code == 0x00A0 ||
|
||||
code == 0x034F || code == 0x1160 || code == 0x1680 || code == 0x180E ||
|
||||
return code <= 0x0020 || code == 0x0085 || code == 0x00A0 || code == 0x034F ||
|
||||
code == 0x115F || code == 0x1160 || code == 0x1680 || code == 0x180E ||
|
||||
(code >= 0x2000 && code <= 0x200F) || (code >= 0x2028 && code <= 0x202F) ||
|
||||
(code >= 0x205F && code <= 0x2064) || (code >= 0x206A && code <= 0x206F) ||
|
||||
code == 0x2800 || code == 0x3000 || code == 0x3164 ||
|
||||
|
|
|
@ -109,7 +109,7 @@ void sort_quick(R range)
|
|||
template<class R>
|
||||
void sort(R range)
|
||||
{
|
||||
std::sort(&range.front(), &range.back() + 1);
|
||||
std::stable_sort(&range.front(), &range.back() + 1);
|
||||
}
|
||||
|
||||
template<class R>
|
||||
|
|
|
@ -125,8 +125,7 @@ public:
|
|||
|
||||
// gfx
|
||||
virtual void SwitchWindowScreen(int Index) = 0;
|
||||
virtual void ToggleFullscreen() = 0;
|
||||
virtual void ToggleWindowBordered() = 0;
|
||||
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0;
|
||||
virtual void ToggleWindowVSync() = 0;
|
||||
virtual void LoadFont() = 0;
|
||||
virtual void Notify(const char *pTitle, const char *pMessage) = 0;
|
||||
|
@ -257,6 +256,7 @@ public:
|
|||
virtual const char *DDNetVersionStr() const = 0;
|
||||
|
||||
virtual void OnDummyDisconnect() = 0;
|
||||
virtual void DummyResetInput() = 0;
|
||||
virtual void Echo(const char *pString) = 0;
|
||||
virtual bool CanDisplayWarning() = 0;
|
||||
virtual bool IsDisplayingWarning() = 0;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include <cmath>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_hints.h"
|
||||
|
||||
#if defined(SDL_VIDEO_DRIVER_X11)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
@ -3785,6 +3787,13 @@ void CCommandProcessorFragment_SDL::Cmd_Init(const SCommand_Init *pCommand)
|
|||
// check what this context can do
|
||||
const char *pVersionString = (const char *)glGetString(GL_VERSION);
|
||||
dbg_msg("opengl", "Version string: %s", pVersionString);
|
||||
|
||||
const char *pRendererString = (const char *)glGetString(GL_RENDERER);
|
||||
|
||||
str_copy(pCommand->m_pVendorString, pVendorString, gs_GPUInfoStringSize);
|
||||
str_copy(pCommand->m_pVersionString, pVersionString, gs_GPUInfoStringSize);
|
||||
str_copy(pCommand->m_pRendererString, pRendererString, gs_GPUInfoStringSize);
|
||||
|
||||
// parse version string
|
||||
ParseVersionString(pVersionString, pCommand->m_pCapabilities->m_ContextMajor, pCommand->m_pCapabilities->m_ContextMinor, pCommand->m_pCapabilities->m_ContextPatch);
|
||||
|
||||
|
@ -4520,6 +4529,10 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt
|
|||
else
|
||||
SdlFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
else if(Flags & (IGraphicsBackend::INITFLAG_DESKTOP_FULLSCREEN))
|
||||
{
|
||||
SdlFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
|
||||
// set gl attributes
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
@ -4614,7 +4627,10 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt
|
|||
CmdSDL.m_GlewPatch = GlewPatch;
|
||||
CmdSDL.m_pInitError = &InitError;
|
||||
CmdSDL.m_pErrStringPtr = &pErrorStr;
|
||||
CmdBuffer.AddCommand(CmdSDL);
|
||||
CmdSDL.m_pVendorString = m_aVendorString;
|
||||
CmdSDL.m_pVersionString = m_aVersionString;
|
||||
CmdSDL.m_pRendererString = m_aRendererString;
|
||||
CmdBuffer.AddCommandUnsafe(CmdSDL);
|
||||
RunBuffer(&CmdBuffer);
|
||||
WaitForIdle();
|
||||
CmdBuffer.Reset();
|
||||
|
@ -4626,7 +4642,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt
|
|||
CmdOpenGL.m_pStorage = pStorage;
|
||||
CmdOpenGL.m_pCapabilities = &m_Capabilites;
|
||||
CmdOpenGL.m_pInitError = &InitError;
|
||||
CmdBuffer.AddCommand(CmdOpenGL);
|
||||
CmdBuffer.AddCommandUnsafe(CmdOpenGL);
|
||||
RunBuffer(&CmdBuffer);
|
||||
WaitForIdle();
|
||||
CmdBuffer.Reset();
|
||||
|
@ -4634,7 +4650,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt
|
|||
if(InitError == -2)
|
||||
{
|
||||
CCommandProcessorFragment_OpenGL::SCommand_Shutdown CmdGL;
|
||||
CmdBuffer.AddCommand(CmdGL);
|
||||
CmdBuffer.AddCommandUnsafe(CmdGL);
|
||||
RunBuffer(&CmdBuffer);
|
||||
WaitForIdle();
|
||||
CmdBuffer.Reset();
|
||||
|
@ -4648,7 +4664,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt
|
|||
if(InitError != 0)
|
||||
{
|
||||
CCommandProcessorFragment_SDL::SCommand_Shutdown Cmd;
|
||||
CmdBuffer.AddCommand(Cmd);
|
||||
CmdBuffer.AddCommandUnsafe(Cmd);
|
||||
RunBuffer(&CmdBuffer);
|
||||
WaitForIdle();
|
||||
CmdBuffer.Reset();
|
||||
|
@ -4701,7 +4717,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt
|
|||
|
||||
CmdSDL.m_Width = CurrentDisplayMode.w;
|
||||
CmdSDL.m_Height = CurrentDisplayMode.h;
|
||||
CmdBuffer.AddCommand(CmdSDL);
|
||||
CmdBuffer.AddCommandUnsafe(CmdSDL);
|
||||
RunBuffer(&CmdBuffer);
|
||||
WaitForIdle();
|
||||
CmdBuffer.Reset();
|
||||
|
@ -4717,13 +4733,13 @@ int CGraphicsBackend_SDL_OpenGL::Shutdown()
|
|||
// issue a shutdown command
|
||||
CCommandBuffer CmdBuffer(1024, 512);
|
||||
CCommandProcessorFragment_OpenGL::SCommand_Shutdown CmdGL;
|
||||
CmdBuffer.AddCommand(CmdGL);
|
||||
CmdBuffer.AddCommandUnsafe(CmdGL);
|
||||
RunBuffer(&CmdBuffer);
|
||||
WaitForIdle();
|
||||
CmdBuffer.Reset();
|
||||
|
||||
CCommandProcessorFragment_SDL::SCommand_Shutdown Cmd;
|
||||
CmdBuffer.AddCommand(Cmd);
|
||||
CmdBuffer.AddCommandUnsafe(Cmd);
|
||||
RunBuffer(&CmdBuffer);
|
||||
WaitForIdle();
|
||||
CmdBuffer.Reset();
|
||||
|
@ -4755,18 +4771,28 @@ void CGraphicsBackend_SDL_OpenGL::Maximize()
|
|||
// TODO: SDL
|
||||
}
|
||||
|
||||
bool CGraphicsBackend_SDL_OpenGL::Fullscreen(bool State)
|
||||
void CGraphicsBackend_SDL_OpenGL::SetWindowParams(int FullscreenMode, bool IsBorderless)
|
||||
{
|
||||
if(FullscreenMode > 0)
|
||||
{
|
||||
if(FullscreenMode == 1)
|
||||
{
|
||||
#if defined(CONF_PLATFORM_MACOS) // Todo SDL: remove this when fixed (game freezes when losing focus in fullscreen)
|
||||
return SDL_SetWindowFullscreen(m_pWindow, State ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0) == 0;
|
||||
SDL_SetWindowFullscreen(m_pWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
#else
|
||||
return SDL_SetWindowFullscreen(m_pWindow, State ? SDL_WINDOW_FULLSCREEN : 0) == 0;
|
||||
SDL_SetWindowFullscreen(m_pWindow, SDL_WINDOW_FULLSCREEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGraphicsBackend_SDL_OpenGL::SetWindowBordered(bool State)
|
||||
{
|
||||
SDL_SetWindowBordered(m_pWindow, SDL_bool(State));
|
||||
}
|
||||
else if(FullscreenMode == 2)
|
||||
{
|
||||
SDL_SetWindowFullscreen(m_pWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_SetWindowFullscreen(m_pWindow, 0);
|
||||
SDL_SetWindowBordered(m_pWindow, SDL_bool(!IsBorderless));
|
||||
}
|
||||
}
|
||||
|
||||
bool CGraphicsBackend_SDL_OpenGL::SetWindowScreen(int Index)
|
||||
|
|
|
@ -433,6 +433,10 @@ public:
|
|||
|
||||
int *m_pInitError;
|
||||
|
||||
char *m_pVendorString;
|
||||
char *m_pVersionString;
|
||||
char *m_pRendererString;
|
||||
|
||||
int m_RequestedMajor;
|
||||
int m_RequestedMinor;
|
||||
int m_RequestedPatch;
|
||||
|
@ -486,6 +490,8 @@ public:
|
|||
virtual void RunBuffer(CCommandBuffer *pBuffer);
|
||||
};
|
||||
|
||||
static constexpr size_t gs_GPUInfoStringSize = 256;
|
||||
|
||||
// graphics backend implemented with SDL and OpenGL
|
||||
class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded
|
||||
{
|
||||
|
@ -497,6 +503,10 @@ class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded
|
|||
|
||||
SBackendCapabilites m_Capabilites;
|
||||
|
||||
char m_aVendorString[gs_GPUInfoStringSize] = {};
|
||||
char m_aVersionString[gs_GPUInfoStringSize] = {};
|
||||
char m_aRendererString[gs_GPUInfoStringSize] = {};
|
||||
|
||||
bool m_UseNewOpenGL;
|
||||
|
||||
char m_aErrorString[256];
|
||||
|
@ -511,8 +521,7 @@ public:
|
|||
|
||||
virtual void Minimize();
|
||||
virtual void Maximize();
|
||||
virtual bool Fullscreen(bool State);
|
||||
virtual void SetWindowBordered(bool State); // on=true/off=false
|
||||
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless);
|
||||
virtual bool SetWindowScreen(int Index);
|
||||
virtual int GetWindowScreen();
|
||||
virtual int WindowActive();
|
||||
|
@ -536,6 +545,21 @@ public:
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual const char *GetVendorString()
|
||||
{
|
||||
return m_aVendorString;
|
||||
}
|
||||
|
||||
virtual const char *GetVersionString()
|
||||
{
|
||||
return m_aVersionString;
|
||||
}
|
||||
|
||||
virtual const char *GetRendererString()
|
||||
{
|
||||
return m_aRendererString;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ENGINE_CLIENT_BACKEND_SDL_H
|
||||
|
|
|
@ -3486,6 +3486,12 @@ void CClient::Con_DummyDisconnect(IConsole::IResult *pResult, void *pUserData)
|
|||
pSelf->DummyDisconnect(0);
|
||||
}
|
||||
|
||||
void CClient::Con_DummyResetInput(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
CClient *pSelf = (CClient *)pUserData;
|
||||
pSelf->GameClient()->DummyResetInput();
|
||||
}
|
||||
|
||||
void CClient::Con_Quit(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
CClient *pSelf = (CClient *)pUserData;
|
||||
|
@ -3990,10 +3996,10 @@ void CClient::SwitchWindowScreen(int Index)
|
|||
// Todo SDL: remove this when fixed (changing screen when in fullscreen is bugged)
|
||||
if(g_Config.m_GfxFullscreen)
|
||||
{
|
||||
ToggleFullscreen();
|
||||
SetWindowParams(0, g_Config.m_GfxBorderless);
|
||||
if(Graphics()->SetWindowScreen(Index))
|
||||
g_Config.m_GfxScreen = Index;
|
||||
ToggleFullscreen();
|
||||
SetWindowParams(g_Config.m_GfxFullscreen, g_Config.m_GfxBorderless);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4014,10 +4020,11 @@ void CClient::ConchainWindowScreen(IConsole::IResult *pResult, void *pUserData,
|
|||
pfnCallback(pResult, pCallbackUserData);
|
||||
}
|
||||
|
||||
void CClient::ToggleFullscreen()
|
||||
void CClient::SetWindowParams(int FullscreenMode, bool IsBorderless)
|
||||
{
|
||||
if(Graphics()->Fullscreen(g_Config.m_GfxFullscreen ^ 1))
|
||||
g_Config.m_GfxFullscreen ^= 1;
|
||||
g_Config.m_GfxFullscreen = clamp(FullscreenMode, 0, 2);
|
||||
g_Config.m_GfxBorderless = (int)IsBorderless;
|
||||
Graphics()->SetWindowParams(FullscreenMode, IsBorderless);
|
||||
}
|
||||
|
||||
void CClient::ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
||||
|
@ -4026,25 +4033,19 @@ void CClient::ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IC
|
|||
if(pSelf->Graphics() && pResult->NumArguments())
|
||||
{
|
||||
if(g_Config.m_GfxFullscreen != pResult->GetInteger(0))
|
||||
pSelf->ToggleFullscreen();
|
||||
pSelf->SetWindowParams(pResult->GetInteger(0), g_Config.m_GfxBorderless);
|
||||
}
|
||||
else
|
||||
pfnCallback(pResult, pCallbackUserData);
|
||||
}
|
||||
|
||||
void CClient::ToggleWindowBordered()
|
||||
{
|
||||
g_Config.m_GfxBorderless ^= 1;
|
||||
Graphics()->SetWindowBordered(!g_Config.m_GfxBorderless);
|
||||
}
|
||||
|
||||
void CClient::ConchainWindowBordered(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
||||
{
|
||||
CClient *pSelf = (CClient *)pUserData;
|
||||
if(pSelf->Graphics() && pResult->NumArguments())
|
||||
{
|
||||
if(!g_Config.m_GfxFullscreen && (g_Config.m_GfxBorderless != pResult->GetInteger(0)))
|
||||
pSelf->ToggleWindowBordered();
|
||||
pSelf->SetWindowParams(g_Config.m_GfxFullscreen, !g_Config.m_GfxBorderless);
|
||||
}
|
||||
else
|
||||
pfnCallback(pResult, pCallbackUserData);
|
||||
|
@ -4175,8 +4176,9 @@ void CClient::RegisterCommands()
|
|||
m_pConsole->Register("stoprecord", "", CFGFLAG_SERVER, 0, 0, "Stop recording");
|
||||
m_pConsole->Register("reload", "", CFGFLAG_SERVER, 0, 0, "Reload the map");
|
||||
|
||||
m_pConsole->Register("dummy_connect", "", CFGFLAG_CLIENT, Con_DummyConnect, this, "connect dummy");
|
||||
m_pConsole->Register("dummy_disconnect", "", CFGFLAG_CLIENT, Con_DummyDisconnect, this, "disconnect dummy");
|
||||
m_pConsole->Register("dummy_connect", "", CFGFLAG_CLIENT, Con_DummyConnect, this, "Connect dummy");
|
||||
m_pConsole->Register("dummy_disconnect", "", CFGFLAG_CLIENT, Con_DummyDisconnect, this, "Disconnect dummy");
|
||||
m_pConsole->Register("dummy_reset", "", CFGFLAG_CLIENT, Con_DummyResetInput, this, "Reset dummy");
|
||||
|
||||
m_pConsole->Register("quit", "", CFGFLAG_CLIENT | CFGFLAG_STORE, Con_Quit, this, "Quit Teeworlds");
|
||||
m_pConsole->Register("exit", "", CFGFLAG_CLIENT | CFGFLAG_STORE, Con_Quit, this, "Quit Teeworlds");
|
||||
|
|
|
@ -400,6 +400,7 @@ public:
|
|||
|
||||
static void Con_DummyConnect(IConsole::IResult *pResult, void *pUserData);
|
||||
static void Con_DummyDisconnect(IConsole::IResult *pResult, void *pUserData);
|
||||
static void Con_DummyResetInput(IConsole::IResult *pResult, void *pUserData);
|
||||
|
||||
static void Con_Quit(IConsole::IResult *pResult, void *pUserData);
|
||||
static void Con_DemoPlay(IConsole::IResult *pResult, void *pUserData);
|
||||
|
@ -465,12 +466,11 @@ public:
|
|||
void HandleMapPath(const char *pPath);
|
||||
|
||||
// gfx
|
||||
void SwitchWindowScreen(int Index);
|
||||
void ToggleFullscreen();
|
||||
void ToggleWindowBordered();
|
||||
void ToggleWindowVSync();
|
||||
void LoadFont();
|
||||
void Notify(const char *pTitle, const char *pMessage);
|
||||
virtual void SwitchWindowScreen(int Index);
|
||||
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless);
|
||||
virtual void ToggleWindowVSync();
|
||||
virtual void LoadFont();
|
||||
virtual void Notify(const char *pTitle, const char *pMessage);
|
||||
void BenchmarkQuit(int Seconds, const char *pFilename);
|
||||
|
||||
// DDRace
|
||||
|
|
|
@ -272,7 +272,8 @@ int CGraphics_Threaded::UnloadTexture(CTextureHandle Index)
|
|||
|
||||
CCommandBuffer::SCommand_Texture_Destroy Cmd;
|
||||
Cmd.m_Slot = Index;
|
||||
m_pCommandBuffer->AddCommand(Cmd);
|
||||
AddCmd(
|
||||
Cmd, [] { return true; }, "failed to unload texture.");
|
||||
|
||||
m_TextureIndices[Index] = m_FirstFreeTexture;
|
||||
m_FirstFreeTexture = Index;
|
||||
|
@ -325,13 +326,8 @@ int CGraphics_Threaded::LoadTextureRawSub(CTextureHandle TextureID, int x, int y
|
|||
mem_copy(pTmpData, pData, MemSize);
|
||||
Cmd.m_pData = pTmpData;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
m_pCommandBuffer->AddCommand(Cmd);
|
||||
}
|
||||
AddCmd(
|
||||
Cmd, [] { return true; }, "failed to load raw sub texture.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -481,13 +477,8 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(int Width, int Heig
|
|||
mem_copy(pTmpData, pData, MemSize);
|
||||
Cmd.m_pData = pTmpData;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
m_pCommandBuffer->AddCommand(Cmd);
|
||||
}
|
||||
AddCmd(
|
||||
Cmd, [] { return true; }, "failed to load raw texture.");
|
||||
|
||||
return CreateTextureHandle(Tex);
|
||||
}
|
||||
|
@ -669,7 +660,8 @@ void CGraphics_Threaded::ScreenshotDirect()
|
|||
|
||||
CCommandBuffer::SCommand_Screenshot Cmd;
|
||||
Cmd.m_pImage = &Image;
|
||||
m_pCommandBuffer->AddCommand(Cmd);
|
||||
AddCmd(
|
||||
Cmd, [] { return true; }, "failed to take screenshot.");
|
||||
|
||||
// kick the buffer and wait for the result
|
||||
KickCommandBuffer();
|
||||
|
@ -688,7 +680,7 @@ void CGraphics_Threaded::ScreenshotDirect()
|
|||
// save png
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "saved screenshot to '%s'", aWholePath);
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf, ColorRGBA{0.75f, 0.4f, 0.0f, 1.0f});
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf, ColorRGBA{1.0f, 0.6f, 0.3f, 1.0f});
|
||||
png_open_file_write(&Png, aWholePath); // ignore_convention
|
||||
png_set_data(&Png, Image.m_Width, Image.m_Height, 8, PNG_TRUECOLOR, (unsigned char *)Image.m_pData); // ignore_convention
|
||||
png_close_file(&Png); // ignore_convention
|
||||
|
@ -710,7 +702,8 @@ void CGraphics_Threaded::Clear(float r, float g, float b)
|
|||
Cmd.m_Color.g = g;
|
||||
Cmd.m_Color.b = b;
|
||||
Cmd.m_Color.a = 0;
|
||||
m_pCommandBuffer->AddCommand(Cmd);
|
||||
AddCmd(
|
||||
Cmd, [] { return true; }, "failed to clear graphics.");
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::QuadsBegin()
|
||||
|
@ -1126,26 +1119,21 @@ void CGraphics_Threaded::RenderTileLayer(int BufferContainerIndex, float *pColor
|
|||
Cmd.m_pIndicesOffsets = (char **)Data;
|
||||
Cmd.m_pDrawCount = (unsigned int *)(((char *)Data) + (sizeof(char *) * NumIndicesOffet));
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [&] {
|
||||
Data = m_pCommandBuffer->AllocData((sizeof(char *) + sizeof(unsigned int)) * NumIndicesOffet);
|
||||
if(Data == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for vertices");
|
||||
return false;
|
||||
}
|
||||
Cmd.m_pIndicesOffsets = (char **)Data;
|
||||
Cmd.m_pDrawCount = (unsigned int *)(((char *)Data) + (sizeof(char *) * NumIndicesOffet));
|
||||
return true;
|
||||
},
|
||||
"failed to allocate memory for render command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
Data = m_pCommandBuffer->AllocData((sizeof(char *) + sizeof(unsigned int)) * NumIndicesOffet);
|
||||
if(Data == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for vertices");
|
||||
return;
|
||||
}
|
||||
Cmd.m_pIndicesOffsets = (char **)Data;
|
||||
Cmd.m_pDrawCount = (unsigned int *)(((char *)Data) + (sizeof(char *) * NumIndicesOffet));
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for render command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mem_copy(Cmd.m_pIndicesOffsets, pOffsets, sizeof(char *) * NumIndicesOffet);
|
||||
|
@ -1174,16 +1162,10 @@ void CGraphics_Threaded::RenderBorderTiles(int BufferContainerIndex, float *pCol
|
|||
Cmd.m_Dir[1] = pDir[1];
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for render command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for render command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1207,16 +1189,10 @@ void CGraphics_Threaded::RenderBorderTileLines(int BufferContainerIndex, float *
|
|||
Cmd.m_Dir[1] = pDir[1];
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for render command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for render command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1237,23 +1213,19 @@ void CGraphics_Threaded::RenderQuadLayer(int BufferContainerIndex, SQuadRenderIn
|
|||
return;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [&] {
|
||||
Cmd.m_pQuadInfo = (SQuadRenderInfo *)m_pCommandBuffer->AllocData(QuadNum * sizeof(SQuadRenderInfo));
|
||||
if(Cmd.m_pQuadInfo == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for the quad info");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
"failed to allocate memory for render quad command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
Cmd.m_pQuadInfo = (SQuadRenderInfo *)m_pCommandBuffer->AllocData(QuadNum * sizeof(SQuadRenderInfo));
|
||||
if(Cmd.m_pQuadInfo == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for the quad info");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for render quad command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mem_copy(Cmd.m_pQuadInfo, pQuadInfo, sizeof(SQuadRenderInfo) * QuadNum);
|
||||
|
@ -1274,17 +1246,10 @@ void CGraphics_Threaded::RenderText(int BufferContainerIndex, int TextQuadNum, i
|
|||
mem_copy(Cmd.m_aTextColor, pTextColor, sizeof(Cmd.m_aTextColor));
|
||||
mem_copy(Cmd.m_aTextOutlineColor, pTextoutlineColor, sizeof(Cmd.m_aTextOutlineColor));
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for render text command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for render text command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1490,17 +1455,10 @@ void CGraphics_Threaded::RenderQuadContainer(int ContainerIndex, int QuadOffset,
|
|||
Cmd.m_pOffset = (void *)(QuadOffset * 6 * sizeof(unsigned int));
|
||||
Cmd.m_BufferContainerIndex = Container.m_QuadBufferContainerIndex;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for render quad container"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for render quad container");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1573,17 +1531,10 @@ void CGraphics_Threaded::RenderQuadContainerEx(int ContainerIndex, int QuadOffse
|
|||
Cmd.m_Center.x = Quad.m_aVertices[0].m_Pos.x + (Quad.m_aVertices[1].m_Pos.x - Quad.m_aVertices[0].m_Pos.x) / 2.f;
|
||||
Cmd.m_Center.y = Quad.m_aVertices[0].m_Pos.y + (Quad.m_aVertices[2].m_Pos.y - Quad.m_aVertices[0].m_Pos.y) / 2.f;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for render quad container extended"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for render quad container extended");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1713,24 +1664,19 @@ void CGraphics_Threaded::RenderQuadContainerAsSpriteMultiple(int ContainerIndex,
|
|||
}
|
||||
}
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [&] {
|
||||
Cmd.m_pRenderInfo = (IGraphics::SRenderSpriteInfo *)m_pCommandBuffer->AllocData(sizeof(IGraphics::SRenderSpriteInfo) * DrawCount);
|
||||
if(Cmd.m_pRenderInfo == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for render info");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
"failed to allocate memory for render quad container sprite"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
Cmd.m_pRenderInfo = (IGraphics::SRenderSpriteInfo *)m_pCommandBuffer->AllocData(sizeof(IGraphics::SRenderSpriteInfo) * DrawCount);
|
||||
if(Cmd.m_pRenderInfo == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for render info");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for render quad container sprite");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mem_copy(Cmd.m_pRenderInfo, pRenderInfo, sizeof(IGraphics::SRenderSpriteInfo) * DrawCount);
|
||||
|
@ -1788,16 +1734,10 @@ int CGraphics_Threaded::CreateBufferObject(size_t UploadDataSize, void *pUploadD
|
|||
{
|
||||
Cmd.m_pUploadData = pUploadData;
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for update buffer object command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for update buffer object command");
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1808,40 +1748,31 @@ int CGraphics_Threaded::CreateBufferObject(size_t UploadDataSize, void *pUploadD
|
|||
if(Cmd.m_pUploadData == NULL)
|
||||
return -1;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [&] {
|
||||
Cmd.m_pUploadData = m_pCommandBuffer->AllocData(UploadDataSize);
|
||||
if(Cmd.m_pUploadData == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for upload data");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
"failed to allocate memory for create buffer object command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
Cmd.m_pUploadData = m_pCommandBuffer->AllocData(UploadDataSize);
|
||||
if(Cmd.m_pUploadData == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for upload data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for create buffer object command");
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
mem_copy(Cmd.m_pUploadData, pUploadData, UploadDataSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
Cmd.m_pUploadData = NULL;
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for create buffer object command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for create buffer object command");
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// update the buffer instead
|
||||
|
@ -1872,16 +1803,10 @@ void CGraphics_Threaded::RecreateBufferObject(int BufferIndex, size_t UploadData
|
|||
{
|
||||
Cmd.m_pUploadData = pUploadData;
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for recreate buffer object command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for recreate buffer object command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1892,24 +1817,19 @@ void CGraphics_Threaded::RecreateBufferObject(int BufferIndex, size_t UploadData
|
|||
if(Cmd.m_pUploadData == NULL)
|
||||
return;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [&] {
|
||||
Cmd.m_pUploadData = m_pCommandBuffer->AllocData(UploadDataSize);
|
||||
if(Cmd.m_pUploadData == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for upload data");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
"failed to allocate memory for recreate buffer object command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
Cmd.m_pUploadData = m_pCommandBuffer->AllocData(UploadDataSize);
|
||||
if(Cmd.m_pUploadData == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for upload data");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for recreate buffer object command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mem_copy(Cmd.m_pUploadData, pUploadData, UploadDataSize);
|
||||
|
@ -1917,16 +1837,11 @@ void CGraphics_Threaded::RecreateBufferObject(int BufferIndex, size_t UploadData
|
|||
else
|
||||
{
|
||||
Cmd.m_pUploadData = NULL;
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for update buffer object command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for update buffer object command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// update the buffer instead
|
||||
|
@ -1956,16 +1871,10 @@ void CGraphics_Threaded::UpdateBufferObject(int BufferIndex, size_t UploadDataSi
|
|||
{
|
||||
Cmd.m_pUploadData = pUploadData;
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for update buffer object command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for update buffer object command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1974,24 +1883,19 @@ void CGraphics_Threaded::UpdateBufferObject(int BufferIndex, size_t UploadDataSi
|
|||
if(Cmd.m_pUploadData == NULL)
|
||||
return;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [&] {
|
||||
Cmd.m_pUploadData = m_pCommandBuffer->AllocData(UploadDataSize);
|
||||
if(Cmd.m_pUploadData == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for upload data");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
"failed to allocate memory for update buffer object command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
Cmd.m_pUploadData = m_pCommandBuffer->AllocData(UploadDataSize);
|
||||
if(Cmd.m_pUploadData == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for upload data");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for update buffer object command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mem_copy(Cmd.m_pUploadData, pUploadData, UploadDataSize);
|
||||
|
@ -2007,17 +1911,10 @@ void CGraphics_Threaded::CopyBufferObject(int WriteBufferIndex, int ReadBufferIn
|
|||
Cmd.m_pReadOffset = ReadOffset;
|
||||
Cmd.m_CopySize = CopyDataSize;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for copy buffer object command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for copy buffer object command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2029,17 +1926,10 @@ void CGraphics_Threaded::DeleteBufferObject(int BufferIndex)
|
|||
CCommandBuffer::SCommand_DeleteBufferObject Cmd;
|
||||
Cmd.m_BufferIndex = BufferIndex;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for delete buffer object command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for delete buffer object command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// also clear the buffer object index
|
||||
|
@ -2071,24 +1961,19 @@ int CGraphics_Threaded::CreateBufferContainer(SBufferContainerInfo *pContainerIn
|
|||
if(Cmd.m_Attributes == NULL)
|
||||
return -1;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [&] {
|
||||
Cmd.m_Attributes = (SBufferContainerInfo::SAttribute *)m_pCommandBuffer->AllocData(Cmd.m_AttrCount * sizeof(SBufferContainerInfo::SAttribute));
|
||||
if(Cmd.m_Attributes == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for upload data");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
"failed to allocate memory for create buffer container command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
Cmd.m_Attributes = (SBufferContainerInfo::SAttribute *)m_pCommandBuffer->AllocData(Cmd.m_AttrCount * sizeof(SBufferContainerInfo::SAttribute));
|
||||
if(Cmd.m_Attributes == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for upload data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for create buffer container command");
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
mem_copy(Cmd.m_Attributes, &pContainerInfo->m_Attributes[0], Cmd.m_AttrCount * sizeof(SBufferContainerInfo::SAttribute));
|
||||
|
@ -2107,17 +1992,10 @@ void CGraphics_Threaded::DeleteBufferContainer(int ContainerIndex, bool DestroyA
|
|||
Cmd.m_BufferContainerIndex = ContainerIndex;
|
||||
Cmd.m_DestroyAllBO = DestroyAllBO;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for delete buffer container command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for delete buffer container command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(DestroyAllBO)
|
||||
|
@ -2158,24 +2036,19 @@ void CGraphics_Threaded::UpdateBufferContainer(int ContainerIndex, SBufferContai
|
|||
if(Cmd.m_Attributes == NULL)
|
||||
return;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [&] {
|
||||
Cmd.m_Attributes = (SBufferContainerInfo::SAttribute *)m_pCommandBuffer->AllocData(Cmd.m_AttrCount * sizeof(SBufferContainerInfo::SAttribute));
|
||||
if(Cmd.m_Attributes == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for upload data");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
"failed to allocate memory for update buffer container command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
Cmd.m_Attributes = (SBufferContainerInfo::SAttribute *)m_pCommandBuffer->AllocData(Cmd.m_AttrCount * sizeof(SBufferContainerInfo::SAttribute));
|
||||
if(Cmd.m_Attributes == 0x0)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for upload data");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for update buffer container command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mem_copy(Cmd.m_Attributes, &pContainerInfo->m_Attributes[0], Cmd.m_AttrCount * sizeof(SBufferContainerInfo::SAttribute));
|
||||
|
@ -2190,17 +2063,10 @@ void CGraphics_Threaded::IndicesNumRequiredNotify(unsigned int RequiredIndicesCo
|
|||
CCommandBuffer::SCommand_IndicesRequiredNumNotify Cmd;
|
||||
Cmd.m_RequiredIndicesNum = RequiredIndicesCount;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to allocate memory for indcies required count notify command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for indcies required count notify command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2210,8 +2076,10 @@ int CGraphics_Threaded::IssueInit()
|
|||
|
||||
if(g_Config.m_GfxBorderless)
|
||||
Flags |= IGraphicsBackend::INITFLAG_BORDERLESS;
|
||||
if(g_Config.m_GfxFullscreen)
|
||||
if(g_Config.m_GfxFullscreen == 1)
|
||||
Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN;
|
||||
else if(g_Config.m_GfxFullscreen == 2)
|
||||
Flags |= IGraphicsBackend::INITFLAG_DESKTOP_FULLSCREEN;
|
||||
if(g_Config.m_GfxVsync)
|
||||
Flags |= IGraphicsBackend::INITFLAG_VSYNC;
|
||||
if(g_Config.m_GfxHighdpi)
|
||||
|
@ -2388,6 +2256,19 @@ int CGraphics_Threaded::Init()
|
|||
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff};
|
||||
|
||||
m_InvalidTexture = LoadTextureRaw(4, 4, CImageInfo::FORMAT_RGBA, s_aNullTextureData, CImageInfo::FORMAT_RGBA, TEXLOAD_NORESAMPLE);
|
||||
|
||||
ColorRGBA GPUInfoPrintColor{0.6f, 0.5f, 1.0f, 1.0f};
|
||||
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "GPU vendor: %s", GetVendorString());
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gfx", aBuf, GPUInfoPrintColor);
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "GPU renderer: %s", GetRendererString());
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gfx", aBuf, GPUInfoPrintColor);
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "GPU version: %s", GetVersionString());
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gfx", aBuf, GPUInfoPrintColor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2419,14 +2300,9 @@ void CGraphics_Threaded::Maximize()
|
|||
m_pBackend->Maximize();
|
||||
}
|
||||
|
||||
bool CGraphics_Threaded::Fullscreen(bool State)
|
||||
void CGraphics_Threaded::SetWindowParams(int FullscreenMode, bool IsBorderless)
|
||||
{
|
||||
return m_pBackend->Fullscreen(State);
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::SetWindowBordered(bool State)
|
||||
{
|
||||
m_pBackend->SetWindowBordered(State);
|
||||
m_pBackend->SetWindowParams(FullscreenMode, IsBorderless);
|
||||
}
|
||||
|
||||
bool CGraphics_Threaded::SetWindowScreen(int Index)
|
||||
|
@ -2461,7 +2337,12 @@ void CGraphics_Threaded::Resize(int w, int h, bool SetWindowSize)
|
|||
CCommandBuffer::SCommand_Resize Cmd;
|
||||
Cmd.m_Width = m_ScreenWidth;
|
||||
Cmd.m_Height = m_ScreenHeight;
|
||||
m_pCommandBuffer->AddCommand(Cmd);
|
||||
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to add resize command"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// kick the command buffer
|
||||
KickCommandBuffer();
|
||||
|
@ -2538,7 +2419,11 @@ void CGraphics_Threaded::Swap()
|
|||
// add swap command
|
||||
CCommandBuffer::SCommand_Swap Cmd;
|
||||
Cmd.m_Finish = g_Config.m_GfxFinish;
|
||||
m_pCommandBuffer->AddCommand(Cmd);
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to add swap command"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// kick the command buffer
|
||||
KickCommandBuffer();
|
||||
|
@ -2554,7 +2439,12 @@ bool CGraphics_Threaded::SetVSync(bool State)
|
|||
CCommandBuffer::SCommand_VSync Cmd;
|
||||
Cmd.m_VSync = State ? 1 : 0;
|
||||
Cmd.m_pRetOk = &RetOk;
|
||||
m_pCommandBuffer->AddCommand(Cmd);
|
||||
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to add vsync command"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// kick the command buffer
|
||||
KickCommandBuffer();
|
||||
|
@ -2567,7 +2457,12 @@ void CGraphics_Threaded::InsertSignal(CSemaphore *pSemaphore)
|
|||
{
|
||||
CCommandBuffer::SCommand_Signal Cmd;
|
||||
Cmd.m_pSemaphore = pSemaphore;
|
||||
m_pCommandBuffer->AddCommand(Cmd);
|
||||
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to add signal command"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool CGraphics_Threaded::IsIdle() const
|
||||
|
@ -2591,6 +2486,21 @@ SWarning *CGraphics_Threaded::GetCurWarning()
|
|||
}
|
||||
}
|
||||
|
||||
const char *CGraphics_Threaded::GetVendorString()
|
||||
{
|
||||
return m_pBackend->GetVendorString();
|
||||
}
|
||||
|
||||
const char *CGraphics_Threaded::GetVersionString()
|
||||
{
|
||||
return m_pBackend->GetVersionString();
|
||||
}
|
||||
|
||||
const char *CGraphics_Threaded::GetRendererString()
|
||||
{
|
||||
return m_pBackend->GetRendererString();
|
||||
}
|
||||
|
||||
int CGraphics_Threaded::GetVideoModes(CVideoMode *pModes, int MaxModes, int Screen)
|
||||
{
|
||||
if(g_Config.m_GfxDisplayAllModes)
|
||||
|
@ -2612,7 +2522,12 @@ int CGraphics_Threaded::GetVideoModes(CVideoMode *pModes, int MaxModes, int Scre
|
|||
Cmd.m_MaxModes = MaxModes;
|
||||
Cmd.m_pNumModes = &NumModes;
|
||||
Cmd.m_Screen = Screen;
|
||||
m_pCommandBuffer->AddCommand(Cmd);
|
||||
|
||||
if(!AddCmd(
|
||||
Cmd, [] { return true; }, "failed to add video mode command"))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// kick the buffer and wait for the result and return it
|
||||
KickCommandBuffer();
|
||||
|
|
|
@ -581,7 +581,7 @@ public:
|
|||
}
|
||||
|
||||
template<class T>
|
||||
bool AddCommand(const T &Command)
|
||||
bool AddCommandUnsafe(const T &Command)
|
||||
{
|
||||
// make sure that we don't do something stupid like ->AddCommand(&Cmd);
|
||||
(void)static_cast<const SCommand *>(&Command);
|
||||
|
@ -640,6 +640,7 @@ public:
|
|||
INITFLAG_RESIZABLE = 1 << 2,
|
||||
INITFLAG_BORDERLESS = 1 << 3,
|
||||
INITFLAG_HIGHDPI = 1 << 4,
|
||||
INITFLAG_DESKTOP_FULLSCREEN = 1 << 5,
|
||||
};
|
||||
|
||||
virtual ~IGraphicsBackend() {}
|
||||
|
@ -653,8 +654,7 @@ public:
|
|||
|
||||
virtual void Minimize() = 0;
|
||||
virtual void Maximize() = 0;
|
||||
virtual bool Fullscreen(bool State) = 0;
|
||||
virtual void SetWindowBordered(bool State) = 0;
|
||||
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0;
|
||||
virtual bool SetWindowScreen(int Index) = 0;
|
||||
virtual int GetWindowScreen() = 0;
|
||||
virtual int WindowActive() = 0;
|
||||
|
@ -675,6 +675,10 @@ public:
|
|||
virtual bool HasQuadContainerBuffering() { return false; }
|
||||
virtual bool Has2DTextureArrays() { return false; }
|
||||
virtual const char *GetErrorString() { return NULL; }
|
||||
|
||||
virtual const char *GetVendorString() = 0;
|
||||
virtual const char *GetVersionString() = 0;
|
||||
virtual const char *GetRendererString() = 0;
|
||||
};
|
||||
|
||||
class CGraphics_Threaded : public IEngineGraphics
|
||||
|
@ -803,6 +807,26 @@ class CGraphics_Threaded : public IEngineGraphics
|
|||
}
|
||||
}
|
||||
|
||||
template<typename TName, typename TFunc>
|
||||
bool AddCmd(TName &Cmd, TFunc &&FailFunc, const char *pFailStr)
|
||||
{
|
||||
if(!m_pCommandBuffer->AddCommandUnsafe(Cmd))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
if(!FailFunc())
|
||||
return false;
|
||||
|
||||
if(!m_pCommandBuffer->AddCommandUnsafe(Cmd))
|
||||
{
|
||||
dbg_msg("graphics", "%s", pFailStr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void KickCommandBuffer();
|
||||
|
||||
void AddBackEndWarningIfExists();
|
||||
|
@ -1065,24 +1089,20 @@ public:
|
|||
Command.m_PrimType = PrimType;
|
||||
Command.m_PrimCount = PrimCount;
|
||||
|
||||
// check if we have enough free memory in the commandbuffer
|
||||
if(!m_pCommandBuffer->AddCommand(Command))
|
||||
if(
|
||||
!AddCmd(
|
||||
Command, [&] {
|
||||
Command.m_pVertices = (decltype(Command.m_pVertices))m_pCommandBuffer->AllocData(VertSize * NumVerts);
|
||||
if(Command.m_pVertices == NULL)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for vertices");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
"failed to allocate memory for render command"))
|
||||
{
|
||||
// kick command buffer and try again
|
||||
KickCommandBuffer();
|
||||
|
||||
Command.m_pVertices = (decltype(Command.m_pVertices))m_pCommandBuffer->AllocData(VertSize * NumVerts);
|
||||
if(Command.m_pVertices == NULL)
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate data for vertices");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_pCommandBuffer->AddCommand(Command))
|
||||
{
|
||||
dbg_msg("graphics", "failed to allocate memory for render command");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1112,8 +1132,7 @@ public:
|
|||
int GetNumScreens() const override;
|
||||
void Minimize() override;
|
||||
void Maximize() override;
|
||||
bool Fullscreen(bool State) override;
|
||||
void SetWindowBordered(bool State) override;
|
||||
void SetWindowParams(int FullscreenMode, bool IsBorderless) override;
|
||||
bool SetWindowScreen(int Index) override;
|
||||
void Resize(int w, int h, bool SetWindowSize = false) override;
|
||||
void AddWindowResizeListener(WINDOW_RESIZE_FUNC pFunc, void *pUser) override;
|
||||
|
@ -1150,6 +1169,10 @@ public:
|
|||
bool IsTextBufferingEnabled() override { return m_OpenGLTextBufferingEnabled; }
|
||||
bool IsQuadContainerBufferingEnabled() override { return m_OpenGLQuadContainerBufferingEnabled; }
|
||||
bool HasTextureArrays() override { return m_OpenGLHasTextureArrays; }
|
||||
|
||||
const char *GetVendorString() override;
|
||||
const char *GetVersionString() override;
|
||||
const char *GetRendererString() override;
|
||||
};
|
||||
|
||||
extern IGraphicsBackend *CreateGraphicsBackend();
|
||||
|
|
|
@ -89,8 +89,6 @@ void CInput::MouseModeRelative()
|
|||
m_InputGrabbed = 1;
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
Graphics()->SetWindowGrab(true);
|
||||
// We should do this call to reset relative mouse position after alt+tab
|
||||
SDL_GetRelativeMouseState(0x0, 0x0);
|
||||
}
|
||||
|
||||
int CInput::MouseDoubleClick()
|
||||
|
@ -336,6 +334,8 @@ int CInput::Update()
|
|||
MouseModeRelative();
|
||||
m_MouseFocus = true;
|
||||
IgnoreKeys = true;
|
||||
// We should do this call to reset relative mouse position after alt+tab
|
||||
SDL_GetRelativeMouseState(0x0, 0x0);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
m_MouseFocus = false;
|
||||
|
|
|
@ -330,15 +330,12 @@ int CServerBrowser::SortHash() const
|
|||
|
||||
void SetFilteredPlayers(const CServerInfo &Item)
|
||||
{
|
||||
if(g_Config.m_BrFilterSpectators)
|
||||
Item.m_NumFilteredPlayers = Item.m_NumPlayers;
|
||||
else
|
||||
Item.m_NumFilteredPlayers = Item.m_NumClients;
|
||||
Item.m_NumFilteredPlayers = g_Config.m_BrFilterSpectators ? Item.m_NumPlayers : Item.m_NumClients;
|
||||
if(g_Config.m_BrFilterConnectingPlayers)
|
||||
{
|
||||
for(const auto &Client : Item.m_aClients)
|
||||
{
|
||||
if(str_comp(Client.m_aName, "(connecting)") == 0 && Client.m_aClan[0] == '\0' && Client.m_Country == -1 && Client.m_Score == 0)
|
||||
if((!g_Config.m_BrFilterSpectators || Client.m_Player) && str_comp(Client.m_aName, "(connecting)") == 0 && Client.m_aClan[0] == '\0')
|
||||
Item.m_NumFilteredPlayers--;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -196,8 +196,7 @@ public:
|
|||
int ScreenHeight() const { return m_ScreenHeight; }
|
||||
float ScreenAspect() const { return (float)ScreenWidth() / (float)ScreenHeight(); }
|
||||
|
||||
virtual bool Fullscreen(bool State) = 0;
|
||||
virtual void SetWindowBordered(bool State) = 0;
|
||||
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless) = 0;
|
||||
virtual bool SetWindowScreen(int Index) = 0;
|
||||
virtual bool SetVSync(bool State) = 0;
|
||||
virtual int GetWindowScreen() = 0;
|
||||
|
@ -276,6 +275,10 @@ public:
|
|||
virtual bool IsQuadContainerBufferingEnabled() = 0;
|
||||
virtual bool HasTextureArrays() = 0;
|
||||
|
||||
virtual const char *GetVendorString() = 0;
|
||||
virtual const char *GetVersionString() = 0;
|
||||
virtual const char *GetRendererString() = 0;
|
||||
|
||||
struct CLineItem
|
||||
{
|
||||
float m_X0, m_Y0, m_X1, m_Y1;
|
||||
|
|
|
@ -100,10 +100,10 @@ MACRO_CONFIG_INT(GfxScreenWidth, gfx_screen_width, 0, 0, 0, CFGFLAG_SAVE | CFGFL
|
|||
MACRO_CONFIG_INT(GfxScreenHeight, gfx_screen_height, 0, 0, 0, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Screen resolution height")
|
||||
#if !defined(CONF_PLATFORM_MACOS)
|
||||
MACRO_CONFIG_INT(GfxBorderless, gfx_borderless, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Borderless window (not to be used with fullscreen)")
|
||||
MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Fullscreen")
|
||||
MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 1, 0, 2, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Set fullscreen mode: 0=no fullscreen, 1=pure fullscreen, 2=desktop fullscreen")
|
||||
#else
|
||||
MACRO_CONFIG_INT(GfxBorderless, gfx_borderless, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Borderless window (not to be used with fullscreen)")
|
||||
MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Fullscreen")
|
||||
MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 0, 0, 2, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Set fullscreen mode: 0=no fullscreen, 1=pure fullscreen, 2=desktop fullscreen")
|
||||
#endif
|
||||
MACRO_CONFIG_INT(GfxHighdpi, gfx_highdpi, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Enable high-dpi")
|
||||
MACRO_CONFIG_INT(GfxAlphabits, gfx_alphabits, 0, 0, 0, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Alpha bits for framebuffer (fullscreen only)")
|
||||
|
@ -230,7 +230,9 @@ MACRO_CONFIG_STR(SvScoreFolder, sv_score_folder, 32, "records", CFGFLAG_SERVER,
|
|||
MACRO_CONFIG_STR(SvRegionName, sv_region_name, 5, "UNK", CFGFLAG_SERVER, "Server region. Used for regional bans")
|
||||
MACRO_CONFIG_STR(SvSqlServerName, sv_sql_servername, 5, "UNK", CFGFLAG_SERVER, "SQL Server name that is inserted into record table")
|
||||
MACRO_CONFIG_INT(SvSaveGames, sv_savegames, 1, 0, 1, CFGFLAG_SERVER, "Enables savegames (/save and /load)")
|
||||
MACRO_CONFIG_INT(SvSaveGamesDelay, sv_savegames_delay, 60, 0, 10000, CFGFLAG_SERVER, "Delay in seconds for loading a savegame")
|
||||
MACRO_CONFIG_INT(SvSaveSwapGamesDelay, sv_saveswapgames_delay, 30, 0, 10000, CFGFLAG_SERVER, "Delay in seconds for loading a savegame or before swapping")
|
||||
MACRO_CONFIG_INT(SvSaveSwapGamesPenalty, sv_saveswapgames_penalty, 60, 0, 10000, CFGFLAG_SERVER, "Penalty in seconds for saving or swapping position")
|
||||
MACRO_CONFIG_INT(SvSwapTimeout, sv_swap_timeout, 30, 0, 10000, CFGFLAG_SERVER, "Timeout in seconds before option to swap expires")
|
||||
MACRO_CONFIG_INT(SvUseSQL, sv_use_sql, 0, 0, 1, CFGFLAG_SERVER, "Enables MySQL backend instead of SQLite backend (sv_sqlite_file is still used as fallback write server when no MySQL server is reachable)")
|
||||
MACRO_CONFIG_INT(SvSqlQueriesDelay, sv_sql_queries_delay, 1, 0, 20, CFGFLAG_SERVER, "Delay in seconds between SQL queries of a single player")
|
||||
MACRO_CONFIG_STR(SvSqliteFile, sv_sqlite_file, 64, "ddnet-server.sqlite", CFGFLAG_SERVER, "File to store ranks in case sv_use_sql is turned off or used as backup sql server")
|
||||
|
|
|
@ -235,7 +235,7 @@ void CNetBan::MakeBanInfo(const CBan<T> *pBan, char *pBuf, unsigned BuffSize, in
|
|||
str_format(pBuf, BuffSize, "%s for %d minutes (%s)", aBuf, Mins, pBan->m_Info.m_aReason);
|
||||
}
|
||||
else
|
||||
str_format(pBuf, BuffSize, "%s for life (%s)", aBuf, pBan->m_Info.m_aReason);
|
||||
str_format(pBuf, BuffSize, "%s (%s)", aBuf, pBan->m_Info.m_aReason);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -198,10 +198,6 @@ void CControls::OnConsoleInit()
|
|||
static CInputState s_State = {this, &m_ShowHookColl[0], &m_ShowHookColl[1]};
|
||||
Console()->Register("+showhookcoll", "", CFGFLAG_CLIENT, ConKeyInputState, (void *)&s_State, "Show Hook Collision");
|
||||
}
|
||||
{
|
||||
static CInputState s_State = {this, &m_ResetDummy[0], &m_ResetDummy[1]};
|
||||
Console()->Register("+resetdummy", "", CFGFLAG_CLIENT, ConKeyInputState, (void *)&s_State, "Reset Dummy");
|
||||
}
|
||||
|
||||
{
|
||||
static CInputSet s_Set = {this, &m_InputData[0].m_WantedWeapon, &m_InputData[1].m_WantedWeapon, 1};
|
||||
|
@ -341,19 +337,6 @@ int CControls::SnapInput(int *pData)
|
|||
pDummyInput->m_Hook = g_Config.m_ClDummyHook;
|
||||
}
|
||||
|
||||
if(m_ResetDummy[g_Config.m_ClDummy])
|
||||
{
|
||||
ResetInput(!g_Config.m_ClDummy);
|
||||
m_InputData[!g_Config.m_ClDummy].m_Hook = 0;
|
||||
|
||||
CNetObj_PlayerInput *pDummyInput = &m_pClient->m_DummyInput;
|
||||
pDummyInput->m_Hook = m_InputData[!g_Config.m_ClDummy].m_Hook;
|
||||
pDummyInput->m_Jump = m_InputData[!g_Config.m_ClDummy].m_Jump;
|
||||
pDummyInput->m_Direction = m_InputData[!g_Config.m_ClDummy].m_Jump;
|
||||
|
||||
pDummyInput->m_Fire = m_InputData[!g_Config.m_ClDummy].m_Fire;
|
||||
}
|
||||
|
||||
// stress testing
|
||||
#ifdef CONF_DEBUG
|
||||
if(g_Config.m_DbgStress)
|
||||
|
|
|
@ -29,7 +29,6 @@ public:
|
|||
int m_InputDirectionLeft[NUM_DUMMIES];
|
||||
int m_InputDirectionRight[NUM_DUMMIES];
|
||||
int m_ShowHookColl[NUM_DUMMIES];
|
||||
int m_ResetDummy[NUM_DUMMIES];
|
||||
int m_LastDummy;
|
||||
int m_OtherFire;
|
||||
|
||||
|
|
|
@ -1253,7 +1253,10 @@ int CMenus::RenderMenubar(CUIRect r)
|
|||
Box.VSplitLeft(4.0f, 0, &Box);
|
||||
static int s_CallVoteButton = 0;
|
||||
if(DoButton_MenuTab(&s_CallVoteButton, Localize("Call vote"), m_ActivePage == PAGE_CALLVOTE, &Button, CUI::CORNER_TR))
|
||||
{
|
||||
NewPage = PAGE_CALLVOTE;
|
||||
m_ControlPageOpening = true;
|
||||
}
|
||||
}
|
||||
|
||||
TextRender()->SetCurFont(TextRender()->GetFont(TEXT_FONT_ICON_FONT));
|
||||
|
|
|
@ -220,6 +220,8 @@ class CMenus : public CComponent
|
|||
CListboxItem UiDoListboxNextRow();
|
||||
int UiDoListboxEnd(float *pScrollValue, bool *pItemActivated, bool *pListBoxActive = 0);
|
||||
|
||||
int UiLogicGetCurrentClickedItem();
|
||||
|
||||
//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);
|
||||
|
||||
|
@ -349,6 +351,7 @@ protected:
|
|||
int m_CallvoteSelectedPlayer;
|
||||
char m_aCallvoteReason[VOTE_REASON_LENGTH];
|
||||
char m_aFilterString[25];
|
||||
bool m_ControlPageOpening;
|
||||
|
||||
// demo
|
||||
enum
|
||||
|
@ -689,6 +692,8 @@ private:
|
|||
ColorHSLA RenderHSLColorPicker(const CUIRect *pRect, unsigned int *pColor, bool Alpha);
|
||||
ColorHSLA RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool Alpha = false);
|
||||
|
||||
int RenderDropDown(int &CurDropDownState, CUIRect *pRect, int CurSelection, const void **pIDs, const char **pStr, int PickNum, const void *pID, float &ScrollVal);
|
||||
|
||||
CServerProcess m_ServerProcess;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -1066,14 +1066,14 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
|
|||
|
||||
for(int i = 0; i < pSelectedServer->m_NumReceivedClients; i++)
|
||||
{
|
||||
CListboxItem Item = UiDoListboxNextItem(&i);
|
||||
CListboxItem Item = UiDoListboxNextItem(&pSelectedServer->m_aClients[i]);
|
||||
|
||||
if(!Item.m_Visible)
|
||||
continue;
|
||||
|
||||
CUIRect Name, Clan, Score, Flag;
|
||||
Item.m_Rect.HSplitTop(25.0f, &Name, &Item.m_Rect);
|
||||
if(UI()->DoButtonLogic(&pSelectedServer->m_aClients[i], "", 0, &Name))
|
||||
if(UiLogicGetCurrentClickedItem() == i)
|
||||
{
|
||||
if(pSelectedServer->m_aClients[i].m_FriendState == IFriends::FRIEND_PLAYER)
|
||||
m_pClient->Friends()->RemoveFriend(pSelectedServer->m_aClients[i].m_aName, pSelectedServer->m_aClients[i].m_aClan);
|
||||
|
|
|
@ -620,7 +620,18 @@ CMenus::CListboxItem CMenus::UiDoListboxNextItem(const void *pId, bool Selected,
|
|||
|
||||
CListboxItem Item = UiDoListboxNextRow();
|
||||
|
||||
if(Item.m_Visible && UI()->DoButtonLogic(pId, "", gs_ListBoxSelectedIndex == gs_ListBoxItemIndex, &Item.m_HitRect))
|
||||
CUIRect HitRect = Item.m_HitRect;
|
||||
|
||||
if(HitRect.y < gs_ListBoxOriginalView.y)
|
||||
{
|
||||
float TmpDiff = gs_ListBoxOriginalView.y - HitRect.y;
|
||||
HitRect.y = gs_ListBoxOriginalView.y;
|
||||
HitRect.h -= TmpDiff;
|
||||
}
|
||||
|
||||
HitRect.h = minimum(HitRect.h, (gs_ListBoxOriginalView.y + gs_ListBoxOriginalView.h) - HitRect.y);
|
||||
|
||||
if(Item.m_Visible && UI()->DoButtonLogic(pId, "", gs_ListBoxSelectedIndex == gs_ListBoxItemIndex, &HitRect))
|
||||
{
|
||||
gs_ListBoxClicked = true;
|
||||
gs_ListBoxNewSelected = ThisItemIndex;
|
||||
|
@ -696,7 +707,7 @@ CMenus::CListboxItem CMenus::UiDoListboxNextItem(const void *pId, bool Selected,
|
|||
r.Margin(1.5f, &r);
|
||||
RenderTools()->DrawUIRect(&r, ColorRGBA(1, 1, 1, 0.5f), CUI::CORNER_ALL, 4.0f);
|
||||
}
|
||||
else if(UI()->MouseInside(&Item.m_Rect) && !NoHoverEffects)
|
||||
else if(UI()->MouseInside(&HitRect) && !NoHoverEffects)
|
||||
{
|
||||
CUIRect r = Item.m_Rect;
|
||||
r.Margin(1.5f, &r);
|
||||
|
@ -718,6 +729,14 @@ int CMenus::UiDoListboxEnd(float *pScrollValue, bool *pItemActivated, bool *pLis
|
|||
return gs_ListBoxNewSelected;
|
||||
}
|
||||
|
||||
int CMenus::UiLogicGetCurrentClickedItem()
|
||||
{
|
||||
if(gs_ListBoxClicked)
|
||||
return gs_ListBoxNewSelected;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CMenus::DemolistFetchCallback(const char *pName, time_t Date, int IsDir, int StorageType, void *pUser)
|
||||
{
|
||||
CMenus *pSelf = (CMenus *)pUser;
|
||||
|
|
|
@ -667,8 +667,11 @@ void CMenus::RenderServerControl(CUIRect MainView)
|
|||
static int s_ClearButton = 0;
|
||||
static float Offset = 0.0f;
|
||||
//static char aFilterString[25];
|
||||
if(Input()->KeyPress(KEY_F) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))
|
||||
if(m_ControlPageOpening || (Input()->KeyPress(KEY_F) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL))))
|
||||
{
|
||||
UI()->SetActiveItem(&m_aFilterString);
|
||||
m_ControlPageOpening = false;
|
||||
}
|
||||
if(DoClearableEditBox(&m_aFilterString, &s_ClearButton, &QuickSearch, m_aFilterString, sizeof(m_aFilterString), 14.0f, &Offset, false, CUI::CORNER_ALL, Localize("Search")))
|
||||
{
|
||||
// TODO: Implement here
|
||||
|
|
|
@ -442,6 +442,21 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView)
|
|||
}
|
||||
}
|
||||
|
||||
struct CUISkin
|
||||
{
|
||||
const CSkin *m_pSkin;
|
||||
|
||||
CUISkin() :
|
||||
m_pSkin(nullptr) {}
|
||||
CUISkin(const CSkin *pSkin) :
|
||||
m_pSkin(pSkin) {}
|
||||
|
||||
bool operator<(const CUISkin &Other) const { return str_comp_nocase(m_pSkin->m_aName, Other.m_pSkin->m_aName) < 0; }
|
||||
|
||||
bool operator<(const char *pOther) const { return str_comp_nocase(m_pSkin->m_aName, pOther) < 0; }
|
||||
bool operator==(const char *pOther) const { return !str_comp_nocase(m_pSkin->m_aName, pOther); }
|
||||
};
|
||||
|
||||
void CMenus::RenderSettingsTee(CUIRect MainView)
|
||||
{
|
||||
CUIRect Button, Label, Button2, Dummy, DummyLabel, SkinList, QuickSearch, QuickSearchClearButton, SkinDB, SkinPrefix, SkinPrefixLabel, DirectoryButton, RefreshButton;
|
||||
|
@ -606,7 +621,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
|
|||
// skin selector
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
MainView.HSplitTop(230.0f, &SkinList, &MainView);
|
||||
static sorted_array<const CSkin *> s_paSkinList;
|
||||
static sorted_array<CUISkin> s_paSkinList;
|
||||
static int s_SkinCount = 0;
|
||||
static float s_ScrollValue = 0.0f;
|
||||
if(s_InitSkinlist || m_pClient->m_pSkins->Num() != s_SkinCount)
|
||||
|
@ -631,7 +646,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
|
|||
if(s == 0)
|
||||
continue;
|
||||
|
||||
s_paSkinList.add_unsorted(s);
|
||||
s_paSkinList.add(CUISkin(s));
|
||||
}
|
||||
s_InitSkinlist = false;
|
||||
s_SkinCount = m_pClient->m_pSkins->Num();
|
||||
|
@ -641,12 +656,12 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
|
|||
UiDoListboxStart(&s_InitSkinlist, &SkinList, 50.0f, Localize("Skins"), "", s_paSkinList.size(), 4, OldSelected, s_ScrollValue);
|
||||
for(int i = 0; i < s_paSkinList.size(); ++i)
|
||||
{
|
||||
const CSkin *s = s_paSkinList[i];
|
||||
const CSkin *s = s_paSkinList[i].m_pSkin;
|
||||
|
||||
if(str_comp(s->m_aName, Skin) == 0)
|
||||
OldSelected = i;
|
||||
|
||||
CListboxItem Item = UiDoListboxNextItem(s_paSkinList[i], OldSelected == i);
|
||||
CListboxItem Item = UiDoListboxNextItem(s_paSkinList[i].m_pSkin, OldSelected == i);
|
||||
char aBuf[128];
|
||||
if(Item.m_Visible)
|
||||
{
|
||||
|
@ -680,7 +695,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
|
|||
const int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0);
|
||||
if(OldSelected != NewSelected)
|
||||
{
|
||||
mem_copy(Skin, s_paSkinList[NewSelected]->m_aName, sizeof(g_Config.m_ClPlayerSkin));
|
||||
mem_copy(Skin, s_paSkinList[NewSelected].m_pSkin->m_aName, sizeof(g_Config.m_ClPlayerSkin));
|
||||
SetNeedSendInfo();
|
||||
}
|
||||
|
||||
|
@ -884,7 +899,9 @@ void CMenus::RenderSettingsControls(CUIRect MainView)
|
|||
static int s_SelectedControl = -1;
|
||||
static float s_ScrollValue = 0;
|
||||
int OldSelected = s_SelectedControl;
|
||||
UiDoListboxStart(&s_ControlsList, &MainView, 500.0f, Localize("Controls"), "", 1, 1, s_SelectedControl, s_ScrollValue);
|
||||
// Hacky values: Size of 10.0f per item for smoother scrolling, 72 elements
|
||||
// fits the current size of controls settings
|
||||
UiDoListboxStart(&s_ControlsList, &MainView, 10.0f, Localize("Controls"), "", 72, 1, s_SelectedControl, s_ScrollValue);
|
||||
|
||||
CUIRect MovementSettings, WeaponSettings, VotingSettings, ChatSettings, DummySettings, MiscSettings, ResetButton;
|
||||
CListboxItem Item = UiDoListboxNextItem(&OldSelected, false, false, true);
|
||||
|
@ -1012,6 +1029,43 @@ void CMenus::RenderSettingsControls(CUIRect MainView)
|
|||
UiDoListboxEnd(&s_ScrollValue, 0);
|
||||
}
|
||||
|
||||
int CMenus::RenderDropDown(int &CurDropDownState, CUIRect *pRect, int CurSelection, const void **pIDs, const char **pStr, int PickNum, const void *pID, float &ScrollVal)
|
||||
{
|
||||
if(CurDropDownState != 0)
|
||||
{
|
||||
CUIRect ListRect;
|
||||
pRect->HSplitTop(24.0f * PickNum, &ListRect, pRect);
|
||||
char aBuf[1024];
|
||||
UiDoListboxStart(&pID, &ListRect, 24.0f, "", aBuf, PickNum, 1, CurSelection, ScrollVal);
|
||||
for(int i = 0; i < PickNum; ++i)
|
||||
{
|
||||
CListboxItem Item = UiDoListboxNextItem(pIDs[i], CurSelection == i);
|
||||
if(Item.m_Visible)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "%s", pStr[i]);
|
||||
UI()->DoLabelScaled(&Item.m_Rect, aBuf, 16.0f, 0);
|
||||
}
|
||||
}
|
||||
bool ClickedItem = false;
|
||||
int NewIndex = UiDoListboxEnd(&ScrollVal, NULL, &ClickedItem);
|
||||
if(ClickedItem)
|
||||
{
|
||||
CurDropDownState = 0;
|
||||
return NewIndex;
|
||||
}
|
||||
else
|
||||
return CurSelection;
|
||||
}
|
||||
else
|
||||
{
|
||||
CUIRect Button;
|
||||
pRect->HSplitTop(24.0f, &Button, pRect);
|
||||
if(DoButton_MenuTab(&pID, CurSelection > -1 ? pStr[CurSelection] : "", 0, &Button, CUI::CORNER_ALL, NULL, NULL, NULL, NULL, 4.0f))
|
||||
CurDropDownState = 1;
|
||||
return CurSelection;
|
||||
}
|
||||
}
|
||||
|
||||
void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
||||
{
|
||||
CUIRect Button, Label;
|
||||
|
@ -1080,16 +1134,28 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
}
|
||||
|
||||
// switches
|
||||
MainView.HSplitTop(20.0f, &Button, &MainView);
|
||||
if(DoButton_CheckBox(&g_Config.m_GfxBorderless, Localize("Borderless window"), g_Config.m_GfxBorderless, &Button))
|
||||
{
|
||||
Client()->ToggleWindowBordered();
|
||||
}
|
||||
static float s_ScrollValueDrop = 0;
|
||||
static const int s_NumWindowMode = 4;
|
||||
static int s_aWindowModeIDs[s_NumWindowMode];
|
||||
const void *aWindowModeIDs[s_NumWindowMode];
|
||||
for(int i = 0; i < s_NumWindowMode; ++i)
|
||||
aWindowModeIDs[i] = &s_aWindowModeIDs[i];
|
||||
static int s_WindowModeDropDownState = 0;
|
||||
const char *pWindowModes[] = {Localize("Windowed"), Localize("Windowed borderless"), Localize("Desktop fullscreen"), Localize("Fullscreen")};
|
||||
|
||||
MainView.HSplitTop(20.0f, &Button, &MainView);
|
||||
if(DoButton_CheckBox(&g_Config.m_GfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button))
|
||||
OldSelected = (g_Config.m_GfxFullscreen ? (g_Config.m_GfxFullscreen == 1 ? 3 : 2) : (g_Config.m_GfxBorderless ? 1 : 0));
|
||||
|
||||
const int NewWindowMode = RenderDropDown(s_WindowModeDropDownState, &MainView, OldSelected, aWindowModeIDs, pWindowModes, s_NumWindowMode, &s_NumWindowMode, s_ScrollValueDrop);
|
||||
if(OldSelected != NewWindowMode)
|
||||
{
|
||||
Client()->ToggleFullscreen();
|
||||
if(NewWindowMode == 0)
|
||||
Client()->SetWindowParams(0, false);
|
||||
else if(NewWindowMode == 1)
|
||||
Client()->SetWindowParams(0, true);
|
||||
else if(NewWindowMode == 2)
|
||||
Client()->SetWindowParams(2, false);
|
||||
else if(NewWindowMode == 3)
|
||||
Client()->SetWindowParams(1, false);
|
||||
}
|
||||
|
||||
MainView.HSplitTop(20.0f, &Button, &MainView);
|
||||
|
|
|
@ -2992,6 +2992,21 @@ void CGameClient::ConchainMenuMap(IConsole::IResult *pResult, void *pUserData, I
|
|||
pfnCallback(pResult, pCallbackUserData);
|
||||
}
|
||||
|
||||
void CGameClient::DummyResetInput()
|
||||
{
|
||||
if(!Client()->DummyConnected())
|
||||
return;
|
||||
|
||||
if((m_DummyInput.m_Fire & 1) != 0)
|
||||
m_DummyInput.m_Fire++;
|
||||
|
||||
m_pControls->ResetInput(!g_Config.m_ClDummy);
|
||||
m_pControls->m_InputData[!g_Config.m_ClDummy].m_Hook = 0;
|
||||
m_pControls->m_InputData[!g_Config.m_ClDummy].m_Fire = m_DummyInput.m_Fire;
|
||||
|
||||
m_DummyInput = m_pControls->m_InputData[!g_Config.m_ClDummy];
|
||||
}
|
||||
|
||||
bool CGameClient::CanDisplayWarning()
|
||||
{
|
||||
return m_pMenus->CanDisplayWarning();
|
||||
|
|
|
@ -451,6 +451,7 @@ public:
|
|||
CGameWorld m_PredictedWorld;
|
||||
CGameWorld m_PrevPredictedWorld;
|
||||
|
||||
void DummyResetInput();
|
||||
void Echo(const char *pString);
|
||||
bool IsOtherTeam(int ClientID);
|
||||
bool CanDisplayWarning();
|
||||
|
|
|
@ -131,10 +131,10 @@ struct CSkin
|
|||
};
|
||||
SSkinMetrics m_Metrics;
|
||||
|
||||
bool operator<(const CSkin &Other) const { return str_comp_nocase(m_aName, Other.m_aName) < 0; }
|
||||
bool operator<(const CSkin &Other) const { return str_comp(m_aName, Other.m_aName) < 0; }
|
||||
|
||||
bool operator<(const char *pOther) const { return str_comp_nocase(m_aName, pOther) < 0; }
|
||||
bool operator==(const char *pOther) const { return !str_comp_nocase(m_aName, pOther); }
|
||||
bool operator<(const char *pOther) const { return str_comp(m_aName, pOther) < 0; }
|
||||
bool operator==(const char *pOther) const { return !str_comp(m_aName, pOther); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,11 +27,14 @@ CHAT_COMMAND("dnd", "", CFGFLAG_CHAT | CFGFLAG_SERVER | CFGFLAG_NONTEEHISTORIC,
|
|||
CHAT_COMMAND("mapinfo", "?r[map]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConMapInfo, this, "Show info about the map with name r gives (current map by default)")
|
||||
CHAT_COMMAND("timeout", "?s[code]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTimeout, this, "Set timeout protection code s")
|
||||
CHAT_COMMAND("practice", "?i['0'|'1']", CFGFLAG_CHAT | CFGFLAG_SERVER, ConPractice, this, "Enable cheats (currently only /rescue) for your current team's run, but you can't earn a rank")
|
||||
CHAT_COMMAND("swap", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConSwap, this, "Request to swap your tee with another team member")
|
||||
CHAT_COMMAND("save", "?r[code]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConSave, this, "Save team with code r.")
|
||||
CHAT_COMMAND("load", "?r[code]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConLoad, this, "Load with code r. /load to check your existing saves")
|
||||
CHAT_COMMAND("map", "?r[map]", CFGFLAG_CHAT | CFGFLAG_SERVER | CFGFLAG_NONTEEHISTORIC, ConMap, this, "Vote a map by name")
|
||||
|
||||
CHAT_COMMAND("rankteam", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTeamRank, this, "Shows the team rank of player with name r (your team rank by default)")
|
||||
CHAT_COMMAND("teamrank", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTeamRank, this, "Shows the team rank of player with name r (your team rank by default)")
|
||||
|
||||
CHAT_COMMAND("rank", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConRank, this, "Shows the rank of player with name r (your rank by default)")
|
||||
CHAT_COMMAND("top5team", "?s[player name] ?i[rank to start with]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTeamTop5, this, "Shows five team ranks of the ladder or of a player beginning with rank i (1 by default, -1 for worst)")
|
||||
CHAT_COMMAND("teamtop5", "?s[player name] ?i[rank to start with]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTeamTop5, this, "Shows five team ranks of the ladder or of a player beginning with rank i (1 by default, -1 for worst)")
|
||||
|
|
|
@ -397,25 +397,17 @@ void CAutoMapper::ProceedLocalized(CLayerTiles *pLayer, int ConfigID, int Seed,
|
|||
int UpdateToX = clamp(X + Width + 3 * pConf->m_EndX, 0, pLayer->m_Width);
|
||||
int UpdateToY = clamp(Y + Height + 3 * pConf->m_EndY, 0, pLayer->m_Height);
|
||||
|
||||
CLayerTiles *pUpdateLayer;
|
||||
if(UpdateFromX != 0 || UpdateFromY != 0 || UpdateToX != pLayer->m_Width || UpdateToY != pLayer->m_Width)
|
||||
{ // Needs a layer to work on
|
||||
pUpdateLayer = new CLayerTiles(UpdateToX - UpdateFromX, UpdateToY - UpdateFromY);
|
||||
CLayerTiles *pUpdateLayer = new CLayerTiles(UpdateToX - UpdateFromX, UpdateToY - UpdateFromY);
|
||||
|
||||
for(int y = UpdateFromY; y < UpdateToY; y++)
|
||||
{
|
||||
for(int x = UpdateFromX; x < UpdateToX; x++)
|
||||
{
|
||||
CTile *in = &pLayer->m_pTiles[y * pLayer->m_Width + x];
|
||||
CTile *out = &pUpdateLayer->m_pTiles[(y - UpdateFromY) * pUpdateLayer->m_Width + x - UpdateFromX];
|
||||
out->m_Index = in->m_Index;
|
||||
out->m_Flags = in->m_Flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
for(int y = UpdateFromY; y < UpdateToY; y++)
|
||||
{
|
||||
pUpdateLayer = pLayer;
|
||||
for(int x = UpdateFromX; x < UpdateToX; x++)
|
||||
{
|
||||
CTile *in = &pLayer->m_pTiles[y * pLayer->m_Width + x];
|
||||
CTile *out = &pUpdateLayer->m_pTiles[(y - UpdateFromY) * pUpdateLayer->m_Width + x - UpdateFromX];
|
||||
out->m_Index = in->m_Index;
|
||||
out->m_Flags = in->m_Flags;
|
||||
}
|
||||
}
|
||||
|
||||
Proceed(pUpdateLayer, ConfigID, Seed, UpdateFromX, UpdateFromY);
|
||||
|
@ -431,8 +423,7 @@ void CAutoMapper::ProceedLocalized(CLayerTiles *pLayer, int ConfigID, int Seed,
|
|||
}
|
||||
}
|
||||
|
||||
if(pUpdateLayer)
|
||||
delete pUpdateLayer;
|
||||
delete pUpdateLayer;
|
||||
}
|
||||
|
||||
void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID, int Seed, int SeedOffsetX, int SeedOffsetY)
|
||||
|
|
|
@ -3811,18 +3811,20 @@ int CEditor::PopupImage(CEditor *pEditor, CUIRect View, void *pContext)
|
|||
pImg->m_External = 0;
|
||||
return 1;
|
||||
}
|
||||
View.HSplitTop(5.0f, &Slot, &View);
|
||||
View.HSplitTop(12.0f, &Slot, &View);
|
||||
}
|
||||
else
|
||||
else if(IsVanillaImage(pImg->m_aName))
|
||||
{
|
||||
if(pEditor->DoButton_MenuItem(&s_ExternalButton, "Make external", 0, &Slot, 0, "Removes the image from the map file."))
|
||||
{
|
||||
pImg->m_External = 1;
|
||||
return 1;
|
||||
}
|
||||
View.HSplitTop(5.0f, &Slot, &View);
|
||||
View.HSplitTop(12.0f, &Slot, &View);
|
||||
}
|
||||
|
||||
View.HSplitTop(5.0f, &Slot, &View);
|
||||
View.HSplitTop(12.0f, &Slot, &View);
|
||||
if(pEditor->DoButton_MenuItem(&s_ReplaceButton, "Replace", 0, &Slot, 0, "Replaces the image with a new one"))
|
||||
{
|
||||
pEditor->InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_IMG, "Replace Image", "Replace", "mapres", "", ReplaceImage, pEditor);
|
||||
|
@ -4038,7 +4040,15 @@ void CEditor::RenderImages(CUIRect ToolBox, CUIRect View)
|
|||
|
||||
static int s_PopupImageID = 0;
|
||||
if(Result == 2)
|
||||
UiInvokePopupMenu(&s_PopupImageID, 0, UI()->MouseX(), UI()->MouseY(), 120, 60, PopupImage);
|
||||
{
|
||||
CEditorImage *pImg = m_Map.m_lImages[m_SelectedImage];
|
||||
int Height;
|
||||
if(pImg->m_External || IsVanillaImage(pImg->m_aName))
|
||||
Height = 60;
|
||||
else
|
||||
Height = 43;
|
||||
UiInvokePopupMenu(&s_PopupImageID, 0, UI()->MouseX(), UI()->MouseY(), 120, Height, PopupImage);
|
||||
}
|
||||
}
|
||||
|
||||
ToolBox.HSplitTop(2.0f, 0, &ToolBox);
|
||||
|
|
|
@ -674,6 +674,81 @@ void CGameContext::ConPractice(IConsole::IResult *pResult, void *pUserData)
|
|||
}
|
||||
}
|
||||
|
||||
void CGameContext::ConSwap(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
CGameContext *pSelf = (CGameContext *)pUserData;
|
||||
const char *pName = pResult->GetString(0);
|
||||
|
||||
if(!CheckClientID(pResult->m_ClientID))
|
||||
return;
|
||||
|
||||
CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientID];
|
||||
if(!pPlayer)
|
||||
return;
|
||||
|
||||
if(pSelf->ProcessSpamProtection(pResult->m_ClientID))
|
||||
return;
|
||||
|
||||
CGameTeams &Teams = ((CGameControllerDDRace *)pSelf->m_pController)->m_Teams;
|
||||
|
||||
int Team = Teams.m_Core.Team(pResult->m_ClientID);
|
||||
|
||||
if(Team < TEAM_FLOCK || (Team == TEAM_FLOCK && g_Config.m_SvTeam != 3) || Team >= TEAM_SUPER)
|
||||
{
|
||||
pSelf->Console()->Print(
|
||||
IConsole::OUTPUT_LEVEL_STANDARD,
|
||||
"print",
|
||||
"Join a team to use swap feature, which means you can swap positions with each other.");
|
||||
return;
|
||||
}
|
||||
|
||||
int TargetClientId = -1;
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if(pSelf->m_apPlayers[i] && !str_comp(pName, pSelf->Server()->ClientName(i)))
|
||||
{
|
||||
TargetClientId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(TargetClientId < 0)
|
||||
{
|
||||
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "swap", "Player not found");
|
||||
return;
|
||||
}
|
||||
|
||||
if(TargetClientId == pResult->m_ClientID)
|
||||
{
|
||||
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "swap", "Can't swap with yourself");
|
||||
return;
|
||||
}
|
||||
|
||||
int TargetTeam = Teams.m_Core.Team(TargetClientId);
|
||||
if(TargetTeam != Team)
|
||||
{
|
||||
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "swap", "Player is on a different team");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!Teams.IsStarted(Team))
|
||||
{
|
||||
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "swap", "Need to have started the map to swap with a player.");
|
||||
return;
|
||||
}
|
||||
|
||||
CPlayer *pSwapPlayer = pSelf->m_apPlayers[TargetClientId];
|
||||
|
||||
bool SwapPending = pSwapPlayer->m_SwapTargetsClientID != pResult->m_ClientID;
|
||||
if(SwapPending)
|
||||
{
|
||||
Teams.RequestTeamSwap(pPlayer, pSwapPlayer, Team);
|
||||
return;
|
||||
}
|
||||
|
||||
Teams.SwapTeamCharacters(pPlayer, pSwapPlayer, Team);
|
||||
}
|
||||
|
||||
void CGameContext::ConSave(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
CGameContext *pSelf = (CGameContext *)pUserData;
|
||||
|
|
|
@ -356,6 +356,7 @@ private:
|
|||
static void ConMapInfo(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConTimeout(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConPractice(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConSwap(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConSave(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConLoad(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConMap(IConsole::IResult *pResult, void *pUserData);
|
||||
|
|
|
@ -138,6 +138,7 @@ void CPlayer::Reset()
|
|||
m_NotEligibleForFinish = false;
|
||||
m_EligibleForFinishCheck = 0;
|
||||
m_VotedForPractice = false;
|
||||
m_SwapTargetsClientID = -1;
|
||||
}
|
||||
|
||||
static int PlayerFlags_SevenToSix(int Flags)
|
||||
|
|
|
@ -210,6 +210,7 @@ public:
|
|||
bool m_NotEligibleForFinish;
|
||||
int64 m_EligibleForFinishCheck;
|
||||
bool m_VotedForPractice;
|
||||
int m_SwapTargetsClientID; //Client ID of the swap target for the given player
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -55,7 +55,7 @@ void CSaveTee::Save(CCharacter *pChr)
|
|||
m_TuneZoneOld = pChr->m_TuneZoneOld;
|
||||
|
||||
if(pChr->m_StartTime)
|
||||
m_Time = pChr->Server()->Tick() - pChr->m_StartTime;
|
||||
m_Time = pChr->Server()->Tick() - pChr->m_StartTime + g_Config.m_SvSaveSwapGamesPenalty * pChr->Server()->TickSpeed();
|
||||
else
|
||||
m_Time = 0;
|
||||
|
||||
|
@ -209,9 +209,6 @@ void CSaveTee::Load(CCharacter *pChr, int Team)
|
|||
|
||||
char *CSaveTee::GetString(const CSaveTeam *pTeam)
|
||||
{
|
||||
// Add time penalty of 60 seconds (only to the database)
|
||||
int Time = m_Time + 60 * SERVER_TICK_SPEED;
|
||||
|
||||
int HookedPlayer = -1;
|
||||
if(m_HookedPlayer != -1)
|
||||
{
|
||||
|
@ -268,7 +265,7 @@ char *CSaveTee::GetString(const CSaveTeam *pTeam)
|
|||
m_LastWeapon, m_QueuedWeapon,
|
||||
// tee states
|
||||
m_SuperJump, m_Jetpack, m_NinjaJetpack, m_FreezeTime, m_FreezeTick, m_DeepFreeze, m_EndlessHook,
|
||||
m_DDRaceState, m_Hit, m_Collision, m_TuneZone, m_TuneZoneOld, m_Hook, Time,
|
||||
m_DDRaceState, m_Hit, m_Collision, m_TuneZone, m_TuneZoneOld, m_Hook, m_Time,
|
||||
(int)m_Pos.x, (int)m_Pos.y, (int)m_PrevPos.x, (int)m_PrevPos.y,
|
||||
m_TeleCheckpoint, m_LastPenalty,
|
||||
(int)m_CorePos.x, (int)m_CorePos.y, m_Vel.x, m_Vel.y,
|
||||
|
|
|
@ -718,7 +718,8 @@ bool CScore::SaveTeamScoreThread(IDbConnection *pSqlServer, const ISqlData *pGam
|
|||
pSqlServer->BindString(2, pData->m_GameUuid);
|
||||
pSqlServer->BindBlob(3, Teamrank.m_TeamID.m_aData, sizeof(Teamrank.m_TeamID.m_aData));
|
||||
pSqlServer->Print();
|
||||
if(pSqlServer->Step(&End, pError, ErrorSize))
|
||||
int NumUpdated;
|
||||
if(pSqlServer->ExecuteUpdate(&NumUpdated, pError, ErrorSize))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -843,18 +844,18 @@ bool CScore::ShowRankThread(IDbConnection *pSqlServer, const ISqlData *pGameData
|
|||
if(str_comp_nocase(pData->m_RequestingPlayer, pData->m_Name) == 0)
|
||||
{
|
||||
str_format(pResult->m_Data.m_aaMessages[0], sizeof(pResult->m_Data.m_aaMessages[0]),
|
||||
"%s Time: %s, better than %d%%",
|
||||
"%s - %s - better than %d%%",
|
||||
pData->m_Name, aBuf, BetterThanPercent);
|
||||
}
|
||||
else
|
||||
{
|
||||
str_format(pResult->m_Data.m_aaMessages[0], sizeof(pResult->m_Data.m_aaMessages[0]),
|
||||
"%s Time: %s, better than %d%%, requested by %s",
|
||||
"%s - %s - better than %d%% - requested by %s",
|
||||
pData->m_Name, aBuf, BetterThanPercent, pData->m_RequestingPlayer);
|
||||
}
|
||||
|
||||
str_format(pResult->m_Data.m_aaMessages[1], sizeof(pResult->m_Data.m_aaMessages[1]),
|
||||
"Global rank %d || %s %s",
|
||||
"Global rank %d - %s %s",
|
||||
Rank, pData->m_Server, aRegionalRank);
|
||||
}
|
||||
}
|
||||
|
@ -996,7 +997,7 @@ bool CScore::ShowTopThread(IDbConnection *pSqlServer, const ISqlData *pGameData,
|
|||
}
|
||||
pSqlServer->BindString(1, pData->m_Map);
|
||||
pSqlServer->BindString(2, pAny);
|
||||
pSqlServer->BindInt(3, 6);
|
||||
pSqlServer->BindInt(3, 5);
|
||||
|
||||
// show top
|
||||
int Line = 0;
|
||||
|
@ -1023,11 +1024,6 @@ bool CScore::ShowTopThread(IDbConnection *pSqlServer, const ISqlData *pGameData,
|
|||
HasLocal = HasLocal || str_comp(aRecordServer, pData->m_Server) == 0;
|
||||
|
||||
Line++;
|
||||
|
||||
if(!HasLocal && Line == 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!HasLocal)
|
||||
|
@ -1873,7 +1869,7 @@ bool CScore::LoadTeamThread(IDbConnection *pSqlServer, const ISqlData *pGameData
|
|||
bool Found = false;
|
||||
for(int i = 0; i < pResult->m_SavedTeam.GetMembersCount(); i++)
|
||||
{
|
||||
if(str_comp(pResult->m_SavedTeam.m_pSavedTees->GetName(), pData->m_RequestingPlayer) == 0)
|
||||
if(str_comp(pResult->m_SavedTeam.m_pSavedTees[i].GetName(), pData->m_RequestingPlayer) == 0)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
|
@ -1886,11 +1882,11 @@ bool CScore::LoadTeamThread(IDbConnection *pSqlServer, const ISqlData *pGameData
|
|||
}
|
||||
|
||||
int Since = pSqlServer->GetInt(2);
|
||||
if(Since < g_Config.m_SvSaveGamesDelay)
|
||||
if(Since < g_Config.m_SvSaveSwapGamesDelay)
|
||||
{
|
||||
str_format(pResult->m_aMessage, sizeof(pResult->m_aMessage),
|
||||
"You have to wait %d seconds until you can load this savegame",
|
||||
g_Config.m_SvSaveGamesDelay - Since);
|
||||
g_Config.m_SvSaveSwapGamesDelay - Since);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ struct CScorePlayerResult : ISqlResult
|
|||
|
||||
enum
|
||||
{
|
||||
MAX_MESSAGES = 8,
|
||||
MAX_MESSAGES = 10,
|
||||
};
|
||||
|
||||
enum Variant
|
||||
|
|
|
@ -19,12 +19,31 @@ void CGameTeams::Reset()
|
|||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
||||
{
|
||||
m_TeamState[i] = TEAMSTATE_EMPTY;
|
||||
m_TeamLocked[i] = false;
|
||||
m_TeeFinished[i] = false;
|
||||
m_LastChat[i] = 0;
|
||||
m_TeamLocked[i] = false;
|
||||
m_pSaveTeamResult[i] = nullptr;
|
||||
|
||||
m_Invited[i] = 0;
|
||||
m_Practice[i] = false;
|
||||
m_pSaveTeamResult[i] = nullptr;
|
||||
m_LastSwap[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CGameTeams::ResetRoundState(int Team)
|
||||
{
|
||||
ResetInvited(Team);
|
||||
ResetSwitchers(Team);
|
||||
m_LastSwap[Team] = 0;
|
||||
|
||||
m_Practice[Team] = 0;
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if(m_Core.Team(i) == Team && GameServer()->m_apPlayers[i])
|
||||
{
|
||||
GameServer()->m_apPlayers[i]->m_VotedForPractice = false;
|
||||
GameServer()->m_apPlayers[i]->m_SwapTargetsClientID = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,13 +287,23 @@ const char *CGameTeams::SetCharacterTeam(int ClientID, int Team)
|
|||
|
||||
void CGameTeams::SetForceCharacterTeam(int ClientID, int Team)
|
||||
{
|
||||
if(Team != m_Core.Team(ClientID))
|
||||
ForceLeaveTeam(ClientID);
|
||||
else
|
||||
m_TeeFinished[ClientID] = false;
|
||||
|
||||
m_TeeFinished[ClientID] = false;
|
||||
int OldTeam = m_Core.Team(ClientID);
|
||||
|
||||
if(Team != OldTeam && (OldTeam != TEAM_FLOCK || g_Config.m_SvTeam == 3) && OldTeam != TEAM_SUPER && m_TeamState[OldTeam] != TEAMSTATE_EMPTY)
|
||||
{
|
||||
bool NoElseInOldTeam = Count(OldTeam) <= 1;
|
||||
if(NoElseInOldTeam)
|
||||
{
|
||||
m_TeamState[OldTeam] = TEAMSTATE_EMPTY;
|
||||
|
||||
// unlock team when last player leaves
|
||||
SetTeamLock(OldTeam, false);
|
||||
ResetRoundState(OldTeam);
|
||||
// do not reset SaveTeamResult, because it should be logged into teehistorian even if the team leaves
|
||||
}
|
||||
}
|
||||
|
||||
m_Core.Team(ClientID, Team);
|
||||
|
||||
if(OldTeam != Team)
|
||||
|
@ -284,7 +313,10 @@ void CGameTeams::SetForceCharacterTeam(int ClientID, int Team)
|
|||
SendTeamsState(LoopClientID);
|
||||
|
||||
if(GetPlayer(ClientID))
|
||||
{
|
||||
GetPlayer(ClientID)->m_VotedForPractice = false;
|
||||
GetPlayer(ClientID)->m_SwapTargetsClientID = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(Team != TEAM_SUPER && (m_TeamState[Team] == TEAMSTATE_EMPTY || m_TeamLocked[Team]))
|
||||
|
@ -296,32 +328,6 @@ void CGameTeams::SetForceCharacterTeam(int ClientID, int Team)
|
|||
}
|
||||
}
|
||||
|
||||
void CGameTeams::ForceLeaveTeam(int ClientID)
|
||||
{
|
||||
m_TeeFinished[ClientID] = false;
|
||||
|
||||
if((m_Core.Team(ClientID) != TEAM_FLOCK || g_Config.m_SvTeam == 3) && m_Core.Team(ClientID) != TEAM_SUPER && m_TeamState[m_Core.Team(ClientID)] != TEAMSTATE_EMPTY)
|
||||
{
|
||||
bool NoOneInOldTeam = true;
|
||||
for(int i = 0; i < MAX_CLIENTS; ++i)
|
||||
if(i != ClientID && m_Core.Team(ClientID) == m_Core.Team(i))
|
||||
{
|
||||
NoOneInOldTeam = false; // all good exists someone in old team
|
||||
break;
|
||||
}
|
||||
if(NoOneInOldTeam)
|
||||
{
|
||||
m_TeamState[m_Core.Team(ClientID)] = TEAMSTATE_EMPTY;
|
||||
|
||||
// unlock team when last player leaves
|
||||
SetTeamLock(m_Core.Team(ClientID), false);
|
||||
ResetInvited(m_Core.Team(ClientID));
|
||||
m_Practice[m_Core.Team(ClientID)] = false;
|
||||
// do not reset SaveTeamResult, because it should be logged into teehistorian even if the team leaves
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CGameTeams::Count(int Team) const
|
||||
{
|
||||
if(Team == TEAM_SUPER)
|
||||
|
@ -675,6 +681,85 @@ void CGameTeams::OnFinish(CPlayer *Player, float Time, const char *pTimestamp)
|
|||
}
|
||||
}
|
||||
|
||||
void CGameTeams::RequestTeamSwap(CPlayer *pPlayer, CPlayer *pTargetPlayer, int Team)
|
||||
{
|
||||
if(!pPlayer || !pTargetPlayer)
|
||||
return;
|
||||
|
||||
char aBuf[512];
|
||||
if(pPlayer->m_SwapTargetsClientID == pTargetPlayer->GetCID())
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf),
|
||||
"%s has already requested to swap with %s.",
|
||||
Server()->ClientName(pPlayer->GetCID()), Server()->ClientName(pTargetPlayer->GetCID()));
|
||||
|
||||
GameServer()->SendChatTeam(Team, aBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
str_format(aBuf, sizeof(aBuf),
|
||||
"%s has requested to swap with %s. Please wait %d seconds then type /swap %s.",
|
||||
Server()->ClientName(pPlayer->GetCID()), Server()->ClientName(pTargetPlayer->GetCID()), g_Config.m_SvSaveSwapGamesDelay, Server()->ClientName(pPlayer->GetCID()));
|
||||
|
||||
GameServer()->SendChatTeam(Team, aBuf);
|
||||
|
||||
pPlayer->m_SwapTargetsClientID = pTargetPlayer->GetCID();
|
||||
m_LastSwap[Team] = Server()->Tick();
|
||||
}
|
||||
|
||||
void CGameTeams::SwapTeamCharacters(CPlayer *pPlayer, CPlayer *pTargetPlayer, int Team)
|
||||
{
|
||||
if(!pPlayer || !pTargetPlayer)
|
||||
return;
|
||||
|
||||
char aBuf[128];
|
||||
|
||||
int Since = (Server()->Tick() - m_LastSwap[Team]) / Server()->TickSpeed();
|
||||
if(Since < g_Config.m_SvSaveSwapGamesDelay)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf),
|
||||
"You have to wait %d seconds until you can swap.",
|
||||
g_Config.m_SvSaveSwapGamesDelay - Since);
|
||||
|
||||
GameServer()->SendChatTeam(Team, aBuf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int TimeoutAfterDelay = g_Config.m_SvSaveSwapGamesDelay + g_Config.m_SvSwapTimeout;
|
||||
if(Since >= TimeoutAfterDelay)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf),
|
||||
"Your swap request timed out %d seconds ago. Use /swap again to re-initiate it.",
|
||||
Since - g_Config.m_SvSwapTimeout);
|
||||
|
||||
GameServer()->SendChatTeam(Team, aBuf);
|
||||
|
||||
pPlayer->m_SwapTargetsClientID = -1;
|
||||
pTargetPlayer->m_SwapTargetsClientID = -1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CSaveTee PrimarySavedTee;
|
||||
PrimarySavedTee.Save(pPlayer->GetCharacter());
|
||||
|
||||
CSaveTee SecondarySavedTee;
|
||||
SecondarySavedTee.Save(pTargetPlayer->GetCharacter());
|
||||
|
||||
PrimarySavedTee.Load(pTargetPlayer->GetCharacter(), Team);
|
||||
SecondarySavedTee.Load(pPlayer->GetCharacter(), Team);
|
||||
|
||||
pPlayer->m_SwapTargetsClientID = -1;
|
||||
pTargetPlayer->m_SwapTargetsClientID = -1;
|
||||
|
||||
str_format(aBuf, sizeof(aBuf),
|
||||
"%s has swapped with %s.",
|
||||
Server()->ClientName(pPlayer->GetCID()), Server()->ClientName(pTargetPlayer->GetCID()));
|
||||
|
||||
GameServer()->SendChatTeam(Team, aBuf);
|
||||
}
|
||||
|
||||
void CGameTeams::ProcessSaveTeam()
|
||||
{
|
||||
for(int Team = 0; Team < MAX_CLIENTS; Team++)
|
||||
|
@ -780,9 +865,7 @@ void CGameTeams::OnCharacterDeath(int ClientID, int Weapon)
|
|||
if(g_Config.m_SvTeam == 3)
|
||||
{
|
||||
ChangeTeamState(Team, CGameTeams::TEAMSTATE_OPEN);
|
||||
ResetSwitchers(Team);
|
||||
m_Practice[Team] = false;
|
||||
GameServer()->m_apPlayers[ClientID]->m_VotedForPractice = false;
|
||||
ResetRoundState(Team);
|
||||
}
|
||||
else if(Locked)
|
||||
{
|
||||
|
@ -859,8 +942,7 @@ void CGameTeams::ResetSavedTeam(int ClientID, int Team)
|
|||
if(g_Config.m_SvTeam == 3)
|
||||
{
|
||||
ChangeTeamState(Team, CGameTeams::TEAMSTATE_OPEN);
|
||||
ResetSwitchers(Team);
|
||||
m_Practice[Team] = false;
|
||||
ResetRoundState(Team);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@ class CGameTeams
|
|||
uint64 m_Invited[MAX_CLIENTS];
|
||||
bool m_Practice[MAX_CLIENTS];
|
||||
std::shared_ptr<CScoreSaveResult> m_pSaveTeamResult[MAX_CLIENTS];
|
||||
uint64 m_LastSwap[MAX_CLIENTS];
|
||||
|
||||
class CGameContext *m_pGameContext;
|
||||
|
||||
|
@ -73,10 +74,9 @@ public:
|
|||
|
||||
// need to be very careful using this method. SERIOUSLY...
|
||||
void SetForceCharacterTeam(int ClientID, int Team);
|
||||
void SetForceCharacterNewTeam(int ClientID, int Team);
|
||||
void ForceLeaveTeam(int ClientID);
|
||||
|
||||
void Reset();
|
||||
void ResetRoundState(int Team);
|
||||
void ResetSwitchers(int Team);
|
||||
|
||||
void SendTeamsState(int ClientID);
|
||||
|
@ -94,6 +94,8 @@ public:
|
|||
void SetCpActive(CPlayer *Player, int CpActive);
|
||||
void KillSavedTeam(int ClientID, int Team);
|
||||
void ResetSavedTeam(int ClientID, int Team);
|
||||
void RequestTeamSwap(CPlayer *pPlayer, CPlayer *pTargetPlayer, int Team);
|
||||
void SwapTeamCharacters(CPlayer *pPlayer, CPlayer *pTargetPlayer, int Team);
|
||||
void ProcessSaveTeam();
|
||||
|
||||
bool TeeFinished(int ClientID)
|
||||
|
@ -119,6 +121,11 @@ public:
|
|||
return m_Invited[Team] & 1LL << ClientID;
|
||||
}
|
||||
|
||||
bool IsStarted(int Team)
|
||||
{
|
||||
return m_TeamState[Team] == CGameTeams::TEAMSTATE_STARTED;
|
||||
}
|
||||
|
||||
void SetFinished(int ClientID, bool finished)
|
||||
{
|
||||
m_TeeFinished[ClientID] = finished;
|
||||
|
|
|
@ -138,10 +138,10 @@ MACRO_CONFIG_INT(ClDummyRestoreWeapon, cl_dummy_restore_weapon, 1, 0, 1, CFGFLAG
|
|||
MACRO_CONFIG_INT(ClDummyCopyMoves, cl_dummy_copy_moves, 0, 0, 1, CFGFLAG_CLIENT, "Whether dummy should copy your moves")
|
||||
|
||||
// more controlable dummy command
|
||||
MACRO_CONFIG_INT(ClDummyControl, cl_dummy_control, 0, 0, 1, CFGFLAG_CLIENT, "Whether can you control dummy at the same time")
|
||||
MACRO_CONFIG_INT(ClDummyJump, cl_dummy_jump, 0, 0, 1, CFGFLAG_CLIENT, "Whether dummy is jumping")
|
||||
MACRO_CONFIG_INT(ClDummyFire, cl_dummy_fire, 0, 0, 1, CFGFLAG_CLIENT, "Whether dummy is firing")
|
||||
MACRO_CONFIG_INT(ClDummyHook, cl_dummy_hook, 0, 0, 1, CFGFLAG_CLIENT, "Whether dummy is hooking")
|
||||
MACRO_CONFIG_INT(ClDummyControl, cl_dummy_control, 0, 0, 1, CFGFLAG_CLIENT, "Whether can you control dummy at the same time (cl_dummy_jump, cl_dummy_fire, cl_dummy_hook)")
|
||||
MACRO_CONFIG_INT(ClDummyJump, cl_dummy_jump, 0, 0, 1, CFGFLAG_CLIENT, "Whether dummy is jumping (requires cl_dummy_control 1)")
|
||||
MACRO_CONFIG_INT(ClDummyFire, cl_dummy_fire, 0, 0, 1, CFGFLAG_CLIENT, "Whether dummy is firing (requires cl_dummy_control 1)")
|
||||
MACRO_CONFIG_INT(ClDummyHook, cl_dummy_hook, 0, 0, 1, CFGFLAG_CLIENT, "Whether dummy is hooking (requires cl_dummy_control 1)")
|
||||
|
||||
// start menu
|
||||
MACRO_CONFIG_INT(ClShowStartMenuImages, cl_show_start_menu_images, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show start menu images")
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
#ifndef GAME_VERSION_H
|
||||
#define GAME_VERSION_H
|
||||
#ifndef GAME_RELEASE_VERSION
|
||||
#define GAME_RELEASE_VERSION "15.3.2"
|
||||
#define GAME_RELEASE_VERSION "15.4"
|
||||
#endif
|
||||
#define GAME_VERSION "0.6.4, " GAME_RELEASE_VERSION
|
||||
#define GAME_NETVERSION "0.6 626fce9a778df4d4"
|
||||
#define GAME_NAME "DDNet"
|
||||
#define CLIENT_VERSIONNR 15032
|
||||
#define CLIENT_VERSIONNR 15040
|
||||
extern const char *GIT_SHORTREV_HASH;
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue