Merge remote-tracking branch 'upstream/master'

This commit is contained in:
2024-04-04 17:57:56 +01:00
613 changed files with 18318 additions and 12531 deletions

View File

@@ -14,3 +14,7 @@ notifications:
pull-request: pull-request:
issue: issue:
tag-created: tag-created:
workflow-run:
only:
- .github/workflows/release.yml
- .github/workflows/ci-nightly.yml

View File

@@ -1,4 +1,4 @@
name: CI name: CI - Build
on: on:
pull_request: pull_request:
@@ -17,79 +17,22 @@ jobs:
emscripten: emscripten:
name: Emscripten name: Emscripten
runs-on: ubuntu-20.04 uses: ./.github/workflows/ci-emscripten.yml
container: secrets: inherit
# If you change this version, change the number in the cache step too.
image: emscripten/emsdk:3.1.42
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup cache
uses: actions/cache@v4
with:
path: /emsdk/upstream/emscripten/cache
key: 3.1.42-${{ runner.os }}
- name: Patch Emscripten to support LZMA
run: |
cd /emsdk/upstream/emscripten
patch -p1 < ${GITHUB_WORKSPACE}/os/emscripten/emsdk-liblzma.patch
- 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"
cmake --build . -j $(nproc) --target 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"
cmake --build . -j $(nproc) --target openttd
echo "::endgroup::"
linux: linux:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- name: Clang - Debug - name: Clang
compiler: clang-15 compiler: clang-15
cxxcompiler: clang++-15 cxxcompiler: clang++-15
libraries: libsdl2-dev libraries: libsdl2-dev
- name: Clang - Release
compiler: clang-15
cxxcompiler: clang++-15
libraries: libsdl2-dev
extra-cmake-parameters: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DOPTION_USE_ASSERTS=OFF
- name: GCC - SDL2 - name: GCC - SDL2
compiler: gcc compiler: gcc
cxxcompiler: g++ cxxcompiler: g++
libraries: libsdl2-dev libraries: libsdl2-dev
- name: GCC - SDL1.2
compiler: gcc
cxxcompiler: g++
libraries: libsdl1.2-dev
- name: GCC - Dedicated - name: GCC - Dedicated
compiler: gcc compiler: gcc
cxxcompiler: g++ cxxcompiler: g++
@@ -99,317 +42,57 @@ jobs:
name: Linux (${{ matrix.name }}) name: Linux (${{ matrix.name }})
runs-on: ubuntu-latest uses: ./.github/workflows/ci-linux.yml
env: secrets: inherit
CC: ${{ matrix.compiler }}
CXX: ${{ matrix.cxxcompiler }}
steps: with:
- name: Checkout compiler: ${{ matrix.compiler }}
uses: actions/checkout@v4 cxxcompiler: ${{ matrix.cxxcompiler }}
libraries: ${{ matrix.libraries }}
- name: Setup vcpkg caching extra-cmake-parameters: ${{ matrix.extra-cmake-parameters }}
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install dependencies
run: |
echo "::group::Update apt"
sudo apt-get update
echo "::endgroup::"
echo "::group::Install dependencies"
sudo apt-get install -y --no-install-recommends \
liballegro4-dev \
libcurl4-openssl-dev \
libfontconfig-dev \
libharfbuzz-dev \
libicu-dev \
liblzma-dev \
liblzo2-dev \
${{ matrix.libraries }} \
zlib1g-dev \
# EOF
echo "::group::Install vcpkg dependencies"
# Disable vcpkg integration, as we mostly use system libraries.
mv vcpkg.json vcpkg-disabled.json
# We only use breakpad from vcpkg, as its CMake files
# are a bit special. So the Ubuntu's variant doesn't work.
vcpkg install breakpad
echo "::endgroup::"
env:
DEBIAN_FRONTEND: noninteractive
- name: Get OpenGFX
run: |
mkdir -p ~/.local/share/openttd/baseset
cd ~/.local/share/openttd/baseset
echo "::group::Download OpenGFX"
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
echo "::endgroup::"
echo "::group::Unpack OpenGFX"
unzip opengfx-all.zip
echo "::endgroup::"
rm -f opengfx-all.zip
- name: Install GCC problem matcher
uses: ammaraskar/gcc-problem-matcher@master
- name: Build
run: |
mkdir build
cd build
echo "::group::CMake"
cmake .. -DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake ${{ matrix.extra-cmake-parameters }}
echo "::endgroup::"
echo "::group::Build"
echo "Running on $(nproc) cores"
cmake --build . -j $(nproc)
echo "::endgroup::"
- name: Test
run: |
(
cd build
ctest -j $(nproc) --timeout 120
)
# Re-enable vcpkg.
mv vcpkg-disabled.json vcpkg.json
# Check no tracked files have been modified.
git diff --exit-code
macos: macos:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- arch: x64 - name: arm64 - Debug
full_arch: x86_64 arch: arm64
full_arch: arm64
extra-cmake-parameters: -DCMAKE_BUILD_TYPE=Debug
- name: arm64 - Release
arch: arm64
full_arch: arm64
extra-cmake-parameters: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DOPTION_USE_ASSERTS=OFF
name: Mac OS (${{ matrix.arch }}) name: Mac OS (${{ matrix.name }})
runs-on: macos-latest uses: ./.github/workflows/ci-macos.yml
env: secrets: inherit
MACOSX_DEPLOYMENT_TARGET: 10.13
steps: with:
- name: Checkout arch: ${{ matrix.arch }}
uses: actions/checkout@v4 full_arch: ${{ matrix.full_arch }}
extra-cmake-parameters: ${{ matrix.extra-cmake-parameters }}
- name: Setup vcpkg caching
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install OpenGFX
run: |
mkdir -p ~/Documents/OpenTTD/baseset
cd ~/Documents/OpenTTD/baseset
echo "::group::Download OpenGFX"
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
echo "::endgroup::"
echo "::group::Unpack OpenGFX"
unzip opengfx-all.zip
echo "::endgroup::"
rm -f opengfx-all.zip
- name: Install GCC problem matcher
uses: ammaraskar/gcc-problem-matcher@master
- name: Build
run: |
mkdir build
cd build
echo "::group::CMake"
cmake .. \
-DCMAKE_OSX_ARCHITECTURES=${{ matrix.full_arch }} \
-DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-osx \
-DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \
# EOF
echo "::endgroup::"
echo "::group::Build"
echo "Running on $(sysctl -n hw.logicalcpu) cores"
cmake --build . -j $(sysctl -n hw.logicalcpu)
echo "::endgroup::"
- name: Test
run: |
cd build
ctest -j $(sysctl -n hw.logicalcpu) --timeout 120
windows: windows:
strategy:
fail-fast: false
matrix:
os: [windows-latest, windows-2019]
arch: [x86, x64]
name: Windows (${{ matrix.os }} / ${{ matrix.arch }})
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup vcpkg caching
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install OpenGFX
shell: bash
run: |
mkdir -p "C:/Users/Public/Documents/OpenTTD/baseset"
cd "C:/Users/Public/Documents/OpenTTD/baseset"
echo "::group::Download OpenGFX"
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
echo "::endgroup::"
echo "::group::Unpack OpenGFX"
unzip opengfx-all.zip
echo "::endgroup::"
rm -f opengfx-all.zip
- name: Install MSVC problem matcher
uses: ammaraskar/msvc-problem-matcher@master
- name: Configure developer command prompt for ${{ matrix.arch }}
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.arch }}
- name: Build
shell: bash
env:
NINJA_STATUS: "[%f/%t -- %e] " # [finished_edges/total_edges -- elapsed_time], default value is "[%f/%t] "
run: |
mkdir build
cd build
echo "::group::CMake"
cmake .. \
-GNinja \
-DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static \
-DCMAKE_TOOLCHAIN_FILE="c:\vcpkg\scripts\buildsystems\vcpkg.cmake" \
# EOF
echo "::endgroup::"
echo "::group::Build"
cmake --build .
echo "::endgroup::"
- name: Test
shell: bash
run: |
cd build
ctest --timeout 120
msys2:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- msystem: MINGW64 - os: windows-latest
arch: x86_64 arch: x86
- msystem: MINGW32 - os: windows-latest
arch: i686 arch: x64
name: MinGW (${{ matrix.arch }}) name: Windows (${{ matrix.arch }})
runs-on: windows-latest uses: ./.github/workflows/ci-windows.yml
secrets: inherit
steps: with:
- name: Checkout os: ${{ matrix.os }}
uses: actions/checkout@v4 arch: ${{ matrix.arch }}
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
release: false
install: >-
git
make
mingw-w64-${{ matrix.arch }}-cmake
mingw-w64-${{ matrix.arch }}-gcc
mingw-w64-${{ matrix.arch }}-lzo2
mingw-w64-${{ matrix.arch }}-libpng
mingw-w64-${{ matrix.arch }}-lld
mingw-w64-${{ matrix.arch }}-ninja
- name: Install OpenGFX
shell: bash
run: |
mkdir -p "C:/Users/Public/Documents/OpenTTD/baseset"
cd "C:/Users/Public/Documents/OpenTTD/baseset"
echo "::group::Download OpenGFX"
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
echo "::endgroup::"
echo "::group::Unpack OpenGFX"
unzip opengfx-all.zip
echo "::endgroup::"
rm -f opengfx-all.zip
- name: Install GCC problem matcher
uses: ammaraskar/gcc-problem-matcher@master
- name: Build
shell: msys2 {0}
env:
NINJA_STATUS: "[%f/%t -- %e] " # [finished_edges/total_edges -- elapsed_time], default value is "[%f/%t] "
run: |
mkdir build
cd build
echo "::group::CMake"
cmake .. \
-GNinja \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
# EOF
echo "::endgroup::"
echo "::group::Build"
cmake --build .
echo "::endgroup::"
- name: Test
shell: msys2 {0}
run: |
cd build
ctest --timeout 120
check_annotations: check_annotations:
name: Check Annotations name: Check Annotations
@@ -418,7 +101,6 @@ jobs:
- linux - linux
- macos - macos
- windows - windows
- msys2
if: always() && github.event_name == 'pull_request' if: always() && github.event_name == 'pull_request'

62
.github/workflows/ci-emscripten.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
name: CI (Emscripten)
on:
workflow_call:
env:
CTEST_OUTPUT_ON_FAILURE: 1
jobs:
emscripten:
name: CI
runs-on: ubuntu-20.04
container:
# If you change this version, change the number in the cache step too.
image: emscripten/emsdk:3.1.42
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup cache
uses: actions/cache@v4
with:
path: /emsdk/upstream/emscripten/cache
key: 3.1.42-${{ runner.os }}
- name: Patch Emscripten to support LZMA
run: |
cd /emsdk/upstream/emscripten
patch -p1 < ${GITHUB_WORKSPACE}/os/emscripten/emsdk-liblzma.patch
- 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"
cmake --build . -j $(nproc) --target 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"
cmake --build . -j $(nproc) --target openttd
echo "::endgroup::"

123
.github/workflows/ci-linux.yml vendored Normal file
View File

@@ -0,0 +1,123 @@
name: CI (Linux)
on:
workflow_call:
inputs:
compiler:
required: true
type: string
cxxcompiler:
required: true
type: string
libraries:
required: true
type: string
extra-cmake-parameters:
required: true
type: string
env:
CTEST_OUTPUT_ON_FAILURE: 1
jobs:
linux:
name: CI
runs-on: ubuntu-latest
env:
CC: ${{ inputs.compiler }}
CXX: ${{ inputs.cxxcompiler }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup vcpkg caching
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install vcpkg
run: |
git clone https://github.com/microsoft/vcpkg ${{ runner.temp }}/vcpkg
${{ runner.temp }}/vcpkg/bootstrap-vcpkg.sh -disableMetrics
- name: Install dependencies
run: |
echo "::group::Update apt"
sudo apt-get update
echo "::endgroup::"
echo "::group::Install dependencies"
sudo apt-get install -y --no-install-recommends \
liballegro4-dev \
libcurl4-openssl-dev \
libfontconfig-dev \
libharfbuzz-dev \
libicu-dev \
liblzma-dev \
liblzo2-dev \
${{ inputs.libraries }} \
zlib1g-dev \
# EOF
echo "::group::Install vcpkg dependencies"
# Disable vcpkg integration, as we mostly use system libraries.
mv vcpkg.json vcpkg-disabled.json
# We only use breakpad from vcpkg, as its CMake files
# are a bit special. So the Ubuntu's variant doesn't work.
${{ runner.temp }}/vcpkg/vcpkg install breakpad
echo "::endgroup::"
env:
DEBIAN_FRONTEND: noninteractive
- name: Get OpenGFX
run: |
mkdir -p ~/.local/share/openttd/baseset
cd ~/.local/share/openttd/baseset
echo "::group::Download OpenGFX"
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
echo "::endgroup::"
echo "::group::Unpack OpenGFX"
unzip opengfx-all.zip
echo "::endgroup::"
rm -f opengfx-all.zip
- name: Install GCC problem matcher
uses: ammaraskar/gcc-problem-matcher@master
- name: Build
run: |
mkdir build
cd build
echo "::group::CMake"
cmake .. -DCMAKE_TOOLCHAIN_FILE=${{ runner.temp }}/vcpkg/scripts/buildsystems/vcpkg.cmake ${{ inputs.extra-cmake-parameters }}
echo "::endgroup::"
echo "::group::Build"
echo "Running on $(nproc) cores"
cmake --build . -j $(nproc)
echo "::endgroup::"
- name: Test
run: |
(
cd build
ctest -j $(nproc) --timeout 120
)
# Re-enable vcpkg.
mv vcpkg-disabled.json vcpkg.json
# Check no tracked files have been modified.
git diff --exit-code

90
.github/workflows/ci-macos.yml vendored Normal file
View File

@@ -0,0 +1,90 @@
name: CI (MacOS)
on:
workflow_call:
inputs:
arch:
required: true
type: string
full_arch:
required: true
type: string
extra-cmake-parameters:
required: false
type: string
default: ""
env:
CTEST_OUTPUT_ON_FAILURE: 1
jobs:
macos:
name: CI
runs-on: macos-14
env:
MACOSX_DEPLOYMENT_TARGET: 10.13
steps:
- name: Setup Xcode version
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Checkout
uses: actions/checkout@v4
- name: Setup vcpkg caching
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install vcpkg
run: |
git clone https://github.com/microsoft/vcpkg ${{ runner.temp }}/vcpkg
${{ runner.temp }}/vcpkg/bootstrap-vcpkg.sh -disableMetrics
- name: Install OpenGFX
run: |
mkdir -p ~/Documents/OpenTTD/baseset
cd ~/Documents/OpenTTD/baseset
echo "::group::Download OpenGFX"
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
echo "::endgroup::"
echo "::group::Unpack OpenGFX"
unzip opengfx-all.zip
echo "::endgroup::"
rm -f opengfx-all.zip
- name: Install GCC problem matcher
uses: ammaraskar/gcc-problem-matcher@master
- name: Build
run: |
mkdir build
cd build
echo "::group::CMake"
cmake .. \
-DCMAKE_OSX_ARCHITECTURES=${{ inputs.full_arch }} \
-DVCPKG_TARGET_TRIPLET=${{ inputs.arch }}-osx \
-DCMAKE_TOOLCHAIN_FILE=${{ runner.temp }}/vcpkg/scripts/buildsystems/vcpkg.cmake \
${{ inputs.extra-cmake-parameters }} \
# EOF
echo "::endgroup::"
echo "::group::Build"
echo "Running on $(sysctl -n hw.logicalcpu) cores"
cmake --build . -j $(sysctl -n hw.logicalcpu)
echo "::endgroup::"
- name: Test
run: |
cd build
ctest -j $(sysctl -n hw.logicalcpu) --timeout 120

83
.github/workflows/ci-mingw.yml vendored Normal file
View File

@@ -0,0 +1,83 @@
name: CI (MinGW)
on:
workflow_call:
inputs:
arch:
required: true
type: string
msystem:
required: true
type: string
env:
CTEST_OUTPUT_ON_FAILURE: 1
jobs:
mingw:
name: CI
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ inputs.msystem }}
release: false
install: >-
git
make
mingw-w64-${{ inputs.arch }}-cmake
mingw-w64-${{ inputs.arch }}-gcc
mingw-w64-${{ inputs.arch }}-lzo2
mingw-w64-${{ inputs.arch }}-libpng
mingw-w64-${{ inputs.arch }}-lld
mingw-w64-${{ inputs.arch }}-ninja
- name: Install OpenGFX
shell: bash
run: |
mkdir -p "C:/Users/Public/Documents/OpenTTD/baseset"
cd "C:/Users/Public/Documents/OpenTTD/baseset"
echo "::group::Download OpenGFX"
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
echo "::endgroup::"
echo "::group::Unpack OpenGFX"
unzip opengfx-all.zip
echo "::endgroup::"
rm -f opengfx-all.zip
- name: Install GCC problem matcher
uses: ammaraskar/gcc-problem-matcher@master
- name: Build
shell: msys2 {0}
env:
NINJA_STATUS: "[%f/%t -- %e] " # [finished_edges/total_edges -- elapsed_time], default value is "[%f/%t] "
run: |
mkdir build
cd build
echo "::group::CMake"
cmake .. \
-GNinja \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
# EOF
echo "::endgroup::"
echo "::group::Build"
cmake --build .
echo "::endgroup::"
- name: Test
shell: msys2 {0}
run: |
cd build
ctest --timeout 120

82
.github/workflows/ci-nightly.yml vendored Normal file
View File

@@ -0,0 +1,82 @@
name: CI - Nightly
on:
schedule:
- cron: '0 3 * * *'
workflow_dispatch:
env:
CTEST_OUTPUT_ON_FAILURE: 1
jobs:
linux:
strategy:
fail-fast: false
matrix:
include:
- name: GCC - SDL1.2
compiler: gcc
cxxcompiler: g++
libraries: libsdl1.2-dev
name: Linux (${{ matrix.name }})
uses: ./.github/workflows/ci-linux.yml
secrets: inherit
with:
compiler: ${{ matrix.compiler }}
cxxcompiler: ${{ matrix.cxxcompiler }}
libraries: ${{ matrix.libraries }}
extra-cmake-parameters:
macos:
strategy:
fail-fast: false
matrix:
include:
- arch: x64
full_arch: x86_64
name: Mac OS (${{ matrix.arch }})
uses: ./.github/workflows/ci-macos.yml
secrets: inherit
with:
arch: ${{ matrix.arch }}
full_arch: ${{ matrix.full_arch }}
mingw:
strategy:
fail-fast: false
matrix:
include:
- msystem: MINGW64
arch: x86_64
- msystem: MINGW32
arch: i686
name: MinGW (${{ matrix.arch }})
uses: ./.github/workflows/ci-mingw.yml
secrets: inherit
with:
msystem: ${{ matrix.msystem }}
arch: ${{ matrix.arch }}
check_annotations:
name: Check Annotations
needs:
- linux
- macos
- mingw
if: always()
runs-on: ubuntu-latest
steps:
- name: Check annotations
uses: OpenTTD/actions/annotation-check@v5

87
.github/workflows/ci-windows.yml vendored Normal file
View File

@@ -0,0 +1,87 @@
name: CI (Windows)
on:
workflow_call:
inputs:
arch:
required: true
type: string
os:
required: true
type: string
env:
CTEST_OUTPUT_ON_FAILURE: 1
jobs:
windows:
name: CI
runs-on: ${{ inputs.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup vcpkg caching
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install vcpkg
run: |
git clone https://github.com/microsoft/vcpkg ${{ runner.temp }}\vcpkg
${{ runner.temp }}\vcpkg\bootstrap-vcpkg.bat -disableMetrics
- name: Install OpenGFX
shell: bash
run: |
mkdir -p "C:/Users/Public/Documents/OpenTTD/baseset"
cd "C:/Users/Public/Documents/OpenTTD/baseset"
echo "::group::Download OpenGFX"
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip -o opengfx-all.zip
echo "::endgroup::"
echo "::group::Unpack OpenGFX"
unzip opengfx-all.zip
echo "::endgroup::"
rm -f opengfx-all.zip
- name: Install MSVC problem matcher
uses: ammaraskar/msvc-problem-matcher@master
- name: Configure developer command prompt for ${{ inputs.arch }}
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ inputs.arch }}
- name: Build
shell: bash
env:
NINJA_STATUS: "[%f/%t -- %e] " # [finished_edges/total_edges -- elapsed_time], default value is "[%f/%t] "
run: |
mkdir build
cd build
echo "::group::CMake"
cmake .. \
-GNinja \
-DVCPKG_TARGET_TRIPLET=${{ inputs.arch }}-windows-static \
-DCMAKE_TOOLCHAIN_FILE="${{ runner.temp }}\vcpkg\scripts\buildsystems\vcpkg.cmake" \
# EOF
echo "::endgroup::"
echo "::group::Build"
cmake --build .
echo "::endgroup::"
- name: Test
shell: bash
run: |
cd build
ctest --timeout 120

View File

@@ -26,6 +26,19 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup vcpkg caching
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install vcpkg
run: |
git clone https://github.com/microsoft/vcpkg ${{ runner.temp }}/vcpkg
${{ runner.temp }}/vcpkg/bootstrap-vcpkg.sh -disableMetrics
- name: Install dependencies - name: Install dependencies
run: | run: |
echo "::group::Update apt" echo "::group::Update apt"
@@ -44,13 +57,28 @@ jobs:
libsdl2-dev \ libsdl2-dev \
zlib1g-dev \ zlib1g-dev \
# EOF # EOF
echo "::group::Install vcpkg dependencies"
# Disable vcpkg integration, as we mostly use system libraries.
mv vcpkg.json vcpkg-disabled.json
# We only use breakpad from vcpkg, as its CMake files
# are a bit special. So the Ubuntu's variant doesn't work.
${{ runner.temp }}/vcpkg/vcpkg install breakpad
echo "::endgroup::" echo "::endgroup::"
env: env:
DEBIAN_FRONTEND: noninteractive DEBIAN_FRONTEND: noninteractive
- name: Set number of make jobs - name: Prepare build
run: | run: |
echo "MAKEFLAGS=-j$(nproc)" >> $GITHUB_ENV mkdir build
cd build
echo "::group::CMake"
cmake .. -DCMAKE_TOOLCHAIN_FILE=${{ runner.temp }}/vcpkg/scripts/buildsystems/vcpkg.cmake
echo "::endgroup::"
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v3
@@ -58,8 +86,14 @@ jobs:
languages: cpp languages: cpp
config-file: ./.github/codeql/codeql-config.yml config-file: ./.github/codeql/codeql-config.yml
- name: Autobuild - name: Build
uses: github/codeql-action/autobuild@v3 run: |
cd build
echo "::group::Build"
echo "Running on $(nproc) cores"
cmake --build . -j $(nproc)
echo "::endgroup::"
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3 uses: github/codeql-action/analyze@v3

View File

@@ -7,6 +7,7 @@ on:
- synchronize - synchronize
branches: branches:
- master - master
- release/**
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }} group: ${{ github.workflow }}-${{ github.event.pull_request.number }}

View File

@@ -124,7 +124,7 @@ jobs:
) )
echo "::group::Install breakpad dependencies" echo "::group::Install breakpad dependencies"
cargo install dump_syms cargo install --locked dump_syms
echo "::endgroup::" echo "::endgroup::"
- name: Install GCC problem matcher - name: Install GCC problem matcher

View File

@@ -12,11 +12,16 @@ jobs:
macos: macos:
name: MacOS name: MacOS
runs-on: macos-latest runs-on: macos-14
env: env:
MACOSX_DEPLOYMENT_TARGET: 10.13 MACOSX_DEPLOYMENT_TARGET: 10.13
steps: steps:
- name: Setup Xcode version
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Download source - name: Download source
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
@@ -40,6 +45,11 @@ jobs:
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite') core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install vcpkg
run: |
git clone https://github.com/microsoft/vcpkg ${{ runner.temp }}/vcpkg
${{ runner.temp }}/vcpkg/bootstrap-vcpkg.sh -disableMetrics
- name: Install dependencies - name: Install dependencies
env: env:
HOMEBREW_NO_AUTO_UPDATE: 1 HOMEBREW_NO_AUTO_UPDATE: 1
@@ -52,7 +62,7 @@ jobs:
echo "::endgroup::" echo "::endgroup::"
echo "::group::Install breakpad dependencies" echo "::group::Install breakpad dependencies"
cargo install dump_syms cargo install --locked dump_syms
echo "::endgroup::" echo "::endgroup::"
- name: Install GCC problem matcher - name: Install GCC problem matcher
@@ -94,7 +104,7 @@ jobs:
cmake ${GITHUB_WORKSPACE} \ cmake ${GITHUB_WORKSPACE} \
-DCMAKE_OSX_ARCHITECTURES=arm64 \ -DCMAKE_OSX_ARCHITECTURES=arm64 \
-DVCPKG_TARGET_TRIPLET=arm64-osx \ -DVCPKG_TARGET_TRIPLET=arm64-osx \
-DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DCMAKE_TOOLCHAIN_FILE=${{ runner.temp }}/vcpkg/scripts/buildsystems/vcpkg.cmake \
-DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DOPTION_SURVEY_KEY=${{ inputs.survey_key }} \ -DOPTION_SURVEY_KEY=${{ inputs.survey_key }} \
@@ -115,7 +125,7 @@ jobs:
cmake ${GITHUB_WORKSPACE} \ cmake ${GITHUB_WORKSPACE} \
-DCMAKE_OSX_ARCHITECTURES=x86_64 \ -DCMAKE_OSX_ARCHITECTURES=x86_64 \
-DVCPKG_TARGET_TRIPLET=x64-osx \ -DVCPKG_TARGET_TRIPLET=x64-osx \
-DCMAKE_TOOLCHAIN_FILE=/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DCMAKE_TOOLCHAIN_FILE=${{ runner.temp }}/vcpkg/scripts/buildsystems/vcpkg.cmake \
-DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DOPTION_SURVEY_KEY=${{ inputs.survey_key }} \ -DOPTION_SURVEY_KEY=${{ inputs.survey_key }} \

View File

@@ -53,6 +53,11 @@ jobs:
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite') core.exportVariable('VCPKG_BINARY_SOURCES', 'clear;x-gha,readwrite')
- name: Install vcpkg
run: |
git clone https://github.com/microsoft/vcpkg ${{ runner.temp }}\vcpkg
${{ runner.temp }}\vcpkg\bootstrap-vcpkg.bat -disableMetrics
- name: Install dependencies - name: Install dependencies
shell: bash shell: bash
run: | run: |
@@ -61,7 +66,7 @@ jobs:
echo "::endgroup::" echo "::endgroup::"
echo "::group::Install breakpad dependencies" echo "::group::Install breakpad dependencies"
cargo install dump_syms cargo install --locked dump_syms
echo "::endgroup::" echo "::endgroup::"
- name: Install MSVC problem matcher - name: Install MSVC problem matcher
@@ -95,21 +100,6 @@ jobs:
with: with:
arch: ${{ matrix.host }} arch: ${{ matrix.host }}
- name: Import code signing certificate
shell: powershell
# If this is run on a fork, there may not be a certificate set up - continue in this case
continue-on-error: true
run: |
$tempFile = [System.IO.Path]::GetTempFileName()
$bytes = [System.Convert]::FromBase64String($env:WINDOWS_CERTIFICATE_P12)
[IO.File]::WriteAllBytes($tempFile, $bytes)
$pwd = ConvertTo-SecureString $env:WINDOWS_CERTIFICATE_PASSWORD -AsPlainText -Force
Import-PfxCertificate -FilePath $tempFile -CertStoreLocation Cert:\CurrentUser\My -Password $pwd
Remove-Item $tempFile
env:
WINDOWS_CERTIFICATE_P12: ${{ secrets.WINDOWS_CERTIFICATE_P12 }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
- name: Build (with installer) - name: Build (with installer)
if: inputs.is_tag == 'true' if: inputs.is_tag == 'true'
shell: bash shell: bash
@@ -121,12 +111,11 @@ jobs:
cmake ${GITHUB_WORKSPACE} \ cmake ${GITHUB_WORKSPACE} \
-GNinja \ -GNinja \
-DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static \ -DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static \
-DCMAKE_TOOLCHAIN_FILE="c:\vcpkg\scripts\buildsystems\vcpkg.cmake" \ -DCMAKE_TOOLCHAIN_FILE="${{ runner.temp }}\vcpkg\scripts\buildsystems\vcpkg.cmake" \
-DOPTION_USE_NSIS=ON \ -DOPTION_USE_NSIS=ON \
-DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DOPTION_SURVEY_KEY=${{ inputs.survey_key }} \ -DOPTION_SURVEY_KEY=${{ inputs.survey_key }} \
-DWINDOWS_CERTIFICATE_COMMON_NAME="${WINDOWS_CERTIFICATE_COMMON_NAME}" \
# EOF # EOF
echo "::endgroup::" echo "::endgroup::"
@@ -134,7 +123,12 @@ jobs:
cmake --build . --target openttd cmake --build . --target openttd
echo "::endgroup::" echo "::endgroup::"
env: env:
WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
AZURE_CODESIGN_ACCOUNT_NAME: ${{ secrets.AZURE_CODESIGN_ACCOUNT_NAME }}
AZURE_CODESIGN_ENDPOINT: ${{ secrets.AZURE_CODESIGN_ENDPOINT }}
AZURE_CODESIGN_PROFILE_NAME: ${{ secrets.AZURE_CODESIGN_PROFILE_NAME }}
- name: Build (without installer) - name: Build (without installer)
if: inputs.is_tag != 'true' if: inputs.is_tag != 'true'
@@ -147,11 +141,10 @@ jobs:
cmake ${GITHUB_WORKSPACE} \ cmake ${GITHUB_WORKSPACE} \
-GNinja \ -GNinja \
-DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static \ -DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static \
-DCMAKE_TOOLCHAIN_FILE="c:\vcpkg\scripts\buildsystems\vcpkg.cmake" \ -DCMAKE_TOOLCHAIN_FILE="${{ runner.temp }}\vcpkg\scripts\buildsystems\vcpkg.cmake" \
-DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \ -DHOST_BINARY_DIR=${GITHUB_WORKSPACE}/build-host \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DOPTION_SURVEY_KEY=${{ inputs.survey_key }} \ -DOPTION_SURVEY_KEY=${{ inputs.survey_key }} \
-DWINDOWS_CERTIFICATE_COMMON_NAME="${WINDOWS_CERTIFICATE_COMMON_NAME}" \
# EOF # EOF
echo "::endgroup::" echo "::endgroup::"
@@ -159,7 +152,12 @@ jobs:
cmake --build . --target openttd cmake --build . --target openttd
echo "::endgroup::" echo "::endgroup::"
env: env:
WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
AZURE_CODESIGN_ACCOUNT_NAME: ${{ secrets.AZURE_CODESIGN_ACCOUNT_NAME }}
AZURE_CODESIGN_ENDPOINT: ${{ secrets.AZURE_CODESIGN_ENDPOINT }}
AZURE_CODESIGN_PROFILE_NAME: ${{ secrets.AZURE_CODESIGN_PROFILE_NAME }}
- name: Create breakpad symbols - name: Create breakpad symbols
shell: bash shell: bash
@@ -193,13 +191,15 @@ jobs:
- name: Sign installer - name: Sign installer
if: inputs.is_tag == 'true' if: inputs.is_tag == 'true'
shell: bash shell: bash
# If this is run on a fork, there may not be a certificate set up - continue in this case
continue-on-error: true
run: | run: |
cd ${GITHUB_WORKSPACE}/build/bundles ${GITHUB_WORKSPACE}/os/windows/sign.bat "${GITHUB_WORKSPACE}/build/bundles"
../../os/windows/sign.bat *.exe "${WINDOWS_CERTIFICATE_COMMON_NAME}"
env: env:
WINDOWS_CERTIFICATE_COMMON_NAME: ${{ secrets.WINDOWS_CERTIFICATE_COMMON_NAME }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
AZURE_CODESIGN_ACCOUNT_NAME: ${{ secrets.AZURE_CODESIGN_ACCOUNT_NAME }}
AZURE_CODESIGN_ENDPOINT: ${{ secrets.AZURE_CODESIGN_ENDPOINT }}
AZURE_CODESIGN_PROFILE_NAME: ${{ secrets.AZURE_CODESIGN_PROFILE_NAME }}
- name: Store bundles - name: Store bundles
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4

View File

@@ -5,7 +5,7 @@ if(NOT BINARY_NAME)
endif() endif()
project(${BINARY_NAME} project(${BINARY_NAME}
VERSION 14.0 VERSION 15.0
LANGUAGES CXX LANGUAGES CXX
) )

View File

@@ -157,7 +157,7 @@ enum SomeEnumeration {
* Use curly braces and put the contained statements on their own lines (e.g., don't put them directly after the **if**). * Use curly braces and put the contained statements on their own lines (e.g., don't put them directly after the **if**).
* Opening curly bracket **{** stays on the first line, closing curly bracket **}** gets a line to itself (except for the **}** preceding an **else**, which should be on the same line as the **else**). * Opening curly bracket **{** stays on the first line, closing curly bracket **}** gets a line to itself (except for the **}** preceding an **else**, which should be on the same line as the **else**).
* When only a single statement is contained, the brackets can be omitted. In this case, put the single statement on the same line as the preceding keyword (**if**, **while**, etc.). Note that this is only allowed for if statements without an **else** clause. * When only a single statement is contained, the brackets can be omitted. In this case, put the single statement on the same line as the preceding keyword (**if**, **while**, etc.). Note that this is only allowed for if statements without an **else** clause.
* All fall throughs must be documented, using a **FALLTHROUGH** define/macro. * Non-trivial fall throughs must be documented, using a `[[fallthrough]]` attribute.
* The NOT_REACHED() macro can be used in default constructs that should never be reached. * The NOT_REACHED() macro can be used in default constructs that should never be reached.
* Unconditional loops are written with **`for (;;) {`** * Unconditional loops are written with **`for (;;) {`**
@@ -180,7 +180,7 @@ switch (a) {
case 1: case 1:
DoSomething(); DoSomething();
FALLTHROUGH; [[fallthrough]];
case 2: case 2:
DoMore(); DoMore();
@@ -191,7 +191,7 @@ switch (a) {
int r = 2; int r = 2;
DoEvenMore(a); DoEvenMore(a);
FALLTHROUGH; [[fallthrough]];
} }
case 4: { case 4: {
@@ -248,7 +248,7 @@ Templates are a very powerful C++ tool, but they can easily confuse beginners. T
* Templates are to be documented in a very clear and verbose manner. Never assume anything in the documentation. * Templates are to be documented in a very clear and verbose manner. Never assume anything in the documentation.
* the template keyword and the template layout get a separate line. typenames are either "T" or preceded by a "T", integers get a single capital letter or a descriptive name preceded by "T". * the template keyword and the template layout get a separate line. typenames are either "T" or preceded by a "T", integers get a single capital letter or a descriptive name preceded by "T".
```c++ ```c++
template <typename T, typename Tsomething, int N, byte Tnumber_of_something> template <typename T, typename Tsomething, int N, uint8_t Tnumber_of_something>
int Func(); int Func();
``` ```

View File

@@ -110,9 +110,6 @@ builds.
- `-DOPTION_USE_ASSERTS=OFF`: disable asserts. Use with care, as assert - `-DOPTION_USE_ASSERTS=OFF`: disable asserts. Use with care, as assert
statements capture early signs of trouble. Release builds have them statements capture early signs of trouble. Release builds have them
disabled by default. disabled by default.
- `-DOPTION_USE_THREADS=OFF`: disable the use of threads. This will block
the interface in many places, and in general gives a worse experience of
the game. Use with care.
- `-DOPTION_TOOLS_ONLY=ON`: only build tools like `strgen`. Does not build - `-DOPTION_TOOLS_ONLY=ON`: only build tools like `strgen`. Does not build
the game itself. Useful for cross-compiling. the game itself. Useful for cross-compiling.

View File

@@ -3,14 +3,15 @@
- Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3) - Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)
- Christoph Elsenhans (frosch) - General coding (since 0.6) - Christoph Elsenhans (frosch) - General coding (since 0.6)
- Loïc Guilloux (glx) - General / Windows Expert (since 0.4.5) - Loïc Guilloux (glx) - General / Windows Expert (since 0.4.5)
- Koen Bussemaker (Kuhnovic) - General / Ship pathfinder (since 14)
- Charles Pigott (LordAro) - General / Correctness police (since 1.9) - Charles Pigott (LordAro) - General / Correctness police (since 1.9)
- Michael Lutz (michi_cc) - General / Path based signals (since 0.7) - Michael Lutz (michi_cc) - General / Path based signals (since 0.7)
- Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9) - Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)
- Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1) - Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)
- Peter Nelson (peter1138) - Spiritual descendant from newGRF gods (since 0.4.5) - Peter Nelson (peter1138) - Spiritual descendant from NewGRF gods (since 0.4.5)
- Remko Bijker (Rubidium) - Coder and way more (since 0.4.5) - Remko Bijker (Rubidium) - Coder and way more (since 0.4.5)
- Patric Stout (TrueBrain) - NoProgrammer (since 0.3), sys op - Patric Stout (TrueBrain) - NoProgrammer (since 0.3), sys op
- Tyler Trahan (2TallTyler) - General coding (since 13) - Tyler Trahan (2TallTyler) - General / Time Lord (since 13)
### Inactive Developers: ### Inactive Developers:

View File

@@ -15,6 +15,7 @@ set(AI_COMPAT_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/compat_12.nut ${CMAKE_CURRENT_SOURCE_DIR}/compat_12.nut
${CMAKE_CURRENT_SOURCE_DIR}/compat_13.nut ${CMAKE_CURRENT_SOURCE_DIR}/compat_13.nut
${CMAKE_CURRENT_SOURCE_DIR}/compat_14.nut ${CMAKE_CURRENT_SOURCE_DIR}/compat_14.nut
${CMAKE_CURRENT_SOURCE_DIR}/compat_15.nut
) )
foreach(AI_COMPAT_SOURCE_FILE IN LISTS AI_COMPAT_SOURCE_FILES) foreach(AI_COMPAT_SOURCE_FILE IN LISTS AI_COMPAT_SOURCE_FILES)

View File

@@ -4,3 +4,5 @@
* 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. * 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/>. * 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/>.
*/ */
AILog.Info("14 API compatibility in effect.");

View File

@@ -4,15 +4,3 @@
* 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. * 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/>. * 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 dropdown_func.h Functions related to the drop down widget. */
#ifndef WIDGETS_DROPDOWN_FUNC_H
#define WIDGETS_DROPDOWN_FUNC_H
#include "../window_gui.h"
/* Show drop down menu containing a fixed list of strings */
void ShowDropDownMenu(Window *w, const StringID *strings, int selected, WidgetID button, uint32_t disabled_mask, uint32_t hidden_mask, uint width = 0);
#endif /* WIDGETS_DROPDOWN_FUNC_H */

View File

@@ -12,6 +12,7 @@ set(GS_COMPAT_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/compat_12.nut ${CMAKE_CURRENT_SOURCE_DIR}/compat_12.nut
${CMAKE_CURRENT_SOURCE_DIR}/compat_13.nut ${CMAKE_CURRENT_SOURCE_DIR}/compat_13.nut
${CMAKE_CURRENT_SOURCE_DIR}/compat_14.nut ${CMAKE_CURRENT_SOURCE_DIR}/compat_14.nut
${CMAKE_CURRENT_SOURCE_DIR}/compat_15.nut
) )
foreach(GS_COMPAT_SOURCE_FILE IN LISTS GS_COMPAT_SOURCE_FILES) foreach(GS_COMPAT_SOURCE_FILE IN LISTS GS_COMPAT_SOURCE_FILES)

View File

@@ -4,3 +4,5 @@
* 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. * 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/>. * 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/>.
*/ */
GSLog.Info("14 API compatibility in effect.");

View File

@@ -4,26 +4,3 @@
* 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. * 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/>. * 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 script_timemode.cpp Implementation of ScriptTimeMode. */
#include "../../stdafx.h"
#include "script_timemode.hpp"
#include "../../safeguards.h"
ScriptTimeMode::ScriptTimeMode(bool calendar)
{
this->last_time_mode = ScriptObject::IsCalendarTimeMode();
ScriptObject::SetTimeMode(calendar);
}
ScriptTimeMode::~ScriptTimeMode()
{
ScriptObject::SetTimeMode(this->last_time_mode);
}
/* static */ bool ScriptTimeMode::IsCalendarMode()
{
return ScriptObject::IsCalendarTimeMode();
}

View File

@@ -74,12 +74,6 @@ macro(compile_flags)
# We use 'ABCD' multichar for SaveLoad chunks identifiers # We use 'ABCD' multichar for SaveLoad chunks identifiers
-Wno-multichar -Wno-multichar
# Compilers complains about that we break strict-aliasing.
# On most places we don't see how to fix it, and it doesn't
# break anything. So disable strict-aliasing to make the
# compiler all happy.
-fno-strict-aliasing
) )
# Ninja processes the output so the output from the compiler # Ninja processes the output so the output from the compiler

View File

@@ -56,7 +56,7 @@ 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" OFF) option(OPTION_USE_ASSERTS "Use assertions; leave enabled for nightlies, betas, and RCs" ON)
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_TOOLS_ONLY "Build only tools target" OFF)
option(OPTION_DOCS_ONLY "Build only docs target" OFF) option(OPTION_DOCS_ONLY "Build only docs target" OFF)

View File

@@ -19,7 +19,7 @@ Now simply open up the `crash.dmp`, and start debugging.
The best tool to use is `minidump-stackwalk` as published in the Rust's cargo index: The best tool to use is `minidump-stackwalk` as published in the Rust's cargo index:
```bash ```bash
cargo install minidump-stackwalk cargo install --locked minidump-stackwalk
``` ```
For how to install Rust, please see [here](https://doc.rust-lang.org/cargo/getting-started/installation.html). For how to install Rust, please see [here](https://doc.rust-lang.org/cargo/getting-started/installation.html).

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -3,4 +3,4 @@
The OpenTTD TrueType font was created by Zephyris and is maintained on [Github](https://github.com/zephyris/openttd-ttf). The OpenTTD TrueType font was created by Zephyris and is maintained on [Github](https://github.com/zephyris/openttd-ttf).
It is licensed under GPL-2.0. It is licensed under GPL-2.0.
The currently included files correspond to release v0.5. The currently included files correspond to release v0.6.

View File

@@ -1,18 +1,2 @@
@echo off @echo off
REM Signing script pwsh -File "%~dp0sign_azure.ps1" %1
REM Arguments: sign.bat exe_to_sign certificate_subject_name
REM This is a loose wrapper around the Microsoft signtool application (included in the Windows SDK).
REM See https://docs.microsoft.com/en-us/dotnet/framework/tools/signtool-exe for more details.
REM Path to signtool.exe
IF NOT DEFINED SIGNTOOL_PATH (SET SIGNTOOL_PATH=signtool)
REM URL of the timestamp server
IF NOT DEFINED SIGNTOOL_TIMESTAMP_URL (SET SIGNTOOL_TIMESTAMP_URL=http://timestamp.digicert.com)
REM Sign with SHA-1 for Windows 7 and below
"%SIGNTOOL_PATH%" sign -v -n %2 -t %SIGNTOOL_TIMESTAMP_URL% -fd sha1 %1
REM Sign with SHA-256 for Windows 8 and above
"%SIGNTOOL_PATH%" sign -v -n %2 -tr %SIGNTOOL_TIMESTAMP_URL% -fd sha256 -td sha256 -as %1

40
os/windows/sign_azure.ps1 Normal file
View File

@@ -0,0 +1,40 @@
# Signing script for Azure Code Signing
# Arguments: sign_azure.ps1 path_to_sign
#
# Environment variables must be set up before use:
#
# AZURE_TENANT_ID
# AZURE_CLIENT_ID
# AZURE_CLIENT_SECRET
# AZURE_CODESIGN_ACCOUNT_NAME
# AZURE_CODESIGN_ENDPOINT
# AZURE_CODESIGN_PROFILE_NAME
Param
(
# Files folder
[Parameter(Mandatory=$true, Position=0)]
$FilesFolder
)
if (!$Env:AZURE_CODESIGN_ENDPOINT -or !$Env:AZURE_CODESIGN_ACCOUNT_NAME -or !$Env:AZURE_CODESIGN_PROFILE_NAME -or
!$Env:AZURE_TENANT_ID -or !$Env:AZURE_CLIENT_ID -or !$Env:AZURE_CLIENT_SECRET)
{
"Code signing variables not found; most likely running in a fork. Skipping signing."
exit
}
Install-Module -Name AzureCodeSigning -Scope CurrentUser -RequiredVersion 0.3.0 -Force -Repository PSGallery
$params = @{}
$params["Endpoint"] = $Env:AZURE_CODESIGN_ENDPOINT
$params["CodeSigningAccountName"] = $Env:AZURE_CODESIGN_ACCOUNT_NAME
$params["CertificateProfileName"] = $Env:AZURE_CODESIGN_PROFILE_NAME
$params["FilesFolder"] = $FilesFolder
$params["FilesFolderFilter"] = "exe"
$params["FileDigest"] = "SHA256"
$params["TimestampRfc3161"] = "http://timestamp.acs.microsoft.com"
$params["TimestampDigest"] = "SHA256"
Invoke-AzureCodeSigning @params

View File

@@ -4,7 +4,7 @@ class Regression extends AIInfo {
function GetShortName() { return "REGR"; } function GetShortName() { return "REGR"; }
function GetDescription() { return "This runs regression-tests on some commands. On the same map the result should always be the same."; } function GetDescription() { return "This runs regression-tests on some commands. On the same map the result should always be the same."; }
function GetVersion() { return 1; } function GetVersion() { return 1; }
function GetAPIVersion() { return "14"; } function GetAPIVersion() { return "15"; }
function GetDate() { return "2007-03-18"; } function GetDate() { return "2007-03-18"; }
function CreateInstance() { return "Regression"; } function CreateInstance() { return "Regression"; }
function UseAsRandomAI() { return false; } function UseAsRandomAI() { return false; }

View File

@@ -4,7 +4,7 @@ class StationList extends AIInfo {
function GetShortName() { return "REGS"; } function GetShortName() { return "REGS"; }
function GetDescription() { return "This runs stationlist-tests on some commands. On the same map the result should always be the same."; } function GetDescription() { return "This runs stationlist-tests on some commands. On the same map the result should always be the same."; }
function GetVersion() { return 1; } function GetVersion() { return 1; }
function GetAPIVersion() { return "14"; } function GetAPIVersion() { return "15"; }
function GetDate() { return "2007-03-18"; } function GetDate() { return "2007-03-18"; }
function CreateInstance() { return "StationList"; } function CreateInstance() { return "StationList"; }
function UseAsRandomAI() { return false; } function UseAsRandomAI() { return false; }

View File

@@ -57,8 +57,8 @@
static const size_t MD5_HASH_BYTES = 16; static const size_t MD5_HASH_BYTES = 16;
/** Container for storing a MD5 hash/checksum/digest. */ /** Container for storing a MD5 hash/checksum/digest. */
struct MD5Hash : std::array<byte, MD5_HASH_BYTES> { struct MD5Hash : std::array<uint8_t, MD5_HASH_BYTES> {
MD5Hash() : std::array<byte, MD5_HASH_BYTES>{} {} MD5Hash() : std::array<uint8_t, MD5_HASH_BYTES>{} {}
/** /**
* Exclusively-or the given hash into this hash. * Exclusively-or the given hash into this hash.

View File

@@ -650,8 +650,7 @@ public:
_fs->AddInstruction(_OP_LOADINT, _exst._deref,_integer(constval)); _fs->AddInstruction(_OP_LOADINT, _exst._deref,_integer(constval));
} }
else if(ctype == OT_FLOAT && sizeof(SQFloat) == sizeof(SQInt32)) { else if(ctype == OT_FLOAT && sizeof(SQFloat) == sizeof(SQInt32)) {
SQFloat f = _float(constval); _fs->AddInstruction(_OP_LOADFLOAT, _exst._deref, std::bit_cast<SQInt32>(_float(constval)));
_fs->AddInstruction(_OP_LOADFLOAT, _exst._deref,*((SQInt32 *)&f));
} }
else { else {
_fs->AddInstruction(_OP_LOAD, _exst._deref, _fs->GetConstant(constval)); _fs->AddInstruction(_OP_LOAD, _exst._deref, _fs->GetConstant(constval));
@@ -697,7 +696,7 @@ public:
break; break;
case TK_FLOAT: case TK_FLOAT:
if(sizeof(SQFloat) == sizeof(SQInt32)) { if(sizeof(SQFloat) == sizeof(SQInt32)) {
_fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(),*((SQInt32 *)&_lex._fvalue)); _fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(), std::bit_cast<SQInt32>(_lex._fvalue));
} }
else { else {
_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue)); _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));

View File

@@ -199,7 +199,7 @@ void SQFuncState::Dump(SQFunctionProto *func)
} }
} }
else if(inst.op==_OP_LOADFLOAT) { else if(inst.op==_OP_LOADFLOAT) {
printf("[%03d] %15s %d %f %d %d\n",n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3); printf("[%03d] %15s %d %f %d %d\n",n,g_InstrDesc[inst.op].name,inst._arg0,std::bit_cast<SQFloat>(inst._arg1),inst._arg2,inst._arg3);
} }
else if(inst.op==_OP_ARITH){ else if(inst.op==_OP_ARITH){
printf("[%03d] %15s %d %d %d %c\n",n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); printf("[%03d] %15s %d %d %d %c\n",n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
@@ -242,19 +242,20 @@ SQInteger SQFuncState::GetConstant(const SQObject &cons)
void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3) void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
{ {
_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0); _instructions[pos]._arg0 = (unsigned char)std::bit_cast<SQUnsignedInteger>(arg0);
_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1); _instructions[pos]._arg1 = (SQInt32)std::bit_cast<SQUnsignedInteger>(arg1);
_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2); _instructions[pos]._arg2 = (unsigned char)std::bit_cast<SQUnsignedInteger>(arg2);
_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3); _instructions[pos]._arg3 = (unsigned char)std::bit_cast<SQUnsignedInteger>(arg3);
} }
void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val) void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
{ {
switch(arg){ switch(arg){
case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break; case 0: _instructions[pos]._arg0 = (unsigned char)std::bit_cast<SQUnsignedInteger>(val); break;
case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break; case 1:
case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break; case 4: _instructions[pos]._arg1 = (SQInt32)std::bit_cast<SQUnsignedInteger>(val); break;
case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break; case 2: _instructions[pos]._arg2 = (unsigned char)std::bit_cast<SQUnsignedInteger>(val); break;
case 3: _instructions[pos]._arg3 = (unsigned char)std::bit_cast<SQUnsignedInteger>(val); break;
}; };
} }

View File

@@ -51,7 +51,7 @@ bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,con
case BW_XOR: res = i1 ^ i2; break; case BW_XOR: res = i1 ^ i2; break;
case BW_SHIFTL: res = i1 << i2; break; case BW_SHIFTL: res = i1 << i2; break;
case BW_SHIFTR: res = i1 >> i2; break; case BW_SHIFTR: res = i1 >> i2; break;
case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); break; case BW_USHIFTR:res = (SQInteger)(std::bit_cast<SQUnsignedInteger>(i1) >> i2); break;
default: { Raise_Error("internal vm error bitwise op failed"); return false; } default: { Raise_Error("internal vm error bitwise op failed"); return false; }
} }
} }
@@ -472,10 +472,10 @@ bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjec
#define arg0 (_i_._arg0) #define arg0 (_i_._arg0)
#define arg1 (_i_._arg1) #define arg1 (_i_._arg1)
#define sarg1 (*(const_cast<SQInt32 *>(&_i_._arg1))) #define sarg1 (std::bit_cast<SQInt32>(_i_._arg1))
#define arg2 (_i_._arg2) #define arg2 (_i_._arg2)
#define arg3 (_i_._arg3) #define arg3 (_i_._arg3)
#define sarg3 ((SQInteger)*((const signed char *)&_i_._arg3)) #define sarg3 ((SQInteger)std::bit_cast<char>(_i_._arg3))
SQRESULT SQVM::Suspend() SQRESULT SQVM::Suspend()
{ {
@@ -764,7 +764,7 @@ exception_restore:
continue; continue;
case _OP_LOAD: TARGET = ci->_literals[arg1]; continue; case _OP_LOAD: TARGET = ci->_literals[arg1]; continue;
case _OP_LOADINT: TARGET = (SQInteger)arg1; continue; case _OP_LOADINT: TARGET = (SQInteger)arg1; continue;
case _OP_LOADFLOAT: TARGET = *((const SQFloat *)&arg1); continue; case _OP_LOADFLOAT: TARGET = std::bit_cast<SQFloat>(arg1); continue;
case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue; case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;
case _OP_TAILCALL: case _OP_TAILCALL:
temp_reg = STK(arg1); temp_reg = STK(arg1);

View File

@@ -52,6 +52,8 @@ add_files(
animated_tile_func.h animated_tile_func.h
articulated_vehicles.cpp articulated_vehicles.cpp
articulated_vehicles.h articulated_vehicles.h
autocompletion.cpp
autocompletion.h
autoreplace.cpp autoreplace.cpp
autoreplace_base.h autoreplace_base.h
autoreplace_cmd.cpp autoreplace_cmd.cpp
@@ -138,6 +140,10 @@ add_files(
dock_gui.cpp dock_gui.cpp
driver.cpp driver.cpp
driver.h driver.h
dropdown.cpp
dropdown_common_type.h
dropdown_func.h
dropdown_type.h
economy.cpp economy.cpp
economy_base.h economy_base.h
economy_cmd.h economy_cmd.h
@@ -393,6 +399,8 @@ add_files(
signs_func.h signs_func.h
signs_gui.cpp signs_gui.cpp
signs_type.h signs_type.h
slider.cpp
slider_func.h
slope_func.h slope_func.h
slope_type.h slope_type.h
smallmap_gui.cpp smallmap_gui.cpp

View File

@@ -27,9 +27,8 @@ public:
/** /**
* Start a new AI company. * Start a new AI company.
* @param company At which slot the AI company should start. * @param company At which slot the AI company should start.
* @param deviate Whether to apply random deviation to the configured AI.
*/ */
static void StartNew(CompanyID company, bool deviate = true); static void StartNew(CompanyID company);
/** /**
* Called every game-tick to let AIs do something. * Called every game-tick to let AIs do something.

View File

@@ -33,14 +33,14 @@
return !_networking || (_network_server && _settings_game.ai.ai_in_multiplayer); return !_networking || (_network_server && _settings_game.ai.ai_in_multiplayer);
} }
/* static */ void AI::StartNew(CompanyID company, bool deviate) /* static */ void AI::StartNew(CompanyID company)
{ {
assert(Company::IsValidID(company)); assert(Company::IsValidID(company));
/* Clients shouldn't start AIs */ /* Clients shouldn't start AIs */
if (_networking && !_network_server) return; if (_networking && !_network_server) return;
Backup<CompanyID> cur_company(_current_company, company, FILE_LINE); Backup<CompanyID> cur_company(_current_company, company);
Company *c = Company::Get(company); Company *c = Company::Get(company);
AIConfig *config = c->ai_config.get(); AIConfig *config = c->ai_config.get();
@@ -56,7 +56,6 @@
/* Load default data and store the name in the settings */ /* Load default data and store the name in the settings */
config->Change(info->GetName(), -1, false); config->Change(info->GetName(), -1, false);
} }
if (deviate) config->AddRandomDeviation(company);
config->AnchorUnchangeableSettings(); config->AnchorUnchangeableSettings();
c->ai_info = info; c->ai_info = info;
@@ -82,7 +81,7 @@
assert(_settings_game.difficulty.competitor_speed <= 4); assert(_settings_game.difficulty.competitor_speed <= 4);
if ((AI::frame_counter & ((1 << (4 - _settings_game.difficulty.competitor_speed)) - 1)) != 0) return; if ((AI::frame_counter & ((1 << (4 - _settings_game.difficulty.competitor_speed)) - 1)) != 0) return;
Backup<CompanyID> cur_company(_current_company, FILE_LINE); Backup<CompanyID> cur_company(_current_company);
for (const Company *c : Company::Iterate()) { for (const Company *c : Company::Iterate()) {
if (c->is_ai) { if (c->is_ai) {
PerformanceMeasurer framerate((PerformanceElement)(PFE_AI0 + c->index)); PerformanceMeasurer framerate((PerformanceElement)(PFE_AI0 + c->index));
@@ -110,7 +109,7 @@
if (_networking && !_network_server) return; if (_networking && !_network_server) return;
PerformanceMeasurer::SetInactive((PerformanceElement)(PFE_AI0 + company)); PerformanceMeasurer::SetInactive((PerformanceElement)(PFE_AI0 + company));
Backup<CompanyID> cur_company(_current_company, company, FILE_LINE); Backup<CompanyID> cur_company(_current_company, company);
Company *c = Company::Get(company); Company *c = Company::Get(company);
delete c->ai_instance; delete c->ai_instance;
@@ -130,7 +129,7 @@
* for the server owner to unpause the script again. */ * for the server owner to unpause the script again. */
if (_network_dedicated) return; if (_network_dedicated) return;
Backup<CompanyID> cur_company(_current_company, company, FILE_LINE); Backup<CompanyID> cur_company(_current_company, company);
Company::Get(company)->ai_instance->Pause(); Company::Get(company)->ai_instance->Pause();
cur_company.Restore(); cur_company.Restore();
@@ -138,7 +137,7 @@
/* static */ void AI::Unpause(CompanyID company) /* static */ void AI::Unpause(CompanyID company)
{ {
Backup<CompanyID> cur_company(_current_company, company, FILE_LINE); Backup<CompanyID> cur_company(_current_company, company);
Company::Get(company)->ai_instance->Unpause(); Company::Get(company)->ai_instance->Unpause();
cur_company.Restore(); cur_company.Restore();
@@ -146,7 +145,7 @@
/* static */ bool AI::IsPaused(CompanyID company) /* static */ bool AI::IsPaused(CompanyID company)
{ {
Backup<CompanyID> cur_company(_current_company, company, FILE_LINE); Backup<CompanyID> cur_company(_current_company, company);
bool paused = Company::Get(company)->ai_instance->IsPaused(); bool paused = Company::Get(company)->ai_instance->IsPaused();
cur_company.Restore(); cur_company.Restore();
@@ -215,25 +214,30 @@
if (!_settings_game.ai_config[c]->ResetInfo(true)) { if (!_settings_game.ai_config[c]->ResetInfo(true)) {
Debug(script, 0, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_game.ai_config[c]->GetName()); Debug(script, 0, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_game.ai_config[c]->GetName());
_settings_game.ai_config[c]->Change(std::nullopt); _settings_game.ai_config[c]->Change(std::nullopt);
if (Company::IsValidAiID(c)) {
/* The code belonging to an already running AI was deleted. We can only do
* one thing here to keep everything sane and that is kill the AI. After
* killing the offending AI we start a random other one in it's place, just
* like what would happen if the AI was missing during loading. */
AI::Stop(c);
AI::StartNew(c, false);
}
} else if (Company::IsValidAiID(c)) {
/* Update the reference in the Company struct. */
Company::Get(c)->ai_info = _settings_game.ai_config[c]->GetInfo();
} }
} }
if (_settings_newgame.ai_config[c] != nullptr && _settings_newgame.ai_config[c]->HasScript()) { if (_settings_newgame.ai_config[c] != nullptr && _settings_newgame.ai_config[c]->HasScript()) {
if (!_settings_newgame.ai_config[c]->ResetInfo(false)) { if (!_settings_newgame.ai_config[c]->ResetInfo(false)) {
Debug(script, 0, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_newgame.ai_config[c]->GetName()); Debug(script, 0, "After a reload, the AI by the name '{}' was no longer found, and removed from the list.", _settings_newgame.ai_config[c]->GetName());
_settings_newgame.ai_config[c]->Change(std::nullopt); _settings_newgame.ai_config[c]->Change(std::nullopt);
} }
} }
if (Company::IsValidAiID(c) && Company::Get(c)->ai_config != nullptr) {
AIConfig *config = Company::Get(c)->ai_config.get();
if (!config->ResetInfo(true)) {
/* The code belonging to an already running AI was deleted. We can only do
* one thing here to keep everything sane and that is kill the AI. After
* killing the offending AI we start a random other one in it's place, just
* like what would happen if the AI was missing during loading. */
AI::Stop(c);
AI::StartNew(c);
} else {
/* Update the reference in the Company struct. */
Company::Get(c)->ai_info = config->GetInfo();
}
}
} }
} }
@@ -255,7 +259,7 @@
} }
/* Queue the event */ /* Queue the event */
Backup<CompanyID> cur_company(_current_company, company, FILE_LINE); Backup<CompanyID> cur_company(_current_company, company);
Company::Get(_current_company)->ai_instance->InsertEvent(event); Company::Get(_current_company)->ai_instance->InsertEvent(event);
cur_company.Restore(); cur_company.Restore();
@@ -285,14 +289,18 @@
{ {
if (!_networking || _network_server) { if (!_networking || _network_server) {
Company *c = Company::GetIfValid(company); Company *c = Company::GetIfValid(company);
assert(c != nullptr && c->ai_instance != nullptr); assert(c != nullptr);
Backup<CompanyID> cur_company(_current_company, company, FILE_LINE); /* When doing emergency saving, an AI can be not fully initialised. */
c->ai_instance->Save(); if (c->ai_instance != nullptr) {
cur_company.Restore(); Backup<CompanyID> cur_company(_current_company, company);
} else { c->ai_instance->Save();
AIInstance::SaveEmpty(); cur_company.Restore();
return;
}
} }
AIInstance::SaveEmpty();
} }
/* static */ void AI::GetConsoleList(std::back_insert_iterator<std::string> &output_iterator, bool newest_only) /* static */ void AI::GetConsoleList(std::back_insert_iterator<std::string> &output_iterator, bool newest_only)

View File

@@ -82,7 +82,7 @@ static constexpr NWidgetPart _nested_ai_config_widgets[] = {
}; };
/** Window definition for the configure AI window. */ /** Window definition for the configure AI window. */
static WindowDesc _ai_config_desc(__FILE__, __LINE__, static WindowDesc _ai_config_desc(
WDP_CENTER, nullptr, 0, 0, WDP_CENTER, nullptr, 0, 0,
WC_GAME_OPTIONS, WC_NONE, WC_GAME_OPTIONS, WC_NONE,
0, 0,

View File

@@ -24,7 +24,7 @@
*/ */
static bool CheckAPIVersion(const std::string &api_version) static bool CheckAPIVersion(const std::string &api_version)
{ {
static const std::set<std::string> versions = { "0.7", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "1.10", "1.11", "12", "13", "14" }; static const std::set<std::string> versions = { "0.7", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "1.10", "1.11", "12", "13", "14", "15" };
return versions.find(api_version) != versions.end(); return versions.find(api_version) != versions.end();
} }

View File

@@ -64,6 +64,9 @@ void AIInstance::Died()
/* Intro is not supposed to use AI, but it may have 'dummy' AI which instant dies. */ /* Intro is not supposed to use AI, but it may have 'dummy' AI which instant dies. */
if (_game_mode == GM_MENU) return; if (_game_mode == GM_MENU) return;
/* Don't show errors while loading savegame. They will be shown at end of loading anyway. */
if (_switch_mode != SM_NONE) return;
ShowScriptDebugWindow(_current_company); ShowScriptDebugWindow(_current_company);
const AIInfo *info = AIConfig::GetConfig(_current_company)->GetInfo(); const AIInfo *info = AIConfig::GetConfig(_current_company)->GetInfo();

View File

@@ -73,14 +73,14 @@ struct AircraftCache {
*/ */
struct Aircraft final : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> { struct Aircraft final : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
uint16_t crashed_counter; ///< Timer for handling crash animations. uint16_t crashed_counter; ///< Timer for handling crash animations.
byte pos; ///< Next desired position of the aircraft. uint8_t pos; ///< Next desired position of the aircraft.
byte previous_pos; ///< Previous desired position of the aircraft. uint8_t previous_pos; ///< Previous desired position of the aircraft.
StationID targetairport; ///< Airport to go to next. StationID targetairport; ///< Airport to go to next.
byte state; ///< State of the airport. @see AirportMovementStates uint8_t state; ///< State of the airport. @see AirportMovementStates
Direction last_direction; Direction last_direction;
byte number_consecutive_turns; ///< Protection to prevent the aircraft of making a lot of turns in order to reach a specific point. uint8_t number_consecutive_turns; ///< Protection to prevent the aircraft of making a lot of turns in order to reach a specific point.
byte turn_counter; ///< Ticks between each turn to prevent > 45 degree turns. uint8_t turn_counter; ///< Ticks between each turn to prevent > 45 degree turns.
byte flags; ///< Aircraft flags. @see AirVehicleFlags uint8_t flags; ///< Aircraft flags. @see AirVehicleFlags
AircraftCache acache; AircraftCache acache;
@@ -111,6 +111,7 @@ struct Aircraft final : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
void OnNewEconomyDay() override; void OnNewEconomyDay() override;
uint Crash(bool flooded = false) override; uint Crash(bool flooded = false) override;
TileIndex GetOrderStationLocation(StationID station) override; TileIndex GetOrderStationLocation(StationID station) override;
TileIndex GetCargoTile() const override { return this->First()->tile; }
ClosestDepot FindClosestDepot() override; ClosestDepot FindClosestDepot() override;
/** /**

View File

@@ -134,7 +134,7 @@ static StationID FindNearestHangar(const Aircraft *v)
const Station *next_dest = nullptr; const Station *next_dest = nullptr;
if (max_range != 0) { if (max_range != 0) {
if (v->current_order.IsType(OT_GOTO_STATION) || if (v->current_order.IsType(OT_GOTO_STATION) ||
(v->current_order.IsType(OT_GOTO_DEPOT) && v->current_order.GetDepotActionType() != ODATFB_NEAREST_DEPOT)) { (v->current_order.IsType(OT_GOTO_DEPOT) && (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0)) {
last_dest = Station::GetIfValid(v->last_station_visited); last_dest = Station::GetIfValid(v->last_station_visited);
next_dest = Station::GetIfValid(v->current_order.GetDestination()); next_dest = Station::GetIfValid(v->current_order.GetDestination());
} else { } else {
@@ -456,6 +456,7 @@ void Aircraft::OnNewCalendarDay()
void Aircraft::OnNewEconomyDay() void Aircraft::OnNewEconomyDay()
{ {
if (!this->IsNormalAircraft()) return; if (!this->IsNormalAircraft()) return;
EconomyAgeVehicle(this);
if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this); if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
@@ -654,7 +655,7 @@ static int UpdateAircraftSpeed(Aircraft *v, uint speed_limit = SPEED_LIMIT_NONE,
* ~ acceleration * 77 (km-ish/h / 256) * ~ acceleration * 77 (km-ish/h / 256)
*/ */
uint spd = v->acceleration * 77; uint spd = v->acceleration * 77;
byte t; uint8_t t;
/* Adjust speed limits by plane speed factor to prevent taxiing /* Adjust speed limits by plane speed factor to prevent taxiing
* and take-off speeds being too low. */ * and take-off speeds being too low. */
@@ -671,7 +672,7 @@ static int UpdateAircraftSpeed(Aircraft *v, uint speed_limit = SPEED_LIMIT_NONE,
speed_limit = v->vcache.cached_max_speed; speed_limit = v->vcache.cached_max_speed;
} }
v->subspeed = (t = v->subspeed) + (byte)spd; v->subspeed = (t = v->subspeed) + (uint8_t)spd;
/* Aircraft's current speed is used twice so that very fast planes are /* Aircraft's current speed is used twice so that very fast planes are
* forced to slow down rapidly in the short distance needed. The magic * forced to slow down rapidly in the short distance needed. The magic
@@ -698,7 +699,7 @@ static int UpdateAircraftSpeed(Aircraft *v, uint speed_limit = SPEED_LIMIT_NONE,
spd = v->GetOldAdvanceSpeed(spd); spd = v->GetOldAdvanceSpeed(spd);
spd += v->progress; spd += v->progress;
v->progress = (byte)spd; v->progress = (uint8_t)spd;
return spd >> 8; return spd >> 8;
} }
@@ -824,7 +825,7 @@ template int GetAircraftFlightLevel(Aircraft *v, bool takeoff);
* @param rotation The rotation of the airport. * @param rotation The rotation of the airport.
* @return The index of the entry point * @return The index of the entry point
*/ */
static byte AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *apc, Direction rotation) static uint8_t AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *apc, Direction rotation)
{ {
assert(v != nullptr); assert(v != nullptr);
assert(apc != nullptr); assert(apc != nullptr);
@@ -1284,7 +1285,7 @@ void HandleMissingAircraftOrders(Aircraft *v)
*/ */
const Station *st = GetTargetAirportIfValid(v); const Station *st = GetTargetAirportIfValid(v);
if (st == nullptr) { if (st == nullptr) {
Backup<CompanyID> cur_company(_current_company, v->owner, FILE_LINE); Backup<CompanyID> cur_company(_current_company, v->owner);
CommandCost ret = Command<CMD_SEND_VEHICLE_TO_DEPOT>::Do(DC_EXEC, v->index, DepotCommand::None, {}); CommandCost ret = Command<CMD_SEND_VEHICLE_TO_DEPOT>::Do(DC_EXEC, v->index, DepotCommand::None, {});
cur_company.Restore(); cur_company.Restore();
@@ -1650,7 +1651,7 @@ static void AircraftEventHandler_HeliTakeOff(Aircraft *v, const AirportFTAClass
/* Send the helicopter to a hangar if needed for replacement */ /* Send the helicopter to a hangar if needed for replacement */
if (v->NeedsAutomaticServicing()) { if (v->NeedsAutomaticServicing()) {
Backup<CompanyID> cur_company(_current_company, v->owner, FILE_LINE); Backup<CompanyID> cur_company(_current_company, v->owner);
Command<CMD_SEND_VEHICLE_TO_DEPOT>::Do(DC_EXEC, v->index, DepotCommand::Service | DepotCommand::LocateHangar, {}); Command<CMD_SEND_VEHICLE_TO_DEPOT>::Do(DC_EXEC, v->index, DepotCommand::Service | DepotCommand::LocateHangar, {});
cur_company.Restore(); cur_company.Restore();
} }
@@ -1665,7 +1666,7 @@ static void AircraftEventHandler_Flying(Aircraft *v, const AirportFTAClass *apc)
/* {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41}, /* {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41},
* if it is an airplane, look for LANDING, for helicopter HELILANDING * if it is an airplane, look for LANDING, for helicopter HELILANDING
* it is possible to choose from multiple landing runways, so loop until a free one is found */ * it is possible to choose from multiple landing runways, so loop until a free one is found */
byte landingtype = (v->subtype == AIR_HELICOPTER) ? HELILANDING : LANDING; uint8_t landingtype = (v->subtype == AIR_HELICOPTER) ? HELILANDING : LANDING;
const AirportFTA *current = apc->layout[v->pos].next; const AirportFTA *current = apc->layout[v->pos].next;
while (current != nullptr) { while (current != nullptr) {
if (current->heading == landingtype) { if (current->heading == landingtype) {
@@ -1701,7 +1702,7 @@ static void AircraftEventHandler_Landing(Aircraft *v, const AirportFTAClass *)
/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */ /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */
if (v->NeedsAutomaticServicing()) { if (v->NeedsAutomaticServicing()) {
Backup<CompanyID> cur_company(_current_company, v->owner, FILE_LINE); Backup<CompanyID> cur_company(_current_company, v->owner);
Command<CMD_SEND_VEHICLE_TO_DEPOT>::Do(DC_EXEC, v->index, DepotCommand::Service, {}); Command<CMD_SEND_VEHICLE_TO_DEPOT>::Do(DC_EXEC, v->index, DepotCommand::Service, {});
cur_company.Restore(); cur_company.Restore();
} }
@@ -1812,8 +1813,8 @@ static bool AirportMove(Aircraft *v, const AirportFTAClass *apc)
const AirportFTA *current = &apc->layout[v->pos]; const AirportFTA *current = &apc->layout[v->pos];
/* we have arrived in an important state (eg terminal, hangar, etc.) */ /* we have arrived in an important state (eg terminal, hangar, etc.) */
if (current->heading == v->state) { if (current->heading == v->state) {
byte prev_pos = v->pos; // location could be changed in state, so save it before-hand uint8_t prev_pos = v->pos; // location could be changed in state, so save it before-hand
byte prev_state = v->state; uint8_t prev_state = v->state;
_aircraft_state_handlers[v->state](v, apc); _aircraft_state_handlers[v->state](v, apc);
if (v->state != FLYING) v->previous_pos = prev_pos; if (v->state != FLYING) v->previous_pos = prev_pos;
if (v->state != prev_state || v->pos != prev_pos) UpdateAircraftCache(v); if (v->state != prev_state || v->pos != prev_pos) UpdateAircraftCache(v);
@@ -1949,7 +1950,7 @@ static const MovementTerminalMapping _airport_terminal_mapping[] = {
* @param last_terminal Terminal number to stop examining. * @param last_terminal Terminal number to stop examining.
* @return A terminal or helipad has been found, and has been assigned to the aircraft. * @return A terminal or helipad has been found, and has been assigned to the aircraft.
*/ */
static bool FreeTerminal(Aircraft *v, byte i, byte last_terminal) static bool FreeTerminal(Aircraft *v, uint8_t i, uint8_t last_terminal)
{ {
assert(last_terminal <= lengthof(_airport_terminal_mapping)); assert(last_terminal <= lengthof(_airport_terminal_mapping));
Station *st = Station::Get(v->targetairport); Station *st = Station::Get(v->targetairport);

View File

@@ -110,12 +110,12 @@ AirportMovingData RotateAirportMovingData(const AirportMovingData *orig, Directi
AirportFTAClass::AirportFTAClass( AirportFTAClass::AirportFTAClass(
const AirportMovingData *moving_data_, const AirportMovingData *moving_data_,
const byte *terminals_, const uint8_t *terminals_,
const byte num_helipads_, const uint8_t num_helipads_,
const byte *entry_points_, const uint8_t *entry_points_,
Flags flags_, Flags flags_,
const AirportFTAbuildup *apFA, const AirportFTAbuildup *apFA,
byte delta_z_ uint8_t delta_z_
) : ) :
moving_data(moving_data_), moving_data(moving_data_),
terminals(terminals_), terminals(terminals_),
@@ -204,7 +204,7 @@ static AirportFTA *AirportBuildAutomata(uint nofelements, const AirportFTAbuildu
* @param airport_type %Airport type to query FTA from. @see AirportTypes * @param airport_type %Airport type to query FTA from. @see AirportTypes
* @return Finite state machine of the airport. * @return Finite state machine of the airport.
*/ */
const AirportFTAClass *GetAirport(const byte airport_type) const AirportFTAClass *GetAirport(const uint8_t airport_type)
{ {
if (airport_type == AT_DUMMY) return &_airportfta_dummy; if (airport_type == AT_DUMMY) return &_airportfta_dummy;
return AirportSpec::Get(airport_type)->fsm; return AirportSpec::Get(airport_type)->fsm;
@@ -215,7 +215,7 @@ const AirportFTAClass *GetAirport(const byte airport_type)
* @param hangar_tile The tile on which the vehicle is build * @param hangar_tile The tile on which the vehicle is build
* @return The position (index in airport node array) where the aircraft ends up * @return The position (index in airport node array) where the aircraft ends up
*/ */
byte GetVehiclePosOnBuild(TileIndex hangar_tile) uint8_t GetVehiclePosOnBuild(TileIndex hangar_tile)
{ {
const Station *st = Station::GetByTile(hangar_tile); const Station *st = Station::GetByTile(hangar_tile);
const AirportFTAClass *apc = st->airport.GetFTA(); const AirportFTAClass *apc = st->airport.GetFTA();

View File

@@ -152,12 +152,12 @@ public:
AirportFTAClass( AirportFTAClass(
const AirportMovingData *moving_data, const AirportMovingData *moving_data,
const byte *terminals, const uint8_t *terminals,
const byte num_helipads, const uint8_t num_helipads,
const byte *entry_points, const uint8_t *entry_points,
Flags flags, Flags flags,
const AirportFTAbuildup *apFA, const AirportFTAbuildup *apFA,
byte delta_z uint8_t delta_z
); );
~AirportFTAClass(); ~AirportFTAClass();
@@ -167,7 +167,7 @@ public:
* @param position Element number to get movement data about. * @param position Element number to get movement data about.
* @return Pointer to the movement data. * @return Pointer to the movement data.
*/ */
const AirportMovingData *MovingData(byte position) const const AirportMovingData *MovingData(uint8_t position) const
{ {
assert(position < nofelements); assert(position < nofelements);
return &moving_data[position]; return &moving_data[position];
@@ -175,12 +175,12 @@ public:
const AirportMovingData *moving_data; ///< Movement data. const AirportMovingData *moving_data; ///< Movement data.
struct AirportFTA *layout; ///< state machine for airport struct AirportFTA *layout; ///< state machine for airport
const byte *terminals; ///< %Array with the number of terminal groups, followed by the number of terminals in each group. const uint8_t *terminals; ///< %Array with the number of terminal groups, followed by the number of terminals in each group.
const byte num_helipads; ///< Number of helipads on this airport. When 0 helicopters will go to normal terminals. const uint8_t num_helipads; ///< Number of helipads on this airport. When 0 helicopters will go to normal terminals.
Flags flags; ///< Flags for this airport type. Flags flags; ///< Flags for this airport type.
byte nofelements; ///< number of positions the airport consists of uint8_t nofelements; ///< number of positions the airport consists of
const byte *entry_points; ///< when an airplane arrives at this airport, enter it at position entry_point, index depends on direction const uint8_t *entry_points; ///< when an airplane arrives at this airport, enter it at position entry_point, index depends on direction
byte delta_z; ///< Z adjustment for helicopter pads uint8_t delta_z; ///< Z adjustment for helicopter pads
}; };
DECLARE_ENUM_AS_BIT_SET(AirportFTAClass::Flags) DECLARE_ENUM_AS_BIT_SET(AirportFTAClass::Flags)
@@ -190,12 +190,12 @@ DECLARE_ENUM_AS_BIT_SET(AirportFTAClass::Flags)
struct AirportFTA { struct AirportFTA {
AirportFTA *next; ///< possible extra movement choices from this position AirportFTA *next; ///< possible extra movement choices from this position
uint64_t block; ///< 64 bit blocks (st->airport.flags), should be enough for the most complex airports uint64_t block; ///< 64 bit blocks (st->airport.flags), should be enough for the most complex airports
byte position; ///< the position that an airplane is at uint8_t position; ///< the position that an airplane is at
byte next_position; ///< next position from this position uint8_t next_position; ///< next position from this position
byte heading; ///< heading (current orders), guiding an airplane to its target on an airport uint8_t heading; ///< heading (current orders), guiding an airplane to its target on an airport
}; };
const AirportFTAClass *GetAirport(const byte airport_type); const AirportFTAClass *GetAirport(const uint8_t airport_type);
byte GetVehiclePosOnBuild(TileIndex hangar_tile); uint8_t GetVehiclePosOnBuild(TileIndex hangar_tile);
#endif /* AIRPORT_H */ #endif /* AIRPORT_H */

View File

@@ -22,7 +22,8 @@
#include "station_type.h" #include "station_type.h"
#include "newgrf_airport.h" #include "newgrf_airport.h"
#include "newgrf_callbacks.h" #include "newgrf_callbacks.h"
#include "widgets/dropdown_type.h" #include "dropdown_type.h"
#include "dropdown_func.h"
#include "core/geometry_func.hpp" #include "core/geometry_func.hpp"
#include "hotkeys.h" #include "hotkeys.h"
#include "vehicle_func.h" #include "vehicle_func.h"
@@ -42,11 +43,11 @@
static AirportClassID _selected_airport_class; ///< the currently visible airport class static AirportClassID _selected_airport_class; ///< the currently visible airport class
static int _selected_airport_index; ///< the index of the selected airport in the current class or -1 static int _selected_airport_index; ///< the index of the selected airport in the current class or -1
static byte _selected_airport_layout; ///< selected airport layout number. static uint8_t _selected_airport_layout; ///< selected airport layout number.
static void ShowBuildAirportPicker(Window *parent); static void ShowBuildAirportPicker(Window *parent);
SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout); SpriteID GetCustomAirportSprite(const AirportSpec *as, uint8_t layout);
void CcBuildAirport(Commands, const CommandCost &result, TileIndex tile) void CcBuildAirport(Commands, const CommandCost &result, TileIndex tile)
{ {
@@ -64,8 +65,8 @@ static void PlaceAirport(TileIndex tile)
{ {
if (_selected_airport_index == -1) return; if (_selected_airport_index == -1) return;
byte airport_type = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex(); uint8_t airport_type = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex();
byte layout = _selected_airport_layout; uint8_t layout = _selected_airport_layout;
bool adjacent = _ctrl_pressed; bool adjacent = _ctrl_pressed;
auto proc = [=](bool test, StationID to_join) -> bool { auto proc = [=](bool test, StationID to_join) -> bool {
@@ -223,7 +224,7 @@ static constexpr NWidgetPart _nested_air_toolbar_widgets[] = {
EndContainer(), EndContainer(),
}; };
static WindowDesc _air_toolbar_desc(__FILE__, __LINE__, static WindowDesc _air_toolbar_desc(
WDP_ALIGN_TOOLBAR, "toolbar_air", 0, 0, WDP_ALIGN_TOOLBAR, "toolbar_air", 0, 0,
WC_BUILD_TOOLBAR, WC_NONE, WC_BUILD_TOOLBAR, WC_NONE,
WDF_CONSTRUCTION, WDF_CONSTRUCTION,
@@ -257,7 +258,7 @@ class BuildAirportWindow : public PickerWindowBase {
DropDownList list; DropDownList list;
for (uint i = 0; i < AirportClass::GetClassCount(); i++) { for (uint i = 0; i < AirportClass::GetClassCount(); i++) {
list.push_back(std::make_unique<DropDownListStringItem>(AirportClass::Get((AirportClassID)i)->name, i, false)); list.push_back(MakeDropDownListStringItem(AirportClass::Get((AirportClassID)i)->name, i));
} }
return list; return list;
@@ -364,7 +365,7 @@ public:
for (int i = 0; i < NUM_AIRPORTS; i++) { for (int i = 0; i < NUM_AIRPORTS; i++) {
const AirportSpec *as = AirportSpec::Get(i); const AirportSpec *as = AirportSpec::Get(i);
if (!as->enabled) continue; if (!as->enabled) continue;
for (byte layout = 0; layout < as->num_table; layout++) { for (uint8_t layout = 0; layout < as->num_table; layout++) {
SpriteID sprite = GetCustomAirportSprite(as, layout); SpriteID sprite = GetCustomAirportSprite(as, layout);
if (sprite != 0) { if (sprite != 0) {
Dimension d = GetSpriteSize(sprite); Dimension d = GetSpriteSize(sprite);
@@ -380,7 +381,7 @@ public:
for (int i = NEW_AIRPORT_OFFSET; i < NUM_AIRPORTS; i++) { for (int i = NEW_AIRPORT_OFFSET; i < NUM_AIRPORTS; i++) {
const AirportSpec *as = AirportSpec::Get(i); const AirportSpec *as = AirportSpec::Get(i);
if (!as->enabled) continue; if (!as->enabled) continue;
for (byte layout = 0; layout < as->num_table; layout++) { for (uint8_t layout = 0; layout < as->num_table; layout++) {
StringID string = GetAirportTextCallback(as, layout, CBID_AIRPORT_ADDITIONAL_TEXT); StringID string = GetAirportTextCallback(as, layout, CBID_AIRPORT_ADDITIONAL_TEXT);
if (string == STR_UNDEFINED) continue; if (string == STR_UNDEFINED) continue;
@@ -512,8 +513,8 @@ public:
break; break;
case WID_AP_AIRPORT_LIST: { case WID_AP_AIRPORT_LIST: {
int num_clicked = this->vscroll->GetScrolledRowFromWidget(pt.y, this, widget, 0, this->line_height); int32_t num_clicked = this->vscroll->GetScrolledRowFromWidget(pt.y, this, widget, 0, this->line_height);
if (num_clicked == INT_MAX) break; if (num_clicked == INT32_MAX) break;
const AirportSpec *as = AirportClass::Get(_selected_airport_class)->GetSpec(num_clicked); const AirportSpec *as = AirportClass::Get(_selected_airport_class)->GetSpec(num_clicked);
if (as->IsAvailable()) this->SelectOtherAirport(num_clicked); if (as->IsAvailable()) this->SelectOtherAirport(num_clicked);
break; break;
@@ -635,7 +636,7 @@ static constexpr NWidgetPart _nested_build_airport_widgets[] = {
EndContainer(), EndContainer(),
}; };
static WindowDesc _build_airport_desc(__FILE__, __LINE__, static WindowDesc _build_airport_desc(
WDP_AUTO, nullptr, 0, 0, WDP_AUTO, nullptr, 0, 0,
WC_BUILD_STATION, WC_BUILD_TOOLBAR, WC_BUILD_STATION, WC_BUILD_TOOLBAR,
WDF_CONSTRUCTION, WDF_CONSTRUCTION,

66
src/autocompletion.cpp Normal file
View File

@@ -0,0 +1,66 @@
/*
* 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 autocompletion.cpp Generic auto-completion engine. */
#include "stdafx.h"
#include "autocompletion.h"
#include "console_internal.h"
#include "town.h"
#include "network/network_base.h"
#include "safeguards.h"
bool AutoCompletion::AutoComplete()
{
// We are pressing TAB for the first time after reset.
if (this->suggestions.empty()) {
this->InitSuggestions(this->textbuf->buf);
if (this->suggestions.empty()) {
return false;
}
this->ApplySuggestion(prefix, suggestions[0]);
return true;
}
// We are pressing TAB again on the same text.
if (this->current_suggestion_index + 1 < this->suggestions.size()) {
this->ApplySuggestion(prefix, this->suggestions[++this->current_suggestion_index]);
} else {
// We are out of options, restore original text.
this->textbuf->Assign(initial_buf);
this->Reset();
}
return true;
}
void AutoCompletion::Reset()
{
this->prefix = "";
this->query = "";
this->initial_buf.clear();
this->suggestions.clear();
this->current_suggestion_index = 0;
}
void AutoCompletion::InitSuggestions(std::string_view text)
{
this->initial_buf = text;
size_t space_pos = this->initial_buf.find_last_of(' ');
this->query = this->initial_buf;
if (space_pos == std::string::npos) {
this->prefix = "";
} else {
this->prefix = this->query.substr(0, space_pos + 1);
this->query.remove_prefix(space_pos + 1);
}
this->suggestions = this->GetSuggestions(prefix, query);
this->current_suggestion_index = 0;
}

46
src/autocompletion.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* 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 autocompletion.h Generic auto-completion engine. */
#ifndef AUTOCOMPLETION_H
#define AUTOCOMPLETION_H
#include "textbuf_type.h"
class AutoCompletion {
protected:
Textbuf *textbuf;
private:
std::string initial_buf; ///< Value of text buffer when we started current suggestion session.
std::string_view prefix; ///< Prefix of the text before the last space.
std::string_view query; ///< Last token of the text. This is used to based the suggestions on.
std::vector<std::string> suggestions;
size_t current_suggestion_index;
public:
AutoCompletion(Textbuf *textbuf) : textbuf(textbuf)
{
this->Reset();
}
virtual ~AutoCompletion() = default;
// Returns true the textbuf was updated.
bool AutoComplete();
void Reset();
private:
void InitSuggestions(std::string_view text);
virtual std::vector<std::string> GetSuggestions(std::string_view prefix, std::string_view query) = 0;
virtual void ApplySuggestion(std::string_view prefix, std::string_view suggestion) = 0;
};
#endif /* AUTOCOMPLETION_H */

View File

@@ -362,7 +362,7 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic
/* Refit the vehicle if needed */ /* Refit the vehicle if needed */
if (refit_cargo != CARGO_NO_REFIT) { if (refit_cargo != CARGO_NO_REFIT) {
byte subtype = GetBestFittingSubType(old_veh, new_veh, refit_cargo); uint8_t subtype = GetBestFittingSubType(old_veh, new_veh, refit_cargo);
cost.AddCost(std::get<0>(Command<CMD_REFIT_VEHICLE>::Do(DC_EXEC, new_veh->index, refit_cargo, subtype, false, false, 0))); cost.AddCost(std::get<0>(Command<CMD_REFIT_VEHICLE>::Do(DC_EXEC, new_veh->index, refit_cargo, subtype, false, false, 0)));
assert(cost.Succeeded()); // This should be ensured by GetNewCargoTypeForReplace() assert(cost.Succeeded()); // This should be ensured by GetNewCargoTypeForReplace()

View File

@@ -25,7 +25,8 @@
#include "core/geometry_func.hpp" #include "core/geometry_func.hpp"
#include "rail_gui.h" #include "rail_gui.h"
#include "road_gui.h" #include "road_gui.h"
#include "widgets/dropdown_func.h" #include "dropdown_type.h"
#include "dropdown_func.h"
#include "autoreplace_cmd.h" #include "autoreplace_cmd.h"
#include "group_cmd.h" #include "group_cmd.h"
#include "settings_cmd.h" #include "settings_cmd.h"
@@ -34,7 +35,7 @@
#include "safeguards.h" #include "safeguards.h"
void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_list, uint16_t min, uint16_t max, EngineID selected_id, bool show_count, GroupID selected_group); void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_list, const Scrollbar &sb, EngineID selected_id, bool show_count, GroupID selected_group);
static bool EngineNumberSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) static bool EngineNumberSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
{ {
@@ -86,7 +87,7 @@ class ReplaceVehicleWindow : public Window {
bool reset_sel_engine; ///< Also reset #sel_engine while updating left and/or right and no valid engine selected. bool reset_sel_engine; ///< Also reset #sel_engine while updating left and/or right and no valid engine selected.
GroupID sel_group; ///< Group selected to replace. GroupID sel_group; ///< Group selected to replace.
int details_height; ///< Minimal needed height of the details panels, in text lines (found so far). int details_height; ///< Minimal needed height of the details panels, in text lines (found so far).
byte sort_criteria; ///< Criteria of sorting vehicles. uint8_t sort_criteria; ///< Criteria of sorting vehicles.
bool descending_sort_order; ///< Order of sorting vehicles. bool descending_sort_order; ///< Order of sorting vehicles.
bool show_hidden_engines; ///< Whether to show the hidden engines. bool show_hidden_engines; ///< Whether to show the hidden engines.
RailType sel_railtype; ///< Type of rail tracks selected. #INVALID_RAILTYPE to show all. RailType sel_railtype; ///< Type of rail tracks selected. #INVALID_RAILTYPE to show all.
@@ -144,7 +145,7 @@ class ReplaceVehicleWindow : public Window {
std::vector<EngineID> variants; std::vector<EngineID> variants;
EngineID selected_engine = INVALID_ENGINE; EngineID selected_engine = INVALID_ENGINE;
VehicleType type = (VehicleType)this->window_number; VehicleType type = (VehicleType)this->window_number;
byte side = draw_left ? 0 : 1; uint8_t side = draw_left ? 0 : 1;
GUIEngineList list; GUIEngineList list;
@@ -490,11 +491,9 @@ public:
case WID_RV_LEFT_MATRIX: case WID_RV_LEFT_MATRIX:
case WID_RV_RIGHT_MATRIX: { case WID_RV_RIGHT_MATRIX: {
int side = (widget == WID_RV_LEFT_MATRIX) ? 0 : 1; int side = (widget == WID_RV_LEFT_MATRIX) ? 0 : 1;
EngineID start = static_cast<EngineID>(this->vscroll[side]->GetPosition()); // what is the offset for the start (scrolling)
EngineID end = static_cast<EngineID>(std::min<size_t>(this->vscroll[side]->GetCapacity() + start, this->engines[side].size()));
/* Do the actual drawing */ /* Do the actual drawing */
DrawEngineList((VehicleType)this->window_number, r, this->engines[side], start, end, this->sel_engine[side], side == 0, this->sel_group); DrawEngineList((VehicleType)this->window_number, r, this->engines[side], *this->vscroll[side], this->sel_engine[side], side == 0, this->sel_group);
break; break;
} }
} }
@@ -568,8 +567,8 @@ public:
case WID_RV_TRAIN_ENGINEWAGON_DROPDOWN: { case WID_RV_TRAIN_ENGINEWAGON_DROPDOWN: {
DropDownList list; DropDownList list;
list.push_back(std::make_unique<DropDownListStringItem>(STR_REPLACE_ENGINES, 1, false)); list.push_back(MakeDropDownListStringItem(STR_REPLACE_ENGINES, 1));
list.push_back(std::make_unique<DropDownListStringItem>(STR_REPLACE_WAGONS, 0, false)); list.push_back(MakeDropDownListStringItem(STR_REPLACE_WAGONS, 0));
ShowDropDownList(this, std::move(list), this->replace_engines ? 1 : 0, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN); ShowDropDownList(this, std::move(list), this->replace_engines ? 1 : 0, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN);
break; break;
} }
@@ -612,7 +611,7 @@ public:
case WID_RV_LEFT_MATRIX: case WID_RV_LEFT_MATRIX:
case WID_RV_RIGHT_MATRIX: { case WID_RV_RIGHT_MATRIX: {
byte click_side; uint8_t click_side;
if (widget == WID_RV_LEFT_MATRIX) { if (widget == WID_RV_LEFT_MATRIX) {
click_side = 0; click_side = 0;
} else { } else {
@@ -788,7 +787,7 @@ static constexpr NWidgetPart _nested_replace_rail_vehicle_widgets[] = {
EndContainer(), EndContainer(),
}; };
static WindowDesc _replace_rail_vehicle_desc(__FILE__, __LINE__, static WindowDesc _replace_rail_vehicle_desc(
WDP_AUTO, "replace_vehicle_train", 500, 140, WDP_AUTO, "replace_vehicle_train", 500, 140,
WC_REPLACE_VEHICLE, WC_NONE, WC_REPLACE_VEHICLE, WC_NONE,
WDF_CONSTRUCTION, WDF_CONSTRUCTION,
@@ -846,7 +845,7 @@ static constexpr NWidgetPart _nested_replace_road_vehicle_widgets[] = {
EndContainer(), EndContainer(),
}; };
static WindowDesc _replace_road_vehicle_desc(__FILE__, __LINE__, static WindowDesc _replace_road_vehicle_desc(
WDP_AUTO, "replace_vehicle_road", 500, 140, WDP_AUTO, "replace_vehicle_road", 500, 140,
WC_REPLACE_VEHICLE, WC_NONE, WC_REPLACE_VEHICLE, WC_NONE,
WDF_CONSTRUCTION, WDF_CONSTRUCTION,
@@ -898,7 +897,7 @@ static constexpr NWidgetPart _nested_replace_vehicle_widgets[] = {
EndContainer(), EndContainer(),
}; };
static WindowDesc _replace_vehicle_desc(__FILE__, __LINE__, static WindowDesc _replace_vehicle_desc(
WDP_AUTO, "replace_vehicle", 456, 118, WDP_AUTO, "replace_vehicle", 456, 118,
WC_REPLACE_VEHICLE, WC_NONE, WC_REPLACE_VEHICLE, WC_NONE,
WDF_CONSTRUCTION, WDF_CONSTRUCTION,

View File

@@ -314,7 +314,7 @@ static const uint NUM_SONGS_PLAYLIST = 32;
/* Functions to read DOS music CAT files, similar to but not quite the same as sound effect CAT files */ /* Functions to read DOS music CAT files, similar to but not quite the same as sound effect CAT files */
char *GetMusicCatEntryName(const std::string &filename, size_t entrynum); char *GetMusicCatEntryName(const std::string &filename, size_t entrynum);
byte *GetMusicCatEntryData(const std::string &filename, size_t entrynum, size_t &entrylen); uint8_t *GetMusicCatEntryData(const std::string &filename, size_t entrynum, size_t &entrylen);
enum MusicTrackType { enum MusicTrackType {
MTT_STANDARDMIDI, ///< Standard MIDI file MTT_STANDARDMIDI, ///< Standard MIDI file
@@ -324,7 +324,7 @@ enum MusicTrackType {
/** Metadata about a music track. */ /** Metadata about a music track. */
struct MusicSongInfo { struct MusicSongInfo {
std::string songname; ///< name of song displayed in UI std::string songname; ///< name of song displayed in UI
byte tracknr; ///< track number of song displayed in UI uint8_t tracknr; ///< track number of song displayed in UI
std::string filename; ///< file on disk containing song (when used in MusicSet class) std::string filename; ///< file on disk containing song (when used in MusicSet class)
MusicTrackType filetype; ///< decoder required for song file MusicTrackType filetype; ///< decoder required for song file
int cat_index; ///< entry index in CAT file, for filetype==MTT_MPSMIDI int cat_index; ///< entry index in CAT file, for filetype==MTT_MPSMIDI
@@ -338,7 +338,7 @@ struct MusicSet : BaseSet<MusicSet, NUM_SONGS_AVAILABLE, false> {
/** Data about individual songs in set. */ /** Data about individual songs in set. */
MusicSongInfo songinfo[NUM_SONGS_AVAILABLE]; MusicSongInfo songinfo[NUM_SONGS_AVAILABLE];
/** Number of valid songs in set. */ /** Number of valid songs in set. */
byte num_available; uint8_t num_available;
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename); bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename);
}; };

View File

@@ -19,16 +19,11 @@
typedef Pool<BaseStation, StationID, 32, 64000> StationPool; typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
extern StationPool _station_pool; extern StationPool _station_pool;
struct StationSpecList { template <typename T>
const StationSpec *spec; struct SpecMapping {
uint32_t grfid; ///< GRF ID of this custom station const T *spec; ///< Custom spec.
uint16_t localidx; ///< Station ID within GRF of station uint32_t grfid; ///< GRF ID of this custom spec.
}; uint16_t localidx; ///< Local ID within GRF of this custom spec.
struct RoadStopSpecList {
const RoadStopSpec *spec;
uint32_t grfid; ///< GRF ID of this custom road stop
uint16_t localidx; ///< Station ID within GRF of road stop
}; };
struct RoadStopTileData { struct RoadStopTileData {
@@ -64,7 +59,7 @@ struct StationRect : public Rect {
struct BaseStation : StationPool::PoolItem<&_station_pool> { struct BaseStation : StationPool::PoolItem<&_station_pool> {
TileIndex xy; ///< Base tile of the station TileIndex xy; ///< Base tile of the station
TrackedViewportSign sign; ///< NOSAVE: Dimensions of sign TrackedViewportSign sign; ///< NOSAVE: Dimensions of sign
byte delete_ctr; ///< Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is deleted. uint8_t delete_ctr; ///< Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is deleted.
std::string name; ///< Custom name std::string name; ///< Custom name
StringID string_id; ///< Default name (town area) of station StringID string_id; ///< Default name (town area) of station
@@ -74,13 +69,13 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
Owner owner; ///< The owner of this station Owner owner; ///< The owner of this station
StationFacility facilities; ///< The facilities that this station has StationFacility facilities; ///< The facilities that this station has
std::vector<StationSpecList> speclist; ///< List of rail station specs of this station. std::vector<SpecMapping<StationSpec>> speclist; ///< List of rail station specs of this station.
std::vector<RoadStopSpecList> roadstop_speclist; ///< List of road stop specs of this station std::vector<SpecMapping<RoadStopSpec>> roadstop_speclist; ///< List of road stop specs of this station
TimerGameCalendar::Date build_date; ///< Date of construction TimerGameCalendar::Date build_date; ///< Date of construction
uint16_t random_bits; ///< Random bits assigned to this station uint16_t random_bits; ///< Random bits assigned to this station
byte waiting_triggers; ///< Waiting triggers (NewGRF) for this station uint8_t waiting_triggers; ///< Waiting triggers (NewGRF) for this station
uint8_t cached_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen. uint8_t cached_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen.
uint8_t cached_roadstop_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask for road stops, used to determine if trigger processing should happen. uint8_t cached_roadstop_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask for road stops, used to determine if trigger processing should happen.
CargoTypes cached_cargo_triggers; ///< NOSAVE: Combined cargo trigger bitmask CargoTypes cached_cargo_triggers; ///< NOSAVE: Combined cargo trigger bitmask
@@ -118,7 +113,7 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
* @param available will return false if ever the variable asked for does not exist * @param available will return false if ever the variable asked for does not exist
* @return the value stored in the corresponding variable * @return the value stored in the corresponding variable
*/ */
virtual uint32_t GetNewGRFVariable(const struct ResolverObject &object, byte variable, byte parameter, bool *available) const = 0; virtual uint32_t GetNewGRFVariable(const struct ResolverObject &object, uint8_t variable, uint8_t parameter, bool *available) const = 0;
/** /**
* Update the coordinated of the sign (as shown in the viewport). * Update the coordinated of the sign (as shown in the viewport).
@@ -184,7 +179,7 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
return (this->facilities & ~FACIL_WAYPOINT) != 0; return (this->facilities & ~FACIL_WAYPOINT) != 0;
} }
inline byte GetRoadStopRandomBits(TileIndex tile) const inline uint8_t GetRoadStopRandomBits(TileIndex tile) const
{ {
for (const RoadStopTileData &tile_data : this->custom_roadstop_tile_data) { for (const RoadStopTileData &tile_data : this->custom_roadstop_tile_data) {
if (tile_data.tile == tile) return tile_data.random_bits; if (tile_data.tile == tile) return tile_data.random_bits;
@@ -192,7 +187,7 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
return 0; return 0;
} }
inline byte GetRoadStopAnimationFrame(TileIndex tile) const inline uint8_t GetRoadStopAnimationFrame(TileIndex tile) const
{ {
for (const RoadStopTileData &tile_data : this->custom_roadstop_tile_data) { for (const RoadStopTileData &tile_data : this->custom_roadstop_tile_data) {
if (tile_data.tile == tile) return tile_data.animation_frame; if (tile_data.tile == tile) return tile_data.animation_frame;
@@ -201,11 +196,11 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
} }
private: private:
void SetRoadStopTileData(TileIndex tile, byte data, bool animation); void SetRoadStopTileData(TileIndex tile, uint8_t data, bool animation);
public: public:
inline void SetRoadStopRandomBits(TileIndex tile, byte random_bits) { this->SetRoadStopTileData(tile, random_bits, false); } inline void SetRoadStopRandomBits(TileIndex tile, uint8_t random_bits) { this->SetRoadStopTileData(tile, random_bits, false); }
inline void SetRoadStopAnimationFrame(TileIndex tile, byte frame) { this->SetRoadStopTileData(tile, frame, true); } inline void SetRoadStopAnimationFrame(TileIndex tile, uint8_t frame) { this->SetRoadStopTileData(tile, frame, true); }
void RemoveRoadStopTileData(TileIndex tile); void RemoveRoadStopTileData(TileIndex tile);
static void PostDestructor(size_t index); static void PostDestructor(size_t index);
@@ -310,4 +305,14 @@ struct SpecializedStation : public BaseStation {
static Pool::IterateWrapper<T> Iterate(size_t from = 0) { return Pool::IterateWrapper<T>(from); } static Pool::IterateWrapper<T> Iterate(size_t from = 0) { return Pool::IterateWrapper<T>(from); }
}; };
/**
* Get spec mapping list for each supported custom spec type.
* @tparam T Spec type.
* @param bst Station of custom spec list.
* @return Speclist of custom spec type.
*/
template <class T> std::vector<SpecMapping<T>> &GetStationSpecList(BaseStation *bst);
template <> inline std::vector<SpecMapping<StationSpec>> &GetStationSpecList<StationSpec>(BaseStation *bst) { return bst->speclist; }
template <> inline std::vector<SpecMapping<RoadStopSpec>> &GetStationSpecList<RoadStopSpec>(BaseStation *bst) { return bst->roadstop_speclist; }
#endif /* BASE_STATION_BASE_H */ #endif /* BASE_STATION_BASE_H */

View File

@@ -34,23 +34,23 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
const uint16_t *src_n = (const uint16_t *)(src->data + src->offset[zoom][1]); const uint16_t *src_n = (const uint16_t *)(src->data + src->offset[zoom][1]);
for (uint i = bp->skip_top; i != 0; i--) { for (uint i = bp->skip_top; i != 0; i--) {
src_px = (const Colour *)((const byte *)src_px + *(const uint32_t *)src_px); src_px = (const Colour *)((const uint8_t *)src_px + *(const uint32_t *)src_px);
src_n = (const uint16_t *)((const byte *)src_n + *(const uint32_t *)src_n); src_n = (const uint16_t *)((const uint8_t *)src_n + *(const uint32_t *)src_n);
} }
Colour *dst = (Colour *)bp->dst + bp->top * bp->pitch + bp->left; Colour *dst = (Colour *)bp->dst + bp->top * bp->pitch + bp->left;
uint16_t *anim = this->anim_buf + this->ScreenToAnimOffset((uint32_t *)bp->dst) + bp->top * this->anim_buf_pitch + bp->left; uint16_t *anim = this->anim_buf + this->ScreenToAnimOffset((uint32_t *)bp->dst) + bp->top * this->anim_buf_pitch + bp->left;
const byte *remap = bp->remap; // store so we don't have to access it via bp every time const uint8_t *remap = bp->remap; // store so we don't have to access it via bp every time
for (int y = 0; y < bp->height; y++) { for (int y = 0; y < bp->height; y++) {
Colour *dst_ln = dst + bp->pitch; Colour *dst_ln = dst + bp->pitch;
uint16_t *anim_ln = anim + this->anim_buf_pitch; uint16_t *anim_ln = anim + this->anim_buf_pitch;
const Colour *src_px_ln = (const Colour *)((const byte *)src_px + *(const uint32_t *)src_px); const Colour *src_px_ln = (const Colour *)((const uint8_t *)src_px + *(const uint32_t *)src_px);
src_px++; src_px++;
const uint16_t *src_n_ln = (const uint16_t *)((const byte *)src_n + *(const uint32_t *)src_n); const uint16_t *src_n_ln = (const uint16_t *)((const uint8_t *)src_n + *(const uint32_t *)src_n);
src_n += 2; src_n += 2;
Colour *dst_end = dst + bp->skip_left; Colour *dst_end = dst + bp->skip_left;

View File

@@ -33,7 +33,7 @@ template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bpp
GNU_TARGET("sse4.1") GNU_TARGET("sse4.1")
inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom) inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom)
{ {
const byte * const remap = bp->remap; const uint8_t * const remap = bp->remap;
Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left; Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left;
uint16_t *anim_line = this->anim_buf + this->ScreenToAnimOffset((uint32_t *)bp->dst) + bp->top * this->anim_buf_pitch + bp->left; uint16_t *anim_line = this->anim_buf + this->ScreenToAnimOffset((uint32_t *)bp->dst) + bp->top * this->anim_buf_pitch + bp->left;
int effective_width = bp->width; int effective_width = bp->width;
@@ -42,7 +42,7 @@ inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom
const Blitter_32bppSSE_Base::SpriteData * const sd = (const Blitter_32bppSSE_Base::SpriteData *) bp->sprite; const Blitter_32bppSSE_Base::SpriteData * const sd = (const Blitter_32bppSSE_Base::SpriteData *) bp->sprite;
const SpriteInfo * const si = &sd->infos[zoom]; const SpriteInfo * const si = &sd->infos[zoom];
const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width; const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width;
const Colour *src_rgba_line = (const Colour *) ((const byte *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size); const Colour *src_rgba_line = (const Colour *) ((const uint8_t *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size);
if (read_mode != RM_WITH_MARGIN) { if (read_mode != RM_WITH_MARGIN) {
src_rgba_line += bp->skip_left; src_rgba_line += bp->skip_left;
@@ -104,20 +104,20 @@ inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom
if (animated) { if (animated) {
/* Remap colours. */ /* Remap colours. */
const byte m0 = mvX2; const uint8_t m0 = mvX2;
if (m0 >= PALETTE_ANIM_START) { if (m0 >= PALETTE_ANIM_START) {
const Colour c0 = (this->LookupColourInPalette(m0).data & 0x00FFFFFF) | (src[0].data & 0xFF000000); const Colour c0 = (this->LookupColourInPalette(m0).data & 0x00FFFFFF) | (src[0].data & 0xFF000000);
InsertFirstUint32(AdjustBrightneSSE(c0, (byte) (mvX2 >> 8)).data, srcABCD); InsertFirstUint32(AdjustBrightneSSE(c0, (uint8_t) (mvX2 >> 8)).data, srcABCD);
} }
const byte m1 = mvX2 >> 16; const uint8_t m1 = mvX2 >> 16;
if (m1 >= PALETTE_ANIM_START) { if (m1 >= PALETTE_ANIM_START) {
const Colour c1 = (this->LookupColourInPalette(m1).data & 0x00FFFFFF) | (src[1].data & 0xFF000000); const Colour c1 = (this->LookupColourInPalette(m1).data & 0x00FFFFFF) | (src[1].data & 0xFF000000);
InsertSecondUint32(AdjustBrightneSSE(c1, (byte) (mvX2 >> 24)).data, srcABCD); InsertSecondUint32(AdjustBrightneSSE(c1, (uint8_t) (mvX2 >> 24)).data, srcABCD);
} }
/* Update anim buffer. */ /* Update anim buffer. */
const byte a0 = src[0].a; const uint8_t a0 = src[0].a;
const byte a1 = src[1].a; const uint8_t a1 = src[1].a;
uint32_t anim01 = 0; uint32_t anim01 = 0;
if (a0 == 255) { if (a0 == 255) {
if (a1 == 255) { if (a1 == 255) {
@@ -185,9 +185,9 @@ bmno_full_transparency:
__m128i dstABCD = _mm_loadl_epi64((__m128i*) dst); __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
/* Remap colours. */ /* Remap colours. */
const uint m0 = (byte) mvX2; const uint m0 = (uint8_t) mvX2;
const uint r0 = remap[m0]; const uint r0 = remap[m0];
const uint m1 = (byte) (mvX2 >> 16); const uint m1 = (uint8_t) (mvX2 >> 16);
const uint r1 = remap[m1]; const uint r1 = remap[m1];
if (mvX2 & 0x00FF00FF) { if (mvX2 & 0x00FF00FF) {
#define CMOV_REMAP(m_colour, m_colour_init, m_src, m_m) \ #define CMOV_REMAP(m_colour, m_colour_init, m_src, m_m) \
@@ -195,7 +195,7 @@ bmno_full_transparency:
Colour m_colour = m_colour_init; \ Colour m_colour = m_colour_init; \
{ \ { \
const Colour srcm = (Colour) (m_src); \ const Colour srcm = (Colour) (m_src); \
const uint m = (byte) (m_m); \ const uint m = (uint8_t) (m_m); \
const uint r = remap[m]; \ const uint r = remap[m]; \
const Colour cmap = (this->LookupColourInPalette(r).data & 0x00FFFFFF) | (srcm.data & 0xFF000000); \ const Colour cmap = (this->LookupColourInPalette(r).data & 0x00FFFFFF) | (srcm.data & 0xFF000000); \
m_colour = r == 0 ? m_colour : cmap; \ m_colour = r == 0 ? m_colour : cmap; \
@@ -225,8 +225,8 @@ bmno_full_transparency:
/* Update anim buffer. */ /* Update anim buffer. */
if (animated) { if (animated) {
const byte a0 = src[0].a; const uint8_t a0 = src[0].a;
const byte a1 = src[1].a; const uint8_t a1 = src[1].a;
uint32_t anim01 = mvX2 & 0xFF00FF00; uint32_t anim01 = mvX2 & 0xFF00FF00;
if (a0 == 255) { if (a0 == 255) {
anim01 |= r0; anim01 |= r0;
@@ -368,7 +368,7 @@ bmcr_alpha_blend_single:
next_line: next_line:
if (mode != BM_TRANSPARENT && mode != BM_TRANSPARENT_REMAP) src_mv_line += si->sprite_width; if (mode != BM_TRANSPARENT && mode != BM_TRANSPARENT_REMAP) src_mv_line += si->sprite_width;
src_rgba_line = (const Colour*) ((const byte*) src_rgba_line + si->sprite_line_size); src_rgba_line = (const Colour*) ((const uint8_t*) src_rgba_line + si->sprite_line_size);
dst_line += bp->pitch; dst_line += bp->pitch;
anim_line += this->anim_buf_pitch; anim_line += this->anim_buf_pitch;
} }

View File

@@ -40,26 +40,26 @@ inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomL
/* skip upper lines in src_px and src_n */ /* skip upper lines in src_px and src_n */
for (uint i = bp->skip_top; i != 0; i--) { for (uint i = bp->skip_top; i != 0; i--) {
src_px = (const Colour *)((const byte *)src_px + *(const uint32_t *)src_px); src_px = (const Colour *)((const uint8_t *)src_px + *(const uint32_t *)src_px);
src_n = (const uint16_t *)((const byte *)src_n + *(const uint32_t *)src_n); src_n = (const uint16_t *)((const uint8_t *)src_n + *(const uint32_t *)src_n);
} }
/* skip lines in dst */ /* skip lines in dst */
Colour *dst = (Colour *)bp->dst + bp->top * bp->pitch + bp->left; Colour *dst = (Colour *)bp->dst + bp->top * bp->pitch + bp->left;
/* store so we don't have to access it via bp every time (compiler assumes pointer aliasing) */ /* store so we don't have to access it via bp every time (compiler assumes pointer aliasing) */
const byte *remap = bp->remap; const uint8_t *remap = bp->remap;
for (int y = 0; y < bp->height; y++) { for (int y = 0; y < bp->height; y++) {
/* next dst line begins here */ /* next dst line begins here */
Colour *dst_ln = dst + bp->pitch; Colour *dst_ln = dst + bp->pitch;
/* next src line begins here */ /* next src line begins here */
const Colour *src_px_ln = (const Colour *)((const byte *)src_px + *(const uint32_t *)src_px); const Colour *src_px_ln = (const Colour *)((const uint8_t *)src_px + *(const uint32_t *)src_px);
src_px++; src_px++;
/* next src_n line begins here */ /* next src_n line begins here */
const uint16_t *src_n_ln = (const uint16_t *)((const byte *)src_n + *(const uint32_t *)src_n); const uint16_t *src_n_ln = (const uint16_t *)((const uint8_t *)src_n + *(const uint32_t *)src_n);
src_n += 2; src_n += 2;
/* we will end this line when we reach this point */ /* we will end this line when we reach this point */
@@ -405,8 +405,8 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
dst_n_ln = (uint32_t *)dst_n; dst_n_ln = (uint32_t *)dst_n;
} }
lengths[z][0] = (byte *)dst_px_ln - (byte *)dst_px_orig[z]; // all are aligned to 4B boundary lengths[z][0] = (uint8_t *)dst_px_ln - (uint8_t *)dst_px_orig[z]; // all are aligned to 4B boundary
lengths[z][1] = (byte *)dst_n_ln - (byte *)dst_n_orig[z]; lengths[z][1] = (uint8_t *)dst_n_ln - (uint8_t *)dst_n_orig[z];
} }
uint len = 0; // total length of data uint len = 0; // total length of data

View File

@@ -18,7 +18,7 @@ public:
/** Data stored about a (single) sprite. */ /** Data stored about a (single) sprite. */
struct SpriteData { struct SpriteData {
uint32_t offset[ZOOM_LVL_END][2]; ///< Offsets (from .data) to streams for different zoom levels, and the normal and remap image information. uint32_t offset[ZOOM_LVL_END][2]; ///< Offsets (from .data) to streams for different zoom levels, and the normal and remap image information.
byte data[]; ///< Data, all zoomlevels. uint8_t data[]; ///< Data, all zoomlevels.
}; };
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override; void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;

View File

@@ -114,7 +114,7 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &spri
(*dst_rgba_line).data = nb_pix_transp; (*dst_rgba_line).data = nb_pix_transp;
Colour *nb_right = dst_rgba_line + 1; Colour *nb_right = dst_rgba_line + 1;
dst_rgba_line = (Colour*) ((byte*) dst_rgba_line + sd.infos[z].sprite_line_size); dst_rgba_line = (Colour*) ((uint8_t*) dst_rgba_line + sd.infos[z].sprite_line_size);
/* Count the number of transparent pixels from the right. */ /* Count the number of transparent pixels from the right. */
dst_rgba = dst_rgba_line - 1; dst_rgba = dst_rgba_line - 1;

View File

@@ -73,7 +73,7 @@ public:
struct SpriteData { struct SpriteData {
SpriteFlags flags; SpriteFlags flags;
SpriteInfo infos[ZOOM_LVL_END]; SpriteInfo infos[ZOOM_LVL_END];
byte data[]; ///< Data, all zoomlevels. uint8_t data[]; ///< Data, all zoomlevels.
}; };
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator); Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator);

View File

@@ -10,10 +10,17 @@
#ifndef BLITTER_32BPP_SSE_FUNC_HPP #ifndef BLITTER_32BPP_SSE_FUNC_HPP
#define BLITTER_32BPP_SSE_FUNC_HPP #define BLITTER_32BPP_SSE_FUNC_HPP
/* ATTENTION
* This file is compiled multiple times with different defines for SSE_VERSION and MARGIN_NORMAL_THRESHOLD.
* Be careful when declaring things with external linkage.
* Use internal linkage instead, i.e. "static".
*/
#define INTERNAL_LINKAGE static
#ifdef WITH_SSE #ifdef WITH_SSE
GNU_TARGET(SSE_TARGET) GNU_TARGET(SSE_TARGET)
inline void InsertFirstUint32(const uint32_t value, __m128i &into) INTERNAL_LINKAGE inline void InsertFirstUint32(const uint32_t value, __m128i &into)
{ {
#if (SSE_VERSION >= 4) #if (SSE_VERSION >= 4)
into = _mm_insert_epi32(into, value, 0); into = _mm_insert_epi32(into, value, 0);
@@ -24,7 +31,7 @@ inline void InsertFirstUint32(const uint32_t value, __m128i &into)
} }
GNU_TARGET(SSE_TARGET) GNU_TARGET(SSE_TARGET)
inline void InsertSecondUint32(const uint32_t value, __m128i &into) INTERNAL_LINKAGE inline void InsertSecondUint32(const uint32_t value, __m128i &into)
{ {
#if (SSE_VERSION >= 4) #if (SSE_VERSION >= 4)
into = _mm_insert_epi32(into, value, 1); into = _mm_insert_epi32(into, value, 1);
@@ -35,7 +42,7 @@ inline void InsertSecondUint32(const uint32_t value, __m128i &into)
} }
GNU_TARGET(SSE_TARGET) GNU_TARGET(SSE_TARGET)
inline void LoadUint64(const uint64_t value, __m128i &into) INTERNAL_LINKAGE inline void LoadUint64(const uint64_t value, __m128i &into)
{ {
#ifdef POINTER_IS_64BIT #ifdef POINTER_IS_64BIT
into = _mm_cvtsi64_si128(value); into = _mm_cvtsi64_si128(value);
@@ -50,7 +57,7 @@ inline void LoadUint64(const uint64_t value, __m128i &into)
} }
GNU_TARGET(SSE_TARGET) GNU_TARGET(SSE_TARGET)
inline __m128i PackUnsaturated(__m128i from, const __m128i &mask) INTERNAL_LINKAGE inline __m128i PackUnsaturated(__m128i from, const __m128i &mask)
{ {
#if (SSE_VERSION == 2) #if (SSE_VERSION == 2)
from = _mm_and_si128(from, mask); // PAND, wipe high bytes to keep low bytes when packing from = _mm_and_si128(from, mask); // PAND, wipe high bytes to keep low bytes when packing
@@ -61,7 +68,7 @@ inline __m128i PackUnsaturated(__m128i from, const __m128i &mask)
} }
GNU_TARGET(SSE_TARGET) GNU_TARGET(SSE_TARGET)
inline __m128i DistributeAlpha(const __m128i from, const __m128i &mask) INTERNAL_LINKAGE inline __m128i DistributeAlpha(const __m128i from, const __m128i &mask)
{ {
#if (SSE_VERSION == 2) #if (SSE_VERSION == 2)
__m128i alphaAB = _mm_shufflelo_epi16(from, 0x3F); // PSHUFLW, put alpha1 in front of each rgb1 __m128i alphaAB = _mm_shufflelo_epi16(from, 0x3F); // PSHUFLW, put alpha1 in front of each rgb1
@@ -73,7 +80,7 @@ inline __m128i DistributeAlpha(const __m128i from, const __m128i &mask)
} }
GNU_TARGET(SSE_TARGET) GNU_TARGET(SSE_TARGET)
inline __m128i AlphaBlendTwoPixels(__m128i src, __m128i dst, const __m128i &distribution_mask, const __m128i &pack_mask, const __m128i &alpha_mask) INTERNAL_LINKAGE inline __m128i AlphaBlendTwoPixels(__m128i src, __m128i dst, const __m128i &distribution_mask, const __m128i &pack_mask, const __m128i &alpha_mask)
{ {
__m128i srcAB = _mm_unpacklo_epi8(src, _mm_setzero_si128()); // PUNPCKLBW, expand each uint8_t into uint16 __m128i srcAB = _mm_unpacklo_epi8(src, _mm_setzero_si128()); // PUNPCKLBW, expand each uint8_t into uint16
__m128i dstAB = _mm_unpacklo_epi8(dst, _mm_setzero_si128()); __m128i dstAB = _mm_unpacklo_epi8(dst, _mm_setzero_si128());
@@ -97,7 +104,7 @@ inline __m128i AlphaBlendTwoPixels(__m128i src, __m128i dst, const __m128i &dist
* rgb = rgb * ((256/4) * 4 - (alpha/4)) / ((256/4) * 4) * rgb = rgb * ((256/4) * 4 - (alpha/4)) / ((256/4) * 4)
*/ */
GNU_TARGET(SSE_TARGET) GNU_TARGET(SSE_TARGET)
inline __m128i DarkenTwoPixels(__m128i src, __m128i dst, const __m128i &distribution_mask, const __m128i &tr_nom_base) INTERNAL_LINKAGE inline __m128i DarkenTwoPixels(__m128i src, __m128i dst, const __m128i &distribution_mask, const __m128i &tr_nom_base)
{ {
__m128i srcAB = _mm_unpacklo_epi8(src, _mm_setzero_si128()); __m128i srcAB = _mm_unpacklo_epi8(src, _mm_setzero_si128());
__m128i dstAB = _mm_unpacklo_epi8(dst, _mm_setzero_si128()); __m128i dstAB = _mm_unpacklo_epi8(dst, _mm_setzero_si128());
@@ -111,7 +118,7 @@ inline __m128i DarkenTwoPixels(__m128i src, __m128i dst, const __m128i &distribu
IGNORE_UNINITIALIZED_WARNING_START IGNORE_UNINITIALIZED_WARNING_START
GNU_TARGET(SSE_TARGET) GNU_TARGET(SSE_TARGET)
static Colour ReallyAdjustBrightness(Colour colour, uint8_t brightness) INTERNAL_LINKAGE Colour ReallyAdjustBrightness(Colour colour, uint8_t brightness)
{ {
uint64_t c16 = colour.b | (uint64_t) colour.g << 16 | (uint64_t) colour.r << 32; uint64_t c16 = colour.b | (uint64_t) colour.g << 16 | (uint64_t) colour.r << 32;
c16 *= brightness; c16 *= brightness;
@@ -145,7 +152,7 @@ IGNORE_UNINITIALIZED_WARNING_STOP
/** ReallyAdjustBrightness() is not called that often. /** ReallyAdjustBrightness() is not called that often.
* Inlining this function implies a far jump, which has a huge latency. * Inlining this function implies a far jump, which has a huge latency.
*/ */
inline Colour AdjustBrightneSSE(Colour colour, uint8_t brightness) INTERNAL_LINKAGE inline Colour AdjustBrightneSSE(Colour colour, uint8_t brightness)
{ {
/* Shortcut for normal brightness. */ /* Shortcut for normal brightness. */
if (brightness == Blitter_32bppBase::DEFAULT_BRIGHTNESS) return colour; if (brightness == Blitter_32bppBase::DEFAULT_BRIGHTNESS) return colour;
@@ -154,7 +161,7 @@ inline Colour AdjustBrightneSSE(Colour colour, uint8_t brightness)
} }
GNU_TARGET(SSE_TARGET) GNU_TARGET(SSE_TARGET)
inline __m128i AdjustBrightnessOfTwoPixels([[maybe_unused]] __m128i from, [[maybe_unused]] uint32_t brightness) INTERNAL_LINKAGE inline __m128i AdjustBrightnessOfTwoPixels([[maybe_unused]] __m128i from, [[maybe_unused]] uint32_t brightness)
{ {
#if (SSE_VERSION < 3) #if (SSE_VERSION < 3)
NOT_REACHED(); NOT_REACHED();
@@ -214,7 +221,7 @@ inline void Blitter_32bppSSSE3::Draw(const Blitter::BlitterParams *bp, ZoomLevel
inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom) inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
#endif #endif
{ {
const byte * const remap = bp->remap; const uint8_t * const remap = bp->remap;
Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left; Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left;
int effective_width = bp->width; int effective_width = bp->width;
@@ -222,7 +229,7 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
const SpriteData * const sd = (const SpriteData *) bp->sprite; const SpriteData * const sd = (const SpriteData *) bp->sprite;
const SpriteInfo * const si = &sd->infos[zoom]; const SpriteInfo * const si = &sd->infos[zoom];
const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width; const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width;
const Colour *src_rgba_line = (const Colour *) ((const byte *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size); const Colour *src_rgba_line = (const Colour *) ((const uint8_t *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size);
if (read_mode != RM_WITH_MARGIN) { if (read_mode != RM_WITH_MARGIN) {
src_rgba_line += bp->skip_left; src_rgba_line += bp->skip_left;
@@ -307,7 +314,7 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
Colour m_colour = m_colour_init; \ Colour m_colour = m_colour_init; \
{ \ { \
const Colour srcm = (Colour) (m_src); \ const Colour srcm = (Colour) (m_src); \
const uint m = (byte) (m_m); \ const uint m = (uint8_t) (m_m); \
const uint r = remap[m]; \ const uint r = remap[m]; \
const Colour cmap = (this->LookupColourInPalette(r).data & 0x00FFFFFF) | (srcm.data & 0xFF000000); \ const Colour cmap = (this->LookupColourInPalette(r).data & 0x00FFFFFF) | (srcm.data & 0xFF000000); \
m_colour = r == 0 ? m_colour : cmap; \ m_colour = r == 0 ? m_colour : cmap; \
@@ -435,7 +442,7 @@ bmcr_alpha_blend_single:
next_line: next_line:
if (mode == BM_COLOUR_REMAP || mode == BM_CRASH_REMAP) src_mv_line += si->sprite_width; if (mode == BM_COLOUR_REMAP || mode == BM_CRASH_REMAP) src_mv_line += si->sprite_width;
src_rgba_line = (const Colour*) ((const byte*) src_rgba_line + si->sprite_line_size); src_rgba_line = (const Colour*) ((const uint8_t*) src_rgba_line + si->sprite_line_size);
dst_line += bp->pitch; dst_line += bp->pitch;
} }
} }

View File

@@ -10,6 +10,12 @@
#ifndef BLITTER_32BPP_SSE_TYPE_H #ifndef BLITTER_32BPP_SSE_TYPE_H
#define BLITTER_32BPP_SSE_TYPE_H #define BLITTER_32BPP_SSE_TYPE_H
/* ATTENTION
* This file is compiled multiple times with different defines for SSE_VERSION.
* Be careful when declaring things with external linkage.
* Use internal linkage instead, i.e. "static".
*/
#ifdef WITH_SSE #ifdef WITH_SSE
#include "32bpp_simple.hpp" #include "32bpp_simple.hpp"

View File

@@ -104,8 +104,8 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
/* skip upper lines in src_px and src_n */ /* skip upper lines in src_px and src_n */
for (uint i = bp->skip_top; i != 0; i--) { for (uint i = bp->skip_top; i != 0; i--) {
src_px = (const Colour *)((const byte *)src_px + *(const uint32_t *)src_px); src_px = (const Colour *)((const uint8_t *)src_px + *(const uint32_t *)src_px);
src_n = (const uint16_t *)((const byte *)src_n + *(const uint32_t *)src_n); src_n = (const uint16_t *)((const uint8_t *)src_n + *(const uint32_t *)src_n);
} }
/* skip lines in dst */ /* skip lines in dst */
@@ -114,7 +114,7 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
uint8_t *anim = VideoDriver::GetInstance()->GetAnimBuffer() + ((uint32_t *)bp->dst - (uint32_t *)_screen.dst_ptr) + bp->top * bp->pitch + bp->left; uint8_t *anim = VideoDriver::GetInstance()->GetAnimBuffer() + ((uint32_t *)bp->dst - (uint32_t *)_screen.dst_ptr) + bp->top * bp->pitch + bp->left;
/* store so we don't have to access it via bp everytime (compiler assumes pointer aliasing) */ /* store so we don't have to access it via bp everytime (compiler assumes pointer aliasing) */
const byte *remap = bp->remap; const uint8_t *remap = bp->remap;
for (int y = 0; y < bp->height; y++) { for (int y = 0; y < bp->height; y++) {
/* next dst line begins here */ /* next dst line begins here */
@@ -122,11 +122,11 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
uint8_t *anim_ln = anim + bp->pitch; uint8_t *anim_ln = anim + bp->pitch;
/* next src line begins here */ /* next src line begins here */
const Colour *src_px_ln = (const Colour *)((const byte *)src_px + *(const uint32_t *)src_px); const Colour *src_px_ln = (const Colour *)((const uint8_t *)src_px + *(const uint32_t *)src_px);
src_px++; src_px++;
/* next src_n line begins here */ /* next src_n line begins here */
const uint16_t *src_n_ln = (const uint16_t *)((const byte *)src_n + *(const uint32_t *)src_n); const uint16_t *src_n_ln = (const uint16_t *)((const uint8_t *)src_n + *(const uint32_t *)src_n);
src_n += 2; src_n += 2;
/* we will end this line when we reach this point */ /* we will end this line when we reach this point */

View File

@@ -147,10 +147,10 @@ Sprite *Blitter_8bppOptimized::Encode(const SpriteLoader::SpriteCollection &spri
/* Don't allocate memory each time, but just keep some /* Don't allocate memory each time, but just keep some
* memory around as this function is called quite often * memory around as this function is called quite often
* and the memory usage is quite low. */ * and the memory usage is quite low. */
static ReusableBuffer<byte> temp_buffer; static ReusableBuffer<uint8_t> temp_buffer;
SpriteData *temp_dst = (SpriteData *)temp_buffer.Allocate(memory); SpriteData *temp_dst = (SpriteData *)temp_buffer.Allocate(memory);
memset(temp_dst, 0, sizeof(*temp_dst)); memset(temp_dst, 0, sizeof(*temp_dst));
byte *dst = temp_dst->data; uint8_t *dst = temp_dst->data;
/* Make the sprites per zoom-level */ /* Make the sprites per zoom-level */
for (ZoomLevel i = zoom_min; i <= zoom_max; i++) { for (ZoomLevel i = zoom_min; i <= zoom_max; i++) {
@@ -166,7 +166,7 @@ Sprite *Blitter_8bppOptimized::Encode(const SpriteLoader::SpriteCollection &spri
uint trans = 0; uint trans = 0;
uint pixels = 0; uint pixels = 0;
uint last_colour = 0; uint last_colour = 0;
byte *count_dst = nullptr; uint8_t *count_dst = nullptr;
/* Store the scaled image */ /* Store the scaled image */
const SpriteLoader::CommonPixel *src = &sprite[i].data[y * sprite[i].width]; const SpriteLoader::CommonPixel *src = &sprite[i].data[y * sprite[i].width];
@@ -213,7 +213,7 @@ Sprite *Blitter_8bppOptimized::Encode(const SpriteLoader::SpriteCollection &spri
} }
} }
uint size = dst - (byte *)temp_dst; uint size = dst - (uint8_t *)temp_dst;
/* Safety check, to make sure we guessed the size correctly */ /* Safety check, to make sure we guessed the size correctly */
assert(size < memory); assert(size < memory);

View File

@@ -19,7 +19,7 @@ public:
/** Data stored about a (single) sprite. */ /** Data stored about a (single) sprite. */
struct SpriteData { struct SpriteData {
uint32_t offset[ZOOM_LVL_END]; ///< Offsets (from .data) to streams for different zoom levels. uint32_t offset[ZOOM_LVL_END]; ///< Offsets (from .data) to streams for different zoom levels.
byte data[]; ///< Data, all zoomlevels. uint8_t data[]; ///< Data, all zoomlevels.
}; };
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override; void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;

View File

@@ -31,7 +31,7 @@ public:
/** Parameters related to blitting. */ /** Parameters related to blitting. */
struct BlitterParams { struct BlitterParams {
const void *sprite; ///< Pointer to the sprite how ever the encoder stored it const void *sprite; ///< Pointer to the sprite how ever the encoder stored it
const byte *remap; ///< XXX -- Temporary storage for remap array const uint8_t *remap; ///< XXX -- Temporary storage for remap array
int skip_left; ///< How much pixels of the source to skip on the left (based on zoom of dst) int skip_left; ///< How much pixels of the source to skip on the left (based on zoom of dst)
int skip_top; ///< How much pixels of the source to skip on the top (based on zoom of dst) int skip_top; ///< How much pixels of the source to skip on the top (based on zoom of dst)

View File

@@ -39,7 +39,7 @@ static inline bool EndOfBuffer(BmpBuffer *buffer)
return buffer->pos == buffer->read; return buffer->pos == buffer->read;
} }
static inline byte ReadByte(BmpBuffer *buffer) static inline uint8_t ReadByte(BmpBuffer *buffer)
{ {
if (buffer->read < 0) return 0; if (buffer->read < 0) return 0;
@@ -83,9 +83,9 @@ static inline void SetStreamOffset(BmpBuffer *buffer, int offset)
static inline bool BmpRead1(BmpBuffer *buffer, BmpInfo *info, BmpData *data) static inline bool BmpRead1(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{ {
uint x, y, i; uint x, y, i;
byte pad = GB(4 - info->width / 8, 0, 2); uint8_t pad = GB(4 - info->width / 8, 0, 2);
byte *pixel_row; uint8_t *pixel_row;
byte b; uint8_t b;
for (y = info->height; y > 0; y--) { for (y = info->height; y > 0; y--) {
x = 0; x = 0;
pixel_row = &data->bitmap[(y - 1) * info->width]; pixel_row = &data->bitmap[(y - 1) * info->width];
@@ -110,9 +110,9 @@ static inline bool BmpRead1(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
static inline bool BmpRead4(BmpBuffer *buffer, BmpInfo *info, BmpData *data) static inline bool BmpRead4(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{ {
uint x, y; uint x, y;
byte pad = GB(4 - info->width / 2, 0, 2); uint8_t pad = GB(4 - info->width / 2, 0, 2);
byte *pixel_row; uint8_t *pixel_row;
byte b; uint8_t b;
for (y = info->height; y > 0; y--) { for (y = info->height; y > 0; y--) {
x = 0; x = 0;
pixel_row = &data->bitmap[(y - 1) * info->width]; pixel_row = &data->bitmap[(y - 1) * info->width];
@@ -140,12 +140,12 @@ static inline bool BmpRead4Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{ {
uint x = 0; uint x = 0;
uint y = info->height - 1; uint y = info->height - 1;
byte *pixel = &data->bitmap[y * info->width]; uint8_t *pixel = &data->bitmap[y * info->width];
while (y != 0 || x < info->width) { while (y != 0 || x < info->width) {
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
byte n = ReadByte(buffer); uint8_t n = ReadByte(buffer);
byte c = ReadByte(buffer); uint8_t c = ReadByte(buffer);
if (n == 0) { if (n == 0) {
switch (c) { switch (c) {
case 0: // end of line case 0: // end of line
@@ -159,8 +159,8 @@ static inline bool BmpRead4Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
case 2: { // delta case 2: { // delta
if (EndOfBuffer(buffer)) return false; if (EndOfBuffer(buffer)) return false;
byte dx = ReadByte(buffer); uint8_t dx = ReadByte(buffer);
byte dy = ReadByte(buffer); uint8_t dy = ReadByte(buffer);
/* Check for over- and underflow. */ /* Check for over- and underflow. */
if (x + dx >= info->width || x + dx < x || dy > y) return false; if (x + dx >= info->width || x + dx < x || dy > y) return false;
@@ -175,7 +175,7 @@ static inline bool BmpRead4Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
uint i = 0; uint i = 0;
while (i++ < c) { while (i++ < c) {
if (EndOfBuffer(buffer) || x >= info->width) return false; if (EndOfBuffer(buffer) || x >= info->width) return false;
byte b = ReadByte(buffer); uint8_t b = ReadByte(buffer);
*pixel++ = GB(b, 4, 4); *pixel++ = GB(b, 4, 4);
x++; x++;
if (i++ < c) { if (i++ < c) {
@@ -214,8 +214,8 @@ static inline bool BmpRead8(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{ {
uint i; uint i;
uint y; uint y;
byte pad = GB(4 - info->width, 0, 2); uint8_t pad = GB(4 - info->width, 0, 2);
byte *pixel; uint8_t *pixel;
for (y = info->height; y > 0; y--) { for (y = info->height; y > 0; y--) {
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
pixel = &data->bitmap[(y - 1) * info->width]; pixel = &data->bitmap[(y - 1) * info->width];
@@ -233,12 +233,12 @@ static inline bool BmpRead8Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{ {
uint x = 0; uint x = 0;
uint y = info->height - 1; uint y = info->height - 1;
byte *pixel = &data->bitmap[y * info->width]; uint8_t *pixel = &data->bitmap[y * info->width];
while (y != 0 || x < info->width) { while (y != 0 || x < info->width) {
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
byte n = ReadByte(buffer); uint8_t n = ReadByte(buffer);
byte c = ReadByte(buffer); uint8_t c = ReadByte(buffer);
if (n == 0) { if (n == 0) {
switch (c) { switch (c) {
case 0: // end of line case 0: // end of line
@@ -252,8 +252,8 @@ static inline bool BmpRead8Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
case 2: { // delta case 2: { // delta
if (EndOfBuffer(buffer)) return false; if (EndOfBuffer(buffer)) return false;
byte dx = ReadByte(buffer); uint8_t dx = ReadByte(buffer);
byte dy = ReadByte(buffer); uint8_t dy = ReadByte(buffer);
/* Check for over- and underflow. */ /* Check for over- and underflow. */
if (x + dx >= info->width || x + dx < x || dy > y) return false; if (x + dx >= info->width || x + dx < x || dy > y) return false;
@@ -294,8 +294,8 @@ static inline bool BmpRead8Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
static inline bool BmpRead24(BmpBuffer *buffer, BmpInfo *info, BmpData *data) static inline bool BmpRead24(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{ {
uint x, y; uint x, y;
byte pad = GB(4 - info->width * 3, 0, 2); uint8_t pad = GB(4 - info->width * 3, 0, 2);
byte *pixel_row; uint8_t *pixel_row;
for (y = info->height; y > 0; y--) { for (y = info->height; y > 0; y--) {
pixel_row = &data->bitmap[(y - 1) * info->width * 3]; pixel_row = &data->bitmap[(y - 1) * info->width * 3];
for (x = 0; x < info->width; x++) { for (x = 0; x < info->width; x++) {
@@ -395,7 +395,7 @@ bool BmpReadBitmap(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{ {
assert(info != nullptr && data != nullptr); assert(info != nullptr && data != nullptr);
data->bitmap = CallocT<byte>(static_cast<size_t>(info->width) * info->height * ((info->bpp == 24) ? 3 : 1)); data->bitmap = CallocT<uint8_t>(static_cast<size_t>(info->width) * info->height * ((info->bpp == 24) ? 3 : 1));
/* Load image */ /* Load image */
SetStreamOffset(buffer, info->offset); SetStreamOffset(buffer, info->offset);

View File

@@ -24,13 +24,13 @@ struct BmpInfo {
struct BmpData { struct BmpData {
Colour *palette; Colour *palette;
byte *bitmap; uint8_t *bitmap;
}; };
#define BMP_BUFFER_SIZE 1024 #define BMP_BUFFER_SIZE 1024
struct BmpBuffer { struct BmpBuffer {
byte data[BMP_BUFFER_SIZE]; uint8_t data[BMP_BUFFER_SIZE];
int pos; int pos;
int read; int read;
FILE *file; FILE *file;

View File

@@ -40,7 +40,7 @@ static constexpr NWidgetPart _background_widgets[] = {
/** /**
* Window description for the background window to prevent smearing. * Window description for the background window to prevent smearing.
*/ */
static WindowDesc _background_desc(__FILE__, __LINE__, static WindowDesc _background_desc(
WDP_MANUAL, nullptr, 0, 0, WDP_MANUAL, nullptr, 0, 0,
WC_BOOTSTRAP, WC_NONE, WC_BOOTSTRAP, WC_NONE,
WDF_NO_CLOSE, WDF_NO_CLOSE,
@@ -76,7 +76,7 @@ static constexpr NWidgetPart _nested_bootstrap_errmsg_widgets[] = {
}; };
/** Window description for the error window. */ /** Window description for the error window. */
static WindowDesc _bootstrap_errmsg_desc(__FILE__, __LINE__, static WindowDesc _bootstrap_errmsg_desc(
WDP_CENTER, nullptr, 0, 0, WDP_CENTER, nullptr, 0, 0,
WC_BOOTSTRAP, WC_NONE, WC_BOOTSTRAP, WC_NONE,
WDF_MODAL | WDF_NO_CLOSE, WDF_MODAL | WDF_NO_CLOSE,
@@ -133,7 +133,7 @@ static constexpr NWidgetPart _nested_bootstrap_download_status_window_widgets[]
}; };
/** Window description for the download window */ /** Window description for the download window */
static WindowDesc _bootstrap_download_status_window_desc(__FILE__, __LINE__, static WindowDesc _bootstrap_download_status_window_desc(
WDP_CENTER, nullptr, 0, 0, WDP_CENTER, nullptr, 0, 0,
WC_NETWORK_STATUS_WINDOW, WC_NONE, WC_NETWORK_STATUS_WINDOW, WC_NONE,
WDF_MODAL | WDF_NO_CLOSE, WDF_MODAL | WDF_NO_CLOSE,
@@ -185,7 +185,7 @@ static constexpr NWidgetPart _bootstrap_query_widgets[] = {
}; };
/** The window description for the query. */ /** The window description for the query. */
static WindowDesc _bootstrap_query_desc(__FILE__, __LINE__, static WindowDesc _bootstrap_query_desc(
WDP_CENTER, nullptr, 0, 0, WDP_CENTER, nullptr, 0, 0,
WC_CONFIRM_POPUP_QUERY, WC_NONE, WC_CONFIRM_POPUP_QUERY, WC_NONE,
WDF_NO_CLOSE, WDF_NO_CLOSE,
@@ -385,9 +385,9 @@ bool HandleBootstrap()
* This way the mauve and gray colours work and we can show the user interface. */ * This way the mauve and gray colours work and we can show the user interface. */
GfxInitPalettes(); GfxInitPalettes();
static const int offsets[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0x04, 0x08 }; static const int offsets[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0x04, 0x08 };
for (uint i = 0; i != 16; i++) { for (Colours i = COLOUR_BEGIN; i != COLOUR_END; i++) {
for (int j = 0; j < 8; j++) { for (ColourShade j = SHADE_BEGIN; j < SHADE_END; j++) {
_colour_gradient[i][j] = offsets[i] + j; SetColourGradient(i, j, offsets[i] + j);
} }
} }

View File

@@ -41,7 +41,7 @@ typedef uint BridgeType; ///< Bridge spec number.
*/ */
struct BridgeSpec { struct BridgeSpec {
TimerGameCalendar::Year avail_year; ///< the year where it becomes available TimerGameCalendar::Year avail_year; ///< the year where it becomes available
byte min_length; ///< the minimum length (not counting start and end tile) uint8_t min_length; ///< the minimum length (not counting start and end tile)
uint16_t max_length; ///< the maximum length (not counting start and end tile) uint16_t max_length; ///< the maximum length (not counting start and end tile)
uint16_t price; ///< the price multiplier uint16_t price; ///< the price multiplier
uint16_t speed; ///< maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h) uint16_t speed; ///< maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h)
@@ -50,7 +50,7 @@ struct BridgeSpec {
StringID material; ///< the string that contains the bridge description StringID material; ///< the string that contains the bridge description
StringID transport_name[2]; ///< description of the bridge, when built for road or rail StringID transport_name[2]; ///< description of the bridge, when built for road or rail
PalSpriteID **sprite_table; ///< table of sprites for drawing the bridge PalSpriteID **sprite_table; ///< table of sprites for drawing the bridge
byte flags; ///< bit 0 set: disable drawing of far pillars. uint8_t flags; ///< bit 0 set: disable drawing of far pillars.
}; };
extern BridgeSpec _bridge[MAX_BRIDGES]; extern BridgeSpec _bridge[MAX_BRIDGES];

View File

@@ -18,7 +18,7 @@
#include "gfx_func.h" #include "gfx_func.h"
#include "tunnelbridge.h" #include "tunnelbridge.h"
#include "sortlist_type.h" #include "sortlist_type.h"
#include "widgets/dropdown_func.h" #include "dropdown_func.h"
#include "core/geometry_func.hpp" #include "core/geometry_func.hpp"
#include "tunnelbridge_map.h" #include "tunnelbridge_map.h"
#include "road_gui.h" #include "road_gui.h"
@@ -55,7 +55,7 @@ typedef GUIList<BuildBridgeData> GUIBridgeList; ///< List of bridges, used in #B
* @param tile_start start tile * @param tile_start start tile
* @param transport_type transport type. * @param transport_type transport type.
*/ */
void CcBuildBridge(Commands, const CommandCost &result, TileIndex end_tile, TileIndex tile_start, TransportType transport_type, BridgeType, byte) void CcBuildBridge(Commands, const CommandCost &result, TileIndex end_tile, TileIndex tile_start, TransportType transport_type, BridgeType, uint8_t)
{ {
if (result.Failed()) return; if (result.Failed()) return;
if (_settings_client.sound.confirm) SndPlayTileFx(SND_27_CONSTRUCTION_BRIDGE, end_tile); if (_settings_client.sound.confirm) SndPlayTileFx(SND_27_CONSTRUCTION_BRIDGE, end_tile);
@@ -83,7 +83,7 @@ private:
TileIndex start_tile; TileIndex start_tile;
TileIndex end_tile; TileIndex end_tile;
TransportType transport_type; TransportType transport_type;
byte road_rail_type; uint8_t road_rail_type;
GUIBridgeList bridges; GUIBridgeList bridges;
int icon_width; ///< Scaled width of the the bridge icon sprite. int icon_width; ///< Scaled width of the the bridge icon sprite.
Scrollbar *vscroll; Scrollbar *vscroll;
@@ -148,7 +148,7 @@ private:
} }
public: public:
BuildBridgeWindow(WindowDesc *desc, TileIndex start, TileIndex end, TransportType transport_type, byte road_rail_type, GUIBridgeList &&bl) : Window(desc), BuildBridgeWindow(WindowDesc *desc, TileIndex start, TileIndex end, TransportType transport_type, uint8_t road_rail_type, GUIBridgeList &&bl) : Window(desc),
start_tile(start), start_tile(start),
end_tile(end), end_tile(end),
transport_type(transport_type), transport_type(transport_type),
@@ -233,11 +233,11 @@ public:
case WID_BBS_BRIDGE_LIST: { case WID_BBS_BRIDGE_LIST: {
Rect tr = r.WithHeight(this->resize.step_height).Shrink(WidgetDimensions::scaled.matrix); Rect tr = r.WithHeight(this->resize.step_height).Shrink(WidgetDimensions::scaled.matrix);
bool rtl = _current_text_dir == TD_RTL; bool rtl = _current_text_dir == TD_RTL;
for (int i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < (int)this->bridges.size(); i++) { auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->bridges);
const BuildBridgeData &bridge_data = this->bridges.at(i); for (auto it = first; it != last; ++it) {
const BridgeSpec *b = bridge_data.spec; const BridgeSpec *b = it->spec;
DrawSpriteIgnorePadding(b->sprite, b->pal, tr.WithWidth(this->icon_width, rtl), SA_HOR_CENTER | SA_BOTTOM); DrawSpriteIgnorePadding(b->sprite, b->pal, tr.WithWidth(this->icon_width, rtl), SA_HOR_CENTER | SA_BOTTOM);
DrawStringMultiLine(tr.Indent(this->icon_width + WidgetDimensions::scaled.hsep_normal, rtl), GetBridgeSelectString(bridge_data)); DrawStringMultiLine(tr.Indent(this->icon_width + WidgetDimensions::scaled.hsep_normal, rtl), GetBridgeSelectString(*it));
tr = tr.Translate(0, this->resize.step_height); tr = tr.Translate(0, this->resize.step_height);
} }
break; break;
@@ -343,7 +343,7 @@ static constexpr NWidgetPart _nested_build_bridge_widgets[] = {
}; };
/** Window definition for the rail bridge selection window. */ /** Window definition for the rail bridge selection window. */
static WindowDesc _build_bridge_desc(__FILE__, __LINE__, static WindowDesc _build_bridge_desc(
WDP_AUTO, "build_bridge", 200, 114, WDP_AUTO, "build_bridge", 200, 114,
WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR, WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR,
WDF_CONSTRUCTION, WDF_CONSTRUCTION,
@@ -360,7 +360,7 @@ static WindowDesc _build_bridge_desc(__FILE__, __LINE__,
* @param transport_type The transport type * @param transport_type The transport type
* @param road_rail_type The road/rail type * @param road_rail_type The road/rail type
*/ */
void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, byte road_rail_type) void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, uint8_t road_rail_type)
{ {
CloseWindowByClass(WC_BUILD_BRIDGE); CloseWindowByClass(WC_BUILD_BRIDGE);

View File

@@ -69,10 +69,9 @@ TileIndex GetOtherBridgeEnd(TileIndex tile)
*/ */
int GetBridgeHeight(TileIndex t) int GetBridgeHeight(TileIndex t)
{ {
int h; auto [tileh, h] = GetTileSlopeZ(t);
Slope tileh = GetTileSlope(t, &h);
Foundation f = GetBridgeFoundation(tileh, DiagDirToAxis(GetTunnelBridgeDirection(t))); Foundation f = GetBridgeFoundation(tileh, DiagDirToAxis(GetTunnelBridgeDirection(t)));
/* one height level extra for the ramp */ /* one height level extra for the ramp */
return h + 1 + ApplyFoundationToSlope(f, &tileh); return h + 1 + ApplyFoundationToSlope(f, tileh);
} }

View File

@@ -35,8 +35,8 @@ static const NWidgetPart _nested_build_info_widgets[] = {
NWidget(WWT_PANEL, COLOUR_GREY, WID_TT_BACKGROUND), SetMinimalSize(200, 32), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY, WID_TT_BACKGROUND), SetMinimalSize(200, 32), EndContainer(),
}; };
static WindowDesc _build_info_desc(__FILE__, __LINE__, static WindowDesc _build_info_desc(
WDP_MANUAL, nullptr, 0, 0, // Coordinates and sizes are not used, WDP_MANUAL, nullptr, 0, 0, // Coordinates and sizes are not used,
WC_TOOLTIPS, WC_NONE, WC_TOOLTIPS, WC_NONE,
WDF_NO_FOCUS, WDF_NO_FOCUS,
std::begin(_nested_build_info_widgets), std::end(_nested_build_info_widgets) std::begin(_nested_build_info_widgets), std::end(_nested_build_info_widgets)
@@ -225,7 +225,7 @@ static const NWidgetPart _nested_build_confirmation_widgets[] = {
EndContainer(), EndContainer(),
}; };
static WindowDesc _build_confirmation_desc(__FILE__, __LINE__, static WindowDesc _build_confirmation_desc(
WDP_MANUAL, "build_confirmation", 0, 0, WDP_MANUAL, "build_confirmation", 0, 0,
WC_BUILD_CONFIRMATION, WC_NONE, WC_BUILD_CONFIRMATION, WC_NONE,
0, 0,

View File

@@ -25,7 +25,8 @@
#include "window_func.h" #include "window_func.h"
#include "timer/timer_game_calendar.h" #include "timer/timer_game_calendar.h"
#include "vehicle_func.h" #include "vehicle_func.h"
#include "widgets/dropdown_func.h" #include "dropdown_type.h"
#include "dropdown_func.h"
#include "engine_gui.h" #include "engine_gui.h"
#include "cargotype.h" #include "cargotype.h"
#include "core/geometry_func.hpp" #include "core/geometry_func.hpp"
@@ -97,7 +98,7 @@ static constexpr NWidgetPart _nested_build_vehicle_widgets[] = {
bool _engine_sort_direction; ///< \c false = descending, \c true = ascending. bool _engine_sort_direction; ///< \c false = descending, \c true = ascending.
byte _engine_sort_last_criteria[] = {0, 0, 0, 0}; ///< Last set sort criteria, for each vehicle type. uint8_t _engine_sort_last_criteria[] = {0, 0, 0, 0}; ///< Last set sort criteria, for each vehicle type.
bool _engine_sort_last_order[] = {false, false, false, false}; ///< Last set direction of the sort order, for each vehicle type. bool _engine_sort_last_order[] = {false, false, false, false}; ///< Last set direction of the sort order, for each vehicle type.
bool _engine_sort_show_hidden_engines[] = {false, false, false, false}; ///< Last set 'show hidden engines' setting for each vehicle type. bool _engine_sort_show_hidden_engines[] = {false, false, false, false}; ///< Last set 'show hidden engines' setting for each vehicle type.
static CargoID _engine_sort_last_cargo_criteria[] = {CargoFilterCriteria::CF_ANY, CargoFilterCriteria::CF_ANY, CargoFilterCriteria::CF_ANY, CargoFilterCriteria::CF_ANY}; ///< Last set filter criteria, for each vehicle type. static CargoID _engine_sort_last_cargo_criteria[] = {CargoFilterCriteria::CF_ANY, CargoFilterCriteria::CF_ANY, CargoFilterCriteria::CF_ANY, CargoFilterCriteria::CF_ANY}; ///< Last set filter criteria, for each vehicle type.
@@ -1000,18 +1001,16 @@ int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number,
* @param type Type of vehicle (VEH_*) * @param type Type of vehicle (VEH_*)
* @param r The Rect of the list * @param r The Rect of the list
* @param eng_list What engines to draw * @param eng_list What engines to draw
* @param min where to start in the list * @param sb Scrollbar of list.
* @param max where in the list to end
* @param selected_id what engine to highlight as selected, if any * @param selected_id what engine to highlight as selected, if any
* @param show_count Whether to show the amount of engines or not * @param show_count Whether to show the amount of engines or not
* @param selected_group the group to list the engines of * @param selected_group the group to list the engines of
*/ */
void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_list, uint16_t min, uint16_t max, EngineID selected_id, bool show_count, GroupID selected_group) void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_list, const Scrollbar &sb, EngineID selected_id, bool show_count, GroupID selected_group)
{ {
static const int sprite_y_offsets[] = { -1, -1, -2, -2 }; static const int sprite_y_offsets[] = { -1, -1, -2, -2 };
/* Obligatory sanity checks! */ auto [first, last] = sb.GetVisibleRangeIterators(eng_list);
assert(max <= eng_list.size());
bool rtl = _current_text_dir == TD_RTL; bool rtl = _current_text_dir == TD_RTL;
int step_size = GetEngineListHeight(type); int step_size = GetEngineListHeight(type);
@@ -1019,7 +1018,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
int sprite_right = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_right; int sprite_right = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_right;
int sprite_width = sprite_left + sprite_right; int sprite_width = sprite_left + sprite_right;
int circle_width = std::max(GetScaledSpriteSize(SPR_CIRCLE_FOLDED).width, GetScaledSpriteSize(SPR_CIRCLE_UNFOLDED).width); int circle_width = std::max(GetScaledSpriteSize(SPR_CIRCLE_FOLDED).width, GetScaledSpriteSize(SPR_CIRCLE_UNFOLDED).width);
int linecolour = _colour_gradient[COLOUR_ORANGE][4]; int linecolour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL);
Rect ir = r.WithHeight(step_size).Shrink(WidgetDimensions::scaled.matrix); Rect ir = r.WithHeight(step_size).Shrink(WidgetDimensions::scaled.matrix);
int sprite_y_offset = ScaleSpriteTrad(sprite_y_offsets[type]) + ir.Height() / 2; int sprite_y_offset = ScaleSpriteTrad(sprite_y_offsets[type]) + ir.Height() / 2;
@@ -1030,9 +1029,8 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
replace_icon = GetSpriteSize(SPR_GROUP_REPLACE_ACTIVE); replace_icon = GetSpriteSize(SPR_GROUP_REPLACE_ACTIVE);
uint biggest_num_engines = 0; uint biggest_num_engines = 0;
for (auto i = min; i < max; i++) { for (auto it = first; it != last; ++it) {
const auto &item = eng_list[i]; const uint num_engines = GetGroupNumEngines(_local_company, selected_group, it->engine_id);
const uint num_engines = GetGroupNumEngines(_local_company, selected_group, item.engine_id);
biggest_num_engines = std::max(biggest_num_engines, num_engines); biggest_num_engines = std::max(biggest_num_engines, num_engines);
} }
@@ -1050,8 +1048,8 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
int replace_icon_y_offset = (ir.Height() - replace_icon.height) / 2; int replace_icon_y_offset = (ir.Height() - replace_icon.height) / 2;
int y = ir.top; int y = ir.top;
for (; min < max; min++, y += step_size) { for (auto it = first; it != last; ++it) {
const auto &item = eng_list[min]; const auto &item = *it;
uint indent = item.indent * WidgetDimensions::scaled.hsep_indent; uint indent = item.indent * WidgetDimensions::scaled.hsep_indent;
bool has_variants = (item.flags & EngineDisplayFlags::HasVariants) != EngineDisplayFlags::None; bool has_variants = (item.flags & EngineDisplayFlags::HasVariants) != EngineDisplayFlags::None;
bool is_folded = (item.flags & EngineDisplayFlags::IsFolded) != EngineDisplayFlags::None; bool is_folded = (item.flags & EngineDisplayFlags::IsFolded) != EngineDisplayFlags::None;
@@ -1087,10 +1085,11 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li
/* Draw tree lines */ /* Draw tree lines */
Rect fr = ir.Indent(indent - WidgetDimensions::scaled.hsep_indent, rtl).WithWidth(circle_width, rtl); Rect fr = ir.Indent(indent - WidgetDimensions::scaled.hsep_indent, rtl).WithWidth(circle_width, rtl);
int ycenter = y + normal_text_y_offset + GetCharacterHeight(FS_NORMAL) / 2; int ycenter = y + normal_text_y_offset + GetCharacterHeight(FS_NORMAL) / 2;
bool continues = (min + 1U) < eng_list.size() && eng_list[min + 1].indent == item.indent; bool continues = std::next(it) != std::end(eng_list) && std::next(it)->indent == item.indent;
GfxDrawLine(fr.left + circle_width / 2, y - WidgetDimensions::scaled.matrix.top, fr.left + circle_width / 2, continues ? y - WidgetDimensions::scaled.matrix.top + step_size - 1 : ycenter, linecolour, WidgetDimensions::scaled.fullbevel.top); GfxDrawLine(fr.left + circle_width / 2, y - WidgetDimensions::scaled.matrix.top, fr.left + circle_width / 2, continues ? y - WidgetDimensions::scaled.matrix.top + step_size - 1 : ycenter, linecolour, WidgetDimensions::scaled.fullbevel.top);
GfxDrawLine(fr.left + circle_width / 2, ycenter, fr.right, ycenter, linecolour, WidgetDimensions::scaled.fullbevel.top); GfxDrawLine(fr.left + circle_width / 2, ycenter, fr.right, ycenter, linecolour, WidgetDimensions::scaled.fullbevel.top);
} }
y += step_size;
} }
} }
@@ -1130,7 +1129,7 @@ struct BuildVehicleWindow : Window {
RoadType roadtype; ///< Road type to show, or #INVALID_ROADTYPE. RoadType roadtype; ///< Road type to show, or #INVALID_ROADTYPE.
} filter; ///< Filter to apply. } filter; ///< Filter to apply.
bool descending_sort_order; ///< Sort direction, @see _engine_sort_direction bool descending_sort_order; ///< Sort direction, @see _engine_sort_direction
byte sort_criteria; ///< Current sort criterium. uint8_t sort_criteria; ///< Current sort criterium.
bool show_hidden_engines; ///< State of the 'show hidden engines' button. bool show_hidden_engines; ///< State of the 'show hidden engines' button.
bool listview_mode; ///< If set, only display the available vehicles and do not show a 'build' button. bool listview_mode; ///< If set, only display the available vehicles and do not show a 'build' button.
EngineID sel_engine; ///< Currently selected engine, or #INVALID_ENGINE EngineID sel_engine; ///< Currently selected engine, or #INVALID_ENGINE
@@ -1569,20 +1568,20 @@ struct BuildVehicleWindow : Window {
DropDownList list; DropDownList list;
/* Add item for disabling filtering. */ /* Add item for disabling filtering. */
list.push_back(std::make_unique<DropDownListStringItem>(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ANY), CargoFilterCriteria::CF_ANY, false)); list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ANY), CargoFilterCriteria::CF_ANY));
/* Specific filters for trains. */ /* Specific filters for trains. */
if (this->vehicle_type == VEH_TRAIN) { if (this->vehicle_type == VEH_TRAIN) {
/* Add item for locomotives only in case of trains. */ /* Add item for locomotives only in case of trains. */
list.push_back(std::make_unique<DropDownListStringItem>(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ENGINES), CargoFilterCriteria::CF_ENGINES, false)); list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ENGINES), CargoFilterCriteria::CF_ENGINES));
/* Add item for vehicles not carrying anything, e.g. train engines. /* Add item for vehicles not carrying anything, e.g. train engines.
* This could also be useful for eyecandy vehicles of other types, but is likely too confusing for joe, */ * This could also be useful for eyecandy vehicles of other types, but is likely too confusing for joe, */
list.push_back(std::make_unique<DropDownListStringItem>(this->GetCargoFilterLabel(CargoFilterCriteria::CF_NONE), CargoFilterCriteria::CF_NONE, false)); list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_NONE), CargoFilterCriteria::CF_NONE));
} }
/* Add cargos */ /* Add cargos */
Dimension d = GetLargestCargoIconSize(); Dimension d = GetLargestCargoIconSize();
for (const CargoSpec *cs : _sorted_standard_cargo_specs) { for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
list.push_back(std::make_unique<DropDownListIconItem>(d, cs->GetCargoIcon(), PAL_NONE, cs->name, cs->Index(), false)); list.push_back(MakeDropDownListIconItem(d, cs->GetCargoIcon(), PAL_NONE, cs->name, cs->Index()));
} }
return list; return list;
@@ -1794,8 +1793,7 @@ struct BuildVehicleWindow : Window {
this->vehicle_type, this->vehicle_type,
r, r,
this->eng_list, this->eng_list,
this->vscroll->GetPosition(), *this->vscroll,
static_cast<uint16_t>(std::min<size_t>(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->eng_list.size())),
this->sel_engine, this->sel_engine,
false, false,
DEFAULT_GROUP DEFAULT_GROUP
@@ -1824,7 +1822,7 @@ struct BuildVehicleWindow : Window {
int needed_height = this->details_height; int needed_height = this->details_height;
/* Draw details panels. */ /* Draw details panels. */
if (this->sel_engine != INVALID_ENGINE) { if (this->sel_engine != INVALID_ENGINE) {
const Rect r = this->GetWidget<NWidgetBase>(WID_BV_PANEL)->GetCurrentRect().Shrink(WidgetDimensions::scaled.frametext, WidgetDimensions::scaled.framerect); const Rect r = this->GetWidget<NWidgetBase>(WID_BV_PANEL)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
int text_end = DrawVehiclePurchaseInfo(r.left, r.right, r.top, this->sel_engine, this->te); int text_end = DrawVehiclePurchaseInfo(r.left, r.right, r.top, this->sel_engine, this->te);
needed_height = std::max(needed_height, (text_end - r.top) / GetCharacterHeight(FS_NORMAL)); needed_height = std::max(needed_height, (text_end - r.top) / GetCharacterHeight(FS_NORMAL));
} }
@@ -1902,7 +1900,7 @@ struct BuildVehicleWindow : Window {
}}; }};
}; };
static WindowDesc _build_vehicle_desc(__FILE__, __LINE__, static WindowDesc _build_vehicle_desc(
WDP_AUTO, "build_vehicle", 240, 268, WDP_AUTO, "build_vehicle", 240, 268,
WC_BUILD_VEHICLE, WC_NONE, WC_BUILD_VEHICLE, WC_NONE,
WDF_CONSTRUCTION, WDF_CONSTRUCTION,

View File

@@ -19,7 +19,7 @@ using CargoLabel = StrongType::Typedef<uint32_t, struct CargoLabelTag, StrongTyp
/** /**
* Cargo slots to indicate a cargo type within a game. * Cargo slots to indicate a cargo type within a game.
*/ */
using CargoID = byte; using CargoID = uint8_t;
/** /**
* Available types of cargo * Available types of cargo
@@ -47,7 +47,7 @@ static constexpr CargoLabel CT_FOOD = CargoLabel{'FOOD'};
/* Tropic */ /* Tropic */
static constexpr CargoLabel CT_RUBBER = CargoLabel{'RUBR'}; static constexpr CargoLabel CT_RUBBER = CargoLabel{'RUBR'};
static constexpr CargoLabel CT_FRUIT = CargoLabel{'FRUI'}; static constexpr CargoLabel CT_FRUIT = CargoLabel{'FRUT'};
static constexpr CargoLabel CT_MAIZE = CargoLabel{'MAIZ'}; static constexpr CargoLabel CT_MAIZE = CargoLabel{'MAIZ'};
static constexpr CargoLabel CT_COPPER_ORE = CargoLabel{'CORE'}; static constexpr CargoLabel CT_COPPER_ORE = CargoLabel{'CORE'};
static constexpr CargoLabel CT_WATER = CargoLabel{'WATR'}; static constexpr CargoLabel CT_WATER = CargoLabel{'WATR'};
@@ -134,7 +134,7 @@ struct CargoArray : std::array<uint, NUM_CARGO> {
/** Types of cargo source and destination */ /** Types of cargo source and destination */
enum class SourceType : byte { enum class SourceType : uint8_t {
Industry, ///< Source/destination is an industry Industry, ///< Source/destination is an industry
Town, ///< Source/destination is a town Town, ///< Source/destination is a town
Headquarters, ///< Source/destination are company headquarters Headquarters, ///< Source/destination are company headquarters

View File

@@ -95,7 +95,7 @@ void BuildCargoLabelMap()
CargoSpec::label_map.clear(); CargoSpec::label_map.clear();
for (const CargoSpec &cs : CargoSpec::array) { for (const CargoSpec &cs : CargoSpec::array) {
/* During initialization, CargoSpec can be marked valid before the label has been set. */ /* During initialization, CargoSpec can be marked valid before the label has been set. */
if (!cs.IsValid() || cs.label == CargoLabel{0}) continue; if (!cs.IsValid() || cs.label == CargoLabel{0} || cs.label == CT_INVALID) continue;
/* Label already exists, don't addd again. */ /* Label already exists, don't addd again. */
if (CargoSpec::label_map.count(cs.label) != 0) continue; if (CargoSpec::label_map.count(cs.label) != 0) continue;

View File

@@ -18,7 +18,7 @@
#include "core/bitmath_func.hpp" #include "core/bitmath_func.hpp"
/** Town growth effect when delivering cargo. */ /** Town growth effect when delivering cargo. */
enum TownAcceptanceEffect : byte { enum TownAcceptanceEffect : uint8_t {
TAE_BEGIN = 0, TAE_BEGIN = 0,
TAE_NONE = TAE_BEGIN, ///< Cargo has no effect. TAE_NONE = TAE_BEGIN, ///< Cargo has no effect.
TAE_PASSENGERS, ///< Cargo behaves passenger-like. TAE_PASSENGERS, ///< Cargo behaves passenger-like.
@@ -31,7 +31,7 @@ enum TownAcceptanceEffect : byte {
}; };
/** Town effect when producing cargo. */ /** Town effect when producing cargo. */
enum TownProductionEffect : byte { enum TownProductionEffect : uint8_t {
TPE_NONE, ///< Town will not produce this cargo type. TPE_NONE, ///< Town will not produce this cargo type.
TPE_PASSENGERS, ///< Cargo behaves passenger-like for production. TPE_PASSENGERS, ///< Cargo behaves passenger-like for production.
TPE_MAIL, ///< Cargo behaves mail-like for production. TPE_MAIL, ///< Cargo behaves mail-like for production.
@@ -60,7 +60,7 @@ enum CargoClass {
CC_SPECIAL = 1 << 15, ///< Special bit used for livery refit tricks instead of normal cargoes. CC_SPECIAL = 1 << 15, ///< Special bit used for livery refit tricks instead of normal cargoes.
}; };
static const byte INVALID_CARGO_BITNUM = 0xFF; ///< Constant representing invalid cargo static const uint8_t INVALID_CARGO_BITNUM = 0xFF; ///< Constant representing invalid cargo
static const uint TOWN_PRODUCTION_DIVISOR = 256; static const uint TOWN_PRODUCTION_DIVISOR = 256;

View File

@@ -107,18 +107,21 @@ static int32_t ClickChangeDateCheat(int32_t new_value, int32_t)
TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date); TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date);
TimerGameCalendar::Date new_calendar_date = TimerGameCalendar::ConvertYMDToDate(new_year, ymd.month, ymd.day); TimerGameCalendar::Date new_calendar_date = TimerGameCalendar::ConvertYMDToDate(new_year, ymd.month, ymd.day);
/* Keep economy and calendar dates synced. */
TimerGameEconomy::Date new_economy_date = new_calendar_date.base();
/* Shift cached dates before we change the date. */
for (auto v : Vehicle::Iterate()) v->ShiftDates(new_economy_date - TimerGameEconomy::date);
LinkGraphSchedule::instance.ShiftDates(new_economy_date - TimerGameEconomy::date);
/* Now it's safe to actually change the date. */
TimerGameCalendar::SetDate(new_calendar_date, TimerGameCalendar::date_fract); TimerGameCalendar::SetDate(new_calendar_date, TimerGameCalendar::date_fract);
/* If not using wallclock units, we keep economy date in sync with calendar date and must change it also. */ /* If not using wallclock units, we keep economy date in sync with calendar date and must change it also. */
if (!TimerGameEconomy::UsingWallclockUnits()) TimerGameEconomy::SetDate(new_economy_date, TimerGameEconomy::date_fract); if (!TimerGameEconomy::UsingWallclockUnits()) {
/* Keep economy and calendar dates synced. */
TimerGameEconomy::Date new_economy_date = new_calendar_date.base();
/* Shift cached dates before we change the date. */
for (auto v : Vehicle::Iterate()) v->ShiftDates(new_economy_date - TimerGameEconomy::date);
LinkGraphSchedule::instance.ShiftDates(new_economy_date - TimerGameEconomy::date);
/* Now it's safe to actually change the date. */
TimerGameEconomy::SetDate(new_economy_date, TimerGameEconomy::date_fract);
}
CalendarEnginesMonthlyLoop(); CalendarEnginesMonthlyLoop();
SetWindowDirty(WC_STATUS_BAR, 0); SetWindowDirty(WC_STATUS_BAR, 0);
@@ -423,7 +426,7 @@ struct CheatWindow : Window {
}; };
/** Window description of the cheats GUI. */ /** Window description of the cheats GUI. */
static WindowDesc _cheats_desc(__FILE__, __LINE__, static WindowDesc _cheats_desc(
WDP_AUTO, "cheats", 0, 0, WDP_AUTO, "cheats", 0, 0,
WC_CHEATS, WC_NONE, WC_CHEATS, WC_NONE,
0, 0,

View File

@@ -44,7 +44,7 @@ static CommandCost ClearTile_Clear(TileIndex tile, DoCommandFlag flags)
return price; return price;
} }
void DrawClearLandTile(const TileInfo *ti, byte set) void DrawClearLandTile(const TileInfo *ti, uint8_t set)
{ {
DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh) + set * 19, PAL_NONE); DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh) + set * 19, PAL_NONE);
} }
@@ -129,8 +129,7 @@ static void DrawTile_Clear(TileInfo *ti)
static int GetSlopePixelZ_Clear(TileIndex tile, uint x, uint y, bool) static int GetSlopePixelZ_Clear(TileIndex tile, uint x, uint y, bool)
{ {
int z; auto [tileh, z] = GetTilePixelSlope(tile);
Slope tileh = GetTilePixelSlope(tile, &z);
return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh); return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
} }
@@ -145,25 +144,25 @@ static void UpdateFences(TileIndex tile)
assert(IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)); assert(IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS));
bool dirty = false; bool dirty = false;
bool neighbour = (IsTileType(TILE_ADDXY(tile, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 1, 0), CLEAR_FIELDS)); bool neighbour = (IsTileType(TileAddXY(tile, 1, 0), MP_CLEAR) && IsClearGround(TileAddXY(tile, 1, 0), CLEAR_FIELDS));
if (!neighbour && GetFence(tile, DIAGDIR_SW) == 0) { if (!neighbour && GetFence(tile, DIAGDIR_SW) == 0) {
SetFence(tile, DIAGDIR_SW, 3); SetFence(tile, DIAGDIR_SW, 3);
dirty = true; dirty = true;
} }
neighbour = (IsTileType(TILE_ADDXY(tile, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, 1), CLEAR_FIELDS)); neighbour = (IsTileType(TileAddXY(tile, 0, 1), MP_CLEAR) && IsClearGround(TileAddXY(tile, 0, 1), CLEAR_FIELDS));
if (!neighbour && GetFence(tile, DIAGDIR_SE) == 0) { if (!neighbour && GetFence(tile, DIAGDIR_SE) == 0) {
SetFence(tile, DIAGDIR_SE, 3); SetFence(tile, DIAGDIR_SE, 3);
dirty = true; dirty = true;
} }
neighbour = (IsTileType(TILE_ADDXY(tile, -1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, -1, 0), CLEAR_FIELDS)); neighbour = (IsTileType(TileAddXY(tile, -1, 0), MP_CLEAR) && IsClearGround(TileAddXY(tile, -1, 0), CLEAR_FIELDS));
if (!neighbour && GetFence(tile, DIAGDIR_NE) == 0) { if (!neighbour && GetFence(tile, DIAGDIR_NE) == 0) {
SetFence(tile, DIAGDIR_NE, 3); SetFence(tile, DIAGDIR_NE, 3);
dirty = true; dirty = true;
} }
neighbour = (IsTileType(TILE_ADDXY(tile, 0, -1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, -1), CLEAR_FIELDS)); neighbour = (IsTileType(TileAddXY(tile, 0, -1), MP_CLEAR) && IsClearGround(TileAddXY(tile, 0, -1), CLEAR_FIELDS));
if (!neighbour && GetFence(tile, DIAGDIR_NW) == 0) { if (!neighbour && GetFence(tile, DIAGDIR_NW) == 0) {
SetFence(tile, DIAGDIR_NW, 3); SetFence(tile, DIAGDIR_NW, 3);
dirty = true; dirty = true;

View File

@@ -13,6 +13,6 @@
#include "tile_cmd.h" #include "tile_cmd.h"
void DrawHillyLandTile(const TileInfo *ti); void DrawHillyLandTile(const TileInfo *ti);
void DrawClearLandTile(const TileInfo *ti, byte set); void DrawClearLandTile(const TileInfo *ti, uint8_t set);
#endif /* CLEAR_FUNC_H */ #endif /* CLEAR_FUNC_H */

View File

@@ -372,7 +372,7 @@ protected:
assert(AllClientIdsSet(args, std::index_sequence_for<Targs...>{})); assert(AllClientIdsSet(args, std::index_sequence_for<Targs...>{}));
} }
Backup<CompanyID> cur_company(_current_company, FILE_LINE); Backup<CompanyID> cur_company(_current_company);
if (!InternalExecutePrepTest(cmd_flags, tile, cur_company)) { if (!InternalExecutePrepTest(cmd_flags, tile, cur_company)) {
cur_company.Trash(); cur_company.Trash();
return MakeResult(CMD_ERROR); return MakeResult(CMD_ERROR);

View File

@@ -462,7 +462,7 @@ template <Commands Tcmd> struct CommandTraits;
}; };
/** Storage buffer for serialized command data. */ /** Storage buffer for serialized command data. */
typedef std::vector<byte> CommandDataBuffer; typedef std::vector<uint8_t> CommandDataBuffer;
/** /**
* Define a callback function for the client, after the command is finished. * Define a callback function for the client, after the command is finished.

View File

@@ -49,6 +49,19 @@ struct CompanyInfrastructure {
uint32_t GetTramTotal() const; uint32_t GetTramTotal() const;
}; };
class FreeUnitIDGenerator {
public:
UnitID NextID() const;
UnitID UseID(UnitID index);
void ReleaseID(UnitID index);
private:
using BitmapStorage = size_t;
static constexpr size_t BITMAP_SIZE = std::numeric_limits<BitmapStorage>::digits;
std::vector<BitmapStorage> used_bitmap;
};
typedef Pool<Company, CompanyID, 1, MAX_COMPANIES> CompanyPool; typedef Pool<Company, CompanyID, 1, MAX_COMPANIES> CompanyPool;
extern CompanyPool _company_pool; extern CompanyPool _company_pool;
@@ -65,20 +78,21 @@ struct CompanyProperties {
CompanyManagerFace face; ///< Face description of the president. CompanyManagerFace face; ///< Face description of the president.
Money money; ///< Money owned by the company. Money money; ///< Money owned by the company.
byte money_fraction; ///< Fraction of money of the company, too small to represent in #money. uint8_t money_fraction; ///< Fraction of money of the company, too small to represent in #money.
Money current_loan; ///< Amount of money borrowed from the bank. Money current_loan; ///< Amount of money borrowed from the bank.
Money max_loan; ///< Max allowed amount of the loan or COMPANY_MAX_LOAN_DEFAULT. Money max_loan; ///< Max allowed amount of the loan or COMPANY_MAX_LOAN_DEFAULT.
Colours colour; ///< Company colour. Colours colour; ///< Company colour.
byte block_preview; ///< Number of quarters that the company is not allowed to get new exclusive engine previews (see CompaniesGenStatistics). uint8_t block_preview; ///< Number of quarters that the company is not allowed to get new exclusive engine previews (see CompaniesGenStatistics).
TileIndex location_of_HQ; ///< Northern tile of HQ; #INVALID_TILE when there is none. TileIndex location_of_HQ; ///< Northern tile of HQ; #INVALID_TILE when there is none.
TileIndex last_build_coordinate; ///< Coordinate of the last build thing by this company. TileIndex last_build_coordinate; ///< Coordinate of the last build thing by this company.
TimerGameEconomy::Year inaugurated_year; ///< Economy year of starting the company. TimerGameEconomy::Year inaugurated_year; ///< Economy year of starting the company.
byte months_of_bankruptcy; ///< Number of months that the company is unable to pay its debts uint8_t months_empty = 0; ///< NOSAVE: Number of months this company has not had a client in multiplayer.
uint8_t months_of_bankruptcy; ///< Number of months that the company is unable to pay its debts
CompanyMask bankrupt_asked; ///< which companies were asked about buying it? CompanyMask bankrupt_asked; ///< which companies were asked about buying it?
int16_t bankrupt_timeout; ///< If bigger than \c 0, amount of time to wait for an answer on an offer to buy this company. int16_t bankrupt_timeout; ///< If bigger than \c 0, amount of time to wait for an answer on an offer to buy this company.
Money bankrupt_value; Money bankrupt_value;
@@ -97,7 +111,7 @@ struct CompanyProperties {
std::array<Expenses, 3> yearly_expenses{}; ///< Expenses of the company for the last three years. std::array<Expenses, 3> yearly_expenses{}; ///< Expenses of the company for the last three years.
CompanyEconomyEntry cur_economy; ///< Economic data of the company of this quarter. CompanyEconomyEntry cur_economy; ///< Economic data of the company of this quarter.
CompanyEconomyEntry old_economy[MAX_HISTORY_QUARTERS]; ///< Economic data of the company of the last #MAX_HISTORY_QUARTERS quarters. CompanyEconomyEntry old_economy[MAX_HISTORY_QUARTERS]; ///< Economic data of the company of the last #MAX_HISTORY_QUARTERS quarters.
byte num_valid_stat_ent; ///< Number of valid statistical entries in #old_economy. uint8_t num_valid_stat_ent; ///< Number of valid statistical entries in #old_economy.
Livery livery[LS_END]; Livery livery[LS_END];
@@ -129,6 +143,8 @@ struct Company : CompanyProperties, CompanyPool::PoolItem<&_company_pool> {
CompanyInfrastructure infrastructure; ///< NOSAVE: Counts of company owned infrastructure. CompanyInfrastructure infrastructure; ///< NOSAVE: Counts of company owned infrastructure.
FreeUnitIDGenerator freeunits[VEH_COMPANY_END];
Money GetMaxLoan() const; Money GetMaxLoan() const;
/** /**

View File

@@ -34,12 +34,13 @@
#include "game/game.hpp" #include "game/game.hpp"
#include "goal_base.h" #include "goal_base.h"
#include "story_base.h" #include "story_base.h"
#include "widgets/statusbar_widget.h"
#include "company_cmd.h" #include "company_cmd.h"
#include "timer/timer.h" #include "timer/timer.h"
#include "timer/timer_game_economy.h" #include "timer/timer_game_economy.h"
#include "timer/timer_game_tick.h" #include "timer/timer_game_tick.h"
#include "widgets/statusbar_widget.h"
#include "table/strings.h" #include "table/strings.h"
#include "safeguards.h" #include "safeguards.h"
@@ -146,8 +147,8 @@ void SetLocalCompany(CompanyID new_company)
*/ */
TextColour GetDrawStringCompanyColour(CompanyID company) TextColour GetDrawStringCompanyColour(CompanyID company)
{ {
if (!Company::IsValidID(company)) return (TextColour)_colour_gradient[COLOUR_WHITE][4] | TC_IS_PALETTE_COLOUR; if (!Company::IsValidID(company)) return (TextColour)GetColourGradient(COLOUR_WHITE, SHADE_NORMAL) | TC_IS_PALETTE_COLOUR;
return (TextColour)_colour_gradient[_company_colours[company]][4] | TC_IS_PALETTE_COLOUR; return (TextColour)GetColourGradient(_company_colours[company], SHADE_NORMAL) | TC_IS_PALETTE_COLOUR;
} }
/** /**
@@ -298,10 +299,10 @@ void SubtractMoneyFromCompany(const CommandCost &cost)
void SubtractMoneyFromCompanyFract(CompanyID company, const CommandCost &cst) void SubtractMoneyFromCompanyFract(CompanyID company, const CommandCost &cst)
{ {
Company *c = Company::Get(company); Company *c = Company::Get(company);
byte m = c->money_fraction; uint8_t m = c->money_fraction;
Money cost = cst.GetCost(); Money cost = cst.GetCost();
c->money_fraction = m - (byte)cost; c->money_fraction = m - (uint8_t)cost;
cost >>= 8; cost >>= 8;
if (c->money_fraction > m) cost++; if (c->money_fraction > m) cost++;
if (cost != 0) SubtractMoneyFromAnyCompany(c, CommandCost(cst.GetExpensesType(), cost)); if (cost != 0) SubtractMoneyFromAnyCompany(c, CommandCost(cst.GetExpensesType(), cost));
@@ -447,7 +448,7 @@ bad_town_name:;
} }
/** Sorting weights for the company colours. */ /** Sorting weights for the company colours. */
static const byte _colour_sort[COLOUR_END] = {2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 3, 1, 1, 1}; static const uint8_t _colour_sort[COLOUR_END] = {2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 3, 1, 1, 1};
/** Similar colours, so we can try to prevent same coloured companies. */ /** Similar colours, so we can try to prevent same coloured companies. */
static const Colours _similar_colour[COLOUR_END][2] = { static const Colours _similar_colour[COLOUR_END][2] = {
{ COLOUR_BLUE, COLOUR_LIGHT_BLUE }, // COLOUR_DARK_BLUE { COLOUR_BLUE, COLOUR_LIGHT_BLUE }, // COLOUR_DARK_BLUE
@@ -477,7 +478,7 @@ static Colours GenerateCompanyColour()
Colours colours[COLOUR_END]; Colours colours[COLOUR_END];
/* Initialize array */ /* Initialize array */
for (uint i = 0; i < COLOUR_END; i++) colours[i] = (Colours)i; for (uint i = 0; i < COLOUR_END; i++) colours[i] = static_cast<Colours>(i);
/* And randomize it */ /* And randomize it */
for (uint i = 0; i < 100; i++) { for (uint i = 0; i < 100; i++) {
@@ -1255,7 +1256,7 @@ CommandCost CmdGiveMoney(DoCommandFlag flags, Money money, CompanyID dest_compan
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
/* Add money to company */ /* Add money to company */
Backup<CompanyID> cur_company(_current_company, dest_company, FILE_LINE); Backup<CompanyID> cur_company(_current_company, dest_company);
SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -amount.GetCost())); SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -amount.GetCost()));
cur_company.Restore(); cur_company.Restore();

View File

@@ -15,7 +15,7 @@
#include "livery.h" #include "livery.h"
enum ClientID : uint32_t; enum ClientID : uint32_t;
enum Colours : byte; enum Colours : uint8_t;
CommandCost CmdCompanyCtrl(DoCommandFlag flags, CompanyCtrlAction cca, CompanyID company_id, CompanyRemoveReason reason, ClientID client_id); CommandCost CmdCompanyCtrl(DoCommandFlag flags, CompanyCtrlAction cca, CompanyID company_id, CompanyRemoveReason reason, ClientID client_id);
CommandCost CmdGiveMoney(DoCommandFlag flags, Money money, CompanyID dest_company); CommandCost CmdGiveMoney(DoCommandFlag flags, Money money, CompanyID dest_company);

View File

@@ -23,7 +23,8 @@
#include "company_manager_face.h" #include "company_manager_face.h"
#include "strings_func.h" #include "strings_func.h"
#include "timer/timer_game_economy.h" #include "timer/timer_game_economy.h"
#include "widgets/dropdown_type.h" #include "dropdown_type.h"
#include "dropdown_common_type.h"
#include "tilehighlight_func.h" #include "tilehighlight_func.h"
#include "company_base.h" #include "company_base.h"
#include "core/geometry_func.hpp" #include "core/geometry_func.hpp"
@@ -41,6 +42,7 @@
#include "company_cmd.h" #include "company_cmd.h"
#include "economy_cmd.h" #include "economy_cmd.h"
#include "group_cmd.h" #include "group_cmd.h"
#include "group_gui.h"
#include "misc_cmd.h" #include "misc_cmd.h"
#include "object_cmd.h" #include "object_cmd.h"
#include "timer/timer.h" #include "timer/timer.h"
@@ -530,7 +532,7 @@ struct CompanyFinancesWindow : Window {
/** First conservative estimate of the maximum amount of money */ /** First conservative estimate of the maximum amount of money */
Money CompanyFinancesWindow::max_money = INT32_MAX; Money CompanyFinancesWindow::max_money = INT32_MAX;
static WindowDesc _company_finances_desc(__FILE__, __LINE__, static WindowDesc _company_finances_desc(
WDP_AUTO, "company_finances", 0, 0, WDP_AUTO, "company_finances", 0, 0,
WC_FINANCES, WC_NONE, WC_FINANCES, WC_NONE,
0, 0,
@@ -592,8 +594,6 @@ public:
} }
}; };
typedef GUIList<const Group*> GUIGroupList;
/** Company livery colour scheme window. */ /** Company livery colour scheme window. */
struct SelectCompanyLiveryWindow : public Window { struct SelectCompanyLiveryWindow : public Window {
private: private:
@@ -603,7 +603,6 @@ private:
uint rows; uint rows;
uint line_height; uint line_height;
GUIGroupList groups; GUIGroupList groups;
std::vector<int> indents;
Scrollbar *vscroll; Scrollbar *vscroll;
void ShowColourDropDownMenu(uint32_t widget) void ShowColourDropDownMenu(uint32_t widget)
@@ -611,7 +610,7 @@ private:
uint32_t used_colours = 0; uint32_t used_colours = 0;
const Livery *livery, *default_livery = nullptr; const Livery *livery, *default_livery = nullptr;
bool primary = widget == WID_SCL_PRI_COL_DROPDOWN; bool primary = widget == WID_SCL_PRI_COL_DROPDOWN;
byte default_col = 0; uint8_t default_col = 0;
/* Disallow other company colours for the primary colour */ /* Disallow other company colours for the primary colour */
if (this->livery_class < LC_GROUP_RAIL && HasBit(this->sel, LS_DEFAULT) && primary) { if (this->livery_class < LC_GROUP_RAIL && HasBit(this->sel, LS_DEFAULT) && primary) {
@@ -652,7 +651,7 @@ private:
list.push_back(std::make_unique<DropDownListColourItem<>>(i, HasBit(used_colours, i))); list.push_back(std::make_unique<DropDownListColourItem<>>(i, HasBit(used_colours, i)));
} }
byte sel; uint8_t sel;
if (default_livery == nullptr || HasBit(livery->in_use, primary ? 0 : 1)) { if (default_livery == nullptr || HasBit(livery->in_use, primary ? 0 : 1)) {
sel = primary ? livery->colour1 : livery->colour2; sel = primary ? livery->colour1 : livery->colour2;
} else { } else {
@@ -661,57 +660,15 @@ private:
ShowDropDownList(this, std::move(list), sel, widget); ShowDropDownList(this, std::move(list), sel, widget);
} }
void AddChildren(GUIGroupList &source, GroupID parent, int indent)
{
for (const Group *g : source) {
if (g->parent != parent) continue;
this->groups.push_back(g);
this->indents.push_back(indent);
AddChildren(source, g->index, indent + 1);
}
}
void BuildGroupList(CompanyID owner) void BuildGroupList(CompanyID owner)
{ {
if (!this->groups.NeedRebuild()) return; if (!this->groups.NeedRebuild()) return;
this->groups.clear(); this->groups.clear();
this->indents.clear();
if (this->livery_class >= LC_GROUP_RAIL) { if (this->livery_class >= LC_GROUP_RAIL) {
GUIGroupList list;
VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL); VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
BuildGuiGroupList(this->groups, false, owner, vtype);
for (const Group *g : Group::Iterate()) {
if (g->owner == owner && g->vehicle_type == vtype) {
list.push_back(g);
}
}
list.ForceResort();
/* Sort the groups by their name */
const Group *last_group[2] = { nullptr, nullptr };
std::string last_name[2] = { {}, {} };
list.Sort([&](const Group * const &a, const Group * const &b) -> bool {
if (a != last_group[0]) {
last_group[0] = a;
SetDParam(0, a->index);
last_name[0] = GetString(STR_GROUP_NAME);
}
if (b != last_group[1]) {
last_group[1] = b;
SetDParam(0, b->index);
last_name[1] = GetString(STR_GROUP_NAME);
}
int r = StrNaturalCompare(last_name[0], last_name[1]); // Sort by name (natural sorting).
if (r == 0) return a->index < b->index;
return r < 0;
});
AddChildren(list, INVALID_GROUP, 0);
} }
this->groups.shrink_to_fit(); this->groups.shrink_to_fit();
@@ -775,7 +732,7 @@ public:
/* Position scrollbar to selected group */ /* Position scrollbar to selected group */
for (uint i = 0; i < this->rows; i++) { for (uint i = 0; i < this->rows; i++) {
if (this->groups[i]->index == sel) { if (this->groups[i].group->index == sel) {
this->vscroll->SetPosition(i - this->vscroll->GetCapacity() / 2); this->vscroll->SetPosition(i - this->vscroll->GetCapacity() / 2);
break; break;
} }
@@ -945,11 +902,11 @@ public:
} }
} }
} else { } else {
uint max = static_cast<uint>(std::min<size_t>(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->groups.size())); auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->groups);
for (uint i = this->vscroll->GetPosition(); i < max; ++i) { for (auto it = first; it != last; ++it) {
const Group *g = this->groups[i]; const Group *g = it->group;
SetDParam(0, g->index); SetDParam(0, g->index);
draw_livery(STR_GROUP_NAME, g->livery, this->sel == g->index, false, this->indents[i] * WidgetDimensions::scaled.hsep_indent); draw_livery(STR_GROUP_NAME, g->livery, this->sel == g->index, false, it->indent * WidgetDimensions::scaled.hsep_indent);
} }
if (this->vscroll->GetCount() == 0) { if (this->vscroll->GetCount() == 0) {
@@ -992,7 +949,7 @@ public:
this->BuildGroupList((CompanyID)this->window_number); this->BuildGroupList((CompanyID)this->window_number);
if (!this->groups.empty()) { if (!this->groups.empty()) {
this->sel = this->groups[0]->index; this->sel = this->groups[0].group->index;
} }
} }
@@ -1009,10 +966,10 @@ public:
break; break;
case WID_SCL_MATRIX: { case WID_SCL_MATRIX: {
uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SCL_MATRIX);
if (row >= this->rows) return;
if (this->livery_class < LC_GROUP_RAIL) { if (this->livery_class < LC_GROUP_RAIL) {
uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, widget);
if (row >= this->rows) return;
LiveryScheme j = (LiveryScheme)row; LiveryScheme j = (LiveryScheme)row;
for (LiveryScheme scheme = LS_BEGIN; scheme <= j && scheme < LS_END; scheme++) { for (LiveryScheme scheme = LS_BEGIN; scheme <= j && scheme < LS_END; scheme++) {
@@ -1026,7 +983,10 @@ public:
this->sel = 1 << j; this->sel = 1 << j;
} }
} else { } else {
this->sel = this->groups[row]->index; auto it = this->vscroll->GetScrolledItemFromWidget(this->groups, pt.y, this, widget);
if (it == std::end(this->groups)) return;
this->sel = it->group->index;
} }
this->SetDirty(); this->SetDirty();
break; break;
@@ -1079,7 +1039,7 @@ public:
if (!Group::IsValidID(this->sel)) { if (!Group::IsValidID(this->sel)) {
this->sel = INVALID_GROUP; this->sel = INVALID_GROUP;
if (!this->groups.empty()) this->sel = this->groups[0]->index; if (!this->groups.empty()) this->sel = this->groups[0].group->index;
} }
this->SetDirty(); this->SetDirty();
@@ -1140,7 +1100,7 @@ static constexpr NWidgetPart _nested_select_company_livery_widgets[] = {
EndContainer(), EndContainer(),
}; };
static WindowDesc _select_company_livery_desc(__FILE__, __LINE__, static WindowDesc _select_company_livery_desc(
WDP_AUTO, "company_color_scheme", 0, 0, WDP_AUTO, "company_color_scheme", 0, 0,
WC_COMPANY_COLOUR, WC_NONE, WC_COMPANY_COLOUR, WC_NONE,
0, 0,
@@ -1769,7 +1729,7 @@ public:
}; };
/** Company manager face selection window description */ /** Company manager face selection window description */
static WindowDesc _select_company_manager_face_desc(__FILE__, __LINE__, static WindowDesc _select_company_manager_face_desc(
WDP_AUTO, nullptr, 0, 0, WDP_AUTO, nullptr, 0, 0,
WC_COMPANY_MANAGER_FACE, WC_NONE, WC_COMPANY_MANAGER_FACE, WC_NONE,
WDF_CONSTRUCTION, WDF_CONSTRUCTION,
@@ -2146,7 +2106,7 @@ struct CompanyInfrastructureWindow : Window
} }
}; };
static WindowDesc _company_infrastructure_desc(__FILE__, __LINE__, static WindowDesc _company_infrastructure_desc(
WDP_AUTO, "company_infrastructure", 0, 0, WDP_AUTO, "company_infrastructure", 0, 0,
WC_COMPANY_INFRASTRUCTURE, WC_NONE, WC_COMPANY_INFRASTRUCTURE, WC_NONE,
0, 0,
@@ -2529,7 +2489,7 @@ struct CompanyWindow : Window
} }
case WID_C_BUILD_HQ: case WID_C_BUILD_HQ:
if ((byte)this->window_number != _local_company) return; if ((uint8_t)this->window_number != _local_company) return;
if (this->IsWidgetLowered(WID_C_BUILD_HQ)) { if (this->IsWidgetLowered(WID_C_BUILD_HQ)) {
ResetObjectToPlace(); ResetObjectToPlace();
this->RaiseButtons(); this->RaiseButtons();
@@ -2614,7 +2574,7 @@ struct CompanyWindow : Window
default: NOT_REACHED(); default: NOT_REACHED();
case WID_C_GIVE_MONEY: { case WID_C_GIVE_MONEY: {
Money money = std::strtoull(str, nullptr, 10) / _currency->rate; Money money = std::strtoull(str, nullptr, 10) / GetCurrency().rate;
Command<CMD_GIVE_MONEY>::Post(STR_ERROR_CAN_T_GIVE_MONEY, money, (CompanyID)this->window_number); Command<CMD_GIVE_MONEY>::Post(STR_ERROR_CAN_T_GIVE_MONEY, money, (CompanyID)this->window_number);
break; break;
} }
@@ -2634,7 +2594,7 @@ struct CompanyWindow : Window
} }
}; };
static WindowDesc _company_desc(__FILE__, __LINE__, static WindowDesc _company_desc(
WDP_AUTO, "company", 0, 0, WDP_AUTO, "company", 0, 0,
WC_COMPANY, WC_NONE, WC_COMPANY, WC_NONE,
0, 0,
@@ -2768,7 +2728,7 @@ static constexpr NWidgetPart _nested_buy_company_widgets[] = {
EndContainer(), EndContainer(),
}; };
static WindowDesc _buy_company_desc(__FILE__, __LINE__, static WindowDesc _buy_company_desc(
WDP_AUTO, nullptr, 0, 0, WDP_AUTO, nullptr, 0, 0,
WC_BUY_COMPANY, WC_NONE, WC_BUY_COMPANY, WC_NONE,
WDF_CONSTRUCTION, WDF_CONSTRUCTION,

View File

@@ -54,9 +54,9 @@ DECLARE_POSTFIX_INCREMENT(CompanyManagerFaceVariable)
/** Information about the valid values of CompanyManagerFace bitgroups as well as the sprites to draw */ /** Information about the valid values of CompanyManagerFace bitgroups as well as the sprites to draw */
struct CompanyManagerFaceBitsInfo { struct CompanyManagerFaceBitsInfo {
byte offset; ///< Offset in bits into the CompanyManagerFace uint8_t offset; ///< Offset in bits into the CompanyManagerFace
byte length; ///< Number of bits used in the CompanyManagerFace uint8_t length; ///< Number of bits used in the CompanyManagerFace
byte valid_values[GE_END]; ///< The number of valid values per gender/ethnicity uint8_t valid_values[GE_END]; ///< The number of valid values per gender/ethnicity
SpriteID first_sprite[GE_END]; ///< The first sprite per gender/ethnicity SpriteID first_sprite[GE_END]; ///< The first sprite per gender/ethnicity
}; };

View File

@@ -15,7 +15,7 @@
/** /**
* Enum for all companies/owners. * Enum for all companies/owners.
*/ */
enum Owner : byte { enum Owner : uint8_t {
/* All companies below MAX_COMPANIES are playable /* All companies below MAX_COMPANIES are playable
* companies, above, they are special, computer controlled 'companies' */ * companies, above, they are special, computer controlled 'companies' */
OWNER_BEGIN = 0x00, ///< First owner OWNER_BEGIN = 0x00, ///< First owner

View File

@@ -206,7 +206,7 @@ static std::string RemoveUnderscores(std::string name)
* @param tokencount the number of parameters passed * @param tokencount the number of parameters passed
* @param *tokens are the parameters given to the original command (0 is the first param) * @param *tokens are the parameters given to the original command (0 is the first param)
*/ */
static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[ICON_TOKEN_COUNT], const uint recurse_count) static void IConsoleAliasExec(const IConsoleAlias *alias, uint8_t tokencount, char *tokens[ICON_TOKEN_COUNT], const uint recurse_count)
{ {
std::string alias_buffer; std::string alias_buffer;

View File

@@ -89,7 +89,7 @@ static ConsoleFileList _console_file_list_scenario{FT_SCENARIO, false}; ///< Fil
static ConsoleFileList _console_file_list_heightmap{FT_HEIGHTMAP, false}; ///< File storage cache for heightmaps. static ConsoleFileList _console_file_list_heightmap{FT_HEIGHTMAP, false}; ///< File storage cache for heightmaps.
/* console command defines */ /* console command defines */
#define DEF_CONSOLE_CMD(function) static bool function([[maybe_unused]] byte argc, [[maybe_unused]] char *argv[]) #define DEF_CONSOLE_CMD(function) static bool function([[maybe_unused]] uint8_t argc, [[maybe_unused]] char *argv[])
#define DEF_CONSOLE_HOOK(function) static ConsoleHookResult function(bool echo) #define DEF_CONSOLE_HOOK(function) static ConsoleHookResult function(bool echo)
@@ -155,6 +155,21 @@ DEF_CONSOLE_HOOK(ConHookNeedNetwork)
return CHR_ALLOW; return CHR_ALLOW;
} }
/**
* Check whether we are in a multiplayer game and are playing, i.e. we are not the dedicated server.
* @return Are we a client or non-dedicated server in a network game? True when yes, false otherwise.
*/
DEF_CONSOLE_HOOK(ConHookNeedNonDedicatedNetwork)
{
if (!NetworkAvailable(echo)) return CHR_DISALLOW;
if (_network_dedicated) {
if (echo) IConsolePrint(CC_ERROR, "This command is not available to a dedicated network server.");
return CHR_DISALLOW;
}
return CHR_ALLOW;
}
/** /**
* Check whether we are in singleplayer mode. * Check whether we are in singleplayer mode.
* @return True when no network is active. * @return True when no network is active.
@@ -835,6 +850,7 @@ DEF_CONSOLE_CMD(ConRcon)
if (argc == 0) { if (argc == 0) {
IConsolePrint(CC_HELP, "Remote control the server from another client. Usage: 'rcon <password> <command>'."); IConsolePrint(CC_HELP, "Remote control the server from another client. Usage: 'rcon <password> <command>'.");
IConsolePrint(CC_HELP, "Remember to enclose the command in quotes, otherwise only the first parameter is sent."); IConsolePrint(CC_HELP, "Remember to enclose the command in quotes, otherwise only the first parameter is sent.");
IConsolePrint(CC_HELP, "When your client's public key is in the 'authorized keys' for 'rcon', the password is not checked and may be '*'.");
return true; return true;
} }
@@ -919,13 +935,19 @@ DEF_CONSOLE_CMD(ConJoinCompany)
CompanyID company_id = (CompanyID)(atoi(argv[1]) <= MAX_COMPANIES ? atoi(argv[1]) - 1 : atoi(argv[1])); CompanyID company_id = (CompanyID)(atoi(argv[1]) <= MAX_COMPANIES ? atoi(argv[1]) - 1 : atoi(argv[1]));
const NetworkClientInfo *info = NetworkClientInfo::GetByClientID(_network_own_client_id);
if (info == nullptr) {
IConsolePrint(CC_ERROR, "You have not joined the game yet!");
return true;
}
/* Check we have a valid company id! */ /* Check we have a valid company id! */
if (!Company::IsValidID(company_id) && company_id != COMPANY_SPECTATOR) { if (!Company::IsValidID(company_id) && company_id != COMPANY_SPECTATOR) {
IConsolePrint(CC_ERROR, "Company does not exist. Company-id must be between 1 and {}.", MAX_COMPANIES); IConsolePrint(CC_ERROR, "Company does not exist. Company-id must be between 1 and {}.", MAX_COMPANIES);
return true; return true;
} }
if (NetworkClientInfo::GetByClientID(_network_own_client_id)->client_playas == company_id) { if (info->client_playas == company_id) {
IConsolePrint(CC_ERROR, "You are already there!"); IConsolePrint(CC_ERROR, "You are already there!");
return true; return true;
} }
@@ -1954,6 +1976,86 @@ DEF_CONSOLE_CMD(ConCompanyPassword)
return true; return true;
} }
/** All the known authorized keys with their name. */
static std::vector<std::pair<std::string_view, NetworkAuthorizedKeys *>> _console_cmd_authorized_keys{
{ "rcon", &_settings_client.network.rcon_authorized_keys },
{ "server", &_settings_client.network.server_authorized_keys },
};
DEF_CONSOLE_CMD(ConNetworkAuthorizedKey)
{
if (argc <= 2) {
IConsolePrint(CC_HELP, "List and update authorized keys. Usage: 'authorized_key list [type]|add [type] [key]|remove [type] [key]'.");
IConsolePrint(CC_HELP, " list: list all the authorized keys of the given type.");
IConsolePrint(CC_HELP, " add: add the given key to the authorized keys of the given type.");
IConsolePrint(CC_HELP, " remove: remove the given key from the authorized keys of the given type; use 'all' to remove all authorized keys.");
IConsolePrint(CC_HELP, "Instead of a key, use 'client:<id>' to add/remove the key of that given client.");
std::string buffer;
for (auto [name, _] : _console_cmd_authorized_keys) fmt::format_to(std::back_inserter(buffer), ", {}", name);
IConsolePrint(CC_HELP, "The supported types are: all{}.", buffer);
return true;
}
bool valid_type = false; ///< Whether a valid type was given.
for (auto [name, authorized_keys] : _console_cmd_authorized_keys) {
if (!StrEqualsIgnoreCase(argv[2], name) && !StrEqualsIgnoreCase(argv[2], "all")) continue;
valid_type = true;
if (StrEqualsIgnoreCase(argv[1], "list")) {
IConsolePrint(CC_WHITE, "The authorized keys for {} are:", name);
for (auto &authorized_key : *authorized_keys) IConsolePrint(CC_INFO, " {}", authorized_key);
continue;
}
if (argc <= 3) {
IConsolePrint(CC_ERROR, "You must enter the key.");
return false;
}
std::string authorized_key = argv[3];
if (StrStartsWithIgnoreCase(authorized_key, "client:")) {
std::string id_string(authorized_key.substr(7));
authorized_key = NetworkGetPublicKeyOfClient(static_cast<ClientID>(std::stoi(id_string)));
if (authorized_key.empty()) {
IConsolePrint(CC_ERROR, "You must enter a valid client id; see 'clients'.");
return false;
}
}
if (StrEqualsIgnoreCase(argv[1], "add")) {
if (authorized_keys->Add(authorized_key)) {
IConsolePrint(CC_INFO, "Added {} to {}.", authorized_key, name);
} else {
IConsolePrint(CC_WARNING, "Not added {} to {} as it already exists.", authorized_key, name);
}
continue;
}
if (StrEqualsIgnoreCase(argv[1], "remove")) {
if (authorized_keys->Remove(authorized_key)) {
IConsolePrint(CC_INFO, "Removed {} from {}.", authorized_key, name);
} else {
IConsolePrint(CC_WARNING, "Not removed {} from {} as it does not exist.", authorized_key, name);
}
continue;
}
IConsolePrint(CC_WARNING, "No valid action was given.");
return false;
}
if (!valid_type) {
IConsolePrint(CC_WARNING, "No valid type was given.");
return false;
}
return true;
}
/* Content downloading only is available with ZLIB */ /* Content downloading only is available with ZLIB */
#if defined(WITH_ZLIB) #if defined(WITH_ZLIB)
#include "network/network_content.h" #include "network/network_content.h"
@@ -2091,10 +2193,14 @@ DEF_CONSOLE_CMD(ConFont)
IConsolePrint(CC_HELP, "Manage the fonts configuration."); IConsolePrint(CC_HELP, "Manage the fonts configuration.");
IConsolePrint(CC_HELP, "Usage 'font'."); IConsolePrint(CC_HELP, "Usage 'font'.");
IConsolePrint(CC_HELP, " Print out the fonts configuration."); IConsolePrint(CC_HELP, " Print out the fonts configuration.");
IConsolePrint(CC_HELP, "Usage 'font [medium|small|large|mono] [<name>] [<size>] [aa|noaa]'."); IConsolePrint(CC_HELP, " The \"Currently active\" configuration is the one actually in effect (after interface scaling and replacing unavailable fonts).");
IConsolePrint(CC_HELP, " The \"Requested\" configuration is the one requested via console command or config file.");
IConsolePrint(CC_HELP, "Usage 'font [medium|small|large|mono] [<font name>] [<size>] [aa|noaa]'.");
IConsolePrint(CC_HELP, " Change the configuration for a font."); IConsolePrint(CC_HELP, " Change the configuration for a font.");
IConsolePrint(CC_HELP, " Omitting an argument will keep the current value."); IConsolePrint(CC_HELP, " Omitting an argument will keep the current value.");
IConsolePrint(CC_HELP, " Set <name> to \"\" for the sprite font (size and aa have no effect on sprite font)."); IConsolePrint(CC_HELP, " Set <font name> to \"\" for the default font. Note that <size> and aa/noaa have no effect if the default font is in use, and fixed defaults are used instead.");
IConsolePrint(CC_HELP, " If the sprite font is enabled in Game Options, it is used instead of the default font.");
IConsolePrint(CC_HELP, " The <size> is automatically multiplied by the current interface scaling.");
return true; return true;
} }
@@ -2112,7 +2218,7 @@ DEF_CONSOLE_CMD(ConFont)
uint size = setting->size; uint size = setting->size;
bool aa = setting->aa; bool aa = setting->aa;
byte arg_index = 2; uint8_t arg_index = 2;
/* We may encounter "aa" or "noaa" but it must be the last argument. */ /* We may encounter "aa" or "noaa" but it must be the last argument. */
if (StrEqualsIgnoreCase(argv[arg_index], "aa") || StrEqualsIgnoreCase(argv[arg_index], "noaa")) { if (StrEqualsIgnoreCase(argv[arg_index], "aa") || StrEqualsIgnoreCase(argv[arg_index], "noaa")) {
aa = !StrStartsWithIgnoreCase(argv[arg_index++], "no"); aa = !StrStartsWithIgnoreCase(argv[arg_index++], "no");
@@ -2152,7 +2258,9 @@ DEF_CONSOLE_CMD(ConFont)
InitFontCache(fs == FS_MONO); InitFontCache(fs == FS_MONO);
fc = FontCache::Get(fs); fc = FontCache::Get(fs);
} }
IConsolePrint(CC_DEFAULT, "{}: \"{}\" {} {} [\"{}\" {} {}]", FontSizeToName(fs), fc->GetFontName(), fc->GetFontSize(), GetFontAAState(fs) ? "aa" : "noaa", setting->font, setting->size, setting->aa ? "aa" : "noaa"); IConsolePrint(CC_DEFAULT, "{} font:", FontSizeToName(fs));
IConsolePrint(CC_DEFAULT, "Currently active: \"{}\", size {}, {}", fc->GetFontName(), fc->GetFontSize(), GetFontAAState(fs) ? "aa" : "noaa");
IConsolePrint(CC_DEFAULT, "Requested: \"{}\", size {}, {}", setting->font, setting->size, setting->aa ? "aa" : "noaa");
} }
return true; return true;
@@ -2708,7 +2816,7 @@ void IConsoleStdLibRegister()
IConsole::CmdRegister("reconnect", ConNetworkReconnect, ConHookClientOnly); IConsole::CmdRegister("reconnect", ConNetworkReconnect, ConHookClientOnly);
IConsole::CmdRegister("rcon", ConRcon, ConHookNeedNetwork); IConsole::CmdRegister("rcon", ConRcon, ConHookNeedNetwork);
IConsole::CmdRegister("join", ConJoinCompany, ConHookNeedNetwork); IConsole::CmdRegister("join", ConJoinCompany, ConHookNeedNonDedicatedNetwork);
IConsole::AliasRegister("spectate", "join 255"); IConsole::AliasRegister("spectate", "join 255");
IConsole::CmdRegister("move", ConMoveClient, ConHookServerOnly); IConsole::CmdRegister("move", ConMoveClient, ConHookServerOnly);
IConsole::CmdRegister("reset_company", ConResetCompany, ConHookServerOnly); IConsole::CmdRegister("reset_company", ConResetCompany, ConHookServerOnly);
@@ -2722,6 +2830,9 @@ void IConsoleStdLibRegister()
IConsole::CmdRegister("pause", ConPauseGame, ConHookServerOrNoNetwork); IConsole::CmdRegister("pause", ConPauseGame, ConHookServerOrNoNetwork);
IConsole::CmdRegister("unpause", ConUnpauseGame, ConHookServerOrNoNetwork); IConsole::CmdRegister("unpause", ConUnpauseGame, ConHookServerOrNoNetwork);
IConsole::CmdRegister("authorized_key", ConNetworkAuthorizedKey, ConHookServerOnly);
IConsole::AliasRegister("ak", "authorized_key %+");
IConsole::CmdRegister("company_pw", ConCompanyPassword, ConHookNeedNetwork); IConsole::CmdRegister("company_pw", ConCompanyPassword, ConHookNeedNetwork);
IConsole::AliasRegister("company_password", "company_pw %+"); IConsole::AliasRegister("company_password", "company_pw %+");

View File

@@ -10,6 +10,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "textbuf_type.h" #include "textbuf_type.h"
#include "window_gui.h" #include "window_gui.h"
#include "autocompletion.h"
#include "console_gui.h" #include "console_gui.h"
#include "console_internal.h" #include "console_internal.h"
#include "window_func.h" #include "window_func.h"
@@ -73,9 +74,44 @@ static std::deque<IConsoleLine> _iconsole_buffer;
static bool TruncateBuffer(); static bool TruncateBuffer();
class ConsoleAutoCompletion final : public AutoCompletion {
public:
using AutoCompletion::AutoCompletion;
private:
std::vector<std::string> GetSuggestions(std::string_view prefix, std::string_view query) override
{
prefix = StrTrimView(prefix);
std::vector<std::string> suggestions;
/* We only suggest commands or aliases, so we only do it for the first token or an argument to help command. */
if (!prefix.empty() && prefix != "help") {
return suggestions;
}
for (const auto &[_, command] : IConsole::Commands()) {
if (command.name.starts_with(query)) {
suggestions.push_back(command.name);
}
}
for (const auto &[_, alias] : IConsole::Aliases()) {
if (alias.name.starts_with(query)) {
suggestions.push_back(alias.name);
}
}
return suggestions;
}
void ApplySuggestion(std::string_view prefix, std::string_view suggestion) override
{
this->textbuf->Assign(fmt::format("{}{} ", prefix, suggestion));
}
};
/* ** main console cmd buffer ** */ /* ** main console cmd buffer ** */
static Textbuf _iconsole_cmdline(ICON_CMDLN_SIZE); static Textbuf _iconsole_cmdline(ICON_CMDLN_SIZE);
static ConsoleAutoCompletion _iconsole_tab_completion(&_iconsole_cmdline);
static std::deque<std::string> _iconsole_history; static std::deque<std::string> _iconsole_history;
static ptrdiff_t _iconsole_historypos; static ptrdiff_t _iconsole_historypos;
IConsoleModes _iconsole_mode; IConsoleModes _iconsole_mode;
@@ -91,6 +127,7 @@ static void IConsoleClearCommand()
_iconsole_cmdline.pixels = 0; _iconsole_cmdline.pixels = 0;
_iconsole_cmdline.caretpos = 0; _iconsole_cmdline.caretpos = 0;
_iconsole_cmdline.caretxoffs = 0; _iconsole_cmdline.caretxoffs = 0;
_iconsole_tab_completion.Reset();
SetWindowDirty(WC_CONSOLE, 0); SetWindowDirty(WC_CONSOLE, 0);
} }
@@ -107,7 +144,7 @@ static constexpr NWidgetPart _nested_console_window_widgets[] = {
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_BACKGROUND), SetResize(1, 1), NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_BACKGROUND), SetResize(1, 1),
}; };
static WindowDesc _console_window_desc(__FILE__, __LINE__, static WindowDesc _console_window_desc(
WDP_MANUAL, nullptr, 0, 0, WDP_MANUAL, nullptr, 0, 0,
WC_CONSOLE, WC_NONE, WC_CONSOLE, WC_NONE,
0, 0,
@@ -274,8 +311,18 @@ struct IConsoleWindow : Window
IConsoleCmdExec("clear"); IConsoleCmdExec("clear");
break; break;
default: case WKC_TAB:
if (_iconsole_cmdline.HandleKeyPress(key, keycode) != HKPR_NOT_HANDLED) { if (_iconsole_tab_completion.AutoComplete()) {
this->SetDirty();
}
break;
default: {
HandleKeyPressResult handle_result = _iconsole_cmdline.HandleKeyPress(key, keycode);
if (handle_result != HKPR_NOT_HANDLED) {
if (handle_result == HKPR_EDITING) {
_iconsole_tab_completion.Reset();
}
IConsoleWindow::scroll = 0; IConsoleWindow::scroll = 0;
IConsoleResetHistoryPos(); IConsoleResetHistoryPos();
this->SetDirty(); this->SetDirty();
@@ -283,6 +330,7 @@ struct IConsoleWindow : Window
return ES_NOT_HANDLED; return ES_NOT_HANDLED;
} }
break; break;
}
} }
return ES_HANDLED; return ES_HANDLED;
} }
@@ -290,13 +338,14 @@ struct IConsoleWindow : Window
void InsertTextString(WidgetID, const char *str, bool marked, const char *caret, const char *insert_location, const char *replacement_end) override void InsertTextString(WidgetID, const char *str, bool marked, const char *caret, const char *insert_location, const char *replacement_end) override
{ {
if (_iconsole_cmdline.InsertString(str, marked, caret, insert_location, replacement_end)) { if (_iconsole_cmdline.InsertString(str, marked, caret, insert_location, replacement_end)) {
_iconsole_tab_completion.Reset();
IConsoleWindow::scroll = 0; IConsoleWindow::scroll = 0;
IConsoleResetHistoryPos(); IConsoleResetHistoryPos();
this->SetDirty(); this->SetDirty();
} }
} }
Textbuf *GetFocusedTextbuf() const override const Textbuf *GetFocusedTextbuf() const override
{ {
return &_iconsole_cmdline; return &_iconsole_cmdline;
} }
@@ -469,6 +518,7 @@ static void IConsoleHistoryNavigate(int direction)
} else { } else {
_iconsole_cmdline.Assign(_iconsole_history[_iconsole_historypos]); _iconsole_cmdline.Assign(_iconsole_history[_iconsole_historypos]);
} }
_iconsole_tab_completion.Reset();
} }
/** /**
@@ -528,8 +578,8 @@ bool IsValidConsoleColour(TextColour c)
/* A text colour from the palette is used; must be the company /* A text colour from the palette is used; must be the company
* colour gradient, so it must be one of those. */ * colour gradient, so it must be one of those. */
c &= ~TC_IS_PALETTE_COLOUR; c &= ~TC_IS_PALETTE_COLOUR;
for (uint i = COLOUR_BEGIN; i < COLOUR_END; i++) { for (Colours i = COLOUR_BEGIN; i < COLOUR_END; i++) {
if (_colour_gradient[i][4] == c) return true; if (GetColourGradient(i, SHADE_NORMAL) == c) return true;
} }
return false; return false;

View File

@@ -30,7 +30,7 @@ enum ConsoleHookResult {
* If you want to handle multiple words as one, enclose them in double-quotes * If you want to handle multiple words as one, enclose them in double-quotes
* eg. 'say "hello everybody"' * eg. 'say "hello everybody"'
*/ */
typedef bool IConsoleCmdProc(byte argc, char *argv[]); typedef bool IConsoleCmdProc(uint8_t argc, char *argv[]);
typedef ConsoleHookResult IConsoleHook(bool echo); typedef ConsoleHookResult IConsoleHook(bool echo);
struct IConsoleCmd { struct IConsoleCmd {
IConsoleCmd(const std::string &name, IConsoleCmdProc *proc, IConsoleHook *hook) : name(name), proc(proc), hook(hook) {} IConsoleCmd(const std::string &name, IConsoleCmdProc *proc, IConsoleHook *hook) : name(name), proc(proc), hook(hook) {}

View File

@@ -93,14 +93,14 @@ public:
* @param size the amount of bytes to allocate. * @param size the amount of bytes to allocate.
* @return the given amounts of bytes zeroed. * @return the given amounts of bytes zeroed.
*/ */
inline void *operator new(size_t size) { return CallocT<byte>(size); } inline void *operator new(size_t size) { return CallocT<uint8_t>(size); }
/** /**
* Memory allocator for an array of class instances. * Memory allocator for an array of class instances.
* @param size the amount of bytes to allocate. * @param size the amount of bytes to allocate.
* @return the given amounts of bytes zeroed. * @return the given amounts of bytes zeroed.
*/ */
inline void *operator new[](size_t size) { return CallocT<byte>(size); } inline void *operator new[](size_t size) { return CallocT<uint8_t>(size); }
/** /**
* Memory release for a single class instance. * Memory release for a single class instance.

View File

@@ -22,20 +22,18 @@ struct Backup {
/** /**
* Backup variable. * Backup variable.
* @param original Variable to backup. * @param original Variable to backup.
* @param file Filename for debug output. Use FILE_LINE macro. * @param location Source location for debug output.
* @param line Linenumber for debug output. Use FILE_LINE macro.
*/ */
Backup(T &original, const char * const file, const int line) : original(original), valid(true), original_value(original), file(file), line(line) {} Backup(T &original, const std::source_location location = std::source_location::current()) : original(original), valid(true), original_value(original), location(location) {}
/** /**
* Backup variable and switch to new value. * Backup variable and switch to new value.
* @param original Variable to backup. * @param original Variable to backup.
* @param new_value New value for variable. * @param new_value New value for variable.
* @param file Filename for debug output. Use FILE_LINE macro. * @param location Source location for debug output.
* @param line Linenumber for debug output. Use FILE_LINE macro.
*/ */
template <typename U> template <typename U>
Backup(T &original, const U &new_value, const char * const file, const int line) : original(original), valid(true), original_value(original), file(file), line(line) Backup(T &original, const U &new_value, const std::source_location location = std::source_location::current()) : original(original), valid(true), original_value(original), location(location)
{ {
/* Note: We use a separate typename U, so type conversions are handled by assignment operator. */ /* Note: We use a separate typename U, so type conversions are handled by assignment operator. */
original = new_value; original = new_value;
@@ -51,7 +49,7 @@ struct Backup {
{ {
/* We cannot assert here, as missing restoration is 'normal' when exceptions are thrown. /* We cannot assert here, as missing restoration is 'normal' when exceptions are thrown.
* Exceptions are especially used to abort world generation. */ * Exceptions are especially used to abort world generation. */
Debug(misc, 0, "{}:{}: Backed-up value was not restored!", this->file, this->line); Debug(misc, 0, "{}:{}: Backed-up value was not restored!", this->location.file_name(), this->location.line());
this->Restore(); this->Restore();
} }
} }
@@ -140,8 +138,7 @@ private:
bool valid; bool valid;
T original_value; T original_value;
const char * const file; const std::source_location location;
const int line;
}; };
/** /**

View File

@@ -46,7 +46,7 @@ inline void MemMoveT(T *destination, const T *source, size_t num = 1)
* @param num number of items to be set (!not number of bytes!) * @param num number of items to be set (!not number of bytes!)
*/ */
template <typename T> template <typename T>
inline void MemSetT(T *ptr, byte value, size_t num = 1) inline void MemSetT(T *ptr, uint8_t value, size_t num = 1)
{ {
memset(ptr, value, num * sizeof(T)); memset(ptr, value, num * sizeof(T));
} }

View File

@@ -140,7 +140,7 @@ public:
inline constexpr OverflowSafeInt operator * (const int factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; } inline constexpr OverflowSafeInt operator * (const int factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; }
inline constexpr OverflowSafeInt operator * (const uint factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; } inline constexpr OverflowSafeInt operator * (const uint factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; }
inline constexpr OverflowSafeInt operator * (const uint16_t factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; } inline constexpr OverflowSafeInt operator * (const uint16_t factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; }
inline constexpr OverflowSafeInt operator * (const byte factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; } inline constexpr OverflowSafeInt operator * (const uint8_t factor) const { OverflowSafeInt result = *this; result *= (int64_t)factor; return result; }
/* Operators for division. */ /* Operators for division. */
inline constexpr OverflowSafeInt& operator /= (const int64_t divisor) { this->m_value /= divisor; return *this; } inline constexpr OverflowSafeInt& operator /= (const int64_t divisor) { this->m_value /= divisor; return *this; }
@@ -200,10 +200,10 @@ template <class T> inline constexpr OverflowSafeInt<T> operator * (const uint a
template <class T> inline constexpr OverflowSafeInt<T> operator / (const uint a, const OverflowSafeInt<T> b) { return (OverflowSafeInt<T>)a / (int)b; } template <class T> inline constexpr OverflowSafeInt<T> operator / (const uint a, const OverflowSafeInt<T> b) { return (OverflowSafeInt<T>)a / (int)b; }
/* Sometimes we got byte operator OverflowSafeInt instead of vice versa. Handle that properly. */ /* Sometimes we got byte operator OverflowSafeInt instead of vice versa. Handle that properly. */
template <class T> inline constexpr OverflowSafeInt<T> operator + (const byte a, const OverflowSafeInt<T> b) { return b + (uint)a; } template <class T> inline constexpr OverflowSafeInt<T> operator + (const uint8_t a, const OverflowSafeInt<T> b) { return b + (uint)a; }
template <class T> inline constexpr OverflowSafeInt<T> operator - (const byte a, const OverflowSafeInt<T> b) { return -b + (uint)a; } template <class T> inline constexpr OverflowSafeInt<T> operator - (const uint8_t a, const OverflowSafeInt<T> b) { return -b + (uint)a; }
template <class T> inline constexpr OverflowSafeInt<T> operator * (const byte a, const OverflowSafeInt<T> b) { return b * (uint)a; } template <class T> inline constexpr OverflowSafeInt<T> operator * (const uint8_t a, const OverflowSafeInt<T> b) { return b * (uint)a; }
template <class T> inline constexpr OverflowSafeInt<T> operator / (const byte a, const OverflowSafeInt<T> b) { return (OverflowSafeInt<T>)a / (int)b; } template <class T> inline constexpr OverflowSafeInt<T> operator / (const uint8_t a, const OverflowSafeInt<T> b) { return (OverflowSafeInt<T>)a / (int)b; }
typedef OverflowSafeInt<int64_t> OverflowSafeInt64; typedef OverflowSafeInt<int64_t> OverflowSafeInt64;
typedef OverflowSafeInt<int32_t> OverflowSafeInt32; typedef OverflowSafeInt<int32_t> OverflowSafeInt32;

View File

@@ -123,9 +123,9 @@ DEFINE_POOL_METHOD(inline void *)::AllocateItem(size_t size, size_t index)
memset((void *)item, 0, sizeof(Titem)); memset((void *)item, 0, sizeof(Titem));
} }
} else if (Tzero) { } else if (Tzero) {
item = (Titem *)CallocT<byte>(size); item = (Titem *)CallocT<uint8_t>(size);
} else { } else {
item = (Titem *)MallocT<byte>(size); item = (Titem *)MallocT<uint8_t>(size);
} }
this->data[index] = item; this->data[index] = item;
SetBit(this->used_bitmap[index / BITMAP_SIZE], index % BITMAP_SIZE); SetBit(this->used_bitmap[index / BITMAP_SIZE], index % BITMAP_SIZE);

View File

@@ -49,17 +49,6 @@ uint32_t Randomizer::Next()
return this->state[1] = std::rotr(s, 3) - 1; return this->state[1] = std::rotr(s, 3) - 1;
} }
/**
* Generate the next pseudo random number scaled to \a limit, excluding \a limit
* itself.
* @param limit Limit of the range to be generated from.
* @return Random number in [0,\a limit)
*/
uint32_t Randomizer::Next(uint32_t limit)
{
return ((uint64_t)this->Next() * (uint64_t)limit) >> 32;
}
/** /**
* (Re)set the state of the random number generator. * (Re)set the state of the random number generator.
* @param seed the new state * @param seed the new state
@@ -81,19 +70,14 @@ void SetRandomSeed(uint32_t seed)
} }
#ifdef RANDOM_DEBUG #ifdef RANDOM_DEBUG
uint32_t DoRandom(int line, const char *file) uint32_t Random(const std::source_location location)
{ {
if (_networking && (!_network_server || (NetworkClientSocket::IsValidID(0) && NetworkClientSocket::Get(0)->status != NetworkClientSocket::STATUS_INACTIVE))) { if (_networking && (!_network_server || (NetworkClientSocket::IsValidID(0) && NetworkClientSocket::Get(0)->status != NetworkClientSocket::STATUS_INACTIVE))) {
Debug(random, 0, "{:08x}; {:02x}; {:04x}; {:02x}; {}:{}", TimerGameEconomy::date, TimerGameEconomy::date_fract, _frame_counter, (byte)_current_company, file, line); Debug(random, 0, "{:08x}; {:02x}; {:04x}; {:02x}; {}:{}", TimerGameEconomy::date, TimerGameEconomy::date_fract, _frame_counter, (uint8_t)_current_company, location.file_name(), location.line());
} }
return _random.Next(); return _random.Next();
} }
uint32_t DoRandomRange(uint32_t limit, int line, const char *file)
{
return ((uint64_t)DoRandom(line, file) * (uint64_t)limit) >> 32;
}
#endif /* RANDOM_DEBUG */ #endif /* RANDOM_DEBUG */
/** /**

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