Merge branch 'master' into pr-downloader
19
.circleci/config.yml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
version: 2
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
docker:
|
||||||
|
- image: buildpack-deps:stretch
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: Build bam
|
||||||
|
command: |
|
||||||
|
apt-get update -y
|
||||||
|
apt-get install libsdl2-dev libfreetype6-dev -y
|
||||||
|
git clone https://github.com/matricks/bam.git ~/bam
|
||||||
|
cd ~/bam/
|
||||||
|
git reset --hard f012dd9a3e38295b8a45af5a101d29573381f169
|
||||||
|
./make_unix.sh
|
||||||
|
- run:
|
||||||
|
name: Build teeworlds
|
||||||
|
command: ~/bam/bam conf=release all
|
3
.gitignore
vendored
|
@ -2,6 +2,8 @@
|
||||||
/.bam
|
/.bam
|
||||||
/config.lua
|
/config.lua
|
||||||
/build
|
/build
|
||||||
|
/other/*/lib
|
||||||
|
/other/*/include
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
*.pyc
|
||||||
*.pyo
|
*.pyo
|
||||||
|
@ -11,3 +13,4 @@ scripts/work/
|
||||||
/autoexec.cfg
|
/autoexec.cfg
|
||||||
other/freetype
|
other/freetype
|
||||||
other/sdl
|
other/sdl
|
||||||
|
_test.exe
|
||||||
|
|
2
.gitmodules
vendored
|
@ -1,6 +1,8 @@
|
||||||
[submodule "datasrc/languages"]
|
[submodule "datasrc/languages"]
|
||||||
path = datasrc/languages
|
path = datasrc/languages
|
||||||
url = git://github.com/teeworlds/teeworlds-translation.git
|
url = git://github.com/teeworlds/teeworlds-translation.git
|
||||||
|
branch = master
|
||||||
[submodule "datasrc/maps"]
|
[submodule "datasrc/maps"]
|
||||||
path = datasrc/maps
|
path = datasrc/maps
|
||||||
url = git://github.com/teeworlds/teeworlds-maps.git
|
url = git://github.com/teeworlds/teeworlds-maps.git
|
||||||
|
branch = master
|
||||||
|
|
77
bam.lua
|
@ -1,4 +1,4 @@
|
||||||
CheckVersion("0.4")
|
CheckVersion("0.5")
|
||||||
|
|
||||||
Import("configure.lua")
|
Import("configure.lua")
|
||||||
Import("other/sdl/sdl.lua")
|
Import("other/sdl/sdl.lua")
|
||||||
|
@ -8,7 +8,7 @@ Import("other/freetype/freetype.lua")
|
||||||
config = NewConfig()
|
config = NewConfig()
|
||||||
config:Add(OptCCompiler("compiler"))
|
config:Add(OptCCompiler("compiler"))
|
||||||
config:Add(OptTestCompileC("stackprotector", "int main(){return 0;}", "-fstack-protector -fstack-protector-all"))
|
config:Add(OptTestCompileC("stackprotector", "int main(){return 0;}", "-fstack-protector -fstack-protector-all"))
|
||||||
config:Add(OptTestCompileC("minmacosxsdk", "int main(){return 0;}", "-mmacosx-version-min=10.5 -isysroot /Developer/SDKs/MacOSX10.5.sdk"))
|
config:Add(OptTestCompileC("minmacosxsdk", "int main(){return 0;}", "-mmacosx-version-min=10.7 -isysroot /Developer/SDKs/MacOSX10.7.sdk"))
|
||||||
config:Add(OptLibrary("zlib", "zlib.h", false))
|
config:Add(OptLibrary("zlib", "zlib.h", false))
|
||||||
config:Add(SDL.OptFind("sdl", true))
|
config:Add(SDL.OptFind("sdl", true))
|
||||||
config:Add(FreeType.OptFind("freetype", true))
|
config:Add(FreeType.OptFind("freetype", true))
|
||||||
|
@ -76,7 +76,7 @@ function ContentCompile(action, output)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function GenerateCommonSettings(settings)
|
function GenerateCommonSettings(settings, conf, arch, compiler)
|
||||||
if compiler == "gcc" or compiler == "clang" then
|
if compiler == "gcc" or compiler == "clang" then
|
||||||
settings.cc.flags:Add("-Wall", "-fno-exceptions")
|
settings.cc.flags:Add("-Wall", "-fno-exceptions")
|
||||||
end
|
end
|
||||||
|
@ -93,15 +93,16 @@ function GenerateCommonSettings(settings)
|
||||||
zlib = Compile(settings, Collect("src/engine/external/zlib/*.c"))
|
zlib = Compile(settings, Collect("src/engine/external/zlib/*.c"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local md5 = Compile(settings, Collect("src/engine/external/md5/*.c"))
|
||||||
local wavpack = Compile(settings, Collect("src/engine/external/wavpack/*.c"))
|
local wavpack = Compile(settings, Collect("src/engine/external/wavpack/*.c"))
|
||||||
local png = Compile(settings, Collect("src/engine/external/pnglite/*.c"))
|
local png = Compile(settings, Collect("src/engine/external/pnglite/*.c"))
|
||||||
local json = Compile(settings, Collect("src/engine/external/json-parser/*.c"))
|
local json = Compile(settings, Collect("src/engine/external/json-parser/*.c"))
|
||||||
|
|
||||||
-- globally available libs
|
-- globally available libs
|
||||||
libs = {zlib=zlib, wavpack=wavpack, png=png, json=json}
|
libs = {zlib=zlib, wavpack=wavpack, png=png, md5=md5, json=json}
|
||||||
end
|
end
|
||||||
|
|
||||||
function GenerateMacOSXSettings(settings, conf, arch)
|
function GenerateMacOSXSettings(settings, conf, arch, compiler)
|
||||||
if arch == "x86" then
|
if arch == "x86" then
|
||||||
settings.cc.flags:Add("-arch i386")
|
settings.cc.flags:Add("-arch i386")
|
||||||
settings.link.flags:Add("-arch i386")
|
settings.link.flags:Add("-arch i386")
|
||||||
|
@ -119,17 +120,23 @@ function GenerateMacOSXSettings(settings, conf, arch)
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
settings.cc.flags:Add("-mmacosx-version-min=10.5")
|
-- c++ stdlib needed
|
||||||
settings.link.flags:Add("-mmacosx-version-min=10.5")
|
settings.cc.flags:Add("--stdlib=libc++")
|
||||||
|
settings.link.flags:Add("--stdlib=libc++")
|
||||||
|
-- this also needs the macOS min SDK version to be at least 10.7
|
||||||
|
|
||||||
|
settings.cc.flags:Add("-mmacosx-version-min=10.7")
|
||||||
|
settings.link.flags:Add("-mmacosx-version-min=10.7")
|
||||||
|
|
||||||
if config.minmacosxsdk.value == 1 then
|
if config.minmacosxsdk.value == 1 then
|
||||||
settings.cc.flags:Add("-isysroot /Developer/SDKs/MacOSX10.5.sdk")
|
settings.cc.flags:Add("-isysroot /Developer/SDKs/MacOSX10.7.sdk")
|
||||||
settings.link.flags:Add("-isysroot /Developer/SDKs/MacOSX10.5.sdk")
|
settings.link.flags:Add("-isysroot /Developer/SDKs/MacOSX10.7.sdk")
|
||||||
end
|
end
|
||||||
|
|
||||||
settings.link.frameworks:Add("Carbon")
|
settings.link.frameworks:Add("Carbon")
|
||||||
settings.link.frameworks:Add("AppKit")
|
settings.link.frameworks:Add("AppKit")
|
||||||
|
|
||||||
GenerateCommonSettings(settings, conf, arch)
|
GenerateCommonSettings(settings, conf, arch, compiler)
|
||||||
|
|
||||||
-- Build server launcher before adding game stuff
|
-- Build server launcher before adding game stuff
|
||||||
local serverlaunch = Link(settings, "serverlaunch", Compile(settings, "src/osxlaunch/server.m"))
|
local serverlaunch = Link(settings, "serverlaunch", Compile(settings, "src/osxlaunch/server.m"))
|
||||||
|
@ -160,20 +167,23 @@ function GenerateMacOSXSettings(settings, conf, arch)
|
||||||
BuildContent(settings)
|
BuildContent(settings)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GenerateLinuxSettings(settings, conf, arch)
|
function GenerateLinuxSettings(settings, conf, arch, compiler)
|
||||||
if arch == "x86" then
|
if arch == "x86" then
|
||||||
|
settings.cc.flags:Add("-msse2") -- for the _mm_pause call
|
||||||
settings.cc.flags:Add("-m32")
|
settings.cc.flags:Add("-m32")
|
||||||
settings.link.flags:Add("-m32")
|
settings.link.flags:Add("-m32")
|
||||||
elseif arch == "x86_64" then
|
elseif arch == "x86_64" then
|
||||||
settings.cc.flags:Add("-m64")
|
settings.cc.flags:Add("-m64")
|
||||||
settings.link.flags:Add("-m64")
|
settings.link.flags:Add("-m64")
|
||||||
|
elseif arch == "armv7l" then
|
||||||
|
-- arm 32 bit
|
||||||
else
|
else
|
||||||
print("Unknown Architecture '" .. arch .. "'. Supported: x86, x86_64")
|
print("Unknown Architecture '" .. arch .. "'. Supported: x86, x86_64")
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
settings.link.libs:Add("pthread")
|
settings.link.libs:Add("pthread")
|
||||||
|
|
||||||
GenerateCommonSettings(settings, conf, arch)
|
GenerateCommonSettings(settings, conf, arch, compiler)
|
||||||
|
|
||||||
-- Master server, version server and tools
|
-- Master server, version server and tools
|
||||||
BuildEngineCommon(settings)
|
BuildEngineCommon(settings)
|
||||||
|
@ -197,29 +207,23 @@ function GenerateLinuxSettings(settings, conf, arch)
|
||||||
BuildContent(settings)
|
BuildContent(settings)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GenerateSolarisSettings(settings, conf, arch)
|
function GenerateSolarisSettings(settings, conf, arch, compiler)
|
||||||
settings.link.libs:Add("socket")
|
settings.link.libs:Add("socket")
|
||||||
settings.link.libs:Add("nsl")
|
settings.link.libs:Add("nsl")
|
||||||
|
|
||||||
GenerateLinuxSettings(settings, conf, arch)
|
GenerateLinuxSettings(settings, conf, arch, compiler)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GenerateWindowsSettings(settings, conf, target_arch, compiler)
|
function GenerateWindowsSettings(settings, conf, target_arch, compiler)
|
||||||
if compiler == "cl" then
|
if compiler == "cl" then
|
||||||
if (target_arch == "x86" and arch ~= "ia32") or
|
if (target_arch == "x86" and arch ~= "ia32") or
|
||||||
(target_arch == "x86_64" and arch ~= "x64" and arch ~= "x86_64") then
|
(target_arch == "x86_64" and arch ~= "ia64" and arch ~= "amd64") then
|
||||||
print("Cross compiling is unsupported on Windows.")
|
print("Cross compiling is unsupported on Windows.")
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
settings.cc.flags:Add("/wd4244")
|
settings.cc.flags:Add("/wd4244", "/wd4577")
|
||||||
elseif compiler == "gcc" or config.compiler.driver == "clang" then
|
elseif compiler == "gcc" or config.compiler.driver == "clang" then
|
||||||
if target_arch == "x86" then
|
if target_arch ~= "x86" and target_arch ~= "x86_64" then
|
||||||
settings.cc.flags:Add("-m32")
|
|
||||||
settings.link.flags:Add("-m32")
|
|
||||||
elseif target_arch == "x86_64" then
|
|
||||||
settings.cc.flags:Add("-m64")
|
|
||||||
settings.link.flags:Add("-m64")
|
|
||||||
else
|
|
||||||
print("Unknown Architecture '" .. arch .. "'. Supported: x86, x86_64")
|
print("Unknown Architecture '" .. arch .. "'. Supported: x86, x86_64")
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
|
@ -237,8 +241,9 @@ function GenerateWindowsSettings(settings, conf, target_arch, compiler)
|
||||||
settings.link.libs:Add("ws2_32")
|
settings.link.libs:Add("ws2_32")
|
||||||
settings.link.libs:Add("ole32")
|
settings.link.libs:Add("ole32")
|
||||||
settings.link.libs:Add("shell32")
|
settings.link.libs:Add("shell32")
|
||||||
|
settings.link.libs:Add("advapi32")
|
||||||
|
|
||||||
GenerateCommonSettings(settings, conf, target_arch)
|
GenerateCommonSettings(settings, conf, target_arch, compiler)
|
||||||
|
|
||||||
-- Master server, version server and tools
|
-- Master server, version server and tools
|
||||||
BuildEngineCommon(settings)
|
BuildEngineCommon(settings)
|
||||||
|
@ -271,7 +276,7 @@ function SharedCommonFiles()
|
||||||
if not shared_common_files then
|
if not shared_common_files then
|
||||||
local network_source = ContentCompile("network_source", "generated/protocol.cpp")
|
local network_source = ContentCompile("network_source", "generated/protocol.cpp")
|
||||||
local network_header = ContentCompile("network_header", "generated/protocol.h")
|
local network_header = ContentCompile("network_header", "generated/protocol.h")
|
||||||
AddDependency(network_source, network_header)
|
AddDependency(network_source, network_header, "src/engine/shared/protocol.h")
|
||||||
|
|
||||||
local nethash = CHash("generated/nethash.cpp", "src/engine/shared/protocol.h", "src/game/tuning.h", "src/game/gamecore.cpp", network_header)
|
local nethash = CHash("generated/nethash.cpp", "src/engine/shared/protocol.h", "src/game/tuning.h", "src/game/gamecore.cpp", network_header)
|
||||||
shared_common_files = {network_source, nethash}
|
shared_common_files = {network_source, nethash}
|
||||||
|
@ -334,7 +339,7 @@ function BuildClient(settings, family, platform)
|
||||||
local game_client = Compile(settings, CollectRecursive("src/game/client/*.cpp"), SharedClientFiles())
|
local game_client = Compile(settings, CollectRecursive("src/game/client/*.cpp"), SharedClientFiles())
|
||||||
local game_editor = Compile(settings, Collect("src/game/editor/*.cpp"))
|
local game_editor = Compile(settings, Collect("src/game/editor/*.cpp"))
|
||||||
|
|
||||||
Link(settings, "teeworlds", libs["zlib"], libs["wavpack"], libs["png"], libs["json"], client, game_client, game_editor)
|
Link(settings, "teeworlds", libs["zlib"], libs["md5"], libs["wavpack"], libs["png"], libs["json"], client, game_client, game_editor)
|
||||||
end
|
end
|
||||||
|
|
||||||
function BuildServer(settings, family, platform)
|
function BuildServer(settings, family, platform)
|
||||||
|
@ -342,24 +347,24 @@ function BuildServer(settings, family, platform)
|
||||||
|
|
||||||
local game_server = Compile(settings, CollectRecursive("src/game/server/*.cpp"), SharedServerFiles())
|
local game_server = Compile(settings, CollectRecursive("src/game/server/*.cpp"), SharedServerFiles())
|
||||||
|
|
||||||
return Link(settings, "teeworlds_srv", libs["zlib"], server, game_server)
|
return Link(settings, "teeworlds_srv", libs["zlib"], libs["md5"], server, game_server)
|
||||||
end
|
end
|
||||||
|
|
||||||
function BuildTools(settings)
|
function BuildTools(settings)
|
||||||
local tools = {}
|
local tools = {}
|
||||||
for i,v in ipairs(Collect("src/tools/*.cpp", "src/tools/*.c")) do
|
for i,v in ipairs(Collect("src/tools/*.cpp", "src/tools/*.c")) do
|
||||||
local toolname = PathFilename(PathBase(v))
|
local toolname = PathFilename(PathBase(v))
|
||||||
tools[i] = Link(settings, toolname, Compile(settings, v), libs["zlib"], libs["wavpack"], libs["png"])
|
tools[i] = Link(settings, toolname, Compile(settings, v), libs["zlib"], libs["md5"], libs["wavpack"], libs["png"])
|
||||||
end
|
end
|
||||||
PseudoTarget(settings.link.Output(settings, "pseudo_tools") .. settings.link.extension, tools)
|
PseudoTarget(settings.link.Output(settings, "pseudo_tools") .. settings.link.extension, tools)
|
||||||
end
|
end
|
||||||
|
|
||||||
function BuildMasterserver(settings)
|
function BuildMasterserver(settings)
|
||||||
return Link(settings, "mastersrv", Compile(settings, Collect("src/mastersrv/*.cpp")), libs["zlib"])
|
return Link(settings, "mastersrv", Compile(settings, Collect("src/mastersrv/*.cpp")), libs["zlib"], libs["md5"])
|
||||||
end
|
end
|
||||||
|
|
||||||
function BuildVersionserver(settings)
|
function BuildVersionserver(settings)
|
||||||
return Link(settings, "versionsrv", Compile(settings, Collect("src/versionsrv/*.cpp")), libs["zlib"])
|
return Link(settings, "versionsrv", Compile(settings, Collect("src/versionsrv/*.cpp")), libs["zlib"], libs["md5"])
|
||||||
end
|
end
|
||||||
|
|
||||||
function BuildContent(settings)
|
function BuildContent(settings)
|
||||||
|
@ -380,6 +385,8 @@ function GenerateSettings(conf, arch, builddir, compiler)
|
||||||
elseif compiler == "cl" then
|
elseif compiler == "cl" then
|
||||||
SetDriversCL(settings)
|
SetDriversCL(settings)
|
||||||
else
|
else
|
||||||
|
-- apply compiler settings
|
||||||
|
config.compiler:Apply(settings)
|
||||||
compiler = config.compiler.driver
|
compiler = config.compiler.driver
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -413,11 +420,11 @@ function GenerateSettings(conf, arch, builddir, compiler)
|
||||||
GenerateWindowsSettings(settings, conf, arch, compiler)
|
GenerateWindowsSettings(settings, conf, arch, compiler)
|
||||||
elseif family == "unix" then
|
elseif family == "unix" then
|
||||||
if platform == "macosx" then
|
if platform == "macosx" then
|
||||||
GenerateMacOSXSettings(settings, conf, arch)
|
GenerateMacOSXSettings(settings, conf, arch, compiler)
|
||||||
elseif platform == "linux" then
|
|
||||||
GenerateLinuxSettings(settings, conf, arch)
|
|
||||||
elseif platform == "solaris" then
|
elseif platform == "solaris" then
|
||||||
GenerateSolarisSettings(settings, conf, arch)
|
GenerateSolarisSettings(settings, conf, arch, compiler)
|
||||||
|
else -- Linux, BSD
|
||||||
|
GenerateLinuxSettings(settings, conf, arch, compiler)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -452,7 +459,7 @@ if ScriptArgs['arch'] then
|
||||||
else
|
else
|
||||||
if arch == "ia32" then
|
if arch == "ia32" then
|
||||||
archs = {"x86"}
|
archs = {"x86"}
|
||||||
elseif arch == "x64" or arch == "amd64" then
|
elseif arch == "ia64" or arch == "amd64" then
|
||||||
archs = {"x86_64"}
|
archs = {"x86_64"}
|
||||||
else
|
else
|
||||||
archs = {arch}
|
archs = {arch}
|
||||||
|
|
|
@ -72,13 +72,13 @@ function NewConfig(on_configured_callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
config.Load = function(self, filename)
|
config.Load = function(self, filename)
|
||||||
local options_func = loadfile(filename)
|
|
||||||
local options_table = {}
|
local options_table = {}
|
||||||
|
local options_func = loadfile(filename, nil, options_table)
|
||||||
|
|
||||||
if not options_func then
|
if not options_func then
|
||||||
print("auto configuration")
|
print("auto configuration")
|
||||||
self:Config(filename)
|
self:Config(filename)
|
||||||
options_func = loadfile(filename)
|
options_func = loadfile(filename, nil, options_table)
|
||||||
end
|
end
|
||||||
|
|
||||||
if options_func then
|
if options_func then
|
||||||
|
@ -86,7 +86,6 @@ function NewConfig(on_configured_callback)
|
||||||
for k,v in pairs(self.options) do
|
for k,v in pairs(self.options) do
|
||||||
options_table[v.name] = {}
|
options_table[v.name] = {}
|
||||||
end
|
end
|
||||||
setfenv(options_func, options_table)
|
|
||||||
|
|
||||||
-- this is to make sure that we get nice error messages when
|
-- this is to make sure that we get nice error messages when
|
||||||
-- someone sets an option that isn't valid.
|
-- someone sets an option that isn't valid.
|
||||||
|
@ -360,10 +359,10 @@ function OptCCompiler(name, default_driver, default_c, default_cxx, desc)
|
||||||
-- no need todo anything if we have a driver
|
-- no need todo anything if we have a driver
|
||||||
-- TODO: test if we can find the compiler
|
-- TODO: test if we can find the compiler
|
||||||
else
|
else
|
||||||
if ExecuteSilent("cl") == 0 then
|
if ExecuteSilent("g++ -v") == 0 then
|
||||||
option.driver = "cl"
|
|
||||||
elseif ExecuteSilent("g++ -v") == 0 then
|
|
||||||
option.driver = "gcc"
|
option.driver = "gcc"
|
||||||
|
elseif ExecuteSilent("cl") == 0 then
|
||||||
|
option.driver = "cl"
|
||||||
else
|
else
|
||||||
error("no c/c++ compiler found")
|
error("no c/c++ compiler found")
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import os, imp, sys
|
import os
|
||||||
|
import sys
|
||||||
from datatypes import *
|
from datatypes import *
|
||||||
import content
|
import content
|
||||||
import network
|
import network
|
||||||
|
@ -127,11 +128,11 @@ if gen_network_header:
|
||||||
class CNetObjHandler
|
class CNetObjHandler
|
||||||
{
|
{
|
||||||
const char *m_pMsgFailedOn;
|
const char *m_pMsgFailedOn;
|
||||||
const char *m_pObjCorrectedOn;
|
|
||||||
char m_aMsgData[1024];
|
char m_aMsgData[1024];
|
||||||
int m_NumObjCorrections;
|
const char *m_pObjFailedOn;
|
||||||
int ClampInt(const char *pErrorMsg, int Value, int Min, int Max);
|
int m_NumObjFailures;
|
||||||
int ClampFlag(const char *pErrorMsg, int Value, int Mask);
|
bool CheckInt(const char *pErrorMsg, int Value, int Min, int Max);
|
||||||
|
bool CheckFlag(const char *pErrorMsg, int Value, int Mask);
|
||||||
|
|
||||||
static const char *ms_apObjNames[];
|
static const char *ms_apObjNames[];
|
||||||
static int ms_aObjSizes[];
|
static int ms_aObjSizes[];
|
||||||
|
@ -143,8 +144,8 @@ public:
|
||||||
int ValidateObj(int Type, const void *pData, int Size);
|
int ValidateObj(int Type, const void *pData, int Size);
|
||||||
const char *GetObjName(int Type) const;
|
const char *GetObjName(int Type) const;
|
||||||
int GetObjSize(int Type) const;
|
int GetObjSize(int Type) const;
|
||||||
int NumObjCorrections() const;
|
const char *FailedObjOn() const;
|
||||||
const char *CorrectedObjOn() const;
|
int NumObjFailures() const;
|
||||||
|
|
||||||
const char *GetMsgName(int Type) const;
|
const char *GetMsgName(int Type) const;
|
||||||
void *SecureUnpackMsg(int Type, CUnpacker *pUnpacker);
|
void *SecureUnpackMsg(int Type, CUnpacker *pUnpacker);
|
||||||
|
@ -167,34 +168,32 @@ if gen_network_source:
|
||||||
lines += ['CNetObjHandler::CNetObjHandler()']
|
lines += ['CNetObjHandler::CNetObjHandler()']
|
||||||
lines += ['{']
|
lines += ['{']
|
||||||
lines += ['\tm_pMsgFailedOn = "";']
|
lines += ['\tm_pMsgFailedOn = "";']
|
||||||
lines += ['\tm_pObjCorrectedOn = "";']
|
lines += ['\tm_pObjFailedOn = "";']
|
||||||
lines += ['\tm_NumObjCorrections = 0;']
|
lines += ['\tm_NumObjFailures = 0;']
|
||||||
lines += ['}']
|
lines += ['}']
|
||||||
lines += ['']
|
lines += ['']
|
||||||
lines += ['int CNetObjHandler::NumObjCorrections() const { return m_NumObjCorrections; }']
|
lines += ['const char *CNetObjHandler::FailedObjOn() const { return m_pObjFailedOn; }']
|
||||||
lines += ['const char *CNetObjHandler::CorrectedObjOn() const { return m_pObjCorrectedOn; }']
|
lines += ['int CNetObjHandler::NumObjFailures() const { return m_NumObjFailures; }']
|
||||||
lines += ['const char *CNetObjHandler::FailedMsgOn() const { return m_pMsgFailedOn; }']
|
lines += ['const char *CNetObjHandler::FailedMsgOn() const { return m_pMsgFailedOn; }']
|
||||||
lines += ['']
|
lines += ['']
|
||||||
lines += ['']
|
lines += ['']
|
||||||
lines += ['']
|
lines += ['']
|
||||||
lines += ['']
|
lines += ['']
|
||||||
lines += ['']
|
|
||||||
|
|
||||||
lines += ['static const int max_int = 0x7fffffff;']
|
lines += ['static const int max_int = 0x7fffffff;']
|
||||||
lines += ['']
|
lines += ['']
|
||||||
|
|
||||||
lines += ['int CNetObjHandler::ClampInt(const char *pErrorMsg, int Value, int Min, int Max)']
|
lines += ['bool CNetObjHandler::CheckInt(const char *pErrorMsg, int Value, int Min, int Max)']
|
||||||
lines += ['{']
|
lines += ['{']
|
||||||
lines += ['\tif(Value < Min) { m_pObjCorrectedOn = pErrorMsg; m_NumObjCorrections++; return Min; }']
|
lines += ['\tif(Value < Min || Value > Max) { m_pObjFailedOn = pErrorMsg; m_NumObjFailures++; return false; }']
|
||||||
lines += ['\tif(Value > Max) { m_pObjCorrectedOn = pErrorMsg; m_NumObjCorrections++; return Max; }']
|
lines += ['\treturn true;']
|
||||||
lines += ['\treturn Value;']
|
|
||||||
lines += ['}']
|
lines += ['}']
|
||||||
lines += ['']
|
lines += ['']
|
||||||
|
|
||||||
lines += ['int CNetObjHandler::ClampFlag(const char *pErrorMsg, int Value, int Mask)']
|
lines += ['bool CNetObjHandler::CheckFlag(const char *pErrorMsg, int Value, int Mask)']
|
||||||
lines += ['{']
|
lines += ['{']
|
||||||
lines += ['\tif((Value&Mask) != Value) { m_pObjCorrectedOn = pErrorMsg; m_NumObjCorrections++; return (Value&Mask); }']
|
lines += ['\tif((Value&Mask) != Value) { m_pObjFailedOn = pErrorMsg; m_NumObjFailures++; return false; }']
|
||||||
lines += ['\treturn Value;']
|
lines += ['\treturn true;']
|
||||||
lines += ['}']
|
lines += ['}']
|
||||||
lines += ['']
|
lines += ['']
|
||||||
|
|
||||||
|
@ -300,6 +299,7 @@ if gen_network_source:
|
||||||
lines += ['void *CNetObjHandler::SecureUnpackMsg(int Type, CUnpacker *pUnpacker)']
|
lines += ['void *CNetObjHandler::SecureUnpackMsg(int Type, CUnpacker *pUnpacker)']
|
||||||
lines += ['{']
|
lines += ['{']
|
||||||
lines += ['\tm_pMsgFailedOn = 0;']
|
lines += ['\tm_pMsgFailedOn = 0;']
|
||||||
|
lines += ['\tm_pObjFailedOn = 0;']
|
||||||
lines += ['\tswitch(Type)']
|
lines += ['\tswitch(Type)']
|
||||||
lines += ['\t{']
|
lines += ['\t{']
|
||||||
|
|
||||||
|
@ -317,9 +317,15 @@ if gen_network_source:
|
||||||
lines += ['\tif(pUnpacker->Error())']
|
lines += ['\tif(pUnpacker->Error())']
|
||||||
lines += ['\t\tm_pMsgFailedOn = "(unpack error)";']
|
lines += ['\t\tm_pMsgFailedOn = "(unpack error)";']
|
||||||
lines += ['\t']
|
lines += ['\t']
|
||||||
lines += ['\tif(m_pMsgFailedOn)']
|
lines += ['\tif(m_pMsgFailedOn || m_pObjFailedOn) {']
|
||||||
|
lines += ['\t\tif(!m_pMsgFailedOn)']
|
||||||
|
lines += ['\t\t\tm_pMsgFailedOn = "";']
|
||||||
|
lines += ['\t\tif(!m_pObjFailedOn)']
|
||||||
|
lines += ['\t\t\tm_pObjFailedOn = "";']
|
||||||
lines += ['\t\treturn 0;']
|
lines += ['\t\treturn 0;']
|
||||||
|
lines += ['\t}']
|
||||||
lines += ['\tm_pMsgFailedOn = "";']
|
lines += ['\tm_pMsgFailedOn = "";']
|
||||||
|
lines += ['\tm_pObjFailedOn = "";']
|
||||||
lines += ['\treturn m_aMsgData;']
|
lines += ['\treturn m_aMsgData;']
|
||||||
lines += ['};']
|
lines += ['};']
|
||||||
lines += ['']
|
lines += ['']
|
||||||
|
|
|
@ -17,10 +17,11 @@ class SoundSet(Struct):
|
||||||
self.sounds.Add(Sound(name))
|
self.sounds.Add(Sound(name))
|
||||||
|
|
||||||
class Image(Struct):
|
class Image(Struct):
|
||||||
def __init__(self, name="", filename=""):
|
def __init__(self, name="", filename="", linear_mapping=0):
|
||||||
Struct.__init__(self, "CDataImage")
|
Struct.__init__(self, "CDataImage")
|
||||||
self.name = String(name)
|
self.name = String(name)
|
||||||
self.filename = String(filename)
|
self.filename = String(filename)
|
||||||
|
self.flag = Int(linear_mapping)
|
||||||
self.id = TextureHandle()
|
self.id = TextureHandle()
|
||||||
|
|
||||||
class SpriteSet(Struct):
|
class SpriteSet(Struct):
|
||||||
|
@ -233,15 +234,20 @@ container.sounds.Add(SoundSet("menu", ["audio/music_menu.wv"]))
|
||||||
image_null = Image("null", "")
|
image_null = Image("null", "")
|
||||||
image_particles = Image("particles", "particles.png")
|
image_particles = Image("particles", "particles.png")
|
||||||
image_game = Image("game", "game.png")
|
image_game = Image("game", "game.png")
|
||||||
image_browseicons = Image("browseicons", "ui/icons/browse.png")
|
image_browseicons = Image("browseicons", "ui/icons/browse.png", 1)
|
||||||
image_emoticons = Image("emoticons", "emoticons.png")
|
image_emoticons = Image("emoticons", "emoticons.png")
|
||||||
image_demobuttons = Image("demobuttons", "ui/demo_buttons.png")
|
image_demobuttons = Image("demobuttons", "ui/demo_buttons.png", 1)
|
||||||
image_fileicons = Image("fileicons", "ui/file_icons.png")
|
image_fileicons = Image("fileicons", "ui/file_icons.png", 1)
|
||||||
image_guibuttons = Image("guibuttons", "ui/gui_buttons.png")
|
image_guibuttons = Image("guibuttons", "ui/gui_buttons.png", 1)
|
||||||
image_guiicons = Image("guiicons", "ui/gui_icons.png")
|
image_guiicons = Image("guiicons", "ui/gui_icons.png", 1)
|
||||||
image_menuicons = Image("menuicons", "ui/icons/menu.png")
|
image_menuicons = Image("menuicons", "ui/icons/menu.png", 1)
|
||||||
image_toolicons = Image("toolicons", "ui/icons/tools.png")
|
image_toolicons = Image("toolicons", "ui/icons/tools.png", 1)
|
||||||
image_infoicons = Image("infoicons", "ui/icons/info.png")
|
image_arrowicons = Image("arrowicons", "ui/icons/arrows.png", 1)
|
||||||
|
image_friendicons = Image("friendicons", "ui/icons/friend.png", 1)
|
||||||
|
image_infoicons = Image("infoicons", "ui/icons/info.png", 1)
|
||||||
|
image_levelicons = Image("levelicons", "ui/icons/level.png", 1)
|
||||||
|
image_sidebaricons = Image("sidebaricons", "ui/icons/sidebar.png", 1)
|
||||||
|
image_chatwhisper = Image("chatwhisper", "ui/icons/chat_whisper.png", 1)
|
||||||
|
|
||||||
container.images.Add(image_null)
|
container.images.Add(image_null)
|
||||||
container.images.Add(image_game)
|
container.images.Add(image_game)
|
||||||
|
@ -260,7 +266,12 @@ container.images.Add(image_guiicons)
|
||||||
container.images.Add(Image("no_skinpart", "ui/no_skinpart.png"))
|
container.images.Add(Image("no_skinpart", "ui/no_skinpart.png"))
|
||||||
container.images.Add(image_menuicons)
|
container.images.Add(image_menuicons)
|
||||||
container.images.Add(image_toolicons)
|
container.images.Add(image_toolicons)
|
||||||
|
container.images.Add(image_arrowicons)
|
||||||
|
container.images.Add(image_friendicons)
|
||||||
container.images.Add(image_infoicons)
|
container.images.Add(image_infoicons)
|
||||||
|
container.images.Add(image_levelicons)
|
||||||
|
container.images.Add(image_sidebaricons)
|
||||||
|
container.images.Add(image_chatwhisper)
|
||||||
|
|
||||||
container.pickups.Add(Pickup("health"))
|
container.pickups.Add(Pickup("health"))
|
||||||
container.pickups.Add(Pickup("armor"))
|
container.pickups.Add(Pickup("armor"))
|
||||||
|
@ -277,6 +288,7 @@ set_tee_decoration = SpriteSet("tee_decoration", image_null, 2, 1)
|
||||||
set_tee_hands = SpriteSet("tee_hands", image_null, 2, 1)
|
set_tee_hands = SpriteSet("tee_hands", image_null, 2, 1)
|
||||||
set_tee_feet = SpriteSet("tee_feet", image_null, 2, 1)
|
set_tee_feet = SpriteSet("tee_feet", image_null, 2, 1)
|
||||||
set_tee_eyes = SpriteSet("tee_eyes", image_null, 2, 4)
|
set_tee_eyes = SpriteSet("tee_eyes", image_null, 2, 4)
|
||||||
|
set_tee_hats = SpriteSet("tee_hats", image_null, 1, 4)
|
||||||
set_browseicons = SpriteSet("browseicons", image_browseicons, 4, 2)
|
set_browseicons = SpriteSet("browseicons", image_browseicons, 4, 2)
|
||||||
set_emoticons = SpriteSet("emoticons", image_emoticons, 4, 4)
|
set_emoticons = SpriteSet("emoticons", image_emoticons, 4, 4)
|
||||||
set_demobuttons = SpriteSet("demobuttons", image_demobuttons, 5, 1)
|
set_demobuttons = SpriteSet("demobuttons", image_demobuttons, 5, 1)
|
||||||
|
@ -285,7 +297,11 @@ set_guibuttons = SpriteSet("guibuttons", image_guibuttons, 12, 4)
|
||||||
set_guiicons = SpriteSet("guiicons", image_guiicons, 8, 2)
|
set_guiicons = SpriteSet("guiicons", image_guiicons, 8, 2)
|
||||||
set_menuicons = SpriteSet("menuicons", image_menuicons, 2, 2)
|
set_menuicons = SpriteSet("menuicons", image_menuicons, 2, 2)
|
||||||
set_toolicons = SpriteSet("toolicons", image_toolicons, 4, 2)
|
set_toolicons = SpriteSet("toolicons", image_toolicons, 4, 2)
|
||||||
|
set_arrowicons = SpriteSet("arrowicons", image_arrowicons, 4, 3)
|
||||||
|
set_friendicons = SpriteSet("friendicons", image_friendicons, 2, 2)
|
||||||
set_infoicons = SpriteSet("infoicons", image_infoicons, 1, 2)
|
set_infoicons = SpriteSet("infoicons", image_infoicons, 1, 2)
|
||||||
|
set_levelicons = SpriteSet("levelicons", image_levelicons, 4, 4)
|
||||||
|
set_sidebaricons = SpriteSet("sidebaricons", image_sidebaricons, 4, 2)
|
||||||
|
|
||||||
container.spritesets.Add(set_particles)
|
container.spritesets.Add(set_particles)
|
||||||
container.spritesets.Add(set_game)
|
container.spritesets.Add(set_game)
|
||||||
|
@ -295,6 +311,7 @@ container.spritesets.Add(set_tee_decoration)
|
||||||
container.spritesets.Add(set_tee_hands)
|
container.spritesets.Add(set_tee_hands)
|
||||||
container.spritesets.Add(set_tee_feet)
|
container.spritesets.Add(set_tee_feet)
|
||||||
container.spritesets.Add(set_tee_eyes)
|
container.spritesets.Add(set_tee_eyes)
|
||||||
|
container.spritesets.Add(set_tee_hats)
|
||||||
container.spritesets.Add(set_browseicons)
|
container.spritesets.Add(set_browseicons)
|
||||||
container.spritesets.Add(set_emoticons)
|
container.spritesets.Add(set_emoticons)
|
||||||
container.spritesets.Add(set_demobuttons)
|
container.spritesets.Add(set_demobuttons)
|
||||||
|
@ -303,7 +320,12 @@ container.spritesets.Add(set_guibuttons)
|
||||||
container.spritesets.Add(set_guiicons)
|
container.spritesets.Add(set_guiicons)
|
||||||
container.spritesets.Add(set_menuicons)
|
container.spritesets.Add(set_menuicons)
|
||||||
container.spritesets.Add(set_toolicons)
|
container.spritesets.Add(set_toolicons)
|
||||||
|
container.spritesets.Add(set_arrowicons)
|
||||||
|
container.spritesets.Add(set_friendicons)
|
||||||
container.spritesets.Add(set_infoicons)
|
container.spritesets.Add(set_infoicons)
|
||||||
|
container.spritesets.Add(set_levelicons)
|
||||||
|
container.spritesets.Add(set_sidebaricons)
|
||||||
|
|
||||||
|
|
||||||
container.sprites.Add(Sprite("part_slice", set_particles, 0,0,1,1))
|
container.sprites.Add(Sprite("part_slice", set_particles, 0,0,1,1))
|
||||||
container.sprites.Add(Sprite("part_ball", set_particles, 1,0,1,1))
|
container.sprites.Add(Sprite("part_ball", set_particles, 1,0,1,1))
|
||||||
|
@ -383,6 +405,11 @@ container.sprites.Add(Sprite("pickup_ninja", set_game, 2,10,8,2))
|
||||||
container.sprites.Add(Sprite("flag_blue", set_game, 12,8,4,8))
|
container.sprites.Add(Sprite("flag_blue", set_game, 12,8,4,8))
|
||||||
container.sprites.Add(Sprite("flag_red", set_game, 16,8,4,8))
|
container.sprites.Add(Sprite("flag_red", set_game, 16,8,4,8))
|
||||||
|
|
||||||
|
container.sprites.Add(Sprite("ninja_bar_full_left", set_game, 21,4,1,2))
|
||||||
|
container.sprites.Add(Sprite("ninja_bar_full", set_game, 22,4,1,2))
|
||||||
|
container.sprites.Add(Sprite("ninja_bar_empty", set_game, 23,4,1,2))
|
||||||
|
container.sprites.Add(Sprite("ninja_bar_empty_right", set_game, 24,4,1,2))
|
||||||
|
|
||||||
container.sprites.Add(Sprite("tee_body_outline", set_tee_body, 0,0,1,1))
|
container.sprites.Add(Sprite("tee_body_outline", set_tee_body, 0,0,1,1))
|
||||||
container.sprites.Add(Sprite("tee_body", set_tee_body, 1,0,1,1))
|
container.sprites.Add(Sprite("tee_body", set_tee_body, 1,0,1,1))
|
||||||
container.sprites.Add(Sprite("tee_body_shadow", set_tee_body, 0,1,1,1))
|
container.sprites.Add(Sprite("tee_body_shadow", set_tee_body, 0,1,1,1))
|
||||||
|
@ -405,6 +432,11 @@ container.sprites.Add(Sprite("tee_eyes_pain", set_tee_eyes, 0,1,1,1))
|
||||||
container.sprites.Add(Sprite("tee_eyes_happy", set_tee_eyes, 1,1,1,1))
|
container.sprites.Add(Sprite("tee_eyes_happy", set_tee_eyes, 1,1,1,1))
|
||||||
container.sprites.Add(Sprite("tee_eyes_surprise", set_tee_eyes, 0,2,1,1))
|
container.sprites.Add(Sprite("tee_eyes_surprise", set_tee_eyes, 0,2,1,1))
|
||||||
|
|
||||||
|
container.sprites.Add(Sprite("tee_hats_top1", set_tee_hats, 0,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("tee_hats_top2", set_tee_hats, 0,1,1,1))
|
||||||
|
container.sprites.Add(Sprite("tee_hats_side1", set_tee_hats, 0,2,1,1))
|
||||||
|
container.sprites.Add(Sprite("tee_hats_side2", set_tee_hats, 0,3,1,1))
|
||||||
|
|
||||||
container.sprites.Add(Sprite("oop", set_emoticons, 0, 0, 1, 1))
|
container.sprites.Add(Sprite("oop", set_emoticons, 0, 0, 1, 1))
|
||||||
container.sprites.Add(Sprite("exclamation", set_emoticons, 1, 0, 1, 1))
|
container.sprites.Add(Sprite("exclamation", set_emoticons, 1, 0, 1, 1))
|
||||||
container.sprites.Add(Sprite("hearts", set_emoticons, 2, 0, 1, 1))
|
container.sprites.Add(Sprite("hearts", set_emoticons, 2, 0, 1, 1))
|
||||||
|
@ -468,9 +500,45 @@ container.sprites.Add(Sprite("tool_edit_b", set_toolicons, 2,1,1,1))
|
||||||
container.sprites.Add(Sprite("tool_x_a", set_toolicons, 3,0,1,1))
|
container.sprites.Add(Sprite("tool_x_a", set_toolicons, 3,0,1,1))
|
||||||
container.sprites.Add(Sprite("tool_x_b", set_toolicons, 3,1,1,1))
|
container.sprites.Add(Sprite("tool_x_b", set_toolicons, 3,1,1,1))
|
||||||
|
|
||||||
|
container.sprites.Add(Sprite("arrow_left_a", set_arrowicons, 0,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("arrow_left_b", set_arrowicons, 0,1,1,1))
|
||||||
|
container.sprites.Add(Sprite("arrow_left_c", set_arrowicons, 0,2,1,1))
|
||||||
|
container.sprites.Add(Sprite("arrow_up_a", set_arrowicons, 1,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("arrow_up_b", set_arrowicons, 1,1,1,1))
|
||||||
|
container.sprites.Add(Sprite("arrow_up_c", set_arrowicons, 1,2,1,1))
|
||||||
|
container.sprites.Add(Sprite("arrow_right_a", set_arrowicons, 2,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("arrow_right_b", set_arrowicons, 2,1,1,1))
|
||||||
|
container.sprites.Add(Sprite("arrow_right_c", set_arrowicons, 2,2,1,1))
|
||||||
|
container.sprites.Add(Sprite("arrow_down_a", set_arrowicons, 3,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("arrow_down_b", set_arrowicons, 3,1,1,1))
|
||||||
|
container.sprites.Add(Sprite("arrow_down_c", set_arrowicons, 3,2,1,1))
|
||||||
|
|
||||||
|
container.sprites.Add(Sprite("friend_plus_a", set_friendicons, 0,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("friend_plus_b", set_friendicons, 0,1,1,1))
|
||||||
|
container.sprites.Add(Sprite("friend_x_a", set_friendicons, 1,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("friend_x_b", set_friendicons, 1,1,1,1))
|
||||||
|
|
||||||
container.sprites.Add(Sprite("info_a", set_infoicons, 0,0,1,1))
|
container.sprites.Add(Sprite("info_a", set_infoicons, 0,0,1,1))
|
||||||
container.sprites.Add(Sprite("info_b", set_infoicons, 0,1,1,1))
|
container.sprites.Add(Sprite("info_b", set_infoicons, 0,1,1,1))
|
||||||
|
|
||||||
|
container.sprites.Add(Sprite("level_a_on", set_levelicons, 0,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("level_a_a", set_levelicons, 0,1,1,1))
|
||||||
|
container.sprites.Add(Sprite("level_a_b", set_levelicons, 0,2,1,1))
|
||||||
|
container.sprites.Add(Sprite("level_b_on", set_levelicons, 1,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("level_b_a", set_levelicons, 1,1,1,1))
|
||||||
|
container.sprites.Add(Sprite("level_b_b", set_levelicons, 1,2,1,1))
|
||||||
|
container.sprites.Add(Sprite("level_c_on", set_levelicons, 2,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("level_c_a", set_levelicons, 2,1,1,1))
|
||||||
|
container.sprites.Add(Sprite("level_c_b", set_levelicons, 2,2,1,1))
|
||||||
|
|
||||||
|
container.sprites.Add(Sprite("sidebar_refresh_a", set_sidebaricons, 0,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("sidebar_refresh_b", set_sidebaricons, 0,1,1,1))
|
||||||
|
container.sprites.Add(Sprite("sidebar_friend_a", set_sidebaricons, 1,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("sidebar_friend_b", set_sidebaricons, 1,1,1,1))
|
||||||
|
container.sprites.Add(Sprite("sidebar_filter_a", set_sidebaricons, 2,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("sidebar_filter_b", set_sidebaricons, 2,1,1,1))
|
||||||
|
container.sprites.Add(Sprite("sidebar_info_a", set_sidebaricons, 3,0,1,1))
|
||||||
|
container.sprites.Add(Sprite("sidebar_info_b", set_sidebaricons, 3,1,1,1))
|
||||||
|
|
||||||
anim = Animation("base")
|
anim = Animation("base")
|
||||||
anim.body.frames.Add(AnimKeyframe(0, 0, -4, 0))
|
anim.body.frames.Add(AnimKeyframe(0, 0, -4, 0))
|
||||||
|
@ -543,7 +611,7 @@ weapon.damage.Set(1)
|
||||||
weapon.ammoregentime.Set(500)
|
weapon.ammoregentime.Set(500)
|
||||||
weapon.visual_size.Set(64)
|
weapon.visual_size.Set(64)
|
||||||
weapon.offsetx.Set(32)
|
weapon.offsetx.Set(32)
|
||||||
weapon.offsety.Set(4)
|
weapon.offsety.Set(-4)
|
||||||
weapon.muzzleoffsetx.Set(50)
|
weapon.muzzleoffsetx.Set(50)
|
||||||
weapon.muzzleoffsety.Set(6)
|
weapon.muzzleoffsety.Set(6)
|
||||||
container.weapons.gun.base.Set(weapon)
|
container.weapons.gun.base.Set(weapon)
|
||||||
|
|
BIN
datasrc/countryflags/PS.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
datasrc/countryflags/XBZ.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
datasrc/countryflags/XCA.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
datasrc/countryflags/XES.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
datasrc/countryflags/XGA.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
|
@ -20,6 +20,26 @@
|
||||||
"id": "XWA",
|
"id": "XWA",
|
||||||
"code": 904
|
"code": 904
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "XBZ",
|
||||||
|
"code": 950,
|
||||||
|
"blocked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "XCA",
|
||||||
|
"code": 951,
|
||||||
|
"blocked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "XES",
|
||||||
|
"code": 952,
|
||||||
|
"blocked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "XGA",
|
||||||
|
"code": 953,
|
||||||
|
"blocked": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "default",
|
"id": "default",
|
||||||
"code": -1
|
"code": -1
|
||||||
|
@ -738,6 +758,10 @@
|
||||||
"id": "PR",
|
"id": "PR",
|
||||||
"code": 630
|
"code": 630
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "PS",
|
||||||
|
"code": 275
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "PT",
|
"id": "PT",
|
||||||
"code": 620
|
"code": 620
|
||||||
|
|
|
@ -147,7 +147,7 @@ class Float(BaseType):
|
||||||
def Set(self, value):
|
def Set(self, value):
|
||||||
self.value = value
|
self.value = value
|
||||||
def EmitDefinition(self, name):
|
def EmitDefinition(self, name):
|
||||||
return ["%f"%self.value]
|
return ["%ff"%self.value]
|
||||||
#return ["%d /* %s */"%(self.value, self._target_name)]
|
#return ["%d /* %s */"%(self.value, self._target_name)]
|
||||||
|
|
||||||
class String(BaseType):
|
class String(BaseType):
|
||||||
|
@ -328,9 +328,9 @@ class NetIntRange(NetIntAny):
|
||||||
self.min = str(min)
|
self.min = str(min)
|
||||||
self.max = str(max)
|
self.max = str(max)
|
||||||
def emit_validate(self):
|
def emit_validate(self):
|
||||||
return ["ClampInt(\"%s\", pObj->%s, %s, %s);"%(self.name,self.name, self.min, self.max)]
|
return ["if(!CheckInt(\"%s\", pObj->%s, %s, %s)) return -1;"%(self.name, self.name, self.min, self.max)]
|
||||||
def emit_unpack_check(self):
|
def emit_unpack_check(self):
|
||||||
return ["if(pMsg->%s < %s || pMsg->%s > %s) { m_pMsgFailedOn = \"%s\"; break; }" % (self.name, self.min, self.name, self.max, self.name)]
|
return ["if(!CheckInt(\"%s\", pMsg->%s, %s, %s)) break;"%(self.name, self.name, self.min, self.max)]
|
||||||
|
|
||||||
class NetEnum(NetIntRange):
|
class NetEnum(NetIntRange):
|
||||||
def __init__(self, name, enum):
|
def __init__(self, name, enum):
|
||||||
|
@ -346,9 +346,9 @@ class NetFlag(NetIntAny):
|
||||||
else:
|
else:
|
||||||
self.mask = "0"
|
self.mask = "0"
|
||||||
def emit_validate(self):
|
def emit_validate(self):
|
||||||
return ["ClampFlag(\"%s\", pObj->%s, %s);"%(self.name, self.name, self.mask)]
|
return ["if(!CheckFlag(\"%s\", pObj->%s, %s)) return -1;"%(self.name, self.name, self.mask)]
|
||||||
def emit_unpack_check(self):
|
def emit_unpack_check(self):
|
||||||
return ["if((pMsg->%s & (%s)) != pMsg->%s) { m_pMsgFailedOn = \"%s\"; break; }" % (self.name, self.mask, self.name, self.name)]
|
return ["if(!CheckFlag(\"%s\", pMsg->%s, %s)) break;"%(self.name, self.name, self.mask)]
|
||||||
|
|
||||||
class NetBool(NetIntRange):
|
class NetBool(NetIntRange):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
|
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.8 KiB |
BIN
datasrc/game.png
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 137 KiB |
|
@ -1 +1 @@
|
||||||
Subproject commit 68c3ccfe095d88028bfe1e2f27f44983a244c7d7
|
Subproject commit d5143007d8492481b687d4adab04b1968107196b
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 225 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 15 KiB |
BIN
datasrc/mapres/generic_shadows.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 159 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 179 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 258 KiB After Width: | Height: | Size: 215 KiB |
Before Width: | Height: | Size: 232 KiB After Width: | Height: | Size: 197 KiB |
Before Width: | Height: | Size: 175 KiB After Width: | Height: | Size: 165 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 245 KiB After Width: | Height: | Size: 255 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 155 B After Width: | Height: | Size: 271 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 181 KiB After Width: | Height: | Size: 164 KiB |
Before Width: | Height: | Size: 190 KiB After Width: | Height: | Size: 219 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 9 KiB After Width: | Height: | Size: 8.6 KiB |
|
@ -1 +1 @@
|
||||||
Subproject commit 7673ace6ac831f3496870fe3c4c79e8423307c0d
|
Subproject commit 7fefdb4c643f4e623f179460b8e68cd51f4d5e9d
|
|
@ -3,9 +3,10 @@ from datatypes import *
|
||||||
Pickups = Enum("PICKUP", ["HEALTH", "ARMOR", "GRENADE", "SHOTGUN", "LASER", "NINJA"])
|
Pickups = Enum("PICKUP", ["HEALTH", "ARMOR", "GRENADE", "SHOTGUN", "LASER", "NINJA"])
|
||||||
Emotes = Enum("EMOTE", ["NORMAL", "PAIN", "HAPPY", "SURPRISE", "ANGRY", "BLINK"])
|
Emotes = Enum("EMOTE", ["NORMAL", "PAIN", "HAPPY", "SURPRISE", "ANGRY", "BLINK"])
|
||||||
Emoticons = Enum("EMOTICON", ["OOP", "EXCLAMATION", "HEARTS", "DROP", "DOTDOT", "MUSIC", "SORRY", "GHOST", "SUSHI", "SPLATTEE", "DEVILTEE", "ZOMG", "ZZZ", "WTF", "EYES", "QUESTION"])
|
Emoticons = Enum("EMOTICON", ["OOP", "EXCLAMATION", "HEARTS", "DROP", "DOTDOT", "MUSIC", "SORRY", "GHOST", "SUSHI", "SPLATTEE", "DEVILTEE", "ZOMG", "ZZZ", "WTF", "EYES", "QUESTION"])
|
||||||
Votes = Enum("VOTE", ["UNKNOWN", "START_OP", "START_KICK", "START_SPEC", "END_ABORT", "END_PASS", "END_FAIL"])
|
Votes = Enum("VOTE", ["UNKNOWN", "START_OP", "START_KICK", "START_SPEC", "END_ABORT", "END_PASS", "END_FAIL"]) # todo: add RUN_OP, RUN_KICK, RUN_SPEC; rem UNKNOWN
|
||||||
|
ChatModes = Enum("CHAT", ["NONE", "ALL", "TEAM", "WHISPER"])
|
||||||
|
|
||||||
PlayerFlags = Flags("PLAYERFLAG", ["ADMIN", "CHATTING", "SCOREBOARD", "READY", "DEAD", "WATCHING"])
|
PlayerFlags = Flags("PLAYERFLAG", ["ADMIN", "CHATTING", "SCOREBOARD", "READY", "DEAD", "WATCHING", "BOT"])
|
||||||
GameFlags = Flags("GAMEFLAG", ["TEAMS", "FLAGS", "SURVIVAL"])
|
GameFlags = Flags("GAMEFLAG", ["TEAMS", "FLAGS", "SURVIVAL"])
|
||||||
GameStateFlags = Flags("GAMESTATEFLAG", ["WARMUP", "SUDDENDEATH", "ROUNDOVER", "GAMEOVER", "PAUSED", "STARTCOUNTDOWN"])
|
GameStateFlags = Flags("GAMESTATEFLAG", ["WARMUP", "SUDDENDEATH", "ROUNDOVER", "GAMEOVER", "PAUSED", "STARTCOUNTDOWN"])
|
||||||
CoreEventFlags = Flags("COREEVENTFLAG", ["GROUND_JUMP", "AIR_JUMP", "HOOK_ATTACH_PLAYER", "HOOK_ATTACH_GROUND", "HOOK_HIT_NOHOOK"])
|
CoreEventFlags = Flags("COREEVENTFLAG", ["GROUND_JUMP", "AIR_JUMP", "HOOK_ATTACH_PLAYER", "HOOK_ATTACH_GROUND", "HOOK_HIT_NOHOOK"])
|
||||||
|
@ -37,7 +38,11 @@ enum
|
||||||
FLAG_ATSTAND,
|
FLAG_ATSTAND,
|
||||||
FLAG_TAKEN,
|
FLAG_TAKEN,
|
||||||
|
|
||||||
SPEC_FREEVIEW=-1,
|
SPEC_FREEVIEW=0,
|
||||||
|
SPEC_PLAYER,
|
||||||
|
SPEC_FLAGRED,
|
||||||
|
SPEC_FLAGBLUE,
|
||||||
|
NUM_SPECMODES,
|
||||||
};
|
};
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
@ -51,6 +56,7 @@ Enums = [
|
||||||
Emotes,
|
Emotes,
|
||||||
Emoticons,
|
Emoticons,
|
||||||
Votes,
|
Votes,
|
||||||
|
ChatModes,
|
||||||
GameMsgIDs,
|
GameMsgIDs,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -147,6 +153,8 @@ Objects = [
|
||||||
|
|
||||||
NetIntAny("m_HookX"),
|
NetIntAny("m_HookX"),
|
||||||
NetIntAny("m_HookY"),
|
NetIntAny("m_HookY"),
|
||||||
|
NetIntAny("m_HookDx"),
|
||||||
|
NetIntAny("m_HookDy"),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
NetObject("Character:CharacterCore", [
|
NetObject("Character:CharacterCore", [
|
||||||
|
@ -166,7 +174,8 @@ Objects = [
|
||||||
]),
|
]),
|
||||||
|
|
||||||
NetObject("SpectatorInfo", [
|
NetObject("SpectatorInfo", [
|
||||||
NetIntRange("m_SpectatorID", 'SPEC_FREEVIEW', 'MAX_CLIENTS-1'),
|
NetIntRange("m_SpecMode", 0, 'NUM_SPECMODES-1'),
|
||||||
|
NetIntRange("m_SpectatorID", -1, 'MAX_CLIENTS-1'),
|
||||||
NetIntAny("m_X"),
|
NetIntAny("m_X"),
|
||||||
NetIntAny("m_Y"),
|
NetIntAny("m_Y"),
|
||||||
]),
|
]),
|
||||||
|
@ -199,7 +208,7 @@ Objects = [
|
||||||
|
|
||||||
NetObject("De_TuneParams", [
|
NetObject("De_TuneParams", [
|
||||||
# todo: should be done differently
|
# todo: should be done differently
|
||||||
NetArray(NetIntAny("m_aTuneParams"), 33),
|
NetArray(NetIntAny("m_aTuneParams"), 32),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
## Events
|
## Events
|
||||||
|
@ -222,8 +231,12 @@ Objects = [
|
||||||
NetIntRange("m_SoundID", 0, 'NUM_SOUNDS-1'),
|
NetIntRange("m_SoundID", 0, 'NUM_SOUNDS-1'),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
NetEvent("DamageInd:Common", [
|
NetEvent("Damage:Common", [ # Unused yet
|
||||||
|
NetIntRange("m_ClientID", 0, 'MAX_CLIENTS-1'),
|
||||||
NetIntAny("m_Angle"),
|
NetIntAny("m_Angle"),
|
||||||
|
NetIntRange("m_HealthAmount", 0, 9),
|
||||||
|
NetIntRange("m_ArmorAmount", 0, 9),
|
||||||
|
NetBool("m_Self"),
|
||||||
]),
|
]),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -234,9 +247,14 @@ Messages = [
|
||||||
NetString("m_pMessage"),
|
NetString("m_pMessage"),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
NetMessage("Sv_Broadcast", [
|
||||||
|
NetString("m_pMessage"),
|
||||||
|
]),
|
||||||
|
|
||||||
NetMessage("Sv_Chat", [
|
NetMessage("Sv_Chat", [
|
||||||
NetIntRange("m_Team", 'TEAM_SPECTATORS', 'TEAM_BLUE'),
|
NetIntRange("m_Mode", 0, 'NUM_CHATS-1'),
|
||||||
NetIntRange("m_ClientID", -1, 'MAX_CLIENTS-1'),
|
NetIntRange("m_ClientID", -1, 'MAX_CLIENTS-1'),
|
||||||
|
NetIntRange("m_TargetID", -1, 'MAX_CLIENTS-1'),
|
||||||
NetStringStrict("m_pMessage"),
|
NetStringStrict("m_pMessage"),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
@ -313,6 +331,7 @@ Messages = [
|
||||||
NetArray(NetStringStrict("m_apSkinPartNames"), 6),
|
NetArray(NetStringStrict("m_apSkinPartNames"), 6),
|
||||||
NetArray(NetBool("m_aUseCustomColors"), 6),
|
NetArray(NetBool("m_aUseCustomColors"), 6),
|
||||||
NetArray(NetIntAny("m_aSkinPartColors"), 6),
|
NetArray(NetIntAny("m_aSkinPartColors"), 6),
|
||||||
|
NetBool("m_Silent"),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
NetMessage("Sv_GameInfo", [
|
NetMessage("Sv_GameInfo", [
|
||||||
|
@ -328,6 +347,7 @@ Messages = [
|
||||||
NetMessage("Sv_ClientDrop", [
|
NetMessage("Sv_ClientDrop", [
|
||||||
NetIntRange("m_ClientID", 0, 'MAX_CLIENTS-1'),
|
NetIntRange("m_ClientID", 0, 'MAX_CLIENTS-1'),
|
||||||
NetStringStrict("m_pReason"),
|
NetStringStrict("m_pReason"),
|
||||||
|
NetBool("m_Silent"),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
NetMessage("Sv_GameMsg", []),
|
NetMessage("Sv_GameMsg", []),
|
||||||
|
@ -335,17 +355,20 @@ Messages = [
|
||||||
## Demo messages
|
## Demo messages
|
||||||
NetMessage("De_ClientEnter", [
|
NetMessage("De_ClientEnter", [
|
||||||
NetStringStrict("m_pName"),
|
NetStringStrict("m_pName"),
|
||||||
|
NetIntRange("m_ClientID", -1, 'MAX_CLIENTS-1'),
|
||||||
NetIntRange("m_Team", 'TEAM_SPECTATORS', 'TEAM_BLUE'),
|
NetIntRange("m_Team", 'TEAM_SPECTATORS', 'TEAM_BLUE'),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
NetMessage("De_ClientLeave", [
|
NetMessage("De_ClientLeave", [
|
||||||
NetStringStrict("m_pName"),
|
NetStringStrict("m_pName"),
|
||||||
|
NetIntRange("m_ClientID", -1, 'MAX_CLIENTS-1'),
|
||||||
NetStringStrict("m_pReason"),
|
NetStringStrict("m_pReason"),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
### Client messages
|
### Client messages
|
||||||
NetMessage("Cl_Say", [
|
NetMessage("Cl_Say", [
|
||||||
NetBool("m_Team"),
|
NetIntRange("m_Mode", 0, 'NUM_CHATS-1'),
|
||||||
|
NetIntRange("m_Target", -1, 'MAX_CLIENTS-1'),
|
||||||
NetStringStrict("m_pMessage"),
|
NetStringStrict("m_pMessage"),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
@ -354,7 +377,8 @@ Messages = [
|
||||||
]),
|
]),
|
||||||
|
|
||||||
NetMessage("Cl_SetSpectatorMode", [
|
NetMessage("Cl_SetSpectatorMode", [
|
||||||
NetIntRange("m_SpectatorID", 'SPEC_FREEVIEW', 'MAX_CLIENTS-1'),
|
NetIntRange("m_SpecMode", 0, 'NUM_SPECMODES-1'),
|
||||||
|
NetIntRange("m_SpectatorID", -1, 'MAX_CLIENTS-1'),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
NetMessage("Cl_StartInfo", [
|
NetMessage("Cl_StartInfo", [
|
||||||
|
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.2 KiB |
|
@ -11,8 +11,8 @@
|
||||||
"custom_colors": "true",
|
"custom_colors": "true",
|
||||||
"hue": 0,
|
"hue": 0,
|
||||||
"sat": 0,
|
"sat": 0,
|
||||||
"lgt": 255,
|
"lgt": 64,
|
||||||
"alp": 127
|
"alp": 255
|
||||||
},
|
},
|
||||||
"hands": {
|
"hands": {
|
||||||
"filename": "standard",
|
"filename": "standard",
|
||||||
|
|
BIN
datasrc/skins/xmas_hat.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
datasrc/ui/gametypes/ctf.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
datasrc/ui/gametypes/dm.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
datasrc/ui/gametypes/lms.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
datasrc/ui/gametypes/lts.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
datasrc/ui/gametypes/mod.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
datasrc/ui/gametypes/tdm.png
Normal file
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.8 KiB |
BIN
datasrc/ui/icons/arrows.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
datasrc/ui/icons/chat_whisper.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
datasrc/ui/icons/friend.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
datasrc/ui/icons/level.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
datasrc/ui/icons/sidebar.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
datasrc/ui/themes/heavens.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
datasrc/ui/themes/heavens_day.map
Normal file
BIN
datasrc/ui/themes/heavens_night.map
Normal file
BIN
datasrc/ui/themes/jungle.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
datasrc/ui/themes/none.png
Normal file
After Width: | Height: | Size: 989 B |
|
@ -1,4 +1,4 @@
|
||||||
Copyright (C) 2007-2014 Magnus Auvinen
|
Copyright (C) 2007-2018 Magnus Auvinen
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,9 +18,14 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
All content under 'data' except the font (which has its own license) is
|
All content under 'data' and 'datasrc' except the font (which has its own license) is
|
||||||
released under CC-BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0/).
|
released under CC-BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0/).
|
||||||
|
|
||||||
|
Authors: android272, Chi11y (chi1), Crises, Daniel, Echchouik, Fisico,
|
||||||
|
Landil, Lappi, LordSk, maikka, matricks, Pocram, red_com,
|
||||||
|
serpis, SkizZ, somerunce, Sonix, Stephanator, teetow, Ubu,
|
||||||
|
Zatline
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
IMPORTANT NOTE! The source under src/engine/external are stripped
|
IMPORTANT NOTE! The source under src/engine/external are stripped
|
||||||
|
|
|
@ -4,11 +4,15 @@ FreeType = {
|
||||||
OptFind = function (name, required)
|
OptFind = function (name, required)
|
||||||
local check = function(option, settings)
|
local check = function(option, settings)
|
||||||
option.value = false
|
option.value = false
|
||||||
|
option.use_pkgconfig = false
|
||||||
option.use_ftconfig = false
|
option.use_ftconfig = false
|
||||||
option.use_winlib = 0
|
option.use_winlib = 0
|
||||||
option.lib_path = nil
|
option.lib_path = nil
|
||||||
|
|
||||||
if ExecuteSilent("freetype-config") > 0 and ExecuteSilent("freetype-config --cflags") == 0 then
|
if ExecuteSilent("pkg-config freetype2") == 0 then
|
||||||
|
option.value = true
|
||||||
|
option.use_pkgconfig = true
|
||||||
|
elseif ExecuteSilent("freetype-config") > 0 and ExecuteSilent("freetype-config --cflags") == 0 then
|
||||||
option.value = true
|
option.value = true
|
||||||
option.use_ftconfig = true
|
option.use_ftconfig = true
|
||||||
end
|
end
|
||||||
|
@ -23,15 +27,18 @@ FreeType = {
|
||||||
end
|
end
|
||||||
|
|
||||||
local apply = function(option, settings)
|
local apply = function(option, settings)
|
||||||
if option.use_ftconfig == true then
|
if option.use_pkgconfig == true then
|
||||||
|
settings.cc.flags:Add("`pkg-config --cflags freetype2`")
|
||||||
|
settings.link.flags:Add("`pkg-config --libs freetype2`")
|
||||||
|
elseif option.use_ftconfig == true then
|
||||||
settings.cc.flags:Add("`freetype-config --cflags`")
|
settings.cc.flags:Add("`freetype-config --cflags`")
|
||||||
settings.link.flags:Add("`freetype-config --libs`")
|
settings.link.flags:Add("`freetype-config --libs`")
|
||||||
elseif option.use_winlib > 0 then
|
elseif option.use_winlib > 0 then
|
||||||
settings.cc.includes:Add(FreeType.basepath .. "/include")
|
settings.cc.includes:Add(FreeType.basepath .. "/include")
|
||||||
if option.use_winlib == 32 then
|
if option.use_winlib == 32 then
|
||||||
settings.link.libpath:Add(FreeType.basepath .. "/lib32")
|
settings.link.libpath:Add(FreeType.basepath .. "/lib/x86")
|
||||||
else
|
else
|
||||||
settings.link.libpath:Add(FreeType.basepath .. "/lib64")
|
settings.link.libpath:Add(FreeType.basepath .. "/lib/x64")
|
||||||
end
|
end
|
||||||
settings.link.libs:Add("freetype")
|
settings.link.libs:Add("freetype")
|
||||||
end
|
end
|
||||||
|
@ -39,12 +46,14 @@ FreeType = {
|
||||||
|
|
||||||
local save = function(option, output)
|
local save = function(option, output)
|
||||||
output:option(option, "value")
|
output:option(option, "value")
|
||||||
|
output:option(option, "use_pkgconfig")
|
||||||
output:option(option, "use_ftconfig")
|
output:option(option, "use_ftconfig")
|
||||||
output:option(option, "use_winlib")
|
output:option(option, "use_winlib")
|
||||||
end
|
end
|
||||||
|
|
||||||
local display = function(option)
|
local display = function(option)
|
||||||
if option.value == true then
|
if option.value == true then
|
||||||
|
if option.use_pkgconfig == true then return "using pkg-config" end
|
||||||
if option.use_ftconfig == true then return "using freetype-config" end
|
if option.use_ftconfig == true then return "using freetype-config" end
|
||||||
if option.use_winlib == 32 then return "using supplied win32 libraries" end
|
if option.use_winlib == 32 then return "using supplied win32 libraries" end
|
||||||
if option.use_winlib == 64 then return "using supplied win64 libraries" end
|
if option.use_winlib == 64 then return "using supplied win64 libraries" end
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
1.2.15
|
2.0.5
|
||||||
|
|
21
other/teeworlds.appdata.xml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<application>
|
||||||
|
<id type="desktop">teeworlds.desktop</id>
|
||||||
|
<license>Zlib and CC-BY-SA-3.0</license>
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<summary>Online multiplayer shooter game</summary>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
Teeworlds is a free online multiplayer game. Battle with up to 16 players
|
||||||
|
in a variety of game modes, including Team Deathmatch and Capture The Flag.
|
||||||
|
You can even design your own maps!
|
||||||
|
</p>
|
||||||
|
</description>
|
||||||
|
<url type="homepage">https://www.teeworlds.com/</url>
|
||||||
|
<screenshots>
|
||||||
|
<screenshot>https://www.teeworlds.com/images/screens/screenshot_desert.png</screenshot>
|
||||||
|
<screenshot>https://www.teeworlds.com/images/screens/screenshot_grass.png</screenshot>
|
||||||
|
<screenshot>https://www.teeworlds.com/images/screens/screenshot_winter.png</screenshot>
|
||||||
|
<screenshot>https://www.teeworlds.com/images/screens/screenshot_jungle.png</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
</application>
|
9
other/teeworlds.desktop
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=Teeworlds
|
||||||
|
GenericName=Online multi-player 2D platform shooter
|
||||||
|
Type=Application
|
||||||
|
Terminal=false
|
||||||
|
Exec=teeworlds
|
||||||
|
Icon=teeworlds
|
||||||
|
Comment=Teeworlds: Jumping the Gun
|
||||||
|
Categories=Game;ArcadeGame;
|
|
@ -1,4 +1,4 @@
|
||||||
Teeworlds
|
Teeworlds [![CircleCI](https://circleci.com/gh/teeworlds/teeworlds.svg?style=svg)](https://circleci.com/gh/teeworlds/teeworlds)
|
||||||
=========
|
=========
|
||||||
|
|
||||||
A retro multiplayer shooter
|
A retro multiplayer shooter
|
||||||
|
@ -17,4 +17,8 @@ text including copyright information.
|
||||||
Please visit https://www.teeworlds.com/ for up-to-date information about
|
Please visit https://www.teeworlds.com/ for up-to-date information about
|
||||||
the game, including new versions, custom maps and much more.
|
the game, including new versions, custom maps and much more.
|
||||||
|
|
||||||
|
Instructions to build the game can be found at
|
||||||
|
https://teeworlds.com/?page=docs&wiki=compiling_everything. In
|
||||||
|
particular, you will need SDL2 and FreeType installed.
|
||||||
|
|
||||||
Originally written by Magnus Auvinen.
|
Originally written by Magnus Auvinen.
|
||||||
|
|
|
@ -52,7 +52,7 @@ def parse_source():
|
||||||
return l10n
|
return l10n
|
||||||
|
|
||||||
def load_languagefile(filename):
|
def load_languagefile(filename):
|
||||||
return json.load(open(filename))
|
return json.load(open(filename), strict=False) # accept \t tabs
|
||||||
|
|
||||||
def write_languagefile(outputfilename, l10n_src, old_l10n_data):
|
def write_languagefile(outputfilename, l10n_src, old_l10n_data):
|
||||||
outputfilename += '.po'
|
outputfilename += '.po'
|
||||||
|
@ -110,7 +110,10 @@ if __name__ == '__main__':
|
||||||
'Content-Transfer-Encoding': '8bit',
|
'Content-Transfer-Encoding': '8bit',
|
||||||
}
|
}
|
||||||
for (msg, ctxt), occurrences in l10n_src.items():
|
for (msg, ctxt), occurrences in l10n_src.items():
|
||||||
po.append(polib.POEntry(msgid=msg, msgstr="", occurrences=occurrences, msgctxt=ctxt))
|
commenttxt = ctxt
|
||||||
|
if(commenttxt):
|
||||||
|
commenttxt = 'Context: '+commenttxt
|
||||||
|
po.append(polib.POEntry(msgid=msg, msgstr="", occurrences=occurrences, msgctxt=ctxt, comment=commenttxt))
|
||||||
po.save('data/languages/base.pot')
|
po.save('data/languages/base.pot')
|
||||||
|
|
||||||
for filename in os.listdir("data/languages"):
|
for filename in os.listdir("data/languages"):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import shutil, optparse, os, re, sys, zipfile
|
import shutil, optparse, os, re, sys, zipfile
|
||||||
|
from distutils.dir_util import copy_tree
|
||||||
os.chdir(os.path.dirname(os.path.realpath(sys.argv[0])) + "/..")
|
os.chdir(os.path.dirname(os.path.realpath(sys.argv[0])) + "/..")
|
||||||
import twlib
|
import twlib
|
||||||
|
|
||||||
|
@ -88,6 +89,12 @@ def clean():
|
||||||
package = "%s-%s-%s" %(name, version, platform)
|
package = "%s-%s-%s" %(name, version, platform)
|
||||||
package_dir = package
|
package_dir = package
|
||||||
|
|
||||||
|
source_package_dir = "build/"
|
||||||
|
if platform == 'win32' or platform == 'linux_x86':
|
||||||
|
source_package_dir += "x86/release/"
|
||||||
|
else:
|
||||||
|
source_package_dir += "x86_64/release/"
|
||||||
|
|
||||||
print("cleaning target")
|
print("cleaning target")
|
||||||
shutil.rmtree(package_dir, True)
|
shutil.rmtree(package_dir, True)
|
||||||
os.mkdir(package_dir)
|
os.mkdir(package_dir)
|
||||||
|
@ -118,18 +125,17 @@ shutil.copy("license.txt", package_dir)
|
||||||
shutil.copy("storage.cfg", package_dir)
|
shutil.copy("storage.cfg", package_dir)
|
||||||
|
|
||||||
if include_data and not use_bundle:
|
if include_data and not use_bundle:
|
||||||
os.mkdir(os.path.join(package_dir, "data"))
|
copy_tree(source_package_dir+"data", package_dir+"/data")
|
||||||
copydir("data", package_dir)
|
copy_tree(languages_dir, package_dir+"/data/languages")
|
||||||
copyfiles(languages_dir, package_dir+"/data/languages")
|
copy_tree(maps_dir, package_dir+"/data/maps")
|
||||||
copyfiles(maps_dir, package_dir+"/data/maps")
|
|
||||||
if platform[:3] == "win":
|
if platform[:3] == "win":
|
||||||
shutil.copy("other/config_directory.bat", package_dir)
|
shutil.copy("other/config_directory.bat", package_dir)
|
||||||
shutil.copy("SDL.dll", package_dir)
|
shutil.copy(source_package_dir+"SDL2.dll", package_dir)
|
||||||
shutil.copy("freetype.dll", package_dir)
|
shutil.copy(source_package_dir+"freetype.dll", package_dir)
|
||||||
|
|
||||||
if include_exe and not use_bundle:
|
if include_exe and not use_bundle:
|
||||||
shutil.copy(name+exe_ext, package_dir)
|
shutil.copy(source_package_dir+name+exe_ext, package_dir)
|
||||||
shutil.copy(name+"_srv"+exe_ext, package_dir)
|
shutil.copy(source_package_dir+name+"_srv"+exe_ext, package_dir)
|
||||||
|
|
||||||
if include_src:
|
if include_src:
|
||||||
for p in ["src", "scripts", "datasrc", "other", "objs"]:
|
for p in ["src", "scripts", "datasrc", "other", "objs"]:
|
||||||
|
@ -140,7 +146,7 @@ if include_src:
|
||||||
|
|
||||||
if use_bundle:
|
if use_bundle:
|
||||||
bins = [name, name+'_srv', 'serverlaunch']
|
bins = [name, name+'_srv', 'serverlaunch']
|
||||||
platforms = ('x86', 'x86_64', 'ppc')
|
platforms = ('x86_64')
|
||||||
for bin in bins:
|
for bin in bins:
|
||||||
to_lipo = []
|
to_lipo = []
|
||||||
for p in platforms:
|
for p in platforms:
|
||||||
|
@ -155,19 +161,24 @@ if use_bundle:
|
||||||
clientbundle_bin_dir = os.path.join(clientbundle_content_dir, "MacOS")
|
clientbundle_bin_dir = os.path.join(clientbundle_content_dir, "MacOS")
|
||||||
clientbundle_resource_dir = os.path.join(clientbundle_content_dir, "Resources")
|
clientbundle_resource_dir = os.path.join(clientbundle_content_dir, "Resources")
|
||||||
clientbundle_framework_dir = os.path.join(clientbundle_content_dir, "Frameworks")
|
clientbundle_framework_dir = os.path.join(clientbundle_content_dir, "Frameworks")
|
||||||
|
binary_path = clientbundle_bin_dir + "/" + name+exe_ext
|
||||||
|
freetypelib_path = clientbundle_framework_dir + "/libfreetype.6.dylib"
|
||||||
os.mkdir(os.path.join(package_dir, "Teeworlds.app"))
|
os.mkdir(os.path.join(package_dir, "Teeworlds.app"))
|
||||||
os.mkdir(clientbundle_content_dir)
|
os.mkdir(clientbundle_content_dir)
|
||||||
os.mkdir(clientbundle_bin_dir)
|
os.mkdir(clientbundle_bin_dir)
|
||||||
os.mkdir(clientbundle_resource_dir)
|
os.mkdir(clientbundle_resource_dir)
|
||||||
os.mkdir(clientbundle_framework_dir)
|
os.mkdir(clientbundle_framework_dir)
|
||||||
os.mkdir(os.path.join(clientbundle_resource_dir, "data"))
|
copy_tree(source_package_dir+"data", clientbundle_resource_dir+"/data")
|
||||||
copydir("data", clientbundle_resource_dir)
|
copy_tree(languages_dir, clientbundle_resource_dir+"/data/languages")
|
||||||
os.chdir(languages_dir)
|
copy_tree(maps_dir, clientbundle_resource_dir+"/data/maps")
|
||||||
copydir("data", "../"+clientbundle_resource_dir)
|
|
||||||
os.chdir("..")
|
|
||||||
shutil.copy("other/icons/Teeworlds.icns", clientbundle_resource_dir)
|
shutil.copy("other/icons/Teeworlds.icns", clientbundle_resource_dir)
|
||||||
shutil.copy(name+exe_ext, clientbundle_bin_dir)
|
shutil.copy(source_package_dir+name+exe_ext, clientbundle_bin_dir)
|
||||||
os.system("cp -R /Library/Frameworks/SDL.framework " + clientbundle_framework_dir)
|
os.system("install_name_tool -change /usr/local/opt/freetype/lib/libfreetype.6.dylib @executable_path/../Frameworks/libfreetype.6.dylib " + binary_path)
|
||||||
|
os.system("install_name_tool -change /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib @executable_path/../Frameworks/libSDL2-2.0.0.dylib " + binary_path)
|
||||||
|
os.system("cp /usr/local/opt/freetype/lib/libfreetype.6.dylib " + clientbundle_framework_dir)
|
||||||
|
os.system("cp /usr/local/opt/libpng/lib/libpng16.16.dylib " + clientbundle_framework_dir)
|
||||||
|
os.system("cp /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib " + clientbundle_framework_dir)
|
||||||
|
os.system("install_name_tool -change /usr/local/opt/libpng/lib/libpng16.16.dylib @executable_path/../Frameworks/libpng16.16.dylib " + freetypelib_path)
|
||||||
file(os.path.join(clientbundle_content_dir, "Info.plist"), "w").write("""
|
file(os.path.join(clientbundle_content_dir, "Info.plist"), "w").write("""
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
@ -187,6 +198,10 @@ if use_bundle:
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>%s</string>
|
<string>%s</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.TeeworldsClient.app</string>
|
||||||
|
<key>NSHighResolutionCapable</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
""" % (version))
|
""" % (version))
|
||||||
|
@ -203,10 +218,10 @@ if use_bundle:
|
||||||
os.mkdir(os.path.join(serverbundle_resource_dir, "data"))
|
os.mkdir(os.path.join(serverbundle_resource_dir, "data"))
|
||||||
os.mkdir(os.path.join(serverbundle_resource_dir, "data/maps"))
|
os.mkdir(os.path.join(serverbundle_resource_dir, "data/maps"))
|
||||||
os.mkdir(os.path.join(serverbundle_resource_dir, "data/mapres"))
|
os.mkdir(os.path.join(serverbundle_resource_dir, "data/mapres"))
|
||||||
copydir("data/maps", serverbundle_resource_dir)
|
copy_tree(maps_dir, serverbundle_resource_dir+"/data/maps")
|
||||||
shutil.copy("other/icons/Teeworlds_srv.icns", serverbundle_resource_dir)
|
shutil.copy("other/icons/Teeworlds_srv.icns", serverbundle_resource_dir)
|
||||||
shutil.copy(name+"_srv"+exe_ext, serverbundle_bin_dir)
|
shutil.copy(source_package_dir+name+"_srv"+exe_ext, serverbundle_bin_dir)
|
||||||
shutil.copy("serverlaunch"+exe_ext, serverbundle_bin_dir + "/"+name+"_server")
|
shutil.copy(source_package_dir+"serverlaunch"+exe_ext, serverbundle_bin_dir + "/"+name+"_server")
|
||||||
file(os.path.join(serverbundle_content_dir, "Info.plist"), "w").write("""
|
file(os.path.join(serverbundle_content_dir, "Info.plist"), "w").write("""
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
|
|
@ -1,162 +1,180 @@
|
||||||
|
#!/bin/env python3
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from socket import *
|
from socket import *
|
||||||
import struct
|
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
NUM_MASTERSERVERS = 4
|
NUM_MASTERSERVERS = 4
|
||||||
MASTERSERVER_PORT = 8300
|
MASTERSERVER_PORT = 8283
|
||||||
|
|
||||||
TIMEOUT = 2
|
TIMEOUT = 2
|
||||||
|
|
||||||
SERVERTYPE_NORMAL = 0
|
# src/mastersrv/mastersrv.h
|
||||||
SERVERTYPE_LEGACY = 1
|
PACKET_GETLIST = b"\xff\xff\xff\xffreq2"
|
||||||
|
PACKET_LIST = b"\xff\xff\xff\xfflis2"
|
||||||
|
|
||||||
PACKET_GETLIST = "\x20\x00\x00\x00\x00\x00\xff\xff\xff\xffreqt"
|
PACKET_GETINFO = b"\xff\xff\xff\xffgie3"
|
||||||
PACKET_GETLIST2 = "\x20\x00\x00\x00\x00\x00\xff\xff\xff\xffreq2"
|
PACKET_INFO = b"\xff\xff\xff\xffinf3"
|
||||||
PACKET_GETINFO = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgief"
|
|
||||||
PACKET_GETINFO2 = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgie2" + "\x00"
|
|
||||||
PACKET_GETINFO3 = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgie3" + "\x00"
|
|
||||||
|
|
||||||
|
# see CNetBase::SendControlMsgWithToken
|
||||||
|
def pack_control_msg_with_token(token_srv,token_cl):
|
||||||
|
NET_PACKETFLAG_CONTROL = 1
|
||||||
|
NET_CTRLMSG_TOKEN = 5
|
||||||
|
NET_TOKENREQUEST_DATASIZE = 512
|
||||||
|
b = [0]*(4 + 3 + NET_TOKENREQUEST_DATASIZE)
|
||||||
|
# Header
|
||||||
|
b[0] = (NET_PACKETFLAG_CONTROL<<2)&0xfc
|
||||||
|
b[3] = (token_srv >> 24) & 0xff
|
||||||
|
b[4] = (token_srv >> 16) & 0xff
|
||||||
|
b[5] = (token_srv >> 8) & 0xff
|
||||||
|
b[6] = (token_srv) & 0xff
|
||||||
|
# Data
|
||||||
|
b[7] = NET_CTRLMSG_TOKEN
|
||||||
|
b[8] = (token_cl >> 24) & 0xff
|
||||||
|
b[9] = (token_cl >> 16) & 0xff
|
||||||
|
b[10] = (token_cl >> 8) & 0xff
|
||||||
|
b[11] = (token_cl) & 0xff
|
||||||
|
return bytes(b)
|
||||||
|
|
||||||
|
def unpack_control_msg_with_token(msg):
|
||||||
|
b = list(msg)
|
||||||
|
token_cl = (b[3] << 24) + (b[4] << 16) + (b[5] << 8) + (b[6])
|
||||||
|
token_srv = (b[8] << 24) + (b[9] << 16) + (b[10] << 8) + (b[11])
|
||||||
|
return token_cl,token_srv
|
||||||
|
|
||||||
|
# CNetBase::SendPacketConnless
|
||||||
|
def header_connless(token_srv, token_cl):
|
||||||
|
NET_PACKETFLAG_CONNLESS = 8
|
||||||
|
NET_PACKETVERSION = 1
|
||||||
|
b = [0]*9
|
||||||
|
# Header
|
||||||
|
b[0] = ((NET_PACKETFLAG_CONNLESS<<2)&0xfc) | (NET_PACKETVERSION&0x03)
|
||||||
|
b[1] = (token_srv >> 24) & 0xff
|
||||||
|
b[2] = (token_srv >> 16) & 0xff
|
||||||
|
b[3] = (token_srv >> 8) & 0xff
|
||||||
|
b[4] = (token_srv) & 0xff
|
||||||
|
# ResponseToken
|
||||||
|
b[5] = (token_cl >> 24) & 0xff
|
||||||
|
b[6] = (token_cl >> 16) & 0xff
|
||||||
|
b[7] = (token_cl >> 8) & 0xff
|
||||||
|
b[8] = (token_cl) & 0xff
|
||||||
|
return bytes(b)
|
||||||
|
|
||||||
|
# CVariableInt::Unpack from src/engine/shared/compression.cpp
|
||||||
|
def unpack_int(b):
|
||||||
|
l = list(b[:5])
|
||||||
|
i = 0
|
||||||
|
Sign = (l[i]>>6)&1;
|
||||||
|
res = l[i] & 0x3F;
|
||||||
|
|
||||||
|
for _ in (0,):
|
||||||
|
if not (l[i]&0x80):
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
res |= (l[i]&(0x7F))<<(6);
|
||||||
|
|
||||||
|
if not (l[i]&0x80):
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
res |= (l[i]&(0x7F))<<(6+7);
|
||||||
|
|
||||||
|
if not (l[i]&0x80):
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
res |= (l[i]&(0x7F))<<(6+7+7);
|
||||||
|
|
||||||
|
if not (l[i]&0x80):
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
res |= (l[i]&(0x7F))<<(6+7+7+7);
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
res ^= -Sign
|
||||||
|
return res, b[i:]
|
||||||
|
|
||||||
class Server_Info(threading.Thread):
|
class Server_Info(threading.Thread):
|
||||||
|
|
||||||
def __init__(self, address, type):
|
def __init__(self, address):
|
||||||
self.address = address
|
self.address = address
|
||||||
self.type = type
|
|
||||||
self.finished = False
|
self.finished = False
|
||||||
threading.Thread.__init__(self, target = self.run)
|
threading.Thread.__init__(self, target = self.run)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.info = None
|
self.info = None
|
||||||
if self.type == SERVERTYPE_NORMAL:
|
|
||||||
self.info = get_server_info3(self.address)
|
|
||||||
elif self.type == SERVERTYPE_LEGACY:
|
|
||||||
self.info = get_server_info(self.address)
|
self.info = get_server_info(self.address)
|
||||||
if self.info:
|
|
||||||
self.info = get_server_info2(self.address)
|
|
||||||
self.finished = True
|
self.finished = True
|
||||||
|
|
||||||
|
|
||||||
def get_server_info(address):
|
def get_server_info(address):
|
||||||
try:
|
try:
|
||||||
sock = socket(AF_INET, SOCK_DGRAM)
|
sock = socket(AF_INET, SOCK_DGRAM)
|
||||||
sock.settimeout(TIMEOUT);
|
sock.settimeout(TIMEOUT)
|
||||||
sock.sendto(PACKET_GETINFO, address)
|
token = random.randrange(0x100000000)
|
||||||
|
|
||||||
|
# Token request
|
||||||
|
sock.sendto(pack_control_msg_with_token(-1,token),address)
|
||||||
data, addr = sock.recvfrom(1024)
|
data, addr = sock.recvfrom(1024)
|
||||||
|
token_cl, token_srv = unpack_control_msg_with_token(data)
|
||||||
|
assert token_cl == token, "Server %s send wrong token: %d (%d expected)" % (address, token_cl, token)
|
||||||
|
|
||||||
|
# Get info request
|
||||||
|
sock.sendto(header_connless(token_srv, token_cl) + PACKET_GETINFO + b'\x00', address)
|
||||||
|
data, addr = sock.recvfrom(4096)
|
||||||
|
head = header_connless(token_cl, token_srv) + PACKET_INFO + b'\x00'
|
||||||
|
assert data[:len(head)] == head, "Server %s info header mismatch: %r != %r (expected)" % (address, data[:len(head)], head)
|
||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
data = data[14:] # skip header
|
data = data[len(head):] # skip header
|
||||||
slots = data.split("\x00")
|
|
||||||
|
slots = data.split(b"\x00", maxsplit=5)
|
||||||
|
|
||||||
server_info = {}
|
server_info = {}
|
||||||
server_info["version"] = slots[0]
|
server_info["address"] = address
|
||||||
server_info["name"] = slots[1]
|
server_info["version"] = slots[0].decode()
|
||||||
server_info["map"] = slots[2]
|
server_info["name"] = slots[1].decode()
|
||||||
server_info["gametype"] = slots[3]
|
server_info["hostname"] = slots[2].decode()
|
||||||
server_info["flags"] = int(slots[4])
|
server_info["map"] = slots[3].decode()
|
||||||
server_info["progression"] = int(slots[5])
|
server_info["gametype"] = slots[4].decode()
|
||||||
server_info["num_players"] = int(slots[6])
|
data = slots[5]
|
||||||
server_info["max_players"] = int(slots[7])
|
|
||||||
|
# these integers should fit in one byte each
|
||||||
|
server_info["flags"], server_info["skill"] = tuple(data[:2])
|
||||||
|
data = data[2:]
|
||||||
|
|
||||||
|
server_info["num_players"], data = unpack_int(data)
|
||||||
|
server_info["max_players"], data = unpack_int(data)
|
||||||
|
server_info["num_clients"], data = unpack_int(data)
|
||||||
|
server_info["max_clients"], data = unpack_int(data)
|
||||||
server_info["players"] = []
|
server_info["players"] = []
|
||||||
|
|
||||||
for i in xrange(0, server_info["num_players"]):
|
for i in range(server_info["num_clients"]):
|
||||||
player = {}
|
player = {}
|
||||||
player["name"] = slots[8+i*2]
|
slots = data.split(b"\x00", maxsplit=2)
|
||||||
player["score"] = int(slots[8+i*2+1])
|
player["name"] = slots[0].decode()
|
||||||
|
player["clan"] = slots[1].decode()
|
||||||
|
data = slots[2]
|
||||||
|
player["country"], data = unpack_int(data)
|
||||||
|
player["score"], data = unpack_int(data)
|
||||||
|
player["player"], data = unpack_int(data)
|
||||||
server_info["players"].append(player)
|
server_info["players"].append(player)
|
||||||
|
|
||||||
return server_info
|
return server_info
|
||||||
|
except AssertionError as e:
|
||||||
|
print(*e.args)
|
||||||
|
except OSError as e: # Timeout
|
||||||
|
print('> Server %s did not answer' % (address,))
|
||||||
except:
|
except:
|
||||||
|
# print('> Server %s did something wrong here' % (address,))
|
||||||
|
# import traceback
|
||||||
|
# traceback.print_exc()
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
sock.close()
|
sock.close()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_server_info2(address):
|
|
||||||
try:
|
|
||||||
sock = socket(AF_INET, SOCK_DGRAM)
|
|
||||||
sock.settimeout(TIMEOUT);
|
|
||||||
sock.sendto(PACKET_GETINFO2, address)
|
|
||||||
data, addr = sock.recvfrom(1024)
|
|
||||||
sock.close()
|
|
||||||
|
|
||||||
data = data[14:] # skip header
|
|
||||||
slots = data.split("\x00")
|
|
||||||
|
|
||||||
server_info = {}
|
|
||||||
server_info["token"] = slots[0]
|
|
||||||
server_info["version"] = slots[1]
|
|
||||||
server_info["name"] = slots[2]
|
|
||||||
server_info["map"] = slots[3]
|
|
||||||
server_info["gametype"] = slots[4]
|
|
||||||
server_info["flags"] = int(slots[5])
|
|
||||||
server_info["progression"] = int(slots[6])
|
|
||||||
server_info["num_players"] = int(slots[7])
|
|
||||||
server_info["max_players"] = int(slots[8])
|
|
||||||
server_info["players"] = []
|
|
||||||
|
|
||||||
for i in xrange(0, server_info["num_players"]):
|
|
||||||
player = {}
|
|
||||||
player["name"] = slots[9+i*2]
|
|
||||||
player["score"] = int(slots[9+i*2+1])
|
|
||||||
server_info["players"].append(player)
|
|
||||||
|
|
||||||
return server_info
|
|
||||||
|
|
||||||
except:
|
|
||||||
sock.close()
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_server_info3(address):
|
|
||||||
try:
|
|
||||||
sock = socket(AF_INET, SOCK_DGRAM)
|
|
||||||
sock.settimeout(TIMEOUT);
|
|
||||||
sock.sendto(PACKET_GETINFO3, address)
|
|
||||||
data, addr = sock.recvfrom(1400)
|
|
||||||
sock.close()
|
|
||||||
|
|
||||||
data = data[14:] # skip header
|
|
||||||
slots = data.split("\x00")
|
|
||||||
|
|
||||||
server_info = {}
|
|
||||||
server_info["token"] = slots[0]
|
|
||||||
server_info["version"] = slots[1]
|
|
||||||
server_info["name"] = slots[2]
|
|
||||||
server_info["map"] = slots[3]
|
|
||||||
server_info["gametype"] = slots[4]
|
|
||||||
server_info["flags"] = int(slots[5])
|
|
||||||
server_info["num_players"] = int(slots[6])
|
|
||||||
server_info["max_players"] = int(slots[7])
|
|
||||||
server_info["num_clients"] = int(slots[8])
|
|
||||||
server_info["max_clients"] = int(slots[9])
|
|
||||||
server_info["players"] = []
|
|
||||||
|
|
||||||
for i in xrange(0, server_info["num_clients"]):
|
|
||||||
player = {}
|
|
||||||
player["name"] = slots[10+i*5]
|
|
||||||
player["clan"] = slots[10+i*5+1]
|
|
||||||
player["country"] = int(slots[10+i*5+2])
|
|
||||||
player["score"] = int(slots[10+i*5+3])
|
|
||||||
if int(slots[10+i*5+4]):
|
|
||||||
player["player"] = True
|
|
||||||
else:
|
|
||||||
player["player"] = False
|
|
||||||
server_info["players"].append(player)
|
|
||||||
|
|
||||||
return server_info
|
|
||||||
|
|
||||||
except:
|
|
||||||
sock.close()
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Master_Server_Info(threading.Thread):
|
class Master_Server_Info(threading.Thread):
|
||||||
|
|
||||||
def __init__(self, address):
|
def __init__(self, address):
|
||||||
|
@ -165,64 +183,62 @@ class Master_Server_Info(threading.Thread):
|
||||||
threading.Thread.__init__(self, target = self.run)
|
threading.Thread.__init__(self, target = self.run)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.servers = get_list(self.address) + get_list2(self.address)
|
self.servers = get_list(self.address)
|
||||||
self.finished = True
|
self.finished = True
|
||||||
|
|
||||||
|
|
||||||
def get_list(address):
|
def get_list(address):
|
||||||
servers = []
|
servers = []
|
||||||
|
answer = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sock = socket(AF_INET, SOCK_DGRAM)
|
sock = socket(AF_INET, SOCK_DGRAM)
|
||||||
sock.settimeout(TIMEOUT)
|
sock.settimeout(TIMEOUT)
|
||||||
sock.sendto(PACKET_GETLIST, address)
|
|
||||||
|
token = random.randrange(0x100000000)
|
||||||
|
|
||||||
|
# Token request
|
||||||
|
sock.sendto(pack_control_msg_with_token(-1,token),address)
|
||||||
|
data, addr = sock.recvfrom(1024)
|
||||||
|
token_cl, token_srv = unpack_control_msg_with_token(data)
|
||||||
|
assert token_cl == token, "Master %s send wrong token: %d (%d expected)" % (address, token_cl, token)
|
||||||
|
answer = True
|
||||||
|
|
||||||
|
# Get list request
|
||||||
|
sock.sendto(header_connless(token_srv, token_cl) + PACKET_GETLIST, addr)
|
||||||
|
head = header_connless(token_cl, token_srv) + PACKET_LIST
|
||||||
|
|
||||||
while 1:
|
while 1:
|
||||||
data, addr = sock.recvfrom(1024)
|
data, addr = sock.recvfrom(1024)
|
||||||
|
# Header should keep consistent
|
||||||
|
assert data[:len(head)] == head, "Master %s list header mismatch: %r != %r (expected)" % (address, data[:len(head)], head)
|
||||||
|
|
||||||
data = data[14:]
|
data = data[len(head):]
|
||||||
num_servers = len(data) / 6
|
num_servers = len(data) // 18
|
||||||
|
|
||||||
for n in range(0, num_servers):
|
for n in range(0, num_servers):
|
||||||
ip = ".".join(map(str, map(ord, data[n*6:n*6+4])))
|
# IPv4
|
||||||
port = ord(data[n*6+5]) * 256 + ord(data[n*6+4])
|
if data[n*18:n*18+12] == b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff":
|
||||||
servers += [[(ip, port), SERVERTYPE_LEGACY]]
|
ip = ".".join(map(str, data[n*18+12:n*18+16]))
|
||||||
|
# IPv6
|
||||||
except:
|
|
||||||
sock.close()
|
|
||||||
|
|
||||||
return servers
|
|
||||||
|
|
||||||
|
|
||||||
def get_list2(address):
|
|
||||||
servers = []
|
|
||||||
|
|
||||||
try:
|
|
||||||
sock = socket(AF_INET, SOCK_DGRAM)
|
|
||||||
sock.settimeout(TIMEOUT)
|
|
||||||
sock.sendto(PACKET_GETLIST2, address)
|
|
||||||
|
|
||||||
while 1:
|
|
||||||
data, addr = sock.recvfrom(1400)
|
|
||||||
|
|
||||||
data = data[14:]
|
|
||||||
num_servers = len(data) / 18
|
|
||||||
|
|
||||||
for n in range(0, num_servers):
|
|
||||||
if data[n*18:n*18+12] == "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff":
|
|
||||||
ip = ".".join(map(str, map(ord, data[n*18+12:n*18+16])))
|
|
||||||
else:
|
else:
|
||||||
ip = ":".join(map(str, map(ord, data[n*18:n*18+16])))
|
ip = ":".join(map(str, data[n*18:n*18+16]))
|
||||||
port = (ord(data[n*18+16])<<8) + ord(data[n*18+17])
|
port = ((data[n*18+16])<<8) + data[n*18+17]
|
||||||
servers += [[(ip, port), SERVERTYPE_NORMAL]]
|
servers += [(ip, port)]
|
||||||
|
|
||||||
|
except AssertionError as e:
|
||||||
|
print(*e.args)
|
||||||
|
except OSError as e: # Timeout
|
||||||
|
if not answer:
|
||||||
|
print('> Master %s did not answer' % (address,))
|
||||||
except:
|
except:
|
||||||
|
# import traceback
|
||||||
|
# traceback.print_exc()
|
||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
return servers
|
return servers
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
master_servers = []
|
master_servers = []
|
||||||
|
|
||||||
for i in range(1, NUM_MASTERSERVERS+1):
|
for i in range(1, NUM_MASTERSERVERS+1):
|
||||||
|
@ -231,40 +247,62 @@ for i in range(1, NUM_MASTERSERVERS+1):
|
||||||
m.start()
|
m.start()
|
||||||
time.sleep(0.001) # avoid issues
|
time.sleep(0.001) # avoid issues
|
||||||
|
|
||||||
servers = []
|
servers = set()
|
||||||
|
|
||||||
while len(master_servers) != 0:
|
while len(master_servers) != 0:
|
||||||
if master_servers[0].finished == True:
|
if master_servers[0].finished == True:
|
||||||
if master_servers[0].servers:
|
if master_servers[0].servers:
|
||||||
servers += master_servers[0].servers
|
servers.update(master_servers[0].servers)
|
||||||
del master_servers[0]
|
del master_servers[0]
|
||||||
time.sleep(0.001) # be nice
|
time.sleep(0.001) # be nice
|
||||||
|
|
||||||
servers_info = []
|
servers_info = []
|
||||||
|
|
||||||
print str(len(servers)) + " servers"
|
print(str(len(servers)) + " servers")
|
||||||
|
|
||||||
for server in servers:
|
for server in servers:
|
||||||
s = Server_Info(server[0], server[1])
|
s = Server_Info(server)
|
||||||
servers_info.append(s)
|
servers_info.append(s)
|
||||||
s.start()
|
s.start()
|
||||||
time.sleep(0.001) # avoid issues
|
time.sleep(0.001) # avoid issues
|
||||||
|
|
||||||
num_players = 0
|
num_players = 0
|
||||||
num_clients = 0
|
num_clients = 0
|
||||||
|
num_botplayers = 0
|
||||||
|
num_botspectators = 0
|
||||||
|
|
||||||
while len(servers_info) != 0:
|
while len(servers_info) != 0:
|
||||||
if servers_info[0].finished == True:
|
if servers_info[0].finished == True:
|
||||||
|
|
||||||
if servers_info[0].info:
|
if servers_info[0].info:
|
||||||
num_players += servers_info[0].info["num_players"]
|
server_info = servers_info[0].info
|
||||||
if servers_info[0].type == SERVERTYPE_NORMAL:
|
# check num/max validity
|
||||||
num_clients += servers_info[0].info["num_clients"]
|
if server_info["num_players"] > server_info["max_players"] \
|
||||||
|
or server_info["num_clients"] > server_info["max_clients"] \
|
||||||
|
or server_info["max_players"] > server_info["max_clients"] \
|
||||||
|
or server_info["num_players"] < 0 \
|
||||||
|
or server_info["num_clients"] < 0 \
|
||||||
|
or server_info["max_clients"] < 0 \
|
||||||
|
or server_info["max_players"] < 0 \
|
||||||
|
or server_info["max_clients"] > 64:
|
||||||
|
server_info["bad"] = 'invalid num/max'
|
||||||
|
print('> Server %s has %s' % (server_info["address"], server_info["bad"]))
|
||||||
|
# check actual purity
|
||||||
|
elif server_info["gametype"] in ('DM', 'TDM', 'CTF', 'LMS', 'LTS') \
|
||||||
|
and server_info["max_players"] > 16:
|
||||||
|
server_info["bad"] = 'too many players for vanilla'
|
||||||
|
print('> Server %s has %s' % (server_info["address"], server_info["bad"]))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
num_clients += servers_info[0].info["num_players"]
|
num_players += server_info["num_players"]
|
||||||
|
num_clients += server_info["num_clients"]
|
||||||
|
for p in servers_info[0].info["players"]:
|
||||||
|
if p["player"] == 2:
|
||||||
|
num_botplayers += 1
|
||||||
|
if p["player"] == 3:
|
||||||
|
num_botspectators += 1
|
||||||
|
|
||||||
del servers_info[0]
|
del servers_info[0]
|
||||||
|
|
||||||
time.sleep(0.001) # be nice
|
time.sleep(0.001) # be nice
|
||||||
|
|
||||||
print str(num_players) + " players and " + str(num_clients-num_players) + " spectators"
|
print('%d players (%d bots) and %d spectators (%d bots)' % (num_players, num_botplayers, num_clients - num_players, num_botspectators))
|
||||||
|
|
|
@ -56,4 +56,97 @@ inline vec4 HexToRgba(int hex)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: HsvToRgb
|
||||||
|
Converts Hsv to Rgb
|
||||||
|
*/
|
||||||
|
inline vec3 HsvToRgb(vec3 hsv)
|
||||||
|
{
|
||||||
|
int h = int(hsv.x * 6.0f);
|
||||||
|
float f = hsv.x * 6.0f - h;
|
||||||
|
float p = hsv.z * (1.0f - hsv.y);
|
||||||
|
float q = hsv.z * (1.0f - hsv.y * f);
|
||||||
|
float t = hsv.z * (1.0f - hsv.y * (1.0f - f));
|
||||||
|
|
||||||
|
vec3 rgb = vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
switch(h % 6)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
rgb.r = hsv.z;
|
||||||
|
rgb.g = t;
|
||||||
|
rgb.b = p;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
rgb.r = q;
|
||||||
|
rgb.g = hsv.z;
|
||||||
|
rgb.b = p;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
rgb.r = p;
|
||||||
|
rgb.g = hsv.z;
|
||||||
|
rgb.b = t;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
rgb.r = p;
|
||||||
|
rgb.g = q;
|
||||||
|
rgb.b = hsv.z;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
rgb.r = t;
|
||||||
|
rgb.g = p;
|
||||||
|
rgb.b = hsv.z;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
rgb.r = hsv.z;
|
||||||
|
rgb.g = p;
|
||||||
|
rgb.b = q;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: RgbToHsv
|
||||||
|
Converts Rgb to Hsv
|
||||||
|
*/
|
||||||
|
inline vec3 RgbToHsv(vec3 rgb)
|
||||||
|
{
|
||||||
|
float h_min = min(min(rgb.r, rgb.g), rgb.b);
|
||||||
|
float h_max = max(max(rgb.r, rgb.g), rgb.b);
|
||||||
|
|
||||||
|
// hue
|
||||||
|
float hue = 0.0f;
|
||||||
|
|
||||||
|
if(h_max == h_min)
|
||||||
|
hue = 0.0f;
|
||||||
|
else if(h_max == rgb.r)
|
||||||
|
hue = (rgb.g-rgb.b) / (h_max-h_min);
|
||||||
|
else if(h_max == rgb.g)
|
||||||
|
hue = 2.0f + (rgb.b-rgb.r) / (h_max-h_min);
|
||||||
|
else
|
||||||
|
hue = 4.0f + (rgb.r-rgb.g) / (h_max-h_min);
|
||||||
|
|
||||||
|
hue /= 6.0f;
|
||||||
|
|
||||||
|
if(hue < 0.0f)
|
||||||
|
hue += 1.0f;
|
||||||
|
|
||||||
|
// saturation
|
||||||
|
float s = 0.0f;
|
||||||
|
if(h_max != 0.0f)
|
||||||
|
s = (h_max - h_min)/h_max;
|
||||||
|
|
||||||
|
// lightness
|
||||||
|
float l = h_max;
|
||||||
|
|
||||||
|
return vec3(hue, s, l);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -140,6 +140,14 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__arm__)
|
||||||
|
#define CONF_ARCH_ARM 1
|
||||||
|
#define CONF_ARCH_STRING "arm"
|
||||||
|
#if !defined(CONF_ARCH_ENDIAN_LITTLE) && !defined(CONF_ARCH_ENDIAN_BIG)
|
||||||
|
#define CONF_ARCH_ENDIAN_LITTLE 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONF_FAMILY_STRING
|
#ifndef CONF_FAMILY_STRING
|
||||||
#define CONF_FAMILY_STRING "unknown"
|
#define CONF_FAMILY_STRING "unknown"
|
||||||
|
|
|
@ -47,6 +47,7 @@ inline T bezier(const T p0, const T p1, const T p2, const T p3, TB amount)
|
||||||
return mix(c20, c21, amount); // c30
|
return mix(c20, c21, amount); // c30
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int random_int() { return (((rand() & 0xffff) << 16) | (rand() & 0xffff)) & 0x7FFFFFFF; };
|
||||||
inline float frandom() { return rand()/(float)(RAND_MAX); }
|
inline float frandom() { return rand()/(float)(RAND_MAX); }
|
||||||
|
|
||||||
// float to fixed
|
// float to fixed
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <wincrypt.h>
|
||||||
#else
|
#else
|
||||||
#error NOT IMPLEMENTED
|
#error NOT IMPLEMENTED
|
||||||
#endif
|
#endif
|
||||||
|
@ -59,7 +60,6 @@ static DBG_LOGGER loggers[16];
|
||||||
static int num_loggers = 0;
|
static int num_loggers = 0;
|
||||||
|
|
||||||
static NETSTATS network_stats = {0};
|
static NETSTATS network_stats = {0};
|
||||||
static MEMSTATS memory_stats = {0};
|
|
||||||
|
|
||||||
static NETSOCKET invalid_socket = {NETTYPE_INVALID, -1, -1};
|
static NETSOCKET invalid_socket = {NETTYPE_INVALID, -1, -1};
|
||||||
|
|
||||||
|
@ -105,6 +105,94 @@ void dbg_msg(const char *sys, const char *fmt, ...)
|
||||||
loggers[i](str);
|
loggers[i](str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
|
static void logger_win_console(const char *line)
|
||||||
|
{
|
||||||
|
#define _MAX_LENGTH 1024
|
||||||
|
#define _MAX_LENGTH_ERROR (_MAX_LENGTH+32)
|
||||||
|
|
||||||
|
static const int UNICODE_REPLACEMENT_CHAR = 0xfffd;
|
||||||
|
|
||||||
|
static const char *STR_TOO_LONG = "(str too long)";
|
||||||
|
static const char *INVALID_UTF8 = "(invalid utf8)";
|
||||||
|
|
||||||
|
wchar_t wline[_MAX_LENGTH_ERROR];
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
const char *read = line;
|
||||||
|
const char *error = STR_TOO_LONG;
|
||||||
|
while(len < _MAX_LENGTH)
|
||||||
|
{
|
||||||
|
// Read a character. This also advances the read pointer
|
||||||
|
int glyph = str_utf8_decode(&read);
|
||||||
|
if(glyph < 0)
|
||||||
|
{
|
||||||
|
// If there was an error decoding the UTF-8 sequence,
|
||||||
|
// emit a replacement character. Since the
|
||||||
|
// str_utf8_decode function will not work after such
|
||||||
|
// an error, end the string here.
|
||||||
|
glyph = UNICODE_REPLACEMENT_CHAR;
|
||||||
|
error = INVALID_UTF8;
|
||||||
|
wline[len] = glyph;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(glyph == 0)
|
||||||
|
{
|
||||||
|
// A character code of 0 signals the end of the string.
|
||||||
|
error = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(glyph > 0xffff)
|
||||||
|
{
|
||||||
|
// Since the windows console does not really support
|
||||||
|
// UTF-16, don't mind doing actual UTF-16 encoding,
|
||||||
|
// but rather emit a replacement character.
|
||||||
|
glyph = UNICODE_REPLACEMENT_CHAR;
|
||||||
|
}
|
||||||
|
else if(glyph == 0x2022)
|
||||||
|
{
|
||||||
|
// The 'bullet' character might get converted to a 'beep',
|
||||||
|
// so it will be replaced by the 'bullet operator'.
|
||||||
|
glyph = 0x2219;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Again, since the windows console does not really support
|
||||||
|
// UTF-16, but rather something along the lines of UCS-2,
|
||||||
|
// simply put the character into the output.
|
||||||
|
wline[len++] = glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(error)
|
||||||
|
{
|
||||||
|
read = error;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Errors are simple ascii, no need for UTF-8
|
||||||
|
// decoding
|
||||||
|
char character = *read;
|
||||||
|
if(character == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
dbg_assert(len < _MAX_LENGTH_ERROR, "str too short for error");
|
||||||
|
wline[len++] = character;
|
||||||
|
read++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminate the line
|
||||||
|
dbg_assert(len < _MAX_LENGTH_ERROR, "str too short for \\r");
|
||||||
|
wline[len++] = '\r';
|
||||||
|
dbg_assert(len < _MAX_LENGTH_ERROR, "str too short for \\n");
|
||||||
|
wline[len++] = '\n';
|
||||||
|
|
||||||
|
// Ignore any error that might occur
|
||||||
|
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), wline, len, 0, 0);
|
||||||
|
|
||||||
|
#undef _MAX_LENGTH
|
||||||
|
#undef _MAX_LENGTH_ERROR
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void logger_stdout(const char *line)
|
static void logger_stdout(const char *line)
|
||||||
{
|
{
|
||||||
printf("%s\n", line);
|
printf("%s\n", line);
|
||||||
|
@ -128,7 +216,18 @@ static void logger_file(const char *line)
|
||||||
io_flush(logfile);
|
io_flush(logfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dbg_logger_stdout() { dbg_logger(logger_stdout); }
|
void dbg_logger_stdout()
|
||||||
|
{
|
||||||
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
|
if(GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == FILE_TYPE_CHAR)
|
||||||
|
{
|
||||||
|
dbg_logger(logger_win_console);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
dbg_logger(logger_stdout);
|
||||||
|
}
|
||||||
|
|
||||||
void dbg_logger_debugger() { dbg_logger(logger_debugger); }
|
void dbg_logger_debugger() { dbg_logger(logger_debugger); }
|
||||||
void dbg_logger_file(const char *filename)
|
void dbg_logger_file(const char *filename)
|
||||||
{
|
{
|
||||||
|
@ -160,79 +259,13 @@ static const int MEM_GUARD_VAL = 0xbaadc0de;
|
||||||
|
|
||||||
void *mem_alloc_debug(const char *filename, int line, unsigned size, unsigned alignment)
|
void *mem_alloc_debug(const char *filename, int line, unsigned size, unsigned alignment)
|
||||||
{
|
{
|
||||||
/* TODO: fix alignment */
|
return malloc(size);
|
||||||
/* TODO: add debugging */
|
|
||||||
MEMTAIL *tail;
|
|
||||||
MEMHEADER *header = (struct MEMHEADER *)malloc(size+sizeof(MEMHEADER)+sizeof(MEMTAIL));
|
|
||||||
dbg_assert(header != 0, "mem_alloc failure");
|
|
||||||
if(!header)
|
|
||||||
return NULL;
|
|
||||||
tail = (struct MEMTAIL *)(((char*)(header+1))+size);
|
|
||||||
header->size = size;
|
|
||||||
header->filename = filename;
|
|
||||||
header->line = line;
|
|
||||||
|
|
||||||
memory_stats.allocated += header->size;
|
|
||||||
memory_stats.total_allocations++;
|
|
||||||
memory_stats.active_allocations++;
|
|
||||||
|
|
||||||
tail->guard = MEM_GUARD_VAL;
|
|
||||||
|
|
||||||
header->prev = (MEMHEADER *)0;
|
|
||||||
header->next = first;
|
|
||||||
if(first)
|
|
||||||
first->prev = header;
|
|
||||||
first = header;
|
|
||||||
|
|
||||||
/*dbg_msg("mem", "++ %p", header+1); */
|
|
||||||
return header+1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_free(void *p)
|
void mem_free(void *p)
|
||||||
{
|
{
|
||||||
if(p)
|
free(p);
|
||||||
{
|
|
||||||
MEMHEADER *header = (MEMHEADER *)p - 1;
|
|
||||||
MEMTAIL *tail = (MEMTAIL *)(((char*)(header+1))+header->size);
|
|
||||||
|
|
||||||
if(tail->guard != MEM_GUARD_VAL)
|
|
||||||
dbg_msg("mem", "!! %p", p);
|
|
||||||
/* dbg_msg("mem", "-- %p", p); */
|
|
||||||
memory_stats.allocated -= header->size;
|
|
||||||
memory_stats.active_allocations--;
|
|
||||||
|
|
||||||
if(header->prev)
|
|
||||||
header->prev->next = header->next;
|
|
||||||
else
|
|
||||||
first = header->next;
|
|
||||||
if(header->next)
|
|
||||||
header->next->prev = header->prev;
|
|
||||||
|
|
||||||
free(header);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void mem_debug_dump(IOHANDLE file)
|
|
||||||
{
|
|
||||||
char buf[1024];
|
|
||||||
MEMHEADER *header = first;
|
|
||||||
if(!file)
|
|
||||||
file = io_open("memory.txt", IOFLAG_WRITE);
|
|
||||||
|
|
||||||
if(file)
|
|
||||||
{
|
|
||||||
while(header)
|
|
||||||
{
|
|
||||||
str_format(buf, sizeof(buf), "%s(%d): %d", header->filename, header->line, header->size);
|
|
||||||
io_write(file, buf, strlen(buf));
|
|
||||||
io_write_newline(file);
|
|
||||||
header = header->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
io_close(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mem_copy(void *dest, const void *source, unsigned size)
|
void mem_copy(void *dest, const void *source, unsigned size)
|
||||||
{
|
{
|
||||||
|
@ -369,14 +402,44 @@ int io_flush(IOHANDLE io)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct THREAD_RUN
|
||||||
|
{
|
||||||
|
void (*threadfunc)(void *);
|
||||||
|
void *u;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(CONF_FAMILY_UNIX)
|
||||||
|
static void *thread_run(void *user)
|
||||||
|
#elif defined(CONF_FAMILY_WINDOWS)
|
||||||
|
static unsigned long __stdcall thread_run(void *user)
|
||||||
|
#else
|
||||||
|
#error not implemented
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
struct THREAD_RUN *data = user;
|
||||||
|
void (*threadfunc)(void *) = data->threadfunc;
|
||||||
|
void *u = data->u;
|
||||||
|
free(data);
|
||||||
|
threadfunc(u);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void *thread_init(void (*threadfunc)(void *), void *u)
|
void *thread_init(void (*threadfunc)(void *), void *u)
|
||||||
{
|
{
|
||||||
|
struct THREAD_RUN *data = malloc(sizeof(*data));
|
||||||
|
data->threadfunc = threadfunc;
|
||||||
|
data->u = u;
|
||||||
#if defined(CONF_FAMILY_UNIX)
|
#if defined(CONF_FAMILY_UNIX)
|
||||||
|
{
|
||||||
pthread_t id;
|
pthread_t id;
|
||||||
pthread_create(&id, NULL, (void *(*)(void*))threadfunc, u);
|
if(pthread_create(&id, NULL, thread_run, data) != 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return (void*)id;
|
return (void*)id;
|
||||||
|
}
|
||||||
#elif defined(CONF_FAMILY_WINDOWS)
|
#elif defined(CONF_FAMILY_WINDOWS)
|
||||||
return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc, u, 0, NULL);
|
return CreateThread(NULL, 0, thread_run, data, 0, NULL);
|
||||||
#else
|
#else
|
||||||
#error not implemented
|
#error not implemented
|
||||||
#endif
|
#endif
|
||||||
|
@ -853,7 +916,7 @@ static int priv_net_close_all_sockets(NETSOCKET sock)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, int sockaddrlen)
|
static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, int sockaddrlen, int use_random_port)
|
||||||
{
|
{
|
||||||
int sock, e;
|
int sock, e;
|
||||||
|
|
||||||
|
@ -883,27 +946,46 @@ static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, i
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* bind the socket */
|
/* bind the socket */
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
/* pick random port */
|
||||||
|
if(use_random_port)
|
||||||
|
{
|
||||||
|
int port = htons(rand()%16384+49152); /* 49152 to 65535 */
|
||||||
|
if(domain == AF_INET)
|
||||||
|
((struct sockaddr_in *)(addr))->sin_port = port;
|
||||||
|
else
|
||||||
|
((struct sockaddr_in6 *)(addr))->sin6_port = port;
|
||||||
|
}
|
||||||
|
|
||||||
e = bind(sock, addr, sockaddrlen);
|
e = bind(sock, addr, sockaddrlen);
|
||||||
if(e != 0)
|
if(e == 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
char buf[128];
|
char buf[128];
|
||||||
int error = WSAGetLastError();
|
int error = WSAGetLastError();
|
||||||
|
if(error == WSAEADDRINUSE && use_random_port)
|
||||||
|
continue;
|
||||||
if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, buf, sizeof(buf), 0) == 0)
|
if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, buf, sizeof(buf), 0) == 0)
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
|
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
|
||||||
#else
|
#else
|
||||||
|
if(errno == EADDRINUSE && use_random_port)
|
||||||
|
continue;
|
||||||
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
|
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
priv_net_close_socket(sock);
|
priv_net_close_socket(sock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* return the newly created socket */
|
/* return the newly created socket */
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
NETSOCKET net_udp_create(NETADDR bindaddr)
|
NETSOCKET net_udp_create(NETADDR bindaddr, int use_random_port)
|
||||||
{
|
{
|
||||||
NETSOCKET sock = invalid_socket;
|
NETSOCKET sock = invalid_socket;
|
||||||
NETADDR tmpbindaddr = bindaddr;
|
NETADDR tmpbindaddr = bindaddr;
|
||||||
|
@ -918,7 +1000,7 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
|
||||||
/* bind, we should check for error */
|
/* bind, we should check for error */
|
||||||
tmpbindaddr.type = NETTYPE_IPV4;
|
tmpbindaddr.type = NETTYPE_IPV4;
|
||||||
netaddr_to_sockaddr_in(&tmpbindaddr, &addr);
|
netaddr_to_sockaddr_in(&tmpbindaddr, &addr);
|
||||||
socket = priv_net_create_socket(AF_INET, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr));
|
socket = priv_net_create_socket(AF_INET, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr), use_random_port);
|
||||||
if(socket >= 0)
|
if(socket >= 0)
|
||||||
{
|
{
|
||||||
sock.type |= NETTYPE_IPV4;
|
sock.type |= NETTYPE_IPV4;
|
||||||
|
@ -940,7 +1022,7 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
|
||||||
/* bind, we should check for error */
|
/* bind, we should check for error */
|
||||||
tmpbindaddr.type = NETTYPE_IPV6;
|
tmpbindaddr.type = NETTYPE_IPV6;
|
||||||
netaddr_to_sockaddr_in6(&tmpbindaddr, &addr);
|
netaddr_to_sockaddr_in6(&tmpbindaddr, &addr);
|
||||||
socket = priv_net_create_socket(AF_INET6, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr));
|
socket = priv_net_create_socket(AF_INET6, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr), use_random_port);
|
||||||
if(socket >= 0)
|
if(socket >= 0)
|
||||||
{
|
{
|
||||||
sock.type |= NETTYPE_IPV6;
|
sock.type |= NETTYPE_IPV6;
|
||||||
|
@ -1077,7 +1159,7 @@ NETSOCKET net_tcp_create(NETADDR bindaddr)
|
||||||
/* bind, we should check for error */
|
/* bind, we should check for error */
|
||||||
tmpbindaddr.type = NETTYPE_IPV4;
|
tmpbindaddr.type = NETTYPE_IPV4;
|
||||||
netaddr_to_sockaddr_in(&tmpbindaddr, &addr);
|
netaddr_to_sockaddr_in(&tmpbindaddr, &addr);
|
||||||
socket = priv_net_create_socket(AF_INET, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr));
|
socket = priv_net_create_socket(AF_INET, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr), 0);
|
||||||
if(socket >= 0)
|
if(socket >= 0)
|
||||||
{
|
{
|
||||||
sock.type |= NETTYPE_IPV4;
|
sock.type |= NETTYPE_IPV4;
|
||||||
|
@ -1093,7 +1175,7 @@ NETSOCKET net_tcp_create(NETADDR bindaddr)
|
||||||
/* bind, we should check for error */
|
/* bind, we should check for error */
|
||||||
tmpbindaddr.type = NETTYPE_IPV6;
|
tmpbindaddr.type = NETTYPE_IPV6;
|
||||||
netaddr_to_sockaddr_in6(&tmpbindaddr, &addr);
|
netaddr_to_sockaddr_in6(&tmpbindaddr, &addr);
|
||||||
socket = priv_net_create_socket(AF_INET6, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr));
|
socket = priv_net_create_socket(AF_INET6, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr), 0);
|
||||||
if(socket >= 0)
|
if(socket >= 0)
|
||||||
{
|
{
|
||||||
sock.type |= NETTYPE_IPV6;
|
sock.type |= NETTYPE_IPV6;
|
||||||
|
@ -1357,19 +1439,46 @@ int fs_storage_path(const char *appname, char *path, int max)
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
char *home = getenv("HOME");
|
char *home = getenv("HOME");
|
||||||
#if !defined(CONF_PLATFORM_MACOSX)
|
|
||||||
int i;
|
|
||||||
#endif
|
|
||||||
if(!home)
|
if(!home)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#if defined(CONF_PLATFORM_MACOSX)
|
#if defined(CONF_PLATFORM_MACOSX)
|
||||||
snprintf(path, max, "%s/Library/Application Support/%s", home, appname);
|
snprintf(path, max, "%s/Library/Application Support/%s", home, appname);
|
||||||
#else
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int i;
|
||||||
|
char *xdgdatahome = getenv("XDG_DATA_HOME");
|
||||||
|
char xdgpath[max];
|
||||||
|
|
||||||
|
/* old folder location */
|
||||||
snprintf(path, max, "%s/.%s", home, appname);
|
snprintf(path, max, "%s/.%s", home, appname);
|
||||||
for(i = strlen(home)+2; path[i]; i++)
|
for(i = strlen(home)+2; path[i]; i++)
|
||||||
path[i] = tolower(path[i]);
|
path[i] = tolower(path[i]);
|
||||||
#endif
|
|
||||||
|
if(!xdgdatahome)
|
||||||
|
{
|
||||||
|
/* use default location */
|
||||||
|
snprintf(xdgpath, max, "%s/.local/share/%s", home, appname);
|
||||||
|
for(i = strlen(home)+14; xdgpath[i]; i++)
|
||||||
|
xdgpath[i] = tolower(xdgpath[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(xdgpath, max, "%s/%s", xdgdatahome, appname);
|
||||||
|
for(i = strlen(xdgdatahome)+1; xdgpath[i]; i++)
|
||||||
|
xdgpath[i] = tolower(xdgpath[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for old location / backward compatibility */
|
||||||
|
if(fs_is_dir(path))
|
||||||
|
{
|
||||||
|
/* use old folder path */
|
||||||
|
/* for backward compatibility */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(path, max, "%s", xdgpath);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1549,6 +1658,18 @@ int time_houroftheday()
|
||||||
return time_info->tm_hour;
|
return time_info->tm_hour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int time_isxmasday()
|
||||||
|
{
|
||||||
|
time_t time_data;
|
||||||
|
struct tm *time_info;
|
||||||
|
|
||||||
|
time(&time_data);
|
||||||
|
time_info = localtime(&time_data);
|
||||||
|
if(time_info->tm_mon == 11 && time_info->tm_mday >= 24 && time_info->tm_mday <= 26)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void str_append(char *dst, const char *src, int dst_size)
|
void str_append(char *dst, const char *src, int dst_size)
|
||||||
{
|
{
|
||||||
int s = strlen(dst);
|
int s = strlen(dst);
|
||||||
|
@ -1847,58 +1968,11 @@ int mem_comp(const void *a, const void *b, int size)
|
||||||
return memcmp(a,b,size);
|
return memcmp(a,b,size);
|
||||||
}
|
}
|
||||||
|
|
||||||
const MEMSTATS *mem_stats()
|
|
||||||
{
|
|
||||||
return &memory_stats;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_stats(NETSTATS *stats_inout)
|
void net_stats(NETSTATS *stats_inout)
|
||||||
{
|
{
|
||||||
*stats_inout = network_stats;
|
*stats_inout = network_stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gui_messagebox(const char *title, const char *message)
|
|
||||||
{
|
|
||||||
#if defined(CONF_PLATFORM_MACOSX)
|
|
||||||
DialogRef theItem;
|
|
||||||
DialogItemIndex itemIndex;
|
|
||||||
|
|
||||||
/* FIXME: really needed? can we rely on glfw? */
|
|
||||||
/* HACK - get events without a bundle */
|
|
||||||
ProcessSerialNumber psn;
|
|
||||||
GetCurrentProcess(&psn);
|
|
||||||
TransformProcessType(&psn,kProcessTransformToForegroundApplication);
|
|
||||||
SetFrontProcess(&psn);
|
|
||||||
/* END HACK */
|
|
||||||
|
|
||||||
CreateStandardAlert(kAlertStopAlert,
|
|
||||||
CFStringCreateWithCString(NULL, title, kCFStringEncodingASCII),
|
|
||||||
CFStringCreateWithCString(NULL, message, kCFStringEncodingASCII),
|
|
||||||
NULL,
|
|
||||||
&theItem);
|
|
||||||
|
|
||||||
RunStandardAlert(theItem, NULL, &itemIndex);
|
|
||||||
#elif defined(CONF_FAMILY_UNIX)
|
|
||||||
static char cmd[1024];
|
|
||||||
int err;
|
|
||||||
/* use xmessage which is available on nearly every X11 system */
|
|
||||||
snprintf(cmd, sizeof(cmd), "xmessage -center -title '%s' '%s'",
|
|
||||||
title,
|
|
||||||
message);
|
|
||||||
|
|
||||||
err = system(cmd);
|
|
||||||
dbg_msg("gui/msgbox", "result = %i", err);
|
|
||||||
#elif defined(CONF_FAMILY_WINDOWS)
|
|
||||||
MessageBox(NULL,
|
|
||||||
message,
|
|
||||||
title,
|
|
||||||
MB_ICONEXCLAMATION | MB_OK);
|
|
||||||
#else
|
|
||||||
/* this is not critical */
|
|
||||||
#warning not implemented
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int str_isspace(char c) { return c == ' ' || c == '\n' || c == '\t'; }
|
int str_isspace(char c) { return c == ' ' || c == '\n' || c == '\t'; }
|
||||||
|
|
||||||
char str_uppercase(char c)
|
char str_uppercase(char c)
|
||||||
|
@ -2030,24 +2104,24 @@ int str_utf8_decode(const char **ptr)
|
||||||
}
|
}
|
||||||
else if((*buf&0xE0) == 0xC0) /* 110xxxxx */
|
else if((*buf&0xE0) == 0xC0) /* 110xxxxx */
|
||||||
{
|
{
|
||||||
ch = (*buf++ & 0x3F) << 6; if(!(*buf)) break;
|
ch = (*buf++ & 0x3F) << 6; if(!(*buf) || (*buf&0xC0) != 0x80) break;
|
||||||
ch += (*buf++ & 0x3F);
|
ch += (*buf++ & 0x3F);
|
||||||
if(ch == 0) ch = -1;
|
if(ch < 0x80 || ch > 0x7FF) ch = -1;
|
||||||
}
|
}
|
||||||
else if((*buf & 0xF0) == 0xE0) /* 1110xxxx */
|
else if((*buf & 0xF0) == 0xE0) /* 1110xxxx */
|
||||||
{
|
{
|
||||||
ch = (*buf++ & 0x1F) << 12; if(!(*buf)) break;
|
ch = (*buf++ & 0x1F) << 12; if(!(*buf) || (*buf&0xC0) != 0x80) break;
|
||||||
ch += (*buf++ & 0x3F) << 6; if(!(*buf)) break;
|
ch += (*buf++ & 0x3F) << 6; if(!(*buf) || (*buf&0xC0) != 0x80) break;
|
||||||
ch += (*buf++ & 0x3F);
|
ch += (*buf++ & 0x3F);
|
||||||
if(ch == 0) ch = -1;
|
if(ch < 0x800 || ch > 0xFFFF) ch = -1;
|
||||||
}
|
}
|
||||||
else if((*buf & 0xF8) == 0xF0) /* 11110xxx */
|
else if((*buf & 0xF8) == 0xF0) /* 11110xxx */
|
||||||
{
|
{
|
||||||
ch = (*buf++ & 0x0F) << 18; if(!(*buf)) break;
|
ch = (*buf++ & 0x0F) << 18; if(!(*buf) || (*buf&0xC0) != 0x80) break;
|
||||||
ch += (*buf++ & 0x3F) << 12; if(!(*buf)) break;
|
ch += (*buf++ & 0x3F) << 12; if(!(*buf) || (*buf&0xC0) != 0x80) break;
|
||||||
ch += (*buf++ & 0x3F) << 6; if(!(*buf)) break;
|
ch += (*buf++ & 0x3F) << 6; if(!(*buf) || (*buf&0xC0) != 0x80) break;
|
||||||
ch += (*buf++ & 0x3F);
|
ch += (*buf++ & 0x3F);
|
||||||
if(ch == 0) ch = -1;
|
if(ch < 0x10000 || ch > 0x10FFFF) ch = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2093,6 +2167,69 @@ unsigned str_quickhash(const char *str)
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SECURE_RANDOM_DATA
|
||||||
|
{
|
||||||
|
int initialized;
|
||||||
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
|
HCRYPTPROV provider;
|
||||||
|
#else
|
||||||
|
IOHANDLE urandom;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct SECURE_RANDOM_DATA secure_random_data = { 0 };
|
||||||
|
|
||||||
|
int secure_random_init()
|
||||||
|
{
|
||||||
|
if(secure_random_data.initialized)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
|
if(CryptAcquireContext(&secure_random_data.provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||||
|
{
|
||||||
|
secure_random_data.initialized = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
secure_random_data.urandom = io_open("/dev/urandom", IOFLAG_READ);
|
||||||
|
if(secure_random_data.urandom)
|
||||||
|
{
|
||||||
|
secure_random_data.initialized = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void secure_random_fill(void *bytes, unsigned length)
|
||||||
|
{
|
||||||
|
if(!secure_random_data.initialized)
|
||||||
|
{
|
||||||
|
dbg_msg("secure", "called secure_random_fill before secure_random_init");
|
||||||
|
dbg_break();
|
||||||
|
}
|
||||||
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
|
if(!CryptGenRandom(secure_random_data.provider, length, bytes))
|
||||||
|
{
|
||||||
|
dbg_msg("secure", "CryptGenRandom failed, last_error=%d", GetLastError());
|
||||||
|
dbg_break();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(length != io_read(secure_random_data.urandom, bytes, length))
|
||||||
|
{
|
||||||
|
dbg_msg("secure", "io_read returned with a short read");
|
||||||
|
dbg_break();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,14 +170,6 @@ void mem_zero(void *block, unsigned size);
|
||||||
*/
|
*/
|
||||||
int mem_comp(const void *a, const void *b, int size);
|
int mem_comp(const void *a, const void *b, int size);
|
||||||
|
|
||||||
/*
|
|
||||||
Function: mem_check
|
|
||||||
Validates the heap
|
|
||||||
Will trigger a assert if memory has failed.
|
|
||||||
*/
|
|
||||||
int mem_check_imp();
|
|
||||||
#define mem_check() dbg_assert_imp(__FILE__, __LINE__, mem_check_imp(), "Memory check failed")
|
|
||||||
|
|
||||||
/* Group: File IO */
|
/* Group: File IO */
|
||||||
enum {
|
enum {
|
||||||
IOFLAG_READ = 1,
|
IOFLAG_READ = 1,
|
||||||
|
@ -475,6 +467,16 @@ int time_timestamp();
|
||||||
*/
|
*/
|
||||||
int time_houroftheday();
|
int time_houroftheday();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: time_isxmasday
|
||||||
|
Checks if it's xmas
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
1 - if it's a xmas day
|
||||||
|
0 - if not
|
||||||
|
*/
|
||||||
|
int time_isxmasday();
|
||||||
|
|
||||||
/* Group: Network General */
|
/* Group: Network General */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -576,12 +578,13 @@ int net_addr_from_str(NETADDR *addr, const char *string);
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
bindaddr - Address to bind the socket to.
|
bindaddr - Address to bind the socket to.
|
||||||
|
use_random_port - use a random port
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
On success it returns an handle to the socket. On failure it
|
On success it returns an handle to the socket. On failure it
|
||||||
returns NETSOCKET_INVALID.
|
returns NETSOCKET_INVALID.
|
||||||
*/
|
*/
|
||||||
NETSOCKET net_udp_create(NETADDR bindaddr);
|
NETSOCKET net_udp_create(NETADDR bindaddr, int use_random_port);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: net_udp_send
|
Function: net_udp_send
|
||||||
|
@ -1202,8 +1205,6 @@ int net_would_block();
|
||||||
|
|
||||||
int net_socket_read_wait(NETSOCKET sock, int time);
|
int net_socket_read_wait(NETSOCKET sock, int time);
|
||||||
|
|
||||||
void mem_debug_dump(IOHANDLE file);
|
|
||||||
|
|
||||||
void swap_endian(void *data, unsigned elem_size, unsigned num);
|
void swap_endian(void *data, unsigned elem_size, unsigned num);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1214,15 +1215,6 @@ void dbg_logger_stdout();
|
||||||
void dbg_logger_debugger();
|
void dbg_logger_debugger();
|
||||||
void dbg_logger_file(const char *filename);
|
void dbg_logger_file(const char *filename);
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int allocated;
|
|
||||||
int active_allocations;
|
|
||||||
int total_allocations;
|
|
||||||
} MEMSTATS;
|
|
||||||
|
|
||||||
const MEMSTATS *mem_stats();
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int sent_packets;
|
int sent_packets;
|
||||||
|
@ -1240,16 +1232,6 @@ int str_isspace(char c);
|
||||||
char str_uppercase(char c);
|
char str_uppercase(char c);
|
||||||
unsigned str_quickhash(const char *str);
|
unsigned str_quickhash(const char *str);
|
||||||
|
|
||||||
/*
|
|
||||||
Function: gui_messagebox
|
|
||||||
Display plain OS-dependent message box
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
title - title of the message box
|
|
||||||
message - text to display
|
|
||||||
*/
|
|
||||||
void gui_messagebox(const char *title, const char *message);
|
|
||||||
|
|
||||||
char *str_utf8_skip_whitespaces(char *str);
|
char *str_utf8_skip_whitespaces(char *str);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1330,6 +1312,27 @@ int str_utf8_encode(char *ptr, int chr);
|
||||||
*/
|
*/
|
||||||
int str_utf8_check(const char *str);
|
int str_utf8_check(const char *str);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: secure_random_init
|
||||||
|
Initializes the secure random module.
|
||||||
|
You *MUST* check the return value of this function.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
0 - Initialization succeeded.
|
||||||
|
1 - Initialization failed.
|
||||||
|
*/
|
||||||
|
int secure_random_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: secure_random_fill
|
||||||
|
Fills the buffer with the specified amount of random bytes.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
bytes - Pointer to the start of the buffer.
|
||||||
|
length - Length of the buffer.
|
||||||
|
*/
|
||||||
|
void secure_random_fill(void *bytes, unsigned length);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,7 +35,9 @@
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
inline unsigned atomic_inc(volatile unsigned *pValue)
|
inline unsigned atomic_inc(volatile unsigned *pValue)
|
||||||
|
|
|
@ -17,7 +17,7 @@ public:
|
||||||
union { T y,v; };
|
union { T y,v; };
|
||||||
|
|
||||||
vector2_base() {}
|
vector2_base() {}
|
||||||
vector2_base(float nx, float ny)
|
vector2_base(T nx, T ny)
|
||||||
{
|
{
|
||||||
x = nx;
|
x = nx;
|
||||||
y = ny;
|
y = ny;
|
||||||
|
@ -119,7 +119,7 @@ public:
|
||||||
union { T z,b,v,l; };
|
union { T z,b,v,l; };
|
||||||
|
|
||||||
vector3_base() {}
|
vector3_base() {}
|
||||||
vector3_base(float nx, float ny, float nz)
|
vector3_base(T nx, T ny, T nz)
|
||||||
{
|
{
|
||||||
x = nx;
|
x = nx;
|
||||||
y = ny;
|
y = ny;
|
||||||
|
@ -198,7 +198,7 @@ public:
|
||||||
union { T w,a; };
|
union { T w,a; };
|
||||||
|
|
||||||
vector4_base() {}
|
vector4_base() {}
|
||||||
vector4_base(float nx, float ny, float nz, float nw)
|
vector4_base(T nx, T ny, T nz, T nw)
|
||||||
{
|
{
|
||||||
x = nx;
|
x = nx;
|
||||||
y = ny;
|
y = ny;
|
||||||
|
|
|
@ -88,10 +88,17 @@ public:
|
||||||
virtual void AutoScreenshot_Start() = 0;
|
virtual void AutoScreenshot_Start() = 0;
|
||||||
virtual void ServerBrowserUpdate() = 0;
|
virtual void ServerBrowserUpdate() = 0;
|
||||||
|
|
||||||
|
// gfx
|
||||||
|
virtual void SwitchWindowScreen(int Index) = 0;
|
||||||
|
virtual void ToggleFullscreen() = 0;
|
||||||
|
virtual void ToggleWindowBordered() = 0;
|
||||||
|
virtual void ToggleWindowVSync() = 0;
|
||||||
|
|
||||||
// networking
|
// networking
|
||||||
virtual void EnterGame() = 0;
|
virtual void EnterGame() = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
virtual const char *MapDownloadName() const = 0;
|
||||||
virtual int MapDownloadAmount() const = 0;
|
virtual int MapDownloadAmount() const = 0;
|
||||||
virtual int MapDownloadTotalsize() const = 0;
|
virtual int MapDownloadTotalsize() const = 0;
|
||||||
|
|
||||||
|
@ -160,6 +167,7 @@ public:
|
||||||
virtual void OnEnterGame() = 0;
|
virtual void OnEnterGame() = 0;
|
||||||
virtual void OnShutdown() = 0;
|
virtual void OnShutdown() = 0;
|
||||||
virtual void OnRender() = 0;
|
virtual void OnRender() = 0;
|
||||||
|
virtual void OnUpdate() = 0;
|
||||||
virtual void OnStateChange(int NewState, int OldState) = 0;
|
virtual void OnStateChange(int NewState, int OldState) = 0;
|
||||||
virtual void OnConnected() = 0;
|
virtual void OnConnected() = 0;
|
||||||
virtual void OnMessage(int MsgID, CUnpacker *pUnpacker) = 0;
|
virtual void OnMessage(int MsgID, CUnpacker *pUnpacker) = 0;
|
||||||
|
@ -171,6 +179,7 @@ public:
|
||||||
virtual const char *GetItemName(int Type) const = 0;
|
virtual const char *GetItemName(int Type) const = 0;
|
||||||
virtual const char *Version() const = 0;
|
virtual const char *Version() const = 0;
|
||||||
virtual const char *NetVersion() const = 0;
|
virtual const char *NetVersion() const = 0;
|
||||||
|
virtual int ClientVersion() const = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,13 @@
|
||||||
#include "graphics_threaded.h"
|
#include "graphics_threaded.h"
|
||||||
#include "backend_sdl.h"
|
#include "backend_sdl.h"
|
||||||
|
|
||||||
|
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
PFNGLTEXIMAGE3DPROC glTexImage3D;
|
PFNGLTEXIMAGE3DPROC glTexImage3DInternal;
|
||||||
|
|
||||||
|
GLAPI void APIENTRY glTexImage3D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
|
||||||
|
{
|
||||||
|
glTexImage3DInternal(target, level, internalFormat, width, height, depth, border, format, type, pixels);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ------------ CGraphicsBackend_Threaded
|
// ------------ CGraphicsBackend_Threaded
|
||||||
|
@ -171,7 +175,7 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St
|
||||||
else if(State.m_Dimension == 3 && (m_aTextures[State.m_Texture].m_State&CTexture::STATE_TEX3D))
|
else if(State.m_Dimension == 3 && (m_aTextures[State.m_Texture].m_State&CTexture::STATE_TEX3D))
|
||||||
{
|
{
|
||||||
glEnable(GL_TEXTURE_3D);
|
glEnable(GL_TEXTURE_3D);
|
||||||
glBindTexture(GL_TEXTURE_3D, m_aTextures[State.m_Texture].m_Tex3D);
|
glBindTexture(GL_TEXTURE_3D, m_aTextures[State.m_Texture].m_Tex3D[State.m_TextureArrayIndex]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dbg_msg("render", "invalid texture %d %d %d\n", State.m_Texture, State.m_Dimension, m_aTextures[State.m_Texture].m_State);
|
dbg_msg("render", "invalid texture %d %d %d\n", State.m_Texture, State.m_Dimension, m_aTextures[State.m_Texture].m_State);
|
||||||
|
@ -244,6 +248,13 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St
|
||||||
void CCommandProcessorFragment_OpenGL::Cmd_Init(const SCommand_Init *pCommand)
|
void CCommandProcessorFragment_OpenGL::Cmd_Init(const SCommand_Init *pCommand)
|
||||||
{
|
{
|
||||||
m_pTextureMemoryUsage = pCommand->m_pTextureMemoryUsage;
|
m_pTextureMemoryUsage = pCommand->m_pTextureMemoryUsage;
|
||||||
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_MaxTexSize);
|
||||||
|
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &m_Max3DTexSize);
|
||||||
|
dbg_msg("render", "opengl max texture sizes: %d, %d(3D)", m_MaxTexSize, m_Max3DTexSize);
|
||||||
|
if(m_Max3DTexSize < IGraphics::NUMTILES_DIMENSION * IGraphics::NUMTILES_DIMENSION)
|
||||||
|
dbg_msg("render", "*** warning *** max 3D texture size is too low - using the fallback system");
|
||||||
|
m_TextureArraySize = IGraphics::NUMTILES_DIMENSION * IGraphics::NUMTILES_DIMENSION / min(m_Max3DTexSize, IGraphics::NUMTILES_DIMENSION * IGraphics::NUMTILES_DIMENSION);
|
||||||
|
*pCommand->m_pTextureArraySize = m_TextureArraySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCommandProcessorFragment_OpenGL::Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand)
|
void CCommandProcessorFragment_OpenGL::Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand)
|
||||||
|
@ -262,7 +273,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Destroy(const CCommandBuffer:
|
||||||
if(m_aTextures[pCommand->m_Slot].m_State&CTexture::STATE_TEX2D)
|
if(m_aTextures[pCommand->m_Slot].m_State&CTexture::STATE_TEX2D)
|
||||||
glDeleteTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex2D);
|
glDeleteTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex2D);
|
||||||
if(m_aTextures[pCommand->m_Slot].m_State&CTexture::STATE_TEX3D)
|
if(m_aTextures[pCommand->m_Slot].m_State&CTexture::STATE_TEX3D)
|
||||||
glDeleteTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex3D);
|
glDeleteTextures(m_TextureArraySize, m_aTextures[pCommand->m_Slot].m_Tex3D);
|
||||||
*m_pTextureMemoryUsage -= m_aTextures[pCommand->m_Slot].m_MemSize;
|
*m_pTextureMemoryUsage -= m_aTextures[pCommand->m_Slot].m_MemSize;
|
||||||
m_aTextures[pCommand->m_Slot].m_State = CTexture::STATE_EMPTY;
|
m_aTextures[pCommand->m_Slot].m_State = CTexture::STATE_EMPTY;
|
||||||
m_aTextures[pCommand->m_Slot].m_MemSize = 0;
|
m_aTextures[pCommand->m_Slot].m_MemSize = 0;
|
||||||
|
@ -278,16 +289,13 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::
|
||||||
// resample if needed
|
// resample if needed
|
||||||
if(pCommand->m_Format == CCommandBuffer::TEXFORMAT_RGBA || pCommand->m_Format == CCommandBuffer::TEXFORMAT_RGB)
|
if(pCommand->m_Format == CCommandBuffer::TEXFORMAT_RGBA || pCommand->m_Format == CCommandBuffer::TEXFORMAT_RGB)
|
||||||
{
|
{
|
||||||
int MaxTexSize;
|
int MaxTexSize = m_MaxTexSize;
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTexSize);
|
if((pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE3D) && m_Max3DTexSize >= CTexture::MIN_GL_MAX_3D_TEXTURE_SIZE)
|
||||||
if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE3D)
|
|
||||||
{
|
{
|
||||||
int Max3DTexSize;
|
|
||||||
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &Max3DTexSize);
|
|
||||||
if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE2D)
|
if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE2D)
|
||||||
MaxTexSize = min(MaxTexSize, Max3DTexSize*16);
|
MaxTexSize = min(MaxTexSize, m_Max3DTexSize * IGraphics::NUMTILES_DIMENSION);
|
||||||
else
|
else
|
||||||
MaxTexSize = Max3DTexSize*16;
|
MaxTexSize = m_Max3DTexSize * IGraphics::NUMTILES_DIMENSION;
|
||||||
}
|
}
|
||||||
if(Width > MaxTexSize || Height > MaxTexSize)
|
if(Width > MaxTexSize || Height > MaxTexSize)
|
||||||
{
|
{
|
||||||
|
@ -302,7 +310,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::
|
||||||
mem_free(pTexData);
|
mem_free(pTexData);
|
||||||
pTexData = pTmpData;
|
pTexData = pTmpData;
|
||||||
}
|
}
|
||||||
else if(Width > 16 && Height > 16 && (pCommand->m_Flags&CCommandBuffer::TEXFLAG_QUALITY) == 0)
|
else if(Width > IGraphics::NUMTILES_DIMENSION && Height > IGraphics::NUMTILES_DIMENSION && (pCommand->m_Flags&CCommandBuffer::TEXFLAG_QUALITY) == 0)
|
||||||
{
|
{
|
||||||
Width>>=1;
|
Width>>=1;
|
||||||
Height>>=1;
|
Height>>=1;
|
||||||
|
@ -357,6 +365,9 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
if(pCommand->m_Flags&CCommandBuffer::TEXTFLAG_LINEARMIPMAPS)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
else
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||||
gluBuild2DMipmaps(GL_TEXTURE_2D, StoreOglformat, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pTexData);
|
gluBuild2DMipmaps(GL_TEXTURE_2D, StoreOglformat, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pTexData);
|
||||||
}
|
}
|
||||||
|
@ -374,43 +385,46 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3D texture
|
// 3D texture
|
||||||
if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE3D)
|
if((pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE3D) && m_Max3DTexSize >= CTexture::MIN_GL_MAX_3D_TEXTURE_SIZE)
|
||||||
{
|
{
|
||||||
Width /= 16;
|
Width /= IGraphics::NUMTILES_DIMENSION;
|
||||||
Height /= 16;
|
Height /= IGraphics::NUMTILES_DIMENSION;
|
||||||
Depth = 256;
|
Depth = min(m_Max3DTexSize, IGraphics::NUMTILES_DIMENSION * IGraphics::NUMTILES_DIMENSION);
|
||||||
|
|
||||||
// copy and reorder texture data
|
// copy and reorder texture data
|
||||||
int MemSize = Width*Height*Depth*pCommand->m_PixelSize;
|
int MemSize = Width*Height*IGraphics::NUMTILES_DIMENSION*IGraphics::NUMTILES_DIMENSION*pCommand->m_PixelSize;
|
||||||
char *pTmpData = (char *)mem_alloc(MemSize, sizeof(void*));
|
char *pTmpData = (char *)mem_alloc(MemSize, sizeof(void*));
|
||||||
|
|
||||||
const int TileSize = (Height * Width) * pCommand->m_PixelSize;
|
const int TileSize = (Height * Width) * pCommand->m_PixelSize;
|
||||||
const int TileRowSize = Width * pCommand->m_PixelSize;
|
const int TileRowSize = Width * pCommand->m_PixelSize;
|
||||||
const int ImagePitch = Width*16 * pCommand->m_PixelSize;
|
const int ImagePitch = Width * IGraphics::NUMTILES_DIMENSION * pCommand->m_PixelSize;
|
||||||
mem_zero(pTmpData, MemSize);
|
mem_zero(pTmpData, MemSize);
|
||||||
for(int i = 0; i < 256; i++)
|
for(int i = 0; i < IGraphics::NUMTILES_DIMENSION * IGraphics::NUMTILES_DIMENSION; i++)
|
||||||
{
|
{
|
||||||
const int px = (i%16) * Width;
|
const int px = (i%IGraphics::NUMTILES_DIMENSION) * Width;
|
||||||
const int py = (i/16) * Height;
|
const int py = (i/IGraphics::NUMTILES_DIMENSION) * Height;
|
||||||
const char *pTileData = (const char *)pTexData + (py * Width*16 + px) * pCommand->m_PixelSize;
|
const char *pTileData = (const char *)pTexData + (py * Width * IGraphics::NUMTILES_DIMENSION + px) * pCommand->m_PixelSize;
|
||||||
for(int y = 0; y < Height; y++)
|
for(int y = 0; y < Height; y++)
|
||||||
mem_copy(pTmpData + i*TileSize + y*TileRowSize, pTileData + y * ImagePitch, TileRowSize);
|
mem_copy(pTmpData + i*TileSize + y*TileRowSize, pTileData + y * ImagePitch, TileRowSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_free(pTexData);
|
mem_free(pTexData);
|
||||||
pTexData = pTmpData;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
glGenTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex3D);
|
glGenTextures(m_TextureArraySize, m_aTextures[pCommand->m_Slot].m_Tex3D);
|
||||||
m_aTextures[pCommand->m_Slot].m_State |= CTexture::STATE_TEX3D;
|
m_aTextures[pCommand->m_Slot].m_State |= CTexture::STATE_TEX3D;
|
||||||
glBindTexture(GL_TEXTURE_3D, m_aTextures[pCommand->m_Slot].m_Tex3D);
|
for(int i = 0; i < m_TextureArraySize; ++i)
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_3D, m_aTextures[pCommand->m_Slot].m_Tex3D[i]);
|
||||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
pTexData = pTmpData+i*(Width*Height*Depth*pCommand->m_PixelSize);
|
||||||
glTexImage3D(GL_TEXTURE_3D, 0, StoreOglformat, Width, Height, Depth, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
|
glTexImage3D(GL_TEXTURE_3D, 0, StoreOglformat, Width, Height, Depth, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
|
||||||
|
|
||||||
m_aTextures[pCommand->m_Slot].m_MemSize += Width*Height*pCommand->m_PixelSize;
|
m_aTextures[pCommand->m_Slot].m_MemSize += Width*Height*pCommand->m_PixelSize;
|
||||||
}
|
}
|
||||||
|
pTexData = pTmpData;
|
||||||
|
}
|
||||||
|
|
||||||
*m_pTextureMemoryUsage += m_aTextures[pCommand->m_Slot].m_MemSize;
|
*m_pTextureMemoryUsage += m_aTextures[pCommand->m_Slot].m_MemSize;
|
||||||
|
|
||||||
|
@ -453,8 +467,10 @@ void CCommandProcessorFragment_OpenGL::Cmd_Screenshot(const CCommandBuffer::SCom
|
||||||
GLint aViewport[4] = {0,0,0,0};
|
GLint aViewport[4] = {0,0,0,0};
|
||||||
glGetIntegerv(GL_VIEWPORT, aViewport);
|
glGetIntegerv(GL_VIEWPORT, aViewport);
|
||||||
|
|
||||||
int w = aViewport[2];
|
int w = pCommand->m_W == -1 ? aViewport[2] : pCommand->m_W;
|
||||||
int h = aViewport[3];
|
int h = pCommand->m_H == -1 ? aViewport[3] : pCommand->m_H;
|
||||||
|
int x = pCommand->m_X;
|
||||||
|
int y = aViewport[3] - pCommand->m_Y - 1 - (h - 1);
|
||||||
|
|
||||||
// we allocate one more row to use when we are flipping the texture
|
// we allocate one more row to use when we are flipping the texture
|
||||||
unsigned char *pPixelData = (unsigned char *)mem_alloc(w*(h+1)*3, 1);
|
unsigned char *pPixelData = (unsigned char *)mem_alloc(w*(h+1)*3, 1);
|
||||||
|
@ -464,15 +480,15 @@ void CCommandProcessorFragment_OpenGL::Cmd_Screenshot(const CCommandBuffer::SCom
|
||||||
GLint Alignment;
|
GLint Alignment;
|
||||||
glGetIntegerv(GL_PACK_ALIGNMENT, &Alignment);
|
glGetIntegerv(GL_PACK_ALIGNMENT, &Alignment);
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||||
glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pPixelData);
|
glReadPixels(x, y, w, h, GL_RGB, GL_UNSIGNED_BYTE, pPixelData);
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT, Alignment);
|
glPixelStorei(GL_PACK_ALIGNMENT, Alignment);
|
||||||
|
|
||||||
// flip the pixel because opengl works from bottom left corner
|
// flip the pixel because opengl works from bottom left corner
|
||||||
for(int y = 0; y < h/2; y++)
|
for(int ty = 0; ty < h/2; ty++)
|
||||||
{
|
{
|
||||||
mem_copy(pTempRow, pPixelData+y*w*3, w*3);
|
mem_copy(pTempRow, pPixelData+ty*w*3, w*3);
|
||||||
mem_copy(pPixelData+y*w*3, pPixelData+(h-y-1)*w*3, w*3);
|
mem_copy(pPixelData+ty*w*3, pPixelData+(h-ty-1)*w*3, w*3);
|
||||||
mem_copy(pPixelData+(h-y-1)*w*3, pTempRow,w*3);
|
mem_copy(pPixelData+(h-ty-1)*w*3, pTempRow,w*3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill in the information
|
// fill in the information
|
||||||
|
@ -539,6 +555,11 @@ void CCommandProcessorFragment_SDL::Cmd_Swap(const CCommandBuffer::SCommand_Swap
|
||||||
glFinish();
|
glFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CCommandProcessorFragment_SDL::Cmd_VSync(const CCommandBuffer::SCommand_VSync *pCommand)
|
||||||
|
{
|
||||||
|
*pCommand->m_pRetOk = SDL_GL_SetSwapInterval(pCommand->m_VSync) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
void CCommandProcessorFragment_SDL::Cmd_VideoModes(const CCommandBuffer::SCommand_VideoModes *pCommand)
|
void CCommandProcessorFragment_SDL::Cmd_VideoModes(const CCommandBuffer::SCommand_VideoModes *pCommand)
|
||||||
{
|
{
|
||||||
SDL_DisplayMode mode;
|
SDL_DisplayMode mode;
|
||||||
|
@ -584,6 +605,7 @@ bool CCommandProcessorFragment_SDL::RunCommand(const CCommandBuffer::SCommand *p
|
||||||
switch(pBaseCommand->m_Cmd)
|
switch(pBaseCommand->m_Cmd)
|
||||||
{
|
{
|
||||||
case CCommandBuffer::CMD_SWAP: Cmd_Swap(static_cast<const CCommandBuffer::SCommand_Swap *>(pBaseCommand)); break;
|
case CCommandBuffer::CMD_SWAP: Cmd_Swap(static_cast<const CCommandBuffer::SCommand_Swap *>(pBaseCommand)); break;
|
||||||
|
case CCommandBuffer::CMD_VSYNC: Cmd_VSync(static_cast<const CCommandBuffer::SCommand_VSync *>(pBaseCommand)); break;
|
||||||
case CCommandBuffer::CMD_VIDEOMODES: Cmd_VideoModes(static_cast<const CCommandBuffer::SCommand_VideoModes *>(pBaseCommand)); break;
|
case CCommandBuffer::CMD_VIDEOMODES: Cmd_VideoModes(static_cast<const CCommandBuffer::SCommand_VideoModes *>(pBaseCommand)); break;
|
||||||
case CMD_INIT: Cmd_Init(static_cast<const SCommand_Init *>(pBaseCommand)); break;
|
case CMD_INIT: Cmd_Init(static_cast<const SCommand_Init *>(pBaseCommand)); break;
|
||||||
case CMD_SHUTDOWN: Cmd_Shutdown(static_cast<const SCommand_Shutdown *>(pBaseCommand)); break;
|
case CMD_SHUTDOWN: Cmd_Shutdown(static_cast<const SCommand_Shutdown *>(pBaseCommand)); break;
|
||||||
|
@ -619,7 +641,7 @@ void CCommandProcessor_SDL_OpenGL::RunBuffer(CCommandBuffer *pBuffer)
|
||||||
|
|
||||||
// ------------ CGraphicsBackend_SDL_OpenGL
|
// ------------ CGraphicsBackend_SDL_OpenGL
|
||||||
|
|
||||||
int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Screen, int *pWidth, int *pHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight)
|
int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidth, int *pHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight)
|
||||||
{
|
{
|
||||||
if(!SDL_WasInit(SDL_INIT_VIDEO))
|
if(!SDL_WasInit(SDL_INIT_VIDEO))
|
||||||
{
|
{
|
||||||
|
@ -628,34 +650,43 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Screen, int *pWidth
|
||||||
dbg_msg("gfx", "unable to init SDL video: %s", SDL_GetError());
|
dbg_msg("gfx", "unable to init SDL video: %s", SDL_GetError());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONF_FAMILY_WINDOWS
|
|
||||||
if(!getenv("SDL_VIDEO_WINDOW_POS") && !getenv("SDL_VIDEO_CENTERED")) // ignore_convention
|
|
||||||
putenv("SDL_VIDEO_WINDOW_POS=center"); // ignore_convention
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Rect ScreenBounds;
|
// set screen
|
||||||
if(SDL_GetDisplayBounds(Screen, &ScreenBounds) < 0)
|
SDL_Rect ScreenPos;
|
||||||
|
m_NumScreens = SDL_GetNumVideoDisplays();
|
||||||
|
if(m_NumScreens > 0)
|
||||||
{
|
{
|
||||||
dbg_msg("gfx", "unable to get current screen bounds: %s", SDL_GetError());
|
clamp(*Screen, 0, m_NumScreens-1);
|
||||||
|
if(SDL_GetDisplayBounds(*Screen, &ScreenPos) != 0)
|
||||||
|
{
|
||||||
|
dbg_msg("gfx", "unable to retrieve screen information: %s", SDL_GetError());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// use current resolution as default
|
}
|
||||||
if(*pWidth == 0 || *pHeight == 0)
|
else
|
||||||
{
|
{
|
||||||
*pWidth = ScreenBounds.w;
|
dbg_msg("gfx", "unable to retrieve number of screens: %s", SDL_GetError());
|
||||||
*pHeight = ScreenBounds.h;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// store desktop resolution for settings reset button
|
// store desktop resolution for settings reset button
|
||||||
*pDesktopWidth = ScreenBounds.w;
|
SDL_DisplayMode DisplayMode;
|
||||||
*pDesktopHeight = ScreenBounds.h;
|
if(SDL_GetDesktopDisplayMode(*Screen, &DisplayMode))
|
||||||
|
{
|
||||||
|
dbg_msg("gfx", "unable to get desktop resolution: %s", SDL_GetError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*pDesktopWidth = DisplayMode.w;
|
||||||
|
*pDesktopHeight = DisplayMode.h;
|
||||||
|
|
||||||
dbg_assert(!(Flags&IGraphicsBackend::INITFLAG_BORDERLESS)
|
// use desktop resolution as default resolution
|
||||||
|| !(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN),
|
if (*pWidth == 0 || *pWidth == 0)
|
||||||
"only one of borderless and fullscreen may be activated at the same time");
|
{
|
||||||
|
*pWidth = *pDesktopWidth;
|
||||||
|
*pHeight = *pDesktopHeight;
|
||||||
|
}
|
||||||
|
|
||||||
// set flags
|
// set flags
|
||||||
int SdlFlags = SDL_WINDOW_OPENGL;
|
int SdlFlags = SDL_WINDOW_OPENGL;
|
||||||
|
@ -664,10 +695,12 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Screen, int *pWidth
|
||||||
if(Flags&IGraphicsBackend::INITFLAG_BORDERLESS)
|
if(Flags&IGraphicsBackend::INITFLAG_BORDERLESS)
|
||||||
SdlFlags |= SDL_WINDOW_BORDERLESS;
|
SdlFlags |= SDL_WINDOW_BORDERLESS;
|
||||||
if(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN)
|
if(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN)
|
||||||
#if defined(CONF_FAMILY_WINDOWS) || defined(CONF_PLATFORM_MACOSX)
|
#if defined(CONF_PLATFORM_MACOSX) // Todo SDL: remove this when fixed (game freezes when losing focus in fullscreen)
|
||||||
SdlFlags |= SDL_WINDOW_FULLSCREEN;
|
SdlFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP; // always use "fake" fullscreen
|
||||||
|
*pWidth = *pDesktopWidth;
|
||||||
|
*pHeight = *pDesktopHeight;
|
||||||
#else
|
#else
|
||||||
SdlFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
SdlFlags |= SDL_WINDOW_FULLSCREEN;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// set gl attributes
|
// set gl attributes
|
||||||
|
@ -683,14 +716,17 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Screen, int *pWidth
|
||||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pWindow = SDL_CreateWindow(
|
// calculate centered position in windowed mode
|
||||||
pName,
|
int OffsetX = 0;
|
||||||
SDL_WINDOWPOS_UNDEFINED_DISPLAY(0),
|
int OffsetY = 0;
|
||||||
SDL_WINDOWPOS_UNDEFINED_DISPLAY(0),
|
if(!(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN) && *pDesktopWidth > *pWidth && *pDesktopHeight > *pHeight)
|
||||||
*pWidth,
|
{
|
||||||
*pHeight,
|
OffsetX = (*pDesktopWidth - *pWidth) / 2;
|
||||||
SdlFlags);
|
OffsetY = (*pDesktopHeight - *pHeight) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create window
|
||||||
|
m_pWindow = SDL_CreateWindow(pName, ScreenPos.x+OffsetX, ScreenPos.y+OffsetY, *pWidth, *pHeight, SdlFlags);
|
||||||
if(m_pWindow == NULL)
|
if(m_pWindow == NULL)
|
||||||
{
|
{
|
||||||
dbg_msg("gfx", "unable to create window: %s", SDL_GetError());
|
dbg_msg("gfx", "unable to create window: %s", SDL_GetError());
|
||||||
|
@ -699,8 +735,8 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Screen, int *pWidth
|
||||||
|
|
||||||
SDL_GetWindowSize(m_pWindow, pWidth, pHeight);
|
SDL_GetWindowSize(m_pWindow, pWidth, pHeight);
|
||||||
|
|
||||||
|
// create gl context
|
||||||
m_GLContext = SDL_GL_CreateContext(m_pWindow);
|
m_GLContext = SDL_GL_CreateContext(m_pWindow);
|
||||||
|
|
||||||
if(m_GLContext == NULL)
|
if(m_GLContext == NULL)
|
||||||
{
|
{
|
||||||
dbg_msg("gfx", "unable to create OpenGL context: %s", SDL_GetError());
|
dbg_msg("gfx", "unable to create OpenGL context: %s", SDL_GetError());
|
||||||
|
@ -708,8 +744,8 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Screen, int *pWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
glTexImage3D = (PFNGLTEXIMAGE3DPROC) wglGetProcAddress("glTexImage3D");
|
glTexImage3DInternal = (PFNGLTEXIMAGE3DPROC) wglGetProcAddress("glTexImage3D");
|
||||||
if(glTexImage3D == 0)
|
if(glTexImage3DInternal == 0)
|
||||||
{
|
{
|
||||||
dbg_msg("gfx", "glTexImage3D not supported");
|
dbg_msg("gfx", "glTexImage3D not supported");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -726,13 +762,14 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Screen, int *pWidth
|
||||||
|
|
||||||
// issue init commands for OpenGL and SDL
|
// issue init commands for OpenGL and SDL
|
||||||
CCommandBuffer CmdBuffer(1024, 512);
|
CCommandBuffer CmdBuffer(1024, 512);
|
||||||
CCommandProcessorFragment_OpenGL::SCommand_Init CmdOpenGL;
|
|
||||||
CmdOpenGL.m_pTextureMemoryUsage = &m_TextureMemoryUsage;
|
|
||||||
CmdBuffer.AddCommand(CmdOpenGL);
|
|
||||||
CCommandProcessorFragment_SDL::SCommand_Init CmdSDL;
|
CCommandProcessorFragment_SDL::SCommand_Init CmdSDL;
|
||||||
CmdSDL.m_pWindow = m_pWindow;
|
CmdSDL.m_pWindow = m_pWindow;
|
||||||
CmdSDL.m_GLContext = m_GLContext;
|
CmdSDL.m_GLContext = m_GLContext;
|
||||||
CmdBuffer.AddCommand(CmdSDL);
|
CmdBuffer.AddCommand(CmdSDL);
|
||||||
|
CCommandProcessorFragment_OpenGL::SCommand_Init CmdOpenGL;
|
||||||
|
CmdOpenGL.m_pTextureMemoryUsage = &m_TextureMemoryUsage;
|
||||||
|
CmdOpenGL.m_pTextureArraySize = &m_TextureArraySize;
|
||||||
|
CmdBuffer.AddCommand(CmdOpenGL);
|
||||||
RunBuffer(&CmdBuffer);
|
RunBuffer(&CmdBuffer);
|
||||||
WaitForIdle();
|
WaitForIdle();
|
||||||
|
|
||||||
|
@ -772,7 +809,41 @@ void CGraphicsBackend_SDL_OpenGL::Minimize()
|
||||||
|
|
||||||
void CGraphicsBackend_SDL_OpenGL::Maximize()
|
void CGraphicsBackend_SDL_OpenGL::Maximize()
|
||||||
{
|
{
|
||||||
// TODO: SDL
|
SDL_MaximizeWindow(m_pWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGraphicsBackend_SDL_OpenGL::Fullscreen(bool State)
|
||||||
|
{
|
||||||
|
#if defined(CONF_PLATFORM_MACOSX) // Todo SDL: remove this when fixed (game freezes when losing focus in fullscreen)
|
||||||
|
return SDL_SetWindowFullscreen(m_pWindow, State ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0) == 0;
|
||||||
|
#else
|
||||||
|
return SDL_SetWindowFullscreen(m_pWindow, State ? SDL_WINDOW_FULLSCREEN : 0) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGraphicsBackend_SDL_OpenGL::SetWindowBordered(bool State)
|
||||||
|
{
|
||||||
|
SDL_SetWindowBordered(m_pWindow, SDL_bool(State));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGraphicsBackend_SDL_OpenGL::SetWindowScreen(int Index)
|
||||||
|
{
|
||||||
|
if(Index >= 0 && Index < m_NumScreens)
|
||||||
|
{
|
||||||
|
SDL_Rect ScreenPos;
|
||||||
|
if(SDL_GetDisplayBounds(Index, &ScreenPos) == 0)
|
||||||
|
{
|
||||||
|
SDL_SetWindowPosition(m_pWindow, ScreenPos.x, ScreenPos.y);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CGraphicsBackend_SDL_OpenGL::GetWindowScreen()
|
||||||
|
{
|
||||||
|
return SDL_GetWindowDisplayIndex(m_pWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CGraphicsBackend_SDL_OpenGL::WindowActive()
|
int CGraphicsBackend_SDL_OpenGL::WindowActive()
|
||||||
|
|
|
@ -91,15 +91,21 @@ class CCommandProcessorFragment_OpenGL
|
||||||
STATE_EMPTY = 0,
|
STATE_EMPTY = 0,
|
||||||
STATE_TEX2D = 1,
|
STATE_TEX2D = 1,
|
||||||
STATE_TEX3D = 2,
|
STATE_TEX3D = 2,
|
||||||
|
|
||||||
|
MIN_GL_MAX_3D_TEXTURE_SIZE = 64, // GL_MAX_3D_TEXTURE_SIZE must be at least 64 according to the standard
|
||||||
|
MAX_ARRAYSIZE_TEX3D = IGraphics::NUMTILES_DIMENSION * IGraphics::NUMTILES_DIMENSION / MIN_GL_MAX_3D_TEXTURE_SIZE, // = 4
|
||||||
};
|
};
|
||||||
GLuint m_Tex2D;
|
GLuint m_Tex2D;
|
||||||
GLuint m_Tex3D;
|
GLuint m_Tex3D[MAX_ARRAYSIZE_TEX3D];
|
||||||
int m_State;
|
int m_State;
|
||||||
int m_Format;
|
int m_Format;
|
||||||
int m_MemSize;
|
int m_MemSize;
|
||||||
};
|
};
|
||||||
CTexture m_aTextures[CCommandBuffer::MAX_TEXTURES];
|
CTexture m_aTextures[CCommandBuffer::MAX_TEXTURES];
|
||||||
volatile int *m_pTextureMemoryUsage;
|
volatile int *m_pTextureMemoryUsage;
|
||||||
|
int m_MaxTexSize;
|
||||||
|
int m_Max3DTexSize;
|
||||||
|
int m_TextureArraySize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
|
@ -111,6 +117,7 @@ public:
|
||||||
{
|
{
|
||||||
SCommand_Init() : SCommand(CMD_INIT) {}
|
SCommand_Init() : SCommand(CMD_INIT) {}
|
||||||
volatile int *m_pTextureMemoryUsage;
|
volatile int *m_pTextureMemoryUsage;
|
||||||
|
int *m_pTextureArraySize;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -163,6 +170,7 @@ private:
|
||||||
void Cmd_Init(const SCommand_Init *pCommand);
|
void Cmd_Init(const SCommand_Init *pCommand);
|
||||||
void Cmd_Shutdown(const SCommand_Shutdown *pCommand);
|
void Cmd_Shutdown(const SCommand_Shutdown *pCommand);
|
||||||
void Cmd_Swap(const CCommandBuffer::SCommand_Swap *pCommand);
|
void Cmd_Swap(const CCommandBuffer::SCommand_Swap *pCommand);
|
||||||
|
void Cmd_VSync(const CCommandBuffer::SCommand_VSync *pCommand);
|
||||||
void Cmd_VideoModes(const CCommandBuffer::SCommand_VideoModes *pCommand);
|
void Cmd_VideoModes(const CCommandBuffer::SCommand_VideoModes *pCommand);
|
||||||
public:
|
public:
|
||||||
CCommandProcessorFragment_SDL();
|
CCommandProcessorFragment_SDL();
|
||||||
|
@ -187,14 +195,23 @@ class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded
|
||||||
SDL_GLContext m_GLContext;
|
SDL_GLContext m_GLContext;
|
||||||
ICommandProcessor *m_pProcessor;
|
ICommandProcessor *m_pProcessor;
|
||||||
volatile int m_TextureMemoryUsage;
|
volatile int m_TextureMemoryUsage;
|
||||||
|
int m_NumScreens;
|
||||||
|
int m_TextureArraySize;
|
||||||
public:
|
public:
|
||||||
virtual int Init(const char *pName, int Screen, int *Width, int *Height, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight);
|
virtual int Init(const char *pName, int *Screen, int *Width, int *Height, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight);
|
||||||
virtual int Shutdown();
|
virtual int Shutdown();
|
||||||
|
|
||||||
virtual int MemoryUsage() const;
|
virtual int MemoryUsage() const;
|
||||||
|
virtual int GetTextureArraySize() const { return m_TextureArraySize; }
|
||||||
|
|
||||||
|
virtual int GetNumScreens() const { return m_NumScreens; }
|
||||||
|
|
||||||
virtual void Minimize();
|
virtual void Minimize();
|
||||||
virtual void Maximize();
|
virtual void Maximize();
|
||||||
|
virtual bool Fullscreen(bool State); // on=true/off=false
|
||||||
|
virtual void SetWindowBordered(bool State); // on=true/off=false
|
||||||
|
virtual bool SetWindowScreen(int Index);
|
||||||
|
virtual int GetWindowScreen();
|
||||||
virtual int WindowActive();
|
virtual int WindowActive();
|
||||||
virtual int WindowOpen();
|
virtual int WindowOpen();
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
#include <immintrin.h> //_mm_pause
|
||||||
#include <stdlib.h> // qsort
|
#include <stdlib.h> // qsort
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
@ -56,15 +57,15 @@
|
||||||
|
|
||||||
void CGraph::Init(float Min, float Max)
|
void CGraph::Init(float Min, float Max)
|
||||||
{
|
{
|
||||||
m_Min = Min;
|
m_MinRange = m_Min = Min;
|
||||||
m_Max = Max;
|
m_MaxRange = m_Max = Max;
|
||||||
m_Index = 0;
|
m_Index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGraph::ScaleMax()
|
void CGraph::ScaleMax()
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
m_Max = 0;
|
m_Max = m_MaxRange;
|
||||||
for(i = 0; i < MAX_VALUES; i++)
|
for(i = 0; i < MAX_VALUES; i++)
|
||||||
{
|
{
|
||||||
if(m_aValues[i] > m_Max)
|
if(m_aValues[i] > m_Max)
|
||||||
|
@ -75,7 +76,7 @@ void CGraph::ScaleMax()
|
||||||
void CGraph::ScaleMin()
|
void CGraph::ScaleMin()
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
m_Min = m_Max;
|
m_Min = m_MinRange;
|
||||||
for(i = 0; i < MAX_VALUES; i++)
|
for(i = 0; i < MAX_VALUES; i++)
|
||||||
{
|
{
|
||||||
if(m_aValues[i] < m_Min)
|
if(m_aValues[i] < m_Min)
|
||||||
|
@ -239,8 +240,7 @@ void CSmoothTime::Update(CGraph *pGraph, int64 Target, int TimeLeft, int AdjustD
|
||||||
UpdateInt(Target);
|
UpdateInt(Target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotDelta), m_pConLinkIdentifier("teeworlds:")
|
||||||
CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotDelta)
|
|
||||||
{
|
{
|
||||||
m_pEditor = 0;
|
m_pEditor = 0;
|
||||||
m_pInput = 0;
|
m_pInput = 0;
|
||||||
|
@ -255,6 +255,8 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD
|
||||||
m_RenderFrameTimeHigh = 0.0f;
|
m_RenderFrameTimeHigh = 0.0f;
|
||||||
m_RenderFrames = 0;
|
m_RenderFrames = 0;
|
||||||
m_LastRenderTime = time_get();
|
m_LastRenderTime = time_get();
|
||||||
|
m_LastCpuTime = time_get();
|
||||||
|
m_LastAvgCpuFrameTime = 0;
|
||||||
|
|
||||||
m_GameTickSpeed = SERVER_TICK_SPEED;
|
m_GameTickSpeed = SERVER_TICK_SPEED;
|
||||||
|
|
||||||
|
@ -290,8 +292,6 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD
|
||||||
m_MapdownloadAmount = -1;
|
m_MapdownloadAmount = -1;
|
||||||
m_MapdownloadTotalsize = -1;
|
m_MapdownloadTotalsize = -1;
|
||||||
|
|
||||||
m_CurrentServerInfoRequestTime = -1;
|
|
||||||
|
|
||||||
m_CurrentInput = 0;
|
m_CurrentInput = 0;
|
||||||
|
|
||||||
m_State = IClient::STATE_OFFLINE;
|
m_State = IClient::STATE_OFFLINE;
|
||||||
|
@ -338,6 +338,7 @@ void CClient::SendInfo()
|
||||||
CMsgPacker Msg(NETMSG_INFO, true);
|
CMsgPacker Msg(NETMSG_INFO, true);
|
||||||
Msg.AddString(GameClient()->NetVersion(), 128);
|
Msg.AddString(GameClient()->NetVersion(), 128);
|
||||||
Msg.AddString(g_Config.m_Password, 128);
|
Msg.AddString(g_Config.m_Password, 128);
|
||||||
|
Msg.AddInt(GameClient()->ClientVersion());
|
||||||
SendMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH);
|
SendMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,20 +377,6 @@ bool CClient::ConnectionProblems() const
|
||||||
return m_NetClient.GotProblems() != 0;
|
return m_NetClient.GotProblems() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::DirectInput(int *pInput, int Size)
|
|
||||||
{
|
|
||||||
CMsgPacker Msg(NETMSG_INPUT, true);
|
|
||||||
Msg.AddInt(m_AckGameTick);
|
|
||||||
Msg.AddInt(m_PredTick);
|
|
||||||
Msg.AddInt(Size);
|
|
||||||
|
|
||||||
for(int i = 0; i < Size/4; i++)
|
|
||||||
Msg.AddInt(pInput[i]);
|
|
||||||
|
|
||||||
SendMsg(&Msg, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CClient::SendInput()
|
void CClient::SendInput()
|
||||||
{
|
{
|
||||||
int64 Now = time_get();
|
int64 Now = time_get();
|
||||||
|
@ -417,6 +404,12 @@ void CClient::SendInput()
|
||||||
for(int i = 0; i < Size/4; i++)
|
for(int i = 0; i < Size/4; i++)
|
||||||
Msg.AddInt(m_aInputs[m_CurrentInput].m_aData[i]);
|
Msg.AddInt(m_aInputs[m_CurrentInput].m_aData[i]);
|
||||||
|
|
||||||
|
int PingCorrection = 0;
|
||||||
|
int64 TagTime;
|
||||||
|
if(m_SnapshotStorage.Get(m_AckGameTick, &TagTime, 0, 0) >= 0)
|
||||||
|
PingCorrection = (int)(((Now-TagTime)*1000)/time_freq());
|
||||||
|
Msg.AddInt(PingCorrection);
|
||||||
|
|
||||||
m_CurrentInput++;
|
m_CurrentInput++;
|
||||||
m_CurrentInput%=200;
|
m_CurrentInput%=200;
|
||||||
|
|
||||||
|
@ -506,7 +499,7 @@ void CClient::Connect(const char *pAddress)
|
||||||
str_format(aBuf, sizeof(aBuf), "connecting to '%s'", m_aServerAddressStr);
|
str_format(aBuf, sizeof(aBuf), "connecting to '%s'", m_aServerAddressStr);
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
|
||||||
|
|
||||||
ServerInfoRequest();
|
mem_zero(&m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
|
||||||
|
|
||||||
if(net_addr_from_str(&m_ServerAddress, m_aServerAddressStr) != 0 && net_host_lookup(m_aServerAddressStr, &m_ServerAddress, m_NetClient.NetType()) != 0)
|
if(net_addr_from_str(&m_ServerAddress, m_aServerAddressStr) != 0 && net_host_lookup(m_aServerAddressStr, &m_ServerAddress, m_NetClient.NetType()) != 0)
|
||||||
{
|
{
|
||||||
|
@ -577,12 +570,6 @@ void CClient::GetServerInfo(CServerInfo *pServerInfo) const
|
||||||
mem_copy(pServerInfo, &m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
|
mem_copy(pServerInfo, &m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::ServerInfoRequest()
|
|
||||||
{
|
|
||||||
mem_zero(&m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
|
|
||||||
m_CurrentServerInfoRequestTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CClient::LoadData()
|
int CClient::LoadData()
|
||||||
{
|
{
|
||||||
m_DebugFont = Graphics()->LoadTexture("ui/debug_font.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, IGraphics::TEXLOAD_NORESAMPLE);
|
m_DebugFont = Graphics()->LoadTexture("ui/debug_font.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, IGraphics::TEXLOAD_NORESAMPLE);
|
||||||
|
@ -685,10 +672,8 @@ void CClient::DebugRender()
|
||||||
total = 42
|
total = 42
|
||||||
*/
|
*/
|
||||||
FrameTimeAvg = FrameTimeAvg*0.9f + m_RenderFrameTime*0.1f;
|
FrameTimeAvg = FrameTimeAvg*0.9f + m_RenderFrameTime*0.1f;
|
||||||
str_format(aBuffer, sizeof(aBuffer), "ticks: %8d %8d mem %dk %d gfxmem: %dk fps: %3d",
|
str_format(aBuffer, sizeof(aBuffer), "ticks: %8d %8d gfxmem: %dk fps: %3d",
|
||||||
m_CurGameTick, m_PredTick,
|
m_CurGameTick, m_PredTick,
|
||||||
mem_stats()->allocated/1024,
|
|
||||||
mem_stats()->total_allocations,
|
|
||||||
Graphics()->MemoryUsage()/1024,
|
Graphics()->MemoryUsage()/1024,
|
||||||
(int)(1.0f/FrameTimeAvg + 0.5f));
|
(int)(1.0f/FrameTimeAvg + 0.5f));
|
||||||
Graphics()->QuadsText(2, 2, 16, aBuffer);
|
Graphics()->QuadsText(2, 2, 16, aBuffer);
|
||||||
|
@ -743,7 +728,11 @@ void CClient::DebugRender()
|
||||||
m_FpsGraph.ScaleMax();
|
m_FpsGraph.ScaleMax();
|
||||||
m_FpsGraph.ScaleMin();
|
m_FpsGraph.ScaleMin();
|
||||||
m_FpsGraph.Render(Graphics(), m_DebugFont, x, sp*5, w, h, "FPS");
|
m_FpsGraph.Render(Graphics(), m_DebugFont, x, sp*5, w, h, "FPS");
|
||||||
|
m_InputtimeMarginGraph.ScaleMin();
|
||||||
|
m_InputtimeMarginGraph.ScaleMax();
|
||||||
m_InputtimeMarginGraph.Render(Graphics(), m_DebugFont, x, sp*5+h+sp, w, h, "Prediction Margin");
|
m_InputtimeMarginGraph.Render(Graphics(), m_DebugFont, x, sp*5+h+sp, w, h, "Prediction Margin");
|
||||||
|
m_GametimeMarginGraph.ScaleMin();
|
||||||
|
m_GametimeMarginGraph.ScaleMax();
|
||||||
m_GametimeMarginGraph.Render(Graphics(), m_DebugFont, x, sp*5+h+sp+h+sp, w, h, "Gametime Margin");
|
m_GametimeMarginGraph.Render(Graphics(), m_DebugFont, x, sp*5+h+sp+h+sp, w, h, "Gametime Margin");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -837,9 +826,9 @@ int CClient::PlayerScoreComp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
CServerInfo::CClient *p0 = (CServerInfo::CClient *)a;
|
CServerInfo::CClient *p0 = (CServerInfo::CClient *)a;
|
||||||
CServerInfo::CClient *p1 = (CServerInfo::CClient *)b;
|
CServerInfo::CClient *p1 = (CServerInfo::CClient *)b;
|
||||||
if(p0->m_Player && !p1->m_Player)
|
if(!(p0->m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC) && (p1->m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC))
|
||||||
return -1;
|
return -1;
|
||||||
if(!p0->m_Player && p1->m_Player)
|
if((p0->m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC) && !(p1->m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC))
|
||||||
return 1;
|
return 1;
|
||||||
if(p0->m_Score == p1->m_Score)
|
if(p0->m_Score == p1->m_Score)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -848,6 +837,68 @@ int CClient::PlayerScoreComp(const void *a, const void *b)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CClient::UnpackServerInfo(CUnpacker *pUnpacker, CServerInfo *pInfo, int *pToken)
|
||||||
|
{
|
||||||
|
if(pToken)
|
||||||
|
*pToken = pUnpacker->GetInt();
|
||||||
|
str_copy(pInfo->m_aVersion, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aVersion));
|
||||||
|
str_copy(pInfo->m_aName, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aName));
|
||||||
|
str_clean_whitespaces(pInfo->m_aName);
|
||||||
|
str_copy(pInfo->m_aHostname, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aHostname));
|
||||||
|
if(pInfo->m_aHostname[0] == 0)
|
||||||
|
str_copy(pInfo->m_aHostname, pInfo->m_aAddress, sizeof(pInfo->m_aHostname));
|
||||||
|
str_copy(pInfo->m_aMap, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aMap));
|
||||||
|
str_copy(pInfo->m_aGameType, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aGameType));
|
||||||
|
pInfo->m_Flags = (pUnpacker->GetInt()&SERVERINFO_FLAG_PASSWORD) ? IServerBrowser::FLAG_PASSWORD : 0;
|
||||||
|
pInfo->m_ServerLevel = clamp<int>(pUnpacker->GetInt(), SERVERINFO_LEVEL_MIN, SERVERINFO_LEVEL_MAX);
|
||||||
|
pInfo->m_NumPlayers = pUnpacker->GetInt();
|
||||||
|
pInfo->m_MaxPlayers = pUnpacker->GetInt();
|
||||||
|
pInfo->m_NumClients = pUnpacker->GetInt();
|
||||||
|
pInfo->m_MaxClients = pUnpacker->GetInt();
|
||||||
|
pInfo->m_NumBotPlayers = 0;
|
||||||
|
pInfo->m_NumBotSpectators = 0;
|
||||||
|
|
||||||
|
// don't add invalid info to the server browser list
|
||||||
|
if(pInfo->m_NumClients < 0 || pInfo->m_NumClients > pInfo->m_MaxClients || pInfo->m_MaxClients < 0 || pInfo->m_MaxClients > MAX_CLIENTS ||
|
||||||
|
pInfo->m_NumPlayers < 0 || pInfo->m_NumPlayers > pInfo->m_NumClients || pInfo->m_MaxPlayers < 0 || pInfo->m_MaxPlayers > pInfo->m_MaxClients)
|
||||||
|
return -1;
|
||||||
|
// drop standard gametype with more than MAX_PLAYERS
|
||||||
|
if(pInfo->m_MaxPlayers > MAX_PLAYERS && (str_comp(pInfo->m_aGameType, "DM") == 0 || str_comp(pInfo->m_aGameType, "TDM") == 0 || str_comp(pInfo->m_aGameType, "CTF") == 0 ||
|
||||||
|
str_comp(pInfo->m_aGameType, "LTS") == 0 || str_comp(pInfo->m_aGameType, "LMS") == 0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// use short version
|
||||||
|
if(!pToken)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int NumPlayers = 0;
|
||||||
|
int NumClients = 0;
|
||||||
|
for(int i = 0; i < pInfo->m_NumClients; i++)
|
||||||
|
{
|
||||||
|
str_copy(pInfo->m_aClients[i].m_aName, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aClients[i].m_aName));
|
||||||
|
str_copy(pInfo->m_aClients[i].m_aClan, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aClients[i].m_aClan));
|
||||||
|
pInfo->m_aClients[i].m_Country = pUnpacker->GetInt();
|
||||||
|
pInfo->m_aClients[i].m_Score = pUnpacker->GetInt();
|
||||||
|
pInfo->m_aClients[i].m_PlayerType = pUnpacker->GetInt()&CServerInfo::CClient::PLAYERFLAG_MASK;
|
||||||
|
|
||||||
|
if(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_BOT)
|
||||||
|
{
|
||||||
|
if(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC)
|
||||||
|
pInfo->m_NumBotSpectators++;
|
||||||
|
else
|
||||||
|
pInfo->m_NumBotPlayers++;
|
||||||
|
}
|
||||||
|
|
||||||
|
NumClients++;
|
||||||
|
if(!(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC))
|
||||||
|
NumPlayers++;
|
||||||
|
}
|
||||||
|
pInfo->m_NumPlayers = NumPlayers;
|
||||||
|
pInfo->m_NumClients = NumClients;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void CClient::ProcessConnlessPacket(CNetChunk *pPacket)
|
void CClient::ProcessConnlessPacket(CNetChunk *pPacket)
|
||||||
{
|
{
|
||||||
// version server
|
// version server
|
||||||
|
@ -884,7 +935,7 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket)
|
||||||
Packet.m_pData = VERSIONSRV_GETMAPLIST;
|
Packet.m_pData = VERSIONSRV_GETMAPLIST;
|
||||||
Packet.m_DataSize = sizeof(VERSIONSRV_GETMAPLIST);
|
Packet.m_DataSize = sizeof(VERSIONSRV_GETMAPLIST);
|
||||||
Packet.m_Flags = NETSENDFLAG_CONNLESS;
|
Packet.m_Flags = NETSENDFLAG_CONNLESS;
|
||||||
m_NetClient.Send(&Packet);
|
m_ContactClient.Send(&Packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
// map version list
|
// map version list
|
||||||
|
@ -951,56 +1002,14 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket)
|
||||||
// server info
|
// server info
|
||||||
if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_INFO) && mem_comp(pPacket->m_pData, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)) == 0)
|
if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_INFO) && mem_comp(pPacket->m_pData, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)) == 0)
|
||||||
{
|
{
|
||||||
// we got ze info
|
|
||||||
CUnpacker Up;
|
CUnpacker Up;
|
||||||
CServerInfo Info = {0};
|
CServerInfo Info = {0};
|
||||||
|
|
||||||
Up.Reset((unsigned char*)pPacket->m_pData+sizeof(SERVERBROWSE_INFO), pPacket->m_DataSize-sizeof(SERVERBROWSE_INFO));
|
Up.Reset((unsigned char*)pPacket->m_pData+sizeof(SERVERBROWSE_INFO), pPacket->m_DataSize-sizeof(SERVERBROWSE_INFO));
|
||||||
int Token = Up.GetInt();
|
|
||||||
str_copy(Info.m_aVersion, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aVersion));
|
|
||||||
str_copy(Info.m_aName, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aName));
|
|
||||||
str_copy(Info.m_aHostname, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aHostname));
|
|
||||||
str_copy(Info.m_aMap, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aMap));
|
|
||||||
str_copy(Info.m_aGameType, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aGameType));
|
|
||||||
Info.m_Flags = (Up.GetInt()&SERVERINFO_FLAG_PASSWORD) ? IServerBrowser::FLAG_PASSWORD : 0;
|
|
||||||
Info.m_ServerLevel = clamp<int>(Up.GetInt(), SERVERINFO_LEVEL_MIN, SERVERINFO_LEVEL_MAX);
|
|
||||||
Info.m_NumPlayers = Up.GetInt();
|
|
||||||
Info.m_MaxPlayers = Up.GetInt();
|
|
||||||
Info.m_NumClients = Up.GetInt();
|
|
||||||
Info.m_MaxClients = Up.GetInt();
|
|
||||||
|
|
||||||
// don't add invalid info to the server browser list
|
|
||||||
if(Info.m_NumClients < 0 || Info.m_NumClients > MAX_CLIENTS || Info.m_MaxClients < 0 || Info.m_MaxClients > MAX_CLIENTS ||
|
|
||||||
Info.m_NumPlayers < 0 || Info.m_NumPlayers > Info.m_NumClients || Info.m_MaxPlayers < 0 || Info.m_MaxPlayers > Info.m_MaxClients)
|
|
||||||
return;
|
|
||||||
|
|
||||||
net_addr_str(&pPacket->m_Address, Info.m_aAddress, sizeof(Info.m_aAddress), true);
|
net_addr_str(&pPacket->m_Address, Info.m_aAddress, sizeof(Info.m_aAddress), true);
|
||||||
if(Info.m_aHostname[0] == 0)
|
int Token;
|
||||||
str_copy(Info.m_aHostname, Info.m_aAddress, sizeof(Info.m_aHostname));
|
if(!UnpackServerInfo(&Up, &Info, &Token) && !Up.Error())
|
||||||
|
|
||||||
for(int i = 0; i < Info.m_NumClients; i++)
|
|
||||||
{
|
{
|
||||||
str_copy(Info.m_aClients[i].m_aName, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aClients[i].m_aName));
|
|
||||||
str_copy(Info.m_aClients[i].m_aClan, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aClients[i].m_aClan));
|
|
||||||
Info.m_aClients[i].m_Country = Up.GetInt();
|
|
||||||
Info.m_aClients[i].m_Score = Up.GetInt();
|
|
||||||
Info.m_aClients[i].m_Player = Up.GetInt() != 0 ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
str_clean_whitespaces(Info.m_aName);
|
|
||||||
|
|
||||||
if(!Up.Error())
|
|
||||||
{
|
|
||||||
// sort players
|
|
||||||
qsort(Info.m_aClients, Info.m_NumClients, sizeof(*Info.m_aClients), PlayerScoreComp);
|
qsort(Info.m_aClients, Info.m_NumClients, sizeof(*Info.m_aClients), PlayerScoreComp);
|
||||||
|
|
||||||
if(net_addr_comp(&m_ServerAddress, &pPacket->m_Address) == 0)
|
|
||||||
{
|
|
||||||
mem_copy(&m_CurrentServerInfo, &Info, sizeof(m_CurrentServerInfo));
|
|
||||||
m_CurrentServerInfo.m_NetAddr = m_ServerAddress;
|
|
||||||
m_CurrentServerInfoRequestTime = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_ServerBrowser.Set(pPacket->m_Address, CServerBrowser::SET_TOKEN, Token, &Info);
|
m_ServerBrowser.Set(pPacket->m_Address, CServerBrowser::SET_TOKEN, Token, &Info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1022,7 +1031,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
if(Sys)
|
if(Sys)
|
||||||
{
|
{
|
||||||
// system message
|
// system message
|
||||||
if(Msg == NETMSG_MAP_CHANGE)
|
if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_MAP_CHANGE)
|
||||||
{
|
{
|
||||||
const char *pMap = Unpacker.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES);
|
const char *pMap = Unpacker.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES);
|
||||||
int MapCrc = Unpacker.GetInt();
|
int MapCrc = Unpacker.GetInt();
|
||||||
|
@ -1088,7 +1097,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(Msg == NETMSG_MAP_DATA)
|
else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_MAP_DATA)
|
||||||
{
|
{
|
||||||
if(!m_MapdownloadFile)
|
if(!m_MapdownloadFile)
|
||||||
return;
|
return;
|
||||||
|
@ -1133,7 +1142,18 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", "requested next chunk package");
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client/network", "requested next chunk package");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(Msg == NETMSG_CON_READY)
|
else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_SERVERINFO)
|
||||||
|
{
|
||||||
|
CServerInfo Info = {0};
|
||||||
|
net_addr_str(&pPacket->m_Address, Info.m_aAddress, sizeof(Info.m_aAddress), true);
|
||||||
|
if(!UnpackServerInfo(&Unpacker, &Info, 0) && !Unpacker.Error())
|
||||||
|
{
|
||||||
|
qsort(Info.m_aClients, Info.m_NumClients, sizeof(*Info.m_aClients), PlayerScoreComp);
|
||||||
|
mem_copy(&m_CurrentServerInfo, &Info, sizeof(m_CurrentServerInfo));
|
||||||
|
m_CurrentServerInfo.m_NetAddr = m_ServerAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_CON_READY)
|
||||||
{
|
{
|
||||||
GameClient()->OnConnected();
|
GameClient()->OnConnected();
|
||||||
}
|
}
|
||||||
|
@ -1142,7 +1162,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
CMsgPacker Msg(NETMSG_PING_REPLY, true);
|
CMsgPacker Msg(NETMSG_PING_REPLY, true);
|
||||||
SendMsg(&Msg, 0);
|
SendMsg(&Msg, 0);
|
||||||
}
|
}
|
||||||
else if(Msg == NETMSG_RCON_CMD_ADD)
|
else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_CMD_ADD)
|
||||||
{
|
{
|
||||||
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
|
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
|
||||||
const char *pHelp = Unpacker.GetString(CUnpacker::SANITIZE_CC);
|
const char *pHelp = Unpacker.GetString(CUnpacker::SANITIZE_CC);
|
||||||
|
@ -1150,25 +1170,25 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
if(Unpacker.Error() == 0)
|
if(Unpacker.Error() == 0)
|
||||||
m_pConsole->RegisterTemp(pName, pParams, CFGFLAG_SERVER, pHelp);
|
m_pConsole->RegisterTemp(pName, pParams, CFGFLAG_SERVER, pHelp);
|
||||||
}
|
}
|
||||||
else if(Msg == NETMSG_RCON_CMD_REM)
|
else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_CMD_REM)
|
||||||
{
|
{
|
||||||
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
|
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
|
||||||
if(Unpacker.Error() == 0)
|
if(Unpacker.Error() == 0)
|
||||||
m_pConsole->DeregisterTemp(pName);
|
m_pConsole->DeregisterTemp(pName);
|
||||||
}
|
}
|
||||||
else if(Msg == NETMSG_RCON_AUTH_ON)
|
else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_AUTH_ON)
|
||||||
{
|
{
|
||||||
m_RconAuthed = 1;
|
m_RconAuthed = 1;
|
||||||
m_UseTempRconCommands = 1;
|
m_UseTempRconCommands = 1;
|
||||||
}
|
}
|
||||||
else if(Msg == NETMSG_RCON_AUTH_OFF)
|
else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_AUTH_OFF)
|
||||||
{
|
{
|
||||||
m_RconAuthed = 0;
|
m_RconAuthed = 0;
|
||||||
if(m_UseTempRconCommands)
|
if(m_UseTempRconCommands)
|
||||||
m_pConsole->DeregisterTempAll();
|
m_pConsole->DeregisterTempAll();
|
||||||
m_UseTempRconCommands = 0;
|
m_UseTempRconCommands = 0;
|
||||||
}
|
}
|
||||||
else if(Msg == NETMSG_RCON_LINE)
|
else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_LINE)
|
||||||
{
|
{
|
||||||
const char *pLine = Unpacker.GetString();
|
const char *pLine = Unpacker.GetString();
|
||||||
if(Unpacker.Error() == 0)
|
if(Unpacker.Error() == 0)
|
||||||
|
@ -1229,7 +1249,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
|
|
||||||
pData = (const char *)Unpacker.GetRaw(PartSize);
|
pData = (const char *)Unpacker.GetRaw(PartSize);
|
||||||
|
|
||||||
if(Unpacker.Error())
|
if(Unpacker.Error() || NumParts < 1 || NumParts > CSnapshot::MAX_PARTS || Part < 0 || Part >= NumParts || PartSize < 0 || PartSize > MAX_SNAPSHOT_PACKSIZE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(GameTick >= m_CurrentRecvTick)
|
if(GameTick >= m_CurrentRecvTick)
|
||||||
|
@ -1293,7 +1313,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
|
|
||||||
if(CompleteSize)
|
if(CompleteSize)
|
||||||
{
|
{
|
||||||
int IntSize = CVariableInt::Decompress(m_aSnapshotIncommingData, CompleteSize, aTmpBuffer2);
|
int IntSize = CVariableInt::Decompress(m_aSnapshotIncommingData, CompleteSize, aTmpBuffer2, sizeof(aTmpBuffer2));
|
||||||
|
|
||||||
if(IntSize < 0) // failure during decompression, bail
|
if(IntSize < 0) // failure during decompression, bail
|
||||||
return;
|
return;
|
||||||
|
@ -1373,7 +1393,6 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
m_GameTime.Init((GameTick-1)*time_freq()/50);
|
m_GameTime.Init((GameTick-1)*time_freq()/50);
|
||||||
m_aSnapshots[SNAP_PREV] = m_SnapshotStorage.m_pFirst;
|
m_aSnapshots[SNAP_PREV] = m_SnapshotStorage.m_pFirst;
|
||||||
m_aSnapshots[SNAP_CURRENT] = m_SnapshotStorage.m_pLast;
|
m_aSnapshots[SNAP_CURRENT] = m_SnapshotStorage.m_pLast;
|
||||||
m_LocalStartTime = time_get();
|
|
||||||
SetState(IClient::STATE_ONLINE);
|
SetState(IClient::STATE_ONLINE);
|
||||||
DemoRecorder_HandleAutoStart();
|
DemoRecorder_HandleAutoStart();
|
||||||
}
|
}
|
||||||
|
@ -1394,6 +1413,8 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0)
|
||||||
{
|
{
|
||||||
// game message
|
// game message
|
||||||
GameClient()->OnMessage(Msg, &Unpacker);
|
GameClient()->OnMessage(Msg, &Unpacker);
|
||||||
|
@ -1402,6 +1423,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
m_DemoRecorder.RecordMessage(pPacket->m_pData, pPacket->m_DataSize);
|
m_DemoRecorder.RecordMessage(pPacket->m_pData, pPacket->m_DataSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CClient::PumpNetwork()
|
void CClient::PumpNetwork()
|
||||||
{
|
{
|
||||||
|
@ -1429,15 +1451,21 @@ void CClient::PumpNetwork()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// process packets
|
// process non-connless packets
|
||||||
CNetChunk Packet;
|
CNetChunk Packet;
|
||||||
while(m_NetClient.Recv(&Packet))
|
while(m_NetClient.Recv(&Packet))
|
||||||
{
|
{
|
||||||
if(Packet.m_ClientID == -1)
|
if(!(Packet.m_Flags&NETSENDFLAG_CONNLESS))
|
||||||
ProcessConnlessPacket(&Packet);
|
|
||||||
else
|
|
||||||
ProcessServerPacket(&Packet);
|
ProcessServerPacket(&Packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// process connless packets data
|
||||||
|
m_ContactClient.Update();
|
||||||
|
while(m_ContactClient.Recv(&Packet))
|
||||||
|
{
|
||||||
|
if(Packet.m_Flags&NETSENDFLAG_CONNLESS)
|
||||||
|
ProcessConnlessPacket(&Packet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::OnDemoPlayerSnapshot(void *pData, int Size)
|
void CClient::OnDemoPlayerSnapshot(void *pData, int Size)
|
||||||
|
@ -1601,15 +1629,6 @@ void CClient::Update()
|
||||||
if(m_PredTick > m_CurGameTick && m_PredTick < m_CurGameTick+50)
|
if(m_PredTick > m_CurGameTick && m_PredTick < m_CurGameTick+50)
|
||||||
GameClient()->OnPredict();
|
GameClient()->OnPredict();
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch server info if we don't have it
|
|
||||||
if(State() >= IClient::STATE_LOADING &&
|
|
||||||
m_CurrentServerInfoRequestTime >= 0 &&
|
|
||||||
time_get() > m_CurrentServerInfoRequestTime)
|
|
||||||
{
|
|
||||||
m_ServerBrowser.Request(m_ServerAddress);
|
|
||||||
m_CurrentServerInfoRequestTime = time_get()+time_freq()*2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// STRESS TEST: join the server again
|
// STRESS TEST: join the server again
|
||||||
|
@ -1646,18 +1665,24 @@ void CClient::Update()
|
||||||
// update the server browser
|
// update the server browser
|
||||||
m_ServerBrowser.Update(m_ResortServerBrowser);
|
m_ServerBrowser.Update(m_ResortServerBrowser);
|
||||||
m_ResortServerBrowser = false;
|
m_ResortServerBrowser = false;
|
||||||
|
|
||||||
|
// update gameclient
|
||||||
|
if(!m_EditorActive)
|
||||||
|
GameClient()->OnUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::VersionUpdate()
|
void CClient::VersionUpdate()
|
||||||
{
|
{
|
||||||
if(m_VersionInfo.m_State == CVersionInfo::STATE_INIT)
|
if(m_VersionInfo.m_State == CVersionInfo::STATE_INIT)
|
||||||
{
|
{
|
||||||
Engine()->HostLookup(&m_VersionInfo.m_VersionServeraddr, g_Config.m_ClVersionServer, m_NetClient.NetType());
|
Engine()->HostLookup(&m_VersionInfo.m_VersionServeraddr, g_Config.m_ClVersionServer, m_ContactClient.NetType());
|
||||||
m_VersionInfo.m_State = CVersionInfo::STATE_START;
|
m_VersionInfo.m_State = CVersionInfo::STATE_START;
|
||||||
}
|
}
|
||||||
else if(m_VersionInfo.m_State == CVersionInfo::STATE_START)
|
else if(m_VersionInfo.m_State == CVersionInfo::STATE_START)
|
||||||
{
|
{
|
||||||
if(m_VersionInfo.m_VersionServeraddr.m_Job.Status() == CJob::STATE_DONE)
|
if(m_VersionInfo.m_VersionServeraddr.m_Job.Status() == CJob::STATE_DONE)
|
||||||
|
{
|
||||||
|
if(m_VersionInfo.m_VersionServeraddr.m_Job.Result() == 0)
|
||||||
{
|
{
|
||||||
CNetChunk Packet;
|
CNetChunk Packet;
|
||||||
|
|
||||||
|
@ -1671,9 +1696,12 @@ void CClient::VersionUpdate()
|
||||||
Packet.m_DataSize = sizeof(VERSIONSRV_GETVERSION);
|
Packet.m_DataSize = sizeof(VERSIONSRV_GETVERSION);
|
||||||
Packet.m_Flags = NETSENDFLAG_CONNLESS;
|
Packet.m_Flags = NETSENDFLAG_CONNLESS;
|
||||||
|
|
||||||
m_NetClient.Send(&Packet);
|
m_ContactClient.Send(&Packet);
|
||||||
m_VersionInfo.m_State = CVersionInfo::STATE_READY;
|
m_VersionInfo.m_State = CVersionInfo::STATE_READY;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
m_VersionInfo.m_State = CVersionInfo::STATE_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1699,10 +1727,90 @@ void CClient::InitInterfaces()
|
||||||
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
||||||
|
|
||||||
//
|
//
|
||||||
m_ServerBrowser.SetBaseInfo(&m_NetClient, m_pGameClient->NetVersion());
|
m_ServerBrowser.Init(&m_ContactClient, m_pGameClient->NetVersion());
|
||||||
m_Friends.Init();
|
m_Friends.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CClient::LimitFps()
|
||||||
|
{
|
||||||
|
if(g_Config.m_GfxVsync || !g_Config.m_GfxLimitFps) return false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
If desired frame time is not reached:
|
||||||
|
Skip rendering the frame
|
||||||
|
Do another game loop
|
||||||
|
|
||||||
|
If we don't have the time to do another game loop:
|
||||||
|
Wait until desired frametime
|
||||||
|
|
||||||
|
Returns true if frame should be skipped
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifdef CONF_DEBUG
|
||||||
|
static double DbgTimeWaited = 0.0;
|
||||||
|
static int64 DbgFramesSkippedCount = 0;
|
||||||
|
static int64 DbgLastSkippedDbgMsg = time_get();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int64 Now = time_get();
|
||||||
|
const double LastCpuFrameTime = (Now - m_LastCpuTime) / (double)time_freq();
|
||||||
|
m_LastAvgCpuFrameTime = (m_LastAvgCpuFrameTime + LastCpuFrameTime * 4.0) / 5.0;
|
||||||
|
m_LastCpuTime = Now;
|
||||||
|
|
||||||
|
bool SkipFrame = true;
|
||||||
|
double RenderDeltaTime = (Now - m_LastRenderTime) / (double)time_freq();
|
||||||
|
const double DesiredTime = 1.0/g_Config.m_GfxMaxFps;
|
||||||
|
|
||||||
|
// we can't skip another frame, so wait instead
|
||||||
|
if(SkipFrame && RenderDeltaTime < DesiredTime &&
|
||||||
|
m_LastAvgCpuFrameTime * 1.20 > (DesiredTime - RenderDeltaTime))
|
||||||
|
{
|
||||||
|
#ifdef CONF_DEBUG
|
||||||
|
DbgTimeWaited += DesiredTime - RenderDeltaTime;
|
||||||
|
#endif
|
||||||
|
const double Freq = (double)time_freq();
|
||||||
|
const int64 LastT = m_LastRenderTime;
|
||||||
|
double d = DesiredTime - RenderDeltaTime;
|
||||||
|
while(d > 0.00001)
|
||||||
|
{
|
||||||
|
Now = time_get();
|
||||||
|
RenderDeltaTime = (Now - LastT) / Freq;
|
||||||
|
d = DesiredTime - RenderDeltaTime;
|
||||||
|
_mm_pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
SkipFrame = false;
|
||||||
|
m_LastCpuTime = Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderDeltaTime exceeds DesiredTime, render
|
||||||
|
if(SkipFrame && RenderDeltaTime > DesiredTime)
|
||||||
|
{
|
||||||
|
SkipFrame = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONF_DEBUG
|
||||||
|
DbgFramesSkippedCount += SkipFrame? 1:0;
|
||||||
|
|
||||||
|
Now = time_get();
|
||||||
|
if(g_Config.m_GfxLimitFps &&
|
||||||
|
g_Config.m_Debug &&
|
||||||
|
(Now - DbgLastSkippedDbgMsg) / (double)time_freq() > 5.0)
|
||||||
|
{
|
||||||
|
char aBuf[128];
|
||||||
|
str_format(aBuf, sizeof(aBuf), "LimitFps: FramesSkippedCount=%d TimeWaited=%.3f (per sec)",
|
||||||
|
DbgFramesSkippedCount/5,
|
||||||
|
DbgTimeWaited/5.0);
|
||||||
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client", aBuf);
|
||||||
|
DbgFramesSkippedCount = 0;
|
||||||
|
DbgTimeWaited = 0;
|
||||||
|
DbgLastSkippedDbgMsg = Now;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return SkipFrame;
|
||||||
|
}
|
||||||
|
|
||||||
void CClient::Run()
|
void CClient::Run()
|
||||||
{
|
{
|
||||||
m_LocalStartTime = time_get();
|
m_LocalStartTime = time_get();
|
||||||
|
@ -1753,9 +1861,15 @@ void CClient::Run()
|
||||||
mem_zero(&BindAddr, sizeof(BindAddr));
|
mem_zero(&BindAddr, sizeof(BindAddr));
|
||||||
BindAddr.type = NETTYPE_ALL;
|
BindAddr.type = NETTYPE_ALL;
|
||||||
}
|
}
|
||||||
if(!m_NetClient.Open(BindAddr, 0))
|
if(!m_NetClient.Open(BindAddr, BindAddr.port ? 0 : NETCREATE_FLAG_RANDOMPORT))
|
||||||
{
|
{
|
||||||
dbg_msg("client", "couldn't open socket");
|
dbg_msg("client", "couldn't open socket(net)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BindAddr.port = 0;
|
||||||
|
if(!m_ContactClient.Open(BindAddr, 0))
|
||||||
|
{
|
||||||
|
dbg_msg("client", "couldn't open socket(contact)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1767,7 +1881,7 @@ void CClient::Run()
|
||||||
Input()->Init();
|
Input()->Init();
|
||||||
|
|
||||||
// start refreshing addresses while we load
|
// start refreshing addresses while we load
|
||||||
MasterServer()->RefreshAddresses(m_NetClient.NetType());
|
MasterServer()->RefreshAddresses(m_ContactClient.NetType());
|
||||||
|
|
||||||
// init the editor
|
// init the editor
|
||||||
m_pEditor->Init();
|
m_pEditor->Init();
|
||||||
|
@ -1783,21 +1897,12 @@ void CClient::Run()
|
||||||
str_format(aBuf, sizeof(aBuf), "version %s", GameClient()->NetVersion());
|
str_format(aBuf, sizeof(aBuf), "version %s", GameClient()->NetVersion());
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
|
||||||
|
|
||||||
// connect to the server if wanted
|
|
||||||
/*
|
|
||||||
if(config.cl_connect[0] != 0)
|
|
||||||
Connect(config.cl_connect);
|
|
||||||
config.cl_connect[0] = 0;
|
|
||||||
*/
|
|
||||||
|
|
||||||
//
|
//
|
||||||
m_FpsGraph.Init(0.0f, 200.0f);
|
m_FpsGraph.Init(0.0f, 120.0f);
|
||||||
|
|
||||||
// never start with the editor
|
// never start with the editor
|
||||||
g_Config.m_ClEditor = 0;
|
g_Config.m_ClEditor = 0;
|
||||||
|
|
||||||
Input()->MouseModeRelative();
|
|
||||||
|
|
||||||
// process pending commands
|
// process pending commands
|
||||||
m_pConsole->StoreCommands(false);
|
m_pConsole->StoreCommands(false);
|
||||||
|
|
||||||
|
@ -1828,7 +1933,7 @@ void CClient::Run()
|
||||||
Input()->MouseModeAbsolute();
|
Input()->MouseModeAbsolute();
|
||||||
m_WindowMustRefocus = 1;
|
m_WindowMustRefocus = 1;
|
||||||
}
|
}
|
||||||
else if (g_Config.m_DbgFocus && Input()->KeyPressed(KEY_ESCAPE))
|
else if (g_Config.m_DbgFocus && Input()->KeyPress(KEY_ESCAPE, true))
|
||||||
{
|
{
|
||||||
Input()->MouseModeAbsolute();
|
Input()->MouseModeAbsolute();
|
||||||
m_WindowMustRefocus = 1;
|
m_WindowMustRefocus = 1;
|
||||||
|
@ -1843,37 +1948,37 @@ void CClient::Run()
|
||||||
m_WindowMustRefocus++;
|
m_WindowMustRefocus++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_WindowMustRefocus >= 3 || Input()->KeyPressed(KEY_MOUSE_1))
|
if(m_WindowMustRefocus >= 3 || Input()->KeyPress(KEY_MOUSE_1, true))
|
||||||
{
|
{
|
||||||
Input()->MouseModeRelative();
|
Input()->MouseModeRelative();
|
||||||
m_WindowMustRefocus = 0;
|
m_WindowMustRefocus = 0;
|
||||||
|
|
||||||
|
// update screen in case it got moved
|
||||||
|
int ActScreen = Graphics()->GetWindowScreen();
|
||||||
|
if(ActScreen >= 0 && ActScreen != g_Config.m_GfxScreen)
|
||||||
|
g_Config.m_GfxScreen = ActScreen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// panic quit button
|
// panic quit button
|
||||||
if(Input()->KeyPressed(KEY_LCTRL) && Input()->KeyPressed(KEY_LSHIFT) && Input()->KeyPressed(KEY_Q))
|
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyIsPressed(KEY_LSHIFT) && Input()->KeyPress(KEY_Q, true))
|
||||||
{
|
{
|
||||||
Quit();
|
Quit();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Input()->KeyPressed(KEY_LCTRL) && Input()->KeyPressed(KEY_LSHIFT) && Input()->KeyDown(KEY_D))
|
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyIsPressed(KEY_LSHIFT) && Input()->KeyPress(KEY_D, true))
|
||||||
g_Config.m_Debug ^= 1;
|
g_Config.m_Debug ^= 1;
|
||||||
|
|
||||||
if(Input()->KeyPressed(KEY_LCTRL) && Input()->KeyPressed(KEY_LSHIFT) && Input()->KeyDown(KEY_G))
|
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyIsPressed(KEY_LSHIFT) && Input()->KeyPress(KEY_G, true))
|
||||||
g_Config.m_DbgGraphs ^= 1;
|
g_Config.m_DbgGraphs ^= 1;
|
||||||
|
|
||||||
if(Input()->KeyPressed(KEY_LCTRL) && Input()->KeyPressed(KEY_LSHIFT) && Input()->KeyDown(KEY_E))
|
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyIsPressed(KEY_LSHIFT) && Input()->KeyPress(KEY_E, true))
|
||||||
{
|
{
|
||||||
g_Config.m_ClEditor = g_Config.m_ClEditor^1;
|
g_Config.m_ClEditor = g_Config.m_ClEditor^1;
|
||||||
Input()->MouseModeRelative();
|
Input()->MouseModeRelative();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if(!gfx_window_open())
|
|
||||||
break;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// render
|
// render
|
||||||
{
|
{
|
||||||
if(g_Config.m_ClEditor)
|
if(g_Config.m_ClEditor)
|
||||||
|
@ -1889,13 +1994,16 @@ void CClient::Run()
|
||||||
|
|
||||||
Update();
|
Update();
|
||||||
|
|
||||||
if(!g_Config.m_GfxAsyncRender || m_pGraphics->IsIdle())
|
const bool SkipFrame = LimitFps();
|
||||||
|
|
||||||
|
if(!SkipFrame && (!g_Config.m_GfxAsyncRender || m_pGraphics->IsIdle()))
|
||||||
{
|
{
|
||||||
m_RenderFrames++;
|
m_RenderFrames++;
|
||||||
|
|
||||||
// update frametime
|
// update frametime
|
||||||
int64 Now = time_get();
|
int64 Now = time_get();
|
||||||
m_RenderFrameTime = (Now - m_LastRenderTime) / (float)time_freq();
|
m_RenderFrameTime = (Now - m_LastRenderTime) / (float)time_freq();
|
||||||
|
|
||||||
if(m_RenderFrameTime < m_RenderFrameTimeLow)
|
if(m_RenderFrameTime < m_RenderFrameTimeLow)
|
||||||
m_RenderFrameTimeLow = m_RenderFrameTime;
|
m_RenderFrameTimeLow = m_RenderFrameTime;
|
||||||
if(m_RenderFrameTime > m_RenderFrameTimeHigh)
|
if(m_RenderFrameTime > m_RenderFrameTimeHigh)
|
||||||
|
@ -1972,6 +2080,8 @@ void CClient::Run()
|
||||||
m_pGraphics->Shutdown();
|
m_pGraphics->Shutdown();
|
||||||
m_pSound->Shutdown();
|
m_pSound->Shutdown();
|
||||||
|
|
||||||
|
m_ServerBrowser.SaveServerlist();
|
||||||
|
|
||||||
// shutdown SDL
|
// shutdown SDL
|
||||||
{
|
{
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
@ -2193,6 +2303,89 @@ void CClient::ConchainServerBrowserUpdate(IConsole::IResult *pResult, void *pUse
|
||||||
((CClient *)pUserData)->ServerBrowserUpdate();
|
((CClient *)pUserData)->ServerBrowserUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CClient::SwitchWindowScreen(int Index)
|
||||||
|
{
|
||||||
|
// Todo SDL: remove this when fixed (changing screen when in fullscreen is bugged)
|
||||||
|
if(g_Config.m_GfxFullscreen)
|
||||||
|
{
|
||||||
|
ToggleFullscreen();
|
||||||
|
if(Graphics()->SetWindowScreen(Index))
|
||||||
|
g_Config.m_GfxScreen = Index;
|
||||||
|
ToggleFullscreen();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(Graphics()->SetWindowScreen(Index))
|
||||||
|
g_Config.m_GfxScreen = Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClient::ConchainWindowScreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
||||||
|
{
|
||||||
|
CClient *pSelf = (CClient *)pUserData;
|
||||||
|
if(pSelf->Graphics() && pResult->NumArguments())
|
||||||
|
{
|
||||||
|
if(g_Config.m_GfxScreen != pResult->GetInteger(0))
|
||||||
|
pSelf->SwitchWindowScreen(pResult->GetInteger(0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pfnCallback(pResult, pCallbackUserData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClient::ToggleFullscreen()
|
||||||
|
{
|
||||||
|
if(Graphics()->Fullscreen(g_Config.m_GfxFullscreen^1))
|
||||||
|
g_Config.m_GfxFullscreen ^= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClient::ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
||||||
|
{
|
||||||
|
CClient *pSelf = (CClient *)pUserData;
|
||||||
|
if(pSelf->Graphics() && pResult->NumArguments())
|
||||||
|
{
|
||||||
|
if(g_Config.m_GfxFullscreen != pResult->GetInteger(0))
|
||||||
|
pSelf->ToggleFullscreen();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pfnCallback(pResult, pCallbackUserData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClient::ToggleWindowBordered()
|
||||||
|
{
|
||||||
|
g_Config.m_GfxBorderless ^= 1;
|
||||||
|
Graphics()->SetWindowBordered(!g_Config.m_GfxBorderless);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClient::ConchainWindowBordered(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
||||||
|
{
|
||||||
|
CClient *pSelf = (CClient *)pUserData;
|
||||||
|
if(pSelf->Graphics() && pResult->NumArguments())
|
||||||
|
{
|
||||||
|
if(!g_Config.m_GfxFullscreen && (g_Config.m_GfxBorderless != pResult->GetInteger(0)))
|
||||||
|
pSelf->ToggleWindowBordered();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pfnCallback(pResult, pCallbackUserData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClient::ToggleWindowVSync()
|
||||||
|
{
|
||||||
|
if(Graphics()->SetVSync(g_Config.m_GfxVsync^1))
|
||||||
|
g_Config.m_GfxVsync ^= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClient::ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
|
||||||
|
{
|
||||||
|
CClient *pSelf = (CClient *)pUserData;
|
||||||
|
if(pSelf->Graphics() && pResult->NumArguments())
|
||||||
|
{
|
||||||
|
if(g_Config.m_GfxVsync != pResult->GetInteger(0))
|
||||||
|
pSelf->ToggleWindowVSync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pfnCallback(pResult, pCallbackUserData);
|
||||||
|
}
|
||||||
|
|
||||||
void CClient::RegisterCommands()
|
void CClient::RegisterCommands()
|
||||||
{
|
{
|
||||||
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
||||||
|
@ -2213,8 +2406,11 @@ void CClient::RegisterCommands()
|
||||||
|
|
||||||
// used for server browser update
|
// used for server browser update
|
||||||
m_pConsole->Chain("br_filter_string", ConchainServerBrowserUpdate, this);
|
m_pConsole->Chain("br_filter_string", ConchainServerBrowserUpdate, this);
|
||||||
m_pConsole->Chain("br_filter_gametype", ConchainServerBrowserUpdate, this);
|
|
||||||
m_pConsole->Chain("br_filter_serveraddress", ConchainServerBrowserUpdate, this);
|
m_pConsole->Chain("gfx_screen", ConchainWindowScreen, this);
|
||||||
|
m_pConsole->Chain("gfx_fullscreen", ConchainFullscreen, this);
|
||||||
|
m_pConsole->Chain("gfx_borderless", ConchainWindowBordered, this);
|
||||||
|
m_pConsole->Chain("gfx_vsync", ConchainWindowVSync, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CClient *CreateClient()
|
static CClient *CreateClient()
|
||||||
|
@ -2224,6 +2420,11 @@ static CClient *CreateClient()
|
||||||
return new(pClient) CClient;
|
return new(pClient) CClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CClient::HandleTeeworldsConnectLink(const char *pConLink)
|
||||||
|
{
|
||||||
|
str_copy(m_aCmdConnect, pConLink, sizeof(m_aCmdConnect));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Server Time
|
Server Time
|
||||||
Client Mirror Time
|
Client Mirror Time
|
||||||
|
@ -2235,7 +2436,6 @@ static CClient *CreateClient()
|
||||||
Prediction Latency
|
Prediction Latency
|
||||||
Upstream latency
|
Upstream latency
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(CONF_PLATFORM_MACOSX)
|
#if defined(CONF_PLATFORM_MACOSX)
|
||||||
extern "C" int SDL_main(int argc, char **argv_) // ignore_convention
|
extern "C" int SDL_main(int argc, char **argv_) // ignore_convention
|
||||||
{
|
{
|
||||||
|
@ -2245,14 +2445,27 @@ int main(int argc, const char **argv) // ignore_convention
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
|
#ifdef CONF_RELEASE
|
||||||
|
bool HideConsole = true;
|
||||||
|
#else
|
||||||
|
bool HideConsole = false;
|
||||||
|
#endif
|
||||||
for(int i = 1; i < argc; i++) // ignore_convention
|
for(int i = 1; i < argc; i++) // ignore_convention
|
||||||
{
|
{
|
||||||
|
if(str_comp("-c", argv[i]) == 0 || str_comp("--console", argv[i]) == 0) // ignore_convention
|
||||||
|
{
|
||||||
|
HideConsole = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(str_comp("-s", argv[i]) == 0 || str_comp("--silent", argv[i]) == 0) // ignore_convention
|
if(str_comp("-s", argv[i]) == 0 || str_comp("--silent", argv[i]) == 0) // ignore_convention
|
||||||
{
|
{
|
||||||
FreeConsole();
|
HideConsole = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(HideConsole)
|
||||||
|
FreeConsole();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool UseDefaultConfig = false;
|
bool UseDefaultConfig = false;
|
||||||
|
@ -2335,9 +2548,26 @@ int main(int argc, const char **argv) // ignore_convention
|
||||||
|
|
||||||
// parse the command line arguments
|
// parse the command line arguments
|
||||||
if(argc > 1) // ignore_convention
|
if(argc > 1) // ignore_convention
|
||||||
|
{
|
||||||
|
switch(argc) // ignore_convention
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
// handle Teeworlds connect link
|
||||||
|
const int Length = str_length(pClient->m_pConLinkIdentifier);
|
||||||
|
if(str_comp_num(pClient->m_pConLinkIdentifier, argv[1], Length) == 0) // ignore_convention
|
||||||
|
{
|
||||||
|
pClient->HandleTeeworldsConnectLink(argv[1] + Length); // ignore_convention
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
pConsole->ParseArguments(argc - 1, &argv[1]); // ignore_convention
|
pConsole->ParseArguments(argc - 1, &argv[1]); // ignore_convention
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// restore empty config strings to their defaults
|
// restore empty config strings to their defaults
|
||||||
pConfig->RestoreStrings();
|
pConfig->RestoreStrings();
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
float m_Min, m_Max;
|
float m_Min, m_Max;
|
||||||
|
float m_MinRange, m_MaxRange;
|
||||||
float m_aValues[MAX_VALUES];
|
float m_aValues[MAX_VALUES];
|
||||||
float m_aColors[MAX_VALUES][3];
|
float m_aColors[MAX_VALUES][3];
|
||||||
int m_Index;
|
int m_Index;
|
||||||
|
@ -70,6 +71,7 @@ class CClient : public IClient, public CDemoPlayer::IListner
|
||||||
};
|
};
|
||||||
|
|
||||||
class CNetClient m_NetClient;
|
class CNetClient m_NetClient;
|
||||||
|
class CNetClient m_ContactClient;
|
||||||
class CDemoPlayer m_DemoPlayer;
|
class CDemoPlayer m_DemoPlayer;
|
||||||
class CDemoRecorder m_DemoRecorder;
|
class CDemoRecorder m_DemoRecorder;
|
||||||
class CServerBrowser m_ServerBrowser;
|
class CServerBrowser m_ServerBrowser;
|
||||||
|
@ -84,6 +86,8 @@ class CClient : public IClient, public CDemoPlayer::IListner
|
||||||
IGraphics::CTextureHandle m_DebugFont;
|
IGraphics::CTextureHandle m_DebugFont;
|
||||||
|
|
||||||
int64 m_LastRenderTime;
|
int64 m_LastRenderTime;
|
||||||
|
int64 m_LastCpuTime;
|
||||||
|
float m_LastAvgCpuFrameTime;
|
||||||
float m_RenderFrameTimeLow;
|
float m_RenderFrameTimeLow;
|
||||||
float m_RenderFrameTimeHigh;
|
float m_RenderFrameTimeHigh;
|
||||||
int m_RenderFrames;
|
int m_RenderFrames;
|
||||||
|
@ -161,7 +165,6 @@ class CClient : public IClient, public CDemoPlayer::IListner
|
||||||
|
|
||||||
//
|
//
|
||||||
class CServerInfo m_CurrentServerInfo;
|
class CServerInfo m_CurrentServerInfo;
|
||||||
int64 m_CurrentServerInfoRequestTime; // >= 0 should request, == -1 got info
|
|
||||||
|
|
||||||
// version info
|
// version info
|
||||||
struct CVersionInfo
|
struct CVersionInfo
|
||||||
|
@ -171,6 +174,7 @@ class CClient : public IClient, public CDemoPlayer::IListner
|
||||||
STATE_INIT=0,
|
STATE_INIT=0,
|
||||||
STATE_START,
|
STATE_START,
|
||||||
STATE_READY,
|
STATE_READY,
|
||||||
|
STATE_ERROR,
|
||||||
};
|
};
|
||||||
|
|
||||||
int m_State;
|
int m_State;
|
||||||
|
@ -208,7 +212,6 @@ public:
|
||||||
|
|
||||||
virtual IGraphics::CTextureHandle GetDebugFont() const { return m_DebugFont; }
|
virtual IGraphics::CTextureHandle GetDebugFont() const { return m_DebugFont; }
|
||||||
|
|
||||||
void DirectInput(int *pInput, int Size);
|
|
||||||
void SendInput();
|
void SendInput();
|
||||||
|
|
||||||
// TODO: OPT: do this alot smarter!
|
// TODO: OPT: do this alot smarter!
|
||||||
|
@ -230,7 +233,6 @@ public:
|
||||||
|
|
||||||
|
|
||||||
virtual void GetServerInfo(CServerInfo *pServerInfo) const;
|
virtual void GetServerInfo(CServerInfo *pServerInfo) const;
|
||||||
void ServerInfoRequest();
|
|
||||||
|
|
||||||
int LoadData();
|
int LoadData();
|
||||||
|
|
||||||
|
@ -255,9 +257,11 @@ public:
|
||||||
|
|
||||||
static int PlayerScoreComp(const void *a, const void *b);
|
static int PlayerScoreComp(const void *a, const void *b);
|
||||||
|
|
||||||
|
int UnpackServerInfo(CUnpacker *pUnpacker, CServerInfo *pInfo, int *pToken);
|
||||||
void ProcessConnlessPacket(CNetChunk *pPacket);
|
void ProcessConnlessPacket(CNetChunk *pPacket);
|
||||||
void ProcessServerPacket(CNetChunk *pPacket);
|
void ProcessServerPacket(CNetChunk *pPacket);
|
||||||
|
|
||||||
|
virtual const char *MapDownloadName() const { return m_aMapdownloadName; }
|
||||||
virtual int MapDownloadAmount() const { return m_MapdownloadAmount; }
|
virtual int MapDownloadAmount() const { return m_MapdownloadAmount; }
|
||||||
virtual int MapDownloadTotalsize() const { return m_MapdownloadTotalsize; }
|
virtual int MapDownloadTotalsize() const { return m_MapdownloadTotalsize; }
|
||||||
|
|
||||||
|
@ -271,6 +275,7 @@ public:
|
||||||
void RegisterInterfaces();
|
void RegisterInterfaces();
|
||||||
void InitInterfaces();
|
void InitInterfaces();
|
||||||
|
|
||||||
|
bool LimitFps();
|
||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
|
|
||||||
|
@ -289,6 +294,10 @@ public:
|
||||||
static void Con_StopRecord(IConsole::IResult *pResult, void *pUserData);
|
static void Con_StopRecord(IConsole::IResult *pResult, void *pUserData);
|
||||||
static void Con_AddDemoMarker(IConsole::IResult *pResult, void *pUserData);
|
static void Con_AddDemoMarker(IConsole::IResult *pResult, void *pUserData);
|
||||||
static void ConchainServerBrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
static void ConchainServerBrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||||
|
static void ConchainFullscreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||||
|
static void ConchainWindowBordered(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||||
|
static void ConchainWindowScreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||||
|
static void ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||||
|
|
||||||
void RegisterCommands();
|
void RegisterCommands();
|
||||||
|
|
||||||
|
@ -303,5 +312,15 @@ public:
|
||||||
void AutoScreenshot_Cleanup();
|
void AutoScreenshot_Cleanup();
|
||||||
|
|
||||||
void ServerBrowserUpdate();
|
void ServerBrowserUpdate();
|
||||||
|
|
||||||
|
// gfx
|
||||||
|
void SwitchWindowScreen(int Index);
|
||||||
|
void ToggleFullscreen();
|
||||||
|
void ToggleWindowBordered();
|
||||||
|
void ToggleWindowVSync();
|
||||||
|
|
||||||
|
// Teeworlds connect link
|
||||||
|
const char * const m_pConLinkIdentifier;
|
||||||
|
void HandleTeeworldsConnectLink(const char *pConLink);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -264,20 +264,22 @@ void CGraphics_Threaded::LinesDraw(const CLineItem *pArray, int Num)
|
||||||
AddVertices(2*Num);
|
AddVertices(2*Num);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CGraphics_Threaded::UnloadTexture(CTextureHandle Index)
|
int CGraphics_Threaded::UnloadTexture(CTextureHandle *Index)
|
||||||
{
|
{
|
||||||
if(Index.Id() == m_InvalidTexture.Id())
|
if(Index->Id() == m_InvalidTexture.Id())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(!Index.IsValid())
|
if(!Index->IsValid())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
CCommandBuffer::SCommand_Texture_Destroy Cmd;
|
CCommandBuffer::SCommand_Texture_Destroy Cmd;
|
||||||
Cmd.m_Slot = Index.Id();
|
Cmd.m_Slot = Index->Id();
|
||||||
m_pCommandBuffer->AddCommand(Cmd);
|
m_pCommandBuffer->AddCommand(Cmd);
|
||||||
|
|
||||||
m_aTextureIndices[Index.Id()] = m_FirstFreeTexture;
|
m_aTextureIndices[Index->Id()] = m_FirstFreeTexture;
|
||||||
m_FirstFreeTexture = Index.Id();
|
m_FirstFreeTexture = Index->Id();
|
||||||
|
|
||||||
|
Index->Invalidate();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,6 +360,8 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(int Width, int Heig
|
||||||
}
|
}
|
||||||
if(Flags&IGraphics::TEXLOAD_MULTI_DIMENSION)
|
if(Flags&IGraphics::TEXLOAD_MULTI_DIMENSION)
|
||||||
Cmd.m_Flags |= CCommandBuffer::TEXFLAG_TEXTURE3D;
|
Cmd.m_Flags |= CCommandBuffer::TEXFLAG_TEXTURE3D;
|
||||||
|
if(Flags&IGraphics::TEXLOAD_LINEARMIPMAPS)
|
||||||
|
Cmd.m_Flags |= CCommandBuffer::TEXTFLAG_LINEARMIPMAPS;
|
||||||
|
|
||||||
|
|
||||||
// copy texture data
|
// copy texture data
|
||||||
|
@ -424,7 +428,7 @@ int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int Sto
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Png.depth != 8 || (Png.color_type != PNG_TRUECOLOR && Png.color_type != PNG_TRUECOLOR_ALPHA)) // ignore_convention
|
if(Png.depth != 8 || (Png.color_type != PNG_TRUECOLOR && Png.color_type != PNG_TRUECOLOR_ALPHA) || Png.width > (2<<12) || Png.height > (2<<12)) // ignore_convention
|
||||||
{
|
{
|
||||||
dbg_msg("game/png", "invalid format. filename='%s'", aCompleteFilename);
|
dbg_msg("game/png", "invalid format. filename='%s'", aCompleteFilename);
|
||||||
png_close_file(&Png); // ignore_convention
|
png_close_file(&Png); // ignore_convention
|
||||||
|
@ -463,6 +467,8 @@ void CGraphics_Threaded::ScreenshotDirect(const char *pFilename)
|
||||||
|
|
||||||
CCommandBuffer::SCommand_Screenshot Cmd;
|
CCommandBuffer::SCommand_Screenshot Cmd;
|
||||||
Cmd.m_pImage = &Image;
|
Cmd.m_pImage = &Image;
|
||||||
|
Cmd.m_X = 0; Cmd.m_Y = 0;
|
||||||
|
Cmd.m_W = -1; Cmd.m_H = -1;
|
||||||
m_pCommandBuffer->AddCommand(Cmd);
|
m_pCommandBuffer->AddCommand(Cmd);
|
||||||
|
|
||||||
// kick the buffer and wait for the result
|
// kick the buffer and wait for the result
|
||||||
|
@ -516,6 +522,7 @@ void CGraphics_Threaded::QuadsBegin()
|
||||||
QuadsSetSubset(0,0,1,1,-1);
|
QuadsSetSubset(0,0,1,1,-1);
|
||||||
QuadsSetRotation(0);
|
QuadsSetRotation(0);
|
||||||
SetColor(1,1,1,1);
|
SetColor(1,1,1,1);
|
||||||
|
m_TextureArrayIndex = m_pBackend->GetTextureArraySize() > 1 ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGraphics_Threaded::QuadsEnd()
|
void CGraphics_Threaded::QuadsEnd()
|
||||||
|
@ -566,17 +573,36 @@ void CGraphics_Threaded::SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft,
|
||||||
SetColorVertex(Array, 4);
|
SetColorVertex(Array, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGraphics_Threaded::TilesetFallbackSystem(int TextureIndex)
|
||||||
|
{
|
||||||
|
int NewTextureArrayIndex = TextureIndex / (256 / m_pBackend->GetTextureArraySize());
|
||||||
|
if(m_TextureArrayIndex == -1)
|
||||||
|
m_TextureArrayIndex = NewTextureArrayIndex;
|
||||||
|
else if(m_TextureArrayIndex != NewTextureArrayIndex)
|
||||||
|
{
|
||||||
|
// have to switch the texture index
|
||||||
|
FlushVertices();
|
||||||
|
m_TextureArrayIndex = NewTextureArrayIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CGraphics_Threaded::QuadsSetSubset(float TlU, float TlV, float BrU, float BrV, int TextureIndex)
|
void CGraphics_Threaded::QuadsSetSubset(float TlU, float TlV, float BrU, float BrV, int TextureIndex)
|
||||||
{
|
{
|
||||||
dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetSubset without begin");
|
dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetSubset without begin");
|
||||||
|
|
||||||
|
// tileset fallback system
|
||||||
|
if(m_pBackend->GetTextureArraySize() > 1 && TextureIndex >= 0)
|
||||||
|
TilesetFallbackSystem(TextureIndex);
|
||||||
|
|
||||||
|
m_State.m_TextureArrayIndex = m_TextureArrayIndex;
|
||||||
|
|
||||||
m_aTexture[0].u = TlU; m_aTexture[1].u = BrU;
|
m_aTexture[0].u = TlU; m_aTexture[1].u = BrU;
|
||||||
m_aTexture[0].v = TlV; m_aTexture[1].v = TlV;
|
m_aTexture[0].v = TlV; m_aTexture[1].v = TlV;
|
||||||
|
|
||||||
m_aTexture[3].u = TlU; m_aTexture[2].u = BrU;
|
m_aTexture[3].u = TlU; m_aTexture[2].u = BrU;
|
||||||
m_aTexture[3].v = BrV; m_aTexture[2].v = BrV;
|
m_aTexture[3].v = BrV; m_aTexture[2].v = BrV;
|
||||||
|
|
||||||
m_aTexture[0].i = m_aTexture[1].i = m_aTexture[2].i = m_aTexture[3].i = (0.5f + TextureIndex) / 256.0f;
|
m_aTexture[0].i = m_aTexture[1].i = m_aTexture[2].i = m_aTexture[3].i = (0.5f + TextureIndex) / (256.0f/m_pBackend->GetTextureArraySize());
|
||||||
m_State.m_Dimension = (TextureIndex < 0) ? 2 : 3;
|
m_State.m_Dimension = (TextureIndex < 0) ? 2 : 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,12 +610,18 @@ void CGraphics_Threaded::QuadsSetSubsetFree(
|
||||||
float x0, float y0, float x1, float y1,
|
float x0, float y0, float x1, float y1,
|
||||||
float x2, float y2, float x3, float y3, int TextureIndex)
|
float x2, float y2, float x3, float y3, int TextureIndex)
|
||||||
{
|
{
|
||||||
|
// tileset fallback system
|
||||||
|
if(m_pBackend->GetTextureArraySize() > 1 && TextureIndex >= 0)
|
||||||
|
TilesetFallbackSystem(TextureIndex);
|
||||||
|
|
||||||
|
m_State.m_TextureArrayIndex = m_TextureArrayIndex;
|
||||||
|
|
||||||
m_aTexture[0].u = x0; m_aTexture[0].v = y0;
|
m_aTexture[0].u = x0; m_aTexture[0].v = y0;
|
||||||
m_aTexture[1].u = x1; m_aTexture[1].v = y1;
|
m_aTexture[1].u = x1; m_aTexture[1].v = y1;
|
||||||
m_aTexture[2].u = x2; m_aTexture[2].v = y2;
|
m_aTexture[2].u = x2; m_aTexture[2].v = y2;
|
||||||
m_aTexture[3].u = x3; m_aTexture[3].v = y3;
|
m_aTexture[3].u = x3; m_aTexture[3].v = y3;
|
||||||
|
|
||||||
m_aTexture[0].i = m_aTexture[1].i = m_aTexture[2].i = m_aTexture[3].i = (0.5f + TextureIndex) / 256.0f;
|
m_aTexture[0].i = m_aTexture[1].i = m_aTexture[2].i = m_aTexture[3].i = (0.5f + TextureIndex) / (256.0f/m_pBackend->GetTextureArraySize());
|
||||||
m_State.m_Dimension = (TextureIndex < 0) ? 2 : 3;
|
m_State.m_Dimension = (TextureIndex < 0) ? 2 : 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,18 +739,12 @@ void CGraphics_Threaded::QuadsText(float x, float y, float Size, const char *pTe
|
||||||
int CGraphics_Threaded::IssueInit()
|
int CGraphics_Threaded::IssueInit()
|
||||||
{
|
{
|
||||||
int Flags = 0;
|
int Flags = 0;
|
||||||
if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
|
|
||||||
{
|
|
||||||
dbg_msg("gfx", "both borderless and fullscreen activated, disabling borderless");
|
|
||||||
g_Config.m_GfxBorderless = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(g_Config.m_GfxBorderless) Flags |= IGraphicsBackend::INITFLAG_BORDERLESS;
|
if(g_Config.m_GfxBorderless) Flags |= IGraphicsBackend::INITFLAG_BORDERLESS;
|
||||||
else if(g_Config.m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN;
|
if(g_Config.m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN;
|
||||||
if(g_Config.m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC;
|
if(g_Config.m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC;
|
||||||
if(g_Config.m_DbgResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE;
|
if(g_Config.m_DbgResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE;
|
||||||
|
|
||||||
return m_pBackend->Init("Teeworlds", g_Config.m_GfxScreen, &g_Config.m_GfxScreenWidth, &g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags, &m_DesktopScreenWidth, &m_DesktopScreenHeight);
|
return m_pBackend->Init("Teeworlds", &g_Config.m_GfxScreen, &g_Config.m_GfxScreenWidth, &g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags, &m_DesktopScreenWidth, &m_DesktopScreenHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CGraphics_Threaded::InitWindow()
|
int CGraphics_Threaded::InitWindow()
|
||||||
|
@ -839,6 +865,11 @@ void CGraphics_Threaded::Shutdown()
|
||||||
delete m_apCommandBuffers[i];
|
delete m_apCommandBuffers[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CGraphics_Threaded::GetNumScreens() const
|
||||||
|
{
|
||||||
|
return m_pBackend->GetNumScreens();
|
||||||
|
}
|
||||||
|
|
||||||
void CGraphics_Threaded::Minimize()
|
void CGraphics_Threaded::Minimize()
|
||||||
{
|
{
|
||||||
m_pBackend->Minimize();
|
m_pBackend->Minimize();
|
||||||
|
@ -846,10 +877,29 @@ void CGraphics_Threaded::Minimize()
|
||||||
|
|
||||||
void CGraphics_Threaded::Maximize()
|
void CGraphics_Threaded::Maximize()
|
||||||
{
|
{
|
||||||
// TODO: SDL
|
|
||||||
m_pBackend->Maximize();
|
m_pBackend->Maximize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CGraphics_Threaded::Fullscreen(bool State)
|
||||||
|
{
|
||||||
|
return m_pBackend->Fullscreen(State);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGraphics_Threaded::SetWindowBordered(bool State)
|
||||||
|
{
|
||||||
|
m_pBackend->SetWindowBordered(State);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGraphics_Threaded::SetWindowScreen(int Index)
|
||||||
|
{
|
||||||
|
return m_pBackend->SetWindowScreen(Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CGraphics_Threaded::GetWindowScreen()
|
||||||
|
{
|
||||||
|
return m_pBackend->GetWindowScreen();
|
||||||
|
}
|
||||||
|
|
||||||
int CGraphics_Threaded::WindowActive()
|
int CGraphics_Threaded::WindowActive()
|
||||||
{
|
{
|
||||||
return m_pBackend->WindowActive();
|
return m_pBackend->WindowActive();
|
||||||
|
@ -861,6 +911,28 @@ int CGraphics_Threaded::WindowOpen()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGraphics_Threaded::ReadBackbuffer(unsigned char **ppPixels, int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
if(!ppPixels)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// add swap command
|
||||||
|
CImageInfo Image;
|
||||||
|
mem_zero(&Image, sizeof(Image));
|
||||||
|
|
||||||
|
CCommandBuffer::SCommand_Screenshot Cmd;
|
||||||
|
Cmd.m_pImage = &Image;
|
||||||
|
Cmd.m_X = x; Cmd.m_Y = y;
|
||||||
|
Cmd.m_W = w; Cmd.m_H = h;
|
||||||
|
m_pCommandBuffer->AddCommand(Cmd);
|
||||||
|
|
||||||
|
// kick the buffer and wait for the result
|
||||||
|
KickCommandBuffer();
|
||||||
|
WaitForIdle();
|
||||||
|
|
||||||
|
*ppPixels = (unsigned char *)Image.m_pData; // take ownership!
|
||||||
|
}
|
||||||
|
|
||||||
void CGraphics_Threaded::TakeScreenshot(const char *pFilename)
|
void CGraphics_Threaded::TakeScreenshot(const char *pFilename)
|
||||||
{
|
{
|
||||||
// TODO: screenshot support
|
// TODO: screenshot support
|
||||||
|
@ -889,6 +961,21 @@ void CGraphics_Threaded::Swap()
|
||||||
KickCommandBuffer();
|
KickCommandBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CGraphics_Threaded::SetVSync(bool State)
|
||||||
|
{
|
||||||
|
// add vsnc command
|
||||||
|
bool RetOk = 0;
|
||||||
|
CCommandBuffer::SCommand_VSync Cmd;
|
||||||
|
Cmd.m_VSync = State ? 1 : 0;
|
||||||
|
Cmd.m_pRetOk = &RetOk;
|
||||||
|
m_pCommandBuffer->AddCommand(Cmd);
|
||||||
|
|
||||||
|
// kick the command buffer
|
||||||
|
KickCommandBuffer();
|
||||||
|
WaitForIdle();
|
||||||
|
return RetOk;
|
||||||
|
}
|
||||||
|
|
||||||
// syncronization
|
// syncronization
|
||||||
void CGraphics_Threaded::InsertSignal(semaphore *pSemaphore)
|
void CGraphics_Threaded::InsertSignal(semaphore *pSemaphore)
|
||||||
{
|
{
|
||||||
|
@ -923,10 +1010,11 @@ int CGraphics_Threaded::GetVideoModes(CVideoMode *pModes, int MaxModes, int Scre
|
||||||
mem_zero(&Image, sizeof(Image));
|
mem_zero(&Image, sizeof(Image));
|
||||||
|
|
||||||
int NumModes = 0;
|
int NumModes = 0;
|
||||||
CCommandBuffer::SCommand_VideoModes Cmd(Screen);
|
CCommandBuffer::SCommand_VideoModes Cmd;
|
||||||
Cmd.m_pModes = pModes;
|
Cmd.m_pModes = pModes;
|
||||||
Cmd.m_MaxModes = MaxModes;
|
Cmd.m_MaxModes = MaxModes;
|
||||||
Cmd.m_pNumModes = &NumModes;
|
Cmd.m_pNumModes = &NumModes;
|
||||||
|
Cmd.m_Screen = Screen;
|
||||||
m_pCommandBuffer->AddCommand(Cmd);
|
m_pCommandBuffer->AddCommand(Cmd);
|
||||||
|
|
||||||
// kick the buffer and wait for the result and return it
|
// kick the buffer and wait for the result and return it
|
||||||
|
|
|
@ -82,6 +82,7 @@ public:
|
||||||
CMD_SWAP,
|
CMD_SWAP,
|
||||||
|
|
||||||
// misc
|
// misc
|
||||||
|
CMD_VSYNC,
|
||||||
CMD_SCREENSHOT,
|
CMD_SCREENSHOT,
|
||||||
CMD_VIDEOMODES,
|
CMD_VIDEOMODES,
|
||||||
|
|
||||||
|
@ -99,6 +100,7 @@ public:
|
||||||
TEXFLAG_QUALITY = 4,
|
TEXFLAG_QUALITY = 4,
|
||||||
TEXFLAG_TEXTURE3D = 8,
|
TEXFLAG_TEXTURE3D = 8,
|
||||||
TEXFLAG_TEXTURE2D = 16,
|
TEXFLAG_TEXTURE2D = 16,
|
||||||
|
TEXTFLAG_LINEARMIPMAPS = 32,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -141,6 +143,7 @@ public:
|
||||||
int m_WrapModeU;
|
int m_WrapModeU;
|
||||||
int m_WrapModeV;
|
int m_WrapModeV;
|
||||||
int m_Texture;
|
int m_Texture;
|
||||||
|
int m_TextureArrayIndex;
|
||||||
int m_Dimension;
|
int m_Dimension;
|
||||||
SPoint m_ScreenTL;
|
SPoint m_ScreenTL;
|
||||||
SPoint m_ScreenBR;
|
SPoint m_ScreenBR;
|
||||||
|
@ -183,13 +186,13 @@ public:
|
||||||
struct SCommand_Screenshot : public SCommand
|
struct SCommand_Screenshot : public SCommand
|
||||||
{
|
{
|
||||||
SCommand_Screenshot() : SCommand(CMD_SCREENSHOT) {}
|
SCommand_Screenshot() : SCommand(CMD_SCREENSHOT) {}
|
||||||
|
int m_X, m_Y, m_W, m_H; // specify rectangle size, -1 if fullscreen (width/height)
|
||||||
CImageInfo *m_pImage; // processor will fill this out, the one who adds this command must free the data as well
|
CImageInfo *m_pImage; // processor will fill this out, the one who adds this command must free the data as well
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SCommand_VideoModes : public SCommand
|
struct SCommand_VideoModes : public SCommand
|
||||||
{
|
{
|
||||||
SCommand_VideoModes(int screen) : SCommand(CMD_VIDEOMODES),
|
SCommand_VideoModes() : SCommand(CMD_VIDEOMODES) {}
|
||||||
m_Screen(screen) {}
|
|
||||||
|
|
||||||
CVideoMode *m_pModes; // processor will fill this in
|
CVideoMode *m_pModes; // processor will fill this in
|
||||||
int m_MaxModes; // maximum of modes the processor can write to the m_pModes
|
int m_MaxModes; // maximum of modes the processor can write to the m_pModes
|
||||||
|
@ -204,6 +207,14 @@ public:
|
||||||
int m_Finish;
|
int m_Finish;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SCommand_VSync : public SCommand
|
||||||
|
{
|
||||||
|
SCommand_VSync() : SCommand(CMD_VSYNC) {}
|
||||||
|
|
||||||
|
int m_VSync;
|
||||||
|
bool *m_pRetOk;
|
||||||
|
};
|
||||||
|
|
||||||
struct SCommand_Texture_Create : public SCommand
|
struct SCommand_Texture_Create : public SCommand
|
||||||
{
|
{
|
||||||
SCommand_Texture_Create() : SCommand(CMD_TEXTURE_CREATE) {}
|
SCommand_Texture_Create() : SCommand(CMD_TEXTURE_CREATE) {}
|
||||||
|
@ -302,13 +313,20 @@ public:
|
||||||
|
|
||||||
virtual ~IGraphicsBackend() {}
|
virtual ~IGraphicsBackend() {}
|
||||||
|
|
||||||
virtual int Init(const char *pName, int Screen, int *pWidth, int *pHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight) = 0;
|
virtual int Init(const char *pName, int *Screen, int *pWidth, int *pHeight, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight) = 0;
|
||||||
virtual int Shutdown() = 0;
|
virtual int Shutdown() = 0;
|
||||||
|
|
||||||
virtual int MemoryUsage() const = 0;
|
virtual int MemoryUsage() const = 0;
|
||||||
|
virtual int GetTextureArraySize() const = 0;
|
||||||
|
|
||||||
|
virtual int GetNumScreens() const = 0;
|
||||||
|
|
||||||
virtual void Minimize() = 0;
|
virtual void Minimize() = 0;
|
||||||
virtual void Maximize() = 0;
|
virtual void Maximize() = 0;
|
||||||
|
virtual bool Fullscreen(bool State) = 0;
|
||||||
|
virtual void SetWindowBordered(bool State) = 0;
|
||||||
|
virtual bool SetWindowScreen(int Index) = 0;
|
||||||
|
virtual int GetWindowScreen() = 0;
|
||||||
virtual int WindowActive() = 0;
|
virtual int WindowActive() = 0;
|
||||||
virtual int WindowOpen() = 0;
|
virtual int WindowOpen() = 0;
|
||||||
|
|
||||||
|
@ -356,6 +374,7 @@ class CGraphics_Threaded : public IEngineGraphics
|
||||||
|
|
||||||
CTextureHandle m_InvalidTexture;
|
CTextureHandle m_InvalidTexture;
|
||||||
|
|
||||||
|
int m_TextureArrayIndex;
|
||||||
int m_aTextureIndices[MAX_TEXTURES];
|
int m_aTextureIndices[MAX_TEXTURES];
|
||||||
int m_FirstFreeTexture;
|
int m_FirstFreeTexture;
|
||||||
int m_TextureMemoryUsage;
|
int m_TextureMemoryUsage;
|
||||||
|
@ -391,7 +410,7 @@ public:
|
||||||
virtual void LinesEnd();
|
virtual void LinesEnd();
|
||||||
virtual void LinesDraw(const CLineItem *pArray, int Num);
|
virtual void LinesDraw(const CLineItem *pArray, int Num);
|
||||||
|
|
||||||
virtual int UnloadTexture(IGraphics::CTextureHandle Index);
|
virtual int UnloadTexture(IGraphics::CTextureHandle *Index);
|
||||||
virtual IGraphics::CTextureHandle LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags);
|
virtual IGraphics::CTextureHandle LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags);
|
||||||
virtual int LoadTextureRawSub(IGraphics::CTextureHandle TextureID, int x, int y, int Width, int Height, int Format, const void *pData);
|
virtual int LoadTextureRawSub(IGraphics::CTextureHandle TextureID, int x, int y, int Width, int Height, int Format, const void *pData);
|
||||||
|
|
||||||
|
@ -413,6 +432,7 @@ public:
|
||||||
virtual void SetColor(float r, float g, float b, float a);
|
virtual void SetColor(float r, float g, float b, float a);
|
||||||
virtual void SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight);
|
virtual void SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight);
|
||||||
|
|
||||||
|
void TilesetFallbackSystem(int TextureIndex);
|
||||||
virtual void QuadsSetSubset(float TlU, float TlV, float BrU, float BrV, int TextureIndex = -1);
|
virtual void QuadsSetSubset(float TlU, float TlV, float BrU, float BrV, int TextureIndex = -1);
|
||||||
virtual void QuadsSetSubsetFree(
|
virtual void QuadsSetSubsetFree(
|
||||||
float x0, float y0, float x1, float y1,
|
float x0, float y0, float x1, float y1,
|
||||||
|
@ -423,8 +443,13 @@ public:
|
||||||
virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num);
|
virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num);
|
||||||
virtual void QuadsText(float x, float y, float Size, const char *pText);
|
virtual void QuadsText(float x, float y, float Size, const char *pText);
|
||||||
|
|
||||||
|
virtual int GetNumScreens() const;
|
||||||
virtual void Minimize();
|
virtual void Minimize();
|
||||||
virtual void Maximize();
|
virtual void Maximize();
|
||||||
|
virtual bool Fullscreen(bool State);
|
||||||
|
virtual void SetWindowBordered(bool State);
|
||||||
|
virtual bool SetWindowScreen(int Index);
|
||||||
|
virtual int GetWindowScreen();
|
||||||
|
|
||||||
virtual int WindowActive();
|
virtual int WindowActive();
|
||||||
virtual int WindowOpen();
|
virtual int WindowOpen();
|
||||||
|
@ -432,8 +457,10 @@ public:
|
||||||
virtual int Init();
|
virtual int Init();
|
||||||
virtual void Shutdown();
|
virtual void Shutdown();
|
||||||
|
|
||||||
|
virtual void ReadBackbuffer(unsigned char **ppPixels, int x, int y, int w, int h);
|
||||||
virtual void TakeScreenshot(const char *pFilename);
|
virtual void TakeScreenshot(const char *pFilename);
|
||||||
virtual void Swap();
|
virtual void Swap();
|
||||||
|
virtual bool SetVSync(bool State);
|
||||||
|
|
||||||
virtual int GetVideoModes(CVideoMode *pModes, int MaxModes, int Screen);
|
virtual int GetVideoModes(CVideoMode *pModes, int MaxModes, int Screen);
|
||||||
|
|
||||||
|
|
|
@ -4,26 +4,30 @@
|
||||||
|
|
||||||
#include <base/system.h>
|
#include <base/system.h>
|
||||||
#include <engine/shared/config.h>
|
#include <engine/shared/config.h>
|
||||||
|
#include <engine/console.h>
|
||||||
#include <engine/graphics.h>
|
#include <engine/graphics.h>
|
||||||
#include <engine/input.h>
|
#include <engine/input.h>
|
||||||
#include <engine/keys.h>
|
#include <engine/keys.h>
|
||||||
|
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
|
||||||
//print >>f, "int inp_key_code(const char *key_name) { int i; if (!strcmp(key_name, \"-?-\")) return -1; else for (i = 0; i < 512; i++) if (!strcmp(key_strings[i], key_name)) return i; return -1; }"
|
|
||||||
|
|
||||||
// this header is protected so you don't include it from anywere
|
// this header is protected so you don't include it from anywere
|
||||||
#define KEYS_INCLUDE
|
#define KEYS_INCLUDE
|
||||||
#include "keynames.h"
|
#include "keynames.h"
|
||||||
#undef KEYS_INCLUDE
|
#undef KEYS_INCLUDE
|
||||||
|
|
||||||
void CInput::AddEvent(int Unicode, int Key, int Flags)
|
void CInput::AddEvent(char *pText, int Key, int Flags)
|
||||||
{
|
{
|
||||||
if(m_NumEvents != INPUT_BUFFER_SIZE)
|
if(m_NumEvents != INPUT_BUFFER_SIZE)
|
||||||
{
|
{
|
||||||
m_aInputEvents[m_NumEvents].m_Unicode = Unicode;
|
|
||||||
m_aInputEvents[m_NumEvents].m_Key = Key;
|
m_aInputEvents[m_NumEvents].m_Key = Key;
|
||||||
m_aInputEvents[m_NumEvents].m_Flags = Flags;
|
m_aInputEvents[m_NumEvents].m_Flags = Flags;
|
||||||
|
if(!pText)
|
||||||
|
m_aInputEvents[m_NumEvents].m_aText[0] = 0;
|
||||||
|
else
|
||||||
|
str_copy(m_aInputEvents[m_NumEvents].m_aText, pText, sizeof(m_aInputEvents[m_NumEvents].m_aText));
|
||||||
|
m_aInputEvents[m_NumEvents].m_InputCount = m_InputCounter;
|
||||||
m_NumEvents++;
|
m_NumEvents++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,9 +37,8 @@ CInput::CInput()
|
||||||
mem_zero(m_aInputCount, sizeof(m_aInputCount));
|
mem_zero(m_aInputCount, sizeof(m_aInputCount));
|
||||||
mem_zero(m_aInputState, sizeof(m_aInputState));
|
mem_zero(m_aInputState, sizeof(m_aInputState));
|
||||||
|
|
||||||
m_InputCurrent = 0;
|
m_InputCounter = 1;
|
||||||
m_InputGrabbed = 0;
|
m_InputGrabbed = 0;
|
||||||
m_InputDispatched = false;
|
|
||||||
|
|
||||||
m_LastRelease = 0;
|
m_LastRelease = 0;
|
||||||
m_ReleaseDelta = -1;
|
m_ReleaseDelta = -1;
|
||||||
|
@ -46,36 +49,49 @@ CInput::CInput()
|
||||||
void CInput::Init()
|
void CInput::Init()
|
||||||
{
|
{
|
||||||
m_pGraphics = Kernel()->RequestInterface<IEngineGraphics>();
|
m_pGraphics = Kernel()->RequestInterface<IEngineGraphics>();
|
||||||
|
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
||||||
// FIXME: unicode handling: use SDL_StartTextInput/SDL_StopTextInput on inputs
|
// FIXME: unicode handling: use SDL_StartTextInput/SDL_StopTextInput on inputs
|
||||||
// FIXME: key repeat: not a global setting anymore; need to do manually
|
|
||||||
|
|
||||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
MouseModeRelative();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInput::MouseRelative(float *x, float *y)
|
void CInput::MouseRelative(float *x, float *y)
|
||||||
{
|
{
|
||||||
|
if(!m_InputGrabbed)
|
||||||
|
return;
|
||||||
|
|
||||||
int nx = 0, ny = 0;
|
int nx = 0, ny = 0;
|
||||||
float Sens = g_Config.m_InpMousesens/100.0f;
|
float Sens = g_Config.m_InpMousesens/100.0f;
|
||||||
|
|
||||||
if(m_InputGrabbed)
|
|
||||||
{
|
|
||||||
SDL_GetRelativeMouseState(&nx,&ny);
|
SDL_GetRelativeMouseState(&nx,&ny);
|
||||||
}
|
|
||||||
|
|
||||||
*x = nx*Sens;
|
*x = nx*Sens;
|
||||||
*y = ny*Sens;
|
*y = ny*Sens;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInput::MouseModeAbsolute()
|
void CInput::MouseModeAbsolute()
|
||||||
|
{
|
||||||
|
if(m_InputGrabbed)
|
||||||
{
|
{
|
||||||
m_InputGrabbed = 0;
|
m_InputGrabbed = 0;
|
||||||
|
SDL_ShowCursor(SDL_ENABLE);
|
||||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CInput::MouseModeRelative()
|
void CInput::MouseModeRelative()
|
||||||
|
{
|
||||||
|
if(!m_InputGrabbed)
|
||||||
{
|
{
|
||||||
m_InputGrabbed = 1;
|
m_InputGrabbed = 1;
|
||||||
|
SDL_ShowCursor(SDL_DISABLE);
|
||||||
|
if(SDL_SetHintWithPriority(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, g_Config.m_InpGrab ? "0" : "1", SDL_HINT_OVERRIDE) == SDL_FALSE)
|
||||||
|
{
|
||||||
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "input", "unable to switch relative mouse mode");
|
||||||
|
}
|
||||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||||
|
SDL_GetRelativeMouseState(NULL, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CInput::MouseDoubleClick()
|
int CInput::MouseDoubleClick()
|
||||||
|
@ -89,47 +105,42 @@ int CInput::MouseDoubleClick()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInput::ClearKeyStates()
|
void CInput::Clear()
|
||||||
{
|
{
|
||||||
mem_zero(m_aInputState, sizeof(m_aInputState));
|
mem_zero(m_aInputState, sizeof(m_aInputState));
|
||||||
mem_zero(m_aInputCount, sizeof(m_aInputCount));
|
mem_zero(m_aInputCount, sizeof(m_aInputCount));
|
||||||
|
m_NumEvents = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CInput::KeyState(int Key)
|
bool CInput::KeyState(int Key) const
|
||||||
{
|
{
|
||||||
return m_aInputState[m_InputCurrent][Key];
|
return m_aInputState[Key>=KEY_MOUSE_1 ? Key : SDL_GetScancodeFromKey(KeyToKeycode(Key))];
|
||||||
}
|
}
|
||||||
|
|
||||||
int CInput::Update()
|
int CInput::Update()
|
||||||
{
|
{
|
||||||
if(m_InputDispatched)
|
// keep the counter between 1..0xFFFF, 0 means not pressed
|
||||||
{
|
m_InputCounter = (m_InputCounter%0xFFFF)+1;
|
||||||
// clear and begin count on the other one
|
|
||||||
m_InputCurrent^=1;
|
|
||||||
mem_zero(&m_aInputCount[m_InputCurrent], sizeof(m_aInputCount[m_InputCurrent]));
|
|
||||||
mem_zero(&m_aInputState[m_InputCurrent], sizeof(m_aInputState[m_InputCurrent]));
|
|
||||||
m_InputDispatched = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const Uint8 *pState = SDL_GetKeyboardState(&i);
|
const Uint8 *pState = SDL_GetKeyboardState(&i);
|
||||||
if(i >= KEY_LAST)
|
if(i >= KEY_LAST)
|
||||||
i = KEY_LAST-1;
|
i = KEY_LAST-1;
|
||||||
mem_copy(m_aInputState[m_InputCurrent], pState, i);
|
mem_copy(m_aInputState, pState, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// these states must always be updated manually because they are not in the GetKeyState from SDL
|
// these states must always be updated manually because they are not in the GetKeyState from SDL
|
||||||
int i = SDL_GetMouseState(NULL, NULL);
|
int i = SDL_GetMouseState(NULL, NULL);
|
||||||
if(i&SDL_BUTTON(1)) m_aInputState[m_InputCurrent][KEY_MOUSE_1] = 1; // 1 is left
|
if(i&SDL_BUTTON(1)) m_aInputState[KEY_MOUSE_1] = 1; // 1 is left
|
||||||
if(i&SDL_BUTTON(3)) m_aInputState[m_InputCurrent][KEY_MOUSE_2] = 1; // 3 is right
|
if(i&SDL_BUTTON(3)) m_aInputState[KEY_MOUSE_2] = 1; // 3 is right
|
||||||
if(i&SDL_BUTTON(2)) m_aInputState[m_InputCurrent][KEY_MOUSE_3] = 1; // 2 is middle
|
if(i&SDL_BUTTON(2)) m_aInputState[KEY_MOUSE_3] = 1; // 2 is middle
|
||||||
if(i&SDL_BUTTON(4)) m_aInputState[m_InputCurrent][KEY_MOUSE_4] = 1;
|
if(i&SDL_BUTTON(4)) m_aInputState[KEY_MOUSE_4] = 1;
|
||||||
if(i&SDL_BUTTON(5)) m_aInputState[m_InputCurrent][KEY_MOUSE_5] = 1;
|
if(i&SDL_BUTTON(5)) m_aInputState[KEY_MOUSE_5] = 1;
|
||||||
if(i&SDL_BUTTON(6)) m_aInputState[m_InputCurrent][KEY_MOUSE_6] = 1;
|
if(i&SDL_BUTTON(6)) m_aInputState[KEY_MOUSE_6] = 1;
|
||||||
if(i&SDL_BUTTON(7)) m_aInputState[m_InputCurrent][KEY_MOUSE_7] = 1;
|
if(i&SDL_BUTTON(7)) m_aInputState[KEY_MOUSE_7] = 1;
|
||||||
if(i&SDL_BUTTON(8)) m_aInputState[m_InputCurrent][KEY_MOUSE_8] = 1;
|
if(i&SDL_BUTTON(8)) m_aInputState[KEY_MOUSE_8] = 1;
|
||||||
if(i&SDL_BUTTON(9)) m_aInputState[m_InputCurrent][KEY_MOUSE_9] = 1;
|
if(i&SDL_BUTTON(9)) m_aInputState[KEY_MOUSE_9] = 1;
|
||||||
|
|
||||||
{
|
{
|
||||||
SDL_Event Event;
|
SDL_Event Event;
|
||||||
|
@ -137,26 +148,23 @@ int CInput::Update()
|
||||||
while(SDL_PollEvent(&Event))
|
while(SDL_PollEvent(&Event))
|
||||||
{
|
{
|
||||||
int Key = -1;
|
int Key = -1;
|
||||||
|
int Scancode = 0;
|
||||||
int Action = IInput::FLAG_PRESS;
|
int Action = IInput::FLAG_PRESS;
|
||||||
switch (Event.type)
|
switch (Event.type)
|
||||||
{
|
{
|
||||||
case SDL_TEXTINPUT:
|
case SDL_TEXTINPUT:
|
||||||
{
|
AddEvent(Event.text.text, 0, IInput::FLAG_TEXT);
|
||||||
int TextLength, i;
|
break;
|
||||||
TextLength = strlen(Event.text.text);
|
|
||||||
for(i = 0; i < TextLength; i++)
|
|
||||||
{
|
|
||||||
AddEvent(Event.text.text[i], 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle keys
|
// handle keys
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
Key = SDL_GetScancodeFromName(SDL_GetKeyName(Event.key.keysym.sym));
|
Key = KeycodeToKey(Event.key.keysym.sym);
|
||||||
|
Scancode = Event.key.keysym.scancode;
|
||||||
break;
|
break;
|
||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
Action = IInput::FLAG_RELEASE;
|
Action = IInput::FLAG_RELEASE;
|
||||||
Key = SDL_GetScancodeFromName(SDL_GetKeyName(Event.key.keysym.sym));
|
Key = KeycodeToKey(Event.key.keysym.sym);
|
||||||
|
Scancode = Event.key.keysym.scancode;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// handle mouse buttons
|
// handle mouse buttons
|
||||||
|
@ -174,19 +182,31 @@ int CInput::Update()
|
||||||
if(Event.button.button == SDL_BUTTON_LEFT) Key = KEY_MOUSE_1; // ignore_convention
|
if(Event.button.button == SDL_BUTTON_LEFT) Key = KEY_MOUSE_1; // ignore_convention
|
||||||
if(Event.button.button == SDL_BUTTON_RIGHT) Key = KEY_MOUSE_2; // ignore_convention
|
if(Event.button.button == SDL_BUTTON_RIGHT) Key = KEY_MOUSE_2; // ignore_convention
|
||||||
if(Event.button.button == SDL_BUTTON_MIDDLE) Key = KEY_MOUSE_3; // ignore_convention
|
if(Event.button.button == SDL_BUTTON_MIDDLE) Key = KEY_MOUSE_3; // ignore_convention
|
||||||
|
if(Event.button.button == 4) Key = KEY_MOUSE_4; // ignore_convention
|
||||||
|
if(Event.button.button == 5) Key = KEY_MOUSE_5; // ignore_convention
|
||||||
if(Event.button.button == 6) Key = KEY_MOUSE_6; // ignore_convention
|
if(Event.button.button == 6) Key = KEY_MOUSE_6; // ignore_convention
|
||||||
if(Event.button.button == 7) Key = KEY_MOUSE_7; // ignore_convention
|
if(Event.button.button == 7) Key = KEY_MOUSE_7; // ignore_convention
|
||||||
if(Event.button.button == 8) Key = KEY_MOUSE_8; // ignore_convention
|
if(Event.button.button == 8) Key = KEY_MOUSE_8; // ignore_convention
|
||||||
if(Event.button.button == 9) Key = KEY_MOUSE_9; // ignore_convention
|
if(Event.button.button == 9) Key = KEY_MOUSE_9; // ignore_convention
|
||||||
|
Scancode = Key;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_MOUSEWHEEL:
|
case SDL_MOUSEWHEEL:
|
||||||
if(Event.wheel.y > 0) Key = KEY_MOUSE_WHEEL_UP; // ignore_convention
|
if(Event.wheel.y > 0) Key = KEY_MOUSE_WHEEL_UP; // ignore_convention
|
||||||
if(Event.wheel.y < 0) Key = KEY_MOUSE_WHEEL_DOWN; // ignore_convention
|
if(Event.wheel.y < 0) Key = KEY_MOUSE_WHEEL_DOWN; // ignore_convention
|
||||||
AddEvent(0, Key, Action);
|
Action |= IInput::FLAG_RELEASE;
|
||||||
Action = IInput::FLAG_RELEASE;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if defined(CONF_PLATFORM_MACOSX) // Todo SDL: remove this when fixed (mouse state is faulty on start)
|
||||||
|
case SDL_WINDOWEVENT:
|
||||||
|
if(Event.window.event == SDL_WINDOWEVENT_MAXIMIZED)
|
||||||
|
{
|
||||||
|
MouseModeAbsolute();
|
||||||
|
MouseModeRelative();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
// other messages
|
// other messages
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -195,9 +215,11 @@ int CInput::Update()
|
||||||
//
|
//
|
||||||
if(Key != -1)
|
if(Key != -1)
|
||||||
{
|
{
|
||||||
m_aInputCount[m_InputCurrent][Key].m_Presses++;
|
if(Action&IInput::FLAG_PRESS)
|
||||||
if(Action == IInput::FLAG_PRESS)
|
{
|
||||||
m_aInputState[m_InputCurrent][Key] = 1;
|
m_aInputState[Scancode] = 1;
|
||||||
|
m_aInputCount[Key] = m_InputCounter;
|
||||||
|
}
|
||||||
AddEvent(0, Key, Action);
|
AddEvent(0, Key, Action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,24 @@
|
||||||
class CInput : public IEngineInput
|
class CInput : public IEngineInput
|
||||||
{
|
{
|
||||||
IEngineGraphics *m_pGraphics;
|
IEngineGraphics *m_pGraphics;
|
||||||
|
IConsole *m_pConsole;
|
||||||
|
|
||||||
int m_InputGrabbed;
|
int m_InputGrabbed;
|
||||||
|
|
||||||
int64 m_LastRelease;
|
int64 m_LastRelease;
|
||||||
int64 m_ReleaseDelta;
|
int64 m_ReleaseDelta;
|
||||||
|
|
||||||
void AddEvent(int Unicode, int Key, int Flags);
|
void AddEvent(char *pText, int Key, int Flags);
|
||||||
|
void Clear();
|
||||||
|
bool IsEventValid(CEvent *pEvent) const { return pEvent->m_InputCount == m_InputCounter; };
|
||||||
|
|
||||||
|
//quick access to input
|
||||||
|
unsigned short m_aInputCount[g_MaxKeys]; // tw-KEY
|
||||||
|
unsigned char m_aInputState[g_MaxKeys]; // SDL_SCANCODE
|
||||||
|
int m_InputCounter;
|
||||||
|
|
||||||
|
void ClearKeyStates();
|
||||||
|
bool KeyState(int Key) const;
|
||||||
|
|
||||||
IEngineGraphics *Graphics() { return m_pGraphics; }
|
IEngineGraphics *Graphics() { return m_pGraphics; }
|
||||||
|
|
||||||
|
@ -21,16 +32,14 @@ public:
|
||||||
|
|
||||||
virtual void Init();
|
virtual void Init();
|
||||||
|
|
||||||
|
bool KeyIsPressed(int Key) const { return KeyState(Key); }
|
||||||
|
bool KeyPress(int Key, bool CheckCounter) const { return CheckCounter ? (m_aInputCount[Key] == m_InputCounter) : m_aInputCount[Key]; }
|
||||||
|
|
||||||
virtual void MouseRelative(float *x, float *y);
|
virtual void MouseRelative(float *x, float *y);
|
||||||
virtual void MouseModeAbsolute();
|
virtual void MouseModeAbsolute();
|
||||||
virtual void MouseModeRelative();
|
virtual void MouseModeRelative();
|
||||||
virtual int MouseDoubleClick();
|
virtual int MouseDoubleClick();
|
||||||
|
|
||||||
void ClearKeyStates();
|
|
||||||
int KeyState(int Key);
|
|
||||||
|
|
||||||
int ButtonPressed(int Button) { return m_aInputState[m_InputCurrent][Button]; }
|
|
||||||
|
|
||||||
virtual int Update();
|
virtual int Update();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,105 @@
|
||||||
#error do not include this header!
|
#error do not include this header!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
const char g_aaKeyStrings[512][20] =
|
const char g_aaKeyStrings[512][20] =
|
||||||
{
|
{
|
||||||
"unknown",
|
"unknown",
|
||||||
"&1",
|
"&1",
|
||||||
"&2",
|
"&2",
|
||||||
"&3",
|
"&3",
|
||||||
|
"&4",
|
||||||
|
"&5",
|
||||||
|
"&6",
|
||||||
|
"&7",
|
||||||
|
"backspace",
|
||||||
|
"tab",
|
||||||
|
"&10",
|
||||||
|
"&11",
|
||||||
|
"&12",
|
||||||
|
"return",
|
||||||
|
"&14",
|
||||||
|
"&15",
|
||||||
|
"&16",
|
||||||
|
"&17",
|
||||||
|
"&18",
|
||||||
|
"&19",
|
||||||
|
"&20",
|
||||||
|
"&21",
|
||||||
|
"&22",
|
||||||
|
"&23",
|
||||||
|
"&24",
|
||||||
|
"&25",
|
||||||
|
"&26",
|
||||||
|
"escape",
|
||||||
|
"&28",
|
||||||
|
"&29",
|
||||||
|
"&30",
|
||||||
|
"&31",
|
||||||
|
"space",
|
||||||
|
"exclaim",
|
||||||
|
"quotedbl",
|
||||||
|
"hash",
|
||||||
|
"dollar",
|
||||||
|
"percent",
|
||||||
|
"ampersand",
|
||||||
|
"quote",
|
||||||
|
"leftparen",
|
||||||
|
"rightparen",
|
||||||
|
"asterix",
|
||||||
|
"plus",
|
||||||
|
"comma",
|
||||||
|
"minus",
|
||||||
|
"period",
|
||||||
|
"slash",
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
"6",
|
||||||
|
"7",
|
||||||
|
"8",
|
||||||
|
"9",
|
||||||
|
"colon",
|
||||||
|
"semicolon",
|
||||||
|
"less",
|
||||||
|
"equals",
|
||||||
|
"greater",
|
||||||
|
"question",
|
||||||
|
"at",
|
||||||
|
"&65",
|
||||||
|
"&66",
|
||||||
|
"&67",
|
||||||
|
"&68",
|
||||||
|
"&69",
|
||||||
|
"&70",
|
||||||
|
"&71",
|
||||||
|
"&72",
|
||||||
|
"&73",
|
||||||
|
"&74",
|
||||||
|
"&75",
|
||||||
|
"&76",
|
||||||
|
"&77",
|
||||||
|
"&78",
|
||||||
|
"&79",
|
||||||
|
"&80",
|
||||||
|
"&81",
|
||||||
|
"&82",
|
||||||
|
"&83",
|
||||||
|
"&84",
|
||||||
|
"&85",
|
||||||
|
"&86",
|
||||||
|
"&87",
|
||||||
|
"&88",
|
||||||
|
"&89",
|
||||||
|
"&90",
|
||||||
|
"leftbracket",
|
||||||
|
"backslash",
|
||||||
|
"rightbracket",
|
||||||
|
"caret",
|
||||||
|
"underscore",
|
||||||
|
"backquote",
|
||||||
"a",
|
"a",
|
||||||
"b",
|
"b",
|
||||||
"c",
|
"c",
|
||||||
|
@ -38,33 +129,68 @@ const char g_aaKeyStrings[512][20] =
|
||||||
"x",
|
"x",
|
||||||
"y",
|
"y",
|
||||||
"z",
|
"z",
|
||||||
"1",
|
"&123",
|
||||||
"2",
|
"&124",
|
||||||
"3",
|
"&125",
|
||||||
"4",
|
"&126",
|
||||||
"5",
|
"delete",
|
||||||
"6",
|
"&128",
|
||||||
"7",
|
"&129",
|
||||||
"8",
|
"&130",
|
||||||
"9",
|
"&131",
|
||||||
"0",
|
"&132",
|
||||||
"return",
|
"&133",
|
||||||
"escape",
|
"&134",
|
||||||
"backspace",
|
"&135",
|
||||||
"tab",
|
"&136",
|
||||||
"space",
|
"&137",
|
||||||
"minus",
|
"&138",
|
||||||
"equals",
|
"&139",
|
||||||
"leftbracket",
|
"&140",
|
||||||
"rightbracket",
|
"&141",
|
||||||
"backslash",
|
"&142",
|
||||||
"nonushash",
|
"&143",
|
||||||
"semicolon",
|
"&144",
|
||||||
"apostrophe",
|
"&145",
|
||||||
"grave",
|
"&146",
|
||||||
"comma",
|
"&147",
|
||||||
"period",
|
"&148",
|
||||||
"slash",
|
"&149",
|
||||||
|
"&150",
|
||||||
|
"&151",
|
||||||
|
"&152",
|
||||||
|
"&153",
|
||||||
|
"&154",
|
||||||
|
"&155",
|
||||||
|
"&156",
|
||||||
|
"&157",
|
||||||
|
"&158",
|
||||||
|
"&159",
|
||||||
|
"&160",
|
||||||
|
"&161",
|
||||||
|
"&162",
|
||||||
|
"&163",
|
||||||
|
"&164",
|
||||||
|
"&165",
|
||||||
|
"&166",
|
||||||
|
"&167",
|
||||||
|
"&168",
|
||||||
|
"&169",
|
||||||
|
"&170",
|
||||||
|
"&171",
|
||||||
|
"&172",
|
||||||
|
"&173",
|
||||||
|
"&174",
|
||||||
|
"&175",
|
||||||
|
"&176",
|
||||||
|
"&177",
|
||||||
|
"&178",
|
||||||
|
"&179",
|
||||||
|
"&180",
|
||||||
|
"&181",
|
||||||
|
"&182",
|
||||||
|
"&183",
|
||||||
|
"&184",
|
||||||
"capslock",
|
"capslock",
|
||||||
"f1",
|
"f1",
|
||||||
"f2",
|
"f2",
|
||||||
|
@ -84,7 +210,7 @@ const char g_aaKeyStrings[512][20] =
|
||||||
"insert",
|
"insert",
|
||||||
"home",
|
"home",
|
||||||
"pageup",
|
"pageup",
|
||||||
"delete",
|
"&204",
|
||||||
"end",
|
"end",
|
||||||
"pagedown",
|
"pagedown",
|
||||||
"right",
|
"right",
|
||||||
|
@ -108,7 +234,7 @@ const char g_aaKeyStrings[512][20] =
|
||||||
"kp_9",
|
"kp_9",
|
||||||
"kp_0",
|
"kp_0",
|
||||||
"kp_period",
|
"kp_period",
|
||||||
"nonusbackslash",
|
"&228",
|
||||||
"application",
|
"application",
|
||||||
"power",
|
"power",
|
||||||
"kp_equals",
|
"kp_equals",
|
||||||
|
@ -138,29 +264,29 @@ const char g_aaKeyStrings[512][20] =
|
||||||
"mute",
|
"mute",
|
||||||
"volumeup",
|
"volumeup",
|
||||||
"volumedown",
|
"volumedown",
|
||||||
"&130",
|
"&258",
|
||||||
"&131",
|
"&259",
|
||||||
"&132",
|
"&260",
|
||||||
"kp_comma",
|
"kp_comma",
|
||||||
"kp_equalsas400",
|
"kp_equalsas400",
|
||||||
"international1",
|
"&263",
|
||||||
"international2",
|
"&264",
|
||||||
"international3",
|
"&265",
|
||||||
"international4",
|
"&266",
|
||||||
"international5",
|
"&267",
|
||||||
"international6",
|
"&268",
|
||||||
"international7",
|
"&269",
|
||||||
"international8",
|
"&270",
|
||||||
"international9",
|
"&271",
|
||||||
"lang1",
|
"&272",
|
||||||
"lang2",
|
"&273",
|
||||||
"lang3",
|
"&274",
|
||||||
"lang4",
|
"&275",
|
||||||
"lang5",
|
"&276",
|
||||||
"lang6",
|
"&277",
|
||||||
"lang7",
|
"&278",
|
||||||
"lang8",
|
"&279",
|
||||||
"lang9",
|
"&280",
|
||||||
"alterase",
|
"alterase",
|
||||||
"sysreq",
|
"sysreq",
|
||||||
"cancel",
|
"cancel",
|
||||||
|
@ -173,17 +299,17 @@ const char g_aaKeyStrings[512][20] =
|
||||||
"clearagain",
|
"clearagain",
|
||||||
"crsel",
|
"crsel",
|
||||||
"exsel",
|
"exsel",
|
||||||
"&165",
|
"&293",
|
||||||
"&166",
|
"&294",
|
||||||
"&167",
|
"&295",
|
||||||
"&168",
|
"&296",
|
||||||
"&169",
|
"&297",
|
||||||
"&170",
|
"&298",
|
||||||
"&171",
|
"&299",
|
||||||
"&172",
|
"&300",
|
||||||
"&173",
|
"&301",
|
||||||
"&174",
|
"&302",
|
||||||
"&175",
|
"&303",
|
||||||
"kp_00",
|
"kp_00",
|
||||||
"kp_000",
|
"kp_000",
|
||||||
"thousandsseparator",
|
"thousandsseparator",
|
||||||
|
@ -230,8 +356,8 @@ const char g_aaKeyStrings[512][20] =
|
||||||
"kp_octal",
|
"kp_octal",
|
||||||
"kp_decimal",
|
"kp_decimal",
|
||||||
"kp_hexadecimal",
|
"kp_hexadecimal",
|
||||||
"&222",
|
"&350",
|
||||||
"&223",
|
"&351",
|
||||||
"lctrl",
|
"lctrl",
|
||||||
"lshift",
|
"lshift",
|
||||||
"lalt",
|
"lalt",
|
||||||
|
@ -240,134 +366,6 @@ const char g_aaKeyStrings[512][20] =
|
||||||
"rshift",
|
"rshift",
|
||||||
"ralt",
|
"ralt",
|
||||||
"rgui",
|
"rgui",
|
||||||
"&232",
|
|
||||||
"&233",
|
|
||||||
"&234",
|
|
||||||
"&235",
|
|
||||||
"&236",
|
|
||||||
"&237",
|
|
||||||
"&238",
|
|
||||||
"&239",
|
|
||||||
"&240",
|
|
||||||
"&241",
|
|
||||||
"&242",
|
|
||||||
"&243",
|
|
||||||
"&244",
|
|
||||||
"&245",
|
|
||||||
"&246",
|
|
||||||
"&247",
|
|
||||||
"&248",
|
|
||||||
"&249",
|
|
||||||
"&250",
|
|
||||||
"&251",
|
|
||||||
"&252",
|
|
||||||
"&253",
|
|
||||||
"&254",
|
|
||||||
"&255",
|
|
||||||
"&256",
|
|
||||||
"mode",
|
|
||||||
"audionext",
|
|
||||||
"audioprev",
|
|
||||||
"audiostop",
|
|
||||||
"audioplay",
|
|
||||||
"audiomute",
|
|
||||||
"mediaselect",
|
|
||||||
"www",
|
|
||||||
"mail",
|
|
||||||
"calculator",
|
|
||||||
"computer",
|
|
||||||
"ac_search",
|
|
||||||
"ac_home",
|
|
||||||
"ac_back",
|
|
||||||
"ac_forward",
|
|
||||||
"ac_stop",
|
|
||||||
"ac_refresh",
|
|
||||||
"ac_bookmarks",
|
|
||||||
"brightnessdown",
|
|
||||||
"brightnessup",
|
|
||||||
"displayswitch",
|
|
||||||
"kbdillumtoggle",
|
|
||||||
"kbdillumdown",
|
|
||||||
"kbdillumup",
|
|
||||||
"eject",
|
|
||||||
"sleep",
|
|
||||||
"app1",
|
|
||||||
"app2",
|
|
||||||
"mouse1",
|
|
||||||
"mouse2",
|
|
||||||
"mouse3",
|
|
||||||
"mouse4",
|
|
||||||
"mouse5",
|
|
||||||
"mouse6",
|
|
||||||
"mouse7",
|
|
||||||
"mouse8",
|
|
||||||
"mousewheelup",
|
|
||||||
"mousewheeldown",
|
|
||||||
"&295",
|
|
||||||
"&296",
|
|
||||||
"&297",
|
|
||||||
"&298",
|
|
||||||
"&299",
|
|
||||||
"&300",
|
|
||||||
"&301",
|
|
||||||
"&302",
|
|
||||||
"&303",
|
|
||||||
"&304",
|
|
||||||
"&305",
|
|
||||||
"&306",
|
|
||||||
"&307",
|
|
||||||
"&308",
|
|
||||||
"&309",
|
|
||||||
"&310",
|
|
||||||
"&311",
|
|
||||||
"&312",
|
|
||||||
"&313",
|
|
||||||
"&314",
|
|
||||||
"&315",
|
|
||||||
"&316",
|
|
||||||
"&317",
|
|
||||||
"&318",
|
|
||||||
"&319",
|
|
||||||
"&320",
|
|
||||||
"&321",
|
|
||||||
"&322",
|
|
||||||
"&323",
|
|
||||||
"&324",
|
|
||||||
"&325",
|
|
||||||
"&326",
|
|
||||||
"&327",
|
|
||||||
"&328",
|
|
||||||
"&329",
|
|
||||||
"&330",
|
|
||||||
"&331",
|
|
||||||
"&332",
|
|
||||||
"&333",
|
|
||||||
"&334",
|
|
||||||
"&335",
|
|
||||||
"&336",
|
|
||||||
"&337",
|
|
||||||
"&338",
|
|
||||||
"&339",
|
|
||||||
"&340",
|
|
||||||
"&341",
|
|
||||||
"&342",
|
|
||||||
"&343",
|
|
||||||
"&344",
|
|
||||||
"&345",
|
|
||||||
"&346",
|
|
||||||
"&347",
|
|
||||||
"&348",
|
|
||||||
"&349",
|
|
||||||
"&350",
|
|
||||||
"&351",
|
|
||||||
"&352",
|
|
||||||
"&353",
|
|
||||||
"&354",
|
|
||||||
"&355",
|
|
||||||
"&356",
|
|
||||||
"&357",
|
|
||||||
"&358",
|
|
||||||
"&359",
|
|
||||||
"&360",
|
"&360",
|
||||||
"&361",
|
"&361",
|
||||||
"&362",
|
"&362",
|
||||||
|
@ -393,43 +391,43 @@ const char g_aaKeyStrings[512][20] =
|
||||||
"&382",
|
"&382",
|
||||||
"&383",
|
"&383",
|
||||||
"&384",
|
"&384",
|
||||||
"&385",
|
"mode",
|
||||||
"&386",
|
"audionext",
|
||||||
"&387",
|
"audioprev",
|
||||||
"&388",
|
"audiostop",
|
||||||
"&389",
|
"audioplay",
|
||||||
"&390",
|
"audiomute",
|
||||||
"&391",
|
"mediaselect",
|
||||||
"&392",
|
"www",
|
||||||
"&393",
|
"mail",
|
||||||
"&394",
|
"calculator",
|
||||||
"&395",
|
"computer",
|
||||||
"&396",
|
"ac_search",
|
||||||
"&397",
|
"ac_home",
|
||||||
"&398",
|
"ac_back",
|
||||||
"&399",
|
"ac_forward",
|
||||||
"&400",
|
"ac_stop",
|
||||||
"&401",
|
"ac_refresh",
|
||||||
"&402",
|
"ac_bookmarks",
|
||||||
"&403",
|
"brightnessdown",
|
||||||
"&404",
|
"brightnessup",
|
||||||
"&405",
|
"displayswitch",
|
||||||
"&406",
|
"kbdillumtoggle",
|
||||||
"&407",
|
"kbdillumdown",
|
||||||
"&408",
|
"kpdillumup",
|
||||||
"&409",
|
"eject",
|
||||||
"&410",
|
"sleep",
|
||||||
"&411",
|
"mouse1",
|
||||||
"&412",
|
"mouse2",
|
||||||
"&413",
|
"mouse3",
|
||||||
"&414",
|
"mouse4",
|
||||||
"&415",
|
"mouse5",
|
||||||
"&416",
|
"mouse6",
|
||||||
"&417",
|
"mouse7",
|
||||||
"&418",
|
"mouse8",
|
||||||
"&419",
|
"mouse9",
|
||||||
"&420",
|
"mousewheelup",
|
||||||
"&421",
|
"mousewheeldown",
|
||||||
"&422",
|
"&422",
|
||||||
"&423",
|
"&423",
|
||||||
"&424",
|
"&424",
|
||||||
|
|