mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-19 17:14:18 +00:00
Compare commits
36 commits
5b2c089155
...
13faf02ae6
Author | SHA1 | Date | |
---|---|---|---|
13faf02ae6 | |||
d5e81ca78d | |||
128ffd2313 | |||
af1b32d296 | |||
0ad1c08c22 | |||
9f278979e5 | |||
32e9240634 | |||
b5d662622c | |||
58ce5985d4 | |||
46acbdd6bf | |||
d536bceed6 | |||
337d5c7ab3 | |||
8e45d0a71a | |||
a865354320 | |||
3595b70170 | |||
11fd82077a | |||
3d30ce4bf2 | |||
9e0ba8a91f | |||
c89509bc4b | |||
306d3c7b58 | |||
9832288983 | |||
fc058fa432 | |||
3b22a3e02f | |||
ed1ef4e694 | |||
9103332e36 | |||
0948a53648 | |||
bbd34c9452 | |||
e4282f100a | |||
eb9e73f68b | |||
6c0427d23c | |||
38324489a2 | |||
4dc74376e5 | |||
849fa743ba | |||
01f77c6059 | |||
ac806a37f9 | |||
ba9ba69d1e |
|
@ -10,7 +10,8 @@ ANDROID_NDK_VERSION="${ANDROID_NDK_VERSION:2}"
|
||||||
# ANDROID_NDK_HOME must be exported for cargo-ndk
|
# ANDROID_NDK_HOME must be exported for cargo-ndk
|
||||||
export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/$ANDROID_NDK_VERSION"
|
export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/$ANDROID_NDK_VERSION"
|
||||||
|
|
||||||
ANDROID_API_LEVEL=34
|
# ANDROID_API_LEVEL must specify the _minimum_ supported SDK version, otherwise this will cause linking errors at launch
|
||||||
|
ANDROID_API_LEVEL=24
|
||||||
ANDROID_SUB_BUILD_DIR=build_arch
|
ANDROID_SUB_BUILD_DIR=build_arch
|
||||||
|
|
||||||
COLOR_RED="\e[1;31m"
|
COLOR_RED="\e[1;31m"
|
||||||
|
|
|
@ -1,15 +1,40 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:installLocation="auto">
|
||||||
|
|
||||||
<!-- Vulkan 1.1.0 is used if supported -->
|
<!-- Vulkan 1.1.0 is used if supported -->
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.vulkan.version"
|
android:name="android.hardware.vulkan.version"
|
||||||
android:required="false"
|
android:required="false"
|
||||||
android:version="0x00401000" />
|
android:version="0x00401000" />
|
||||||
<!-- android:glEsVersion is not specified as OpenGL ES 1.0 is supported as fallback -->
|
<!-- android:glEsVersion is not specified as OpenGL ES 1.0 is supported as fallback -->
|
||||||
|
|
||||||
|
<!-- Only playable in landscape mode -->
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.screen.landscape"
|
android:name="android.hardware.screen.landscape"
|
||||||
android:required="true" />
|
android:required="true" />
|
||||||
|
|
||||||
|
<!-- Touchscreen support -->
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.touchscreen"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
|
<!-- Game controller support -->
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.bluetooth"
|
||||||
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.gamepad"
|
||||||
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.usb.host"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
|
<!-- External mouse input events -->
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.type.pc"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
<!-- Teeworlds does broadcasts over local networks -->
|
<!-- Teeworlds does broadcasts over local networks -->
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
||||||
|
@ -25,17 +50,24 @@
|
||||||
android:isGame="true"
|
android:isGame="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||||
|
android:hardwareAccelerated="true">
|
||||||
<activity
|
<activity
|
||||||
android:name="org.ddnet.client.NativeMain"
|
android:name="org.ddnet.client.NativeMain"
|
||||||
|
android:alwaysRetainTaskState="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
|
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
|
||||||
|
android:preferMinimalPostProcessing="true"
|
||||||
android:screenOrientation="landscape"
|
android:screenOrientation="landscape"
|
||||||
android:launchMode="singleInstance">
|
android:launchMode="singleInstance">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<!-- Let Android know that we can handle some USB devices and should receive this event -->
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||||
|
</intent-filter>
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.app.lib_name"
|
android:name="android.app.lib_name"
|
||||||
android:value="DDNet" />
|
android:value="DDNet" />
|
||||||
|
|
|
@ -21,7 +21,7 @@ android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "org.ddnet.client"
|
applicationId "org.ddnet.client"
|
||||||
namespace("org.ddnet.client")
|
namespace("org.ddnet.client")
|
||||||
minSdkVersion 19
|
minSdkVersion 24
|
||||||
targetSdkVersion 34
|
targetSdkVersion 34
|
||||||
versionCode TW_VERSION_CODE
|
versionCode TW_VERSION_CODE
|
||||||
versionName "TW_VERSION_NAME"
|
versionName "TW_VERSION_NAME"
|
||||||
|
|
|
@ -29,6 +29,8 @@ function compile_source_android() {
|
||||||
-DCMAKE_SYSTEM_NAME=Android \
|
-DCMAKE_SYSTEM_NAME=Android \
|
||||||
-DCMAKE_SYSTEM_VERSION="$1" \
|
-DCMAKE_SYSTEM_VERSION="$1" \
|
||||||
-DCMAKE_ANDROID_ARCH_ABI="${3}" \
|
-DCMAKE_ANDROID_ARCH_ABI="${3}" \
|
||||||
|
-DCMAKE_C_FLAGS="$COMPILEFLAGS" -DCMAKE_CXX_FLAGS="$COMPILEFLAGS" -DCMAKE_CXX_FLAGS_RELEASE="$COMPILEFLAGS" -DCMAKE_C_FLAGS_RELEASE="$COMPILEFLAGS" \
|
||||||
|
-DCMAKE_SHARED_LINKER_FLAGS="$LINKFLAGS" -DCMAKE_SHARED_LINKER_FLAGS_RELEASE="$LINKFLAGS" \
|
||||||
-B"$2" \
|
-B"$2" \
|
||||||
-DBUILD_SHARED_LIBS=OFF \
|
-DBUILD_SHARED_LIBS=OFF \
|
||||||
-DHIDAPI_SKIP_LIBUSB=TRUE \
|
-DHIDAPI_SKIP_LIBUSB=TRUE \
|
||||||
|
|
|
@ -46,7 +46,8 @@ fi
|
||||||
mkdir -p "$1"
|
mkdir -p "$1"
|
||||||
cd "$1" || exit 1
|
cd "$1" || exit 1
|
||||||
|
|
||||||
_ANDROID_ABI_LEVEL=34
|
# ANDROID_API_LEVEL must specify the _minimum_ supported SDK version, otherwise this will cause linking errors at launch
|
||||||
|
ANDROID_API_LEVEL=24
|
||||||
|
|
||||||
function build_cmake_lib() {
|
function build_cmake_lib() {
|
||||||
if [ ! -d "${1}" ]; then
|
if [ ! -d "${1}" ]; then
|
||||||
|
@ -59,7 +60,7 @@ function build_cmake_lib() {
|
||||||
(
|
(
|
||||||
cd "${1}" || exit 1
|
cd "${1}" || exit 1
|
||||||
cp "${CURDIR}"/scripts/compile_libs/cmake_lib_compile.sh cmake_lib_compile.sh
|
cp "${CURDIR}"/scripts/compile_libs/cmake_lib_compile.sh cmake_lib_compile.sh
|
||||||
./cmake_lib_compile.sh "$_ANDROID_ABI_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS"
|
./cmake_lib_compile.sh "$ANDROID_API_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +75,7 @@ cd compile_libs || exit 1
|
||||||
(
|
(
|
||||||
cd openssl || exit 1
|
cd openssl || exit 1
|
||||||
cp "${CURDIR}"/scripts/compile_libs/make_lib_openssl.sh make_lib_openssl.sh
|
cp "${CURDIR}"/scripts/compile_libs/make_lib_openssl.sh make_lib_openssl.sh
|
||||||
./make_lib_openssl.sh "$_ANDROID_ABI_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS"
|
./make_lib_openssl.sh "$ANDROID_API_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -97,7 +98,7 @@ build_cmake_lib opus https://github.com/xiph/opus
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
fi
|
fi
|
||||||
cp "${CURDIR}"/scripts/compile_libs/make_lib_opusfile.sh make_lib_opusfile.sh
|
cp "${CURDIR}"/scripts/compile_libs/make_lib_opusfile.sh make_lib_opusfile.sh
|
||||||
./make_lib_opusfile.sh "$_ANDROID_ABI_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS"
|
./make_lib_opusfile.sh "$ANDROID_API_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS"
|
||||||
)
|
)
|
||||||
|
|
||||||
# SQLite, just download and built by hand
|
# SQLite, just download and built by hand
|
||||||
|
@ -109,7 +110,7 @@ fi
|
||||||
(
|
(
|
||||||
cd sqlite3 || exit 1
|
cd sqlite3 || exit 1
|
||||||
cp "${CURDIR}"/scripts/compile_libs/make_lib_sqlite3.sh make_lib_sqlite3.sh
|
cp "${CURDIR}"/scripts/compile_libs/make_lib_sqlite3.sh make_lib_sqlite3.sh
|
||||||
./make_lib_sqlite3.sh "$_ANDROID_ABI_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS"
|
./make_lib_sqlite3.sh "$ANDROID_API_LEVEL" "$OS_NAME" "$COMPILEFLAGS" "$LINKFLAGS"
|
||||||
)
|
)
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
|
|
|
@ -163,19 +163,19 @@
|
||||||
#define CONF_ARCH_ARM 1
|
#define CONF_ARCH_ARM 1
|
||||||
#define CONF_ARCH_STRING "arm"
|
#define CONF_ARCH_STRING "arm"
|
||||||
#define CONF_ARCH_ENDIAN_BIG 1
|
#define CONF_ARCH_ENDIAN_BIG 1
|
||||||
#endif
|
#elif defined(__ARMEL__)
|
||||||
|
|
||||||
#if defined(__ARMEL__)
|
|
||||||
#define CONF_ARCH_ARM 1
|
#define CONF_ARCH_ARM 1
|
||||||
#define CONF_ARCH_STRING "arm"
|
#define CONF_ARCH_STRING "arm"
|
||||||
#define CONF_ARCH_ENDIAN_LITTLE 1
|
#define CONF_ARCH_ENDIAN_LITTLE 1
|
||||||
#endif
|
#elif defined(__aarch64__) || defined(__arm64__) || defined(__ARM_ARCH_ISA_A64)
|
||||||
|
|
||||||
#if defined(__aarch64__) || defined(__arm64__) || defined(__ARM_ARCH)
|
|
||||||
#define CONF_ARCH_ARM64 1
|
#define CONF_ARCH_ARM64 1
|
||||||
#define CONF_ARCH_STRING "arm64"
|
#define CONF_ARCH_STRING "arm64"
|
||||||
|
#if defined(__ARM_BIG_ENDIAN)
|
||||||
|
#define CONF_ARCH_ENDIAN_BIG 1
|
||||||
|
#else
|
||||||
#define CONF_ARCH_ENDIAN_LITTLE 1
|
#define CONF_ARCH_ENDIAN_LITTLE 1
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CONF_FAMILY_STRING
|
#ifndef CONF_FAMILY_STRING
|
||||||
#define CONF_FAMILY_STRING "unknown"
|
#define CONF_FAMILY_STRING "unknown"
|
||||||
|
|
|
@ -1508,8 +1508,9 @@ protected:
|
||||||
vkInvalidateMappedMemoryRanges(m_VKDevice, 1, &MemRange);
|
vkInvalidateMappedMemoryRanges(m_VKDevice, 1, &MemRange);
|
||||||
|
|
||||||
size_t RealFullImageSize = maximum(ImageTotalSize, (size_t)(Height * m_GetPresentedImgDataHelperMappedLayoutPitch));
|
size_t RealFullImageSize = maximum(ImageTotalSize, (size_t)(Height * m_GetPresentedImgDataHelperMappedLayoutPitch));
|
||||||
if(vDstData.size() < RealFullImageSize)
|
size_t ExtraRowSize = Width * 4;
|
||||||
vDstData.resize(RealFullImageSize);
|
if(vDstData.size() < RealFullImageSize + ExtraRowSize)
|
||||||
|
vDstData.resize(RealFullImageSize + ExtraRowSize);
|
||||||
|
|
||||||
mem_copy(vDstData.data(), pResImageData, RealFullImageSize);
|
mem_copy(vDstData.data(), pResImageData, RealFullImageSize);
|
||||||
|
|
||||||
|
@ -1520,7 +1521,8 @@ protected:
|
||||||
{
|
{
|
||||||
size_t OffsetImagePacked = (Y * Width * 4);
|
size_t OffsetImagePacked = (Y * Width * 4);
|
||||||
size_t OffsetImageUnpacked = (Y * m_GetPresentedImgDataHelperMappedLayoutPitch);
|
size_t OffsetImageUnpacked = (Y * m_GetPresentedImgDataHelperMappedLayoutPitch);
|
||||||
mem_copy(vDstData.data() + OffsetImagePacked, vDstData.data() + OffsetImageUnpacked, Width * 4);
|
mem_copy(vDstData.data() + RealFullImageSize, vDstData.data() + OffsetImageUnpacked, Width * 4);
|
||||||
|
mem_copy(vDstData.data() + OffsetImagePacked, vDstData.data() + RealFullImageSize, Width * 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -668,10 +668,7 @@ void CClient::DisconnectWithReason(const char *pReason)
|
||||||
m_CurrentServerCurrentPingTime = -1;
|
m_CurrentServerCurrentPingTime = -1;
|
||||||
m_CurrentServerNextPingTime = -1;
|
m_CurrentServerNextPingTime = -1;
|
||||||
|
|
||||||
ResetMapDownload();
|
ResetMapDownload(true);
|
||||||
m_aMapdownloadFilename[0] = '\0';
|
|
||||||
m_aMapdownloadFilenameTemp[0] = '\0';
|
|
||||||
m_aMapdownloadName[0] = '\0';
|
|
||||||
|
|
||||||
// clear the current server info
|
// clear the current server info
|
||||||
mem_zero(&m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
|
mem_zero(&m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
|
||||||
|
@ -1019,11 +1016,11 @@ void CClient::Render()
|
||||||
GameClient()->OnRender();
|
GameClient()->OnRender();
|
||||||
DebugRender();
|
DebugRender();
|
||||||
|
|
||||||
if(State() == IClient::STATE_ONLINE && g_Config.m_ClAntiPingLimit)
|
// if(State() == IClient::STATE_ONLINE && g_Config.m_ClAntiPingLimit)
|
||||||
{
|
// {
|
||||||
int64_t Now = time_get();
|
// int64_t Now = time_get();
|
||||||
g_Config.m_ClAntiPing = (m_PredictedTime.Get(Now) - m_aGameTime[g_Config.m_ClDummy].Get(Now)) * 1000 / (float)time_freq() > g_Config.m_ClAntiPingLimit;
|
// g_Config.m_ClAntiPing = (m_PredictedTime.Get(Now) - m_aGameTime[g_Config.m_ClDummy].Get(Now)) * 1000 / (float)time_freq() > g_Config.m_ClAntiPingLimit;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CClient::LoadMap(const char *pName, const char *pFilename, SHA256_DIGEST *pWantedSha256, unsigned WantedCrc)
|
const char *CClient::LoadMap(const char *pName, const char *pFilename, SHA256_DIGEST *pWantedSha256, unsigned WantedCrc)
|
||||||
|
@ -1528,7 +1525,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
|
||||||
DummyDisconnect(0);
|
DummyDisconnect(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetMapDownload();
|
ResetMapDownload(true);
|
||||||
|
|
||||||
SHA256_DIGEST *pMapSha256 = nullptr;
|
SHA256_DIGEST *pMapSha256 = nullptr;
|
||||||
const char *pMapUrl = nullptr;
|
const char *pMapUrl = nullptr;
|
||||||
|
@ -2196,7 +2193,7 @@ int CClient::UnpackAndValidateSnapshot(CSnapshot *pFrom, CSnapshot *pTo)
|
||||||
return Builder.Finish(pTo);
|
return Builder.Finish(pTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::ResetMapDownload()
|
void CClient::ResetMapDownload(bool ResetActive)
|
||||||
{
|
{
|
||||||
if(m_pMapdownloadTask)
|
if(m_pMapdownloadTask)
|
||||||
{
|
{
|
||||||
|
@ -2215,19 +2212,24 @@ void CClient::ResetMapDownload()
|
||||||
Storage()->RemoveFile(m_aMapdownloadFilenameTemp, IStorage::TYPE_SAVE);
|
Storage()->RemoveFile(m_aMapdownloadFilenameTemp, IStorage::TYPE_SAVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ResetActive)
|
||||||
|
{
|
||||||
m_MapdownloadChunk = 0;
|
m_MapdownloadChunk = 0;
|
||||||
m_MapdownloadSha256Present = false;
|
m_MapdownloadSha256Present = false;
|
||||||
m_MapdownloadSha256 = SHA256_ZEROED;
|
m_MapdownloadSha256 = SHA256_ZEROED;
|
||||||
m_MapdownloadCrc = 0;
|
m_MapdownloadCrc = 0;
|
||||||
m_MapdownloadTotalsize = -1;
|
m_MapdownloadTotalsize = -1;
|
||||||
m_MapdownloadAmount = 0;
|
m_MapdownloadAmount = 0;
|
||||||
|
m_aMapdownloadFilename[0] = '\0';
|
||||||
|
m_aMapdownloadFilenameTemp[0] = '\0';
|
||||||
|
m_aMapdownloadName[0] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::FinishMapDownload()
|
void CClient::FinishMapDownload()
|
||||||
{
|
{
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "download complete, loading map");
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "download complete, loading map");
|
||||||
|
|
||||||
const int PrevMapdownloadTotalsize = m_MapdownloadTotalsize;
|
|
||||||
SHA256_DIGEST *pSha256 = m_MapdownloadSha256Present ? &m_MapdownloadSha256 : nullptr;
|
SHA256_DIGEST *pSha256 = m_MapdownloadSha256Present ? &m_MapdownloadSha256 : nullptr;
|
||||||
|
|
||||||
bool FileSuccess = true;
|
bool FileSuccess = true;
|
||||||
|
@ -2236,7 +2238,6 @@ void CClient::FinishMapDownload()
|
||||||
FileSuccess &= Storage()->RenameFile(m_aMapdownloadFilenameTemp, m_aMapdownloadFilename, IStorage::TYPE_SAVE);
|
FileSuccess &= Storage()->RenameFile(m_aMapdownloadFilenameTemp, m_aMapdownloadFilename, IStorage::TYPE_SAVE);
|
||||||
if(!FileSuccess)
|
if(!FileSuccess)
|
||||||
{
|
{
|
||||||
ResetMapDownload();
|
|
||||||
char aError[128 + IO_MAX_PATH_LENGTH];
|
char aError[128 + IO_MAX_PATH_LENGTH];
|
||||||
str_format(aError, sizeof(aError), Localize("Could not save downloaded map. Try manually deleting this file: %s"), m_aMapdownloadFilename);
|
str_format(aError, sizeof(aError), Localize("Could not save downloaded map. Try manually deleting this file: %s"), m_aMapdownloadFilename);
|
||||||
DisconnectWithReason(aError);
|
DisconnectWithReason(aError);
|
||||||
|
@ -2246,19 +2247,17 @@ void CClient::FinishMapDownload()
|
||||||
const char *pError = LoadMap(m_aMapdownloadName, m_aMapdownloadFilename, pSha256, m_MapdownloadCrc);
|
const char *pError = LoadMap(m_aMapdownloadName, m_aMapdownloadFilename, pSha256, m_MapdownloadCrc);
|
||||||
if(!pError)
|
if(!pError)
|
||||||
{
|
{
|
||||||
ResetMapDownload();
|
ResetMapDownload(true);
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done");
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done");
|
||||||
SendReady(CONN_MAIN);
|
SendReady(CONN_MAIN);
|
||||||
}
|
}
|
||||||
else if(m_pMapdownloadTask) // fallback
|
else if(m_pMapdownloadTask) // fallback
|
||||||
{
|
{
|
||||||
ResetMapDownload();
|
ResetMapDownload(false);
|
||||||
m_MapdownloadTotalsize = PrevMapdownloadTotalsize;
|
|
||||||
SendMapRequest();
|
SendMapRequest();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ResetMapDownload();
|
|
||||||
DisconnectWithReason(pError);
|
DisconnectWithReason(pError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2784,7 +2783,7 @@ void CClient::Update()
|
||||||
else if(m_pMapdownloadTask->State() == EHttpState::ERROR || m_pMapdownloadTask->State() == EHttpState::ABORTED)
|
else if(m_pMapdownloadTask->State() == EHttpState::ERROR || m_pMapdownloadTask->State() == EHttpState::ABORTED)
|
||||||
{
|
{
|
||||||
dbg_msg("webdl", "http failed, falling back to gameserver");
|
dbg_msg("webdl", "http failed, falling back to gameserver");
|
||||||
ResetMapDownload();
|
ResetMapDownload(false);
|
||||||
SendMapRequest();
|
SendMapRequest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2930,6 +2929,24 @@ void CClient::Run()
|
||||||
g_UuidManager.DebugDump();
|
g_UuidManager.DebugDump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONF_WEBASM
|
||||||
|
char aNetworkError[256];
|
||||||
|
if(!InitNetworkClient(aNetworkError, sizeof(aNetworkError)))
|
||||||
|
{
|
||||||
|
log_error("client", "%s", aNetworkError);
|
||||||
|
ShowMessageBox("Network Error", aNetworkError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!m_Http.Init(std::chrono::seconds{1}))
|
||||||
|
{
|
||||||
|
const char *pErrorMessage = "Failed to initialize the HTTP client.";
|
||||||
|
log_error("client", "%s", pErrorMessage);
|
||||||
|
ShowMessageBox("HTTP Error", pErrorMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// init graphics
|
// init graphics
|
||||||
m_pGraphics = CreateEngineGraphicsThreaded();
|
m_pGraphics = CreateEngineGraphicsThreaded();
|
||||||
Kernel()->RegisterInterface(m_pGraphics); // IEngineGraphics
|
Kernel()->RegisterInterface(m_pGraphics); // IEngineGraphics
|
||||||
|
@ -2953,24 +2970,6 @@ void CClient::Run()
|
||||||
CVideo::Init();
|
CVideo::Init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONF_WEBASM
|
|
||||||
char aNetworkError[256];
|
|
||||||
if(!InitNetworkClient(aNetworkError, sizeof(aNetworkError)))
|
|
||||||
{
|
|
||||||
log_error("client", "%s", aNetworkError);
|
|
||||||
ShowMessageBox("Network Error", aNetworkError);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(!m_Http.Init(std::chrono::seconds{1}))
|
|
||||||
{
|
|
||||||
const char *pErrorMessage = "Failed to initialize the HTTP client.";
|
|
||||||
log_error("client", "%s", pErrorMessage);
|
|
||||||
ShowMessageBox("HTTP Error", pErrorMessage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init text render
|
// init text render
|
||||||
m_pTextRender = Kernel()->RequestInterface<IEngineTextRender>();
|
m_pTextRender = Kernel()->RequestInterface<IEngineTextRender>();
|
||||||
m_pTextRender->Init();
|
m_pTextRender->Init();
|
||||||
|
|
|
@ -360,7 +360,7 @@ public:
|
||||||
|
|
||||||
int UnpackAndValidateSnapshot(CSnapshot *pFrom, CSnapshot *pTo);
|
int UnpackAndValidateSnapshot(CSnapshot *pFrom, CSnapshot *pTo);
|
||||||
|
|
||||||
void ResetMapDownload();
|
void ResetMapDownload(bool ResetActive);
|
||||||
void FinishMapDownload();
|
void FinishMapDownload();
|
||||||
|
|
||||||
void RequestDDNetInfo() override;
|
void RequestDDNetInfo() override;
|
||||||
|
|
|
@ -300,7 +300,7 @@ void CGraphics_Threaded::UnloadTexture(CTextureHandle *pIndex)
|
||||||
FreeTextureIndex(pIndex);
|
FreeTextureIndex(pIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage)
|
bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage)
|
||||||
{
|
{
|
||||||
if(SrcImage.m_Format == CImageInfo::FORMAT_RGBA)
|
if(SrcImage.m_Format == CImageInfo::FORMAT_RGBA)
|
||||||
{
|
{
|
||||||
|
|
|
@ -283,6 +283,7 @@ void CVideo::Pause(bool Pause)
|
||||||
void CVideo::Stop()
|
void CVideo::Stop()
|
||||||
{
|
{
|
||||||
dbg_assert(!m_Stopped, "Already stopped");
|
dbg_assert(!m_Stopped, "Already stopped");
|
||||||
|
m_Stopped = true;
|
||||||
|
|
||||||
m_pGraphics->WaitForIdle();
|
m_pGraphics->WaitForIdle();
|
||||||
|
|
||||||
|
@ -341,8 +342,6 @@ void CVideo::Stop()
|
||||||
pSound->PauseAudioDevice();
|
pSound->PauseAudioDevice();
|
||||||
delete ms_pCurrentVideo;
|
delete ms_pCurrentVideo;
|
||||||
pSound->UnpauseAudioDevice();
|
pSound->UnpauseAudioDevice();
|
||||||
|
|
||||||
m_Stopped = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVideo::NextVideoFrameThread()
|
void CVideo::NextVideoFrameThread()
|
||||||
|
|
|
@ -124,6 +124,8 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Structure: CVideoMode
|
Structure: CVideoMode
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
// client
|
// client
|
||||||
MACRO_CONFIG_INT(ClPredict, cl_predict, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict client movements")
|
MACRO_CONFIG_INT(ClPredict, cl_predict, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict client movements")
|
||||||
MACRO_CONFIG_INT(ClPredictDummy, cl_predict_dummy, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict dummy movements")
|
MACRO_CONFIG_INT(ClPredictDummy, cl_predict_dummy, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict dummy movements")
|
||||||
MACRO_CONFIG_INT(ClAntiPingLimit, cl_antiping_limit, 0, 0, 200, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Antiping limit (0 to disable)")
|
MACRO_CONFIG_INT(ClAntiPingLimit, cl_antiping_limit, 0, 0, 200, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Adds delay to antiping (0 to disable)")
|
||||||
|
MACRO_CONFIG_INT(ClAntiPingpercent, cl_antiping_percent, 100, 0, 100, CFGFLAG_CLIENT | CFGFLAG_SAVE, "how far ahead Antiping predicts, ignored when antiping limit is used")
|
||||||
MACRO_CONFIG_INT(ClAntiPing, cl_antiping, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Enable antiping, i. e. more aggressive prediction.")
|
MACRO_CONFIG_INT(ClAntiPing, cl_antiping, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Enable antiping, i. e. more aggressive prediction.")
|
||||||
MACRO_CONFIG_INT(ClAntiPingPlayers, cl_antiping_players, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict other player's movement more aggressively (only enabled if cl_antiping is set to 1)")
|
MACRO_CONFIG_INT(ClAntiPingPlayers, cl_antiping_players, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict other player's movement more aggressively (only enabled if cl_antiping is set to 1)")
|
||||||
MACRO_CONFIG_INT(ClAntiPingGrenade, cl_antiping_grenade, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict grenades (only enabled if cl_antiping is set to 1)")
|
MACRO_CONFIG_INT(ClAntiPingGrenade, cl_antiping_grenade, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict grenades (only enabled if cl_antiping is set to 1)")
|
||||||
|
|
|
@ -341,7 +341,7 @@ void CConsole::Print(int Level, const char *pFrom, const char *pStr, ColorRGBA P
|
||||||
{
|
{
|
||||||
LEVEL LogLevel = IConsole::ToLogLevel(Level);
|
LEVEL LogLevel = IConsole::ToLogLevel(Level);
|
||||||
// if console colors are not enabled or if the color is pure white, use default terminal color
|
// if console colors are not enabled or if the color is pure white, use default terminal color
|
||||||
if(g_Config.m_ConsoleEnableColors && mem_comp(&PrintColor, &gs_ConsoleDefaultColor, sizeof(ColorRGBA)) != 0)
|
if(g_Config.m_ConsoleEnableColors && PrintColor != gs_ConsoleDefaultColor)
|
||||||
{
|
{
|
||||||
log_log_color(LogLevel, ColorToLogColor(PrintColor), pFrom, "%s", pStr);
|
log_log_color(LogLevel, ColorToLogColor(PrintColor), pFrom, "%s", pStr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,18 +70,18 @@ void CEcon::Init(CConfig *pConfig, IConsole *pConsole, CNetBan *pNetBan)
|
||||||
}
|
}
|
||||||
|
|
||||||
NETADDR BindAddr;
|
NETADDR BindAddr;
|
||||||
if(g_Config.m_EcBindaddr[0] == '\0')
|
if(g_Config.m_EcBindaddr[0] && net_host_lookup(g_Config.m_EcBindaddr, &BindAddr, NETTYPE_ALL) == 0)
|
||||||
{
|
{
|
||||||
mem_zero(&BindAddr, sizeof(BindAddr));
|
// got bindaddr
|
||||||
|
BindAddr.port = g_Config.m_EcPort;
|
||||||
}
|
}
|
||||||
else if(net_host_lookup(g_Config.m_EcBindaddr, &BindAddr, NETTYPE_ALL) != 0)
|
else
|
||||||
{
|
{
|
||||||
char aBuf[256];
|
char aBuf[256];
|
||||||
str_format(aBuf, sizeof(aBuf), "The configured bindaddr '%s' cannot be resolved.", g_Config.m_Bindaddr);
|
str_format(aBuf, sizeof(aBuf), "The configured bindaddr '%s' cannot be resolved.", g_Config.m_EcBindaddr);
|
||||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "econ", aBuf);
|
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "econ", aBuf);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
BindAddr.type = NETTYPE_ALL;
|
|
||||||
BindAddr.port = g_Config.m_EcPort;
|
|
||||||
|
|
||||||
if(m_NetConsole.Open(BindAddr, pNetBan))
|
if(m_NetConsole.Open(BindAddr, pNetBan))
|
||||||
{
|
{
|
||||||
|
|
|
@ -93,6 +93,7 @@ MAYBE_UNUSED static const char *FONT_ICON_EARTH_AMERICAS = "\xEF\x95\xBD";
|
||||||
MAYBE_UNUSED static const char *FONT_ICON_NETWORK_WIRED = "\xEF\x9B\xBF";
|
MAYBE_UNUSED static const char *FONT_ICON_NETWORK_WIRED = "\xEF\x9B\xBF";
|
||||||
MAYBE_UNUSED static const char *FONT_ICON_LIST_UL = "\xEF\x83\x8A";
|
MAYBE_UNUSED static const char *FONT_ICON_LIST_UL = "\xEF\x83\x8A";
|
||||||
MAYBE_UNUSED static const char *FONT_ICON_INFO = "\xEF\x84\xA9";
|
MAYBE_UNUSED static const char *FONT_ICON_INFO = "\xEF\x84\xA9";
|
||||||
|
MAYBE_UNUSED static const char *FONT_ICON_TERMINAL = "\xEF\x84\xA0";
|
||||||
|
|
||||||
MAYBE_UNUSED static const char *FONT_ICON_SLASH = "\xEF\x9C\x95";
|
MAYBE_UNUSED static const char *FONT_ICON_SLASH = "\xEF\x9C\x95";
|
||||||
MAYBE_UNUSED static const char *FONT_ICON_PLAY = "\xEF\x81\x8B";
|
MAYBE_UNUSED static const char *FONT_ICON_PLAY = "\xEF\x81\x8B";
|
||||||
|
|
|
@ -160,8 +160,6 @@ class CGameConsole : public CComponent
|
||||||
static const ColorRGBA ms_SearchHighlightColor;
|
static const ColorRGBA ms_SearchHighlightColor;
|
||||||
static const ColorRGBA ms_SearchSelectedColor;
|
static const ColorRGBA ms_SearchSelectedColor;
|
||||||
|
|
||||||
void Toggle(int Type);
|
|
||||||
|
|
||||||
static void PossibleCommandsRenderCallback(int Index, const char *pStr, void *pUser);
|
static void PossibleCommandsRenderCallback(int Index, const char *pStr, void *pUser);
|
||||||
static void ConToggleLocalConsole(IConsole::IResult *pResult, void *pUserData);
|
static void ConToggleLocalConsole(IConsole::IResult *pResult, void *pUserData);
|
||||||
static void ConToggleRemoteConsole(IConsole::IResult *pResult, void *pUserData);
|
static void ConToggleRemoteConsole(IConsole::IResult *pResult, void *pUserData);
|
||||||
|
@ -196,6 +194,7 @@ public:
|
||||||
virtual bool OnInput(const IInput::CEvent &Event) override;
|
virtual bool OnInput(const IInput::CEvent &Event) override;
|
||||||
void Prompt(char (&aPrompt)[32]);
|
void Prompt(char (&aPrompt)[32]);
|
||||||
|
|
||||||
|
void Toggle(int Type);
|
||||||
bool IsClosed() { return m_ConsoleState == CONSOLE_CLOSED; }
|
bool IsClosed() { return m_ConsoleState == CONSOLE_CLOSED; }
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -58,9 +58,11 @@ void CItems::RenderProjectile(const CProjectileData *pCurrent, int ItemId)
|
||||||
|
|
||||||
bool IsOtherTeam = (pCurrent->m_ExtraInfo && pCurrent->m_Owner >= 0 && m_pClient->IsOtherTeam(pCurrent->m_Owner));
|
bool IsOtherTeam = (pCurrent->m_ExtraInfo && pCurrent->m_Owner >= 0 && m_pClient->IsOtherTeam(pCurrent->m_Owner));
|
||||||
|
|
||||||
|
int predictTick = GameClient()->GetPredictionTick();
|
||||||
|
|
||||||
float Ct;
|
float Ct;
|
||||||
if(m_pClient->Predict() && m_pClient->AntiPingGrenade() && LocalPlayerInGame && !IsOtherTeam)
|
if(m_pClient->Predict() && m_pClient->AntiPingGrenade() && LocalPlayerInGame && !IsOtherTeam)
|
||||||
Ct = ((float)(Client()->PredGameTick(g_Config.m_ClDummy) - 1 - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy)) / (float)Client()->GameTickSpeed();
|
Ct = ((float)(predictTick - 1 - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy)) / (float)Client()->GameTickSpeed();
|
||||||
else
|
else
|
||||||
Ct = (Client()->PrevGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) / (float)Client()->GameTickSpeed() + s_LastGameTickTime;
|
Ct = (Client()->PrevGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) / (float)Client()->GameTickSpeed() + s_LastGameTickTime;
|
||||||
if(Ct < 0)
|
if(Ct < 0)
|
||||||
|
@ -304,9 +306,11 @@ void CItems::RenderLaser(const CLaserData *pCurrent, bool IsPredicted)
|
||||||
{
|
{
|
||||||
Dir = normalize_pre_length(Pos - From, Len);
|
Dir = normalize_pre_length(Pos - From, Len);
|
||||||
|
|
||||||
|
int predictTick = GameClient()->GetPredictionTick();
|
||||||
|
|
||||||
float Ticks;
|
float Ticks;
|
||||||
if(IsPredicted)
|
if(IsPredicted)
|
||||||
Ticks = (float)(Client()->PredGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy);
|
Ticks = (float)(predictTick - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy);
|
||||||
else
|
else
|
||||||
Ticks = (float)(Client()->GameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->IntraGameTick(g_Config.m_ClDummy);
|
Ticks = (float)(Client()->GameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->IntraGameTick(g_Config.m_ClDummy);
|
||||||
float Ms = (Ticks / Client()->GameTickSpeed()) * 1000.0f;
|
float Ms = (Ticks / Client()->GameTickSpeed()) * 1000.0f;
|
||||||
|
@ -377,7 +381,7 @@ void CItems::OnRender()
|
||||||
auto &aSwitchers = GameClient()->Switchers();
|
auto &aSwitchers = GameClient()->Switchers();
|
||||||
if(UsePredicted)
|
if(UsePredicted)
|
||||||
{
|
{
|
||||||
for(auto *pProj = (CProjectile *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PROJECTILE); pProj; pProj = (CProjectile *)pProj->NextEntity())
|
for(auto *pProj = (CProjectile *)GameClient()->m_PrevPredictedWorld.FindFirst(CGameWorld::ENTTYPE_PROJECTILE); pProj; pProj = (CProjectile *)pProj->NextEntity())
|
||||||
{
|
{
|
||||||
if(!IsSuper && pProj->m_Number > 0 && pProj->m_Number < (int)aSwitchers.size() && !aSwitchers[pProj->m_Number].m_aStatus[SwitcherTeam] && (pProj->m_Explosive ? BlinkingProjEx : BlinkingProj))
|
if(!IsSuper && pProj->m_Number > 0 && pProj->m_Number < (int)aSwitchers.size() && !aSwitchers[pProj->m_Number].m_aStatus[SwitcherTeam] && (pProj->m_Explosive ? BlinkingProjEx : BlinkingProj))
|
||||||
continue;
|
continue;
|
||||||
|
@ -385,7 +389,7 @@ void CItems::OnRender()
|
||||||
CProjectileData Data = pProj->GetData();
|
CProjectileData Data = pProj->GetData();
|
||||||
RenderProjectile(&Data, pProj->GetId());
|
RenderProjectile(&Data, pProj->GetId());
|
||||||
}
|
}
|
||||||
for(CEntity *pEnt = GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_LASER); pEnt; pEnt = pEnt->NextEntity())
|
for(CEntity *pEnt = GameClient()->m_PrevPredictedWorld.FindFirst(CGameWorld::ENTTYPE_LASER); pEnt; pEnt = pEnt->NextEntity())
|
||||||
{
|
{
|
||||||
auto *const pLaser = dynamic_cast<CLaser *>(pEnt);
|
auto *const pLaser = dynamic_cast<CLaser *>(pEnt);
|
||||||
if(!pLaser || pLaser->GetOwner() < 0 || !GameClient()->m_aClients[pLaser->GetOwner()].m_IsPredictedLocal)
|
if(!pLaser || pLaser->GetOwner() < 0 || !GameClient()->m_aClients[pLaser->GetOwner()].m_IsPredictedLocal)
|
||||||
|
@ -393,7 +397,7 @@ void CItems::OnRender()
|
||||||
CLaserData Data = pLaser->GetData();
|
CLaserData Data = pLaser->GetData();
|
||||||
RenderLaser(&Data, true);
|
RenderLaser(&Data, true);
|
||||||
}
|
}
|
||||||
for(auto *pPickup = (CPickup *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PICKUP); pPickup; pPickup = (CPickup *)pPickup->NextEntity())
|
for(auto *pPickup = (CPickup *)GameClient()->m_PrevPredictedWorld.FindFirst(CGameWorld::ENTTYPE_PICKUP); pPickup; pPickup = (CPickup *)pPickup->NextEntity())
|
||||||
{
|
{
|
||||||
if(!IsSuper && pPickup->m_Layer == LAYER_SWITCH && pPickup->m_Number > 0 && pPickup->m_Number < (int)aSwitchers.size() && !aSwitchers[pPickup->m_Number].m_aStatus[SwitcherTeam] && BlinkingPickup)
|
if(!IsSuper && pPickup->m_Layer == LAYER_SWITCH && pPickup->m_Number > 0 && pPickup->m_Number < (int)aSwitchers.size() && !aSwitchers[pPickup->m_Number].m_aStatus[SwitcherTeam] && BlinkingPickup)
|
||||||
continue;
|
continue;
|
||||||
|
@ -601,7 +605,10 @@ void CItems::ReconstructSmokeTrail(const CProjectileData *pCurrent, int DestroyT
|
||||||
LocalPlayerInGame = m_pClient->m_aClients[m_pClient->m_Snap.m_pLocalInfo->m_ClientId].m_Team != TEAM_SPECTATORS;
|
LocalPlayerInGame = m_pClient->m_aClients[m_pClient->m_Snap.m_pLocalInfo->m_ClientId].m_Team != TEAM_SPECTATORS;
|
||||||
if(!m_pClient->AntiPingGunfire() || !LocalPlayerInGame)
|
if(!m_pClient->AntiPingGunfire() || !LocalPlayerInGame)
|
||||||
return;
|
return;
|
||||||
if(Client()->PredGameTick(g_Config.m_ClDummy) == pCurrent->m_StartTick)
|
|
||||||
|
int predictTick = GameClient()->GetPredictionTick();
|
||||||
|
|
||||||
|
if(predictTick == pCurrent->m_StartTick)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// get positions
|
// get positions
|
||||||
|
@ -625,7 +632,7 @@ void CItems::ReconstructSmokeTrail(const CProjectileData *pCurrent, int DestroyT
|
||||||
Speed = pTuning->m_GunSpeed;
|
Speed = pTuning->m_GunSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Pt = ((float)(Client()->PredGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy)) / (float)Client()->GameTickSpeed();
|
float Pt = ((float)(predictTick - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy)) / (float)Client()->GameTickSpeed();
|
||||||
if(Pt < 0)
|
if(Pt < 0)
|
||||||
return; // projectile haven't been shot yet
|
return; // projectile haven't been shot yet
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include "menus.h"
|
#include "menus.h"
|
||||||
|
|
||||||
|
using namespace FontIcons;
|
||||||
|
|
||||||
void CMenus::RenderStartMenu(CUIRect MainView)
|
void CMenus::RenderStartMenu(CUIRect MainView)
|
||||||
{
|
{
|
||||||
GameClient()->m_MenuBackground.ChangePosition(CMenuBackground::POS_START);
|
GameClient()->m_MenuBackground.ChangePosition(CMenuBackground::POS_START);
|
||||||
|
@ -186,13 +188,27 @@ void CMenus::RenderStartMenu(CUIRect MainView)
|
||||||
}
|
}
|
||||||
|
|
||||||
// render version
|
// render version
|
||||||
CUIRect VersionUpdate, CurVersion;
|
CUIRect CurVersion, ConsoleButton;
|
||||||
MainView.HSplitBottom(20.0f, nullptr, &VersionUpdate);
|
MainView.HSplitBottom(45.0f, nullptr, &CurVersion);
|
||||||
VersionUpdate.VSplitRight(50.0f, &CurVersion, nullptr);
|
CurVersion.VSplitRight(40.0f, &CurVersion, nullptr);
|
||||||
VersionUpdate.VMargin(VMargin, &VersionUpdate);
|
CurVersion.HSplitTop(20.0f, &ConsoleButton, &CurVersion);
|
||||||
|
CurVersion.HSplitTop(5.0f, nullptr, &CurVersion);
|
||||||
|
ConsoleButton.VSplitRight(40.0f, nullptr, &ConsoleButton);
|
||||||
Ui()->DoLabel(&CurVersion, GAME_RELEASE_VERSION, 14.0f, TEXTALIGN_MR);
|
Ui()->DoLabel(&CurVersion, GAME_RELEASE_VERSION, 14.0f, TEXTALIGN_MR);
|
||||||
|
|
||||||
|
static CButtonContainer s_ConsoleButton;
|
||||||
|
TextRender()->SetFontPreset(EFontPreset::ICON_FONT);
|
||||||
|
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
|
||||||
|
if(DoButton_Menu(&s_ConsoleButton, FONT_ICON_TERMINAL, 0, &ConsoleButton, nullptr, IGraphics::CORNER_ALL, 5.0f, 0.0f, ColorRGBA(0.0f, 0.0f, 0.0f, 0.1f)))
|
||||||
|
{
|
||||||
|
GameClient()->m_GameConsole.Toggle(CGameConsole::CONSOLETYPE_LOCAL);
|
||||||
|
}
|
||||||
|
TextRender()->SetRenderFlags(0);
|
||||||
|
TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT);
|
||||||
|
|
||||||
|
CUIRect VersionUpdate;
|
||||||
|
MainView.HSplitBottom(20.0f, nullptr, &VersionUpdate);
|
||||||
|
VersionUpdate.VMargin(VMargin, &VersionUpdate);
|
||||||
#if defined(CONF_AUTOUPDATE)
|
#if defined(CONF_AUTOUPDATE)
|
||||||
CUIRect UpdateButton;
|
CUIRect UpdateButton;
|
||||||
VersionUpdate.VSplitRight(100.0f, &VersionUpdate, &UpdateButton);
|
VersionUpdate.VSplitRight(100.0f, &VersionUpdate, &UpdateButton);
|
||||||
|
|
|
@ -2100,6 +2100,25 @@ void CGameClient::UpdateEditorIngameMoved()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CGameClient::GetPredictionTick()
|
||||||
|
{
|
||||||
|
int predictTick = Client()->GetPredictionTime() * Client()->GameTickSpeed() / 1000.0f;
|
||||||
|
|
||||||
|
float predictPercentage = 1 - g_Config.m_ClAntiPingpercent / 100.0f;
|
||||||
|
int predictMin = std::floor(predictTick * predictPercentage);
|
||||||
|
int predictMin2 = g_Config.m_ClAntiPingLimit * Client()->GameTickSpeed() / 1000.0f;
|
||||||
|
if (g_Config.m_ClAntiPingLimit != 0)
|
||||||
|
predictMin = predictMin2;
|
||||||
|
|
||||||
|
predictTick = Client()->PredGameTick(g_Config.m_ClDummy) - predictMin;
|
||||||
|
|
||||||
|
if(predictTick < Client()->GameTick(g_Config.m_ClDummy) + 1)
|
||||||
|
{
|
||||||
|
predictTick = Client()->GameTick(g_Config.m_ClDummy) + 1;
|
||||||
|
}
|
||||||
|
return predictTick;
|
||||||
|
}
|
||||||
|
|
||||||
void CGameClient::OnPredict()
|
void CGameClient::OnPredict()
|
||||||
{
|
{
|
||||||
// store the previous values so we can detect prediction errors
|
// store the previous values so we can detect prediction errors
|
||||||
|
@ -2157,19 +2176,32 @@ void CGameClient::OnPredict()
|
||||||
if(PredictDummy())
|
if(PredictDummy())
|
||||||
pDummyChar = m_PredictedWorld.GetCharacterById(m_PredictedDummyId);
|
pDummyChar = m_PredictedWorld.GetCharacterById(m_PredictedDummyId);
|
||||||
|
|
||||||
|
int predictTick = GetPredictionTick();
|
||||||
// predict
|
// predict
|
||||||
for(int Tick = Client()->GameTick(g_Config.m_ClDummy) + 1; Tick <= Client()->PredGameTick(g_Config.m_ClDummy); Tick++)
|
for(int Tick = Client()->GameTick(g_Config.m_ClDummy) + 1; Tick <= Client()->PredGameTick(g_Config.m_ClDummy); Tick++)
|
||||||
{
|
{
|
||||||
// fetch the previous characters
|
// fetch the previous characters
|
||||||
if(Tick == Client()->PredGameTick(g_Config.m_ClDummy))
|
if(Tick == predictTick)
|
||||||
{
|
{
|
||||||
m_PrevPredictedWorld.CopyWorld(&m_PredictedWorld);
|
|
||||||
m_PredictedPrevChar = pLocalChar->GetCore();
|
|
||||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||||
if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i))
|
if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i))
|
||||||
m_aClients[i].m_PrevPredicted = pChar->GetCore();
|
m_aClients[i].m_PrevPredicted = pChar->GetCore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Tick == Client()->PredGameTick(g_Config.m_ClDummy))
|
||||||
|
{
|
||||||
|
m_PredictedPrevChar = pLocalChar->GetCore();
|
||||||
|
m_aClients[m_Snap.m_LocalClientId].m_PrevPredicted = pLocalChar->GetCore();
|
||||||
|
|
||||||
|
if(pDummyChar)
|
||||||
|
m_aClients[m_PredictedDummyId].m_PrevPredicted = pDummyChar->GetCore();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Tick == predictTick)
|
||||||
|
{
|
||||||
|
m_PrevPredictedWorld.CopyWorld(&m_PredictedWorld);
|
||||||
|
}
|
||||||
|
|
||||||
// optionally allow some movement in freeze by not predicting freeze the last one to two ticks
|
// optionally allow some movement in freeze by not predicting freeze the last one to two ticks
|
||||||
if(g_Config.m_ClPredictFreeze == 2 && Client()->PredGameTick(g_Config.m_ClDummy) - 1 - Client()->PredGameTick(g_Config.m_ClDummy) % 2 <= Tick)
|
if(g_Config.m_ClPredictFreeze == 2 && Client()->PredGameTick(g_Config.m_ClDummy) - 1 - Client()->PredGameTick(g_Config.m_ClDummy) % 2 <= Tick)
|
||||||
pLocalChar->m_CanMoveInFreeze = true;
|
pLocalChar->m_CanMoveInFreeze = true;
|
||||||
|
@ -2193,14 +2225,22 @@ void CGameClient::OnPredict()
|
||||||
m_PredictedWorld.Tick();
|
m_PredictedWorld.Tick();
|
||||||
|
|
||||||
// fetch the current characters
|
// fetch the current characters
|
||||||
if(Tick == Client()->PredGameTick(g_Config.m_ClDummy))
|
if(Tick == predictTick)
|
||||||
{
|
{
|
||||||
m_PredictedChar = pLocalChar->GetCore();
|
|
||||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||||
if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i))
|
if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i))
|
||||||
m_aClients[i].m_Predicted = pChar->GetCore();
|
m_aClients[i].m_Predicted = pChar->GetCore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Tick == Client()->PredGameTick(g_Config.m_ClDummy))
|
||||||
|
{
|
||||||
|
m_PredictedChar = pLocalChar->GetCore();
|
||||||
|
m_aClients[m_Snap.m_LocalClientId].m_Predicted = pLocalChar->GetCore();
|
||||||
|
|
||||||
|
if(pDummyChar)
|
||||||
|
m_aClients[m_PredictedDummyId].m_Predicted = pDummyChar->GetCore();
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||||
if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i))
|
if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i))
|
||||||
{
|
{
|
||||||
|
|
|
@ -499,6 +499,7 @@ public:
|
||||||
CRenderTools m_RenderTools;
|
CRenderTools m_RenderTools;
|
||||||
|
|
||||||
void OnReset();
|
void OnReset();
|
||||||
|
int GetPredictionTick();
|
||||||
|
|
||||||
size_t ComponentCount() { return m_vpAll.size(); }
|
size_t ComponentCount() { return m_vpAll.size(); }
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ void CUIElement::SUIElementRect::Reset()
|
||||||
void CUIElement::SUIElementRect::Draw(const CUIRect *pRect, ColorRGBA Color, int Corners, float Rounding)
|
void CUIElement::SUIElementRect::Draw(const CUIRect *pRect, ColorRGBA Color, int Corners, float Rounding)
|
||||||
{
|
{
|
||||||
bool NeedsRecreate = false;
|
bool NeedsRecreate = false;
|
||||||
if(m_UIRectQuadContainer == -1 || m_Width != pRect->w || m_Height != pRect->h || mem_comp(&m_QuadColor, &Color, sizeof(Color)) != 0)
|
if(m_UIRectQuadContainer == -1 || m_Width != pRect->w || m_Height != pRect->h || m_QuadColor != Color)
|
||||||
{
|
{
|
||||||
m_pParent->Ui()->Graphics()->DeleteQuadContainer(m_UIRectQuadContainer);
|
m_pParent->Ui()->Graphics()->DeleteQuadContainer(m_UIRectQuadContainer);
|
||||||
NeedsRecreate = true;
|
NeedsRecreate = true;
|
||||||
|
|
|
@ -4384,7 +4384,7 @@ bool CEditor::ReplaceImage(const char *pFileName, int StorageType, bool CheckDup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CEditorImage ImgInfo(this);
|
CImageInfo ImgInfo;
|
||||||
if(!Graphics()->LoadPng(ImgInfo, pFileName, StorageType))
|
if(!Graphics()->LoadPng(ImgInfo, pFileName, StorageType))
|
||||||
{
|
{
|
||||||
ShowFileDialogError("Failed to load image from file '%s'.", pFileName);
|
ShowFileDialogError("Failed to load image from file '%s'.", pFileName);
|
||||||
|
@ -4394,21 +4394,33 @@ bool CEditor::ReplaceImage(const char *pFileName, int StorageType, bool CheckDup
|
||||||
std::shared_ptr<CEditorImage> pImg = m_Map.m_vpImages[m_SelectedImage];
|
std::shared_ptr<CEditorImage> pImg = m_Map.m_vpImages[m_SelectedImage];
|
||||||
Graphics()->UnloadTexture(&(pImg->m_Texture));
|
Graphics()->UnloadTexture(&(pImg->m_Texture));
|
||||||
pImg->Free();
|
pImg->Free();
|
||||||
*pImg = ImgInfo;
|
pImg->m_Width = ImgInfo.m_Width;
|
||||||
|
pImg->m_Height = ImgInfo.m_Height;
|
||||||
|
pImg->m_Format = ImgInfo.m_Format;
|
||||||
|
pImg->m_pData = ImgInfo.m_pData;
|
||||||
str_copy(pImg->m_aName, aBuf);
|
str_copy(pImg->m_aName, aBuf);
|
||||||
pImg->m_External = IsVanillaImage(pImg->m_aName);
|
pImg->m_External = IsVanillaImage(pImg->m_aName);
|
||||||
|
|
||||||
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1 && pImg->m_Format == CImageInfo::FORMAT_RGBA)
|
if(!pImg->m_External && pImg->m_Format != CImageInfo::FORMAT_RGBA)
|
||||||
{
|
{
|
||||||
DilateImage(ImgInfo.m_pData, ImgInfo.m_Width, ImgInfo.m_Height);
|
uint8_t *pRgbaData = static_cast<uint8_t *>(malloc((size_t)pImg->m_Width * pImg->m_Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA)));
|
||||||
|
ConvertToRGBA(pRgbaData, *pImg);
|
||||||
|
free(pImg->m_pData);
|
||||||
|
pImg->m_pData = pRgbaData;
|
||||||
|
pImg->m_Format = CImageInfo::FORMAT_RGBA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1)
|
||||||
|
{
|
||||||
|
DilateImage(pImg->m_pData, pImg->m_Width, pImg->m_Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
pImg->m_AutoMapper.Load(pImg->m_aName);
|
pImg->m_AutoMapper.Load(pImg->m_aName);
|
||||||
int TextureLoadFlag = Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
int TextureLoadFlag = Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
||||||
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0)
|
if(pImg->m_Width % 16 != 0 || pImg->m_Height % 16 != 0)
|
||||||
TextureLoadFlag = 0;
|
TextureLoadFlag = 0;
|
||||||
pImg->m_Texture = Graphics()->LoadTextureRaw(ImgInfo, TextureLoadFlag, pFileName);
|
pImg->m_Texture = Graphics()->LoadTextureRaw(*pImg, TextureLoadFlag, pFileName);
|
||||||
ImgInfo.m_pData = nullptr;
|
|
||||||
SortImages();
|
SortImages();
|
||||||
for(size_t i = 0; i < m_Map.m_vpImages.size(); ++i)
|
for(size_t i = 0; i < m_Map.m_vpImages.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -4447,7 +4459,7 @@ bool CEditor::AddImage(const char *pFileName, int StorageType, void *pUser)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CEditorImage ImgInfo(pEditor);
|
CImageInfo ImgInfo;
|
||||||
if(!pEditor->Graphics()->LoadPng(ImgInfo, pFileName, StorageType))
|
if(!pEditor->Graphics()->LoadPng(ImgInfo, pFileName, StorageType))
|
||||||
{
|
{
|
||||||
pEditor->ShowFileDialogError("Failed to load image from file '%s'.", pFileName);
|
pEditor->ShowFileDialogError("Failed to load image from file '%s'.", pFileName);
|
||||||
|
@ -4455,19 +4467,30 @@ bool CEditor::AddImage(const char *pFileName, int StorageType, void *pUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<CEditorImage> pImg = std::make_shared<CEditorImage>(pEditor);
|
std::shared_ptr<CEditorImage> pImg = std::make_shared<CEditorImage>(pEditor);
|
||||||
*pImg = ImgInfo;
|
pImg->m_Width = ImgInfo.m_Width;
|
||||||
|
pImg->m_Height = ImgInfo.m_Height;
|
||||||
|
pImg->m_Format = ImgInfo.m_Format;
|
||||||
|
pImg->m_pData = ImgInfo.m_pData;
|
||||||
pImg->m_External = IsVanillaImage(aBuf);
|
pImg->m_External = IsVanillaImage(aBuf);
|
||||||
|
|
||||||
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1 && pImg->m_Format == CImageInfo::FORMAT_RGBA)
|
if(pImg->m_Format != CImageInfo::FORMAT_RGBA)
|
||||||
{
|
{
|
||||||
DilateImage(ImgInfo.m_pData, ImgInfo.m_Width, ImgInfo.m_Height);
|
uint8_t *pRgbaData = static_cast<uint8_t *>(malloc((size_t)pImg->m_Width * pImg->m_Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA)));
|
||||||
|
ConvertToRGBA(pRgbaData, *pImg);
|
||||||
|
free(pImg->m_pData);
|
||||||
|
pImg->m_pData = pRgbaData;
|
||||||
|
pImg->m_Format = CImageInfo::FORMAT_RGBA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1)
|
||||||
|
{
|
||||||
|
DilateImage(pImg->m_pData, pImg->m_Width, pImg->m_Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextureLoadFlag = pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
int TextureLoadFlag = pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
||||||
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0)
|
if(pImg->m_Width % 16 != 0 || pImg->m_Height % 16 != 0)
|
||||||
TextureLoadFlag = 0;
|
TextureLoadFlag = 0;
|
||||||
pImg->m_Texture = pEditor->Graphics()->LoadTextureRaw(ImgInfo, TextureLoadFlag, pFileName);
|
pImg->m_Texture = pEditor->Graphics()->LoadTextureRaw(*pImg, TextureLoadFlag, pFileName);
|
||||||
ImgInfo.m_pData = nullptr;
|
|
||||||
str_copy(pImg->m_aName, aBuf);
|
str_copy(pImg->m_aName, aBuf);
|
||||||
pImg->m_AutoMapper.Load(pImg->m_aName);
|
pImg->m_AutoMapper.Load(pImg->m_aName);
|
||||||
pEditor->m_Map.m_vpImages.push_back(pImg);
|
pEditor->m_Map.m_vpImages.push_back(pImg);
|
||||||
|
|
|
@ -509,6 +509,15 @@ bool CEditorMap::Load(const char *pFileName, int StorageType, const std::functio
|
||||||
pImg->m_Height = ImgInfo.m_Height;
|
pImg->m_Height = ImgInfo.m_Height;
|
||||||
pImg->m_Format = ImgInfo.m_Format;
|
pImg->m_Format = ImgInfo.m_Format;
|
||||||
pImg->m_pData = ImgInfo.m_pData;
|
pImg->m_pData = ImgInfo.m_pData;
|
||||||
|
if(pImg->m_Format != CImageInfo::FORMAT_RGBA)
|
||||||
|
{
|
||||||
|
uint8_t *pRgbaData = static_cast<uint8_t *>(malloc((size_t)pImg->m_Width * pImg->m_Height * CImageInfo::PixelSize(CImageInfo::FORMAT_RGBA)));
|
||||||
|
ConvertToRGBA(pRgbaData, *pImg);
|
||||||
|
free(pImg->m_pData);
|
||||||
|
pImg->m_pData = pRgbaData;
|
||||||
|
pImg->m_Format = CImageInfo::FORMAT_RGBA;
|
||||||
|
}
|
||||||
|
|
||||||
int TextureLoadFlag = m_pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
int TextureLoadFlag = m_pEditor->Graphics()->Uses2DTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
||||||
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0)
|
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0)
|
||||||
TextureLoadFlag = 0;
|
TextureLoadFlag = 0;
|
||||||
|
|
|
@ -123,6 +123,13 @@ bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos)
|
||||||
delete GameServer()->m_apSavedTees[m_pPlayer->GetCid()];
|
delete GameServer()->m_apSavedTees[m_pPlayer->GetCid()];
|
||||||
GameServer()->m_apSavedTees[m_pPlayer->GetCid()] = nullptr;
|
GameServer()->m_apSavedTees[m_pPlayer->GetCid()] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(GameServer()->m_apSavedTeleTees[m_pPlayer->GetCid()])
|
||||||
|
{
|
||||||
|
m_pPlayer->m_LastTeleTee = *GameServer()->m_apSavedTeleTees[m_pPlayer->GetCid()];
|
||||||
|
delete GameServer()->m_apSavedTeleTees[m_pPlayer->GetCid()];
|
||||||
|
GameServer()->m_apSavedTeleTees[m_pPlayer->GetCid()] = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -108,6 +108,9 @@ void CGameContext::Construct(int Resetting)
|
||||||
for(auto &pSavedTee : m_apSavedTees)
|
for(auto &pSavedTee : m_apSavedTees)
|
||||||
pSavedTee = nullptr;
|
pSavedTee = nullptr;
|
||||||
|
|
||||||
|
for(auto &pSavedTeleTee : m_apSavedTeleTees)
|
||||||
|
pSavedTeleTee = nullptr;
|
||||||
|
|
||||||
for(auto &pSavedTeam : m_apSavedTeams)
|
for(auto &pSavedTeam : m_apSavedTeams)
|
||||||
pSavedTeam = nullptr;
|
pSavedTeam = nullptr;
|
||||||
|
|
||||||
|
@ -131,6 +134,9 @@ void CGameContext::Destruct(int Resetting)
|
||||||
for(auto &pSavedTee : m_apSavedTees)
|
for(auto &pSavedTee : m_apSavedTees)
|
||||||
delete pSavedTee;
|
delete pSavedTee;
|
||||||
|
|
||||||
|
for(auto &pSavedTeleTee : m_apSavedTeleTees)
|
||||||
|
delete pSavedTeleTee;
|
||||||
|
|
||||||
for(auto &pSavedTeam : m_apSavedTeams)
|
for(auto &pSavedTeam : m_apSavedTeams)
|
||||||
delete pSavedTeam;
|
delete pSavedTeam;
|
||||||
|
|
||||||
|
@ -773,7 +779,6 @@ void CGameContext::StartVote(const char *pDesc, const char *pCommand, const char
|
||||||
{
|
{
|
||||||
// reset votes
|
// reset votes
|
||||||
m_VoteEnforce = VOTE_ENFORCE_UNKNOWN;
|
m_VoteEnforce = VOTE_ENFORCE_UNKNOWN;
|
||||||
m_VoteEnforcer = -1;
|
|
||||||
for(auto &pPlayer : m_apPlayers)
|
for(auto &pPlayer : m_apPlayers)
|
||||||
{
|
{
|
||||||
if(pPlayer)
|
if(pPlayer)
|
||||||
|
@ -1204,7 +1209,7 @@ void CGameContext::OnTick()
|
||||||
}
|
}
|
||||||
else if(m_VoteEnforce == VOTE_ENFORCE_YES_ADMIN)
|
else if(m_VoteEnforce == VOTE_ENFORCE_YES_ADMIN)
|
||||||
{
|
{
|
||||||
Console()->ExecuteLine(m_aVoteCommand, m_VoteEnforcer);
|
Console()->ExecuteLine(m_aVoteCommand, m_VoteCreator);
|
||||||
SendChat(-1, TEAM_ALL, "Vote passed enforced by authorized player", -1, FLAG_SIX);
|
SendChat(-1, TEAM_ALL, "Vote passed enforced by authorized player", -1, FLAG_SIX);
|
||||||
EndVote();
|
EndVote();
|
||||||
}
|
}
|
||||||
|
@ -1712,6 +1717,9 @@ void CGameContext::OnClientDrop(int ClientId, const char *pReason)
|
||||||
delete m_apSavedTees[ClientId];
|
delete m_apSavedTees[ClientId];
|
||||||
m_apSavedTees[ClientId] = nullptr;
|
m_apSavedTees[ClientId] = nullptr;
|
||||||
|
|
||||||
|
delete m_apSavedTeleTees[ClientId];
|
||||||
|
m_apSavedTeleTees[ClientId] = nullptr;
|
||||||
|
|
||||||
m_aTeamMapping[ClientId] = -1;
|
m_aTeamMapping[ClientId] = -1;
|
||||||
|
|
||||||
m_VoteUpdate = true;
|
m_VoteUpdate = true;
|
||||||
|
@ -3208,12 +3216,19 @@ void CGameContext::ConHotReload(IConsole::IResult *pResult, void *pUserData)
|
||||||
if(!pSelf->GetPlayerChar(i))
|
if(!pSelf->GetPlayerChar(i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
CCharacter *pChar = pSelf->GetPlayerChar(i);
|
||||||
|
|
||||||
// Save the tee individually
|
// Save the tee individually
|
||||||
pSelf->m_apSavedTees[i] = new CSaveTee();
|
pSelf->m_apSavedTees[i] = new CSaveTee();
|
||||||
pSelf->m_apSavedTees[i]->Save(pSelf->GetPlayerChar(i), false);
|
pSelf->m_apSavedTees[i]->Save(pChar, false);
|
||||||
|
|
||||||
|
if(pSelf->m_apPlayers[i])
|
||||||
|
pSelf->m_apSavedTeleTees[i] = new CSaveTee(pSelf->m_apPlayers[i]->m_LastTeleTee);
|
||||||
|
|
||||||
// Save the team state
|
// Save the team state
|
||||||
pSelf->m_aTeamMapping[i] = pSelf->GetDDRaceTeam(i);
|
pSelf->m_aTeamMapping[i] = pSelf->GetDDRaceTeam(i);
|
||||||
|
if(pSelf->m_aTeamMapping[i] == TEAM_SUPER)
|
||||||
|
pSelf->m_aTeamMapping[i] = pChar->m_TeamBeforeSuper;
|
||||||
|
|
||||||
if(pSelf->m_apSavedTeams[pSelf->m_aTeamMapping[i]])
|
if(pSelf->m_apSavedTeams[pSelf->m_aTeamMapping[i]])
|
||||||
continue;
|
continue;
|
||||||
|
@ -4820,7 +4835,6 @@ void CGameContext::ForceVote(int EnforcerId, bool Success)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_VoteEnforce = Success ? CGameContext::VOTE_ENFORCE_YES_ADMIN : CGameContext::VOTE_ENFORCE_NO_ADMIN;
|
m_VoteEnforce = Success ? CGameContext::VOTE_ENFORCE_YES_ADMIN : CGameContext::VOTE_ENFORCE_NO_ADMIN;
|
||||||
m_VoteEnforcer = EnforcerId;
|
|
||||||
|
|
||||||
char aBuf[256];
|
char aBuf[256];
|
||||||
const char *pOption = Success ? "yes" : "no";
|
const char *pOption = Success ? "yes" : "no";
|
||||||
|
|
|
@ -183,6 +183,7 @@ public:
|
||||||
bool m_aPlayerHasInput[MAX_CLIENTS];
|
bool m_aPlayerHasInput[MAX_CLIENTS];
|
||||||
CSaveTeam *m_apSavedTeams[MAX_CLIENTS];
|
CSaveTeam *m_apSavedTeams[MAX_CLIENTS];
|
||||||
CSaveTee *m_apSavedTees[MAX_CLIENTS];
|
CSaveTee *m_apSavedTees[MAX_CLIENTS];
|
||||||
|
CSaveTee *m_apSavedTeleTees[MAX_CLIENTS];
|
||||||
int m_aTeamMapping[MAX_CLIENTS];
|
int m_aTeamMapping[MAX_CLIENTS];
|
||||||
|
|
||||||
// returns last input if available otherwise nulled PlayerInput object
|
// returns last input if available otherwise nulled PlayerInput object
|
||||||
|
@ -575,7 +576,6 @@ public:
|
||||||
VOTE_TYPE_SPECTATE,
|
VOTE_TYPE_SPECTATE,
|
||||||
};
|
};
|
||||||
int m_VoteVictim;
|
int m_VoteVictim;
|
||||||
int m_VoteEnforcer;
|
|
||||||
|
|
||||||
inline bool IsOptionVote() const { return m_VoteType == VOTE_TYPE_OPTION; }
|
inline bool IsOptionVote() const { return m_VoteType == VOTE_TYPE_OPTION; }
|
||||||
inline bool IsKickVote() const { return m_VoteType == VOTE_TYPE_KICK; }
|
inline bool IsKickVote() const { return m_VoteType == VOTE_TYPE_KICK; }
|
||||||
|
|
Loading…
Reference in a new issue