mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-19 01:02:20 +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
|
||||
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
|
||||
|
||||
COLOR_RED="\e[1;31m"
|
||||
|
|
|
@ -1,15 +1,40 @@
|
|||
<?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 -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.vulkan.version"
|
||||
android:required="false"
|
||||
android:version="0x00401000" />
|
||||
<!-- android:glEsVersion is not specified as OpenGL ES 1.0 is supported as fallback -->
|
||||
|
||||
<!-- Only playable in landscape mode -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.screen.landscape"
|
||||
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 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
||||
|
@ -25,17 +50,24 @@
|
|||
android:isGame="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||
android:hardwareAccelerated="true">
|
||||
<activity
|
||||
android:name="org.ddnet.client.NativeMain"
|
||||
android:alwaysRetainTaskState="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:launchMode="singleInstance">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</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
|
||||
android:name="android.app.lib_name"
|
||||
android:value="DDNet" />
|
||||
|
|
|
@ -21,7 +21,7 @@ android {
|
|||
defaultConfig {
|
||||
applicationId "org.ddnet.client"
|
||||
namespace("org.ddnet.client")
|
||||
minSdkVersion 19
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 34
|
||||
versionCode TW_VERSION_CODE
|
||||
versionName "TW_VERSION_NAME"
|
||||
|
|
|
@ -29,6 +29,8 @@ function compile_source_android() {
|
|||
-DCMAKE_SYSTEM_NAME=Android \
|
||||
-DCMAKE_SYSTEM_VERSION="$1" \
|
||||
-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" \
|
||||
-DBUILD_SHARED_LIBS=OFF \
|
||||
-DHIDAPI_SKIP_LIBUSB=TRUE \
|
||||
|
|
|
@ -46,7 +46,8 @@ fi
|
|||
mkdir -p "$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() {
|
||||
if [ ! -d "${1}" ]; then
|
||||
|
@ -59,7 +60,7 @@ function build_cmake_lib() {
|
|||
(
|
||||
cd "${1}" || exit 1
|
||||
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
|
||||
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
|
||||
fi
|
||||
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
|
||||
|
@ -109,7 +110,7 @@ fi
|
|||
(
|
||||
cd sqlite3 || exit 1
|
||||
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 ..
|
||||
|
|
|
@ -163,19 +163,19 @@
|
|||
#define CONF_ARCH_ARM 1
|
||||
#define CONF_ARCH_STRING "arm"
|
||||
#define CONF_ARCH_ENDIAN_BIG 1
|
||||
#endif
|
||||
|
||||
#if defined(__ARMEL__)
|
||||
#elif defined(__ARMEL__)
|
||||
#define CONF_ARCH_ARM 1
|
||||
#define CONF_ARCH_STRING "arm"
|
||||
#define CONF_ARCH_ENDIAN_LITTLE 1
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__) || defined(__arm64__) || defined(__ARM_ARCH)
|
||||
#elif defined(__aarch64__) || defined(__arm64__) || defined(__ARM_ARCH_ISA_A64)
|
||||
#define CONF_ARCH_ARM64 1
|
||||
#define CONF_ARCH_STRING "arm64"
|
||||
#if defined(__ARM_BIG_ENDIAN)
|
||||
#define CONF_ARCH_ENDIAN_BIG 1
|
||||
#else
|
||||
#define CONF_ARCH_ENDIAN_LITTLE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONF_FAMILY_STRING
|
||||
#define CONF_FAMILY_STRING "unknown"
|
||||
|
|
|
@ -1508,8 +1508,9 @@ protected:
|
|||
vkInvalidateMappedMemoryRanges(m_VKDevice, 1, &MemRange);
|
||||
|
||||
size_t RealFullImageSize = maximum(ImageTotalSize, (size_t)(Height * m_GetPresentedImgDataHelperMappedLayoutPitch));
|
||||
if(vDstData.size() < RealFullImageSize)
|
||||
vDstData.resize(RealFullImageSize);
|
||||
size_t ExtraRowSize = Width * 4;
|
||||
if(vDstData.size() < RealFullImageSize + ExtraRowSize)
|
||||
vDstData.resize(RealFullImageSize + ExtraRowSize);
|
||||
|
||||
mem_copy(vDstData.data(), pResImageData, RealFullImageSize);
|
||||
|
||||
|
@ -1520,7 +1521,8 @@ protected:
|
|||
{
|
||||
size_t OffsetImagePacked = (Y * Width * 4);
|
||||
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_CurrentServerNextPingTime = -1;
|
||||
|
||||
ResetMapDownload();
|
||||
m_aMapdownloadFilename[0] = '\0';
|
||||
m_aMapdownloadFilenameTemp[0] = '\0';
|
||||
m_aMapdownloadName[0] = '\0';
|
||||
ResetMapDownload(true);
|
||||
|
||||
// clear the current server info
|
||||
mem_zero(&m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
|
||||
|
@ -1019,11 +1016,11 @@ void CClient::Render()
|
|||
GameClient()->OnRender();
|
||||
DebugRender();
|
||||
|
||||
if(State() == IClient::STATE_ONLINE && g_Config.m_ClAntiPingLimit)
|
||||
{
|
||||
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;
|
||||
}
|
||||
// if(State() == IClient::STATE_ONLINE && g_Config.m_ClAntiPingLimit)
|
||||
// {
|
||||
// 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;
|
||||
// }
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
ResetMapDownload();
|
||||
ResetMapDownload(true);
|
||||
|
||||
SHA256_DIGEST *pMapSha256 = nullptr;
|
||||
const char *pMapUrl = nullptr;
|
||||
|
@ -2196,7 +2193,7 @@ int CClient::UnpackAndValidateSnapshot(CSnapshot *pFrom, CSnapshot *pTo)
|
|||
return Builder.Finish(pTo);
|
||||
}
|
||||
|
||||
void CClient::ResetMapDownload()
|
||||
void CClient::ResetMapDownload(bool ResetActive)
|
||||
{
|
||||
if(m_pMapdownloadTask)
|
||||
{
|
||||
|
@ -2215,19 +2212,24 @@ void CClient::ResetMapDownload()
|
|||
Storage()->RemoveFile(m_aMapdownloadFilenameTemp, IStorage::TYPE_SAVE);
|
||||
}
|
||||
|
||||
m_MapdownloadChunk = 0;
|
||||
m_MapdownloadSha256Present = false;
|
||||
m_MapdownloadSha256 = SHA256_ZEROED;
|
||||
m_MapdownloadCrc = 0;
|
||||
m_MapdownloadTotalsize = -1;
|
||||
m_MapdownloadAmount = 0;
|
||||
if(ResetActive)
|
||||
{
|
||||
m_MapdownloadChunk = 0;
|
||||
m_MapdownloadSha256Present = false;
|
||||
m_MapdownloadSha256 = SHA256_ZEROED;
|
||||
m_MapdownloadCrc = 0;
|
||||
m_MapdownloadTotalsize = -1;
|
||||
m_MapdownloadAmount = 0;
|
||||
m_aMapdownloadFilename[0] = '\0';
|
||||
m_aMapdownloadFilenameTemp[0] = '\0';
|
||||
m_aMapdownloadName[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::FinishMapDownload()
|
||||
{
|
||||
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;
|
||||
|
||||
bool FileSuccess = true;
|
||||
|
@ -2236,7 +2238,6 @@ void CClient::FinishMapDownload()
|
|||
FileSuccess &= Storage()->RenameFile(m_aMapdownloadFilenameTemp, m_aMapdownloadFilename, IStorage::TYPE_SAVE);
|
||||
if(!FileSuccess)
|
||||
{
|
||||
ResetMapDownload();
|
||||
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);
|
||||
DisconnectWithReason(aError);
|
||||
|
@ -2246,19 +2247,17 @@ void CClient::FinishMapDownload()
|
|||
const char *pError = LoadMap(m_aMapdownloadName, m_aMapdownloadFilename, pSha256, m_MapdownloadCrc);
|
||||
if(!pError)
|
||||
{
|
||||
ResetMapDownload();
|
||||
ResetMapDownload(true);
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done");
|
||||
SendReady(CONN_MAIN);
|
||||
}
|
||||
else if(m_pMapdownloadTask) // fallback
|
||||
{
|
||||
ResetMapDownload();
|
||||
m_MapdownloadTotalsize = PrevMapdownloadTotalsize;
|
||||
ResetMapDownload(false);
|
||||
SendMapRequest();
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetMapDownload();
|
||||
DisconnectWithReason(pError);
|
||||
}
|
||||
}
|
||||
|
@ -2784,7 +2783,7 @@ void CClient::Update()
|
|||
else if(m_pMapdownloadTask->State() == EHttpState::ERROR || m_pMapdownloadTask->State() == EHttpState::ABORTED)
|
||||
{
|
||||
dbg_msg("webdl", "http failed, falling back to gameserver");
|
||||
ResetMapDownload();
|
||||
ResetMapDownload(false);
|
||||
SendMapRequest();
|
||||
}
|
||||
}
|
||||
|
@ -2930,6 +2929,24 @@ void CClient::Run()
|
|||
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
|
||||
m_pGraphics = CreateEngineGraphicsThreaded();
|
||||
Kernel()->RegisterInterface(m_pGraphics); // IEngineGraphics
|
||||
|
@ -2953,24 +2970,6 @@ void CClient::Run()
|
|||
CVideo::Init();
|
||||
#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
|
||||
m_pTextRender = Kernel()->RequestInterface<IEngineTextRender>();
|
||||
m_pTextRender->Init();
|
||||
|
|
|
@ -360,7 +360,7 @@ public:
|
|||
|
||||
int UnpackAndValidateSnapshot(CSnapshot *pFrom, CSnapshot *pTo);
|
||||
|
||||
void ResetMapDownload();
|
||||
void ResetMapDownload(bool ResetActive);
|
||||
void FinishMapDownload();
|
||||
|
||||
void RequestDDNetInfo() override;
|
||||
|
|
|
@ -300,7 +300,7 @@ void CGraphics_Threaded::UnloadTexture(CTextureHandle *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)
|
||||
{
|
||||
|
|
|
@ -283,6 +283,7 @@ void CVideo::Pause(bool Pause)
|
|||
void CVideo::Stop()
|
||||
{
|
||||
dbg_assert(!m_Stopped, "Already stopped");
|
||||
m_Stopped = true;
|
||||
|
||||
m_pGraphics->WaitForIdle();
|
||||
|
||||
|
@ -341,8 +342,6 @@ void CVideo::Stop()
|
|||
pSound->PauseAudioDevice();
|
||||
delete ms_pCurrentVideo;
|
||||
pSound->UnpauseAudioDevice();
|
||||
|
||||
m_Stopped = true;
|
||||
}
|
||||
|
||||
void CVideo::NextVideoFrameThread()
|
||||
|
|
|
@ -124,6 +124,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
bool ConvertToRGBA(uint8_t *pDest, const CImageInfo &SrcImage);
|
||||
|
||||
/*
|
||||
Structure: CVideoMode
|
||||
*/
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
// client
|
||||
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(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(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)")
|
||||
|
|
|
@ -341,7 +341,7 @@ void CConsole::Print(int Level, const char *pFrom, const char *pStr, ColorRGBA P
|
|||
{
|
||||
LEVEL LogLevel = IConsole::ToLogLevel(Level);
|
||||
// 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);
|
||||
}
|
||||
|
|
|
@ -70,18 +70,18 @@ void CEcon::Init(CConfig *pConfig, IConsole *pConsole, CNetBan *pNetBan)
|
|||
}
|
||||
|
||||
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];
|
||||
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);
|
||||
return;
|
||||
}
|
||||
BindAddr.type = NETTYPE_ALL;
|
||||
BindAddr.port = g_Config.m_EcPort;
|
||||
|
||||
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_LIST_UL = "\xEF\x83\x8A";
|
||||
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_PLAY = "\xEF\x81\x8B";
|
||||
|
|
|
@ -160,8 +160,6 @@ class CGameConsole : public CComponent
|
|||
static const ColorRGBA ms_SearchHighlightColor;
|
||||
static const ColorRGBA ms_SearchSelectedColor;
|
||||
|
||||
void Toggle(int Type);
|
||||
|
||||
static void PossibleCommandsRenderCallback(int Index, const char *pStr, void *pUser);
|
||||
static void ConToggleLocalConsole(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;
|
||||
void Prompt(char (&aPrompt)[32]);
|
||||
|
||||
void Toggle(int Type);
|
||||
bool IsClosed() { return m_ConsoleState == CONSOLE_CLOSED; }
|
||||
};
|
||||
#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));
|
||||
|
||||
int predictTick = GameClient()->GetPredictionTick();
|
||||
|
||||
float Ct;
|
||||
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
|
||||
Ct = (Client()->PrevGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) / (float)Client()->GameTickSpeed() + s_LastGameTickTime;
|
||||
if(Ct < 0)
|
||||
|
@ -304,9 +306,11 @@ void CItems::RenderLaser(const CLaserData *pCurrent, bool IsPredicted)
|
|||
{
|
||||
Dir = normalize_pre_length(Pos - From, Len);
|
||||
|
||||
int predictTick = GameClient()->GetPredictionTick();
|
||||
|
||||
float Ticks;
|
||||
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
|
||||
Ticks = (float)(Client()->GameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->IntraGameTick(g_Config.m_ClDummy);
|
||||
float Ms = (Ticks / Client()->GameTickSpeed()) * 1000.0f;
|
||||
|
@ -377,7 +381,7 @@ void CItems::OnRender()
|
|||
auto &aSwitchers = GameClient()->Switchers();
|
||||
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))
|
||||
continue;
|
||||
|
@ -385,7 +389,7 @@ void CItems::OnRender()
|
|||
CProjectileData Data = pProj->GetData();
|
||||
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);
|
||||
if(!pLaser || pLaser->GetOwner() < 0 || !GameClient()->m_aClients[pLaser->GetOwner()].m_IsPredictedLocal)
|
||||
|
@ -393,7 +397,7 @@ void CItems::OnRender()
|
|||
CLaserData Data = pLaser->GetData();
|
||||
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)
|
||||
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;
|
||||
if(!m_pClient->AntiPingGunfire() || !LocalPlayerInGame)
|
||||
return;
|
||||
if(Client()->PredGameTick(g_Config.m_ClDummy) == pCurrent->m_StartTick)
|
||||
|
||||
int predictTick = GameClient()->GetPredictionTick();
|
||||
|
||||
if(predictTick == pCurrent->m_StartTick)
|
||||
return;
|
||||
|
||||
// get positions
|
||||
|
@ -625,7 +632,7 @@ void CItems::ReconstructSmokeTrail(const CProjectileData *pCurrent, int DestroyT
|
|||
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)
|
||||
return; // projectile haven't been shot yet
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#include "menus.h"
|
||||
|
||||
using namespace FontIcons;
|
||||
|
||||
void CMenus::RenderStartMenu(CUIRect MainView)
|
||||
{
|
||||
GameClient()->m_MenuBackground.ChangePosition(CMenuBackground::POS_START);
|
||||
|
@ -186,13 +188,27 @@ void CMenus::RenderStartMenu(CUIRect MainView)
|
|||
}
|
||||
|
||||
// render version
|
||||
CUIRect VersionUpdate, CurVersion;
|
||||
MainView.HSplitBottom(20.0f, nullptr, &VersionUpdate);
|
||||
VersionUpdate.VSplitRight(50.0f, &CurVersion, nullptr);
|
||||
VersionUpdate.VMargin(VMargin, &VersionUpdate);
|
||||
|
||||
CUIRect CurVersion, ConsoleButton;
|
||||
MainView.HSplitBottom(45.0f, nullptr, &CurVersion);
|
||||
CurVersion.VSplitRight(40.0f, &CurVersion, nullptr);
|
||||
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);
|
||||
|
||||
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)
|
||||
CUIRect 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()
|
||||
{
|
||||
// store the previous values so we can detect prediction errors
|
||||
|
@ -2156,20 +2175,33 @@ void CGameClient::OnPredict()
|
|||
CCharacter *pDummyChar = 0;
|
||||
if(PredictDummy())
|
||||
pDummyChar = m_PredictedWorld.GetCharacterById(m_PredictedDummyId);
|
||||
|
||||
|
||||
int predictTick = GetPredictionTick();
|
||||
// predict
|
||||
for(int Tick = Client()->GameTick(g_Config.m_ClDummy) + 1; Tick <= Client()->PredGameTick(g_Config.m_ClDummy); Tick++)
|
||||
{
|
||||
// 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++)
|
||||
if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i))
|
||||
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
|
||||
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;
|
||||
|
@ -2193,14 +2225,22 @@ void CGameClient::OnPredict()
|
|||
m_PredictedWorld.Tick();
|
||||
|
||||
// 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++)
|
||||
if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i))
|
||||
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++)
|
||||
if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i))
|
||||
{
|
||||
|
|
|
@ -499,6 +499,7 @@ public:
|
|||
CRenderTools m_RenderTools;
|
||||
|
||||
void OnReset();
|
||||
int GetPredictionTick();
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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))
|
||||
{
|
||||
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];
|
||||
Graphics()->UnloadTexture(&(pImg->m_Texture));
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
pImg->m_Texture = Graphics()->LoadTextureRaw(ImgInfo, TextureLoadFlag, pFileName);
|
||||
ImgInfo.m_pData = nullptr;
|
||||
pImg->m_Texture = Graphics()->LoadTextureRaw(*pImg, TextureLoadFlag, pFileName);
|
||||
|
||||
SortImages();
|
||||
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;
|
||||
}
|
||||
|
||||
CEditorImage ImgInfo(pEditor);
|
||||
CImageInfo ImgInfo;
|
||||
if(!pEditor->Graphics()->LoadPng(ImgInfo, pFileName, StorageType))
|
||||
{
|
||||
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);
|
||||
*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);
|
||||
|
||||
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;
|
||||
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0)
|
||||
if(pImg->m_Width % 16 != 0 || pImg->m_Height % 16 != 0)
|
||||
TextureLoadFlag = 0;
|
||||
pImg->m_Texture = pEditor->Graphics()->LoadTextureRaw(ImgInfo, TextureLoadFlag, pFileName);
|
||||
ImgInfo.m_pData = nullptr;
|
||||
pImg->m_Texture = pEditor->Graphics()->LoadTextureRaw(*pImg, TextureLoadFlag, pFileName);
|
||||
str_copy(pImg->m_aName, aBuf);
|
||||
pImg->m_AutoMapper.Load(pImg->m_aName);
|
||||
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_Format = ImgInfo.m_Format;
|
||||
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;
|
||||
if(ImgInfo.m_Width % 16 != 0 || ImgInfo.m_Height % 16 != 0)
|
||||
TextureLoadFlag = 0;
|
||||
|
|
|
@ -123,6 +123,13 @@ bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos)
|
|||
delete GameServer()->m_apSavedTees[m_pPlayer->GetCid()];
|
||||
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;
|
||||
|
|
|
@ -108,6 +108,9 @@ void CGameContext::Construct(int Resetting)
|
|||
for(auto &pSavedTee : m_apSavedTees)
|
||||
pSavedTee = nullptr;
|
||||
|
||||
for(auto &pSavedTeleTee : m_apSavedTeleTees)
|
||||
pSavedTeleTee = nullptr;
|
||||
|
||||
for(auto &pSavedTeam : m_apSavedTeams)
|
||||
pSavedTeam = nullptr;
|
||||
|
||||
|
@ -131,6 +134,9 @@ void CGameContext::Destruct(int Resetting)
|
|||
for(auto &pSavedTee : m_apSavedTees)
|
||||
delete pSavedTee;
|
||||
|
||||
for(auto &pSavedTeleTee : m_apSavedTeleTees)
|
||||
delete pSavedTeleTee;
|
||||
|
||||
for(auto &pSavedTeam : m_apSavedTeams)
|
||||
delete pSavedTeam;
|
||||
|
||||
|
@ -773,7 +779,6 @@ void CGameContext::StartVote(const char *pDesc, const char *pCommand, const char
|
|||
{
|
||||
// reset votes
|
||||
m_VoteEnforce = VOTE_ENFORCE_UNKNOWN;
|
||||
m_VoteEnforcer = -1;
|
||||
for(auto &pPlayer : m_apPlayers)
|
||||
{
|
||||
if(pPlayer)
|
||||
|
@ -1204,7 +1209,7 @@ void CGameContext::OnTick()
|
|||
}
|
||||
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);
|
||||
EndVote();
|
||||
}
|
||||
|
@ -1712,6 +1717,9 @@ void CGameContext::OnClientDrop(int ClientId, const char *pReason)
|
|||
delete m_apSavedTees[ClientId];
|
||||
m_apSavedTees[ClientId] = nullptr;
|
||||
|
||||
delete m_apSavedTeleTees[ClientId];
|
||||
m_apSavedTeleTees[ClientId] = nullptr;
|
||||
|
||||
m_aTeamMapping[ClientId] = -1;
|
||||
|
||||
m_VoteUpdate = true;
|
||||
|
@ -3208,12 +3216,19 @@ void CGameContext::ConHotReload(IConsole::IResult *pResult, void *pUserData)
|
|||
if(!pSelf->GetPlayerChar(i))
|
||||
continue;
|
||||
|
||||
CCharacter *pChar = pSelf->GetPlayerChar(i);
|
||||
|
||||
// Save the tee individually
|
||||
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
|
||||
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]])
|
||||
continue;
|
||||
|
@ -4820,7 +4835,6 @@ void CGameContext::ForceVote(int EnforcerId, bool Success)
|
|||
return;
|
||||
|
||||
m_VoteEnforce = Success ? CGameContext::VOTE_ENFORCE_YES_ADMIN : CGameContext::VOTE_ENFORCE_NO_ADMIN;
|
||||
m_VoteEnforcer = EnforcerId;
|
||||
|
||||
char aBuf[256];
|
||||
const char *pOption = Success ? "yes" : "no";
|
||||
|
|
|
@ -183,6 +183,7 @@ public:
|
|||
bool m_aPlayerHasInput[MAX_CLIENTS];
|
||||
CSaveTeam *m_apSavedTeams[MAX_CLIENTS];
|
||||
CSaveTee *m_apSavedTees[MAX_CLIENTS];
|
||||
CSaveTee *m_apSavedTeleTees[MAX_CLIENTS];
|
||||
int m_aTeamMapping[MAX_CLIENTS];
|
||||
|
||||
// returns last input if available otherwise nulled PlayerInput object
|
||||
|
@ -575,7 +576,6 @@ public:
|
|||
VOTE_TYPE_SPECTATE,
|
||||
};
|
||||
int m_VoteVictim;
|
||||
int m_VoteEnforcer;
|
||||
|
||||
inline bool IsOptionVote() const { return m_VoteType == VOTE_TYPE_OPTION; }
|
||||
inline bool IsKickVote() const { return m_VoteType == VOTE_TYPE_KICK; }
|
||||
|
|
Loading…
Reference in a new issue