Иконка ресурса

SafeNameAndChat 1.2 Beta 3a

Сообщения
1,293
Реакции
2,295
Помог
57 раз(а)
Code_0xABC,
Код:
client_print(pPlayer, print_chat, "%i", get_user_weapon(pPlayer))
2023-12-10_14-59-57.jpg
 
Сообщения
15
Реакции
3
this is an unofficial edit
-----------------------------------

i made this edit on stable version from github(i didn t noticed https://symbl.cc/en/unicode/blocks/halfwidth-and-fullwidth-forms/ ....)
you can see in .CFG what is new , this module was compiled & tested with success (i will not upload .SO because is not official)
i used it for over 1 year, no problems founded
why i made this 'modifications' ? from what ik, in amxx menus there is a bug about '+' symbol in player nick (because i didn t noticed that link, i didn t used to replace '^ , & , +' symbols with ascii code, i just 'deleted' them)
in original code, replacing text is working only for 'say & say_team' , in this one u will notice in .CFG 'CheckCommand' where you can add multiple console commands to be checked(we know that old non-steam clients can be crashed with amx_psay too)
in this moment i got idea to hook hud/dhud/old & new menu for those replacements, but from what i saw, the game is going down and i think nobody will use it

SafeNameAndChat.cfg
Код:
SNAC_Chat_ReplaceNumberSign                    1
SNAC_Chat_ReplacePercentSign                1
SNAC_Chat_ReplaceAmpersandSign                1
SNAC_Chat_ReplacePlusSign                    0
SNAC_Chat_ReplaceHatSign                    0
SNAC_Chat_RemoveUnprintable                    1
SNAC_Chat_RemoveColors                        1
SNAC_Chat_TrimSpaces                        1
SNAC_Chat_TruncateToEngineLimitAfterReplace    1

CheckCommand                                = say , say_team , amx_say , amx_chat , amx_psay , amx_csay , amx_tsay

SNAC_Name_ReplaceNumberSign                    1
SNAC_Name_ReplacePercentSign                1
SNAC_Name_ReplaceAmpersandSign                1
SNAC_Name_ReplacePlusSign                    1
SNAC_Name_ReplaceHatSign                    1
SNAC_Name_RemoveUnprintable                    1
SNAC_Name_RemoveColors                        1
SNAC_Name_TrimSpaces                        1
CMakeLists.txt
Код:
cmake_minimum_required(VERSION 3.1)
project(snac CXX)

option(DEBUG "Build with debug information." OFF)
option(USE_STATIC_LIBSTDC "Enables static linking libstdc++." ON)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Avoid -rdynamic -fPIC options
set(CMAKE_SHARED_LIBRARY_CXX_FLAGS "")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")

set(COMPILE_FLAGS "-m32 -U_FORTIFY_SOURCE")
set(LINK_FLAGS "-m32")

set(COMPILE_FLAGS "${COMPILE_FLAGS} -Wall -fno-exceptions -fno-builtin -Wno-unknown-pragmas")

# Remove noxref code and data
set(COMPILE_FLAGS "${COMPILE_FLAGS} -ffunction-sections -fdata-sections")

if (DEBUG)
    set(COMPILE_FLAGS "${COMPILE_FLAGS} -g3 -O3 -ggdb")
else()
    set(COMPILE_FLAGS "${COMPILE_FLAGS} -g0 -O3 -fno-stack-protector")
endif()

set(COMPILE_FLAGS "${COMPILE_FLAGS} -msse2 -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden -ffunction-sections -fdata-sections")

# Check Intel C++ compiler
if ("$ENV{CXX}" MATCHES "icpc")
    set(COMPILE_FLAGS "${COMPILE_FLAGS} \
        -fp-model=strict\
        -fasm-blocks\
        -fomit-frame-pointer\
        -Qoption,cpp,--treat_func_as_string_literal_cpp")

    set(LINK_FLAGS "${LINK_FLAGS} \
        -static-intel\
        -no-intel-extensions")

    if (NOT DEBUG)
        set(COMPILE_FLAGS "${COMPILE_FLAGS} -ipo")
        set(LINK_FLAGS "${LINK_FLAGS} -ipo")
    endif()
else()
    # Produce code optimized for the most common IA32/AMD64/EM64T processors.
    # As new processors are deployed in the marketplace, the behavior of this option will change.
    set(COMPILE_FLAGS "${COMPILE_FLAGS} -fpermissive -fno-sized-deallocation")

    # Check if not Clang compiler
    if (NOT "$ENV{CXX}" MATCHES "clang")
        set(COMPILE_FLAGS "${COMPILE_FLAGS} -fno-gnu-unique")
    endif()
endif()

# GCC >= 8.3
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0)
    set(COMPILE_FLAGS "${COMPILE_FLAGS} -fcf-protection=none")
endif()

if (NOT DEBUG)
    set(LINK_FLAGS "${LINK_FLAGS} \
        -s -Wl,-gc-sections -Wl,--version-script=\"${PROJECT_SOURCE_DIR}/version_script.lds\"")
endif()

set(PROJECT_PUBLIC_DIR
    "../SDK/include/common"
    "../SDK/include/dlls"
    "../SDK/include/engine"
    "../SDK/include/pm_shared"
    "../SDK/src"
)

set(MAIN_SRCS
    "Main.cpp"
)

add_library(snac SHARED)

target_include_directories(snac PRIVATE
    ${PROJECT_SOURCE_DIR}
    ${PROJECT_PUBLIC_DIR}
)

target_compile_definitions(snac PRIVATE
    _LINUX
    LINUX
    NDEBUG
    _GLIBCXX_USE_CXX11_ABI=0
)

target_sources(snac PRIVATE
    ${MAIN_SRCS}
)

target_link_libraries(snac PRIVATE
    rt
    m
    dl
)

if (USE_STATIC_LIBSTDC)
    target_compile_definitions(snac PRIVATE BUILD_STATIC_LIBSTDC)
    set(LINK_FLAGS "${LINK_FLAGS} -static-libgcc -static-libstdc++")
endif()

set_target_properties(snac PROPERTIES
    OUTPUT_NAME SafeNameAndChat
    PREFIX ""
    COMPILE_FLAGS ${COMPILE_FLAGS}
    LINK_FLAGS ${LINK_FLAGS}
    POSITION_INDEPENDENT_CODE OFF
)
Main,cpp
C++:
#include <extdll.h>
#include <meta_api.h>
#include "Main.h"
#include <vector>
#include <unordered_set>
#include <iostream>

// metamod plugin?
//#define USE_METAMOD

using namespace std;

std::unordered_set<std::string> StoredCfgCommands;

extern void OnClientCommand_PreHook(edict_t *pPlayerEntity);
extern void OnClientUserInfoChanged_PreHook(edict_t *pPlayerEntity, char *infoBuffer);

extern void OnServerActivate_PostHook(edict_t *pEdictList, int edictCount, int maxClients);

static const uint32_t g_isPrintTable[2048] = {
    0x00000200, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF9FFFFFF, 0x00030003, 0x0000401F,
    0x00000000, 0x00000000, 0x00000000, 0x7CCF0000, 0xFFFFD7C0, 0xFFFFFFFB, 0xFFFFFFFF, 0xFFBFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC03, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFE000F, 0xFE7FFFFF, 0xFFFFFFFE, 0x000006FF, 0x40000000, 0xFFFF0049, 0x001F07FF,
    0xC8003600, 0xFFFFFFFE, 0x000007FF, 0xFFFEFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x003FFFFF, 0x9FFFC060,
    0xFFFD3FFF, 0x0000FFFF, 0xFFFFE000, 0xFFFFFFFF, 0xFFFFFFFF, 0x0002003F, 0xFFFFFFFF, 0x07B007FF,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0xFFFFFFF0, 0x23FFFFFF, 0xFF010000, 0xF807FFF3, 0xFFF99FE0, 0x23C5FDFF, 0xB0004000, 0x0003FFC3,
    0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001CFFC0, 0xFFFBBFE0, 0x23EDFDFF, 0x00010000, 0x0000FFC3,
    0xFFF99FE0, 0x23EDFDFF, 0xB0000000, 0x0002FFC3, 0xD63DC7E8, 0x03FFC718, 0x00010000, 0x0000FFC0,
    0xFFFDDFE0, 0x23EFFDFF, 0x03000000, 0x0000FFC3, 0xFFFDDFE0, 0x23EFFDFF, 0x40000000, 0x0000FFC3,
    0xFFFDDFE0, 0x23FFFDFF, 0x00000000, 0xFC00FFC3, 0xFC7FFFE0, 0x2FFBFFFF, 0x0000007F, 0x00100000,
    0xFFFFFFFE, 0x07FFFFFF, 0x0FFFFFFF, 0x00000000, 0xFEF02596, 0x200DECAE, 0x33FF005F, 0x00000000,
    0x0007FFF1, 0x3C0003FF, 0xFFFFFEFF, 0x00001FFF, 0x00000F20, 0x00000000, 0x001F0000, 0x00000000,
    0xFFFFFFFF, 0x800007FF, 0x3C3FFFFF, 0xFFE1C062, 0x03FF4003, 0xFFFFFFFF, 0xFFFF003F, 0x1FFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFF07, 0xFFFFFFFF, 0x03FFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0x3D7F3DFF, 0xFFFFFFFF, 0xFFFF3DFF, 0x7F3DFFFF, 0xFF7FFF3D, 0xFFFFFFFF,
    0xFF3DFFFF, 0xFFFFFFFF, 0x07FFFFFF, 0x000001FE, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x001FFFFF,
    0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x007FFFFF, 0x1FFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0x0001FFFF,
    0x0003DFFF, 0x0063FFFF, 0x0003FFFF, 0x0001DFFF, 0xFFFFFFFF, 0x000FFFFF, 0x17F00000, 0x000003FF,
    0x03FF07FF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00FFFFFF, 0xFFFFFFFF, 0x000005FF, 0x00000000, 0x00000000,
    0x1FFFFFFF, 0x00000000, 0xFFFFFFF0, 0x001F3FFF, 0xFFFFFFFF, 0x000003FF, 0xC3FF00FE, 0x00000000,
    0xC07FFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0xFFFFFFE0, 0x000FFFFF, 0xFFFF0FE0, 0x00000001, 0xFFFFFFF8, 0x03FFC001, 0x00000000, 0x00000000,
    0xFFFFFFFF, 0xF800000F, 0xFFFFE3FF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, 0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF,
    0xFFFF0000, 0xFFFF00FF, 0x7FFBFFEF, 0xE0020000, 0x001F6000, 0x00000000, 0x00000000, 0x00000000,
    0x3E2FFC84, 0xF3FFBD50, 0x000043E0, 0xFFFFFFFF, 0x000001FF, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000600, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x003FFF00, 0x00000000, 0x00000000, 0x00000060, 0x0000FFC0,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x01FFFFF8, 0x00000000, 0x0F000000, 0x30000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0xFFFFFFFF, 0xFFFF7FFF, 0x7FFFFFFF, 0x3FFEFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xDE00001F,
    0xFFFFFFFF, 0xFFFF003F, 0xFFFFFFFF, 0x0000803F, 0x007FFFFF, 0x7F7F7F7F, 0x7F7F7F7F, 0x00000000,
    0xFFFFFFFF, 0x00017FFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0xFFF3FFEF, 0x3F3F03FE, 0xFFFFFFFE, 0xFFFFFFFF, 0xE07FFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFE0, 0xFFFE3FFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00007FFF, 0x00FFFFFF, 0x00000000, 0xFFFF0000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x003FFFFF, 0x00000000, 0x00000000,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000000F, 0x00000000,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00001FFF, 0x00000000, 0x00000000, 0x00000000,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0x00000FFF, 0xFFFFFFFF, 0x40087FFC, 0x00FFFFFF, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0x000018FF, 0x00000000, 0x00000000, 0xF8000000,
    0xFFFFF7BB, 0x00000007, 0xFFFFFFFF, 0x00FFFFFF, 0xFFFFFFFC, 0x000FFFFF, 0x03FFC000, 0x00000000,
    0xFFFFFFFF, 0xFFFFC03F, 0x8000007F, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0xFFFFFFFF, 0x000001FF, 0xF3FF0FF7, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFF3FFF, 0xFFFFFFFF, 0xFFFF07FF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, 0x00000000,
    0xA0F8007F, 0x5F7FFDFF, 0xFFFFFFDB, 0xFFFFFFFF, 0xFFFFFFFF, 0x0003FFFF, 0xFFF80000, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0xFFFFFFFF, 0xFFFCFFFF, 0xFFFFFFFF, 0x000000FF, 0x0FFF0000,
    0x03FF0000, 0xFFFF0000, 0xFFF7FFFF, 0xFFDF0D0B, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x9FFFFFFF,
    0x8FFFF7EE, 0xBFFFFFFF, 0xAFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFE, 0x1CFCFCFC, 0x00000000
};

enginefuncs_t g_engfuncs;
globalvars_t *gpGlobals;

extern void PF_MessageEnd_I();

char g_originalBytes[5];
char g_patchedBytes[5];

bool PatternMemoryEqual(const void* memory, const int* pattern, int size) {
    for (int i = 0; i < size; i++) {
        if (pattern[i] == -1)
            continue;
        if (((byte *)memory)[i] == pattern[i])
            continue;

        return false;
    }

    return true;
}

uintptr_t FindMemoryByPattern(void* startPtr, string pattern) {
    pattern.erase(std::remove_if(pattern.begin(), pattern.end(), [](char c) {
        return std::isspace(static_cast<unsigned char>(c));
    }), pattern.end());

    auto HexDigitToNum = [](char hexDigit) -> int { return ('0' <= hexDigit && hexDigit <= '9') ? (hexDigit - '0') : ((hexDigit - 'A') + 10); };

    auto searchSize = pattern.length() / 2;

    auto search = std::make_unique<int[]>(searchSize);
    for (size_t i = 0; i < searchSize; i++) {
        if (pattern[2 * i] == '?')
            search[i] = -1;
        else
            search[i] = ((byte)HexDigitToNum(pattern[2 * i]) << 4) | ((byte)HexDigitToNum(pattern[2 * i + 1]));
    }

    auto codeBase = (uintptr_t)startPtr;

    for (auto codePtr = codeBase; ; codePtr++) {
        if (PatternMemoryEqual((const void *)codePtr, search.get(), searchSize)) {
            return codePtr;
        }
    }
}

#ifndef _WIN32

#include <fcntl.h>
#include <link.h>
#include <sys/mman.h>

uintptr_t FindSymbol(void *handle, const char *symbolName)
{
    link_map *dlmap;
    struct stat dlstat;
    int dlfile;
    uintptr_t map_base;
    Elf32_Ehdr *file_hdr;
    Elf32_Shdr *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
    Elf32_Sym *symtab;
    const char *shstrtab, *strtab;
    uint16_t section_count;
    uint32_t symbol_count;
    uintptr_t address;

    // let's give it a chance
    address = (uintptr_t)dlsym(handle, symbolName);
    if (address)
        return address;

    dlmap = (struct link_map *)handle;
    symtab_hdr = nullptr;
    strtab_hdr = nullptr;

    dlfile = open(dlmap->l_name, O_RDONLY);
    if (dlfile == -1 || fstat(dlfile, &dlstat) == -1) {
        close(dlfile);
        return 0;
    }

    // Map library file into memory
    file_hdr = (Elf32_Ehdr *)mmap(nullptr, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
    map_base = (uintptr_t)file_hdr;
    close(dlfile);
    if (file_hdr == MAP_FAILED)
        return 0;

    if (file_hdr->e_shoff == 0 || file_hdr->e_shstrndx == SHN_UNDEF) {
        munmap(file_hdr, dlstat.st_size);
        return 0;
    }

    sections = (Elf32_Shdr *)(map_base + file_hdr->e_shoff);
    section_count = file_hdr->e_shnum;

    // Get ELF section header string table
    shstrtab_hdr = &sections[file_hdr->e_shstrndx];
    shstrtab = (const char *)(map_base + shstrtab_hdr->sh_offset);

    // Iterate sections while looking for ELF symbol table and string table
    for (uint16_t i = 0; i < section_count; i++)
    {
        Elf32_Shdr &hdr = sections[i];
        const char *section_name = shstrtab + hdr.sh_name;
        if (strcmp(section_name, ".symtab") == 0) {
            symtab_hdr = &hdr;
        }
        else if (strcmp(section_name, ".strtab") == 0) {
            strtab_hdr = &hdr;
        }
    }

    if (!symtab_hdr || !strtab_hdr) {
        munmap(file_hdr, dlstat.st_size);
        return 0;
    }

    symtab = (Elf32_Sym *)(map_base + symtab_hdr->sh_offset);
    strtab = (const char *)(map_base + strtab_hdr->sh_offset);
    symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize;

    // Iterate symbol table
    for (uint32_t i = 0; i < symbol_count; i++)
    {
        Elf32_Sym &sym = symtab[i];
        unsigned char sym_type = ELF32_ST_TYPE(sym.st_info);
        const char *sym_name = strtab + sym.st_name;

        // Skip symbols that are undefined or do not refer to functions or objects
        if (sym.st_shndx == SHN_UNDEF ||
            (sym_type != STT_FUNC && sym_type != STT_OBJECT))
            continue;

        if (strcmp(sym_name, symbolName) == 0) {
            address = (uintptr_t)(dlmap->l_addr + sym.st_value);
            break;
        }
    }

    munmap(file_hdr, dlstat.st_size);
    return address;
}
#endif

struct {
    const char *buffername;
    uint16 flags;
    byte *data;
    int maxsize;
    int cursize;
} *g_msgBuffer;
int *g_msgType;

#ifndef _WIN32
#include <sys/mman.h>
#ifndef PAGESIZE
constexpr auto PAGESIZE = 0x1000;
#endif
#endif

void Init() {
    string gameName = GET_GAME_INFO(PLID, GINFO_NAME);
    if (gameName != "cstrike" && gameName != "czero") {
        return;
    }
#ifdef _WIN32
    bool isReHLDS = false;
    {
        auto swds = GetModuleHandleA("swds.dll");
        if (swds != nullptr) {
            auto createInterface = GetProcAddress(swds, "CreateInterface");
            if (((void* (*)(const char*, void*))createInterface)("VREHLDS_HLDS_API_VERSION001", nullptr) != nullptr) {
                isReHLDS = true;
            }
        }
    }

    if (isReHLDS) {
        uintptr_t addr = FindMemoryByPattern(g_engfuncs.pfnMessageEnd, "F6 05 ?? ?? ?? ?? 02 0F 85 ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 83");
        g_msgBuffer = decltype(g_msgBuffer)(*(uintptr_t *)(addr + 2) - offsetof(remove_pointer_t<decltype(g_msgBuffer)>, flags));
        g_msgType = *(int **)(addr + 15);
    } else {
        uintptr_t addr = FindMemoryByPattern(g_engfuncs.pfnMessageEnd, "F6 05 ?? ?? ?? ?? 02 74 11 68 ?? ?? ?? ?? E8 ?? ?? ?? ?? 83 C4 ?? 5F 5E 5B C3 8B");
        g_msgBuffer = decltype(g_msgBuffer)(*(uintptr_t *)(addr + 2) - offsetof(remove_pointer_t<decltype(g_msgBuffer)>, flags));
        g_msgType = *(int **)(addr + 28);
    }

    DWORD oldProtect;
    VirtualProtect(g_engfuncs.pfnMessageEnd, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
    memcpy(g_originalBytes, g_engfuncs.pfnMessageEnd, 5);
    g_patchedBytes[0] = char(0xE9);
    *(uint32_t*)&g_patchedBytes[1] = (uint32_t)&PF_MessageEnd_I - ((uint32_t)g_engfuncs.pfnMessageEnd + 5);
    memcpy(g_engfuncs.pfnMessageEnd, g_patchedBytes, 5);
    VirtualProtect(g_engfuncs.pfnMessageEnd, 5, oldProtect, &oldProtect);
#else
    Dl_info dlinfo;
    dladdr((void*)g_engfuncs.pfnMessageEnd, &dlinfo);

    auto handle = dlopen(dlinfo.dli_fname, RTLD_NOW);

    g_msgBuffer = (decltype(g_msgBuffer))FindSymbol(handle, "gMsgBuffer");
    if (g_msgBuffer != nullptr) {
        g_msgType = (decltype(g_msgType))FindSymbol(handle, "gMsgType");
    } else {
        uintptr_t addr = FindMemoryByPattern((void*)g_engfuncs.pfnMessageEnd, "F6 05 ?? ?? ?? ?? 02 0F 85 ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 83");
        g_msgBuffer = decltype(g_msgBuffer)(*(uintptr_t *)(addr + 2) - offsetof(remove_pointer_t<decltype(g_msgBuffer)>, flags));
        g_msgType = *(int **)(addr + 15);
    }

    dlclose(handle);

    uintptr_t addr = (uintptr_t)g_engfuncs.pfnMessageEnd;
    mprotect((void*)(addr/PAGESIZE*PAGESIZE), 5 + addr%PAGESIZE, PROT_EXEC | PROT_READ | PROT_WRITE);
    memcpy(g_originalBytes, (void*)g_engfuncs.pfnMessageEnd, 5);
    g_patchedBytes[0] = char(0xE9);
    *(uint32_t*)&g_patchedBytes[1] = (uint32_t)&PF_MessageEnd_I - ((uint32_t)g_engfuncs.pfnMessageEnd + 5);
    memcpy((void*)g_engfuncs.pfnMessageEnd, g_patchedBytes, 5);
    mprotect((void*)(addr/PAGESIZE*PAGESIZE), 5 + addr%PAGESIZE, PROT_EXEC | PROT_READ);
#endif
}

C_DLLEXPORT
#ifdef _WIN32
__declspec(naked)
#endif
void GiveFnptrsToDll(enginefuncs_t *pEngFuncs, globalvars_t *pGlobalVars) {
#ifdef _WIN32
    __asm
    {
        push ebp
        mov  ebp, esp
        sub  esp, __LOCAL_SIZE
        push ebx
        push esi
        push edi
    }
#endif

    memcpy(&g_engfuncs, pEngFuncs, sizeof(g_engfuncs));
    gpGlobals = pGlobalVars;

#ifdef _WIN32
    __asm
    {
        pop edi
        pop esi
        pop ebx
        mov esp, ebp
        pop ebp
        ret 8
    }
#endif
}

C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) {
    pFunctionTable->pfnClientCommand = &OnClientCommand_PreHook;
    pFunctionTable->pfnClientUserInfoChanged = &OnClientUserInfoChanged_PreHook;

    return TRUE;
}

C_DLLEXPORT int GetEntityAPI2_Post(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) {
    pFunctionTable->pfnServerActivate = &OnServerActivate_PostHook;

    return TRUE;
}

template <typename T>
T Min(T a, T b) {
    return (a < b) ? a : b;
}

size_t GetPluginRelPath(char *path, size_t maxPathLength) {
    const char *pluginAbsPath = GET_PLUGIN_PATH(PLID);
    const char *gamedirAbsPath = GET_GAME_INFO(PLID, GINFO_GAMEDIR);
    const char *pluginRelPath = &pluginAbsPath[strlen(gamedirAbsPath) + 1]; // + slash

    // Find last slash
    const char *searchChar = pluginRelPath + strlen(pluginRelPath) - 1; // go to string end

    while (true) {
        if (*searchChar == '/' || *searchChar == '\\') {
            break; // ok we found it
        }

        searchChar--;
    }

    size_t charsToCopy = Min((size_t)searchChar - (size_t)pluginRelPath + 1, maxPathLength); // with slash
    strncpy(path, pluginRelPath, charsToCopy);
    path[charsToCopy] = '\0';

    return charsToCopy;
}

void CheckedCommands(const std::string& cfgFileName) {
    std::ifstream cfgFile(cfgFileName);
    if (!cfgFile.is_open()) {
        std::cerr << "Couldn't open " << cfgFileName << std::endl;
        //cfgFile.close();
        return;
    }

    std::string line;
    while (std::getline(cfgFile, line)) {
        size_t equalPos = line.find('=');
        if (equalPos != std::string::npos) {
            std::string commandsStr = line.substr(equalPos + 1);
            std::istringstream iss(commandsStr);
            std::string command;
            while (std::getline(iss, command, ',')) {
                command.erase(0, command.find_first_not_of(" "));
                command.erase(command.find_last_not_of(" ") + 1);
                if (command != "CheckCommand") {
                    StoredCfgCommands.insert(command);
                }
            }
        }
    }
    cfgFile.close();
}

void ExecPluginConfig() {
    static char loadCFGFile[300];
    if (loadCFGFile[0] == '\0') {
        char *pos;

        strcpy(loadCFGFile, GET_PLUGIN_PATH(PLID));

        pos = strrchr(loadCFGFile, '/');
        if(pos == nullptr || *pos == '\0') {
            return FALSE;
        }
        *(pos + 1) = '\0';

        strcat(loadCFGFile, Plugin_info.name);
        strcat(loadCFGFile, ".cfg");
        CheckedCommands(loadCFGFile);
    }

    loadCFGFile[0] = '\0';

    if (loadCFGFile[0] == '\0') {
        char relPath[260];
        GetPluginRelPath(relPath, sizeof(relPath) - 1);
        snprintf(loadCFGFile, sizeof(loadCFGFile) - 1, "exec \"%s%s.cfg\"\n", relPath, Plugin_info.name);
    }

    SERVER_COMMAND(loadCFGFile);
    SERVER_EXECUTE();
}

void OnServerActivate_PostHook(edict_t *pEdictList, int edictCount, int maxClients) {
    ExecPluginConfig();

    //RETURN_META(MRES_IGNORED);
}

cvar_t *g_pcvarChatReplaceAmpersandSign;
cvar_t *g_pcvarChatRemoveColors;
cvar_t *g_pcvarChatReplacePlusSign;
cvar_t *g_pcvarChatReplaceHatSign;

void FromUtf8ToUtf16(char16_t *out, const char *in) {
    while (*in != '\0') {
        if (*in == '&' && g_pcvarChatReplaceAmpersandSign->value) {
            *out++ = u'&';
            in++;
        } else if ((*in == '+' && g_pcvarChatReplacePlusSign->value) || (*in == '^' && g_pcvarChatReplaceHatSign->value) ||
            ((*in == '' || *in == '' || *in == '' || *in == '') && g_pcvarChatRemoveColors->value)) {
            *out++ = u' ';
            in++;
        } else {
            if (0x0 < *in && *in < 0x80) {
                *out++ = (char16_t)*in++;
            } else if ((*in & 0xE0) == 0xC0) {
                *out = (char16_t)(*in++ & 0x1F) << 6;

                if (*in != '\0') {
                    *out++ |= (char16_t)(*in++ & 0x3F);
                }
            } else if ((*in & 0xF0) == 0xE0) {
                *out = (char16_t)(*in++ & 0x0F) << 12;

                if (*in != '\0') {
                    *out |= (char16_t)(*in++ & 0x3F) << 6;

                    if (*in != '\0') {
                        *out++ |= (char16_t)(*in++ & 0x3F);
                    }
                }
            } else {
                in++;
            }
        }
    }
    *out = u'\0';
}


void FromUtf16ToUtf8(char *out, const char16_t *in) {
    while (*in != u'\0') {
        if (*in < 0x80) {
            *out++ = (char)*in++;
        } else if (*in < 0x800) {
            *out++ = 0xC0 | (char)(*in >> 6);
            *out++ = 0x80 | (char)(*in++ & 0x3F);
        } else {
            *out++ = 0xE0 | (char)(*in >> 12);
            *out++ = 0x80 | (char)((*in >> 6) & 0x3F);
            *out++ = 0x80 | (char)(*in++ & 0x3F);
        }
    }
    *out = '\0';
}

bool IsUtf16CharPrintable(char16_t ch) {
    return (g_isPrintTable[ch / 32] & (1 << (ch % 32))) != 0;
}

bool IsUtf16CharMeanSpace(char16_t ch) {
    switch (ch) {
        case 0x0020:
        case 0x0082:   // BREAK PERMITTED HERE
        case 0x0083:   // NO BREAK PERMITTED HERE
        case 0x00A0:   // NO-BREAK SPACE
        case 0x034F:   // COMBINING GRAPHEME JOINER
        case 0x1680:
        case 0x180E:
        case 0x2000:   // EN QUAD
        case 0x2001:   // EM QUAD
        case 0x2002:   // EN SPACE
        case 0x2003:   // EM SPACE
        case 0x2004:   // THICK SPACE
        case 0x2005:   // MID SPACE
        case 0x2006:   // SIX SPACE
        case 0x2007:   // figure space
        case 0x2008:   // PUNCTUATION SPACE
        case 0x2009:   // THIN SPACE
        case 0x200A:   // HAIR SPACE
        case 0x200B:   // ZERO-WIDTH SPACE
        case 0x200C:   // ZERO-WIDTH NON-JOINER
        case 0x200D:   // ZERO WIDTH JOINER
        case 0x2028:   // LINE SEPARATOR
        case 0x2029:   // PARAGRAPH SEPARATOR
        case 0x202F:   // NARROW NO-BREAK SPACE
        case 0x205F:
        case 0x2060:   // word joiner
        case 0x3000:
        case 0xFEFF:   // ZERO-WIDTH NO BREAK SPACE
        case 0xFFFC:   // OBJECT REPLACEMENT CHARACTER
            return true;
    }

    return false;
}

cvar_t g_cvarVersion = {
    "SNAC_Version",
    Plugin_info.version,
    FCVAR_EXTDLL | FCVAR_SERVER,
    0,
    nullptr
};

// all symbols ?? - AND = too ?

cvar_t g_cvarChatReplaceNumberSign = {
    "SNAC_Chat_ReplaceNumberSign",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarChatReplacePercentSign = {
    "SNAC_Chat_ReplacePercentSign",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarChatReplaceAmpersandSign = {
    "SNAC_Chat_ReplaceAmpersandSign",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarChatReplacePlusSign = {
    "SNAC_Chat_ReplacePlusSign",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarChatReplaceHatSign = {
    "SNAC_Chat_ReplaceHatSign",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarChatRemoveUnprintable = {
    "SNAC_Chat_RemoveUnprintable",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarChatRemoveColors = {
    "SNAC_Chat_RemoveColors",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarChatTrimSpaces = {
    "SNAC_Chat_TrimSpaces",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarChatTruncateToEngineLimitAfterReplace = {
    "SNAC_Chat_TruncateToEngineLimitAfterReplace",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};

cvar_t g_cvarNameReplaceNumberSign = {
    "SNAC_Name_ReplaceNumberSign",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarNameReplacePercentSign = {
    "SNAC_Name_ReplacePercentSign",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarNameReplaceAmpersandSign = {
    "SNAC_Name_ReplaceAmpersandSign",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarNameReplacePlusSign = {
    "SNAC_Name_ReplacePlusSign",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarNameReplaceHatSign = {
    "SNAC_Name_ReplaceHatSign",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarNameRemoveUnprintable = {
    "SNAC_Name_RemoveUnprintable",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarNameRemoveColors = {
    "SNAC_Name_RemoveColors",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};
cvar_t g_cvarNameTrimSpaces = {
    "SNAC_Name_TrimSpaces",
    "1",
    FCVAR_EXTDLL,
    0,
    nullptr
};

cvar_t *g_pcvarChatReplaceNumberSign;
cvar_t *g_pcvarChatReplacePercentSign;
cvar_t *g_pcvarChatRemoveUnprintable;
cvar_t *g_pcvarChatTrimSpaces;
cvar_t *g_pcvarChatTruncateToEngineLimitAfterReplace;

cvar_t *g_pcvarNameReplaceNumberSign;
cvar_t *g_pcvarNameReplacePercentSign;
cvar_t *g_pcvarNameReplaceAmpersandSign;
cvar_t *g_pcvarNameReplacePlusSign;
cvar_t *g_pcvarNameReplaceHatSign;
cvar_t *g_pcvarNameRemoveUnprintable;
cvar_t *g_pcvarNameRemoveColors;
cvar_t *g_pcvarNameTrimSpaces;

void OnClientCommand_PreHook(edict_t *pPlayerEntity) {
    if (!g_pcvarChatReplaceNumberSign->value &&
        !g_pcvarChatReplacePercentSign->value &&
        !g_pcvarChatReplaceAmpersandSign->value &&
        !g_pcvarChatReplacePlusSign->value &&
        !g_pcvarChatReplaceHatSign->value &&
        !g_pcvarChatRemoveUnprintable->value &&
        !g_pcvarChatRemoveColors->value &&
        !g_pcvarChatTrimSpaces->value) {
        RETURN_META(MRES_IGNORED);
    }

    const char *commandName = CMD_ARGV(0);
    if (StoredCfgCommands.find(commandName) != StoredCfgCommands.end() && CMD_ARGC() > 1) {
        const char *origArgs = CMD_ARGS();

        bool restoreQuotes = false;
        if (*origArgs == '"') {
            origArgs++;
            *(char *)&origArgs[strlen(origArgs) - 1] = '\0';
            restoreQuotes = true;
        }

        char16_t utf16OrigArgs[196];
        FromUtf8ToUtf16(utf16OrigArgs, origArgs);

        char16_t utf16Args[196];
        size_t n = 0;
        bool isStrBegin = true;
        size_t lastNonSpacePos = 0;
        for (size_t i = 0; utf16OrigArgs[i] != '\0'; i++) {
            if (!IsUtf16CharPrintable(utf16OrigArgs[i]) && g_pcvarChatRemoveUnprintable->value) {
                continue;
            }
            if (IsUtf16CharMeanSpace(utf16OrigArgs[i]) && g_pcvarChatTrimSpaces->value) {
                if (!isStrBegin) {
                    utf16Args[n++] = utf16OrigArgs[i];
                }

                continue;
            }

            if (utf16OrigArgs[i] == '#' && g_pcvarChatReplaceNumberSign->value) {
                utf16Args[n++] = u'#';
            } else if (utf16OrigArgs[i] == '%' && g_pcvarChatReplacePercentSign->value) {
                utf16Args[n++] = u'%';
            } else if (utf16OrigArgs[i] == '&' && g_pcvarChatReplaceAmpersandSign->value) {
                utf16Args[n++] = u'&';
            } else if ((utf16OrigArgs[i] == '+' && g_pcvarChatReplacePlusSign->value) || (utf16OrigArgs[i] == '^' && g_pcvarChatReplaceHatSign->value) ||
                ((utf16OrigArgs[i] == '' || utf16OrigArgs[i] == '' || utf16OrigArgs[i] == '' || utf16OrigArgs[i] == '') &&
                    g_pcvarChatRemoveColors->value)) {
                utf16Args[n++] = u' ';
            } else {
                utf16Args[n++] = utf16OrigArgs[i];
            }

            lastNonSpacePos = n;
            isStrBegin = false;
        }
        utf16Args[lastNonSpacePos] = u'\0';

        if (g_pcvarChatTruncateToEngineLimitAfterReplace->value != 0.0f) {
            size_t utf8Length = 0;
            size_t maxLength = restoreQuotes ? 193 : 195;
            for (size_t i = 0; i != lastNonSpacePos; i++) {
                if (utf16Args[i] < 0x80) {
                    utf8Length++;
                } else if (utf16Args[i] < 0x800) {
                    utf8Length += 2;
                } else {
                    utf8Length += 3;
                }

                if (utf8Length > maxLength) {
                    utf16Args[i] = u'\0';
                    break;
                }
            }
        }

        if (restoreQuotes) {
            origArgs = CMD_ARGS();
            *(char *)&origArgs[0] = '"';
            FromUtf16ToUtf8((char *)&origArgs[1], utf16Args);
            size_t len = strlen(origArgs);
            *(char *)&origArgs[len++] = '"';
            *(char *)&origArgs[len] = '\0';
        } else {
            FromUtf16ToUtf8((char *)CMD_ARGS(), utf16Args);
        }
    }

    RETURN_META(MRES_IGNORED);
}

const char *GetClientName(edict_t *pClientEntity) {
    return GET_INFOKEYBUFFER(pClientEntity) + 256 + 4 + 4 + 64;
}

void OnClientUserInfoChanged_PreHook(edict_t *pPlayerEntity, char *infoBuffer) {
    if (!g_pcvarNameReplaceNumberSign->value &&
        !g_pcvarNameReplacePercentSign->value &&
        !g_pcvarNameReplaceAmpersandSign->value &&
        !g_pcvarNameReplacePlusSign->value &&
        !g_pcvarNameReplaceHatSign->value &&
        !g_pcvarNameRemoveUnprintable->value &&
        !g_pcvarNameRemoveColors->value &&
        !g_pcvarNameTrimSpaces->value) {
        RETURN_META(MRES_IGNORED);
    }

    const char *oldName = GetClientName(pPlayerEntity);
    const char *newName = INFOKEY_VALUE(infoBuffer, "name");

    if (oldName[0] == '\0' || !FStrEq(newName, oldName)) {
        char16_t utf16NewName[33];
        FromUtf8ToUtf16(utf16NewName, newName);

        char16_t utf16CorrectedName[33];
        size_t n = 0;
        bool isStrBegin = true;
        size_t lastNonSpacePos = 0;
        for (size_t i = 0; utf16NewName[i] != '\0'; i++) {
            if (!IsUtf16CharPrintable(utf16NewName[i]) && g_pcvarNameRemoveUnprintable->value) {
                continue;
            }
            if (IsUtf16CharMeanSpace(utf16NewName[i]) && g_pcvarNameTrimSpaces->value) {
                if (!isStrBegin) {
                    utf16CorrectedName[n++] = utf16NewName[i];
                }

                continue;
            }

            if((utf16NewName[i] == '#' && g_pcvarNameReplaceNumberSign->value) ||
                (utf16NewName[i] == '%' && g_pcvarNameReplacePercentSign->value) ||
                (utf16NewName[i] == '&' && g_pcvarNameReplaceAmpersandSign->value) ||
                ((utf16NewName[i] == '' || utf16NewName[i] == '' || utf16NewName[i] == '' || utf16NewName[i] == '' ) &&
                g_pcvarNameRemoveColors->value) || (n && g_pcvarNameReplacePlusSign->value && (utf16CorrectedName[n-1] == '+' ||
                utf16CorrectedName[n-1] == '"' || utf16CorrectedName[n-1] == '\'') && utf16NewName[i] <= 127 && (isdigit(utf16NewName[i]) ||
                isalpha(utf16NewName[i]))) || (utf16NewName[i] == '^' && g_pcvarNameReplaceHatSign->value)) {
                utf16CorrectedName[n++] = 0xFF00 + utf16NewName[i] - 0x20;
            } else {
                utf16CorrectedName[n++] = utf16NewName[i];
            }

            lastNonSpacePos = n;
            isStrBegin = false;
        }
        utf16CorrectedName[lastNonSpacePos] = u'\0';

        size_t utf8Length = 0;
        for (size_t i = 0; i != lastNonSpacePos; i++) {
            if (utf16CorrectedName[i] < 0x80) {
                utf8Length++;
            } else if (utf16CorrectedName[i] < 0x800) {
                utf8Length += 2;
            } else {
                utf8Length += 3;
            }

            if (utf8Length > 32) {
                utf16CorrectedName[i] = u'\0';
                break;
            }
        }

        char correctedName[33];
        FromUtf16ToUtf8(correctedName, utf16CorrectedName);
        SET_CLIENT_KEYVALUE(ENTINDEX(pPlayerEntity), infoBuffer, "name", correctedName);
    }

    RETURN_META(MRES_IGNORED);
}

plugin_info_t Plugin_info = {
    META_INTERFACE_VERSION, // ifvers
    "SafeNameAndChat",      // name
    PLUGIN_VERSION,         // version
    "2017.02.01",           // date
    "WPMG.PRoSToC0der",     // author
    "http://snac.wpmg.ru/", // url
    "SNAC",                 // logtag, all caps please
    PT_ANYTIME,             // (when) loadable
    PT_ANYTIME,             // (when) unloadable
};

meta_globals_t *gpMetaGlobals;
gamedll_funcs_t *gpGamedllFuncs;
mutil_funcs_t *gpMetaUtilFuncs;

C_DLLEXPORT int Meta_Query(char *pchInterfaceVersion, plugin_info_t **pPluginInfo, mutil_funcs_t *pMetaUtilFuncs) {
    *pPluginInfo = &Plugin_info;
    gpMetaUtilFuncs = pMetaUtilFuncs;

    return TRUE;
}

C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs) {
    pFunctionTable->pfnGetEntityAPI2 = &GetEntityAPI2;
    pFunctionTable->pfnGetEntityAPI2_Post = &GetEntityAPI2_Post;

    gpMetaGlobals = pMGlobals;
    gpGamedllFuncs = pGamedllFuncs;

    Init();

    CVAR_REGISTER(&g_cvarVersion);
    CVAR_SET_STRING(g_cvarVersion.name, g_cvarVersion.string);

    CVAR_REGISTER(&g_cvarChatReplaceNumberSign);
    CVAR_REGISTER(&g_cvarChatReplacePercentSign);
    CVAR_REGISTER(&g_cvarChatReplaceAmpersandSign);
    CVAR_REGISTER(&g_cvarChatReplacePlusSign);
    CVAR_REGISTER(&g_cvarChatReplaceHatSign);
    CVAR_REGISTER(&g_cvarChatRemoveUnprintable);
    CVAR_REGISTER(&g_cvarChatRemoveColors);
    CVAR_REGISTER(&g_cvarChatTrimSpaces);
    CVAR_REGISTER(&g_cvarChatTruncateToEngineLimitAfterReplace);

    CVAR_REGISTER(&g_cvarNameReplaceNumberSign);
    CVAR_REGISTER(&g_cvarNameReplacePercentSign);
    CVAR_REGISTER(&g_cvarNameReplaceAmpersandSign);
    CVAR_REGISTER(&g_cvarNameReplacePlusSign);
    CVAR_REGISTER(&g_cvarNameReplaceHatSign);
    CVAR_REGISTER(&g_cvarNameRemoveUnprintable);
    CVAR_REGISTER(&g_cvarNameRemoveColors);
    CVAR_REGISTER(&g_cvarNameTrimSpaces);

    g_pcvarChatReplaceNumberSign                     = CVAR_GET_POINTER(g_cvarChatReplaceNumberSign                     .name);
    g_pcvarChatReplacePercentSign                     = CVAR_GET_POINTER(g_cvarChatReplacePercentSign                 .name);
    g_pcvarChatReplaceAmpersandSign                 = CVAR_GET_POINTER(g_cvarChatReplaceAmpersandSign                 .name);
    g_pcvarChatReplacePlusSign                         = CVAR_GET_POINTER(g_cvarChatReplacePlusSign                     .name);
    g_pcvarChatReplaceHatSign                         = CVAR_GET_POINTER(g_cvarChatReplaceHatSign                     .name);
    g_pcvarChatRemoveUnprintable                     = CVAR_GET_POINTER(g_cvarChatRemoveUnprintable                     .name);
    g_pcvarChatRemoveColors                         = CVAR_GET_POINTER(g_cvarChatRemoveColors                         .name);
    g_pcvarChatTrimSpaces                             = CVAR_GET_POINTER(g_cvarChatTrimSpaces                         .name);
    g_pcvarChatTruncateToEngineLimitAfterReplace     = CVAR_GET_POINTER(g_cvarChatTruncateToEngineLimitAfterReplace     .name);

    g_pcvarNameReplaceNumberSign                     = CVAR_GET_POINTER(g_cvarNameReplaceNumberSign                     .name);
    g_pcvarNameReplacePercentSign                     = CVAR_GET_POINTER(g_cvarNameReplacePercentSign                 .name);
    g_pcvarNameReplaceAmpersandSign                 = CVAR_GET_POINTER(g_cvarNameReplaceAmpersandSign                 .name);
    g_pcvarNameReplacePlusSign                         = CVAR_GET_POINTER(g_cvarNameReplacePlusSign                     .name);
    g_pcvarNameReplaceHatSign                         = CVAR_GET_POINTER(g_cvarNameReplaceHatSign                     .name);
    g_pcvarNameRemoveUnprintable                     = CVAR_GET_POINTER(g_cvarNameRemoveUnprintable                     .name);
    g_pcvarNameRemoveColors                         = CVAR_GET_POINTER(g_cvarNameRemoveColors                         .name);
    g_pcvarNameTrimSpaces                             = CVAR_GET_POINTER(g_cvarNameTrimSpaces                         .name);

    ExecPluginConfig();

    return TRUE;
}

void Deinit() {
    string gameName = GET_GAME_INFO(PLID, GINFO_NAME);
    if (gameName != "cstrike" && gameName != "czero") {
        return;
    }
#ifdef _WIN32
    DWORD oldProtect;
    VirtualProtect(g_engfuncs.pfnMessageEnd, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
    memcpy(g_engfuncs.pfnMessageEnd, g_originalBytes, 5);
    VirtualProtect(g_engfuncs.pfnMessageEnd, 5, oldProtect, &oldProtect);
#else
    uintptr_t addr = (uintptr_t)g_engfuncs.pfnMessageEnd;
    mprotect((void*)(addr/PAGESIZE*PAGESIZE), 5 + addr%PAGESIZE, PROT_EXEC | PROT_READ | PROT_WRITE);
    memcpy((void*)g_engfuncs.pfnMessageEnd, g_originalBytes, 5);
    mprotect((void*)(addr/PAGESIZE*PAGESIZE), 5 + addr%PAGESIZE, PROT_EXEC | PROT_READ);
#endif
}

C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
    Deinit();

    return TRUE;
}

string SafePositionalPrintf(string format, vector<string> args, bool positional = true) {
    string result{};
    enum class State {
        None,
        FoundPercent,
        FoundHash,
        FoundString,
    } state = State::None;
    size_t curArg = 0;
    for (auto ch : format) {
        switch (state) {
        case State::None: {
            if (ch == '%') {
                state = State::FoundPercent;
            }
            else if (ch == '#') {
                state = State::FoundHash;
            }
            else {
                result.push_back(ch);
                state = State::None;
            }
        }
        break;
        case State::FoundPercent: {
            if (ch == 's') {
                state = State::FoundString;
            } else {
                result.push_back('%');
                if (ch != '%') {
                    result.push_back(ch);
                }
                state = State::None;
            }
        }
        break;
        case State::FoundHash: {
            if (ch == 's') {
                state = State::FoundString;
            }
            else if (ch == '%') {
                state = State::FoundPercent;
            }
            else {
                result.push_back('#');
                if (ch != '#') {
                    result.push_back(ch);
                }
                state = State::None;
            }
        }
        break;
        case State::FoundString: {
            if ('1' <= ch && ch <= '9' && ch - '1' < (int)args.size() && positional) //sau <int>
            {
                result += args[ch - '1'];
                state = State::None;
            } else if (curArg < args.size()) {
                result += args[curArg++];
                result.push_back(ch);
                state = State::None;
            } else {
                result.push_back('%');
                result.push_back('s');
                result.push_back(ch);
                state = State::None;
            }
        }
        break;
        }
    }
    if (state == State::FoundPercent) {
        result.push_back('%');
    }
    else if(state == State::FoundHash) {
        result.push_back('#');
    }
    else if (state == State::FoundString) {
        if (curArg < args.size()) {
            result += args[curArg++];
        } else {
            result.push_back('%');
            result.push_back('s');
        }
    }
    return result;
}

string FitUtf8_Helper(string str, size_t maxByteCount) {
    if (str.length() <= maxByteCount)
        return str;

    str.resize(maxByteCount + 1);

    /*bool addN = false;
    if (str[str.length() - 1] == '\n') {
        str.pop_back();
        addN = true;
    }*/

    char last = str[str.length() - 1];
    str.pop_back();
    if (((unsigned char)last & (0x80 | 0x40)) == 0x80) {
        while (true) {
            char ch = str[str.length() - 1];
            if (((unsigned char)ch & 0x80) == 0) {
                break;
            }

            str.pop_back();

            if (((unsigned char)ch & (0x80 | 0x40)) == (0x80 | 0x40)) {
                break;
            }
        }
    }

    /*if (addN) {
        str.push_back('\n');
    }*/

    return str;
}

string FitUtf8(string str, size_t maxByteCount) {
    str = FitUtf8_Helper(str, maxByteCount);

    if (str[str.length() - 1] != '\n') {
        str = FitUtf8_Helper(str, maxByteCount - 1);
        str.push_back('\n');
    }

    return str;
}

void PF_MessageEnd_I() {
    //LOG_CONSOLE(PLID, "Message end! %d %d", *g_msgType, g_msgBuffer->cursize);
    const char *temp = GET_USER_MSG_NAME(PLID, *g_msgType, nullptr);
    string msgName = temp != nullptr ? temp : "";
    if (msgName == "SayText" || msgName == "TextMsg") {
        int curPos = 0;
        int arg = 0;

        if (curPos != g_msgBuffer->cursize) {
            arg = g_msgBuffer->data[curPos];
            curPos++;
        }

        string format{};
        if (curPos != g_msgBuffer->cursize) {
            format = (const char*)&g_msgBuffer->data[curPos];
            curPos += format.length() + 1;
        }

        vector<string> args{};
        while (curPos != g_msgBuffer->cursize) {
            args.emplace_back((const char*)&g_msgBuffer->data[curPos]);
            curPos += args[args.size() - 1].length() + 1;
        }

        if (msgName == "SayText" && format[0] != '#' && !(args.size() != 0 && format.find('#') != string::npos)) {
            if (args.size() == 0) {
                g_msgBuffer->cursize = 0;
                g_msgBuffer->data[g_msgBuffer->cursize++] = arg;
                strcpy((char*)&g_msgBuffer->data[g_msgBuffer->cursize], "#Spec_PlayerItem");
                g_msgBuffer->cursize += sizeof("#Spec_PlayerItem");
                format = FitUtf8(format, 196 - g_msgBuffer->cursize - 1);
                strcpy((char*)&g_msgBuffer->data[g_msgBuffer->cursize], format.c_str());
                g_msgBuffer->cursize += format.length() + 1;
            } else {
                g_msgBuffer->cursize = 0;
                g_msgBuffer->data[g_msgBuffer->cursize++] = arg;
                strcpy((char*)&g_msgBuffer->data[g_msgBuffer->cursize], "#Spec_PlayerItem");
                g_msgBuffer->cursize += sizeof("#Spec_PlayerItem");
                if (arg != 0 && args[0] == "") {
                    args[0] = STRING(INDEXENT(arg)->v.netname);
                }
                string formatted = FitUtf8(SafePositionalPrintf(format, args), 196 - g_msgBuffer->cursize - 1);
                strcpy((char*)&g_msgBuffer->data[g_msgBuffer->cursize], formatted.c_str());
                g_msgBuffer->cursize += formatted.length() + 1;
            }
        } else if (msgName == "TextMsg" && format[0] != '#' && arg == HUD_PRINTTALK && !(args.size() != 0 && format.find('#') != string::npos)) {
            if (args.size() == 0) {
                g_msgBuffer->cursize = 0;
                g_msgBuffer->data[g_msgBuffer->cursize++] = arg;
                strcpy((char*)&g_msgBuffer->data[g_msgBuffer->cursize], "#Spec_PlayerItem");
                g_msgBuffer->cursize += sizeof("#Spec_PlayerItem");
                format = FitUtf8(format, 196 - g_msgBuffer->cursize - 1);
                strcpy((char*)&g_msgBuffer->data[g_msgBuffer->cursize], format.c_str());
                g_msgBuffer->cursize += format.length() + 1;
            } else {
                g_msgBuffer->cursize = 0;
                g_msgBuffer->data[g_msgBuffer->cursize++] = arg;
                strcpy((char*)&g_msgBuffer->data[g_msgBuffer->cursize], "#Spec_PlayerItem");
                g_msgBuffer->cursize += sizeof("#Spec_PlayerItem");
                string formatted = FitUtf8(SafePositionalPrintf(format, args), 196 - g_msgBuffer->cursize - 1);
                strcpy((char*)&g_msgBuffer->data[g_msgBuffer->cursize], formatted.c_str());
                g_msgBuffer->cursize += formatted.length() + 1;
            }
        }

        //LOG_MESSAGE(PLID, "%s: %s %s %s %s", GET_USER_MSG_NAME(PLID, *g_msgType, nullptr), format.c_str(), arg1.c_str(), arg2.c_str(), arg3.c_str());
    }

#ifdef _WIN32
    DWORD oldProtect;
    VirtualProtect(g_engfuncs.pfnMessageEnd, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
    memcpy(g_engfuncs.pfnMessageEnd, g_originalBytes, 5);
    VirtualProtect(g_engfuncs.pfnMessageEnd, 5, oldProtect, &oldProtect);
    g_engfuncs.pfnMessageEnd();
    VirtualProtect(g_engfuncs.pfnMessageEnd, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
    memcpy(g_engfuncs.pfnMessageEnd, g_patchedBytes, 5);
    VirtualProtect(g_engfuncs.pfnMessageEnd, 5, oldProtect, &oldProtect);
#else
    uintptr_t addr = (uintptr_t)g_engfuncs.pfnMessageEnd;
    mprotect((void*)(addr/PAGESIZE*PAGESIZE), 5 + addr%PAGESIZE, PROT_EXEC | PROT_READ | PROT_WRITE);
    memcpy((void*)g_engfuncs.pfnMessageEnd, g_originalBytes, 5);
    mprotect((void*)(addr / PAGESIZE*PAGESIZE), 5 + addr%PAGESIZE, PROT_EXEC | PROT_READ);
    g_engfuncs.pfnMessageEnd();
    mprotect((void*)(addr / PAGESIZE*PAGESIZE), 5 + addr%PAGESIZE, PROT_EXEC | PROT_READ | PROT_WRITE);
    memcpy((void*)g_engfuncs.pfnMessageEnd, g_patchedBytes, 5);
    mprotect((void*)(addr/PAGESIZE*PAGESIZE), 5 + addr%PAGESIZE, PROT_EXEC | PROT_READ);
#endif
}
Edit: from what i can see, color code is not printed here are they - , , ,
should look like this -
1. 1713779152647.png

2.
1713779229117.png

3.
1713779257317.png
 
Последнее редактирование:

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу