Compare commits

..

39 Commits

Author SHA1 Message Date
Paul Chote
7d455a1fe2 Switch Appimages to net 5. 2020-12-28 21:32:00 +00:00
Paul Chote
9a46fd7454 Run appimagetool directly. 2020-12-28 21:11:34 +00:00
Paul Chote
f28bf15668 Use ULFO format for non-compat disk images (requires macOS 10.11+). 2020-12-28 20:54:22 +00:00
Paul Chote
e11f8ce66d Trim unused assemblies to reduce packaged size further. 2020-12-28 20:54:22 +00:00
Paul Chote
e9b02833ca Replace duplicate runtime files with hardlinks to reduce dmg size. 2020-12-28 20:54:22 +00:00
Paul Chote
1ff7c2cd06 Switch macOS packages to .NET 5. 2020-12-28 20:54:22 +00:00
teinarss
d781331ade Add support for dotnet core for Windows 2020-12-28 16:31:20 +01:00
teinarss
73bba97aaa Update MasterServerPinger to modern approach 2020-12-22 20:57:40 +01:00
abcdefg30
d6e9cdab5b Add the 9th Dark Tournament map as "Oil Spill" 2020-12-21 21:08:39 +01:00
Paul Chote
1a177bc2de Remove unused variables from Map.SavePreview. 2020-12-19 13:07:01 +01:00
Paul Chote
e0b3e631fe Remove obsolete null checks. 2020-12-19 13:07:01 +01:00
Paul Chote
2518a353af Add lint test for invalid map tiles. 2020-12-19 13:07:01 +01:00
Paul Chote
989800efff Fix missing tiles in upstream maps. 2020-12-19 13:07:01 +01:00
Paul Chote
c02846e2cb Replace invalid tiles on map load. 2020-12-19 13:07:01 +01:00
Matthias Mailänder
09db4a0e25 Enable debug mode by default. 2020-12-15 23:06:05 +01:00
Trevor Nichols
a85da9d86c Implement loader for MegV3 file format 2020-12-15 11:11:05 +01:00
Paul Chote
920d00bbae Use nearest-neighbour scaling in --debug-chrome-regions utility command. 2020-12-14 22:38:25 +01:00
Ivaylo Draganov
62475279ee Remove unneeded chrome yaml declarations 2020-12-14 20:52:38 +01:00
Matthias Mailänder
d8e979d283 Remove dead code. 2020-12-14 20:38:50 +01:00
Paul Chote
299b8880dd Fix api output directory. 2020-12-14 18:33:35 +01:00
Paul Chote
61027e4067 Fix docs.openra.net repository reference. 2020-12-14 18:33:35 +01:00
Paul Chote
a7249c10dc Fix docs.openra.net documentation workflow. 2020-12-13 15:35:31 +01:00
Paul Chote
611d12ac78 Migrate CI and packaging from Travis CI to GitHub Actions. 2020-12-12 20:17:29 +00:00
abcdefg30
ef9f26a60d Fix MissionObjectives not properly ending the game 2020-12-12 14:59:49 +01:00
abcdefg30
aeaffc0a8e Properly restrict the spectator view in mission maps 2020-12-12 14:59:49 +01:00
Paul Chote
e3084e230e Switch mirror for nsis3 package. 2020-12-12 14:54:50 +01:00
Paul Chote
4c01c772f8 Fix incorrect animation playing when moving infantry stop to attack. 2020-12-12 14:40:13 +01:00
Paul Chote
ed94f7680a Revert "Fix WithInfantryBody wrongly overwriting attack animations"
This reverts commit 1a63cc4a41.
2020-12-12 14:40:13 +01:00
yuantse
408d66cdaf Add Allies 09a 2020-12-12 13:18:08 +01:00
Smittytron
c4a0f2f169 Add Counterstrike mission Sarin Gas 3: Controlled Burn 2020-12-12 13:15:18 +01:00
Paul Chote
26b28d26da Prevent Civilians from wandering onto Tiberium. 2020-12-12 12:54:46 +01:00
Paul Chote
8ded6dafd4 Add AvoidTerrainTypes to ScaredyCat. 2020-12-12 12:54:46 +01:00
Paul Chote
57a94ad667 Add AvoidTerrainTypes to Wanders. 2020-12-12 12:54:46 +01:00
Paul Chote
53933a4d8f Fix restart black screen race condition. 2020-12-11 22:57:57 +01:00
Paul Chote
6606d7dd93 Add DisplayFaction details to the replay metadata. 2020-12-11 18:05:44 +01:00
Paul Chote
7a256dcafa Fix rally point target line exit display. 2020-12-11 17:25:30 +01:00
abcdefg30
7899c52b6d Add an update rule 2020-12-11 17:13:02 +01:00
abcdefg30
919c670502 Update the rules of the default mods 2020-12-11 17:13:02 +01:00
abcdefg30
aac3174efc Rename Stances to Relationships in the yaml api 2020-12-11 17:13:02 +01:00
77 changed files with 1694 additions and 550 deletions

View File

@@ -2,14 +2,13 @@ name: Continuous Integration
on:
push:
workflow_dispatch:
pull_request:
branches: [ bleed ]
jobs:
linux-mono:
name: Linux (mono)
runs-on: ubuntu-16.04
runs-on: ubuntu-20.04
steps:
- name: Clone Repository
@@ -19,7 +18,6 @@ jobs:
run: |
mono --version
make check
mono ~/.nuget/packages/nunit.consolerunner/3.11.1/tools/nunit3-console.exe --noresult bin/OpenRA.Test.dll
- name: Check Mods
run: |
@@ -28,18 +26,26 @@ jobs:
make test
windows:
name: Windows (Framework 4.7)
name: Windows (Net 5.0)
runs-on: windows-2019
steps:
- name: Clone Repository
uses: actions/checkout@v2
- name: Install .NET 5
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.x'
- name: Check Code
shell: powershell
run: |
# Work around runtime failures on the GH Actions runner
dotnet nuget locals all --clear
.\make.ps1 check
Invoke-Expression "$home\.nuget\packages\nunit.consolerunner\3.11.1\tools\nunit3-console.exe --noresult bin/OpenRA.Test.dll"
dotnet build OpenRA.Test\OpenRA.Test.csproj -c Debug --nologo -p:TargetPlatform=win-x64
dotnet test bin\OpenRA.Test.dll --test-adapter-path:.
- name: Check Mods
run: |

107
.github/workflows/documentation.yml vendored Normal file
View File

@@ -0,0 +1,107 @@
name: Deploy Documentation
on:
workflow_dispatch:
inputs:
tag:
description: 'Git Tag'
required: true
default: 'release-xxxxxxxx'
jobs:
wiki:
name: Update Wiki
if: github.repository == 'openra/openra'
runs-on: ubuntu-20.04
steps:
- name: Clone Repository
uses: actions/checkout@v2
with:
ref: ${{ github.event.inputs.tag }}
- name: Prepare Environment
run: |
make all
- name: Clone Wiki
uses: actions/checkout@v2
with:
repository: openra/openra.wiki
token: ${{ secrets.DOCS_TOKEN }}
path: wiki
- name: Update Wiki (Playtest)
if: startsWith(github.event.inputs.tag, 'playtest-')
env:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
./utility.sh all --settings-docs "${GIT_TAG}" > "wiki/Settings (playtest).md"
- name: Update Wiki (Release)
if: startsWith(github.event.inputs.tag, 'release-')
env:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
./utility.sh all --settings-docs "${GIT_TAG}" > "wiki/Settings.md"
- name: Push Wiki
env:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
cd wiki
git config --local user.email "actions@github.com"
git config --local user.name "GitHub Actions"
git add --all
git commit -m "Update auto-generated documentation for ${GIT_TAG}"
git push origin master
docs:
name: Update docs.openra.net
if: github.repository == 'openra/openra'
runs-on: ubuntu-20.04
steps:
- name: Clone Repository
uses: actions/checkout@v2
with:
ref: ${{ github.event.inputs.tag }}
- name: Prepare Environment
run: |
make all
- name: Clone docs.openra.net
uses: actions/checkout@v2
with:
repository: openra/docs
token: ${{ secrets.DOCS_TOKEN }}
path: docs
- name: Update docs.openra.net (Playtest)
if: startsWith(github.event.inputs.tag, 'playtest-')
env:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
./utility.sh all --docs "${GIT_TAG}" > "docs/api/playtest/traits.md"
./utility.sh all --weapon-docs "${GIT_TAG}" > "docs/api/playtest/weapons.md"
./utility.sh all --lua-docs "${GIT_TAG}" > "docs/api/playtest/lua.md"
- name: Update docs.openra.net (Release)
if: startsWith(github.event.inputs.tag, 'release-')
env:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
./utility.sh all --docs "${GIT_TAG}" > "docs/api/release/traits.md"
./utility.sh all --weapon-docs "${GIT_TAG}" > "docs/api/release/weapons.md"
./utility.sh all --lua-docs "${GIT_TAG}" > "docs/api/release/lua.md"
- name: Push docs.openra.net
env:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
cd docs
git config --local user.email "actions@github.com"
git config --local user.name "GitHub Actions"
git add --all
git commit -m "Update auto-generated documentation for ${GIT_TAG}"
git push origin master

88
.github/workflows/itch.yml vendored Normal file
View File

@@ -0,0 +1,88 @@
name: Deploy itch.io Packages
on:
workflow_dispatch:
inputs:
tag:
description: 'Git Tag'
required: true
default: 'release-xxxxxxxx'
jobs:
itch:
name: Deploy to itch.io
runs-on: ubuntu-20.04
if: github.repository == 'openra/openra'
steps:
- name: Download Packages
env:
GIT_TAG: ${{ github.event.inputs.tag }}
run: |
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-${GIT_TAG}-x64.exe"
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-${GIT_TAG}-x64-winportable.zip" -O "OpenRA-${GIT_TAG}-x64-win-itch.zip"
wget -q "https://github.com${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-${GIT_TAG}.dmg"
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-Dune-2000-x86_64.AppImage"
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-Red-Alert-x86_64.AppImage"
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-Tiberian-Dawn-x86_64.AppImage"
wget -q "https://raw.githubusercontent.com/${{ github.repository }}/${GIT_TAG}/packaging/.itch.toml"
zip -u "OpenRA-${GIT_TAG}-x64-win-itch.zip" .itch.toml
- name: Publish Windows Installer
uses: josephbmanley/butler-publish-itchio-action@master
env:
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
CHANNEL: win
ITCH_GAME: openra
ITCH_USER: openra-developers
VERSION: ${{ github.event.inputs.tag }}
PACKAGE: OpenRA-${{ github.event.inputs.tag }}}-x64.exe"
- name: Publish Windows Itch Bundle
uses: josephbmanley/butler-publish-itchio-action@master
env:
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
CHANNEL: itch
ITCH_GAME: openra
ITCH_USER: openra-developers
VERSION: ${{ github.event.inputs.tag }}
PACKAGE: OpenRA-${{ github.event.inputs.tag }}-x64-win-itch.zip
- name: Publish macOS Package
uses: josephbmanley/butler-publish-itchio-action@master
env:
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
CHANNEL: macos
ITCH_GAME: openra
ITCH_USER: openra-developers
VERSION: ${{ github.event.inputs.tag }}
PACKAGE: OpenRA-${{ github.event.inputs.tag }}}.dmg"
- name: Publish RA AppImage
uses: josephbmanley/butler-publish-itchio-action@master
env:
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
CHANNEL: linux-ra
ITCH_GAME: openra
ITCH_USER: openra-developers
VERSION: ${{ github.event.inputs.tag }}
PACKAGE: OpenRA-Red-Alert-x86_64.AppImage
- name: Publish TD AppImage
uses: josephbmanley/butler-publish-itchio-action@master
env:
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
CHANNEL: linux-cnc
ITCH_GAME: openra
ITCH_USER: openra-developers
VERSION: ${{ github.event.inputs.tag }}
PACKAGE: OpenRA-Tiberian-Dawn-x86_64.AppImage
- name: Publish D2k AppImage
uses: josephbmanley/butler-publish-itchio-action@master
env:
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
CHANNEL: linux-d2k
ITCH_GAME: openra
ITCH_USER: openra-developers
VERSION: ${{ github.event.inputs.tag }}
PACKAGE: OpenRA-Dune-2000-x86_64.AppImage

View File

@@ -10,7 +10,7 @@ on:
jobs:
linux:
name: Linux AppImages
runs-on: ubuntu-16.04
runs-on: ubuntu-20.04
steps:
- name: Clone Repository
uses: actions/checkout@v2
@@ -39,6 +39,11 @@ jobs:
- name: Clone Repository
uses: actions/checkout@v2
- name: Install .NET 5
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.x'
- name: Prepare Environment
run: echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> ${GITHUB_ENV}
@@ -64,18 +69,20 @@ jobs:
windows:
name: Windows Installers
runs-on: ubuntu-16.04
runs-on: ubuntu-20.04
steps:
- name: Clone Repository
uses: actions/checkout@v2
- name: Install .NET 5
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.x'
- name: Prepare Environment
run: |
echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> ${GITHUB_ENV}
wget https://mirrors.edge.kernel.org/ubuntu/pool/universe/n/nsis/nsis-common_3.04-1_all.deb
wget https://mirrors.edge.kernel.org/ubuntu/pool/universe/n/nsis/nsis_3.04-1_amd64.deb
sudo dpkg -i nsis-common_3.04-1_all.deb
sudo dpkg -i nsis_3.04-1_amd64.deb
sudo apt install nsis wine64
- name: Package Installers
run: |
@@ -90,155 +97,3 @@ jobs:
overwrite: true
file_glob: true
file: build/windows/*
itch:
name: Deploy to itch.io
runs-on: ubuntu-16.04
if: github.repository == 'openra/openra' && startsWith(github.ref, 'refs/tags/release-')
needs: [linux, macos, windows]
steps:
- name: Prepare Environment
run: |
echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> ${GITHUB_ENV}
- name: Download Packages
run: |
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-${GIT_TAG}-x64.exe"
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-${GIT_TAG}-x64-winportable.zip" -O "OpenRA-${GIT_TAG}-x64-win-itch.zip"
wget -q "https://github.com${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-${GIT_TAG}.dmg"
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-Dune-2000-x86_64.AppImage"
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-Red-Alert-x86_64.AppImage"
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-Tiberian-Dawn-x86_64.AppImage"
wget -q "https://raw.githubusercontent.com/${{ github.repository }}/${GIT_TAG}/packaging/.itch.toml"
zip -u "OpenRA-${GIT_TAG}-x64-win-itch.zip" .itch.toml
- name: Publish Windows Installer
uses: josephbmanley/butler-publish-itchio-action@master
env:
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
CHANNEL: win
ITCH_GAME: openra
ITCH_USER: openra-developers
VERSION: ${{ env.GIT_TAG }}
PACKAGE: OpenRA-${{ env.GIT_TAG }}}-x64.exe"
- name: Publish Windows Itch Bundle
uses: josephbmanley/butler-publish-itchio-action@master
env:
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
CHANNEL: itch
ITCH_GAME: openra
ITCH_USER: openra-developers
VERSION: ${{ env.GIT_TAG }}
PACKAGE: OpenRA-${{ env.GIT_TAG }}-x64-win-itch.zip
- name: Publish macOS Package
uses: josephbmanley/butler-publish-itchio-action@master
env:
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
CHANNEL: macos
ITCH_GAME: openra
ITCH_USER: openra-developers
VERSION: ${{ env.GIT_TAG }}
PACKAGE: OpenRA-${{ env.GIT_TAG }}}.dmg"
- name: Publish RA AppImage
uses: josephbmanley/butler-publish-itchio-action@master
env:
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
CHANNEL: linux-ra
ITCH_GAME: openra
ITCH_USER: openra-developers
VERSION: ${{ env.GIT_TAG }}
PACKAGE: OpenRA-Red-Alert-x86_64.AppImage
- name: Publish TD AppImage
uses: josephbmanley/butler-publish-itchio-action@master
env:
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
CHANNEL: linux-cnc
ITCH_GAME: openra
ITCH_USER: openra-developers
VERSION: ${{ env.GIT_TAG }}
PACKAGE: OpenRA-Tiberian-Dawn-x86_64.AppImage
- name: Publish D2k AppImage
uses: josephbmanley/butler-publish-itchio-action@master
env:
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
CHANNEL: linux-d2k
ITCH_GAME: openra
ITCH_USER: openra-developers
VERSION: ${{ env.GIT_TAG }}
PACKAGE: OpenRA-Dune-2000-x86_64.AppImage
docs:
name: Update Docs
if: github.repository == 'openra/openra' && (startsWith(github.ref, 'refs/tags/playtest-') || startsWith(github.ref, 'refs/tags/release-'))
runs-on: ubuntu-16.04
needs: [linux, macos, windows]
steps:
- name: Clone Repository
uses: actions/checkout@v2
- name: Prepare Environment
run: |
echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> ${GITHUB_ENV}
make all
- name: Clone Wiki
uses: actions/checkout@v2
with:
repository: openra/openra.wiki
token: ${{ secrets.DOCS_TOKEN }}
path: wiki
- name: Update Wiki (Playtest)
if: startsWith(github.ref, 'refs/tags/playtest-')
run: |
./utility.sh all --settings-docs "${GIT_TAG}" > "wiki/Settings (playtest).md"
- name: Update Wiki (Release)
if: startsWith(github.ref, 'refs/tags/release-')
run: |
./utility.sh all --settings-docs "${GIT_TAG}" > "wiki/Settings.md"
- name: Push Wiki
run: |
cd wiki
git config --local user.email "actions@github.com"
git config --local user.name "GitHub Actions"
git add --all
git commit -m "Update auto-generated documentation for ${GIT_TAG}"
git push origin master
- name: Clone docs.openra.net
uses: actions/checkout@v2
with:
repository: openra/docs.git
token: ${{ secrets.DOCS_TOKEN }}
path: docs
- name: Update docs.openra.net (Playtest)
if: startsWith(github.ref, 'refs/tags/playtest-')
run: |
./utility.sh all --docs "${GIT_TAG}" > "docs/playtest/traits.md"
./utility.sh all --weapon-docs "${GIT_TAG}" > "docs/playtest/weapons.md"
./utility.sh all --lua-docs "${GIT_TAG}" > "docs/playtest/lua.md"
- name: Update docs.openra.net (Release)
if: startsWith(github.ref, 'refs/tags/release-')
run: |
./utility.sh all --docs "${GIT_TAG}" > "docs/release/traits.md"
./utility.sh all --weapon-docs "${GIT_TAG}" > "docs/release/weapons.md"
./utility.sh all --lua-docs "${GIT_TAG}" > "docs/release/lua.md"
- name: Push docs.openra.net
run: |
cd docs
git config --local user.email "actions@github.com"
git config --local user.name "GitHub Actions"
git add --all
git commit -m "Update auto-generated documentation for ${GIT_TAG}"
git push origin master

View File

@@ -8,18 +8,16 @@ Windows
Compiling OpenRA requires the following dependencies:
* [Windows PowerShell >= 4.0](http://microsoft.com/powershell) (included by default in recent Windows 10 versions)
* [.NET Framework 4.7.2 (Developer Pack)](https://dotnet.microsoft.com/download/dotnet-framework/net472) (or via Visual Studio 2017)
* [.NET Core 2.2 SDK](https://dotnet.microsoft.com/download/dotnet-core/2.2) (or via Visual Studio 2017)
* [.NET 5 SDK](https://dotnet.microsoft.com/download/dotnet/5.0) (or via Visual Studio)
To compile OpenRA, open the `OpenRA.sln` solution in the main folder, build it from the command-line with MSBuild or use the Makefile analogue command `make all` scripted in PowerShell syntax.
To compile OpenRA, open the `OpenRA.sln` solution in the main folder, build it from the command-line with `dotnet` or use the Makefile analogue command `make all` scripted in PowerShell syntax.
Run the game with `launch-game.cmd`. It can be handed arguments that specify the exact mod one wishes to run, for example, run `launch-game.cmd Game.Mod=ra` to launch Red Alert, `launch-game.cmd Game.Mod=cnc` to start Tiberian dawn or `launch-game.cmd Game.Mod=d2k` to launch Dune 2000.
Linux
=====
Mono, version 5.18 or later, is required to compile OpenRA. You can add the [upstream mono repository](https://www.mono-project.com/download/stable/#download-lin) for your distro to obtain the latest version if your system packages are not sufficient.
Mono, version 6.4 or later, is required to compile OpenRA. You can add the [upstream mono repository](https://www.mono-project.com/download/stable/#download-lin) for your distro to obtain the latest version if your system packages are not sufficient.
To compile OpenRA, run `make` from the command line. After this one can run the game with `./launch-game.sh`. It is also possible to specify the mod you wish to run from the command line, e.g. with `./launch-game.sh Game.Mod=ts` if you wish to try the experimental Tiberian Sun mod.
@@ -99,7 +97,7 @@ macOS
=====
Before compiling OpenRA you must install the following dependencies:
* [Mono >= 5.18](https://www.mono-project.com/download/stable/#download-mac)
* [Mono >= 6.4](https://www.mono-project.com/download/stable/#download-mac)
To compile OpenRA, run `make` from the command line. Run with `./launch-game.sh`.

View File

@@ -28,14 +28,14 @@
############################## TOOLCHAIN ###############################
#
# List of .NET assemblies that we can guarantee exist
WHITELISTED_OPENRA_ASSEMBLIES = OpenRA.exe OpenRA.Utility.exe OpenRA.Server.exe OpenRA.Platforms.Default.dll OpenRA.Game.dll OpenRA.Mods.Common.dll OpenRA.Mods.Cnc.dll OpenRA.Mods.D2k.dll
WHITELISTED_OPENRA_ASSEMBLIES = OpenRA.dll OpenRA.Utility.dll OpenRA.Server.dll OpenRA.Platforms.Default.dll OpenRA.Game.dll OpenRA.Mods.Common.dll OpenRA.Mods.Cnc.dll OpenRA.Mods.D2k.dll
# These are explicitly shipped alongside our core files by the packaging script
WHITELISTED_THIRDPARTY_ASSEMBLIES = ICSharpCode.SharpZipLib.dll FuzzyLogicLibrary.dll Eluant.dll BeaconLib.dll Open.Nat.dll SDL2-CS.dll OpenAL-CS.Core.dll DiscordRPC.dll Newtonsoft.Json.dll
# These are shipped in our custom minimal mono runtime and also available in the full system-installed .NET/mono stack
# This list *must* be kept in sync with the files packaged by the AppImageSupport and OpenRALauncherOSX repositories
WHITELISTED_CORE_ASSEMBLIES = mscorlib.dll System.dll System.Configuration.dll System.Core.dll System.Numerics.dll System.Security.dll System.Xml.dll Mono.Security.dll netstandard.dll
WHITELISTED_CORE_ASSEMBLIES = mscorlib.dll System.dll System.Configuration.dll System.Core.dll System.Numerics.dll System.Security.dll System.Xml.dll Mono.Security.dll netstandard.dll Microsoft.Win32.Registry.dll System.Security.AccessControl.dll System.Security.Principal.Windows.dll System.Xml.Linq.dll System.Runtime.Serialization.dll
######################### UTILITIES/SETTINGS ###########################
#
@@ -78,13 +78,13 @@ endif
endif
endif
OPENRA_UTILITY = ENGINE_DIR=".." $(MONO) --debug bin/OpenRA.Utility.exe
OPENRA_UTILITY = ENGINE_DIR=".." $(MONO) --debug bin/OpenRA.Utility.dll
##################### DEVELOPMENT BUILDS AND TESTS #####################
#
all:
@command -v $(firstword $(MSBUILD)) >/dev/null || (echo "OpenRA requires the '$(MSBUILD)' tool provided by Mono >= 5.18."; exit 1)
@$(MSBUILD) -t:Build -restore -p:Configuration=Release -p:TargetPlatform=$(TARGETPLATFORM)
@$(MSBUILD) -t:Build -restore -p:Configuration=Release -p:TargetPlatform=$(TARGETPLATFORM) -p:Mono=true -p:DefineConstants="MONO"
ifeq ($(TARGETPLATFORM), unix-generic)
@./configure-system-libraries.sh
endif
@@ -92,13 +92,13 @@ endif
clean:
@-$(RM_RF) ./bin ./*/bin ./*/obj
@$(MSBUILD) -t:Clean
@$(MSBUILD) -t:Clean -p:Mono=true
@-$(RM_F) IP2LOCATION-LITE-DB1.IPV6.BIN.ZIP
check:
@echo
@echo "Compiling in debug mode..."
@$(MSBUILD) -t:build -restore -p:Configuration=Debug
@$(MSBUILD) -t:build -restore -p:Configuration=Debug -p:TargetPlatform=$(TARGETPLATFORM) -p:Mono=true -p:DefineConstants="MONO"
@echo
@echo "Checking runtime assemblies..."
@$(OPENRA_UTILITY) all --check-runtime-assemblies $(WHITELISTED_OPENRA_ASSEMBLIES) $(WHITELISTED_THIRDPARTY_ASSEMBLIES) $(WHITELISTED_CORE_ASSEMBLIES)

View File

@@ -297,6 +297,7 @@ namespace OpenRA
EngineVersion = "Unknown";
Console.WriteLine("Engine version is {0}", EngineVersion);
Console.WriteLine("Runtime: {0}", Platform.RuntimeVersion);
// Special case handling of Game.Mod argument: if it matches a real filesystem path
// then we use this to override the mod search path, and replace it with the mod id
@@ -329,9 +330,16 @@ namespace OpenRA
try
{
var rendererPath = Path.Combine(Platform.BinDir, "OpenRA.Platforms." + p + ".dll");
var assembly = Assembly.LoadFile(rendererPath);
#if !MONO
var loader = new AssemblyLoader(rendererPath);
var platformType = loader.LoadDefaultAssembly().GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t));
#else
var assembly = Assembly.LoadFile(rendererPath);
var platformType = assembly.GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t));
#endif
if (platformType == null)
throw new InvalidOperationException("Platform dll must include exactly one IPlatform implementation.");

View File

@@ -168,10 +168,7 @@ namespace OpenRA.Graphics
for (var x = 0; x < template.Size.X; x++)
{
var tile = new TerrainTile(template.Id, (byte)(i++));
var tileInfo = tileset.GetTileInfo(tile);
// Empty tile
if (tileInfo == null)
if (!tileset.TryGetTileInfo(tile, out var tileInfo))
continue;
var sprite = TileSprite(tile);

View File

@@ -206,6 +206,8 @@ namespace OpenRA
public readonly MiniYaml NotificationDefinitions;
public readonly MiniYaml TranslationDefinitions;
public readonly Dictionary<CPos, TerrainTile> ReplacedInvalidTerrainTiles = new Dictionary<CPos, TerrainTile>();
// Generated data
public readonly MapGrid Grid;
public IReadOnlyPackage Package { get; private set; }
@@ -287,7 +289,6 @@ namespace OpenRA
this.modData = modData;
var size = new Size(width, height);
Grid = modData.Manifest.Get<MapGrid>();
var tileRef = new TerrainTile(tileset.Templates.First().Key, 0);
Title = "Name your map here";
Author = "Your name here";
@@ -310,7 +311,7 @@ namespace OpenRA
Tiles.CellEntryChanged += UpdateRamp;
}
Tiles.Clear(tileRef);
Tiles.Clear(tileset.DefaultTerrainTile);
PostInit();
}
@@ -430,12 +431,18 @@ namespace OpenRA
foreach (var uv in AllCells.MapCoords)
CustomTerrain[uv] = byte.MaxValue;
// Cache initial ramp state
// Replace invalid tiles and cache ramp state
var tileset = Rules.TileSet;
foreach (var uv in AllCells)
foreach (var uv in AllCells.MapCoords)
{
var tile = tileset.GetTileInfo(Tiles[uv]);
Ramp[uv] = tile != null ? tile.RampType : (byte)0;
if (!tileset.TryGetTileInfo(Tiles[uv], out var info))
{
ReplacedInvalidTerrainTiles[uv.ToCPos(this)] = Tiles[uv];
Tiles[uv] = tileset.DefaultTerrainTile;
info = tileset.GetTileInfo(tileset.DefaultTerrainTile);
}
Ramp[uv] = info.RampType;
}
AllEdgeCells = UpdateEdgeCells();
@@ -443,8 +450,7 @@ namespace OpenRA
void UpdateRamp(CPos cell)
{
var tile = Rules.TileSet.GetTileInfo(Tiles[cell]);
Ramp[cell] = tile != null ? tile.RampType : (byte)0;
Ramp[cell] = Rules.TileSet.GetTileInfo(Tiles[cell]).RampType;
}
void InitializeCellProjection()
@@ -670,32 +676,26 @@ namespace OpenRA
Color left, right;
var tileset = Rules.TileSet;
var type = tileset.GetTileInfo(Tiles[uv]);
if (type != null)
if (type.MinColor != type.MaxColor)
{
if (type.MinColor != type.MaxColor)
{
left = Exts.ColorLerp(Game.CosmeticRandom.NextFloat(), type.MinColor, type.MaxColor);
right = Exts.ColorLerp(Game.CosmeticRandom.NextFloat(), type.MinColor, type.MaxColor);
}
else
left = right = type.MinColor;
if (tileset.MinHeightColorBrightness != 1.0f || tileset.MaxHeightColorBrightness != 1.0f)
{
var scale = float2.Lerp(tileset.MinHeightColorBrightness, tileset.MaxHeightColorBrightness, Height[uv] * 1f / Grid.MaximumTerrainHeight);
left = Color.FromArgb((int)(scale * left.R).Clamp(0, 255), (int)(scale * left.G).Clamp(0, 255), (int)(scale * left.B).Clamp(0, 255));
right = Color.FromArgb((int)(scale * right.R).Clamp(0, 255), (int)(scale * right.G).Clamp(0, 255), (int)(scale * right.B).Clamp(0, 255));
}
left = Exts.ColorLerp(Game.CosmeticRandom.NextFloat(), type.MinColor, type.MaxColor);
right = Exts.ColorLerp(Game.CosmeticRandom.NextFloat(), type.MinColor, type.MaxColor);
}
else
left = right = Color.Black;
left = right = type.MinColor;
if (tileset.MinHeightColorBrightness != 1.0f || tileset.MaxHeightColorBrightness != 1.0f)
{
var scale = float2.Lerp(tileset.MinHeightColorBrightness, tileset.MaxHeightColorBrightness, Height[uv] * 1f / Grid.MaximumTerrainHeight);
left = Color.FromArgb((int)(scale * left.R).Clamp(0, 255), (int)(scale * left.G).Clamp(0, 255), (int)(scale * left.B).Clamp(0, 255));
right = Color.FromArgb((int)(scale * right.R).Clamp(0, 255), (int)(scale * right.G).Clamp(0, 255), (int)(scale * right.B).Clamp(0, 255));
}
return (left, right);
}
public byte[] SavePreview()
{
var tileset = Rules.TileSet;
var actorTypes = Rules.Actors.Values.Where(a => a.HasTraitInfo<IMapPreviewSignatureInfo>());
var actors = ActorDefinitions.Where(a => actorTypes.Where(ai => ai.Name == a.Value.Value).Any());
var positions = new List<(MPos Position, Color Color)>();
@@ -715,76 +715,73 @@ namespace OpenRA
foreach (var worldimpsi in worldimpsis)
worldimpsi.PopulateMapPreviewSignatureCells(this, worldActorInfo, null, positions);
using (var stream = new MemoryStream())
var isRectangularIsometric = Grid.Type == MapGridType.RectangularIsometric;
// Fudge the heightmap offset by adding as much extra as we need / can.
// This tries to correct for our incorrect assumption that MPos == PPos
var heightOffset = Math.Min(Grid.MaximumTerrainHeight, MapSize.Y - Bounds.Bottom);
var width = Bounds.Width;
var height = Bounds.Height + heightOffset;
var bitmapWidth = width;
if (isRectangularIsometric)
bitmapWidth = 2 * bitmapWidth - 1;
var stride = bitmapWidth * 4;
var pxStride = 4;
var minimapData = new byte[stride * height];
(Color Left, Color Right) terrainColor = default((Color, Color));
for (var y = 0; y < height; y++)
{
var isRectangularIsometric = Grid.Type == MapGridType.RectangularIsometric;
// Fudge the heightmap offset by adding as much extra as we need / can.
// This tries to correct for our incorrect assumption that MPos == PPos
var heightOffset = Math.Min(Grid.MaximumTerrainHeight, MapSize.Y - Bounds.Bottom);
var width = Bounds.Width;
var height = Bounds.Height + heightOffset;
var bitmapWidth = width;
if (isRectangularIsometric)
bitmapWidth = 2 * bitmapWidth - 1;
var stride = bitmapWidth * 4;
var pxStride = 4;
var minimapData = new byte[stride * height];
(Color Left, Color Right) terrainColor = default((Color, Color));
for (var y = 0; y < height; y++)
for (var x = 0; x < width; x++)
{
for (var x = 0; x < width; x++)
var uv = new MPos(x + Bounds.Left, y + Bounds.Top);
// FirstOrDefault will return a (MPos.Zero, Color.Transparent) if positions is empty
var actorColor = positions.FirstOrDefault(ap => ap.Position == uv).Color;
if (actorColor.A == 0)
terrainColor = GetTerrainColorPair(uv);
if (isRectangularIsometric)
{
var uv = new MPos(x + Bounds.Left, y + Bounds.Top);
// FirstOrDefault will return a (MPos.Zero, Color.Transparent) if positions is empty
var actorColor = positions.FirstOrDefault(ap => ap.Position == uv).Color;
if (actorColor.A == 0)
terrainColor = GetTerrainColorPair(uv);
if (isRectangularIsometric)
// Odd rows are shifted right by 1px
var dx = uv.V & 1;
var xOffset = pxStride * (2 * x + dx);
if (x + dx > 0)
{
// Odd rows are shifted right by 1px
var dx = uv.V & 1;
var xOffset = pxStride * (2 * x + dx);
if (x + dx > 0)
{
var z = y * stride + xOffset - pxStride;
var c = actorColor.A == 0 ? terrainColor.Left : actorColor;
minimapData[z++] = c.R;
minimapData[z++] = c.G;
minimapData[z++] = c.B;
minimapData[z] = c.A;
}
if (xOffset < stride)
{
var z = y * stride + xOffset;
var c = actorColor.A == 0 ? terrainColor.Right : actorColor;
minimapData[z++] = c.R;
minimapData[z++] = c.G;
minimapData[z++] = c.B;
minimapData[z] = c.A;
}
}
else
{
var z = y * stride + pxStride * x;
var z = y * stride + xOffset - pxStride;
var c = actorColor.A == 0 ? terrainColor.Left : actorColor;
minimapData[z++] = c.R;
minimapData[z++] = c.G;
minimapData[z++] = c.B;
minimapData[z] = c.A;
}
if (xOffset < stride)
{
var z = y * stride + xOffset;
var c = actorColor.A == 0 ? terrainColor.Right : actorColor;
minimapData[z++] = c.R;
minimapData[z++] = c.G;
minimapData[z++] = c.B;
minimapData[z] = c.A;
}
}
else
{
var z = y * stride + pxStride * x;
var c = actorColor.A == 0 ? terrainColor.Left : actorColor;
minimapData[z++] = c.R;
minimapData[z++] = c.G;
minimapData[z++] = c.B;
minimapData[z] = c.A;
}
}
var png = new Png(minimapData, bitmapWidth, height);
return png.Save();
}
var png = new Png(minimapData, bitmapWidth, height);
return png.Save();
}
public bool Contains(CPos cell)

View File

@@ -23,6 +23,8 @@ namespace OpenRA
}
public override int GetHashCode() { return Type.GetHashCode() ^ Index.GetHashCode(); }
public override string ToString() { return Type + "," + Index; }
}
public struct ResourceTile

View File

@@ -221,25 +221,30 @@ namespace OpenRA
public byte GetTerrainIndex(TerrainTile r)
{
if (!Templates.TryGetValue(r.Type, out var tpl))
return defaultWalkableTerrainIndex;
if (tpl.Contains(r.Index))
{
var tile = tpl[r.Index];
if (tile != null && tile.TerrainType != byte.MaxValue)
return tile.TerrainType;
}
var tile = Templates[r.Type][r.Index];
if (tile.TerrainType != byte.MaxValue)
return tile.TerrainType;
return defaultWalkableTerrainIndex;
}
public TerrainTileInfo GetTileInfo(TerrainTile r)
{
if (!Templates.TryGetValue(r.Type, out var tpl))
return null;
return tpl.Contains(r.Index) ? tpl[r.Index] : null;
return Templates[r.Type][r.Index];
}
public bool TryGetTileInfo(TerrainTile r, out TerrainTileInfo info)
{
if (!Templates.TryGetValue(r.Type, out var tpl) || !tpl.Contains(r.Index))
{
info = null;
return false;
}
info = tpl[r.Index];
return info != null;
}
public TerrainTile DefaultTerrainTile { get { return new TerrainTile(Templates.First().Key, 0); } }
}
}

View File

@@ -15,6 +15,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using OpenRA.Primitives;
using OpenRA.Support;
namespace OpenRA
{
@@ -42,25 +43,48 @@ namespace OpenRA
if (resolvedPath == null)
throw new FileNotFoundException("Assembly `{0}` not found.".F(path));
// .NET doesn't provide any way of querying the metadata of an assembly without either:
// (a) loading duplicate data into the application domain, breaking the world.
// (b) crashing if the assembly has already been loaded.
// We can't check the internal name of the assembly, so we'll work off the data instead
var hash = CryptoUtil.SHA1Hash(File.ReadAllBytes(resolvedPath));
if (!ResolvedAssemblies.TryGetValue(hash, out var assembly))
{
assembly = Assembly.LoadFile(resolvedPath);
ResolvedAssemblies.Add(hash, assembly);
}
assemblyList.Add(assembly);
LoadAssembly(assemblyList, resolvedPath);
}
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;
assemblies = assemblyList.SelectMany(asm => asm.GetNamespaces().Select(ns => (asm, ns))).ToArray();
}
void LoadAssembly(List<Assembly> assemblyList, string resolvedPath)
{
// .NET doesn't provide any way of querying the metadata of an assembly without either:
// (a) loading duplicate data into the application domain, breaking the world.
// (b) crashing if the assembly has already been loaded.
// We can't check the internal name of the assembly, so we'll work off the data instead
var hash = CryptoUtil.SHA1Hash(File.ReadAllBytes(resolvedPath));
if (!ResolvedAssemblies.TryGetValue(hash, out var assembly))
{
#if MONO
assembly = Assembly.LoadFile(resolvedPath);
ResolvedAssemblies.Add(hash, assembly);
// Allow mods to use libraries.
var assemblyPath = Path.GetDirectoryName(resolvedPath);
if (assemblyPath != null)
{
foreach (var referencedAssembly in assembly.GetReferencedAssemblies())
{
var depedencyPath = Path.Combine(assemblyPath, referencedAssembly.Name + ".dll");
if (File.Exists(depedencyPath))
LoadAssembly(assemblyList, depedencyPath);
}
}
#else
var loader = new AssemblyLoader(resolvedPath);
assembly = loader.LoadDefaultAssembly();
ResolvedAssemblies.Add(hash, assembly);
#endif
}
assemblyList.Add(assembly);
}
Assembly ResolveAssembly(object sender, ResolveEventArgs e)
{
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net472</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<UseVSHostingProcess>false</UseVSHostingProcess>
@@ -39,6 +39,11 @@
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
<AdditionalFiles Include="../stylecop.json" />
</ItemGroup>
<ItemGroup Condition="'$(Mono)' == ''">
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="5.0.0-preview.3-runtime.20214.6" />
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
</ItemGroup>
<Target Name="DisableAnalyzers" BeforeTargets="CoreCompile" Condition="'$(Configuration)'=='Release'">
<!-- Disable code style analysis on Release builds to improve compile-time performance -->
<ItemGroup Condition="'$(Configuration)'=='Release'">

View File

@@ -80,6 +80,7 @@ namespace OpenRA
{
get
{
// Players in mission maps must not leave the player view
return !inMissionMap && (spectating || WinState != WinState.Undefined);
}
}

View File

@@ -0,0 +1,363 @@
#region Copyright & License Information
/*
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
// Not used/usable on Mono. Only used for Dotnet Core.
// Based on https://github.com/natemcmaster/DotNetCorePlugins and used under the terms of the Apache 2.0 license
#if !MONO
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
using Microsoft.Extensions.DependencyModel;
namespace OpenRA.Support
{
public class AssemblyLoader
{
readonly string mainAssembly;
readonly AssemblyLoadContext context;
public Assembly LoadDefaultAssembly() => context.LoadFromAssemblyPath(mainAssembly);
public AssemblyLoader(string assemblyFile)
{
mainAssembly = assemblyFile;
var baseDir = Path.GetDirectoryName(assemblyFile);
context = CreateLoadContext(baseDir, assemblyFile);
}
static AssemblyLoadContext CreateLoadContext(string baseDir, string assemblyFile)
{
var depsJsonFile = Path.Combine(baseDir, Path.GetFileNameWithoutExtension(assemblyFile) + ".deps.json");
var builder = new AssemblyLoadContextBuilder();
builder.TryAddDependencyContext(depsJsonFile, out _);
builder.SetBaseDirectory(baseDir);
return builder.Build();
}
}
public class AssemblyLoadContextBuilder
{
readonly Dictionary<string, ManagedLibrary> managedLibraries = new Dictionary<string, ManagedLibrary>(StringComparer.Ordinal);
readonly Dictionary<string, NativeLibrary> nativeLibraries = new Dictionary<string, NativeLibrary>(StringComparer.Ordinal);
string basePath;
public AssemblyLoadContext Build()
{
return new ManagedLoadContext(basePath, managedLibraries, nativeLibraries);
}
public AssemblyLoadContextBuilder SetBaseDirectory(string path)
{
if (string.IsNullOrEmpty(path))
throw new ArgumentException("Argument must not be null or empty.", nameof(path));
if (!Path.IsPathRooted(path))
throw new ArgumentException("Argument must be a full path.", nameof(path));
basePath = path;
return this;
}
public AssemblyLoadContextBuilder AddManagedLibrary(ManagedLibrary library)
{
managedLibraries.Add(library.Name.Name, library);
return this;
}
public AssemblyLoadContextBuilder AddNativeLibrary(NativeLibrary library)
{
ValidateRelativePath(library.AppLocalPath);
nativeLibraries.Add(library.Name, library);
return this;
}
static void ValidateRelativePath(string probingPath)
{
if (string.IsNullOrEmpty(probingPath))
throw new ArgumentException("Value must not be null or empty.", nameof(probingPath));
if (Path.IsPathRooted(probingPath))
throw new ArgumentException("Argument must be a relative path.", nameof(probingPath));
}
}
class ManagedLoadContext : AssemblyLoadContext
{
readonly string basePath;
readonly Dictionary<string, ManagedLibrary> managedAssemblies;
readonly Dictionary<string, NativeLibrary> nativeLibraries;
static readonly string[] NativeLibraryExtensions;
static readonly string[] NativeLibraryPrefixes;
static readonly string[] ManagedAssemblyExtensions =
{
".dll",
".ni.dll",
".exe",
".ni.exe"
};
static ManagedLoadContext()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
NativeLibraryPrefixes = new[] { "" };
NativeLibraryExtensions = new[] { ".dll" };
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
NativeLibraryPrefixes = new[] { "", "lib", };
NativeLibraryExtensions = new[] { ".dylib" };
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
NativeLibraryPrefixes = new[] { "", "lib" };
NativeLibraryExtensions = new[] { ".so", ".so.1" };
}
else
{
NativeLibraryPrefixes = Array.Empty<string>();
NativeLibraryExtensions = Array.Empty<string>();
}
}
public ManagedLoadContext(string baseDirectory, Dictionary<string, ManagedLibrary> managedAssemblies, Dictionary<string, NativeLibrary> nativeLibraries)
{
basePath = baseDirectory ?? throw new ArgumentNullException(nameof(baseDirectory));
this.managedAssemblies = managedAssemblies ?? throw new ArgumentNullException(nameof(managedAssemblies));
this.nativeLibraries = nativeLibraries ?? throw new ArgumentNullException(nameof(nativeLibraries));
}
protected override Assembly Load(AssemblyName assemblyName)
{
// If default context is preferred, check first for types in the default context unless the dependency has been declared as private
try
{
var defaultAssembly = Default.LoadFromAssemblyName(assemblyName);
if (defaultAssembly != null)
return null;
}
catch
{
// Swallow errors in loading from the default context
}
if (managedAssemblies.TryGetValue(assemblyName.Name, out var library) && SearchForLibrary(library, out var path))
return LoadFromAssemblyPath(path);
return null;
}
protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
{
foreach (var prefix in NativeLibraryPrefixes)
if (nativeLibraries.TryGetValue(prefix + unmanagedDllName, out var library) && SearchForLibrary(library, prefix, out var path))
return LoadUnmanagedDllFromPath(path);
return base.LoadUnmanagedDll(unmanagedDllName);
}
bool SearchForLibrary(ManagedLibrary library, out string path)
{
// 1. Search in base path
foreach (var ext in ManagedAssemblyExtensions)
{
var local = Path.Combine(basePath, library.Name.Name + ext);
if (File.Exists(local))
{
path = local;
return true;
}
}
path = null;
return false;
}
bool SearchForLibrary(NativeLibrary library, string prefix, out string path)
{
// 1. Search in base path
foreach (var ext in NativeLibraryExtensions)
{
var candidate = Path.Combine(basePath, $"{prefix}{library.Name}{ext}");
if (File.Exists(candidate))
{
path = candidate;
return true;
}
}
// 2. Search in base path + app local (for portable deployments of netcoreapp)
var local = Path.Combine(basePath, library.AppLocalPath);
if (File.Exists(local))
{
path = local;
return true;
}
path = null;
return false;
}
}
public class ManagedLibrary
{
public AssemblyName Name { get; private set; }
public static ManagedLibrary CreateFromPackage(string assetPath)
{
return new ManagedLibrary
{
Name = new AssemblyName(Path.GetFileNameWithoutExtension(assetPath))
};
}
}
public class NativeLibrary
{
public string Name { get; private set; }
public string AppLocalPath { get; private set; }
public static NativeLibrary CreateFromPackage(string assetPath)
{
return new NativeLibrary
{
Name = Path.GetFileNameWithoutExtension(assetPath),
AppLocalPath = assetPath
};
}
}
public static class DependencyContextExtensions
{
public static AssemblyLoadContextBuilder TryAddDependencyContext(this AssemblyLoadContextBuilder builder, string depsFilePath, out Exception error)
{
error = null;
try
{
builder.AddDependencyContext(depsFilePath);
}
catch (Exception ex)
{
error = ex;
}
return builder;
}
public static AssemblyLoadContextBuilder AddDependencyContext(this AssemblyLoadContextBuilder builder, string depsFilePath)
{
var reader = new DependencyContextJsonReader();
using (var file = File.OpenRead(depsFilePath))
{
var deps = reader.Read(file);
builder.SetBaseDirectory(Path.GetDirectoryName(depsFilePath));
builder.AddDependencyContext(deps);
}
return builder;
}
static string GetFallbackRid()
{
string ridBase;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
ridBase = "win10";
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
ridBase = "linux";
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
ridBase = "osx.10.12";
else
return "any";
switch (RuntimeInformation.OSArchitecture)
{
case Architecture.X86:
return ridBase + "-x86";
case Architecture.X64:
return ridBase + "-x64";
case Architecture.Arm:
return ridBase + "-arm";
case Architecture.Arm64:
return ridBase + "-arm64";
}
return ridBase;
}
public static AssemblyLoadContextBuilder AddDependencyContext(this AssemblyLoadContextBuilder builder, DependencyContext dependencyContext)
{
var ridGraph = dependencyContext.RuntimeGraph.Any()
? dependencyContext.RuntimeGraph
: DependencyContext.Default.RuntimeGraph;
var rid = Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.GetRuntimeIdentifier();
var fallbackRid = GetFallbackRid();
var fallbackGraph = ridGraph.FirstOrDefault(g => g.Runtime == rid)
?? ridGraph.FirstOrDefault(g => g.Runtime == fallbackRid)
?? new RuntimeFallbacks("any");
foreach (var managed in dependencyContext.ResolveRuntimeAssemblies(fallbackGraph))
builder.AddManagedLibrary(managed);
foreach (var native in dependencyContext.ResolveNativeAssets(fallbackGraph))
builder.AddNativeLibrary(native);
return builder;
}
static IEnumerable<ManagedLibrary> ResolveRuntimeAssemblies(this DependencyContext depContext, RuntimeFallbacks runtimeGraph)
{
var rids = GetRids(runtimeGraph);
return from library in depContext.RuntimeLibraries
from assetPath in SelectAssets(rids, library.RuntimeAssemblyGroups)
select ManagedLibrary.CreateFromPackage(assetPath);
}
static IEnumerable<NativeLibrary> ResolveNativeAssets(this DependencyContext depContext, RuntimeFallbacks runtimeGraph)
{
var rids = GetRids(runtimeGraph);
return from library in depContext.RuntimeLibraries
from assetPath in SelectAssets(rids, library.NativeLibraryGroups)
where !assetPath.EndsWith(".a", StringComparison.Ordinal)
select NativeLibrary.CreateFromPackage(assetPath);
}
static IEnumerable<string> GetRids(RuntimeFallbacks runtimeGraph)
{
return Enumerable.Concat(new[] { runtimeGraph.Runtime }, runtimeGraph?.Fallbacks ?? Enumerable.Empty<string>());
}
static IEnumerable<string> SelectAssets(IEnumerable<string> rids, IEnumerable<RuntimeAssetGroup> groups)
{
foreach (var rid in rids)
{
var group = groups.FirstOrDefault(g => g.Runtime == rid);
if (group != null)
return group.AssetPaths;
}
return groups.GetDefaultAssets();
}
}
}
#endif

View File

@@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net472</TargetFramework>
<TargetFramework Condition="'$(Mono)' == ''">net5.0</TargetFramework>
<TargetFramework Condition="'$(Mono)' != ''">netstandard2.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<UseVSHostingProcess>false</UseVSHostingProcess>
@@ -17,6 +18,8 @@
<CodeAnalysisRuleSet>..\OpenRA.ruleset</CodeAnalysisRuleSet>
<Configurations>Release;Debug</Configurations>
<AssemblyName>OpenRA</AssemblyName>
<IsPublishable Condition="'$(CopyGenericLauncher)' == 'False'">false</IsPublishable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<PropertyGroup>
<TargetPlatform Condition="$([MSBuild]::IsOsPlatform('Windows'))">win-x64</TargetPlatform>
@@ -62,4 +65,8 @@
<Analyzer Remove="@(Analyzer)" />
</ItemGroup>
</Target>
<ItemGroup>
<TrimmerRootAssembly Include="netstandard" />
<TrimmerRootAssembly Include="System.IO.Pipes" />
</ItemGroup>
</Project>

View File

@@ -32,11 +32,6 @@ namespace OpenRA.Mods.Cnc.FileFormats
public static class AudReader
{
public static byte[] LoadSound(byte[] raw, ref int index)
{
return ImaAdpcmReader.LoadImaAdpcmSound(raw, ref index);
}
public static float SoundLength(Stream s)
{
var sampleRate = s.ReadUInt16();

View File

@@ -0,0 +1,138 @@
#region Copyright & License Information
/*
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using OpenRA.FileSystem;
using OpenRA.Primitives;
namespace OpenRA.Mods.Cnc.FileSystem
{
/// <summary>
/// This class supports loading unencrypted V3 .meg files using
/// reference documentation from here https://modtools.petrolution.net/docs/MegFileFormat
/// </summary>
public class MegV3Loader : IPackageLoader
{
const uint UnencryptedMegID = 0xFFFFFFFF;
// Float value 0.99, but it is simpler to read and compare as an integer
const uint MegVersion = 0x3F7D70A4;
public bool TryParsePackage(Stream s, string filename, OpenRA.FileSystem.FileSystem context, out IReadOnlyPackage package)
{
var position = s.Position;
var id = s.ReadUInt32();
var version = s.ReadUInt32();
s.Position = position;
if (id != UnencryptedMegID || version != MegVersion)
{
package = null;
return false;
}
package = new MegFile(s, filename);
return true;
}
public sealed class MegFile : IReadOnlyPackage
{
readonly Stream s;
readonly Dictionary<string, (uint Offset, int Length)> contents = new Dictionary<string, (uint Offset, int Length)>();
public MegFile(Stream s, string filename)
{
Name = filename;
this.s = s;
var id = s.ReadUInt32();
var version = s.ReadUInt32();
if (id != UnencryptedMegID || version != MegVersion)
throw new Exception("Invalid file signature for meg file");
var headerSize = s.ReadUInt32();
var numStrings = s.ReadUInt32();
var numFiles = s.ReadUInt32();
var stringsSize = s.ReadUInt32();
var stringsStart = s.Position;
var filenames = new List<string>();
// The file names are an indexed array of strings
for (var i = 0; i < numStrings; i++)
{
var length = s.ReadUInt16();
filenames.Add(s.ReadASCII(length));
}
// The header indicates where we should be, so verify it
if (s.Position != stringsSize + stringsStart)
throw new Exception("File name table in .meg file inconsistent");
// Now we load each file entry and associated info
for (var i = 0; i < numFiles; i++)
{
// Ignore flags, crc, index
s.Position += 10;
var size = s.ReadUInt32();
var offset = s.ReadUInt32();
var nameIndex = s.ReadUInt16();
contents[filenames[nameIndex]] = (offset, (int)size);
}
if (s.Position != headerSize)
throw new Exception("Expected to be at data start offset");
}
public string Name { get; }
public IEnumerable<string> Contents => contents.Keys;
public bool Contains(string filename)
{
return contents.ContainsKey(filename);
}
public void Dispose()
{
s.Dispose();
}
public Stream GetStream(string filename)
{
// Look up the index of the filename
if (!contents.TryGetValue(filename, out var index))
return null;
return SegmentStream.CreateWithoutOwningStream(s, index.Offset, index.Length);
}
public IReadOnlyPackage OpenPackage(string filename, OpenRA.FileSystem.FileSystem context)
{
var childStream = GetStream(filename);
if (childStream == null)
return null;
if (context.TryParsePackage(childStream, filename, out var package))
return package;
childStream.Dispose();
return null;
}
}
}
}

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<LangVersion>7.3</LangVersion>
@@ -11,6 +11,7 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<CodeAnalysisRuleSet>..\OpenRA.ruleset</CodeAnalysisRuleSet>
<IsPublishable Condition="'$(CopyCncDll)' == 'False'">false</IsPublishable>
</PropertyGroup>
<ItemGroup>
<!-- Work around an issue where Rider does not detect files in the project root using the default glob -->
@@ -37,4 +38,4 @@
<Analyzer Remove="@(Analyzer)" />
</ItemGroup>
</Target>
</Project>
</Project>

View File

@@ -89,9 +89,6 @@ namespace OpenRA.Mods.Common.Widgets
var tile = world.Map.Tiles[cell];
var tileInfo = world.Map.Rules.TileSet.GetTileInfo(tile);
if (tileInfo == null)
return false;
var terrainType = world.Map.Rules.TileSet.TerrainInfo[tileInfo.TerrainType];
if (mapResources[cell].Type == ResourceType.ResourceType)

View File

@@ -0,0 +1,25 @@
#region Copyright & License Information
/*
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System;
using System.Linq;
namespace OpenRA.Mods.Common.Lint
{
public class CheckMapTiles : ILintMapPass
{
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Map map)
{
foreach (var kv in map.ReplacedInvalidTerrainTiles)
emitError("Cell {0} references invalid terrain tile {1}.".F(kv.Key, kv.Value));
}
}
}

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<LangVersion>7.3</LangVersion>
@@ -11,6 +11,7 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<CodeAnalysisRuleSet>..\OpenRA.ruleset</CodeAnalysisRuleSet>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
<!-- Work around an issue where Rider does not detect files in the project root using the default glob -->
@@ -24,6 +25,7 @@
<ProjectReference Include="..\OpenRA.Game\OpenRA.Game.csproj">
<Private>False</Private>
</ProjectReference>
<PackageReference Include="Microsoft.Win32.Registry" Version="4.7.0" />
<PackageReference Include="OpenRA-FuzzyLogicLibrary" Version="1.0.1" />
<PackageReference Include="DiscordRichPresence" Version="1.0.150" />
<PackageReference Include="rix0rrr.BeaconLib" Version="1.0.2" />

View File

@@ -13,6 +13,7 @@ using System;
using System.Collections.Generic;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BeaconLib;
using OpenRA.Network;
using OpenRA.Server;
@@ -107,7 +108,7 @@ namespace OpenRA.Mods.Common.Server
{
isBusy = true;
Action a = () =>
Task.Run(() =>
{
try
{
@@ -160,9 +161,7 @@ namespace OpenRA.Mods.Common.Server
}
isBusy = false;
};
a.BeginInvoke(null, null);
});
}
}
}

View File

@@ -30,7 +30,7 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Chance (out of 100) the unit has to enter panic mode when attacking.")]
public readonly int AttackPanicChance = 20;
[Desc("The terrain types that this actor should avoid running on to while panicing.")]
[Desc("The terrain types that this actor should avoid running on to while panicking.")]
public readonly HashSet<string> AvoidTerrainTypes = new HashSet<string>();
[SequenceReference(prefix: true)]

View File

@@ -12,6 +12,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
@@ -58,15 +59,19 @@ namespace OpenRA.Mods.Common.Traits
[NotificationReference("Speech")]
public readonly string LeaveNotification = null;
public override object Create(ActorInitializer init) { return new MissionObjectives(init.World, this); }
public override object Create(ActorInitializer init) { return new MissionObjectives(init.Self.Owner, this); }
}
public class MissionObjectives : INotifyWinStateChanged, ISync, IResolveOrder
public class MissionObjectives : INotifyWinStateChanged, ISync, IResolveOrder, IWorldLoaded
{
public readonly MissionObjectivesInfo Info;
readonly List<MissionObjective> objectives = new List<MissionObjective>();
readonly Player player;
public ReadOnlyList<MissionObjective> Objectives;
Player[] enemies;
Player[] allies;
[Sync]
public int ObjectivesHash
{
@@ -83,12 +88,21 @@ namespace OpenRA.Mods.Common.Traits
// The player's WinState is only updated when his allies have all completed their objective as well.
public WinState WinStateCooperative { get; private set; }
public MissionObjectives(World world, MissionObjectivesInfo info)
public MissionObjectives(Player player, MissionObjectivesInfo info)
{
Info = info;
this.player = player;
Objectives = new ReadOnlyList<MissionObjective>(objectives);
}
void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr)
{
// Players and NonCombatants are fixed once the game starts, but the result of IsAlliedWith
// may change once players are marked as spectators, so cache these
allies = player.World.Players.Where(p => !p.NonCombatant && player.IsAlliedWith(p)).ToArray();
enemies = player.World.Players.Where(p => !p.NonCombatant && player.RelationshipWith(p) == PlayerRelationship.Enemy).ToArray();
}
public int Add(Player player, string description, string type, bool required = true, bool inhibitAnnouncement = false)
{
var newID = objectives.Count;
@@ -140,10 +154,9 @@ namespace OpenRA.Mods.Common.Traits
void CheckIfGameIsOver(Player player)
{
var players = player.World.Players.Where(p => !p.NonCombatant);
var gameOver = players.All(p => p.WinState != WinState.Undefined || !p.HasObjectives);
var gameOver = player.World.Players.All(p => p.NonCombatant || p.WinState != WinState.Undefined || !p.HasObjectives);
if (gameOver)
{
Game.RunAfterDelay(Info.GameOverDelay, () =>
{
if (!Game.IsCurrentWorld(player.World))
@@ -153,17 +166,14 @@ namespace OpenRA.Mods.Common.Traits
player.World.SetPauseState(true);
player.World.PauseStateLocked = true;
});
}
}
void INotifyWinStateChanged.OnPlayerWon(Player player)
{
var players = player.World.Players.Where(p => !p.NonCombatant);
var enemies = players.Where(p => !p.IsAlliedWith(player));
if (Info.Cooperative)
{
WinStateCooperative = WinState.Won;
var allies = players.Where(p => p.IsAlliedWith(player));
if (allies.All(p => p.PlayerActor.Trait<MissionObjectives>().WinStateCooperative == WinState.Won))
{
@@ -193,13 +203,9 @@ namespace OpenRA.Mods.Common.Traits
void INotifyWinStateChanged.OnPlayerLost(Player player)
{
var players = player.World.Players.Where(p => !p.NonCombatant);
var enemies = players.Where(p => !p.IsAlliedWith(player));
if (Info.Cooperative)
{
WinStateCooperative = WinState.Lost;
var allies = players.Where(p => p.IsAlliedWith(player));
if (allies.Any(p => p.PlayerActor.Trait<MissionObjectives>().WinStateCooperative == WinState.Lost))
{

View File

@@ -100,7 +100,8 @@ namespace OpenRA.Mods.Common.Traits
if (++ticksIdle % info.ReduceMoveRadiusDelay == 0)
effectiveMoveRadius--;
return null; // We'll be back the next tick; better to sit idle for a few seconds than prolong this tick indefinitely with a loop
// We'll be back the next tick; better to sit idle for a few seconds than prolong this tick indefinitely with a loop
return null;
}
if (info.AvoidTerrainTypes.Count > 0)

View File

@@ -78,10 +78,7 @@ namespace OpenRA.Mods.Common.Traits
for (var x = 0; x < TerrainTemplate.Size.X; x++)
{
var tile = new TerrainTile(TerrainTemplate.Id, (byte)i++);
var tileInfo = world.Map.Rules.TileSet.GetTileInfo(tile);
// Empty tile
if (tileInfo == null)
if (!world.Map.Rules.TileSet.TryGetTileInfo(tile, out var tileInfo))
continue;
var sprite = wr.Theater.TileSprite(tile, 0);

View File

@@ -104,6 +104,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
" for (var j = 0; j < ctx.canvas.height / 4; j++)",
" for (var i = j % 2; i < ctx.canvas.width / 4; i += 2)",
" ctx.fillRect(4 * i, 4 * j, 4, 4);",
" ctx.imageSmoothingEnabled = false;",
" ctx.drawImage(image, 0, 0, c.width, c.height);",
" ctx.strokeStyle = \"#ffff00\";",
" ctx.lineWidth = 1;",

View File

@@ -81,10 +81,7 @@ namespace OpenRA.Mods.Common.Widgets
for (var x = 0; x < Template.Size.X; x++)
{
var tile = new TerrainTile(Template.Id, (byte)(i++));
var tileInfo = tileset.GetTileInfo(tile);
// Empty tile
if (tileInfo == null)
if (!tileset.TryGetTileInfo(tile, out var tileInfo))
continue;
var sprite = worldRenderer.Theater.TileSprite(tile, 0);

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<LangVersion>7.3</LangVersion>
@@ -11,6 +11,7 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<CodeAnalysisRuleSet>..\OpenRA.ruleset</CodeAnalysisRuleSet>
<IsPublishable Condition="'$(CopyD2kDll)' == 'False'">false</IsPublishable>
</PropertyGroup>
<ItemGroup>
<!-- Work around an issue where Rider does not detect files in the project root using the default glob -->
@@ -37,4 +38,4 @@
<Analyzer Remove="@(Analyzer)" />
</ItemGroup>
</Target>
</Project>
</Project>

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<LangVersion>7.3</LangVersion>
@@ -11,6 +11,7 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<CodeAnalysisRuleSet>..\OpenRA.ruleset</CodeAnalysisRuleSet>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<PropertyGroup>
<TargetPlatform Condition="$([MSBuild]::IsOsPlatform('Windows'))">win-x64</TargetPlatform>

View File

@@ -59,7 +59,6 @@ namespace OpenRA.Platforms.Default
Name = "ThreadedGraphicsContext RenderThread",
IsBackground = true
};
renderThread.SetApartmentState(ApartmentState.STA);
lock (syncObject)
{
// Start and wait for the rendering thread to have initialized before returning.

View File

@@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net472</TargetFramework>
<TargetFramework Condition="'$(Mono)' == ''">net5.0</TargetFramework>
<TargetFramework Condition="'$(Mono)' != ''">netstandard2.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<UseVSHostingProcess>false</UseVSHostingProcess>
@@ -39,4 +40,8 @@
<Analyzer Remove="@(Analyzer)" />
</ItemGroup>
</Target>
<ItemGroup>
<TrimmerRootAssembly Include="netstandard" />
<TrimmerRootAssembly Include="System.IO.Pipes" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>7.3</LangVersion>
<DebugSymbols>true</DebugSymbols>
@@ -10,6 +10,7 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<CodeAnalysisRuleSet>..\OpenRA.ruleset</CodeAnalysisRuleSet>
<IsPublishable>false</IsPublishable>
</PropertyGroup>
<ItemGroup>
<!-- Work around an issue where Rider does not detect files in the project root using the default glob -->
@@ -22,14 +23,12 @@
<ItemGroup>
<ProjectReference Include="..\OpenRA.Game\OpenRA.Game.csproj" />
<ProjectReference Include="..\OpenRA.Mods.Common\OpenRA.Mods.Common.csproj">
<Private>False</Private>
<Private>True</Private>
</ProjectReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit.Console" Version="3.11.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0-beta.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
<AdditionalFiles Include="../stylecop.json" />
@@ -40,4 +39,4 @@
<Analyzer Remove="@(Analyzer)" />
</ItemGroup>
</Target>
</Project>
</Project>

View File

@@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net472</TargetFramework>
<TargetFramework Condition="'$(Mono)' == ''">net5.0</TargetFramework>
<TargetFramework Condition="'$(Mono)' != ''">netstandard2.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<UseVSHostingProcess>false</UseVSHostingProcess>
@@ -39,4 +40,8 @@
<Analyzer Remove="@(Analyzer)" />
</ItemGroup>
</Target>
<ItemGroup>
<TrimmerRootAssembly Include="netstandard" />
<TrimmerRootAssembly Include="System.IO.Pipes" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>winexe</OutputType>
<TargetFramework>net472</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<ApplicationIcon>$(LauncherIcon)</ApplicationIcon>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<UseVSHostingProcess>false</UseVSHostingProcess>
@@ -10,14 +12,12 @@
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>
<OutputPath>../bin</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<PlatformTarget>AnyCPU</PlatformTarget>
<ExternalConsole>false</ExternalConsole>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<CodeAnalysisRuleSet>..\OpenRA.ruleset</CodeAnalysisRuleSet>
<Configurations>Release;Debug</Configurations>
<AssemblyName>$(LauncherName)</AssemblyName>
<ApplicationIcon>$(LauncherIcon)</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<!-- Work around an issue where Rider does not detect files in the project root using the default glob -->
@@ -58,4 +58,8 @@
<Analyzer Remove="@(Analyzer)" />
</ItemGroup>
</Target>
<ItemGroup>
<TrimmerRootAssembly Include="netstandard" />
<TrimmerRootAssembly Include="System.IO.Pipes" />
</ItemGroup>
</Project>

View File

@@ -58,9 +58,7 @@ Global
{FE6C8CC0-2F07-442A-B29F-17617B3B7FC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE6C8CC0-2F07-442A-B29F-17617B3B7FC6}.Release|Any CPU.Build.0 = Release|Any CPU
{6CB8E1B7-6B36-4D93-8633-7C573E194AC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6CB8E1B7-6B36-4D93-8633-7C573E194AC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6CB8E1B7-6B36-4D93-8633-7C573E194AC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CB8E1B7-6B36-4D93-8633-7C573E194AC4}.Release|Any CPU.Build.0 = Release|Any CPU
{54DAE0E0-3125-49D3-992E-A0E931EB5FC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54DAE0E0-3125-49D3-992E-A0E931EB5FC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54DAE0E0-3125-49D3-992E-A0E931EB5FC8}.Release|Any CPU.ActiveCfg = Release|Any CPU

View File

@@ -25,7 +25,7 @@ ShareAnonymizedIPs="${ShareAnonymizedIPs:-"True"}"
SupportDir="${SupportDir:-""}"
while true; do
mono --debug bin/OpenRA.Server.exe Engine.EngineDir=".." Game.Mod="$Mod" \
mono --debug bin/OpenRA.Server.dll Engine.EngineDir=".." Game.Mod="$Mod" \
Server.Name="$Name" \
Server.ListenPort="$ListenPort" \
Server.AdvertiseOnline="$AdvertiseOnline" \

View File

@@ -25,7 +25,7 @@ then
fi
# Launch the engine with the appropriate arguments
mono bin/OpenRA.exe Engine.EngineDir=".." Engine.LaunchPath="$MODLAUNCHER" $MODARG "$@"
mono --debug bin/OpenRA.dll Engine.EngineDir=".." Engine.LaunchPath="$MODLAUNCHER" $MODARG "$@"
# Show a crash dialog if something went wrong
if [ $? != 0 ] && [ $? != 1 ]; then

View File

@@ -10,7 +10,7 @@ function All-Command
return
}
dotnet build /p:Configuration=Release /nologo
dotnet build -c Release --nologo -p:TargetPlatform=win-x64
if ($lastexitcode -ne 0)
{
Write-Host "Build failed. If just the development tools failed to build, try installing Visual Studio. You may also still be able to run the game." -ForegroundColor Red
@@ -111,7 +111,7 @@ function Test-Command
function Check-Command
{
Write-Host "Compiling in debug configuration..." -ForegroundColor Cyan
dotnet build /p:Configuration=Debug /nologo
dotnet build -c Debug --nologo -p:TargetPlatform=win-x64
if ($lastexitcode -ne 0)
{
Write-Host "Build failed." -ForegroundColor Red

View File

@@ -366,23 +366,18 @@ scrollpanel-decorations:
Inherits: ^Chrome
Regions:
down: 836, 17, 16, 16
down-pressed: 836, 17, 16, 16
down-disabled: 853, 17, 16, 16
up: 870, 17, 16, 16
up-pressed: 870, 17, 16, 16
up-disabled: 887, 17, 16, 16
right: 904, 17, 16, 16
right-pressed: 904, 17, 16, 16
right-disabled: 921, 17, 16, 16
left: 938, 17, 16, 16
left-pressed: 938, 17, 16, 16
left-disabled: 955, 17, 16, 16
dropdown-decorations:
Inherits: ^Chrome
Regions:
marker: 836, 17, 16, 16
marker-pressed: 836, 17, 16, 16
marker-disabled: 853, 17, 16, 16
dropdown-separators:

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -558,23 +558,18 @@ scrollpanel-decorations:
Inherits: ^Glyphs
Regions:
down: 68, 17, 16, 16
down-pressed: 68, 17, 16, 16
down-disabled: 85, 17, 16, 16
up: 102, 17, 16, 16
up-pressed: 102, 17, 16, 16
up-disabled: 119, 17, 16, 16
right: 136, 17, 16, 16
right-pressed: 136, 17, 16, 16
right-disabled: 153, 17, 16, 16
left: 170, 17, 16, 16
left-pressed: 170, 17, 16, 16
left-disabled: 187, 17, 16, 16
dropdown-decorations:
Inherits: ^Glyphs
Regions:
marker: 68, 17, 16, 16
marker-pressed: 68, 17, 16, 16
marker-disabled: 85, 17, 16, 16
dropdown-separators:

View File

@@ -58,7 +58,7 @@ CreateKosygin = function()
Media.PlaySpeechNotification(Greece, "ObjectiveMet")
local kosygin = Actor.Create(KosyginType, true, { Location = KosyginSpawnPoint.Location, Owner = Greece })
Trigger.OnKilled(kosygin, RescueFailed)
ExtractObjective = Greece.AddPrimaryObjective("Extract Kosygin and\nget him back to your base.")
ExtractObjective = Greece.AddObjective("Extract Kosygin and\nget him back to your base.")
Trigger.AfterDelay(DateTime.Seconds(1), function() Media.PlaySpeechNotification(Greece, "TargetFreed") end)
end
@@ -168,9 +168,9 @@ WorldLoaded = function()
Greece = Player.GetPlayer("Greece")
USSR = Player.GetPlayer("USSR")
Camera.Position = DefaultCameraPosition.CenterPosition
UseSpyObjective = Greece.AddPrimaryObjective("Infiltrate the Soviet command center and\ncontact Kosygin.")
KosyginSurviveObjective = Greece.AddPrimaryObjective("Kosygin must survive.")
USSRObj = USSR.AddPrimaryObjective("Eliminate all Allied forces.")
UseSpyObjective = Greece.AddObjective("Infiltrate the Soviet command center and\ncontact Kosygin.")
KosyginSurviveObjective = Greece.AddObjective("Kosygin must survive.")
USSRObj = USSR.AddObjective("Eliminate all Allied forces.")
Trigger.OnPlayerLost(Greece, MissionFailed)
Trigger.OnPlayerWon(Greece, MissionAccomplished)
InitialAlliedReinforcements()

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,309 @@
MapFormat: 11
RequiresMod: ra
Title: Oil Spill
Author: Super Newbie
Tileset: DESERT
MapSize: 120,120
Bounds: 1,1,118,118
Visibility: Lobby
Categories: Minigame
Players:
PlayerReference@Neutral:
Name: Neutral
OwnsWorld: True
NonCombatant: True
Faction: england
PlayerReference@Creeps:
Name: Creeps
NonCombatant: True
Faction: england
Enemies: Multi0, Multi1, Multi2, Multi3
PlayerReference@Multi0:
Name: Multi0
Playable: True
AllowBots: False
LockFaction: True
Faction: allies
Enemies: Creeps
PlayerReference@Multi1:
Name: Multi1
Playable: True
AllowBots: False
LockFaction: True
Faction: allies
Enemies: Creeps
PlayerReference@Multi2:
Name: Multi2
Playable: True
AllowBots: False
LockFaction: True
Faction: allies
Enemies: Creeps
PlayerReference@Multi3:
Name: Multi3
Playable: True
AllowBots: False
LockFaction: True
Faction: allies
Enemies: Creeps
Actors:
Actor1: rock1
Owner: Neutral
Location: 112,21
Actor2: tc01
Owner: Neutral
Location: 50,4
Actor3: tc01
Owner: Neutral
Location: 117,23
Actor4: tc01
Owner: Neutral
Location: 115,31
Actor5: tc01
Owner: Neutral
Location: 113,13
Actor6: tc01
Owner: Neutral
Location: 108,3
Actor7: v37
Owner: Neutral
Location: 66,3
Actor8: v30
Owner: Neutral
Location: 69,2
Actor9: v31
Owner: Neutral
Location: 48,3
Actor10: v24
Owner: Neutral
Location: 46,3
Actor12: v24
Owner: Neutral
Location: 117,102
Actor13: tc01
Owner: Neutral
Location: 94,116
Actor14: tc01
Owner: Neutral
Location: 102,111
Actor15: t08
Owner: Neutral
Location: 105,4
Actor18: rock6
Owner: Neutral
Location: 15,114
Actor19: rock7
Owner: Neutral
Location: 41,112
Actor20: rock6
Owner: Neutral
Location: 74,113
Actor21: tc01
Owner: Neutral
Location: 31,113
Actor22: tc01
Owner: Neutral
Location: 62,113
Actor23: t08
Owner: Neutral
Location: 74,112
Actor24: v25
Owner: Neutral
Location: 116,99
Actor26: tc01
Owner: Neutral
Location: 3,30
Actor25: tc01
Owner: Neutral
Location: 4,36
Actor27: rock2
Owner: Neutral
Location: 5,81
Actor28: v21
Owner: Neutral
Location: 3,88
Actor29: v30
Owner: Neutral
Location: 2,91
Actor30: t08
Owner: Neutral
Location: 5,41
Actor31: tc01
Owner: Neutral
Location: 72,34
Actor32: t08
Owner: Neutral
Location: 71,34
Actor33: tc01
Owner: Neutral
Location: 82,44
Actor36: oilb
Owner: Neutral
Location: 51,51
Actor37: oilb
Owner: Neutral
Location: 67,51
Actor38: oilb
Owner: Neutral
Location: 51,67
Actor39: oilb
Owner: Neutral
Location: 67,67
Actor44: oilb
Owner: Neutral
Location: 46,82
Actor45: oilb
Owner: Neutral
Location: 36,72
Actor46: oilb
Owner: Neutral
Location: 72,82
Actor47: oilb
Owner: Neutral
Location: 36,46
Actor48: oilb
Owner: Neutral
Location: 46,36
Actor49: oilb
Owner: Neutral
Location: 82,46
Actor50: oilb
Owner: Neutral
Location: 72,36
Actor53: oilb
Owner: Neutral
Location: 59,34
Actor54: oilb
Owner: Neutral
Location: 34,59
Actor55: oilb
Owner: Neutral
Location: 59,84
Actor56: oilb
Owner: Neutral
Location: 84,59
OilBottomLeft2: oilb
Location: 18,96
Owner: Neutral
OilBottomLeft1: oilb
Location: 22,100
Owner: Neutral
OilBottomRight2: oilb
Owner: Neutral
Location: 96,100
OilBottomRight1: oilb
Owner: Neutral
Location: 100,96
OilTopLeft2: oilb
Owner: Neutral
Location: 22,18
OilTopLeft1: oilb
Owner: Neutral
Location: 18,22
OilTopRight2: oilb
Location: 100,22
Owner: Neutral
OilTopRight1: oilb
Location: 96,18
Owner: Neutral
Actor65: fcom
Owner: Neutral
Location: 48,96
Actor69: fcom
Owner: Neutral
Location: 70,96
Actor70: fcom
Owner: Neutral
Location: 22,70
Actor72: fcom
Owner: Neutral
Location: 22,48
Actor73: fcom
Owner: Neutral
Location: 48,22
Actor71: fcom
Owner: Neutral
Location: 70,22
Actor74: fcom
Owner: Neutral
Location: 96,48
Actor75: fcom
Owner: Neutral
Location: 96,70
Actor77: oilb
Owner: Neutral
Location: 82,72
Actor80: oilb
Owner: Neutral
Location: 46,20
Actor81: oilb
Owner: Neutral
Location: 72,20
Actor82: oilb
Owner: Neutral
Location: 46,98
Actor83: oilb
Owner: Neutral
Location: 72,98
Actor84: oilb
Owner: Neutral
Location: 20,72
Actor85: oilb
Owner: Neutral
Location: 20,46
Actor86: oilb
Owner: Neutral
Location: 98,46
Actor87: oilb
Owner: Neutral
Location: 98,72
OilTopLeft3: oilb
Owner: Neutral
Location: 29,29
OilBottomLeft3: oilb
Location: 29,89
Owner: Neutral
OilTopRight3: oilb
Location: 89,29
Owner: Neutral
OilBottomRight3: oilb
Owner: Neutral
Location: 89,89
Spawn0: mpspawn
Owner: Neutral
Location: 31,31
Spawn1: mpspawn
Owner: Neutral
Location: 87,31
Spawn2: mpspawn
Owner: Neutral
Location: 31,87
Spawn3: mpspawn
Owner: Neutral
Location: 87,87
FCOMTopLeft: fcom
Owner: Neutral
Location: 31,31
FCOMTopRight: fcom
Owner: Neutral
Location: 87,31
FCOMBottomLeft: fcom
Owner: Neutral
Location: 31,87
FCOMBottomRight: fcom
Owner: Neutral
Location: 87,87
Rules: rules.yaml
Sequences: sequences.yaml

View File

@@ -0,0 +1,27 @@
--[[
Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
This file is part of OpenRA, which is free software. It is made
available to you under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version. For more
information, see COPYING.
]]
SpawnBuildings =
{
{ FCOMTopLeft, OilTopLeft1, OilTopLeft2, OilTopLeft3 },
{ FCOMTopRight, OilTopRight1, OilTopRight2, OilTopRight3 },
{ FCOMBottomLeft, OilBottomLeft1, OilBottomLeft2, OilBottomLeft3 },
{ FCOMBottomRight, OilBottomRight1, OilBottomRight2, OilBottomRight3 },
}
WorldLoaded = function()
for i = 0, 4 do
local player = Player.GetPlayer("Multi" .. i)
if player then
Utils.Do(SpawnBuildings[player.Spawn], function(actor)
actor.Owner = player
end)
end
end
end

View File

@@ -0,0 +1,215 @@
World:
LuaScript:
Scripts: oil-spill.lua
SpawnMPUnits:
DropdownVisible: False
MPStartUnits@mcvonly:
BaseActor: fcom
FCOM:
MustBeDestroyed:
RequiredForShortGame: true
Power:
Amount: 50
Health:
HP: 110000
Production:
Produces: Building, Defense
RepairableBuilding:
RepairStep: 700
PlayerExperience: 25
RepairingNotification: Repairing
WithBuildingRepairDecoration:
Image: allyrepair
Sequence: repair
Position: Center
Palette: player
IsPlayerPalette: True
ProductionBar@Building:
ProductionType: Building
ProductionBar@Defense:
ProductionType: Defense
Color: 8A8A8A
BaseBuilding:
ProvidesPrerequisite@buildingname:
OILB:
CashTrickler:
Interval: 250
Amount: 100
SpawnActorOnDeath:
Actor: OILB.Husk
OwnerType: InternalName
OILB.Husk:
Inherits: ^TechBuilding
Inherits@shape: ^2x2Shape
Selectable:
Priority: 0
Bounds: 48,48
CapturableProgressBar:
CapturableProgressBlink:
Building:
Footprint: xx xx
Dimensions: 2,2
Tooltip:
Name: Husk (Oil Derrick)
CaptureManager:
Capturable:
Types: building-husk
TransformOnCapture:
IntoActor: OILB
ForceHealthPercentage: 50
Targetable:
TargetTypes: building-husk
E6:
Captures@husk:
RequiresCondition: !global-reusable-engineers
CaptureTypes: building-husk
PlayerExperience: 25
CaptureDelay: 200
EnterCursor: goldwrench
Captures@husk-reusable:
RequiresCondition: global-reusable-engineers
CaptureTypes: building-husk
PlayerExperience: 25
CaptureDelay: 375
EnterCursor: goldwrench
ConsumedByCapture: False
WEAP:
Buildable:
Prerequisites: ~disabled
PROC:
Buildable:
Prerequisites: ~disabled
SILO:
Buildable:
Prerequisites: ~disabled
BRIK:
Buildable:
Prerequisites: ~disabled
POWR:
Power:
Amount: 125
-SpawnActorsOnSell:
-MustBeDestroyed:
APWR:
Power:
Amount: 250
-SpawnActorsOnSell:
-MustBeDestroyed:
TENT:
Buildable:
Prerequisites: fcom
-SpawnActorsOnSell:
-MustBeDestroyed:
DOME:
Buildable:
Prerequisites: anypower
-SpawnActorsOnSell:
-MustBeDestroyed:
SYRD:
Buildable:
Prerequisites: fcom
-MustBeDestroyed:
SPEN:
Buildable:
Prerequisites: fcom
-MustBeDestroyed:
STEK:
Buildable:
Prerequisites: dome, tent
-SpawnActorsOnSell:
-MustBeDestroyed:
AFLD:
Buildable:
Prerequisites: dome
-SpawnActorsOnSell:
-MustBeDestroyed:
AirstrikePower@spyplane:
Prerequisites: afld
AirstrikePower@parabombs:
Prerequisites: afld
HPAD:
Buildable:
Prerequisites: dome
-SpawnActorsOnSell:
-MustBeDestroyed:
FIX:
Buildable:
Prerequisites: dome
-SpawnActorsOnSell:
-MustBeDestroyed:
IRON:
Buildable:
Prerequisites: stek
PDOX:
Buildable:
Prerequisites: atek
ChronoshiftPower@chronoshift:
-Prerequisites:
-ChronoshiftPower@advancedchronoshift:
ATEK:
Buildable:
Prerequisites: dome, tent
-SpawnActorsOnSell:
-MustBeDestroyed:
FTUR:
Buildable:
Prerequisites: tent
-SpawnActorsOnSell:
GUN:
Buildable:
Prerequisites: tent
-SpawnActorsOnSell:
GAP:
Buildable:
Prerequisites: atek
-SpawnActorsOnSell:
AGUN:
Buildable:
Prerequisites: dome
-SpawnActorsOnSell:
TSLA:
Buildable:
Prerequisites: dome
-SpawnActorsOnSell:
MECH:
Buildable:
Prerequisites: dome
E1:
Buildable:
Prerequisites: ~disabled
E3:
Buildable:
Prerequisites: ~disabled
E7:
Buildable:
Prerequisites: ~disabled

View File

@@ -0,0 +1,4 @@
oilb.husk: oilb
idle: oilb
Start: 1
Offset: 0,-6

Binary file not shown.

Binary file not shown.

View File

@@ -680,23 +680,18 @@ scrollpanel-decorations:
Inherits: ^Glyphs
Regions:
down: 68, 17, 16, 16
down-pressed: 68, 17, 16, 16
down-disabled: 85, 17, 16, 16
up: 102, 17, 16, 16
up-pressed: 102, 17, 16, 16
up-disabled: 119, 17, 16, 16
right: 136, 17, 16, 16
right-pressed: 136, 17, 16, 16
right-disabled: 153, 17, 16, 16
left: 170, 17, 16, 16
left-pressed: 170, 17, 16, 16
left-disabled: 187, 17, 16, 16
dropdown-decorations:
Inherits: ^Glyphs
Regions:
marker: 68, 17, 16, 16
marker-pressed: 68, 17, 16, 16
marker-disabled: 85, 17, 16, 16
dropdown-separators:

View File

@@ -1,6 +1,3 @@
[[prereqs]]
name = "net-4.7.2"
[[actions]]
os = "windows"
name = "Red Alert"

View File

@@ -18,7 +18,6 @@
# Makefile (install target for local installs and downstream packaging)
# Linux AppImage packaging
# macOS packaging
# Windows packaging
# Mod SDK Linux AppImage packaging
# Mod SDK macOS packaging
# Mod SDK Windows packaging
@@ -33,26 +32,27 @@ install_assemblies_mono() {
echo "Building assemblies"
ORIG_PWD=$(pwd)
cd "${SRC_PATH}" || exit 1
msbuild -verbosity:m -nologo -t:Clean
rm -rf "${SRC_PATH}/OpenRA."*/obj
rm -rf "${SRC_PATH:?}/bin"
msbuild -verbosity:m -nologo -t:Build -restore -p:Configuration=Release -p:TargetPlatform="${TARGETPLATFORM}"
msbuild -verbosity:m -nologo -t:Build -restore -p:Configuration=Release -p:TargetPlatform="${TARGETPLATFORM}" -p:Mono=true -p:DefineConstants="MONO"
if [ "${TARGETPLATFORM}" = "unix-generic" ]; then
./configure-system-libraries.sh
fi
./fetch-geoip.sh
cd "${ORIG_PWD}" || exit 1
echo "Installing engine to ${DEST_PATH}"
install -d "${DEST_PATH}"
# Core engine
install -m755 "${SRC_PATH}/bin/OpenRA.Server.exe" "${DEST_PATH}"
install -m755 "${SRC_PATH}/bin/OpenRA.Utility.exe" "${DEST_PATH}"
install -m755 "${SRC_PATH}/bin/OpenRA.Server.dll" "${DEST_PATH}"
install -m755 "${SRC_PATH}/bin/OpenRA.Utility.dll" "${DEST_PATH}"
install -m644 "${SRC_PATH}/bin/OpenRA.Game.dll" "${DEST_PATH}"
install -m644 "${SRC_PATH}/bin/OpenRA.Platforms.Default.dll" "${DEST_PATH}"
if [ "${COPY_GENERIC_LAUNCHER}" = "True" ]; then
install -m755 "${SRC_PATH}/bin/OpenRA.exe" "${DEST_PATH}"
install -m755 "${SRC_PATH}/bin/OpenRA.dll" "${DEST_PATH}"
fi
# Mod dlls
@@ -97,6 +97,32 @@ install_assemblies_mono() {
fi
}
# Compile and publish the core engine and specified mod assemblies to the target directory
# Arguments:
# SRC_PATH: Path to the root OpenRA directory
# DEST_PATH: Path to the root of the install destination (will be created if necessary)
# TARGETPLATFORM: Platform type (win-x86, win-x64, osx-x64, linux-x64, unix-generic)
# COPY_GENERIC_LAUNCHER: If set to True the OpenRA.exe will also be copied (True, False)
# COPY_CNC_DLL: If set to True the OpenRA.Mods.Cnc.dll will also be copied (True, False)
# COPY_D2K_DLL: If set to True the OpenRA.Mods.D2k.dll will also be copied (True, False)
# Used by:
# Windows packaging
install_assemblies() {
SRC_PATH="${1}"
DEST_PATH="${2}"
TARGETPLATFORM="${3}"
COPY_GENERIC_LAUNCHER="${4}"
COPY_CNC_DLL="${5}"
COPY_D2K_DLL="${6}"
ORIG_PWD=$(pwd)
cd "${SRC_PATH}" || exit 1
dotnet publish -c Release -p:TargetPlatform="${TARGETPLATFORM}" -p:PublishTrimmed=true -p:CopyGenericLauncher="${COPY_GENERIC_LAUNCHER}" -p:CopyCncDll="${COPY_CNC_DLL}" -p:CopyD2kDll="${COPY_D2K_DLL}" -r "${TARGETPLATFORM}" -o "${DEST_PATH}"
cd "${ORIG_PWD}" || exit 1
}
# Copy the core engine and specified mod data to the target directory
# Arguments:
# SRC_PATH: Path to the root OpenRA directory
@@ -115,6 +141,8 @@ install_data() {
DEST_PATH="${2}"
shift 2
"${SRC_PATH}"/fetch-geoip.sh
echo "Installing engine files to ${DEST_PATH}"
for FILE in VERSION AUTHORS COPYING IP2LOCATION-LITE-DB1.IPV6.BIN.ZIP "global mix database.dat"; do
install -m644 "${SRC_PATH}/${FILE}" "${DEST_PATH}"
@@ -160,20 +188,15 @@ install_windows_launcher()
MOD_ID="${4}"
LAUNCHER_NAME="${5}"
MOD_NAME="${6}"
ICON_PATH="${7}"
FAQ_URL="${8}"
FAQ_URL="${7}"
msbuild -verbosity:m -nologo -t:Clean "${SRC_PATH}/OpenRA.WindowsLauncher/OpenRA.WindowsLauncher.csproj"
rm -rf "${SRC_PATH:?}/bin"
msbuild -t:Build "${SRC_PATH}/OpenRA.WindowsLauncher/OpenRA.WindowsLauncher.csproj" -restore -p:Configuration=Release -p:TargetPlatform="${TARGETPLATFORM}" -p:LauncherName="${LAUNCHER_NAME}" -p:LauncherIcon="${ICON_PATH}" -p:ModID="${MOD_ID}" -p:DisplayName="${MOD_NAME}" -p:FaqUrl="${FAQ_URL}"
install -m755 "${SRC_PATH}/bin/${LAUNCHER_NAME}.exe" "${DEST_PATH}"
install -m644 "${SRC_PATH}/bin/${LAUNCHER_NAME}.exe.config" "${DEST_PATH}"
rm -rf "${SRC_PATH}/OpenRA.WindowsLauncher/obj"
dotnet publish "${SRC_PATH}/OpenRA.WindowsLauncher/OpenRA.WindowsLauncher.csproj" -c Release -r "${TARGETPLATFORM}" -p:LauncherName="${LAUNCHER_NAME}" -p:TargetPlatform="${TARGETPLATFORM}" -p:ModID="${MOD_ID}" -p:DisplayName="${MOD_NAME}" -p:FaqUrl="${FAQ_URL}" -o "${DEST_PATH}"
# Enable the full 4GB address space for the 32 bit game executable
# The server and utility do not use enough memory to need this
if [ "${TARGETPLATFORM}" = "win-x86" ]; then
python3 "${SRC_PATH}/packaging/windows/MakeLAA.py" "${DEST_PATH}/${LAUNCHER_NAME}.exe"
fi
# NET 5 is unable to customize the application host for windows when compiling from Linux,
# so we must patch the properties we need in the PE header.
# Setting the application icon requires an external tool, so is left to the calling code
python3 "${SRC_PATH}/packaging/windows/fixlauncher.py" "${DEST_PATH}/${LAUNCHER_NAME}.exe"
}
# Write a version string to the engine VERSION file

View File

@@ -2,43 +2,15 @@
HERE="$(dirname "$(readlink -f "${0}")")"
# Stash original environment values so they can be restored
# when switching to other mods using restore-environment
export OPENRA_ORIG_PATH="${PATH}"
export OPENRA_ORIG_XDG_DATA_DIRS="${XDG_DATA_DIRS}"
export OPENRA_ORIG_DYLD_LIBRARY_PATH="${DYLD_LIBRARY_PATH}"
export OPENRA_ORIG_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}"
export OPENRA_ORIG_MONO_PATH="${MONO_PATH}"
export OPENRA_ORIG_MONO_CFG_DIR="${MONO_CFG_DIR}"
export OPENRA_ORIG_MONO_CONFIG="${MONO_CONFIG}"
# Override runtime paths to use bundled mono and shared libraries
export PATH="${HERE}/usr/bin:${PATH}"
export XDG_DATA_DIRS="${HERE}/usr/share:${XDG_DATA_DIRS}"
export DYLD_LIBRARY_PATH="${HERE}/usr/lib:${DYLD_LIBRARY_PATH}"
export LD_LIBRARY_PATH="${HERE}/usr/lib:${LD_LIBRARY_PATH}"
export MONO_PATH="${HERE}/usr/lib/mono/4.5"
export MONO_CFG_DIR="${HERE}/etc"
export MONO_CONFIG="${HERE}/etc/mono/config"
# Update/create the mono certificate store to enable https web queries
if [ -f "/etc/pki/tls/certs/ca-bundle.crt" ]; then
mono "${HERE}/usr/lib/mono/4.5/cert-sync.exe" --quiet --user /etc/pki/tls/certs/ca-bundle.crt
elif [ -f "/etc/ssl/certs/ca-certificates.crt" ]; then
mono "${HERE}/usr/lib/mono/4.5/cert-sync.exe" --quiet --user /etc/ssl/certs/ca-certificates.crt
else
echo "WARNING: Unable to sync system certificate store - https requests will fail"
fi
# Run the game or server
if [ -n "$1" ] && [ "$1" = "--server" ]; then
# Drop the --server argument
shift
exec "openra-{MODID}-server" "$@"
"${HERE}/usr/bin/openra-{MODID}-server" "$@"
elif [ -n "$1" ] && [ "$1" = "--utility" ]; then
# Drop the --utility argument
shift
exec "openra-{MODID}-utility" "$@"
"${HERE}/usr/bin/openra-{MODID}-utility" "$@"
else
exec "openra-{MODID}" "$@"
"${HERE}/usr/bin/openra-{MODID}" "$@"
fi

View File

@@ -2,11 +2,10 @@
# OpenRA packaging script for Linux (AppImage)
set -e
command -v make >/dev/null 2>&1 || { echo >&2 "Linux packaging requires make."; exit 1; }
command -v tar >/dev/null 2>&1 || { echo >&2 "Linux packaging requires tar."; exit 1; }
command -v curl >/dev/null 2>&1 || command -v wget > /dev/null 2>&1 || { echo >&2 "Linux packaging requires curl or wget."; exit 1; }
DEPENDENCIES_TAG="20200328"
DEPENDENCIES_TAG="20201222"
if [ $# -eq "0" ]; then
echo "Usage: $(basename "$0") version [outputdir]"
@@ -20,7 +19,6 @@ cd "$(dirname "$0")" || exit 1
TAG="$1"
OUTPUTDIR="$2"
SRCDIR="$(pwd)/../.."
BUILTDIR="$(pwd)/build"
ARTWORK_DIR="$(pwd)/../artwork/"
UPDATE_CHANNEL=""
@@ -44,30 +42,16 @@ if [ ! -d "${OUTPUTDIR}" ]; then
fi
# Add native libraries
echo "Downloading dependencies"
echo "Downloading appimagetool"
if command -v curl >/dev/null 2>&1; then
curl -s -L -O https://github.com/OpenRA/AppImageSupport/releases/download/${DEPENDENCIES_TAG}/mono.tar.bz2 || exit 3
curl -s -L -O https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage || exit 3
else
wget -cq https://github.com/OpenRA/AppImageSupport/releases/download/${DEPENDENCIES_TAG}/mono.tar.bz2 || exit 3
wget -cq https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage || exit 3
fi
# travis-ci doesn't support mounting FUSE filesystems so extract and run the contents manually
chmod a+x appimagetool-x86_64.AppImage
./appimagetool-x86_64.AppImage --appimage-extract
echo "Building AppImage"
mkdir "${BUILTDIR}"
tar xf mono.tar.bz2 -C "${BUILTDIR}"
chmod 0755 "${BUILTDIR}/usr/bin/mono"
chmod 0644 "${BUILTDIR}/etc/mono/config"
chmod 0644 "${BUILTDIR}/etc/mono/4.5/machine.config"
chmod 0644 "${BUILTDIR}/usr/lib/mono/4.5/Facades/"*.dll
chmod 0644 "${BUILTDIR}/usr/lib/mono/4.5/"*.dll "${BUILTDIR}/usr/lib/mono/4.5/"*.exe
chmod 0755 "${BUILTDIR}/usr/lib/"*.so
rm -rf mono.tar.bz2
echo "Building AppImages"
build_appimage() {
MOD_ID=${1}
@@ -76,14 +60,12 @@ build_appimage() {
APPDIR="$(pwd)/${MOD_ID}.appdir"
APPIMAGE="OpenRA-$(echo "${DISPLAY_NAME}" | sed 's/ /-/g')${SUFFIX}-x86_64.AppImage"
cp -r "${BUILTDIR}" "${APPDIR}"
IS_D2K="False"
if [ "${MOD_ID}" = "d2k" ]; then
IS_D2K="True"
fi
install_assemblies_mono "${SRCDIR}" "${APPDIR}/usr/lib/openra" "linux-x64" "True" "True" "${IS_D2K}"
install_assemblies "${SRCDIR}" "${APPDIR}/usr/lib/openra" "linux-x64" "True" "True" "${IS_D2K}"
install_data "${SRCDIR}" "${APPDIR}/usr/lib/openra" "${MOD_ID}"
set_engine_version "${TAG}" "${APPDIR}/usr/lib/openra"
set_mod_version "${TAG}" "${APPDIR}/usr/lib/openra/mods/${MOD_ID}/mod.yaml" "${APPDIR}/usr/lib/openra/mods/modcontent/mod.yaml"
@@ -114,6 +96,7 @@ build_appimage() {
fi
done
mkdir -p "${APPDIR}/usr/bin"
sed "s/{MODID}/${MOD_ID}/g" openra.appimage.in | sed "s/{TAG}/${TAG}/g" | sed "s/{MODNAME}/${DISPLAY_NAME}/g" > "${APPDIR}/usr/bin/openra-${MOD_ID}"
chmod 0755 "${APPDIR}/usr/bin/openra-${MOD_ID}"
@@ -124,14 +107,13 @@ build_appimage() {
chmod 0755 "${APPDIR}/usr/bin/openra-${MOD_ID}-utility"
install -m 0755 gtk-dialog.py "${APPDIR}/usr/bin/gtk-dialog.py"
install -m 0755 restore-environment.sh "${APPDIR}/usr/bin/restore-environment.sh"
# Embed update metadata if (and only if) compiled on GitHub Actions
if [ -n "${GITHUB_REPOSITORY}" ]; then
ARCH=x86_64 ./squashfs-root/AppRun --no-appstream -u "zsync|https://master.openra.net/appimagecheck?mod=${MOD_ID}&channel=${UPDATE_CHANNEL}" "${APPDIR}" "${OUTPUTDIR}/${APPIMAGE}"
ARCH=x86_64 ./appimagetool-x86_64.AppImage --no-appstream -u "zsync|https://master.openra.net/appimagecheck?mod=${MOD_ID}&channel=${UPDATE_CHANNEL}" "${APPDIR}" "${OUTPUTDIR}/${APPIMAGE}"
zsyncmake -u "https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}/${APPIMAGE}" -o "${OUTPUTDIR}/${APPIMAGE}.zsync" "${OUTPUTDIR}/${APPIMAGE}"
else
ARCH=x86_64 ./squashfs-root/AppRun --no-appstream "${APPDIR}" "${OUTPUTDIR}/${APPIMAGE}"
ARCH=x86_64 ./appimagetool-x86_64.AppImage --no-appstream "${APPDIR}" "${OUTPUTDIR}/${APPIMAGE}"
fi
rm -rf "${APPDIR}"
@@ -142,4 +124,4 @@ build_appimage "cnc" "Tiberian Dawn" "699223250181292033"
build_appimage "d2k" "Dune 2000" "712711732770111550"
# Clean up
rm -rf appimagetool-x86_64.AppImage squashfs-root "${BUILTDIR}"
rm -rf appimagetool-x86_64.AppImage "${BUILTDIR}"

View File

@@ -2,4 +2,4 @@
HERE="$(dirname "$(readlink -f "${0}")")"
cd "${HERE}/../lib/openra" || exit 1
mono --debug OpenRA.Server.exe Game.Mod="{MODID}" "$@"
./OpenRA.Server Game.Mod="{MODID}" "$@"

View File

@@ -1,4 +1,4 @@
#!/bin/sh
cd "{GAME_INSTALL_DIR}"
mono {DEBUG} OpenRA.Server.exe Game.Mod={MODID} "$@"
mono {DEBUG} OpenRA.Server.dll Game.Mod={MODID} "$@"

View File

@@ -2,4 +2,4 @@
# OpenRA.Utility relies on keeping the original working directory, so don't change directory
HERE="$(dirname "$(readlink -f "${0}")")"
mono --debug "${HERE}/../lib/openra/OpenRA.Utility.exe" {MODID} "$@"
"${HERE}/../lib/openra/OpenRA.Utility" {MODID} "$@"

View File

@@ -35,7 +35,7 @@ fi
# Run the game
export SDL_VIDEO_X11_WMCLASS="openra-{MODID}-{TAG}"
mono --debug OpenRA.exe Game.Mod={MODID} Engine.LaunchPath="${LAUNCHER}" Engine.LaunchWrapper="${HERE}/restore-environment.sh" "${JOIN_SERVER}" "$@"
./OpenRA Game.Mod={MODID} Engine.LaunchPath="${LAUNCHER}" "${JOIN_SERVER}" "$@"
# Show a crash dialog if something went wrong
if [ $? != 0 ] && [ $? != 1 ]; then

View File

@@ -9,7 +9,7 @@ if [ "${1#${PROTOCOL_PREFIX}}" != "${1}" ]; then
fi
# Run the game
mono {DEBUG} OpenRA.exe Game.Mod={MODID} Engine.LaunchPath="{BIN_DIR}/openra-{MODID}" "${JOIN_SERVER}" "$@"
mono {DEBUG} OpenRA.dll Game.Mod={MODID} Engine.LaunchPath="{BIN_DIR}/openra-{MODID}" "${JOIN_SERVER}" "$@"
# Show a crash dialog if something went wrong
if [ $? != 0 ] && [ $? != 1 ]; then

View File

@@ -1,26 +0,0 @@
#!/bin/sh
# Restore the environment variables that were set by AppRun
export PATH="${OPENRA_ORIG_PATH}"
export XDG_DATA_DIRS="${OPENRA_ORIG_XDG_DATA_DIRS}"
export DYLD_LIBRARY_PATH="${OPENRA_ORIG_DYLD_LIBRARY_PATH}"
export LD_LIBRARY_PATH="${OPENRA_ORIG_LD_LIBRARY_PATH}"
unset OPENRA_ORIG_PATH OPENRA_ORIG_XDG_DATA_DIRS OPENRA_ORIG_DYLD_LIBRARY_PATH OPENRA_ORIG_LD_LIBRARY_PATH
unset MONO_PATH MONO_CFG_DIR MONO_CONFIG
if [ -n "${OPENRA_ORIG_MONO_PATH}" ]; then
export MONO_PATH="${OPENRA_ORIG_MONO_PATH}"
fi
if [ -n "${OPENRA_ORIG_MONO_CFG_DIR}" ]; then
export MONO_CFG_DIR="${OPENRA_ORIG_MONO_CFG_DIR}"
fi
if [ -n "${OPENRA_ORIG_MONO_CONFIG}" ]; then
export MONO_CONFIG="${OPENRA_ORIG_MONO_CONFIG}"
fi
unset SDL_VIDEO_X11_WMCLASS OPENRA_ORIG_MONO_PATH OPENRA_ORIG_MONO_CFG_DIR OPENRA_ORIG_MONO_CONFIG
# Run the given command
exec "$@"

View File

@@ -7,7 +7,7 @@
<key>CFBundleDisplayName</key>
<string>{MOD_NAME}</string>
<key>CFBundleExecutable</key>
<string>OpenRA</string>
<string>Launcher</string>
<key>CFBundleIconFile</key>
<string>{MOD_ID}.icns</string>
<key>CFBundleIdentifier</key>

View File

@@ -15,7 +15,7 @@
#
set -e
MONO_TAG="osx-launcher-20200830"
MONO_TAG="osx-launcher-20201222"
if [ $# -ne "2" ]; then
echo "Usage: $(basename "$0") tag outputdir"
@@ -55,13 +55,15 @@ modify_plist() {
# Copies the game files and sets metadata
build_app() {
TEMPLATE_DIR="${1}"
LAUNCHER_DIR="${2}"
MOD_ID="${3}"
MOD_NAME="${4}"
DISCORD_APPID="${5}"
PLATFORM="${1}"
TEMPLATE_DIR="${2}"
LAUNCHER_DIR="${3}"
MOD_ID="${4}"
MOD_NAME="${5}"
DISCORD_APPID="${6}"
LAUNCHER_CONTENTS_DIR="${LAUNCHER_DIR}/Contents"
LAUNCHER_ASSEMBLY_DIR="${LAUNCHER_CONTENTS_DIR}/MacOS"
LAUNCHER_RESOURCES_DIR="${LAUNCHER_CONTENTS_DIR}/Resources"
cp -r "${TEMPLATE_DIR}" "${LAUNCHER_DIR}"
@@ -72,7 +74,12 @@ build_app() {
fi
# Install engine and mod files
install_assemblies_mono "${SRCDIR}" "${LAUNCHER_RESOURCES_DIR}" "osx-x64" "True" "True" "${IS_D2K}"
if [ "${PLATFORM}" = "compat" ]; then
install_assemblies_mono "${SRCDIR}" "${LAUNCHER_ASSEMBLY_DIR}" "osx-x64" "True" "True" "${IS_D2K}"
else
install_assemblies "${SRCDIR}" "${LAUNCHER_ASSEMBLY_DIR}" "osx-x64" "True" "True" "${IS_D2K}"
fi
install_data "${SRCDIR}" "${LAUNCHER_RESOURCES_DIR}" "${MOD_ID}"
set_engine_version "${TAG}" "${LAUNCHER_RESOURCES_DIR}"
set_mod_version "${TAG}" "${LAUNCHER_RESOURCES_DIR}/mods/${MOD_ID}/mod.yaml" "${LAUNCHER_RESOURCES_DIR}/mods/modcontent/mod.yaml"
@@ -99,7 +106,6 @@ build_app() {
# Sign binaries with developer certificate
if [ -n "${MACOS_DEVELOPER_IDENTITY}" ]; then
codesign -s "${MACOS_DEVELOPER_IDENTITY}" --timestamp --options runtime -f --entitlements entitlements.plist "${LAUNCHER_RESOURCES_DIR}/"*.dylib
codesign -s "${MACOS_DEVELOPER_IDENTITY}" --timestamp --options runtime -f --entitlements entitlements.plist --deep "${LAUNCHER_DIR}"
fi
}
@@ -120,23 +126,15 @@ build_platform() {
if [ "${PLATFORM}" = "compat" ]; then
modify_plist "{MINIMUM_SYSTEM_VERSION}" "10.9" "${TEMPLATE_DIR}/Contents/Info.plist"
clang -m64 launcher-mono.m -o "${TEMPLATE_DIR}/Contents/MacOS/OpenRA" -framework AppKit -mmacosx-version-min=10.9
clang -m64 launcher-mono.m -o "${TEMPLATE_DIR}/Contents/MacOS/Launcher" -framework AppKit -mmacosx-version-min=10.9
else
modify_plist "{MINIMUM_SYSTEM_VERSION}" "10.13" "${TEMPLATE_DIR}/Contents/Info.plist"
clang -m64 launcher.m -o "${TEMPLATE_DIR}/Contents/MacOS/OpenRA" -framework AppKit -mmacosx-version-min=10.13
curl -s -L -O https://github.com/OpenRA/OpenRALauncherOSX/releases/download/${MONO_TAG}/mono.zip || exit 3
unzip -qq -d "${BUILTDIR}/mono" mono.zip
mv "${BUILTDIR}/mono/mono" "${TEMPLATE_DIR}/Contents/MacOS/"
mv "${BUILTDIR}/mono/etc" "${TEMPLATE_DIR}/Contents/Resources"
mv "${BUILTDIR}/mono/lib" "${TEMPLATE_DIR}/Contents/Resources"
rm mono.zip
rmdir "${BUILTDIR}/mono"
clang -m64 launcher.m -o "${TEMPLATE_DIR}/Contents/MacOS/Launcher" -framework AppKit -mmacosx-version-min=10.13
fi
build_app "${TEMPLATE_DIR}" "${BUILTDIR}/OpenRA - Red Alert.app" "ra" "Red Alert" "699222659766026240"
build_app "${TEMPLATE_DIR}" "${BUILTDIR}/OpenRA - Tiberian Dawn.app" "cnc" "Tiberian Dawn" "699223250181292033"
build_app "${TEMPLATE_DIR}" "${BUILTDIR}/OpenRA - Dune 2000.app" "d2k" "Dune 2000" "712711732770111550"
build_app "${PLATFORM}" "${TEMPLATE_DIR}" "${BUILTDIR}/OpenRA - Red Alert.app" "ra" "Red Alert" "699222659766026240"
build_app "${PLATFORM}" "${TEMPLATE_DIR}" "${BUILTDIR}/OpenRA - Tiberian Dawn.app" "cnc" "Tiberian Dawn" "699223250181292033"
build_app "${PLATFORM}" "${TEMPLATE_DIR}" "${BUILTDIR}/OpenRA - Dune 2000.app" "d2k" "Dune 2000" "712711732770111550"
rm -rf "${TEMPLATE_DIR}"
@@ -183,6 +181,25 @@ build_platform() {
SetFile -c icnC "/Volumes/OpenRA/.VolumeIcon.icns"
SetFile -a C "/Volumes/OpenRA"
# Replace duplicate .NET runtime files with hard links to improve compression
if [ "${PLATFORM}" != "compat" ]; then
OIFS="$IFS"
IFS=$'\n'
for MOD in "Red Alert" "Tiberian Dawn"; do
for f in $(find /Volumes/OpenRA/OpenRA\ -\ ${MOD}.app/Contents/MacOS/*); do
g="/Volumes/OpenRA/OpenRA - Dune 2000.app/Contents/MacOS/"$(basename "${f}")
hashf=$(shasum "${f}" | awk '{ print $1 }')
hashg=$(shasum "${g}" | awk '{ print $1 }')
if [ "${hashf}" = "${hashg}" ]; then
echo "Deduplicating ${f}"
rm "${f}"
ln "${g}" "${f}"
fi
done
done
IFS="$OIFS"
fi
chmod -Rf go-w /Volumes/OpenRA
sync
sync
@@ -200,7 +217,7 @@ notarize_package() {
sudo xcode-select -r
# Create a temporary read-only dmg for submission (notarization service rejects read/write images)
hdiutil convert "${DMG_PATH}" -format UDZO -imagekey zlib-level=9 -ov -o "${NOTARIZE_DMG_PATH}"
hdiutil convert "${DMG_PATH}" -format ULFO -ov -o "${NOTARIZE_DMG_PATH}"
NOTARIZATION_UUID=$(xcrun altool --notarize-app --primary-bundle-id "net.openra.packaging" -u "${MACOS_DEVELOPER_USERNAME}" -p "${MACOS_DEVELOPER_PASSWORD}" --file "${NOTARIZE_DMG_PATH}" 2>&1 | awk -F' = ' '/RequestUUID/ { print $2; exit }')
if [ -z "${NOTARIZATION_UUID}" ]; then
@@ -242,10 +259,17 @@ notarize_package() {
}
finalize_package() {
INPUT_PATH="${1}"
OUTPUT_PATH="${2}"
PLATFORM="${1}"
INPUT_PATH="${2}"
OUTPUT_PATH="${3}"
if [ "${PLATFORM}" = "compat" ]; then
hdiutil convert "${INPUT_PATH}" -format UDZO -imagekey zlib-level=9 -ov -o "${OUTPUT_PATH}"
else
# ULFO offers better compression and faster decompression speeds, but is only supported by 10.11+
hdiutil convert "${INPUT_PATH}" -format ULFO -ov -o "${OUTPUT_PATH}"
fi
hdiutil convert "${INPUT_PATH}" -format UDZO -imagekey zlib-level=9 -ov -o "${OUTPUT_PATH}"
rm "${INPUT_PATH}"
}
@@ -263,5 +287,5 @@ if [ -n "${MACOS_DEVELOPER_USERNAME}" ] && [ -n "${MACOS_DEVELOPER_PASSWORD}" ];
wait
fi
finalize_package "build.dmg" "${OUTPUTDIR}/OpenRA-${TAG}.dmg"
finalize_package "build-compat.dmg" "${OUTPUTDIR}/OpenRA-${TAG}-compat.dmg"
finalize_package "standard" "build.dmg" "${OUTPUTDIR}/OpenRA-${TAG}.dmg"
finalize_package "compat" "build-compat.dmg" "${OUTPUTDIR}/OpenRA-${TAG}-compat.dmg"

View File

@@ -238,7 +238,7 @@ static int check_mono_version(const char *version, const char *req_version)
[self exitWithMonoPrompt];
// Default values - can be overriden by setting certain keys Info.plist
NSString *gameName = @"OpenRA.exe";
NSString *gameName = @"OpenRA.dll";
NSString *modId = nil;
NSDictionary *plist = [[NSBundle mainBundle] infoDictionary];
@@ -262,8 +262,9 @@ static int check_mono_version(const char *version, const char *req_version)
NSMutableArray *launchArgs = [NSMutableArray arrayWithCapacity: [gameArgs count] + 2];
[launchArgs addObject: @"--debug"];
[launchArgs addObject: [gamePath stringByAppendingPathComponent: gameName]];
[launchArgs addObject: [exePath stringByAppendingPathComponent: gameName]];
[launchArgs addObject: [NSString stringWithFormat:@"Engine.LaunchPath=\"%@\"", engineLaunchPath]];
[launchArgs addObject: [NSString stringWithFormat:@"Engine.EngineDir=../Resources"]];
if (modId)
[launchArgs addObject: [NSString stringWithFormat:@"Game.Mod=%@", modId]];

View File

@@ -131,16 +131,11 @@ NSTask *gameTask;
launched = YES;
// Default values - can be overriden by setting certain keys Info.plist
NSString *gameName = @"OpenRA.exe";
NSString *modId = nil;
NSDictionary *plist = [[NSBundle mainBundle] infoDictionary];
if (plist)
{
NSString *exeValue = [plist objectForKey:@"MonoGameExe"];
if (exeValue && [exeValue length] > 0)
gameName = exeValue;
NSString *modIdValue = [plist objectForKey:@"ModId"];
if (modIdValue && [modIdValue length] > 0)
modId = modIdValue;
@@ -149,21 +144,20 @@ NSTask *gameTask;
NSString *exePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent: @"Contents/MacOS/"];
NSString *gamePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent: @"Contents/Resources/"];
NSString *launchPath = [exePath stringByAppendingPathComponent: @"mono"];
NSString *appPath = [exePath stringByAppendingPathComponent: @"OpenRA"];
NSString *launchPath = [exePath stringByAppendingPathComponent: @"OpenRA"];
NSString *appPath = [exePath stringByAppendingPathComponent: @"Launcher"];
NSString *engineLaunchPath = [self resolveTranslocatedPath: appPath];
NSMutableArray *launchArgs = [NSMutableArray arrayWithCapacity: [gameArgs count] + 2];
[launchArgs addObject: @"--debug"];
[launchArgs addObject: [gamePath stringByAppendingPathComponent: gameName]];
[launchArgs addObject: [NSString stringWithFormat:@"Engine.LaunchPath=\"%@\"", engineLaunchPath]];
[launchArgs addObject: [NSString stringWithFormat:@"Engine.EngineDir=../Resources"]];
if (modId)
[launchArgs addObject: [NSString stringWithFormat:@"Game.Mod=%@", modId]];
[launchArgs addObjectsFromArray: gameArgs];
NSLog(@"Running mono with arguments:");
NSLog(@"Running OpenRA with arguments:");
for (size_t i = 0; i < [launchArgs count]; i++)
NSLog(@"%@", [launchArgs objectAtIndex: i]);
@@ -172,12 +166,6 @@ NSTask *gameTask;
[gameTask setLaunchPath: launchPath];
[gameTask setArguments: launchArgs];
NSMutableDictionary *environment = [NSMutableDictionary dictionaryWithDictionary: [[NSProcessInfo processInfo] environment]];
[environment setObject: [gamePath stringByAppendingPathComponent: @"lib/mono/4.5"] forKey: @"MONO_PATH"];
[environment setObject: [gamePath stringByAppendingPathComponent: @"etc"] forKey: @"MONO_CFG_DIR"];
[environment setObject: [gamePath stringByAppendingPathComponent: @"etc/mono/config"] forKey: @"MONO_CONFIG"];
[gameTask setEnvironment: environment];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(taskExited:)

View File

@@ -129,14 +129,16 @@ Section "Game" GAME
SetOutPath "$INSTDIR"
File "${SRCDIR}\*.exe"
File "${SRCDIR}\*.exe.config"
File "${SRCDIR}\*.dll.config"
File "${SRCDIR}\*.dll"
File "${SRCDIR}\*.ico"
File "${SRCDIR}\*.deps.json"
File "${SRCDIR}\*.runtimeconfig.json"
File "${SRCDIR}\global mix database.dat"
File "${SRCDIR}\IP2LOCATION-LITE-DB1.IPV6.BIN.ZIP"
File "${SRCDIR}\VERSION"
File "${SRCDIR}\AUTHORS"
File "${SRCDIR}\COPYING"
File "${SRCDIR}\global mix database.dat"
File "${SRCDIR}\IP2LOCATION-LITE-DB1.IPV6.BIN.ZIP"
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
@@ -162,6 +164,7 @@ Section "Game" GAME
SetShellVarContext all
CreateDirectory "$APPDATA\OpenRA\ModMetadata"
SetOutPath "$INSTDIR"
nsExec::ExecToLog '"$INSTDIR\OpenRA.Utility.exe" ra --register-mod "$INSTDIR\RedAlert.exe" system'
nsExec::ExecToLog '"$INSTDIR\OpenRA.Utility.exe" ra --clear-invalid-mod-registrations system'
nsExec::ExecToLog '"$INSTDIR\OpenRA.Utility.exe" cnc --register-mod "$INSTDIR\TiberianDawn.exe" system'
@@ -182,21 +185,6 @@ Section "Desktop Shortcut" DESKTOPSHORTCUT
"$INSTDIR\Dune2000.exe" "" "" "" ""
SectionEnd
;***************************
;Dependency Sections
;***************************
Section "-DotNet" DotNet
ClearErrors
; https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed
ReadRegDWORD $0 HKLM "SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" "Release"
IfErrors error 0
IntCmp $0 461808 done error done
error:
MessageBox MB_OK ".NET Framework v4.7.2 or later is required to run OpenRA."
Abort
done:
SectionEnd
;***************************
;Uninstaller Sections
;***************************
@@ -225,14 +213,17 @@ Function ${UN}Clean
RMDir /r $INSTDIR\glsl
RMDir /r $INSTDIR\lua
Delete $INSTDIR\*.exe
Delete $INSTDIR\*.exe.config
Delete $INSTDIR\*.dll
Delete $INSTDIR\*.ico
Delete $INSTDIR\*.dll.config
Delete $INSTDIR\*.deps.json
Delete $INSTDIR\*.runtimeconfig.json
Delete $INSTDIR\VERSION
Delete $INSTDIR\AUTHORS
Delete $INSTDIR\COPYING
Delete "$INSTDIR\global mix database.dat"
Delete $INSTDIR\IP2LOCATION-LITE-DB1.IPV6.BIN.ZIP
RMDir /r $INSTDIR\Support
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenRA${SUFFIX}"

View File

@@ -32,6 +32,12 @@ elif [[ ${TAG} == playtest* ]]; then
SUFFIX=" (playtest)"
fi
if command -v curl >/dev/null 2>&1; then
curl -s -L -O https://github.com/electron/rcedit/releases/download/v1.1.1/rcedit-x64.exe || exit 3
else
wget -cq https://github.com/electron/rcedit/releases/download/v1.1.1/rcedit-x64.exe || exit 3
fi
function makelauncher()
{
LAUNCHER_NAME="${1}"
@@ -40,7 +46,9 @@ function makelauncher()
PLATFORM="${4}"
convert "${ARTWORK_DIR}/${MOD_ID}_16x16.png" "${ARTWORK_DIR}/${MOD_ID}_24x24.png" "${ARTWORK_DIR}/${MOD_ID}_32x32.png" "${ARTWORK_DIR}/${MOD_ID}_48x48.png" "${ARTWORK_DIR}/${MOD_ID}_256x256.png" "${BUILTDIR}/${MOD_ID}.ico"
install_windows_launcher "${SRCDIR}" "${BUILTDIR}" "win-${PLATFORM}" "${MOD_ID}" "${LAUNCHER_NAME}" "${DISPLAY_NAME}" "${BUILTDIR}/${MOD_ID}.ico" "${FAQ_URL}"
install_windows_launcher "${SRCDIR}" "${BUILTDIR}" "win-${PLATFORM}" "${MOD_ID}" "${LAUNCHER_NAME}" "${DISPLAY_NAME}" "${FAQ_URL}"
wine64 rcedit-x64.exe "${BUILTDIR}/${LAUNCHER_NAME}.exe" --set-icon "${BUILTDIR}/${MOD_ID}.ico"
}
function build_platform()
@@ -54,7 +62,7 @@ function build_platform()
USE_PROGRAMFILES32=""
fi
install_assemblies_mono "${SRCDIR}" "${BUILTDIR}" "win-${PLATFORM}" "False" "True" "True"
install_assemblies "${SRCDIR}" "${BUILTDIR}" "win-${PLATFORM}" "False" "True" "True"
install_data "${SRCDIR}" "${BUILTDIR}" "cnc" "d2k" "ra"
set_engine_version "${TAG}" "${BUILTDIR}"
set_mod_version "${TAG}" "${BUILTDIR}/mods/cnc/mod.yaml" "${BUILTDIR}/mods/d2k/mod.yaml" "${BUILTDIR}/mods/ra/mod.yaml" "${BUILTDIR}/mods/modcontent/mod.yaml"

View File

@@ -9,11 +9,21 @@ import struct
import sys
if __name__ == "__main__":
print(sys.argv[1] + ': Enabling /LARGEADDRESSAWARE')
print('Patching ' + sys.argv[1] + ':')
with open(sys.argv[1], 'r+b') as assembly:
assembly.seek(0x3c)
peOffset = struct.unpack('i', assembly.read(4))[0]
peOffset = struct.unpack('H', assembly.read(2))[0]
assembly.seek(peOffset)
peSignature = struct.unpack('I', assembly.read(4))[0]
if peSignature != 0x4550:
print(" ERROR: Invalid PE signature")
print(' - Setting /LARGEADDRESSAWARE')
assembly.seek(peOffset + 4 + 18)
flags = struct.unpack('B', assembly.read(1))[0] | 0x20
assembly.seek(peOffset + 4 + 18)
assembly.write(struct.pack('B', flags))
print(' - Setting /subsystem:windows')
assembly.seek(peOffset + 0x5C)
assembly.write(struct.pack("H", 0x02))

View File

@@ -1,2 +1,2 @@
#!/bin/sh
ENGINE_DIR=.. mono --debug bin/OpenRA.Utility.exe $@
ENGINE_DIR=.. mono --debug bin/OpenRA.Utility.dll $@