2
0
mirror of https://github.com/rehlds/rehlds.git synced 2024-12-29 08:05:50 +03:00

Merge pull request #440 from s1lentq/hltv

Add project HLTV
This commit is contained in:
s1lentq 2017-05-03 21:38:15 +03:00 committed by GitHub
commit f48ddcfadd
212 changed files with 38337 additions and 4222 deletions

View File

@ -1,51 +1,43 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Filter Include="Source Files"> <Filter Include="src">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter> </Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Text Include="ReadMe.txt" /> <Text Include="ReadMe.txt" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\src\blocksort.c"> <ClCompile Include="..\src\blocksort.c">
<Filter>Source Files</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\bzlib.c"> <ClCompile Include="..\src\bzlib.c">
<Filter>Source Files</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\compress.c"> <ClCompile Include="..\src\compress.c">
<Filter>Source Files</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\crctable.c"> <ClCompile Include="..\src\crctable.c">
<Filter>Source Files</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\decompress.c"> <ClCompile Include="..\src\decompress.c">
<Filter>Source Files</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\huffman.c"> <ClCompile Include="..\src\huffman.c">
<Filter>Source Files</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\randtable.c"> <ClCompile Include="..\src\randtable.c">
<Filter>Source Files</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\precompiled.c"> <ClCompile Include="..\src\precompiled.c">
<Filter>Source Files</Filter> <Filter>src</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\src\bzlib_private.h"> <ClInclude Include="..\src\bzlib_private.h">
<Filter>Source Files</Filter> <Filter>src</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -35,20 +35,32 @@ task publishPrepareFiles {
} }
pubRootDir.mkdirs() pubRootDir.mkdirs()
project.file('publish/publishRoot/bin/win32/valve/dlls').mkdirs()
project.file('publish/publishRoot/bin/linux32/valve/dlls').mkdirs()
// bugfixed binaries // bugfixed binaries
_copyFileToDir('publish/releaseRehldsFixes/swds.dll', 'publish/publishRoot/bin/bugfixed/') _copyFile('publish/releaseRehldsFixes/swds.dll', 'publish/publishRoot/bin/win32/swds.dll')
_copyFileToDir('publish/releaseRehldsFixes/swds.pdb', 'publish/publishRoot/bin/bugfixed/') _copyFile('publish/releaseRehldsFixes/libengine_i486.so', 'publish/publishRoot/bin/linux32/engine_i486.so')
_copyFile('publish/releaseRehldsFixes/libengine_i486.so', 'publish/publishRoot/bin/bugfixed/engine_i486.so')
// pure binaries
_copyFileToDir('publish/releaseRehldsNofixes/swds.dll', 'publish/publishRoot/bin/pure/')
_copyFileToDir('publish/releaseRehldsNofixes/swds.pdb', 'publish/publishRoot/bin/pure/')
_copyFile('publish/releaseRehldsNofixes/libengine_i486.so', 'publish/publishRoot/bin/pure/engine_i486.so')
// dedicated binaries // dedicated binaries
_copyFile('publish/hlds.exe', 'publish/publishRoot/bin/hlds.exe') _copyFile('publish/hlds.exe', 'publish/publishRoot/bin/win32/hlds.exe')
_copyFile('publish/hlds_linux', 'publish/publishRoot/bin/hlds_linux') _copyFile('publish/hlds_linux', 'publish/publishRoot/bin/linux32/hlds_linux')
// HLTV binaries
_copyFile('publish/hltv.exe', 'publish/publishRoot/bin/win32/hltv.exe')
_copyFile('publish/hltv', 'publish/publishRoot/bin/linux32/hltv')
_copyFile('publish/core.dll', 'publish/publishRoot/bin/win32/core.dll')
_copyFile('publish/libcore.so', 'publish/publishRoot/bin/linux32/core.so')
_copyFile('publish/proxy.dll', 'publish/publishRoot/bin/win32/proxy.dll')
_copyFile('publish/libproxy.so', 'publish/publishRoot/bin/linux32/proxy.so')
_copyFile('publish/demoplayer.dll', 'publish/publishRoot/bin/win32/demoplayer.dll')
_copyFile('publish/libdemoplayer.so', 'publish/publishRoot/bin/linux32/demoplayer.so')
_copyFile('publish/director.dll', 'publish/publishRoot/bin/win32/valve/dlls/director.dll')
_copyFile('publish/libdirector.so', 'publish/publishRoot/bin/linux32/valve/dlls/director.so')
// hlsdk // hlsdk
project.file('publish/publishRoot/hlsdk').mkdirs() project.file('publish/publishRoot/hlsdk').mkdirs()

View File

@ -0,0 +1,153 @@
import org.doomedsociety.gradlecpp.cfg.ToolchainConfigUtils
import org.doomedsociety.gradlecpp.msvc.MsvcToolchainConfig
import org.doomedsociety.gradlecpp.gcc.GccToolchainConfig
import org.doomedsociety.gradlecpp.toolchain.icc.Icc
import org.doomedsociety.gradlecpp.toolchain.icc.IccCompilerPlugin
import org.doomedsociety.gradlecpp.GradleCppUtils
import org.gradle.nativeplatform.NativeExecutableSpec
import org.gradle.nativeplatform.NativeExecutableBinarySpec
apply plugin: 'cpp'
apply plugin: 'windows-resources'
apply plugin: IccCompilerPlugin
apply plugin: GccCompilerPlugin
List<Task> getRcCompileTasks(NativeBinarySpec binary)
{
def linkTask = GradleCppUtils.getLinkTask(binary)
def res = linkTask.taskDependencies.getDependencies(linkTask).findAll { Task t -> t instanceof WindowsResourceCompile }
return res as List
}
void setupToolchain(NativeBinarySpec b) {
def cfg = rootProject.createToolchainConfig(b);
cfg.projectInclude(project, '/..', '/../..', '/src', '/../../common', '/../../engine', '/../../public', '/../../public/rehlds');
cfg.singleDefines 'USE_BREAKPAD_HANDLER', 'HLTV', '_CONSOLE'
if (cfg instanceof MsvcToolchainConfig) {
cfg.compilerOptions.pchConfig = new MsvcToolchainConfig.PrecompiledHeadersConfig(
enabled: true,
pchHeader: 'precompiled.h',
pchSourceSet: 'hltv_pch'
);
cfg.singleDefines('_CRT_SECURE_NO_WARNINGS')
cfg.compilerOptions.args '/Ob2', '/Oi', '/GF', '/GR-'
cfg.extraLibs "user32.lib"
}
else if (cfg instanceof GccToolchainConfig) {
cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions(
enabled: true,
pchSourceSet: 'hltv_pch'
);
cfg.compilerOptions.languageStandard = 'c++0x'
cfg.defines([
'_strdup': 'strdup',
'_stricmp': 'strcasecmp',
'_strnicmp': 'strncasecmp',
'_vsnprintf': 'vsnprintf',
'_snprintf': 'snprintf',
]);
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-fno-rtti', '-fno-exceptions'
cfg.extraLibs 'dl'
}
ToolchainConfigUtils.apply(project, cfg, b);
}
model {
buildTypes {
release
}
platforms {
x86 {
architecture "x86"
}
}
toolChains {
visualCpp(VisualCpp) {
}
icc(Icc) {
}
}
components {
hltv(NativeExecutableSpec) {
targetPlatform 'x86'
baseName 'hltv'
sources {
hltv_main(CppSourceSet) {
source {
srcDir "src"
include "**/*.cpp"
exclude "precompiled.cpp"
}
}
hltv_common(CppSourceSet) {
source {
srcDirs "../../common", "../common"
// common
include "BaseSystemModule.cpp"
include "ObjectList.cpp"
include "TokenLine.cpp"
include "textconsole.cpp"
if (GradleCppUtils.windows) {
include "TextConsoleWin32.cpp"
}
else {
include "TextConsoleUnix.cpp"
}
// HLTV common
include "random.cpp"
include "common.cpp"
}
}
hltv_engine(CppSourceSet) {
source {
srcDir "../../engine"
include "mem.cpp"
}
}
hltv_pch(CppSourceSet) {
source {
srcDir "src"
include "precompiled.cpp"
}
}
rc {
source {
srcDir "msvc"
include "hltv.rc"
}
exportedHeaders {
srcDirs "msvc"
}
}
}
binaries.all {
NativeExecutableBinarySpec b -> project.setupToolchain(b)
}
}
}
}
task buildFixes {
dependsOn binaries.withType(NativeExecutableBinarySpec).matching { NativeExecutableBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
}
}
task buildRelease {
dependsOn binaries.withType(NativeExecutableBinarySpec).matching { NativeExecutableBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
}
}

View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Console", "Console.vcxproj", "{D5CAB879-D54F-456F-8592-31D549CFD1D8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D5CAB879-D54F-456F-8592-31D549CFD1D8}.Debug|Win32.ActiveCfg = Debug|Win32
{D5CAB879-D54F-456F-8592-31D549CFD1D8}.Debug|Win32.Build.0 = Debug|Win32
{D5CAB879-D54F-456F-8592-31D549CFD1D8}.Release|Win32.ActiveCfg = Release|Win32
{D5CAB879-D54F-456F-8592-31D549CFD1D8}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\common\BaseSystemModule.h" />
<ClInclude Include="..\..\..\common\ObjectList.h" />
<ClInclude Include="..\..\..\common\textconsole.h" />
<ClInclude Include="..\..\..\common\TokenLine.h" />
<ClInclude Include="..\..\..\engine\mem.h" />
<ClInclude Include="..\..\..\game_shared\bitvec.h" />
<ClInclude Include="..\..\..\game_shared\perf_counter.h" />
<ClInclude Include="..\..\..\game_shared\voice_common.h" />
<ClInclude Include="..\..\common\common_hltv.h" />
<ClInclude Include="..\..\common\random.h" />
<ClInclude Include="..\src\precompiled.h" />
<ClInclude Include="..\src\System.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\common\BaseSystemModule.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\..\common\ObjectList.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\..\common\textconsole.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\..\common\TextConsoleUnix.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\..\common\TextConsoleWin32.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\..\common\TokenLine.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\..\engine\mem.cpp" />
<ClCompile Include="..\..\common\common.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\common\random.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\src\precompiled.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\src\public_amalgamation.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\src\System.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Image Include="icon.ico" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="hltv.rc" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D5CAB879-D54F-456F-8592-31D549CFD1D8}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Console</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<ProjectName>Console</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetName>hltv</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<TargetName>hltv</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>HLTV;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)\..\src;$(ProjectDir)\..\..\;$(ProjectDir)\..\..\..\;$(ProjectDir)\..\..\..\common;$(ProjectDir)\..\..\..\engine;$(ProjectDir)\..\..\..\public;$(ProjectDir)\..\..\..\public\rehlds;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<FullProgramDatabaseFile>false</FullProgramDatabaseFile>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
<CustomBuildStep>
<Command>echo Empty Action</Command>
<Message>Force build to run Pre-Build event</Message>
<Outputs>git.always.run</Outputs>
<Inputs>git.always.run</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>Disabled</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>HLTV;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)\..\src;$(ProjectDir)\..\..\;$(ProjectDir)\..\..\..\;$(ProjectDir)\..\..\..\common;$(ProjectDir)\..\..\..\engine;$(ProjectDir)\..\..\..\public;$(ProjectDir)\..\..\..\public\rehlds;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
<CustomBuildStep>
<Command>echo Empty Action</Command>
<Message>Force build to run Pre-Build event</Message>
<Outputs>git.always.run</Outputs>
<Inputs>git.always.run</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{9111aa50-a4d2-45d9-8e74-ae8045065799}</UniqueIdentifier>
</Filter>
<Filter Include="game_shared">
<UniqueIdentifier>{753dfdd8-0143-4b2f-8da1-0d60981a1388}</UniqueIdentifier>
</Filter>
<Filter Include="HLTV">
<UniqueIdentifier>{2fbfe7d4-1a55-4e00-a1d0-7a0fea11bdc1}</UniqueIdentifier>
</Filter>
<Filter Include="HLTV\common">
<UniqueIdentifier>{36d6fd93-a7f4-4f53-9a15-9983679abe00}</UniqueIdentifier>
</Filter>
<Filter Include="common">
<UniqueIdentifier>{26672827-46c9-4080-babb-f002c2e71cf8}</UniqueIdentifier>
</Filter>
<Filter Include="engine">
<UniqueIdentifier>{6b303ee4-f4a5-4e82-8a4d-a374240de8d0}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\precompiled.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\System.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\game_shared\bitvec.h">
<Filter>game_shared</Filter>
</ClInclude>
<ClInclude Include="..\..\..\game_shared\perf_counter.h">
<Filter>game_shared</Filter>
</ClInclude>
<ClInclude Include="..\..\..\game_shared\voice_common.h">
<Filter>game_shared</Filter>
</ClInclude>
<ClInclude Include="..\..\common\common_hltv.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="resource.h" />
<ClInclude Include="..\..\common\random.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\BaseSystemModule.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\ObjectList.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\textconsole.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\TokenLine.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\engine\mem.h">
<Filter>engine</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\precompiled.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\public_amalgamation.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\System.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\common\common.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\random.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\BaseSystemModule.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\ObjectList.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\textconsole.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\TextConsoleUnix.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\TextConsoleWin32.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\TokenLine.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\engine\mem.cpp">
<Filter>engine</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Image Include="icon.ico" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="hltv.rc" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,39 @@
@echo OFF
::
:: Post-build auto-deploy script
:: Create and fill PublishPath.txt file with path to deployment folder
:: I.e. PublishPath.txt should contain one line with a folder path
:: Call it so:
:: IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")
::
SET targetDir=%~1
SET targetName=%~2
SET targetExt=%~3
SET projectDir=%~4
SET destination=
IF NOT EXIST "%projectDir%\PublishPath.txt" (
ECHO No deployment path specified. Create PublishPath.txt near PostBuild.bat with paths on separate lines for auto deployment.
exit /B 0
)
FOR /f "tokens=* delims= usebackq" %%a IN ("%projectDir%\PublishPath.txt") DO (
ECHO Deploying to: %%a
IF NOT "%%a" == "" (
copy /Y "%targetDir%%targetName%%targetExt%" "%%a"
IF NOT ERRORLEVEL 1 (
IF EXIST "%targetDir%%targetName%.pdb" (
copy /Y "%targetDir%%targetName%.pdb" "%%a"
)
) ELSE (
ECHO PostBuild.bat ^(27^) : warning : Can't copy '%targetName%%targetExt%' to deploy path '%%a'
)
)
)
IF "%%a" == "" (
ECHO No deployment path specified.
)
exit /B 0

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

View File

@ -0,0 +1,16 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by resource.rc
//
#define IDI_ICON1 107
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,188 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "TokenLine.h"
#include "interface.h"
#include "textconsole.h"
#include "BaseSystemModule.h"
#include "ObjectList.h"
class Panel;
class System: public IBaseSystem, public BaseSystemModule {
public:
System() {}
~System() {}
double GetTime();
unsigned int GetTick();
void SetFPS(float fps);
void Printf(char *fmt, ...);
void DPrintf(char *fmt, ...);
void RedirectOutput(char *buffer, int maxSize);
IFileSystem *GetFileSystem();
unsigned char *LoadFile(const char *name, int *length);
void FreeFile(unsigned char *fileHandle);
void SetTitle(char *pszTitle);
void SetStatusLine(char *pszStatus);
void ShowConsole(bool visible);
void LogConsole(char *filename);
bool InitVGUI(IVGuiModule *module);
Panel *GetPanel();
bool RegisterCommand(char *name, ISystemModule *module, int commandID);
void GetCommandMatches(char *string, ObjectList *pMatchList);
void ExecuteString(char *commands);
void ExecuteFile(char *filename);
void Errorf(char *fmt, ...);
char *CheckParam(char *param);
bool AddModule(ISystemModule *module, char *name);
ISystemModule *GetModule(char *interfacename, char *library, char *instancename = nullptr);
bool RemoveModule(ISystemModule *module);
void Stop();
bool Init(IBaseSystem *system, int serial, char *name);
void RunFrame(double time);
void ExecuteCommand(int commandID, char *commandLine);
char *GetType();
char *GetStatusLine();
void ShutDown();
char *GetBaseDir();
#ifdef _WIN32
void BuildCommandLine(char *argv);
#else
void BuildCommandLine(int argc, char **argv);
#endif // _WIN32
void Sleep(int msec);
protected:
struct command_t {
char name[32];
int commandID;
ISystemModule *module;
};
struct library_t {
char name[MAX_PATH];
CSysModule *handle;
CreateInterfaceFn createInterfaceFn;
};
library_t *GetLibrary(char *name);
ISystemModule *FindModule(char *type, char *name = nullptr);
bool InitTimer();
bool InitFileSystem();
void Error();
void OpenLogFile(char *filename);
void CloseLogFile();
void Log(char *string);
bool DispatchCommand(char *command);
void ExecuteCommandLine();
void UpdateTime();
char *GetInput();
bool StartVGUI();
void StopVGUI();
void SetName(char *newName);
protected:
enum LocalCommandIDs {
CMD_ID_DEVELOPER = 1,
CMD_ID_EXEC,
CMD_ID_MODULES,
CMD_ID_CMDLIST,
CMD_ID_LOGFILE,
CMD_ID_QUIT,
CMD_ID_LOADMODULE,
CMD_ID_UNLOADMODULE,
CMD_ID_TITLE,
CMD_ID_SHOWCON,
CMD_ID_ECHO
};
void CMD_Developer(char *cmdLine);
void CMD_Exec(char *cmdLine);
void CMD_Title(char *cmdLine);
void CMD_Modules(char *cmdLine);
void CMD_CmdList(char *cmdLine);
void CMD_ShowCon(char *cmdLine);
void CMD_Logfile(char *cmdLine);
void CMD_Quit(char *cmdLine);
void CMD_UnloadModule(char *cmdLine);
void CMD_LoadModule(char *cmdLine);
void CMD_Echo(char *cmdLine);
struct LocalCommandID_s {
char *name;
LocalCommandIDs id;
void (System::*pfnCmd)(char *cmdLine);
};
static LocalCommandID_s m_LocalCmdReg[];
private:
double m_LastTime;
#ifdef _WIN32
CTextConsoleWin32 m_Console;
#else
CTextConsoleUnix m_Console;
#endif // _WIN32
CCounter m_Counter;
CSysModule *m_FileSystemModule;
IFileSystem *m_FileSystem;
CSysModule *m_VGUIModule;
TokenLine m_Parameters;
char m_BaseDir[MAX_PATH];
char m_StatusLine[80];
FileHandle_t m_LogFile;
char m_LogFileName[MAX_PATH];
ObjectList m_Modules;
ObjectList m_Libraries;
ObjectList m_Commands;
float m_MaxFPS;
char *m_RedirectBuffer;
unsigned int m_RedirectSize;
bool m_Developer;
unsigned int m_SerialCounter;
unsigned int m_Tick;
unsigned int m_SleepMSecs;
CreateInterfaceFn m_Factorylist[3];
bool m_VGUIStarted;
Panel *m_MainPanel;
};
extern System gSystem;
void Sys_Printf(char *fmt, ...);

View File

@ -0,0 +1 @@
#include "precompiled.h"

View File

@ -0,0 +1,19 @@
#pragma once
#include "osconfig.h"
#include "archtypes.h"
#include "mathlib.h"
#include "FileSystem.h"
#include <HLTV/IProxy.h>
#include <game_shared/counter.h>
#include "interface.h"
#include "mem.h"
#include "common.h"
#include "common/common_hltv.h"
// Console stuff
#include "System.h"
#include "common/random.h"

View File

@ -0,0 +1,3 @@
#include "precompiled.h"
#include "interface.cpp"

View File

@ -0,0 +1,154 @@
import org.doomedsociety.gradlecpp.cfg.ToolchainConfigUtils
import org.doomedsociety.gradlecpp.msvc.MsvcToolchainConfig
import org.doomedsociety.gradlecpp.toolchain.icc.Icc
import org.doomedsociety.gradlecpp.toolchain.icc.IccCompilerPlugin
import org.doomedsociety.gradlecpp.gcc.GccToolchainConfig
import org.gradle.nativeplatform.NativeBinarySpec
import org.gradle.nativeplatform.NativeLibrarySpec
import org.gradle.nativeplatform.toolchain.VisualCpp
apply plugin: 'cpp'
apply plugin: IccCompilerPlugin
apply plugin: GccCompilerPlugin
project.ext.dep_bzip2 = project(':dep/bzip2')
void setupToolchain(NativeBinarySpec b) {
def cfg = rootProject.createToolchainConfig(b);
cfg.projectInclude(project, '/..', '/../..', '/src', '/../../common', '/../../engine', '/../../public', '/../../public/rehlds', '/../../pm_shared');
cfg.projectInclude(dep_bzip2, '/include')
cfg.singleDefines 'USE_BREAKPAD_HANDLER', 'HLTV', 'CORE_MODULE'
if (cfg instanceof MsvcToolchainConfig) {
cfg.compilerOptions.pchConfig = new MsvcToolchainConfig.PrecompiledHeadersConfig(
enabled: true,
pchHeader: 'precompiled.h',
pchSourceSet: 'core_pch'
);
cfg.singleDefines('_CRT_SECURE_NO_WARNINGS')
cfg.compilerOptions.args '/Ob2', '/Oi', '/GF'
cfg.extraLibs "ws2_32.lib", "psapi.lib"
}
else if (cfg instanceof GccToolchainConfig) {
cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions(
enabled: true,
pchSourceSet: 'core_pch'
);
cfg.compilerOptions.languageStandard = 'c++0x'
cfg.defines([
'_strdup': 'strdup',
'_stricmp': 'strcasecmp',
'_strnicmp': 'strncasecmp',
'_vsnprintf': 'vsnprintf',
'_snprintf': 'snprintf',
]);
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-fno-exceptions'
}
ToolchainConfigUtils.apply(project, cfg, b);
}
model {
buildTypes {
release
}
platforms {
x86 {
architecture "x86"
}
}
toolChains {
visualCpp(VisualCpp) {
}
icc(Icc) {
}
}
components {
core(NativeLibrarySpec) {
targetPlatform 'x86'
baseName 'core'
sources {
core_main(CppSourceSet) {
source {
srcDir "src"
include "**/*.cpp"
exclude "precompiled.cpp"
}
lib project: ':dep/bzip2', library: 'bzip2', linkage: 'static'
}
core_common(CppSourceSet) {
source {
srcDirs "../../common", "../common"
// common
include "BaseSystemModule.cpp"
include "ObjectDictionary.cpp"
include "ObjectList.cpp"
include "TokenLine.cpp"
// HLTV common
include "BitBuffer.cpp"
include "byteorder.cpp"
include "common.cpp"
include "DemoFile.cpp"
include "DirectorCmd.cpp"
include "InfoString.cpp"
include "mathlib.cpp"
include "md5.cpp"
include "munge.cpp"
include "NetAddress.cpp"
include "NetChannel.cpp"
include "random.cpp"
}
}
core_engine(CppSourceSet) {
source {
srcDir "../../engine"
include "mem.cpp"
}
}
core_pch(CppSourceSet) {
source {
srcDir "src"
include "precompiled.cpp"
lib project: ':dep/bzip2', library: 'bzip2', linkage: 'static'
}
}
}
binaries.all {
NativeBinarySpec b -> project.setupToolchain(b)
}
}
}
}
task buildFixes {
dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
}
}
task buildRelease {
dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
}
}
// prevent static lib building
binaries.withType(StaticLibraryBinarySpec) { binary ->
buildable = false
}

View File

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "Core.vcxproj", "{52F752EA-73D1-422D-B805-17EF1FB20E09}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bzip2", "..\..\..\..\dep\bzip2\msvc\bzip2.vcxproj", "{792DF067-9904-4579-99B9-46C17277ADE3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{52F752EA-73D1-422D-B805-17EF1FB20E09}.Debug|Win32.ActiveCfg = Debug|Win32
{52F752EA-73D1-422D-B805-17EF1FB20E09}.Debug|Win32.Build.0 = Debug|Win32
{52F752EA-73D1-422D-B805-17EF1FB20E09}.Release|Win32.ActiveCfg = Release|Win32
{52F752EA-73D1-422D-B805-17EF1FB20E09}.Release|Win32.Build.0 = Release|Win32
{792DF067-9904-4579-99B9-46C17277ADE3}.Debug|Win32.ActiveCfg = Debug|Win32
{792DF067-9904-4579-99B9-46C17277ADE3}.Debug|Win32.Build.0 = Debug|Win32
{792DF067-9904-4579-99B9-46C17277ADE3}.Release|Win32.ActiveCfg = Release|Win32
{792DF067-9904-4579-99B9-46C17277ADE3}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,251 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{52F752EA-73D1-422D-B805-17EF1FB20E09}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Core</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetName>core</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>HLTV;WIN32;_DEBUG;_WINDOWS;_USRDLL;CORE_MODULE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>
</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)\..\src;$(ProjectDir)\..\..\;$(ProjectDir)\..\..\..\;$(ProjectDir)\..\..\..\common;$(ProjectDir)\..\..\..\engine;$(ProjectDir)\..\..\..\public;$(ProjectDir)\..\..\..\public\rehlds;$(ProjectDir)\..\..\..\pm_shared;$(ProjectDir)\..\..\..\..\dep\bzip2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>psapi.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
<CustomBuildStep>
<Command>echo Empty Action</Command>
</CustomBuildStep>
<CustomBuildStep>
<Message>Force build to run Pre-Build event</Message>
</CustomBuildStep>
<CustomBuildStep>
<Outputs>git.always.run</Outputs>
</CustomBuildStep>
<CustomBuildStep>
<Inputs>git.always.run</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>HLTV;WIN32;NDEBUG;_WINDOWS;_USRDLL;CORE_MODULE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>
</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)\..\src;$(ProjectDir)\..\..\;$(ProjectDir)\..\..\..\;$(ProjectDir)\..\..\..\common;$(ProjectDir)\..\..\..\engine;$(ProjectDir)\..\..\..\public;$(ProjectDir)\..\..\..\public\rehlds;$(ProjectDir)\..\..\..\pm_shared;$(ProjectDir)\..\..\..\..\dep\bzip2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>psapi.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
<CustomBuildStep>
<Command>echo Empty Action</Command>
</CustomBuildStep>
<CustomBuildStep>
<Message>Force build to run Pre-Build event</Message>
</CustomBuildStep>
<CustomBuildStep>
<Outputs>git.always.run</Outputs>
</CustomBuildStep>
<CustomBuildStep>
<Inputs>git.always.run</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\common\BaseSystemModule.cpp" />
<ClCompile Include="..\..\..\common\ObjectDictionary.cpp" />
<ClCompile Include="..\..\..\common\ObjectList.cpp" />
<ClCompile Include="..\..\..\common\TokenLine.cpp" />
<ClCompile Include="..\..\..\engine\mem.cpp" />
<ClCompile Include="..\..\..\hookers\HLTV\Core\DeltaEx.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\..\hookers\HLTV\Core\hooklist.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\..\hookers\HLTV\Core\main.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\BitBuffer.cpp" />
<ClCompile Include="..\..\common\byteorder.cpp" />
<ClCompile Include="..\..\common\common.cpp" />
<ClCompile Include="..\..\common\DemoFile.cpp" />
<ClCompile Include="..\..\common\DirectorCmd.cpp" />
<ClCompile Include="..\..\common\InfoString.cpp" />
<ClCompile Include="..\..\common\mathlib.cpp" />
<ClCompile Include="..\..\common\md5.cpp" />
<ClCompile Include="..\..\common\munge.cpp" />
<ClCompile Include="..\..\common\NetAddress.cpp" />
<ClCompile Include="..\..\common\NetChannel.cpp" />
<ClCompile Include="..\..\common\random.cpp" />
<ClCompile Include="..\src\BSPModel.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">precompiled.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">precompiled.h</PrecompiledHeaderFile>
</ClCompile>
<ClCompile Include="..\src\Delta.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">precompiled.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">precompiled.h</PrecompiledHeaderFile>
</ClCompile>
<ClCompile Include="..\src\NetSocket.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">precompiled.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">precompiled.h</PrecompiledHeaderFile>
</ClCompile>
<ClCompile Include="..\src\Network.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">precompiled.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">precompiled.h</PrecompiledHeaderFile>
</ClCompile>
<ClCompile Include="..\src\precompiled.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">precompiled.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">precompiled.h</PrecompiledHeaderFile>
</ClCompile>
<ClCompile Include="..\src\public_amalgamation.cpp" />
<ClCompile Include="..\src\Server.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">precompiled.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">precompiled.h</PrecompiledHeaderFile>
</ClCompile>
<ClCompile Include="..\src\World.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">precompiled.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">precompiled.h</PrecompiledHeaderFile>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\common\BaseSystemModule.h" />
<ClInclude Include="..\..\..\common\ObjectDictionary.h" />
<ClInclude Include="..\..\..\common\ObjectList.h" />
<ClInclude Include="..\..\..\common\TokenLine.h" />
<ClInclude Include="..\..\..\engine\mem.h" />
<ClInclude Include="..\..\..\hookers\HLTV\Core\DeltaEx.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\..\..\hookers\HLTV\Core\hooklist.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\..\common\BitBuffer.h" />
<ClInclude Include="..\..\common\byteorder.h" />
<ClInclude Include="..\..\common\common_hltv.h" />
<ClInclude Include="..\..\common\DemoFile.h" />
<ClInclude Include="..\..\common\DirectorCmd.h" />
<ClInclude Include="..\..\common\InfoString.h" />
<ClInclude Include="..\..\common\mathlib_internal.h" />
<ClInclude Include="..\..\common\md5.h" />
<ClInclude Include="..\..\common\munge.h" />
<ClInclude Include="..\..\common\NetAddress.h" />
<ClInclude Include="..\..\common\NetChannel.h" />
<ClInclude Include="..\..\common\net_internal.h" />
<ClInclude Include="..\..\common\random.h" />
<ClInclude Include="..\src\BSPModel.h" />
<ClInclude Include="..\src\Delta.h" />
<ClInclude Include="..\src\NetSocket.h" />
<ClInclude Include="..\src\Network.h" />
<ClInclude Include="..\src\precompiled.h" />
<ClInclude Include="..\src\Server.h" />
<ClInclude Include="..\src\World.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\dep\bzip2\msvc\bzip2.vcxproj">
<Project>{792df067-9904-4579-99b9-46c17277ade3}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,192 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{a2b59fb8-08c7-4528-89af-ade37c2610c8}</UniqueIdentifier>
</Filter>
<Filter Include="HLTV">
<UniqueIdentifier>{2c80c58c-56fb-4bd9-b106-8ed08029173e}</UniqueIdentifier>
</Filter>
<Filter Include="HLTV\common">
<UniqueIdentifier>{664fe3c6-46ae-4fa5-bf0c-f70873228f5e}</UniqueIdentifier>
</Filter>
<Filter Include="src\hookers">
<UniqueIdentifier>{fb482bcd-a131-4e66-be87-c7b0ffe6a4cf}</UniqueIdentifier>
</Filter>
<Filter Include="engine">
<UniqueIdentifier>{0997bc0d-a67f-47eb-abc1-3c7ebb128beb}</UniqueIdentifier>
</Filter>
<Filter Include="common">
<UniqueIdentifier>{3a1d44ef-34e6-4921-a2b7-ff9808b3cfad}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\BSPModel.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Delta.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\NetSocket.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Network.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Server.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\World.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\precompiled.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\common\BitBuffer.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\byteorder.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\common.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\DemoFile.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\DirectorCmd.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\InfoString.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\mathlib.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\munge.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\NetAddress.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\NetChannel.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\random.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\src\public_amalgamation.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\hookers\HLTV\Core\hooklist.cpp">
<Filter>src\hookers</Filter>
</ClCompile>
<ClCompile Include="..\..\..\hookers\HLTV\Core\main.cpp">
<Filter>src\hookers</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\BaseSystemModule.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\ObjectDictionary.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\ObjectList.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\TokenLine.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\md5.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\hookers\HLTV\Core\DeltaEx.cpp">
<Filter>src\hookers</Filter>
</ClCompile>
<ClCompile Include="..\..\..\engine\mem.cpp">
<Filter>engine</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\Network.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\Server.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\World.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\precompiled.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\common\BitBuffer.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\byteorder.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\common_hltv.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\DemoFile.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\DirectorCmd.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\InfoString.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\mathlib_internal.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\munge.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\NetAddress.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\NetChannel.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\random.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\net_internal.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\src\BSPModel.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\NetSocket.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\Delta.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\hookers\HLTV\Core\hooklist.h">
<Filter>src\hookers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\BaseSystemModule.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\ObjectDictionary.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\ObjectList.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\TokenLine.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\md5.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\hookers\HLTV\Core\DeltaEx.h">
<Filter>src\hookers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\engine\mem.h">
<Filter>engine</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,39 @@
@echo OFF
::
:: Post-build auto-deploy script
:: Create and fill PublishPath.txt file with path to deployment folder
:: I.e. PublishPath.txt should contain one line with a folder path
:: Call it so:
:: IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")
::
SET targetDir=%~1
SET targetName=%~2
SET targetExt=%~3
SET projectDir=%~4
SET destination=
IF NOT EXIST "%projectDir%\PublishPath.txt" (
ECHO No deployment path specified. Create PublishPath.txt near PostBuild.bat with paths on separate lines for auto deployment.
exit /B 0
)
FOR /f "tokens=* delims= usebackq" %%a IN ("%projectDir%\PublishPath.txt") DO (
ECHO Deploying to: %%a
IF NOT "%%a" == "" (
copy /Y "%targetDir%%targetName%%targetExt%" "%%a"
IF NOT ERRORLEVEL 1 (
IF EXIST "%targetDir%%targetName%.pdb" (
copy /Y "%targetDir%%targetName%.pdb" "%%a"
)
) ELSE (
ECHO PostBuild.bat ^(27^) : warning : Can't copy '%targetName%%targetExt%' to deploy path '%%a'
)
)
)
IF "%%a" == "" (
ECHO No deployment path specified.
)
exit /B 0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include <HLTV/IBSPModel.h>
#include "l_studio.h"
#include "edict.h"
// values for model_t's needload
#define NL_PRESENT 0
#define NL_NEEDS_LOADED 1
#define NL_UNREFERENCED 2
const int MAX_WORLD_SIZE = 32000;
class IBaseSystem;
class BSPModel: public IBSPModel {
public:
BSPModel() {}
virtual ~BSPModel() {}
void Init(IBaseSystem *system);
void Clear();
bool Load(const char *name, bool minimal);
bool IsValid();
bool IsMinimal();
void SetPVS(vec_t *point);
bool InPVS(vec_t *point);
bool TraceLine(vec_t *start, vec_t *end, vec_t *impact);
int TruePointContents(vec_t *point);
private:
void LoadTextures(lump_t *l);
void LoadEdges(lump_t *l);
bool LoadFromBuffer(unsigned int *buffer, int length, const char *name);
void LoadLeafs(lump_t *l);
void LoadNodes(lump_t *l);
void LoadVisibility(lump_t *l);
void LoadPlanes(lump_t *l);
void LoadVertexes(lump_t *l);
void LoadTexinfo(lump_t *l);
void LoadClipnodes(lump_t *l);
void LoadMarksurfaces(lump_t *l);
void LoadFaces(lump_t *l);
void LoadLighting(lump_t *l);
void LoadEntities(lump_t *l);
void LoadSurfedges(lump_t *l);
int HullPointContents(hull_t *hull, int num, const vec_t *point);
bool RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, vec_t *p1, vec_t *p2, trace_t *trace);
void MakeHull0();
mleaf_t *PointInLeaf(vec_t *point);
void GetDimension(vec_t *min, vec_t *max);
mnode_t *PVSNode(mnode_t *node, vec_t *emins, vec_t *emaxs);
void PVSMark(unsigned char *ppvs);
unsigned char *LeafPVS(mleaf_t *leaf);
void DecompressPVS(unsigned char *in, unsigned char *decompressed, int byteCount);
unsigned char *DecompressVis(unsigned char *in);
void SetParent(mnode_t *node, mnode_t *parent);
protected:
model_t m_model;
enum { MODEL_MAX_PVS = 1024 };
byte m_novis[MODEL_MAX_PVS];
byte *m_base;
int m_visframecount;
mleaf_t *m_currentLeaf;
bool m_IsMinimal;
char *m_wadpath;
IBaseSystem *m_System;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,208 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "event_args.h"
#include "BaseSystemModule.h"
#define DELTA_MAX_FIELDS 56 // 7*8
#define DT_BYTE BIT(0) // A byte
#define DT_SHORT BIT(1) // 2 byte field
#define DT_FLOAT BIT(2) // A floating point field
#define DT_INTEGER BIT(3) // 4 byte integer
#define DT_ANGLE BIT(4) // A floating point angle
#define DT_TIMEWINDOW_8 BIT(5) // A floating point timestamp relative to server time
#define DT_TIMEWINDOW_BIG BIT(6) // A floating point timestamp relative to server time (with more precision and custom multiplier)
#define DT_STRING BIT(7) // A null terminated string, sent as 8 byte chars
#define DT_SIGNED BIT(31) // sign modificator
#define FDT_MARK BIT(0) // Delta mark for sending
typedef void (*encoder_t)(struct delta_s *, const unsigned char *, const unsigned char *);
typedef struct delta_encoder_s
{
struct delta_encoder_s *next;
char *name;
encoder_t conditionalencode;
} delta_encoder_t;
typedef struct delta_stats_s
{
int sendcount;
int receivedcount;
} delta_stats_t;
typedef struct delta_description_s
{
int fieldType;
char fieldName[32];
int fieldOffset;
short int fieldSize;
int significant_bits;
float premultiply;
float postmultiply;
short int flags;
delta_stats_t stats;
} delta_description_t;
typedef struct deltacallback_s
{
int numbase;
int num;
bool remove;
bool custom;
bool newbl;
int newblindex;
bool full;
int offset;
bool instanced_baseline;
} deltacallback_t;
typedef struct delta_s
{
int dynamic;
int fieldCount;
char conditionalencodename[32];
encoder_t conditionalencode;
delta_description_t *pdd;
} delta_t;
#include "hookers/HLTV/Core/DeltaEx.h"
#ifndef HOOK_HLTV
class Delta {
public:
void Init(IBaseSystem *system);
void Shutdown();
void UpdateDescriptions();
void WriteHeader(BitBuffer *stream, deltacallback_t *header);
bool WriteDelta(BitBuffer *stream, unsigned char *from, unsigned char *to, bool force, delta_t *pFields, deltacallback_t *header = nullptr);
int ParseDelta(BitBuffer *stream, unsigned char *from, unsigned char *to, delta_t *pFields);
void SetTime(double time);
void SetLargeTimeBufferSize(bool bigBuffers);
int TestDelta(unsigned char *from, unsigned char *to, delta_t *pFields);
delta_t **LookupRegistration(char *name);
void FreeDescription(delta_t **ppdesc);
private:
typedef struct delta_link_s
{
struct delta_link_s *next;
delta_description_t *delta;
} delta_link_t;
typedef struct delta_definition_s
{
char *fieldName;
size_t fieldOffset;
} delta_definition_t;
typedef struct delta_definition_list_s
{
struct delta_definition_list_s *next;
char *ptypename;
int numelements;
delta_definition_t *pdefinition;
} delta_definition_list_t;
typedef struct delta_registry_s
{
struct delta_registry_s *next;
char *name;
delta_t *pdesc;
} delta_registry_t;
delta_registry_t *GetRegistry() const { return m_DeltaRegistry; }
delta_description_t *FindField(delta_t *pFields, const char *pszField);
int FindFieldIndex(delta_t *pFields, const char *fieldname);
void SetField(delta_t *pFields, const char *fieldname);
void UnsetField(delta_t *pFields, const char *fieldname);
void SetFieldByIndex(delta_t *pFields, int fieldNumber);
void UnsetFieldByIndex(delta_t *pFields, int fieldNumber);
void ClearFlags(delta_t *pFields);
int CountSendFields(delta_t *pFields);
void MarkSendFields(unsigned char *from, unsigned char *to, delta_t *pFields);
void SetSendFlagBits(delta_t *pFields, int *bits, int *bytecount);
void WriteMarkedFields(BitBuffer *stream, unsigned char *from, unsigned char *to, delta_t *pFields);
bool CheckDelta(unsigned char *from, unsigned char *to, delta_t *pFields);
void AddEncoder(char *name, encoder_t conditionalencode);
void ClearEncoders();
encoder_t LookupEncoder(char *name);
int CountLinks(delta_link_t *plinks);
void ReverseLinks(delta_link_t **plinks);
void ClearLinks(delta_link_t **plinks);
delta_t *BuildFromLinks(delta_link_t **pplinks);
int FindOffset(int count, delta_definition_t *pdef, char *fieldname);
bool ParseType(delta_description_t *pdelta, char **pstream);
bool ParseField(int count, delta_definition_t *pdefinition, delta_link_t *pField, char **pstream);
void AddDefinition(char *name, delta_definition_t *pdef, int numelements);
void ClearDefinitions();
delta_definition_t *FindDefinition(char *name, int *count);
void SkipDescription(char **pstream);
bool ParseOneField(char **ppstream, delta_link_t **pplist, int count, delta_definition_t *pdefinition);
bool ParseDescription(char *name, delta_t **ppdesc, char *pstream);
bool Load(char *name, delta_t **ppdesc, char *pszFile);
void RegisterDescription(char *name);
void ClearRegistrations();
void ClearStats(delta_t *p);
public:
static delta_t m_MetaDelta[];
static delta_description_t m_MetaDescription[];
static delta_definition_t m_DeltaDataDefinition[];
static delta_definition_t m_EventDataDefinition[];
static delta_definition_t m_EntityDataDefinition[];
static delta_definition_t m_UsercmdDataDefinition[];
static delta_definition_t m_WeaponDataDefinition[];
static delta_definition_t m_ClientDataDefinition[];
static delta_t *m_EntityDelta;
static delta_t *m_PlayerDelta;
static delta_t *m_CustomentityDelta;
static delta_t *m_ClientDelta;
static delta_t *m_WeaponDelta;
static delta_t *m_EventDelta;
private:
friend class World;
IBaseSystem *m_System;
delta_definition_list_t *m_Defs;
delta_encoder_t *m_Encoders;
delta_registry_t *m_DeltaRegistry;
double m_Time;
bool m_LargeTime_Buffers;
};
#endif // HOOK_HLTV

View File

@ -0,0 +1,555 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
bool NetSocket::AddChannel(INetChannel *channel)
{
return m_Channels.AddTail(channel);
}
bool NetSocket::RemoveChannel(INetChannel *channel)
{
return m_Channels.Remove(channel);
}
int NetSocket::DispatchIncoming()
{
int length = 0;
int count = 0;
NetAddress from;
while ((length = ReceivePacketIntern(&from)))
{
if (length == -1)
break;
INetChannel *channel = (INetChannel *)m_Channels.GetFirst();
while (channel)
{
if (from.Equal(channel->GetTargetAddress())) {
channel->ProcessIncoming(m_Buffer, length);
break;
}
channel = (INetChannel *)m_Channels.GetNext();
}
// not found an existing channel for this address.
// create a new channel
if (!channel)
{
// do accept only connectionless (\xFF\xFF\xFF\xFF) incoming packet.
if (*(int *)m_Buffer == CONNECTIONLESS_HEADER)
{
NetPacket *p = new NetPacket;
p->time = m_System->GetTime();
p->address.FromNetAddress(&from);
p->connectionless = true;
p->seqnr = -1;
// cut connectionless data
p->data.Resize(length - 4);
p->data.WriteBuf(&m_Buffer[4], length - 4);
p->data.Reset();
m_IncomingPackets.AddHead(p);
}
}
count++;
}
return count;
}
bool NetSocket::SendPacket(NetPacket *packet)
{
return SendPacket(&packet->address, packet->data.GetData(), packet->data.CurrentSize());
}
bool NetSocket::SendPacket(NetAddress *to, const void *data, int length)
{
struct sockaddr addr;
int ret;
if (m_Network->m_FakeLoss && RandomFloat(0, 1) < m_Network->m_FakeLoss) {
return true;
}
if (length <= 0 || !data || !to) {
return true;
}
to->ToSockadr(&addr);
if (length > MAX_ROUTEABLE_PACKET)
{
ret = SendLong((const char *)data, length, 0, &addr, sizeof(addr));
}
else
{
if (length < sizeof(addr))
ret = SendShort((const char *)data, length, 0, &addr, sizeof(addr));
else
ret = sendto(m_Socket, (const char *)data, length, 0, &addr, sizeof(addr));
}
if (ret == -1)
{
int err = m_Network->GetLastErrorCode();
// wouldblock is silent
if (err == WSAEWOULDBLOCK)
return true;
if (err == WSAECONNREFUSED || err == WSAECONNRESET)
return true;
// some PPP links dont allow broadcasts
if (err == WSAEADDRNOTAVAIL)
return true;
m_System->Printf("WARNING! NetSocket::SendPacket: %s\n", m_Network->GetErrorText(err));
return false;
}
m_BytesOut += ret + UDP_HEADER_SIZE;
return true;
}
INetwork *NetSocket::GetNetwork()
{
return m_Network;
}
int NetSocket::ReceivePacketIntern(NetAddress *fromHost)
{
sockaddr from;
socklen_t fromlen = sizeof(from);
int size = recvfrom(m_Socket, (char *)m_Buffer, sizeof(m_Buffer), 0, &from, &fromlen);
if (size == -1)
{
int err = m_Network->GetLastErrorCode();
if (err != WSAEWOULDBLOCK && err != WSAECONNRESET && err != WSAECONNREFUSED)
{
if (err == WSAEMSGSIZE)
{
m_System->DPrintf("WARNING! NetSocket::ReceivePacket: Ignoring oversized network message\n");
}
else
{
m_System->DPrintf("WARNING! NetSocket::ReceivePacket: %s %d %i\n", m_Network->GetErrorText(err), err, errno);
perror("err");
}
}
return false;
}
if (size == 0 || RandomFloat(0, 1) < m_Network->m_FakeLoss) {
return 0;
}
if (size > 0 && size < 4) {
m_System->DPrintf("WARNING! NetSocket::ReceivePacket: Ignoring undersized network message\n");
return 0;
}
if (size >= MAX_UDP_PACKET) {
m_System->DPrintf("WARNING! NetSocket::ReceivePacket: Oversize packet from %s\n", fromHost->ToString());
return 0;
}
if (*(uint32 *)m_Buffer == NET_HEADER_FLAG_SPLITPACKET)
{
if (size < sizeof(SPLITPACKET))
{
m_System->Printf("Invalid split packet length %i\n", size);
return 0;
}
size = GetLong(m_Buffer, size);
}
fromHost->FromSockadr(&from);
m_BytesIn += size + UDP_HEADER_SIZE;
return size;
}
void NetSocket::Close()
{
INetChannel *channel;
while ((channel = (INetChannel *)m_Channels.RemoveHead())) {
channel->Close();
}
Flush();
m_Network->RemoveSocket(this);
shutdown(m_Socket, 2);
SOCKET_CLOSE(m_Socket);
}
bool NetSocket::JoinGroup(NetAddress *group)
{
ip_mreq mreq;
SIN_SET_ADDR(&mreq.imr_multiaddr, *(unsigned int *)&group->m_IP[0]);
SIN_SET_ADDR(&mreq.imr_interface, 0);
if (setsockopt(m_Socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq)) == SOCKET_ERROR)
{
int err = m_Network->GetLastErrorCode();
if (err != WSAEAFNOSUPPORT) {
m_System->DPrintf("WARNING! NetSocket::JoinGroup: IP_ADD_MEMBERSHIP: %s\n", m_Network->GetErrorText(err));
}
return false;
}
return true;
}
bool NetSocket::LeaveGroup(NetAddress *group)
{
ip_mreq mreq;
SIN_SET_ADDR(&mreq.imr_multiaddr, *(unsigned int *)&group->m_IP[0]);
SIN_SET_ADDR(&mreq.imr_interface, 0);
if (setsockopt(m_Socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) == SOCKET_ERROR)
{
int err = m_Network->GetLastErrorCode();
if (err != WSAEAFNOSUPPORT) {
m_System->DPrintf("WARNING! NetSocket::LeaveGroup: IP_DROP_MEMBERSHIP: %s\n", m_Network->GetErrorText(err));
}
return false;
}
return true;
}
int NetSocket::DrainChannels()
{
int count = 0;
INetChannel *channel = (INetChannel *)m_Channels.GetFirst();
while (channel)
{
if (channel->IsReadyToSend()
&& channel->KeepAlive()
&& channel->IsConnected())
{
count++;
channel->TransmitOutgoing();
}
channel = (INetChannel *)m_Channels.GetNext();
}
return count;
}
int NetSocket::GetLong(unsigned char *pData, int size)
{
unsigned int packetNumber;
unsigned int packetCount;
int sequenceNumber;
unsigned char packetID;
static int netSplitFlags[MAX_SPLIT_FRAGMENTS] = { -1, -1, -1, -1, -1 };
SPLITPACKET *pHeader = (SPLITPACKET *)pData;
sequenceNumber = pHeader->sequenceNumber;
packetID = pHeader->packetID;
packetCount = packetID & 0xF;
packetNumber = (unsigned int)packetID >> 4;
if (packetNumber >= MAX_SPLIT_FRAGMENTS || packetCount > MAX_SPLIT_FRAGMENTS)
{
m_System->Printf("Malformed packet number (%i)\n", packetNumber);
return 0;
}
if (m_NetSplitPacket.currentSequence == -1 || sequenceNumber != m_NetSplitPacket.currentSequence)
{
m_NetSplitPacket.currentSequence = sequenceNumber;
m_NetSplitPacket.splitCount = packetCount;
}
unsigned int packetPayloadSize = size - sizeof(SPLITPACKET);
if (netSplitFlags[packetNumber] == sequenceNumber)
{
m_System->DPrintf("NetSocket::GetLong: Ignoring duplicated split packet %i of %i ( %i bytes )\n", packetNumber + 1, packetCount, packetPayloadSize);
}
else
{
if (packetNumber == packetCount - 1) {
m_NetSplitPacket.totalSize = packetPayloadSize + SPLIT_SIZE * (packetCount - 1);
}
--m_NetSplitPacket.splitCount;
netSplitFlags[packetNumber] = sequenceNumber;
}
memcpy(&m_NetSplitPacket.buffer[SPLIT_SIZE * packetNumber], pHeader + 1, packetPayloadSize);
if (m_NetSplitPacket.splitCount > 0) {
return 0;
}
m_NetSplitPacket.currentSequence = -1;
if (m_NetSplitPacket.totalSize > MAX_UDP_PACKET)
{
m_System->DPrintf("WARNING! NetSocket::GetLong: Split packet too large! %d bytes\n", m_NetSplitPacket.totalSize);
return -1;
}
memcpy(pData, m_NetSplitPacket.buffer, m_NetSplitPacket.totalSize);
return m_NetSplitPacket.totalSize;
}
void NetSocket::OutOfBandPrintf(NetAddress *to, const char *format, ...)
{
va_list argptr;
char string[NET_MAX_MESSAGE];
*(int *)string = CONNECTIONLESS_HEADER;
va_start(argptr, format);
_vsnprintf(&string[4], sizeof(string) - 4, format, argptr);
va_end(argptr);
SendPacket(to, string, strlen(string) + 1);
}
void NetSocket::GetFlowStats(float *avgInKBSec, float *avgOutKBSec)
{
*avgInKBSec = m_AvgBytesIn / 1024;
*avgOutKBSec = m_AvgBytesOut / 1024;
}
NetPacket *NetSocket::ReceivePacket()
{
return (NetPacket *)m_IncomingPackets.RemoveTail();
}
void NetSocket::FreePacket(NetPacket *packet)
{
if (packet) {
delete packet;
}
}
void NetSocket::AddPacket(NetPacket *packet)
{
if (!packet->connectionless) {
m_System->DPrintf("WARNING! NetSocket::AddPacket: only connectionless packets accepted.\n");
return;
}
NetPacket *newpacket = new NetPacket;
newpacket->time = packet->time;
newpacket->address.FromNetAddress(&packet->address);
newpacket->connectionless = true;
newpacket->seqnr = -1;
newpacket->data.Resize(packet->data.GetMaxSize());
newpacket->data.WriteBuf(packet->data.GetData(), packet->data.GetMaxSize());
newpacket->data.Reset();
m_IncomingPackets.AddHead(newpacket);
}
void NetSocket::Flush()
{
NetPacket *in;
while ((in = (NetPacket *)m_IncomingPackets.RemoveTail())) {
FreePacket(in);
}
if (m_Socket != INVALID_SOCKET)
{
sockaddr from;
socklen_t fromlen = sizeof(from);
while (recvfrom(m_Socket, (char *)m_Buffer, sizeof(m_Buffer), 0, &from, &fromlen) > 0)
;
}
}
bool NetSocket::Create(Network *network, int port, bool reuse, bool loopback)
{
sockaddr_in address;
char _true = 1;
uint32 i = 1;
m_Network = network;
m_System = network->GetSystem();
m_Channels.Init();
memset(m_Buffer, 0, sizeof(m_Buffer));
memset(&m_NetSplitPacket, 0, sizeof(m_NetSplitPacket));
if ((m_Socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
return false;
}
if (SOCKET_FIONBIO(m_Socket, i) == SOCKET_ERROR) {
return false;
}
if (setsockopt(m_Socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == SOCKET_ERROR) {
return false;
}
// resue
if (reuse && setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, &_true, sizeof(_true)) == SOCKET_ERROR) {
return false;
}
if (m_Network->m_IsMultihomed)
{
m_Network->GetLocalAddress()->ToSockadr((sockaddr *)&address);
}
else
{
address.sin_addr.s_addr = 0;
}
m_Port = port;
address.sin_port = htons(port);
address.sin_family = AF_INET;
if (bind(m_Socket, (struct sockaddr *)&address, sizeof(address)) == SOCKET_ERROR) {
SOCKET_CLOSE(m_Socket);
return false;
}
// Time-To-Live (TTL) for Multicast Packets
// As the values of the TTL field increase, routers will expand the number of hops they will forward a multicast packet.
// To provide meaningful scope control, multicast routers enforce the following
// "thresholds" on forwarding based on the TTL field:
//
// 0: restricted to the same host
// 1: restricted to the same subnet
// 32: restricted to the same site
// 64: restricted to the same region
// 128: restricted to the same continent
// 255: unrestricted
uint32 ttl = 32;
char *ttlparam = m_System->CheckParam("-multicastttl");
if (ttlparam) {
ttl = atoi(ttlparam);
}
if (setsockopt(m_Socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl)) == SOCKET_ERROR) {
return false;
}
m_BytesOut = 0;
m_BytesIn = 0;
m_LastUpdateTime = 0;
m_AvgBytesOut = 0;
m_AvgBytesIn = 0;
return true;
}
int NetSocket::GetPort()
{
return m_Port;
}
void NetSocket::UpdateStats(double time)
{
float timeDiff = time - m_LastUpdateTime;
if (timeDiff > 0)
{
m_AvgBytesIn = m_BytesIn / timeDiff * 0.3 + m_AvgBytesIn * 0.6;
m_AvgBytesOut = m_BytesOut / timeDiff * 0.3 + m_AvgBytesOut * 0.6;
m_BytesIn = 0;
m_BytesOut = 0;
m_LastUpdateTime = time;
}
}
int NetSocket::SendLong(const char *pData, int len, int flags, const sockaddr *to, int tolen)
{
char packet[MAX_ROUTEABLE_PACKET];
int totalSent, ret, size, packetCount, packetNumber;
SPLITPACKET *pPacket;
if (++m_netSplitSequenceNumber < 0) {
m_netSplitSequenceNumber = 1;
}
pPacket = (SPLITPACKET *)packet;
pPacket->netID = -2;
pPacket->sequenceNumber = m_netSplitSequenceNumber;
packetNumber = 0;
totalSent = 0;
packetCount = (len + SPLIT_SIZE - 1) / SPLIT_SIZE;
while (len > 0)
{
size = min(SPLIT_SIZE, (unsigned)len);
pPacket->packetID = (packetNumber << 4) + packetCount;
memcpy(packet + sizeof(SPLITPACKET), pData + (packetNumber * SPLIT_SIZE), size);
ret = sendto(m_Socket, packet, size + sizeof(SPLITPACKET), flags, to, tolen);
if (ret < 0) {
return ret;
}
if (ret >= size) {
totalSent += size;
}
len -= size;
packetNumber++;
}
return totalSent;
}
int NetSocket::SendShort(const char *pData, int len, int flags, const sockaddr *to, int tolen)
{
if (len > MIN_ROUTEABLE_PACKET) {
m_System->DPrintf("WARNING! NetSocket::SendShort: length > MIN_ROUTEABLE_PACKET.\n");
return 0;
}
char packet[MAX_ROUTEABLE_PACKET];
memcpy(packet, pData, len);
memset(&packet[len], 0, sizeof(packet) - len);
return sendto(m_Socket, packet, sizeof(packet), flags, to, tolen);
}

View File

@ -0,0 +1,108 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include <HLTV/INetSocket.h>
class Network;
class IBaseSytem;
class NetSocket: public INetSocket {
public:
NetSocket() : m_netSplitSequenceNumber(0) {}
virtual ~NetSocket() {}
NetPacket *ReceivePacket();
void FreePacket(NetPacket *packet);
bool SendPacket(NetPacket *packet);
bool SendPacket(NetAddress *packet, const void *data, int length);
void AddPacket(NetPacket *packet);
bool AddChannel(INetChannel *channel);
bool RemoveChannel(INetChannel *channel);
INetwork *GetNetwork();
void OutOfBandPrintf(NetAddress *to, const char *format, ...);
void Flush();
void GetFlowStats(float *avgInKBSec, float *avgOutKBSec);
bool LeaveGroup(NetAddress *group);
bool JoinGroup(NetAddress *group);
void Close();
int GetPort();
bool Create(Network *network, int port, bool reuse, bool loopback);
void UpdateStats(double time);
int DrainChannels();
int DispatchIncoming();
private:
int ReceivePacketIntern(NetAddress *fromHost);
int SendLong(const char *pData, int len, int flags, const sockaddr *to, int tolen);
int SendShort(const char *pData, int len, int flags, const sockaddr *to, int tolen);
int GetLong(unsigned char *pData, int size);
protected:
int m_Port;
unsigned char m_Buffer[MAX_UDP_PACKET];
ObjectList m_IncomingPackets;
ObjectList m_Channels;
SOCKET m_Socket;
Network *m_Network;
IBaseSystem *m_System;
enum { MAX_SPLIT_FRAGMENTS = 5 };
// Use this to pick apart the network stream, must be packed
#pragma pack(push, 1)
typedef struct SPLITPACKET_t
{
int netID;
int sequenceNumber;
unsigned char packetID;
} SPLITPACKET;
#pragma pack(pop)
// Split long packets. Anything over 1460 is failing on some routers.
typedef struct LONGPACKET_t
{
int currentSequence;
int splitCount;
int totalSize;
// TODO: It should be NET_MAX_MESSAGE, but value differs
char buffer[MAX_UDP_PACKET]; // This has to be big enough to hold the largest message
} LONGPACKET;
LONGPACKET m_NetSplitPacket;
int m_netSplitSequenceNumber;
int m_netSplitFlags[MAX_SPLIT_FRAGMENTS];
int m_BytesIn;
int m_BytesOut;
double m_LastUpdateTime;
float m_AvgBytesIn;
float m_AvgBytesOut;
};

View File

@ -0,0 +1,445 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
bool Network::Init(IBaseSystem *system, int serial, char *name)
{
BaseSystemModule::Init(system, serial, name);
if (!name) {
SetName(NETWORK_INTERFACE_VERSION);
}
m_FakeLoss = 0;
m_IsMultihomed = false;
m_NoDNS = false;
m_Sockets.Init();
m_System->RegisterCommand("fakeloss", this, CMD_ID_FAKELOSS);
#ifdef _WIN32
// Startup winock
WORD version = MAKEWORD(2, 2); // for use Winsock 2.2, version should be 514
WSADATA wsaData;
int err = WSAStartup(version, &wsaData);
if (err != NO_ERROR)
{
m_System->Printf("Network Error WSAStartup:%s\n", GetErrorText(GetLastErrorCode()));
return false;
}
#endif // _WIN32
if (m_System->CheckParam("-nodns")) {
m_NoDNS = true;
}
if (ResolveAddress(m_System->CheckParam("-ip"), &m_LocalAddress))
{
m_IsMultihomed = true;
m_System->Printf("Network uses %s as host IP.\n", m_LocalAddress.ToBaseString());
}
else
{
char hostname[512];
gethostname(hostname, sizeof(hostname));
ResolveAddress(hostname, &m_LocalAddress);
}
char *portparam = m_System->CheckParam("-port");
if (!portparam) {
portparam = "27020";
}
m_LocalAddress.m_Port = htons(atoi(portparam));
m_LastStatsUpdateTime = 0;
m_State = MODULE_RUNNING;
m_System->Printf("Network initialized.\n");
return true;
}
void Network::ExecuteCommand(int commandID, char *commandLine)
{
if (commandID == CMD_ID_FAKELOSS) {
CMD_FakeLoss(commandLine);
return;
}
m_System->Printf("ERROR! Network::ExecuteCommand: unknown command ID %i.\n", commandID);
}
void Network::ShutDown()
{
if (m_State == MODULE_DISCONNECTED) {
return;
}
NetSocket *sock;
while ((sock = (NetSocket *)m_Sockets.RemoveTail()))
{
sock->Close();
delete sock;
}
#ifdef _WIN32
if (WSACleanup() == SOCKET_ERROR) {
m_System->Printf("Network Error WSACleanup:%s\n", GetErrorText(GetLastErrorCode()));
}
#endif // _WIN32
m_System->Printf("Network module shutdown.\n");
BaseSystemModule::ShutDown();
}
INetSocket *Network::CreateSocket(int port, bool reuse, bool loopback)
{
NetSocket *socket = GetSocket(port);
if (socket) {
return socket;
}
socket = new NetSocket;
if (!socket) {
m_System->Printf("ERROR! Network::CreateSocket: out of memory.\n");
return nullptr;
}
if (!socket->Create(this, port, reuse, loopback))
{
m_System->Printf("ERROR! Network::CreateSocket: %s.\n", GetErrorText(GetLastErrorCode()));
delete socket;
return nullptr;
}
m_Sockets.Add(socket);
return socket;
}
bool Network::RemoveSocket(INetSocket *netsocket)
{
return m_Sockets.Remove(netsocket);
}
char *Network::GetType()
{
return NETWORK_INTERFACE_VERSION;
}
int Network::ReceiveData()
{
int countPackets = 0;
NetSocket *sock = (NetSocket *)m_Sockets.GetFirst();
while (sock)
{
countPackets += sock->DispatchIncoming();
sock = (NetSocket *)m_Sockets.GetNext();
}
return countPackets;
}
int Network::SendData()
{
int countPackets = 0;
NetSocket *sock = (NetSocket *)m_Sockets.GetFirst();
while (sock)
{
countPackets += sock->DrainChannels();
sock = (NetSocket *)m_Sockets.GetNext();
}
return countPackets;
}
NetSocket *Network::GetSocket(int port)
{
NetSocket *sock = (NetSocket *)m_Sockets.GetFirst();
if (!sock) {
return nullptr;
}
while (sock)
{
if (sock->GetPort() == port || !port) {
return sock;
}
sock = (NetSocket *)m_Sockets.GetNext();
}
return nullptr;
}
void Network::RunFrame(double time)
{
BaseSystemModule::RunFrame(time);
SendData();
ReceiveData();
UpdateStats();
}
NetAddress *Network::GetLocalAddress()
{
return &m_LocalAddress;
}
char *Network::GetStatusLine()
{
static char string[256];
float in, out;
GetFlowStats(&in, &out);
_snprintf(string, sizeof(string), "Local IP %s, Sockets %i, In %.2f, Out %.2f.\n", m_LocalAddress.ToBaseString(), m_Sockets.CountElements(), in, out);
return string;
}
void Network::GetFlowStats(float *totalIn, float *totalOut)
{
*totalIn = 0;
*totalOut = 0;
NetSocket *sock = (NetSocket *)m_Sockets.GetFirst();
while (sock)
{
float in, out;
sock->GetFlowStats(&in, &out);
*totalIn += in;
*totalOut += out;
sock = (NetSocket *)m_Sockets.GetNext();
}
}
void Network::CMD_FakeLoss(char *cmdLine)
{
TokenLine params(cmdLine);
if (params.CountToken() != 2) {
m_System->Printf("Syntax: fakeloss <float>\n");
m_System->Printf("Current fakeloss is %.2f\n", m_FakeLoss);
return;
}
m_FakeLoss = atof(params.GetToken(1));
}
int Network::GetLastErrorCode()
{
return WSAGetLastError();
}
bool Network::ResolveAddress(char *string, NetAddress *address)
{
sockaddr sadr;
hostent *h;
char copy[128];
address->Clear();
if (!string || !strlen(string)) {
return 0;
}
memset(&sadr, 0, sizeof(sadr));
((sockaddr_in *)&sadr)->sin_family = AF_INET;
((sockaddr_in *)&sadr)->sin_port = 0;
strcopy(copy, string);
// Parse port
char *colon = copy;
while (*colon != '\0')
{
if (*colon == ':')
{
*colon = '\0';
int val = atoi(colon + 1);
((sockaddr_in *)&sadr)->sin_port = htons(val);
}
colon++;
}
// Parse address
// Validate IPv4
if (copy[0] >= '0' && copy[0] <= '9' && strstr(copy, "."))
{
uint32 ret = inet_addr(copy);
if (ret == INADDR_NONE) {
return false;
}
((sockaddr_in *)&sadr)->sin_addr.s_addr = ret;
}
else if (m_NoDNS)
{
// do not resolve address via DNS.
return false;
}
// If we allow the use of DNS,
// let's get the address by the hostname.
else
{
h = gethostbyname(copy);
if (!h || !h->h_addr) {
return false;
}
((sockaddr_in *)&sadr)->sin_addr.s_addr = *(uint32 *)h->h_addr;
}
return address->FromSockadr(&sadr);
}
char *Network::GetErrorText(int code)
{
switch (code)
{
case WSAEINTR: return "WSAEINTR";
case WSAEBADF: return "WSAEBADF";
case WSAEACCES: return "WSAEACCES";
case WSAEFAULT: return "WSAEFAULT";
case WSAEINVAL: return "WSAEINVAL";
case WSAEMFILE: return "WSAEMFILE";
case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
case WSAEINPROGRESS: return "WSAEINPROGRESS";
case WSAEALREADY: return "WSAEALREADY";
case WSAENOTSOCK: return "WSAENOTSOCK";
case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
case WSAEMSGSIZE: return "WSAEMSGSIZE";
case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
case WSAEADDRINUSE: return "WSAEADDRINUSE";
case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
case WSAENETDOWN: return "WSAENETDOWN";
case WSAENETUNREACH: return "WSAENETUNREACH";
case WSAENETRESET: return "WSAENETRESET";
case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR";
case WSAECONNRESET: return "WSAECONNRESET";
case WSAENOBUFS: return "WSAENOBUFS";
case WSAEISCONN: return "WSAEISCONN";
case WSAENOTCONN: return "WSAENOTCONN";
case WSAESHUTDOWN: return "WSAESHUTDOWN";
case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
case WSAETIMEDOUT: return "WSAETIMEDOUT";
case WSAECONNREFUSED: return "WSAECONNREFUSED";
case WSAELOOP: return "WSAELOOP";
case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
default: return "UNKNOWN ERROR";
#ifdef _WIN32
case WSASYSNOTREADY: return "WSASYSNOTREADY";
case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
case WSANOTINITIALISED: return "WSANOTINITIALISED";
case WSAEDISCON: return "WSAEDISCON";
case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
case WSATRY_AGAIN: return "WSATRY_AGAIN";
case WSANO_RECOVERY: return "WSANO_RECOVERY";
case WSANO_DATA: return "WSANO_DATA";
#endif // _WIN32
}
}
void Network::SetName(char *newName)
{
strcopy(m_Name, newName);
}
void Network::UpdateStats()
{
if (m_LastStatsUpdateTime + 0.5 > m_SystemTime) {
return;
}
NetSocket *sock = (NetSocket *)m_Sockets.GetFirst();
while (sock)
{
sock->UpdateStats(m_SystemTime);
sock = (NetSocket *)m_Sockets.GetNext();
}
m_LastStatsUpdateTime = m_SystemTime;
}
void Network::ReceiveSignal(ISystemModule *module, unsigned int signal, void *data)
{
BaseSystemModule::ReceiveSignal(module, signal, data);
}
void Network::RegisterListener(ISystemModule *module)
{
BaseSystemModule::RegisterListener(module);
}
void Network::RemoveListener(ISystemModule *module)
{
BaseSystemModule::RemoveListener(module);
}
IBaseSystem *Network::GetSystem()
{
return BaseSystemModule::GetSystem();
}
int Network::GetSerial()
{
return BaseSystemModule::GetSerial();
}
char *Network::GetName()
{
return BaseSystemModule::GetName();
}
int Network::GetState()
{
return BaseSystemModule::GetState();
}
int Network::GetVersion()
{
return BaseSystemModule::GetVersion();
}
IBaseInterface *CreateNetwork()
{
INetwork *pNetwork = new Network;
return (IBaseInterface *)pNetwork;
}
#ifndef HOOK_HLTV
EXPOSE_INTERFACE_FN(CreateNetwork, Network, NETWORK_INTERFACE_VERSION);
#endif // HOOK_HLTV

View File

@ -0,0 +1,130 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include <HLTV/INetwork.h>
#include "BaseSystemModule.h"
#ifndef _WIN32
#define WSAEWOULDBLOCK EWOULDBLOCK // Operation would block EAGAIN (11)
#define WSAEMSGSIZE EMSGSIZE // Message too long (90)
#define WSAEADDRNOTAVAIL EADDRNOTAVAIL // Cannot assign requested address (99)
#define WSAEAFNOSUPPORT EAFNOSUPPORT // Address family not supported by protocol (97)
#define WSAECONNRESET ECONNRESET // Connection reset by peer (104)
#define WSAECONNREFUSED ECONNREFUSED // Connection refused (111)
#define WSAEADDRINUSE EADDRINUSE // Address already in use (98)
#define WSAENOBUFS ENOBUFS // No buffer space available (105)
#define WSAEINTR EINTR // Interrupted system call
#define WSAEBADF EBADF // Bad file number
#define WSAEACCES EACCES // Permission denied
#define WSAEFAULT EFAULT // Bad address
#define WSAEINVAL EINVAL // Invalid argument
#define WSAEMFILE EMFILE // Too many open files
#define WSAEWOULDBLOCK EWOULDBLOCK // Operation would block
#define WSAEINPROGRESS EINPROGRESS // Operation now in progress
#define WSAEALREADY EALREADY // Operation already in progress
#define WSAENOTSOCK ENOTSOCK // Socket operation on non-socket
#define WSAEDESTADDRREQ EDESTADDRREQ // Destination address required
#define WSAEMSGSIZE EMSGSIZE // Message too long
#define WSAEPROTOTYPE EPROTOTYPE // Protocol wrong type for socket
#define WSAENOPROTOOPT ENOPROTOOPT // Protocol not available
#define WSAEPROTONOSUPPORT EPROTONOSUPPORT // Protocol not supported
#define WSAESOCKTNOSUPPORT ESOCKTNOSUPPORT // Socket type not supported
#define WSAEOPNOTSUPP EOPNOTSUPP // Operation not supported on transport endpoint
#define WSAEPFNOSUPPORT EPFNOSUPPORT // Protocol family not supported
#define WSAEAFNOSUPPORT EAFNOSUPPORT // Address family not supported by protocol
#define WSAEADDRINUSE EADDRINUSE // Address already in use
#define WSAEADDRNOTAVAIL EADDRNOTAVAIL // Cannot assign requested address
#define WSAENETDOWN ENETDOWN // Network is down
#define WSAENETUNREACH ENETUNREACH // Network is unreachable
#define WSAENETRESET ENETRESET // Network dropped connection because of reset
#define WSAECONNABORTED ECONNABORTED // Software caused connection abort
#define WSAECONNRESET ECONNRESET // Connection reset by peer
#define WSAENOBUFS ENOBUFS // No buffer space available
#define WSAEISCONN EISCONN // Transport endpoint is already connected
#define WSAENOTCONN ENOTCONN // Transport endpoint is not connected
#define WSAESHUTDOWN ESHUTDOWN // Cannot send after transport endpoint shutdown
#define WSAETOOMANYREFS ETOOMANYREFS // Too many references: cannot splice
#define WSAETIMEDOUT ETIMEDOUT // Connection timed out
#define WSAECONNREFUSED ECONNREFUSED // Connection refused
#define WSAELOOP ELOOP // Too many symbolic links encountered
#define WSAENAMETOOLONG ENAMETOOLONG // File name too long
#define WSAEHOSTDOWN EHOSTDOWN // Host is down
#endif // _WIN32
class NetSocket;
class Network: public BaseSystemModule, public INetwork {
public:
Network() {}
virtual ~Network() {}
bool Init(IBaseSystem *system, int serial, char *name);
void RunFrame(double time);
void ReceiveSignal(ISystemModule *module, unsigned int signal, void *data);
void ExecuteCommand(int commandID, char *commandLine);
void RegisterListener(ISystemModule *module);
void RemoveListener(ISystemModule *module);
IBaseSystem *GetSystem();
int GetSerial();
char *GetStatusLine();
char *GetType();
char *GetName();
int GetState();
int GetVersion();
void ShutDown();
INetSocket *CreateSocket(int port, bool reuse, bool loopback);
bool RemoveSocket(INetSocket *netsocket);
NetAddress *GetLocalAddress();
bool ResolveAddress(char *string, NetAddress *address);
void GetFlowStats(float *totalIn, float *totalOut);
int GetLastErrorCode();
char *GetErrorText(int code);
protected:
enum LocalCommandIDs { CMD_ID_FAKELOSS = 1 };
void CMD_FakeLoss(char *cmdLine);
void SetName(char *newName);
void UpdateStats();
NetSocket *GetSocket(int port);
int SendData();
int ReceiveData();
protected:
friend class NetSocket;
float m_FakeLoss;
NetAddress m_LocalAddress;
bool m_IsMultihomed;
bool m_NoDNS;
double m_LastStatsUpdateTime;
ObjectList m_Sockets;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,266 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include <HLTV/IServer.h>
#include "BaseSystemModule.h"
#include "TokenLine.h"
class IWorld;
class IProxy;
class IDirector;
class IFileSystem;
class NetPacket;
class INetSocket;
#define MAX_SERVER_RATE 20000
#define MAX_SERVER_UPDATERATE 100
#define TE_MAX 128
// Sound flags
enum
{
SND_FL_VOLUME = BIT(0), // send volume
SND_FL_ATTENUATION = BIT(1), // send attenuation
SND_FL_LARGE_INDEX = BIT(2), // send sound number as short instead of byte
SND_FL_PITCH = BIT(3), // send pitch
SND_FL_SENTENCE = BIT(4), // set if sound num is actually a sentence num
SND_FL_STOP = BIT(5), // stop the sound
SND_FL_CHANGE_VOL = BIT(6), // change sound vol
SND_FL_CHANGE_PITCH = BIT(7), // change sound pitch
SND_FL_SPAWNING = BIT(8) // we're spawning, used in some cases for ambients (not sent across network)
};
class Server: public IServer, public BaseSystemModule {
public:
Server() {}
virtual ~Server() {}
bool Init(IBaseSystem *system, int serial, char *name);
void RunFrame(double time);
void ReceiveSignal(ISystemModule *module, unsigned int signal, void *data);
void ExecuteCommand(int commandID, char *commandLine);
void RegisterListener(ISystemModule *module);
void RemoveListener(ISystemModule *module);
IBaseSystem *GetSystem();
int GetSerial();
char *GetStatusLine();
char *GetType();
char *GetName();
int GetState();
int GetVersion();
void ShutDown();
bool Connect(IWorld *world, NetAddress *address, INetSocket *socket);
bool LoadDemo(IWorld *world, char *filename, bool forceHLTV, bool continuous);
void Reconnect();
void Disconnect();
void Retry();
void StopRetry();
void SendStringCommand(char *command);
void SendHLTVCommand(BitBuffer *msg);
void SetPlayerName(char *newName);
void SetProxy(IProxy *proxy);
void SetDirector(IDirector *director);
void SetDelayReconnect(bool state);
void SetAutoRetry(bool state);
void SetVoiceBlocking(bool state);
void SetRate(int rate);
void SetUpdateRate(int updaterate);
void SetUserInfo(char *key, char *value);
bool SetProtocol(int version);
void SetGameDirectory(const char *defaultDir, const char *gameDir);
bool IsConnected();
bool IsDemoFile();
bool IsGameServer();
bool IsRelayProxy();
bool IsVoiceBlocking();
int GetRate();
int GetUpdateRate();
char *GetPlayerName();
InfoString *GetServerInfoString();
float GetTime();
IWorld *GetWorld();
char *GetDemoFileName();
NetAddress *GetAddress();
bool GetAutoRetry();
char *GetHostName();
float GetPacketLoss();
int GetProtocol();
private:
public:
void CheckAutoRetry();
void CheckConnection();
void ScheduleAutoRetry();
void AcceptConnection();
void AcceptBadPassword();
void AcceptRejection(char *reason);
void AcceptRedirect(char *toAddress);
void SendConnectPacket();
void SendServerCommands();
enum ServerState {
SERVER_UNDEFINED,
SERVER_INITIALIZING,
SERVER_DISCONNECTED,
SERVER_CHALLENGING,
SERVER_AUTHENTICATING,
SERVER_CONNECTING,
SERVER_CONNECTED,
SERVER_RUNNING,
SERVER_INTERMISSION,
};
void SetState(ServerState newState);
void Challenge();
void Reset();
void AcceptChallenge(char *cmdLine);
void SendUserVar(char *key, char *value);
char *GetCmdName(int cmd);
void SetName(char *newName);
void ProcessMessage(unsigned int seqNr);
void ProcessEntityUpdate();
bool ProcessConnectionlessMessage(NetAddress *from, BitBuffer *stream);
void ClearFrame(bool completely);
void ParseHLTV();
void ParseDirector();
void ParseFileTransferFailed();
void ParseInfo(BitBuffer *stream, bool detailed);
void ParseParticle();
void ParseRoomType();
void ParseSpawnStaticSound();
void ParseEventReliable();
void ParsePings();
void ParseStopSound();
void ParseEvent();
void ParseSound();
void ParseDeltaPacketEntities();
void ParsePacketEntities();
bool ParseUserMessage(int cmd);
void ParseCustomization();
void ParseCrosshairAngle();
void ParseSoundFade();
void ParseSignonNum();
void ParseDisconnect();
void ParseChoke();
void ParseSetAngle();
void ParseAddAngle();
void ParseLightStyle();
void ParseTime();
void ParseVersion();
void ParseBaseline();
void ParseTempEntity();
void ParseResourceList();
void ParseUpdateUserInfo();
void ParseStuffText();
void ParseNewUserMsg();
void ParseResourceRequest();
void ParseSetView();
void ParseCDTrack();
void ParseRestore();
void ParseMoveVars();
void ParseDeltaDescription();
void ParseServerinfo();
void ParseBad();
void ParseNop();
void ParsePrint();
void ParseVoiceInit();
void ParseVoiceData();
void ParseTimeScale();
void ParseSendExtraInfo();
void ParseCenterPrint();
void ParseSetPause();
void ParseCutscene();
void ParseWeaponAnim();
void ParseDecalName();
void ParseFinale();
void ParseIntermission();
void ParseClientData();
void ParseResourceLocation();
void ParseSendCvarValue();
void ParseSendCvarValue2();
protected:
struct svc_func_s {
svc_commands_e opcode;
char *pszname;
void (Server::*func)();
};
static svc_func_s m_ClientFuncs[];
IWorld *m_World;
IProxy *m_Proxy;
IDirector *m_Director;
IFileSystem *m_FileSystem;
int m_ChallengeNumber;
INetSocket *m_ServerSocket;
NetChannel m_ServerChannel;
NetAddress m_ServerAddress;
int m_ServerState;
char m_HostName[MAX_PATH];
int m_CurrentRetry;
InfoString m_UserInfo;
char m_CDKey[32];
int m_AuthProtocol;
frame_t m_Frame;
unsigned char m_EntityBuffer[87040];
int m_Rate;
int m_UpdateRate;
float m_Time;
BitBuffer m_ReliableData;
BitBuffer m_UnreliableData;
BitBuffer m_VoiceData;
BitBuffer m_UserMessages;
BitBuffer m_ClientData;
BitBuffer *m_Instream;
int m_validSequence;
bool m_AutoRetry;
double m_NextAutoRetry;
bool m_IsHLTV;
bool m_ForceHLTV;
bool m_IsGameServer;
bool m_IsPaused;
bool m_IsVoiceBlocking;
DemoFile m_DemoFile;
demo_info_t m_DemoInfo;
BitBuffer m_DemoData;
CRC32_t m_ServerCRC;
int m_ServerCount;
int m_ClientPlayerNum;
int m_Protocol;
clientdata_t m_ClientDataStruct;
InfoString m_ServerInfo;
bool m_DelayReconnect;
unsigned int m_SeqNrMap[256];
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,310 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "info.h" // MAX_INFO_STRING
#include "qlimits.h" // MAX_PACKET_ENTITIES
#include "Delta.h"
#include "ObjectDictionary.h"
#include "BSPModel.h"
// TODO: move to qlimits.h
#define RESOURCE_INDEX_BITS 12
#define RESOURCE_MAX_COUNT (1 << RESOURCE_INDEX_BITS)
class World: public IWorld, public BaseSystemModule {
public:
World() {}
virtual ~World() {}
bool Init(IBaseSystem *system, int serial, char *name);
void RunFrame(double time);
void ReceiveSignal(ISystemModule *module, unsigned int signal, void *data);
void ExecuteCommand(int commandID, char *commandLine);
void RegisterListener(ISystemModule *module);
void RemoveListener(ISystemModule *module);
IBaseSystem *GetSystem();
int GetSerial();
char *GetStatusLine();
char *GetType();
char *GetName();
int GetState();
int GetVersion();
void ShutDown();
double GetTime();
NetAddress *GetGameServerAddress();
char *GetLevelName();
char *GetGameDir();
frame_t *GetFrameByTime(double time);
frame_t *GetFrameBySeqNr(unsigned int seqnr);
frame_t *GetLastFrame();
frame_t *GetFirstFrame();
int GetServerCount();
int GetSlotNumber();
int GetMaxClients();
int GetNumPlayers();
IBSPModel *GetWorldModel();
InfoString *GetServerInfoString();
bool GetPlayerInfoString(int playerNum, InfoString *infoString);
UserMsg *GetUserMsg(int msgNumber);
char *GetHostName();
serverinfo_t *GetServerInfo();
bool IsPlayerIndex(int index);
bool IsVoiceEnabled();
bool IsActive();
bool IsPaused();
bool IsComplete();
bool IsHLTV();
void Reset();
void SetServerInfo(int protocol, CRC32_t nserverCRC, unsigned char *nclientdllmd5, int nmaxclients, int nplayernum, int ngametype, char *ngamedir, char *nservername, char *nlevelname);
void SetServerInfoString(char *infostring);
void SetServerInfo(serverinfo_t *serverinfo);
void UpdateServerInfo();
void SetPaused(bool state);
void SetTime(double newTime);
void SetBufferSize(float seconds);
void SetVoiceEnabled(bool state);
void SetMoveVars(movevars_t *nmovevars);
void SetCDInfo(int ncdtrack, int nlooptrack);
void SetHLTV(bool state);
void SetExtraInfo(char *nclientfallback, int nallowCheats);
void SetViewEntity(int nviewentity);
void SetGameServerAddress(NetAddress *address);
void SetHostName(char *name);
void NewGame(int newServerCount);
void FinishGame();
bool SaveAsDemo(char *filename, IDirector *director);
void StopGame();
int FindUserMsgByName(char *name);
void ParseDeltaDescription(BitBuffer *stream);
void ParseBaseline(BitBuffer *stream);
void ParseEvent(BitBuffer *stream);
void ParseClientData(BitBuffer *stream, unsigned int deltaSeqNr, BitBuffer *to, clientdata_t *clientData);
bool GetUncompressedFrame(unsigned int seqNr, frame_t *frame);
bool UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream);
bool UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream, unsigned int from);
bool GetClientData(unsigned int SeqNr, clientdata_t *clientData);
bool GetClientData(frame_t *frame, clientdata_t *clientData);
int AddFrame(frame_t *newFrame);
bool AddResource(resource_t *resource);
void AddLightStyle(int index, char *style);
bool AddSignonData(unsigned char type, unsigned char *data, int size);
bool AddUserMessage(int msgNumber, int size, char *name);
void AddBaselineEntity(int index, entity_state_t *ent);
void AddInstancedBaselineEntity(int index, entity_state_t *ent);
void UpdatePlayer(int playerNum, int userId, char *infostring, char *hashedcdkey);
void WriteFrame(frame_t *frame, unsigned int lastFrameSeqnr, BitBuffer *reliableStream, BitBuffer *unreliableStream, unsigned int deltaSeqNr, unsigned int clientDelta, bool addVoice);
void WriteNewData(BitBuffer *stream);
void WriteClientUpdate(BitBuffer *stream, int playerIndex);
void WriteMovevars(BitBuffer *stream);
void WriteSigonData(BitBuffer *stream);
void WriteLightStyles(BitBuffer *stream);
int RemoveFrames(unsigned int startSeqNr, unsigned int endSeqNr);
int DuplicateFrames(unsigned int startSeqNr, unsigned int endSeqNr);
int MoveFrames(unsigned int startSeqNr, unsigned int endSeqNr, double destSeqnr);
int RevertFrames(unsigned int startSeqNr, unsigned int endSeqNr);
private:
int CompressFrame(frame_t *from, BitBuffer *stream);
int ParseDeltaHeader(BitBuffer *stream, bool *remove, bool *custom, int *numbase, bool *newbl, int *newblindex, bool full, int *offset);
void SetDirector(IDirector *director);
void SetTimeScale(float scale);
void SetGameGroupAddress(NetAddress *addr);
bool SetMaxClients(int max);
void SetName(char *newName);
IDirector *GetDirector();
float GetBufferedGameTime();
void ConnectionComplete();
void WriteResources(BitBuffer *stream);
void WriteDeltaDescriptions(BitBuffer *stream);
void WriteRegisteredUserMessages(BitBuffer *stream);
void WriteBaseline(BitBuffer *stream);
void WriteServerinfo(BitBuffer *stream);
void WriteCustomDecals(BitBuffer *stream);
void WritePacketEntities(BitBuffer *stream, frame_t *frame, frame_t *deltaframe);
bool WriteDeltaEntities(BitBuffer *stream, frame_t *fullFrame, unsigned int deltaSeqNr, unsigned int clientDelta);
enum WorldState {
WORLD_UNDEFINED,
WORLD_INITIALIZING,
WORLD_DISCONNECTED,
WORLD_CONNECTING,
WORLD_RUNNING,
WORLD_COMPLETE
};
void SetState(WorldState newState);
void ClearUserMessages();
void ClearServerInfo();
void ClearResources();
void ClearInstancedBaseline();
void ClearBaseline();
void ClearLightStyles();
void ClearPlayers();
void ClearFrames();
void ClearEntityCache();
bool GetFrameFromCache(unsigned int seqNr, entity_state_t **entities);
bool GetUncompressedFrame(frame_t *deltaFrame, frame_t *frame);
bool GetDeltaFromCache(unsigned int seqNr, unsigned int deltaNr, BitBuffer **buffer);
void CheckFrameBufferSize();
void ReorderFrameTimes(float newLastTime);
int FindBestBaseline(int index, entity_state_t **baseline, entity_state_t *to, int num, bool custom);
void RearrangeFrame(frame_t *frame, int seqNrOffset, float timeOffset);
delta_t *GetEventDelta() const;
delta_t *GetClientDelta() const;
delta_t *GetEntityDelta() const;
delta_t *GetWeaponDelta() const;
delta_t *GetDeltaEncoder(int index, bool custom);
bool IsDeltaEncoder() const;
protected:
bool m_IsPaused;
int m_WorldState;
int m_Protocol;
int m_ServerCount;
CRC32_t m_ServerCRC;
unsigned char m_ClientdllMD5[16];
int m_Maxclients;
int m_PlayerNum;
int m_GameType;
char m_GameDir[MAX_PATH];
char m_LevelName[40];
char m_ServerName[255];
int m_ViewEntity;
serverinfo_t m_DetailedServerInfo;
enum {
MAX_ENTITIES = 1380,
MAX_INSTANCED_BASELINES = 64,
MAX_FRAME_CACHE = 32,
MAX_SCOREBOARDNAME = 32,
MAX_SERVERINFO_STRING = 512,
MAX_BUFFER_SIGNONDATA = 32768
};
// Defined in client.h differently
typedef struct player_info_s
{
int userid; // User id on server
// User info string
char userinfo[MAX_INFO_STRING]; // User info string
char name[MAX_SCOREBOARDNAME]; // Name
int spectator; // Spectator or not, unused
int ping;
int packet_loss;
// skin information
char model[MAX_PATH];
int topcolor;
int bottomcolor;
bool active;
char hashedcdkey[16];
int trackerID;
} player_info_t;
player_info_t m_Players[MAX_CLIENTS];
unsigned char m_EntityBuffer[87040];
entity_state_t m_BaseLines[MAX_ENTITIES];
int m_MaxBaseLines;
entity_state_t m_Instanced_BaseLines[MAX_INSTANCED_BASELINES];
int m_MaxInstanced_BaseLine;
char m_Lightstyles[MAX_LIGHTSTYLES][65];
movevars_t m_MoveVars;
BSPModel m_WorldModel;
InfoString m_ServerInfo;
UserMsg *m_ClientUserMsgs;
resource_t *m_ResourcesList;
int m_ResourcesNum;
BitBuffer m_SignonData;
int m_CDTrack;
int m_LoopTrack;
ObjectDictionary m_Frames;
ObjectDictionary m_FramesByTime;
ObjectDictionary m_CamCommands;
unsigned int m_SequenceNr;
float m_MaxBufferLength;
typedef struct frameCache_s {
unsigned int seqNr;
entity_state_t entities[MAX_PACKET_ENTITIES];
} frameCache_t;
typedef struct deltaCache_s {
unsigned int seqNr;
unsigned int deltaNr;
BitBuffer buffer;
} deltaCache_t;
int m_MaxCacheIndex;
frameCache_t *m_FrameCache;
deltaCache_t *m_DeltaCache;
int m_CacheHits;
int m_CacheFaults;
double m_WorldTime;
double m_StartTime;
bool m_VoiceEnabled;
char m_ClientFallback[MAX_PATH];
bool m_AllowCheats;
bool m_IsHLTV;
char m_HostName[255];
NetAddress m_GameServerAddress;
#ifdef HOOK_HLTV
static DeltaWrapper m_Delta;
#else
Delta m_Delta;
#endif // HOOK_HLTV
};
extern char g_DownloadURL[128];

View File

@ -0,0 +1 @@
#include "precompiled.h"

View File

@ -0,0 +1,44 @@
#pragma once
#include "basetypes.h"
#include "archtypes.h"
#include "mathlib.h"
#include "FileSystem.h"
#include "interface.h"
#include "IBaseSystem.h"
#include "mem.h"
#include "common.h"
// Hooks stuff
#include "hookers/HLTV/Core/hooklist.h"
#include "common/md5.h"
#include "common/random.h"
#include "common/byteorder.h"
#include "common/ServerInfo.h"
#include "common/common_hltv.h"
#include "common/net_internal.h"
#include "common/mathlib_internal.h"
#include "common/DirectorCmd.h"
#include "common/NetAddress.h"
#include "common/NetChannel.h"
#include "common/BaseClient.h"
#include "common/DemoFile.h"
#include "common/munge.h"
#include <HLTV/IWorld.h>
#include <HLTV/IProxy.h>
#include <HLTV/IServer.h>
#include <HLTV/IClient.h>
#include <HLTV/INetChannel.h>
#include <HLTV/INetwork.h>
// Core module stuff
#include "World.h"
#include "Network.h"
#include "NetSocket.h"
#include "Server.h"

View File

@ -0,0 +1,3 @@
#include "precompiled.h"
#include "interface.cpp"

View File

@ -0,0 +1,139 @@
import org.doomedsociety.gradlecpp.cfg.ToolchainConfigUtils
import org.doomedsociety.gradlecpp.msvc.MsvcToolchainConfig
import org.doomedsociety.gradlecpp.toolchain.icc.Icc
import org.doomedsociety.gradlecpp.toolchain.icc.IccCompilerPlugin
import org.doomedsociety.gradlecpp.gcc.GccToolchainConfig
import org.gradle.nativeplatform.NativeBinarySpec
import org.gradle.nativeplatform.NativeLibrarySpec
import org.gradle.nativeplatform.toolchain.VisualCpp
apply plugin: 'cpp'
apply plugin: IccCompilerPlugin
apply plugin: GccCompilerPlugin
void setupToolchain(NativeBinarySpec b) {
def cfg = rootProject.createToolchainConfig(b);
cfg.projectInclude(project, '/..', '/../..', '/src', '/../common', '/../../common', '/../../engine', '/../../public', '/../../public/rehlds', '/../../pm_shared');
cfg.singleDefines 'USE_BREAKPAD_HANDLER', 'HLTV', 'DEMOPLAYER_MODULE'
if (cfg instanceof MsvcToolchainConfig) {
cfg.compilerOptions.pchConfig = new MsvcToolchainConfig.PrecompiledHeadersConfig(
enabled: true,
pchHeader: 'precompiled.h',
pchSourceSet: 'demoplayer_pch'
);
cfg.singleDefines('_CRT_SECURE_NO_WARNINGS')
cfg.compilerOptions.args '/Ob2', '/Oi', '/GF'
cfg.extraLibs "psapi.lib"
}
else if (cfg instanceof GccToolchainConfig) {
cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions(
enabled: true,
pchSourceSet: 'demoplayer_pch'
);
cfg.compilerOptions.languageStandard = 'c++0x'
cfg.defines([
'_strdup': 'strdup',
'_stricmp': 'strcasecmp',
'_strnicmp': 'strncasecmp',
'_vsnprintf': 'vsnprintf',
'_snprintf': 'snprintf',
]);
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-fno-exceptions'
}
ToolchainConfigUtils.apply(project, cfg, b);
}
model {
buildTypes {
release
}
platforms {
x86 {
architecture "x86"
}
}
toolChains {
visualCpp(VisualCpp) {
}
icc(Icc) {
}
}
components {
demoplayer(NativeLibrarySpec) {
targetPlatform 'x86'
baseName 'demoplayer'
sources {
demoplayer_main(CppSourceSet) {
source {
srcDir "src"
include "**/*.cpp"
exclude "precompiled.cpp"
}
}
demoplayer_common(CppSourceSet) {
source {
srcDirs "/../../common", "/../common"
// common
include "BaseSystemModule.cpp"
include "ObjectDictionary.cpp"
include "ObjectList.cpp"
include "TokenLine.cpp"
// HLTV common
include "BitBuffer.cpp"
include "byteorder.cpp"
include "common.cpp"
include "DirectorCmd.cpp"
include "mathlib.cpp"
}
}
demoplayer_engine(CppSourceSet) {
source {
srcDir "../../engine"
include "mem.cpp"
}
}
demoplayer_pch(CppSourceSet) {
source {
srcDir "src"
include "precompiled.cpp"
}
}
}
binaries.all {
NativeBinarySpec b -> project.setupToolchain(b)
}
}
}
}
task buildFixes {
dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
}
}
task buildRelease {
dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
}
}
// prevent static lib building
binaries.withType(StaticLibraryBinarySpec) { binary ->
buildable = false
}

View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DemoPlayer", "DemoPlayer.vcxproj", "{05292761-0847-4A68-BA10-9D384DC0D3EE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{05292761-0847-4A68-BA10-9D384DC0D3EE}.Debug|Win32.ActiveCfg = Debug|Win32
{05292761-0847-4A68-BA10-9D384DC0D3EE}.Debug|Win32.Build.0 = Debug|Win32
{05292761-0847-4A68-BA10-9D384DC0D3EE}.Release|Win32.ActiveCfg = Release|Win32
{05292761-0847-4A68-BA10-9D384DC0D3EE}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\common\BaseSystemModule.cpp" />
<ClCompile Include="..\..\..\common\ObjectDictionary.cpp" />
<ClCompile Include="..\..\..\common\ObjectList.cpp" />
<ClCompile Include="..\..\..\common\TokenLine.cpp" />
<ClCompile Include="..\..\..\engine\mem.cpp" />
<ClCompile Include="..\..\..\hookers\HLTV\DemoPlayer\hooklist.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\..\hookers\HLTV\DemoPlayer\main.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\BitBuffer.cpp" />
<ClCompile Include="..\..\common\byteorder.cpp" />
<ClCompile Include="..\..\common\common.cpp" />
<ClCompile Include="..\..\common\DirectorCmd.cpp" />
<ClCompile Include="..\..\common\mathlib.cpp" />
<ClCompile Include="..\src\DemoPlayer.cpp" />
<ClCompile Include="..\src\precompiled.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\src\public_amalgamation.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\common\BaseSystemModule.h" />
<ClInclude Include="..\..\..\common\ObjectDictionary.h" />
<ClInclude Include="..\..\..\common\ObjectList.h" />
<ClInclude Include="..\..\..\common\TokenLine.h" />
<ClInclude Include="..\..\..\engine\mem.h" />
<ClInclude Include="..\..\..\hookers\HLTV\DemoPlayer\hooklist.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\..\common\BitBuffer.h" />
<ClInclude Include="..\..\common\byteorder.h" />
<ClInclude Include="..\..\common\common_hltv.h" />
<ClInclude Include="..\..\common\DemoFile.h" />
<ClInclude Include="..\..\common\DirectorCmd.h" />
<ClInclude Include="..\..\common\mathlib_internal.h" />
<ClInclude Include="..\src\DemoPlayer.h" />
<ClInclude Include="..\src\precompiled.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{05292761-0847-4A68-BA10-9D384DC0D3EE}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>DemoPlayer</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>HLTV;WIN32;_DEBUG;_WINDOWS;_USRDLL;DEMOPLAYER_MODULE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>$(ProjectDir)\..\src;$(ProjectDir)\..\..\;$(ProjectDir)\..\..\..\;$(ProjectDir)\..\..\..\common;$(ProjectDir)\..\..\..\engine;$(ProjectDir)\..\..\..\public;$(ProjectDir)\..\..\..\public\rehlds;$(ProjectDir)\..\..\..\pm_shared;$(ProjectDir)\..\..\..\game_shared;$(ProjectDir)\..\..\..\..\dep\bzip2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
<CustomBuildStep>
<Command>echo Empty Action</Command>
</CustomBuildStep>
<CustomBuildStep>
<Message>Force build to run Pre-Build event</Message>
</CustomBuildStep>
<CustomBuildStep>
<Outputs>git.always.run</Outputs>
</CustomBuildStep>
<CustomBuildStep>
<Inputs>git.always.run</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>HOOK_HLTV;HLTV;WIN32;NDEBUG;_WINDOWS;_USRDLL;DEMOPLAYER_MODULE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitiHOOons)</PreprocessorDefinitions>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>$(ProjectDir)\..\src;$(ProjectDir)\..\..\;$(ProjectDir)\..\..\..\;$(ProjectDir)\..\..\..\common;$(ProjectDir)\..\..\..\engine;$(ProjectDir)\..\..\..\public;$(ProjectDir)\..\..\..\public\rehlds;$(ProjectDir)\..\..\..\pm_shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<FullProgramDatabaseFile>false</FullProgramDatabaseFile>
</Link>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
<CustomBuildStep>
<Command>echo Empty Action</Command>
</CustomBuildStep>
<CustomBuildStep>
<Message>Force build to run Pre-Build event</Message>
</CustomBuildStep>
<CustomBuildStep>
<Outputs>git.always.run</Outputs>
</CustomBuildStep>
<CustomBuildStep>
<Inputs>git.always.run</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{4d99bbd6-4658-4bed-a29e-9322ec16db5a}</UniqueIdentifier>
</Filter>
<Filter Include="HLTV">
<UniqueIdentifier>{c58ccefe-767c-4f0a-b075-c55e24d15263}</UniqueIdentifier>
</Filter>
<Filter Include="HLTV\common">
<UniqueIdentifier>{ca1c7722-8e65-480d-9e3c-34f7f2524372}</UniqueIdentifier>
</Filter>
<Filter Include="src\hookers">
<UniqueIdentifier>{1f62aa80-c3f7-4f97-a93e-5b67b153a751}</UniqueIdentifier>
</Filter>
<Filter Include="engine">
<UniqueIdentifier>{8712d29d-6fec-42fb-9f6e-5618302f3203}</UniqueIdentifier>
</Filter>
<Filter Include="common">
<UniqueIdentifier>{fab89dcf-8536-490e-81b3-d9bb29fce8c6}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\DemoPlayer.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\precompiled.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\public_amalgamation.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\common\common.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\BitBuffer.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\byteorder.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\DirectorCmd.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\mathlib.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\hookers\HLTV\DemoPlayer\hooklist.cpp">
<Filter>src\hookers</Filter>
</ClCompile>
<ClCompile Include="..\..\..\hookers\HLTV\DemoPlayer\main.cpp">
<Filter>src\hookers</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\BaseSystemModule.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\ObjectDictionary.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\ObjectList.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\TokenLine.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\engine\mem.cpp">
<Filter>engine</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\DemoPlayer.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\precompiled.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\common\common_hltv.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\BitBuffer.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\byteorder.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\DirectorCmd.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\mathlib_internal.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\hookers\HLTV\DemoPlayer\hooklist.h">
<Filter>src\hookers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\BaseSystemModule.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\ObjectDictionary.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\ObjectList.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\TokenLine.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\engine\mem.h">
<Filter>engine</Filter>
</ClInclude>
<ClInclude Include="..\..\common\DemoFile.h">
<Filter>HLTV\common</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,39 @@
@echo OFF
::
:: Post-build auto-deploy script
:: Create and fill PublishPath.txt file with path to deployment folder
:: I.e. PublishPath.txt should contain one line with a folder path
:: Call it so:
:: IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")
::
SET targetDir=%~1
SET targetName=%~2
SET targetExt=%~3
SET projectDir=%~4
SET destination=
IF NOT EXIST "%projectDir%\PublishPath.txt" (
ECHO No deployment path specified. Create PublishPath.txt near PostBuild.bat with paths on separate lines for auto deployment.
exit /B 0
)
FOR /f "tokens=* delims= usebackq" %%a IN ("%projectDir%\PublishPath.txt") DO (
ECHO Deploying to: %%a
IF NOT "%%a" == "" (
copy /Y "%targetDir%%targetName%%targetExt%" "%%a"
IF NOT ERRORLEVEL 1 (
IF EXIST "%targetDir%%targetName%.pdb" (
copy /Y "%targetDir%%targetName%.pdb" "%%a"
)
) ELSE (
ECHO PostBuild.bat ^(27^) : warning : Can't copy '%targetName%%targetExt%' to deploy path '%%a'
)
)
)
IF "%%a" == "" (
ECHO No deployment path specified.
)
exit /B 0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,193 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include <HLTV/IWorld.h>
#include <HLTV/IServer.h>
#include <HLTV/IDirector.h>
#include "vmodes.h"
#include "cdll_int.h"
#include "IDemoPlayer.h"
#include "IEngineWrapper.h"
#include "BaseSystemModule.h"
#include "ObjectDictionary.h"
class IProxy;
class DirectorCmd;
class IBaseSystem;
class IObjectContainer;
class DemoPlayer: public IDemoPlayer, public BaseSystemModule, public IDirector {
public:
DemoPlayer();
virtual ~DemoPlayer() {}
bool Init(IBaseSystem *system, int serial, char *name);
void RunFrame(double time);
void ReceiveSignal(ISystemModule *module, unsigned int signal, void *data);
void ExecuteCommand(int commandID, char *commandLine);
void RegisterListener(ISystemModule *module);
void RemoveListener(ISystemModule *module);
IBaseSystem *GetSystem();
int GetSerial();
char *GetStatusLine();
char *GetType();
char *GetName();
int GetState();
int GetVersion();
void ShutDown();
void NewGame(IWorld *world, IProxy *proxy = nullptr);
char *GetModName();
void WriteCommands(BitBuffer *stream, float startTime, float endTime);
int AddCommand(DirectorCmd *cmd);
bool RemoveCommand(int index);
DirectorCmd *GetLastCommand();
IObjectContainer *GetCommands();
IDirector *GetDirector();
void SetWorldTime(double time, bool relative);
void SetTimeScale(float scale);
void SetPaused(bool state);
void SetEditMode(bool state);
void SetMasterMode(bool state);
bool IsPaused();
bool IsLoading();
bool IsActive();
bool IsEditMode();
bool IsMasterMode();
void RemoveFrames(double starttime, double endtime);
void ExecuteDirectorCmd(DirectorCmd *cmd);
double GetWorldTime();
double GetStartTime();
double GetEndTime();
float GetTimeScale();
IWorld *GetWorld();
char *GetFileName();
bool SaveGame(char *filename);
bool LoadGame(char *filename);
void Stop();
void ForceHLTV(bool state);
void GetDemoViewInfo(ref_params_t *rp, float *view, int *viewmodel);
int ReadDemoMessage(unsigned char *buffer, int size);
void ReadNetchanState(int *incoming_sequence, int *incoming_acknowledged, int *incoming_reliable_acknowledged, int *incoming_reliable_sequence, int *outgoing_sequence, int *reliable_sequence, int *last_reliable_sequence);
void SetName(char *newName);
private:
enum LocalCommandIDs {
CMD_ID_JUMP = 1,
CMD_ID_FORCEHLTV,
CMD_ID_PAUSE,
CMD_ID_SPEED,
CMD_ID_START,
CMD_ID_SAVE,
};
void CMD_Jump(char *cmdLine);
void CMD_ForceHLTV(char *cmdLine);
void CMD_Pause(char *cmdLine);
void CMD_Speed(char *cmdLine);
void CMD_Start(char *cmdLine);
void CMD_Save(char *cmdLine);
struct LocalCommandID_s {
char *name;
LocalCommandIDs id;
void (DemoPlayer::*pfnCmd)(char *cmdLine);
};
static LocalCommandID_s m_LocalCmdReg[];
protected:
double GetPlayerTime();
char *FormatTime(float time);
void RunClocks();
void WriteDatagram(BitBuffer *stream);
void WriteSpawn(BitBuffer *stream);
void ReindexCommands();
void WriteCameraPath(DirectorCmd *, BitBuffer *stream);
enum DemoCmds {
DEMO_STRINCMD = 3,
DEMO_CLIENTDATA = 4,
DEMO_EVENT = 6,
DEMO_WEAPONANIM = 7,
DEMO_PLAYSOUND = 8,
DEMO_DATA = 9
};
void ExecuteDemoFileCommands(BitBuffer *stream);
private:
IEngineWrapper *m_Engine;
IWorld *m_World;
IServer *m_Server;
ObjectDictionary m_Commands;
DirectorCmd *m_LastCmd;
unsigned int m_CommandCounter;
char m_DemoFileName[MAX_PATH];
enum PlayerState {
DEMOPLAYER_UNDEFINED,
DEMOPLAYER_INITIALIZING,
DEMOPLAYER_CONNECTING,
DEMOPLAYER_CONNECTED,
DEMOPLAYER_RUNNING
};
int m_PlayerState;
BitBuffer m_DemoStream;
bool m_EditorMode;
bool m_MasterMode;
bool m_ForceHLTV;
bool m_IsSaving;
float m_TimeScale;
double m_WorldTime;
double m_PlayerTime;
double m_StartTime;
double m_LastFrameTime;
bool m_IsPaused;
double m_LastClockUpdateTime;
unsigned int m_LastFrameSeqNr;
unsigned int m_DeltaFrameSeqNr;
unsigned int m_Outgoing_sequence;
};
#ifndef HOOK_HLTV
// Use this to expose a singleton interface. This creates the global variable for you automatically.
#define EXPOSE_SINGLE_INTERFACE2(className, interfaceName, versionName) \
static className __g_##className##_singleton;\
static IBaseInterface *__Create##className##interfaceName##_interface() {return (IBaseInterface *)((interfaceName *)&__g_##className##_singleton);}\
static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName);
EXPOSE_SINGLE_INTERFACE2(DemoPlayer, IDemoPlayer, DEMOPLAYER_INTERFACE_VERSION);
#endif // HOOK_HLTV

View File

@ -0,0 +1 @@
#include "precompiled.h"

View File

@ -0,0 +1,23 @@
#pragma once
#include "archtypes.h"
#include "maintypes.h"
#include "TokenLine.h"
#include "interface.h"
#include "mem.h"
#include "common.h"
#include "common/common_hltv.h"
#include "common/net_internal.h"
#include "common/mathlib_internal.h"
#include "common/byteorder.h"
#include "common/BitBuffer.h"
#include "common/DirectorCmd.h"
#include "common/DemoFile.h"
#include "DemoPlayer.h"
// Hooks stuff
#include "hookers/HLTV/DemoPlayer/hooklist.h"

View File

@ -0,0 +1,3 @@
#include "precompiled.h"
#include "interface.cpp"

View File

@ -0,0 +1,139 @@
import org.doomedsociety.gradlecpp.cfg.ToolchainConfigUtils
import org.doomedsociety.gradlecpp.msvc.MsvcToolchainConfig
import org.doomedsociety.gradlecpp.toolchain.icc.Icc
import org.doomedsociety.gradlecpp.toolchain.icc.IccCompilerPlugin
import org.doomedsociety.gradlecpp.gcc.GccToolchainConfig
import org.gradle.nativeplatform.NativeBinarySpec
import org.gradle.nativeplatform.NativeLibrarySpec
import org.gradle.nativeplatform.toolchain.VisualCpp
apply plugin: 'cpp'
apply plugin: IccCompilerPlugin
apply plugin: GccCompilerPlugin
void setupToolchain(NativeBinarySpec b) {
def cfg = rootProject.createToolchainConfig(b);
cfg.projectInclude(project, '/..', '/../..', '/src', '/../../common', '/../../engine', '/../../public', '/../../public/rehlds', '/../../pm_shared');
cfg.singleDefines 'USE_BREAKPAD_HANDLER', 'HLTV', 'DIRECTOR_MODULE'
if (cfg instanceof MsvcToolchainConfig) {
cfg.compilerOptions.pchConfig = new MsvcToolchainConfig.PrecompiledHeadersConfig(
enabled: true,
pchHeader: 'precompiled.h',
pchSourceSet: 'director_pch'
);
cfg.singleDefines('_CRT_SECURE_NO_WARNINGS')
cfg.compilerOptions.args '/Ob2', '/Oi', '/GF'
}
else if (cfg instanceof GccToolchainConfig) {
cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions(
enabled: true,
pchSourceSet: 'director_pch'
);
cfg.compilerOptions.languageStandard = 'c++0x'
cfg.defines([
'_strdup': 'strdup',
'_stricmp': 'strcasecmp',
'_strnicmp': 'strncasecmp',
'_vsnprintf': 'vsnprintf',
'_snprintf': 'snprintf',
]);
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-fno-exceptions'
}
ToolchainConfigUtils.apply(project, cfg, b);
}
model {
buildTypes {
release
}
platforms {
x86 {
architecture "x86"
}
}
toolChains {
visualCpp(VisualCpp) {
}
icc(Icc) {
}
}
components {
director(NativeLibrarySpec) {
targetPlatform 'x86'
baseName 'director'
sources {
director_main(CppSourceSet) {
source {
srcDir "src"
include "**/*.cpp"
exclude "precompiled.cpp"
}
}
director_common(CppSourceSet) {
source {
srcDirs "../../common", "../common"
// common
include "BaseSystemModule.cpp"
include "ObjectDictionary.cpp"
include "ObjectList.cpp"
include "TokenLine.cpp"
// HLTV common
include "BitBuffer.cpp"
include "byteorder.cpp"
include "common.cpp"
include "DirectorCmd.cpp"
include "mathlib.cpp"
include "random.cpp"
}
}
director_engine(CppSourceSet) {
source {
srcDir "../../engine"
include "mem.cpp"
}
}
director_pch(CppSourceSet) {
source {
srcDir "src"
include "precompiled.cpp"
}
}
}
binaries.all {
NativeBinarySpec b -> project.setupToolchain(b)
}
}
}
}
task buildFixes {
dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
}
}
task buildRelease {
dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
}
}
// prevent static lib building
binaries.withType(StaticLibraryBinarySpec) { binary ->
buildable = false
}

View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Director", "Director.vcxproj", "{04D0594C-57F5-4277-AF1B-EAE90AED0C3C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{04D0594C-57F5-4277-AF1B-EAE90AED0C3C}.Debug|Win32.ActiveCfg = Debug|Win32
{04D0594C-57F5-4277-AF1B-EAE90AED0C3C}.Debug|Win32.Build.0 = Debug|Win32
{04D0594C-57F5-4277-AF1B-EAE90AED0C3C}.Release|Win32.ActiveCfg = Release|Win32
{04D0594C-57F5-4277-AF1B-EAE90AED0C3C}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{04D0594C-57F5-4277-AF1B-EAE90AED0C3C}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Director</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>HLTV;WIN32;_DEBUG;_WINDOWS;_USRDLL;DIRECTOR_MODULE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)\..\..\;$(ProjectDir)\..\src;$(ProjectDir)\..\..\..\common;$(ProjectDir)\..\..\..\engine;$(ProjectDir)\..\..\..\public;$(ProjectDir)\..\..\..\public\rehlds;$(ProjectDir)\..\..\..\pm_shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
<CustomBuildStep>
<Command>echo Empty Action</Command>
</CustomBuildStep>
<CustomBuildStep>
<Message>Force build to run Pre-Build event</Message>
<Outputs>git.always.run</Outputs>
<Inputs>git.always.run</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>HLTV;WIN32;NDEBUG;_WINDOWS;_USRDLL;DIRECTOR_MODULE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)\..\..\;$(ProjectDir)\..\src;$(ProjectDir)\..\..\..\common;$(ProjectDir)\..\..\..\engine;$(ProjectDir)\..\..\..\public;$(ProjectDir)\..\..\..\public\rehlds;$(ProjectDir)\..\..\..\pm_shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<CustomBuildStep>
<Command>echo Empty Action</Command>
</CustomBuildStep>
<CustomBuildStep>
<Message>Force build to run Pre-Build event</Message>
<Outputs>git.always.run</Outputs>
<Inputs>git.always.run</Inputs>
</CustomBuildStep>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\common\BaseSystemModule.cpp" />
<ClCompile Include="..\..\..\common\ObjectDictionary.cpp" />
<ClCompile Include="..\..\..\common\ObjectList.cpp" />
<ClCompile Include="..\..\..\common\TokenLine.cpp" />
<ClCompile Include="..\..\..\engine\mem.cpp" />
<ClCompile Include="..\..\common\BitBuffer.cpp" />
<ClCompile Include="..\..\common\byteorder.cpp" />
<ClCompile Include="..\..\common\common.cpp" />
<ClCompile Include="..\..\common\DirectorCmd.cpp" />
<ClCompile Include="..\..\common\mathlib.cpp" />
<ClCompile Include="..\..\common\random.cpp" />
<ClCompile Include="..\src\Director.cpp" />
<ClCompile Include="..\src\precompiled.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\src\public_amalgamation.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\common\BaseSystemModule.h" />
<ClInclude Include="..\..\..\common\ObjectDictionary.h" />
<ClInclude Include="..\..\..\common\ObjectList.h" />
<ClInclude Include="..\..\..\common\TokenLine.h" />
<ClInclude Include="..\..\..\engine\mem.h" />
<ClInclude Include="..\..\common\BitBuffer.h" />
<ClInclude Include="..\..\common\byteorder.h" />
<ClInclude Include="..\..\common\common_hltv.h" />
<ClInclude Include="..\..\common\DirectorCmd.h" />
<ClInclude Include="..\..\common\mathlib_internal.h" />
<ClInclude Include="..\..\common\random.h" />
<ClInclude Include="..\src\Director.h" />
<ClInclude Include="..\src\DirectorNull.h" />
<ClInclude Include="..\src\precompiled.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{e86d9738-6b9c-4a2d-ba74-454526be3b1c}</UniqueIdentifier>
</Filter>
<Filter Include="HLTV">
<UniqueIdentifier>{b2fdbdd6-d164-4470-97e9-b454d0dc7b0f}</UniqueIdentifier>
</Filter>
<Filter Include="HLTV\common">
<UniqueIdentifier>{722c9b02-95dc-410f-a5b4-955878646049}</UniqueIdentifier>
</Filter>
<Filter Include="engine">
<UniqueIdentifier>{33779299-5f45-402f-a52f-888505614cbe}</UniqueIdentifier>
</Filter>
<Filter Include="common">
<UniqueIdentifier>{188c9b98-4976-4512-9313-8c3ffe3d0249}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\Director.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\precompiled.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\public_amalgamation.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\common\common.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\random.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\BitBuffer.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\DirectorCmd.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\byteorder.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\mathlib.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\BaseSystemModule.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\ObjectDictionary.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\ObjectList.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\TokenLine.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\engine\mem.cpp">
<Filter>engine</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\Director.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\DirectorNull.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\precompiled.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\common\common_hltv.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\random.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\BitBuffer.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\DirectorCmd.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\byteorder.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\mathlib_internal.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\BaseSystemModule.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\ObjectDictionary.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\ObjectList.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\TokenLine.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\engine\mem.h">
<Filter>engine</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,39 @@
@echo OFF
::
:: Post-build auto-deploy script
:: Create and fill PublishPath.txt file with path to deployment folder
:: I.e. PublishPath.txt should contain one line with a folder path
:: Call it so:
:: IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")
::
SET targetDir=%~1
SET targetName=%~2
SET targetExt=%~3
SET projectDir=%~4
SET destination=
IF NOT EXIST "%projectDir%\PublishPath.txt" (
ECHO No deployment path specified. Create PublishPath.txt near PostBuild.bat with paths on separate lines for auto deployment.
exit /B 0
)
FOR /f "tokens=* delims= usebackq" %%a IN ("%projectDir%\PublishPath.txt") DO (
ECHO Deploying to: %%a
IF NOT "%%a" == "" (
copy /Y "%targetDir%%targetName%%targetExt%" "%%a"
IF NOT ERRORLEVEL 1 (
IF EXIST "%targetDir%%targetName%.pdb" (
copy /Y "%targetDir%%targetName%.pdb" "%%a"
)
) ELSE (
ECHO PostBuild.bat ^(27^) : warning : Can't copy '%targetName%%targetExt%' to deploy path '%%a'
)
)
)
IF "%%a" == "" (
ECHO No deployment path specified.
)
exit /B 0

View File

@ -0,0 +1,771 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
#ifdef DIRECTOR_MODULE
EXPOSE_SINGLE_INTERFACE(Director, IDirector, DIRECTOR_INTERFACE_VERSION);
#endif // DIRECTOR_MODULE
bool Director::Init(IBaseSystem *system, int serial, char *name)
{
BaseSystemModule::Init(system, serial, name);
m_System->RegisterCommand("slowmotion", this, CMD_ID_SLOWMOTION);
m_historyLength = MAX_WORLD_HISTORY;
m_history = (worldHistory_t *)malloc(sizeof(worldHistory_t) * m_historyLength);
if (!m_history) {
m_System->Printf("ERROR!Director::Init: not enough memory for world history.\n");
return false;
}
m_LastExecTime = 0;
m_currentTime = 0;
m_slowMotion = 0.5f;
for (int i = 0; i < MAX_WORLD_HISTORY; i++) {
m_gaussFilter[i] = 1.0f / exp((i * i) / 10000.0f);
}
m_World = nullptr;
m_Active = false;
m_System->ExecuteFile("director.cfg");
m_System->Printf("Director module initialized.\n");
return true;
}
float WeightedAngle(vec_t *vec1, vec_t *vec2)
{
float a = AngleBetweenVectors(vec1, vec2);
if (a < 11.25f) {
return 1;
}
else if (a < 22.5f) {
return 0.5f;
}
else if (a < 45.0f) {
return 0.25f;
}
else if (a < 90.0f) {
return 0.125f;
}
return 0.05f;
}
void Director::WriteProxyStatus(BitBuffer *stream)
{
;
}
void Director::ShutDown()
{
if (m_State == MODULE_DISCONNECTED) {
return;
}
if (m_history) {
free(m_history);
}
if (m_World) {
m_World->RemoveListener(this);
}
ClearDirectorCommands();
BaseSystemModule::ShutDown();
m_System->Printf("Director module shutdown.\n");
}
void Director::RunFrame(double time)
{
BaseSystemModule::RunFrame(time);
if (!m_World || !m_World->IsActive()) {
return;
}
if (m_nextCutTime && m_Active)
{
ExecuteDirectorCommands();
if ((m_currentTime - m_nextCutTime) > 10)
{
float duration = AddBestMODCut();
if (!duration) {
duration = AddBestGenericCut();
}
m_nextCutTime += duration;
while (m_nextCutTime > m_history[m_nextCutSeqnr % m_historyLength].time) {
m_nextCutSeqnr++;
}
}
}
}
void Director::ReceiveSignal(ISystemModule *module, unsigned int signal, void *data)
{
int from = module->GetSerial();
if (m_World->GetSerial() != from) {
return;
}
if (signal != 3) {
return;
}
if (!m_World) {
m_System->Printf("Director::ReceiveSignal: world == NULL\n");
return;
}
frame_t frame;
m_World->GetUncompressedFrame(m_World->GetLastFrame()->seqnr, &frame);
AnalyseFrame(&frame);
}
char *Director::GetModName()
{
return "valve";
}
void Director::NewGame(IWorld *world, IProxy *proxy)
{
m_World = world;
m_Proxy = proxy;
world->RegisterListener(this);
m_WorldModel = m_World->GetWorldModel();
memset(m_history, 0, sizeof(*m_history) * m_historyLength);
memset(&m_frameEvent, 0, sizeof(m_frameEvent));
ClearDirectorCommands();
m_lastCut = nullptr;
m_LastExecTime = 0;
m_nextCutTime = 0;
m_currentTime = 0;
m_nextCutSeqnr = 0;
m_maxRank = 0;
WriteSignonData();
m_Active = true;
}
void Director::AnalyseFrame(frame_t *frame)
{
unsigned int i;
unsigned int num;
float ranks[MAX_CLIENTS];
unsigned int maxclients = m_World->GetMaxClients();
unsigned int seqnr = frame->seqnr;
worldHistory_t *now = &m_history[seqnr % m_historyLength];
for (i = 0; i < MAX_CLIENTS; i++) {
ranks[i] = now->players[i].rank;
}
memset(now, 0, sizeof(*now));
for (i = 0; i < MAX_CLIENTS; i++) {
now->players[i].rank = ranks[i];
}
if (frame->delta || !m_Active) {
m_System->DPrintf("Director::AnalyseFrame: frame must be uncompressed.\n");
return;
}
if (m_currentTime)
{
m_nextCutTime = frame->time;
m_nextCutSeqnr = seqnr;
}
m_currentSeqnr = seqnr;
now->seqNr = seqnr;
m_currentTime = frame->time;
now->time = frame->time;
unsigned int count = min(maxclients, frame->entitynum);
for (num = 0; num < count; num++)
{
entity_state_t *ent = &((entity_state_t *)frame->entities)[num];
unsigned int index = ent->number - 1;
if (index >= maxclients) {
continue;
}
playerData_t *player = &now->players[i];
player->active = (ent->solid != SOLID_NOT);
if (player->active)
{
player->origin[0] = ent->origin[0];
player->origin[1] = ent->origin[1];
player->origin[2] = ent->origin[2];
vec3_t angles;
AngleVectors(ent->angles, angles);
VectorCopy(angles, player->angles);
}
}
for (i = 0; i < MAX_CLIENTS; i++) {
AnalysePlayer(i);
}
now->event.entity1 = m_frameEvent.entity1;
now->event.entity2 = m_frameEvent.entity2;
now->event.flags = m_frameEvent.flags;
memset(&m_frameEvent, 0, sizeof(m_frameEvent));
}
void Director::SmoothRank(int playerNum, float rank)
{
const unsigned int smoothRange = 40;
m_history[(m_currentSeqnr + smoothRange) % m_historyLength].players[playerNum].rank = 0;
unsigned int steps;
for (unsigned int i = 0; i < smoothRange; i++)
{
float addition = rank * m_gaussFilter[i * (MAX_WORLD_HISTORY / smoothRange)];
steps = (m_currentSeqnr - i) % m_historyLength;
m_history[steps].players[playerNum].rank += addition;
steps = (i + m_currentSeqnr) % m_historyLength;
m_history[steps].players[playerNum].rank += addition;
}
}
void Director::AnalysePlayer(int playerNum)
{
int secondTarget = 0;
float rank = RandomFloat(0.0f, 0.01f) + 1;
float targetRank, bestTargetRank = 0;
worldHistory_t *now = &m_history[m_currentSeqnr % m_historyLength];
playerData_t *player = &now->players[playerNum];
if (player->active)
{
if (m_WorldModel->IsValid())
{
m_WorldModel->SetPVS(player->origin);
for (int i = 0; i < MAX_CLIENTS; i++)
{
playerData_t *target = &now->players[i];
if (!target->active || !m_WorldModel->InPVS(target->origin)) {
continue;
}
vec3_t offset;
VectorSubtract(target->origin, player->origin, offset);
float distance = Length(offset);
if (distance >= 1.0f)
{
targetRank = WeightedAngle(target->angles, offset) + 1 / distance;
// inverted
VectorScale(offset, -1.0f, offset);
targetRank = WeightedAngle(target->angles, offset) * targetRank;
rank += targetRank;
// remember closest player
if (targetRank > bestTargetRank)
{
bestTargetRank = targetRank;
secondTarget = i + 1;
}
}
}
}
}
else
{
rank = 0;
}
player->target = secondTarget;
player->rank = player->rank + rank;
SmoothRank(playerNum, rank);
}
void Director::WriteCommands(BitBuffer *stream, float startTime, float endTime)
{
DirectorCmd *cmd = (DirectorCmd *)m_Commands.FindClosestKey(startTime);
while (cmd && cmd->GetTime() <= endTime)
{
if (cmd->GetTime() > startTime)
{
if (cmd->GetType() == DRC_CMD_TIMESCALE)
{
float timescale;
cmd->GetTimeScaleData(timescale);
stream->WriteByte(svc_timescale);
stream->WriteFloat(timescale);
}
cmd->WriteToStream(stream);
}
cmd = (DirectorCmd *)m_Commands.GetNext();
}
}
void Director::WriteSignonData()
{
static unsigned char cmd[] = {
1, // command length in bytes
DRC_CMD_START // tell them for start director
};
m_World->AddSignonData(svc_director, cmd, sizeof(cmd));
}
void Director::AddEvent(int entity1, int entity2, unsigned int flags)
{
if ((flags & DRC_FLAG_PRIO_MASK) > (m_frameEvent.flags & DRC_FLAG_PRIO_MASK))
{
m_frameEvent.flags = flags;
m_frameEvent.entity1 = entity1;
m_frameEvent.entity2 = entity2;
}
}
float Director::AddBestGenericCut()
{
int seqNrMod = m_nextCutSeqnr % m_historyLength;
float sumTarget2Rank[MAX_CLIENTS];
float bestTarget2Rank, bestRank = 0;
float targetRankSum = 0;
int newTarget, newTarget2;
int bestTarget2;
for (int i = 0; i < MAX_CLIENTS; i++)
{
memset(sumTarget2Rank, 0, sizeof(sumTarget2Rank));
float tillTime = m_nextCutTime + 4;
while (tillTime > m_history[seqNrMod].time)
{
playerData_t *player = &m_history[seqNrMod].players[i];
targetRankSum += player->rank;
if (player->target) {
sumTarget2Rank[player->target - 1] += player->rank;
}
if (++seqNrMod == m_historyLength) {
seqNrMod = 0;
}
}
bestTarget2 = 0;
bestTarget2Rank = 0;
for (int j = 0; j < MAX_CLIENTS; j++)
{
if (sumTarget2Rank[j] > bestTarget2Rank)
{
bestTarget2 = j + 1;
bestTarget2Rank = sumTarget2Rank[j];
}
}
if (targetRankSum > bestRank)
{
bestRank = targetRankSum;
newTarget = i + 1;
newTarget2 = bestTarget2;
}
}
if (bestRank > m_maxRank) {
m_maxRank = bestRank;
}
float duration = 1.0f;
if (newTarget > 0)
{
if (m_lastCut && m_lastCut->GetType() == TYPE_DIRECTOR)
{
int lastTarget1, lastTarget2,flags;
m_lastCut->GetEventData(lastTarget1, lastTarget2, flags);
if (newTarget == lastTarget1 && newTarget2 == lastTarget2) {
return 1.0f;
}
if (newTarget == lastTarget1) {
duration = 2.0f;
}
}
DirectorCmd *cmd = new DirectorCmd;
cmd->SetEventData(newTarget, newTarget2, 0);
cmd->SetTime(m_nextCutTime);
RandomizeCommand(cmd);
m_Commands.Add(cmd, m_nextCutTime);
m_lastCut = cmd;
}
return duration;
}
float Director::AddBestMODCut()
{
worldHistory_t *timepoint = FindBestEvent();
if (!timepoint) {
return 0;
}
DirectorCmd *cmd = new DirectorCmd;
cmd->SetEventData(timepoint->event.entity1, timepoint->event.entity2, timepoint->event.flags);
cmd->SetTime(m_nextCutTime);
RandomizeCommand(cmd);
m_Commands.Add(cmd, cmd->GetTime());
m_lastCut = cmd;
int lastTarget1, lastTarget2, lastFlags;
cmd->GetEventData(lastTarget1, lastTarget2, lastFlags);
float trailTime = 2.0f;
if ((lastFlags & DRC_FLAG_SLOWMOTION) && m_slowMotion)
{
trailTime = 1.5f;
cmd = new DirectorCmd;
cmd->SetTimeScaleData(m_slowMotion);
cmd->SetTime(timepoint->time - 0.25f);
m_Commands.Add(cmd, cmd->GetTime());
cmd = new DirectorCmd;
cmd->SetTimeScaleData(1.0);
cmd->SetTime(timepoint->time + 1.5f);
m_Commands.Add(cmd, cmd->GetTime());
}
return trailTime + timepoint->time - m_nextCutTime;
}
int Director::GetClosestPlayer(frame_t *frame, int entityIndex)
{
unsigned int i;
unsigned int bestPlayer = 0;
unsigned int maxclients = m_World->GetMaxClients();
if (!m_WorldModel->IsValid()) {
return 0;
}
vec3_t origin;
for (i = 0; i < frame->entitynum; i++)
{
entity_state_t *ent = &((entity_state_t *)frame->entities)[i];
if (ent->number == entityIndex) {
VectorCopy(origin, ent->origin);
break;
}
}
// entityIndex not found
if (i == frame->entitynum) {
return 0;
}
m_WorldModel->SetPVS(origin);
float minDistance = 32000.0f;
unsigned int count = min(maxclients, frame->entitynum);
for (i = 0; i < count; i++)
{
entity_state_t *ent = &((entity_state_t *)frame->entities)[i];
if ((unsigned)(ent->number - 1) < maxclients && m_WorldModel->InPVS(ent->origin))
{
vec3_t offset;
VectorSubtract(ent->origin, origin, offset);
float distance = Length(offset);
if (distance >= 1 && distance < minDistance)
{
minDistance = distance;
bestPlayer = ent->number;
}
}
}
return bestPlayer;
}
void Director::ClearDirectorCommands()
{
DirectorCmd *cmd = (DirectorCmd *)m_Commands.GetFirst();
while (cmd)
{
delete cmd;
cmd = (DirectorCmd *)m_Commands.GetNext();
}
m_Commands.Clear();
}
void Director::RandomizeCommand(DirectorCmd *cmd)
{
if ((cmd->GetType() & DRC_FLAG_NO_RANDOM) || cmd->GetType() != DRC_CMD_EVENT) {
return;
}
int target1, target2, flags;
cmd->GetEventData(target1, target2, flags);
if ((flags & DRC_FLAG_SLOWMOTION) && RandomFloat(0, 1) > 0.25f)
{
flags &= ~DRC_FLAG_SLOWMOTION;
}
// check DRC_CMD_SOUND, DRC_CMD_STATUS, DRC_CMD_BANNER
else if ((flags & DRC_FLAG_PRIO_MASK) > DRC_CMD_MESSAGE
&& (flags & DRC_FLAG_PRIO_MASK) < DRC_CMD_STUFFTEXT && RandomFloat(0, 1) < 0.15f)
{
flags |= DRC_FLAG_SLOWMOTION;
}
// toggle flag DRC_FLAG_DRAMATIC
if (RandomFloat(0, 1) < 0.33f) {
flags ^= DRC_FLAG_DRAMATIC;
}
if (target1 && target2 && !(flags & DRC_FLAG_SLOWMOTION) && RandomFloat(0, 1) < 0.33f)
{
int swap = target1;
target1 = target2;
target2 = swap;
}
worldHistory_t *now = &m_history[m_nextCutSeqnr % m_historyLength];
vec3_t v1, v2;
VectorSubtract(now->players[target2 % MAX_CLIENTS].origin, now->players[target1 % MAX_CLIENTS].origin, v1);
v1[2] = 0;
VectorAngles(v1, v1);
VectorCopy(now->players[target1 % MAX_CLIENTS].angles, v2);
if (AngleLeftOfOther(v1, v2))
flags &= ~DRC_FLAG_SIDE;
else
flags |= DRC_FLAG_SIDE;
if (target1 == target2) {
target2 = 0;
}
cmd->SetEventData(target1, target2, flags);
}
void Director::ExecuteCommand(int commandID, char *commandLine)
{
if (commandID == CMD_ID_SLOWMOTION) {
CMD_SlowMotion(commandLine);
return;
}
m_System->Printf("ERROR! Director::ExecuteCommand: unknown command ID %i.\n", commandID);
}
char *Director::GetStatusLine()
{
return "Default Director";
}
char *Director::GetType()
{
return DIRECTOR_INTERFACE_VERSION;
}
void Director::ExecuteDirectorCommands()
{
unsigned char bufferdata[4096];
BitBuffer buffer(bufferdata, sizeof(bufferdata));
buffer.Clear();
float newTime = (float)m_Proxy->GetSpectatorTime();
DirectorCmd *cmd = (DirectorCmd *)m_Commands.FindClosestKey(m_LastExecTime);
if (!cmd) {
return;
}
while (cmd && cmd->GetTime() <= newTime)
{
if (cmd->GetTime() > m_LastExecTime)
{
if (cmd->GetType() == DRC_CMD_TIMESCALE)
{
float timescale;
cmd->GetTimeScaleData(timescale);
m_Proxy->SetClientTimeScale(timescale);
if (timescale < 1.0)
{
vec3_t pos = { 0.02f, 0.85f, 0.f };
DirectorCmd slowmo;
slowmo.SetMessageData(0, COM_PackRGBA(255, 160, 0, 255), pos, 0.3f, 0.1f, 2, 0, "Slow Motion");
slowmo.WriteToStream(&buffer);
}
}
else
{
cmd->WriteToStream(&buffer);
}
}
cmd = (DirectorCmd *)m_Commands.GetNext();
}
if (buffer.IsOverflowed())
{
m_System->Printf("Director::ExecuteDirectorCommands: command overflow.\n");
}
else
{
m_Proxy->Broadcast(buffer.GetData(), buffer.CurrentSize(), GROUP_CLIENT_ALL, true);
}
m_LastExecTime = newTime;
}
void Director::CMD_SlowMotion(char *cmdLine)
{
TokenLine params(cmdLine);
if (params.CountToken() != 2) {
m_System->Printf("Syntax: slowmotion <factor>\n");
m_System->Printf("Currently slowmotion factor is %.2f\n", m_slowMotion);
return;
}
float val = (float)atof(params.GetToken(1));
m_slowMotion = clamp(val, 0.05f, 4.0f);
}
Director::worldHistory_t *Director::FindBestEvent()
{
int i;
int nseqMod = m_nextCutSeqnr % m_historyLength;
int bestEvent[] = { 0, 0, 0, 0 };
int bestEventPrio[] = { 0, 0, 0, 0 };
for (i = 0; i < 4; i++)
{
bestEventPrio[i] = 0;
bestEvent[i] = 0;
float tillTime = (i + 1) * 2 + m_nextCutTime;
while (tillTime > m_history[nseqMod].time)
{
if ((m_history[nseqMod].event.flags & DRC_FLAG_PRIO_MASK) > (unsigned int)bestEventPrio[i]) {
bestEventPrio[i] = (m_history[nseqMod].event.flags & DRC_FLAG_PRIO_MASK);
bestEvent[i] = nseqMod;
}
if (++nseqMod == m_historyLength) {
nseqMod = 0;
}
}
}
if (bestEventPrio[0] || bestEventPrio[1] || bestEventPrio[2])
{
if (bestEventPrio[1] >= bestEventPrio[0]
&& bestEventPrio[1] >= bestEventPrio[2]
&& bestEventPrio[1] >= bestEventPrio[3]) {
return &m_history[ bestEvent[1] ];
}
else if (bestEventPrio[0] > bestEventPrio[1]
&& bestEventPrio[0] > bestEventPrio[2]) {
return &m_history[ bestEvent[0] ];
}
else if (bestEventPrio[2] > bestEventPrio[3]) {
return &m_history[ bestEvent[2] ];
}
if (bestEventPrio[0]) {
return &m_history[ bestEvent[0] ];
}
}
return nullptr;
}
int Director::AddCommand(DirectorCmd *cmd)
{
if (cmd->GetType() > DRC_CMD_LAST) {
return 0;
}
if (cmd->GetType() == DRC_CMD_EVENT)
{
int target1, target2, flags;
cmd->GetEventData(target1, target2, flags);
AddEvent(target1, target2, flags);
return 0;
}
DirectorCmd *newcmd = new DirectorCmd;
newcmd->Copy(cmd);
m_Commands.Add(newcmd, newcmd->GetTime());
return 1;
}
IObjectContainer *Director::GetCommands()
{
return &m_Commands;
}
bool Director::RemoveCommand(int index)
{
return false;
}
DirectorCmd *Director::GetLastCommand()
{
return nullptr;
}

View File

@ -0,0 +1,126 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include <HLTV/IProxy.h>
#include <HLTV/IWorld.h>
#include <HLTV/IDirector.h>
#include "BaseSystemModule.h"
#include "ObjectDictionary.h"
class Director: public IDirector, public BaseSystemModule {
public:
Director() {}
virtual ~Director() {}
virtual bool Init(IBaseSystem *system, int serial, char *name);
virtual void RunFrame(double time);
virtual void ReceiveSignal(ISystemModule *module, unsigned int signal, void *data);
virtual void ExecuteCommand(int commandID, char *commandLine);
virtual char *GetStatusLine();
virtual char *GetType();
virtual void ShutDown();
virtual void NewGame(IWorld *world, IProxy *proxy);
virtual int AddCommand(DirectorCmd *cmd);
virtual void WriteCommands(BitBuffer *stream, float startTime, float endTime);
virtual char *GetModName();
virtual bool RemoveCommand(int index);
virtual DirectorCmd *GetLastCommand();
virtual IObjectContainer *GetCommands();
typedef struct playerData_s {
vec3_t origin;
vec3_t angles;
int active;
int target;
float rank;
} playerData_t;
typedef struct worldHistory_s
{
float time;
unsigned int seqNr;
typedef struct worldEvent_s {
int entity1;
int entity2;
unsigned int flags;
} worldEvent_t;
worldEvent_t event;
playerData_t players[MAX_CLIENTS];
} worldHistory_t;
worldHistory_t *FindBestEvent();
void ExecuteDirectorCommands();
void RandomizeCommand(DirectorCmd *cmd);
int GetClosestPlayer(frame_t *frame, int entityIndex);
void AddEvent(int entity1, int entity2, unsigned int flags);
void SmoothRank(int playerNum, float rank);
void AnalysePlayer(int playerNum);
void AnalyseFrame(frame_t *frame);
void ClearDirectorCommands();
float AddBestMODCut();
float AddBestGenericCut();
void WriteSignonData();
void WriteProxyStatus(BitBuffer *stream);
private:
enum LocalCommandIDs { CMD_ID_SLOWMOTION = 1 };
void CMD_SlowMotion(char *cmdLine);
protected:
ObjectDictionary m_Commands;
worldHistory_t *m_history;
float m_maxRank;
enum { MAX_WORLD_HISTORY = 200 };
float m_gaussFilter[MAX_WORLD_HISTORY];
int m_historyLength;
unsigned int m_nextCutSeqnr;
unsigned int m_currentSeqnr;
float m_nextCutTime;
float m_currentTime;
float m_LastExecTime;
float m_slowMotion;
worldHistory_t::worldEvent_t m_frameEvent;
DirectorCmd *m_lastCut;
IBSPModel *m_WorldModel;
bool m_Active;
IWorld *m_World;
IProxy *m_Proxy;
};

View File

@ -0,0 +1,57 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include <HLTV/IWorld.h>
#include <HLTV/IDirector.h>
#include "BaseSystemModule.h"
class IObjectContainer;
class DirectorNull: public IDirector, public BaseSystemModule {
public:
void NewGame(IWorld *world, IProxy *proxy)
{
static unsigned char cmd[] = {
1, // command length in bytes
DRC_CMD_START // tell them for start director
};
world->AddSignonData(svc_director, cmd, sizeof(cmd));
}
int AddCommand(DirectorCmd *cmd) { return 0; }
void WriteCommands(BitBuffer *stream, float startTime, float endTime) {}
char *GetModName() { return "NULL"; }
bool RemoveCommand(int index) { return false; }
DirectorCmd *GetLastCommand() { return nullptr; }
IObjectContainer *GetCommands() { return nullptr; }
virtual ~DirectorNull() {}
};

View File

@ -0,0 +1 @@
#include "precompiled.h"

View File

@ -0,0 +1,24 @@
#pragma once
#include "osconfig.h"
#include "archtypes.h"
#include "mathlib.h"
#include "FileSystem.h"
#include "TokenLine.h"
#include "interface.h"
#include "hltv.h"
#include "mem.h"
#include "common.h"
#include "common/random.h"
#include "common/byteorder.h"
#include "common/BitBuffer.h"
#include "common/DirectorCmd.h"
#include "common/mathlib_internal.h"
#include "common/net_internal.h"
#include "common/common_hltv.h"
#include "Director.h"
#include "DirectorNull.h"

View File

@ -0,0 +1,3 @@
#include "precompiled.h"
#include "interface.cpp"

View File

@ -0,0 +1,165 @@
import org.doomedsociety.gradlecpp.cfg.ToolchainConfigUtils
import org.doomedsociety.gradlecpp.msvc.MsvcToolchainConfig
import org.doomedsociety.gradlecpp.toolchain.icc.Icc
import org.doomedsociety.gradlecpp.toolchain.icc.IccCompilerPlugin
import org.doomedsociety.gradlecpp.gcc.GccToolchainConfig
import org.gradle.nativeplatform.NativeBinarySpec
import org.gradle.nativeplatform.NativeLibrarySpec
import org.gradle.nativeplatform.toolchain.VisualCpp
apply plugin: 'cpp'
apply plugin: IccCompilerPlugin
apply plugin: GccCompilerPlugin
project.ext.dep_bzip2 = project(':dep/bzip2')
void setupToolchain(NativeBinarySpec b) {
def cfg = rootProject.createToolchainConfig(b);
cfg.projectInclude(project, '/..', '/../..', '/src', '/../Director/src', '/../../common', '/../../engine', '/../../public', '/../../public/rehlds', '/../../pm_shared');
cfg.projectInclude(dep_bzip2, '/include')
cfg.singleDefines 'USE_BREAKPAD_HANDLER', 'HLTV', 'CORE_MODULE'
if (cfg instanceof MsvcToolchainConfig) {
cfg.compilerOptions.pchConfig = new MsvcToolchainConfig.PrecompiledHeadersConfig(
enabled: true,
pchHeader: 'precompiled.h',
pchSourceSet: 'proxy_pch'
);
cfg.singleDefines('_CRT_SECURE_NO_WARNINGS')
cfg.compilerOptions.args '/Ob2', '/Oi', '/GF'
cfg.projectLibpath(project, '/../../lib')
cfg.extraLibs "steam_api.lib", "psapi.lib", "ws2_32.lib"
}
else if (cfg instanceof GccToolchainConfig) {
cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions(
enabled: true,
pchSourceSet: 'proxy_pch'
);
cfg.compilerOptions.languageStandard = 'c++0x'
cfg.defines([
'_strdup': 'strdup',
'_stricmp': 'strcasecmp',
'_strnicmp': 'strncasecmp',
'_vsnprintf': 'vsnprintf',
'_snprintf': 'snprintf',
]);
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-fno-exceptions'
cfg.projectLibpath(project, '/../../lib/linux32')
cfg.extraLibs "steam_api"
}
ToolchainConfigUtils.apply(project, cfg, b);
}
model {
buildTypes {
release
}
platforms {
x86 {
architecture "x86"
}
}
toolChains {
visualCpp(VisualCpp) {
}
icc(Icc) {
}
}
components {
proxy(NativeLibrarySpec) {
targetPlatform 'x86'
baseName 'proxy'
sources {
proxy_main(CppSourceSet) {
source {
srcDir "src"
include "**/*.cpp"
exclude "precompiled.cpp"
}
lib project: ':dep/bzip2', library: 'bzip2', linkage: 'static'
}
proxy_common(CppSourceSet) {
source {
srcDirs "../../common", "../common"
// common
include "BaseSystemModule.cpp"
include "ObjectDictionary.cpp"
include "ObjectList.cpp"
include "TokenLine.cpp"
// HLTV common
include "BaseClient.cpp"
include "BitBuffer.cpp"
include "byteorder.cpp"
include "common.cpp"
include "DemoFile.cpp"
include "DirectorCmd.cpp"
include "InfoString.cpp"
include "mathlib.cpp"
include "md5.cpp"
include "munge.cpp"
include "NetAddress.cpp"
include "NetChannel.cpp"
include "random.cpp"
}
}
proxy_engine(CppSourceSet) {
source {
srcDir "../../engine"
include "mem.cpp"
}
}
proxy_director(CppSourceSet) {
source {
srcDir "../Director/src"
include "Director.cpp"
}
}
proxy_pch(CppSourceSet) {
source {
srcDir "src"
include "precompiled.cpp"
lib project: ':dep/bzip2', library: 'bzip2', linkage: 'static'
}
}
}
binaries.all {
NativeBinarySpec b -> project.setupToolchain(b)
}
}
}
}
task buildFixes {
dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
}
}
task buildRelease {
dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
}
}
// prevent static lib building
binaries.withType(StaticLibraryBinarySpec) { binary ->
buildable = false
}

View File

@ -0,0 +1,39 @@
@echo OFF
::
:: Post-build auto-deploy script
:: Create and fill PublishPath.txt file with path to deployment folder
:: I.e. PublishPath.txt should contain one line with a folder path
:: Call it so:
:: IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")
::
SET targetDir=%~1
SET targetName=%~2
SET targetExt=%~3
SET projectDir=%~4
SET destination=
IF NOT EXIST "%projectDir%\PublishPath.txt" (
ECHO No deployment path specified. Create PublishPath.txt near PostBuild.bat with paths on separate lines for auto deployment.
exit /B 0
)
FOR /f "tokens=* delims= usebackq" %%a IN ("%projectDir%\PublishPath.txt") DO (
ECHO Deploying to: %%a
IF NOT "%%a" == "" (
copy /Y "%targetDir%%targetName%%targetExt%" "%%a"
IF NOT ERRORLEVEL 1 (
IF EXIST "%targetDir%%targetName%.pdb" (
copy /Y "%targetDir%%targetName%.pdb" "%%a"
)
) ELSE (
ECHO PostBuild.bat ^(27^) : warning : Can't copy '%targetName%%targetExt%' to deploy path '%%a'
)
)
)
IF "%%a" == "" (
ECHO No deployment path specified.
)
exit /B 0

View File

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Proxy", "Proxy.vcxproj", "{ADDFF069-D39D-4A1B-87C9-85A62B980547}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bzip2", "..\..\..\..\dep\bzip2\msvc\bzip2.vcxproj", "{792DF067-9904-4579-99B9-46C17277ADE3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{ADDFF069-D39D-4A1B-87C9-85A62B980547}.Debug|Win32.ActiveCfg = Debug|Win32
{ADDFF069-D39D-4A1B-87C9-85A62B980547}.Debug|Win32.Build.0 = Debug|Win32
{ADDFF069-D39D-4A1B-87C9-85A62B980547}.Release|Win32.ActiveCfg = Release|Win32
{ADDFF069-D39D-4A1B-87C9-85A62B980547}.Release|Win32.Build.0 = Release|Win32
{792DF067-9904-4579-99B9-46C17277ADE3}.Debug|Win32.ActiveCfg = Debug|Win32
{792DF067-9904-4579-99B9-46C17277ADE3}.Debug|Win32.Build.0 = Debug|Win32
{792DF067-9904-4579-99B9-46C17277ADE3}.Release|Win32.ActiveCfg = Release|Win32
{792DF067-9904-4579-99B9-46C17277ADE3}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,377 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\common\BaseSystemModule.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\..\common\ObjectDictionary.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\..\common\ObjectList.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\..\common\TokenLine.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\..\engine\mem.cpp" />
<ClCompile Include="..\..\..\hookers\HLTV\Proxy\hooklist.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\..\hookers\HLTV\Proxy\main.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\BaseClient.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\BitBuffer.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\byteorder.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\common.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\DemoFile.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\DirectorCmd.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\InfoString.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\mathlib.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\md5.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\munge.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\NetAddress.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\NetChannel.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\common\random.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\Director\src\Director.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\DemoClient.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\FakeClient.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\Master.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\precompiled.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\src\Proxy.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\ProxyClient.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\public_amalgamation.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\Status.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\common\BaseSystemModule.h" />
<ClInclude Include="..\..\..\common\ObjectDictionary.h" />
<ClInclude Include="..\..\..\common\ObjectList.h" />
<ClInclude Include="..\..\..\common\TokenLine.h" />
<ClInclude Include="..\..\..\engine\mem.h" />
<ClInclude Include="..\..\..\hookers\HLTV\Proxy\hooklist.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\..\common\BaseClient.h" />
<ClInclude Include="..\..\common\BitBuffer.h" />
<ClInclude Include="..\..\common\byteorder.h" />
<ClInclude Include="..\..\common\common_hltv.h" />
<ClInclude Include="..\..\common\DemoFile.h" />
<ClInclude Include="..\..\common\DirectorCmd.h" />
<ClInclude Include="..\..\common\InfoString.h" />
<ClInclude Include="..\..\common\mathlib_internal.h" />
<ClInclude Include="..\..\common\md5.h" />
<ClInclude Include="..\..\common\munge.h" />
<ClInclude Include="..\..\common\NetChannel.h" />
<ClInclude Include="..\..\common\NetAddress.h" />
<ClInclude Include="..\..\common\net_internal.h" />
<ClInclude Include="..\..\common\random.h" />
<ClInclude Include="..\src\DemoClient.h" />
<ClInclude Include="..\src\FakeClient.h" />
<ClInclude Include="..\src\Master.h" />
<ClInclude Include="..\src\precompiled.h" />
<ClInclude Include="..\src\Proxy.h" />
<ClInclude Include="..\src\ProxyClient.h" />
<ClInclude Include="..\src\Status.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\dep\bzip2\msvc\bzip2.vcxproj">
<Project>{792df067-9904-4579-99b9-46c17277ade3}</Project>
</ProjectReference>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{ADDFF069-D39D-4A1B-87C9-85A62B980547}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Proxy</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetName>proxy</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<TargetName>proxy</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>HLTV;WIN32;_DEBUG;_WINDOWS;_USRDLL;PROXY_MODULE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)\..\src;$(ProjectDir)\..\..\;$(ProjectDir)\..\..\..\;$(ProjectDir)\..\..\Director\src;$(ProjectDir)\..\..\..\common;$(ProjectDir)\..\..\..\engine;$(ProjectDir)\..\..\..\public;$(ProjectDir)\..\..\..\public\rehlds;$(ProjectDir)\..\..\..\pm_shared;$(ProjectDir)\..\..\..\..\dep\bzip2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>psapi.lib;ws2_32.lib;steam_api.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)../../../lib</AdditionalLibraryDirectories>
</Link>
<CustomBuildStep>
<Message>Force build to run Pre-Build event</Message>
</CustomBuildStep>
<CustomBuildStep>
<Outputs>git.always.run</Outputs>
</CustomBuildStep>
<CustomBuildStep>
<Inputs>git.always.run</Inputs>
<Command>echo Empty Action</Command>
</CustomBuildStep>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>HLTV;WIN32;NDEBUG;_WINDOWS;_USRDLL;PROXY_MODULE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)\..\src;$(ProjectDir)\..\..\;$(ProjectDir)\..\..\..\;$(ProjectDir)\..\..\Director\src;$(ProjectDir)\..\..\..\common;$(ProjectDir)\..\..\..\engine;$(ProjectDir)\..\..\..\public;$(ProjectDir)\..\..\..\public\rehlds;$(ProjectDir)\..\..\..\pm_shared;$(ProjectDir)\..\..\..\..\dep\bzip2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>psapi.lib;ws2_32.lib;steam_api.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)../../../lib</AdditionalLibraryDirectories>
</Link>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>
</Message>
</PreBuildEvent>
<CustomBuildStep>
<Command>echo Empty Action</Command>
</CustomBuildStep>
<CustomBuildStep>
<Message>Force build to run Pre-Build event</Message>
</CustomBuildStep>
<CustomBuildStep>
<Outputs>git.always.run</Outputs>
</CustomBuildStep>
<CustomBuildStep>
<Inputs>git.always.run</Inputs>
</CustomBuildStep>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
</PostBuildEvent>
<PostBuildEvent>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,195 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{e272c141-8f15-473d-9ea7-8c46b9f2db19}</UniqueIdentifier>
</Filter>
<Filter Include="HLTV">
<UniqueIdentifier>{b7066def-60e7-4352-8787-a31a8f9dec0d}</UniqueIdentifier>
</Filter>
<Filter Include="HLTV\common">
<UniqueIdentifier>{feda00f0-7c09-4c63-b5a1-e4fbcdfc6b69}</UniqueIdentifier>
</Filter>
<Filter Include="src\hookers">
<UniqueIdentifier>{199d99ef-8924-48fc-8c8a-2859f8d40c82}</UniqueIdentifier>
</Filter>
<Filter Include="engine">
<UniqueIdentifier>{1777708a-8593-40c0-8caa-9154180854dc}</UniqueIdentifier>
</Filter>
<Filter Include="common">
<UniqueIdentifier>{ee194364-02f4-428c-a25f-0a60a7d20263}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\common\BaseClient.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\BitBuffer.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\DemoFile.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\DirectorCmd.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\InfoString.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\mathlib.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\md5.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\munge.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\NetAddress.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\NetChannel.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\src\DemoClient.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\FakeClient.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Master.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\precompiled.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Proxy.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\ProxyClient.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\public_amalgamation.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Status.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\common\common.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\random.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\common\byteorder.cpp">
<Filter>HLTV\common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\hookers\HLTV\Proxy\hooklist.cpp">
<Filter>src\hookers</Filter>
</ClCompile>
<ClCompile Include="..\..\..\hookers\HLTV\Proxy\main.cpp">
<Filter>src\hookers</Filter>
</ClCompile>
<ClCompile Include="..\..\Director\src\Director.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\BaseSystemModule.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\ObjectDictionary.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\ObjectList.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\common\TokenLine.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\..\engine\mem.cpp">
<Filter>engine</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\common\BitBuffer.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\DemoFile.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\DirectorCmd.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\InfoString.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\mathlib_internal.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\md5.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\munge.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\src\precompiled.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\Proxy.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\DemoClient.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\common\BaseClient.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\src\FakeClient.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\Master.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\ProxyClient.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\Status.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\common\common_hltv.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\net_internal.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\NetChannel.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\random.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\byteorder.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\common\NetAddress.h">
<Filter>HLTV\common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\hookers\HLTV\Proxy\hooklist.h">
<Filter>src\hookers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\BaseSystemModule.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\ObjectDictionary.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\ObjectList.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\common\TokenLine.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\engine\mem.h">
<Filter>engine</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,294 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
bool DemoClient::Init(IBaseSystem *system, int serial, char *name)
{
BaseSystemModule::Init(system, serial, name);
m_Proxy = nullptr;
m_LastFrameSeqNr = 0;
m_ClientDelta = 0;
m_IsActive = false;
memset(m_BaseFileName, 0, sizeof(m_BaseFileName));
m_DemoInfo.SetMaxSize(MAX_DEMO_INFO);
m_State = MODULE_RUNNING;
m_System->Printf("Demo client initialized.\n");
return true;
}
char *DemoClient::GetStatusLine()
{
static char string[256];
_snprintf(string, sizeof(string), "Recording to %s (%.1f seconds)\n", m_DemoFile.GetFileName(), m_DemoFile.GetDemoTime());
return string;
}
bool DemoClient::IsHearingVoices()
{
return true;
}
bool DemoClient::HasChatEnabled()
{
return false;
}
char *DemoClient::GetType()
{
return DEMOCLIENT_INTERFACE_VERSION;
}
int DemoClient::GetClientType()
{
return TYPE_DEMO;
}
void DemoClient::Reconnect()
{
FinishDemo();
}
bool DemoClient::Connect(INetSocket *socket, NetAddress *adr, char *userinfo)
{
if (IsActive())
{
if (m_DemoFile.IsRecording()) {
m_System->Printf("Already recording to %s.\n", m_DemoFile.GetFileName());
} else {
m_System->Printf("Already recording initialized for %s.\n", m_BaseFileName);
}
return false;
}
m_DemoChannel.Create(m_System);
m_DemoChannel.SetUpdateRate(40);
m_DemoChannel.SetRate(20000);
m_LastFrameSeqNr = 0;
m_ClientDelta = 0;
m_DemoChannel.SetKeepAlive(false);
m_DemoFile.Init(m_World, nullptr, &m_DemoChannel);
m_IsActive = true;
m_System->Printf("Recording initialized.\n");
return true;
}
void DemoClient::RunFrame(double time)
{
BaseSystemModule::RunFrame(time);
NetPacket *packet = m_DemoChannel.GetPacket();
while (packet)
{
m_System->DPrintf("WARNING! Incoming data in demo game channel.Ignored.\n");
m_DemoChannel.FreePacket(packet);
packet = m_DemoChannel.GetPacket();
}
if (IsActive() && m_World->IsActive() && m_DemoChannel.IsReadyToSend()) {
SendDatagram();
}
}
void DemoClient::SendDatagram()
{
if (m_Proxy->GetDelay() > 0)
{
double worldTime = m_Proxy->GetSpectatorTime();
double proxyTime = m_Proxy->GetProxyTime();
frame_t *frame = m_World->GetFrameByTime(worldTime);
if (!frame) {
return;
}
if (frame->seqnr > 1) {
WriteDatagram(proxyTime - (worldTime - frame->time), frame);
}
return;
}
frame_t *frame = m_World->GetLastFrame();
if (frame) {
WriteDatagram(frame->time, frame);
}
}
void DemoClient::WriteDatagram(double time, frame_t *frame)
{
unsigned int deltaFrameSeqNr = m_LastFrameSeqNr;
if (deltaFrameSeqNr > 0)
{
if (deltaFrameSeqNr == frame->seqnr)
return;
if (deltaFrameSeqNr > frame->seqnr)
m_LastFrameSeqNr = frame->seqnr - 1;
}
else
{
char mapname[MAX_PATH];
COM_FileBase(m_World->GetLevelName(), mapname);
char fileName[MAX_PATH];
_snprintf(fileName, sizeof(fileName), "%s-%s-%s.dem", m_BaseFileName, COM_TimeString(), mapname);
m_DemoFile.StartRecording(fileName);
m_Proxy->WriteSignonData(TYPE_DEMO, &m_DemoChannel.m_reliableStream);
}
m_DemoChannel.m_unreliableStream.WriteByte(svc_time);
m_DemoChannel.m_unreliableStream.WriteFloat((float)time);
m_World->WriteFrame(frame, m_LastFrameSeqNr, &m_DemoChannel.m_reliableStream, &m_DemoChannel.m_unreliableStream, deltaFrameSeqNr, m_ClientDelta, true);
m_LastFrameSeqNr = frame->seqnr;
m_ClientDelta = (m_DemoChannel.m_outgoing_sequence & 0xFF);
// reliable stream has overflowed
if (m_DemoChannel.m_reliableStream.IsOverflowed())
{
m_System->Printf("WARNING! DemoClient::WriteDatagram: reliable data overflow.\n");
Disconnect("reliable data overflow");
return;
}
if (m_DemoChannel.m_unreliableStream.IsOverflowed()) {
m_DemoChannel.m_unreliableStream.Clear();
}
m_DemoFile.WriteDemoMessage(&m_DemoChannel.m_unreliableStream, &m_DemoChannel.m_reliableStream);
m_DemoChannel.TransmitOutgoing();
client_data_t cdata;
memset(&cdata, 0, sizeof(cdata));
m_DemoFile.WriteUpdateClientData(&cdata);
}
bool DemoClient::IsActive()
{
return m_IsActive;
}
void DemoClient::Disconnect(const char *reason)
{
if (!IsActive())
return;
if (reason)
{
m_DemoChannel.m_reliableStream.WriteByte(svc_print);
m_DemoChannel.m_reliableStream.WriteString(reason);
}
FinishDemo();
m_IsActive = false;
}
void DemoClient::ShutDown()
{
if (m_State == MODULE_DISCONNECTED)
return;
FinishDemo();
m_IsActive = false;
BaseSystemModule::ShutDown();
m_System->Printf("Demo module shutdown.\n");
}
void DemoClient::FinishDemo()
{
if (!IsActive())
return;
m_DemoChannel.m_reliableStream.WriteByte(svc_print);
m_DemoChannel.m_reliableStream.WriteString("HLTV Demo finished.\n");
m_DemoFile.WriteDemoMessage(&m_DemoChannel.m_unreliableStream, &m_DemoChannel.m_reliableStream);
m_DemoFile.CloseFile();
m_DemoChannel.Clear();
m_LastFrameSeqNr = 0;
m_ClientDelta = 0;
}
NetAddress *DemoClient::GetAddress()
{
static NetAddress fakeaddress;
fakeaddress.Clear();
return &fakeaddress;
}
void DemoClient::Send(unsigned char *data, int length, bool isReliable)
{
if (isReliable)
m_DemoChannel.m_reliableStream.WriteBuf(data, length);
else
m_DemoChannel.m_unreliableStream.WriteBuf(data, length);
}
void DemoClient::SetProxy(IProxy *proxy)
{
m_Proxy = proxy;
}
InfoString *DemoClient::GetUserInfo()
{
return &m_DemoInfo;
}
char *DemoClient::GetClientName()
{
return m_Name;
}
void DemoClient::SetWorld(IWorld *world)
{
m_World = world;
}
void DemoClient::SetFileName(char *fileName)
{
strcopy(m_BaseFileName, fileName);
}
DemoFile *DemoClient::GetDemoFile()
{
return &m_DemoFile;
}

View File

@ -0,0 +1,78 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "common/InfoString.h"
class DemoClient: public IClient, public BaseSystemModule {
public:
DemoClient() {}
virtual ~DemoClient() {}
bool Init(IBaseSystem *system, int serial, char *name);
void RunFrame(double time);
char *GetStatusLine();
char *GetType();
void ShutDown();
bool Connect(INetSocket *socket = nullptr, NetAddress *adr = nullptr, char *userinfo = "");
void Disconnect(const char *reason);
void Reconnect();
void SetWorld(IWorld *world);
bool IsHearingVoices();
bool HasChatEnabled();
NetAddress *GetAddress();
int GetClientType();
char *GetClientName();
InfoString *GetUserInfo();
bool IsActive();
void Send(unsigned char *data, int length, bool isReliable);
void SetProxy(IProxy *proxy);
void SetFileName(char *fileName);
DemoFile *GetDemoFile();
void FinishDemo();
void SendDatagram();
void WriteDatagram(double time, frame_t *frame);
protected:
IProxy *m_Proxy;
IWorld *m_World;
bool m_IsActive;
NetChannel m_DemoChannel;
enum { MAX_DEMO_INFO = 256 };
DemoFile m_DemoFile;
char m_BaseFileName[MAX_PATH];
InfoString m_DemoInfo;
unsigned int m_LastFrameSeqNr;
unsigned int m_ClientDelta;
};
#define DEMOCLIENT_INTERFACE_VERSION "democlient000"

View File

@ -0,0 +1,156 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
bool FakeClient::Init(IBaseSystem *system, int serial, char *name)
{
BaseSystemModule::Init(system, serial, name);
_snprintf(m_Name, sizeof(m_Name), "fakeclient%i", serial);
m_Network = dynamic_cast<INetwork *>(m_System->GetModule(NETWORK_INTERFACE_VERSION, "core"));
if (!m_Network)
{
m_System->Errorf("FakeClient::Init: couldn't load network module.\n");
return false;
}
if (!(m_Socket = m_Network->CreateSocket(serial + 2048)))
{
m_System->Errorf("FakeClient::Init: Could not create port %i.\n", serial + 2048);
return false;
}
char temp[256];
sprintf(temp, "fakeserver%i", serial);
m_Server = dynamic_cast<IServer *>(m_System->GetModule(SERVER_INTERFACE_VERSION, "core", temp));
if (!m_Server)
{
m_System->Errorf("FakeClient::Init: couldn't load server module.\n");
return false;
}
m_Server->RegisterListener(this);
m_Server->SetUserInfo("hspecs", "0");
m_Server->SetUserInfo("hslots", "0");
m_Server->SetDelayReconnect(false);
m_Server->SetPlayerName(m_Name);
m_Server->SetAutoRetry(false);
sprintf(temp, "fakeworld%i", serial);
m_World = dynamic_cast<IWorld *>(m_System->GetModule(WORLD_INTERFACE_VERSION, "core", temp));
if (!m_World)
{
m_System->Errorf("FakeClient::Init: couldn't load world module.\n");
return false;
}
m_World->RegisterListener(this);
m_State = MODULE_RUNNING;
m_System->Printf("Fake client module initialized (%i).\n", serial);
return true;
}
void FakeClient::RunFrame(double time)
{
BaseSystemModule::RunFrame(time);
NetPacket *packet;
while ((packet = m_Socket->ReceivePacket()))
{
m_System->DPrintf("FakeClient: WARNING! Packet from %s with invalid sequence number.\n", packet->address.ToString());
m_Socket->FreePacket(packet);
}
}
void FakeClient::SetRate(int rate)
{
m_Server->SetRate(rate);
}
void FakeClient::Connect(NetAddress *adr)
{
m_Server->Connect(m_World, adr, m_Socket);
}
void FakeClient::Retry()
{
m_Server->Retry();
}
void FakeClient::Say(char *text)
{
if (!m_Server->IsConnected())
return;
char string[1024];
_snprintf(string, sizeof(string), "say \"%s\"", text);
m_Server->SendStringCommand(text);
}
void FakeClient::Disconnect()
{
m_Server->Disconnect();
}
void FakeClient::ShutDown()
{
if (m_State == MODULE_DISCONNECTED)
return;
if (m_World) {
m_World->RemoveListener(this);
}
BaseSystemModule::ShutDown();
m_System->Printf("FakeClient module shutdown.\n");
}
void FakeClient::ReceiveSignal(ISystemModule *module, unsigned int signal, void *data)
{
if (module->GetSerial() != m_World->GetSerial())
return;
if (signal == 8 /* signal to shutdown*/) {
ShutDown();
}
}
char *FakeClient::GetType()
{
return FAKECLIENT_INTERFACE_VERSION;
}
char *FakeClient::GetStatusLine()
{
return "I am a fake client.\n";
}

View File

@ -0,0 +1,63 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "BaseSystemModule.h"
class IWorld;
class IServer;
class INetwork;
class INetSocket;
class FakeClient: public BaseSystemModule {
public:
FakeClient() {}
virtual ~FakeClient() {}
bool Init(IBaseSystem *system, int serial, char *name);
void RunFrame(double time);
void ReceiveSignal(ISystemModule *module, unsigned int signal, void *data);
char *GetStatusLine();
char *GetType();
void ShutDown();
void SetRate(int rate);
void Connect(NetAddress *adr);
void Retry();
void Say(char *text);
void Disconnect();
protected:
INetwork *m_Network;
IWorld *m_World;
IServer *m_Server;
INetSocket *m_Socket;
};
#define FAKECLIENT_INTERFACE_VERSION "fakeclient000"

View File

@ -0,0 +1,293 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
Master::GameToAppIDMapItem_t Master::m_GameToAppIDMap[] =
{
{ GAME_APPID_CSTRIKE, "cstrike" },
{ GAME_APPID_TFC, "tfc" },
{ GAME_APPID_DOD, "dod" },
{ GAME_APPID_DMC, "dmc" },
{ GAME_APPID_GEARBOX, "gearbox" },
{ GAME_APPID_RICOCHET, "ricochet" },
{ GAME_APPID_VALVE, "valve" },
{ GAME_APPID_CZERO, "czero" },
{ GAME_APPID_CZEROR, "czeror" },
{ GAME_APPID_BSHIFT, "bshift" },
{ GAME_APPID_CSTRIKE_BETA, "cstrike_beta" }
};
Master::Master() :
m_flMasterUpdateTime(0),
m_bSteamInitialized(false)
{
}
int Master::GetGameAppID(const char *gamedir) const
{
for (auto& game : m_GameToAppIDMap) {
if (!_stricmp(game.dir, gamedir)) {
return game.appID;
}
}
return GAME_APPID_VALVE;
}
bool Master::Init(IBaseSystem *system, int serial, char *name)
{
BaseSystemModule::Init(system, serial, name);
m_MasterSocket = m_Proxy->GetSocket();
m_System->RegisterCommand("heartbeat", this, CMD_ID_HEARTBEAT);
m_System->RegisterCommand("nomaster", this, CMD_ID_NOMASTER);
m_System->RegisterCommand("listmaster", this, CMD_ID_LISTMASTER);
m_State = MODULE_RUNNING;
m_NoMaster = false;
m_bMasterLoaded = false;
INetwork *network = m_MasterSocket->GetNetwork();
if (!network->GetLocalAddress()) {
m_System->Printf("Master module failed to initialize (no net).\n");
return false;
}
m_bSteamInitialized = false;
m_System->Printf("Master module initialized.\n");
return true;
}
void Master::SetProxy(IProxy *proxy)
{
m_Proxy = proxy;
}
void Master::RunFrame(double time)
{
BaseSystemModule::RunFrame(time);
static double s_flLastRunCallbacks = 0.0f;
if ((time - s_flLastRunCallbacks) > 0.1)
{
SteamGameServer_RunCallbacks();
s_flLastRunCallbacks = time;
}
if (m_NoMaster)
return;
if (m_Proxy->IsActive())
{
if (!m_bSteamInitialized)
{
IWorld *world = m_Proxy->GetWorld();
if (world)
{
int nAppID = GetGameAppID(world->GetGameDir());
if (nAppID > 0)
{
FILE *f = fopen("steam_appid.txt", "w+");
if (f)
{
fprintf(f, "%d\n", nAppID);
fclose(f);
}
}
INetwork *network = m_MasterSocket->GetNetwork();
NetAddress *netAdr = network->GetLocalAddress();
if (SteamGameServer_Init(ntohl(*(u_long *)&netAdr->m_IP[0]), 0, 0, 0xFFFFu, eServerModeNoAuthentication, MASTER_VERSION))
{
SteamGameServer()->SetProduct("hltv");
SteamGameServer()->SetGameDescription("hltv");
SteamGameServer()->SetModDir(world->GetGameDir());
SteamGameServer()->SetDedicatedServer(true);
SteamGameServer()->SetSpectatorPort(netAdr->m_Port);
SteamGameServer()->LogOnAnonymous();
SteamGameServer()->EnableHeartbeats(true);
}
else
{
// NOTE: Actually here call via Printf, but we will be use DPrintf to avoid useless print into console
// or at least make only print once.
m_System->DPrintf("Master module failed to initialize. (init failed)\n");
}
m_bSteamInitialized = SteamGameServer() ? true : false;
}
}
if (m_bSteamInitialized)
{
IWorld *world = m_Proxy->GetWorld();
if (m_flMasterUpdateTime < m_System->GetTime())
{
char mapName[MAX_PATH];
COM_FileBase(world->GetLevelName(), mapName);
char szHostName[MAX_PATH];
strcopy(szHostName, world->GetHostName());
int slots, proxies, spectators;
m_Proxy->GetStatistics(proxies, slots, spectators);
SteamGameServer()->SetMaxPlayerCount(min(slots, 127)); // max slots
SteamGameServer()->SetServerName(szHostName);
SteamGameServer()->SetMapName(mapName);
SteamGameServer()->SetPasswordProtected(m_Proxy->IsPasswordProtected());
SteamGameServer()->SetModDir(world->GetGameDir());
m_flMasterUpdateTime = m_System->GetTime() + 5.0f;
}
}
}
if (m_bSteamInitialized)
{
uint32 ip;
uint16 port;
char szOutBuf[4096];
int iLen = SteamGameServer()->GetNextOutgoingPacket(szOutBuf, sizeof(szOutBuf), &ip, &port);
while (iLen > 0)
{
NetAddress netAdr;
*((uint32 *)&netAdr.m_IP[0]) = htonl(ip);
netAdr.m_Port = htons(port);
m_MasterSocket->SendPacket(&netAdr, szOutBuf, iLen);
iLen = SteamGameServer()->GetNextOutgoingPacket(szOutBuf, sizeof(szOutBuf), &ip, &port);
}
}
}
void Master::ShutDown()
{
if (m_State == MODULE_DISCONNECTED) {
return;
}
if (SteamGameServer()) {
SteamGameServer()->LogOff();
}
BaseSystemModule::ShutDown();
SteamGameServer_Shutdown();
m_System->Printf("Master module shutdown.\n");
}
void Master::CMD_Heartbeat(char *cmdLine)
{
if (m_State == MODULE_DISCONNECTED) {
return;
}
if (SteamGameServer()) {
SteamGameServer()->ForceHeartbeat();
}
}
void Master::CMD_NoMaster(char *cmdLine)
{
if (m_State == MODULE_DISCONNECTED || !SteamGameServer()) {
return;
}
TokenLine params(cmdLine);
if (params.CountToken() != 2)
{
m_System->Printf("Syntax: nomaster <0|1>\n");
m_System->Printf("Master server notification is %s.\n", m_NoMaster ? "disabled" : "enabled");
return;
}
bool bOldMasterState = m_NoMaster;
m_NoMaster = atoi(params.GetToken(1)) ? true : false;
if (bOldMasterState != m_NoMaster) {
SteamGameServer()->EnableHeartbeats(m_NoMaster);
}
}
void Master::CMD_ListMaster(char *pchCmdLine)
{
if (m_State == MODULE_DISCONNECTED) {
return;
}
m_System->Printf("No longer used\n");
}
void Master::ExecuteCommand(int commandID, char *commandLine)
{
switch (commandID)
{
case CMD_ID_HEARTBEAT:
CMD_Heartbeat(commandLine);
break;
case CMD_ID_NOMASTER:
CMD_NoMaster(commandLine);
break;
case CMD_ID_LISTMASTER:
CMD_ListMaster(commandLine);
break;
default:
m_System->Printf("ERROR! Master::ExecuteCommand: unknown command ID %i.\n", commandID);
break;
}
}
char *Master::GetType()
{
return MASTER_INTERFACE_VERSION;
}
void Master::SendShutdown()
{
if (m_State == MODULE_DISCONNECTED) {
return;
}
if (SteamGameServer()) {
SteamGameServer()->EnableHeartbeats(false);
}
}
char *Master::GetStatusLine()
{
static char string[256];
_snprintf(string, sizeof(string), "Master servers: 0\n");
return string;
}

View File

@ -0,0 +1,115 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "BaseSystemModule.h"
#include "TokenLine.h"
#define MASTER_VERSION "1.1.2.6"
enum GameType_e
{
GT_CSTRIKE,
GT_TFC,
GT_DOD,
GT_DMC,
GT_GEARBOX,
GT_RICOCHET,
GT_VALVE,
GT_CZERO,
GT_CZEROR,
GT_BSHIFT,
GT_CSTRIKE_BETA,
};
class Proxy;
class INetSocket;
class Master: public BaseSystemModule {
public:
Master();
virtual ~Master() {}
bool Init(IBaseSystem *system, int serial, char *name);
void ExecuteCommand(int commandID, char *commandLine);
void RunFrame(double time);
char *GetStatusLine();
char *GetType();
void ShutDown();
void InitializeSteam();
void SendShutdown();
void SetProxy(IProxy *proxy);
private:
enum LocalCommandIDs {
CMD_ID_HEARTBEAT = 1,
CMD_ID_NOMASTER,
CMD_ID_LISTMASTER,
};
void CMD_Heartbeat(char *cmdLine);
void CMD_NoMaster(char *cmdLine);
void CMD_ListMaster(char *cmdLine);
enum {
GAME_APPID_CSTRIKE = 10,
GAME_APPID_TFC = 20,
GAME_APPID_DOD = 30,
GAME_APPID_DMC = 40,
GAME_APPID_GEARBOX = 50,
GAME_APPID_RICOCHET = 60,
GAME_APPID_VALVE = 70,
GAME_APPID_CZERO = 80,
GAME_APPID_CZEROR = 100,
GAME_APPID_BSHIFT = 130,
GAME_APPID_CSTRIKE_BETA = 150,
};
typedef struct GameToAppIDMapItem_s
{
size_t appID;
const char *dir;
} GameToAppIDMapItem_t;
static GameToAppIDMapItem_t m_GameToAppIDMap[];
int GetGameAppID(const char *gamedir) const;
protected:
friend class Proxy;
bool m_NoMaster;
bool m_bMasterLoaded;
INetSocket *m_MasterSocket;
IProxy *m_Proxy;
double m_flMasterUpdateTime;
bool m_bSteamInitialized;
};
#define MASTER_INTERFACE_VERSION "master000"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,377 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "BaseSystemModule.h"
#include "common/NetAddress.h"
#include "ObjectList.h"
#include "DemoClient.h"
#include "Status.h"
#include "Master.h"
#include "Director.h"
#include "DirectorNull.h"
class IWorld;
class IServer;
class INetwork;
class IDirector;
class IBaseSystem;
#define MAX_NAME 32
#define MAX_PROXY_RATE 20000
#define MAX_PROXY_UPDATERATE 40
#define PROXY_CHALLENGE_LIFE 40.0f
#define PROXY_PRIVATE 0x8000
#define PROXY_VERSION "1.1.2.0"
#define PROXY_DEFAULT_PORT "27020"
// TODO: it is necessary to unify with rehlsdk
typedef struct textmessage_s {
int effect;
byte r1, g1, b1, a1; // 2 colors for effects
byte r2, g2, b2, a2;
float x;
float y;
float fadein;
float fadeout;
float holdtime;
float fxtime;
char text[80];
} textmessage_t;
class Proxy: public IProxy, public BaseSystemModule {
public:
Proxy() {}
virtual ~Proxy() {}
bool Init(IBaseSystem *system, int serial, char *name);
void RunFrame(double time);
void ReceiveSignal(ISystemModule *module, unsigned int signal, void *data);
void ExecuteCommand(int commandID, char *commandLine);
char *GetStatusLine();
char *GetType();
void ShutDown();
void Reset();
void Broadcast(byte *data, int length, int groupType, bool isReliable);
void IncreaseCheering(int votes);
void ChatCommentator(char *nick, char *text);
void ChatSpectator(char *nick, char *text);
void CountLocalClients(int &spectators, int &proxies);
void ParseStatusMsg(BitBuffer *stream);
void ParseStatusReport(NetAddress *from, BitBuffer *stream);
bool ProcessConnectionlessMessage(NetAddress *from, BitBuffer *stream);
resource_t *AddResource(char *fileName, resourcetype_t type, char *asFileName = nullptr);
bool IsMaster();
bool IsLanOnly();
bool IsActive();
bool IsPublicGame();
bool IsPasswordProtected();
bool IsStressed();
void SetDelay(float seconds);
void SetClientTime(double time, bool relative);
void SetClientTimeScale(float scale);
void SetMaxRate(int rate);
void SetMaxLoss(float maxloss);
void SetMaxUpdateRate(int updaterate);
bool SetMaxClients(int number);
void SetRegion(unsigned char region);
float GetDelay();
double GetSpectatorTime();
double GetProxyTime();
IObjectContainer *GetClients();
IWorld *GetWorld();
IServer *GetServer();
IDirector *GetDirector();
INetSocket *GetSocket();
ChatMode_e GetChatMode();
void GetStatistics(int &proxies, int &slots, int &spectators);
int GetMaxRate();
int GetMaxClients();
int GetMaxUpdateRate();
resource_t *GetResource(char *fileName);
int GetDispatchMode();
unsigned char GetRegion();
bool WriteSignonData(int type, BitBuffer *stream);
void ReconnectClients();
void ExecuteRcon(NetAddress *from, char *command);
void SendRcon(NetAddress *to, unsigned int challenge);
void ReplyServiceChallenge(NetAddress *to, char *type);
void ReplyListen(NetAddress *to);
void RejectConnection(NetAddress *adr, bool badPassword, const char *fmt, ...);
void ReplyConnect(NetAddress *to, int protocol, int challenge, char *protinfo, char *userinfo);
void ReplyRules(NetAddress *to);
void ReplyPlayers(NetAddress *to);
void ReplyInfo(NetAddress *to, bool detailed);
void ReplyInfoString(NetAddress *to);
void ReplyChallenge(NetAddress *to);
void ReplyPing(NetAddress *to);
void UpdateStatusLine();
void DispatchClient(NetAddress *client, NetAddress *proxy);
bool IsValidPassword(int type, char *pw);
void WriteHUDMsg(textmessage_t *msg, BitBuffer *stream);
typedef struct loopcmd_s {
int id;
float interval;
float lastTime;
char command[255];
} loopcmd_t;
void ExecuteLoopCommands();
unsigned int GetChallengeNumber(NetAddress *host);
bool CheckChallenge(NetAddress *from, unsigned int challengeNumber);
void CreateServerInfoString(InfoString *info);
bool CheckDirectorModule();
void RunClocks();
void NewGameStarted();
void NewServerConnection();
void BroadcastPaused(bool paused);
void BroadcastRetryMessage();
void StopBroadcast(const char *message);
char *GetModVersion(char *gamedir);
void DisconnectClients(const char *reason);
void FreeResource(resource_t *resource);
void ClearResources();
resource_t *LoadResourceFromFile(char *fileName, resourcetype_t type);
bool IsBanned(NetAddress *adr);
void UpdateInfoMessages();
void SetName(char *newName);
private:
enum LocalCommandIDs {
CMD_ID_RCON = 1,
CMD_ID_RCONPASSWORD,
CMD_ID_RCONADDRESS,
CMD_ID_SAY,
CMD_ID_MSG,
CMD_ID_CLIENTS,
CMD_ID_KICK,
CMD_ID_CHATMODE,
CMD_ID_PUBLICGAME,
CMD_ID_OFFLINETEXT,
CMD_ID_ADMINPASSWORD,
CMD_ID_SIGNONCOMMANDS,
CMD_ID_SPECTATORPASSWORD,
CMD_ID_DISPATCHMODE,
CMD_ID_CHEERINGTHRESHOLD,
CMD_ID_INFORMPLAYERS,
CMD_ID_PING,
CMD_ID_PROXYPASSWORD,
CMD_ID_MAXRATE,
CMD_ID_LOOPCMD,
CMD_ID_MAXCLIENTS,
CMD_ID_DISCONNECT,
CMD_ID_LOCALMSG,
CMD_ID_CONNECT,
CMD_ID_PLAYDEMO,
CMD_ID_DELAY,
CMD_ID_STOP,
CMD_ID_RECORD,
CMD_ID_STOPRECORDING,
CMD_ID_SERVERCMD,
CMD_ID_CLIENTCMD,
CMD_ID_BLOCKVOICE,
CMD_ID_NAME,
CMD_ID_UPDATERATE,
CMD_ID_RATE,
CMD_ID_ADDRESOURCE,
CMD_ID_RESOURCES,
CMD_ID_BANNERFILE,
CMD_ID_BANN,
CMD_ID_ADDFAKECLIENTS,
CMD_ID_RETRY,
CMD_ID_PLAYERS,
CMD_ID_AUTORETRY,
CMD_ID_SERVERPASSWORD,
CMD_ID_STATUS,
CMD_ID_HOSTNAME,
CMD_ID_MAXQUERIES,
CMD_ID_CLEARBANNS,
CMD_ID_MAXLOSS,
CMD_ID_PROTOCOL,
CMD_ID_REGION
};
void CMD_Rcon(char *cmdLine);
void CMD_ServerCmd(char *cmdLine);
void CMD_ClientCmd(char *cmdLine);
void CMD_RconPassword(char *cmdLine);
void CMD_RconAddress(char *cmdLine);
void CMD_Say(char *cmdLine);
void CMD_Msg(char *cmdLine);
void CMD_Clients(char *cmdLine);
void CMD_Kick(char *cmdLine);
void CMD_ChatMode(char *cmdLine);
void CMD_PublicGame(char *cmdLine);
void CMD_OffLineText(char *cmdLine);
void CMD_AdminPassword(char *cmdLine);
void CMD_SignOnCommands(char *cmdLine);
void CMD_SpectatorPassword(char *cmdLine);
void CMD_DispatchMode(char *cmdLine);
void CMD_CheeringThreshold(char *cmdLine);
void CMD_InformPlayers(char *cmdLine);
void CMD_Ping(char *cmdLine);
void CMD_ProxyPassword(char *cmdLine);
void CMD_MaxRate(char *cmdLine);
void CMD_MaxUpdateRate(char *cmdLine);
void CMD_LoopCmd(char *cmdLine);
void CMD_MaxClients(char *cmdLine);
void CMD_LocalMsg(char *cmdLine);
void CMD_Connect(char *cmdLine);
void CMD_Disconnect(char *cmdLine);
void CMD_PlayDemo(char *cmdLine);
void CMD_Delay(char *cmdLine);
void CMD_Stop(char *cmdLine);
void CMD_Record(char *cmdLine);
void CMD_StopRecording(char *cmdLine);
void CMD_BlockVoice(char *cmdLine);
void CMD_Name(char *cmdLine);
void CMD_Rate(char *cmdLine);
void CMD_Updaterate(char *cmdLine);
void CMD_HostName(char *cmdLine);
void CMD_AddResource(char *cmdLine);
void CMD_Resources(char *cmdLine);
void CMD_BannerFile(char *cmdLine);
void CMD_Bann(char *cmdLine);
void CMD_AddFakeClients(char *cmdLine);
void CMD_Retry(char *cmdLine);
void CMD_AutoRetry(char *cmdLine);
void CMD_ServerPassword(char *cmdLine);
void CMD_Status(char *cmdLine);
void CMD_MaxQueries(char *cmdLine);
void CMD_Players(char *cmdLine);
void CMD_ClearBanns(char *cmdLine);
void CMD_MaxLoss(char *cmdLine);
void CMD_Protocol(char *cmdLine);
void CMD_Region(char *cmdLine);
struct LocalCommandID_s {
char *name;
LocalCommandIDs id;
void (Proxy::*pfnCmd)(char *cmdLine);
};
static LocalCommandID_s m_LocalCmdReg[];
const char *GetDescription();
protected:
friend class DemoClient;
friend class Status;
friend class Master;
friend class Director;
INetwork *m_Network;
IWorld *m_World;
IDirector *m_Director;
IServer *m_Server;
ObjectList m_Clients;
DemoClient m_DemoClient;
Status m_Status;
Master m_Master;
Director m_DefaultDirector;
DirectorNull m_NullDirector;
INetSocket *m_Socket;
typedef struct challenge_s {
NetAddress adr;
unsigned int challenge;
float time;
} challenge_t;
// MAX_CHALLENGES is made large to prevent a denial
// of service attack that could cycle all of them
// out before legitimate users connected
enum { MAX_CHALLENGES = 1024 };
challenge_t m_Challenges[MAX_CHALLENGES];
bool m_IsMaster;
bool m_IsFinishingBroadcast;
bool m_IsReconnectRequested;
int m_MaxRate;
int m_MaxUpdateRate;
ChatMode_e m_ChatMode;
int m_MaxClients;
float m_MaxQueries;
int m_MaxFrameQueries;
int m_MaxSeenClients;
NetAddress m_RconAddress;
char m_RconPassword[128];
char m_AdminPassword[128];
char m_ProxyPassword[128];
char m_SpectatorPassword[128];
char m_LastRconCommand[1024];
char m_OffLineText[128];
char m_SignonCommands[256];
ObjectList m_LoopCommands;
bool m_PublicGame;
enum DispatchMode_e : int {
DISPATCH_OFF, // Won't redirect any clients.
DISPATCH_BALANCE, // Will redirect connecting clients to other proxies balancing work load between all proxies.
DISPATCH_ALL, // Any spectator clients will be redirected, so this proxy serves only as dispatcher.
};
DispatchMode_e m_DispatchMode;
float m_ClientDelay;
float m_ClientTimeScale;
double m_ClientWorldTime;
double m_ClientProxyTime;
double m_LastClockUpdateTime;
float m_CheeringThreshold;
float m_LastCheeringUpdate;
int m_CheeringPlayers;
resource_t *m_BannerTGA;
ObjectList m_Resources;
double m_NextStatusUpdateTime;
float m_FPS;
float m_MaxLoss;
float m_CurrentLoss;
ObjectList m_BannList;
unsigned char m_Region;
textmessage_t m_LocalMessage;
textmessage_t m_CommentatorMessage;
double m_NextInfoMessagesUpdate;
BitBuffer m_InfoRules;
BitBuffer m_InfoPlayers;
BitBuffer m_InfoDetails;
BitBuffer m_InfoInfo;
BitBuffer m_InfoString;
};

View File

@ -0,0 +1,317 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
void ProxyClient::ShutDown()
{
char *clientTypeString[] = { "Spectator", "Relay Proxy", "Director", "Commentator", "Fake Client" };
if (m_State == MODULE_DISCONNECTED) {
return;
}
m_System->Printf("%s disconnected (%s)\n", clientTypeString[m_ClientType], m_ClientChannel.m_remote_address.ToString());
m_Proxy->GetClients()->Remove(this);
BaseClient::ShutDown();
delete this;
}
bool ProxyClient::Init(IBaseSystem *system, int serial, char *name)
{
BaseClient::Init(system, serial, name);
m_ClientType = TYPE_CLIENT;
m_ChatEnabled = true;
m_LastChatTime = 0;
m_LastCheerTime = 0;
m_NextDecalTime = 0;
return true;
}
ProxyClient::LocalCommandID_s ProxyClient::m_LocalCmdReg[] = {
{ "cheer", CMD_ID_CHEER, &ProxyClient::CMD_Cheer },
{ "say", CMD_ID_SAY, &ProxyClient::CMD_Say },
{ "joingame", CMD_ID_JOINGAME, &ProxyClient::CMD_JoinGame },
{ "status", CMD_ID_STATUS, &ProxyClient::CMD_Status },
{ "ignoremsg", CMD_ID_IGNOREMSG, &ProxyClient::CMD_IgnoreMsg },
};
bool ProxyClient::ProcessStringCmd(char *string)
{
if (BaseClient::ProcessStringCmd(string)) {
return true;
}
TokenLine cmdLine;
if (!cmdLine.SetLine(string)) {
m_System->Printf("WARNING! ProxyClient::ProcessStringCmd: string command too long.\n");
return true;
}
char *cmd = cmdLine.GetToken(0);
for (auto& local_cmd : m_LocalCmdReg)
{
if (!_stricmp(local_cmd.name, cmd)) {
(this->*local_cmd.pfnCmd)(&cmdLine);
return true;
}
}
if (m_ClientType < TYPE_COMMENTATOR) {
m_System->DPrintf("Unkown client command: \"%s\"\n", cmd);
}
m_System->DPrintf("Unkown director command: \"%s\"\n", cmd);
return false;
}
void ProxyClient::CMD_Cheer(TokenLine *cmd)
{
if (m_SystemTime <= m_LastCheerTime + 6) {
return;
}
m_LastCheerTime = float(m_SystemTime);
m_Proxy->IncreaseCheering(1);
}
void ProxyClient::CMD_Say(TokenLine *cmd)
{
char *chatText = (cmd->CountToken() > 2) ? cmd->GetRestOfLine(1) : cmd->GetToken(1);
if (m_ClientType == TYPE_COMMENTATOR) {
m_Proxy->ChatCommentator(nullptr, chatText);
return;
}
if (m_ClientType == TYPE_PROXY && m_Proxy->GetChatMode() == CHAT_GLOBAL) {
m_Proxy->ChatSpectator("Unknown", chatText);
return;
}
if (m_SystemTime >= m_LastChatTime + 6) {
m_Proxy->ChatSpectator(m_ClientName, chatText);
m_LastChatTime = float(m_SystemTime);
return;
}
}
void ProxyClient::CMD_JoinGame(TokenLine *cmd)
{
if (m_Proxy->GetServer()->IsDemoFile()) {
PrintfToClient("Proxy is replaying demo.\n");
return;
}
if (m_Proxy->IsPublicGame())
{
char string[64];
_snprintf(string, sizeof(string), "connect %s\n", m_World->GetGameServerAddress()->ToString());
m_ClientChannel.m_reliableStream.WriteByte(svc_stufftext);
m_ClientChannel.m_reliableStream.WriteString(string);
}
PrintfToClient("Joining game is not allowed.\n");
}
void ProxyClient::CMD_Status(TokenLine *cmd)
{
PrintfToClient("--- HLTV Status ---\n");
if (m_Proxy->GetServer()->IsDemoFile()) {
PrintfToClient("Replay demo file %s\n", m_Proxy->GetServer()->GetDemoFileName());
}
else if (m_Proxy->IsPublicGame()) {
PrintfToClient("Game Server: %s\n", m_World->GetGameServerAddress()->ToString());
}
else {
PrintfToClient("Private game server\n");
}
int proxies, spectators, slots;
m_Proxy->GetStatistics(proxies, slots, spectators);
PrintfToClient("Global HLTV stats: spectators %i, slots %i, proxies %i\n", spectators, slots, proxies);
}
void ProxyClient::CMD_IgnoreMsg(TokenLine *cmd)
{
if (cmd->CountToken() != 2) {
return;
}
m_ChatEnabled = !atoi(cmd->GetToken(1));
PrintfToClient("Global HLTV stats: spectators %i, slots %i, proxies %i\n", m_ChatEnabled ? "Spectator chat enabled.\n" : "Spectator chat disabled.\n");
}
void ProxyClient::UpdateUserInfo(char *userinfostring)
{
BaseClient::UpdateUserInfo(userinfostring);
if (m_ClientType > TYPE_DEMO) {
m_System->DPrintf("WARNING! Client::UpdateUserInfo: invalid client ype %i\n", m_ClientType);
m_ClientType = TYPE_CLIENT;
}
if (m_ClientType) {
return;
}
// clamp rate
if (m_ClientChannel.GetRate() > m_Proxy->GetMaxRate()) {
m_ClientChannel.SetRate(m_Proxy->GetMaxRate());
}
if (m_ClientType == TYPE_CLIENT)
{
if (m_ClientChannel.GetUpdateRate() > m_Proxy->GetMaxUpdateRate()) {
m_ClientChannel.SetUpdateRate(m_Proxy->GetMaxUpdateRate());
}
}
}
void ProxyClient::ParseHLTV(NetPacket *packet)
{
unsigned char cmd = packet->data.ReadByte();
if (cmd != HLTV_STATUS) {
m_System->Printf("WARNING! unknown HLTV client msg %i\n", cmd);
return;
}
if (m_ClientType != TYPE_PROXY) {
m_System->DPrintf("WARNING! HLTV status data from spectator client\n");
packet->data.SkipBytes(12);
return;
}
m_Proxy->ParseStatusReport(GetAddress(), &packet->data);
}
void ProxyClient::ReplySpawn(int spawncount, int crcMap)
{
BaseClient::ReplySpawn(spawncount, crcMap);
if (m_ClientType == TYPE_PROXY) {
m_VoiceQuery = false;
}
m_Proxy->WriteSignonData(m_ClientType, &m_ClientChannel.m_reliableStream);
}
void ProxyClient::SendDatagram()
{
if (m_Proxy->GetDelay() > 0)
{
double worldTime = m_Proxy->GetSpectatorTime();
double proxyTime = m_Proxy->GetProxyTime();
frame_t *frame = m_World->GetFrameByTime(worldTime);
if (!frame) {
return;
}
if (m_ClientChannel.GetIdleTime() > 2) {
m_ClientChannel.m_unreliableStream.WriteByte(svc_centerprint);
m_ClientChannel.m_unreliableStream.WriteString((frame->seqnr > 1) ? "Game pending..." : "Buffering game...");
}
double time = proxyTime - (worldTime - frame->time);
WriteDatagram(time, frame);
return;
}
frame_t *frame = m_World->GetLastFrame();
if (frame)
{
if (m_ClientChannel.GetIdleTime() > 2) {
m_ClientChannel.m_unreliableStream.WriteByte(svc_centerprint);
m_ClientChannel.m_unreliableStream.WriteString("Game pending...");
}
WriteDatagram(frame->time, frame);
}
}
bool ProxyClient::HasChatEnabled()
{
return m_ChatEnabled;
}
void ProxyClient::ParseVoiceData(NetPacket *packet)
{
int nDataLength = packet->data.ReadShort();
BitBuffer voiceMsg(nDataLength + 8);
if (m_ClientType != TYPE_COMMENTATOR) {
packet->data.SkipBytes(nDataLength);
return;
}
if (nDataLength > MAX_VOICEDATA_LEN) {
Disconnect("Invalid voice message.\n");
return;
}
voiceMsg.WriteByte(svc_voicedata);
voiceMsg.WriteByte(m_World->GetSlotNumber());
voiceMsg.WriteShort(nDataLength);
voiceMsg.WriteBuf(packet->data.CurrentByte(), nDataLength);
m_Proxy->Broadcast(voiceMsg.GetData(), voiceMsg.CurrentSize(), GROUP_PROXY | GROUP_DEMO | GROUP_UNKNOWN | GROUP_VOICE, false);
packet->data.SkipBytes(nDataLength);
}
void ProxyClient::DownloadFile(char *fileName)
{
if (!fileName || !fileName[0])
return;
const char szMD5[] = "!MD5";
if (strstr(fileName, "..") ||
// ignore customization's
(strlen(fileName) == 36 && !_strnicmp(fileName, szMD5, sizeof(szMD5) - 1)))
{
DownloadFailed(fileName);
return;
}
resource_t *resource = m_Proxy->GetResource(fileName);
if (resource) {
m_ClientChannel.CreateFragmentsFromBuffer(resource->data, resource->nDownloadSize, FRAG_FILE_STREAM, fileName);
return;
}
if (m_ClientChannel.CreateFragmentsFromFile(fileName)) {
m_ClientChannel.FragSend();
return;
}
DownloadFailed(fileName);
}

View File

@ -0,0 +1,82 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "common/BaseClient.h"
class IProxy;
class NetPacket;
class IBaseSystem;
class ProxyClient: public BaseClient {
public:
ProxyClient(IProxy *proxy) : m_Proxy(proxy) {}
virtual ~ProxyClient() {}
bool Init(IBaseSystem *system, int serial, char *name);
void ShutDown();
bool HasChatEnabled();
bool ProcessStringCmd(char *string);
void ReplySpawn(int spawncount, int crcMap);
void UpdateUserInfo(char *userinfostring = nullptr);
void ParseVoiceData(NetPacket *packet);
void DownloadFile(char *fileName);
void SendDatagram();
void ParseHLTV(NetPacket *packet);
private:
enum LocalCommandIDs {
CMD_ID_CHEER = 1,
CMD_ID_SAY,
CMD_ID_JOINGAME,
CMD_ID_STATUS,
CMD_ID_IGNOREMSG
};
void CMD_Cheer(TokenLine *cmd);
void CMD_Say(TokenLine *cmd);
void CMD_JoinGame(TokenLine *cmd);
void CMD_Status(TokenLine *cmd);
void CMD_IgnoreMsg(TokenLine *cmd);
struct LocalCommandID_s {
char *name;
LocalCommandIDs id;
void (ProxyClient::*pfnCmd)(TokenLine *cmd);
};
static LocalCommandID_s m_LocalCmdReg[];
protected:
IProxy *m_Proxy;
float m_LastChatTime;
float m_LastCheerTime;
float m_NextDecalTime;
bool m_ChatEnabled;
};

View File

@ -0,0 +1,318 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
bool Status::Init(IBaseSystem *system, int serial, char *name)
{
BaseSystemModule::Init(system, serial, name);
SetName("status");
m_Proxies.Init();
m_System->RegisterCommand("proxies", this, CMD_ID_PROXIES);
Reset();
m_State = MODULE_RUNNING;
m_System->DPrintf("Status module initialized.\n");
return true;
}
void Status::RunFrame(double time)
{
BaseSystemModule::RunFrame(time);
if (m_MaxNumberOfSpectators < m_NumberOfSpectators) {
m_MaxNumberOfSpectators = m_NumberOfSpectators;
}
if (!m_Proxy->IsMaster() || !m_Proxy->IsActive())
return;
if (m_SystemTime > m_NextUpdateTime)
{
GetLocalStats(m_NumberOfProxies, m_NumberOfSlots, m_NumberOfSpectators);
SendStatusUpdate();
m_Proxy->GetServer()->SetUserInfo("hspecs", COM_VarArgs("%u", m_NumberOfSpectators));
m_Proxy->GetServer()->SetUserInfo("hslots", COM_VarArgs("%u", m_NumberOfSlots));
m_NextUpdateTime = float(m_SystemTime) + 16.f;
}
}
void Status::ExecuteCommand(int commandID, char *commandLine)
{
if (commandID == CMD_ID_PROXIES) {
CMD_Proxies(commandLine);
return;
}
m_System->Printf("ERROR! Status::ExecuteCommand: unknown command ID %i.\n", commandID);
}
void Status::ShutDown()
{
if (m_State == MODULE_DISCONNECTED)
return;
m_Proxies.Clear(true);
m_System->Printf("Status module shutdown.\n");
BaseSystemModule::ShutDown();
}
void Status::GetGlobalStats(int &proxies, int &slots, int &spectators)
{
proxies = m_NumberOfProxies;
slots = m_NumberOfSlots;
spectators = m_NumberOfSpectators;
}
void Status::SetProxy(IProxy *proxy)
{
m_Proxy = proxy;
}
void Status::SendStatusUpdate()
{
BitBuffer buffer(128);
buffer.WriteByte(svc_hltv);
buffer.WriteByte(HLTV_STATUS);
buffer.WriteWord(m_NumberOfProxies);
buffer.WriteLong(m_NumberOfSlots);
buffer.WriteLong(m_NumberOfSpectators);
m_Proxy->Broadcast(buffer.GetData(), buffer.CurrentSize(), GROUP_PROXY, true);
buffer.FastClear();
DirectorCmd cmd;
cmd.SetStatusData(m_NumberOfSlots, m_NumberOfSpectators, m_NumberOfProxies);
cmd.WriteToStream(&buffer);
// group spectators
m_Proxy->Broadcast(buffer.GetData(), buffer.CurrentSize(), GROUP_CLIENT | GROUP_DEMO | GROUP_UNKNOWN, false);
buffer.FastClear();
}
void Status::SetName(char *newName)
{
strcopy(m_Name, newName);
}
char *Status::GetType()
{
return STATUS_INTERFACE_VERSION;
}
char *Status::GetStatusLine()
{
static char string[256];
_snprintf(string, sizeof(string), "Global Status: Proxies %i, Slots %i, Spectators %i (max %i)\n",
m_NumberOfProxies, m_NumberOfSlots,
m_NumberOfSpectators, m_MaxNumberOfSpectators);
return string;
}
void Status::Reset()
{
m_Proxies.Clear(true);
m_NumberOfProxies = 0;
m_NumberOfSlots = 0;
m_NumberOfSpectators = 0;
m_MaxNumberOfSpectators = 0;
m_NextUpdateTime = 0;
}
void Status::ParseStatusMsg(BitBuffer *stream)
{
if (m_Proxy->IsMaster()) {
m_System->Printf("WARNING! Status::ParseStatusMsg: unexpected HLTV_STATUS message as Master.\n");
stream->SkipBytes(10);
return;
}
m_NumberOfProxies = stream->ReadWord();
m_NumberOfSlots = stream->ReadLong();
m_NumberOfSpectators = stream->ReadLong();
ReplyStatusReport();
SendStatusUpdate();
}
void Status::ReplyStatusReport()
{
BitBuffer buf(128);
int slots, proxies, spectators;
GetLocalStats(proxies, slots, spectators);
if (!m_Proxy->IsPasswordProtected())
{
if (!m_Proxy->GetDispatchMode()) {
slots = m_Proxy->GetMaxClients();
}
else if (m_Proxy->IsStressed()) {
proxies |= PROXY_PRIVATE;
}
}
buf.WriteByte(1);
buf.WriteWord(proxies);
buf.WriteLong(slots);
buf.WriteLong(spectators);
m_Proxy->GetServer()->SendHLTVCommand(&buf);
}
int Status::GetMaxSpectatorNumber()
{
return m_MaxNumberOfSpectators;
}
void Status::ParseStatusReport(NetAddress *from, BitBuffer *stream)
{
int proxies = stream->ReadWord();
int slots = stream->ReadLong();
int spectators = stream->ReadLong();
bool isPrivate = false;
if (proxies & PROXY_PRIVATE) {
proxies &= ~PROXY_PRIVATE;
isPrivate = true;
}
proxyInfo_t *proxy = (proxyInfo_t *)m_Proxies.GetFirst();
while (proxy)
{
if (from->Equal(&proxy->address)) {
break;
}
proxy = (proxyInfo_t *)m_Proxies.GetNext();
}
// couldn't find it?
// allocate for
if (!proxy)
{
proxy = (proxyInfo_t *)Mem_ZeroMalloc(sizeof(proxyInfo_t));
if (!proxy) {
m_System->Printf("WARNING! Status::ParseStatusReport: not enough memory to increase proxy list.\n");
return;
}
proxy->address.FromNetAddress(from);
m_Proxies.Add(proxy);
}
proxy->slots = slots;
proxy->spectators = spectators;
proxy->proxies = proxies;
proxy->time = float(m_SystemTime);
proxy->isPrivate = isPrivate;
float ratio = (slots > 0 && !isPrivate) ? float(spectators / slots) : 1;
m_Proxies.ChangeKey(proxy, ratio);
}
void Status::GetLocalStats(int &proxies, int &slots, int &spectators)
{
slots = 0;
spectators = 0;
proxies = 0;
proxyInfo_t *proxy = (proxyInfo_t *)m_Proxies.GetFirst();
while (proxy)
{
if (m_SystemTime > proxy->time + 64)
{
m_Proxies.Remove(proxy);
free(proxy);
}
else
{
proxies += proxy->proxies;
slots += proxy->slots;
spectators += proxy->spectators;
}
proxy = (proxyInfo_t *)m_Proxies.GetNext();
}
int mySpecs, myProxies;
m_Proxy->CountLocalClients(mySpecs, myProxies);
spectators += mySpecs;
slots += m_Proxy->GetMaxClients();
proxies++;
}
void Status::CMD_Proxies(char *cmdLine)
{
int nCount = 0;
proxyInfo_t *proxy = (proxyInfo_t *)m_Proxies.GetFirst();
while (proxy)
{
nCount++;
m_System->Printf("IP %s, Clients %i, MaxClients %i%s\n", proxy->address.ToString(), proxy->spectators, proxy->slots, proxy->isPrivate ? " (excluded)" : "");
proxy = (proxyInfo_t *)m_Proxies.GetNext();
}
m_System->Printf("--- Total %i relay proxies ---\n", nCount);
}
float Status::GetBestRelayProxy(NetAddress *addr)
{
proxyInfo_t *proxy = (proxyInfo_t *)m_Proxies.GetFirst();
while (proxy)
{
if (proxy->slots > 0 && proxy->slots >= proxy->spectators && !proxy->isPrivate)
{
float ratio = float(++proxy->spectators / proxy->slots);
m_Proxies.ChangeKey(proxy, ratio);
addr->FromNetAddress(&proxy->address);
return ratio;
}
m_Proxies.ChangeKey(proxy, 1);
proxy = (proxyInfo_t *)m_Proxies.GetNext();
}
addr->Clear();
return -1;
}

View File

@ -0,0 +1,85 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "common/NetAddress.h"
#include "ObjectDictionary.h"
#include "hltv.h"
typedef struct proxyInfo_s {
NetAddress address;
int slots;
int proxies;
int spectators;
int isPrivate;
float time;
} proxyInfo_t;
class IProxy;
class Status: public BaseSystemModule {
public:
Status() {}
virtual ~Status() {}
bool Init(IBaseSystem *system, int serial, char *name);
void ExecuteCommand(int commandID, char *commandLine);
void RunFrame(double time);
char *GetStatusLine();
char *GetType();
void ShutDown();
void GetGlobalStats(int &proxies, int &slots, int &spectators);
void GetLocalStats(int &proxies, int &slots, int &spectators);
void SetProxy(IProxy *proxy);
float GetBestRelayProxy(NetAddress *addr);
void ParseStatusMsg(BitBuffer *stream);
void ParseStatusReport(NetAddress *from, BitBuffer *stream);
void Reset();
int GetMaxSpectatorNumber();
void RemoveProxy(NetAddress *addr);
void ClearProxyList();
void ReplyStatusReport();
void SendStatusUpdate();
void SetName(char *newName);
protected:
enum LocalCommandIDs { CMD_ID_PROXIES = 1 };
void CMD_Proxies(char *cmdLine);
private:
IProxy *m_Proxy;
float m_NextUpdateTime;
ObjectDictionary m_Proxies;
int m_NumberOfProxies;
int m_NumberOfSlots;
int m_NumberOfSpectators;
int m_MaxNumberOfSpectators;
};
#define STATUS_INTERFACE_VERSION "status000"

View File

@ -0,0 +1 @@
#include "precompiled.h"

View File

@ -0,0 +1,49 @@
#pragma once
#include "basetypes.h"
#include "archtypes.h"
#include "mathlib.h"
#include "FileSystem.h"
#include "interface.h"
#include "IBaseSystem.h"
#include "mem.h"
#include "common.h"
#include "common/md5.h"
#include "common/random.h"
#include "common/byteorder.h"
#include "common/ServerInfo.h"
#include "common/common_hltv.h"
#include "common/net_internal.h"
#include "common/mathlib_internal.h"
// Hooks stuff
#include "hookers/HLTV/Proxy/hooklist.h"
#include "common/DirectorCmd.h"
#include "common/NetAddress.h"
#include "common/NetChannel.h"
#include "common/BaseClient.h"
#include "common/DemoFile.h"
#include "common/munge.h"
#include <steam/steam_gameserver.h>
#include <HLTV/IWorld.h>
#include <HLTV/IProxy.h>
#include <HLTV/IServer.h>
#include <HLTV/IClient.h>
#include <HLTV/INetChannel.h>
#include <HLTV/INetwork.h>
// Proxy module stuff
#include "Proxy.h"
#include "ProxyClient.h"
#include "DemoClient.h"
#include "FakeClient.h"
#include "Master.h"
#include "Status.h"

View File

@ -0,0 +1,3 @@
#include "precompiled.h"
#include "interface.cpp"

333
rehlds/HLTV/README.md Normal file
View File

@ -0,0 +1,333 @@
## Half-Life TV for Goldsrc based games <img align="right" src="https://cloud.githubusercontent.com/assets/5860435/25316484/320cce9a-2892-11e7-8d12-3290baf4458c.png" alt="HLTV Launcher"/>
### Building
On Windows:
<pre>gradlew --max-workers=1 clean rehlds/HLTV:build</pre>
On Linux (ICC):
<pre>./gradlew --max-workers=1 clean rehlds/HLTV:build</pre>
On Linux (GCC):
<pre>./gradlew --max-workers=1 -PuseGcc clean rehlds/HLTV:build</pre>
Compiled binaries will be placed in each project rehlds/HLTV/**/binaries/ directory
### Overview
Half-Life TV offers the ability to have an unlimited number of spectators watching online games.
They can follow the game just like they would as a spectator on the game server.
Spectators are invisible to players and can't interact with the running game in any way.
Each spectator can choose any view position or choose any player to track individually.
To have the most enjoyable spectating experience, spectators can enable the Auto-Director mode.
Then the camera is changed automatically so that only interesting scenes are shown from a suitable viewpoint.
Thus the spectator can lean back and won't miss any relevant action.
All the time, spectators may communicate between each other using the standard HL chat system.
Most popular Half-Life MODs are supported like `Counter-Strike`, `Team Fortress Classic`, `Day of Defeat` and many others.
HLTV providers have full control over their HLTV system, may change number of spectator slots, add text messages or change the HLTV logo.
The broadcast is delayed by a customizable amount of time, by default 30 seconds. This ensures that the playing teams can't use
HLTV to get any usable information about their opponents. Providing a single HLTV server for up to 100 spectators is an easy task
and doesn't need any changes in default configurations.
Installing a larger HLTV network for thousands of spectators needs some more planning time and experience about required bandwidth
and CPU/RAM demands (see [Larger Broadcasts](#larger-broadcasts)).
### Spectating Games
To watch a HLTV game, start Half-Life, open the Multiplayer menu and select 'Find Servers'.
To search for currently broadcasted games, choose the 'Spectate' section and hit 'Refresh All'.
After the list has been updated, double click on the server you want to spectate and you'll be connected.
If computer game leagues announce important matches to be broadcasted via HLTV, they often provide IP:Port addresses of their HLTV servers.
Instead of searching them via the server browser, you can also go to the 'Favorites' folder and add the HLTV address to your server
list by pressing the right mouse button. Otherwise, you can also open the console window and use the 'connect' command to spectate a certain game.
For example:
<pre>
connect 192.168.130.42:27020
</pre>
The default HLTV port number is 27020, but may be changed.
It should always be included in the given address, since commonly this port number is different from the default port number 27015.
You can spectate the game in different modes: `Chase Cam`, `First Person`, `Free Look`, `Map Overview` and `Map Chase`.<br />
The easiest way to change modes is to press the JUMP key (default `SPACE`). Alternatively you can use the spectator menu, which can be enabled by pressing the `DUCK` key (default `CTRL`).
Here you can customize your personal view style and enable the Auto-Director Mode. Press `USE` (default `E`) to cycle through the different `Picture-In-Picture` modes.
The following HL console commands can be used to customize spectator settings:
| Console commands | Default | Min | Max | Description |
| :---------------------------- | :-----: | :-: | :----------: | :--------------------------------------------- |
| spec_autodirector | 1 | 0 | 1 | Turns Auto Director mode on or off |
| spec_drawcone | 1 | 0 | 1 | Shows your view cone in map overview mode |
| spec_drawnames | 1 | 0 | 1 | Shows player names under their icons |
| spec_drawstatus | 1 | 0 | 1 | Shows game information (time, map etc) |
| spec_pip | 0 | 0 | 1 | Turns Picture-In-Picture mode on or off |
| spec_mode | 1 | 1 | 6 | Set the main view mode, seconds parameter is the PIP mode.<br />Not all combinations are valid.<br />Main modes are:<br />`1` Locked Chase<br />`2` Free Chase<br />`3` Free Roaming<br />`4` First Person<br />`5` Map Overview<br />`6` Chase Map Overview<br /><br />PIP modes are:<br />`0` PIP off<br />`1` Free Chase<br />`2` First Person<br />`3` Map Overview<br />`4` Chase Map Overview<br /> |
| spec_menu | - | - | - | Opens the spectator menu |
| spec_help | - | - | - | Shows a help screen |
### HLTV Basics
The core of the HLTV broadcasting system is the HLTV server, also called HLTV proxy.
The HLTV executable is a console application that works much like a HL dedicated server.
To broadcast a game running on a certain game server, the HLTV proxy connects to this server just like a normal player.
Spectators connect themselves to the HLTV proxy and the game data stream is relayed through the HLTV proxy to all connected spectator clients.
The next figure shows a basic HLTV configuration:
<pre>
HL Game Server -> HLTV Proxy => Spectator Clients
</pre>
The number of clients that one HLTV proxy can serve depends on available hardware and network resources.
Theoretically, a single proxy can hold a maximum of 255 spectator clients.
But be careful, even a proxy with 100 spectator clients needs a full 2 MBit line to run smoothly.
If more spectator slots are needed, the required network load must be distributed over multiple HLTV proxies.
The first HLTV proxy connected to the game server is called the Master proxy, which sets the general broadcast settings like
game stream delay or packet rate. All other HLTV proxies linked to this proxy are the Relay proxies. Their total number and
link order is not restricted, they may form a chain or tree of proxies.
Most important is that their location is in different networks to ensure a balanced bandwidth usage.
<pre>
-> HLTV Relay Proxy 1 => Spectator Clients
HL Game Server -> HLTV Master -> HLTV Relay Proxy 2 => Spectator Clients
-> HLTV Relay Proxy 3 => Spectator Clients
</pre>
### Broadcasting Games
Let's assume the most simple configuration, a single HLTV proxy in a LAN environment.
This is a very common situation and the default HLTV settings doesn't need to be changed.
Choose a dedicated computer as your HLTV proxy and install the Half-Life Dedicated Server, which also includes all files needed by a HLTV proxy.
This isn't needed if Half-Life is already installed.
Start the HLTV application (HL icon with a small camera) and the HLTV console will open, showing some initialization messages
(if that takes a long time, HLTV maybe can't resolve some IP addresses, then start HLTV with the '-nodns' command line option).
Then the console is ready to accept your commands, here we use '>' as the console prompt.
First give your HLTV proxy an unique name:
<pre>
>name "My HLTV Proxy"
</pre>
Let's assume you have started the proxy on host `192.168.1.2` and the game server,
you want to spectate is running on host `192.168.1.3:27015`.
Then connect the HLTV proxy to this game server by typing:
<pre>
>connect 192.168.1.3:27015
</pre>
After a few seconds HLTV will be fully connected and ready to serve spectator clients.
Use the 'status' command to verify that the HLTV proxy has connected properly:
<pre>
>status
--- HLTV Status ---
Online 00:23, FPS 79.0, Version 2435 (Win32)
Local IP 192.168.1.2:27020, Network In 1.7, Out 1.0, Loss 0.00
Local Slots 128, Spectators 0, Proxies 0
Total Slots 128, Spectators 0, Proxies 1
Source Game Server 192.168.1.3:27015, Delay 30
Server Name "Half-Life dedicated server"
Time 01:35, Game "valve", Map "maps/rapidcore.bsp", Players 1
</pre>
The 'status' command shows your own IP address, HLTV system cycles per second, total incoming and outgoing network traffic in `kB/sec`.
Local slot and spectator numbers your HLTV proxy is providing, total numbers are the sum of all slots & spectators on all proxies broadcasting this game.
The game source can be a game server, another HLTV proxy or a demo file.
### Recording HLTV demos
HLTV demo files are like normal recorded games in Half-Life, but you can choose any view point,
view mode or player to chase during replay. To play back a HLTV demo, a HLTV proxy is not needed.
Just start Half-Life and type in console `playdemo <demoname>` or `viewdemo <demoname>`
(viewdemo offers more options during playback like fast forward/backward, pause & slowmotion).
To record a HLTV demo, connect the proxy to a game server (see [Broadcasting Games](#broadcasting-games)) and type in console:
<pre>
>record <name>
</pre>
All games will be recorded after issuing this command. The demo files will be saved in the current Mod directory, e.g. `\cstrike`.
All demo files have a special naming convention `<name>-<YYMMDDhhmm>-<map>.dem`, including the given name, date/time and map name.
Demo files record the same data as send to spectator clients. That means also, the demo file records the game with the same delay as used for spectators.
To verify, that a demo file is recorded use the `status` command. The recording may be stopped with `stoprecording`.
Sometimes a HLTV broadcast is not wanted and the HLTV proxy is only used to record a demo file.
In this case, some HLTV settings should be made to gain optimal recording results:
<pre>
>maxclients 0 // don't allow any spectator clients
>delay 0 // no game stream delay
>rate 10000 // maximum data rate
>updaterate 20 // standard update rate
>nomaster 1 // don't register at master servers
</pre>
### Larger Broadcasts
Setting up a HLTV network that can handle a larger number of spectators (>1000) is a difficult and time consuming task.
The following guide should help to configure and run such a HLTV network. One of the most important rule should be `Quality, not Quantity`.
It's better to offer a smaller number of spectator slots, than operating at the maximum bandwidth limit, thus all spectators would suffer from lags and timeouts.
Check carefully your available bandwidth capacity and calculate how many spectators can be handled by your HLTV servers.
The average bandwidth demand per spectator is between 2 and 3 KB/sec and depends on the current mod, map and number of players.
CPU and RAM shouldn't be a bottleneck on modern PC systems.
This list for common Internet connection types gives a feeling, how bandwidth demanding HLTV can be:
<pre>
- ISDN 64 Kbps : 2 spectators
- DSL 128 Kbps (upstream) : 5 spectators
- T1 1.5 Mbps : 75 spectators
- LAN 10 Mbps : 500 spectators
- T3 75 Mbps : 4000 spectators
</pre>
Use the `maxclients` command to set how many clients should be accepted by a HLTV proxy.
Make sure that the `maxrate` variable is set too a reasonable value, e.g. `3500 kB/sec`. Lower values are possible,
but make sure spectators don't get too much `choke` during a running game. The `maxrate` command doesn't effect
the bandwidth limit between HLTV proxies, only for spectator clients.
To lower the general bandwidth demand, you can turn off the internal HLTV chat (`chatmode 0`) or decrease the game
update rate from the default value 20 to 10 (`updaterate 10`). A lower update rate may save up to 25% network traffic
and is an acceptable tradeoff in this case since spectators doesn't need a high update rate like real players does.
A very common setup for large broadcasts is to use 2 dedicated HLTV servers to create a private and a public HLTV segment.
Let's assume the game server is in a closed LAN and not accessible from outside.
This ensures a maximum security against attacks (DOS etc) from outside. The HLTV master server is started within the
LAN and it's IP address should be kept secret. The second HLTV server is started outside the LAN with a global IP
and is connected to the HLTV master server. This second HLTV server is the public HLTV dispatcher, which IP address is given to the audience.
Any relay proxies are connected to this HLTV dispatcher. Thus the HLTV master server is in a secure LAN environment
and can be used for demo recording or for HL clients serving video projectors.
Spectators connect to the HLTV dispatcher and are relayed through the HLTV network to a relay proxy with a low usage.
Thus the total network load is balanced between all connected HLTV proxies.
<pre>
Private LAN Public Internet
-> HLTV Proxy 1
HL Server -> HLTV Master -> HLTV Dispatcher -> HLTV Proxy 2
-> HLTV Proxy 3
</pre>
The configuration files of HLTV master and HLTV dispatcher are different:
**master.cfg:**
<pre>
nomaster 1 // don't register at WON master servers
proxypassword MyPWD // protect HLTV server
publicgame 0 // don't show game server IP
dispatchmode 0 // don't dispatch spectators
</pre>
**dispatcher.cfg:**
<pre>
forcemaster 1 // register at WON master servers
publicgame 0 // don't show game server IP
dispatchmode 2 // dispatch all clients to other proxies
hostname MyGame // public HLTV server name
</pre>
If you're running 3 or more HLTV servers in total, it's a good idea to use RCON to manage them via a single server admin tool.
To enable RCON on a HLTV server an `adminpassword` must been set.
Also `proxypassword` should be set to ensure only known HLTV providers can connect to your HLTV network.
Otherwise anybody can connect with slow HLTV proxies and disturb your network load balancing.
### HLTV Configuration
A short note about console command syntax.
A command may have one or more parameters. Parameters in brackets `[]` are optional.
Common used parameters are:
<pre>
<string> : text, must be in quotes if text contains spaces "My Name"
<n> : a whole number, e.g. 42
<f> : a floating point number, e.g. 4.2
<IP:Port> : an IP address, e.g. 192.168.130.42:27020
<a|b|c> : a set of options, a or b or c
</pre>
`NOTE:` Any of these special characters <, >, |, [ or ] are not part of the final command as typed in the console.
Lots of these commands are boolean switches, were 1 is meaning ON and 0 is respectively OFF.
| HLTV Commands | Arguments | Description |
| :---------------------------- | :--------------------------------------------------------- | :------------------------------------------------------------------------------------------------------ |
| connect | IP:Port | Connect HLTV proxy to game server. (default port `27015`) |
| disconnect | - | Disconnects proxy from server, but doesn't stop the broadcast.<br />All spectator clients stay connected. |
| stop | [ `text` ] | Disconnects from server, disconnects all clients and stops demo recording.<br />Optional goodbye message. |
| quit | 1 | Quits the HLTV process. |
| retry | 0 | Retries the last server connection. |
| autoretry | `0/1` | If enabled, proxy will retry connection to server.<br />If connection was interrupted for any reason. |
| name | `text` | Sets the HLTV proxy scoreboard name. |
| hostname | `text` | Sets the HLTV host name for game browser list. |
| serverpassword | `text` | Sets the game server password. |
| adminpassword | `text` | Sets password for RCON & commentator. |
| proxypassword | `text` | Sets password for other relay proxies. |
| spectatorpassword | `text` | Sets spectator password. Will also exclude proxy from global load balancing. |
| clients | - | Lists connected spectator clients. |
| proxies | - | Lists connected relay proxies. |
| players | - | Lists players on game server. |
| kick | `ID` | Kicks a spectator client from proxy. |
| bann | `IP` | Banns an IP address. (completely ignored) |
| clearbanns | - | Removes all IPs from bann list. |
| say | `text` | Sends a text message to game server. (chat with players) |
| msg | `text` [ `duration` `pos x` `pos y` `rgba` ] | Sends a text message to all spectators as big HUD text. |
| localmsg | `text` [ `duration` `pos x` `pos y` `rgba` ] | Same as msg, but only seen by local clients. |
| servercmd | `string` | Forwards console command to game server. |
| clientcmd | `group` `string` | Forwards a console command to all clients of given group:<br />`1` SPECTATORS<br />`2` PROXIES<br />`3` ALL |
| loopcmd | `id` `n` `string` | Loopcmd will execute `string` every `n` seconds.<br />`<id>` is a number between `1` and `64` to identify this loopcmd.<br />`loopcmd <id> none` will disable a looping command again.<br />loopcmd without any parameter will list any command currently in the list. |
| signoncommands | `string` | Console commands that will be executed by local<br />spectator clients after connection is established.<br />Commands may be separated by semicolons. |
| maxclients | `n` | Set spectator number limit for this proxy. (default `128`) |
| delay | `n` | Delays the game stream for n seconds on the Master Proxy.<br />The default value is 30 seconds to avoid cheating.<br />If the delay is set to a value below 10 seconds (e.g. 0),<br />the auto director function will be disabled. |
| rate | `n` | Bandwidth rate the game server sends data to the proxy. |
| updaterate | `n` | Game updates per seconds send from server to proxy. |
| maxrate | `n` | Sets the maximum bandwidth rate for spectator clients. |
| maxloss | `f` | Sets the acceptable packet loss rate, default value is 0.05 (5%).<br />If packet loss is higher, new spectator clients will be rejected. |
| maxqueries | `n` | Maximum of status queries per second requested by server browsers. |
| dispatchmode | `0/1/2` | `0` (OFF) Won't redirect any clients.<br />`1` (AUTO) Will redirect connecting clients to other<br />proxies balancing work load between all proxies.<br />`2` (ALWAYS) Any spectator clients will be redirected,<br />so this proxy serves only as dispatcher.<br /> |
| publicgame | `0/1` | `0` Private.<br />`1` Game server IP will be visible to spectators and 'joingame' is allowed. |
| offlinetext | `string` | Info text clients will see as reject reason if HLTV isn't broadcasting yet. |
| chatmode | `0/1/2` | `0` Spectators can't chat.<br />`1` Only spectators connected to the same proxy can see their chat messages.<br />`2` All spectators can chat between each other (then Master and all Relay proxies must have set chatmode 2).<br /> |
| bannerfile | `file` | Specifies a TGA file (`RGBA`) that will be shown as logo in spectator GUI. |
| ping | `host:port` | Pings a HL server on the given port. (default `27015`) |
| nomaster | `0/1` | `0` Disabled.<br />`1` Proxy won't register at WON master servers. |
| forcemaster | `0/1` | `0` Disabled.<br />`1` Proxy will register at WON master server. |
| heartbeat | - | Sends manually a status packet to WON master servers. |
| region | `n` | Set the region your HLTV proxy is located in. |
| rcon | `string` | Sends a remote control command to other servers. |
| rconaddress | `IP:Port` | Sets the remote control target address. |
| rconpassword | `string` | Sets the password for the remote controlled host. |
| cheeringthreshold | `f` | Number of cheering players must be above this threshold to play<br />the cheering sound. (by default `0.25`). |
| blockvoice | `0/1` | `0` Disabled.<br />`1` All incoming voice data is blocked.<br />This is useful to override incoming voice commentators<br />or player voice with own commentators voice. |
| cmdlist | - | Shows all registered proxy commands. |
| logfile | `0/1` | Starts/stops console logging in `logfile<date>.log` |
| status | - | Shows proxy status information. |
| modules | - | Shows all loaded HLTV modules and versions. |
| exec | `filename` | Executes a `.cfg` file. |
| echo | `string` | Prints a text to HLTV console. |
| developer | `0/1` | `0` Disabled.<br />`1` Additional debug messages are shown in developer mode. |
| record | `filename` | Records all following games to demo files<br />using name syntax `filename-<date>-<map>.dem` |
| stoprecording | - | Stops recording a demo file. |
| playdemo | `filename` | Starts broadcasting a demo file. |
The console does auto-completion by hitting `TAB`.
All commands in the config file `hltv.cfg` are executed during startup.
Some parameters can only be set in the command line:
<pre>
-port <n> - sets the HLTV proxy port that spectators connect to (default "27020" )
-ip <IP> - forces the proxy to use this IP on a multihomed host
-nodns - disables any DNS resolving (useful for LAN proxies)
-maxfps <n> - sets maximum system cycles per seconds (default "100")
-highpriority - starts the HLTV proxy as high priority process
-multicastttl <n> - sets the Time-To-Live value for multicast packets
-steam - proxy enables special Steam support
-dev - developer mode
</pre>
These parameters cannot be changed during runtime, thus they can't be used in config files.<br />
All console commands can be used in the command line, if a `+` is prepended to them, for example:
<pre>
hltv.exe +connect localhost:27015 -port 27021
</pre>
A Half-Life server can set sv_proxies `n`, to determine how many proxies are allowed to connect.<br />
If HLTV proxies should be forbidden, set it to `0`, otherwise `1` to allow for a Master Proxy.<br />
Other values are experimental.
Copyright © 2003, `Valve LLC`, All rights reserved.

13
rehlds/HLTV/build.gradle Normal file
View File

@ -0,0 +1,13 @@
evaluationDependsOn(':rehlds/HLTV/Console');
evaluationDependsOn(':rehlds/HLTV/Core');
evaluationDependsOn(':rehlds/HLTV/DemoPlayer');
evaluationDependsOn(':rehlds/HLTV/Director');
evaluationDependsOn(':rehlds/HLTV/Proxy');
task build {
dependsOn project(':rehlds/HLTV/Console').tasks.build,
project(':rehlds/HLTV/Core').tasks.build,
project(':rehlds/HLTV/DemoPlayer').tasks.build,
project(':rehlds/HLTV/Director').tasks.build,
project(':rehlds/HLTV/Proxy').tasks.build
}

View File

@ -0,0 +1,776 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
bool BaseClient::Init(IBaseSystem *system, int serial, char *name)
{
if (!BaseSystemModule::Init(system, serial, name)) {
return false;
}
if (!name) {
strcopy(m_Name, CLIENT_INTERFACE_VERSION);
}
SetState(CLIENT_INITIALIZING);
m_ClientType = TYPE_CLIENT;
m_World = nullptr;
m_Socket = nullptr;
m_VoiceEnabled = false;
m_VoiceQuery = false;
m_Userinfo.SetMaxSize(MAX_USER_INFO);
return false;
}
void BaseClient::RunFrame(double time)
{
BaseSystemModule::RunFrame(time);
if (m_ClientState != CLIENT_DISCONNECTED && m_ClientChannel.IsTimedOut()) {
m_System->Printf("Client %s timed out.\n", m_ClientChannel.GetTargetAddress()->ToString());
Disconnect("Timed out.\n");
}
if (m_ClientState != CLIENT_DISCONNECTED && m_ClientChannel.IsCrashed()) {
m_System->Printf("Client %s netchannel crashed.\n", m_ClientChannel.GetTargetAddress()->ToString());
Disconnect("Netchannel crashed.\n");
}
int numPackets = 0;
NetPacket *packet;
while ((packet = m_ClientChannel.GetPacket()))
{
if (packet->connectionless)
{
m_Socket->AddPacket(packet);
}
else if (numPackets < 32)
{
numPackets++;
ProcessMessage(packet);
}
m_ClientChannel.FreePacket(packet);
}
// process state
switch (m_ClientState)
{
case CLIENT_RUNNING:
{
if (m_World->IsActive() && m_ClientChannel.IsReadyToSend()) {
SendDatagram();
}
break;
}
case CLIENT_DISCONNECTED:
ShutDown();
break;
case CLIENT_INITIALIZING:
case CLIENT_CONNECTING:
/* do nothing */
break;
default:
case CLIENT_UNDEFINED:
m_System->Errorf("Client::RunFrame: not valid state.\n");
break;
}
}
void BaseClient::ShutDown()
{
if (m_State == MODULE_DISCONNECTED) {
return;
}
if (m_ClientState != CLIENT_DISCONNECTED) {
Disconnect("Connection dropped (hard).\n");
}
m_ClientChannel.Close();
BaseSystemModule::ShutDown();
}
bool BaseClient::Connect(INetSocket *socket, NetAddress *adr, char *userinfo)
{
if (!userinfo || !adr) {
return false;
}
m_ClientType = TYPE_CLIENT;
m_Socket = socket;
if (!adr->Equal(m_ClientChannel.GetTargetAddress())) {
m_ClientChannel.Create(m_System, m_Socket, adr);
} else {
m_ClientChannel.Clear();
m_ClientChannel.Reset();
}
SetState(CLIENT_CONNECTING);
m_ClientChannel.SetUpdateRate(20);
m_ClientChannel.SetRate(20000);
m_ClientChannel.SetConnected(1);
UpdateUserInfo(userinfo);
m_ClientChannel.OutOfBandPrintf("%c0000000000000000", S2C_CONNECTION);
return true;
}
BaseClient::clc_func_s BaseClient::m_ClientFuncs[] = {
{ clc_bad, "clc_bad", &BaseClient::ParseBad },
{ clc_nop, "clc_nop", &BaseClient::ParseNop },
{ clc_move, "clc_move", &BaseClient::ParseMove },
{ clc_stringcmd, "clc_stringcmd", &BaseClient::ParseStringCmd },
{ clc_delta, "clc_delta", &BaseClient::ParseDelta },
{ clc_resourcelist, "clc_resourcelist", nullptr },
{ clc_tmove, "clc_tmove", nullptr },
{ clc_fileconsistency, "clc_fileconsistency", nullptr },
{ clc_voicedata, "clc_voicedata", &BaseClient::ParseVoiceData },
{ clc_hltv, "clc_hltv", &BaseClient::ParseHLTV },
{ clc_cvarvalue, "clc_cvarvalue", &BaseClient::ParseCvarValue },
{ clc_cvarvalue2, "clc_cvarvalue2", &BaseClient::ParseCvarValue2 },
{ clc_endoflist, "End of List", nullptr },
};
void BaseClient::ProcessMessage(NetPacket *packet)
{
m_ClientDelta = 0;
m_DeltaFrameSeqNr = 0;
while (true)
{
if (packet->data.IsOverflowed()) {
m_System->Printf("Client::ProcessMessage: packet read overflow\n");
Disconnect("Dropped due to bad message format!\n");
break;
}
int cmd = packet->data.ReadByte();
if (cmd == -1)
break;
if (cmd < clc_bad || cmd > clc_cvarvalue2)
{
m_System->Printf("Client::ProcessMessage: unknown command char\n");
Disconnect("Bad command character in client command");
return;
}
if (!m_ClientFuncs[cmd].func) {
m_System->Printf("TODO! Client::ProcessMessage: missing parsing routine for %s.\n", m_ClientFuncs[cmd].pszname);
return;
}
(this->*m_ClientFuncs[cmd].func)(packet);
}
}
char *BaseClient::GetClientName()
{
return m_ClientName;
}
InfoString *BaseClient::GetUserInfo()
{
return &m_Userinfo;
}
void BaseClient::Disconnect(const char *reason)
{
SetState(CLIENT_DISCONNECTED);
m_ClientChannel.m_reliableStream.WriteByte(svc_disconnect);
m_ClientChannel.m_reliableStream.WriteString(reason ? reason : "");
m_ClientChannel.m_unreliableStream.WriteByte(svc_disconnect);
m_ClientChannel.m_unreliableStream.WriteString(reason ? reason : "");
m_ClientChannel.TransmitOutgoing();
}
void BaseClient::ParseNop(NetPacket *packet)
{
;
}
void BaseClient::ParseBad(NetPacket *packet)
{
m_System->Printf("Client::ParseBad: bad command char\n");
Disconnect("Bad command character in client command");
}
void BaseClient::ParseStringCmd(NetPacket *packet)
{
char *string = packet->data.ReadString();
ProcessStringCmd(string);
}
BaseClient::LocalCommandID_s BaseClient::m_LocalCmdReg[] = {
{ "name", CMD_ID_NAME, &BaseClient::CMD_Name },
{ "spawn", CMD_ID_SPAWN, &BaseClient::CMD_Spawn },
{ "new", CMD_ID_NEW, &BaseClient::CMD_New },
{ "fullupdate", CMD_ID_FULLUPDATE, &BaseClient::CMD_FullUpdate },
{ "dropclient", CMD_ID_DROPCLIENT, &BaseClient::CMD_DropClient },
{ "dlfile", CMD_ID_DLFILE, &BaseClient::CMD_DownloadFile },
{ "setinfo", CMD_ID_SETINFO, &BaseClient::CMD_SetInfo },
{ "showinfo", CMD_ID_SHOWINFO, &BaseClient::CMD_ShowInfo },
{ "sendents", CMD_ID_SENDENTS, &BaseClient::CMD_SendEntities },
{ "VModEnable", CMD_ID_VMODENABLE, &BaseClient::CMD_VoiceModEnable },
{ "vban", CMD_ID_VBAN, &BaseClient::CMD_VoiceBan },
// TODO: Pure function's, finish them.
{ "sendres", CMD_ID_SENDERS, &BaseClient::CMD_SendResources },
{ "ping", CMD_ID_PING, &BaseClient::CMD_RequestPing },
{ "spectate", CMD_ID_SPECTATE, &BaseClient::CMD_Spectate },
{ "spk", CMD_ID_SPK, &BaseClient::CMD_Spk },
{ "pause", CMD_ID_PAUSE, &BaseClient::CMD_Pause },
{ "unpause", CMD_ID_UNPAUSE, &BaseClient::CMD_UnPause },
{ "setpause", CMD_ID_SETPAUSE, &BaseClient::CMD_SetPause }
};
bool BaseClient::ProcessStringCmd(char *string)
{
TokenLine cmdLine;
if (!cmdLine.SetLine(string)) {
m_System->Printf("WARNING! BaseClient::ProcessStringCmd: string command too long.\n");
return false;
}
char *cmd = cmdLine.GetToken(0);
for (auto& local_cmd : m_LocalCmdReg)
{
if (!_stricmp(local_cmd.name, cmd)) {
(this->*local_cmd.pfnCmd)(&cmdLine);
return true;
}
}
return false;
}
void BaseClient::CMD_Name(TokenLine *cmd)
{
SetName(cmd->GetRestOfLine(1));
}
void BaseClient::CMD_Spawn(TokenLine *cmd)
{
if (cmd->CountToken() != 3) {
m_System->Printf("Client::ParseStringCmd: spawn is not valid\n");
Disconnect("Spawn is not valid.");
return;
}
ReplySpawn(atoi(cmd->GetToken(1)), atoi(cmd->GetToken(2)));
}
void BaseClient::CMD_New(TokenLine *cmd)
{
ReplyNew();
}
void BaseClient::CMD_FullUpdate(TokenLine *cmd)
{
ReplyFullUpdate();
}
void BaseClient::CMD_DropClient(TokenLine *cmd)
{
Disconnect();
}
void BaseClient::CMD_DownloadFile(TokenLine *cmd)
{
DownloadFile(cmd->GetToken(1));
}
void BaseClient::CMD_SetInfo(TokenLine *cmd)
{
if (cmd->CountToken() != 3) {
return;
}
m_Userinfo.SetValueForKey(cmd->GetToken(1), cmd->GetToken(2));
UpdateUserInfo();
}
void BaseClient::CMD_ShowInfo(TokenLine *cmd)
{
InfoString info(MAX_INFO_STRING);
info.SetString(m_World->GetServerInfoString()->GetString());
info.RemoveKey("proxy"); // remove proxy ip
PrintfToClient("%s\n", info.GetString());
}
void BaseClient::CMD_SendEntities(TokenLine *cmd)
{
m_System->DPrintf("Client fully connected.\n");
SetState(CLIENT_RUNNING);
}
void BaseClient::CMD_VoiceModEnable(TokenLine *cmd)
{
if (cmd->CountToken() != 2) {
return;
}
m_VoiceQuery = false;
m_VoiceEnabled = atoi(cmd->GetToken(1)) ? true : false;
UpdateVoiceMask(&m_ClientChannel.m_reliableStream);
}
void BaseClient::CMD_VoiceBan(TokenLine *cmd)
{
if (cmd->CountToken() < 2) {
return;
}
for (int i = 1; i < cmd->CountToken(); i++)
{
uint32 mask = 0;
sscanf(cmd->GetToken(i), "%x", &mask);
if (i <= VOICE_MAX_PLAYERS_DW) {
m_SentBanMask.SetDWord(i - 1, mask);
}
}
UpdateVoiceMask(&m_ClientChannel.m_reliableStream);
}
void BaseClient::CMD_SendResources(TokenLine *cmd) { /* do nothing */ }
void BaseClient::CMD_RequestPing(TokenLine *cmd) { /* do nothing */ }
void BaseClient::CMD_Spectate(TokenLine *cmd) { /* do nothing */ }
void BaseClient::CMD_Spk(TokenLine *cmd) { /* do nothing */ }
void BaseClient::CMD_Pause(TokenLine *cmd) { /* do nothing */ }
void BaseClient::CMD_UnPause(TokenLine *cmd) { /* do nothing */ }
void BaseClient::CMD_SetPause(TokenLine *cmd) { /* do nothing */ }
void BaseClient::UpdateUserInfo(char *userinfostring)
{
char buffer[1024];
char *string;
if (userinfostring) {
m_Userinfo.SetString(userinfostring);
}
strcopy(buffer, m_Userinfo.ValueForKey("name"));
SetName(buffer);
m_ClientType = atoi(m_Userinfo.ValueForKey("*hltv"));
if (m_ClientType < TYPE_CLIENT) {
m_System->DPrintf("WARNING! BaseClient::UpdateUserInfo: invalid client ype %i\n", m_ClientType);
m_ClientType = TYPE_CLIENT;
}
string = m_Userinfo.ValueForKey("rate");
if (*string) {
m_ClientChannel.SetRate(atoi(string));
}
string = m_Userinfo.ValueForKey("cl_updaterate");
if (*string) {
m_ClientChannel.SetUpdateRate(atoi(string));
}
}
void BaseClient::PrintfToClient(char *fmt, ...)
{
va_list argptr;
static char string[1024];
va_start(argptr, fmt);
_vsnprintf(string, sizeof(string), fmt, argptr);
va_end(argptr);
m_ClientChannel.m_reliableStream.WriteByte(svc_print);
m_ClientChannel.m_reliableStream.WriteString(string);
}
void BaseClient::ReplySpawn(int spawncount, int crcMap)
{
BitBuffer msg(MAX_POSSIBLE_MSG);
m_CRC_Value = crcMap;
COM_UnMunge2((unsigned char *)&m_CRC_Value, 4, (-1 - m_World->GetServerCount()) & 0xFF);
if (m_World->GetServerCount() != spawncount) {
ReplyNew();
return;
}
m_World->WriteSigonData(&msg);
WriteSpawn(&msg);
m_ClientChannel.CreateFragmentsFromBuffer(msg.GetData(), msg.CurrentSize(), FRAG_NORMAL_STREAM, nullptr);
m_ClientChannel.FragSend();
m_LastFrameSeqNr = 0;
}
void BaseClient::ReplyNew()
{
BitBuffer msg(MAX_POSSIBLE_MSG);
Reset();
m_World->WriteNewData(&msg);
m_ClientChannel.CreateFragmentsFromBuffer(msg.GetData(), msg.CurrentSize(), FRAG_NORMAL_STREAM, nullptr);
m_ClientChannel.FragSend();
msg.Free();
}
void BaseClient::ReplyFullUpdate()
{
BitBuffer msg(1024 * 9);
for (int i = 0; i < m_World->GetMaxClients(); i++) {
m_World->WriteClientUpdate(&msg, i);
}
m_ClientChannel.CreateFragmentsFromBuffer(msg.GetData(), msg.CurrentSize(), FRAG_NORMAL_STREAM, nullptr);
m_ClientChannel.FragSend();
}
void BaseClient::SetState(ClientState newState)
{
if (newState == m_ClientState)
return;
bool stateError = false;
switch (newState)
{
case CLIENT_INITIALIZING:
break;
case CLIENT_CONNECTING:
{
if (m_ClientState != CLIENT_INITIALIZING
&& m_ClientState != CLIENT_RUNNING) {
stateError = true;
}
m_ClientChannel.SetKeepAlive(true);
m_ClientChannel.SetTimeOut(60);
break;
}
case CLIENT_RUNNING:
{
if (m_ClientState != CLIENT_CONNECTING) {
stateError = true;
}
m_ClientChannel.SetKeepAlive(false);
m_ClientChannel.SetTimeOut(30);
break;
}
case CLIENT_DISCONNECTED:
{
m_ClientChannel.SetKeepAlive(true);
break;
}
default:
stateError = true;
break;
}
if (stateError)
{
m_System->Errorf("Client::SetState: not valid m_ClientState (%i -> %i).\n", m_ClientState, newState);
return;
}
m_ClientState = newState;
}
void BaseClient::WriteSpawn(BitBuffer *stream)
{
stream->WriteByte(svc_time);
stream->WriteFloat(1);
for (int i = 0; i < m_World->GetMaxClients(); i++) {
m_World->WriteClientUpdate(stream, i);
}
m_World->WriteLightStyles(stream);
stream->WriteByte(svc_signonnum);
stream->WriteByte(1);
}
void BaseClient::WriteDatagram(double time, frame_t *frame)
{
if (!frame) {
return;
}
if (!m_LastFrameSeqNr || m_LastFrameSeqNr > frame->seqnr) {
m_LastFrameSeqNr = frame->seqnr - 1;
m_ClientDelta = 0;
m_DeltaFrameSeqNr = 0;
}
if (m_LastFrameSeqNr >= frame->seqnr && m_ClientChannel.GetIdleTime() <= 2) {
return;
}
m_ClientChannel.m_unreliableStream.WriteByte(svc_time);
m_ClientChannel.m_unreliableStream.WriteFloat(float(time));
m_World->WriteFrame(frame, m_LastFrameSeqNr, &m_ClientChannel.m_reliableStream, &m_ClientChannel.m_unreliableStream, m_DeltaFrameSeqNr, m_ClientDelta, IsHearingVoices());
if (m_VoiceQuery) {
QueryVoiceEnabled(&m_ClientChannel.m_unreliableStream);
}
if (m_ClientChannel.m_reliableStream.IsOverflowed()) {
Disconnect("Reliable data stream overflow.\n");
return;
}
if (m_ClientChannel.m_unreliableStream.IsOverflowed()) {
m_System->DPrintf("Unreliable data stream overflow.\n");
m_ClientChannel.m_unreliableStream.Clear();
m_LastFrameSeqNr = 0;
}
m_LastFrameSeqNr = frame->seqnr;
m_SeqNrMap[m_ClientChannel.m_outgoing_sequence & 0xFF] = frame->seqnr;
m_ClientChannel.TransmitOutgoing();
}
void BaseClient::ParseDelta(NetPacket *packet)
{
if (m_ClientState != CLIENT_RUNNING) {
packet->data.SkipBytes(1);
return;
}
m_ClientDelta = packet->data.ReadByte();
m_DeltaFrameSeqNr = m_SeqNrMap[m_ClientDelta];
}
char *BaseClient::GetStatusLine()
{
float in, out;
static char string[256];
m_ClientChannel.GetFlowStats(&in, &out);
_snprintf(string, sizeof(string),
"ID: %i, Name \"%s\", Time %s, IP %s, In %.2f, Out %.2f.\n",
GetSerial(),
m_ClientName,
COM_FormatTime(float(m_SystemTime - m_ClientChannel.m_connect_time)),
m_ClientChannel.GetTargetAddress()->ToString(),
in,
out
);
return string;
}
void BaseClient::SetWorld(IWorld *world)
{
if (m_World && m_World != world) {
Reconnect();
}
m_World = world;
}
void BaseClient::Reconnect()
{
Reset();
m_ClientChannel.m_reliableStream.WriteByte(svc_stufftext);
m_ClientChannel.m_reliableStream.WriteString("reconnect\n");
}
bool BaseClient::IsActive()
{
return (m_ClientState == CLIENT_RUNNING);
}
void BaseClient::ParseVoiceData(NetPacket *packet)
{
int nDataLength = packet->data.ReadShort();
packet->data.SkipBytes(nDataLength);
}
void BaseClient::ParseMove(NetPacket *packet)
{
int nDataLength = packet->data.ReadByte();
packet->data.SkipBytes(nDataLength + 1);
}
void BaseClient::SetName(char *newName)
{
char temp[32];
COM_RemoveEvilChars(newName);
COM_TrimSpace(newName, temp);
if (strlen(temp) > sizeof(temp) - 1) {
temp[sizeof(temp) - 1] = '\0';
}
if (!temp[0] || !_stricmp(temp, "console")) {
strcpy(temp, "unnamed");
}
strcopy(m_ClientName, temp);
m_Userinfo.SetValueForKey("name", m_ClientName);
}
void BaseClient::ParseHLTV(NetPacket *packet)
{
Disconnect("TODO Client::ParseHLTV: Invalid client command.\n");
}
void BaseClient::ParseCvarValue(NetPacket *packet)
{
packet->data.ReadString();
}
void BaseClient::ParseCvarValue2(NetPacket *packet)
{
packet->data.ReadWord();
packet->data.ReadString();
packet->data.ReadString();
}
void BaseClient::QueryVoiceEnabled(BitBuffer *stream)
{
int reqState = m_World->FindUserMsgByName("ReqState");
if (!reqState || !m_World->IsVoiceEnabled())
return;
stream->WriteByte(reqState);
}
void BaseClient::UpdateVoiceMask(BitBuffer *stream)
{
int voiceMask = m_World->FindUserMsgByName("VoiceMask");
if (!voiceMask) {
m_System->DPrintf("WARNING! Client::UpdateVoiceMask(): could find User Msg VoiceMaks.\n");
return;
}
if (!m_World->IsVoiceEnabled()) {
return;
}
CPlayerBitVec gameRulesMask;
gameRulesMask[m_World->GetSlotNumber()] = !!m_VoiceEnabled;
if (gameRulesMask != m_SentGameRulesMask || m_BanMask != m_SentBanMask)
{
m_SentGameRulesMask = gameRulesMask;
m_SentBanMask = m_BanMask;
stream->WriteByte(voiceMask);
for (int dw = 0; dw < VOICE_MAX_PLAYERS_DW; dw++)
{
stream->WriteLong(gameRulesMask.GetDWord(dw));
stream->WriteLong(m_BanMask.GetDWord(dw));
}
}
}
bool BaseClient::IsHearingVoices()
{
return m_BanMask[m_World->GetSlotNumber()] ? true : false;
}
bool BaseClient::HasChatEnabled()
{
return false;
}
void BaseClient::DownloadFile(char *fileName)
{
if (!fileName || !fileName[0])
return;
DownloadFailed(fileName);
}
void BaseClient::DownloadFailed(char *fileName)
{
if (!fileName || !fileName[0])
return;
m_ClientChannel.m_reliableStream.WriteByte(svc_filetxferfailed);
m_ClientChannel.m_reliableStream.WriteString(fileName);
}
void BaseClient::Send(unsigned char *data, int length, bool isReliable)
{
if (isReliable)
m_ClientChannel.m_reliableStream.WriteBuf(data, length);
else
m_ClientChannel.m_unreliableStream.WriteBuf(data, length);
}
NetAddress *BaseClient::GetAddress()
{
return m_ClientChannel.GetTargetAddress();
}
int BaseClient::GetClientType()
{
return m_ClientType;
}
char *BaseClient::GetType()
{
return CLIENT_INTERFACE_VERSION;
}
void BaseClient::SendDatagram()
{
frame_t *frame = m_World->GetLastFrame();
if (frame) {
WriteDatagram(frame->time, frame);
}
}
void BaseClient::Reset()
{
SetState(CLIENT_CONNECTING);
m_LastFrameSeqNr = 0;
m_DeltaFrameSeqNr = 0;
m_ClientDelta = 0;
memset(m_SeqNrMap, 0, sizeof(m_SeqNrMap));
m_VoiceQuery = true;
m_ClientChannel.Clear();
}

View File

@ -0,0 +1,176 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include <HLTV/IClient.h>
#include <HLTV/IWorld.h>
#include <game_shared/voice_common.h>
#include "InfoString.h"
#include "NetChannel.h"
#include "BaseSystemModule.h"
class TokenLine;
class BaseClient: public IClient, public BaseSystemModule {
public:
BaseClient() {}
virtual ~BaseClient() {}
virtual bool Init(IBaseSystem *system, int serial, char *name);
virtual void RunFrame(double time);
virtual char *GetStatusLine();
virtual char *GetType();
virtual void ShutDown();
virtual bool Connect(INetSocket *socket, NetAddress *adr, char *userinfo);
virtual void Disconnect(const char *reason = nullptr);
virtual void Reconnect();
virtual void SetWorld(IWorld *world);
virtual bool IsHearingVoices();
virtual bool HasChatEnabled();
virtual NetAddress *GetAddress();
virtual InfoString *GetUserInfo();
virtual int GetClientType();
virtual char *GetClientName();
virtual bool IsActive();
virtual void Send(unsigned char *data, int length, bool isReliable);
virtual void DownloadFailed(char *fileName);
virtual void DownloadFile(char *fileName);
virtual void UpdateVoiceMask(BitBuffer *stream);
virtual void QueryVoiceEnabled(BitBuffer *stream);
virtual void SetName(char *newName);
virtual void WriteSpawn(BitBuffer *stream);
virtual void WriteDatagram(double time, frame_t *frame);
virtual void SendDatagram();
virtual void Reset();
enum ClientState {
CLIENT_UNDEFINED = 0,
CLIENT_INITIALIZING,
CLIENT_CONNECTING,
CLIENT_RUNNING,
CLIENT_DISCONNECTED
};
virtual void SetState(ClientState newState);
virtual void ReplyNew();
virtual void ReplySpawn(int spawncount, int crcMap);
virtual void ReplyFullUpdate();
virtual void PrintfToClient(char *fmt, ...);
virtual void UpdateUserInfo(char *userinfostring = nullptr);
virtual void ParseStringCmd(NetPacket *packet);
virtual void ParseNop(NetPacket *packet);
virtual void ParseBad(NetPacket *packet);
virtual void ParseMove(NetPacket *packet);
virtual void ParseVoiceData(NetPacket *packet);
virtual void ParseHLTV(NetPacket *packet);
virtual void ParseDelta(NetPacket *packet);
virtual void ParseCvarValue(NetPacket *packet);
virtual void ParseCvarValue2(NetPacket *packet);
virtual void ProcessMessage(NetPacket *packet);
virtual bool ProcessStringCmd(char *string);
private:
enum LocalCommandIDs {
CMD_ID_NAME = 1,
CMD_ID_SPAWN,
CMD_ID_NEW,
CMD_ID_FULLUPDATE,
CMD_ID_DROPCLIENT,
CMD_ID_DLFILE,
CMD_ID_SETINFO,
CMD_ID_SHOWINFO,
CMD_ID_SENDENTS,
CMD_ID_VMODENABLE,
CMD_ID_VBAN,
CMD_ID_SENDERS,
CMD_ID_PING,
CMD_ID_SPECTATE,
CMD_ID_SPK,
CMD_ID_PAUSE,
CMD_ID_UNPAUSE,
CMD_ID_SETPAUSE
};
void CMD_Name(TokenLine *cmd);
void CMD_Spawn(TokenLine *cmd);
void CMD_New(TokenLine *cmd);
void CMD_FullUpdate(TokenLine *cmd);
void CMD_DropClient(TokenLine *cmd);
void CMD_DownloadFile(TokenLine *cmd);
void CMD_SetInfo(TokenLine *cmd);
void CMD_ShowInfo(TokenLine *cmd);
void CMD_SendEntities(TokenLine *cmd);
void CMD_VoiceModEnable(TokenLine *cmd);
void CMD_VoiceBan(TokenLine *cmd);
void CMD_SendResources(TokenLine *cmd);
void CMD_RequestPing(TokenLine *cmd);
void CMD_Spectate(TokenLine *cmd);
void CMD_Spk(TokenLine *cmd);
void CMD_Pause(TokenLine *cmd);
void CMD_UnPause(TokenLine *cmd);
void CMD_SetPause(TokenLine *cmd);
struct LocalCommandID_s {
char *name;
LocalCommandIDs id;
void (BaseClient::*pfnCmd)(TokenLine *cmd);
};
static LocalCommandID_s m_LocalCmdReg[];
protected:
struct clc_func_s {
clc_commands opcode;
char *pszname;
void (BaseClient::*func)(NetPacket *packet);
};
static clc_func_s m_ClientFuncs[];
IWorld *m_World;
INetSocket *m_Socket;
NetChannel m_ClientChannel;
int m_ClientType;
int m_ClientState;
char m_ClientName[32];
enum { MAX_USER_INFO = 256 };
InfoString m_Userinfo;
unsigned int m_LastFrameSeqNr;
unsigned int m_DeltaFrameSeqNr;
unsigned int m_ClientDelta;
unsigned int m_SeqNrMap[256];
int m_CRC_Value;
bool m_VoiceEnabled;
bool m_VoiceQuery;
CPlayerBitVec m_SentGameRulesMask;
CPlayerBitVec m_SentBanMask;
CPlayerBitVec m_BanMask;
};

View File

@ -0,0 +1,887 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
const uint32 BITTABLE[] =
{
0x00000001, 0x00000002, 0x00000004, 0x00000008,
0x00000010, 0x00000020, 0x00000040, 0x00000080,
0x00000100, 0x00000200, 0x00000400, 0x00000800,
0x00001000, 0x00002000, 0x00004000, 0x00008000,
0x00010000, 0x00020000, 0x00040000, 0x00080000,
0x00100000, 0x00200000, 0x00400000, 0x00800000,
0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000,
0x00000000,
};
const uint32 ROWBITTABLE[] =
{
0x00000000, 0x00000001, 0x00000003, 0x00000007,
0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F,
0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF,
0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF,
0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF,
0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF,
0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF,
0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF,
0xFFFFFFFF,
};
const uint32 INVBITTABLE[] =
{
0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFB, 0xFFFFFFF7,
0xFFFFFFEF, 0xFFFFFFDF, 0xFFFFFFBF, 0xFFFFFF7F,
0xFFFFFEFF, 0xFFFFFDFF, 0xFFFFFBFF, 0xFFFFF7FF,
0xFFFFEFFF, 0xFFFFDFFF, 0xFFFFBFFF, 0xFFFF7FFF,
0xFFFEFFFF, 0xFFFDFFFF, 0xFFFBFFFF, 0xFFF7FFFF,
0xFFEFFFFF, 0xFFDFFFFF, 0xFFBFFFFF, 0xFF7FFFFF,
0xFEFFFFFF, 0xFDFFFFFF, 0xFBFFFFFF, 0xF7FFFFFF,
0xEFFFFFFF, 0xDFFFFFFF, 0xBFFFFFFF, 0x7FFFFFFF,
0xFFFFFFFF,
};
BitBuffer::BitBuffer() : m_Data(nullptr),
m_CurByte(nullptr),
m_CurSize(0),
m_MaxSize(0),
m_Overflowed(false),
m_LittleEndian(false),
m_OwnData(false)
{
;
}
BitBuffer::BitBuffer(void *newData, unsigned int size)
{
m_Data = (unsigned char *)newData;
m_CurByte = m_Data;
m_CurSize = 0;
m_MaxSize = size;
m_Overflowed = false;
m_LittleEndian = true;
m_OwnData = false;
}
BitBuffer::~BitBuffer()
{
Free();
}
BitBuffer::BitBuffer(unsigned int size)
{
m_Data = nullptr;
m_CurByte = nullptr;
m_CurSize = 0;
m_MaxSize = size;
m_Overflowed = false;
m_LittleEndian = false;
m_OwnData = false;
Resize(size);
}
bool BitBuffer::Resize(unsigned int size)
{
Free();
m_Data = (unsigned char *)Mem_ZeroMalloc(size + 4);
m_CurSize = 0;
m_Overflowed = false;
if (m_Data)
{
m_CurByte = m_Data;
m_MaxSize = size;
m_OwnData = true;
m_LittleEndian = true;
return true;
}
m_MaxSize = 0;
m_OwnData = false;
m_CurByte = nullptr;
return false;
}
void BitBuffer::Clear()
{
memset(m_Data, 0, m_MaxSize);
m_CurByte = m_Data;
m_CurSize = 0;
m_Overflowed = false;
m_LittleEndian = true;
}
int BitBuffer::CurrentBit()
{
return m_CurSize + 8 * (m_CurByte - m_Data);
}
void BitBuffer::Reset()
{
m_CurByte = m_Data;
m_CurSize = 0;
m_Overflowed = false;
m_LittleEndian = true;
}
void BitBuffer::Free()
{
if (m_Data && m_OwnData) {
free(m_Data);
}
m_Data = nullptr;
m_CurByte = nullptr;
m_CurSize = 0;
m_MaxSize = 0;
m_OwnData = false;
m_Overflowed = false;
m_LittleEndian = true;
}
unsigned int BitBuffer::ReadBits(int numbits)
{
unsigned int result = 0;
if (m_LittleEndian)
{
if (m_CurByte - m_Data >= m_MaxSize)
{
m_Overflowed = true;
return -1;
}
int bits = m_CurSize + numbits;
if (bits <= 32)
{
result = (*(unsigned int *)m_CurByte >> m_CurSize) & ROWBITTABLE[numbits];
m_CurByte += numbits >> 3;
m_CurSize += numbits & 7;
if (m_CurSize > 7)
{
m_CurSize &= 7;
m_CurByte++;
}
}
else
{
unsigned int data = *(unsigned int *)m_CurByte >> m_CurSize;
m_CurByte += 4;
result = ((ROWBITTABLE[bits & 7] & *(unsigned int *)m_CurByte) << (32 - m_CurSize)) | data;
m_CurSize = bits & 7;
}
}
else
{
int d = numbits;
while (d > 0)
{
--d;
if (ReadBit()) {
result |= (1 << d);
}
}
}
return result;
}
int BitBuffer::ReadBit()
{
int result;
if (m_CurByte - m_Data >= m_MaxSize) {
m_Overflowed = true;
result = -1;
}
else
{
if (m_LittleEndian)
{
if (m_CurSize == 7)
{
m_CurSize = 0;
result = (*m_CurByte++ >> 7) & 1;
}
else
{
result = ((unsigned int)*m_CurByte >> m_CurSize++) & 1;
}
}
else
{
if (m_CurSize == 7)
{
m_CurSize = 0;
result = *m_CurByte++ & 1;
}
else
{
result = ((unsigned int)*m_CurByte >> (7 - m_CurSize++)) & 1;
}
}
}
return result;
}
unsigned int BitBuffer::PeekBits(int numbits)
{
int oldcurrentBit = m_CurSize;
unsigned char *oldcurrentByte = m_CurByte;
unsigned int data = ReadBits(numbits);
m_CurSize = oldcurrentBit;
m_CurByte = oldcurrentByte;
return data;
}
int BitBuffer::ReadChar()
{
return ReadBits(8);
}
int BitBuffer::ReadByte()
{
return ReadBits(8);
}
int BitBuffer::ReadShort()
{
return ReadBits(16);
}
int BitBuffer::ReadWord()
{
return ReadBits(16);
}
unsigned int BitBuffer::ReadLong()
{
return ReadBits(32);
}
float BitBuffer::ReadFloat()
{
union {
float f;
int i;
} dat;
dat.i = _LittleLong(ReadLong());
return dat.f;
}
bool BitBuffer::ReadBuf(int iSize, void *pbuf)
{
if (m_CurByte - m_Data + iSize > m_MaxSize) {
m_Overflowed = true;
return false;
}
if (m_CurSize)
{
int i, j;
unsigned int *p = (unsigned int *)pbuf;
for (i = 4; i < iSize; i += 4) {
*p++ = ReadLong();
}
for (j = 0; j < iSize - (i - 4); ++j) {
*((unsigned char *)p + j) = ReadByte();
}
}
else
{
memcpy(pbuf, m_CurByte, iSize);
m_CurByte += iSize;
}
return true;
}
void BitBuffer::WriteBuf(BitBuffer *buf, int length)
{
WriteBuf(buf->m_CurByte, length);
buf->SkipBytes(length);
}
char *BitBuffer::ReadString()
{
int c = 0, l = 0;
static char string[8192];
while ((c = ReadChar(), c) && c != -1 && l < sizeof(string) - 1) {
string[l++] = c;
}
string[l] = '\0';
return string;
}
char *BitBuffer::ReadStringLine()
{
int c = 0, l = 0;
static char string[2048];
while ((c = ReadChar(), c) && c != '\n' && c != -1 && l < sizeof(string) - 1) {
string[l++] = c;
}
string[l] = '\0';
return string;
}
float BitBuffer::ReadAngle()
{
int c = ReadChar();
if (c == -1)
{
// FIXED: Added check for wrong value, but just return 0 instead of -1 * (360.0 / 256)
return 0;
}
return (float)(c * (360.0 / 256));
}
float BitBuffer::ReadHiresAngle()
{
int c = ReadShort();
if (c == -1)
{
// FIXED: Added check for wrong value, but just return 0 instead of -1 * (360.0 / 65536)
return 0;
}
return (float)(c * (360.0 / 65536));
}
void BitBuffer::WriteBit(int c)
{
if (m_CurByte - m_Data >= m_MaxSize) {
m_Overflowed = true;
return;
}
if (m_LittleEndian)
{
if (m_CurSize == 7)
{
if (c)
{
m_CurByte[0] |= 0x80u;
}
else
{
m_CurByte[0] &= 0x7Fu;
}
m_CurByte++;
m_CurSize = 0;
}
else
{
if (c)
{
m_CurByte[0] |= BITTABLE[ m_CurSize ];
}
else
{
m_CurByte[0] &= INVBITTABLE[ m_CurSize ];
}
m_CurSize++;
}
}
else
{
static unsigned char masks[] = { 0x80u, 0x40u, 0x20u, 0x10u, 0x8u, 0x4u, 0x2u, 0x1u };
static unsigned char inv_masks[] = { 0x7Fu, 0xBFu, 0xDFu, 0xEFu, 0xF7u, 0xFBu, 0xFDu, 0xFEu };
if (c)
m_CurByte[0] |= masks[ m_CurSize ];
else
m_CurByte[0] &= inv_masks[ m_CurSize ];
if (++m_CurSize == 8)
{
m_CurSize = 0;
m_CurByte++;
}
}
}
void BitBuffer::WriteBits(unsigned int data, int numbits)
{
if (m_Overflowed) {
return;
}
if (m_LittleEndian)
{
if (m_CurByte - m_Data + (numbits >> 8) > m_MaxSize) {
m_Overflowed = true;
return;
}
int bits = numbits + m_CurSize;
if (bits <= 32)
{
*(uint32 *)m_CurByte |= (ROWBITTABLE[numbits] & data) << m_CurSize;
m_CurByte = &m_CurByte[numbits >> 3];
m_CurSize = m_CurSize + (numbits & 7);
if (m_CurSize > 7)
{
m_CurSize = m_CurSize & 7;
m_CurByte = m_CurByte + 1;
}
}
else
{
*(uint32 *)m_CurByte |= (ROWBITTABLE[numbits] & data) << m_CurSize;
int leftBits = (32 - m_CurSize);
m_CurSize = (m_CurSize + numbits) & 7;
m_CurByte += 4;
*(uint32 *)m_CurByte |= (ROWBITTABLE[numbits] & data) >> leftBits;
}
return;
}
int nBitValue = data;
if (numbits <= 31 && nBitValue >= (1 << numbits) && nBitValue != -1)
nBitValue = (1 << numbits) - 1;
while (--numbits > 0)
{
if (m_CurByte - m_Data >= m_MaxSize) {
m_Overflowed = true;
break;
}
WriteBit(nBitValue & (1 << numbits));
}
}
void BitBuffer::WriteSBits(int data, int numbits)
{
int idata = data;
if (numbits < 32)
{
int maxnum = (1 << (numbits - 1)) - 1;
if (data > maxnum || (maxnum = -maxnum, data < maxnum))
{
idata = maxnum;
}
}
int sigbits = idata < 0;
WriteBit(sigbits);
WriteBits(abs(idata), numbits - 1);
}
void BitBuffer::WriteChar(int c)
{
WriteBits(c, 8 * sizeof(char));
}
void BitBuffer::WriteByte(int c)
{
WriteBits(c, 8 * sizeof(uint8));
}
void BitBuffer::WriteShort(int c)
{
WriteBits(c, 8 * sizeof(int16));
}
void BitBuffer::WriteWord(int c)
{
WriteBits(c, 8 * sizeof(uint16));
}
void BitBuffer::WriteLong(unsigned int c)
{
WriteBits(c, 8 * sizeof(uint32));
}
void BitBuffer::WriteFloat(float f)
{
union {
float f;
int i;
} dat;
dat.f = f;
WriteBits(_LittleLong(dat.i), 8 * sizeof(float));
}
void BitBuffer::WriteString(const char *p)
{
if (p)
{
WriteBuf(p, strlen(p) + 1);
}
else
{
WriteChar('\0');
}
}
void BitBuffer::WriteBuf(const void *buf, int iSize)
{
if (!buf || m_Overflowed || !iSize) {
return;
}
if (m_CurByte - m_Data + iSize > m_MaxSize) {
m_Overflowed = true;
return;
}
if (m_CurSize)
{
int i, j;
unsigned int *p = (unsigned int *)buf;
for (i = 4; i < iSize; i += 4) {
WriteLong(*p++);
}
for (j = 0; j < (iSize - (i - 4)); j++) {
WriteChar(*((unsigned char *)p + j));
}
}
else
{
memcpy(m_CurByte, buf, iSize);
m_CurByte += iSize;
}
}
void BitBuffer::WriteBitData(void *src, int length)
{
int i;
unsigned char *p = (unsigned char *)src;
for (i = 0; i < length; i++, p++)
{
WriteChar(*p);
}
}
void BitBuffer::WriteAngle(float f)
{
WriteByte((int64)(fmod((double)f, 360.0) * 256.0 / 360.0) & 0xFF);
}
void BitBuffer::WriteHiresAngle(float f)
{
WriteShort((int64)(fmod((double)f, 360.0) * 65536.0 / 360.0) & 0xFFFF);
}
int BitBuffer::CurrentSize()
{
return (m_CurSize != 0) + m_CurByte - m_Data;
}
unsigned char *BitBuffer::CurrentByte()
{
return m_CurByte;
}
int BitBuffer::SpaceLeft()
{
return m_MaxSize + m_Data - m_CurByte;
}
void BitBuffer::AlignByte()
{
if (m_CurSize)
{
m_CurByte++;
m_CurSize = 0;
}
}
int BitBuffer::ReadSBits(int numbits)
{
int nSignBit = ReadBit();
int result = ReadBits(numbits - 1);
if (nSignBit)
{
result = -result;
}
return result;
}
float BitBuffer::ReadBitAngle(int numbits)
{
return (float)(ReadBits(numbits) * (360.0 / (1 << numbits)));
}
void BitBuffer::WriteBitAngle(float fAngle, int numbits)
{
if (numbits >= 32) {
m_Overflowed = true;
return;
}
unsigned int shift = (1 << numbits);
unsigned int mask = shift - 1;
int d = (int)(shift * fmod((double)fAngle, 360.0)) / 360;
d &= mask;
WriteBits(d, numbits);
}
char *BitBuffer::ReadBitString()
{
static char buf[8192];
buf[0] = '\0';
char *p = &buf[0];
for (unsigned int c = ReadChar(); c; c = ReadChar())
{
// Prevent infinite cycle if m_Overflowed
if (m_Overflowed) {
break;
}
*p++ = c;
}
*p = '\0';
return buf;
}
void BitBuffer::WriteBitString(const char *p)
{
const unsigned char *pch = (unsigned char *)p;
while (*pch)
{
WriteChar(*pch++);
}
WriteChar('\0');
}
void BitBuffer::StartBitMode()
{
if (m_CurSize) {
m_Overflowed = true;
}
}
void BitBuffer::EndBitMode()
{
AlignByte();
}
int BitBuffer::ReadBitData(void *dest, int length)
{
unsigned char *p = (unsigned char *)dest;
for (int i = 0; i < length; i++) {
*p++ = ReadByte();
}
return length;
}
void BitBuffer::SetBuffer(void *buffer, int size)
{
Free();
m_Data = (unsigned char *)buffer;
m_CurByte = (unsigned char *)buffer;
m_MaxSize = size;
m_CurSize = 0;
m_OwnData = false;
m_Overflowed = false;
m_LittleEndian = true;
}
void BitBuffer::ReadBitVec3Coord(float *fa)
{
int xflag = ReadBit();
int yflag = ReadBit();
int zflag = ReadBit();
if (xflag)
fa[0] = ReadBitCoord();
if (yflag)
fa[1] = ReadBitCoord();
if (zflag)
fa[2] = ReadBitCoord();
}
float BitBuffer::ReadBitCoord()
{
float value = 0;
int intval = ReadBit();
int fractval = ReadBit();
if (intval || fractval)
{
int signbit = ReadBit();
if (intval) {
intval = ReadBits(12);
}
if (fractval) {
fractval = ReadBits(3);
}
value = (float)(fractval / 8.0 + intval);
if (signbit) {
value = -value;
}
}
return value;
}
float BitBuffer::ReadCoord()
{
return (float)(ReadShort() * (1.0 / 8));
}
void BitBuffer::SkipBytes(int numbits)
{
if (numbits + m_CurByte - m_Data > m_MaxSize) {
m_Overflowed = true;
}
m_CurByte += numbits;
}
void BitBuffer::SkipBits(int numbits)
{
if (m_LittleEndian)
{
if (m_CurByte - m_Data >= m_MaxSize)
{
m_Overflowed = true;
return;
}
int bits = m_CurSize + numbits;
if (bits <= 32)
{
m_CurByte += numbits >> 3;
m_CurSize += numbits & 7;
if (m_CurSize > 7)
{
m_CurSize &= 7;
m_CurByte++;
}
}
else
{
m_CurByte += 4;
m_CurSize = bits & 7;
}
}
else
{
int d = numbits;
while (d > 0)
{
--d;
if (m_CurSize == 7)
{
m_CurByte++;
m_CurSize = 0;
}
else
{
m_CurSize++;
}
}
}
}
int BitBuffer::SkipString()
{
int c = 0, l = 1;
const int maxString = 8192;
while ((c = ReadChar(), c) && c != -1 && l < maxString) {
l++;
}
return l;
}
void BitBuffer::FastClear()
{
int iSize = CurrentSize() + 4;
if (iSize > m_MaxSize) {
iSize = m_MaxSize;
}
memset(m_Data, 0, iSize);
m_CurByte = m_Data;
m_CurSize = 0;
m_Overflowed = false;
m_LittleEndian = true;
}
void BitBuffer::ConcatBuffer(BitBuffer *buffer)
{
WriteBuf(buffer->m_Data, buffer->CurrentSize());
}
void BitBuffer::WriteCoord(float f)
{
WriteShort((int)(f * 8.0));
}

View File

@ -0,0 +1,117 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
class BitBuffer {
public:
BitBuffer();
BitBuffer(unsigned int size);
BitBuffer(void *newData, unsigned int size);
virtual ~BitBuffer();
unsigned int PeekBits(int numbits);
int CurrentBit();
int CurrentSize();
unsigned char *CurrentByte();
int GetMaxSize() const { return m_MaxSize; }
unsigned int GetCurSize() const { return m_CurSize; }
unsigned char *GetData() const { return m_Data; }
bool IsOverflowed() const { return m_Overflowed; }
void SetBuffer(void *buffer, int size);
void Free();
void Reset();
void Clear();
void FastClear();
int SpaceLeft();
void EndBitMode();
void StartBitMode();
bool Resize(unsigned int size);
void ConcatBuffer(BitBuffer *buffer);
int SkipString();
void SkipBits(int numbits);
void SkipBytes(int numbits);
void AlignByte();
// function's read stuff
unsigned int ReadBits(int numbits);
int ReadBit();
int ReadChar();
int ReadByte();
int ReadShort();
int ReadWord();
unsigned int ReadLong();
float ReadFloat();
char *ReadString();
char *ReadStringLine();
char *ReadBitString();
int ReadSBits(int numbits);
float ReadBitAngle(int numbits);
int ReadBitData(void *dest, int length);
bool ReadBuf(int iSize, void *pbuf);
float ReadAngle();
float ReadHiresAngle();
float ReadCoord();
float ReadBitCoord();
void ReadBitVec3Coord(float *fa);
// function's write stuff
void WriteBits(unsigned int data, int numbits);
void WriteBit(int c);
void WriteChar(int c);
void WriteByte(int c);
void WriteShort(int c);
void WriteWord(int c);
void WriteLong(unsigned int c);
void WriteFloat(float f);
void WriteString(const char *p);
void WriteBitString(const char *p);
void WriteSBits(int data, int numbits);
void WriteBitAngle(float fAngle, int numbits);
void WriteBitData(void *src, int length);
void WriteBuf(const void *buf, int iSize);
void WriteBuf(BitBuffer *buf, int length);
void WriteAngle(float f);
void WriteHiresAngle(float f);
void WriteCoord(float f);
bool m_Overflowed;
unsigned char *m_Data;
unsigned char *m_CurByte;
int m_CurSize;
int m_MaxSize;
protected:
bool m_LittleEndian;
bool m_OwnData;
};

View File

@ -0,0 +1,604 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
DemoFile::DemoFile() :
m_FileSystem(nullptr),
m_FileHandle(FILESYSTEM_INVALID_HANDLE),
m_DemoChannel(nullptr),
m_Entries(nullptr)
{
Reset();
}
void DemoFile::Init(IWorld *world, IServer *server, NetChannel *channel)
{
m_World = world;
m_Server = server;
m_System = world->GetSystem();
m_FileSystem = m_System->GetFileSystem();
m_DemoChannel = channel;
m_Entries = nullptr;
Reset();
}
void DemoFile::Reset()
{
memset(m_FileName, 0, sizeof(m_FileName));
memset(&m_zeroDemoInfo, 0, sizeof(m_zeroDemoInfo));
CloseFile();
m_Continuous = true;
}
bool DemoFile::IsRecording()
{
return m_DemoState == DEMO_RECORDING;
}
void DemoFile::CloseFile()
{
unsigned char c;
float f;
int curpos;
int i;
if (m_FileSystem && m_FileHandle != FILESYSTEM_INVALID_HANDLE)
{
if (m_DemoState == DEMO_RECORDING)
{
c = 5;
m_FileSystem->Write(&c, sizeof(unsigned char), m_FileHandle);
f = _LittleFloat(GetDemoTime());
m_FileSystem->Write(&f, sizeof(float), m_FileHandle);
i = _LittleLong(m_frameCount);
m_FileSystem->Write(&i, sizeof(int), m_FileHandle);
curpos = m_FileSystem->Tell(m_FileHandle);
m_gameEntry.nFileLength = curpos - m_gameEntry.nOffset;
m_gameEntry.fTrackTime = GetDemoTime();
m_gameEntry.nFrames = m_frameCount;
i = 2;
m_FileSystem->Write(&i, sizeof(int), m_FileHandle);
m_FileSystem->Write(&m_loadEntry, sizeof(m_loadEntry), m_FileHandle);
m_FileSystem->Write(&m_gameEntry, sizeof(m_gameEntry), m_FileHandle);
m_demoHeader.nDirectoryOffset = curpos;
m_FileSystem->Seek(m_FileHandle, 0, FILESYSTEM_SEEK_HEAD);
m_FileSystem->Write(&m_demoHeader, sizeof(m_demoHeader), m_FileHandle);
m_System->Printf("Completed demo %s.\n", m_FileName);
}
m_FileSystem->Close(m_FileHandle);
}
if (m_Entries)
{
free(m_Entries);
m_Entries = nullptr;
}
m_FileHandle = FILESYSTEM_INVALID_HANDLE;
m_DemoState = DEMO_IDLE;
}
void DemoFile::WriteDemoInfo(demo_info_t *demoInfo)
{
m_FileSystem->Write(demoInfo, sizeof(*demoInfo), m_FileHandle);
}
void DemoFile::WriteSequenceInfo()
{
m_FileSystem->Write(&m_DemoChannel->m_outgoing_sequence, sizeof(int), m_FileHandle);
m_FileSystem->Write(&m_DemoChannel->m_incoming_sequence, sizeof(int), m_FileHandle);
m_FileSystem->Write(&m_DemoChannel->m_last_reliable_sequence, sizeof(int), m_FileHandle);
m_FileSystem->Write(&m_DemoChannel->m_reliable_sequence, sizeof(int), m_FileHandle);
m_FileSystem->Write(&m_DemoChannel->m_incoming_acknowledged, sizeof(int), m_FileHandle);
m_FileSystem->Write(&m_DemoChannel->m_incoming_reliable_sequence, sizeof(int), m_FileHandle);
m_FileSystem->Write(&m_DemoChannel->m_incoming_reliable_acknowledged, sizeof(int), m_FileHandle);
}
void DemoFile::WriteDemoStartup(BitBuffer *buffer)
{
unsigned char c;
int i;
float f;
int len = buffer->CurrentSize();
if (len <= 0) {
return;
}
c = 0;
m_FileSystem->Write(&c, sizeof(unsigned char), m_FileHandle);
f = _LittleFloat(GetDemoTime());
m_FileSystem->Write(&f, sizeof(float), m_FileHandle);
i = _LittleLong(m_frameCount);
m_FileSystem->Write(&i, sizeof(int), m_FileHandle);
WriteDemoInfo(&m_zeroDemoInfo);
WriteSequenceInfo();
i = _LittleLong(len);
m_FileSystem->Write(&i, sizeof(int), m_FileHandle);
m_FileSystem->Write(buffer->GetData(), len, m_FileHandle);
}
void DemoFile::WriteDemoMessage(BitBuffer *unreliableData, BitBuffer *reliableData)
{
int len;
int i;
float f;
unsigned char c;
len = reliableData->CurrentSize() + unreliableData->CurrentSize();
if (len <= 0 || m_FileHandle == FILESYSTEM_INVALID_HANDLE) {
return;
}
if (!m_FileSystem) {
return;
}
c = 1;
m_frameCount++;
m_FileSystem->Write(&c, sizeof(unsigned char), m_FileHandle);
f = _LittleFloat(GetDemoTime());
m_FileSystem->Write(&f, sizeof(float), m_FileHandle);
i = _LittleLong(m_frameCount);
m_FileSystem->Write(&i, sizeof(int), m_FileHandle);
WriteDemoInfo(&m_zeroDemoInfo);
WriteSequenceInfo();
i = _LittleLong(len);
m_FileSystem->Write(&i, sizeof(int), m_FileHandle);
m_FileSystem->Write(unreliableData->GetData(), unreliableData->CurrentSize(), m_FileHandle);
m_FileSystem->Write(reliableData->GetData(), reliableData->CurrentSize(), m_FileHandle);
}
void DemoFile::WriteUpdateClientData(client_data_t *cdata)
{
if (!m_FileSystem || m_FileHandle == FILESYSTEM_INVALID_HANDLE) {
return;
}
unsigned char cmd = 4;
m_FileSystem->Write(&cmd, sizeof(unsigned char), m_FileHandle);
float f = _LittleFloat(GetDemoTime());
m_FileSystem->Write(&f, sizeof(float), m_FileHandle);
int i = _LittleLong(m_frameCount);
m_FileSystem->Write(&i, sizeof(int), m_FileHandle);
m_FileSystem->Write(cdata, sizeof(*cdata), m_FileHandle);
}
float DemoFile::GetDemoTime()
{
return m_System->GetTime() - m_startTime;
}
void DemoFile::WriteSignonData()
{
BitBuffer buffer(MAX_POSSIBLE_MSG * 2);
m_World->WriteNewData(&buffer);
m_World->WriteSigonData(&buffer);
buffer.WriteByte(svc_time);
buffer.WriteFloat(GetDemoTime());
for (int i = 0; i < m_World->GetMaxClients(); i++) {
m_World->WriteClientUpdate(&buffer, i);
}
m_World->WriteLightStyles(&buffer);
buffer.WriteByte(svc_signonnum);
buffer.WriteByte(1);
WriteDemoStartup(&buffer);
}
bool DemoFile::StartRecording(char *newName)
{
unsigned char b;
int i;
float f;
if (IsPlaying() || !m_FileSystem) {
return false;
}
if (m_FileHandle != FILESYSTEM_INVALID_HANDLE) {
CloseFile();
}
strcopy(m_FileName, newName);
m_FileHandle = m_FileSystem->Open(m_FileName, "wb");
if (!m_FileHandle) {
m_System->Printf("WARNING! DemoFile::StartRecording: coudn't open demo file %s.\n", m_FileName);
return false;
}
memset(&m_demoHeader, 0, sizeof(m_demoHeader));
strcopy(m_demoHeader.szFileStamp, "HLDEMO");
COM_FileBase(m_World->GetLevelName(), m_demoHeader.szMapName);
COM_FileBase(m_World->GetGameDir(), m_demoHeader.szDllDir);
m_demoHeader.mapCRC = 0;
m_demoHeader.nDemoProtocol = DEMO_VERSION;
m_demoHeader.nNetProtocolVersion = PROTOCOL_VERSION;
m_demoHeader.nDirectoryOffset = 0;
m_FileSystem->Write(&m_demoHeader, sizeof(m_demoHeader), m_FileHandle);
memset(&m_loadEntry, 0, sizeof(m_loadEntry));
strcopy(m_loadEntry.szDescription, "LOADING");
m_loadEntry.nEntryType = 0;
m_loadEntry.nOffset = m_FileSystem->Tell(m_FileHandle);
m_frameCount = 0;
m_startTime = m_System->GetTime();
WriteSignonData();
b = 5;
m_FileSystem->Write(&b, sizeof(unsigned char), m_FileHandle);
f = _LittleFloat(GetDemoTime());
m_FileSystem->Write(&f, sizeof(float), m_FileHandle);
i = _LittleLong(m_frameCount);
m_FileSystem->Write(&i, sizeof(int), m_FileHandle);
m_loadEntry.nFileLength = m_FileSystem->Tell(m_FileHandle) - m_loadEntry.nOffset;
memset(&m_gameEntry, 0, sizeof(m_gameEntry));
_snprintf(m_gameEntry.szDescription, sizeof(m_gameEntry.szDescription), "Playback");
m_gameEntry.nEntryType = 1;
m_gameEntry.nOffset = m_FileSystem->Tell(m_FileHandle);
b = 2;
m_FileSystem->Write(&b, sizeof(unsigned char), m_FileHandle);
f = _LittleFloat(GetDemoTime());
m_FileSystem->Write(&f, sizeof(float), m_FileHandle);
i = _LittleLong(m_frameCount);
m_FileSystem->Write(&i, sizeof(int), m_FileHandle);
m_DemoState = DEMO_RECORDING;
m_System->Printf("Start recording to %s.\n", m_FileName);
return true;
}
bool DemoFile::IsPlaying()
{
return m_DemoState == DEMO_PLAYING;
}
bool DemoFile::LoadDemo(char *demoname)
{
if (IsRecording()) {
m_System->Printf("Cannot load demo, still recording.\n");
return false;
}
if (!m_FileSystem) {
return false;
}
CloseFile();
strcopy(m_FileName, demoname);
_strlwr(m_FileName);
if (!strstr(m_FileName, ".dem")) {
strcat(m_FileName, ".dem");
}
m_FileHandle = m_FileSystem->Open(m_FileName, "rb");
if (!m_FileHandle) {
m_System->Printf("Coudn't open demo file %s.\n", m_FileName);
return false;
}
memset(&m_demoHeader, 0, sizeof(m_demoHeader));
m_FileSystem->Read(&m_demoHeader, sizeof(m_demoHeader), m_FileHandle);
if (strcmp(m_demoHeader.szFileStamp, "HLDEMO") != 0) {
m_System->Printf("%s is not a HL demo file.\n", m_FileName);
m_FileSystem->Close(m_FileHandle);
return false;
}
if (m_demoHeader.nNetProtocolVersion != PROTOCOL_VERSION || m_demoHeader.nDemoProtocol != DEMO_VERSION) {
m_System->Printf("WARNING! %s has an outdated demo format.\n", m_FileName);
}
int fileMarker = m_FileSystem->Tell(m_FileHandle);
m_FileSystem->Seek(m_FileHandle, m_demoHeader.nDirectoryOffset, FILESYSTEM_SEEK_HEAD);
m_FileSystem->Read(&m_EntryNumber, sizeof(int), m_FileHandle);
m_CurrentEntry = 0;
if (m_EntryNumber > 0 && m_EntryNumber <= 1024)
{
m_Entries = (demoentry_t *)Mem_ZeroMalloc(m_EntryNumber * MAX_DEMO_ENTRY);
m_FileSystem->Read(m_Entries, m_EntryNumber * MAX_DEMO_ENTRY, m_FileHandle);
m_FileSystem->Seek(m_FileHandle, m_Entries[m_CurrentEntry].nOffset, FILESYSTEM_SEEK_HEAD);
}
else
{
m_EntryNumber = 2;
m_Entries = nullptr;
m_System->Printf("WARNING! Demo had bogus number of directory entries!\n");
m_FileSystem->Seek(m_FileHandle, fileMarker, FILESYSTEM_SEEK_HEAD);
}
m_startTime = m_System->GetTime();
m_nextReadTime = m_System->GetTime();
m_Continuous = true;
memset(&m_ServerInfo, 0, sizeof(m_ServerInfo));
strcopy(m_ServerInfo.address, m_DemoChannel->m_remote_address.ToBaseString());
strcopy(m_ServerInfo.name, m_FileName);
strcopy(m_ServerInfo.map, m_demoHeader.szMapName);
strcopy(m_ServerInfo.gamedir, m_demoHeader.szDllDir);
strcopy(m_ServerInfo.description, "Demo Playback");
m_ServerInfo.activePlayers = 0;
m_ServerInfo.maxPlayers = MAX_CLIENTS;
m_ServerInfo.protocol = m_demoHeader.nNetProtocolVersion;
m_ServerInfo.type = GetServerType(HLST_Dedicated)[0];
m_ServerInfo.os = GetServerOS()[0];
m_ServerInfo.pw = '\0';
m_ServerInfo.mod = false;
m_DemoState = DEMO_PLAYING;
return true;
}
void DemoFile::StopPlayBack()
{
if (m_DemoState != DEMO_PLAYING) {
return;
}
CloseFile();
if (m_Server) {
m_Server->Disconnect();
}
}
void DemoFile::ReadDemoPacket(BitBuffer *demoData, demo_info_t *demoInfo)
{
if (!m_FileHandle || (m_nextReadTime > m_System->GetTime() && m_Continuous)) {
return;
}
int msglen;
unsigned char msgbuf[MAX_POSSIBLE_MSG];
float time;
unsigned char cmd;
int frame;
int channel;
int sampleSize;
bool readNextCmd = true;
while (readNextCmd)
{
unsigned int curpos = m_FileSystem->Tell(m_FileHandle);
if (m_FileSystem->Read(&cmd, sizeof(unsigned char), m_FileHandle) != 1) {
StopPlayBack();
return;
}
m_FileSystem->Read(&time, sizeof(float), m_FileHandle);
time = _LittleFloat(time);
m_FileSystem->Read(&frame, sizeof(int), m_FileHandle);
frame = _LittleLong(frame);
if (cmd && cmd != 5) {
m_nextReadTime = m_startTime + time;
}
if (m_nextReadTime > m_System->GetTime() && m_Continuous) {
m_FileSystem->Seek(m_FileHandle, curpos, FILESYSTEM_SEEK_HEAD);
return;
}
msglen = 0;
// TODO: Find out or guess the names of the opcode
switch (cmd)
{
case 2:
m_startTime = (float)m_System->GetTime();
break;
case 3:
msglen = 64;
break;
case 4:
msglen = 32;
break;
case 5:
{
if (++m_CurrentEntry >= m_EntryNumber) {
StopPlayBack();
return;
}
if (m_Entries) {
m_FileSystem->Seek(m_FileHandle, m_Entries[m_CurrentEntry].nOffset, FILESYSTEM_SEEK_HEAD);
}
break;
}
case 6:
msglen = 84;
break;
case 7:
msglen = 8;
break;
case 8:
{
m_FileSystem->Read(&channel, sizeof(int), m_FileHandle);
channel = _LittleLong(channel);
m_FileSystem->Read(&sampleSize, sizeof(int), m_FileHandle);
sampleSize = _LittleLong(sampleSize);
msglen = sampleSize + 16;
break;
}
case 9:
{
m_FileSystem->Read(&msglen, sizeof(int), m_FileHandle);
msglen = _LittleLong(msglen);
break;
}
default:
readNextCmd = false;
break;
}
if (msglen)
{
m_FileSystem->Read(msgbuf, msglen, m_FileHandle);
demoData->WriteByte(cmd);
switch (cmd)
{
case 8:
demoData->WriteLong(channel);
demoData->WriteLong(sampleSize);
break;
case 9:
demoData->WriteLong(msglen);
break;
}
demoData->WriteBuf(msgbuf, msglen);
}
}
ReadDemoInfo(demoInfo);
ReadSequenceInfo();
int length;
if (m_FileSystem->Read(&length, sizeof(int), m_FileHandle) != 4) {
m_System->DPrintf("WARNING! DemoFile::ReadDemoPacket: Bad demo length.\n");
StopPlayBack();
return;
}
length = _LittleLong(length);
if (length < 0) {
m_System->DPrintf("WARNING! DemoFile::ReadDemoPacket: Demo message length < 0.\n");
StopPlayBack();
return;
}
if (length > MAX_POSSIBLE_MSG) {
m_System->DPrintf("WARNING! DemoFile::ReadDemoPacket: message length > MAX_POSSIBLE_MSG\n");
StopPlayBack();
return;
}
if (length > 0)
{
if (m_FileSystem->Read(msgbuf, length, m_FileHandle) != length) {
m_System->DPrintf("WARNING! DemoFile::ReadDemoPacket: Error reading demo message data.\n");
StopPlayBack();
return;
}
NetPacket *p = new NetPacket;
p->connectionless = false;
p->time = m_System->GetTime();
p->seqnr = m_DemoChannel->m_incoming_sequence;
p->data.Resize(length);
p->data.WriteBuf(msgbuf, length);
p->data.Reset();
m_DemoChannel->m_incomingPackets.AddHead(p);
}
}
void DemoFile::ReadDemoInfo(demo_info_t *demoInfo)
{
m_FileSystem->Read(demoInfo, sizeof(*demoInfo), m_FileHandle);
demoInfo->rp.cmd = &demoInfo->cmd;
demoInfo->rp.movevars = &demoInfo->movevars;
}
void DemoFile::ReadSequenceInfo()
{
m_FileSystem->Read(&m_DemoChannel->m_incoming_sequence, sizeof(int), m_FileHandle);
m_FileSystem->Read(&m_DemoChannel->m_incoming_acknowledged, sizeof(int), m_FileHandle);
m_FileSystem->Read(&m_DemoChannel->m_incoming_reliable_acknowledged, sizeof(int), m_FileHandle);
m_FileSystem->Read(&m_DemoChannel->m_incoming_reliable_sequence, sizeof(int), m_FileHandle);
m_FileSystem->Read(&m_DemoChannel->m_outgoing_sequence, sizeof(int), m_FileHandle);
m_FileSystem->Read(&m_DemoChannel->m_reliable_sequence, sizeof(int), m_FileHandle);
m_FileSystem->Read(&m_DemoChannel->m_last_reliable_sequence, sizeof(int), m_FileHandle);
}
char *DemoFile::GetFileName()
{
return m_FileName;
}
bool DemoFile::IsContinuous()
{
return m_Continuous;
}
void DemoFile::SetContinuous(bool state)
{
m_Continuous = state;
}

View File

@ -0,0 +1,135 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include <HLTV/IWorld.h>
#include <HLTV/IServer.h>
#include "usercmd.h"
#include "ref_params.h"
#include "common/ServerInfo.h"
#include "vmodes.h"
#include "cdll_int.h"
#define DEMO_VERSION 5
#define MAX_DEMO_ENTRY 92
typedef struct demoheader_s {
char szFileStamp[6];
int nDemoProtocol;
int nNetProtocolVersion;
char szMapName[260];
char szDllDir[260];
CRC32_t mapCRC;
int nDirectoryOffset;
} demoheader_t;
typedef struct demoentry_s {
int nEntryType;
char szDescription[64];
int nFlags;
int nCDTrack;
float fTrackTime;
int nFrames;
int nOffset;
int nFileLength;
} demoentry_t;
typedef struct demo_info_s {
float timestamp;
ref_params_t rp;
usercmd_t cmd;
movevars_t movevars;
vec3_t view;
int viewmodel;
} demo_info_t;
class NetChannel;
class DemoFile {
public:
DemoFile();
virtual ~DemoFile() {}
void Init(IWorld *world, IServer *server, NetChannel *channel);
bool LoadDemo(char *demoname);
void StopPlayBack();
bool StartRecording(char *newName);
void CloseFile();
void Reset();
void SetContinuous(bool state);
bool IsContinuous();
bool IsPlaying();
bool IsRecording();
char *GetFileName();
void ReadDemoPacket(BitBuffer *demoData, demo_info_t *demoInfo);
void WriteDemoMessage(BitBuffer *unreliableData, BitBuffer *reliableData);
void WriteUpdateClientData(client_data_t *cdata);
float GetDemoTime();
void ReadSequenceInfo();
void ReadDemoInfo(demo_info_t *demoInfo);
void WriteDemoStartup(BitBuffer *buffer);
void WriteSequenceInfo();
void WriteDemoInfo(demo_info_t *demoInfo);
void WriteSignonData();
serverinfo_t m_ServerInfo;
private:
char m_FileName[MAX_PATH];
enum DemoState {
DEMO_IDLE,
DEMO_PLAYING,
DEMO_RECORDING
};
int m_DemoState;
unsigned int m_frameCount;
FileHandle_t m_FileHandle;
demoheader_t m_demoHeader;
demoentry_t m_loadEntry;
demoentry_t m_gameEntry;
demo_info_t m_zeroDemoInfo;
float m_startTime;
float m_nextReadTime;
NetChannel *m_DemoChannel;
int m_StartPos;
int m_EntryNumber;
int m_CurrentEntry;
demoentry_t *m_Entries;
bool m_Continuous;
IBaseSystem *m_System;
IWorld *m_World;
IServer *m_Server;
IFileSystem *m_FileSystem;
};

View File

@ -0,0 +1,683 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
// define DRC_CMD_*
char *DirectorCmd::m_CMD_Name[] =
{
"NONE",
"START",
"EVENT",
"MODE",
"CAMERA",
"TIMESCALE",
"MESSAGE",
"SOUND",
"STATUS",
"BANNER",
"STUFFTEXT",
"CHASE",
"INEYE",
"MAP",
"CAMPATH",
"WAYPOINTS"
};
DirectorCmd::DirectorCmd()
{
Clear();
}
DirectorCmd::~DirectorCmd()
{
Clear();
}
bool DirectorCmd::GetEventData(int &entity1, int &entity2, int &flags)
{
if (m_Type != DRC_CMD_EVENT) {
return false;
}
m_Data.Reset();
entity1 = m_Data.ReadWord();
entity2 = m_Data.ReadWord();
flags = m_Data.ReadLong();
return true;
}
bool DirectorCmd::GetModeData(int &mode)
{
if (m_Type != DRC_CMD_MODE) {
return false;
}
m_Data.Reset();
mode = m_Data.ReadByte();
return true;
}
bool DirectorCmd::GetChaseData(int &entity1, int &entity2, float &distance, int &flags)
{
if (m_Type != DRC_CMD_CHASE) {
return false;
}
m_Data.Reset();
entity1 = m_Data.ReadByte();
entity2 = m_Data.ReadByte();
distance = m_Data.ReadFloat();
flags = m_Data.ReadByte();
return true;
}
bool DirectorCmd::GetInEyeData(int &player)
{
if (m_Type != DRC_CMD_INEYE) {
return false;
}
m_Data.Reset();
player = m_Data.ReadByte();
return true;
}
bool DirectorCmd::GetMapData(int &entity, float &angle, float &distance)
{
if (m_Type != DRC_CMD_MAP) {
return false;
}
m_Data.Reset();
entity = m_Data.ReadByte();
angle = m_Data.ReadFloat();
distance = m_Data.ReadFloat();
return true;
}
bool DirectorCmd::GetCameraData(vec_t *position, vec_t *angles, float &fov, int &entity)
{
if (m_Type != DRC_CMD_CAMERA) {
return false;
}
m_Data.Reset();
position[0] = m_Data.ReadCoord();
position[1] = m_Data.ReadCoord();
position[2] = m_Data.ReadCoord();
angles[0] = m_Data.ReadCoord();
angles[1] = m_Data.ReadCoord();
angles[2] = m_Data.ReadCoord();
fov = (float)m_Data.ReadByte();
entity = m_Data.ReadWord();
return true;
}
bool DirectorCmd::GetCamPathData(vec_t *position, vec_t *angles, float &fov, int &flags)
{
if (m_Type != DRC_CMD_CAMPATH) {
return false;
}
m_Data.Reset();
position[0] = m_Data.ReadCoord();
position[1] = m_Data.ReadCoord();
position[2] = m_Data.ReadCoord();
angles[0] = m_Data.ReadCoord();
angles[1] = m_Data.ReadCoord();
angles[2] = m_Data.ReadCoord();
fov = (float)m_Data.ReadByte();
flags = m_Data.ReadByte();
return true;
}
bool DirectorCmd::GetSoundData(char *name, float &volume)
{
if (m_Type != DRC_CMD_SOUND) {
return false;
}
m_Data.Reset();
strcpy(name, m_Data.ReadString());
volume = m_Data.ReadFloat();
return true;
}
float DirectorCmd::GetTime()
{
return m_Time;
}
int DirectorCmd::GetType()
{
return m_Type;
}
char *DirectorCmd::GetName()
{
return m_CMD_Name[m_Type];
}
bool DirectorCmd::GetTimeScaleData(float &factor)
{
if (m_Type != DRC_CMD_TIMESCALE) {
return false;
}
m_Data.Reset();
factor = m_Data.ReadFloat();
return true;
}
bool DirectorCmd::GetWayPointsData(int &number)
{
if (m_Type != DRC_CMD_WAYPOINTS) {
return false;
}
m_Data.Reset();
number = m_Data.ReadByte();
return true;
}
bool DirectorCmd::GetMessageData(int &effect, int &color, vec_t *position, float &fadein, float &fadeout, float &holdtime, float &fxtime, char *text)
{
if (m_Type != DRC_CMD_MESSAGE) {
return false;
}
m_Data.Reset();
effect = m_Data.ReadByte();
color = m_Data.ReadLong();
position[0] = m_Data.ReadFloat();
position[1] = m_Data.ReadFloat();
fadein = m_Data.ReadFloat();
fadeout = m_Data.ReadFloat();
holdtime = m_Data.ReadFloat();
fxtime = m_Data.ReadFloat();
strcpy(text, m_Data.ReadString());
return true;
}
bool DirectorCmd::GetStatusData(int &slots, int &spectators, int &proxies)
{
if (m_Type != DRC_CMD_STATUS) {
return false;
}
m_Data.Reset();
slots = m_Data.ReadLong();
spectators = m_Data.ReadLong();
proxies = m_Data.ReadWord();
return true;
}
bool DirectorCmd::GetBannerData(char *filename)
{
if (m_Type != DRC_CMD_BANNER) {
return false;
}
m_Data.Reset();
strcpy(filename, m_Data.ReadString());
return true;
}
bool DirectorCmd::GetStuffTextData(char *commands)
{
if (m_Type != DRC_CMD_STUFFTEXT) {
return false;
}
m_Data.Reset();
strcpy(commands, m_Data.ReadString());
return true;
}
void DirectorCmd::SetEventData(int entity1, int entity2, int flags)
{
m_Type = DRC_CMD_EVENT;
Resize(8);
m_Data.WriteWord(entity1);
m_Data.WriteWord(entity2);
m_Data.WriteLong(flags);
}
void DirectorCmd::SetChaseData(int entity1, int entity2, float distance, int flags)
{
m_Type = DRC_CMD_CHASE;
Resize(9);
m_Data.WriteWord(entity1);
m_Data.WriteWord(entity2);
m_Data.WriteFloat(distance);
m_Data.WriteByte(flags);
}
void DirectorCmd::SetInEyeData(int entity)
{
m_Type = DRC_CMD_INEYE;
Resize(2);
m_Data.WriteWord(entity);
}
void DirectorCmd::SetMapData(int entity, float angle, float distance)
{
m_Type = DRC_CMD_MAP;
Resize(10);
m_Data.WriteWord(entity);
m_Data.WriteFloat(angle);
m_Data.WriteFloat(distance);
}
void DirectorCmd::SetStartData()
{
m_Type = DRC_CMD_START;
Resize(0);
}
void DirectorCmd::SetModeData(int mode)
{
m_Type = DRC_CMD_MODE;
Resize(1);
m_Data.WriteByte(mode);
}
void DirectorCmd::SetCameraData(vec_t *position, vec_t *angles, float fov, int entity)
{
m_Type = DRC_CMD_CAMERA;
Resize(15);
m_Data.WriteCoord(position[0]);
m_Data.WriteCoord(position[1]);
m_Data.WriteCoord(position[2]);
m_Data.WriteCoord(angles[0]);
m_Data.WriteCoord(angles[1]);
m_Data.WriteCoord(angles[2]);
m_Data.WriteByte((int)fov);
m_Data.WriteWord(entity);
}
void DirectorCmd::SetCamPathData(vec_t *position, vec_t *angles, float fov, int flags)
{
m_Type = DRC_CMD_CAMPATH;
Resize(14);
m_Data.WriteCoord(position[0]);
m_Data.WriteCoord(position[1]);
m_Data.WriteCoord(position[2]);
m_Data.WriteCoord(angles[0]);
m_Data.WriteCoord(angles[1]);
m_Data.WriteCoord(angles[2]);
m_Data.WriteByte((int)fov);
m_Data.WriteByte(flags);
}
void DirectorCmd::SetSoundData(char *name, float volume)
{
int len = strlen(name);
m_Type = DRC_CMD_SOUND;
Resize(len + 5);
m_Data.WriteString(name);
m_Data.WriteFloat(volume);
}
void DirectorCmd::SetTimeScaleData(float factor)
{
m_Type = DRC_CMD_TIMESCALE;
Resize(sizeof(float));
m_Data.WriteFloat(factor);
}
void DirectorCmd::SetTime(float time)
{
m_Time = time;
}
void DirectorCmd::SetMessageData(int effect, unsigned int color, vec_t *position, float fadein, float fadeout, float holdtime, float fxtime, char *text)
{
int len = strlen(text);
m_Type = DRC_CMD_MESSAGE;
Resize(len + 30);
m_Data.WriteByte(effect);
m_Data.WriteLong(color);
m_Data.WriteFloat(position[0]);
m_Data.WriteFloat(position[1]);
m_Data.WriteFloat(fadein);
m_Data.WriteFloat(fadeout);
m_Data.WriteFloat(holdtime);
m_Data.WriteFloat(fxtime);
m_Data.WriteString(text);
}
void DirectorCmd::Copy(DirectorCmd *cmd)
{
Clear();
m_Time = cmd->m_Time;
m_Type = cmd->m_Type;
m_Size = cmd->m_Size;
m_Index = cmd->m_Index;
m_Data.Resize(m_Size);
m_Data.WriteBuf(cmd->m_Data.GetData(), m_Size);
}
void DirectorCmd::SetStatusData(int slots, int spectators, int proxies)
{
m_Type = DRC_CMD_STATUS;
Resize(10);
m_Data.WriteLong(slots);
m_Data.WriteLong(spectators);
m_Data.WriteWord(proxies);
}
void DirectorCmd::SetBannerData(char *filename)
{
m_Type = DRC_CMD_BANNER;
int len = strlen(filename);
Resize(len + 1);
m_Data.WriteString(filename);
}
void DirectorCmd::SetStuffTextData(char *commands)
{
m_Type = DRC_CMD_STUFFTEXT;
int len = strlen(commands);
Resize(len + 1);
m_Data.WriteString(commands);
}
void DirectorCmd::SetWayPoints(int number)
{
m_Type = DRC_CMD_WAYPOINTS;
Resize(1);
m_Data.WriteByte(number);
}
bool DirectorCmd::ReadFromStream(BitBuffer *stream)
{
char *string;
unsigned char *start;
int length;
if (!stream) {
return false;
}
Clear();
m_Type = stream->ReadByte();
switch (m_Type)
{
case DRC_CMD_START:
Resize(0);
break;
case DRC_CMD_EVENT:
Resize(8);
m_Data.WriteBuf(stream, 8);
break;
case DRC_CMD_MODE:
Resize(1);
m_Data.WriteBuf(stream, 1);
break;
case DRC_CMD_CAMERA:
Resize(15);
m_Data.WriteBuf(stream, 15);
break;
case DRC_CMD_TIMESCALE:
Resize(4);
m_Data.WriteBuf(stream, 4);
break;
case DRC_CMD_MESSAGE:
{
start = stream->m_CurByte;
stream->SkipBytes(29);
string = stream->ReadString();
length = strlen(string);
Resize(length + 30);
m_Data.WriteBuf(start, 29);
m_Data.WriteBuf(string, length + 1);
break;
}
case DRC_CMD_SOUND:
{
string = stream->ReadString();
length = strlen(string);
Resize(length + 5);
m_Data.WriteBuf(string, length + 1);
m_Data.WriteFloat(stream->ReadFloat());
break;
}
case DRC_CMD_STATUS:
Resize(10);
m_Data.WriteBuf(stream, 10);
break;
case DRC_CMD_BANNER:
{
string = stream->ReadString();
length = strlen(string) + 1;
Resize(length);
m_Data.WriteBuf(string, length);
break;
}
case DRC_CMD_STUFFTEXT:
{
string = stream->ReadString();
length = strlen(string) + 1;
Resize(length);
m_Data.WriteBuf(string, length);
break;
}
case DRC_CMD_CHASE:
Resize(7);
m_Data.WriteBuf(stream, 7);
break;
case DRC_CMD_INEYE:
Resize(1);
m_Data.WriteBuf(stream, 1);
break;
case DRC_CMD_MAP:
Resize(10);
m_Data.WriteBuf(stream, 15);
break;
case DRC_CMD_CAMPATH:
Resize(14);
m_Data.WriteBuf(stream, 14);
break;
case DRC_CMD_WAYPOINTS:
{
Resize(1);
length = stream->ReadByte();
m_Data.WriteByte(length);
stream->SkipBytes(length * 14);
break;
}
default:
case DRC_CMD_NONE:
return false;
}
return true;
}
void DirectorCmd::WriteToStream(BitBuffer *stream)
{
if (!stream) {
return;
}
if ((m_Type > DRC_CMD_NONE && m_Type <= DRC_CMD_LAST) && m_Size < 255)
{
stream->WriteByte(svc_director);
stream->WriteByte(m_Size + 1);
stream->WriteByte(m_Type);
stream->WriteBuf(m_Data.GetData(), m_Size);
}
}
char *DirectorCmd::ToString()
{
int i1, i2, i3;
float f1, f2, f3, f4;
vec3_t v1, v2;
char *t1 = m_CMD_Name[m_Type];
char t2[1024];
static char s[1024];
memset(s, 0, sizeof(s));
switch (m_Type)
{
case DRC_CMD_START:
sprintf(s, "%s", t1);
break;
case DRC_CMD_EVENT:
GetEventData(i1, i2, i3);
sprintf(s, "%s %i %i %i", t1, i1, i2, i3);
break;
case DRC_CMD_MODE:
GetModeData(i1);
sprintf(s, "%s %i", t1, i1);
break;
case DRC_CMD_CAMERA:
GetCameraData(v1, v2, f1, i1);
sprintf(s, "%s (%.1f %.1f %.1f) (%.1f %.1f %.1f) %.1f %i", t1, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], f1, i1);
break;
case DRC_CMD_TIMESCALE:
GetTimeScaleData(f1);
sprintf(s, "%s %.2f", t1, f1);
break;
case DRC_CMD_MESSAGE:
GetMessageData(i1, i2, v1, f1, f2, f3, f4, t2);
sprintf(s, "%s \"%s\" %i %x (%.2f %.2f) %.1f, %.1f %.1f %.1f", t1, t2, i1, i2, v1[0], v1[1], f1, f2, f3, f4);
break;
case DRC_CMD_SOUND:
GetSoundData(t2, f1);
sprintf(s, "%s \"%s\" %.2f", t1, t2, f1);
break;
case DRC_CMD_STATUS:
GetStatusData(i1, i2, i3);
sprintf(s, "%s %i %i %i", t1, i1, i2, i3);
break;
case DRC_CMD_BANNER:
GetBannerData(t2);
sprintf(s, "%s \"%s\"", t1, t2);
break;
case DRC_CMD_STUFFTEXT:
GetStuffTextData(t2);
sprintf(s, "%s \"%s\"", t1, t2);
break;
case DRC_CMD_CHASE:
GetChaseData(i1, i2, f1, i3);
sprintf(s, "%s %i %i %.1f %i", t1, i1, i2, f1, i3);
break;
case DRC_CMD_INEYE:
GetInEyeData(i1);
sprintf(s, "%s %i", t1, i1);
break;
case DRC_CMD_MAP:
GetMapData(i1, f1, f2);
sprintf(s, "%s %i %.1f %.1f", t1, i1, f1, f2);
break;
case DRC_CMD_CAMPATH:
GetCamPathData(v1, v2, f1, i1);
sprintf(s, "%s (%.1f %.1f %.1f) (%.1f %.1f %.1f) %.1f %i", t1, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], f1, i1);
break;
case DRC_CMD_WAYPOINTS:
GetWayPointsData(i1);
sprintf(s, "%s %i", t1, i1);
break;
default:
case DRC_CMD_NONE:
return nullptr;
}
return s;
}
void DirectorCmd::FromString(char *string)
{
;
}
void DirectorCmd::Clear()
{
m_Type = 0;
m_Time = 0;
m_Data.Free();
}
void DirectorCmd::Resize(int size)
{
m_Data.Resize(size);
m_Size = size;
}

View File

@ -0,0 +1,89 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "hltv.h"
#include "BitBuffer.h"
class DirectorCmd {
public:
DirectorCmd();
virtual ~DirectorCmd();
void Clear();
void Copy(DirectorCmd *cmd);
void Resize(int size);
void FromString(char *string);
char *ToString();
void WriteToStream(BitBuffer *stream);
bool ReadFromStream(BitBuffer *stream);
int GetType();
char *GetName();
float GetTime();
void SetTime(float time);
void SetStartData();
void SetEventData(int entity1, int entity2, int flags);
void SetChaseData(int entity1, int entity2, float distance, int flags);
void SetModeData(int mode);
void SetInEyeData(int entity);
void SetMapData(int entity, float angle, float distance);
void SetCameraData(vec_t *position, vec_t *angles, float fov, int entity);
void SetCamPathData(vec_t *position, vec_t *angles, float fov, int flags);
void SetTimeScaleData(float factor);
void SetMessageData(int effect, unsigned int color, vec_t *position, float fadein, float fadeout, float holdtime, float fxtime, char *text);
void SetSoundData(char *name, float volume);
void SetStatusData(int slots, int spectators, int proxies);
void SetBannerData(char *filename);
void SetStuffTextData(char *commands);
void SetWayPoints(int number);
bool GetEventData(int &entity1, int &entity2, int &flags);
bool GetChaseData(int &entity1, int &entity2, float &distance, int &flags);
bool GetInEyeData(int &player);
bool GetMapData(int &entity, float &angle, float &distance);
bool GetCameraData(vec_t *position, vec_t *angles, float &fov, int &entity);
bool GetCamPathData(vec_t *position, vec_t *angles, float &fov, int &flags);
bool GetTimeScaleData(float &factor);
bool GetMessageData(int &effect, int &color, vec_t *position, float &fadein, float &fadeout, float &holdtime, float &fxtime, char *text);
bool GetSoundData(char *name, float &volume);
bool GetModeData(int &mode);
bool GetStatusData(int &slots, int &spectators, int &proxies);
bool GetBannerData(char *filename);
bool GetStuffTextData(char *commands);
bool GetWayPointsData(int &number);
public:
static char *m_CMD_Name[];
float m_Time;
int m_Type;
int m_Size;
BitBuffer m_Data;
int m_Index;
};

View File

@ -0,0 +1,431 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
InfoString::InfoString(char *string, unsigned int maxSize)
: m_String(nullptr), m_MaxSize(0)
{
unsigned int len = strlen(string) + 1;
if (len < maxSize) {
len = maxSize;
}
SetMaxSize(len);
SetString(string);
}
InfoString::InfoString()
: m_String(nullptr), m_MaxSize(0)
{
}
InfoString::InfoString(unsigned int maxSize)
: m_String(nullptr), m_MaxSize(0)
{
SetMaxSize(maxSize);
}
InfoString::InfoString(char *string)
: m_String(nullptr), m_MaxSize(0)
{
unsigned int len = strlen(string) + 1;
if (len < MAX_INFO_LEN) {
len = MAX_INFO_LEN;
}
SetMaxSize(len);
SetString(string);
}
InfoString::~InfoString()
{
if (m_String) {
free(m_String);
m_String = nullptr;
}
}
bool InfoString::SetString(char *string)
{
if (!m_String || !string) {
return false;
}
if (strlen(string) >= m_MaxSize) {
return false;
}
strncpy(m_String, string, m_MaxSize - 1);
m_String[m_MaxSize - 1] = '\0';
return true;
}
void InfoString::SetMaxSize(unsigned int maxSize)
{
char *newBuffer = (char *)Mem_ZeroMalloc(maxSize);
if (!newBuffer) {
return;
}
if (m_String)
{
if (maxSize > strlen(m_String)) {
strncpy(newBuffer, m_String, maxSize - 1);
newBuffer[maxSize - 1] = '\0';
}
free(m_String);
}
m_MaxSize = maxSize;
m_String = newBuffer;
}
int InfoString::GetMaxSize()
{
return m_MaxSize;
}
int InfoString::GetCurrentSize()
{
return strlen(m_String);
}
void InfoString::Clear()
{
if (m_String) {
memset(m_String, 0, m_MaxSize);
}
}
char *InfoString::GetString()
{
return m_String;
}
// Searches the string for the given key and returns the associated value, or an empty string.
char *InfoString::ValueForKey(const char *key)
{
// use two buffers so compares work without stomping on each other
static char value[MAX_INFO_VALUES][MAX_INFO_VALUE];
static int valueindex;
char pkey[MAX_INFO_KEY];
char *c;
char *s = m_String;
int nCount;
while (*s)
{
if (*s == '\\') {
// skip the slash
s++;
}
// Copy a key
nCount = 0;
c = pkey;
while (*s != '\\')
{
if (!*s)
{
// key should end with a \, not a nullptr, but suppose its value as absent
return "";
}
if (nCount >= MAX_INFO_KEY)
{
s++;
// skip oversized key chars till the slash or EOL
continue;
}
*c++ = *s++;
nCount++;
}
*c = '\0';
// skip the slash
s++;
// Copy a value
nCount = 0;
c = value[valueindex];
while (*s != '\\')
{
if (!*s)
{
// allow value to be ended with nullptr
break;
}
if (nCount >= MAX_INFO_VALUE)
{
s++;
// skip oversized value chars till the slash or EOL
continue;
}
*c++ = *s++;
nCount++;
}
*c = '\0';
if (!strcmp(key, pkey))
{
c = value[valueindex];
valueindex = (valueindex + 1) % MAX_INFO_VALUES;
return c;
}
}
return "";
}
bool InfoString::RemoveKey(const char *key)
{
char *start;
char pkey[MAX_INFO_KEY];
char value[MAX_INFO_VALUE];
char *c;
char *s;
int cmpsize;
int nCount;
s = m_String;
if (strchr(key, '\\')) {
return false;
}
cmpsize = strlen(key);
if (cmpsize > MAX_INFO_LEN - 1) {
cmpsize = MAX_INFO_LEN - 1;
}
bool found = false;
while (*s)
{
start = s;
if (*s == '\\') {
// skip the slash
s++;
}
// Copy a key
nCount = 0;
c = pkey;
while (*s != '\\')
{
if (!*s) {
// key should end with a \, not a nullptr, but allow to remove it
break;
}
if (nCount >= MAX_INFO_KEY)
{
s++;
// skip oversized key chars till the slash or EOL
continue;
}
*c++ = *s++;
nCount++;
}
*c = '\0';
if (*s) {
// skip the slash
s++;
}
// Copy a value
nCount = 0;
c = value;
while (*s != '\\')
{
if (!*s) {
// allow value to be ended with nullptr
break;
}
if (nCount >= MAX_INFO_VALUE)
{
s++;
// skip oversized value chars till the slash or EOL
continue;
}
*c++ = *s++;
nCount++;
}
*c = '\0';
// Compare keys
if (!strncmp(key, pkey, cmpsize) )
{
found = true;
strcpy_safe(start, s); // remove this part
s = start; // continue searching
}
}
return found;
}
void InfoString::RemovePrefixedKeys(char prefix)
{
char pkey[MAX_INFO_KEY];
char value[MAX_INFO_VALUE];
char *start;
char *c;
char *s;
int nCount;
s = m_String;
while (*s)
{
start = s;
if (*s == '\\') {
// skip the slash
s++;
}
// Copy a key
nCount = 0;
c = pkey;
while (*s != '\\')
{
if (!*s) {
// key should end with a \, not a nullptr, but allow to remove it
break;
}
if (nCount >= MAX_INFO_KEY)
{
s++;
// skip oversized key chars till the slash or EOL
continue;
}
*c++ = *s++;
nCount++;
}
*c = '\0';
if (*s) {
// skip the slash
s++;
}
// Copy a value
nCount = 0;
c = value;
while (*s != '\\')
{
if (!*s) {
// allow value to be ended with nullptr
break;
}
if (nCount >= MAX_INFO_VALUE) {
s++;
// skip oversized value chars till the slash or EOL
continue;
}
*c++ = *s++;
nCount++;
}
*c = '\0';
// Compare prefix
if (pkey[0] == prefix)
{
strcpy_safe(start, s); // remove this part
s = start; // continue searching
}
}
}
bool InfoString::SetValueForStarKey(const char *key, const char *value)
{
char newtoken[MAX_INFO_LEN + 4];
if (strstr(key, "\\") || strstr(value, "\\")) {
return false;
}
if (strstr(key, "\"") || strstr(value, "\"")) {
return false;
}
if (strlen(key) > MAX_INFO_KEY || strlen(value) > MAX_INFO_VALUE) {
return false;
}
// Remove current key/value and return if we doesn't specified to set a value
RemoveKey(key);
if (!value || !strlen(value)) {
return true;
}
// Create key/value pair
_snprintf(newtoken, sizeof(newtoken), "\\%s\\%s", key, value);
int length = strlen(m_String);
if ((length + strlen(newtoken)) < m_MaxSize)
{
char *v = newtoken;
char *s = m_String + length;
unsigned char c;
while (*v)
{
c = (unsigned char)*v++;
*s++ = c;
}
*s = '\0';
return true;
}
return false;
}
bool InfoString::SetValueForKey(const char *key, const char *value)
{
return SetValueForStarKey(key, value);
}

View File

@ -0,0 +1,65 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
class InfoString {
public:
InfoString();
InfoString(unsigned int maxSize);
InfoString(char *string);
InfoString(char *string, unsigned int maxSize);
virtual ~InfoString();
void SetMaxSize(unsigned int maxSize);
bool SetString(char *string);
char *GetString();
void Clear();
int GetMaxSize();
int GetCurrentSize();
bool SetValueForStarKey(const char *key, const char *value);
char *ValueForKey(const char *key);
bool RemoveKey(const char *key);
void RemovePrefixedKeys(char prefix);
bool SetValueForKey(const char *key, const char *value);
protected:
enum {
MAX_INFO_KEY = 512,
MAX_INFO_VALUE = 512,
MAX_INFO_LEN = 256,
MAX_INFO_VALUES = 4
};
unsigned int m_MaxSize;
char *m_String;
};

View File

@ -0,0 +1,170 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
NetAddress::NetAddress()
{
memset(this, 0, sizeof(NetAddress));
}
void NetAddress::SetPort_(int16 port)
{
m_Port = htons(port);
}
void NetAddress::ToSockadr(sockaddr *s)
{
s->sa_family = AF_INET;
((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&m_IP;
((struct sockaddr_in *)s)->sin_port = m_Port;
}
bool NetAddress::FromSockadr(sockaddr *s)
{
if (s->sa_family != AF_INET) {
return false;
}
*(int *)&m_IP = ((struct sockaddr_in *)s)->sin_addr.s_addr;
m_Port = ((struct sockaddr_in *)s)->sin_port;
return true;
}
bool NetAddress::Equal(NetAddress *a)
{
if (*(int *)&m_IP == *(int *)&a->m_IP && m_Port == a->m_Port) {
return true;
}
return false;
}
bool NetAddress::EqualBase(NetAddress *a)
{
if (*(int *)&m_IP == *(int *)&a->m_IP) {
return true;
}
return false;
}
void NetAddress::ToStream(BitBuffer *stream)
{
stream->WriteByte(m_IP[0]);
stream->WriteByte(m_IP[1]);
stream->WriteByte(m_IP[2]);
stream->WriteByte(m_IP[3]);
stream->WriteShort(m_Port);
}
void NetAddress::FromStream(BitBuffer *stream)
{
m_IP[0] = stream->ReadByte();
m_IP[1] = stream->ReadByte();
m_IP[2] = stream->ReadByte();
m_IP[3] = stream->ReadByte();
m_Port = stream->ReadShort();
}
char *NetAddress::ToString()
{
_snprintf(m_String, sizeof(m_String), "%i.%i.%i.%i:%i", m_IP[0], m_IP[1], m_IP[2], m_IP[3], ntohs(m_Port));
return m_String;
}
char *NetAddress::ToBaseString()
{
_snprintf(m_String, sizeof(m_String), "%i.%i.%i.%i", m_IP[0], m_IP[1], m_IP[2], m_IP[3]);
return m_String;
}
void NetAddress::FromNetAddress(NetAddress *adr)
{
if (!adr) {
memset(m_IP, 0, sizeof(m_IP));
m_Port = 0;
return;
}
*(int *)&m_IP[0] = *(int *)&adr->m_IP[0];
m_Port = adr->m_Port;
}
netadr_t *NetAddress::ToOldNetAdr()
{
static netadr_t adr;
adr.type = NA_IP;
adr.port = m_Port;
*(int *)&adr.ip[0] = *(int *)&m_IP[0];
return &adr;
}
bool NetAddress::FromOldNetAdr(netadr_t *adr)
{
if (adr->type != NA_IP) {
return false;
}
*(int *)&m_IP[0] = *(int *)&adr->ip[0];
m_Port = adr->port;
return true;
}
bool NetAddress::IsValid()
{
return m_Port && (m_IP[0] || m_IP[1] || m_IP[2] || m_IP[3]);
}
void NetAddress::Clear()
{
m_IP[3] = 0;
m_IP[2] = 0;
m_IP[1] = 0;
m_IP[0] = 0;
m_Port = 0;
memset(m_String, 0, sizeof(m_String));
}
bool NetAddress::IsSubAdress(NetAddress *adr)
{
if ((!m_IP[0] || m_IP[0] == adr->m_IP[0])
&& (!m_IP[1] || m_IP[1] == adr->m_IP[1])
&& (!m_IP[2] || m_IP[2] == adr->m_IP[2])
&& (!m_IP[3] || m_IP[3] == adr->m_IP[3])
&& (m_IP[0] || m_IP[1] || m_IP[2] || m_IP[3]))
{
return true;
}
return false;
}

View File

@ -0,0 +1,74 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "netadr.h"
#include "BitBuffer.h"
class NetAddress {
public:
NetAddress();
bool IsValid();
bool IsSubAdress(NetAddress *adr);
void Clear();
bool FromOldNetAdr(netadr_t *adr);
netadr_t *ToOldNetAdr();
void FromNetAddress(NetAddress *adr);
char *ToBaseString();
char *ToString();
bool EqualBase(NetAddress *a);
bool Equal(NetAddress *a);
bool FromSockadr(struct sockaddr *s);
void ToSockadr(struct sockaddr *s);
void SetPort_(int16 port);
void ToStream(BitBuffer *stream);
void FromStream(BitBuffer *stream);
virtual ~NetAddress() {}
public:
unsigned char m_IP[4];
short unsigned int m_Port;
char m_String[32];
};
class NetPacket {
public:
NetAddress address;
BitBuffer data;
double time;
bool connectionless;
unsigned int seqnr;
bool hasReliableData;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,237 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include <HLTV/INetSocket.h>
#include <HLTV/INetChannel.h>
#include "bzip2/bzlib.h"
#include "ObjectList.h"
// 0 == regular, 1 == file stream
enum
{
FRAG_NORMAL_STREAM = 0,
FRAG_FILE_STREAM,
MAX_STREAMS
};
enum
{
FLOW_OUTGOING = 0,
FLOW_INCOMING,
MAX_FLOWS
};
#define MAX_LATENT 32
#define FRAGMENT_MAX_SIZE 1400 // Size of fragmentation buffer internal buffers
#define UDP_HEADER_SIZE 28
#define MAX_RELIABLE_PAYLOAD 1200
#define MAKE_FRAGID(id, count) (((id & 0xffff) << 16) | (count & 0xffff))
#define FRAG_GETID(fragid) ((fragid >> 16) & 0xffff)
#define FRAG_GETCOUNT(fragid) (fragid & 0xffff)
// Max length of a reliable message
#define MAX_MSGLEN 3990 // 10 reserved for fragheader?
#define MAX_POSSIBLE_MSG 65536
#define MAX_ROUTEABLE_PACKET 1400
#define MIN_ROUTEABLE_PACKET 16
#define SPLIT_SIZE (MAX_ROUTEABLE_PACKET - sizeof(SPLITPACKET))
// Pad this to next higher 16 byte boundary
// This is the largest packet that can come in/out over the wire, before processing the header
// bytes will be stripped by the networking channel layer
// #define NET_MAX_MESSAGE PAD_NUMBER( ( MAX_MSGLEN + HEADER_BYTES ), 16 )
// This is currently used value in the engine. TODO: define above gives 4016, check it why.
#define NET_MAX_MESSAGE 4037
#define NET_HEADER_FLAG_SPLITPACKET -2
class IBaseSystem;
// Network Connection Channel
class NetChannel: public INetChannel {
public:
NetChannel();
virtual ~NetChannel() {}
virtual bool Create(IBaseSystem *system, INetSocket *netsocket = nullptr, NetAddress *adr = nullptr);
virtual bool IsConnected();
virtual bool IsReadyToSend();
virtual bool IsCrashed();
virtual bool IsTimedOut();
virtual bool IsFakeChannel();
virtual bool KeepAlive();
virtual NetAddress *GetTargetAddress();
virtual void Close();
virtual void Clear();
virtual void Reset();
virtual void TransmitOutgoing();
virtual void ProcessIncoming(unsigned char *data, int size);
virtual void OutOfBandPrintf(const char *format, ...);
virtual void FakeAcknowledgement();
virtual void SetUpdateRate(int newupdaterate);
virtual void SetRate(int newRate);
virtual void SetKeepAlive(bool flag);
virtual void SetTimeOut(float time);
virtual float GetIdleTime();
virtual int GetRate();
virtual int GetUpdateRate();
virtual float GetLoss();
enum { FRAGMENT_C2S_MIN_SIZE = 16, FRAGMENT_S2C_MIN_SIZE = 256, FRAGMENT_S2C_MAX_SIZE = 1024 };
// Message data
typedef struct flowstats_s
{
int size; // Size of message sent/received
double time; // Time that message was sent/received
} flowstats_t;
typedef struct flow_s
{
flowstats_t stats[MAX_LATENT]; // Data for last MAX_LATENT messages
int current; // Current message position
double nextcompute; // Time when we should recompute k/sec data
// Average data
float kbytespersec;
float avgkbytespersec;
} flow_t;
// Generic fragment structure
typedef struct fragbuf_s
{
struct fragbuf_s *next; // Next buffer in chain
int bufferId; // Id of this buffer
byte data[FRAGMENT_MAX_SIZE]; // The actual data sits here
int size; // Size of data to read at that offset
bool isfile; // Is this a file buffer?
bool isbuffer; // Is this file buffer from memory ( custom decal, etc. ).
char fileName[MAX_PATH]; // Name of the file to save out on remote host
int fOffset; // Offset in file from which to read data
} fragbuf_t;
// Waiting list of fragbuf chains
typedef struct fragbufwaiting_s
{
struct fragbufwaiting_s *next; // Next chain in waiting list
int fragbufcount; // Number of buffers in this chain
fragbuf_t *fragbufs; // The actual buffers
} fragbufwaiting_t;
bool CreateFragmentsFromFile(char *fileName);
bool CopyFileFragments();
void GetFlowStats(float *avgInKBSec, float *avgOutKBSec);
void SetConnected(bool flag);
void FlushOutgoing();
void CopyNormalFragments();
void UpdateFlow(int stream);
void FlushIncoming(int stream);
void ClearFragments();
void ClearFragbufs(fragbuf_t **ppbuf);
void UnlinkFragment(fragbuf_t *buf, int stream);
NetPacket *GetPacket();
void FreePacket(NetPacket *packet);
void AddFragbufToTail(fragbufwaiting_t *wait, fragbuf_t *buf);
bool CreateFragmentsFromBuffer(void *buffer, int size, int streamtype, char *filename = nullptr);
void AddBufferToList(fragbuf_t ** pplist, fragbuf_t *pbuf);
void FragSend();
bool CheckForCompletion(int stream, int intotalbuffers);
fragbuf_t *FindBufferById(fragbuf_t **pplist, int id, bool allocate);
public:
IBaseSystem *m_System;
INetSocket *m_Socket;
NetAddress m_remote_address; // Address this channel is talking to.
double m_last_received;
double m_last_send;
double m_connect_time; // Time when channel was connected.
float m_timeout;
int m_max_bandwidth_rate;
double m_send_interval;
int m_updaterate; // Bandwidth choke, bytes per second
double m_cleartime; // If realtime > cleartime, free to send next packet
bool m_keep_alive;
bool m_crashed;
bool m_connected;
// Sequencing variables
int m_incoming_sequence; // Increasing count of sequence numbers
int m_incoming_acknowledged; // # of last outgoing message that has been ack'd.
int m_incoming_reliable_acknowledged; // Toggles T/F as reliable messages are received.
int m_incoming_reliable_sequence; // single bit, maintained local
int m_outgoing_sequence; // Message we are sending to remote
int m_reliable_sequence; // Whether the message contains reliable payload, single bit
int m_last_reliable_sequence; // Outgoing sequence number of last send that had reliable data
void *m_connection_status;
int m_blocksize;
BitBuffer m_reliableStream;
BitBuffer m_unreliableStream;
ObjectList m_incomingPackets;
// Reliable message buffer.
// We keep adding to it until reliable is acknowledged. Then we clear it.
int m_reliableOutSize;
unsigned char m_reliableOutBuffer[MAX_MSGLEN + 20];
fragbufwaiting_t *m_waitlist[MAX_STREAMS]; // Waiting list of buffered fragments to go onto queue. Multiple outgoing buffers can be queued in succession.
int m_reliable_fragment[MAX_STREAMS]; // Is reliable waiting buf a fragment?
size_t m_reliable_fragid[MAX_STREAMS]; // Buffer id for each waiting fragment
fragbuf_t *m_fragbufs[MAX_STREAMS]; // The current fragment being set
int m_fragbufcount[MAX_STREAMS]; // The total number of fragments in this stream
int16 m_frag_startpos[MAX_STREAMS]; // Position in outgoing buffer where frag data starts
int16 m_frag_length[MAX_STREAMS]; // Length of frag data in the buffer
fragbuf_t *m_incomingbufs[MAX_STREAMS]; // Incoming fragments are stored here
// Only referenced by the FRAG_FILE_STREAM component
// Name of file being downloaded
char m_incomingfilename[MAX_PATH];
void *m_tempBuffer;
int m_tempBufferSize;
// Incoming and outgoing flow metrics
flow_t m_flow[MAX_FLOWS];
float m_loss;
};

View File

@ -0,0 +1,85 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
typedef struct serverinfo_s
{
char address[64];
char name[80];
char map[16];
char gamedir[256];
char description[256];
int activePlayers;
int maxPlayers;
char type; // HLServerType
char os;
char pw;
bool mod;
char url_info[256];
char url_dl[256];
char hlversion[256];
int ver;
int size;
bool svonly;
bool cldll;
unsigned char protocol;
} serverinfo_t;
enum HLServerType {
HLST_Dedicated,
HLST_NonDedicated,
HLST_TV,
};
inline const char *GetServerType(HLServerType type)
{
switch (type)
{
case HLST_Dedicated: return "d";
case HLST_NonDedicated: return "l";
case HLST_TV: return "p";
}
return "";
}
inline const char *GetServerOS()
{
#ifdef _WIN32
return "w";
#else
return "l";
#endif
}

View File

@ -0,0 +1,89 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
short _BigShort(short l)
{
return bswap(l);
}
short _LittleShort(short l)
{
return l;
}
int _BigLong(int l)
{
return bswap(l);
}
int _LittleLong(int l)
{
return l;
}
float _BigFloat(float l)
{
return bswap(l);
}
float _LittleFloat(float l)
{
return l;
}
int _LongSwap(int l)
{
return bswap(l);
}
int _LongNoSwap(int l)
{
return l;
}
short _ShortSwap(short l)
{
return bswap(l);
}
short _ShortNoSwap(short l)
{
return l;
}
float _FloatSwap(float f)
{
return bswap(f);
}
float _FloatNoSwap(float f)
{
return f;
}

View File

@ -0,0 +1,42 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
short _BigShort(short l);
short _LittleShort(short l);
int _BigLong(int l);
int _LittleLong(int l);
float _BigFloat(float l);
float _LittleFloat(float l);
int _LongSwap(int l);
int _LongNoSwap(int l);
short _ShortSwap(short l);
short _ShortNoSwap(short l);
float _FloatSwap(float f);
float _FloatNoSwap(float f);

View File

@ -0,0 +1,468 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
static char *date = __DATE__;
static char *mon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
static char mond[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int COM_BuildNumber()
{
int m = 0;
int d = 0;
int y = 0;
static int b = 0;
if (b != 0)
return b;
for (m = 0; m < 11; m++)
{
if (_strnicmp(&date[0], mon[m], 3) == 0)
break;
d += mond[m];
}
d += atoi(&date[4]) - 1;
y = atoi(&date[7]) - 1900;
b = d + (int)((y - 1) * 365.25);
if (((y % 4) == 0) && m > 1)
{
b += 1;
}
// return days since initial commit on Apr 12 2014 (Happy Cosmonautics Day!)
b -= 41374;
return b;
}
char *COM_TimeString()
{
static char timedate[16];
time_t ltime = time(nullptr);
tm *now = localtime(&ltime);
strftime(timedate, sizeof(timedate), "%y%m%d%H%M", now);
return timedate;
}
char *COM_SkipPath(char *pathname)
{
char *last = pathname;
while (*pathname)
{
if (*pathname == '/' || *pathname == '\\') {
last = pathname + 1;
}
pathname++;
}
return last;
}
#ifdef _WIN32
char *COM_GetBaseDir()
{
static char basedir[MAX_PATH];
basedir[0] = '\0';
if (GetModuleFileName((HMODULE)nullptr, basedir, sizeof(basedir)))
{
char *pBuffer = strrchr(basedir, '\\');
if (pBuffer && *pBuffer)
pBuffer[1] = '\0';
int j = strlen(basedir);
if (j > 0 && (basedir[j - 1] == '\\' || basedir[j - 1] == '/'))
basedir[j - 1] = '\0';
}
return basedir;
}
#else // _WIN32
char g_szEXEName[256];
char *COM_GetBaseDir()
{
static char basedir[MAX_PATH];
basedir[0] = '\0';
strcpy(basedir, g_szEXEName);
char *pBuffer = strrchr(basedir, '/');
if (pBuffer && *pBuffer)
pBuffer[1] = '\0';
int j = strlen(basedir);
if (j > 0 && (basedir[j - 1] == '\\' || basedir[j - 1] == '/'))
basedir[j - 1] = '\0';
return basedir;
}
#endif // _WIN32
void COM_FixSlashes(char *pname)
{
while (*pname)
{
#ifdef _WIN32
if (*pname == '/')
{
*pname = '\\';
}
#else
if (*pname == '\\')
{
*pname = '/';
}
#endif
pname++;
}
}
// Fills "out" with the file name without path and extension.
void COM_FileBase(char *in, char *out)
{
*out = '\0';
int len = strlen(in);
if (len <= 0) {
return;
}
const char *start = in + len - 1;
const char *end = in + len;
while (start >= in && *start != '/' && *start != '\\')
{
if (*start == '.') {
end = start;
}
start--;
}
start++;
len = end - start;
strncpy(out, start, len);
out[len] = '\0';
}
char com_token[COM_TOKEN_LEN];
qboolean s_com_token_unget = FALSE;
void COM_UngetToken()
{
s_com_token_unget = TRUE;
}
char *COM_Parse(char *data)
{
int c;
int len;
if (s_com_token_unget)
{
s_com_token_unget = FALSE;
return data;
}
len = 0;
com_token[0] = '\0';
if (!data) {
return nullptr;
}
skipwhite:
while (*data <= 32)
{
if (!*data) {
return nullptr;
}
data++;
}
c = *data;
// skip // comments till the next line
if (c == '/' && data[1] == '/')
{
while (*data && *data != '\n')
data++;
// start over new line
goto skipwhite;
}
// handle quoted strings specially: copy till the end or another quote
if (c == '\"')
{
// skip starting quote
data++;
while (true)
{
c = *data++; // get char and advance
if (c == '\"') // closing quote
{
com_token[len] = '\0';
return data;
}
if (!c || len == COM_TOKEN_LEN - 1) // check if buffer is full
{
com_token[len] = 0;
return data;
}
com_token[len++] = c;
}
}
else
{
// parse single characters
if (c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ',')
{
com_token[len++] = c;
com_token[len] = '\0';
return data + 1;
}
// parse a regular word
do
{
com_token[len] = c;
data++;
len++;
c = *data;
if (c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ',')
break;
}
while (len < COM_TOKEN_LEN - 1 && (c < 0 || c > 32));
}
com_token[len] = '\0';
return data;
}
char *COM_VarArgs(char *format, ...)
{
va_list argptr;
static char string[1024];
va_start(argptr, format);
_vsnprintf(string, sizeof(string), format, argptr);
va_end(argptr);
return string;
}
unsigned char COM_Nibble(char c)
{
if (c >= '0' && c <= '9')
{
return (unsigned char)(c - '0');
}
if (c >= 'A' && c <= 'F')
{
return (unsigned char)(c - 'A' + 0x0A);
}
if (c >= 'a' && c <= 'f')
{
return (unsigned char)(c - 'a' + 0x0A);
}
return '0';
}
void COM_HexConvert(const char *pszInput, int nInputLength, unsigned char *pOutput)
{
const char *pIn;
unsigned char *p = pOutput;
for (int i = 0; i < nInputLength - 1; i += 2)
{
pIn = &pszInput[i];
if (!pIn[0] || !pIn[1])
break;
*p++ = ((COM_Nibble(pIn[0]) << 4) | COM_Nibble(pIn[1]));
}
}
char *COM_BinPrintf(unsigned char *buf, int length)
{
char szChunk[10];
static char szReturn[4096];
memset(szReturn, 0, sizeof(szReturn));
for (int i = 0; i < length; i++)
{
_snprintf(szChunk, sizeof(szChunk), "%02x", buf[i]);
strncat(szReturn, szChunk, sizeof(szReturn) - strlen(szReturn) - 1);
}
return szReturn;
}
char *COM_FormatTime(float seconds)
{
static char time[32];
int hours = (int)seconds / 3600;
if (hours > 0)
{
_snprintf(time, sizeof(time), "%02i:%2i:%02i", hours, (int)seconds / 60, (int)seconds % 60);
}
else
{
_snprintf(time, sizeof(time), "%02i:%02i", (int)seconds / 60, (int)seconds % 60);
}
return time;
}
void COM_RemoveEvilChars(char *string)
{
char *c = string;
if (!c) {
return;
}
while (*c)
{
if (*c < ' ' || *c > '~' || *c == '%' || *c == ';') {
*c = ' ';
}
c++;
}
}
int COM_FileNameCmp(const char *file1, const char *file2)
{
while (*file1 && *file2)
{
if ((*file1 != '/' || *file2 != '\\') && (*file2 != '/' || *file1 != '\\'))
{
if (tolower(*file1) != tolower(*file2))
return -1;
if (!*file1)
return 0;
}
file1++;
file2++;
}
return 0;
}
bool COM_IsWhiteSpace(char space)
{
switch (space) {
case '\t':
case '\r':
case '\n':
case ' ':
return true;
}
return false;
}
void COM_TrimSpace(const char *source, char *dest)
{
int start = 0;
while (source[start] && COM_IsWhiteSpace(source[start])) {
start++;
}
int end = strlen(source) - 1;
while (end > 0 && COM_IsWhiteSpace(source[end])) {
end--;
}
end++;
int length = end - start;
if (length > 0) {
strncpy(dest, &source[start], length);
}
else
length = 0;
dest[length] = '\0';
}
void COM_UnpackRGB(unsigned char &r, unsigned char &g, unsigned char &b, unsigned int color)
{
r = (color >> 16) & 0xFF;
g = (color >> 8) & 0xFF;
b = (color) & 0xFF;
}
unsigned int COM_PackRGB(unsigned char r, unsigned char g, unsigned char b)
{
return (r << 16) | (g << 8) | b;
}
unsigned int COM_PackRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
return (a << 24) | (r << 16) | (g << 8) | b;
}
void NORETURN HLTV_SysError(const char *fmt, ...)
{
va_list argptr;
static char string[8192];
va_start(argptr, fmt);
vsnprintf(string, sizeof(string), fmt, argptr);
va_end(argptr);
printf("%s\n", string);
FILE* fl = fopen("hltv_error.txt", "w");
fprintf(fl, "%s\n", string);
fclose(fl);
int *null = 0;
*null = 0;
exit(-1);
}

View File

@ -0,0 +1,55 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
int COM_BuildNumber();
char *COM_TimeString();
char *COM_SkipPath(char *pathname);
char *COM_GetBaseDir();
void COM_FixSlashes(char *pname);
void COM_FileBase(char *in, char *out);
void COM_UngetToken();
char *COM_Parse(char *data);
char *COM_VarArgs(char *format, ...);
unsigned char COM_Nibble(char c);
void COM_HexConvert(const char *pszInput, int nInputLength, unsigned char *pOutput);
char *COM_BinPrintf(unsigned char *buf, int length);
char *COM_FormatTime(float seconds);
void COM_RemoveEvilChars(char *string);
int COM_FileNameCmp(const char *file1, const char *file2);
bool COM_IsWhiteSpace(char space);
void COM_TrimSpace(const char *source, char *dest);
void COM_UnpackRGB(unsigned char &r, unsigned char &g, unsigned char &b, unsigned int color);
unsigned int COM_PackRGB(unsigned char r, unsigned char g, unsigned char b);
unsigned int COM_PackRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
void NORETURN HLTV_SysError(const char *fmt, ...);
#ifdef LINUX
extern char g_szEXEName[256];
#endif // LINUX

View File

@ -0,0 +1,390 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
vec3_t vec3_origin;
float TriangleDiameter(const vec_t *v1, vec_t *v2, vec_t *v3)
{
vec3_t e1, e2, e3;
float l1, l2, l3;
int i;
l1 = 0;
l2 = 0;
l3 = 0;
VectorSubtract(v2, v1, e1);
VectorSubtract(v3, v2, e2);
VectorSubtract(v1, v3, e3);
for (i = 0; i < 3; i++) {
l3 = e1[i] * e1[i] + l3;
}
for (i = 0; i < 3; i++) {
l2 = e2[i] * e2[i] + l2;
}
for (i = 0; i < 3; i++) {
l1 = e3[i] * e3[i] + l1;
}
if (l3 > l2 && l3 > l1) {
return sqrt(l3);
}
if (l2 > l3 && l2 > l1) {
return sqrt(l2);
}
return sqrt(l1);
}
float VectorNormalize(vec_t *v)
{
float length = Length(v);
if (length)
{
float ilength = 1 / length;
v[0] *= ilength;
v[1] *= ilength;
v[2] *= ilength;
}
return length;
}
float VectorDistance(const vec_t *v1, const vec_t *v2)
{
vec3_t t;
VectorSubtract(v1, v2, t);
return Length(t);
}
void VectorAngles(const float *forward, float *angles)
{
float tmp, yaw, pitch;
if (forward[1] == 0 && forward[0] == 0)
{
yaw = 0;
if (forward[2] > 0)
pitch = 90;
else
pitch = 270;
}
else
{
yaw = float(atan2(forward[1], forward[0]) * 180 / M_PI);
if (yaw < 0)
yaw += 360;
tmp = sqrt(forward[0] * forward[0] + forward[1] * forward[1]);
pitch = float(atan2(forward[2], tmp) * 180 / M_PI);
if (pitch < 0)
pitch += 360;
}
angles[0] = pitch;
angles[1] = yaw;
angles[2] = 0;
}
void VectorRAngles(const float *v, float *a)
{
a[0] = atan2(v[2], sqrt(v[0] * v[0] + v[1] * v[1]));
a[1] = atan2(v[1], v[0]);
NormalizeRAngles(a);
}
int BoxOnPlaneSide(vec_t *emins, vec_t *emaxs, mplane_t *p)
{
// From sources
float dist1, dist2;
int sides = 0;
// general case
switch (p->signbits)
{
case 0:
dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
dist2 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
break;
case 1:
dist1 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
break;
case 2:
dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
dist2 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
break;
case 3:
dist1 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
break;
case 4:
dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
dist2 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
break;
case 5:
dist1 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
break;
case 6:
dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
dist2 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
break;
case 7:
dist1 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
break;
default:
dist1 = dist2 = 0.0;
break;
}
if (dist1 >= p->dist)
sides = 1;
if (dist2 < p->dist)
sides |= 2;
return sides;
}
float AngleBetweenVectors(const vec_t *angle1, const vec_t *angle2)
{
float angle;
float d1 = Length(angle1);
float d2 = Length(angle2);
if (!d1 || !d2) {
return 0;
}
angle = acos(DotProduct(angle1, angle2) / (d1 * d2));
angle = angle * float(180.0f / M_PI);
return angle;
}
float RAngleBetweenVectors(const vec_t *angle1, const vec_t *angle2)
{
float d1, d2, d3;
d1 = Length(angle1);
d2 = Length(angle2);
if (!d1 || !d2) {
return 0;
}
d3 = DotProduct(angle1, angle2) / (d1 * d2);
if (d3 > 1) {
return 0;
}
if (d3 < -1) {
return (float)M_PI;
}
return acosf(d3);
}
void NormalizeAngles(vec_t *angles)
{
// Normalize angles
for (int i = 0; i < 3; ++i)
{
if (angles[i] > 180.0)
{
angles[i] -= 360.0;
}
else if (angles[i] < -180.0)
{
angles[i] += 360.0;
}
}
}
void NormalizeRAngles(vec_t *a)
{
if (a[0] > M_PI) {
a[0] -= float(M_PI * 2);
}
else if (a[0] < -M_PI) {
a[0] += float(M_PI * 2);
}
if (a[1] > M_PI) {
a[1] -= float(M_PI * 2);
}
else if (a[1] < -M_PI) {
a[1] += float(M_PI * 2);
}
a[2] = 0;
}
void AngleVectors(const vec_t *angles, vec_t *forward, vec_t *right, vec_t *up)
{
float sr, sp, sy, cr, cp, cy;
float angle;
angle = (float)(angles[YAW] * (M_PI * 2 / 360));
sy = sin(angle);
cy = cos(angle);
angle = (float)(angles[PITCH] * (M_PI * 2 / 360));
sp = sin(angle);
cp = cos(angle);
angle = (float)(angles[ROLL] * (M_PI * 2 / 360));
sr = sin(angle);
cr = cos(angle);
if (forward)
{
forward[0] = cp * cy;
forward[1] = cp * sy;
forward[2] = -sp;
}
if (right)
{
right[0] = (-1 * sr * sp * cy + -1 * cr * -sy);
right[1] = (-1 * sr * sp * sy + -1 * cr * cy);
right[2] = -1 * sr * cp;
}
if (up)
{
up[0] = (cr * sp * cy + -sr * -sy);
up[1] = (cr * sp * sy + -sr * cy);
up[2] = cr * cp;
}
}
int AngleLeftOfOther(const vec_t *v1, const vec_t *v2)
{
float a = v1[1];
float b = v2[1];
if (a >= 180)
return (b >= a) || ((a - 180) > b);
else
return (b > a) && ((a + 180) >= b);
}
float RadiusFromBounds(const vec_t *mins, const vec_t *maxs)
{
vec3_t corner;
for (int i = 0; i < 3; i++)
{
float fmin = fabs(mins[i]);
float fmax = fabs(mins[i]);
if (fmin > fmax)
corner[i] = fmin;
else
corner[i] = fmax;
}
return Length(corner);
}
bool SolveLSE(vec_t *v0, vec_t *v1, vec_t *v2, vec_t *v3, float *x, float *y, float *z)
{
float d = v1[2] * (v2[0] * v3[1] - v2[1] * v3[0]) + v1[1] * (v3[0] * v2[2] - v2[0] * v3[2]) + v1[0] * (v2[1] * v3[2] - v3[1] * v2[2]);
if (!d) {
return false;
}
if (x) *x = ((v2[0] * v3[1] - v2[1] * v3[0]) * v0[2] + (v3[0] * v2[2] - v2[0] * v3[2]) * v0[1] + (v2[1] * v3[2] - v3[1] * v2[2]) * v0[0]) / d;
if (y) *y = ((v0[0] * v3[1] - v0[1] * v3[0]) * v1[2] + (v3[0] * v0[2] - v0[0] * v3[2]) * v1[1] + (v0[1] * v3[2] - v3[1] * v0[2]) * v1[0]) / d;
if (z) *z = ((v2[0] * v0[1] - v2[1] * v0[0]) * v1[2] + (v0[0] * v2[2] - v2[0] * v0[2]) * v1[1] + (v2[1] * v0[2] - v0[1] * v2[2]) * v1[0]) / d;
return true;
}
void NormalizePoints(vec_t *v0, vec_t *v1)
{
vec3_t a;
VectorSubtract(v1, v0, a);
if (Length(a))
{
VectorNormalize(a);
VectorAdd(a, v0, v1);
}
}
void Normal2Plane(vec_t *v1, vec_t *v2, vec_t *v3)
{
if (v1[0])
{
v2[0] = -v1[1] / v1[0];
v2[1] = 1;
v2[2] = 0;
v3[0] = -v1[2] / v1[0];
v3[1] = 0;
v3[2] = 1;
return;
}
if (v1[1])
{
v2[0] = 1;
v2[1] = -v1[0] / v1[1];
v2[2] = 0;
v3[0] = 0;
v3[1] = -v1[2] / v1[1];
v3[2] = 1;
return;
}
v2[0] = 1;
v2[1] = 0;
v2[2] = -v1[0] / v1[2];
v3[0] = 0;
v3[1] = 1;
v3[2] = -v1[1] / v1[2];
}
float Length(const vec_t *v)
{
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
}
float DotProduct(const vec_t *v1, const vec_t *v2)
{
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}

View File

@ -0,0 +1,65 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "model.h"
#define PITCH 0 // up / down
#define YAW 1 // left / right
#define ROLL 2 // fall over
extern vec3_t vec3_origin;
static const int nanmask = 0x7F800000;
#define IS_NAN(fvar) ((*reinterpret_cast<int*>(&(fvar)) & nanmask) == nanmask)
#define VectorScale(a,b,c) {(c)[0]=(b)*(a)[0];(c)[1]=(b)*(a)[1];(c)[2]=(b)*(a)[2];}
#define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];}
#define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];}
#define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];}
#define VectorClear(a) {(a)[0]=0.0;(a)[1]=0.0;(a)[2]=0.0;}
float DotProduct(const vec_t *v1, const vec_t *v2);
float TriangleDiameter(const vec_t *v1, vec_t *v2, vec_t *v3);
float VectorNormalize(vec_t *v);
float VectorDistance(const vec_t *v1, const vec_t *v2);
void VectorAngles(const float *forward, float *angles);
void VectorRAngles(const float *v, float *a);
int BoxOnPlaneSide(vec_t *emins, vec_t *emaxs, struct mplane_s *p);
float AngleBetweenVectors(const vec_t *angle1, const vec_t *angle2);
float RAngleBetweenVectors(const vec_t *angle1, const vec_t *angle2);
void NormalizeAngles(vec_t *angles);
void NormalizeRAngles(vec_t *a);
void AngleVectors(const vec_t *angles, vec_t *forward, vec_t *right = nullptr, vec_t *up = nullptr);
int AngleLeftOfOther(const vec_t *v1, const vec_t *v2);
float RadiusFromBounds(const vec_t *mins, const vec_t *maxs);
bool SolveLSE(vec_t *v0, vec_t *v1, vec_t *v2, vec_t *v3, float *x, float *y, float *z);
void NormalizePoints(vec_t *v0, vec_t *v1);
void Normal2Plane(vec_t *v1, vec_t *v2, vec_t *v3);
float Length(const vec_t *v);

317
rehlds/HLTV/common/md5.cpp Normal file
View File

@ -0,0 +1,317 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
static unsigned char PADDING[64] =
{
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* F, G and H are basic MD5 functions: selection, majority, parity */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s, ac) \
{ \
(a) += F ((b), (c), (d)) + (x) + (uint32)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) \
{ \
(a) += G ((b), (c), (d)) + (x) + (uint32)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) \
{ \
(a) += H ((b), (c), (d)) + (x) + (uint32)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) \
{ \
(a) += I ((b), (c), (d)) + (x) + (uint32)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
void MD5_Init(MD5Context_t *ctx)
{
ctx->bits[0] = ctx->bits[1] = 0;
// Load magic initialization constants.
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
}
void MD5_Transform(unsigned int *buf, const unsigned int *in)
{
uint32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
// Round 1
#define S11 7
#define S12 12
#define S13 17
#define S14 22
FF(a, b, c, d, in[0], S11, 3614090360); /* 1 */
FF(d, a, b, c, in[1], S12, 3905402710); /* 2 */
FF(c, d, a, b, in[2], S13, 606105819); /* 3 */
FF(b, c, d, a, in[3], S14, 3250441966); /* 4 */
FF(a, b, c, d, in[4], S11, 4118548399); /* 5 */
FF(d, a, b, c, in[5], S12, 1200080426); /* 6 */
FF(c, d, a, b, in[6], S13, 2821735955); /* 7 */
FF(b, c, d, a, in[7], S14, 4249261313); /* 8 */
FF(a, b, c, d, in[8], S11, 1770035416); /* 9 */
FF(d, a, b, c, in[9], S12, 2336552879); /* 10 */
FF(c, d, a, b, in[10], S13, 4294925233); /* 11 */
FF(b, c, d, a, in[11], S14, 2304563134); /* 12 */
FF(a, b, c, d, in[12], S11, 1804603682); /* 13 */
FF(d, a, b, c, in[13], S12, 4254626195); /* 14 */
FF(c, d, a, b, in[14], S13, 2792965006); /* 15 */
FF(b, c, d, a, in[15], S14, 1236535329); /* 16 */
// Round 2
#define S21 5
#define S22 9
#define S23 14
#define S24 20
GG(a, b, c, d, in[1], S21, 4129170786); /* 17 */
GG(d, a, b, c, in[6], S22, 3225465664); /* 18 */
GG(c, d, a, b, in[11], S23, 643717713); /* 19 */
GG(b, c, d, a, in[0], S24, 3921069994); /* 20 */
GG(a, b, c, d, in[5], S21, 3593408605); /* 21 */
GG(d, a, b, c, in[10], S22, 38016083); /* 22 */
GG(c, d, a, b, in[15], S23, 3634488961); /* 23 */
GG(b, c, d, a, in[4], S24, 3889429448); /* 24 */
GG(a, b, c, d, in[9], S21, 568446438); /* 25 */
GG(d, a, b, c, in[14], S22, 3275163606); /* 26 */
GG(c, d, a, b, in[3], S23, 4107603335); /* 27 */
GG(b, c, d, a, in[8], S24, 1163531501); /* 28 */
GG(a, b, c, d, in[13], S21, 2850285829); /* 29 */
GG(d, a, b, c, in[2], S22, 4243563512); /* 30 */
GG(c, d, a, b, in[7], S23, 1735328473); /* 31 */
GG(b, c, d, a, in[12], S24, 2368359562); /* 32 */
// Round 3
#define S31 4
#define S32 11
#define S33 16
#define S34 23
HH(a, b, c, d, in[5], S31, 4294588738); /* 33 */
HH(d, a, b, c, in[8], S32, 2272392833); /* 34 */
HH(c, d, a, b, in[11], S33, 1839030562); /* 35 */
HH(b, c, d, a, in[14], S34, 4259657740); /* 36 */
HH(a, b, c, d, in[1], S31, 2763975236); /* 37 */
HH(d, a, b, c, in[4], S32, 1272893353); /* 38 */
HH(c, d, a, b, in[7], S33, 4139469664); /* 39 */
HH(b, c, d, a, in[10], S34, 3200236656); /* 40 */
HH(a, b, c, d, in[13], S31, 681279174); /* 41 */
HH(d, a, b, c, in[0], S32, 3936430074); /* 42 */
HH(c, d, a, b, in[3], S33, 3572445317); /* 43 */
HH(b, c, d, a, in[6], S34, 76029189); /* 44 */
HH(a, b, c, d, in[9], S31, 3654602809); /* 45 */
HH(d, a, b, c, in[12], S32, 3873151461); /* 46 */
HH(c, d, a, b, in[15], S33, 530742520); /* 47 */
HH(b, c, d, a, in[2], S34, 3299628645); /* 48 */
// Round 4
#define S41 6
#define S42 10
#define S43 15
#define S44 21
II(a, b, c, d, in[0], S41, 4096336452); /* 49 */
II(d, a, b, c, in[7], S42, 1126891415); /* 50 */
II(c, d, a, b, in[14], S43, 2878612391); /* 51 */
II(b, c, d, a, in[5], S44, 4237533241); /* 52 */
II(a, b, c, d, in[12], S41, 1700485571); /* 53 */
II(d, a, b, c, in[3], S42, 2399980690); /* 54 */
II(c, d, a, b, in[10], S43, 4293915773); /* 55 */
II(b, c, d, a, in[1], S44, 2240044497); /* 56 */
II(a, b, c, d, in[8], S41, 1873313359); /* 57 */
II(d, a, b, c, in[15], S42, 4264355552); /* 58 */
II(c, d, a, b, in[6], S43, 2734768916); /* 59 */
II(b, c, d, a, in[13], S44, 1309151649); /* 60 */
II(a, b, c, d, in[4], S41, 4149444226); /* 61 */
II(d, a, b, c, in[11], S42, 3174756917); /* 62 */
II(c, d, a, b, in[2], S43, 718787259); /* 63 */
II(b, c, d, a, in[9], S44, 3951481745); /* 64 */
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
void MD5_Update(MD5Context_t *ctx, const unsigned char *buf, unsigned int len)
{
uint32 in[16];
int mdi;
unsigned int i, ii;
// Compute number of bytes mod 64
mdi = (int)((ctx->bits[0] >> 3) & 0x3F);
// Update number of bits
if ((ctx->bits[0] + ((uint32)len << 3)) < ctx->bits[0])
{
ctx->bits[1]++;
}
ctx->bits[0] += ((uint32)len << 3);
ctx->bits[1] += ((uint32)len >> 29);
while (len--)
{
// Add new character to buffer, increment mdi
ctx->in[mdi++] = *buf++;
// Transform if necessary
if (mdi == 0x40)
{
for (i = 0, ii = 0; i < 16; i++, ii += 4)
in[i] = (((uint32)ctx->in[ii + 3]) << 24) |
(((uint32)ctx->in[ii + 2]) << 16) |
(((uint32)ctx->in[ii + 1]) << 8) |
((uint32)ctx->in[ii]);
MD5_Transform(ctx->buf, in);
mdi = 0;
}
}
}
void MD5_Final(unsigned char *digest, MD5Context_t *ctx)
{
uint32 in[16];
int mdi;
unsigned int i, ii;
unsigned int padLen;
// save number of bits
in[14] = ctx->bits[0];
in[15] = ctx->bits[1];
// Compute number of bytes mod 64
mdi = (int)((ctx->bits[0] >> 3) & 0x3F);
// Pad out to 56 mod 64
padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
MD5_Update(ctx, PADDING, padLen);
// Append length in bits and transform
for (i = 0, ii = 0; i < 14; i++, ii += 4)
in[i] = (((uint32)ctx->in[ii + 3]) << 24) |
(((uint32)ctx->in[ii + 2]) << 16) |
(((uint32)ctx->in[ii + 1]) << 8) |
((uint32)ctx->in[ii]);
MD5_Transform(ctx->buf, in);
// Store buffer in digest
for (i = 0, ii = 0; i < 4; i++, ii += 4)
{
digest[ii] = (unsigned char)(ctx->buf[i] & 0xFF);
digest[ii + 1] = (unsigned char)((ctx->buf[i] >> 8) & 0xFF);
digest[ii + 2] = (unsigned char)((ctx->buf[i] >> 16) & 0xFF);
digest[ii + 3] = (unsigned char)((ctx->buf[i] >> 24) & 0xFF);
}
}
char *MD5_Print(unsigned char *hash)
{
static char szReturn[64];
char szChunk[10];
int i;
memset(szReturn, 0, sizeof(szReturn));
for (i = 0; i < 16; i++)
{
_snprintf(szChunk, sizeof(szChunk), "%02x", hash[i]);
strncat(szReturn, szChunk, sizeof(szReturn) - strlen(szReturn) - 1);
}
return szReturn;
}
char *MD5_GetCDKeyHash(const char *key)
{
static char szHashedKeyBuffer[256];
char szKeyBuffer[256];
int nKeyLength = strlen(key);
if (nKeyLength <= 0 || nKeyLength > 255) {
return nullptr;
}
strncpy(szKeyBuffer, key, sizeof(szKeyBuffer) - 1);
szKeyBuffer[sizeof(szKeyBuffer) - 1] = '\0';
szKeyBuffer[nKeyLength] = '\0';
MD5Context_t ctx;
unsigned char digest[16];
memset(&ctx, 0, sizeof(ctx));
memset(digest, 0, sizeof(digest));
memset(szHashedKeyBuffer, 0, sizeof(szHashedKeyBuffer));
MD5_Init(&ctx);
MD5_Update(&ctx, (unsigned char *)szKeyBuffer, nKeyLength);
MD5_Final(digest, &ctx);
strncpy(szHashedKeyBuffer, MD5_Print(digest), sizeof(szHashedKeyBuffer) - 1);
szHashedKeyBuffer[sizeof(szHashedKeyBuffer) - 1] = '\0';
return szHashedKeyBuffer;
}
void MD5_Hash_Mem(unsigned char *digest, unsigned char *mem, int size)
{
MD5Context_t ctx;
memset(&ctx, 0, sizeof(ctx));
MD5_Init(&ctx);
MD5_Update(&ctx, mem, size);
MD5_Final(digest, &ctx);
}

Some files were not shown because too many files have changed in this diff Show More