Merge branch 'master' into jgrpp
# Conflicts: # .gitignore # CMakeLists.txt # src/3rdparty/optional/optional.hpp # src/group_cmd.cpp # src/industry_cmd.cpp # src/misc_gui.cpp # src/video/sdl2_v.cpp
This commit is contained in:
49
.github/workflows/ci-build.yml
vendored
49
.github/workflows/ci-build.yml
vendored
@@ -10,6 +10,55 @@ env:
|
|||||||
CTEST_OUTPUT_ON_FAILURE: 1
|
CTEST_OUTPUT_ON_FAILURE: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
emscripten:
|
||||||
|
name: Emscripten
|
||||||
|
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
container:
|
||||||
|
# If you change this version, change the number in the cache step too.
|
||||||
|
image: emscripten/emsdk:2.0.10
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /emsdk/upstream/emscripten/cache
|
||||||
|
key: 2.0.10-${{ runner.os }}
|
||||||
|
|
||||||
|
- name: Build (host tools)
|
||||||
|
run: |
|
||||||
|
mkdir build-host
|
||||||
|
cd build-host
|
||||||
|
|
||||||
|
echo "::group::CMake"
|
||||||
|
cmake .. -DOPTION_TOOLS_ONLY=ON
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
echo "::group::Build"
|
||||||
|
echo "Running on $(nproc) cores"
|
||||||
|
make -j$(nproc) tools
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
- name: Install GCC problem matcher
|
||||||
|
uses: ammaraskar/gcc-problem-matcher@master
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
|
||||||
|
echo "::group::CMake"
|
||||||
|
emcmake cmake .. -DHOST_BINARY_DIR=../build-host
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
echo "::group::Build"
|
||||||
|
echo "Running on $(nproc) cores"
|
||||||
|
emmake make -j$(nproc)
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
linux:
|
linux:
|
||||||
name: Linux
|
name: Linux
|
||||||
|
|
||||||
|
133
.github/workflows/preview_build.yml
vendored
Normal file
133
.github/workflows/preview_build.yml
vendored
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
name: Preview build
|
||||||
|
|
||||||
|
on:
|
||||||
|
repository_dispatch:
|
||||||
|
types:
|
||||||
|
- Preview*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
preview:
|
||||||
|
name: Build preview
|
||||||
|
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
container:
|
||||||
|
# If you change this version, change the number in the cache step too.
|
||||||
|
image: emscripten/emsdk:2.0.10
|
||||||
|
# uid=1001(runner) gid=121(docker)
|
||||||
|
options: -u 1001:121
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Update deployment status to in progress
|
||||||
|
uses: octokit/request-action@v2.x
|
||||||
|
with:
|
||||||
|
route: POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses
|
||||||
|
mediaType: |
|
||||||
|
previews:
|
||||||
|
- ant-man
|
||||||
|
- flash
|
||||||
|
owner: ${{ github.event.repository.owner.login }}
|
||||||
|
repo: ${{ github.event.repository.name }}
|
||||||
|
deployment_id: ${{ github.event.client_payload.deployment_id }}
|
||||||
|
state: in_progress
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.client_payload.sha }}
|
||||||
|
|
||||||
|
- name: Name branch
|
||||||
|
run: |
|
||||||
|
name=$(echo "${{ github.event.client_payload.folder }}")
|
||||||
|
git checkout -b ${name}
|
||||||
|
|
||||||
|
- name: Setup cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /emsdk/upstream/emscripten/cache
|
||||||
|
key: 2.0.10-${{ runner.os }}
|
||||||
|
|
||||||
|
- name: Build (host tools)
|
||||||
|
run: |
|
||||||
|
mkdir build-host
|
||||||
|
cd build-host
|
||||||
|
|
||||||
|
echo "::group::CMake"
|
||||||
|
cmake .. -DOPTION_TOOLS_ONLY=ON
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
echo "::group::Build"
|
||||||
|
echo "Running on $(nproc) cores"
|
||||||
|
make -j$(nproc) tools
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
- name: Install GCC problem matcher
|
||||||
|
uses: ammaraskar/gcc-problem-matcher@master
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
|
||||||
|
echo "::group::CMake"
|
||||||
|
emcmake cmake .. \
|
||||||
|
-DHOST_BINARY_DIR=../build-host \
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
|
# EOF
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
echo "::group::Build"
|
||||||
|
echo "Running on $(nproc) cores"
|
||||||
|
emmake make -j$(nproc)
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
- name: Publish preview
|
||||||
|
run: |
|
||||||
|
# setuptools is missing in this Docker image, which breaks installing
|
||||||
|
# awscli. So we need to do this in two steps to recover sanity.
|
||||||
|
pip3 install setuptools
|
||||||
|
pip3 install awscli
|
||||||
|
|
||||||
|
~/.local/bin/aws s3 cp --only-show-errors build/openttd.data s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||||
|
~/.local/bin/aws s3 cp --only-show-errors build/openttd.html s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||||
|
~/.local/bin/aws s3 cp --only-show-errors build/openttd.js s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||||
|
~/.local/bin/aws s3 cp --only-show-errors build/openttd.wasm s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/
|
||||||
|
|
||||||
|
# Invalidate the cache of the CloudFront distribution
|
||||||
|
~/.local/bin/aws cloudfront create-invalidation --distribution-id ${{ secrets.PREVIEW_CF_DISTRIBUTION_ID }} --paths "/${{ github.event.client_payload.folder }}/*"
|
||||||
|
env:
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
|
||||||
|
- name: Update deployment status to success
|
||||||
|
uses: octokit/request-action@v2.x
|
||||||
|
with:
|
||||||
|
route: POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses
|
||||||
|
mediaType: |
|
||||||
|
previews:
|
||||||
|
- ant-man
|
||||||
|
- flash
|
||||||
|
owner: ${{ github.event.repository.owner.login }}
|
||||||
|
repo: ${{ github.event.repository.name }}
|
||||||
|
deployment_id: ${{ github.event.client_payload.deployment_id }}
|
||||||
|
state: success
|
||||||
|
environment_url: https://preview.openttd.org/${{ github.event.client_payload.folder }}/
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- if: failure()
|
||||||
|
name: Update deployment status to failure
|
||||||
|
uses: octokit/request-action@v2.x
|
||||||
|
with:
|
||||||
|
route: POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses
|
||||||
|
mediaType: |
|
||||||
|
previews:
|
||||||
|
- ant-man
|
||||||
|
- flash
|
||||||
|
owner: ${{ github.event.repository.owner.login }}
|
||||||
|
repo: ${{ github.event.repository.name }}
|
||||||
|
deployment_id: ${{ github.event.client_payload.deployment_id }}
|
||||||
|
state: failure
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
66
.github/workflows/preview_label.yml
vendored
Normal file
66
.github/workflows/preview_label.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
name: Preview label
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types:
|
||||||
|
- labeled
|
||||||
|
|
||||||
|
env:
|
||||||
|
TEAM_CORE_DEVELOPER: core-developers
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check_preview_label:
|
||||||
|
name: Check for preview label
|
||||||
|
if: github.event.action == 'labeled' && github.event.label.name == 'preview'
|
||||||
|
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check if label was added by core developer
|
||||||
|
id: core_developer
|
||||||
|
continue-on-error: true
|
||||||
|
uses: octokit/request-action@v2.x
|
||||||
|
with:
|
||||||
|
route: GET /orgs/OpenTTD/teams/${{ env.TEAM_CORE_DEVELOPER }}/memberships/${{ github.event.sender.login }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- if: steps.core_developer.outcome == 'failure'
|
||||||
|
name: Remove preview label if not core developer
|
||||||
|
uses: octokit/request-action@v2.x
|
||||||
|
with:
|
||||||
|
route: DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/preview
|
||||||
|
owner: ${{ github.event.repository.owner.login }}
|
||||||
|
repo: ${{ github.event.repository.name }}
|
||||||
|
issue_number: ${{ github.event.number }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- if: steps.core_developer.outcome == 'success'
|
||||||
|
name: Create deployment
|
||||||
|
id: deployment
|
||||||
|
uses: octokit/request-action@v2.x
|
||||||
|
with:
|
||||||
|
route: POST /repos/{owner}/{repo}/deployments
|
||||||
|
mediaType: |
|
||||||
|
previews:
|
||||||
|
- ant-man
|
||||||
|
- flash
|
||||||
|
owner: ${{ github.event.repository.owner.login }}
|
||||||
|
repo: ${{ github.event.repository.name }}
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
task: deploy:preview
|
||||||
|
auto_merge: false
|
||||||
|
required_contexts: "[]"
|
||||||
|
environment: preview-pr-${{ github.event.number }}
|
||||||
|
description: "Preview for Pull Request #${{ github.event.number }}"
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- if: steps.core_developer.outcome == 'success'
|
||||||
|
name: Trigger 'preview build'
|
||||||
|
uses: peter-evans/repository-dispatch@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||||
|
event-type: "Preview build #${{ github.event.number }}"
|
||||||
|
client-payload: '{"folder": "pr${{ github.event.number }}", "sha": "${{ github.event.pull_request.head.sha }}", "deployment_id": "${{ fromJson(steps.deployment.outputs.data).id }}"}'
|
66
.github/workflows/preview_push.yml
vendored
Normal file
66
.github/workflows/preview_push.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
name: Preview push
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types:
|
||||||
|
- synchronize
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check_new_preview:
|
||||||
|
name: Check preview needs update
|
||||||
|
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check if earlier preview exists
|
||||||
|
id: earlier_preview
|
||||||
|
uses: octokit/request-action@v2.x
|
||||||
|
with:
|
||||||
|
route: GET /repos/{owner}/{repo}/deployments
|
||||||
|
owner: ${{ github.event.repository.owner.login }}
|
||||||
|
repo: ${{ github.event.repository.name }}
|
||||||
|
environment: preview-pr-${{ github.event.number }}
|
||||||
|
per_page: 1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- if: toJson(fromJson(steps.earlier_preview.outputs.data)) != '[]'
|
||||||
|
name: Check for preview label
|
||||||
|
id: preview_label
|
||||||
|
uses: octokit/request-action@v2.x
|
||||||
|
with:
|
||||||
|
route: GET /repos/{owner}/{repo}/issues/{issue_number}/labels
|
||||||
|
owner: ${{ github.event.repository.owner.login }}
|
||||||
|
repo: ${{ github.event.repository.name }}
|
||||||
|
issue_number: ${{ github.event.number }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- if: toJson(fromJson(steps.earlier_preview.outputs.data)) != '[]' && contains(fromJson(steps.preview_label.outputs.data).*.name, 'preview')
|
||||||
|
name: Create deployment
|
||||||
|
id: deployment
|
||||||
|
uses: octokit/request-action@v2.x
|
||||||
|
with:
|
||||||
|
route: POST /repos/{owner}/{repo}/deployments
|
||||||
|
mediaType: |
|
||||||
|
previews:
|
||||||
|
- ant-man
|
||||||
|
- flash
|
||||||
|
owner: ${{ github.event.repository.owner.login }}
|
||||||
|
repo: ${{ github.event.repository.name }}
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
task: deploy:preview
|
||||||
|
auto_merge: false
|
||||||
|
required_contexts: "[]"
|
||||||
|
environment: preview-pr-${{ github.event.number }}
|
||||||
|
description: "Preview for Pull Request #${{ github.event.number }}"
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- if: toJson(fromJson(steps.earlier_preview.outputs.data)) != '[]' && contains(fromJson(steps.preview_label.outputs.data).*.name, 'preview')
|
||||||
|
name: Trigger 'preview build'
|
||||||
|
uses: peter-evans/repository-dispatch@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.PREVIEW_GITHUB_TOKEN }}
|
||||||
|
event-type: "Preview build #${{ github.event.number }}"
|
||||||
|
client-payload: '{"folder": "pr${{ github.event.number }}", "sha": "${{ github.event.pull_request.head.sha }}", "deployment_id": "${{ fromJson(steps.deployment.outputs.data).id }}"}'
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,5 @@
|
|||||||
/.vs
|
/.vs
|
||||||
/build*/
|
/build*
|
||||||
CMakeSettings.json
|
CMakeSettings.json
|
||||||
docs/aidocs/*
|
docs/aidocs/*
|
||||||
docs/gamedocs/*
|
docs/gamedocs/*
|
||||||
|
144
CMakeLists.txt
144
CMakeLists.txt
@@ -10,6 +10,10 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
|
|||||||
message(FATAL_ERROR "In-source builds not allowed. Please run \"cmake ..\" from the bin directory")
|
message(FATAL_ERROR "In-source builds not allowed. Please run \"cmake ..\" from the bin directory")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (EMSCRIPTEN)
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/os/emscripten/cmake")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9)
|
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9)
|
||||||
|
|
||||||
@@ -27,6 +31,61 @@ set_directory_options()
|
|||||||
include(Static)
|
include(Static)
|
||||||
set_static_if_needed()
|
set_static_if_needed()
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS NO)
|
||||||
|
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS YES)
|
||||||
|
|
||||||
|
# An empty target for the tools
|
||||||
|
add_custom_target(tools)
|
||||||
|
|
||||||
|
include(Endian)
|
||||||
|
add_endian_definition()
|
||||||
|
|
||||||
|
include(CompileFlags)
|
||||||
|
compile_flags()
|
||||||
|
|
||||||
|
if(APPLE OR UNIX)
|
||||||
|
add_definitions(-DUNIX)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
find_package(Doxygen)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/rev.cpp")
|
||||||
|
if(WIN32)
|
||||||
|
list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/ottdres.rc")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
if(DOXYGEN_EXECUTABLE)
|
||||||
|
add_custom_target(docs)
|
||||||
|
add_custom_target(docs_source
|
||||||
|
${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/docs
|
||||||
|
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
COMMENT "Generating documentation for source"
|
||||||
|
)
|
||||||
|
add_dependencies(docs_source
|
||||||
|
find_version
|
||||||
|
)
|
||||||
|
add_dependencies(docs
|
||||||
|
docs_source
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(AddCustomXXXTimestamp)
|
||||||
|
|
||||||
|
if(OPTION_TOOLS_ONLY)
|
||||||
|
if(HOST_BINARY_DIR)
|
||||||
|
unset(HOST_BINARY_DIR CACHE)
|
||||||
|
endif()
|
||||||
|
add_subdirectory(${CMAKE_SOURCE_DIR}/src)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Prefer -pthread over -lpthread, which is often the better option of the two.
|
# Prefer -pthread over -lpthread, which is often the better option of the two.
|
||||||
set(CMAKE_THREAD_PREFER_PTHREAD YES)
|
set(CMAKE_THREAD_PREFER_PTHREAD YES)
|
||||||
# Make sure we have Threads available.
|
# Make sure we have Threads available.
|
||||||
@@ -98,10 +157,6 @@ find_package(Xaudio2)
|
|||||||
|
|
||||||
find_package(Grfcodec)
|
find_package(Grfcodec)
|
||||||
|
|
||||||
if(UNIX)
|
|
||||||
find_package(Doxygen)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# IPO is only properly supported from CMake 3.9. Despite the fact we are
|
# IPO is only properly supported from CMake 3.9. Despite the fact we are
|
||||||
# CMake 3.5, still enable IPO if we detect we are 3.9+.
|
# CMake 3.5, still enable IPO if we detect we are 3.9+.
|
||||||
if(POLICY CMP0069)
|
if(POLICY CMP0069)
|
||||||
@@ -129,47 +184,7 @@ if(APPLE)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MSVC)
|
|
||||||
# C++17 for MSVC
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
|
||||||
else()
|
|
||||||
# C++11 for all other targets
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
|
||||||
set(CMAKE_CXX_EXTENSIONS NO)
|
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS YES)
|
|
||||||
|
|
||||||
list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/rev.cpp")
|
|
||||||
if(WIN32)
|
|
||||||
list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/ottdres.rc")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# An empty target for the tools
|
|
||||||
add_custom_target(tools)
|
|
||||||
|
|
||||||
# Documentation
|
|
||||||
if(DOXYGEN_EXECUTABLE)
|
|
||||||
add_custom_target(docs)
|
|
||||||
add_custom_target(docs_source
|
|
||||||
${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/docs
|
|
||||||
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
|
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
||||||
COMMENT "Generating documentation for source"
|
|
||||||
)
|
|
||||||
add_dependencies(docs_source
|
|
||||||
find_version
|
|
||||||
)
|
|
||||||
add_dependencies(docs
|
|
||||||
docs_source
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(SourceList)
|
include(SourceList)
|
||||||
include(Endian)
|
|
||||||
add_endian_definition()
|
|
||||||
|
|
||||||
# Needed by rev.cpp
|
# Needed by rev.cpp
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/src)
|
include_directories(${CMAKE_SOURCE_DIR}/src)
|
||||||
@@ -178,9 +193,6 @@ include_directories(${CMAKE_SOURCE_DIR}/src/3rdparty/squirrel/include)
|
|||||||
|
|
||||||
include(MSVCFilters)
|
include(MSVCFilters)
|
||||||
|
|
||||||
include(CompileFlags)
|
|
||||||
compile_flags()
|
|
||||||
|
|
||||||
add_executable(openttd WIN32 ${GENERATED_SOURCE_FILES})
|
add_executable(openttd WIN32 ${GENERATED_SOURCE_FILES})
|
||||||
set_target_properties(openttd PROPERTIES OUTPUT_NAME "${BINARY_NAME}")
|
set_target_properties(openttd PROPERTIES OUTPUT_NAME "${BINARY_NAME}")
|
||||||
# All other files are added via target_sources()
|
# All other files are added via target_sources()
|
||||||
@@ -215,7 +227,6 @@ else()
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(AddCustomXXXTimestamp)
|
|
||||||
add_subdirectory(${CMAKE_SOURCE_DIR}/src)
|
add_subdirectory(${CMAKE_SOURCE_DIR}/src)
|
||||||
add_subdirectory(${CMAKE_SOURCE_DIR}/media/baseset)
|
add_subdirectory(${CMAKE_SOURCE_DIR}/media/baseset)
|
||||||
add_subdirectory(${CMAKE_SOURCE_DIR}/bin)
|
add_subdirectory(${CMAKE_SOURCE_DIR}/bin)
|
||||||
@@ -248,10 +259,6 @@ endif()
|
|||||||
set_target_properties(openttd PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
|
set_target_properties(openttd PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
|
||||||
process_compile_flags()
|
process_compile_flags()
|
||||||
|
|
||||||
if(APPLE OR UNIX)
|
|
||||||
add_definitions(-DUNIX)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(LinkPackage)
|
include(LinkPackage)
|
||||||
link_package(PNG TARGET PNG::PNG ENCOURAGED)
|
link_package(PNG TARGET PNG::PNG ENCOURAGED)
|
||||||
link_package(ZLIB TARGET ZLIB::ZLIB ENCOURAGED)
|
link_package(ZLIB TARGET ZLIB::ZLIB ENCOURAGED)
|
||||||
@@ -288,6 +295,39 @@ if(APPLE)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
add_library(WASM::WASM INTERFACE IMPORTED)
|
||||||
|
|
||||||
|
# Allow heap-growth, and start with a bigger memory size.
|
||||||
|
target_link_libraries(WASM::WASM INTERFACE "-s ALLOW_MEMORY_GROWTH=1")
|
||||||
|
target_link_libraries(WASM::WASM INTERFACE "-s INITIAL_MEMORY=33554432")
|
||||||
|
|
||||||
|
# Export functions to Javascript.
|
||||||
|
target_link_libraries(WASM::WASM INTERFACE "-s EXPORTED_FUNCTIONS='[\"_main\", \"_em_openttd_add_server\"]' -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
|
||||||
|
|
||||||
|
# Preload all the files we generate during build.
|
||||||
|
# As we do not compile with FreeType / FontConfig, we also have no way to
|
||||||
|
# render several languages (like Chinese, ..), so where do you draw the
|
||||||
|
# line what languages to include and which not? In the end, especially as
|
||||||
|
# the more languages you add the slower downloading becomes, we decided to
|
||||||
|
# only ship the English language.
|
||||||
|
target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_BINARY_DIR}/baseset@/baseset")
|
||||||
|
target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_BINARY_DIR}/lang/english.lng@/lang/english.lng")
|
||||||
|
target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/bin/ai@/ai")
|
||||||
|
target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/bin/game@/game")
|
||||||
|
|
||||||
|
# We use IDBFS for persistent storage.
|
||||||
|
target_link_libraries(WASM::WASM INTERFACE "-lidbfs.js")
|
||||||
|
|
||||||
|
# Use custom pre-js and shell.html.
|
||||||
|
target_link_libraries(WASM::WASM INTERFACE "--pre-js ${CMAKE_SOURCE_DIR}/os/emscripten/pre.js")
|
||||||
|
target_link_libraries(WASM::WASM INTERFACE "--shell-file ${CMAKE_SOURCE_DIR}/os/emscripten/shell.html")
|
||||||
|
|
||||||
|
# Build the .html (which builds the .js, .wasm, and .data too).
|
||||||
|
set_target_properties(openttd PROPERTIES SUFFIX ".html")
|
||||||
|
target_link_libraries(openttd WASM::WASM)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT PERSONAL_DIR STREQUAL "(not set)")
|
if(NOT PERSONAL_DIR STREQUAL "(not set)")
|
||||||
add_definitions(
|
add_definitions(
|
||||||
-DWITH_PERSONAL_DIR
|
-DWITH_PERSONAL_DIR
|
||||||
|
@@ -83,9 +83,9 @@ make
|
|||||||
|
|
||||||
## Supported compilers
|
## Supported compilers
|
||||||
|
|
||||||
Every compiler that is supported by CMake and supports C++11, should be
|
Every compiler that is supported by CMake and supports C++17, should be
|
||||||
able to compile OpenTTD. As the exact list of compilers changes constantly,
|
able to compile OpenTTD. As the exact list of compilers changes constantly,
|
||||||
we refer to the compiler manual to see if it supports C++11, and to CMake
|
we refer to the compiler manual to see if it supports C++17, and to CMake
|
||||||
to see if it supports your compiler.
|
to see if it supports your compiler.
|
||||||
|
|
||||||
## Compilation of base sets
|
## Compilation of base sets
|
||||||
|
@@ -55,8 +55,20 @@ function(set_options)
|
|||||||
option(OPTION_DEDICATED "Build dedicated server only (no GUI)" OFF)
|
option(OPTION_DEDICATED "Build dedicated server only (no GUI)" OFF)
|
||||||
option(OPTION_INSTALL_FHS "Install with Filesystem Hierarchy Standard folders" ${DEFAULT_OPTION_INSTALL_FHS})
|
option(OPTION_INSTALL_FHS "Install with Filesystem Hierarchy Standard folders" ${DEFAULT_OPTION_INSTALL_FHS})
|
||||||
option(OPTION_USE_ASSERTS "Use assertions; leave enabled for nightlies, betas, and RCs" ON)
|
option(OPTION_USE_ASSERTS "Use assertions; leave enabled for nightlies, betas, and RCs" ON)
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
# Although pthreads is supported, it is not in a way yet that is
|
||||||
|
# useful for us.
|
||||||
|
option(OPTION_USE_THREADS "Use threads" OFF)
|
||||||
|
else()
|
||||||
option(OPTION_USE_THREADS "Use threads" ON)
|
option(OPTION_USE_THREADS "Use threads" ON)
|
||||||
|
endif()
|
||||||
option(OPTION_USE_NSIS "Use NSIS to create windows installer; enable only for stable releases" OFF)
|
option(OPTION_USE_NSIS "Use NSIS to create windows installer; enable only for stable releases" OFF)
|
||||||
|
option(OPTION_TOOLS_ONLY "Build only tools target" OFF)
|
||||||
|
option(OPTION_DOCS_ONLY "Build only docs target" OFF)
|
||||||
|
|
||||||
|
if (OPTION_DOCS_ONLY)
|
||||||
|
set(OPTION_TOOLS_ONLY ON PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
# Show the values of the generic options.
|
# Show the values of the generic options.
|
||||||
|
@@ -5,6 +5,7 @@ set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/os/macosx/openttd.icns")
|
|||||||
set(CPACK_BUNDLE_PLIST "${CMAKE_CURRENT_BINARY_DIR}/Info.plist")
|
set(CPACK_BUNDLE_PLIST "${CMAKE_CURRENT_BINARY_DIR}/Info.plist")
|
||||||
set(CPACK_BUNDLE_STARTUP_COMMAND "${CMAKE_SOURCE_DIR}/os/macosx/launch.sh")
|
set(CPACK_BUNDLE_STARTUP_COMMAND "${CMAKE_SOURCE_DIR}/os/macosx/launch.sh")
|
||||||
set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/os/macosx/splash.png")
|
set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/os/macosx/splash.png")
|
||||||
|
set(CPACK_DMG_FORMAT "UDBZ")
|
||||||
|
|
||||||
# Create a temporary Info.plist.in, where we will fill in the version via
|
# Create a temporary Info.plist.in, where we will fill in the version via
|
||||||
# CPackProperties.cmake.in. This because at this point in time the version
|
# CPackProperties.cmake.in. This because at this point in time the version
|
||||||
|
4
os/emscripten/Dockerfile
Normal file
4
os/emscripten/Dockerfile
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
FROM emscripten/emsdk
|
||||||
|
|
||||||
|
COPY emsdk-liblzma.patch /
|
||||||
|
RUN cd /emsdk/upstream/emscripten && patch -p1 < /emsdk-liblzma.patch
|
40
os/emscripten/README.md
Normal file
40
os/emscripten/README.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
## How to build with Emscripten
|
||||||
|
|
||||||
|
Building with Emscripten works with emsdk 2.0.10 and above.
|
||||||
|
|
||||||
|
Currently there is no LibLZMA support upstream; for this we suggest to apply
|
||||||
|
the provided patch in this folder to your emsdk installation.
|
||||||
|
|
||||||
|
For convenience, a Dockerfile is supplied that does this patches for you
|
||||||
|
against upstream emsdk docker. Best way to use it:
|
||||||
|
|
||||||
|
Build the docker image:
|
||||||
|
```
|
||||||
|
docker build -t emsdk-lzma .
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the host tools first:
|
||||||
|
```
|
||||||
|
mkdir build-host
|
||||||
|
docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build-host emsdk-lzma cmake .. -DOPTION_TOOLS_ONLY=ON
|
||||||
|
docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build-host emsdk-lzma make -j5 tools
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, build the game with emscripten:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build
|
||||||
|
docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build emsdk-lzma emcmake cmake .. -DHOST_BINARY_DIR=$(pwd)/build-host -DCMAKE_BUILD_TYPE=RelWithDebInfo -DOPTION_USE_ASSERTS=OFF
|
||||||
|
docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build emsdk-lzma emmake make -j5
|
||||||
|
```
|
||||||
|
|
||||||
|
And now you have in your build folder files like "openttd.html".
|
||||||
|
|
||||||
|
To run it locally, you would have to start a local webserver, like:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd build
|
||||||
|
python3 -m http.server
|
||||||
|
````
|
||||||
|
|
||||||
|
Now you can play the game via http://127.0.0.1:8000/openttd.html .
|
20
os/emscripten/cmake/FindLibLZMA.cmake
Normal file
20
os/emscripten/cmake/FindLibLZMA.cmake
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# LibLZMA is a recent addition to the emscripten SDK, so it is possible
|
||||||
|
# someone hasn't updated his SDK yet. Test out if the SDK supports LibLZMA.
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "-sUSE_LIBLZMA=1")
|
||||||
|
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <lzma.h>
|
||||||
|
int main() { return 0; }"
|
||||||
|
LIBLZMA_FOUND
|
||||||
|
)
|
||||||
|
|
||||||
|
if (LIBLZMA_FOUND)
|
||||||
|
add_library(LibLZMA::LibLZMA INTERFACE IMPORTED)
|
||||||
|
set_target_properties(LibLZMA::LibLZMA PROPERTIES
|
||||||
|
INTERFACE_COMPILE_OPTIONS "-sUSE_LIBLZMA=1"
|
||||||
|
INTERFACE_LINK_LIBRARIES "-sUSE_LIBLZMA=1"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(WARNING "You are using an emscripten SDK without LibLZMA support. Many savegames won't be able to load in OpenTTD. Please apply 'emsdk-liblzma.patch' to your local emsdk installation.")
|
||||||
|
endif()
|
7
os/emscripten/cmake/FindPNG.cmake
Normal file
7
os/emscripten/cmake/FindPNG.cmake
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
add_library(PNG::PNG INTERFACE IMPORTED)
|
||||||
|
set_target_properties(PNG::PNG PROPERTIES
|
||||||
|
INTERFACE_COMPILE_OPTIONS "-sUSE_LIBPNG=1"
|
||||||
|
INTERFACE_LINK_LIBRARIES "-sUSE_LIBPNG=1"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(PNG_FOUND on)
|
7
os/emscripten/cmake/FindSDL2.cmake
Normal file
7
os/emscripten/cmake/FindSDL2.cmake
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
add_library(SDL2::SDL2 INTERFACE IMPORTED)
|
||||||
|
set_target_properties(SDL2::SDL2 PROPERTIES
|
||||||
|
INTERFACE_COMPILE_OPTIONS "-sUSE_SDL=2"
|
||||||
|
INTERFACE_LINK_LIBRARIES "-sUSE_SDL=2"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SDL2_FOUND on)
|
7
os/emscripten/cmake/FindZLIB.cmake
Normal file
7
os/emscripten/cmake/FindZLIB.cmake
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
add_library(ZLIB::ZLIB INTERFACE IMPORTED)
|
||||||
|
set_target_properties(ZLIB::ZLIB PROPERTIES
|
||||||
|
INTERFACE_COMPILE_OPTIONS "-sUSE_ZLIB=1"
|
||||||
|
INTERFACE_LINK_LIBRARIES "-sUSE_ZLIB=1"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(ZLIB_FOUND on)
|
213
os/emscripten/emsdk-liblzma.patch
Normal file
213
os/emscripten/emsdk-liblzma.patch
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
From 90dd4d4c6b1cedec338ff5b375fffca93700f7bc Mon Sep 17 00:00:00 2001
|
||||||
|
From: milek7 <me@milek7.pl>
|
||||||
|
Date: Tue, 8 Dec 2020 01:03:31 +0100
|
||||||
|
Subject: [PATCH] Add liblzma port
|
||||||
|
|
||||||
|
---
|
||||||
|
Source: https://github.com/emscripten-core/emscripten/pull/12990
|
||||||
|
|
||||||
|
Modifed by OpenTTD to have the bare minimum needed to work. Otherwise there
|
||||||
|
are constantly conflicts when trying to apply this patch to different versions
|
||||||
|
of emsdk.
|
||||||
|
|
||||||
|
diff --git a/embuilder.py b/embuilder.py
|
||||||
|
index 818262190ed..ab7d5adb7b2 100755
|
||||||
|
--- a/embuilder.py
|
||||||
|
+++ b/embuilder.py
|
||||||
|
@@ -60,6 +60,7 @@
|
||||||
|
'harfbuzz',
|
||||||
|
'icu',
|
||||||
|
'libjpeg',
|
||||||
|
+ 'liblzma',
|
||||||
|
'libpng',
|
||||||
|
'ogg',
|
||||||
|
'regal',
|
||||||
|
@@ -197,6 +198,8 @@ def main():
|
||||||
|
build_port('ogg', libname('libogg'))
|
||||||
|
elif what == 'libjpeg':
|
||||||
|
build_port('libjpeg', libname('libjpeg'))
|
||||||
|
+ elif what == 'liblzma':
|
||||||
|
+ build_port('liblzma', libname('liblzma'))
|
||||||
|
elif what == 'libpng':
|
||||||
|
build_port('libpng', libname('libpng'))
|
||||||
|
elif what == 'sdl2':
|
||||||
|
diff --git a/src/settings.js b/src/settings.js
|
||||||
|
index 61cd98939ba..be6fcb678c6 100644
|
||||||
|
--- a/src/settings.js
|
||||||
|
+++ b/src/settings.js
|
||||||
|
@@ -1197,6 +1197,9 @@ var USE_BZIP2 = 0;
|
||||||
|
// 1 = use libjpeg from emscripten-ports
|
||||||
|
var USE_LIBJPEG = 0;
|
||||||
|
|
||||||
|
+// 1 = use liblzma from emscripten-ports
|
||||||
|
+var USE_LIBLZMA = 0;
|
||||||
|
+
|
||||||
|
// 1 = use libpng from emscripten-ports
|
||||||
|
var USE_LIBPNG = 0;
|
||||||
|
|
||||||
|
diff --git a/tools/ports/liblzma.py b/tools/ports/liblzma.py
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000000..e9567ef36ff
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tools/ports/liblzma.py
|
||||||
|
@@ -0,0 +1,160 @@
|
||||||
|
+# Copyright 2020 The Emscripten Authors. All rights reserved.
|
||||||
|
+# Emscripten is available under two separate licenses, the MIT license and the
|
||||||
|
+# University of Illinois/NCSA Open Source License. Both these licenses can be
|
||||||
|
+# found in the LICENSE file.
|
||||||
|
+
|
||||||
|
+import os
|
||||||
|
+import shutil
|
||||||
|
+
|
||||||
|
+VERSION = '5.2.5'
|
||||||
|
+HASH = '7443674247deda2935220fbc4dfc7665e5bb5a260be8ad858c8bd7d7b9f0f868f04ea45e62eb17c0a5e6a2de7c7500ad2d201e2d668c48ca29bd9eea5a73a3ce'
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def needed(settings):
|
||||||
|
+ return settings.USE_LIBLZMA
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def get(ports, settings, shared):
|
||||||
|
+ libname = ports.get_lib_name('liblzma')
|
||||||
|
+ ports.fetch_project('liblzma', 'https://tukaani.org/xz/xz-' + VERSION + '.tar.gz', 'xz-' + VERSION, sha512hash=HASH)
|
||||||
|
+
|
||||||
|
+ def create():
|
||||||
|
+ ports.clear_project_build('liblzma')
|
||||||
|
+
|
||||||
|
+ source_path = os.path.join(ports.get_dir(), 'liblzma', 'xz-' + VERSION)
|
||||||
|
+ dest_path = os.path.join(ports.get_build_dir(), 'liblzma')
|
||||||
|
+
|
||||||
|
+ shared.try_delete(dest_path)
|
||||||
|
+ os.makedirs(dest_path)
|
||||||
|
+ shutil.rmtree(dest_path, ignore_errors=True)
|
||||||
|
+ shutil.copytree(source_path, dest_path)
|
||||||
|
+
|
||||||
|
+ build_flags = ['-DHAVE_CONFIG_H', '-DTUKLIB_SYMBOL_PREFIX=lzma_', '-fvisibility=hidden']
|
||||||
|
+ exclude_dirs = ['xzdec', 'xz', 'lzmainfo']
|
||||||
|
+ exclude_files = ['crc32_small.c', 'crc64_small.c', 'crc32_tablegen.c', 'crc64_tablegen.c', 'price_tablegen.c', 'fastpos_tablegen.c'
|
||||||
|
+ 'tuklib_exit.c', 'tuklib_mbstr_fw.c', 'tuklib_mbstr_width.c', 'tuklib_open_stdxxx.c', 'tuklib_progname.c']
|
||||||
|
+ include_dirs_rel = ['../common', 'api', 'common', 'check', 'lz', 'rangecoder', 'lzma', 'delta', 'simple']
|
||||||
|
+
|
||||||
|
+ open(os.path.join(dest_path, 'src', 'config.h'), 'w').write(config_h)
|
||||||
|
+
|
||||||
|
+ final = os.path.join(dest_path, libname)
|
||||||
|
+ include_dirs = [os.path.join(dest_path, 'src', 'liblzma', p) for p in include_dirs_rel]
|
||||||
|
+ ports.build_port(os.path.join(dest_path, 'src'), final, flags=build_flags, exclude_dirs=exclude_dirs, exclude_files=exclude_files, includes=include_dirs)
|
||||||
|
+
|
||||||
|
+ ports.install_headers(os.path.join(dest_path, 'src', 'liblzma', 'api'), 'lzma.h')
|
||||||
|
+ ports.install_headers(os.path.join(dest_path, 'src', 'liblzma', 'api', 'lzma'), '*.h', 'lzma')
|
||||||
|
+
|
||||||
|
+ return final
|
||||||
|
+
|
||||||
|
+ return [shared.Cache.get(libname, create, what='port')]
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def clear(ports, settings, shared):
|
||||||
|
+ shared.Cache.erase_file(ports.get_lib_name('liblzma'))
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def process_args(ports):
|
||||||
|
+ return []
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def show():
|
||||||
|
+ return 'liblzma (USE_LIBLZMA=1; public domain)'
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+config_h = r'''
|
||||||
|
+#define ASSUME_RAM 128
|
||||||
|
+#define ENABLE_NLS 1
|
||||||
|
+#define HAVE_CHECK_CRC32 1
|
||||||
|
+#define HAVE_CHECK_CRC64 1
|
||||||
|
+#define HAVE_CHECK_SHA256 1
|
||||||
|
+#define HAVE_CLOCK_GETTIME 1
|
||||||
|
+#define HAVE_DCGETTEXT 1
|
||||||
|
+#define HAVE_DECL_CLOCK_MONOTONIC 1
|
||||||
|
+#define HAVE_DECL_PROGRAM_INVOCATION_NAME 1
|
||||||
|
+#define HAVE_DECODERS 1
|
||||||
|
+#define HAVE_DECODER_ARM 1
|
||||||
|
+#define HAVE_DECODER_ARMTHUMB 1
|
||||||
|
+#define HAVE_DECODER_DELTA 1
|
||||||
|
+#define HAVE_DECODER_IA64 1
|
||||||
|
+#define HAVE_DECODER_LZMA1 1
|
||||||
|
+#define HAVE_DECODER_LZMA2 1
|
||||||
|
+#define HAVE_DECODER_POWERPC 1
|
||||||
|
+#define HAVE_DECODER_SPARC 1
|
||||||
|
+#define HAVE_DECODER_X86 1
|
||||||
|
+#define HAVE_DLFCN_H 1
|
||||||
|
+#define HAVE_ENCODERS 1
|
||||||
|
+#define HAVE_ENCODER_ARM 1
|
||||||
|
+#define HAVE_ENCODER_ARMTHUMB 1
|
||||||
|
+#define HAVE_ENCODER_DELTA 1
|
||||||
|
+#define HAVE_ENCODER_IA64 1
|
||||||
|
+#define HAVE_ENCODER_LZMA1 1
|
||||||
|
+#define HAVE_ENCODER_LZMA2 1
|
||||||
|
+#define HAVE_ENCODER_POWERPC 1
|
||||||
|
+#define HAVE_ENCODER_SPARC 1
|
||||||
|
+#define HAVE_ENCODER_X86 1
|
||||||
|
+#define HAVE_FCNTL_H 1
|
||||||
|
+#define HAVE_FUTIMENS 1
|
||||||
|
+#define HAVE_GETOPT_H 1
|
||||||
|
+#define HAVE_GETOPT_LONG 1
|
||||||
|
+#define HAVE_GETTEXT 1
|
||||||
|
+#define HAVE_IMMINTRIN_H 1
|
||||||
|
+#define HAVE_INTTYPES_H 1
|
||||||
|
+#define HAVE_LIMITS_H 1
|
||||||
|
+#define HAVE_MBRTOWC 1
|
||||||
|
+#define HAVE_MEMORY_H 1
|
||||||
|
+#define HAVE_MF_BT2 1
|
||||||
|
+#define HAVE_MF_BT3 1
|
||||||
|
+#define HAVE_MF_BT4 1
|
||||||
|
+#define HAVE_MF_HC3 1
|
||||||
|
+#define HAVE_MF_HC4 1
|
||||||
|
+#define HAVE_OPTRESET 1
|
||||||
|
+#define HAVE_POSIX_FADVISE 1
|
||||||
|
+#define HAVE_PTHREAD_CONDATTR_SETCLOCK 1
|
||||||
|
+#define HAVE_PTHREAD_PRIO_INHERIT 1
|
||||||
|
+#define HAVE_STDBOOL_H 1
|
||||||
|
+#define HAVE_STDINT_H 1
|
||||||
|
+#define HAVE_STDLIB_H 1
|
||||||
|
+#define HAVE_STRINGS_H 1
|
||||||
|
+#define HAVE_STRING_H 1
|
||||||
|
+#define HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC 1
|
||||||
|
+#define HAVE_SYS_PARAM_H 1
|
||||||
|
+#define HAVE_SYS_STAT_H 1
|
||||||
|
+#define HAVE_SYS_TIME_H 1
|
||||||
|
+#define HAVE_SYS_TYPES_H 1
|
||||||
|
+#define HAVE_UINTPTR_T 1
|
||||||
|
+#define HAVE_UNISTD_H 1
|
||||||
|
+#define HAVE_VISIBILITY 1
|
||||||
|
+#define HAVE_WCWIDTH 1
|
||||||
|
+#define HAVE__BOOL 1
|
||||||
|
+#define HAVE___BUILTIN_ASSUME_ALIGNED 1
|
||||||
|
+#define HAVE___BUILTIN_BSWAPXX 1
|
||||||
|
+#define MYTHREAD_POSIX 1
|
||||||
|
+#define NDEBUG 1
|
||||||
|
+#define PACKAGE "xz"
|
||||||
|
+#define PACKAGE_BUGREPORT "lasse.collin@tukaani.org"
|
||||||
|
+#define PACKAGE_NAME "XZ Utils"
|
||||||
|
+#define PACKAGE_STRING "XZ Utils 5.2.5"
|
||||||
|
+#define PACKAGE_TARNAME "xz"
|
||||||
|
+#define PACKAGE_VERSION "5.2.5"
|
||||||
|
+#define SIZEOF_SIZE_T 4
|
||||||
|
+#define STDC_HEADERS 1
|
||||||
|
+#define TUKLIB_CPUCORES_SYSCONF 1
|
||||||
|
+#define TUKLIB_FAST_UNALIGNED_ACCESS 1
|
||||||
|
+#define TUKLIB_PHYSMEM_SYSCONF 1
|
||||||
|
+#ifndef _ALL_SOURCE
|
||||||
|
+# define _ALL_SOURCE 1
|
||||||
|
+#endif
|
||||||
|
+#ifndef _GNU_SOURCE
|
||||||
|
+# define _GNU_SOURCE 1
|
||||||
|
+#endif
|
||||||
|
+#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||||
|
+# define _POSIX_PTHREAD_SEMANTICS 1
|
||||||
|
+#endif
|
||||||
|
+#ifndef _TANDEM_SOURCE
|
||||||
|
+# define _TANDEM_SOURCE 1
|
||||||
|
+#endif
|
||||||
|
+#ifndef __EXTENSIONS__
|
||||||
|
+# define __EXTENSIONS__ 1
|
||||||
|
+#endif
|
||||||
|
+#define VERSION "5.2.5"
|
||||||
|
+'''
|
BIN
os/emscripten/loading.png
Executable file
BIN
os/emscripten/loading.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
93
os/emscripten/pre.js
Normal file
93
os/emscripten/pre.js
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
Module.arguments.push('-mnull', '-snull', '-vsdl:relative_mode');
|
||||||
|
Module['websocket'] = { url: function(host, port, proto) {
|
||||||
|
/* openttd.org hosts a WebSocket proxy for the content service. */
|
||||||
|
if (host == "content.openttd.org" && port == 3978 && proto == "tcp") {
|
||||||
|
return "wss://content.openttd.org/";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Everything else just tries to make a default WebSocket connection.
|
||||||
|
* If you run your own server you can setup your own WebSocket proxy in
|
||||||
|
* front of it and let people connect to your server via the proxy. You
|
||||||
|
* are best to add another "if" statement as above for this. */
|
||||||
|
return null;
|
||||||
|
} };
|
||||||
|
|
||||||
|
Module.preRun.push(function() {
|
||||||
|
personal_dir = '/home/web_user/.openttd';
|
||||||
|
content_download_dir = personal_dir + '/content_download'
|
||||||
|
|
||||||
|
/* Because of the "-c" above, all user-data is stored in /user_data. */
|
||||||
|
FS.mkdir(personal_dir);
|
||||||
|
FS.mount(IDBFS, {}, personal_dir);
|
||||||
|
|
||||||
|
Module.addRunDependency('syncfs');
|
||||||
|
FS.syncfs(true, function (err) {
|
||||||
|
/* FS.mkdir() tends to fail if parent folders do not exist. */
|
||||||
|
if (!FS.analyzePath(content_download_dir).exists) {
|
||||||
|
FS.mkdir(content_download_dir);
|
||||||
|
}
|
||||||
|
if (!FS.analyzePath(content_download_dir + '/baseset').exists) {
|
||||||
|
FS.mkdir(content_download_dir + '/baseset');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the OpenGFX baseset is already downloaded. */
|
||||||
|
if (!FS.analyzePath(content_download_dir + '/baseset/opengfx-0.6.0.tar').exists) {
|
||||||
|
window.openttd_downloaded_opengfx = true;
|
||||||
|
FS.createPreloadedFile(content_download_dir + '/baseset', 'opengfx-0.6.0.tar', 'https://installer.cdn.openttd.org/emscripten/opengfx-0.6.0.tar', true, true);
|
||||||
|
} else {
|
||||||
|
/* Fake dependency increase, so the counter is stable. */
|
||||||
|
Module.addRunDependency('opengfx');
|
||||||
|
Module.removeRunDependency('opengfx');
|
||||||
|
}
|
||||||
|
|
||||||
|
Module.removeRunDependency('syncfs');
|
||||||
|
});
|
||||||
|
|
||||||
|
window.openttd_syncfs_shown_warning = false;
|
||||||
|
window.openttd_syncfs = function() {
|
||||||
|
/* Copy the virtual FS to the persistent storage. */
|
||||||
|
FS.syncfs(false, function (err) { });
|
||||||
|
|
||||||
|
/* On first time, warn the user about the volatile behaviour of
|
||||||
|
* persistent storage. */
|
||||||
|
if (!window.openttd_syncfs_shown_warning) {
|
||||||
|
window.openttd_syncfs_shown_warning = true;
|
||||||
|
Module.onWarningFs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.openttd_exit = function() {
|
||||||
|
Module.onExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.openttd_abort = function() {
|
||||||
|
Module.onAbort();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.openttd_server_list = function() {
|
||||||
|
add_server = Module.cwrap("em_openttd_add_server", null, ["string", "number"]);
|
||||||
|
|
||||||
|
/* Add servers that support WebSocket here. Example:
|
||||||
|
* add_server("localhost", 3979); */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* https://github.com/emscripten-core/emscripten/pull/12995 implements this
|
||||||
|
* properly. Till that time, we use a polyfill. */
|
||||||
|
SOCKFS.websocket_sock_ops.createPeer_ = SOCKFS.websocket_sock_ops.createPeer;
|
||||||
|
SOCKFS.websocket_sock_ops.createPeer = function(sock, addr, port)
|
||||||
|
{
|
||||||
|
let func = Module['websocket']['url'];
|
||||||
|
Module['websocket']['url'] = func(addr, port, (sock.type == 2) ? 'udp' : 'tcp');
|
||||||
|
let ret = SOCKFS.websocket_sock_ops.createPeer_(sock, addr, port);
|
||||||
|
Module['websocket']['url'] = func;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Module.postRun.push(function() {
|
||||||
|
/* Check if we downloaded OpenGFX; if so, sync the virtual FS back to the
|
||||||
|
* IDBFS so OpenGFX is stored persistent. */
|
||||||
|
if (window['openttd_downloaded_opengfx']) {
|
||||||
|
FS.syncfs(false, function (err) { });
|
||||||
|
}
|
||||||
|
});
|
205
os/emscripten/shell.html
Normal file
205
os/emscripten/shell.html
Normal file
File diff suppressed because one or more lines are too long
@@ -9075,7 +9075,7 @@ ERROR: IsEnd() is invalid as Begin() is never called
|
|||||||
--Accounting--
|
--Accounting--
|
||||||
GetCosts(): -5947
|
GetCosts(): -5947
|
||||||
Should be: -5947
|
Should be: -5947
|
||||||
GetName(): Road Vehicle 1
|
GetName(): Road Vehicle #1
|
||||||
SetName(): true
|
SetName(): true
|
||||||
GetName(): MyVehicleName
|
GetName(): MyVehicleName
|
||||||
CloneVehicle(): 13
|
CloneVehicle(): 13
|
||||||
|
23
src/3rdparty/optional/LICENSE_1_0.txt
vendored
23
src/3rdparty/optional/LICENSE_1_0.txt
vendored
@@ -1,23 +0,0 @@
|
|||||||
Boost Software License - Version 1.0 - August 17th, 2003
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person or organization
|
|
||||||
obtaining a copy of the software and accompanying documentation covered by
|
|
||||||
this license (the "Software") to use, reproduce, display, distribute,
|
|
||||||
execute, and transmit the Software, and to prepare derivative works of the
|
|
||||||
Software, and to permit third-parties to whom the Software is furnished to
|
|
||||||
do so, all subject to the following:
|
|
||||||
|
|
||||||
The copyright notices in the Software and this entire statement, including
|
|
||||||
the above license grant, this restriction and the following disclaimer,
|
|
||||||
must be included in all copies of the Software, in whole or in part, and
|
|
||||||
all derivative works of the Software, unless such copies or derivative
|
|
||||||
works are solely in the form of machine-executable object code generated by
|
|
||||||
a source language processor.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
|
||||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
|
||||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
1066
src/3rdparty/optional/optional.hpp
vendored
1066
src/3rdparty/optional/optional.hpp
vendored
File diff suppressed because it is too large
Load Diff
33
src/3rdparty/optional/ottd_optional.h
vendored
33
src/3rdparty/optional/ottd_optional.h
vendored
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of OpenTTD.
|
|
||||||
* OpenTTD 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, version 2.
|
|
||||||
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @file ottd_optional.h Header to select between native. */
|
|
||||||
|
|
||||||
#ifndef OTTD_OPTIONAL_H
|
|
||||||
#define OTTD_OPTIONAL_H
|
|
||||||
|
|
||||||
#if defined(__has_include)
|
|
||||||
# if __has_include(<version>)
|
|
||||||
# include <version>
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (__cplusplus >= 201703L) || (defined(__cpp_lib_optional) && __cpp_lib_optional >= 201606L)
|
|
||||||
|
|
||||||
/* Native std::optional. */
|
|
||||||
#include <optional>
|
|
||||||
namespace opt = std;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* No std::optional, use local copy instead. */
|
|
||||||
#include "optional.hpp"
|
|
||||||
namespace opt = std::experimental;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* OTTD_OPTIONAL_H */
|
|
@@ -1,3 +1,11 @@
|
|||||||
|
add_subdirectory(script)
|
||||||
|
add_subdirectory(settingsgen)
|
||||||
|
add_subdirectory(strgen)
|
||||||
|
|
||||||
|
if(OPTION_TOOLS_ONLY)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
add_subdirectory(3rdparty)
|
add_subdirectory(3rdparty)
|
||||||
add_subdirectory(ai)
|
add_subdirectory(ai)
|
||||||
add_subdirectory(blitter)
|
add_subdirectory(blitter)
|
||||||
@@ -11,11 +19,8 @@ add_subdirectory(network)
|
|||||||
add_subdirectory(os)
|
add_subdirectory(os)
|
||||||
add_subdirectory(pathfinder)
|
add_subdirectory(pathfinder)
|
||||||
add_subdirectory(saveload)
|
add_subdirectory(saveload)
|
||||||
add_subdirectory(script)
|
|
||||||
add_subdirectory(settingsgen)
|
|
||||||
add_subdirectory(sound)
|
add_subdirectory(sound)
|
||||||
add_subdirectory(spriteloader)
|
add_subdirectory(spriteloader)
|
||||||
add_subdirectory(strgen)
|
|
||||||
add_subdirectory(table)
|
add_subdirectory(table)
|
||||||
add_subdirectory(video)
|
add_subdirectory(video)
|
||||||
add_subdirectory(widgets)
|
add_subdirectory(widgets)
|
||||||
|
@@ -55,15 +55,15 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetch_metadata("shortname");
|
fetch_metadata("shortname");
|
||||||
for (uint i = 0; item->value.value()[i] != '\0' && i < 4; i++) {
|
for (uint i = 0; (*item->value)[i] != '\0' && i < 4; i++) {
|
||||||
this->shortname |= ((uint8)item->value.value()[i]) << (i * 8);
|
this->shortname |= ((uint8)(*item->value)[i]) << (i * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch_metadata("version");
|
fetch_metadata("version");
|
||||||
this->version = atoi(item->value->c_str());
|
this->version = atoi(item->value->c_str());
|
||||||
|
|
||||||
item = metadata->GetItem("fallback", false);
|
item = metadata->GetItem("fallback", false);
|
||||||
this->fallback = (item != nullptr && item->value && item->value.value() != "0" && item->value.value() != "false");
|
this->fallback = (item != nullptr && item->value && *item->value != "0" && *item->value != "false");
|
||||||
|
|
||||||
/* For each of the file types we want to find the file, MD5 checksums and warning messages. */
|
/* For each of the file types we want to find the file, MD5 checksums and warning messages. */
|
||||||
IniGroup *files = ini->GetGroup("files");
|
IniGroup *files = ini->GetGroup("files");
|
||||||
|
@@ -442,8 +442,7 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
|
|||||||
/* Re-check bridge building possibility is initial bridge builindg query indicated a bridge type dependent failure */
|
/* Re-check bridge building possibility is initial bridge builindg query indicated a bridge type dependent failure */
|
||||||
if (query_per_bridge_type && DoCommand(end, start, type | brd_type, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)) | DC_QUERY_COST, CMD_BUILD_BRIDGE).Failed()) continue;
|
if (query_per_bridge_type && DoCommand(end, start, type | brd_type, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)) | DC_QUERY_COST, CMD_BUILD_BRIDGE).Failed()) continue;
|
||||||
/* bridge is accepted, add to list */
|
/* bridge is accepted, add to list */
|
||||||
/*C++17: BuildBridgeData &item = */ bl->emplace_back();
|
BuildBridgeData &item = bl->emplace_back();
|
||||||
BuildBridgeData &item = bl->back();
|
|
||||||
item.index = brd_type;
|
item.index = brd_type;
|
||||||
item.spec = GetBridgeSpec(brd_type);
|
item.spec = GetBridgeSpec(brd_type);
|
||||||
/* Add to terraforming & bulldozing costs the cost of the
|
/* Add to terraforming & bulldozing costs the cost of the
|
||||||
|
@@ -142,8 +142,7 @@ struct SmallMap : std::vector<std::pair<T, U> > {
|
|||||||
for (uint i = 0; i < std::vector<Pair>::size(); i++) {
|
for (uint i = 0; i < std::vector<Pair>::size(); i++) {
|
||||||
if (key == std::vector<Pair>::operator[](i).first) return std::vector<Pair>::operator[](i).second;
|
if (key == std::vector<Pair>::operator[](i).first) return std::vector<Pair>::operator[](i).second;
|
||||||
}
|
}
|
||||||
/*C++17: Pair &n = */ std::vector<Pair>::emplace_back();
|
Pair &n = std::vector<Pair>::emplace_back();
|
||||||
Pair &n = std::vector<Pair>::back();
|
|
||||||
n.first = key;
|
n.first = key;
|
||||||
return n.second;
|
return n.second;
|
||||||
}
|
}
|
||||||
|
@@ -26,14 +26,14 @@
|
|||||||
* | | | | | | | */
|
* | | | | | | | */
|
||||||
/** The original currency specifications. */
|
/** The original currency specifications. */
|
||||||
static const CurrencySpec origin_currency_specs[CURRENCY_END] = {
|
static const CurrencySpec origin_currency_specs[CURRENCY_END] = {
|
||||||
{ 1, "", CF_NOEURO, "\xC2\xA3", "", 0, STR_GAME_OPTIONS_CURRENCY_GBP }, ///< british pound
|
{ 1, "", CF_NOEURO, u8"\u00a3", "", 0, STR_GAME_OPTIONS_CURRENCY_GBP }, ///< british pound
|
||||||
{ 2, "", CF_NOEURO, "$", "", 0, STR_GAME_OPTIONS_CURRENCY_USD }, ///< american dollar
|
{ 2, "", CF_NOEURO, "$", "", 0, STR_GAME_OPTIONS_CURRENCY_USD }, ///< american dollar
|
||||||
{ 2, "", CF_ISEURO, "\xE2\x82\xAC", "", 0, STR_GAME_OPTIONS_CURRENCY_EUR }, ///< euro
|
{ 2, "", CF_ISEURO, u8"\u20ac", "", 0, STR_GAME_OPTIONS_CURRENCY_EUR }, ///< euro
|
||||||
{ 220, "", CF_NOEURO, "\xC2\xA5", "", 0, STR_GAME_OPTIONS_CURRENCY_JPY }, ///< japanese yen
|
{ 220, "", CF_NOEURO, u8"\u00a5", "", 0, STR_GAME_OPTIONS_CURRENCY_JPY }, ///< japanese yen
|
||||||
{ 27, "", 2002, "", NBSP "S.", 1, STR_GAME_OPTIONS_CURRENCY_ATS }, ///< austrian schilling
|
{ 27, "", 2002, "", NBSP "S.", 1, STR_GAME_OPTIONS_CURRENCY_ATS }, ///< austrian schilling
|
||||||
{ 81, "", 2002, "BEF" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_BEF }, ///< belgian franc
|
{ 81, "", 2002, "BEF" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_BEF }, ///< belgian franc
|
||||||
{ 2, "", CF_NOEURO, "CHF" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_CHF }, ///< swiss franc
|
{ 2, "", CF_NOEURO, "CHF" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_CHF }, ///< swiss franc
|
||||||
{ 41, "", CF_NOEURO, "", NBSP "K\xC4\x8D", 1, STR_GAME_OPTIONS_CURRENCY_CZK }, ///< czech koruna
|
{ 41, "", CF_NOEURO, "", NBSP u8"K\u010d", 1, STR_GAME_OPTIONS_CURRENCY_CZK }, ///< czech koruna
|
||||||
{ 4, "", 2002, "DM" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_DEM }, ///< deutsche mark
|
{ 4, "", 2002, "DM" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_DEM }, ///< deutsche mark
|
||||||
{ 11, "", CF_NOEURO, "", NBSP "kr", 1, STR_GAME_OPTIONS_CURRENCY_DKK }, ///< danish krone
|
{ 11, "", CF_NOEURO, "", NBSP "kr", 1, STR_GAME_OPTIONS_CURRENCY_DKK }, ///< danish krone
|
||||||
{ 333, "", 2002, "Pts" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_ESP }, ///< spanish peseta
|
{ 333, "", 2002, "Pts" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_ESP }, ///< spanish peseta
|
||||||
@@ -45,7 +45,7 @@ static const CurrencySpec origin_currency_specs[CURRENCY_END] = {
|
|||||||
{ 3873, "", 2002, "", NBSP "L.", 1, STR_GAME_OPTIONS_CURRENCY_ITL }, ///< italian lira
|
{ 3873, "", 2002, "", NBSP "L.", 1, STR_GAME_OPTIONS_CURRENCY_ITL }, ///< italian lira
|
||||||
{ 4, "", 2002, "NLG" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_NLG }, ///< dutch gulden
|
{ 4, "", 2002, "NLG" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_NLG }, ///< dutch gulden
|
||||||
{ 12, "", CF_NOEURO, "", NBSP "Kr", 1, STR_GAME_OPTIONS_CURRENCY_NOK }, ///< norwegian krone
|
{ 12, "", CF_NOEURO, "", NBSP "Kr", 1, STR_GAME_OPTIONS_CURRENCY_NOK }, ///< norwegian krone
|
||||||
{ 6, "", CF_NOEURO, "", NBSP "z\xC5\x82", 1, STR_GAME_OPTIONS_CURRENCY_PLN }, ///< polish zloty
|
{ 6, "", CF_NOEURO, "", NBSP u8"z\u0142", 1, STR_GAME_OPTIONS_CURRENCY_PLN }, ///< polish zloty
|
||||||
{ 5, "", CF_NOEURO, "", NBSP "Lei", 1, STR_GAME_OPTIONS_CURRENCY_RON }, ///< romanian leu
|
{ 5, "", CF_NOEURO, "", NBSP "Lei", 1, STR_GAME_OPTIONS_CURRENCY_RON }, ///< romanian leu
|
||||||
{ 50, "", CF_NOEURO, "", NBSP "p", 1, STR_GAME_OPTIONS_CURRENCY_RUR }, ///< russian rouble
|
{ 50, "", CF_NOEURO, "", NBSP "p", 1, STR_GAME_OPTIONS_CURRENCY_RUR }, ///< russian rouble
|
||||||
{ 479, "", 2007, "", NBSP "SIT", 1, STR_GAME_OPTIONS_CURRENCY_SIT }, ///< slovenian tolar
|
{ 479, "", 2007, "", NBSP "SIT", 1, STR_GAME_OPTIONS_CURRENCY_SIT }, ///< slovenian tolar
|
||||||
@@ -55,7 +55,7 @@ static const CurrencySpec origin_currency_specs[CURRENCY_END] = {
|
|||||||
{ 4, "", CF_NOEURO, "R$" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_BRL }, ///< brazil real
|
{ 4, "", CF_NOEURO, "R$" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_BRL }, ///< brazil real
|
||||||
{ 31, "", 2011, "", NBSP "EEK", 1, STR_GAME_OPTIONS_CURRENCY_EEK }, ///< estonian krooni
|
{ 31, "", 2011, "", NBSP "EEK", 1, STR_GAME_OPTIONS_CURRENCY_EEK }, ///< estonian krooni
|
||||||
{ 4, "", 2015, "", NBSP "Lt", 1, STR_GAME_OPTIONS_CURRENCY_LTL }, ///< lithuanian litas
|
{ 4, "", 2015, "", NBSP "Lt", 1, STR_GAME_OPTIONS_CURRENCY_LTL }, ///< lithuanian litas
|
||||||
{ 1850, "", CF_NOEURO, "\xE2\x82\xA9", "", 0, STR_GAME_OPTIONS_CURRENCY_KRW }, ///< south korean won
|
{ 1850, "", CF_NOEURO, u8"\u20a9", "", 0, STR_GAME_OPTIONS_CURRENCY_KRW }, ///< south korean won
|
||||||
{ 13, "", CF_NOEURO, "R" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_ZAR }, ///< south african rand
|
{ 13, "", CF_NOEURO, "R" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_ZAR }, ///< south african rand
|
||||||
{ 1, "", CF_NOEURO, "", "", 2, STR_GAME_OPTIONS_CURRENCY_CUSTOM }, ///< custom currency (add further languages below)
|
{ 1, "", CF_NOEURO, "", "", 2, STR_GAME_OPTIONS_CURRENCY_CUSTOM }, ///< custom currency (add further languages below)
|
||||||
{ 3, "", CF_NOEURO, "", NBSP "GEL", 1, STR_GAME_OPTIONS_CURRENCY_GEL }, ///< Georgian Lari
|
{ 3, "", CF_NOEURO, "", NBSP "GEL", 1, STR_GAME_OPTIONS_CURRENCY_GEL }, ///< Georgian Lari
|
||||||
@@ -63,9 +63,9 @@ static const CurrencySpec origin_currency_specs[CURRENCY_END] = {
|
|||||||
{ 80, "", CF_NOEURO, "", NBSP "rub", 1, STR_GAME_OPTIONS_CURRENCY_RUB }, ///< New Russian Ruble
|
{ 80, "", CF_NOEURO, "", NBSP "rub", 1, STR_GAME_OPTIONS_CURRENCY_RUB }, ///< New Russian Ruble
|
||||||
{ 24, "", CF_NOEURO, "$", "", 0, STR_GAME_OPTIONS_CURRENCY_MXN }, ///< Mexican peso
|
{ 24, "", CF_NOEURO, "$", "", 0, STR_GAME_OPTIONS_CURRENCY_MXN }, ///< Mexican peso
|
||||||
{ 40, "", CF_NOEURO, "NTD" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_NTD }, ///< new taiwan dollar
|
{ 40, "", CF_NOEURO, "NTD" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_NTD }, ///< new taiwan dollar
|
||||||
{ 8, "", CF_NOEURO, "\xC2\xA5", "", 0, STR_GAME_OPTIONS_CURRENCY_CNY }, ///< chinese renminbi
|
{ 8, "", CF_NOEURO, u8"\u00a5", "", 0, STR_GAME_OPTIONS_CURRENCY_CNY }, ///< chinese renminbi
|
||||||
{ 10, "", CF_NOEURO, "HKD" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_HKD }, ///< hong kong dollar
|
{ 10, "", CF_NOEURO, "HKD" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_HKD }, ///< hong kong dollar
|
||||||
{ 90, "", CF_NOEURO, "\xE2\x82\xB9", "", 0, STR_GAME_OPTIONS_CURRENCY_INR }, ///< Indian Rupee
|
{ 90, "", CF_NOEURO, u8"\u20b9", "", 0, STR_GAME_OPTIONS_CURRENCY_INR }, ///< Indian Rupee
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Array of currencies used by the system */
|
/** Array of currencies used by the system */
|
||||||
|
@@ -496,8 +496,7 @@ void EngineOverrideManager::ResetToDefaultMapping()
|
|||||||
this->clear();
|
this->clear();
|
||||||
for (VehicleType type = VEH_TRAIN; type <= VEH_AIRCRAFT; type++) {
|
for (VehicleType type = VEH_TRAIN; type <= VEH_AIRCRAFT; type++) {
|
||||||
for (uint internal_id = 0; internal_id < _engine_counts[type]; internal_id++) {
|
for (uint internal_id = 0; internal_id < _engine_counts[type]; internal_id++) {
|
||||||
/*C++17: EngineIDMapping &eid = */ this->emplace_back();
|
EngineIDMapping &eid = this->emplace_back();
|
||||||
EngineIDMapping &eid = this->back();
|
|
||||||
eid.type = type;
|
eid.type = type;
|
||||||
eid.grfid = INVALID_GRFID;
|
eid.grfid = INVALID_GRFID;
|
||||||
eid.internal_id = internal_id;
|
eid.internal_id = internal_id;
|
||||||
|
@@ -126,8 +126,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline FiosItem *Append()
|
inline FiosItem *Append()
|
||||||
{
|
{
|
||||||
/*C++17: return &*/ this->files.emplace_back();
|
return &this->files.emplace_back();
|
||||||
return &this->files.back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -26,7 +26,6 @@
|
|||||||
#include "safeguards.h"
|
#include "safeguards.h"
|
||||||
|
|
||||||
static const int ASCII_LETTERSTART = 32; ///< First printable ASCII letter.
|
static const int ASCII_LETTERSTART = 32; ///< First printable ASCII letter.
|
||||||
static const int MAX_FONT_SIZE = 72; ///< Maximum font size.
|
|
||||||
|
|
||||||
/** Default heights for the different sizes of fonts. */
|
/** Default heights for the different sizes of fonts. */
|
||||||
static const int _default_font_height[FS_END] = {10, 6, 18, 10};
|
static const int _default_font_height[FS_END] = {10, 6, 18, 10};
|
||||||
@@ -200,6 +199,8 @@ void UpdateFontHeightCache()
|
|||||||
|
|
||||||
FreeTypeSettings _freetype;
|
FreeTypeSettings _freetype;
|
||||||
|
|
||||||
|
static const int MAX_FONT_SIZE = 72; ///< Maximum font size.
|
||||||
|
|
||||||
static const byte FACE_COLOUR = 1;
|
static const byte FACE_COLOUR = 1;
|
||||||
static const byte SHADOW_COLOUR = 2;
|
static const byte SHADOW_COLOUR = 2;
|
||||||
|
|
||||||
|
24
src/gfx.cpp
24
src/gfx.cpp
@@ -2090,6 +2090,30 @@ void SetAnimatedMouseCursor(const AnimCursor *table)
|
|||||||
SwitchAnimatedCursor();
|
SwitchAnimatedCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update cursor position on mouse movement for relative modes.
|
||||||
|
* @param delta_x How much change in the X position.
|
||||||
|
* @param delta_y How much change in the Y position.
|
||||||
|
*/
|
||||||
|
void CursorVars::UpdateCursorPositionRelative(int delta_x, int delta_y)
|
||||||
|
{
|
||||||
|
if (this->fix_at) {
|
||||||
|
this->delta.x = delta_x;
|
||||||
|
this->delta.y = delta_y;
|
||||||
|
} else {
|
||||||
|
int last_position_x = this->pos.x;
|
||||||
|
int last_position_y = this->pos.y;
|
||||||
|
|
||||||
|
this->pos.x = Clamp(this->pos.x + delta_x, 0, _cur_resolution.width - 1);
|
||||||
|
this->pos.y = Clamp(this->pos.y + delta_y, 0, _cur_resolution.height - 1);
|
||||||
|
|
||||||
|
this->delta.x = last_position_x - this->pos.x;
|
||||||
|
this->delta.y = last_position_y - this->pos.y;
|
||||||
|
|
||||||
|
this->dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update cursor position on mouse movement.
|
* Update cursor position on mouse movement.
|
||||||
* @param x New X position.
|
* @param x New X position.
|
||||||
|
@@ -144,6 +144,7 @@ struct CursorVars {
|
|||||||
/* Drag data */
|
/* Drag data */
|
||||||
bool vehchain; ///< vehicle chain is dragged
|
bool vehchain; ///< vehicle chain is dragged
|
||||||
|
|
||||||
|
void UpdateCursorPositionRelative(int delta_x, int delta_y);
|
||||||
bool UpdateCursorPosition(int x, int y, bool queued_warp);
|
bool UpdateCursorPosition(int x, int y, bool queued_warp);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -163,7 +164,9 @@ struct DrawPixelInfo {
|
|||||||
union Colour {
|
union Colour {
|
||||||
uint32 data; ///< Conversion of the channel information to a 32 bit number.
|
uint32 data; ///< Conversion of the channel information to a 32 bit number.
|
||||||
struct {
|
struct {
|
||||||
#if TTD_ENDIAN == TTD_BIG_ENDIAN
|
#if defined(__EMSCRIPTEN__)
|
||||||
|
uint8 r, g, b, a; ///< colour channels as used in browsers
|
||||||
|
#elif TTD_ENDIAN == TTD_BIG_ENDIAN
|
||||||
uint8 a, r, g, b; ///< colour channels in BE order
|
uint8 a, r, g, b; ///< colour channels in BE order
|
||||||
#else
|
#else
|
||||||
uint8 b, g, r, a; ///< colour channels in LE order
|
uint8 b, g, r, a; ///< colour channels in LE order
|
||||||
@@ -178,7 +181,9 @@ union Colour {
|
|||||||
* @param a The channel for the alpha/transparency.
|
* @param a The channel for the alpha/transparency.
|
||||||
*/
|
*/
|
||||||
Colour(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) :
|
Colour(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) :
|
||||||
#if TTD_ENDIAN == TTD_BIG_ENDIAN
|
#if defined(__EMSCRIPTEN__)
|
||||||
|
r(r), g(g), b(b), a(a)
|
||||||
|
#elif TTD_ENDIAN == TTD_BIG_ENDIAN
|
||||||
a(a), r(r), g(g), b(b)
|
a(a), r(r), g(g), b(b)
|
||||||
#else
|
#else
|
||||||
b(b), g(g), r(r), a(a)
|
b(b), g(g), r(r), a(a)
|
||||||
|
@@ -504,11 +504,11 @@ bool GraphicsSet::FillSetDetails(IniFile *ini, const char *path, const char *ful
|
|||||||
IniItem *item;
|
IniItem *item;
|
||||||
|
|
||||||
fetch_metadata("palette");
|
fetch_metadata("palette");
|
||||||
this->palette = (item->value.value()[0] == 'D' || item->value.value()[0] == 'd') ? PAL_DOS : PAL_WINDOWS;
|
this->palette = ((*item->value)[0] == 'D' || (*item->value)[0] == 'd') ? PAL_DOS : PAL_WINDOWS;
|
||||||
|
|
||||||
/* Get optional blitter information. */
|
/* Get optional blitter information. */
|
||||||
item = metadata->GetItem("blitter", false);
|
item = metadata->GetItem("blitter", false);
|
||||||
this->blitter = (item != nullptr && item->value.value()[0] == '3') ? BLT_32BPP : BLT_8BPP;
|
this->blitter = (item != nullptr && (*item->value)[0] == '3') ? BLT_32BPP : BLT_8BPP;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -473,6 +473,8 @@ CommandCost CmdAlterGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
|||||||
InvalidateWindowData(WC_REPLACE_VEHICLE, g->vehicle_type, 1);
|
InvalidateWindowData(WC_REPLACE_VEHICLE, g->vehicle_type, 1);
|
||||||
InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).Pack());
|
InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).Pack());
|
||||||
InvalidateWindowData(WC_COMPANY_COLOUR, g->owner, g->vehicle_type);
|
InvalidateWindowData(WC_COMPANY_COLOUR, g->owner, g->vehicle_type);
|
||||||
|
InvalidateWindowClassesData(WC_VEHICLE_VIEW);
|
||||||
|
InvalidateWindowClassesData(WC_VEHICLE_DETAILS);
|
||||||
InvalidateWindowData(WC_TEMPLATEGUI_MAIN, 0, 0, 0);
|
InvalidateWindowData(WC_TEMPLATEGUI_MAIN, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,6 +611,8 @@ CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, u
|
|||||||
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
|
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
|
||||||
SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
|
SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
|
||||||
InvalidateWindowData(GetWindowClassForVehicleType(v->type), VehicleListIdentifier(VL_GROUP_LIST, v->type, _current_company).Pack());
|
InvalidateWindowData(GetWindowClassForVehicleType(v->type), VehicleListIdentifier(VL_GROUP_LIST, v->type, _current_company).Pack());
|
||||||
|
InvalidateWindowData(WC_VEHICLE_VIEW, v->index);
|
||||||
|
InvalidateWindowData(WC_VEHICLE_DETAILS, v->index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CommandCost();
|
return CommandCost();
|
||||||
|
@@ -2633,8 +2633,7 @@ struct IndustryCargoesWindow : public Window {
|
|||||||
_displayed_industries.set(it);
|
_displayed_industries.set(it);
|
||||||
|
|
||||||
this->fields.clear();
|
this->fields.clear();
|
||||||
/*C++17: CargoesRow &row = */ this->fields.emplace_back();
|
CargoesRow &row = this->fields.emplace_back();
|
||||||
CargoesRow &row = this->fields.back();
|
|
||||||
row.columns[0].MakeHeader(STR_INDUSTRY_CARGOES_PRODUCERS);
|
row.columns[0].MakeHeader(STR_INDUSTRY_CARGOES_PRODUCERS);
|
||||||
row.columns[1].MakeEmpty(CFT_SMALL_EMPTY);
|
row.columns[1].MakeEmpty(CFT_SMALL_EMPTY);
|
||||||
row.columns[2].MakeEmpty(CFT_SMALL_EMPTY);
|
row.columns[2].MakeEmpty(CFT_SMALL_EMPTY);
|
||||||
@@ -2649,8 +2648,7 @@ struct IndustryCargoesWindow : public Window {
|
|||||||
int num_cust = CountMatchingAcceptingIndustries(central_sp->produced_cargo, lengthof(central_sp->produced_cargo)) + houses_accept;
|
int num_cust = CountMatchingAcceptingIndustries(central_sp->produced_cargo, lengthof(central_sp->produced_cargo)) + houses_accept;
|
||||||
int num_indrows = max(3, max(num_supp, num_cust)); // One is needed for the 'it' industry, and 2 for the cargo labels.
|
int num_indrows = max(3, max(num_supp, num_cust)); // One is needed for the 'it' industry, and 2 for the cargo labels.
|
||||||
for (int i = 0; i < num_indrows; i++) {
|
for (int i = 0; i < num_indrows; i++) {
|
||||||
/*C++17: CargoesRow &row = */ this->fields.emplace_back();
|
CargoesRow &row = this->fields.emplace_back();
|
||||||
CargoesRow &row = this->fields.back();
|
|
||||||
row.columns[0].MakeEmpty(CFT_EMPTY);
|
row.columns[0].MakeEmpty(CFT_EMPTY);
|
||||||
row.columns[1].MakeCargo(central_sp->accepts_cargo, lengthof(central_sp->accepts_cargo));
|
row.columns[1].MakeCargo(central_sp->accepts_cargo, lengthof(central_sp->accepts_cargo));
|
||||||
row.columns[2].MakeEmpty(CFT_EMPTY);
|
row.columns[2].MakeEmpty(CFT_EMPTY);
|
||||||
@@ -2713,8 +2711,7 @@ struct IndustryCargoesWindow : public Window {
|
|||||||
_displayed_industries.reset();
|
_displayed_industries.reset();
|
||||||
|
|
||||||
this->fields.clear();
|
this->fields.clear();
|
||||||
/*C++17: CargoesRow &row = */ this->fields.emplace_back();
|
CargoesRow &row = this->fields.emplace_back();
|
||||||
CargoesRow &row = this->fields.back();
|
|
||||||
row.columns[0].MakeHeader(STR_INDUSTRY_CARGOES_PRODUCERS);
|
row.columns[0].MakeHeader(STR_INDUSTRY_CARGOES_PRODUCERS);
|
||||||
row.columns[1].MakeEmpty(CFT_SMALL_EMPTY);
|
row.columns[1].MakeEmpty(CFT_SMALL_EMPTY);
|
||||||
row.columns[2].MakeHeader(STR_INDUSTRY_CARGOES_CUSTOMERS);
|
row.columns[2].MakeHeader(STR_INDUSTRY_CARGOES_CUSTOMERS);
|
||||||
@@ -2727,8 +2724,7 @@ struct IndustryCargoesWindow : public Window {
|
|||||||
int num_cust = CountMatchingAcceptingIndustries(&cid, 1) + houses_accept;
|
int num_cust = CountMatchingAcceptingIndustries(&cid, 1) + houses_accept;
|
||||||
int num_indrows = max(num_supp, num_cust);
|
int num_indrows = max(num_supp, num_cust);
|
||||||
for (int i = 0; i < num_indrows; i++) {
|
for (int i = 0; i < num_indrows; i++) {
|
||||||
/*C++17: CargoesRow &row = */ this->fields.emplace_back();
|
CargoesRow &row = this->fields.emplace_back();
|
||||||
CargoesRow &row = this->fields.back();
|
|
||||||
row.columns[0].MakeEmpty(CFT_EMPTY);
|
row.columns[0].MakeEmpty(CFT_EMPTY);
|
||||||
row.columns[1].MakeCargo(&cid, 1);
|
row.columns[1].MakeCargo(&cid, 1);
|
||||||
row.columns[2].MakeEmpty(CFT_EMPTY);
|
row.columns[2].MakeEmpty(CFT_EMPTY);
|
||||||
|
@@ -13,6 +13,9 @@
|
|||||||
#include "string_func.h"
|
#include "string_func.h"
|
||||||
#include "fileio_func.h"
|
#include "fileio_func.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
# include <emscripten.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500)
|
#if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500)
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
@@ -115,6 +118,10 @@ bool IniFile::SaveToDisk(const char *filename)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs());
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#include "fileio_type.h"
|
#include "fileio_type.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "3rdparty/optional/ottd_optional.h"
|
#include <optional>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ enum IniGroupType {
|
|||||||
struct IniItem {
|
struct IniItem {
|
||||||
IniItem *next; ///< The next item in this group
|
IniItem *next; ///< The next item in this group
|
||||||
std::string name; ///< The name of this item
|
std::string name; ///< The name of this item
|
||||||
opt::optional<std::string> value; ///< The value of this item
|
std::optional<std::string> value; ///< The value of this item
|
||||||
std::string comment; ///< The comment associated with this item
|
std::string comment; ///< The comment associated with this item
|
||||||
|
|
||||||
IniItem(struct IniGroup *parent, const std::string &name);
|
IniItem(struct IniGroup *parent, const std::string &name);
|
||||||
|
@@ -5825,10 +5825,10 @@ STR_INDUSTRY_NAME_SUGAR_MINE :Sugar Mine
|
|||||||
##id 0x6000
|
##id 0x6000
|
||||||
STR_SV_EMPTY :
|
STR_SV_EMPTY :
|
||||||
STR_SV_UNNAMED :Unnamed
|
STR_SV_UNNAMED :Unnamed
|
||||||
STR_SV_TRAIN_NAME :Train {COMMA}
|
STR_SV_TRAIN_NAME :Train #{COMMA}
|
||||||
STR_SV_ROAD_VEHICLE_NAME :Road Vehicle {COMMA}
|
STR_SV_ROAD_VEHICLE_NAME :Road Vehicle #{COMMA}
|
||||||
STR_SV_SHIP_NAME :Ship {COMMA}
|
STR_SV_SHIP_NAME :Ship #{COMMA}
|
||||||
STR_SV_AIRCRAFT_NAME :Aircraft {COMMA}
|
STR_SV_AIRCRAFT_NAME :Aircraft #{COMMA}
|
||||||
|
|
||||||
STR_SV_STNAME :{STRING1}
|
STR_SV_STNAME :{STRING1}
|
||||||
STR_SV_STNAME_NORTH :{STRING1} North
|
STR_SV_STNAME_NORTH :{STRING1} North
|
||||||
@@ -6135,6 +6135,7 @@ STR_FORMAT_BUOY_NAME :{TOWN} Buoy
|
|||||||
STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} Buoy #{COMMA}
|
STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} Buoy #{COMMA}
|
||||||
STR_FORMAT_COMPANY_NUM :(Company {COMMA})
|
STR_FORMAT_COMPANY_NUM :(Company {COMMA})
|
||||||
STR_FORMAT_GROUP_NAME :Group {COMMA}
|
STR_FORMAT_GROUP_NAME :Group {COMMA}
|
||||||
|
STR_FORMAT_GROUP_VEHICLE_NAME :{GROUP} #{COMMA}
|
||||||
STR_FORMAT_INDUSTRY_NAME :{TOWN} {STRING}
|
STR_FORMAT_INDUSTRY_NAME :{TOWN} {STRING}
|
||||||
STR_FORMAT_WAYPOINT_NAME :{TOWN} Waypoint
|
STR_FORMAT_WAYPOINT_NAME :{TOWN} Waypoint
|
||||||
STR_FORMAT_WAYPOINT_NAME_SERIAL :{TOWN} Waypoint #{COMMA}
|
STR_FORMAT_WAYPOINT_NAME_SERIAL :{TOWN} Waypoint #{COMMA}
|
||||||
|
134
src/misc_gui.cpp
134
src/misc_gui.cpp
@@ -450,73 +450,73 @@ static WindowDesc _about_desc(
|
|||||||
);
|
);
|
||||||
|
|
||||||
static const char * const _credits[] = {
|
static const char * const _credits[] = {
|
||||||
"Original design by Chris Sawyer",
|
u8"Original design by Chris Sawyer",
|
||||||
"Original graphics by Simon Foster",
|
u8"Original graphics by Simon Foster",
|
||||||
"",
|
u8"",
|
||||||
"The OpenTTD team (in alphabetical order):",
|
u8"The OpenTTD team (in alphabetical order):",
|
||||||
" Grzegorz Duczy\xC5\x84ski (adf88) - General coding (since 1.7.2)",
|
u8" Grzegorz Duczy\u0144ski (adf88) - General coding (since 1.7.2)",
|
||||||
" Albert Hofkamp (Alberth) - GUI expert (since 0.7)",
|
u8" Albert Hofkamp (Alberth) - GUI expert (since 0.7)",
|
||||||
" Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)",
|
u8" Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)",
|
||||||
" Ulf Hermann (fonsinchen) - Cargo Distribution (since 1.3)",
|
u8" Ulf Hermann (fonsinchen) - Cargo Distribution (since 1.3)",
|
||||||
" Christoph Elsenhans (frosch) - General coding (since 0.6)",
|
u8" Christoph Elsenhans (frosch) - General coding (since 0.6)",
|
||||||
" Lo\xC3\xAF""c Guilloux (glx) - General / Windows Expert (since 0.4.5)",
|
u8" Lo\u00efc Guilloux (glx) - General / Windows Expert (since 0.4.5)",
|
||||||
" Charles Pigott (LordAro) - General / Correctness police (since 1.9)",
|
u8" Charles Pigott (LordAro) - General / Correctness police (since 1.9)",
|
||||||
" Michael Lutz (michi_cc) - Path based signals (since 0.7)",
|
u8" Michael Lutz (michi_cc) - Path based signals (since 0.7)",
|
||||||
" Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)",
|
u8" Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)",
|
||||||
" Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)",
|
u8" Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)",
|
||||||
" Peter Nelson (peter1138) - Spiritual descendant from NewGRF gods (since 0.4.5)",
|
u8" Peter Nelson (peter1138) - Spiritual descendant from NewGRF gods (since 0.4.5)",
|
||||||
" Ingo von Borstel (planetmaker) - General, Support (since 1.1)",
|
u8" Ingo von Borstel (planetmaker) - General, Support (since 1.1)",
|
||||||
" Remko Bijker (Rubidium) - Lead coder and way more (since 0.4.5)",
|
u8" Remko Bijker (Rubidium) - Lead coder and way more (since 0.4.5)",
|
||||||
" Jos\xC3\xA9 Soler (Terkhen) - General coding (since 1.0)",
|
u8" Jos\u00e9 Soler (Terkhen) - General coding (since 1.0)",
|
||||||
" Leif Linse (Zuu) - AI/Game Script (since 1.2)",
|
u8" Leif Linse (Zuu) - AI/Game Script (since 1.2)",
|
||||||
"",
|
u8"",
|
||||||
"Inactive Developers:",
|
u8"Inactive Developers:",
|
||||||
" Jean-Fran\xC3\xA7ois Claeys (Belugas) - GUI, NewGRF and more (0.4.5 - 1.0)",
|
u8" Jean-Fran\u00e7ois Claeys (Belugas) - GUI, NewGRF and more (0.4.5 - 1.0)",
|
||||||
" Bjarni Corfitzen (Bjarni) - MacOSX port, coder and vehicles (0.3 - 0.7)",
|
u8" Bjarni Corfitzen (Bjarni) - MacOSX port, coder and vehicles (0.3 - 0.7)",
|
||||||
" Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6)",
|
u8" Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6)",
|
||||||
" Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6)",
|
u8" Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6)",
|
||||||
" Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6)",
|
u8" Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6)",
|
||||||
" Attila B\xC3\xA1n (MiHaMiX) - Developer WebTranslator 1 and 2 (0.3 - 0.5)",
|
u8" Attila B\u00e1n (MiHaMiX) - Developer WebTranslator 1 and 2 (0.3 - 0.5)",
|
||||||
" Zden\xC4\x9Bk Sojka (SmatZ) - Bug finder and fixer (0.6 - 1.3)",
|
u8" Zden\u011bk Sojka (SmatZ) - Bug finder and fixer (0.6 - 1.3)",
|
||||||
" Christoph Mallon (Tron) - Programmer, code correctness police (0.3 - 0.5)",
|
u8" Christoph Mallon (Tron) - Programmer, code correctness police (0.3 - 0.5)",
|
||||||
" Patric Stout (TrueBrain) - NoAI, NoGo, Network (0.3 - 1.2), sys op (active)",
|
u8" Patric Stout (TrueBrain) - NoAI, NoGo, Network (0.3 - 1.2), sys op (active)",
|
||||||
" Thijs Marinussen (Yexo) - AI Framework, General (0.6 - 1.3)",
|
u8" Thijs Marinussen (Yexo) - AI Framework, General (0.6 - 1.3)",
|
||||||
"",
|
u8"",
|
||||||
"Retired Developers:",
|
u8"Retired Developers:",
|
||||||
" Tam\xC3\xA1s Farag\xC3\xB3 (Darkvater) - Ex-Lead coder (0.3 - 0.5)",
|
u8" Tam\u00e1s Farag\u00f3 (Darkvater) - Ex-Lead coder (0.3 - 0.5)",
|
||||||
" Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3)",
|
u8" Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3)",
|
||||||
" Emil Djupfeld (egladil) - MacOSX (0.4.5 - 0.6)",
|
u8" Emil Djupfeld (egladil) - MacOSX (0.4.5 - 0.6)",
|
||||||
" Simon Sasburg (HackyKid) - Many bugfixes (0.4 - 0.4.5)",
|
u8" Simon Sasburg (HackyKid) - Many bugfixes (0.4 - 0.4.5)",
|
||||||
" Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3)",
|
u8" Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3)",
|
||||||
" Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3)",
|
u8" Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3)",
|
||||||
" Petr Baudi\xC5\xA1 (pasky) - Many patches, NewGRF support (0.3 - 0.3)",
|
u8" Petr Baudi\u0161 (pasky) - Many patches, NewGRF support (0.3 - 0.3)",
|
||||||
" Benedikt Br\xC3\xBCggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7)",
|
u8" Benedikt Br\u00fcggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7)",
|
||||||
" Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3)",
|
u8" Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3)",
|
||||||
"",
|
u8"",
|
||||||
"Special thanks go out to:",
|
u8"Special thanks go out to:",
|
||||||
" Josef Drexler - For his great work on TTDPatch",
|
u8" Josef Drexler - For his great work on TTDPatch",
|
||||||
" Marcin Grzegorczyk - Track foundations and for describing TTD internals",
|
u8" Marcin Grzegorczyk - Track foundations and for describing TTD internals",
|
||||||
" Stefan Mei\xC3\x9Fner (sign_de) - For his work on the console",
|
u8" Stefan Mei\u00dfner (sign_de) - For his work on the console",
|
||||||
" Mike Ragsdale - OpenTTD installer",
|
u8" Mike Ragsdale - OpenTTD installer",
|
||||||
" Christian Rosentreter (tokai) - MorphOS / AmigaOS port",
|
u8" Christian Rosentreter (tokai) - MorphOS / AmigaOS port",
|
||||||
" Richard Kempton (richK) - additional airports, initial TGP implementation",
|
u8" Richard Kempton (richK) - additional airports, initial TGP implementation",
|
||||||
"",
|
u8"",
|
||||||
" Alberto Demichelis - Squirrel scripting language \xC2\xA9 2003-2008",
|
u8" Alberto Demichelis - Squirrel scripting language \u00a9 2003-2008",
|
||||||
" L. Peter Deutsch - MD5 implementation \xC2\xA9 1999, 2000, 2002",
|
u8" L. Peter Deutsch - MD5 implementation \u00a9 1999, 2000, 2002",
|
||||||
" Michael Blunck - Pre-signals and semaphores \xC2\xA9 2003",
|
u8" Michael Blunck - Pre-signals and semaphores \u00a9 2003",
|
||||||
" George - Canal/Lock graphics \xC2\xA9 2003-2004",
|
u8" George - Canal/Lock graphics \u00a9 2003-2004",
|
||||||
" Andrew Parkhouse (andythenorth) - River graphics",
|
u8" Andrew Parkhouse (andythenorth) - River graphics",
|
||||||
" David Dallaston (Pikka) - Tram tracks",
|
u8" David Dallaston (Pikka) - Tram tracks",
|
||||||
" All Translators - Who made OpenTTD a truly international game",
|
u8" All Translators - Who made OpenTTD a truly international game",
|
||||||
" Bug Reporters - Without whom OpenTTD would still be full of bugs!",
|
u8" Bug Reporters - Without whom OpenTTD would still be full of bugs!",
|
||||||
"",
|
u8"",
|
||||||
"",
|
u8"",
|
||||||
"Developer of this patchpack:",
|
u8"Developer of this patchpack:",
|
||||||
" Jonathan G. Rennison (JGR)",
|
u8" Jonathan G. Rennison (JGR)",
|
||||||
"",
|
u8"",
|
||||||
"",
|
u8"",
|
||||||
"And last but not least:",
|
u8"And last but not least:",
|
||||||
" Chris Sawyer - For an amazing game!"
|
u8" Chris Sawyer - For an amazing game!"
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AboutWindow : public Window {
|
struct AboutWindow : public Window {
|
||||||
|
@@ -265,6 +265,18 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList *
|
|||||||
this->address_length = (int)runp->ai_addrlen;
|
this->address_length = (int)runp->ai_addrlen;
|
||||||
assert(sizeof(this->address) >= runp->ai_addrlen);
|
assert(sizeof(this->address) >= runp->ai_addrlen);
|
||||||
memcpy(&this->address, runp->ai_addr, runp->ai_addrlen);
|
memcpy(&this->address, runp->ai_addr, runp->ai_addrlen);
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
/* Emscripten doesn't zero sin_zero, but as we compare addresses
|
||||||
|
* to see if they are the same address, we need them to be zero'd.
|
||||||
|
* Emscripten is, as far as we know, the only OS not doing this.
|
||||||
|
*
|
||||||
|
* https://github.com/emscripten-core/emscripten/issues/12998
|
||||||
|
*/
|
||||||
|
if (this->address.ss_family == AF_INET) {
|
||||||
|
sockaddr_in *address_ipv4 = (sockaddr_in *)&this->address;
|
||||||
|
memset(address_ipv4->sin_zero, 0, sizeof(address_ipv4->sin_zero));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +309,15 @@ static SOCKET ConnectLoopProc(addrinfo *runp)
|
|||||||
|
|
||||||
if (!SetNoDelay(sock)) DEBUG(net, 1, "[%s] setting TCP_NODELAY failed", type);
|
if (!SetNoDelay(sock)) DEBUG(net, 1, "[%s] setting TCP_NODELAY failed", type);
|
||||||
|
|
||||||
if (connect(sock, runp->ai_addr, (int)runp->ai_addrlen) != 0) {
|
int err = connect(sock, runp->ai_addr, (int)runp->ai_addrlen);
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
/* Emscripten is asynchronous, and as such a connect() is still in
|
||||||
|
* progress by the time the call returns. */
|
||||||
|
if (err != 0 && errno != EINPROGRESS)
|
||||||
|
#else
|
||||||
|
if (err != 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
DEBUG(net, 1, "[%s] could not connect %s socket: %s", type, family, strerror(errno));
|
DEBUG(net, 1, "[%s] could not connect %s socket: %s", type, family, strerror(errno));
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
|
@@ -99,6 +99,16 @@ typedef unsigned long in_addr_t;
|
|||||||
# include <errno.h>
|
# include <errno.h>
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
# include <netdb.h>
|
# include <netdb.h>
|
||||||
|
|
||||||
|
# if defined(__EMSCRIPTEN__)
|
||||||
|
/* Emscripten doesn't support AI_ADDRCONFIG and errors out on it. */
|
||||||
|
# undef AI_ADDRCONFIG
|
||||||
|
# define AI_ADDRCONFIG 0
|
||||||
|
/* Emscripten says it supports FD_SETSIZE fds, but it really only supports 64.
|
||||||
|
* https://github.com/emscripten-core/emscripten/issues/1711 */
|
||||||
|
# undef FD_SETSIZE
|
||||||
|
# define FD_SETSIZE 64
|
||||||
|
# endif
|
||||||
#endif /* UNIX */
|
#endif /* UNIX */
|
||||||
|
|
||||||
/* OS/2 stuff */
|
/* OS/2 stuff */
|
||||||
@@ -160,6 +170,28 @@ typedef unsigned long in_addr_t;
|
|||||||
|
|
||||||
#endif /* OS/2 */
|
#endif /* OS/2 */
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
/**
|
||||||
|
* Emscripten doesn't set 'addrlen' for accept(), getsockname(), getpeername()
|
||||||
|
* and recvfrom(), which confuses other functions and causes them to crash.
|
||||||
|
* This function needs to be called after these four functions to make sure
|
||||||
|
* 'addrlen' is patched up.
|
||||||
|
*
|
||||||
|
* https://github.com/emscripten-core/emscripten/issues/12996
|
||||||
|
*
|
||||||
|
* @param address The address returned by those four functions.
|
||||||
|
* @return The correct value for addrlen.
|
||||||
|
*/
|
||||||
|
static inline socklen_t FixAddrLenForEmscripten(struct sockaddr_storage &address)
|
||||||
|
{
|
||||||
|
switch (address.ss_family) {
|
||||||
|
case AF_INET6: return sizeof(struct sockaddr_in6);
|
||||||
|
case AF_INET: return sizeof(struct sockaddr_in);
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to set the socket into non-blocking mode.
|
* Try to set the socket into non-blocking mode.
|
||||||
* @param d The socket to set the non-blocking more for.
|
* @param d The socket to set the non-blocking more for.
|
||||||
@@ -167,12 +199,16 @@ typedef unsigned long in_addr_t;
|
|||||||
*/
|
*/
|
||||||
static inline bool SetNonBlocking(SOCKET d)
|
static inline bool SetNonBlocking(SOCKET d)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef __EMSCRIPTEN__
|
||||||
u_long nonblocking = 1;
|
return true;
|
||||||
#else
|
#else
|
||||||
|
# ifdef _WIN32
|
||||||
|
u_long nonblocking = 1;
|
||||||
|
# else
|
||||||
int nonblocking = 1;
|
int nonblocking = 1;
|
||||||
#endif
|
# endif
|
||||||
return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
|
return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -197,10 +233,14 @@ static inline bool SetBlocking(SOCKET d)
|
|||||||
*/
|
*/
|
||||||
static inline bool SetNoDelay(SOCKET d)
|
static inline bool SetNoDelay(SOCKET d)
|
||||||
{
|
{
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
/* XXX should this be done at all? */
|
/* XXX should this be done at all? */
|
||||||
int b = 1;
|
int b = 1;
|
||||||
/* The (const char*) cast is needed for windows */
|
/* The (const char*) cast is needed for windows */
|
||||||
return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0;
|
return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -42,6 +42,9 @@ public:
|
|||||||
socklen_t sin_len = sizeof(sin);
|
socklen_t sin_len = sizeof(sin);
|
||||||
SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
|
SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
|
||||||
if (s == INVALID_SOCKET) return;
|
if (s == INVALID_SOCKET) return;
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
sin_len = FixAddrLenForEmscripten(sin);
|
||||||
|
#endif
|
||||||
|
|
||||||
SetNonBlocking(s); // XXX error handling?
|
SetNonBlocking(s); // XXX error handling?
|
||||||
|
|
||||||
|
@@ -164,6 +164,9 @@ void NetworkUDPSocketHandler::ReceivePackets()
|
|||||||
/* Did we get the bytes for the base header of the packet? */
|
/* Did we get the bytes for the base header of the packet? */
|
||||||
if (nbytes <= 0) break; // No data, i.e. no packet
|
if (nbytes <= 0) break; // No data, i.e. no packet
|
||||||
if (nbytes <= 2) continue; // Invalid data; try next packet
|
if (nbytes <= 2) continue; // Invalid data; try next packet
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
client_len = FixAddrLenForEmscripten(client_addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
NetworkAddress address(client_addr, client_len);
|
NetworkAddress address(client_addr, client_len);
|
||||||
p.PrepareToRead();
|
p.PrepareToRead();
|
||||||
|
@@ -1122,3 +1122,14 @@ bool IsNetworkCompatibleVersion(const char *other, bool extended)
|
|||||||
{
|
{
|
||||||
return strncmp(_openttd_revision, other, (extended ? NETWORK_LONG_REVISION_LENGTH : NETWORK_REVISION_LENGTH) - 1) == 0;
|
return strncmp(_openttd_revision, other, (extended ? NETWORK_LONG_REVISION_LENGTH : NETWORK_REVISION_LENGTH) - 1) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
void CDECL em_openttd_add_server(const char *host, int port)
|
||||||
|
{
|
||||||
|
NetworkUDPQueryServer(NetworkAddress(host, port), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@@ -23,6 +23,10 @@
|
|||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
# include <emscripten.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../safeguards.h"
|
#include "../safeguards.h"
|
||||||
|
|
||||||
extern bool HasScenario(const ContentInfo *ci, bool md5sum);
|
extern bool HasScenario(const ContentInfo *ci, bool md5sum);
|
||||||
@@ -296,6 +300,13 @@ void ClientNetworkContentSocketHandler::DownloadSelectedContent(uint &files, uin
|
|||||||
{
|
{
|
||||||
bytes = 0;
|
bytes = 0;
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
/* Emscripten is loaded via an HTTPS connection. As such, it is very
|
||||||
|
* difficult to make HTTP connections. So always use the TCP method of
|
||||||
|
* downloading content. */
|
||||||
|
fallback = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
ContentIDList content;
|
ContentIDList content;
|
||||||
for (const ContentInfo *ci : this->infos) {
|
for (const ContentInfo *ci : this->infos) {
|
||||||
if (!ci->IsSelected() || ci->state == ContentInfo::ALREADY_HERE) continue;
|
if (!ci->IsSelected() || ci->state == ContentInfo::ALREADY_HERE) continue;
|
||||||
@@ -542,6 +553,10 @@ void ClientNetworkContentSocketHandler::AfterDownload()
|
|||||||
unlink(GetFullFilename(this->curInfo, false));
|
unlink(GetFullFilename(this->curInfo, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs());
|
||||||
|
#endif
|
||||||
|
|
||||||
this->OnDownloadComplete(this->curInfo->id);
|
this->OnDownloadComplete(this->curInfo->id);
|
||||||
} else {
|
} else {
|
||||||
ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_EXTRACT, INVALID_STRING_ID, WL_ERROR);
|
ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_EXTRACT, INVALID_STRING_ID, WL_ERROR);
|
||||||
|
@@ -41,6 +41,9 @@
|
|||||||
|
|
||||||
#include "../safeguards.h"
|
#include "../safeguards.h"
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
# include <emscripten.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static void ShowNetworkStartServerWindow();
|
static void ShowNetworkStartServerWindow();
|
||||||
static void ShowNetworkLobbyWindow(NetworkGameList *ngl);
|
static void ShowNetworkLobbyWindow(NetworkGameList *ngl);
|
||||||
@@ -490,6 +493,14 @@ public:
|
|||||||
this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
|
this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
|
||||||
this->SetFocusedWidget(WID_NG_FILTER);
|
this->SetFocusedWidget(WID_NG_FILTER);
|
||||||
|
|
||||||
|
/* As the master-server doesn't support "websocket" servers yet, we
|
||||||
|
* let "os/emscripten/pre.js" hardcode a list of servers people can
|
||||||
|
* join. This means the serverlist is curated for now, but it is the
|
||||||
|
* best we can offer. */
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
EM_ASM(if (window["openttd_server_list"]) openttd_server_list());
|
||||||
|
#endif
|
||||||
|
|
||||||
this->last_joined = NetworkGameListAddItem(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
|
this->last_joined = NetworkGameListAddItem(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
|
||||||
this->server = this->last_joined;
|
this->server = this->last_joined;
|
||||||
if (this->last_joined != nullptr) NetworkUDPQueryServer(this->last_joined->address);
|
if (this->last_joined != nullptr) NetworkUDPQueryServer(this->last_joined->address);
|
||||||
@@ -630,6 +641,12 @@ public:
|
|||||||
this->GetWidget<NWidgetStacked>(WID_NG_NEWGRF_SEL)->SetDisplayedPlane(sel == nullptr || !sel->online || sel->info.grfconfig == nullptr);
|
this->GetWidget<NWidgetStacked>(WID_NG_NEWGRF_SEL)->SetDisplayedPlane(sel == nullptr || !sel->online || sel->info.grfconfig == nullptr);
|
||||||
this->GetWidget<NWidgetStacked>(WID_NG_NEWGRF_MISSING_SEL)->SetDisplayedPlane(sel == nullptr || !sel->online || sel->info.grfconfig == nullptr || !sel->info.version_compatible || sel->info.compatible);
|
this->GetWidget<NWidgetStacked>(WID_NG_NEWGRF_MISSING_SEL)->SetDisplayedPlane(sel == nullptr || !sel->online || sel->info.grfconfig == nullptr || !sel->info.version_compatible || sel->info.compatible);
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
this->SetWidgetDisabledState(WID_NG_FIND, true);
|
||||||
|
this->SetWidgetDisabledState(WID_NG_ADD, true);
|
||||||
|
this->SetWidgetDisabledState(WID_NG_START, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
this->DrawWidgets();
|
this->DrawWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1951,8 +1951,7 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, cons
|
|||||||
tmp_layout.clear();
|
tmp_layout.clear();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* no relative bounding box support */
|
/* no relative bounding box support */
|
||||||
/*C++17: DrawTileSeqStruct &dtss = */ tmp_layout.emplace_back();
|
DrawTileSeqStruct &dtss = tmp_layout.emplace_back();
|
||||||
DrawTileSeqStruct &dtss = tmp_layout.back();
|
|
||||||
MemSetT(&dtss, 0);
|
MemSetT(&dtss, 0);
|
||||||
|
|
||||||
dtss.delta_x = buf->ReadByte();
|
dtss.delta_x = buf->ReadByte();
|
||||||
@@ -5159,8 +5158,7 @@ static void NewSpriteGroup(ByteReader *buf)
|
|||||||
/* Loop through the var adjusts. Unfortunately we don't know how many we have
|
/* Loop through the var adjusts. Unfortunately we don't know how many we have
|
||||||
* from the outset, so we shall have to keep reallocing. */
|
* from the outset, so we shall have to keep reallocing. */
|
||||||
do {
|
do {
|
||||||
/*C++17: DeterministicSpriteGroupAdjust &adjust = */ adjusts.emplace_back();
|
DeterministicSpriteGroupAdjust &adjust = adjusts.emplace_back();
|
||||||
DeterministicSpriteGroupAdjust &adjust = adjusts.back();
|
|
||||||
|
|
||||||
/* The first var adjust doesn't have an operation specified, so we set it to add. */
|
/* The first var adjust doesn't have an operation specified, so we set it to add. */
|
||||||
adjust.operation = adjusts.size() == 1 ? DSGA_OP_ADD : (DeterministicSpriteGroupAdjustOperation)buf->ReadByte();
|
adjust.operation = adjusts.size() == 1 ? DSGA_OP_ADD : (DeterministicSpriteGroupAdjustOperation)buf->ReadByte();
|
||||||
|
@@ -664,8 +664,7 @@ uint32 NewGRFSpriteLayout::PrepareLayout(uint32 orig_offset, uint32 newgrf_groun
|
|||||||
|
|
||||||
/* Create a copy of the spritelayout, so we can modify some values.
|
/* Create a copy of the spritelayout, so we can modify some values.
|
||||||
* Also include the groundsprite into the sequence for easier processing. */
|
* Also include the groundsprite into the sequence for easier processing. */
|
||||||
/*C++17: DrawTileSeqStruct *result = &*/ result_seq.emplace_back();
|
DrawTileSeqStruct *result = &result_seq.emplace_back();
|
||||||
DrawTileSeqStruct *result = &result_seq.back();
|
|
||||||
result->image = ground;
|
result->image = ground;
|
||||||
result->delta_x = 0;
|
result->delta_x = 0;
|
||||||
result->delta_y = 0;
|
result->delta_y = 0;
|
||||||
@@ -675,8 +674,7 @@ uint32 NewGRFSpriteLayout::PrepareLayout(uint32 orig_offset, uint32 newgrf_groun
|
|||||||
foreach_draw_tile_seq(dtss, this->seq) {
|
foreach_draw_tile_seq(dtss, this->seq) {
|
||||||
result_seq.push_back(*dtss);
|
result_seq.push_back(*dtss);
|
||||||
}
|
}
|
||||||
result_seq.emplace_back() /*C++17: .MakeTerminator()*/;
|
result_seq.emplace_back().MakeTerminator();
|
||||||
result_seq.back().MakeTerminator();
|
|
||||||
/* Determine the var10 values the action-1-2-3 chains needs to be resolved for,
|
/* Determine the var10 values the action-1-2-3 chains needs to be resolved for,
|
||||||
* and apply the default sprite offsets (unless disabled). */
|
* and apply the default sprite offsets (unless disabled). */
|
||||||
const TileLayoutRegisters *regs = this->registers;
|
const TileLayoutRegisters *regs = this->registers;
|
||||||
|
@@ -87,6 +87,11 @@
|
|||||||
|
|
||||||
#include "safeguards.h"
|
#include "safeguards.h"
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
# include <emscripten.h>
|
||||||
|
# include <emscripten/html5.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
void CallLandscapeTick();
|
void CallLandscapeTick();
|
||||||
void IncreaseDate();
|
void IncreaseDate();
|
||||||
void MusicLoop();
|
void MusicLoop();
|
||||||
@@ -123,6 +128,15 @@ void CDECL usererror(const char *s, ...)
|
|||||||
ShowOSErrorBox(buf, false);
|
ShowOSErrorBox(buf, false);
|
||||||
if (VideoDriver::GetInstance() != nullptr) VideoDriver::GetInstance()->Stop();
|
if (VideoDriver::GetInstance() != nullptr) VideoDriver::GetInstance()->Stop();
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
emscripten_exit_pointerlock();
|
||||||
|
/* In effect, the game ends here. As emscripten_set_main_loop() caused
|
||||||
|
* the stack to be unwound, the code after MainLoop() in
|
||||||
|
* openttd_main() is never executed. */
|
||||||
|
EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs());
|
||||||
|
EM_ASM(if (window["openttd_abort"]) openttd_abort());
|
||||||
|
#endif
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3293,8 +3293,7 @@ bool AfterLoadGame()
|
|||||||
cur_skip = prev_tile_skip;
|
cur_skip = prev_tile_skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*C++17: uint &this_skip = */ skip_frames.push_back(prev_tile_skip);
|
uint &this_skip = skip_frames.emplace_back(prev_tile_skip);
|
||||||
uint &this_skip = skip_frames.back();
|
|
||||||
|
|
||||||
/* The following 3 curves now take longer than before */
|
/* The following 3 curves now take longer than before */
|
||||||
switch (u->state) {
|
switch (u->state) {
|
||||||
|
@@ -191,8 +191,7 @@ static void Load_EIDS()
|
|||||||
_engine_mngr.clear();
|
_engine_mngr.clear();
|
||||||
|
|
||||||
while (SlIterateArray() != -1) {
|
while (SlIterateArray() != -1) {
|
||||||
/*C++17: EngineIDMapping *eid = &*/ _engine_mngr.emplace_back();
|
EngineIDMapping *eid = &_engine_mngr.emplace_back();
|
||||||
EngineIDMapping *eid = &_engine_mngr.back();
|
|
||||||
SlObject(eid, _engine_id_mapping_desc);
|
SlObject(eid, _engine_id_mapping_desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -46,6 +46,9 @@
|
|||||||
#include "../scope.h"
|
#include "../scope.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
# include <emscripten.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../tbtr_template_vehicle.h"
|
#include "../tbtr_template_vehicle.h"
|
||||||
|
|
||||||
@@ -2928,6 +2931,10 @@ static void SaveFileDone()
|
|||||||
|
|
||||||
InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
|
InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH);
|
||||||
_sl.saveinprogress = false;
|
_sl.saveinprogress = false;
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the error message from outside of the actual loading/saving of the game (AfterLoadGame and friends) */
|
/** Set the error message from outside of the actual loading/saving of the game (AfterLoadGame and friends) */
|
||||||
|
@@ -192,8 +192,7 @@ static void Load_WAYP()
|
|||||||
int index;
|
int index;
|
||||||
|
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
/*C++17: OldWaypoint *wp = &*/ _old_waypoints.emplace_back();
|
OldWaypoint *wp = &_old_waypoints.emplace_back();
|
||||||
OldWaypoint *wp = &_old_waypoints.back();
|
|
||||||
|
|
||||||
wp->index = index;
|
wp->index = index;
|
||||||
SlObject(wp, _old_waypoint_desc);
|
SlObject(wp, _old_waypoint_desc);
|
||||||
|
@@ -1,5 +1,9 @@
|
|||||||
add_subdirectory(api)
|
add_subdirectory(api)
|
||||||
|
|
||||||
|
if(OPTION_TOOLS_ONLY)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
add_files(
|
add_files(
|
||||||
script_config.cpp
|
script_config.cpp
|
||||||
script_config.hpp
|
script_config.hpp
|
||||||
|
@@ -131,6 +131,10 @@ foreach(API "ai;AI" "game;GS" "template;Template")
|
|||||||
)
|
)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
if(OPTION_TOOLS_ONLY)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
add_library(openttd::script_api ALIAS script_api)
|
add_library(openttd::script_api ALIAS script_api)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -118,8 +118,7 @@ public:
|
|||||||
text += stored_size;
|
text += stored_size;
|
||||||
}
|
}
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
/*C++17: OutputBuffer &block =*/ this->output_buffer.emplace_back();
|
OutputBuffer &block = this->output_buffer.emplace_back();
|
||||||
OutputBuffer &block = this->output_buffer.back();
|
|
||||||
block.Clear(); // Initialize the new block.
|
block.Clear(); // Initialize the new block.
|
||||||
size_t stored_size = block.Add(text, length);
|
size_t stored_size = block.Add(text, length);
|
||||||
length -= stored_size;
|
length -= stored_size;
|
||||||
|
@@ -22,6 +22,10 @@ if (NOT HOST_BINARY_DIR)
|
|||||||
add_dependencies(tools strgen)
|
add_dependencies(tools strgen)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(OPTION_TOOLS_ONLY)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Source Files
|
# Source Files
|
||||||
add_files(strgen_base.cpp)
|
add_files(strgen_base.cpp)
|
||||||
|
|
||||||
|
@@ -15,10 +15,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
/** A non-breaking space. */
|
/** A non-breaking space. */
|
||||||
#define NBSP "\xC2\xA0"
|
#define NBSP u8"\u00a0"
|
||||||
|
|
||||||
/** A left-to-right marker, marks the next character as left-to-right. */
|
/** A left-to-right marker, marks the next character as left-to-right. */
|
||||||
#define LRM "\xE2\x80\x8E"
|
#define LRM u8"\u200e"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Valid filter types for IsValidChar.
|
* Valid filter types for IsValidChar.
|
||||||
|
@@ -74,8 +74,7 @@ void StringFilter::SetFilterTerm(const char *str)
|
|||||||
|
|
||||||
/* Add to word */
|
/* Add to word */
|
||||||
if (word == nullptr) {
|
if (word == nullptr) {
|
||||||
/*C++17: word = &*/ this->word_index.push_back({dest, false});
|
word = &this->word_index.emplace_back(WordState{ dest, false });
|
||||||
word = &this->word_index.back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dest, pos, len);
|
memcpy(dest, pos, len);
|
||||||
|
@@ -1758,6 +1758,11 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg
|
|||||||
int64 args_array[] = {(int64)(size_t)v->name.c_str()};
|
int64 args_array[] = {(int64)(size_t)v->name.c_str()};
|
||||||
StringParameters tmp_params(args_array);
|
StringParameters tmp_params(args_array);
|
||||||
buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
|
buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
|
||||||
|
} else if (v->group_id != DEFAULT_GROUP) {
|
||||||
|
/* The vehicle has no name, but is member of a group, so print group name */
|
||||||
|
int64 args_array[] = {v->group_id, v->unitnumber};
|
||||||
|
StringParameters tmp_params(args_array);
|
||||||
|
buff = GetStringWithArgs(buff, STR_FORMAT_GROUP_VEHICLE_NAME, &tmp_params, last);
|
||||||
} else {
|
} else {
|
||||||
int64 args_array[] = {v->unitnumber};
|
int64 args_array[] = {v->unitnumber};
|
||||||
StringParameters tmp_params(args_array);
|
StringParameters tmp_params(args_array);
|
||||||
|
1150
src/table/townname.h
1150
src/table/townname.h
File diff suppressed because it is too large
Load Diff
@@ -359,7 +359,7 @@ static void Xunzip(byte **bufp, size_t *sizep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for the byte-order-mark, and skip it if needed. */
|
/* Check for the byte-order-mark, and skip it if needed. */
|
||||||
char *p = this->text + (strncmp("\xEF\xBB\xBF", this->text, 3) == 0 ? 3 : 0);
|
char *p = this->text + (strncmp(u8"\ufeff", this->text, 3) == 0 ? 3 : 0);
|
||||||
|
|
||||||
/* Make sure the string is a valid UTF-8 sequence. */
|
/* Make sure the string is a valid UTF-8 sequence. */
|
||||||
str_validate(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE);
|
str_validate(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE);
|
||||||
|
@@ -505,7 +505,7 @@ static char *MakeFinnishTownName(char *buf, const char *last, uint32 seed)
|
|||||||
strstr(orig, "A") != nullptr || strstr(orig, "O") != nullptr || strstr(orig, "U") != nullptr) {
|
strstr(orig, "A") != nullptr || strstr(orig, "O") != nullptr || strstr(orig, "U") != nullptr) {
|
||||||
buf = strecpy(buf, "la", last);
|
buf = strecpy(buf, "la", last);
|
||||||
} else {
|
} else {
|
||||||
buf = strecpy(buf, "l\xC3\xA4", last);
|
buf = strecpy(buf, u8"l\u00e4", last);
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
@@ -1013,8 +1013,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
|
|||||||
* Do this for all tiles (like trees), not only objects. */
|
* Do this for all tiles (like trees), not only objects. */
|
||||||
ClearedObjectArea *coa = FindClearedObject(end_tile);
|
ClearedObjectArea *coa = FindClearedObject(end_tile);
|
||||||
if (coa == nullptr) {
|
if (coa == nullptr) {
|
||||||
/*C++17: coa = &*/ _cleared_object_areas.push_back({end_tile, TileArea(end_tile, 1, 1)});
|
coa = &_cleared_object_areas.emplace_back(ClearedObjectArea{ end_tile, TileArea(end_tile, 1, 1) });
|
||||||
coa = &_cleared_object_areas.back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hide the tile from the terraforming command */
|
/* Hide the tile from the terraforming command */
|
||||||
|
@@ -31,6 +31,10 @@
|
|||||||
#include "../3rdparty/mingw-std-threads/mingw.mutex.h"
|
#include "../3rdparty/mingw-std-threads/mingw.mutex.h"
|
||||||
#include "../3rdparty/mingw-std-threads/mingw.condition_variable.h"
|
#include "../3rdparty/mingw-std-threads/mingw.condition_variable.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
# include <emscripten.h>
|
||||||
|
# include <emscripten/html5.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(WITH_FCITX)
|
#if defined(WITH_FCITX)
|
||||||
#include <fcitx/frontend.h>
|
#include <fcitx/frontend.h>
|
||||||
@@ -61,6 +65,11 @@ static volatile bool _draw_continue;
|
|||||||
static Palette _local_palette;
|
static Palette _local_palette;
|
||||||
static SDL_Palette *_sdl_palette;
|
static SDL_Palette *_sdl_palette;
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
/** Whether we just had a window-enter event. */
|
||||||
|
static bool _cursor_new_in_window = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_DIRTY_RECTS 100
|
#define MAX_DIRTY_RECTS 100
|
||||||
static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS];
|
static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS];
|
||||||
static int _num_dirty_rects;
|
static int _num_dirty_rects;
|
||||||
@@ -578,6 +587,9 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize)
|
|||||||
bool VideoDriver_SDL::ClaimMousePointer()
|
bool VideoDriver_SDL::ClaimMousePointer()
|
||||||
{
|
{
|
||||||
SDL_ShowCursor(0);
|
SDL_ShowCursor(0);
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,9 +808,27 @@ int VideoDriver_SDL::PollEvent()
|
|||||||
|
|
||||||
switch (ev.type) {
|
switch (ev.type) {
|
||||||
case SDL_MOUSEMOTION:
|
case SDL_MOUSEMOTION:
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
if (_cursor_new_in_window) {
|
||||||
|
/* The cursor just moved into the window; this means we don't
|
||||||
|
* know the absolutely position yet to move relative from.
|
||||||
|
* Before this time, SDL didn't know it either, and this is
|
||||||
|
* why we postpone it till now. Update the absolute position
|
||||||
|
* for this once, and work relative after. */
|
||||||
|
_cursor.pos.x = ev.motion.x;
|
||||||
|
_cursor.pos.y = ev.motion.y;
|
||||||
|
_cursor.dirty = true;
|
||||||
|
|
||||||
|
_cursor_new_in_window = false;
|
||||||
|
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||||
|
} else {
|
||||||
|
_cursor.UpdateCursorPositionRelative(ev.motion.xrel, ev.motion.yrel);
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (_cursor.UpdateCursorPosition(ev.motion.x, ev.motion.y, true)) {
|
if (_cursor.UpdateCursorPosition(ev.motion.x, ev.motion.y, true)) {
|
||||||
SDL_WarpMouseInWindow(_sdl_window, _cursor.pos.x, _cursor.pos.y);
|
SDL_WarpMouseInWindow(_sdl_window, _cursor.pos.x, _cursor.pos.y);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
HandleMouseEvents();
|
HandleMouseEvents();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -932,6 +962,12 @@ int VideoDriver_SDL::PollEvent()
|
|||||||
} else if (ev.window.event == SDL_WINDOWEVENT_ENTER) {
|
} else if (ev.window.event == SDL_WINDOWEVENT_ENTER) {
|
||||||
// mouse entered the window, enable cursor
|
// mouse entered the window, enable cursor
|
||||||
_cursor.in_window = true;
|
_cursor.in_window = true;
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
/* Disable relative mouse mode for the first mouse motion,
|
||||||
|
* so we can pick up the absolutely position again. */
|
||||||
|
_cursor_new_in_window = true;
|
||||||
|
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||||
|
#endif
|
||||||
} else if (ev.window.event == SDL_WINDOWEVENT_LEAVE) {
|
} else if (ev.window.event == SDL_WINDOWEVENT_LEAVE) {
|
||||||
// mouse left the window, undraw cursor
|
// mouse left the window, undraw cursor
|
||||||
UndrawMouseCursor();
|
UndrawMouseCursor();
|
||||||
@@ -968,7 +1004,8 @@ const char *VideoDriver_SDL::Start(const StringList &parm)
|
|||||||
/* Explicitly disable hardware acceleration. Enabling this causes
|
/* Explicitly disable hardware acceleration. Enabling this causes
|
||||||
* UpdateWindowSurface() to update the window's texture instead of
|
* UpdateWindowSurface() to update the window's texture instead of
|
||||||
* its surface. */
|
* its surface. */
|
||||||
SDL_SetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION , "0");
|
SDL_SetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION, "0");
|
||||||
|
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1");
|
||||||
|
|
||||||
/* Just on the offchance the audio subsystem started before the video system,
|
/* Just on the offchance the audio subsystem started before the video system,
|
||||||
* check whether any part of SDL has been initialised before getting here.
|
* check whether any part of SDL has been initialised before getting here.
|
||||||
@@ -1012,55 +1049,28 @@ void VideoDriver_SDL::Stop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoDriver_SDL::MainLoop()
|
void VideoDriver_SDL::LoopOnce()
|
||||||
{
|
{
|
||||||
uint32 cur_ticks = SDL_GetTicks();
|
|
||||||
uint32 last_cur_ticks = cur_ticks;
|
|
||||||
uint32 next_tick = cur_ticks + MILLISECONDS_PER_TICK;
|
|
||||||
uint32 mod;
|
uint32 mod;
|
||||||
int numkeys;
|
int numkeys;
|
||||||
const Uint8 *keys;
|
const Uint8 *keys;
|
||||||
|
|
||||||
CheckPaletteAnim();
|
|
||||||
|
|
||||||
std::thread draw_thread;
|
|
||||||
std::unique_lock<std::recursive_mutex> draw_lock;
|
|
||||||
if (_draw_threaded) {
|
|
||||||
/* Initialise the mutex first, because that's the thing we *need*
|
|
||||||
* directly in the newly created thread. */
|
|
||||||
_draw_mutex = new std::recursive_mutex();
|
|
||||||
if (_draw_mutex == nullptr) {
|
|
||||||
_draw_threaded = false;
|
|
||||||
} else {
|
|
||||||
draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
|
|
||||||
_draw_signal = new std::condition_variable_any();
|
|
||||||
_draw_continue = true;
|
|
||||||
|
|
||||||
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &DrawSurfaceToScreenThread);
|
|
||||||
|
|
||||||
/* Free the mutex if we won't be able to use it. */
|
|
||||||
if (!_draw_threaded) {
|
|
||||||
draw_lock.unlock();
|
|
||||||
draw_lock.release();
|
|
||||||
delete _draw_mutex;
|
|
||||||
delete _draw_signal;
|
|
||||||
_draw_mutex = nullptr;
|
|
||||||
_draw_signal = nullptr;
|
|
||||||
} else {
|
|
||||||
/* Wait till the draw mutex has started itself. */
|
|
||||||
_draw_signal->wait(*_draw_mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(driver, 1, "SDL2: using %sthreads", _draw_threaded ? "" : "no ");
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
uint32 prev_cur_ticks = cur_ticks; // to check for wrapping
|
uint32 prev_cur_ticks = cur_ticks; // to check for wrapping
|
||||||
InteractiveRandom(); // randomness
|
InteractiveRandom(); // randomness
|
||||||
|
|
||||||
while (PollEvent() == -1) {}
|
while (PollEvent() == -1) {}
|
||||||
if (_exit_game) break;
|
if (_exit_game) {
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
/* Emscripten is event-driven, and as such the main loop is inside
|
||||||
|
* the browser. So if _exit_game goes true, the main loop ends (the
|
||||||
|
* cancel call), but we still have to call the cleanup that is
|
||||||
|
* normally done at the end of the main loop for non-Emscripten.
|
||||||
|
* After that, Emscripten just halts, and the HTML shows a nice
|
||||||
|
* "bye, see you next time" message. */
|
||||||
|
emscripten_cancel_main_loop();
|
||||||
|
MainLoopCleanup();
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mod = SDL_GetModState();
|
mod = SDL_GetModState();
|
||||||
keys = SDL_GetKeyboardState(&numkeys);
|
keys = SDL_GetKeyboardState(&numkeys);
|
||||||
@@ -1113,9 +1123,17 @@ void VideoDriver_SDL::MainLoop()
|
|||||||
_local_palette = _cur_palette;
|
_local_palette = _cur_palette;
|
||||||
} else {
|
} else {
|
||||||
/* Release the thread while sleeping */
|
/* Release the thread while sleeping */
|
||||||
if (_draw_mutex != nullptr) draw_lock.unlock();
|
if (_draw_mutex != nullptr) {
|
||||||
|
draw_lock.unlock();
|
||||||
CSleep(1);
|
CSleep(1);
|
||||||
if (_draw_mutex != nullptr) draw_lock.lock();
|
draw_lock.lock();
|
||||||
|
} else {
|
||||||
|
/* Emscripten is running an event-based mainloop; there is already some
|
||||||
|
* downtime between each iteration, so no need to sleep. */
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
|
CSleep(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
NetworkDrawChatMessage();
|
NetworkDrawChatMessage();
|
||||||
DrawMouseCursor();
|
DrawMouseCursor();
|
||||||
@@ -1129,8 +1147,60 @@ void VideoDriver_SDL::MainLoop()
|
|||||||
CheckPaletteAnim();
|
CheckPaletteAnim();
|
||||||
DrawSurfaceToScreen();
|
DrawSurfaceToScreen();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoDriver_SDL::MainLoop()
|
||||||
|
{
|
||||||
|
cur_ticks = SDL_GetTicks();
|
||||||
|
last_cur_ticks = cur_ticks;
|
||||||
|
next_tick = cur_ticks + MILLISECONDS_PER_TICK;
|
||||||
|
|
||||||
|
CheckPaletteAnim();
|
||||||
|
|
||||||
|
if (_draw_threaded) {
|
||||||
|
/* Initialise the mutex first, because that's the thing we *need*
|
||||||
|
* directly in the newly created thread. */
|
||||||
|
_draw_mutex = new std::recursive_mutex();
|
||||||
|
if (_draw_mutex == nullptr) {
|
||||||
|
_draw_threaded = false;
|
||||||
|
} else {
|
||||||
|
draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
|
||||||
|
_draw_signal = new std::condition_variable_any();
|
||||||
|
_draw_continue = true;
|
||||||
|
|
||||||
|
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &DrawSurfaceToScreenThread);
|
||||||
|
|
||||||
|
/* Free the mutex if we won't be able to use it. */
|
||||||
|
if (!_draw_threaded) {
|
||||||
|
draw_lock.unlock();
|
||||||
|
draw_lock.release();
|
||||||
|
delete _draw_mutex;
|
||||||
|
delete _draw_signal;
|
||||||
|
_draw_mutex = nullptr;
|
||||||
|
_draw_signal = nullptr;
|
||||||
|
} else {
|
||||||
|
/* Wait till the draw mutex has started itself. */
|
||||||
|
_draw_signal->wait(*_draw_mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG(driver, 1, "SDL2: using %sthreads", _draw_threaded ? "" : "no ");
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
/* Run the main loop event-driven, based on RequestAnimationFrame. */
|
||||||
|
emscripten_set_main_loop_arg(&this->EmscriptenLoop, this, 0, 1);
|
||||||
|
#else
|
||||||
|
while (!_exit_game) {
|
||||||
|
LoopOnce();
|
||||||
|
}
|
||||||
|
|
||||||
|
MainLoopCleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoDriver_SDL::MainLoopCleanup()
|
||||||
|
{
|
||||||
if (_draw_mutex != nullptr) {
|
if (_draw_mutex != nullptr) {
|
||||||
_draw_continue = false;
|
_draw_continue = false;
|
||||||
/* Sending signal if there is no thread blocked
|
/* Sending signal if there is no thread blocked
|
||||||
@@ -1146,6 +1216,15 @@ void VideoDriver_SDL::MainLoop()
|
|||||||
_draw_mutex = nullptr;
|
_draw_mutex = nullptr;
|
||||||
_draw_signal = nullptr;
|
_draw_signal = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
emscripten_exit_pointerlock();
|
||||||
|
/* In effect, the game ends here. As emscripten_set_main_loop() caused
|
||||||
|
* the stack to be unwound, the code after MainLoop() in
|
||||||
|
* openttd_main() is never executed. */
|
||||||
|
EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs());
|
||||||
|
EM_ASM(if (window["openttd_exit"]) openttd_exit());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VideoDriver_SDL::ChangeResolution(int w, int h)
|
bool VideoDriver_SDL::ChangeResolution(int w, int h)
|
||||||
|
@@ -42,12 +42,26 @@ public:
|
|||||||
const char *GetName() const override { return "sdl"; }
|
const char *GetName() const override { return "sdl"; }
|
||||||
private:
|
private:
|
||||||
int PollEvent();
|
int PollEvent();
|
||||||
|
void LoopOnce();
|
||||||
|
void MainLoopCleanup();
|
||||||
bool CreateMainSurface(uint w, uint h, bool resize);
|
bool CreateMainSurface(uint w, uint h, bool resize);
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
/* Convert a constant pointer back to a non-constant pointer to a member function. */
|
||||||
|
static void EmscriptenLoop(void *self) { ((VideoDriver_SDL *)self)->LoopOnce(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is true to indicate that keyboard input is in text input mode, and SDL_TEXTINPUT events are enabled.
|
* This is true to indicate that keyboard input is in text input mode, and SDL_TEXTINPUT events are enabled.
|
||||||
*/
|
*/
|
||||||
bool edit_box_focused;
|
bool edit_box_focused;
|
||||||
|
|
||||||
|
uint32 cur_ticks;
|
||||||
|
uint32 last_cur_ticks;
|
||||||
|
uint32 next_tick;
|
||||||
|
|
||||||
|
std::thread draw_thread;
|
||||||
|
std::unique_lock<std::recursive_mutex> draw_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Factory for the SDL video driver. */
|
/** Factory for the SDL video driver. */
|
||||||
|
@@ -816,8 +816,7 @@ static void AddTileSpriteToDraw(SpriteID image, PaletteID pal, int32 x, int32 y,
|
|||||||
{
|
{
|
||||||
assert((image & SPRITE_MASK) < MAX_SPRITES);
|
assert((image & SPRITE_MASK) < MAX_SPRITES);
|
||||||
|
|
||||||
/*C++17: TileSpriteToDraw &ts = */ _vd.tile_sprites_to_draw.emplace_back();
|
TileSpriteToDraw &ts = _vd.tile_sprites_to_draw.emplace_back();
|
||||||
TileSpriteToDraw &ts = _vd.tile_sprites_to_draw.back();
|
|
||||||
ts.image = image;
|
ts.image = image;
|
||||||
ts.pal = pal;
|
ts.pal = pal;
|
||||||
ts.sub = sub;
|
ts.sub = sub;
|
||||||
@@ -1038,8 +1037,7 @@ void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*C++17: ParentSpriteToDraw &ps = */ _vd.parent_sprites_to_draw.emplace_back();
|
ParentSpriteToDraw &ps = _vd.parent_sprites_to_draw.emplace_back();
|
||||||
ParentSpriteToDraw &ps = _vd.parent_sprites_to_draw.back();
|
|
||||||
ps.x = tmp_x;
|
ps.x = tmp_x;
|
||||||
ps.y = tmp_y;
|
ps.y = tmp_y;
|
||||||
|
|
||||||
@@ -1180,8 +1178,7 @@ void AddChildSpriteScreen(SpriteID image, PaletteID pal, int x, int y, bool tran
|
|||||||
|
|
||||||
*_vd.last_child = (uint)_vd.child_screen_sprites_to_draw.size();
|
*_vd.last_child = (uint)_vd.child_screen_sprites_to_draw.size();
|
||||||
|
|
||||||
/*C++17: ChildScreenSpriteToDraw &cs = */ _vd.child_screen_sprites_to_draw.emplace_back();
|
ChildScreenSpriteToDraw &cs = _vd.child_screen_sprites_to_draw.emplace_back();
|
||||||
ChildScreenSpriteToDraw &cs = _vd.child_screen_sprites_to_draw.back();
|
|
||||||
cs.image = image;
|
cs.image = image;
|
||||||
cs.pal = pal;
|
cs.pal = pal;
|
||||||
cs.sub = sub;
|
cs.sub = sub;
|
||||||
@@ -1201,8 +1198,7 @@ void AddChildSpriteScreen(SpriteID image, PaletteID pal, int x, int y, bool tran
|
|||||||
static void AddStringToDraw(int x, int y, StringID string, uint64 params_1, uint64 params_2, Colours colour, uint16 width)
|
static void AddStringToDraw(int x, int y, StringID string, uint64 params_1, uint64 params_2, Colours colour, uint16 width)
|
||||||
{
|
{
|
||||||
assert(width != 0);
|
assert(width != 0);
|
||||||
/*C++17: StringSpriteToDraw &ss = */ _vd.string_sprites_to_draw.emplace_back();
|
StringSpriteToDraw &ss = _vd.string_sprites_to_draw.emplace_back();
|
||||||
StringSpriteToDraw &ss = _vd.string_sprites_to_draw.back();
|
|
||||||
ss.string = string;
|
ss.string = string;
|
||||||
ss.x = x;
|
ss.x = x;
|
||||||
ss.y = y;
|
ss.y = y;
|
||||||
|
Reference in New Issue
Block a user