diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 8c2988ca8f..9eca1cbd81 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -12,7 +12,7 @@ on: jobs: analyze: name: Analyze - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 strategy: fail-fast: false diff --git a/.github/workflows/gh-actions-pr.yml b/.github/workflows/gh-actions-pr.yml index f786ca3d31..3a0090966b 100644 --- a/.github/workflows/gh-actions-pr.yml +++ b/.github/workflows/gh-actions-pr.yml @@ -5,7 +5,7 @@ on: [ pull_request ] jobs: build: name: Build - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 continue-on-error: ${{ matrix.allow_failure }} defaults: @@ -36,91 +36,16 @@ jobs: OpenGL_GL_PREFERENCE: 'GLVND' ENABLE_PIE: 'OFF' allow_failure: true - - FROM: 'ubuntu:jammy' - COMPILER: 'gcc' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'OFF' - allow_failure: false - - FROM: 'ubuntu:jammy' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'OFF' - allow_failure: false - - FROM: 'ubuntu:focal' - COMPILER: 'gcc' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'OFF' - allow_failure: false - - FROM: 'ubuntu:focal' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'OFF' - allow_failure: false - FROM: 'linuxmintd/mint22-amd64' COMPILER: 'clang' OpenGL_GL_PREFERENCE: 'GLVND' ENABLE_PIE: 'OFF' allow_failure: true - - FROM: 'linuxmintd/mint21.3-amd64' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'OFF' - allow_failure: true - - FROM: 'linuxmintd/mint21.2-amd64' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'OFF' - allow_failure: true - - FROM: 'linuxmintd/mint21.1-amd64' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'OFF' - allow_failure: true - - FROM: 'linuxmintd/mint21-amd64' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'OFF' - allow_failure: false - - FROM: 'linuxmintd/mint20-amd64' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'OFF' - allow_failure: false - FROM: 'debian:bookworm' COMPILER: 'clang' OpenGL_GL_PREFERENCE: 'GLVND' ENABLE_PIE: 'OFF' allow_failure: false - - FROM: 'debian:bullseye' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'OFF' - allow_failure: false - - FROM: 'opensuse/leap:15.6' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'LEGACY' - ENABLE_PIE: 'ON' - allow_failure: true - - FROM: 'opensuse/leap:15.6' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'ON' - allow_failure: true - - FROM: 'opensuse/leap:15.5' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'LEGACY' - ENABLE_PIE: 'ON' - allow_failure: true - - FROM: 'opensuse/leap:15.5' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'ON' - allow_failure: true - - FROM: 'opensuse/leap:15.4' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'ON' - allow_failure: false - FROM: 'fedora:39' COMPILER: 'clang' OpenGL_GL_PREFERENCE: 'LEGACY' @@ -141,11 +66,13 @@ jobs: OpenGL_GL_PREFERENCE: 'GLVND' ENABLE_PIE: 'ON' allow_failure: false - - FROM: 'rockylinux_rockylinux:9.4' - COMPILER: 'clang' - OpenGL_GL_PREFERENCE: 'GLVND' - ENABLE_PIE: 'ON' - allow_failure: false + # Removing rockylinux due to https://github.com/boostorg/mpl/issues/69 + # TODO: add newer rocklinux (9.5?) when it comes out + # - FROM: 'rockylinux_rockylinux:9.4' + # COMPILER: 'clang' + # OpenGL_GL_PREFERENCE: 'GLVND' + # ENABLE_PIE: 'ON' + # allow_failure: false # Disabled until the build can be fixed #- FROM: 'rockylinux_rockylinux:8.10' # COMPILER: 'clang' @@ -193,6 +120,9 @@ jobs: run: | echo "${SHORT_SHA}" + - name: Execute bootstrap + run: sudo script/bootstrap + - name: Build and Test env: FROM: ${{ matrix.FROM }} diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 910df8b761..cab8e082b4 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -117,6 +117,10 @@ SET(VEGASTRIKE_ASSETS_API_VERSION "3") # CMAKE_POLICY (SET CMP0091 NEW) #ENDIF () +# TODO: this suppresses warnings about CMP0102 caching. +# We should do something about it instead. +CMAKE_POLICY(SET CMP0102 OLD) + PROJECT(Vega_Strike VERSION "${VEGASTRIKE_VERSION_MAJOR}.${VEGASTRIKE_VERSION_MINOR}.${VEGASTRIKE_VERSION_PATCH}" #.${VEGASTRIKE_VERSION_TWEAK} # CMake only allows numeric version components, unfortunately. @@ -384,85 +388,17 @@ ELSE (Python3_FOUND) ENDIF (Python3_FOUND) # Find Boost with boost_python library -OPTION(USE_SYSTEM_BOOST "Use system boost" ON) -IF (USE_SYSTEM_BOOST) - MESSAGE("++ Using System Boost") - FIND_PACKAGE(Boost) - IF (Boost_FOUND) - - # VERSION_EQUAL / VERSION_GREATER requires a version in the form X.Y.Z - # Until CMake v3.15, Boost_VERSION is in the form as written in boost/version.hpp (e.g. 106700) - # Thus, build the version from parts, which should work across all supported CMake versions - SET(Boost_DERIVED_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - MESSAGE("++ Found System Boost version : ${Boost_DERIVED_VERSION}") - - # With boost version 1.67 and above, python components are specified with a version suffix - # (`python27`, `python38`) instead of their invocation name (`python`, `python3`) - IF (Boost_DERIVED_VERSION VERSION_EQUAL 1.67.0) - SET(Boost_1_67_Or_Later_Result TRUE) - ELSEIF (Boost_DERIVED_VERSION VERSION_GREATER 1.67.0) - SET(Boost_1_67_Or_Later_Result TRUE) - ELSE (Boost_DERIVED_VERSION VERSION_EQUAL 1.67.0) - SET(Boost_1_67_Or_Later_Result FALSE) - ENDIF (Boost_DERIVED_VERSION VERSION_EQUAL 1.67.0) - MESSAGE("-- Boost_1_67_Or_Later_Result: ${Boost_1_67_Or_Later_Result}") - IF (Boost_1_67_Or_Later_Result) - SET(BOOST_PYTHON_COMPONENT "python${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR}") - ELSE (Boost_1_67_Or_Later_Result) - SET(BOOST_PYTHON_COMPONENT "python3") - - # Debian and Debian-based systems up to Boost 1.67 lack libboost_python3.{so|a} - # but have libboost_python-py{major}{minor}.{so|a}. E.g., Ubuntu xenial and - # Debian stretch. - IF (CMAKE_SYSTEM_NAME STREQUAL Linux) - IF (LINUX_CODENAME STREQUAL xenial OR LINUX_CODENAME STREQUAL stretch) - SET(BOOST_PYTHON_COMPONENT "python-py3${Python3_VERSION_MINOR}") - ENDIF (LINUX_CODENAME STREQUAL xenial OR LINUX_CODENAME STREQUAL stretch) - ENDIF (CMAKE_SYSTEM_NAME STREQUAL Linux) - ENDIF (Boost_1_67_Or_Later_Result) - UNSET(Boost_1_67_Or_Later_Result) - - UNSET(Boost_${BOOST_PYTHON_COMPONENT}_FOUND) - MESSAGE("++ Looking for System Boost::python") - FIND_PACKAGE(Boost COMPONENTS ${BOOST_PYTHON_COMPONENT} log log_setup date_time system filesystem thread chrono atomic REQUIRED) - IF (Boost_python3_FOUND) - MESSAGE("++ Found System Boost::python3 : ${Boost_PYTHON3_LIBRARY}") - ELSEIF (Boost_${BOOST_PYTHON_COMPONENT}_FOUND) - MESSAGE("++ Found System Boost::python") - ENDIF (Boost_python3_FOUND) - - SET(BOOST_PYTHON_NO_PY_SIGNATURES 1) - SET(TST_INCLUDES ${TST_INCLUDES} ${Python3_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) - MESSAGE("** Boost_LIBRARIES: ${Boost_LIBRARIES}") - SET(TST_LIBS ${TST_LIBS} ${Boost_LIBRARIES}) - INCLUDE_DIRECTORIES(${TST_INCLUDES}) - ELSE (Boost_FOUND) - SET(USE_SYSTEM_BOOST OFF) - ENDIF (Boost_FOUND) -ENDIF (USE_SYSTEM_BOOST) - -IF (NOT USE_SYSTEM_BOOST) - MESSAGE("++ Using Internal Boost") - # This is just to cleanup advanced variable viewing, since they're not used anyway - UNSET(Boost_INCLUDE_DIRS) - UNSET(Boost_LIBRARIES) - UNSET(Boost_INCLUDE_DIR) - UNSET(Boost_LIBRARY_DIRS) - SET(Boost_DIR ../ext/) - SET(BOOST_PYTHON_NO_PY_SIGNATURES 1) - SET(TST_INCLUDES ${TST_INCLUDES} ${Vega_Strike_SOURCE_DIR}/${Boost_DIR}) - MESSAGE("++ Using Internal Boost::python3") - SET(TST_LIBS ${TST_LIBS} boost_python3) - INCLUDE_DIRECTORIES(${TST_INCLUDES}) - ADD_SUBDIRECTORY(${Boost_DIR} build) - MESSAGE("++ boost dir: ${Boost_DIR}") - #IF (NOT DISABLE_CLIENT) - # ADD_DEPENDENCIES(vegastrike-engine boost_python) - #ENDIF (NOT DISABLE_CLIENT) - #IF (NOT DISABLE_SERVER) - # ADD_DEPENDENCIES(vegaserver boost_python) - #ENDIF (NOT DISABLE_SERVER) -ENDIF (NOT USE_SYSTEM_BOOST) +# Note: we now use Cmake 3.16 and Boost 1.75. +MESSAGE("++ From now on, always using System Boost (ver. 1.75 or higher)") +SET(BOOST_PYTHON_COMPONENT "python${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR}") +FIND_PACKAGE(Boost COMPONENTS ${BOOST_PYTHON_COMPONENT} json log log_setup date_time system filesystem thread chrono atomic REQUIRED) +MESSAGE("++ Found System Boost version ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") +SET(BOOST_PYTHON_NO_PY_SIGNATURES 1) + +SET(TST_INCLUDES ${TST_INCLUDES} ${Python3_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) +MESSAGE("** Boost_LIBRARIES: ${Boost_LIBRARIES}") +SET(TST_LIBS ${TST_LIBS} ${Boost_LIBRARIES}) +INCLUDE_DIRECTORIES(${TST_INCLUDES}) IF (NOT DISABLE_CLIENT) ########## @@ -717,8 +653,8 @@ SET(LIBRESOURCE src/resource/product.cpp src/resource/cargo.cpp src/resource/manifest.cpp + src/resource/json_utils.cpp src/resource/random_utils.cpp - src/cmd/json.cpp ) SET(LIBPYTHON @@ -1487,7 +1423,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl-gfx1.2-5, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl-gfx1.2-5, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}, libboost-json${BOOST_VER}") ELSEIF (DEBIAN_RELEASE_VERSION STREQUAL "bullseye") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.9") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1495,7 +1431,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx1.2-5, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx1.2-5, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}, libboost-json${BOOST_VER}") ELSEIF (DEBIAN_RELEASE_VERSION STREQUAL "buster") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.7") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1503,7 +1439,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}, libboost-json${BOOST_VER}") ELSEIF (DEBIAN_RELEASE_VERSION STREQUAL "stretch") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.5") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1511,7 +1447,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}, libboost-json${BOOST_VER}") ELSE () MESSAGE(SEND_WARNING "!! Unsupported Debian version.") ENDIF () @@ -1525,7 +1461,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, ${VEGA_STRIKE_GLU_DEPENDENCY}, libopengl0, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, ${VEGA_STRIKE_GLU_DEPENDENCY}, libopengl0, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER} libboost-json${BOOST_VER}") ELSEIF (LSB_LINUX_DISTRIBUTION_CODENAME STREQUAL "focal") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.8") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1533,7 +1469,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER} libboost-json${BOOST_VER}") ELSEIF (LSB_LINUX_DISTRIBUTION_CODENAME STREQUAL "bookworm") # Apparently some versions of Debian have lsb_release after all SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.11") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1541,7 +1477,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}, libboost-json${BOOST_VER}") ELSEIF (LSB_LINUX_DISTRIBUTION_CODENAME STREQUAL "bullseye") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.9") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1549,7 +1485,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl-gfx1.2-5, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl-gfx1.2-5, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER} libboost-json${BOOST_VER}") ELSEIF (LSB_LINUX_DISTRIBUTION_CODENAME STREQUAL "buster") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.7") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1557,7 +1493,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER} libboost-json${BOOST_VER}") ELSEIF (DEBIAN_RELEASE_VERSION STREQUAL "stretch") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.5") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1565,7 +1501,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}, libboost-json${BOOST_VER}") ELSEIF (LSB_LINUX_DISTRIBUTION_CODENAME STREQUAL "groovy") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.9") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1573,7 +1509,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}, libboost-json${BOOST_VER}") ELSEIF (LSB_LINUX_DISTRIBUTION_CODENAME STREQUAL "hirsute") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.9") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1581,7 +1517,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}, libboost-json${BOOST_VER}") ELSEIF (LSB_LINUX_DISTRIBUTION_CODENAME STREQUAL "ulyana") # Linux Mint 20 codename "ulyana" SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.8") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1589,7 +1525,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}, libboost-json${BOOST_VER}") ELSEIF (LSB_LINUX_DISTRIBUTION_CODENAME STREQUAL "vanessa") # Linux Mint 20 codename "vanessa" SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.10") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1597,7 +1533,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}, libboost-json${BOOST_VER}") ELSEIF (LSB_LINUX_DISTRIBUTION_CODENAME STREQUAL "impish") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.10") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1605,7 +1541,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}, libboost-json${BOOST_VER}") ELSEIF (LSB_LINUX_DISTRIBUTION_CODENAME STREQUAL "jammy") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libpython3.10") IF (Boost_DERIVED_VERSION STREQUAL "") @@ -1613,7 +1549,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) ELSE (Boost_DERIVED_VERSION STREQUAL "") SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libjpeg62-turbo, libpng16-16, freeglut3, libgtk-3-0, libvorbis0a, libopenal1, libsdl2-gfx2.0.14, xdg-utils, libgl1, libopengl0, ${VEGA_STRIKE_GLU_DEPENDENCY}, libboost-atomic${BOOST_VER}, libboost-chrono${BOOST_VER}, libboost-date-time${BOOST_VER}, libboost-filesystem${BOOST_VER}, libboost-log${BOOST_VER}, libboost-python${BOOST_VER}, libboost-regex${BOOST_VER}, libboost-system${BOOST_VER}, libboost-thread${BOOST_VER}, libboost-json${BOOST_VER}") ELSE () MESSAGE(SEND_WARNING "!! Unsupported Debian derivative.") ENDIF () @@ -1664,7 +1600,7 @@ ELSEIF (CMAKE_SYSTEM_NAME STREQUAL Linux) SET(BOOST_VER "${Boost_DERIVED_VERSION}") ENDIF (Boost_DERIVED_VERSION STREQUAL "") SET(CPACK_RPM_PACKAGE_REQUIRES "libboost_python-py3-${BOOST_VER}, libpython3_10-1_0") - SET(CPACK_RPM_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES}, libjpeg-turbo, libpng16-16, libglut3, libgtk-3-0, libvorbis0, libopenal0, libSDL-1_2-0, libglvnd, expat, libboost_log${BOOST_VER}, libboost_system${BOOST_VER}, libboost_filesystem${BOOST_VER}, libboost_thread${BOOST_VER}, libboost_regex${BOOST_VER}, libboost_chrono${BOOST_VER}, libboost_atomic${BOOST_VER}") + SET(CPACK_RPM_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES}, libjpeg-turbo, libpng16-16, libglut3, libgtk-3-0, libvorbis0, libopenal0, libSDL-1_2-0, libglvnd, expat, libboost_log${BOOST_VER}, libboost_system${BOOST_VER}, libboost_filesystem${BOOST_VER}, libboost_thread${BOOST_VER}, libboost_regex${BOOST_VER}, libboost_chrono${BOOST_VER}, libboost_atomic${BOOST_VER}, libboost_json${BOOST_VER}") ELSE (LINUX_VERSION_ID VERSION_EQUAL 15.2 OR LINUX_VERSION_ID VERSION_EQUAL 15.3) MESSAGE (SEND_WARNING "!! Unsupported version of openSUSE") SET(CPACK_RPM_PACKAGE_REQUIRES "") @@ -1790,6 +1726,7 @@ IF (USE_GTEST) vegastrike-testing Boost::log Boost::log_setup + Boost::json ) TARGET_COMPILE_DEFINITIONS(${TEST_NAME} PUBLIC "BOOST_ALL_DYN_LINK" "$<$:BOOST_DEBUG_PYTHON>") IF (WIN32) diff --git a/engine/src/cmd/carrier.cpp b/engine/src/cmd/carrier.cpp index 540cd3d29a..7e6112a651 100644 --- a/engine/src/cmd/carrier.cpp +++ b/engine/src/cmd/carrier.cpp @@ -36,27 +36,13 @@ #include "vs_logging.h" #include "vega_cast_utils.h" -#include "json.h" // TODO: find out where this is and maybe refactor extern int SelectDockPort(Unit *, Unit *parent); extern void SwitchUnits(Unit *, Unit *); extern void abletodock(int dock); -// Replace with std:sto* here and at unit_csv.cpp -static double stof(const string &inp, double def = 0) { - if (inp.length() != 0) { - return XMLSupport::parse_float(inp); - } - return def; -} -static int stoi(const string &inp, int def = 0) { - if (inp.length() != 0) { - return XMLSupport::parse_int(inp); - } - return def; -} // TODO: probably replace with a lambda expression class CatCompare { diff --git a/engine/src/cmd/controls_factory.cpp b/engine/src/cmd/controls_factory.cpp index 00bde31447..a5252293ff 100644 --- a/engine/src/cmd/controls_factory.cpp +++ b/engine/src/cmd/controls_factory.cpp @@ -31,11 +31,12 @@ #include #include #include +#include -#include "json.h" #include "drawable.h" #include "vs_globals.h" #include "configxml.h" +#include "resource/json_utils.h" #include "gui/staticdisplay.h" #include "gui/newbutton.h" @@ -55,24 +56,34 @@ std::map> parseControlsJSON(VSFi std::map> controls_map; - std::vector controls_json = json::parsing::parse_array(json_text.c_str()); - - // Iterate over root - for (const std::string &control_text : controls_json) { - json::jobject control_json = json::jobject::parse(control_text); + boost::json::value json_value = boost::json::parse(json_text); + boost::json::array root_array = json_value.get_array(); + + for(boost::json::value& control_value : root_array) { + boost::json::object control = control_value.get_object(); std::map control_attributes; for (const std::string &key : keys) { - // For some reason, parser adds quotes - if(control_json.has_key(key)) { - const std::string attribute = control_json.get(key); - const std::string stripped_attribute = attribute.substr(1, attribute.size() - 2); - control_attributes[key] = stripped_attribute; - } - } + if(!control.if_contains(key)) { + continue; + } + // Worked in singleson because it saw everything as string. + if(key == "multiline") { + bool multiline = JsonGetWithDefault(control, key, false); + if(multiline) { + control_attributes["multiline"] = "true"; + } else { + control_attributes["multiline"] = "false"; + } + } else { + const std::string attribute = JsonGetStringWithDefault(control, key, ""); + control_attributes[key] = attribute; + } + } + controls_map[control_attributes["name"]] = control_attributes; - } + } return controls_map; } diff --git a/engine/src/cmd/json.cpp b/engine/src/cmd/json.cpp deleted file mode 100644 index cb576a1d68..0000000000 --- a/engine/src/cmd/json.cpp +++ /dev/null @@ -1,617 +0,0 @@ -/*! \file json.cpp - * \brief Simpleson source file - */ - -#include "json.h" -#include - -#include "vs_logging.h" - -/*! \brief Checks for an empty string - * - * @param str The string to check - * @return True if the string is empty, false if the string is not empty - * @warning The string must be null-terminated for this macro to work - */ -#define EMPTY_STRING(str) (*str == '\0') - -/*! \brief Moves a pointer to the first character that is not white space - * - * @param str The pointer to move - */ -#define SKIP_WHITE_SPACE(str) { const char *next = json::parsing::tlws(str); str = next; } - -/*! \brief Determines if the end character of serialized JSON is encountered - * - * @param obj The JSON object or array that is being written to - * @param index The pointer to the character to be checked - */ -#define END_CHARACTER_ENCOUNTERED(obj, index) (obj.is_array() ? *index == ']' : *index == '}') - -/*! \brief Format used for integer to string conversion */ -const char * INT_FORMAT = "%i"; - -/*! \brief Format used for unsigned integer to string conversion */ -const char * UINT_FORMAT = "%u"; - -/*! \brief Format used for long integer to string conversion */ -const char * LONG_FORMAT = "%li"; - -/*! \brief Format used for unsigned long integer to string conversion */ -const char * ULONG_FORMAT = "%lu"; - -/*! \brief Format used for character to string conversion */ -const char * CHAR_FORMAT = "%c"; - -/*! \brief Format used for floating-point number to string conversion */ -const char * FLOAT_FORMAT = "%f"; - -/*! \brief Format used for double floating-opint number to string conversion */ -const char * DOUBLE_FORMAT = "%lf"; - -const char* json::parsing::tlws(const char *input) -{ - const char *output = input; - while(!EMPTY_STRING(output) && std::isspace(*output)) output++; - return output; -} - -json::jtype::jtype json::jtype::detect(const char *input) -{ - const char *start = json::parsing::tlws(input); - if (EMPTY_STRING(start)) return json::jtype::not_valid; - switch (*start) - { - case '[': - return json::jtype::jarray; - break; - case '"': - return json::jtype::jstring; - break; - case '{': - return json::jtype::jobject; - break; - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return json::jtype::jnumber; - case 't': - case 'f': - return (strncmp(start, "true", 4) == 0 || strncmp(start, "false", 5) == 0) ? json::jtype::jbool : json::jtype::not_valid; - break; - case 'n': - return (strncmp(start, "null", 4) == 0) ? json::jtype::jnull : json::jtype::not_valid; - break; - default: - return json::jtype::not_valid; - break; - } -} - -std::string json::parsing::read_digits(const char *input) -{ - // Trim leading white space - const char *index = json::parsing::tlws(input); - - // Initialize the result - std::string result; - - // Loop until all digits are read - while ( - !EMPTY_STRING(index) && - ( - *index == '0' || - *index == '1' || - *index == '2' || - *index == '3' || - *index == '4' || - *index == '5' || - *index == '6' || - *index == '7' || - *index == '8' || - *index == '9' - ) - ) - { - result += *index; - index++; - } - - // Return the result - return result; -} - -std::string json::parsing::escape_quotes(const char *input) -{ - std::string parsed; - const size_t len = strlen(input); - for (size_t i = 0; i < len; i++) - { - if (input[i] == '\"' && parsed[parsed.size() - 1] != '\\') - { - parsed += '\\'; - } - parsed += input[i]; - } - return parsed; -} - -std::string json::parsing::unescape_quotes(const char *input) -{ - std::string result; - const char *index = input; - while (!EMPTY_STRING(index)) - { - if (strlen(index) > 1 && *index == '\\' && index[1] == '\"') - { - result += '\"'; - index += 2; - } - else - { - result.push_back(*index); - index++; - } - } - return result; -} - -json::parsing::parse_results json::parsing::parse(const char *input) -{ - // Strip white space - const char *index = json::parsing::tlws(input); - - // Validate input - if (EMPTY_STRING(index)) throw json::parsing_error("Input was only whitespace"); - - // Initialize the output - json::parsing::parse_results result; - - // Detect the type - result.type = json::jtype::detect(index); - - // Parse the values - switch (result.type) - { - case json::jtype::jstring: - // Validate the input - if (*index != '"') throw json::parsing_error("Expected '\"' as first character"); - - // Remove the opening quote - index++; - - // Copy the string - while (!EMPTY_STRING(index)) - { - if (*index != '"' || (result.value.size() > 0 && result.value[result.value.size() - 1] == '\\')) - { - result.value.push_back(*index); - index++; - } - else - { - break; - } - } - if (EMPTY_STRING(index) || *index != '"') result.type = json::jtype::not_valid; - else index++; - break; - case json::jtype::jnumber: - { - const char error[] = "Input did not contain a valid number"; - - if (*index == '-') - { - result.value.push_back('-'); - index++; - } - - if (EMPTY_STRING(index)) throw json::parsing_error(error); - - // Read the whole digits - std::string whole_digits = json::parsing::read_digits(index); - - // Validate the read - if (whole_digits.length() == 0) throw json::parsing_error(error); - - // Tack on the value - result.value += whole_digits; - index += whole_digits.length(); - - // Check for decimal number - if (*index == '.') - { - result.value.push_back('.'); - index++; - std::string decimal_digits = json::parsing::read_digits(index); - - if (decimal_digits.length() == 0) throw json::parsing_error(error); - - result.value += decimal_digits; - index += decimal_digits.size(); - } - - // Check for exponential number - if (*index == 'e' || *index == 'E') - { - result.value.push_back(*index); - index++; - - if (EMPTY_STRING(index)) throw json::parsing_error(error); - - if (*index == '+' || *index == '-') - { - result.value.push_back(*index); - index++; - } - - if (EMPTY_STRING(index)) throw json::parsing_error(error); - - std::string exponential_digits = json::parsing::read_digits(index); - - if (exponential_digits.size() == 0) throw json::parsing_error(error); - - result.value += exponential_digits; - index += exponential_digits.size(); - } - break; - } - case json::jtype::jobject: - { - const char error[] = "Input did not contain a valid object"; - - // The first character should be an open bracket - if (*index != '{') throw json::parsing_error(error); - result.value += '{'; - index++; - SKIP_WHITE_SPACE(index); - - // Loop until the closing bracket is encountered - while (!EMPTY_STRING(index) && *index != '}') - { - // Read the key - json::parsing::parse_results key = json::parsing::parse(index); - - // Validate that the key is a string - if (key.type != json::jtype::jstring) throw json::parsing_error(error); - - // Store the key - result.value += "\"" + json::parsing::escape_quotes(key.value.c_str()) + "\""; - index = json::parsing::tlws(key.remainder); - - // Look for the colon - if (*index != ':') throw json::parsing_error(error); - result.value.push_back(':'); - index++; - - // Get the value - json::parsing::parse_results subvalue = json::parsing::parse(index); - - // Validate the value type - if (subvalue.type == json::jtype::not_valid) throw json::parsing_error(error); - - // Store the value - if (subvalue.type == json::jtype::jstring) result.value += "\"" + json::parsing::escape_quotes(subvalue.value.c_str()) + "\""; - else result.value += subvalue.value; - index = json::parsing::tlws(subvalue.remainder); - - // Validate format - if (*index != ',' && *index != '}') throw json::parsing_error(error); - - // Check for next line - if (*index == ',') - { - result.value.push_back(','); - index++; - } - } - if (*index != '}') throw json::parsing_error(error); - result.value += '}'; - index++; - break; - } - case json::jtype::jarray: - { - const char error[] = "Input did not contain a valid array"; - if (*index != '[') throw json::parsing_error(error); - result.value += '['; - index++; - SKIP_WHITE_SPACE(index); - if (EMPTY_STRING(index)) throw json::parsing_error(error); - while (!EMPTY_STRING(index) && *index != ']') - { - json::parsing::parse_results array_value = json::parsing::parse(index); - if (array_value.type == json::jtype::not_valid) throw json::parsing_error(error); - if (array_value.type == json::jtype::jstring) result.value += "\"" + json::parsing::escape_quotes(array_value.value.c_str()) + "\""; - else result.value += array_value.value; - index = json::parsing::tlws(array_value.remainder); - if (*index != ',' && *index != ']') throw json::parsing_error(error); - if (*index == ',') - { - result.value.push_back(','); - index++; - } - } - if (*index != ']') throw json::parsing_error(error); - result.value.push_back(']'); - index++; - break; - } - case json::jtype::jbool: - { - if (strncmp(index, "true", 4) == 0) - { - result.value += "true"; - index += 4; - } - else if (strncmp(index, "false", 4) == 0) - { - result.value += "false"; - index += 5; - } - else - { - throw json::parsing_error("Input did not contain a valid boolean"); - } - break; - } - case json::jtype::jnull: - { - if (strncmp(index, "null", 4) == 0) - { - result.value += "null"; - index+= 4; - } - else - { - throw json::parsing_error("Input did not contain a valid null"); - } - break; - } - default: - throw json::parsing_error("Input did not contain valid json"); - break; - } - - result.remainder = index; - return result; -} - -std::vector json::parsing::parse_array(const char *input) -{ - // Initalize the result - std::vector result; - - if (input != nullptr) { - VS_LOG_AND_FLUSH(debug, boost::format("JSON Data: %s") % input); - } else { - VS_LOG_AND_FLUSH(debug, "Invalid JSON Input - NULL Pointer"); - } - - const char *index = json::parsing::tlws(input); - if (*index != '[') throw json::parsing_error("Input was not an array"); - index++; - SKIP_WHITE_SPACE(index); - if (*index == ']') - { - return result; - } - const char error[] = "Input was not properly formated"; - while (!EMPTY_STRING(index)) - { - SKIP_WHITE_SPACE(index); - json::parsing::parse_results parse_results = json::parsing::parse(index); - if (parse_results.type == json::jtype::not_valid) throw json::parsing_error(error); - result.push_back(parse_results.value); - index = json::parsing::tlws(parse_results.remainder); - if (*index == ']') break; - if (*index == ',') index++; - } - if (*index != ']') throw json::parsing_error(error); - index++; - return result; -} - -json::jobject::entry::operator int() const { return this->get_number(INT_FORMAT); } -json::jobject::entry::operator unsigned int() const { return this->get_number(UINT_FORMAT); } -json::jobject::entry::operator long() const { return this->get_number(LONG_FORMAT); } -json::jobject::entry::operator unsigned long() const { return this->get_number(ULONG_FORMAT); } -json::jobject::entry::operator char() const { return this->get_number(CHAR_FORMAT); } -json::jobject::entry::operator float() const { return this->get_number(FLOAT_FORMAT); } -json::jobject::entry::operator double() const { return this->get_number(DOUBLE_FORMAT); } - -json::jobject::entry::operator std::vector() const { return this->get_number_array(INT_FORMAT); } -json::jobject::entry::operator std::vector() const { return this->get_number_array(UINT_FORMAT); } -json::jobject::entry::operator std::vector() const { return this->get_number_array(LONG_FORMAT); } -json::jobject::entry::operator std::vector() const { return this->get_number_array(ULONG_FORMAT); } -json::jobject::entry::operator std::vector() const { return this->get_number_array(CHAR_FORMAT); } -json::jobject::entry::operator std::vector() const { return this->get_number_array(FLOAT_FORMAT); } -json::jobject::entry::operator std::vector() const { return this->get_number_array(DOUBLE_FORMAT); } - -void json::jobject::proxy::set_array(const std::vector &values, const bool wrap) -{ - std::string value = "["; - for (size_t i = 0; i < values.size(); i++) - { - if (wrap) value += "\"" + json::parsing::escape_quotes(values[i].c_str()) + "\","; - else value += values[i] + ","; - } - if(values.size() > 0) value.erase(value.size() - 1, 1); - value += "]"; - this->sink.set(key, value); -} - -json::jobject json::jobject::parse(const char *input) -{ - const char error[] = "Input is not a valid object"; - const char *index = json::parsing::tlws(input); - json::jobject result; - switch (*index) - { - case '{': - // Result is already an object - break; - case '[': - result = json::jobject(true); - break; - default: - throw json::parsing_error(error); - break; - } - index++; - SKIP_WHITE_SPACE(index); - if (EMPTY_STRING(index)) throw json::parsing_error(error); - - while (!EMPTY_STRING(index) && !END_CHARACTER_ENCOUNTERED(result, index)) - { - // Get key - kvp entry; - - if(!result.is_array()) { - json::parsing::parse_results key = json::parsing::parse(index); - if (key.type != json::jtype::jstring || key.value == "") throw json::parsing_error(error); - entry.first = key.value; - index = key.remainder; - - // Get value - SKIP_WHITE_SPACE(index); - if (*index != ':') throw json::parsing_error(error); - index++; - } - - SKIP_WHITE_SPACE(index); - json::parsing::parse_results value = json::parsing::parse(index); - if (value.type == json::jtype::not_valid) throw json::parsing_error(error); - if (value.type == json::jtype::jstring) entry.second = "\"" + value.value + "\""; - else entry.second = value.value; - index = value.remainder; - - // Clean up - SKIP_WHITE_SPACE(index); - if (*index != ',' && !END_CHARACTER_ENCOUNTERED(result, index)) throw json::parsing_error(error); - if (*index == ',') index++; - result += entry; - - } - if (EMPTY_STRING(index) || !END_CHARACTER_ENCOUNTERED(result, index)) throw json::parsing_error(error); - index++; - return result; -} - -void json::jobject::set(const std::string &key, const std::string &value) -{ - if(this->array_flag) throw json::invalid_key(key); - for (size_t i = 0; i < this->size(); i++) - { - if (this->data.at(i).first == key) - { - this->data.at(i).second = value; - return; - } - } - kvp entry; - entry.first = key; - entry.second = value; - this->data.push_back(entry); -} - -void json::jobject::remove(const std::string &key) -{ - for (size_t i = 0; i < this->size(); i++) - { - if (this->data.at(i).first == key) - { - this->remove(i); - } - } -} - -json::jobject::operator std::string() const -{ - if (is_array()) { - if (this->size() == 0) return "[]"; - std::string result = "["; - for (size_t i = 0; i < this->size(); i++) - { - result += this->data.at(i).second + ","; - } - result.erase(result.size() - 1, 1); - result += "]"; - return result; - } else { - if (this->size() == 0) return "{}"; - std::string result = "{"; - for (size_t i = 0; i < this->size(); i++) - { - result += "\"" + this->data.at(i).first + "\":" + this->data.at(i).second + ","; - } - result.erase(result.size() - 1, 1); - result += "}"; - return result; - } -} - -std::string json::jobject::pretty(unsigned int indent_level) const -{ - std::string result = ""; - for(unsigned int i = 0; i < indent_level; i++) result += "\t"; - if (is_array()) { - if(this->size() == 0) { - result += "[]"; - return result; - } - result += "[\n"; - for (size_t i = 0; i < this->size(); i++) - { - switch(json::jtype::detect(this->data.at(i).second.c_str())) { - case json::jtype::jarray: - case json::jtype::jobject: - result += json::jobject::parse(this->data.at(i).second).pretty(indent_level + 1); - break; - default: - for(unsigned int j = 0; j < indent_level + 1; j++) result += "\t"; - result += this->data.at(i).second; - break; - } - - result += ",\n"; - } - result.erase(result.size() - 2, 1); - for(unsigned int i = 0; i < indent_level; i++) result += "\t"; - result += "]"; - } else { - if(this->size() == 0) { - result += "{}"; - return result; - } - result += "{\n"; - for (size_t i = 0; i < this->size(); i++) - { - for(unsigned int j = 0; j < indent_level + 1; j++) result += "\t"; - result += "\"" + this->data.at(i).first + "\": "; - switch(json::jtype::detect(this->data.at(i).second.c_str())) { - case json::jtype::jarray: - case json::jtype::jobject: - result += std::string(json::parsing::tlws(json::jobject::parse(this->data.at(i).second).pretty(indent_level + 1).c_str())); - break; - default: - result += this->data.at(i).second; - break; - } - - result += ",\n"; - } - result.erase(result.size() - 2, 1); - for(unsigned int i = 0; i < indent_level; i++) result += "\t"; - result += "}"; - } - return result; -} diff --git a/engine/src/cmd/json.h b/engine/src/cmd/json.h deleted file mode 100644 index d4bb2648ac..0000000000 --- a/engine/src/cmd/json.h +++ /dev/null @@ -1,850 +0,0 @@ -#ifndef VEGA_STRIKE_ENGINE_CMD_JSON_H -#define VEGA_STRIKE_ENGINE_CMD_JSON_H - -/*! \file json.h - * \brief Simpleson header file - */ - -#include -#include -#include -#include -#include -#include -#include - -/*! \brief Base namespace for simpleson */ -namespace json -{ - /*! \brief Exception used for invalid JSON keys */ - class invalid_key : public std::exception - { - public: - /*! \brief The key used that was invalid */ - const std::string key; - - /*! \brief Constructor - * - * @param key The key that was not valid - */ - inline invalid_key(const std::string &key) : key(key) { } - - /*! \brief Destructor */ - inline virtual ~invalid_key() throw() { } - - /*! \brief Returns the invalid key */ - virtual const char* what() const throw() - { - return key.c_str(); - } - }; - - /*! \brief Exception used when invalid JSON is encountered */ - class parsing_error : public std::invalid_argument - { - public: - /*! \brief Constructor - * - * @param message Details regarding the parsing error - */ - inline parsing_error(const char *message) : std::invalid_argument(message) { } - - /*! \brief Destructor */ - inline virtual ~parsing_error() throw() { } - }; - - /* \brief Namespace for handling of JSON data types */ - namespace jtype - { - /*! \brief Descriptor for the type of JSON data */ - enum jtype { - jstring, ///< String value - jnumber, ///< Number value - jobject, ///< JSON object - jarray, ///< JSON array - jbool, ///< Boolean value - jnull, ///< Null value - not_valid ///< Value does not conform to JSON standard - }; - - /*! \brief Geven a string, determines the type of value the string contains - * - * @param input The string to be tested - * @return The type of JSON value encountered - * - * \note The function will only determine the type of the first value encountered in the string. - */ - jtype detect(const char *input); - } - - /*! \brief Namespace used for JSON parsing functions */ - namespace parsing - { - /*! \brief (t)rims (l)eading (w)hite (s)pace - * - * \details Given a string, returns a pointer to the first character that is not white space. Spaces, tabs, and carriage returns are all considered white space. - * @param start The string to examine - * @return A pointer within the input string that points at the first charactor that is not white space - * \note If the string consists of entirely white space, then the null terminator is returned - * \warning The behavior of this function with string that is not null-terminated is undefined - */ - const char* tlws(const char *start); - - /*! \brief Reads a set of digits from a string - * - * \details This function will take an input string and read the digits at the front of the string until a character other than a digit (0-9) is encountered. - * @param input A string that starts with a set of digits (0-9) - * @return A string containing the digits - */ - std::string read_digits(const char *input); - - /*! \brief Escape quotes in a string - * - * \details See json::parsing::unescape_quotes() for the reverse function - * @param input A string potentially containing quotes - * @return A string that has all quotes escaped - * @see unescape_quotes() - */ - std::string escape_quotes(const char *input); - - /*! \brief Removes the escape charater from quotes - * - * \details See json::parsing::escape_quotes for the reverse function - * @param input A string potentially containing escaped quotes - * @return A string with quotes that are not escaped - * @see escape_quotes() - */ - std::string unescape_quotes(const char *input); - - /*! \brief Structure for capturing the results of parsing */ - struct parse_results - { - /*! \brief The type of value encountered while parsing */ - jtype::jtype type; - - /*! \brief The parsed value encountered */ - std::string value; - - /*! \brief A pointer to the first character after the parsed value */ - const char *remainder; - }; - - /*! \brief Parses the first value encountered in a JSON string - * - * @param input The string to be parsed - * @return Details regarding the first value encountered - * \exception json::parsing_error Exception thrown when the input is not valid JSON - */ - parse_results parse(const char *input); - - /*! \brief Template for reading a numeric value - * - * @tparam T The C data type the input will be convered to - * @param input The string to conver to a number - * @param format The format to use when converting the string to a number - * @return The numeric value contained by the input - */ - template - T get_number(const char *input, const char* format) - { - T result; - std::sscanf(input, format, &result); - return result; - } - - /*! \brief Converts a number to a string - * - * @tparam The C data type of the number to be converted - * @param number A reference to the number to be converted - * @param format The format to be used when converting the number - * @return A string representation of the input number - */ - template - std::string get_number_string(const T &number, const char *format) - { - std::vector cstr(6); - int remainder = std::snprintf(&cstr[0], cstr.size(), format, number); - if(remainder < 0) { - return std::string(); - } else if(remainder >= (int)cstr.size()) { - cstr.resize(remainder + 1); - std::snprintf(&cstr[0], cstr.size(), format, number); - } - std::string result(&cstr[0]); - return result; - } - - /*! \brief Parses a JSON array - * - * \details Converts a serialized JSON array into a vector of the values in the array - * @param input The serialized JSON array - * @return A vector containing each element of the array with each element being serialized JSON - */ - std::vector parse_array(const char *input); - } - - /*! \brief (k)ey (v)alue (p)air */ - typedef std::pair kvp; - - /*! \class jobject - * \brief The class used for manipulating JSON objects and arrays - * - * \example jobject.cpp - * This is a basic of example of using simpleson for manipulating JSON - * - * \example rootarray.cpp - * This is an example of how to handle JSON where the root object is an array - * - * \example objectarray.cpp - * This is an example of how to handle an array of JSON objects - */ - class jobject - { - private: - /*! \brief The container used to store the object's data */ - std::vector data; - - /*! \brief Flag for marking whether the object is actually a JSON array - * - * \details When true, the class should be interpreted as a JSON array - */ - bool array_flag; - - public: - /*! \brief Default constructor - * - * @param array If true, the instance is initialized as an array. If false, the instance is initalized as an object. - */ - inline jobject(bool array = false) - : array_flag(array) - { } - - /*! \brief Copy constructor */ - inline jobject(const jobject &other) - : data(other.data), - array_flag(other.array_flag) - { } - - /*! \brief Destructor */ - inline virtual ~jobject() { } - - /*! \brief Flag for differentiating objects and arrays - * - * @return True if the instance represents an array, false if the instance represents an object - */ - bool is_array() const { return this->array_flag; } - - /*! \brief Returns the number of entries in the JSON object or array */ - inline size_t size() const { return this->data.size(); } - - /*! \brief Clears the JSON object or array */ - inline void clear() { this->data.resize(0); } - - /*! \brief Comparison operator - * - * \todo Currently, the comparison just seralizes both objects and compares the strings, which is probably not as efficent as it could be - */ - bool operator== (const json::jobject other) const { return ((std::string)(*this)) == (std::string)other; } - - /*! \brief Comparison operator */ - bool operator!= (const json::jobject other) const { return ((std::string)(*this)) != (std::string)other; } - - /*! \brief Assignment operator */ - inline jobject& operator=(const jobject rhs) - { - this->array_flag = rhs.array_flag; - this->data = rhs.data; - return *this; - } - - /*! \brief Appends a key-value pair to a JSON object - * - * \exception json::parsing_error Thrown if the key-value is incompatable with the existing object (object/array mismatch) - */ - jobject& operator+=(const kvp& other) - { - if (!this->array_flag && this->has_key(other.first)) throw json::parsing_error("Key conflict"); - if(this->array_flag && other.first != "") throw json::parsing_error("Array cannot have key"); - if(!this->array_flag && other.first == "") throw json::parsing_error("Missing key"); - this->data.push_back(other); - return *this; - } - - /*! \brief Appends one JSON object to another */ - jobject& operator+=(const jobject& other) - { - if(this->array_flag != other.array_flag) throw json::parsing_error("Array/object mismatch"); - json::jobject copy(other); - for (size_t i = 0; i < copy.size(); i++) { - this->operator+=(copy.data.at(i)); - } - return *this; - } - - /*! \brief Merges two JSON objects */ - jobject operator+(jobject& other) - { - jobject result = *this; - result += other; - return result; - } - - /*! \brief Parses a serialized JSON string - * - * @param input Serialized JSON string - * @return JSON object or array - * \exception json::parsing_error Thrown when the input string is not valid JSON - */ - static jobject parse(const char *input); - - /*! \brief Parses a serialized JSON string - * - * @see json::jobject::parse(const char*) - */ - static inline jobject parse(const std::string input) { return parse(input.c_str()); } - - /*! /brief Attempts to parse the input string - * - * @param input A serialized JSON object or array - * @param[out] output Should the parsing attempt be successful, the resultant JSON object or array - * @return True of the parsing attempt was successful and false if the parsing attempt was not successful - */ - inline bool static tryparse(const char *input, jobject &output) - { - try - { - output = parse(input); - } - catch(...) - { - return false; - } - return true; - } - - /*! \brief Determines if an object contains a key - * - * @param key The key to check for - * @return True if the object contains the provided key and false if the object does not contain the key - * \note If the object represents a JSON array, then this function will always return false - */ - inline bool has_key(const std::string &key) const - { - if(this->array_flag) return false; - for (size_t i = 0; i < this->size(); i++) if (this->data.at(i).first == key) return true; - return false; - } - - /*! \brief Sets the value assocaited with the key - * - * \details If the key exists, then the value is updated. If the key does not exist, then the key value pair is added to the object. - * @param key The key for the entry - * @param value The value for the entry - * \exception json::invalid_key Exception thrown if the object actually represents a JSON array - */ - void set(const std::string &key, const std::string &value); - - /*! \brief Returns the serialized value at a given index - * - * @param index The index of the desired element - * @return A serialized representation of the value at the given index - */ - inline std::string get(const size_t index) const - { - return this->data.at(index).second; - } - - /*! \brief Returns the serialized value associated with a key - * - * @param key The key for the desired element - * @return A serialized representation of the value associated with the key - * \exception json::invalid_key Exception thrown if the key does not exist in the object or the object actually represents a JSON array - */ - inline std::string get(const std::string &key) const - { - if(this->array_flag) throw json::invalid_key(key); - for (size_t i = 0; i < this->size(); i++) if (this->data.at(i).first == key) return this->get(i); - throw json::invalid_key(key); - } - - /*! \brief Removes the entry associated with the key - * - * @param key The key of the key value pair to be removed - * \note If the key is not found in the object, no action is taken - */ - void remove(const std::string &key); - - /*! \brief Removes the entry at the specified index - * - * @param index The index of the element to be removed - */ - void remove(const size_t index) - { - this->data.erase(this->data.begin() + index); - } - - /*! \brief Representation of a value in the object */ - class entry - { - protected: - /*! \brief A method for reference the entry's value - * - * @return A string represnting the entry's serialized value - */ - virtual const std::string& ref() const = 0; - - /*! \brief Converts an serialzed value to a numeric value - * - * @tparam The C data type used to represent the value - * @param format The format used to convert the serialized value to a numeric value - * @return The value as a number - */ - template - inline T get_number(const char* format) const - { - return json::parsing::get_number(this->ref().c_str(), format); - } - - /*! \brief Converts a serialized array of numbers to a vector of numbers - * - * @tparam The C data type used to represent the values in the array - * @param format The format used to convert the serialized values in the array to numeric values - * @return The value as a vector of numbers - */ - template - inline std::vector get_number_array(const char* format) const - { - std::vector numbers = json::parsing::parse_array(this->ref().c_str()); - std::vector result; - for (size_t i = 0; i < numbers.size(); i++) - { - result.push_back(json::parsing::get_number(numbers[i].c_str(), format)); - } - return result; - } - - public: - /*! \brief Returns a string representation of the value */ - inline std::string as_string() const - { - return json::parsing::unescape_quotes( - json::parsing::parse(this->ref().c_str()).value.c_str() - ); - } - - /*! @see json::jobject::entry::as_string() */ - inline operator std::string() const - { - return this->as_string(); - } - - /*! \brief Comparison operator */ - bool operator== (const std::string other) const { return ((std::string)(*this)) == other; } - - /*! \brief Comparison operator */ - bool operator!= (const std::string other) const { return !(((std::string)(*this)) == other); } - - /*! \brief Casts the value as an integer */ - operator int() const; - - /*! \brief Casts the value as an unsigned integer */ - operator unsigned int() const; - - /*! \brief Casts teh value as a long integer */ - operator long() const; - - /*! \brief Casts the value as an unsigned long integer */ - operator unsigned long() const; - - /*! \brief Casts teh value as a char */ - operator char() const; - - /*! \brief Casts the value as a floating point numer */ - operator float() const; - - /*! \brief Casts the value as a double-precision floating point number */ - operator double() const; - - /*! \brief Casts the value as a JSON object - * - * \note This method also works for JSON arrays - */ - inline json::jobject as_object() const - { - return json::jobject::parse(this->ref().c_str()); - } - - /*! \see json::jobject::entry::as_object() */ - inline operator json::jobject() const - { - return this->as_object(); - } - - /*! \brief Casts an array of integers */ - operator std::vector() const; - - /*! \brief Casts an array of unsigned integers */ - operator std::vector() const; - - /*! \brief Casts an array of long integers */ - operator std::vector() const; - - /*! \brief Casts an array of unsigned long integers */ - operator std::vector() const; - - /*! \brief Casts an array of chars */ - operator std::vector() const; - - /*! \brief Casts an array of floating-point numbers */ - operator std::vector() const; - - /*! \brief Casts an array of double floating-point numbers */ - operator std::vector() const; - - /*! \brief Casts an array of JSON objects */ - operator std::vector() const - { - const std::vector objs = json::parsing::parse_array(this->ref().c_str()); - std::vector results; - for (size_t i = 0; i < objs.size(); i++) results.push_back(json::jobject::parse(objs[i].c_str())); - return results; - } - - /*! \brief Casts an array of strings */ - operator std::vector() const { return json::parsing::parse_array(this->ref().c_str()); } - - /*! \brief Casts an array - * - * @tparam T The type of array to be cast to - */ - template - inline std::vector as_array() const - { - return (std::vector)(*this); - } - - /*! \brief Returns true if the value is a boolean and set to true */ - inline bool is_true() const - { - json::parsing::parse_results result = json::parsing::parse(this->ref().c_str()); - return (result.type == json::jtype::jbool && result.value == "true"); - } - - /*! \brief Returns true if the value is a null value */ - inline bool is_null() const - { - return json::parsing::parse(this->ref().c_str()).type == json::jtype::jnull; - } - }; - - /*! \brief Represents an entry as a constant value */ - class const_value : public entry - { - private: - /*! \brief A copy of the entry data */ - std::string data; - - protected: - /*! \brief Reference to the entry data - * - * @return A reference to the copied entry data - */ - inline const std::string& ref() const - { - return this->data; - } - - public: - /*! \brief Constructs a proxy with the provided value - * - * @param value The entry value to copy - */ - inline const_value(std::string value) - : data(value) - { } - - /*! \brief Returns another constant value from this object - * - * This method assumed the entry contains a JSON object and returns another constant value from within - * - * @param key The key of the subvalue to return - * @return A proxy for the value for the key - */ - inline const_value get(const std::string &key) const - { - return const_value(json::jobject::parse(this->data).get(key)); - } - - /*! \brief Returns another constant value from this array - * - * This method assumed the entry contains a JSON array and returns another constant value from within - * - * @param index The index of the subvalue to return - * @return A proxy for the value for the index - */ - inline const_value array(const size_t index) const - { - return const_value(json::jobject::parse(this->data).get(index)); - } - }; - - /*! \brief Represents an entry as a constant proxy to the value - * - * This proxy is more memory-efficent than a json::jobject::const_value but cannot use a JSON array as a source - */ - class const_proxy : public entry - { - private: - /*! \brief The source object the value is referencing */ - const jobject &source; - - protected: - /*! \brief The key for the referenced value */ - const std::string key; - - /*! \brief Returns a reference to the value */ - inline const std::string& ref() const - { - for (size_t i = 0; i < this->source.size(); i++) if (this->source.data.at(i).first == key) return this->source.data.at(i).second; - throw json::invalid_key(key); - } - - public: - /*! \brief Constructor - * - * @param source The JSON object the value is being sourced from - * @param key The key for the value being referenced - */ - const_proxy(const jobject &source, const std::string key) : source(source), key(key) - { - if(source.array_flag) throw std::logic_error("Source cannot be an array"); - } - - /*! \brief Returns another constant value from this array - * - * This method assumed the entry contains a JSON array and returns another constant value from within - * - * @param index The index of the subvalue to return - * @return A proxy for the value for the index - */ - const_value array(size_t index) const - { - const char *value = this->ref().c_str(); - if(json::jtype::detect(value) != json::jtype::jarray) - throw std::invalid_argument("Input is not an array"); - const std::vector values = json::parsing::parse_array(value); - return const_value(values[index]); - } - }; - - /*! \brief A proxy that allows modification of the value - * - * \todo Currently, proxies only support JSON object and not arrays - */ - class proxy : public json::jobject::const_proxy - { - private: - /*! \brief The parent object to be manipulated */ - jobject &sink; - - protected: - /*! \brief Sets a number value in the parent object - * - * @tparam T The data type to be translated into JSON - * @param value The value to be translated to JSON - * @param format The format to use when translating the number - */ - template - inline void set_number(const T value, const char* format) - { - this->sink.set(key, json::parsing::get_number_string(value, format)); - } - - /*! \brief Stores an array of values - * - * @param values The values to store as an array - * @param wrap When true, the values are wrapped in quotes. When false, the values are stored as-is - */ - void set_array(const std::vector &values, const bool wrap = false); - - /*! \brief Stores an array of numbers - * - * @tparam T The data type to be translated into JSON - * @param values The array of values to be translated into JSON - * @param format The format to use when translating the numbers - */ - template - inline void set_number_array(const std::vector &values, const char* format) - { - std::vector numbers; - for (size_t i = 0; i < values.size(); i++) - { - numbers.push_back(json::parsing::get_number_string(values[i], format)); - } - this->set_array(numbers); - } - public: - /*! \brief Constructor - * - * @param source The JSON object that will be updated when a value is assigned - * @param key The key for the value to be updated - */ - proxy(jobject &source, const std::string key) - : json::jobject::const_proxy(source, key), - sink(source) - { } - - /*! \brief Assigns a string value */ - inline void operator= (const std::string value) - { - this->sink.set(this->key, "\"" + json::parsing::escape_quotes(value.c_str()) + "\""); - } - - /*! \brief Assigns a string value */ - inline void operator= (const char* value) - { - this->operator=(std::string(value)); - } - - /*! \brief Assigns an integer */ - void operator=(const int input) { this->set_number(input, "%i"); } - - /*! \brief Assigns an unsigned integer */ - void operator=(const unsigned int input) { this->set_number(input, "%u"); } - - /*! \brief Assigns a long integer */ - void operator=(const long input) { this->set_number(input, "%li"); } - - /*! \brief Assigns a long unsigned integer */ - void operator=(const unsigned long input) { this->set_number(input, "%lu"); } - - /*! \brief Assigns an character */ - void operator=(const char input) { this->set_number(input, "%c"); } - - /*! \brief Assigns an double floating-point integer */ - void operator=(const double input) { this->set_number(input, "%e"); } - - /*! \brief Assigns an floating-point integer */ - void operator=(const float input) { this->set_number(input, "%e"); } - - /*! \brief Assigns a JSON object or array */ - void operator=(json::jobject input) - { - this->sink.set(key, (std::string)input); - } - - /*! \brief Assigns an array of integers */ - void operator=(const std::vector input) { this->set_number_array(input, "%i"); } - - /*! \brief Assigns an array of unsigned integers */ - void operator=(const std::vector input) { this->set_number_array(input, "%u"); } - - /*! \brief Assigns an array of long integers */ - void operator=(const std::vector input) { this->set_number_array(input, "%li"); } - - /*! \brief Assigns an array of unsigned long integers */ - void operator=(const std::vector input) { this->set_number_array(input, "%lu"); } - - /*! \brief Assigns an array of characters */ - void operator=(const std::vector input) { this->set_number_array(input, "%c"); } - - /*! \brief Assigns an array of floating-point numbers */ - void operator=(const std::vector input) { this->set_number_array(input, "%e"); } - - /*! \brief Assigns an array of double floating-point numbers */ - void operator=(const std::vector input) { this->set_number_array(input, "%e"); } - - /*! \brief Assigns an array of strings */ - void operator=(const std::vector input) { this->set_array(input, true); } - - /*! \brief Assigns an array of JSON objects */ - void operator=(const std::vector input) - { - std::vector objs; - for (size_t i = 0; i < input.size(); i++) - { - objs.push_back((std::string)input[i]); - } - this->set_array(objs, false); - } - - /*! \brief Sets a boolean value - * - * This method is required because operator=(bool value) conflict with number-based assignments - */ - inline void set_boolean(const bool value) - { - if (value) this->sink.set(key, "true"); - else this->sink.set(key, "false"); - } - - /*! Sets a null value */ - inline void set_null() - { - this->sink.set(key, "null"); - } - - /*! Clears the value */ - inline void clear() - { - this->sink.remove(key); - } - }; - - /*! \brief Returns an element of the JSON object - * - * @param key The key of the element to be returned - * @return A proxy for the value paired with the key - * \exception json::invalid_key Exception thrown if the object is actually a JSON array - */ - inline virtual jobject::proxy operator[](const std::string key) - { - if(this->array_flag) throw json::invalid_key(key); - return jobject::proxy(*this, key); - } - - /*! \brief Returns an element of the JSON object - * - * @param key The key of the element to be returned - * @return A proxy for the value paired with the key - * \exception json::invalid_key Exception thrown if the object is actually a JSON array - */ - inline virtual const jobject::const_proxy operator[](const std::string key) const - { - if(this->array_flag) throw json::invalid_key(key); - return jobject::const_proxy(*this, key); - } - - /*! \brief Returns the value of an element in an array - * - * @param index The index of the element to be returned - * @return A proxy for the value - * - * \note While this method is intended for JSON arrays, this method is also valid for JSON objects - */ - inline const jobject::const_value array(const size_t index) const - { - return jobject::const_value(this->data.at(index).second); - } - - /*! \see json::jobject::as_string() */ - operator std::string() const; - - /*! \brief Serialzes the object or array - * \note The serialized object or array will be in the most compact form and will not contain any extra white space, even if the serialized string used to generate the object or array contained extra white space. - */ - inline std::string as_string() const - { - return this->operator std::string(); - } - - /*! \brief Returns a pretty (multi-line indented) serialzed representation of the object or array - * - * @param indent_level The number of indents (tabs) to start with - * @return A "pretty" version of the serizlied object or array - */ - std::string pretty(unsigned int indent_level = 0) const; - }; -} - -#endif //VEGA_STRIKE_ENGINE_CMD_JSON_H diff --git a/engine/src/cmd/unit_json_factory.cpp b/engine/src/cmd/unit_json_factory.cpp index 28216c41a5..760dc2fd99 100644 --- a/engine/src/cmd/unit_json_factory.cpp +++ b/engine/src/cmd/unit_json_factory.cpp @@ -31,41 +31,33 @@ #include #include #include +#include -#include "json.h" +#include "resource/json_utils.h" void UnitJSONFactory::ParseJSON(VSFileSystem::VSFile &file, bool player_ship) { const std::string json_text = file.ReadFull(); - std::vector units = json::parsing::parse_array(json_text.c_str()); - // Iterate over root - for (const std::string &unit_text : units) { - json::jobject unit = json::jobject::parse(unit_text); + boost::json::value json_value = boost::json::parse(json_text); + boost::json::array root_array = json_value.get_array(); + + for(boost::json::value& unit_value : root_array) { + boost::json::object unit_object = unit_value.get_object(); std::map unit_attributes; - for (const std::string &key : keys) { - // For some reason, parser adds quotes - if(unit.has_key(key)) { - const std::string attribute = unit.get(key); - const std::string stripped_attribute = attribute.substr(1, attribute.size() - 2); - unit_attributes[key] = stripped_attribute; - } else { - unit_attributes[key] = ""; - } + for(boost::json::key_value_pair& pair : unit_object) { + const std::string value = boost::json::value_to(pair.value()); + unit_attributes[pair.key()] = value; } // Add root - unit_attributes["root"] = file.GetRoot(); - - + unit_attributes["root"] = file.GetRoot(); if(player_ship) { UnitCSVFactory::units["player_ship"] = unit_attributes; } else { - std::string unit_key = unit.get("Key"); - std::string stripped_unit_key = unit_key.substr(1, unit_key.size() - 2); - UnitCSVFactory::units[stripped_unit_key] = unit_attributes; + UnitCSVFactory::units[unit_attributes["Key"]] = unit_attributes; } } } diff --git a/engine/src/cmd/unit_optimize_factory.cpp b/engine/src/cmd/unit_optimize_factory.cpp index 17dc8447d5..dcf7d257b3 100644 --- a/engine/src/cmd/unit_optimize_factory.cpp +++ b/engine/src/cmd/unit_optimize_factory.cpp @@ -25,46 +25,40 @@ #include "unit_optimize_factory.h" #include "unit_csv_factory.h" -#include "json.h" void UnitOptimizeFactory::RecursiveParse(std::map unit_attributes, - const std::string& json_text) { - json::jobject json = json::jobject::parse(json_text); - + const boost::json::object object) { // Parse the data section - std::string data = json.get("data"); - json::jobject data_json = json::jobject::parse(data); + if(object.if_contains("data")) { + const boost::json::object data_object = object.at("data").as_object(); - for (const std::string &key : keys) { - // For some reason, parser adds quotes - - if(data_json.has_key(key)) { - const std::string attribute = data_json.get(key); - const std::string stripped_attribute = attribute.substr(1, attribute.size() - 2); - unit_attributes[key] = stripped_attribute; - } - } + for(const boost::json::key_value_pair& pair : data_object) { + const std::string value = boost::json::value_to(pair.value()); + unit_attributes[pair.key()] = value; + } - if(unit_attributes.count("Key")) { - std::string unit_key = unit_attributes["Key"]; - UnitCSVFactory::units[unit_key] = unit_attributes; + if(unit_attributes.count("Key")) { + std::string unit_key = unit_attributes["Key"]; + UnitCSVFactory::units[unit_key] = unit_attributes; + } } - - // Parse the units array - if(json.has_key("units")) { - std::vector units = json::parsing::parse_array(json.get("units").c_str()); - // Iterate over root - for (const std::string &unit_text : units) { - RecursiveParse(unit_attributes, unit_text); - } - } + + if(object.if_contains("units")) { + const boost::json::array units_array = object.at("units").as_array(); + + for(const boost::json::value& value : units_array) { + RecursiveParse(unit_attributes, value.as_object()); + } + } } void UnitOptimizeFactory::ParseJSON(VSFileSystem::VSFile &file) { const std::string json_text = file.ReadFull(); + boost::json::value json_value = boost::json::parse(json_text); + boost::json::object root_object = json_value.as_object(); std::map unit_attributes; @@ -72,5 +66,5 @@ void UnitOptimizeFactory::ParseJSON(VSFileSystem::VSFile &file) { // Add root unit_attributes["root"] = file.GetRoot(); - RecursiveParse(unit_attributes, json_text); + RecursiveParse(unit_attributes, root_object); } diff --git a/engine/src/cmd/unit_optimize_factory.h b/engine/src/cmd/unit_optimize_factory.h index 7ae09c773a..bb3e12b7b3 100644 --- a/engine/src/cmd/unit_optimize_factory.h +++ b/engine/src/cmd/unit_optimize_factory.h @@ -26,15 +26,16 @@ #include #include +#include #include "vsfilesystem.h" class UnitOptimizeFactory { public: - static void ParseJSON(VSFileSystem::VSFile &file); static void RecursiveParse(std::map unit_attributes, - const std::string& json_text); + const boost::json::object object); + static void ParseJSON(VSFileSystem::VSFile &file); }; #endif //VEGA_STRIKE_ENGINE_CMD_UNIT_OPTIMIZE_FACTORY_H diff --git a/engine/src/cmd/weapon_factory.cpp b/engine/src/cmd/weapon_factory.cpp index 123f606b23..42441c9287 100644 --- a/engine/src/cmd/weapon_factory.cpp +++ b/engine/src/cmd/weapon_factory.cpp @@ -28,28 +28,21 @@ #include "weapon_factory.h" #include "weapon_info.h" -#include "options.h" #include "role_bitmask.h" #include "audiolib.h" + #include "hashtable.h" -#include "json.h" #include +#include +#include -#include -#include +#include #include -#include - -namespace pt = boost::property_tree; -namespace alg = boost::algorithm; - -using boost::property_tree::ptree; -using std::string; -using std::endl; +#include "resource/json_utils.h" -extern Hashtable lookuptable; +extern Hashtable lookuptable; // TODO: reenable this? /*constexpr int color_step(49); @@ -61,59 +54,7 @@ bool gamma_needed(int gamma, int count, int depth) -100); }*/ -WeaponFactory::WeaponFactory(std::string filename) { - pt::ptree tree; - pt::read_xml(filename, tree); - - // Iterate over root - for (const auto &iterator : tree) { - //parse(iterator.second); - - // There should be only one root. Exiting - break; - } - - const std::string json_filename = "weapons.json"; - - std::ifstream ifs(json_filename, std::ifstream::in); - std::stringstream buffer; - buffer << ifs.rdbuf(); - - const std::string json_text = buffer.str(); - - std::vector weapons = json::parsing::parse_array(json_text.c_str()); - for (const std::string &weapon_text : weapons) { - parseJSON(weapon_text); - } -} - -// TODO: dup in MPL. Remove -static std::string getJSONValue(const json::jobject& object, const std::string &key, const std::string &default_value) { - if(object.has_key(key)) { - std::string value = object.get(key); - value = value.substr(1, value.size() - 2); - return value; - } - - return default_value; -} - -static float getJSONValue(const json::jobject& object, const std::string &key, const float &default_value) { - if(object.has_key(key)) { - try { - return std::stof(object.get(key)); - } catch(...) {} - try { - return std::stoi(object.get(key)); - } catch(...) {} - } - - return default_value; -} - - -void WeaponFactory::parseJSON(const std::string &weapon_text) { - json::jobject weapon = json::jobject::parse(weapon_text); +void ParseWeapon(const boost::json::object& weapon) { WeaponInfo wi; /*static float gun_speed = game_options()->gun_speed * (game_options()->gun_speed_adjusted_game_speed ? game_options()->game_speed : 1); @@ -121,42 +62,43 @@ void WeaponFactory::parseJSON(const std::string &weapon_text) { // Weapon Type - wi.type = getWeaponTypeFromString(getJSONValue(weapon, "type", "")); + const std::string weapon_type = JsonGetWithDefault(weapon, "type", std::string()); + wi.type = getWeaponTypeFromString(weapon_type); wi.file = getFilenameFromWeaponType(wi.type); // Name - wi.name = getJSONValue(weapon, "name", "Unknown"); + wi.name = JsonGetStringWithDefault(weapon, "name", "Unknown"); // Mount Size - wi.size = getMountSize(getJSONValue(weapon, "mountsize", "Unknown_mount")); + wi.size = getMountSize(JsonGetStringWithDefault(weapon, "mountsize", "Unknown_mount")); // Energy - wi.energy_rate = getJSONValue(weapon, "Energy.rate", wi.energy_rate); - wi.stability = getJSONValue(weapon, "Energy.stability", wi.stability); - wi.refire_rate = getJSONValue(weapon, "Energy.refire", wi.refire_rate); - wi.lock_time = getJSONValue(weapon, "Energy.locktime", wi.lock_time); + wi.energy_rate = JsonGetWithDefault(weapon, "Energy.rate", wi.energy_rate); + wi.stability = JsonGetWithDefault(weapon, "Energy.stability", wi.stability); + wi.refire_rate = JsonGetWithDefault(weapon, "Energy.refire", wi.refire_rate); + wi.lock_time = JsonGetWithDefault(weapon, "Energy.locktime", wi.lock_time); // Damage // TODO: weapon_list.xml laser has damage. Everything else has rate. Correct. - wi.damage = getJSONValue(weapon, "Damage.rate", wi.damage); - wi.phase_damage = getJSONValue(weapon, "Damage.phasedamage", wi.phase_damage); - wi.radius = getJSONValue(weapon, "Damage.radius", wi.radius); - wi.radial_speed = getJSONValue(weapon, "Damage.radialspeed", wi.radial_speed); - wi.long_range = getJSONValue(weapon, "Damage.longrange", wi.long_range); + wi.damage = JsonGetWithDefault(weapon, "Damage.rate", wi.damage); + wi.phase_damage = JsonGetWithDefault(weapon, "Damage.phasedamage", wi.phase_damage); + wi.radius = JsonGetWithDefault(weapon, "Damage.radius", wi.radius); + wi.radial_speed = JsonGetWithDefault(weapon, "Damage.radialspeed", wi.radial_speed); + wi.long_range = JsonGetWithDefault(weapon, "Damage.longrange", wi.long_range); // Distance - wi.volume = getJSONValue(weapon, "Distance.volume", wi.volume); - wi.speed = getJSONValue(weapon, "Distance.speed", wi.speed); - wi.pulse_speed = getJSONValue(weapon, "Distance.pulsespeed", wi.pulse_speed); - wi.range = getJSONValue(weapon, "Distance.range", wi.range); - wi.length = getJSONValue(weapon, "Distance.length", wi.length); + wi.volume = JsonGetWithDefault(weapon, "Distance.volume", wi.volume); + wi.speed = JsonGetWithDefault(weapon, "Distance.speed", wi.speed); + wi.pulse_speed = JsonGetWithDefault(weapon, "Distance.pulsespeed", wi.pulse_speed); + wi.range = JsonGetWithDefault(weapon, "Distance.range", wi.range); + wi.length = JsonGetWithDefault(weapon, "Distance.length", wi.length); // TODO: this is a bug. It gets parsed into the same radius and radial_speed variables. - wi.radius = getJSONValue(weapon, "Distance.radius", wi.radius); - wi.radial_speed = getJSONValue(weapon, "Distance.radialspeed", wi.radial_speed); + wi.radius = JsonGetWithDefault(weapon, "Distance.radius", wi.radius); + wi.radial_speed = JsonGetWithDefault(weapon, "Distance.radialspeed", wi.radial_speed); // TODO: detonation range not implemented. Incorrectly assigns to pulse_speed... @@ -176,11 +118,11 @@ void WeaponFactory::parseJSON(const std::string &weapon_text) { }*/ // Appearance - wi.file = getJSONValue(weapon, "Appearance.file", wi.file); - wi.r = getJSONValue(weapon, "Appearance.r", wi.r); - wi.g = getJSONValue(weapon, "Appearance.g", wi.g); - wi.b = getJSONValue(weapon, "Appearance.b", wi.b); - wi.a = getJSONValue(weapon, "Appearance.a", wi.a); + wi.file = JsonGetWithDefault(weapon, "Appearance.file", wi.file); + wi.r = JsonGetWithDefault(weapon, "Appearance.r", wi.r); + wi.g = JsonGetWithDefault(weapon, "Appearance.g", wi.g); + wi.b = JsonGetWithDefault(weapon, "Appearance.b", wi.b); + wi.a = JsonGetWithDefault(weapon, "Appearance.a", wi.a); // TODO: reenable? No idea why or what this is... /*if ( (gamma > 0) && gamma_needed( gamma, counts, 32 ) ) { @@ -191,13 +133,13 @@ void WeaponFactory::parseJSON(const std::string &weapon_text) { }*/ // Sound - std::string sound_wave = getJSONValue(weapon, "Appearance.soundwav", ""); + std::string sound_wave = JsonGetStringWithDefault(weapon, "Appearance.soundwav", ""); if (!sound_wave.empty()) { // Missiles don't play the sound in a loop. Others do. wi.sound = AUDCreateSoundWAV(sound_wave, wi.type != WEAPON_TYPE::PROJECTILE); } - std::string sound_mp3 = getJSONValue(weapon, "Appearance.soundmp3", ""); + std::string sound_mp3 = JsonGetStringWithDefault(weapon, "Appearance.soundmp3", ""); if (!sound_mp3.empty()) { // Missiles don't play the sound in a loop. Others do. wi.sound = AUDCreateSoundMP3(sound_wave, wi.type != WEAPON_TYPE::PROJECTILE); @@ -207,97 +149,23 @@ void WeaponFactory::parseJSON(const std::string &weapon_text) { lookuptable.Put(boost::to_upper_copy(wi.name), new WeaponInfo(wi)); } -void WeaponFactory::parse(ptree tree) { -// static float gun_speed = -// game_options()->gun_speed * (game_options()->gun_speed_adjusted_game_speed ? game_options()->game_speed : 1); -// static int gamma = (int) (20 * game_options()->weapon_gamma); - - for (const auto &iterator : tree) { - WeaponInfo wi; - - ptree inner = iterator.second; - - // Weapon Type - wi.type = getWeaponTypeFromString(iterator.first); - wi.file = getFilenameFromWeaponType(wi.type); - - // Name - wi.name = inner.get(".name", "Unknown"); - - // Mount Size - wi.size = getMountSize(inner.get(".mountsize", "Unknown_mount")); - - // Energy - wi.energy_rate = inner.get("Energy..rate", wi.energy_rate); - wi.stability = inner.get("Energy..stability", wi.stability); - wi.refire_rate = inner.get("Energy..refire", wi.refire_rate); - wi.lock_time = inner.get("Energy..locktime", wi.lock_time); - - // Damage - // TODO: weapon_list.xml laser has damage. Everything else has rate. Correct. - wi.damage = inner.get("Damage..rate", wi.damage); - wi.phase_damage = inner.get("Damage..phasedamage", wi.phase_damage); - wi.radius = inner.get("Damage..radius", wi.radius); - wi.radial_speed = inner.get("Damage..radialspeed", wi.radial_speed); - wi.long_range = inner.get("Damage..longrange", wi.long_range); - - // Distance - wi.volume = inner.get("Distance..volume", wi.volume); - wi.speed = inner.get("Distance..speed", wi.speed); - wi.pulse_speed = inner.get("Distance..pulsespeed", wi.pulse_speed); - wi.range = inner.get("Distance..range", wi.range); - wi.length = inner.get("Distance..length", wi.length); - - // TODO: this is a bug. It gets parsed into the same radius and radial_speed variables. - wi.radius = inner.get("Distance..radius", wi.radius); - wi.radial_speed = inner.get("Distance..radialspeed", wi.radial_speed); - - // TODO: detonation range not implemented. Incorrectly assigns to pulse_speed... - //wi.bug = inner.get( "Energy..detonationrange", wi.bug ); - - // TODO: is this really necessary??? - /*if(game_options()->gun_speed_adjusted_game_speed) { - if (wi.speed < 1000) { - wi.speed *= 1.0+gun_speed/1.25; - } else if (wi.speed < 2000) { - wi.speed *= 1.0+gun_speed/2.5; - } else if (wi.speed < 4000) { - wi.speed *= 1.0+gun_speed/6.0; - } else if (wi.speed < 8000) { - wi.speed *= 1.0+gun_speed/17.0; - } - }*/ - - // Appearance - wi.file = inner.get("Appearance..file", wi.file); - wi.a = inner.get("Appearance..a", wi.a); - wi.r = inner.get("Appearance..r", wi.r); - wi.g = inner.get("Appearance..g", wi.g); - wi.b = inner.get("Appearance..b", wi.b); - wi.a = inner.get("Appearance..a", wi.a); - - // TODO: reenable? No idea why or what this is... - /*if ( (gamma > 0) && gamma_needed( gamma, counts, 32 ) ) { - //approximate the color func - wi.b = (wi.b+color_step*5)/255.; - wi.g = (wi.g+color_step/5)/255.; - wi.r = (wi.r+color_step*2)/255.; - }*/ - - // Sound - std::string sound_wave = inner.get("Appearance..soundwav", ""); - if (!sound_wave.empty()) { - // Missiles don't play the sound in a loop. Others do. - wi.sound = AUDCreateSoundWAV(sound_wave, wi.type != WEAPON_TYPE::PROJECTILE); - } - std::string sound_mp3 = inner.get("Appearance..soundmp3", ""); - if (!sound_mp3.empty()) { - // Missiles don't play the sound in a loop. Others do. - wi.sound = AUDCreateSoundMP3(sound_wave, wi.type != WEAPON_TYPE::PROJECTILE); - } +WeaponFactory::WeaponFactory(std::string filename) { + std::ifstream ifs(filename, std::ifstream::in); + std::stringstream buffer; + buffer << ifs.rdbuf(); + + const std::string json_text = buffer.str(); + + boost::json::value json_value = boost::json::parse(json_text); + boost::json::array root_array = json_value.get_array(); - // Add new WeaponInfo to weapons table - lookuptable.Put(boost::to_upper_copy(wi.name), new WeaponInfo(wi)); + for(boost::json::value& weapon_value : root_array) { + boost::json::object weapon = weapon_value.get_object(); + ParseWeapon(weapon); } } + + + + diff --git a/engine/src/cmd/weapon_factory.h b/engine/src/cmd/weapon_factory.h index 066b334cae..3f4904abd2 100644 --- a/engine/src/cmd/weapon_factory.h +++ b/engine/src/cmd/weapon_factory.h @@ -23,15 +23,11 @@ #define VEGA_STRIKE_ENGINE_CMD_WEAPON_FACTORY_H #include -#include +#include class WeaponFactory { public: WeaponFactory(std::string filename); - -private: - void parse(boost::property_tree::ptree tree); - void parseJSON(const std::string &weapon_text); }; #endif //VEGA_STRIKE_ENGINE_CMD_WEAPON_FACTORY_H diff --git a/engine/src/configuration/graphics_config.cpp b/engine/src/configuration/graphics_config.cpp index a255b99057..3058a2a78f 100644 --- a/engine/src/configuration/graphics_config.cpp +++ b/engine/src/configuration/graphics_config.cpp @@ -1,48 +1,23 @@ #include +#include +#include #include #include "graphics_config.h" -#include "json.h" - -// Exposes the struct to python -// TODO: move this somewhere as the same library should have multiple -// definitions -// Can we spread a boost python module over several files? -/*BOOST_PYTHON_MODULE(vegastrike_python) { - boost::python::class_("GraphicsConfig", boost::python::init<>()) - .def_readwrite("screen", &Graphics2Config::screen) - .def_readwrite("resolution_x", &Graphics2Config::resolution_x) - .def_readwrite("resolution_y", &Graphics2Config::resolution_y); -}*/ - -// a temporary helper function until we move to Boost/JSON -// TODO: remove -static const int GetValue( - const std::string key, - const int default_value, - const json::jobject object) { - if(!object.has_key(key)) { - return default_value; - } +#include "resource/json_utils.h" - const std::string attribute = object.get(key); - const int value = std::stoi(attribute); - return value; -} +// TODO: delete this. Graphics2Config should be generated automatically from config.json Graphics2Config::Graphics2Config(const std::string config) { - json::jobject json_root = json::jobject::parse(config); - - if(!json_root.has_key("graphics")) { - return; + boost::json::value json_value = boost::json::parse(config); + boost::json::object root = json_value.get_object(); + + if (root.if_contains("graphics")) { + boost::json::object graphics = root.at("graphics").get_object(); + ConditionalJsonGet(graphics, screen, "screen"); + ConditionalJsonGet(graphics, resolution_x, "resolution_x"); + ConditionalJsonGet(graphics, resolution_y, "resolution_y"); } - - const std::string graphics_json = json_root.get("graphics"); - json::jobject json_graphics = json::jobject::parse(graphics_json); - - screen = GetValue("screen", 0, json_graphics); - resolution_x = GetValue("resolution_x", 2560, json_graphics); - resolution_y = GetValue("resolution_y", 1600, json_graphics); } diff --git a/engine/src/resource/json_utils.cpp b/engine/src/resource/json_utils.cpp new file mode 100644 index 0000000000..15cd70d6b6 --- /dev/null +++ b/engine/src/resource/json_utils.cpp @@ -0,0 +1,36 @@ +/* + * json_utils.cpp + * + * Copyright (C) 2001-2024 Daniel Horn, Benjamen Meyer, Roy Falk, Stephen G. Tuggy, + * and other Vega Strike contributors. + * + * https://github.com/vegastrike/Vega-Strike-Engine-Source + * + * This file is part of Vega Strike. + * + * Vega Strike is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Vega Strike is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Vega Strike. If not, see . + */ + +#include + + +const std::string JsonGetStringWithDefault(boost::json::object object, + const std::string& key, + const char* default_value) { + if (object.if_contains(key)) { + return boost::json::value_to(object.at(key)); + } + + return default_value; +} \ No newline at end of file diff --git a/engine/src/resource/json_utils.h b/engine/src/resource/json_utils.h new file mode 100644 index 0000000000..346b2a540a --- /dev/null +++ b/engine/src/resource/json_utils.h @@ -0,0 +1,57 @@ +/* + * json_utils.h + * + * Copyright (C) 2001-2024 Daniel Horn, Benjamen Meyer, Roy Falk, Stephen G. Tuggy, + * and other Vega Strike contributors. + * + * https://github.com/vegastrike/Vega-Strike-Engine-Source + * + * This file is part of Vega Strike. + * + * Vega Strike is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Vega Strike is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Vega Strike. If not, see . + */ + +#ifndef VEGA_STRIKE_ENGINE_RESOURCE_JSON_UTILS_H +#define VEGA_STRIKE_ENGINE_RESOURCE_JSON_UTILS_H + +#include +#include + +// Use when default value already defined +template +void ConditionalJsonGet(boost::json::object& object, + T& value, + const std::string& key) { + if (object.if_contains(key)) { + value = boost::json::value_to(object.at(key)); + } +} + +// Use when default value is not defined +template +const T JsonGetWithDefault(boost::json::object object, + const std::string& key, + const T default_value) { + if (object.if_contains(key)) { + return boost::json::value_to(object.at(key)); + } + + return default_value; +} + +const std::string JsonGetStringWithDefault(boost::json::object object, + const std::string& key, + const char* default_value); + +#endif //VEGA_STRIKE_ENGINE_RESOURCE_JSON_UTILS_H \ No newline at end of file diff --git a/engine/src/resource/manifest.cpp b/engine/src/resource/manifest.cpp index 53e3c896d7..7534771955 100644 --- a/engine/src/resource/manifest.cpp +++ b/engine/src/resource/manifest.cpp @@ -29,41 +29,11 @@ #include #include -//#include "xml_support.h" // TODO: replace this later -#include "json.h" -#include "random_utils.h" - -// TODO: get rid of this function when we move to C++20 - -static bool ends_with(const std::string& str, const std::string& suffix){ - return str.size() >= suffix.size() && str.compare(str.size()-suffix.size(), suffix.size(), suffix) == 0; -} - - - -// TODO: get rid of this helper function and others like it. -static std::string getJSONValue(const json::jobject& object, const std::string &key, const std::string &default_value) { - if(object.has_key(key)) { - std::string value = object.get(key); - value = value.substr(1, value.size() - 2); - return value; - } - - return default_value; -} +#include +#include -static float getJSONValue(const json::jobject& object, const std::string &key, const float &default_value) { - if(object.has_key(key)) { - try { - return std::stof(object.get(key)); - } catch(...) {} - try { - return std::stoi(object.get(key)); - } catch(...) {} - } - - return default_value; -} +#include "random_utils.h" +#include "resource/json_utils.h" Manifest::Manifest() { @@ -101,21 +71,21 @@ Manifest::Manifest(int dummy) { buffer << ifs.rdbuf(); const std::string json_text = buffer.str(); + boost::json::value json_value = boost::json::parse(json_text); + boost::json::array root_array = json_value.get_array(); - std::vector parts = json::parsing::parse_array(json_text.c_str()); - for (const std::string &part_text : parts) { - json::jobject part = json::jobject::parse(part_text); + for(boost::json::value& item_value : root_array) { + boost::json::object item = item_value.get_object(); - std::string name = getJSONValue(part, "file", ""); - std::string category = getJSONValue(part, "categoryname", ""); + std::string name = JsonGetStringWithDefault(item, "file", ""); + std::string category = JsonGetStringWithDefault(item, "categoryname", ""); + int price = std::stoi(JsonGetStringWithDefault(item, "price", "0")); + double mass = std::stod(JsonGetStringWithDefault(item, "mass", "0.0")); + double volume = std::stod(JsonGetStringWithDefault(item, "volume", "0.0")); + std::string description = JsonGetStringWithDefault(item, "description", ""); - Cargo cargo = Cargo(name, - category, - std::stoi(getJSONValue(part, "price", "")), // Price - 1, // Quantity - std::stof(getJSONValue(part, "mass", "")), // Mass - std::stof(getJSONValue(part, "volume", ""))); // Volume - cargo.SetDescription(getJSONValue(part, "description", "")); // Description + Cargo cargo = Cargo(name, category, price, 1, mass, volume); + cargo.SetDescription(description); _items.push_back(cargo); } } @@ -132,7 +102,7 @@ Cargo Manifest::GetCargoByName(const std::string name) { std::string filename; // Check if we need to remove __upgrades suffix - if(ends_with(name, upgrades_suffix)) { + if(boost::algorithm::ends_with(name, upgrades_suffix)) { filename = name.substr(0, name.length() - upgrades_suffix.length()); } else { filename = name; diff --git a/engine/src/universe.cpp b/engine/src/universe.cpp index 6851ecf890..5dd37d0284 100644 --- a/engine/src/universe.cpp +++ b/engine/src/universe.cpp @@ -325,7 +325,6 @@ Universe::Universe(int argc, char **argv, const char *galaxy_str) { bootstrap_first_loop(); ROLES::getAllRolePriorities(); - //LoadWeapons( VSFileSystem::weapon_list.c_str() ); WeaponFactory wf = WeaponFactory(VSFileSystem::weapon_list); galaxy.reset(new GalaxyXML::Galaxy(galaxy_str)); @@ -355,7 +354,6 @@ StarSystem *Universe::Init(string systemfile, const Vector ¢r, const string static bool js = true; if (js) { js = false; - // LoadWeapons( VSFileSystem::weapon_list.c_str() ); WeaponFactory wf = WeaponFactory(VSFileSystem::weapon_list); CacheJumpStar(false); diff --git a/engine/src/vsfilesystem.cpp b/engine/src/vsfilesystem.cpp index 00899ce2a2..c3b37be78d 100644 --- a/engine/src/vsfilesystem.cpp +++ b/engine/src/vsfilesystem.cpp @@ -626,7 +626,7 @@ void LoadConfig(string subdir) { bool found = false; bool foundweapons = false; //First check if we have a config file in homedir+"/"+subdir or in datadir+"/"+subdir - weapon_list = "weapon_list.xml"; + weapon_list = "weapons.json"; if (!subdir.empty()) { modname = subdir; if (DirectoryExists(homedir + "/mods/" + subdir)) { @@ -634,8 +634,8 @@ void LoadConfig(string subdir) { VS_LOG(info, (boost::format("CONFIGFILE - Found a config file in home mod directory, using : %1%") % (homedir + "/mods/" + subdir + "/" + config_file))); - if (FileExists(homedir + "/mods/" + subdir, "weapon_list.xml") >= 0) { - weapon_list = homedir + "/mods/" + subdir + "/weapon_list.xml"; + if (FileExists(homedir + "/mods/" + subdir, "weapons.json") >= 0) { + weapon_list = homedir + "/mods/" + subdir + "/weapons.json"; foundweapons = true; } config_file = homedir + "/mods/" + subdir + "/" + config_file; @@ -652,8 +652,8 @@ void LoadConfig(string subdir) { (boost::format("CONFIGFILE - Found a config file in mods directory, using : %1%") % (moddir + "/" + subdir + "/" + config_file))); } - if ((!foundweapons) && FileExists(moddir + "/" + subdir, "weapon_list.xml") >= 0) { - weapon_list = moddir + "/" + subdir + "/weapon_list.xml"; + if ((!foundweapons) && FileExists(moddir + "/" + subdir, "weapons.json") >= 0) { + weapon_list = moddir + "/" + subdir + "/weapons.json"; foundweapons = true; } if (!found) { diff --git a/engine/vcpkg.json b/engine/vcpkg.json index e7d79b999e..3802cc5f04 100644 --- a/engine/vcpkg.json +++ b/engine/vcpkg.json @@ -15,6 +15,7 @@ "boost-atomic", "boost-assign", "boost-format", + "boost-json", "egl-registry", "expat", "freeglut", diff --git a/script/bootstrap b/script/bootstrap index 446e5ed571..57f7b18dee 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -62,37 +62,11 @@ function bootstrapOnDebian() case "$LINUX_CODENAME" in "bookworm") - apt-get -qy install \ - git \ - cmake \ - python3-dev \ - build-essential \ - automake \ - autoconf \ - libpng16-16 \ - libpng-dev \ - libpng-tools \ - libjpeg62-turbo-dev \ - libexpat1-dev \ - libgtk-3-dev \ - libopenal-dev \ - libogg-dev \ - libvorbis-dev \ - libglvnd-dev \ - libgl1-mesa-dev \ - libsdl1.2-dev \ - libsdl2-dev \ - libpostproc-dev \ - freeglut3-dev \ + apt-get -qy remove \ libboost-python-dev \ libboost-log-dev \ - libboost-regex-dev \ - libboost-program-options-dev \ - libxmu-dev \ - clang \ - lsb-release - ;; - "bullseye") + libboost-regex-dev + apt-get -qy autoremove apt-get -qy install \ git \ cmake \ @@ -115,14 +89,19 @@ function bootstrapOnDebian() libsdl2-dev \ libpostproc-dev \ freeglut3-dev \ - libboost-python-dev \ - libboost-log-dev \ - libboost-regex-dev \ - libboost-program-options-dev \ + libboost-python1.81-dev \ + libboost-log1.81-dev \ + libboost-regex1.81-dev \ + libboost-json1.81-dev \ + libboost-program-options1.81-dev \ libxmu-dev \ clang \ lsb-release ;; + "bullseye") + echo "Sorry, Debian bullseye is no longer supported" + exit 2 + ;; "buster") echo "Sorry, Debian buster is no longer supported" exit 2 @@ -176,74 +155,19 @@ function bootstrapOnUbuntu() libboost-python-dev \ libboost-log-dev \ libboost-regex-dev \ + libboost-json-dev \ libboost-program-options-dev \ libxmu-dev \ clang \ lsb-release ;; "jammy") - apt-get -qy install \ - git \ - cmake \ - python3-dev \ - build-essential \ - automake \ - autoconf \ - libpng16-16 \ - libpng-dev \ - libpng-tools \ - libjpeg-turbo8-dev \ - libexpat1-dev \ - libgdk-pixbuf-2.0-dev \ - libgtk-3-dev \ - libopenal-dev \ - libogg-dev \ - libvorbis-dev \ - libglvnd-dev \ - libgl1-mesa-dev \ - libsdl1.2-dev \ - libsdl2-dev \ - libopengl0 \ - libpostproc-dev \ - freeglut3-dev \ - libboost-python-dev \ - libboost-log-dev \ - libboost-regex-dev \ - libboost-program-options-dev \ - libxmu-dev \ - clang \ - lsb-release + echo "Sorry, Ubuntu jammy is no longer supported" + exit 2 ;; "focal") - apt-get -qy install \ - git \ - cmake \ - build-essential \ - automake \ - autoconf \ - libpng16-16 \ - libpng-dev \ - libpng-tools \ - libjpeg62-dev \ - libexpat1-dev \ - libgtk-3-dev \ - libopenal-dev \ - libogg-dev \ - libvorbis-dev \ - libglvnd-dev \ - libgl1-mesa-dev \ - libsdl1.2-dev \ - libsdl2-dev \ - libopengl0 \ - libpostproc-dev \ - freeglut3-dev \ - libboost-python-dev \ - libboost-log-dev \ - libboost-regex-dev \ - libboost-program-options-dev \ - libxmu-dev \ - clang \ - lsb-release + echo "Sorry, Ubuntu focal is no longer supported" + exit 2 ;; "bionic") echo "Sorry, Ubuntu bionic is no longer supported" @@ -306,6 +230,7 @@ function bootstrapOnPopOS () libboost-python-dev \ libboost-log-dev \ libboost-regex-dev \ + libboost-json-dev \ libboost-program-options-dev \ libxmu-dev \ clang \ @@ -339,6 +264,7 @@ function bootstrapOnPopOS () libboost-python-dev \ libboost-log-dev \ libboost-regex-dev \ + libboost-json-dev \ libboost-program-options-dev \ libxmu-dev \ clang \ @@ -389,6 +315,7 @@ function bootstrapOnLinuxMint () libboost-python-dev \ libboost-log-dev \ libboost-regex-dev \ + libboost-json-dev \ libboost-program-options-dev \ libxmu-dev \ clang \ @@ -422,6 +349,7 @@ function bootstrapOnLinuxMint () libboost-python-dev \ libboost-log-dev \ libboost-regex-dev \ + libboost-json-dev \ libboost-program-options-dev \ libxmu-dev \ clang \ @@ -455,6 +383,7 @@ function bootstrapOnLinuxMint () libboost-python-dev \ libboost-log-dev \ libboost-regex-dev \ + libboost-json-dev \ libboost-program-options-dev \ libxmu-dev \ clang \ @@ -488,6 +417,7 @@ function bootstrapOnLinuxMint () libboost-python-dev \ libboost-log-dev \ libboost-regex-dev \ + libboost-json-dev \ libboost-program-options-dev \ libxmu-dev \ clang \ @@ -521,6 +451,7 @@ function bootstrapOnLinuxMint () libboost-python-dev \ libboost-log-dev \ libboost-regex-dev \ + libboost-json-dev \ libboost-program-options-dev \ libxmu-dev \ clang \ @@ -551,6 +482,7 @@ function bootstrapOnLinuxMint () freeglut3-dev \ libboost-python-dev \ libboost-log-dev \ + libboost-json-dev \ libboost-regex-dev \ libboost-program-options-dev \ libxmu-dev \ @@ -567,72 +499,6 @@ function bootstrapOnLinuxMint () function bootstrapOnOpenSuseLeap () { case "${LINUX_VERSION_ID}" in - "15.2") - zypper --non-interactive install -y \ - libboost_log1_66_0-devel \ - libboost_python-py3-1_66_0-devel \ - libboost_system1_66_0-devel \ - libboost_filesystem1_66_0-devel \ - libboost_thread1_66_0-devel \ - libboost_regex1_66_0-devel \ - libboost_chrono1_66_0-devel \ - libboost_atomic1_66_0-devel \ - libboost_program_options1_66_0-devel \ - cmake \ - gcc-c++ \ - freeglut-devel \ - libopenal0 \ - openal-soft-devel \ - libSDL-1_2-0 \ - libSDL-devel \ - libSDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo \ - libjpeg62-devel \ - libpng16-devel \ - expat \ - libexpat-devel \ - libgtk-3-0 \ - gtk3-devel \ - python3-devel \ - git \ - rpm-build \ - clang - ;; - "15.3") - zypper --non-interactive install -y \ - libboost_log1_66_0-devel \ - libboost_python-py3-1_66_0-devel \ - libboost_system1_66_0-devel \ - libboost_filesystem1_66_0-devel \ - libboost_thread1_66_0-devel \ - libboost_regex1_66_0-devel \ - libboost_chrono1_66_0-devel \ - libboost_atomic1_66_0-devel \ - libboost_program_options1_66_0-devel \ - cmake \ - gcc-c++ \ - freeglut-devel \ - libopenal0 \ - openal-soft-devel \ - libSDL-1_2-0 \ - libSDL-devel \ - libSDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo \ - libjpeg62-devel \ - libpng16-devel \ - expat \ - libexpat-devel \ - libgtk-3-0 \ - gtk3-devel \ - python3-devel \ - git \ - rpm-build \ - clang - ;; "15.4") zypper --non-interactive install -y \ libboost_log1_75_0-devel \ @@ -643,6 +509,7 @@ function bootstrapOnOpenSuseLeap () libboost_regex1_75_0-devel \ libboost_chrono1_75_0-devel \ libboost_atomic1_75_0-devel \ + libboost_json1_75_0-devel \ libboost_program_options1_75_0-devel \ cmake \ gcc-c++ \ @@ -676,6 +543,8 @@ function bootstrapOnOpenSuseLeap () libboost_regex1_75_0-devel \ libboost_chrono1_75_0-devel \ libboost_atomic1_75_0-devel \ + libboost_json1_75_0-devel \ + libboost_container1_75_0-devel \ libboost_program_options1_75_0-devel \ cmake \ gcc-c++ \ @@ -709,6 +578,8 @@ function bootstrapOnOpenSuseLeap () libboost_regex1_75_0-devel \ libboost_chrono1_75_0-devel \ libboost_atomic1_75_0-devel \ + libboost_json1_75_0-devel \ + libboost_container1_75_0-devel \ libboost_program_options1_75_0-devel \ cmake \ gcc-c++ \ @@ -1497,303 +1368,6 @@ function bootstrapOnRedHat () function bootstrapOnRockyLinux () { case "${LINUX_VERSION_ID}" in - "8.0") - dnf -y install dnf-plugins-core - dnf -y install epel-release - dnf config-manager --enable epel - dnf config-manager --set-enabled powertools - dnf -y update - dnf -y install \ - git \ - cmake \ - boost-devel \ - boost-python3-devel \ - freeglut-devel \ - gcc-c++ \ - openal-soft-devel \ - SDL-devel \ - SDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo-devel \ - libpng-devel \ - expat-devel \ - gtk3-devel \ - python3-devel \ - rpm-build \ - make \ - clang - ;; - "8.1") - dnf -y install dnf-plugins-core - dnf -y install epel-release - dnf config-manager --enable epel - dnf config-manager --set-enabled powertools - dnf -y update - dnf -y install \ - git \ - cmake \ - boost-devel \ - boost-python3-devel \ - freeglut-devel \ - gcc-c++ \ - openal-soft-devel \ - SDL-devel \ - SDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo-devel \ - libpng-devel \ - expat-devel \ - gtk3-devel \ - python3-devel \ - rpm-build \ - make \ - clang - ;; - "8.2") - dnf -y install dnf-plugins-core - dnf -y install epel-release - dnf config-manager --enable epel - dnf config-manager --set-enabled powertools - dnf -y update - dnf -y install \ - git \ - cmake \ - boost-devel \ - boost-python3-devel \ - freeglut-devel \ - gcc-c++ \ - openal-soft-devel \ - SDL-devel \ - SDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo-devel \ - libpng-devel \ - expat-devel \ - gtk3-devel \ - python3-devel \ - rpm-build \ - make \ - clang - ;; - "8.3") - dnf -y install dnf-plugins-core - dnf -y install epel-release - dnf config-manager --enable epel - dnf config-manager --set-enabled powertools - dnf -y update - dnf -y install \ - git \ - cmake \ - boost-devel \ - boost-python3-devel \ - freeglut-devel \ - gcc-c++ \ - openal-soft-devel \ - SDL-devel \ - SDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo-devel \ - libpng-devel \ - expat-devel \ - gtk3-devel \ - python3-devel \ - rpm-build \ - make \ - clang - ;; - "8.4") - dnf -y install dnf-plugins-core - dnf -y install epel-release - dnf config-manager --enable epel - dnf config-manager --set-enabled powertools - dnf -y update - dnf -y install \ - git \ - cmake \ - boost-devel \ - boost-python3-devel \ - freeglut-devel \ - gcc-c++ \ - openal-soft-devel \ - SDL-devel \ - SDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo-devel \ - libpng-devel \ - expat-devel \ - gtk3-devel \ - python3-devel \ - rpm-build \ - make \ - clang - ;; - "8.5") - dnf -y install dnf-plugins-core - dnf -y install epel-release - dnf config-manager --enable epel - dnf config-manager --set-enabled powertools - dnf -y update - dnf -y install \ - git \ - cmake \ - boost-devel \ - boost-python3-devel \ - freeglut-devel \ - gcc-c++ \ - openal-soft-devel \ - SDL-devel \ - SDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo-devel \ - libpng-devel \ - expat-devel \ - gtk3-devel \ - python3-devel \ - rpm-build \ - make \ - clang - ;; - "8.6") - dnf -y install dnf-plugins-core - dnf -y install epel-release - dnf config-manager --enable epel - dnf config-manager --set-enabled powertools - dnf -y update - dnf -y install \ - git \ - cmake \ - boost-devel \ - boost-python3-devel \ - freeglut-devel \ - gcc-c++ \ - openal-soft-devel \ - SDL-devel \ - SDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo-devel \ - libpng-devel \ - expat-devel \ - gtk3-devel \ - python3-devel \ - rpm-build \ - make \ - clang - ;; - "8.7") - dnf -y install dnf-plugins-core - dnf -y install epel-release - dnf config-manager --enable epel - dnf config-manager --set-enabled powertools - dnf -y update - dnf -y install \ - git \ - cmake \ - boost-devel \ - boost-python3-devel \ - freeglut-devel \ - gcc-c++ \ - openal-soft-devel \ - SDL-devel \ - SDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo-devel \ - libpng-devel \ - expat-devel \ - gtk3-devel \ - python3-devel \ - rpm-build \ - make \ - clang - ;; - "8.8") - dnf -y install dnf-plugins-core - dnf -y install epel-release - dnf config-manager --enable epel - dnf config-manager --set-enabled powertools - dnf -y update - dnf -y install \ - git \ - cmake \ - boost-devel \ - boost-python3-devel \ - freeglut-devel \ - gcc-c++ \ - openal-soft-devel \ - SDL-devel \ - SDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo-devel \ - libpng-devel \ - expat-devel \ - gtk3-devel \ - python3.11-devel \ - rpm-build \ - make \ - clang - ;; - "8.9") - dnf -y install dnf-plugins-core - dnf -y install epel-release - dnf config-manager --enable epel - dnf config-manager --set-enabled powertools - dnf -y update - dnf -y install \ - git \ - cmake \ - boost-devel \ - boost-python3-devel \ - freeglut-devel \ - gcc-c++ \ - openal-soft-devel \ - SDL-devel \ - SDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo-devel \ - libpng-devel \ - expat-devel \ - gtk3-devel \ - python3.11-devel \ - rpm-build \ - make \ - clang - ;; - "8.10") - dnf -y install dnf-plugins-core - dnf -y install epel-release - dnf config-manager --enable epel - dnf config-manager --set-enabled powertools - dnf -y update - dnf -y install \ - git \ - cmake \ - boost-devel \ - boost-python3-devel \ - freeglut-devel \ - gcc-c++ \ - openal-soft-devel \ - SDL-devel \ - SDL2-devel \ - libvorbis-devel \ - libglvnd-devel \ - libjpeg-turbo-devel \ - libpng-devel \ - expat-devel \ - gtk3-devel \ - python3.11-devel \ - rpm-build \ - make \ - clang - ;; "9.0") dnf -y install dnf-plugins-core dnf config-manager --set-enabled devel @@ -1803,11 +1377,13 @@ function bootstrapOnRockyLinux () cmake \ boost-devel \ boost-python3-devel \ + boost-json \ freeglut-devel \ gcc-c++ \ openal-soft-devel \ sdl12-compat-devel \ SDL2-devel \ + libboost-json1.81-dev \ libvorbis-devel \ libglvnd-devel \ libjpeg-turbo-devel \ @@ -1828,11 +1404,13 @@ function bootstrapOnRockyLinux () cmake \ boost-devel \ boost-python3-devel \ + boost-json \ freeglut-devel \ gcc-c++ \ openal-soft-devel \ sdl12-compat-devel \ SDL2-devel \ + libboost-json1.81-dev \ libvorbis-devel \ libglvnd-devel \ libjpeg-turbo-devel \ @@ -1853,11 +1431,13 @@ function bootstrapOnRockyLinux () cmake \ boost-devel \ boost-python3-devel \ + boost-json \ freeglut-devel \ gcc-c++ \ openal-soft-devel \ sdl12-compat-devel \ SDL2-devel \ + libboost-json1.81-dev \ libvorbis-devel \ libglvnd-devel \ libjpeg-turbo-devel \ @@ -1878,11 +1458,13 @@ function bootstrapOnRockyLinux () cmake \ boost-devel \ boost-python3-devel \ + boost-json \ freeglut-devel \ gcc-c++ \ openal-soft-devel \ sdl12-compat-devel \ SDL2-devel \ + libboost-json1.81-dev \ libvorbis-devel \ libglvnd-devel \ libjpeg-turbo-devel \ @@ -1903,6 +1485,7 @@ function bootstrapOnRockyLinux () cmake \ boost-devel \ boost-python3-devel \ + boost-json \ freeglut-devel \ gcc-c++ \ openal-soft-devel \ diff --git a/script/cibuild b/script/cibuild index c4e2ffc28b..f1d0341540 100755 --- a/script/cibuild +++ b/script/cibuild @@ -45,7 +45,9 @@ then SRC_DOCKER_IMG_NAME="vegastrike/vega-strike-build-env:$(echo $FROM | sed 's/:/_/' | sed 's/\//_/')" DST_DOCKER_IMG_NAME="building-vega-strike:$(echo $FROM | sed 's/:/_/' | sed 's/\//_/')" DOCKER_CONTAINER_NAME="building-vega-strike_$(echo $FROM | sed 's/:/_/' | sed 's/\//_/')" + echo "Building docker image for $FROM / $COMPILER" docker build --build-arg from=$SRC_DOCKER_IMG_NAME -t $DST_DOCKER_IMG_NAME . + echo "Running docker image for $FROM / $COMPILER" docker run --env CC=$CC --env CXX=$CXX --env IS_RELEASE=$IS_RELEASE --env TAG_NAME=$TAG_NAME --env GITHUB_SHA=$GITHUB_SHA --env SHORT_SHA=$SHORT_SHA --env FLAGS="$FLAGS" --name $DOCKER_CONTAINER_NAME $DST_DOCKER_IMG_NAME docker cp $DOCKER_CONTAINER_NAME:/usr/src/Vega-Strike-Engine-Source/bin . if [ $IS_RELEASE -eq 1 ] diff --git a/script/docker-entrypoint.sh b/script/docker-entrypoint.sh index fe135e2e7a..0ef2098956 100755 --- a/script/docker-entrypoint.sh +++ b/script/docker-entrypoint.sh @@ -31,6 +31,9 @@ echo "docker-entrypoint.sh: Flags passed in: $FLAGS" # find /usr -iname '*libboost_python*' +echo "Re-run bootstrap" +script/bootstrap + if [ $IS_RELEASE -eq 1 ] then script/build -DCMAKE_BUILD_TYPE=RelWithDebInfo $FLAGS