From d2e39d2f50684151490da446156622e69dd84a48 Mon Sep 17 00:00:00 2001
From: heinrich5991 <heinrich5991@gmail.com>
Date: Mon, 26 Nov 2018 20:47:20 +0100
Subject: [PATCH 1/2] Add CMake
(cherry picked from commit ee2afdac33f43d96a457bcf692a817489d6f896e)
---
.gitignore | 40 +-
CMakeLists.txt | 1824 +++++++++++++++++
bam.lua | 2 +
cmake/FindFreetype.cmake | 37 +
cmake/FindPnglite.cmake | 46 +
cmake/FindSDL2.cmake | 48 +
cmake/FindWavpack.cmake | 52 +
cmake/FindZLIB.cmake | 50 +
cmake/toolchains/darwin.toolchain | 11 +
cmake/toolchains/mingw32.toolchain | 10 +
cmake/toolchains/mingw64.toolchain | 10 +
other/bundle/client/Info.plist.in | 24 +
other/bundle/client/PkgInfo | 1 +
other/bundle/server/Info.plist.in | 20 +
other/bundle/server/PkgInfo | 1 +
other/freetype/freetype.lua | 4 +-
.../icons/{Teeworlds.icns => teeworlds.icns} | Bin
other/icons/{Teeworlds.ico => teeworlds.ico} | Bin
other/icons/teeworlds.rc | 1 +
...{Teeworlds_srv.icns => teeworlds_srv.icns} | Bin
.../{Teeworlds_srv.ico => teeworlds_srv.ico} | Bin
other/icons/teeworlds_srv.rc | 1 +
other/icons/teeworlds_srv_cl.rc | 2 +-
other/icons/teeworlds_srv_gcc.rc | 2 +-
other/sdl/sdl.lua | 4 +-
scripts/darwin_change_dylib.py | 63 +
scripts/dmg.py | 106 +
scripts/git_revision.py | 21 +
src/base/system.c | 13 +-
src/base/system.h | 15 +
src/engine/client/backend_sdl.cpp | 2 +-
src/engine/client/graphics_threaded.cpp | 3 +-
src/engine/client/sound.cpp | 78 +-
src/engine/client/sound.h | 4 -
src/osxlaunch/server.mm | 112 +
35 files changed, 2570 insertions(+), 37 deletions(-)
create mode 100644 CMakeLists.txt
create mode 100644 cmake/FindFreetype.cmake
create mode 100644 cmake/FindPnglite.cmake
create mode 100644 cmake/FindSDL2.cmake
create mode 100644 cmake/FindWavpack.cmake
create mode 100644 cmake/FindZLIB.cmake
create mode 100644 cmake/toolchains/darwin.toolchain
create mode 100644 cmake/toolchains/mingw32.toolchain
create mode 100644 cmake/toolchains/mingw64.toolchain
create mode 100644 other/bundle/client/Info.plist.in
create mode 100644 other/bundle/client/PkgInfo
create mode 100644 other/bundle/server/Info.plist.in
create mode 100644 other/bundle/server/PkgInfo
rename other/icons/{Teeworlds.icns => teeworlds.icns} (100%)
rename other/icons/{Teeworlds.ico => teeworlds.ico} (100%)
create mode 100644 other/icons/teeworlds.rc
rename other/icons/{Teeworlds_srv.icns => teeworlds_srv.icns} (100%)
rename other/icons/{Teeworlds_srv.ico => teeworlds_srv.ico} (100%)
create mode 100644 other/icons/teeworlds_srv.rc
create mode 100644 scripts/darwin_change_dylib.py
create mode 100644 scripts/dmg.py
create mode 100644 scripts/git_revision.py
create mode 100644 src/osxlaunch/server.mm
diff --git a/.gitignore b/.gitignore
index 2fbc9201f..3d102c096 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,12 @@
-/bam
/.bam
-/config.lua
+/bam
/build
-/other/*/lib
+/config.lua
+/objs
/other/*/include
+/other/*/lib
__pycache__/
+*.dll
*.pyc
*.pyo
scripts/work/
@@ -12,3 +14,35 @@ scripts/work/
/freetype.dll
/autoexec.cfg
_test.exe
+Info.plist
+
+crapnet*
+fake_server*
+map_resave*
+map_version*
+mastersrv*
+packetgen*
+teeworlds*
+teeworlds_srv*
+versionsrv*
+
+# CMake
+data
+generated
+
+.ninja_deps
+.ninja_log
+CMakeCache.txt
+CMakeFiles
+CMakeSettings*
+CPackConfig.cmake
+CPackSourceConfig.cmake
+Debug
+Makefile
+Release
+_CPack_Packages/
+build.ninja
+cmake_install.cmake
+install_manifest.txt
+pack_*/
+rules.ninja
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 000000000..f5be54e07
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,1824 @@
+cmake_minimum_required(VERSION 2.8)
+
+file(STRINGS src/game/version.h VERSION_LINE
+ LIMIT_COUNT 1
+ REGEX GAME_RELEASE_VERSION
+)
+
+if(VERSION_LINE MATCHES "\"([0-9]+)\\.([0-9]+)\\.([0-9]+)\"")
+ set(VERSION_MAJOR ${CMAKE_MATCH_1})
+ set(VERSION_MINOR ${CMAKE_MATCH_2})
+ set(VERSION_PATCH ${CMAKE_MATCH_3})
+elseif(VERSION_LINE MATCHES "\"([0-9]+)\\.([0-9]+)\"")
+ set(VERSION_MAJOR ${CMAKE_MATCH_1})
+ set(VERSION_MINOR ${CMAKE_MATCH_2})
+ set(VERSION_PATCH "0")
+else()
+ message(FATAL_ERROR "Couldn't parse version from src/game/version.h")
+endif()
+
+if(POLICY CMP0048)
+ cmake_policy(SET CMP0048 NEW)
+ project(teeworlds VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
+else()
+ project(teeworlds)
+ set(PROJECT_VERSION_MAJOR ${VERSION_MAJOR})
+ set(PROJECT_VERSION_MINOR ${VERSION_MINOR})
+ set(PROJECT_VERSION_PATCH ${VERSION_PATCH})
+ set(PROJECT_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
+endif()
+
+set(ORIGINAL_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH})
+set(ORIGINAL_CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES})
+set(ORIGINAL_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+set(OWN_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
+set(CMAKE_MODULE_PATH ${OWN_CMAKE_MODULE_PATH})
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(TARGET_BITS "64")
+elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
+ set(TARGET_BITS "32")
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ set(TARGET_OS "windows")
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(TARGET_OS "linux")
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set(TARGET_OS "mac")
+endif()
+
+include(CheckCCompilerFlag)
+include(CheckCXXCompilerFlag)
+include(CheckSymbolExists)
+
+check_symbol_exists(__i386 "" TARGET_ARCH_X86_i386)
+if(TARGET_ARCH_X86_i386)
+ set(TARGET_ARCH x86)
+else()
+ set(TARGET_ARCH)
+endif()
+
+set(AUTO_DEPENDENCIES_DEFAULT OFF)
+if(TARGET_OS STREQUAL "windows")
+ set(AUTO_DEPENDENCIES_DEFAULT ON)
+endif()
+
+option(CLIENT "Compile client" ON)
+option(PREFER_BUNDLED_LIBS "Prefer bundled libraries over system libraries" ${AUTO_DEPENDENCIES_DEFAULT})
+option(DEV "Don't generate stuff necessary for packaging" OFF)
+
+# Set the default build type to Release
+if(NOT(CMAKE_BUILD_TYPE))
+ if(DEV)
+ set(CMAKE_BUILD_TYPE Release)
+ else()
+ set(CMAKE_BUILD_TYPE Debug)
+ endif()
+endif()
+
+set(DBG $<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>)
+
+set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
+ src/game/version.h
+)
+
+set(SERVER_EXECUTABLE teeworlds_srv CACHE STRING "Name of the built server executable")
+set(CLIENT_EXECUTABLE teeworlds CACHE STRING "Name of the build client executable")
+
+########################################################################
+# Compiler flags
+########################################################################
+
+function(add_c_compiler_flag_if_supported VARIABLE FLAG)
+ if(ARGC GREATER 2)
+ set(CHECKED_FLAG "${ARGV2}")
+ else()
+ set(CHECKED_FLAG "${FLAG}")
+ endif()
+ string(REGEX REPLACE "[^A-Za-z0-9]" "_" CONFIG_VARIABLE "FLAG_SUPPORTED${CHECKED_FLAG}")
+ check_c_compiler_flag("${CHECKED_FLAG}" ${CONFIG_VARIABLE})
+ if(${CONFIG_VARIABLE})
+ if(${VARIABLE})
+ set("${VARIABLE}" "${${VARIABLE}};${FLAG}" PARENT_SCOPE)
+ else()
+ set("${VARIABLE}" "${FLAG}" PARENT_SCOPE)
+ endif()
+ endif()
+endfunction()
+
+if(NOT MSVC)
+ # Protect the stack pointer.
+ # -fstack-protector-all doesn't work on MinGW.
+ add_c_compiler_flag_if_supported(OUR_FLAGS -fstack-protector-all)
+
+ # Inaccurate floating point numbers cause problems on mingw-w64-gcc when
+ # compiling for x86, might cause problems elsewhere. So don't store floats
+ # in registers but keep them at higher accuracy.
+
+ if(TARGET_ARCH STREQUAL "x86")
+ add_c_compiler_flag_if_supported(OUR_FLAGS -ffloat-store)
+ endif()
+
+ if(TARGET_OS STREQUAL "mac")
+ add_c_compiler_flag_if_supported(OUR_FLAGS -stdlib=libc++)
+ add_c_compiler_flag_if_supported(OUR_FLAGS -mmacosx-version-min=10.7)
+ endif()
+
+ add_c_compiler_flag_if_supported(OUR_FLAGS_OWN -Wall)
+ if(CMAKE_VERSION VERSION_GREATER 3.3 OR CMAKE_VERSION VERSION_EQUAL 3.3)
+ add_c_compiler_flag_if_supported(OUR_FLAGS_OWN
+ $<$<COMPILE_LANGUAGE:C>:-Wdeclaration-after-statement>
+ -Wdeclaration-after-statement
+ )
+ endif()
+ add_c_compiler_flag_if_supported(OUR_FLAGS_OWN -Wextra)
+ add_c_compiler_flag_if_supported(OUR_FLAGS_OWN -Wno-unused-parameter)
+ add_c_compiler_flag_if_supported(OUR_FLAGS_OWN -Wno-missing-field-initializers)
+ add_c_compiler_flag_if_supported(OUR_FLAGS_OWN -Wformat=2) # Warn about format strings.
+ add_c_compiler_flag_if_supported(OUR_FLAGS_DEP -Wno-implicit-function-declaration)
+endif()
+
+if(NOT MSVC)
+ check_c_compiler_flag("-O2;-Wp,-Werror;-D_FORTIFY_SOURCE=2" DEFINE_FORTIFY_SOURCE) # Some distributions define _FORTIFY_SOURCE by themselves.
+endif()
+
+########################################################################
+# COMMON FUNCTIONS
+########################################################################
+
+function(set_glob VAR GLOBBING EXTS DIRECTORY) # ...
+ set(GLOBS)
+ foreach(ext ${EXTS})
+ list(APPEND GLOBS "${DIRECTORY}/*.${ext}")
+ endforeach()
+ file(${GLOBBING} GLOB_RESULT ${GLOBS})
+ list(SORT GLOB_RESULT)
+ set(FILES)
+ foreach(file ${ARGN})
+ list(APPEND FILES "${PROJECT_SOURCE_DIR}/${DIRECTORY}/${file}")
+ endforeach()
+
+ if(NOT FILES STREQUAL GLOB_RESULT)
+ message(AUTHOR_WARNING "${VAR} does not contain every file from directory ${DIRECTORY}")
+ set(LIST_BUT_NOT_GLOB)
+ if(POLICY CMP0057)
+ cmake_policy(SET CMP0057 NEW)
+ foreach(file ${FILES})
+ if(NOT file IN_LIST GLOB_RESULT)
+ list(APPEND LIST_BUT_NOT_GLOB ${file})
+ endif()
+ endforeach()
+ if(LIST_BUT_NOT_GLOB)
+ message(AUTHOR_WARNING "Entries only present in ${VAR}: ${LIST_BUT_NOT_GLOB}")
+ endif()
+ set(GLOB_BUT_NOT_LIST)
+ foreach(file ${GLOB_RESULT})
+ if(NOT file IN_LIST FILES)
+ list(APPEND GLOB_BUT_NOT_LIST ${file})
+ endif()
+ endforeach()
+ if(GLOB_BUT_NOT_LIST)
+ message(AUTHOR_WARNING "Entries only present in ${DIRECTORY}: ${GLOB_BUT_NOT_LIST}")
+ endif()
+ endif()
+ endif()
+
+ set(${VAR} ${FILES} PARENT_SCOPE)
+endfunction()
+
+function(set_src VAR GLOBBING DIRECTORY) # ...
+ set_glob(${VAR} ${GLOBBING} "c;cpp;h" ${DIRECTORY} ${ARGN})
+ set(${VAR} ${${VAR}} PARENT_SCOPE)
+endfunction()
+
+########################################################################
+# INITIALIZE TARGET LISTS
+########################################################################
+
+set(TARGETS_OWN)
+set(TARGETS_DEP)
+
+set(TARGETS_LINK) # Targets with a linking stage.
+
+########################################################################
+# DEPENDENCIES
+########################################################################
+
+function(set_extra_dirs_lib VARIABLE NAME)
+ set("PATHS_${VARIABLE}_LIBDIR" PARENT_SCOPE)
+ set("HINTS_${VARIABLE}_LIBDIR" PARENT_SCOPE)
+ if(PREFER_BUNDLED_LIBS)
+ set(TYPE HINTS)
+ else()
+ set(TYPE PATHS)
+ endif()
+ if(TARGET_BITS AND TARGET_OS)
+ set(DIR "other/${NAME}/${TARGET_OS}/lib${TARGET_BITS}")
+ set("${TYPE}_${VARIABLE}_LIBDIR" "${DIR}" PARENT_SCOPE)
+ set("EXTRA_${VARIABLE}_LIBDIR" "${DIR}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(set_extra_dirs_include VARIABLE NAME LIBRARY)
+ set("PATHS_${VARIABLE}_INCLUDEDIR" PARENT_SCOPE)
+ set("HINTS_${VARIABLE}_INCLUDEDIR" PARENT_SCOPE)
+ is_bundled(IS_BUNDLED "${LIBRARY}")
+ if(IS_BUNDLED)
+ set("HINTS_${VARIABLE}_INCLUDEDIR" "other/${NAME}/include" "other/${NAME}/include/${TARGET_OS}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+if(CMAKE_CROSSCOMPILING)
+ set(CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH NO_CMAKE_SYSTEM_PATH)
+else()
+ set(CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH)
+endif()
+
+function(is_bundled VARIABLE PATH)
+ if(PATH)
+ string(FIND "${PATH}" "${PROJECT_SOURCE_DIR}" LOCAL_PATH_POS)
+ if(LOCAL_PATH_POS EQUAL 0 AND TARGET_BITS AND TARGET_OS)
+ set("${VARIABLE}" ON PARENT_SCOPE)
+ else()
+ set("${VARIABLE}" OFF PARENT_SCOPE)
+ endif()
+ else()
+ set("${VARIABLE}" OFF PARENT_SCOPE)
+ endif()
+endfunction()
+
+if(NOT CMAKE_CROSSCOMPILING)
+ # Check for PkgConfig once so all the other `find_package` calls can do it
+ # quietly.
+ find_package(PkgConfig)
+endif()
+find_package(ZLIB)
+find_package(Freetype)
+find_package(Git)
+find_package(Pnglite)
+find_package(PythonInterp)
+find_package(SDL2)
+find_package(Threads)
+find_package(Wavpack)
+
+
+if(TARGET_OS AND TARGET_OS STREQUAL "mac")
+ find_program(CMAKE_OTOOL otool)
+ find_program(DMG dmg)
+ find_program(HFSPLUS hfsplus)
+ find_program(NEWFS_HFS newfs_hfs)
+ if(DMG AND HFSPLUS AND NEWFS_HFS)
+ set(DMGTOOLS_FOUND ON)
+ else()
+ set(DMGTOOLS_FOUND OFF)
+ endif()
+
+ find_program(HDIUTIL hdiutil)
+endif()
+
+message(STATUS "******** Teeworlds ********")
+message(STATUS "Target OS: ${TARGET_OS} ${TARGET_BITS}bit")
+message(STATUS "Compiler: ${CMAKE_CXX_COMPILER}")
+message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
+
+message(STATUS "Dependencies:")
+function(show_dependency_status OUTPUT_NAME NAME)
+ if(${NAME}_FOUND)
+ if(${NAME}_BUNDLED)
+ message(STATUS " * ${OUTPUT_NAME} not found (using bundled version)")
+ else()
+ message(STATUS " * ${OUTPUT_NAME} found")
+ endif()
+ else()
+ message(STATUS " * ${OUTPUT_NAME} not found")
+ endif()
+endfunction()
+
+if(TARGET_OS AND TARGET_OS STREQUAL "mac")
+ show_dependency_status("Dmg tools" DMGTOOLS)
+endif()
+show_dependency_status("Freetype" FREETYPE)
+if(TARGET_OS AND TARGET_OS STREQUAL "mac")
+ show_dependency_status("Hdiutil" HDIUTIL)
+endif()
+show_dependency_status("Pnglite" PNGLITE)
+show_dependency_status("PythonInterp" PYTHONINTERP)
+show_dependency_status("SDL2" SDL2)
+show_dependency_status("Wavpack" WAVPACK)
+show_dependency_status("Zlib" ZLIB)
+
+if(NOT(PYTHONINTERP_FOUND))
+ message(SEND_ERROR "You must install Python to compile Teeworlds")
+endif()
+
+if(CLIENT AND NOT(FREETYPE_FOUND))
+ message(SEND_ERROR "You must install Freetype to compile the Teeworlds client")
+endif()
+if(CLIENT AND NOT(SDL2_FOUND))
+ message(SEND_ERROR "You must install SDL2 to compile the Teeworlds client")
+endif()
+
+if(TARGET_OS STREQUAL "windows")
+ set(PLATFORM_CLIENT)
+ set(PLATFORM_CLIENT_LIBS opengl32 glu32 winmm)
+ set(PLATFORM_LIBS ws2_32) # Windows sockets
+elseif(TARGET_OS STREQUAL "mac")
+ find_library(CARBON Carbon)
+ find_library(COCOA Cocoa)
+ find_library(OPENGL OpenGL)
+ set(PLATFORM_CLIENT
+ src/osxlaunch/client.h
+ src/osxlaunch/client.m
+ )
+ set(PLATFORM_CLIENT_LIBS ${COCOA} ${OPENGL})
+ set(PLATFORM_LIBS ${CARBON})
+else()
+ set(PLATFORM_CLIENT)
+ set(PLATFORM_CLIENT_LIBS GL GLU X11)
+ if(TARGET_OS STREQUAL "linux")
+ set(PLATFORM_LIBS rt) # clock_gettime for glibc < 2.17
+ else()
+ set(PLATFORM_LIBS)
+ endif()
+endif()
+
+########################################################################
+# DEPENDENCY COMPILATION
+########################################################################
+
+set_src(DEP_JSON_SRC GLOB src/engine/external/json-parser json.c json.h)
+add_library(json EXCLUDE_FROM_ALL OBJECT ${DEP_JSON_SRC})
+
+set_src(DEP_MD5_SRC GLOB src/engine/external/md5 md5.c md5.h)
+add_library(md5 EXCLUDE_FROM_ALL OBJECT ${DEP_MD5_SRC})
+
+list(APPEND TARGETS_DEP json md5)
+set(DEP_MD5 $<TARGET_OBJECTS:json> $<TARGET_OBJECTS:md5>)
+
+########################################################################
+# DATA
+########################################################################
+
+set_glob(DATA GLOB_RECURSE "json;map;png;rules;ttf;txt;wv" datasrc
+ audio/foley_body_impact-01.wv
+ audio/foley_body_impact-02.wv
+ audio/foley_body_impact-03.wv
+ audio/foley_body_splat-01.wv
+ audio/foley_body_splat-02.wv
+ audio/foley_body_splat-03.wv
+ audio/foley_body_splat-04.wv
+ audio/foley_dbljump-01.wv
+ audio/foley_dbljump-02.wv
+ audio/foley_dbljump-03.wv
+ audio/foley_foot_left-01.wv
+ audio/foley_foot_left-02.wv
+ audio/foley_foot_left-03.wv
+ audio/foley_foot_left-04.wv
+ audio/foley_foot_right-01.wv
+ audio/foley_foot_right-02.wv
+ audio/foley_foot_right-03.wv
+ audio/foley_foot_right-04.wv
+ audio/foley_land-01.wv
+ audio/foley_land-02.wv
+ audio/foley_land-03.wv
+ audio/foley_land-04.wv
+ audio/hook_attach-01.wv
+ audio/hook_attach-02.wv
+ audio/hook_attach-03.wv
+ audio/hook_loop-01.wv
+ audio/hook_loop-02.wv
+ audio/hook_noattach-01.wv
+ audio/hook_noattach-02.wv
+ audio/hook_noattach-03.wv
+ audio/music_menu.wv
+ audio/sfx_ctf_cap_pl.wv
+ audio/sfx_ctf_drop.wv
+ audio/sfx_ctf_grab_en.wv
+ audio/sfx_ctf_grab_pl.wv
+ audio/sfx_ctf_rtn.wv
+ audio/sfx_hit_strong-01.wv
+ audio/sfx_hit_strong-02.wv
+ audio/sfx_hit_weak-01.wv
+ audio/sfx_hit_weak-02.wv
+ audio/sfx_hit_weak-03.wv
+ audio/sfx_msg-client.wv
+ audio/sfx_msg-highlight.wv
+ audio/sfx_msg-server.wv
+ audio/sfx_pickup_arm-01.wv
+ audio/sfx_pickup_arm-02.wv
+ audio/sfx_pickup_arm-03.wv
+ audio/sfx_pickup_arm-04.wv
+ audio/sfx_pickup_gun.wv
+ audio/sfx_pickup_hrt-01.wv
+ audio/sfx_pickup_hrt-02.wv
+ audio/sfx_pickup_launcher.wv
+ audio/sfx_pickup_ninja.wv
+ audio/sfx_pickup_sg.wv
+ audio/sfx_skid-01.wv
+ audio/sfx_skid-02.wv
+ audio/sfx_skid-03.wv
+ audio/sfx_skid-04.wv
+ audio/sfx_spawn_wpn-01.wv
+ audio/sfx_spawn_wpn-02.wv
+ audio/sfx_spawn_wpn-03.wv
+ audio/vo_teefault_cry-01.wv
+ audio/vo_teefault_cry-02.wv
+ audio/vo_teefault_ninja-01.wv
+ audio/vo_teefault_ninja-02.wv
+ audio/vo_teefault_ninja-03.wv
+ audio/vo_teefault_ninja-04.wv
+ audio/vo_teefault_pain_long-01.wv
+ audio/vo_teefault_pain_long-02.wv
+ audio/vo_teefault_pain_short-01.wv
+ audio/vo_teefault_pain_short-02.wv
+ audio/vo_teefault_pain_short-03.wv
+ audio/vo_teefault_pain_short-04.wv
+ audio/vo_teefault_pain_short-05.wv
+ audio/vo_teefault_pain_short-06.wv
+ audio/vo_teefault_pain_short-07.wv
+ audio/vo_teefault_pain_short-08.wv
+ audio/vo_teefault_pain_short-09.wv
+ audio/vo_teefault_pain_short-10.wv
+ audio/vo_teefault_pain_short-11.wv
+ audio/vo_teefault_pain_short-12.wv
+ audio/vo_teefault_sledge-01.wv
+ audio/vo_teefault_sledge-02.wv
+ audio/vo_teefault_sledge-03.wv
+ audio/vo_teefault_spawn-01.wv
+ audio/vo_teefault_spawn-02.wv
+ audio/vo_teefault_spawn-03.wv
+ audio/vo_teefault_spawn-04.wv
+ audio/vo_teefault_spawn-05.wv
+ audio/vo_teefault_spawn-06.wv
+ audio/vo_teefault_spawn-07.wv
+ audio/wp_flump_explo-01.wv
+ audio/wp_flump_explo-02.wv
+ audio/wp_flump_explo-03.wv
+ audio/wp_flump_launch-01.wv
+ audio/wp_flump_launch-02.wv
+ audio/wp_flump_launch-03.wv
+ audio/wp_gun_fire-01.wv
+ audio/wp_gun_fire-02.wv
+ audio/wp_gun_fire-03.wv
+ audio/wp_hammer_hit-01.wv
+ audio/wp_hammer_hit-02.wv
+ audio/wp_hammer_hit-03.wv
+ audio/wp_hammer_swing-01.wv
+ audio/wp_hammer_swing-02.wv
+ audio/wp_hammer_swing-03.wv
+ audio/wp_laser_bnce-01.wv
+ audio/wp_laser_bnce-02.wv
+ audio/wp_laser_bnce-03.wv
+ audio/wp_laser_fire-01.wv
+ audio/wp_laser_fire-02.wv
+ audio/wp_laser_fire-03.wv
+ audio/wp_ninja_attack-01.wv
+ audio/wp_ninja_attack-02.wv
+ audio/wp_ninja_attack-03.wv
+ audio/wp_ninja_attack-04.wv
+ audio/wp_ninja_hit-01.wv
+ audio/wp_ninja_hit-02.wv
+ audio/wp_ninja_hit-03.wv
+ audio/wp_ninja_hit-04.wv
+ audio/wp_noammo-01.wv
+ audio/wp_noammo-02.wv
+ audio/wp_noammo-03.wv
+ audio/wp_noammo-04.wv
+ audio/wp_noammo-05.wv
+ audio/wp_shotty_fire-01.wv
+ audio/wp_shotty_fire-02.wv
+ audio/wp_shotty_fire-03.wv
+ audio/wp_switch-01.wv
+ audio/wp_switch-02.wv
+ audio/wp_switch-03.wv
+ countryflags/AD.png
+ countryflags/AE.png
+ countryflags/AF.png
+ countryflags/AG.png
+ countryflags/AI.png
+ countryflags/AL.png
+ countryflags/AM.png
+ countryflags/AO.png
+ countryflags/AR.png
+ countryflags/AS.png
+ countryflags/AT.png
+ countryflags/AU.png
+ countryflags/AW.png
+ countryflags/AX.png
+ countryflags/AZ.png
+ countryflags/BA.png
+ countryflags/BB.png
+ countryflags/BD.png
+ countryflags/BE.png
+ countryflags/BF.png
+ countryflags/BG.png
+ countryflags/BH.png
+ countryflags/BI.png
+ countryflags/BJ.png
+ countryflags/BL.png
+ countryflags/BM.png
+ countryflags/BN.png
+ countryflags/BO.png
+ countryflags/BR.png
+ countryflags/BS.png
+ countryflags/BT.png
+ countryflags/BW.png
+ countryflags/BY.png
+ countryflags/BZ.png
+ countryflags/CA.png
+ countryflags/CC.png
+ countryflags/CD.png
+ countryflags/CF.png
+ countryflags/CG.png
+ countryflags/CH.png
+ countryflags/CI.png
+ countryflags/CK.png
+ countryflags/CL.png
+ countryflags/CM.png
+ countryflags/CN.png
+ countryflags/CO.png
+ countryflags/CR.png
+ countryflags/CU.png
+ countryflags/CV.png
+ countryflags/CW.png
+ countryflags/CX.png
+ countryflags/CY.png
+ countryflags/CZ.png
+ countryflags/DE.png
+ countryflags/DJ.png
+ countryflags/DK.png
+ countryflags/DM.png
+ countryflags/DO.png
+ countryflags/DZ.png
+ countryflags/EC.png
+ countryflags/EE.png
+ countryflags/EG.png
+ countryflags/EH.png
+ countryflags/ER.png
+ countryflags/ES.png
+ countryflags/ET.png
+ countryflags/FI.png
+ countryflags/FJ.png
+ countryflags/FK.png
+ countryflags/FM.png
+ countryflags/FO.png
+ countryflags/FR.png
+ countryflags/GA.png
+ countryflags/GB.png
+ countryflags/GD.png
+ countryflags/GE.png
+ countryflags/GF.png
+ countryflags/GG.png
+ countryflags/GH.png
+ countryflags/GI.png
+ countryflags/GL.png
+ countryflags/GM.png
+ countryflags/GN.png
+ countryflags/GP.png
+ countryflags/GQ.png
+ countryflags/GR.png
+ countryflags/GS.png
+ countryflags/GT.png
+ countryflags/GU.png
+ countryflags/GW.png
+ countryflags/GY.png
+ countryflags/HK.png
+ countryflags/HN.png
+ countryflags/HR.png
+ countryflags/HT.png
+ countryflags/HU.png
+ countryflags/ID.png
+ countryflags/IE.png
+ countryflags/IL.png
+ countryflags/IM.png
+ countryflags/IN.png
+ countryflags/IO.png
+ countryflags/IQ.png
+ countryflags/IR.png
+ countryflags/IS.png
+ countryflags/IT.png
+ countryflags/JE.png
+ countryflags/JM.png
+ countryflags/JO.png
+ countryflags/JP.png
+ countryflags/KE.png
+ countryflags/KG.png
+ countryflags/KH.png
+ countryflags/KI.png
+ countryflags/KM.png
+ countryflags/KN.png
+ countryflags/KP.png
+ countryflags/KR.png
+ countryflags/KW.png
+ countryflags/KY.png
+ countryflags/KZ.png
+ countryflags/LA.png
+ countryflags/LB.png
+ countryflags/LC.png
+ countryflags/LI.png
+ countryflags/LK.png
+ countryflags/LR.png
+ countryflags/LS.png
+ countryflags/LT.png
+ countryflags/LU.png
+ countryflags/LV.png
+ countryflags/LY.png
+ countryflags/MA.png
+ countryflags/MC.png
+ countryflags/MD.png
+ countryflags/ME.png
+ countryflags/MF.png
+ countryflags/MG.png
+ countryflags/MH.png
+ countryflags/MK.png
+ countryflags/ML.png
+ countryflags/MM.png
+ countryflags/MN.png
+ countryflags/MO.png
+ countryflags/MP.png
+ countryflags/MQ.png
+ countryflags/MR.png
+ countryflags/MS.png
+ countryflags/MT.png
+ countryflags/MU.png
+ countryflags/MV.png
+ countryflags/MW.png
+ countryflags/MX.png
+ countryflags/MY.png
+ countryflags/MZ.png
+ countryflags/NA.png
+ countryflags/NC.png
+ countryflags/NE.png
+ countryflags/NF.png
+ countryflags/NG.png
+ countryflags/NI.png
+ countryflags/NL.png
+ countryflags/NO.png
+ countryflags/NP.png
+ countryflags/NR.png
+ countryflags/NU.png
+ countryflags/NZ.png
+ countryflags/OM.png
+ countryflags/PA.png
+ countryflags/PE.png
+ countryflags/PF.png
+ countryflags/PG.png
+ countryflags/PH.png
+ countryflags/PK.png
+ countryflags/PL.png
+ countryflags/PM.png
+ countryflags/PN.png
+ countryflags/PR.png
+ countryflags/PS.png
+ countryflags/PT.png
+ countryflags/PW.png
+ countryflags/PY.png
+ countryflags/QA.png
+ countryflags/RE.png
+ countryflags/RO.png
+ countryflags/RS.png
+ countryflags/RU.png
+ countryflags/RW.png
+ countryflags/SA.png
+ countryflags/SB.png
+ countryflags/SC.png
+ countryflags/SD.png
+ countryflags/SE.png
+ countryflags/SG.png
+ countryflags/SH.png
+ countryflags/SI.png
+ countryflags/SK.png
+ countryflags/SL.png
+ countryflags/SM.png
+ countryflags/SN.png
+ countryflags/SO.png
+ countryflags/SR.png
+ countryflags/SS.png
+ countryflags/ST.png
+ countryflags/SV.png
+ countryflags/SX.png
+ countryflags/SY.png
+ countryflags/SZ.png
+ countryflags/TC.png
+ countryflags/TD.png
+ countryflags/TF.png
+ countryflags/TG.png
+ countryflags/TH.png
+ countryflags/TJ.png
+ countryflags/TK.png
+ countryflags/TL.png
+ countryflags/TM.png
+ countryflags/TN.png
+ countryflags/TO.png
+ countryflags/TR.png
+ countryflags/TT.png
+ countryflags/TV.png
+ countryflags/TW.png
+ countryflags/TZ.png
+ countryflags/UA.png
+ countryflags/UG.png
+ countryflags/US.png
+ countryflags/UY.png
+ countryflags/UZ.png
+ countryflags/VA.png
+ countryflags/VC.png
+ countryflags/VE.png
+ countryflags/VG.png
+ countryflags/VI.png
+ countryflags/VN.png
+ countryflags/VU.png
+ countryflags/WF.png
+ countryflags/WS.png
+ countryflags/XBZ.png
+ countryflags/XCA.png
+ countryflags/XEN.png
+ countryflags/XES.png
+ countryflags/XGA.png
+ countryflags/XNI.png
+ countryflags/XSC.png
+ countryflags/XWA.png
+ countryflags/YE.png
+ countryflags/ZA.png
+ countryflags/ZM.png
+ countryflags/ZW.png
+ countryflags/default.png
+ countryflags/index.json
+ deadtee.png
+ editor/automap/grass_doodads.json
+ editor/automap/grass_main.json
+ editor/background.png
+ editor/checker.png
+ editor/cursor.png
+ editor/desert_main.rules
+ editor/entities.png
+ editor/grass_main.rules
+ editor/jungle_main.rules
+ editor/winter_main.rules
+ emoticons.png
+ fonts/DejaVuSans.ttf
+ game.png
+ languages/belarusian.json
+ languages/bosnian.json
+ languages/brazilian_portuguese.json
+ languages/breton.json
+ languages/bulgarian.json
+ languages/catalan.json
+ languages/chinese.json
+ languages/chuvash.json
+ languages/czech.json
+ languages/danish.json
+ languages/dutch.json
+ languages/esperanto.json
+ languages/estonian.json
+ languages/finnish.json
+ languages/french.json
+ languages/gaelic_scottish.json
+ languages/galician.json
+ languages/german.json
+ languages/greek.json
+ languages/hungarian.json
+ languages/index.json
+ languages/irish.json
+ languages/italian.json
+ languages/japanese.json
+ languages/korean.json
+ languages/kyrgyz.json
+ languages/license.txt
+ languages/lithuanian.json
+ languages/norwegian.json
+ languages/polish.json
+ languages/portuguese.json
+ languages/readme.txt
+ languages/romanian.json
+ languages/russian.json
+ languages/serbian.json
+ languages/simplified_chinese.json
+ languages/slovak.json
+ languages/slovenian.json
+ languages/spanish.json
+ languages/swedish.json
+ languages/turkish.json
+ languages/ukrainian.json
+ mapres/bg_cloud1.png
+ mapres/bg_cloud2.png
+ mapres/bg_cloud3.png
+ mapres/desert_doodads.png
+ mapres/desert_main.png
+ mapres/desert_mountains.png
+ mapres/desert_mountains2.png
+ mapres/desert_sun.png
+ mapres/generic_deathtiles.png
+ mapres/generic_lamps.png
+ mapres/generic_shadows.png
+ mapres/generic_unhookable.png
+ mapres/grass_doodads.png
+ mapres/grass_main.png
+ mapres/jungle_background.png
+ mapres/jungle_deathtiles.png
+ mapres/jungle_doodads.png
+ mapres/jungle_main.png
+ mapres/jungle_midground.png
+ mapres/jungle_unhookables.png
+ mapres/light.png
+ mapres/moon.png
+ mapres/mountains.png
+ mapres/snow.png
+ mapres/stars.png
+ mapres/sun.png
+ mapres/winter_doodads.png
+ mapres/winter_main.png
+ mapres/winter_mountains.png
+ mapres/winter_mountains2.png
+ mapres/winter_mountains3.png
+ maps/ctf1.map
+ maps/ctf2.map
+ maps/ctf3.map
+ maps/ctf4.map
+ maps/ctf5.map
+ maps/ctf6.map
+ maps/ctf7.map
+ maps/ctf8.map
+ maps/dm1.map
+ maps/dm2.map
+ maps/dm3.map
+ maps/dm6.map
+ maps/dm7.map
+ maps/dm8.map
+ maps/dm9.map
+ maps/license.txt
+ maps/lms1.map
+ maps/readme.txt
+ particles.png
+ skins/bluekitty.json
+ skins/bluestripe.json
+ skins/body/bear.png
+ skins/body/kitty.png
+ skins/body/standard.png
+ skins/body/x_ninja.png
+ skins/brownbear.json
+ skins/cammo.json
+ skins/cammostripes.json
+ skins/decoration/hair.png
+ skins/decoration/twinbopp.png
+ skins/decoration/unibop.png
+ skins/default.json
+ skins/eyes/standard.png
+ skins/eyes/standardreal.png
+ skins/eyes/x_ninja.png
+ skins/feet/standard.png
+ skins/hands/standard.png
+ skins/koala.json
+ skins/limekitty.json
+ skins/marking/bear.png
+ skins/marking/cammo1.png
+ skins/marking/cammo2.png
+ skins/marking/cammostripes.png
+ skins/marking/donny.png
+ skins/marking/duodonny.png
+ skins/marking/saddo.png
+ skins/marking/stripe.png
+ skins/marking/stripes.png
+ skins/marking/toptri.png
+ skins/marking/twintri.png
+ skins/marking/uppy.png
+ skins/marking/warpaint.png
+ skins/marking/whisker.png
+ skins/pinky.json
+ skins/redbopp.json
+ skins/redstripe.json
+ skins/saddo.json
+ skins/toptri.json
+ skins/twinbop.json
+ skins/twintri.json
+ skins/warpaint.json
+ skins/x_ninja.json
+ skins/xmas_hat.png
+ ui/blob.png
+ ui/console.png
+ ui/console_bar.png
+ ui/debug_font.png
+ ui/demo_buttons.png
+ ui/file_icons.png
+ ui/gametypes/ctf.png
+ ui/gametypes/dm.png
+ ui/gametypes/lms.png
+ ui/gametypes/lts.png
+ ui/gametypes/mod.png
+ ui/gametypes/tdm.png
+ ui/gui_buttons.png
+ ui/gui_cursor.png
+ ui/gui_icons.png
+ ui/gui_logo.png
+ ui/icons/arrows.png
+ ui/icons/browse.png
+ ui/icons/chat_whisper.png
+ ui/icons/friend.png
+ ui/icons/info.png
+ ui/icons/level.png
+ ui/icons/menu.png
+ ui/icons/sidebar.png
+ ui/icons/tools.png
+ ui/menuimages/demos.png
+ ui/menuimages/editor.png
+ ui/menuimages/local_server.png
+ ui/menuimages/play_game.png
+ ui/menuimages/settings.png
+ ui/no_skinpart.png
+ ui/themes/heavens.png
+ ui/themes/heavens_day.map
+ ui/themes/heavens_night.map
+ ui/themes/jungle.png
+ ui/themes/jungle_day.map
+ ui/themes/jungle_night.map
+ ui/themes/none.png
+)
+
+########################################################################
+# COPY DATA AND DLLS
+########################################################################
+
+foreach(datafile ${DATA})
+ file(RELATIVE_PATH OUT ${PROJECT_SOURCE_DIR}/datasrc ${datafile})
+ get_filename_component(DESTINATION data/${OUT} PATH)
+ file(MAKE_DIRECTORY ${DESTINATION})
+ file(COPY ${datafile} DESTINATION ${DESTINATION})
+endforeach()
+set(COPY_FILES
+ ${FREETYPE_COPY_FILES}
+ ${SDL2_COPY_FILES}
+)
+file(COPY ${COPY_FILES} DESTINATION .)
+
+########################################################################
+# CODE GENERATION
+########################################################################
+
+function(chash output_file)
+ add_custom_command(OUTPUT ${output_file}
+ COMMAND ${PYTHON_EXECUTABLE} scripts/cmd5.py ${ARGN}
+ > "${PROJECT_BINARY_DIR}/${output_file}"
+ DEPENDS scripts/cmd5.py ${ARGN}
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ )
+endfunction()
+
+function(generate_source output_file script_parameter)
+ add_custom_command(OUTPUT ${output_file}
+ COMMAND ${PYTHON_EXECUTABLE} datasrc/compile.py ${script_parameter}
+ > "${PROJECT_BINARY_DIR}/${output_file}"
+ DEPENDS
+ datasrc/compile.py
+ datasrc/content.py
+ datasrc/datatypes.py
+ datasrc/network.py
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ )
+endfunction()
+
+file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/src/generated/")
+if(GIT_FOUND)
+ execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --git-dir
+ ERROR_QUIET
+ OUTPUT_VARIABLE PROJECT_GIT_DIR
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE PROJECT_GIT_DIR_ERROR
+ )
+ if(NOT PROJECT_GIT_DIR_ERROR)
+ set(GIT_REVISION_EXTRA_DEPS
+ ${PROJECT_GIT_DIR}/index
+ ${PROJECT_GIT_DIR}/logs/HEAD
+ )
+ endif()
+endif()
+add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src/generated/git_revision.cpp
+ COMMAND ${PYTHON_EXECUTABLE}
+ scripts/git_revision.py
+ > ${PROJECT_BINARY_DIR}/src/generated/git_revision.cpp
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ DEPENDS
+ ${GIT_REVISION_EXTRA_DEPS}
+ scripts/git_revision.py
+)
+chash("src/generated/nethash.cpp"
+ "src/engine/shared/protocol.h"
+ "src/game/tuning.h"
+ "src/game/gamecore.cpp"
+ "${PROJECT_BINARY_DIR}/src/generated/protocol.h"
+)
+generate_source("src/generated/client_data.cpp" "client_content_source")
+generate_source("src/generated/client_data.h" "client_content_header")
+generate_source("src/generated/protocol.cpp" "network_source")
+generate_source("src/generated/protocol.h" "network_header")
+generate_source("src/generated/server_data.cpp" "server_content_source")
+generate_source("src/generated/server_data.h" "server_content_header")
+
+
+########################################################################
+# SHARED
+########################################################################
+
+# Sources
+set_src(BASE GLOB_RECURSE src/base
+ color.h
+ detect.h
+ math.h
+ system.c
+ system.h
+ tl/algorithm.h
+ tl/allocator.h
+ tl/array.h
+ tl/base.h
+ tl/range.h
+ tl/sorted_array.h
+ tl/string.h
+ tl/threading.h
+ vmath.h
+)
+set_src(ENGINE_INTERFACE GLOB src/engine
+ client.h
+ config.h
+ console.h
+ demo.h
+ editor.h
+ engine.h
+ friends.h
+ graphics.h
+ input.h
+ kernel.h
+ keys.h
+ map.h
+ masterserver.h
+ message.h
+ server.h
+ serverbrowser.h
+ sound.h
+ storage.h
+ textrender.h
+)
+set_src(ENGINE_SHARED GLOB src/engine/shared
+ compression.cpp
+ compression.h
+ config.cpp
+ config.h
+ config_variables.h
+ console.cpp
+ console.h
+ datafile.cpp
+ datafile.h
+ demo.cpp
+ demo.h
+ econ.cpp
+ econ.h
+ engine.cpp
+ filecollection.cpp
+ filecollection.h
+ huffman.cpp
+ huffman.h
+ jobs.cpp
+ jobs.h
+ kernel.cpp
+ linereader.cpp
+ linereader.h
+ map.cpp
+ mapchecker.cpp
+ mapchecker.h
+ masterserver.cpp
+ memheap.cpp
+ memheap.h
+ message.h
+ netban.cpp
+ netban.h
+ network.cpp
+ network.h
+ network_client.cpp
+ network_conn.cpp
+ network_console.cpp
+ network_console_conn.cpp
+ network_server.cpp
+ network_token.cpp
+ packer.cpp
+ packer.h
+ protocol.h
+ ringbuffer.cpp
+ ringbuffer.h
+ snapshot.cpp
+ snapshot.h
+ storage.cpp
+)
+set(ENGINE_GENERATED_SHARED src/generated/protocol.cpp src/generated/protocol.h)
+set_src(GAME_SHARED GLOB src/game
+ collision.cpp
+ collision.h
+ gamecore.cpp
+ gamecore.h
+ layers.cpp
+ layers.h
+ mapitems.h
+ tuning.h
+ variables.h
+ version.h
+ voting.h
+)
+set(GAME_GENERATED_SHARED
+ src/generated/git_revision.cpp
+ src/generated/nethash.cpp
+ src/generated/protocol.h
+)
+
+set(DEPS ${DEP_MD5} ${ZLIB_DEP})
+
+# Libraries
+set(LIBS ${CMAKE_THREAD_LIBS_INIT} ${ZLIB_LIBRARIES} ${PLATFORM_LIBS})
+
+# Targets
+add_library(engine-shared EXCLUDE_FROM_ALL OBJECT ${ENGINE_INTERFACE} ${ENGINE_SHARED} ${ENGINE_GENERATED_SHARED} ${BASE})
+add_library(game-shared EXCLUDE_FROM_ALL OBJECT ${GAME_SHARED} ${GAME_GENERATED_SHARED})
+list(APPEND TARGETS_OWN engine-shared game-shared)
+
+
+########################################################################
+# CLIENT
+########################################################################
+
+if(CLIENT)
+ # Sources
+ set_src(ENGINE_CLIENT GLOB src/engine/client
+ backend_sdl.cpp
+ backend_sdl.h
+ client.cpp
+ client.h
+ friends.cpp
+ friends.h
+ graphics_threaded.cpp
+ graphics_threaded.h
+ input.cpp
+ input.h
+ keynames.h
+ serverbrowser.cpp
+ serverbrowser.h
+ serverbrowser_entry.h
+ serverbrowser_fav.cpp
+ serverbrowser_fav.h
+ serverbrowser_filter.cpp
+ serverbrowser_filter.h
+ sound.cpp
+ sound.h
+ text.cpp
+ )
+ set_src(GAME_CLIENT GLOB_RECURSE src/game/client
+ animstate.cpp
+ animstate.h
+ component.h
+ components/binds.cpp
+ components/binds.h
+ components/broadcast.cpp
+ components/broadcast.h
+ components/camera.cpp
+ components/camera.h
+ components/chat.cpp
+ components/chat.h
+ components/console.cpp
+ components/console.h
+ components/controls.cpp
+ components/controls.h
+ components/countryflags.cpp
+ components/countryflags.h
+ components/damageind.cpp
+ components/damageind.h
+ components/debughud.cpp
+ components/debughud.h
+ components/effects.cpp
+ components/effects.h
+ components/emoticon.cpp
+ components/emoticon.h
+ components/flow.cpp
+ components/flow.h
+ components/hud.cpp
+ components/hud.h
+ components/items.cpp
+ components/items.h
+ components/killmessages.cpp
+ components/killmessages.h
+ components/mapimages.cpp
+ components/mapimages.h
+ components/maplayers.cpp
+ components/maplayers.h
+ components/menus.cpp
+ components/menus.h
+ components/menus_browser.cpp
+ components/menus_callback.cpp
+ components/menus_demo.cpp
+ components/menus_ingame.cpp
+ components/menus_popups.cpp
+ components/menus_settings.cpp
+ components/menus_start.cpp
+ components/motd.cpp
+ components/motd.h
+ components/nameplates.cpp
+ components/nameplates.h
+ components/particles.cpp
+ components/particles.h
+ components/players.cpp
+ components/players.h
+ components/scoreboard.cpp
+ components/scoreboard.h
+ components/skins.cpp
+ components/skins.h
+ components/sounds.cpp
+ components/sounds.h
+ components/spectator.cpp
+ components/spectator.h
+ components/voting.cpp
+ components/voting.h
+ gameclient.cpp
+ gameclient.h
+ lineinput.cpp
+ lineinput.h
+ localization.cpp
+ localization.h
+ render.cpp
+ render.h
+ render_map.cpp
+ ui.cpp
+ ui.h
+ )
+ set_src(GAME_EDITOR GLOB src/game/editor
+ auto_map.cpp
+ auto_map.h
+ editor.cpp
+ editor.h
+ io.cpp
+ layer_game.cpp
+ layer_quads.cpp
+ layer_tiles.cpp
+ popups.cpp
+ )
+ set(GAME_GENERATED_CLIENT
+ src/generated/client_data.cpp
+ src/generated/client_data.h
+ )
+ set(CLIENT_SRC ${PLATFORM_CLIENT} ${ENGINE_CLIENT} ${GAME_CLIENT} ${GAME_EDITOR} ${GAME_GENERATED_CLIENT})
+
+ set(DEPS_CLIENT ${DEPS} ${PNGLITE_DEP} ${WAVPACK_DEP})
+
+ # Libraries
+ set(LIBS_CLIENT
+ ${LIBS}
+ ${FREETYPE_LIBRARIES}
+ ${PNGLITE_LIBRARIES}
+ ${SDL2_LIBRARIES}
+ ${WAVPACK_LIBRARIES}
+ ${PLATFORM_CLIENT_LIBS}
+ )
+
+ if(TARGET_OS STREQUAL "windows")
+ set(CLIENT_ICON "other/icons/${CLIENT_EXECUTABLE}.rc")
+ else()
+ set(CLIENT_ICON)
+ endif()
+
+ # Target
+ set(TARGET_CLIENT ${CLIENT_EXECUTABLE})
+ add_executable(${TARGET_CLIENT}
+ ${CLIENT_SRC}
+ ${CLIENT_ICON}
+ ${CLIENT_MANIFEST}
+ ${DEPS_CLIENT}
+ $<TARGET_OBJECTS:engine-shared>
+ $<TARGET_OBJECTS:game-shared>
+ )
+ target_link_libraries(${TARGET_CLIENT} ${LIBS_CLIENT})
+
+ target_include_directories(${TARGET_CLIENT} PRIVATE
+ ${FREETYPE_INCLUDE_DIRS}
+ ${PNGLITE_INCLUDE_DIRS}
+ ${SDL2_INCLUDE_DIRS}
+ ${WAVPACK_INCLUDE_DIRS}
+ )
+
+ set(PARAMS "${WAVPACK_INCLUDE_DIRS};${WAVPACK_INCLUDE_DIRS}")
+ if(NOT(WAVPACK_OPEN_FILE_INPUT_EX_PARAMS STREQUAL PARAMS))
+ unset(WAVPACK_OPEN_FILE_INPUT_EX CACHE)
+ endif()
+ set(WAVPACK_OPEN_FILE_INPUT_EX_PARAMS "${PARAMS}" CACHE INTERNAL "")
+
+ set(CMAKE_REQUIRED_INCLUDES ${ORIGINAL_CMAKE_REQUIRED_INCLUDES} ${WAVPACK_INCLUDE_DIRS})
+ set(CMAKE_REQUIRED_LIBRARIES ${ORIGINAL_CMAKE_REQUIRED_LIBRARIES} ${WAVPACK_LIBRARIES})
+ check_symbol_exists(WavpackOpenFileInputEx wavpack.h WAVPACK_OPEN_FILE_INPUT_EX)
+ set(CMAKE_REQUIRED_INCLUDES ${ORIGINAL_CMAKE_REQUIRED_INCLUDES})
+ set(CMAKE_REQUIRED_LIBRARIES ${ORIGINAL_CMAKE_REQUIRED_LIBRARIES})
+
+ if(WAVPACK_OPEN_FILE_INPUT_EX)
+ target_compile_definitions(${TARGET_CLIENT} PRIVATE CONF_WAVPACK_OPEN_FILE_INPUT_EX)
+ endif()
+
+ list(APPEND TARGETS_OWN ${TARGET_CLIENT})
+ list(APPEND TARGETS_LINK ${TARGET_CLIENT})
+endif()
+
+
+########################################################################
+# SERVER
+########################################################################
+
+# Sources
+set_src(ENGINE_SERVER GLOB src/engine/server
+ register.cpp
+ register.h
+ server.cpp
+ server.h
+)
+set_src(GAME_SERVER GLOB_RECURSE src/game/server
+ alloc.h
+ entities/character.cpp
+ entities/character.h
+ entities/flag.cpp
+ entities/flag.h
+ entities/laser.cpp
+ entities/laser.h
+ entities/pickup.cpp
+ entities/pickup.h
+ entities/projectile.cpp
+ entities/projectile.h
+ entity.cpp
+ entity.h
+ eventhandler.cpp
+ eventhandler.h
+ gamecontext.cpp
+ gamecontext.h
+ gamecontroller.cpp
+ gamecontroller.h
+ gamemodes/ctf.cpp
+ gamemodes/ctf.h
+ gamemodes/dm.cpp
+ gamemodes/dm.h
+ gamemodes/lms.cpp
+ gamemodes/lms.h
+ gamemodes/lts.cpp
+ gamemodes/lts.h
+ gamemodes/mod.cpp
+ gamemodes/mod.h
+ gamemodes/tdm.cpp
+ gamemodes/tdm.h
+ gameworld.cpp
+ gameworld.h
+ player.cpp
+ player.h
+)
+set(GAME_GENERATED_SERVER
+ src/generated/server_data.cpp
+ src/generated/server_data.h
+)
+set(SERVER_SRC ${ENGINE_SERVER} ${GAME_SERVER} ${GAME_GENERATED_SERVER})
+if(TARGET_OS STREQUAL "windows")
+ set(SERVER_ICON "other/icons/${SERVER_EXECUTABLE}.rc")
+else()
+ set(SERVER_ICON)
+endif()
+
+# Libraries
+set(LIBS_SERVER ${LIBS})
+
+# Target
+set(TARGET_SERVER ${SERVER_EXECUTABLE})
+add_executable(${TARGET_SERVER}
+ ${DEPS}
+ ${SERVER_SRC}
+ ${SERVER_ICON}
+ $<TARGET_OBJECTS:engine-shared>
+ $<TARGET_OBJECTS:game-shared>
+)
+target_link_libraries(${TARGET_SERVER} ${LIBS_SERVER})
+list(APPEND TARGETS_OWN ${TARGET_SERVER})
+list(APPEND TARGETS_LINK ${TARGET_SERVER})
+
+if(TARGET_OS AND TARGET_OS STREQUAL "mac")
+ set(SERVER_LAUNCHER_SRC src/osxlaunch/server.mm)
+ set(TARGET_SERVER_LAUNCHER ${TARGET_SERVER}-Launcher)
+ add_executable(${TARGET_SERVER_LAUNCHER} ${SERVER_LAUNCHER_SRC})
+ target_link_libraries(${TARGET_SERVER_LAUNCHER} ${COCOA})
+ list(APPEND TARGETS_OWN ${TARGET_SERVER_LAUNCHER})
+ list(APPEND TARGETS_LINK ${TARGET_SERVER_LAUNCHER})
+endif()
+
+########################################################################
+# VARIOUS TARGETS
+########################################################################
+
+set_src(MASTERSRV_SRC GLOB src/mastersrv mastersrv.cpp mastersrv.h)
+set_src(VERSIONSRV_SRC GLOB src/versionsrv mapversions.h versionsrv.cpp versionsrv.h)
+
+set(TARGET_MASTERSRV mastersrv)
+set(TARGET_VERSIONSRV versionsrv)
+
+add_executable(${TARGET_MASTERSRV} EXCLUDE_FROM_ALL ${MASTERSRV_SRC} $<TARGET_OBJECTS:engine-shared> ${DEPS})
+add_executable(${TARGET_VERSIONSRV} EXCLUDE_FROM_ALL ${VERSIONSRV_SRC} $<TARGET_OBJECTS:engine-shared> ${DEPS})
+
+target_link_libraries(${TARGET_MASTERSRV} ${LIBS})
+target_link_libraries(${TARGET_VERSIONSRV} ${LIBS})
+
+list(APPEND TARGETS_OWN ${TARGET_MASTERSRV} ${TARGET_VERSIONSRV})
+list(APPEND TARGETS_LINK ${TARGET_MASTERSRV} ${TARGET_VERSIONSRV})
+
+set(TARGETS_TOOLS)
+set_src(TOOLS GLOB src/tools
+ crapnet.cpp
+ fake_server.cpp
+ map_resave.cpp
+ map_version.cpp
+ packetgen.cpp
+)
+foreach(ABS_T ${TOOLS})
+ file(RELATIVE_PATH T "${PROJECT_SOURCE_DIR}/src/tools/" ${ABS_T})
+ if(T MATCHES "\\.cpp$")
+ string(REGEX REPLACE "\\.cpp$" "" TOOL "${T}")
+ add_executable(${TOOL} EXCLUDE_FROM_ALL
+ ${DEPS}
+ src/tools/${TOOL}.cpp
+ ${EXTRA_TOOL_SRC}
+ $<TARGET_OBJECTS:engine-shared>
+ )
+ target_link_libraries(${TOOL} ${LIBS})
+ list(APPEND TARGETS_TOOLS ${TOOL})
+ endif()
+endforeach()
+
+list(APPEND TARGETS_OWN ${TARGETS_TOOLS})
+list(APPEND TARGETS_LINK ${TARGETS_TOOLS})
+
+add_custom_target(tools DEPENDS ${TARGETS_TOOLS})
+add_custom_target(everything DEPENDS ${TARGETS_OWN})
+
+########################################################################
+# INSTALLATION
+########################################################################
+
+function(escape_regex VAR STRING)
+ string(REGEX REPLACE "([][^$.+*?|()\\\\])" "\\\\\\1" ESCAPED "${STRING}")
+ set(${VAR} ${ESCAPED} PARENT_SCOPE)
+endfunction()
+
+function(escape_backslashes VAR STRING)
+ string(REGEX REPLACE "\\\\" "\\\\\\\\" ESCAPED "${STRING}")
+ set(${VAR} ${ESCAPED} PARENT_SCOPE)
+endfunction()
+
+function(max_length VAR)
+ set(MAX_LENGTH 0)
+ foreach(str ${ARGN})
+ string(LENGTH ${str} LENGTH)
+ if(LENGTH GREATER MAX_LENGTH)
+ set(MAX_LENGTH ${LENGTH})
+ endif()
+ endforeach()
+ set(${VAR} ${MAX_LENGTH} PARENT_SCOPE)
+endfunction()
+
+# Tries to generate a list of regex that matches everything except the given
+# parameters.
+function(regex_inverted VAR)
+ max_length(MAX_LENGTH ${ARGN})
+ math(EXPR UPPER_BOUND "${MAX_LENGTH}-1")
+
+ set(REMAINING ${ARGN})
+ set(RESULT)
+
+ foreach(i RANGE ${UPPER_BOUND})
+ set(TEMP ${REMAINING})
+ set(REMAINING)
+ foreach(str ${TEMP})
+ string(LENGTH ${str} LENGTH)
+ if(i LESS LENGTH)
+ list(APPEND REMAINING ${str})
+ endif()
+ endforeach()
+
+ set(ADDITIONAL)
+ foreach(outer ${REMAINING})
+ string(SUBSTRING ${outer} 0 ${i} OUTER_PREFIX)
+ set(CHARS "")
+ foreach(inner ${REMAINING})
+ string(SUBSTRING ${inner} 0 ${i} INNER_PREFIX)
+ if(OUTER_PREFIX STREQUAL INNER_PREFIX)
+ string(SUBSTRING ${inner} ${i} 1 INNER_NEXT)
+ set(CHARS "${CHARS}${INNER_NEXT}")
+ endif()
+ endforeach()
+ escape_regex(OUTER_PREFIX_ESCAPED "${OUTER_PREFIX}")
+
+ list(APPEND ADDITIONAL "${OUTER_PREFIX_ESCAPED}([^${CHARS}]|$)")
+ endforeach()
+ list(REMOVE_DUPLICATES ADDITIONAL)
+ list(APPEND RESULT ${ADDITIONAL})
+ endforeach()
+ set(${VAR} ${RESULT} PARENT_SCOPE)
+endfunction()
+
+set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
+set(CPACK_GENERATOR TGZ TXZ)
+set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
+set(CPACK_STRIP_FILES TRUE)
+set(CPACK_COMPONENTS_ALL portable)
+set(CPACK_SOURCE_GENERATOR ZIP TGZ TBZ2 TXZ)
+set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
+set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
+set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
+set(CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
+set(CPACK_SYSTEM_NAME ${CMAKE_SYSTEM_NAME})
+
+if(TARGET_OS AND TARGET_BITS)
+ if(TARGET_OS STREQUAL "windows")
+ set(CPACK_SYSTEM_NAME "win${TARGET_BITS}")
+ set(CPACK_GENERATOR ZIP)
+ elseif(TARGET_OS STREQUAL "linux")
+ # Assuming Intel here.
+ if(TARGET_BITS EQUAL 32)
+ set(CPACK_SYSTEM_NAME "linux_x86")
+ elseif(TARGET_BITS EQUAL 64)
+ set(CPACK_SYSTEM_NAME "linux_x86_64")
+ endif()
+ elseif(TARGET_OS STREQUAL "mac")
+ set(CPACK_SYSTEM_NAME "osx")
+ set(CPACK_GENERATOR DMG)
+ endif()
+endif()
+
+set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME})
+set(CPACK_ARCHIVE_PORTABLE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME})
+set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-src)
+set(CPACK_SOURCE_FILES
+ CMakeLists.txt
+ bam.lua
+ cmake/
+ configure.lua
+ datasrc/
+ license.txt
+ other/
+ readme.md
+ scripts/
+ src/
+ storage.cfg
+)
+set(CPACK_SOURCE_IGNORE_FILES
+ "\\\\.o$"
+ "\\\\.pyc$"
+ "/\\\\.git"
+ "/__pycache__/"
+)
+
+regex_inverted(CPACK_SOURCE_FILES_INVERTED ${CPACK_SOURCE_FILES})
+escape_regex(PROJECT_SOURCE_DIR_ESCAPED ${PROJECT_SOURCE_DIR})
+
+foreach(str ${CPACK_SOURCE_FILES_INVERTED})
+ escape_backslashes(STR_ESCAPED "${PROJECT_SOURCE_DIR_ESCAPED}/${str}")
+ list(APPEND CPACK_SOURCE_IGNORE_FILES "${STR_ESCAPED}")
+endforeach()
+
+set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME ${PROJECT_NAME})
+
+set(CPACK_TARGETS
+ ${TARGET_CLIENT}
+ ${TARGET_SERVER}
+)
+set(CPACK_DIRS ${PROJECT_BINARY_DIR}/data)
+set(CPACK_FILES
+ license.txt
+ storage.cfg
+ ${COPY_FILES}
+)
+if(TARGET_OS STREQUAL "windows")
+ list(APPEND CPACK_FILES other/config_directory.bat)
+endif()
+
+if(NOT DEV)
+ install(DIRECTORY ${PROJECT_BINARY_DIR}/data DESTINATION share/${PROJECT_NAME} COMPONENT data)
+ install(TARGETS ${TARGET_CLIENT} DESTINATION bin COMPONENT client)
+ install(TARGETS ${TARGET_SERVER} DESTINATION bin COMPONENT server)
+endif()
+
+if(DEV)
+ # Don't generate CPack targets.
+elseif(CMAKE_VERSION VERSION_LESS 3.6 OR CMAKE_VERSION VERSION_EQUAL 3.6)
+ message(WARNING "Cannot create CPack targets, CMake version too old. Use CMake 3.6 or newer.")
+else()
+ set(EXTRA_ARGS DESTINATION ${CPACK_PACKAGE_FILE_NAME} COMPONENT portable EXCLUDE_FROM_ALL)
+ install(TARGETS ${CPACK_TARGETS} ${EXTRA_ARGS})
+ install(DIRECTORY ${CPACK_DIRS} ${EXTRA_ARGS})
+ install(FILES ${CPACK_FILES} ${EXTRA_ARGS})
+endif()
+
+set(PACKAGE_TARGETS)
+
+if(CLIENT AND (DMGTOOLS_FOUND OR HDIUTIL))
+ file(MAKE_DIRECTORY bundle/client/)
+ file(MAKE_DIRECTORY bundle/server/)
+ configure_file(other/bundle/client/Info.plist.in bundle/client/Info.plist)
+ configure_file(other/bundle/server/Info.plist.in bundle/server/Info.plist)
+
+ if(HDIUTIL)
+ set(DMG_PARAMS --hdiutil ${HDIUTIL})
+ elseif(DMGTOOLS_FOUND)
+ set(DMG_PARAMS --dmgtools ${DMG} ${HFSPLUS} ${NEWFS_HFS})
+ endif()
+ set(DMG_TMPDIR pack_${CPACK_PACKAGE_FILE_NAME}_dmg)
+ set(DMG_MKDIRS
+ ${TARGET_CLIENT}.app
+ ${TARGET_CLIENT}.app/Contents
+ ${TARGET_CLIENT}.app/Contents/Frameworks
+ ${TARGET_CLIENT}.app/Contents/MacOS
+ ${TARGET_CLIENT}.app/Contents/Resources
+ ${TARGET_SERVER}.app
+ ${TARGET_SERVER}.app/Contents
+ ${TARGET_SERVER}.app/Contents/MacOS
+ ${TARGET_SERVER}.app/Contents/Resources
+ ${TARGET_SERVER}.app/Contents/Resources/data
+ # Needed so the server recognizes the data directory.
+ ${TARGET_SERVER}.app/Contents/Resources/data/mapres
+ )
+ set(DMG_MKDIR_COMMANDS)
+ foreach(dir ${DMG_MKDIRS})
+ list(APPEND DMG_MKDIR_COMMANDS COMMAND ${CMAKE_COMMAND} -E make_directory ${DMG_TMPDIR}/${dir})
+ endforeach()
+ add_custom_command(OUTPUT ${CPACK_PACKAGE_FILE_NAME}.dmg
+ COMMAND ${CMAKE_COMMAND} -E remove_directory ${DMG_TMPDIR}
+ ${DMG_MKDIR_COMMANDS}
+
+ # CLIENT
+ COMMAND ${CMAKE_COMMAND} -E copy_directory data ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Resources/data
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/other/icons/${TARGET_CLIENT}.icns ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Resources/
+ COMMAND ${CMAKE_COMMAND} -E copy bundle/client/Info.plist ${PROJECT_SOURCE_DIR}/other/bundle/client/PkgInfo ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/
+ COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${TARGET_CLIENT}> ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/MacOS/
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/other/sdl/mac/lib64/SDL2.framework ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/SDL2.framework
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/other/freetype/mac/lib64/libfreetype.6.dylib ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/Frameworks/
+ COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/darwin_change_dylib.py change --tools ${CMAKE_INSTALL_NAME_TOOL} ${CMAKE_OTOOL} ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/MacOS/${TARGET_CLIENT} SDL2 @executable_path/../Frameworks/SDL2.framework/SDL2
+ COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/darwin_change_dylib.py change --tools ${CMAKE_INSTALL_NAME_TOOL} ${CMAKE_OTOOL} ${DMG_TMPDIR}/${TARGET_CLIENT}.app/Contents/MacOS/${TARGET_CLIENT} libfreetype @executable_path/../Frameworks/libfreetype.6.dylib
+
+ # SERVER
+ COMMAND ${CMAKE_COMMAND} -E copy_directory data/maps ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/Resources/data/maps
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/other/icons/${TARGET_SERVER}.icns ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/Resources/
+ COMMAND ${CMAKE_COMMAND} -E copy bundle/server/Info.plist ${PROJECT_SOURCE_DIR}/other/bundle/server/PkgInfo ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/
+ COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${TARGET_SERVER}> $<TARGET_FILE:${TARGET_SERVER_LAUNCHER}> ${DMG_TMPDIR}/${TARGET_SERVER}.app/Contents/MacOS/
+
+ # DMG
+ COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/dmg.py create ${DMG_PARAMS} ${CPACK_PACKAGE_FILE_NAME}.dmg ${CPACK_PACKAGE_FILE_NAME} ${DMG_TMPDIR}
+
+ DEPENDS
+ ${TARGET_CLIENT}
+ ${TARGET_SERVER_LAUNCHER}
+ ${TARGET_SERVER}
+ ${PROJECT_BINARY_DIR}/bundle/client/Info.plist
+ ${PROJECT_BINARY_DIR}/bundle/server/Info.plist
+ other/bundle/client/PkgInfo
+ other/bundle/server/PkgInfo
+ other/icons/${TARGET_CLIENT}.icns
+ other/icons/${TARGET_SERVER}.icns
+ scripts/dmg.py
+ )
+ add_custom_target(package_dmg DEPENDS ${CPACK_PACKAGE_FILE_NAME}.dmg)
+ list(APPEND PACKAGE_TARGETS package_dmg)
+endif()
+
+foreach(ext zip tar.gz tar.xz)
+ set(TAR_MODE c)
+ set(TAR_EXTRA_ARGS)
+ string(REPLACE . _ EXT_SLUG ${ext})
+
+ set(TMPDIR pack_${CPACK_PACKAGE_FILE_NAME}_${EXT_SLUG}/${CPACK_PACKAGE_FILE_NAME})
+
+ set(COPY_FILE_COMMANDS)
+ set(COPY_DIR_COMMANDS)
+ set(COPY_TARGET_COMMANDS)
+ set(STRIP_TARGET_COMMANDS)
+ foreach(file ${CPACK_FILES})
+ list(APPEND COPY_FILE_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/${file} ${TMPDIR}/)
+ endforeach()
+ foreach(dir ${CPACK_DIRS})
+ get_filename_component(NAME ${dir} NAME)
+ list(APPEND COPY_DIR_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy_directory ${dir} ${TMPDIR}/${NAME})
+ endforeach()
+ foreach(target ${CPACK_TARGETS})
+ list(APPEND COPY_TARGET_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${target}> ${TMPDIR}/)
+ endforeach()
+
+ if(ext STREQUAL zip)
+ set(TAR_EXTRA_ARGS --format=zip)
+ elseif(ext STREQUAL tar.gz)
+ set(TAR_MODE cz)
+ elseif(ext STREQUAL tar.xz)
+ set(TAR_MODE cJ)
+ endif()
+ add_custom_command(OUTPUT ${CPACK_PACKAGE_FILE_NAME}.${ext}
+ COMMAND ${CMAKE_COMMAND} -E remove_directory ${TMPDIR}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${TMPDIR}
+ ${COPY_FILE_COMMANDS}
+ ${COPY_DIR_COMMANDS}
+ ${COPY_TARGET_COMMANDS}
+ ${STRIP_TARGET_COMMANDS}
+ COMMAND ${CMAKE_COMMAND} -E chdir pack_${CPACK_PACKAGE_FILE_NAME}_${EXT_SLUG} ${CMAKE_COMMAND} -E tar ${TAR_MODE} ../${CPACK_PACKAGE_FILE_NAME}.${ext} ${TAR_EXTRA_ARGS} -- ${CPACK_PACKAGE_FILE_NAME}/
+ DEPENDS ${CPACK_TARGETS}
+ )
+ add_custom_target(package_${EXT_SLUG} DEPENDS ${CPACK_PACKAGE_FILE_NAME}.${ext})
+ list(APPEND PACKAGE_TARGETS package_${EXT_SLUG})
+endforeach()
+
+set(PACKAGE_DEFAULT tar_xz)
+if(TARGET_OS STREQUAL "windows")
+ set(PACKAGE_DEFAULT zip)
+elseif(TARGET_OS STREQUAL "mac")
+ set(PACKAGE_DEFAULT dmg)
+endif()
+add_custom_target(package_default DEPENDS package_${PACKAGE_DEFAULT})
+
+add_custom_target(package_all DEPENDS ${PACKAGE_TARGETS})
+
+# Unset these variables, they might do something in the future of CPack.
+unset(CPACK_SOURCE_FILES)
+unset(CPACK_SOURCE_FILES_INVERTED)
+unset(CPACK_TARGETS)
+unset(CPACK_DIRS)
+unset(CPACK_FILES)
+
+include(CPack)
+
+########################################################################
+# COMPILER-SPECIFICS
+########################################################################
+
+# In the future (CMake 3.8.0+), use source_group(TREE ...)
+macro(source_group_tree dir)
+ file(GLOB ents RELATIVE ${PROJECT_SOURCE_DIR}/${dir} ${PROJECT_SOURCE_DIR}/${dir}/*)
+ foreach(ent ${ents})
+ if(IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${dir}/${ent})
+ source_group_tree(${dir}/${ent})
+ else()
+ string(REPLACE "/" "\\" group ${dir})
+ source_group(${group} FILES ${PROJECT_SOURCE_DIR}/${dir}/${ent})
+ endif()
+ endforeach()
+endmacro()
+source_group_tree(src)
+
+set(TARGETS ${TARGETS_OWN} ${TARGETS_DEP})
+
+foreach(target ${TARGETS})
+ if(MSVC)
+ target_compile_options(${target} PRIVATE $<$<NOT:${DBG}>:/MT> $<${DBG}:/MTd>) # Use static CRT
+ target_compile_options(${target} PRIVATE /MP) # Use multiple cores
+ target_compile_options(${target} PRIVATE /EHsc) # Only catch C++ exceptions with catch.
+ target_compile_options(${target} PRIVATE /GS) # Protect the stack pointer.
+ target_compile_options(${target} PRIVATE /wd4996) # Use of non-_s functions.
+ endif()
+ if(OUR_FLAGS)
+ target_compile_options(${target} PRIVATE ${OUR_FLAGS})
+ endif()
+ if(DEFINE_FORTIFY_SOURCE)
+ target_compile_definitions(${target} PRIVATE $<$<NOT:$<CONFIG:Debug>>:_FORTIFY_SOURCE=2>) # Detect some buffer overflows.
+ endif()
+endforeach()
+
+foreach(target ${TARGETS_LINK})
+ if(MSVC)
+ set_property(TARGET ${target} APPEND PROPERTY LINK_FLAGS /SAFESEH:NO) # Disable SafeSEH because the shipped libraries don't support it (would cause error LNK2026 otherwise).
+ endif()
+ if(TARGET_OS STREQUAL "mac")
+ target_link_libraries(${target} -stdlib=libc++)
+ target_link_libraries(${target} -mmacosx-version-min=10.7)
+ endif()
+ if((MINGW OR TARGET_OS STREQUAL "linux") AND PREFER_BUNDLED_LIBS)
+ # Statically link the standard libraries with on MinGW/Linux so we don't
+ # have to ship them as DLLs.
+ target_link_libraries(${target} -static-libgcc)
+ target_link_libraries(${target} -static-libstdc++)
+ if(MINGW)
+ # Link pthread library statically instead of dynamically.
+ # Solution from https://stackoverflow.com/a/28001261.
+ target_link_libraries(${target} -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic)
+ endif()
+ endif()
+endforeach()
+
+foreach(target ${TARGETS_OWN})
+ if(MSVC)
+ target_compile_options(${target} PRIVATE /wd4244) # Possible loss of data (float -> int, int -> float, etc.).
+ target_compile_options(${target} PRIVATE /wd4267) # Possible loss of data (size_t - int on win64).
+ target_compile_options(${target} PRIVATE /wd4800) # Implicit conversion of int to bool.
+ endif()
+ if(OUR_FLAGS_OWN)
+ target_compile_options(${target} PRIVATE ${OUR_FLAGS_OWN})
+ endif()
+ target_include_directories(${target} PRIVATE ${PROJECT_BINARY_DIR}/src)
+ target_include_directories(${target} PRIVATE src)
+ target_compile_definitions(${target} PRIVATE $<$<CONFIG:Debug>:CONF_DEBUG>)
+ target_include_directories(${target} PRIVATE ${CURL_INCLUDE_DIRS})
+ target_include_directories(${target} PRIVATE ${ZLIB_INCLUDE_DIRS})
+endforeach()
+
+foreach(target ${TARGETS_DEP})
+ if(MSVC)
+ target_compile_options(${target} PRIVATE /W0)
+ endif()
+ if(OUR_FLAGS_DEP)
+ target_compile_options(${target} PRIVATE ${OUR_FLAGS_DEP})
+ endif()
+endforeach()
diff --git a/bam.lua b/bam.lua
index 77a1aab72..1988d217c 100644
--- a/bam.lua
+++ b/bam.lua
@@ -414,6 +414,8 @@ function GenerateSettings(conf, arch, builddir, compiler)
end
settings.cc.includes:Add("src")
+ settings.cc.includes:Add("src/engine/external/pnglite")
+ settings.cc.includes:Add("src/engine/external/wavpack")
settings.cc.includes:Add(generated_src_dir)
if family == "windows" then
diff --git a/cmake/FindFreetype.cmake b/cmake/FindFreetype.cmake
new file mode 100644
index 000000000..347b68442
--- /dev/null
+++ b/cmake/FindFreetype.cmake
@@ -0,0 +1,37 @@
+if(NOT CMAKE_CROSSCOMPILING)
+ find_package(PkgConfig QUIET)
+ pkg_check_modules(PC_FREETYPE freetype2)
+endif()
+
+set_extra_dirs_lib(FREETYPE freetype)
+find_library(FREETYPE_LIBRARY
+ NAMES freetype freetype.6
+ HINTS ${HINTS_FREETYPE_LIBDIR} ${PC_FREETYPE_LIBDIR} ${PC_FREETYPE_LIBRARY_DIRS}
+ PATHS ${PATHS_FREETYPE_LIBDIR}
+ ${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
+)
+set_extra_dirs_include(FREETYPE freetype "${FREETYPE_LIBRARY}")
+find_path(FREETYPE_INCLUDEDIR
+ NAMES config/ftheader.h freetype/config/ftheader.h
+ PATH_SUFFIXES freetype2
+ HINTS ${HINTS_FREETYPE_INCLUDEDIR} ${PC_FREETYPE_INCLUDEDIR} ${PC_FREETYPE_INCLUDE_DIRS}
+ PATHS ${PATHS_FREETYPE_INCLUDEDIR}
+ ${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Freetype DEFAULT_MSG FREETYPE_LIBRARY FREETYPE_INCLUDEDIR)
+
+mark_as_advanced(FREETYPE_LIBRARY FREETYPE_INCLUDEDIR)
+
+if(FREETYPE_FOUND)
+ set(FREETYPE_LIBRARIES ${FREETYPE_LIBRARY})
+ set(FREETYPE_INCLUDE_DIRS ${FREETYPE_INCLUDEDIR})
+
+ is_bundled(FREETYPE_BUNDLED "${FREETYPE_LIBRARY}")
+ if(FREETYPE_BUNDLED AND TARGET_OS STREQUAL "windows")
+ set(FREETYPE_COPY_FILES "${EXTRA_FREETYPE_LIBDIR}/freetype.dll")
+ else()
+ set(FREETYPE_COPY_FILES)
+ endif()
+endif()
diff --git a/cmake/FindPnglite.cmake b/cmake/FindPnglite.cmake
new file mode 100644
index 000000000..6a877c257
--- /dev/null
+++ b/cmake/FindPnglite.cmake
@@ -0,0 +1,46 @@
+if(NOT PREFER_BUNDLED_LIBS)
+ if(NOT CMAKE_CROSSCOMPILING)
+ find_package(PkgConfig QUIET)
+ pkg_check_modules(PC_PNGLITE pnglite)
+ endif()
+
+ find_library(PNGLITE_LIBRARY
+ NAMES pnglite
+ HINTS ${PC_PNGLITE_LIBDIR} ${PC_PNGLITE_LIBRARY_DIRS}
+ ${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
+ )
+ find_path(PNGLITE_INCLUDEDIR
+ NAMES pnglite.h
+ HINTS ${PC_PNGLITE_INCLUDEDIR} ${PC_PNGLITE_INCLUDE_DIRS}
+ ${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
+ )
+
+ mark_as_advanced(PNGLITE_LIBRARY PNGLITE_INCLUDEDIR)
+
+ if(PNGLITE_LIBRARY AND PNGLITE_INCLUDEDIR)
+ include(FindPackageHandleStandardArgs)
+ find_package_handle_standard_args(Pnglite DEFAULT_MSG PNGLITE_LIBRARY PNGLITE_INCLUDEDIR)
+
+ set(PNGLITE_LIBRARIES ${PNGLITE_LIBRARY})
+ set(PNGLITE_INCLUDE_DIRS ${PNGLITE_INCLUDEDIR})
+ set(PNGLITE_BUNDLED OFF)
+ endif()
+endif()
+
+if(NOT PNGLITE_FOUND)
+ set(PNGLITE_SRC_DIR src/engine/external/pnglite)
+ set_src(PNGLITE_SRC GLOB ${PNGLITE_SRC_DIR} pnglite.c pnglite.h)
+ add_library(pnglite EXCLUDE_FROM_ALL OBJECT ${PNGLITE_SRC})
+ list(APPEND TARGETS_DEP pnglite)
+
+ set(PNGLITE_INCLUDEDIR ${PNGLITE_SRC_DIR})
+ target_include_directories(pnglite PRIVATE ${ZLIB_INCLUDE_DIRS})
+
+ set(PNGLITE_DEP $<TARGET_OBJECTS:pnglite>)
+ set(PNGLITE_INCLUDE_DIRS ${PNGLITE_INCLUDEDIR})
+ set(PNGLITE_LIBRARIES)
+
+ include(FindPackageHandleStandardArgs)
+ find_package_handle_standard_args(Pnglite DEFAULT_MSG PNGLITE_INCLUDEDIR)
+ set(PNGLITE_BUNDLED ON)
+endif()
diff --git a/cmake/FindSDL2.cmake b/cmake/FindSDL2.cmake
new file mode 100644
index 000000000..94e293294
--- /dev/null
+++ b/cmake/FindSDL2.cmake
@@ -0,0 +1,48 @@
+if(NOT PREFER_BUNDLED_LIBS)
+ set(CMAKE_MODULE_PATH ${ORIGINAL_CMAKE_MODULE_PATH})
+ find_package(SDL2)
+ set(CMAKE_MODULE_PATH ${OWN_CMAKE_MODULE_PATH})
+ if(SDL2_FOUND)
+ set(SDL2_BUNDLED OFF)
+ set(SDL2_DEP)
+ endif()
+endif()
+
+if(NOT CMAKE_CROSSCOMPILING)
+ find_package(PkgConfig QUIET)
+ pkg_check_modules(PC_SDL2 sdl2)
+endif()
+
+set_extra_dirs_lib(SDL2 sdl)
+find_library(SDL2_LIBRARY
+ NAMES SDL2
+ HINTS ${HINTS_SDL2_LIBDIR} ${PC_SDL2_LIBDIR} ${PC_SDL2_LIBRARY_DIRS}
+ PATHS ${PATHS_SDL2_LIBDIR}
+ ${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
+)
+set(CMAKE_FIND_FRAMEWORK FIRST)
+set_extra_dirs_include(SDL2 sdl "${SDL2_LIBRARY}")
+# Looking for 'SDL.h' directly might accidentally find a SDL 1 instead of SDL 2
+# installation. Look for a header file only present in SDL 2 instead.
+find_path(SDL2_INCLUDEDIR SDL_assert.h
+ PATH_SUFFIXES SDL
+ HINTS ${HINTS_SDL2_INCLUDEDIR} ${PC_SDL2_INCLUDEDIR} ${PC_SDL2_INCLUDE_DIRS}
+ PATHS ${PATHS_SDL2_INCLUDEDIR}
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(SDL2 DEFAULT_MSG SDL2_LIBRARY SDL2_INCLUDEDIR)
+
+mark_as_advanced(SDL2_LIBRARY SDL2_INCLUDEDIR)
+
+if(SDL2_FOUND)
+ set(SDL2_LIBRARIES ${SDL2_LIBRARY})
+ set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDEDIR})
+
+ is_bundled(SDL2_BUNDLED "${SDL2_LIBRARY}")
+ if(SDL2_BUNDLED AND TARGET_OS STREQUAL "windows")
+ set(SDL2_COPY_FILES "${EXTRA_SDL2_LIBDIR}/SDL2.dll")
+ else()
+ set(SDL2_COPY_FILES)
+ endif()
+endif()
diff --git a/cmake/FindWavpack.cmake b/cmake/FindWavpack.cmake
new file mode 100644
index 000000000..b7e855268
--- /dev/null
+++ b/cmake/FindWavpack.cmake
@@ -0,0 +1,52 @@
+if(NOT PREFER_BUNDLED_LIBS)
+ if(NOT CMAKE_CROSSCOMPILING)
+ find_package(PkgConfig QUIET)
+ pkg_check_modules(PC_WAVPACK wavpack)
+ endif()
+
+ find_library(WAVPACK_LIBRARY
+ NAMES wavpack
+ HINTS ${PC_WAVPACK_LIBDIR} ${PC_WAVPACK_LIBRARY_DIRS}
+ ${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
+ )
+ find_path(WAVPACK_INCLUDEDIR
+ NAMES wavpack.h
+ PATH_SUFFIXES wavpack
+ HINTS ${PC_WAVPACK_INCLUDEDIR} ${PC_WAVPACK_INCLUDE_DIRS}
+ ${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
+ )
+
+ mark_as_advanced(WAVPACK_LIBRARY WAVPACK_INCLUDEDIR)
+
+ if(WAVPACK_LIBRARY AND WAVPACK_INCLUDEDIR)
+ include(FindPackageHandleStandardArgs)
+ find_package_handle_standard_args(Wavpack DEFAULT_MSG WAVPACK_LIBRARY WAVPACK_INCLUDEDIR)
+
+ set(WAVPACK_LIBRARIES ${WAVPACK_LIBRARY})
+ set(WAVPACK_INCLUDE_DIRS ${WAVPACK_INCLUDEDIR})
+ set(WAVPACK_BUNDLED OFF)
+ endif()
+endif()
+
+if(NOT WAVPACK_FOUND)
+ set(WAVPACK_SRC_DIR src/engine/external/wavpack)
+ set_src(WAVPACK_SRC GLOB ${WAVPACK_SRC_DIR}
+ bits.c
+ float.c
+ metadata.c
+ unpack.c
+ wavpack.h
+ words.c
+ wputils.c
+ )
+ add_library(wavpack EXCLUDE_FROM_ALL OBJECT ${WAVPACK_SRC})
+ set(WAVPACK_DEP $<TARGET_OBJECTS:wavpack>)
+ set(WAVPACK_INCLUDEDIR ${WAVPACK_SRC_DIR})
+ set(WAVPACK_INCLUDE_DIRS ${WAVPACK_INCLUDEDIR})
+
+ list(APPEND TARGETS_DEP wavpack)
+
+ include(FindPackageHandleStandardArgs)
+ find_package_handle_standard_args(Wavpack DEFAULT_MSG WAVPACK_INCLUDEDIR)
+ set(WAVPACK_BUNDLED ON)
+endif()
diff --git a/cmake/FindZLIB.cmake b/cmake/FindZLIB.cmake
new file mode 100644
index 000000000..a8dfca4d3
--- /dev/null
+++ b/cmake/FindZLIB.cmake
@@ -0,0 +1,50 @@
+if(NOT PREFER_BUNDLED_LIBS)
+ set(CMAKE_MODULE_PATH ${ORIGINAL_CMAKE_MODULE_PATH})
+ find_package(ZLIB)
+ set(CMAKE_MODULE_PATH ${OWN_CMAKE_MODULE_PATH})
+ if(ZLIB_FOUND)
+ set(ZLIB_BUNDLED OFF)
+ set(ZLIB_DEP)
+ endif()
+endif()
+
+if(NOT ZLIB_FOUND)
+ set(ZLIB_BUNDLED ON)
+ set(ZLIB_SRC_DIR src/engine/external/zlib)
+ set_src(ZLIB_SRC GLOB ${ZLIB_SRC_DIR}
+ adler32.c
+ compress.c
+ crc32.c
+ crc32.h
+ deflate.c
+ deflate.h
+ gzguts.h
+ infback.c
+ inffast.c
+ inffast.h
+ inffixed.h
+ inflate.c
+ inflate.h
+ inftrees.c
+ inftrees.h
+ trees.c
+ trees.h
+ uncompr.c
+ zconf.h
+ zlib.h
+ zutil.c
+ zutil.h
+ )
+ add_library(zlib EXCLUDE_FROM_ALL OBJECT ${ZLIB_SRC})
+ set(ZLIB_INCLUDEDIR ${ZLIB_SRC_DIR})
+ target_include_directories(zlib PRIVATE ${ZLIB_INCLUDEDIR})
+
+ set(ZLIB_DEP $<TARGET_OBJECTS:zlib>)
+ set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDEDIR})
+ set(ZLIB_LIBRARIES)
+
+ list(APPEND TARGETS_DEP zlib)
+
+ include(FindPackageHandleStandardArgs)
+ find_package_handle_standard_args(ZLIB DEFAULT_MSG ZLIB_INCLUDEDIR)
+endif()
diff --git a/cmake/toolchains/darwin.toolchain b/cmake/toolchains/darwin.toolchain
new file mode 100644
index 000000000..6d1d6eb3e
--- /dev/null
+++ b/cmake/toolchains/darwin.toolchain
@@ -0,0 +1,11 @@
+set(CMAKE_SYSTEM_NAME Darwin)
+
+set(CMAKE_C_COMPILER o64-clang)
+set(CMAKE_CXX_COMPILER o64-clang++)
+set(CMAKE_INSTALL_NAME_TOOL x86_64-apple-darwin15-install_name_tool)
+set(CMAKE_OTOOL x86_64-apple-darwin15-otool)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
diff --git a/cmake/toolchains/mingw32.toolchain b/cmake/toolchains/mingw32.toolchain
new file mode 100644
index 000000000..c4c065b7e
--- /dev/null
+++ b/cmake/toolchains/mingw32.toolchain
@@ -0,0 +1,10 @@
+set(CMAKE_SYSTEM_NAME Windows)
+
+set(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
+set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
+set(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
diff --git a/cmake/toolchains/mingw64.toolchain b/cmake/toolchains/mingw64.toolchain
new file mode 100644
index 000000000..bec41e944
--- /dev/null
+++ b/cmake/toolchains/mingw64.toolchain
@@ -0,0 +1,10 @@
+set(CMAKE_SYSTEM_NAME Windows)
+
+set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
+set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
+set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
diff --git a/other/bundle/client/Info.plist.in b/other/bundle/client/Info.plist.in
new file mode 100644
index 000000000..34d919702
--- /dev/null
+++ b/other/bundle/client/Info.plist.in
@@ -0,0 +1,24 @@
+<?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">
+<plist version="1.0">
+ <dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${TARGET_CLIENT}</string>
+ <key>CFBundleIconFile</key>
+ <string>${TARGET_CLIENT}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>${PROJECT_VERSION}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.teeworlds.app</string>
+ <key>NSHighResolutionCapable</key>
+ <true/>
+ </dict>
+</plist>
diff --git a/other/bundle/client/PkgInfo b/other/bundle/client/PkgInfo
new file mode 100644
index 000000000..6f749b0f3
--- /dev/null
+++ b/other/bundle/client/PkgInfo
@@ -0,0 +1 @@
+APPL????
diff --git a/other/bundle/server/Info.plist.in b/other/bundle/server/Info.plist.in
new file mode 100644
index 000000000..6cdd38f0d
--- /dev/null
+++ b/other/bundle/server/Info.plist.in
@@ -0,0 +1,20 @@
+<?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">
+<plist version="1.0">
+ <dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${TARGET_SERVER_LAUNCHER}</string>
+ <key>CFBundleIconFile</key>
+ <string>${TARGET_SERVER}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>${PROJECT_VERSION}</string>
+ </dict>
+</plist>
diff --git a/other/bundle/server/PkgInfo b/other/bundle/server/PkgInfo
new file mode 100644
index 000000000..6f749b0f3
--- /dev/null
+++ b/other/bundle/server/PkgInfo
@@ -0,0 +1 @@
+APPL????
diff --git a/other/freetype/freetype.lua b/other/freetype/freetype.lua
index bfd6523cc..f2517fd6c 100644
--- a/other/freetype/freetype.lua
+++ b/other/freetype/freetype.lua
@@ -36,9 +36,9 @@ FreeType = {
elseif option.use_winlib > 0 then
settings.cc.includes:Add(FreeType.basepath .. "/include")
if option.use_winlib == 32 then
- settings.link.libpath:Add(FreeType.basepath .. "/lib/x86")
+ settings.link.libpath:Add(FreeType.basepath .. "/windows/lib32")
else
- settings.link.libpath:Add(FreeType.basepath .. "/lib/x64")
+ settings.link.libpath:Add(FreeType.basepath .. "/windows/lib64")
end
settings.link.libs:Add("freetype")
end
diff --git a/other/icons/Teeworlds.icns b/other/icons/teeworlds.icns
similarity index 100%
rename from other/icons/Teeworlds.icns
rename to other/icons/teeworlds.icns
diff --git a/other/icons/Teeworlds.ico b/other/icons/teeworlds.ico
similarity index 100%
rename from other/icons/Teeworlds.ico
rename to other/icons/teeworlds.ico
diff --git a/other/icons/teeworlds.rc b/other/icons/teeworlds.rc
new file mode 100644
index 000000000..aa5dcb44f
--- /dev/null
+++ b/other/icons/teeworlds.rc
@@ -0,0 +1 @@
+ID ICON "teeworlds.ico"
diff --git a/other/icons/Teeworlds_srv.icns b/other/icons/teeworlds_srv.icns
similarity index 100%
rename from other/icons/Teeworlds_srv.icns
rename to other/icons/teeworlds_srv.icns
diff --git a/other/icons/Teeworlds_srv.ico b/other/icons/teeworlds_srv.ico
similarity index 100%
rename from other/icons/Teeworlds_srv.ico
rename to other/icons/teeworlds_srv.ico
diff --git a/other/icons/teeworlds_srv.rc b/other/icons/teeworlds_srv.rc
new file mode 100644
index 000000000..44287bb51
--- /dev/null
+++ b/other/icons/teeworlds_srv.rc
@@ -0,0 +1 @@
+ID ICON "teeworlds_srv.ico"
diff --git a/other/icons/teeworlds_srv_cl.rc b/other/icons/teeworlds_srv_cl.rc
index f7b046d92..8e18b64ce 100644
--- a/other/icons/teeworlds_srv_cl.rc
+++ b/other/icons/teeworlds_srv_cl.rc
@@ -1 +1 @@
-50h ICON "Teeworlds_srv.ico"
+50h ICON "teeworlds_srv.ico"
diff --git a/other/icons/teeworlds_srv_gcc.rc b/other/icons/teeworlds_srv_gcc.rc
index 3b7c78a56..44287bb51 100644
--- a/other/icons/teeworlds_srv_gcc.rc
+++ b/other/icons/teeworlds_srv_gcc.rc
@@ -1 +1 @@
-ID ICON "Teeworlds_srv.ico"
+ID ICON "teeworlds_srv.ico"
diff --git a/other/sdl/sdl.lua b/other/sdl/sdl.lua
index 19196ba2d..4bf5fe0f9 100644
--- a/other/sdl/sdl.lua
+++ b/other/sdl/sdl.lua
@@ -36,9 +36,9 @@ SDL = {
elseif option.use_winlib > 0 then
settings.cc.includes:Add(SDL.basepath .. "/include")
if option.use_winlib == 32 then
- settings.link.libpath:Add(SDL.basepath .. "/lib/x86")
+ settings.link.libpath:Add(SDL.basepath .. "/windows/lib32")
else
- settings.link.libpath:Add(SDL.basepath .. "/lib/x64")
+ settings.link.libpath:Add(SDL.basepath .. "/windows/lib64")
end
settings.link.libs:Add("SDL2")
settings.link.libs:Add("SDL2main")
diff --git a/scripts/darwin_change_dylib.py b/scripts/darwin_change_dylib.py
new file mode 100644
index 000000000..6f3922572
--- /dev/null
+++ b/scripts/darwin_change_dylib.py
@@ -0,0 +1,63 @@
+from collections import namedtuple
+import os
+import re
+import shlex
+import subprocess
+
+Config = namedtuple('Config', 'install_name_tool otool verbose')
+
+def dylib_regex(name):
+ return re.compile(r'\S*{}\S*'.format(re.escape(name)))
+
+class ChangeDylib:
+ def __init__(self, config):
+ self.config = config
+ def _check_call(self, process_args, *args, **kwargs):
+ if self.config.verbose >= 1:
+ print("EXECUTING {}".format(" ".join(shlex.quote(x) for x in process_args)))
+ if not (self.config.verbose >= 2 and "stdout" not in kwargs):
+ kwargs["stdout"] = open(os.devnull, 'wb')
+ return subprocess.check_call(process_args, *args, **kwargs)
+ def _check_output(self, process_args, *args, **kwargs):
+ if self.config.verbose >= 1:
+ print("EXECUTING {} FOR OUTPUT".format(" ".join(shlex.quote(x) for x in process_args)))
+ return subprocess.check_output(process_args, *args, **kwargs)
+ def _install_name_tool(self, *args):
+ return self._check_call((self.config.install_name_tool,) + args)
+ def _otool(self, *args):
+ return self._check_output((self.config.otool,) + args)
+
+ def change(self, filename, from_, to):
+ lines = self._otool("-L", filename).decode().splitlines()
+ regex = dylib_regex(from_)
+ matches = sum([regex.findall(l) for l in lines], [])
+ if len(matches) != 1:
+ if matches:
+ raise ValueError("More than one match found for {}: {}".format(from_, matches))
+ else:
+ raise ValueError("No matches found for {}".format(from_))
+ actual_from = matches[0]
+ self._install_name_tool("-change", actual_from, to, filename)
+
+def main():
+ import argparse
+ p = argparse.ArgumentParser(description="Manipulate shared library dependencies for macOS")
+
+ subcommands = p.add_subparsers(help="Subcommand", dest='command', metavar="COMMAND")
+ subcommands.required = True
+
+ change = subcommands.add_parser("change", help="Change a shared library dependency to a given value")
+ change.add_argument('-v', '--verbose', action='count', help="Verbose output")
+ change.add_argument('--tools', nargs=2, help="Paths to the install_name_tool and otool", default=("install_name_tool", "otool"))
+ change.add_argument('filename', metavar="FILE", help="Filename of the executable to manipulate")
+ change.add_argument('from_', metavar="FROM", help="Fuzzily matched library name to change")
+ change.add_argument('to', metavar="TO", help="Exact name that the library dependency should be changed to")
+ args = p.parse_args()
+
+ verbose = args.verbose or 0
+ install_name_tool, otool = args.tools
+ dylib = ChangeDylib(Config(install_name_tool, otool, verbose))
+ dylib.change(filename=args.filename, from_=args.from_, to=args.to)
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/dmg.py b/scripts/dmg.py
new file mode 100644
index 000000000..8f2d4cfc1
--- /dev/null
+++ b/scripts/dmg.py
@@ -0,0 +1,106 @@
+from collections import namedtuple
+import os
+import shlex
+import subprocess
+import tempfile
+
+ConfigDmgtools = namedtuple('Config', 'dmg hfsplus newfs_hfs verbose')
+ConfigHdiutil = namedtuple('Config', 'hdiutil verbose')
+
+def chunks(l, n):
+ """
+ Yield successive n-sized chunks from l.
+
+ From https://stackoverflow.com/a/312464.
+ """
+ for i in range(0, len(l), n):
+ yield l[i:i + n]
+
+class Dmg:
+ def __init__(self, config):
+ self.config = config
+
+ def _check_call(self, process_args, *args, **kwargs):
+ if self.config.verbose >= 1:
+ print("EXECUTING {}".format(" ".join(shlex.quote(x) for x in process_args)))
+ if not (self.config.verbose >= 2 and "stdout" not in kwargs):
+ kwargs["stdout"] = open(os.devnull, 'wb')
+ subprocess.check_call(process_args, *args, **kwargs)
+
+class Dmgtools(Dmg):
+ def _mkfs_hfs(self, *args):
+ self._check_call((self.config.newfs_hfs,) + args)
+ def _hfs(self, *args):
+ self._check_call((self.config.hfsplus,) + args)
+ def _dmg(self, *args):
+ self._check_call((self.config.dmg,) + args)
+
+ def _create_hfs(self, hfs, volume_name, size):
+ if self.config.verbose >= 1:
+ print("TRUNCATING {} to {} bytes".format(hfs, size))
+ with open(hfs, 'wb') as f:
+ f.truncate(size)
+ self._mkfs_hfs('-v', volume_name, hfs)
+
+ def _symlink(self, hfs, target, link_name):
+ self._hfs(hfs, 'symlink', link_name, target)
+
+ def _add(self, hfs, directory):
+ self._hfs(hfs, 'addall', directory)
+
+ def _finish(self, hfs, dmg):
+ self._dmg('build', hfs, dmg)
+
+ def create(self, dmg, volume_name, directory, symlinks):
+ input_size = sum(os.stat(os.path.join(path, f)).st_size for path, dirs, files in os.walk(directory) for f in files)
+ output_size = max(input_size * 2, 1024**2)
+ hfs = tempfile.mktemp(prefix=dmg + '.', suffix='.hfs')
+ self._create_hfs(hfs, volume_name, output_size)
+ self._add(hfs, directory)
+ for target, link_name in symlinks:
+ self._symlink(hfs, target, link_name)
+ self._finish(hfs, dmg)
+ if self.config.verbose >= 1:
+ print("REMOVING {}".format(hfs))
+ os.remove(hfs)
+
+class Hdiutil(Dmg):
+ def _hdiutil(self, *args):
+ self._check_call((self.config.hdiutil,) + args)
+
+ def create(self, dmg, volume_name, directory, symlinks):
+ if symlinks:
+ raise NotImplementedError("symlinks are not yet implemented")
+ self._hdiutil('create', '-volname', volume_name, '-srcdir', directory, dmg)
+
+def main():
+ import argparse
+ p = argparse.ArgumentParser(description="Manipulate dmg archives")
+
+ subcommands = p.add_subparsers(help="Subcommand", dest='command', metavar="COMMAND")
+ subcommands.required = True
+
+ create = subcommands.add_parser("create", help="Create a dmg archive from files or directories")
+ create.add_argument('-v', '--verbose', action='count', help="Verbose output")
+ createx = create.add_mutually_exclusive_group(required=True)
+ createx.add_argument('--dmgtools', nargs=3, help="Paths to the dmg and hfsplus executable (https://github.com/mozilla/libdmg-hfsplus) and the newfs_hfs executable (http://pkgs.fedoraproject.org/repo/pkgs/hfsplus-tools/diskdev_cmds-540.1.linux3.tar.gz/0435afc389b919027b69616ad1b05709/diskdev_cmds-540.1.linux3.tar.gz)")
+ createx.add_argument('--hdiutil', help="Path to the hdiutil (only exists for macOS at time of writing)")
+ create.add_argument('output', metavar="OUTPUT", help="Filename of the output dmg archive")
+ create.add_argument('volume_name', metavar="VOLUME_NAME", help="Name of the dmg archive")
+ create.add_argument('directory', metavar="DIR", help="Directory to create the archive from")
+ create.add_argument('--symlink', metavar="SYMLINK", nargs=2, action="append", help="Symlink the first argument under the second name")
+ args = p.parse_args()
+
+ verbose = args.verbose or 0
+ symlinks = args.symlink or []
+ if args.dmgtools:
+ dmg, hfsplus, newfs_hfs = args.dmgtools
+ dmg = Dmgtools(ConfigDmgtools(dmg=dmg, hfsplus=hfsplus, newfs_hfs=newfs_hfs, verbose=verbose))
+ elif args.hdiutil:
+ dmg = Hdiutil(ConfigHdiutil(hdiutil=args.hdiutil, verbose=verbose))
+ else:
+ raise RuntimeError("unreachable")
+ dmg.create(volume_name=args.volume_name, directory=args.directory, dmg=args.output, symlinks=symlinks)
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/git_revision.py b/scripts/git_revision.py
new file mode 100644
index 000000000..ae1186c42
--- /dev/null
+++ b/scripts/git_revision.py
@@ -0,0 +1,21 @@
+import errno
+import subprocess
+try:
+ from subprocess import DEVNULL
+except ImportError:
+ import os
+ DEVNULL = open(os.devnull, 'wb')
+try:
+ FileNotFoundError
+except NameError:
+ FileNotFoundError = OSError
+try:
+ git_hash = subprocess.check_output(["git", "rev-parse", "--short=16", "HEAD"], stderr=DEVNULL).decode().strip()
+ definition = '"{}"'.format(git_hash)
+except FileNotFoundError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ definition = "0"
+except subprocess.CalledProcessError:
+ definition = "0";
+print("const char *GIT_SHORTREV_HASH = {};".format(definition))
diff --git a/src/base/system.c b/src/base/system.c
index bcab1771e..92e090622 100644
--- a/src/base/system.c
+++ b/src/base/system.c
@@ -334,6 +334,11 @@ unsigned io_read(IOHANDLE io, void *buffer, unsigned size)
return fread(buffer, 1, size, (FILE*)io);
}
+unsigned io_unread_byte(IOHANDLE io, unsigned char byte)
+{
+ return ungetc(byte, (FILE*)io) == EOF;
+}
+
unsigned io_skip(IOHANDLE io, int size)
{
fseek((FILE*)io, size, SEEK_CUR);
@@ -1439,6 +1444,10 @@ int fs_storage_path(const char *appname, char *path, int max)
return 0;
#else
char *home = getenv("HOME");
+ int i;
+ char *xdgdatahome = getenv("XDG_DATA_HOME");
+ char xdgpath[max];
+
if(!home)
return -1;
@@ -1447,10 +1456,6 @@ int fs_storage_path(const char *appname, char *path, int max)
return 0;
#endif
- int i;
- char *xdgdatahome = getenv("XDG_DATA_HOME");
- char xdgpath[max];
-
/* old folder location */
snprintf(path, max, "%s/.%s", home, appname);
for(i = strlen(home)+2; path[i]; i++)
diff --git a/src/base/system.h b/src/base/system.h
index 3f842279e..318b4f3d9 100644
--- a/src/base/system.h
+++ b/src/base/system.h
@@ -212,6 +212,21 @@ IOHANDLE io_open(const char *filename, int flags);
*/
unsigned io_read(IOHANDLE io, void *buffer, unsigned size);
+/*
+ Function: io_unread_byte
+ "Unreads" a single byte, making it available for future read
+ operations.
+
+ Parameters:
+ io - Handle to the file to unread the byte from.
+ byte - Byte to unread.
+
+ Returns:
+ Returns 0 on success and 1 on failure.
+
+*/
+unsigned io_unread_byte(IOHANDLE io, unsigned char byte);
+
/*
Function: io_skip
Skips data in a file.
diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp
index 1bf9ae531..81de48b0b 100644
--- a/src/engine/client/backend_sdl.cpp
+++ b/src/engine/client/backend_sdl.cpp
@@ -16,7 +16,7 @@
#if defined(CONF_FAMILY_WINDOWS)
PFNGLTEXIMAGE3DPROC glTexImage3DInternal;
- GLAPI void GLAPIENTRY glTexImage3D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+ void GLAPIENTRY 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);
}
diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp
index 7807fc8ab..abf00ad83 100644
--- a/src/engine/client/graphics_threaded.cpp
+++ b/src/engine/client/graphics_threaded.cpp
@@ -6,7 +6,8 @@
#include <base/tl/threading.h>
#include <base/system.h>
-#include <engine/external/pnglite/pnglite.h>
+
+#include <pnglite.h>
#include <engine/shared/config.h>
#include <engine/graphics.h>
diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp
index 6d7088f33..0c627640b 100644
--- a/src/engine/client/sound.cpp
+++ b/src/engine/client/sound.cpp
@@ -12,8 +12,9 @@
#include "sound.h"
-extern "C" { // wavpack
- #include <engine/external/wavpack/wavpack.h>
+extern "C"
+{
+ #include <wavpack.h>
}
#include <math.h>
@@ -68,6 +69,8 @@ static int m_NextVoice = 0;
static int *m_pMixBuffer = 0; // buffer only used by the thread callback function
static unsigned m_MaxFrames = 0;
+static IOHANDLE s_File;
+
// TODO: there should be a faster way todo this
static short Int2Short(int i)
{
@@ -325,11 +328,43 @@ void CSound::RateConvert(int SampleID)
pSample->m_NumFrames = NumFrames;
}
-int CSound::ReadData(void *pBuffer, int Size)
+static int ReadDataOld(void *pBuffer, int Size)
+{
+ return io_read(s_File, pBuffer, Size);
+}
+
+#if defined(CONF_WAVPACK_OPEN_FILE_INPUT_EX)
+static int ReadData(void *pId, void *pBuffer, int Size)
+{
+ (void)pId;
+ return ReadDataOld(pBuffer, Size);
+}
+
+static int ReturnFalse(void *pId)
+{
+ (void)pId;
+ return 0;
+}
+
+static unsigned int GetPos(void *pId)
+{
+ (void)pId;
+ return io_tell(s_File);
+}
+
+static unsigned int GetLength(void *pId)
{
- return io_read(ms_File, pBuffer, Size);
+ (void)pId;
+ return io_length(s_File);
}
+static int PushBackByte(void *pId, int Char)
+{
+ (void)pId;
+ return io_unread_byte(s_File, Char);
+}
+#endif
+
ISound::CSampleHandle CSound::LoadWV(const char *pFilename)
{
CSample *pSample;
@@ -349,8 +384,8 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename)
return CSampleHandle();
lock_wait(m_SoundLock);
- ms_File = m_pStorage->OpenFile(pFilename, IOFLAG_READ, IStorage::TYPE_ALL);
- if(!ms_File)
+ s_File = m_pStorage->OpenFile(pFilename, IOFLAG_READ, IStorage::TYPE_ALL);
+ if(!s_File)
{
dbg_msg("sound/wv", "failed to open file. filename='%s'", pFilename);
lock_unlock(m_SoundLock);
@@ -360,14 +395,24 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename)
SampleID = AllocID();
if(SampleID < 0)
{
- io_close(ms_File);
- ms_File = 0;
+ io_close(s_File);
+ s_File = 0;
lock_unlock(m_SoundLock);
return CSampleHandle();
}
pSample = &m_aSamples[SampleID];
- pContext = WavpackOpenFileInput(ReadData, aError);
+#if defined(CONF_WAVPACK_OPEN_FILE_INPUT_EX)
+ WavpackStreamReader Callback = {0};
+ Callback.can_seek = ReturnFalse;
+ Callback.get_length = GetLength;
+ Callback.get_pos = GetPos;
+ Callback.push_back_byte = PushBackByte;
+ Callback.read_bytes = ReadData;
+ pContext = WavpackOpenFileInputEx(&Callback, (void *)1, 0, aError, 0, 0);
+#else
+ pContext = WavpackOpenFileInput(ReadDataOld, aError);
+#endif
if (pContext)
{
int m_aSamples = WavpackGetNumSamples(pContext);
@@ -385,8 +430,8 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename)
if(pSample->m_Channels > 2)
{
dbg_msg("sound/wv", "file is not mono or stereo. filename='%s'", pFilename);
- io_close(ms_File);
- ms_File = 0;
+ io_close(s_File);
+ s_File = 0;
lock_unlock(m_SoundLock);
return CSampleHandle();
}
@@ -401,8 +446,8 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename)
if(BitsPerSample != 16)
{
dbg_msg("sound/wv", "bps is %d, not 16, filname='%s'", BitsPerSample, pFilename);
- io_close(ms_File);
- ms_File = 0;
+ io_close(s_File);
+ s_File = 0;
lock_unlock(m_SoundLock);
return CSampleHandle();
}
@@ -429,8 +474,8 @@ ISound::CSampleHandle CSound::LoadWV(const char *pFilename)
dbg_msg("sound/wv", "failed to open %s: %s", pFilename, aError);
}
- io_close(ms_File);
- ms_File = NULL;
+ io_close(s_File);
+ s_File = NULL;
if(g_Config.m_Debug)
dbg_msg("sound/wv", "loaded %s", pFilename);
@@ -560,7 +605,4 @@ bool CSound::IsPlaying(CSampleHandle SampleID)
return Ret;
}
-IOHANDLE CSound::ms_File = 0;
-
IEngineSound *CreateEngineSound() { return new CSound; }
-
diff --git a/src/engine/client/sound.h b/src/engine/client/sound.h
index ff357c047..cec2cdeda 100644
--- a/src/engine/client/sound.h
+++ b/src/engine/client/sound.h
@@ -21,10 +21,6 @@ public:
static void RateConvert(int SampleID);
- // TODO: Refactor: clean this mess up
- static IOHANDLE ms_File;
- static int ReadData(void *pBuffer, int Size);
-
virtual bool IsSoundEnabled() { return m_SoundEnabled != 0; }
virtual CSampleHandle LoadWV(const char *pFilename);
diff --git a/src/osxlaunch/server.mm b/src/osxlaunch/server.mm
new file mode 100644
index 000000000..5ad2d4eda
--- /dev/null
+++ b/src/osxlaunch/server.mm
@@ -0,0 +1,112 @@
+#import <Cocoa/Cocoa.h>
+
+@interface ServerView : NSTextView
+{
+ NSTask *task;
+ NSFileHandle *file;
+}
+- (void)listenTo: (NSTask*)t;
+@end
+
+@implementation ServerView
+- (void)listenTo: (NSTask*)t;
+{
+ NSPipe *pipe;
+ task = t;
+ pipe = [NSPipe pipe];
+ [task setStandardOutput: pipe];
+ file = [pipe fileHandleForReading];
+
+ [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(outputNotification:) name: NSFileHandleReadCompletionNotification object: file];
+
+ [file readInBackgroundAndNotify];
+}
+
+- (void) outputNotification: (NSNotification *) notification
+{
+ NSData *data = [[[notification userInfo] objectForKey: NSFileHandleNotificationDataItem] retain];
+ NSString *string = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
+ NSAttributedString *attrstr = [[NSAttributedString alloc] initWithString: string];
+
+ [[self textStorage] appendAttributedString: attrstr];
+ int length = [[self textStorage] length];
+ NSRange range = NSMakeRange(length, 0);
+ [self scrollRangeToVisible: range];
+
+ [attrstr release];
+ [string release];
+ [file readInBackgroundAndNotify];
+}
+
+-(void)windowWillClose:(NSNotification *)notification
+{
+ [task terminate];
+ [NSApp terminate:self];
+}
+@end
+
+void runServer()
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSApp = [NSApplication sharedApplication];
+ NSBundle* mainBundle = [NSBundle mainBundle];
+ NSTask *task;
+ task = [[NSTask alloc] init];
+ [task setCurrentDirectoryPath: [mainBundle resourcePath]];
+
+ // get a server config
+ NSOpenPanel* openDlg = [NSOpenPanel openPanel];
+ [openDlg setCanChooseFiles:YES];
+
+ if([openDlg runModalForDirectory:nil file:nil] != NSOKButton)
+ return;
+
+ NSArray* filenames = [openDlg filenames];
+ if([filenames count] != 1)
+ return;
+
+ NSString* filename = [filenames objectAtIndex: 0];
+ NSArray* arguments = [NSArray arrayWithObjects: @"-f", filename, nil];
+
+ // run server
+ NSWindow *window;
+ ServerView *view;
+ NSRect graphicsRect;
+
+ graphicsRect = NSMakeRect(100.0, 1000.0, 600.0, 400.0);
+
+ window = [[NSWindow alloc]
+ initWithContentRect: graphicsRect
+ styleMask: NSTitledWindowMask
+ | NSClosableWindowMask
+ | NSMiniaturizableWindowMask
+ backing: NSBackingStoreBuffered
+ defer: NO];
+
+ [window setTitle: @"Teeworlds Server"];
+
+ view = [[[ServerView alloc] initWithFrame: graphicsRect] autorelease];
+ [view setEditable: NO];
+ [view setRulerVisible: YES];
+
+ [window setContentView: view];
+ [window setDelegate: (id<NSWindowDelegate>)view];
+ [window makeKeyAndOrderFront: nil];
+
+ [view listenTo: task];
+ [task setLaunchPath: [mainBundle pathForAuxiliaryExecutable: @"teeworlds_srv"]];
+ [task setArguments: arguments];
+ [task launch];
+ [NSApp run];
+ [task terminate];
+
+ [NSApp release];
+ [pool release];
+}
+
+int main (int argc, char **argv)
+{
+ runServer();
+
+ return 0;
+}
--
2.20.1