Compare commits

..

49 Commits

Author SHA1 Message Date
Paul Chote
65fc9af8b5 Revert "Update macOS launcher template to osx-launcher-20180723."
This reverts commit 904c3afc4d.
2018-09-22 19:00:42 +02:00
abcdefg30
dc8c8b9fb5 Disable the restart button on dedicated servers 2018-09-22 15:45:32 +01:00
abcdefg30
968c5b7fba Make the menu widget readonly 2018-09-22 15:45:25 +01:00
Paul Chote
086938b812 Revert RA Grenadier explosion DamageSource. 2018-09-13 17:12:07 +02:00
SoScared
c1bd98626b Fix d2k bots not excluding harvesters from squads 2018-09-13 17:05:17 +02:00
SoScared
6a50c156dd Enable airfield for AI as Ukraine 2018-09-10 03:46:31 +01:00
abcdefg30
20aca08fa2 Remove the CodeAnalysisRuleSet property from all csproj files 2018-08-25 22:06:22 +02:00
Paul Chote
78929ab311 Make SetupLatencyWidget consistent with SetupProfileWidget. 2018-08-25 22:06:00 +02:00
Paul Chote
06946b3a10 Don't crash when mousing over a bot as a non-admin. 2018-08-25 22:05:47 +02:00
Paul Chote
424bf012a7 Ignore malformed orders instead of crashing. 2018-08-25 18:27:46 +02:00
rtri
8c173dc870 fix threadedRenderer context creation logic 2018-08-23 01:50:28 +02:00
Paul Chote
14b286291f Add requires-auth indicator to the server lists. 2018-08-18 17:02:03 +02:00
Paul Chote
c4de10a974 Give server operators more control over client validation. 2018-08-18 17:01:45 +02:00
Paul Chote
518bbed9dc Sync auth information with the master server. 2018-08-18 17:01:31 +02:00
Paul Chote
4236e52c25 Revert "Re-active Edge-Scrolling for inverted Mouse-Scrolling"
This reverts commit c4867d4030.
2018-08-18 16:55:47 +02:00
Paul Chote
79fe31530e Add Engine.SupportDir argument. 2018-08-17 21:06:18 +02:00
Paul Chote
fbb31720c2 Ensure that TLS 1.2 is enabled for web downloads. 2018-08-16 19:59:43 +02:00
Mustafa Alperen Seki
f8e9692fa6 Fix GivesExperienceModifier not working 2018-08-16 19:49:28 +02:00
Paul Chote
772344ea02 Add a hard requirement on the cert-sync utility.
This tool is required to sync the certificates
used for https queries. This also has a side-effect
of prompting the mono-complete package on Mint,
which pulls in other required but missing packages.
2018-08-15 21:23:19 +01:00
Paul Chote
ce979a16dc Fix the Chronoshift-return cancellation bug. 2018-08-15 21:20:22 +01:00
Paul Chote
6fd99fdd4a Kill chronoshifted actors if the return-to-origin fails. 2018-08-15 21:20:18 +01:00
Paul Chote
d0ebe02cbb Remove IPreventsTeleport interface.
MadTank is changed to use conditions instead.
This has a side-benefit of disabling the move
cursor while deployed.
2018-08-15 21:20:14 +01:00
Paul Chote
f36c7bbca1 Make Chronoshiftable conditional. 2018-08-15 21:20:09 +01:00
Paul Chote
5c98973b6d Fix a typo in ChronosphereProperties class name. 2018-08-15 21:20:03 +01:00
reaperrr
115567f67f Fix husks not updating targetable positions on teleport
This should have checked for IPositionableInfo to begin with.

Husk already implements IPositionable, so implementing *Info as well
makes sense, even if it only serves to exclude it from
ITargetablePositions caching for now.
2018-08-14 17:27:06 +01:00
Paul Chote
15400cad3b Revert "Add "Restart" button for multiplayer replays"
This reverts commit 3a377a572c.
2018-08-12 19:08:14 +02:00
Smittytron
cbc33b91a7 Revert ranger change and dial back missile sub damage 2018-08-11 22:58:04 +02:00
Paul Chote
2d9bb75cbb Fix badge label padding. 2018-08-11 22:57:36 +02:00
abcdefg30
d3be09b60a Remove RA95Launcher.exe from the IDFiles of the origin ra install 2018-08-11 22:54:27 +02:00
abcdefg30
0985e12777 Remove CNC95Launcher.exe from the IDFiles of the origin cnc and ra installs 2018-08-11 22:54:09 +02:00
Paul Chote
510757cb2e Add EnabledByDefault check to WithInfantryBody. 2018-08-11 14:34:57 +02:00
Paul Chote
cccced6709 Add missing EnabledByDefault checks to WithSpriteBodyInfo subclasses. 2018-08-11 14:34:43 +02:00
abcdefg30
3cf09a7a18 Revert "Add conyard.corrino"
This reverts commit bdaff27656.
2018-08-10 21:04:41 +02:00
abcdefg30
ce3df9d859 Revert "Limit D2K Palace SWs to their Faction's Palaces'"
This reverts commit d110b9c648.
2018-08-10 21:04:41 +02:00
abcdefg30
4fd0d047a0 Resolve conflicts between actor and API names (Radar) 2018-08-10 20:50:25 +02:00
Oliver Brakmann
de0ccf8769 Fix issueing superfluous difficulty lobby command from mission browser 2018-08-09 20:07:31 +01:00
Smittytron
a152e526e5 Fix death sequences of Chan, Einstein, and Delphi 2018-08-05 13:12:33 +02:00
reaperrr
1e3545c6f3 Fix AI idle harvester management
This was broken because our default mods now list `harv` under `ExcludeFromSquads`, which prevents them from being added to `activeUnits`.
2018-08-04 22:30:51 +02:00
reaperrr
3c4f19d855 Some HackyAI cleanups
- harvManager.Tick should run after FindNewUnits() in case new harvesters have appeared
- moved the FindNewUnits Mcv and ExcludeFromSquads checks to the foreach loop, for better readability and preparation of the idle harvester fix
2018-08-04 22:30:40 +02:00
Paul Chote
8220f4122a Hide the Ready checkbox when a spectator transfers away Admin. 2018-08-04 22:17:16 +02:00
Paul Chote
f4dc0aa0f4 Clear selection when a text field's contents is changed programatically. 2018-08-04 20:35:20 +02:00
Paul Chote
1ebb16e418 Fix missing profile indicator for spectators. 2018-08-04 20:25:29 +02:00
Paul Chote
9395f0c672 Disable the threaded renderer on Windows.
A DisableWindowsRenderThread graphics setting is
added to allow players to optionally reenable it.
2018-08-04 20:15:05 +02:00
reaperrr
999b998329 Fix tree owners in TD (for real this time) 2018-08-04 19:07:42 +01:00
Paul Chote
a3559d8803 Revert ShpTD empty space trimming.
This reverts the following commits:
 * 1faae73c08
 * a7d39fc76d
2018-08-04 20:04:25 +02:00
reaperrr
9d0d25eca6 Fix tree owner on TD maps
Needs to be Neutral instead of Creeps, to avoid confusing the AI.
2018-08-04 14:03:30 +01:00
reaperrr
ced9ff26b5 Fix tree owner on several RA maps
Owner: Creeps can lead to AI trying to attack trees, so all trees must have Neutral as owner.
2018-08-04 14:03:24 +01:00
abcdefg30
3498ad11dd Remove all uses of Server.ExternalPort 2018-08-04 12:38:35 +02:00
abcdefg30
ad03b40635 Fix the die1 sequence of fremen 2018-07-31 21:05:14 +02:00
2216 changed files with 25565 additions and 58926 deletions

View File

@@ -4,7 +4,6 @@ root = true
; Unix-style newlines
[*]
end_of_line = LF
insert_final_newline = true
; 4-column tab indentation
[*.cs]

5
.gitattributes vendored
View File

@@ -8,3 +8,8 @@
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union

21
.gitignore vendored
View File

@@ -13,6 +13,12 @@ obj
_ReSharper.*/
/.vs
# movies
*.vqa
# archives
*.mix
# binaries
mods/*/*.dll
mods/*/*.mdb
@@ -24,7 +30,6 @@ mods/*/*.pdb
/*.pdb
/*.mdb
/*.exe
/*.exe.config
thirdparty/download/*
*.mmdb.gz
@@ -41,6 +46,20 @@ thirdparty/download/*
# Mac OS X
.DS_Store
# XCode
packaging/osx/launcher/build/
packaging/osx/launcher/OpenRA.xcodeproj/*.pbxuser
packaging/osx/launcher/OpenRA.xcodeproj/*.perspectivev3
packaging/osx/launcher/OpenRA.xcodeproj/*.mode1v3
temp.c
temp.o
temp.s
OpenRA.Launcher.Mac/build/
OpenRA.Launcher.Mac/OpenRA.xcodeproj/*.pbxuser
OpenRA.Launcher.Mac/OpenRA.xcodeproj/*.perspectivev3
OpenRA.Launcher.Mac/OpenRA.xcodeproj/*.mode1v3
*.resources
# auto-generated documentation
DOCUMENTATION.md
WEAPONS.md

View File

@@ -1,9 +1,11 @@
# Travis-CI Build for OpenRA
# see travis-ci.org for details
dist: xenial
language: csharp
mono: 5.20.1
mono: 4.6.1
# http://docs.travis-ci.com/user/migrating-from-legacy
sudo: false
cache:
directories:
@@ -13,6 +15,8 @@ addons:
apt:
packages:
- lua5.1
- nsis
- nsis-common
- dpkg
- markdown
- zlib1g-dev
@@ -33,7 +37,15 @@ env:
# Run the NUnit tests
script:
- travis_retry make all-dependencies
- make all
- make all SDK="-sdk:4.5"
- make check
- make check-scripts
- make test
- make nunit
# Automatically update the trait documentation and Lua API
after_success:
- test $TRAVIS_PULL_REQUEST == "false" && cd packaging && ./update-wiki.sh $TRAVIS_BRANCH; cd ..
# Only watch the development branch and tagged release.
branches:
@@ -41,30 +53,33 @@ branches:
- /^release-.*$/
- /^playtest-.*$/
- /^pkgtest-.*$/
- /^devtest-.*$/
- /^prep-.*$/
- bleed
# Notify developers when build passed/failed.
notifications:
irc:
template:
- "%{repository}#%{build_number} %{commit} %{author}: %{message} %{build_url}"
channels:
- "irc.freenode.net#openra"
use_notice: true
skip_join: true
before_deploy:
- wget http://mirrors.kernel.org/ubuntu/pool/universe/n/nsis/nsis-common_3.03-2_all.deb
- wget http://mirrors.kernel.org/ubuntu/pool/universe/n/nsis/nsis_3.03-2_amd64.deb
- sudo dpkg -i nsis-common_3.03-2_all.deb
- sudo dpkg -i nsis_3.03-2_amd64.deb
- makensis -VERSION
- export PATH=$PATH:$HOME/usr/bin
- DOTVERSION=`echo ${TRAVIS_TAG} | sed "s/-/\\./g"`
- cd packaging
- mkdir build
- ./package-all.sh ${TRAVIS_TAG} ${PWD}/build/
deploy:
provider: releases
api_key:
secure: BzLdjZHvDqd5jyyHS8KK8zrNiXEIQiGRS/RMfqK6LuFPC4mXYDE4C/0oLPe93ULtai6LgUUkwB+zKq4lDV109EBO8Xp0jXKdDLLsepGU5xRLt3Z2tT4Zj+Nx6daVjAJe1MaKO5Zo5ODi8kBploRnPCffA8AMzOyQ+OwwJNlcRSs=
secure: "g/LU11f+mjqv+lj0sR1UliHwogXL4ofJUwoG5Dbqlvdf5UTLWytw/OWSCv8RGyuh10miyWeaoqHh1cn2C1IFhUEqN1sSeKKKOWOTvJ2FR5mzi9uH3d/MOBzG5icQ7Qh0fZ1YPz5RaJJhYu6bmfvA/1gD49GoaX2kxQL4J5cEBgg="
file_glob: true
file: build/*
skip_cleanup: true
on:
all_branches: true
tags: true
repo: pchote/OpenRA
repo: OpenRA/OpenRA

14
AUTHORS
View File

@@ -54,7 +54,6 @@ Also thanks to:
* David Russell (DavidARussell)
* DeadlySurprise
* Dmitri Suvorov (suvjunmd)
* dtluna
* Erasmus Schroder (rasco)
* Eric Bajumpaa (SteelPhase)
* Evgeniy Sergeev (evgeniysergeev)
@@ -62,10 +61,11 @@ Also thanks to:
* Florian Wiesbauer (FiveAces)
* Frank Razenberg (zzattack)
* Gareth Needham (Ripley`)
* Glen Anderson (glen7)
* Glen Anderson (GlenLife)
* Glenn Martin Jensen (Baxxster)
* Gordon Martin (Happy0)
* Guido Lipke (LipkeGu)
* Gyula Zimmermann (Graion Dilach)
* Hervé Matysiak (Herve-M)
* Huw Pascoe
* Ian T. Jacobsen (Smilex)
@@ -89,12 +89,10 @@ Also thanks to:
* Kenny Hoxworth (hoxworth)
* Kevin Azzam (ChaoticMind)
* Krishnakanth Mallik
* Kyle Smith (Smitty)
* Kyrre Soerensen (zypres)
* Lawrence Wang
* Lesueur Benjamin (Valkirie)
* Maarten Meuris (Nyerguds)
* Manuel Geiger (Ectras)
* Mark Olson (markolson)
* Markus Hartung (hartmark)
* Matija Hustic (matija-hustic)
@@ -103,15 +101,12 @@ Also thanks to:
* Matthijs Benschop (Nerdie)
* Max621
* Max Ugrumov (katzsmile)
* Mazar Farran (mazarf)
* Michael Rätzel
* Michael Silber (frühstück)
* Michael Sztolcman (s1w_)
* Mike Gagné (AngryBirdz)
* Muh
* Mustafa Alperen Seki (MustaphaTR)
* Neil Shivkar (havok13888)
* Nikolay Fomin (netnazgul)
* Nooze
* Nukem
* Okunev Yu Dmitry (xaionaro)
@@ -139,8 +134,6 @@ Also thanks to:
* Teemu Nieminen (Temeez)
* Tim Mylemans (gecko)
* Tirili
* Tomas Einarsson (Mesacer)
* Tom van Leth (tovl)
* Tristan Keating (Kilkakon)
* Tristan Mühlbacher (MicroBit)
* UnknownProgrammer
@@ -164,6 +157,9 @@ the Apache 2.0 license.
Using GeoLite2 data created by MaxMind and
distributed under the CC BY-SA 3.0 license.
Using SharpFont created by Robert Rouhani and
distributed under the MIT license.
Using SDL2-CS and OpenAL-CS created by Ethan
Lee and released under the zlib license.

View File

@@ -1,8 +1,5 @@
# OpenRA Contributing Guidelines
## Participating
Help us keep OpenRA open and inclusive. Please read and follow our [Code of Conduct](https://github.com/OpenRA/OpenRA/blob/bleed/CODE_OF_CONDUCT.md).
## Bug reports
* Have you read the [FAQ](https://github.com/OpenRA/OpenRA/wiki/FAQ)?

View File

@@ -6,107 +6,70 @@ The following lists per-platform dependencies required to build from source.
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.6.1 (Developer Pack)](https://dotnet.microsoft.com/download/dotnet-framework/net461) (or via Visual Studio 2017)
* [.NET Core 2.2 SDK](https://dotnet.microsoft.com/download/dotnet-core/2.2) (or via Visual Studio 2017)
* [Windows PowerShell >= 4.0](http://microsoft.com/powershell)
* [.NET Framework >= 4.5 (Client Profile)](http://www.microsoft.com/en-us/download/details.aspx?id=30653)
* [SDL 2](http://www.libsdl.org/download-2.0.php) (included)
* [FreeType](http://gnuwin32.sourceforge.net/packages/freetype.htm) (included)
* [zlib](http://gnuwin32.sourceforge.net/packages/zlib.htm) (included)
* [OpenAL](http://kcat.strangesoft.net/openal.html) (included)
* [liblua 5.1](http://luabinaries.sourceforge.net/download.html) (included)
Type `make dependencies` in a command terminal to download pre-compiled native libraries for:
* [SDL 2](http://www.libsdl.org/download-2.0.php)
* [FreeType](http://gnuwin32.sourceforge.net/packages/freetype.htm)
* [zlib](http://gnuwin32.sourceforge.net/packages/zlib.htm)
* [OpenAL](http://kcat.strangesoft.net/openal.html)
* [liblua 5.1](http://luabinaries.sourceforge.net/download.html)
You need to fetch the thirdparty dependencies and place them at the appropriate places by typing `make dependencies` in a command terminal.
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.
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.
Run the game with `OpenRA.Game.exe Game.Mod=ra` for Red Alert or `OpenRA.Game.exe Game.Mod=cnc` for Tiberian Dawn.
Linux
=====
Mono, version 5.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.
Use `make dependencies` to map the native libraries to your system and fetch the remaining CLI dependencies to place them at the appropriate places.
To compile OpenRA, run `make all` 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.
To compile OpenRA, run `make all` from the command line.
Type `sudo make install` for system-wide installation. Run `sudo make install-linux-shortcuts` to get startup scripts, icons and desktop files. You can then run the Red Alert by executing the `openra-ra` command, the Dune 2000 mod by running the `openra-d2k` command and Tiberian Dawn by the `openra-cnc` command. Alternatively, you can also run these mods by clicking on their desktop shortcuts if you ran `sudo make install-linux-shortcuts`.
Run with either `launch-game.sh` or `mono --debug OpenRA.Game.exe`.
Arch Linux
----------
It is important to note there is an unofficial [`openra-git`](https://aur.archlinux.org/packages/openra-git) package in the Arch User Repository (AUR) of Arch Linux. If manually compiling is the way you wish to go the build and runtime dependencies can be installed with:
```
sudo pacman -S mono openal libgl freetype2 sdl2 lua51 xdg-utils zenity
```
Type `sudo make install` for system wide installation. Run `make install-linux-shortcuts` to get startup scripts, icons and desktop files. You can then run from the `openra` shortcut.
Debian/Ubuntu
-------------
:warning: The `mono` packages in the Ubuntu < 19.04 and Debian < 10 repositories are too old to support OpenRA. :warning:
See the instructions under the *Linux* section above to upgrade `mono` using the upstream releases if needed.
```
sudo apt install mono-devel libfreetype6 libopenal1 liblua5.1-0 libsdl2-2.0-0 xdg-utils zenity wget
```
Fedora
------
:warning: The `mono` packages in the Fedora repositories are too old to support OpenRA. :warning:
See the instructions under the *Linux* section above to upgrade `mono` using the upstream releases.
```
sudo dnf install "pkgconfig(mono)" SDL2 freetype "lua = 5.1" openal-soft xdg-utils zenity
```
Gentoo
------
```
sudo emerge -av dev-lang/mono dev-dotnet/libgdiplus media-libs/freetype:2 media-libs/libsdl2 media-libs/openal virtual/jpeg virtual/opengl '=dev-lang/lua-5.1.5*' x11-misc/xdg-utils gnome-extra/zenity
```
Mageia
------
```
sudo dnf install "pkgconfig(mono)" SDL2 freetype "lib*lua5.1" "lib*freetype2" "lib*sdl2.0_0" openal-soft xdg-utils zenity
```
* mono-devel
* libfreetype6
* libopenal1
* liblua5.1-0
* libsdl2-2.0-0
* xdg-utils
* zenity
* curl
openSUSE
--------
```
sudo zypper in mono-devel openal-soft freetype2 SDL2 lua51 xdg-utils zenity
sudo zypper in mono-devel openal-soft freetype2 SDL2 lua51 xdg-utils zenity curl
```
Red Hat Enterprise Linux (and rebuilds, e.g. CentOS)
----------------------------------------------------
Gentoo
------
The EPEL repository is required in order for the following command to run properly.
```
sudo yum install "pkgconfig(mono)" SDL2 freetype "lua = 5.1" openal-soft xdg-utils zenity
```
* dev-lang/mono
* dev-dotnet/libgdiplus
* media-libs/freetype:2
* media-libs/libsdl2
* media-libs/openal
* virtual/jpeg
* virtual/opengl
* dev-lang/lua-5.1.5
* x11-misc/xdg-utils
* gnome-extra/zenity
* net-misc/curl
OSX
=====
Before compiling OpenRA you must install the following dependencies:
* [Mono >= 5.4](https://www.mono-project.com/download/stable/#download-mac)
Use `make dependencies` to download pre-compiled native libraries for:
* [SDL 2](http://www.libsdl.org/download-2.0.php)
* [FreeType](http://gnuwin32.sourceforge.net/packages/freetype.htm)
* [OpenAL](http://kcat.strangesoft.net/openal.html)
* [liblua 5.1](http://luabinaries.sourceforge.net/download.html)
Use `make dependencies` to map the native libraries to your system.
To compile OpenRA, run `make` from the command line.
Run with `./launch-game.sh`.
Run with `mono --debug OpenRA.Game.exe`.

247
Makefile
View File

@@ -1,7 +1,7 @@
############################# INSTRUCTIONS #############################
#
# to compile, run:
# make [DEBUG=true]
# make [DEBUG=false]
#
# to check unit tests (requires NUnit version >= 2.6), run:
# make nunit [NUNIT_CONSOLE=<path-to/nunit[2]-console>] [NUNIT_LIBS_PATH=<path-to-libs-dir>] [NUNIT_LIBS=<nunit-libs>]
@@ -33,22 +33,28 @@
# to start the game, run:
# openra
############################## TOOLCHAIN ###############################
#
# List of .NET assemblies that we can guarantee exist
# OpenRA.Game.dll is a harmless false positive that we can ignore
WHITELISTED_OPENRA_ASSEMBLIES = OpenRA.Game.exe OpenRA.Utility.exe OpenRA.Platforms.Default.dll OpenRA.Mods.Common.dll OpenRA.Mods.Cnc.dll OpenRA.Mods.D2k.dll OpenRA.Game.dll
# These are explicitly shipped alongside our core files by the packaging script
WHITELISTED_THIRDPARTY_ASSEMBLIES = ICSharpCode.SharpZipLib.dll FuzzyLogicLibrary.dll MaxMind.Db.dll Eluant.dll rix0rrr.BeaconLib.dll Open.Nat.dll SDL2-CS.dll OpenAL-CS.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
SDK ?=
CSC = mcs $(SDK)
CSFLAGS = -nologo -warn:4 -codepage:utf8 -langversion:5 -unsafe -warnaserror
DEFINE = TRACE
COMMON_LIBS = System.dll System.Core.dll System.Data.dll System.Data.DataSetExtensions.dll System.Drawing.dll System.Numerics.dll System.Xml.dll thirdparty/download/ICSharpCode.SharpZipLib.dll thirdparty/download/FuzzyLogicLibrary.dll thirdparty/download/MaxMind.Db.dll thirdparty/download/Eluant.dll thirdparty/download/rix0rrr.BeaconLib.dll
NUNIT_LIBS_PATH :=
NUNIT_LIBS := $(NUNIT_LIBS_PATH)nunit.framework.dll
DEBUG = true
ifeq ($(DEBUG), $(filter $(DEBUG),false no n off 0))
CSFLAGS += -debug:pdbonly -optimize+
else
CSFLAGS += -debug:full -optimize-
DEFINE := DEBUG;$(DEFINE)
endif
######################### UTILITIES/SETTINGS ###########################
#
# install locations
@@ -75,13 +81,8 @@ INSTALL_DIR = $(INSTALL) -d
INSTALL_PROGRAM = $(INSTALL) -m755
INSTALL_DATA = $(INSTALL) -m644
# Toolchain
MSBUILD = msbuild -verbosity:m -nologo
# Enable 32 bit builds while generating the windows installer
WIN32 = false
# program targets
CORE = pdefault game utility server
VERSION = $(shell git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null || echo git-`git rev-parse --short HEAD`)
# dependencies
@@ -92,30 +93,108 @@ else
os-dependencies = linux-dependencies
endif
######################## PROGRAM TARGET RULES ##########################
#
# Core binaries
game_SRCS := $(shell find OpenRA.Game/ -iname '*.cs')
game_TARGET = OpenRA.Game.exe
game_KIND = winexe
game_LIBS = $(COMMON_LIBS) $(game_DEPS) thirdparty/download/SharpFont.dll thirdparty/download/Open.Nat.dll
PROGRAMS += game
game: $(game_TARGET)
# Platform dlls
pdefault_SRCS := $(shell find OpenRA.Platforms.Default/ -iname '*.cs')
pdefault_TARGET = OpenRA.Platforms.Default.dll
pdefault_KIND = library
pdefault_DEPS = $(game_TARGET)
pdefault_LIBS = $(COMMON_LIBS) thirdparty/download/SDL2-CS.dll thirdparty/download/OpenAL-CS.dll $(pdefault_DEPS)
PROGRAMS += pdefault
platforms: $(pdefault_TARGET)
# Mods Common
mod_common_SRCS := $(shell find OpenRA.Mods.Common/ -iname '*.cs')
mod_common_TARGET = mods/common/OpenRA.Mods.Common.dll
mod_common_KIND = library
mod_common_DEPS = $(game_TARGET)
mod_common_LIBS = $(COMMON_LIBS) $(STD_MOD_LIBS)
PROGRAMS += mod_common
mod_common: $(mod_common_TARGET)
# NUnit testing
test_dll_SRCS := $(shell find OpenRA.Test/ -iname '*.cs')
test_dll_TARGET = OpenRA.Test.dll
test_dll_KIND = library
test_dll_DEPS = $(game_TARGET) $(mod_common_TARGET)
test_dll_FLAGS = -warn:1
test_dll_LIBS = $(COMMON_LIBS) $(game_TARGET) $(mod_common_TARGET) $(NUNIT_LIBS)
PROGRAMS += test_dll
test_dll: $(test_dll_TARGET)
##### Official Mods #####
STD_MOD_LIBS = $(game_TARGET)
STD_MOD_DEPS = $(STD_MOD_LIBS)
# Command and Conquer
mod_cnc_SRCS := $(shell find OpenRA.Mods.Cnc/ -iname '*.cs')
mod_cnc_TARGET = mods/common/OpenRA.Mods.Cnc.dll
mod_cnc_KIND = library
mod_cnc_DEPS = $(STD_MOD_DEPS) $(mod_common_TARGET)
mod_cnc_LIBS = $(COMMON_LIBS) $(STD_MOD_LIBS) $(mod_common_TARGET)
PROGRAMS += mod_cnc
mod_cnc: $(mod_cnc_TARGET)
# Dune 2000
mod_d2k_SRCS := $(shell find OpenRA.Mods.D2k/ -iname '*.cs')
mod_d2k_TARGET = mods/d2k/OpenRA.Mods.D2k.dll
mod_d2k_KIND = library
mod_d2k_DEPS = $(STD_MOD_DEPS) $(mod_common_TARGET)
mod_d2k_LIBS = $(COMMON_LIBS) $(STD_MOD_LIBS) $(mod_common_TARGET)
PROGRAMS += mod_d2k
mod_d2k: $(mod_d2k_TARGET)
check-scripts:
@echo
@echo "Checking for Lua syntax errors..."
@luac -p $(shell find mods/*/maps/* -iname '*.lua')
@luac -p $(shell find lua/* -iname '*.lua')
check: dependencies
@echo
@echo "Compiling in debug mode..."
@$(MSBUILD) -t:build -p:Configuration=Debug
@echo
@echo "Checking runtime assemblies..."
@mono --debug OpenRA.Utility.exe all --check-runtime-assemblies $(WHITELISTED_OPENRA_ASSEMBLIES) $(WHITELISTED_THIRDPARTY_ASSEMBLIES) $(WHITELISTED_CORE_ASSEMBLIES)
check: utility stylecheck mods
@echo
@echo "Checking for explicit interface violations..."
@mono --debug OpenRA.Utility.exe all --check-explicit-interfaces
@echo
@echo "Checking for incorrect conditional trait interface overrides..."
@mono --debug OpenRA.Utility.exe all --check-conditional-trait-interface-overrides
@echo "Checking for code style violations in OpenRA.Game..."
@mono --debug OpenRA.StyleCheck.exe OpenRA.Game
@echo
@echo "Checking for code style violations in OpenRA.Platforms.Default..."
@mono --debug OpenRA.StyleCheck.exe OpenRA.Platforms.Default
@echo
@echo "Checking for code style violations in OpenRA.Mods.Common..."
@mono --debug OpenRA.StyleCheck.exe OpenRA.Mods.Common
@echo
@echo "Checking for code style violations in OpenRA.Mods.Cnc..."
@mono --debug OpenRA.StyleCheck.exe OpenRA.Mods.Cnc
@echo
@echo "Checking for code style violations in OpenRA.Mods.D2k..."
@mono --debug OpenRA.StyleCheck.exe OpenRA.Mods.D2k
@echo
@echo "Checking for code style violations in OpenRA.Utility..."
@mono --debug OpenRA.StyleCheck.exe OpenRA.Utility
@echo
@echo "Checking for code style violations in OpenRA.Test..."
@mono --debug OpenRA.StyleCheck.exe OpenRA.Test
@echo
@echo "Checking for code style violations in OpenRA.Server..."
@mono --debug OpenRA.StyleCheck.exe OpenRA.Server
NUNIT_CONSOLE := $(shell test -f thirdparty/download/nunit3-console.exe && echo mono thirdparty/download/nunit3-console.exe || \
which nunit3-console 2>/dev/null || which nunit2-console 2>/dev/null || which nunit-console 2>/dev/null)
nunit: core
nunit: test_dll
@echo
@echo "Checking unit tests..."
@if [ "$(NUNIT_CONSOLE)" = "" ] ; then \
@@ -132,7 +211,7 @@ nunit: core
fi
@$(NUNIT_CONSOLE) --noresult OpenRA.Test.nunit
test: core
test: utility mods
@echo
@echo "Testing Tiberian Sun mod MiniYAML..."
@mono --debug OpenRA.Utility.exe ts --check-yaml
@@ -146,22 +225,71 @@ test: core
@echo "Testing Red Alert mod MiniYAML..."
@mono --debug OpenRA.Utility.exe ra --check-yaml
##### Launchers / Utilities #####
utility_SRCS := $(shell find OpenRA.Utility/ -iname '*.cs')
utility_TARGET = OpenRA.Utility.exe
utility_KIND = exe
utility_DEPS = $(game_TARGET)
utility_LIBS = $(COMMON_LIBS) $(utility_DEPS) thirdparty/download/ICSharpCode.SharpZipLib.dll
PROGRAMS += utility
utility: $(utility_TARGET)
stylecheck_SRCS := $(shell find OpenRA.StyleCheck/ -iname '*.cs')
stylecheck_TARGET = OpenRA.StyleCheck.exe
stylecheck_KIND = exe
stylecheck_LIBS = thirdparty/download/StyleCop.dll thirdparty/download/StyleCop.CSharp.dll thirdparty/download/StyleCop.CSharp.Rules.dll
PROGRAMS += stylecheck
stylecheck: $(stylecheck_TARGET)
# Dedicated server
server_SRCS := $(shell find OpenRA.Server/ -iname '*.cs')
server_TARGET = OpenRA.Server.exe
server_KIND = exe
server_DEPS = $(game_TARGET)
server_LIBS = $(COMMON_LIBS) $(server_DEPS)
PROGRAMS += server
server: $(server_TARGET)
# Patches binary headers to work around a mono bug
fixheader.exe: packaging/fixheader.cs
@command -v $(CSC) >/dev/null || (echo "Mono is not installed. Please install Mono from http://www.mono-project.com/download/ before building OpenRA."; exit 1)
@echo CSC fixheader.exe
@$(CSC) packaging/fixheader.cs $(CSFLAGS) -out:fixheader.exe -t:exe $(COMMON_LIBS:%=-r:%)
# Generate build rules for each target defined above in PROGRAMS
define BUILD_ASSEMBLY
$$($(1)_TARGET): $$($(1)_SRCS) Makefile $$($(1)_DEPS) fixheader.exe
@echo CSC $$(@)
@$(CSC) $$($(1)_LIBS:%=-r:%) \
-out:$$(@) $(CSFLAGS) $$($(1)_FLAGS) \
-define:"$(DEFINE)" \
-t:"$$($(1)_KIND)" \
$$($(1)_EXTRA) \
$$($(1)_SRCS)
@mono fixheader.exe $$(@) > /dev/null
@test `echo $$(@) | sed 's/^.*\.//'` = "dll" && chmod a-x $$(@) || ``
@$$($(1)_EXTRA_CMDS)
endef
$(foreach prog,$(PROGRAMS),$(eval $(call BUILD_ASSEMBLY,$(prog))))
########################## MAKE/INSTALL RULES ##########################
#
all: dependencies core
default: core
core:
@command -v $(MSBUILD) >/dev/null || (echo "OpenRA requires the '$(MSBUILD)' tool provided by Mono >= 5.4."; exit 1)
ifeq ($(WIN32), $(filter $(WIN32),true yes y on 1))
@$(MSBUILD) -t:build -p:Configuration="Release-x86"
else
@$(MSBUILD) -t:build -p:Configuration=Release
endif
core: dependencies game platforms mods utility server
mods: mod_common mod_cnc mod_d2k
all: dependencies core stylecheck
clean:
@ $(MSBUILD) -t:clean
@-$(RM_F) *.config
@-$(RM_F) *.exe *.dll *.dylib ./OpenRA*/*.dll *.pdb mods/**/*.dll mods/**/*.pdb *.resources
@-$(RM_F) *.exe *.dll *.dylib *.dll.config ./OpenRA*/*.dll ./OpenRA*/*.mdb *.mdb mods/**/*.dll mods/**/*.mdb *.resources
@-$(RM_RF) ./*/bin ./*/obj
@-$(RM_RF) ./thirdparty/download
@@ -171,7 +299,6 @@ cli-dependencies:
@./thirdparty/fetch-thirdparty-deps.sh
@ $(CP_R) thirdparty/download/*.dll .
@ $(CP_R) thirdparty/download/*.dll.config .
@ test -f OpenRA.Game/obj/project.assets.json || $(MSBUILD) -t:restore
linux-dependencies: cli-dependencies geoip-dependencies linux-native-dependencies
@@ -179,11 +306,7 @@ linux-native-dependencies:
@./thirdparty/configure-native-deps.sh
windows-dependencies: cli-dependencies geoip-dependencies
ifeq ($(WIN32), $(filter $(WIN32),true yes y on 1))
@./thirdparty/fetch-thirdparty-deps-windows.sh x86
else
@./thirdparty/fetch-thirdparty-deps-windows.sh x64
endif
@./thirdparty/fetch-thirdparty-deps-windows.sh
osx-dependencies: cli-dependencies geoip-dependencies
@./thirdparty/fetch-thirdparty-deps-osx.sh
@@ -206,19 +329,18 @@ version: VERSION mods/ra/mod.yaml mods/cnc/mod.yaml mods/d2k/mod.yaml mods/ts/mo
rm $${i}.tmp; \
done
install: dependencies core install-core
man-page: utility mods
@mono --debug OpenRA.Utility.exe all --man-page > openra.6
install: default install-core
install-linux-shortcuts: install-linux-scripts install-linux-icons install-linux-desktop
install-engine:
@-echo "Installing OpenRA engine to $(DATA_INSTALL_DIR)"
@$(INSTALL_DIR) "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) OpenRA.Game.exe "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) OpenRA.Server.exe "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) OpenRA.Utility.exe "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) OpenRA.Platforms.Default.dll "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) $(foreach prog,$(CORE),$($(prog)_TARGET)) "$(DATA_INSTALL_DIR)"
@$(INSTALL_DATA) OpenRA.Platforms.Default.dll.config "$(DATA_INSTALL_DIR)"
@$(INSTALL_DATA) "GeoLite2-Country.mmdb.gz" "$(DATA_INSTALL_DIR)/GeoLite2-Country.mmdb.gz"
@$(INSTALL_DATA) VERSION "$(DATA_INSTALL_DIR)/VERSION"
@$(INSTALL_DATA) AUTHORS "$(DATA_INSTALL_DIR)/AUTHORS"
@@ -231,6 +353,8 @@ install-engine:
@$(CP) Eluant* "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) ICSharpCode.SharpZipLib.dll "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) FuzzyLogicLibrary.dll "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) SharpFont.dll "$(DATA_INSTALL_DIR)"
@$(CP) SharpFont.dll.config "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) Open.Nat.dll "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) MaxMind.Db.dll "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) rix0rrr.BeaconLib.dll "$(DATA_INSTALL_DIR)"
@@ -239,8 +363,8 @@ install-common-mod-files:
@-echo "Installing OpenRA common mod files to $(DATA_INSTALL_DIR)"
@$(INSTALL_DIR) "$(DATA_INSTALL_DIR)/mods"
@$(CP_R) mods/common "$(DATA_INSTALL_DIR)/mods/"
@$(INSTALL_PROGRAM) mods/common/OpenRA.Mods.Common.dll "$(DATA_INSTALL_DIR)/mods/common"
@$(INSTALL_PROGRAM) mods/common/OpenRA.Mods.Cnc.dll "$(DATA_INSTALL_DIR)/mods/common"
@$(INSTALL_PROGRAM) $(mod_common_TARGET) "$(DATA_INSTALL_DIR)/mods/common"
@$(INSTALL_PROGRAM) $(mod_cnc_TARGET) "$(DATA_INSTALL_DIR)/mods/common"
@$(INSTALL_DATA) "global mix database.dat" "$(DATA_INSTALL_DIR)/global mix database.dat"
install-default-mods:
@@ -249,7 +373,7 @@ install-default-mods:
@$(CP_R) mods/cnc "$(DATA_INSTALL_DIR)/mods/"
@$(CP_R) mods/ra "$(DATA_INSTALL_DIR)/mods/"
@$(CP_R) mods/d2k "$(DATA_INSTALL_DIR)/mods/"
@$(INSTALL_PROGRAM) mods/d2k/OpenRA.Mods.D2k.dll "$(DATA_INSTALL_DIR)/mods/d2k"
@$(INSTALL_PROGRAM) $(mod_d2k_TARGET) "$(DATA_INSTALL_DIR)/mods/d2k"
@$(CP_R) mods/modcontent "$(DATA_INSTALL_DIR)/mods/"
install-core: install-engine install-common-mod-files install-default-mods
@@ -295,11 +419,9 @@ install-linux-appdata:
@$(INSTALL_DATA) packaging/linux/openra-d2k.appdata.xml "$(DESTDIR)$(datadir)/appdata/"
@-$(RM) packaging/linux/openra-ra.appdata.xml packaging/linux/openra-cnc.appdata.xml packaging/linux/openra-d2k.appdata.xml
install-man-page:
install-man-page: man-page
@$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man6/"
@mono --debug OpenRA.Utility.exe all --man-page > openra.6
@$(INSTALL_DATA) openra.6 "$(DESTDIR)$(mandir)/man6/"
@-$(RM) openra.6
install-linux-scripts:
ifeq ($(DEBUG), $(filter $(DEBUG),false no n off 0))
@@ -381,10 +503,13 @@ help:
@echo 'to start the game, run:'
@echo ' openra'
########################### MAKEFILE SETTINGS ##########################
#
.DEFAULT_GOAL := all
.DEFAULT_GOAL := default
.SUFFIXES:
.PHONY: check-scripts check nunit test all core clean distclean cli-dependencies linux-dependencies linux-native-dependencies windows-dependencies osx-dependencies geoip-dependencies dependencies all-dependencies version install install-linux-shortcuts install-engine install-common-mod-files install-default-mods install-core install-linux-icons install-linux-desktop install-linux-mime install-linux-appdata install-man-page install-linux-scripts uninstall help
.PHONY: core package all mods clean distclean dependencies version $(PROGRAMS) nunit

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -12,61 +12,158 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Activities
{
public enum ActivityState { Queued, Active, Canceling, Done }
public class TargetLineNode
{
public readonly Target Target;
public readonly Color Color;
public readonly Sprite Tile;
public TargetLineNode(Target target, Color color, Sprite tile = null)
{
// Note: Not all activities are drawable. In that case, pass Target.Invalid as target,
// if "yield break" in TargetLineNode(Actor self) is not feasible.
Target = target;
Color = color;
Tile = tile;
}
}
public enum ActivityState { Queued, Active, Done, Canceled }
/*
* Activities are actions carried out by actors during each tick.
*
* Activities exist in a graph data structure built up amongst themselves. Each activity has a parent activity,
* optionally child activities, and usually a next activity. An actor's CurrentActivity is a pointer into that graph
* and moves through it as activities run.
*
* There are two kinds of activities, the base activity and composite activities. They differ in the way their children
* are run: while a base activity is responsible for running its children itself, a composite activity relies on the actor's
* activity-running code. Therefore, the actor's CurrentActivity stays on the base activity while it runs its children. With
* composite activities however, the CurrentActivity moves through the list of children as they run.
*
*
* Things to be aware of when writing activities:
*
* - Use "return true" at least once somewhere in the tick method.
* - Do not "reuse" (with "SequenceActivities", for example) activity objects that have already started running.
* - Use "return NextActivity" at least once somewhere in the tick method.
* - Do not use "return new SomeActivity()" as that will break the graph. Queue the new activity and use "return NextActivity" instead.
* - Do not "reuse" (with "SequenceActivities", for example) activity objects that have already finished running.
* Queue a new instance instead.
* - Avoid calling actor.CancelActivity(). It is almost always a bug. Call activity.Cancel() instead.
*/
public abstract class Activity : IActivityInterface
* - A composite activity will run at least twice. The first time when it returns its children,
* the second time when its last child returns its Parent.
* - Do not return the Parent explicitly unless you have an extremly good reason. "return NextActivity"
* will do the right thing in all circumstances.
* - You do not need to care about the ChildActivity pointer advancing through the list of children,
* the activity code already takes care of that.
* - If you want to check whether there are any follow-up activities queued, check against "NextInQueue"
* in favour of "NextActivity" to avoid checking against the Parent activity.
*
*
* Guide when to use which kind of activity:
*
* - The activity does not have any children -> base activity
* - The activity needs to run preparatory steps during each tick before its children can be run -> base activity
* - The activity or the actor is left in a bogus state when one of the child activities is canceled -> base activity
* - The activity's children are self-contained and can run independently of the parent -> composite activity
* - The activity does not have any or little logic of its own, but is just composed of sub-steps -> composite activity
*/
public abstract class Activity
{
public ActivityState State { get; private set; }
protected Activity ChildActivity { get; private set; }
public Activity NextActivity { get; private set; }
/// <summary>
/// Returns the top-most activity *from the point of view of the calling activity*. Note that the root activity
/// can and likely will have next activities of its own, which would in turn be the root for their children.
/// </summary>
public Activity RootActivity
{
get
{
var p = this;
while (p.ParentActivity != null)
p = p.ParentActivity;
return p;
}
}
Activity parentActivity;
public Activity ParentActivity
{
get
{
return parentActivity;
}
protected set
{
parentActivity = value;
var next = NextInQueue;
if (next != null)
next.ParentActivity = parentActivity;
}
}
Activity childActivity;
protected Activity ChildActivity
{
get
{
return childActivity != null && childActivity.State < ActivityState.Done ? childActivity : null;
}
set
{
if (value == this || value == ParentActivity || value == NextInQueue)
childActivity = null;
else
{
childActivity = value;
if (childActivity != null)
childActivity.ParentActivity = this;
}
}
}
Activity nextActivity;
/// <summary>
/// The getter will return either the next activity or, if there is none, the parent one.
/// </summary>
public virtual Activity NextActivity
{
get
{
return nextActivity != null ? nextActivity : ParentActivity;
}
set
{
if (value == this || value == ParentActivity || (value != null && value.ParentActivity == this))
nextActivity = null;
else
{
nextActivity = value;
if (nextActivity != null)
nextActivity.ParentActivity = ParentActivity;
}
}
}
/// <summary>
/// The getter will return the next activity on the same level _only_, in contrast to NextActivity.
/// Use this to check whether there are any follow-up activities queued.
/// </summary>
public Activity NextInQueue
{
get { return nextActivity; }
set { NextActivity = value; }
}
public bool IsInterruptible { get; protected set; }
public bool ChildHasPriority { get; protected set; }
public bool IsCanceling { get { return State == ActivityState.Canceling; } }
bool finishing;
bool lastRun;
public bool IsCanceled { get { return State == ActivityState.Canceled; } }
public Activity()
{
IsInterruptible = true;
ChildHasPriority = true;
}
public Activity TickOuter(Actor self)
{
if (State == ActivityState.Done)
throw new InvalidOperationException("Actor {0} attempted to tick activity {1} after it had already completed.".F(self, GetType()));
if (State == ActivityState.Done && Game.Settings.Debug.StrictActivityChecking)
throw new InvalidOperationException("Actor {0} attempted to tick activity {1} after it had already completed.".F(self, this.GetType()));
if (State == ActivityState.Queued)
{
@@ -74,61 +171,24 @@ namespace OpenRA.Activities
State = ActivityState.Active;
}
// Only run the parent tick when the child is done.
// We must always let the child finish on its own before continuing.
if (ChildHasPriority)
var ret = Tick(self);
if (ret == null || (ret != this && ret.ParentActivity != this))
{
lastRun = TickChild(self) && (finishing || Tick(self));
finishing |= lastRun;
}
// Make sure that the Parent's ChildActivity pointer is moved forwards as the child queue advances.
// The Child's ParentActivity will be set automatically during assignment.
if (ParentActivity != null && ParentActivity != ret)
ParentActivity.ChildActivity = ret;
// The parent determines whether the child gets a chance at ticking.
else
lastRun = Tick(self);
if (State != ActivityState.Canceled)
State = ActivityState.Done;
// Avoid a single tick delay if the childactivity was just queued.
if (ChildActivity != null && ChildActivity.State == ActivityState.Queued)
{
if (ChildHasPriority)
lastRun = TickChild(self) && finishing;
else
TickChild(self);
}
if (lastRun)
{
State = ActivityState.Done;
OnLastRun(self);
return NextActivity;
}
return this;
return ret;
}
protected bool TickChild(Actor self)
{
ChildActivity = ActivityUtils.RunActivity(self, ChildActivity);
return ChildActivity == null;
}
/// <summary>
/// Called every tick to run activity logic. Returns false if the activity should
/// remain active, or true if it is complete. Cancelled activities must ensure they
/// return the actor to a consistent state before returning true.
///
/// Child activities can be queued using QueueChild, and these will be ticked
/// instead of the parent while they are active. Activities that need to run logic
/// in parallel with child activities should set ChildHasPriority to false and
/// manually call TickChildren.
///
/// Queuing one or more child activities and returning true is valid, and causes
/// the activity to be completed immediately (without ticking again) once the
/// children have completed.
/// </summary>
public virtual bool Tick(Actor self)
{
return true;
}
public abstract Activity Tick(Actor self);
/// <summary>
/// Runs once immediately before the first Tick() execution.
@@ -140,47 +200,32 @@ namespace OpenRA.Activities
/// </summary>
protected virtual void OnLastRun(Actor self) { }
/// <summary>
/// Runs once on Actor.Dispose() (through OnActorDisposeOuter) and can be used to perform activity clean-up on actor death/disposal,
/// for example by force-triggering OnLastRun (which would otherwise be skipped).
/// </summary>
protected virtual void OnActorDispose(Actor self) { }
/// <summary>
/// Runs once on Actor.Dispose().
/// Main purpose is to ensure ChildActivity.OnActorDispose runs as well (which isn't otherwise accessible due to protection level).
/// </summary>
internal void OnActorDisposeOuter(Actor self)
public virtual bool Cancel(Actor self, bool keepQueue = false)
{
if (ChildActivity != null)
ChildActivity.OnActorDisposeOuter(self);
if (!IsInterruptible)
return false;
OnActorDispose(self);
}
if (ChildActivity != null && !ChildActivity.Cancel(self))
return false;
public virtual void Cancel(Actor self, bool keepQueue = false)
{
if (!keepQueue)
NextActivity = null;
if (!IsInterruptible)
return;
ChildActivity = null;
State = ActivityState.Canceled;
if (ChildActivity != null)
ChildActivity.Cancel(self);
State = ActivityState.Canceling;
return true;
}
public void Queue(Activity activity)
public virtual void Queue(Activity activity)
{
if (NextActivity != null)
NextActivity.Queue(activity);
if (NextInQueue != null)
NextInQueue.Queue(activity);
else
NextActivity = activity;
NextInQueue = activity;
}
public void QueueChild(Activity activity)
public virtual void QueueChild(Activity activity)
{
if (ChildActivity != null)
ChildActivity.Queue(activity);
@@ -189,31 +234,30 @@ namespace OpenRA.Activities
}
/// <summary>
/// Prints the activity tree, starting from the top or optionally from a given origin.
/// Prints the activity tree, starting from the root or optionally from a given origin.
///
/// Call this method from any place that's called during a tick, such as the Tick() method itself or
/// the Before(First|Last)Run() methods. The origin activity will be marked in the output.
/// </summary>
/// <param name="self">The actor performing this activity.</param>
/// <param name="origin">Activity from which to start traversing, and which to mark. If null, mark the calling activity, and start traversal from the top.</param>
/// <param name="origin">Activity from which to start traversing, and which to mark. If null, mark the calling activity, and start traversal from the root.</param>
/// <param name="level">Initial level of indentation.</param>
protected void PrintActivityTree(Actor self, Activity origin = null, int level = 0)
protected void PrintActivityTree(Activity origin = null, int level = 0)
{
if (origin == null)
self.CurrentActivity.PrintActivityTree(self, this);
RootActivity.PrintActivityTree(this);
else
{
Console.Write(new string(' ', level * 2));
if (origin == this)
Console.Write("*");
Console.WriteLine(GetType().ToString().Split('.').Last());
Console.WriteLine(this.GetType().ToString().Split('.').Last());
if (ChildActivity != null)
ChildActivity.PrintActivityTree(self, origin, level + 1);
ChildActivity.PrintActivityTree(origin, level + 1);
if (NextActivity != null)
NextActivity.PrintActivityTree(self, origin, level);
if (NextInQueue != null)
NextInQueue.PrintActivityTree(origin, level);
}
}
@@ -221,34 +265,39 @@ namespace OpenRA.Activities
{
yield break;
}
}
public virtual IEnumerable<TargetLineNode> TargetLineNodes(Actor self)
/// <summary>
/// In contrast to the base activity class, which is responsible for running its children itself,
/// composite activities rely on the actor's activity-running logic for their children.
/// </summary>
public abstract class CompositeActivity : Activity
{
/// <summary>
/// The getter will return the first non-null value of either child, next or parent activity, in that order, or ultimately null.
/// </summary>
public override Activity NextActivity
{
yield break;
}
public IEnumerable<string> DebugLabelComponents()
{
var act = this;
while (act != null)
get
{
yield return act.GetType().Name;
act = act.ChildActivity;
if (ChildActivity != null)
return ChildActivity;
else if (NextInQueue != null)
return NextInQueue;
else
return ParentActivity;
}
}
}
public IEnumerable<T> ActivitiesImplementing<T>(bool includeChildren = true) where T : IActivityInterface
public static class ActivityExts
{
public static IEnumerable<Target> GetTargetQueue(this Actor self)
{
if (includeChildren && ChildActivity != null)
foreach (var a in ChildActivity.ActivitiesImplementing<T>())
yield return a;
if (this is T)
yield return (T)(object)this;
if (NextActivity != null)
foreach (var a in NextActivity.ActivitiesImplementing<T>())
yield return a;
return self.CurrentActivity
.Iterate(u => u.NextActivity)
.TakeWhile(u => u != null)
.SelectMany(u => u.GetTargets(self));
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -24,10 +24,10 @@ namespace OpenRA.Activities
Action a;
public override bool Tick(Actor self)
public override Activity Tick(Actor self)
{
if (a != null) a();
return true;
return NextActivity;
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using Eluant;
using Eluant.ObjectBinding;
@@ -41,13 +42,11 @@ namespace OpenRA
public Player Owner { get; internal set; }
public bool IsInWorld { get; internal set; }
public bool WillDispose { get; private set; }
public bool Disposed { get; private set; }
public Activity CurrentActivity { get; private set; }
public int Generation;
public Actor ReplacedByActor;
public IEffectiveOwner EffectiveOwner { get; private set; }
public IOccupySpace OccupiesSpace { get; private set; }
@@ -78,8 +77,6 @@ namespace OpenRA
readonly IMouseBounds[] mouseBounds;
readonly IVisibilityModifier[] visibilityModifiers;
readonly IDefaultVisibility defaultVisibility;
readonly INotifyBecomingIdle[] becomingIdles;
readonly INotifyIdle[] tickIdles;
readonly ITargetablePositions[] targetablePositions;
WPos[] staticTargetablePositions;
@@ -122,8 +119,6 @@ namespace OpenRA
mouseBounds = TraitsImplementing<IMouseBounds>().ToArray();
visibilityModifiers = TraitsImplementing<IVisibilityModifier>().ToArray();
defaultVisibility = Trait<IDefaultVisibility>();
becomingIdles = TraitsImplementing<INotifyBecomingIdle>().ToArray();
tickIdles = TraitsImplementing<INotifyIdle>().ToArray();
Targetables = TraitsImplementing<ITargetable>().ToArray();
targetablePositions = TraitsImplementing<ITargetablePositions>().ToArray();
world.AddFrameEndTask(w =>
@@ -144,18 +139,8 @@ namespace OpenRA
CurrentActivity = ActivityUtils.RunActivity(this, CurrentActivity);
if (!wasIdle && IsIdle)
{
foreach (var n in becomingIdles)
foreach (var n in TraitsImplementing<INotifyBecomingIdle>())
n.OnBecomingIdle(this);
// If IsIdle is true, it means the last CurrentActivity.Tick returned null.
// If a next activity has been queued via OnBecomingIdle, we need to start running it now,
// to avoid an 'empty' null tick where the actor will (visibly, if moving) do nothing.
CurrentActivity = ActivityUtils.RunActivity(this, CurrentActivity);
}
else if (wasIdle)
foreach (var tickIdle in tickIdles)
tickIdle.TickIdle(this);
}
public IEnumerable<IRenderable> Render(WorldRenderer wr)
@@ -222,13 +207,15 @@ namespace OpenRA
if (CurrentActivity == null)
CurrentActivity = nextActivity;
else
CurrentActivity.Queue(nextActivity);
CurrentActivity.RootActivity.Queue(nextActivity);
}
public void CancelActivity()
public bool CancelActivity()
{
if (CurrentActivity != null)
CurrentActivity.Cancel(this);
return CurrentActivity.RootActivity.Cancel(this);
return true;
}
public override int GetHashCode()
@@ -278,14 +265,6 @@ namespace OpenRA
public void Dispose()
{
// If CurrentActivity isn't null, run OnActorDisposeOuter in case some cleanups are needed.
// This should be done before the FrameEndTask to avoid dependency issues.
if (CurrentActivity != null)
CurrentActivity.OnActorDisposeOuter(this);
// Allow traits/activities to prevent a race condition when they depend on disposing the actor (e.g. Transforms)
WillDispose = true;
World.AddFrameEndTask(w =>
{
if (Disposed)
@@ -333,9 +312,6 @@ namespace OpenRA
foreach (var t in TraitsImplementing<INotifyOwnerChanged>())
t.OnOwnerChanged(this, oldOwner, newOwner);
foreach (var t in World.WorldActor.TraitsImplementing<INotifyOwnerChanged>())
t.OnOwnerChanged(this, oldOwner, newOwner);
if (wasInWorld)
World.Add(this);
}
@@ -377,7 +353,7 @@ namespace OpenRA
public BitSet<TargetableType> GetAllTargetTypes()
{
// PERF: Avoid LINQ.
var targetTypes = default(BitSet<TargetableType>);
var targetTypes = new BitSet<TargetableType>();
foreach (var targetable in Targetables)
targetTypes = targetTypes.Union(targetable.TargetTypes);
return targetTypes;
@@ -386,7 +362,7 @@ namespace OpenRA
public BitSet<TargetableType> GetEnabledTargetTypes()
{
// PERF: Avoid LINQ.
var targetTypes = default(BitSet<TargetableType>);
var targetTypes = new BitSet<TargetableType>();
foreach (var targetable in Targetables)
if (targetable.IsTraitEnabled())
targetTypes = targetTypes.Union(targetable.TargetTypes);
@@ -412,7 +388,7 @@ namespace OpenRA
if (enabledTargetablePositionTraits.Any())
return enabledTargetablePositionTraits.SelectMany(tp => tp.TargetablePositions(this));
return new[] { CenterPosition };
return new[] { this.CenterPosition };
}
#region Scripting interface

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -18,29 +18,11 @@ namespace OpenRA
{
public struct CPos : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding, IEquatable<CPos>
{
// Coordinates are packed in a 32 bit signed int
// X and Y are 12 bits (signed): -2048...2047
// Layer is an unsigned byte
// Packing is XXXX XXXX XXXX YYYY YYYY YYYY LLLL LLLL
public readonly int Bits;
// X is padded to MSB, so bit shift does the correct sign extension
public int X { get { return Bits >> 20; } }
// Align Y with a short, cast, then shift the rest of the way
// The signed short bit shift does the correct sign extension
public int Y { get { return ((short)(Bits >> 4)) >> 4; } }
public byte Layer { get { return (byte)Bits; } }
public CPos(int bits) { Bits = bits; }
public CPos(int x, int y)
: this(x, y, 0) { }
public CPos(int x, int y, byte layer)
{
Bits = (x & 0xFFF) << 20 | (y & 0xFFF) << 8 | layer;
}
public readonly int X, Y;
public readonly byte Layer;
public CPos(int x, int y) { X = x; Y = y; Layer = 0; }
public CPos(int x, int y, byte layer) { X = x; Y = y; Layer = layer; }
public static readonly CPos Zero = new CPos(0, 0, 0);
public static explicit operator CPos(int2 a) { return new CPos(a.X, a.Y); }
@@ -50,12 +32,12 @@ namespace OpenRA
public static CPos operator -(CPos a, CVec b) { return new CPos(a.X - b.X, a.Y - b.Y, a.Layer); }
public static CVec operator -(CPos a, CPos b) { return new CVec(a.X - b.X, a.Y - b.Y); }
public static bool operator ==(CPos me, CPos other) { return me.Bits == other.Bits; }
public static bool operator ==(CPos me, CPos other) { return me.X == other.X && me.Y == other.Y && me.Layer == other.Layer; }
public static bool operator !=(CPos me, CPos other) { return !(me == other); }
public override int GetHashCode() { return Bits.GetHashCode(); }
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode() ^ Layer.GetHashCode(); }
public bool Equals(CPos other) { return Bits == other.Bits; }
public bool Equals(CPos other) { return X == other.X && Y == other.Y && Layer == other.Layer; }
public override bool Equals(object obj) { return obj is CPos && Equals((CPos)obj); }
public override string ToString() { return X + "," + Y; }
@@ -150,4 +132,4 @@ namespace OpenRA
#endregion
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,9 +10,9 @@
#endregion
using System;
using System.Drawing;
using Eluant;
using Eluant.ObjectBinding;
using OpenRA.Primitives;
using OpenRA.Scripting;
namespace OpenRA

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -17,4 +17,4 @@ namespace OpenRA
void Store(string key, T data);
T Retrieve(string key);
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -123,14 +123,14 @@ namespace OpenRA
// SEQUENCE -> BIT_STRING -> SEQUENCE -> INTEGER
// Modulus is padded with a zero to avoid issues with the sign bit
writer.Write((byte)0x02);
writer.Write((byte)0x02);
WriteTLVLength(writer, parameters.Modulus.Length + 1);
writer.Write((byte)0);
writer.Write(parameters.Modulus);
// SEQUENCE -> BIT_STRING -> SEQUENCE -> INTEGER
// Exponent is padded with a zero to avoid issues with the sign bit
writer.Write((byte)0x02);
writer.Write((byte)0x02);
WriteTLVLength(writer, parameters.Exponent.Length + 1);
writer.Write((byte)0);
writer.Write(parameters.Exponent);
@@ -180,7 +180,7 @@ namespace OpenRA
try
{
using (var rsa = new RSACryptoServiceProvider())
{
{
rsa.ImportParameters(parameters);
return Encoding.UTF8.GetString(rsa.Decrypt(Convert.FromBase64String(data), false));
}
@@ -203,7 +203,7 @@ namespace OpenRA
try
{
using (var rsa = new RSACryptoServiceProvider())
{
{
rsa.ImportParameters(parameters);
using (var csp = SHA1.Create())
return Convert.ToBase64String(rsa.SignHash(csp.ComputeHash(data), CryptoConfig.MapNameToOID("SHA1")));
@@ -227,7 +227,7 @@ namespace OpenRA
try
{
using (var rsa = new RSACryptoServiceProvider())
{
{
rsa.ImportParameters(parameters);
using (var csp = SHA1.Create())
return rsa.VerifyHash(csp.ComputeHash(data), CryptoConfig.MapNameToOID("SHA1"), Convert.FromBase64String(signature));

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -9,6 +9,7 @@
*/
#endregion
using System;
using System.Collections.Generic;
using OpenRA.Graphics;
using OpenRA.Traits;
@@ -42,4 +43,4 @@ namespace OpenRA.Effects
public IEnumerable<IRenderable> Render(WorldRenderer wr) { yield break; }
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -12,9 +12,9 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
namespace OpenRA
@@ -77,7 +77,8 @@ namespace OpenRA
if (iconNode != null && !string.IsNullOrEmpty(iconNode.Value.Value))
{
using (var stream = new MemoryStream(Convert.FromBase64String(iconNode.Value.Value)))
mod.Icon = sheetBuilder.Add(new Png(stream));
using (var bitmap = new Bitmap(stream))
mod.Icon = sheetBuilder.Add(bitmap);
}
// Avoid possibly overwriting a valid mod with an obviously bogus one

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,10 +11,11 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.Linq;
using System.Reflection;
using OpenRA.Primitives;
using OpenRA.Support;
using OpenRA.Traits;
@@ -78,6 +79,16 @@ namespace OpenRA
return val;
}
public static bool Contains(this Rectangle r, int2 p)
{
return r.Contains(p.ToPoint());
}
public static bool Contains(this RectangleF r, int2 p)
{
return r.Contains(p.ToPointF());
}
static int WindingDirectionTest(int2 v0, int2 v1, int2 p)
{
return (v1.X - v0.X) * (p.Y - v0.Y) - (p.X - v0.X) * (v1.Y - v0.Y);
@@ -164,11 +175,7 @@ namespace OpenRA
public static IEnumerable<T> Iterate<T>(this T t, Func<T, T> f)
{
while (true)
{
yield return t;
t = f(t);
}
for (;;) { yield return t; t = f(t); }
}
public static T MinBy<T, U>(this IEnumerable<T> ts, Func<T, U> selector)
@@ -441,6 +448,27 @@ namespace OpenRA
return result;
}
public static Rectangle Bounds(this Bitmap b) { return new Rectangle(0, 0, b.Width, b.Height); }
public static Bitmap CloneWith32bbpArgbPixelFormat(this Bitmap original)
{
// Note: We would use original.Clone(original.Bounds(), PixelFormat.Format32bppArgb)
// but this doesn't work on mono.
var clone = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
try
{
using (var g = System.Drawing.Graphics.FromImage(clone))
g.DrawImage(original, original.Bounds());
}
catch (Exception)
{
clone.Dispose();
throw;
}
return clone;
}
public static int ToBits(this IEnumerable<bool> bits)
{
var i = 0;
@@ -460,11 +488,6 @@ namespace OpenRA
return int.Parse(s, NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
}
public static byte ParseByte(string s)
{
return byte.Parse(s, NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
}
public static bool TryParseIntegerInvariant(string s, out int i)
{
return int.TryParse(s, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out i);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -12,6 +12,8 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -40,8 +42,7 @@ namespace OpenRA
}
}
public MissingFieldsException(string[] missing, string header = null, string headerSingle = null)
: base(null)
public MissingFieldsException(string[] missing, string header = null, string headerSingle = null) : base(null)
{
Header = missing.Length > 1 ? header : headerSingle ?? header;
Missing = missing;
@@ -229,11 +230,46 @@ namespace OpenRA
else if (fieldType == typeof(Color))
{
Color color;
if (value != null && Color.TryParse(value, out color))
if (value != null && HSLColor.TryParseRGB(value, out color))
return color;
return InvalidValueAction(value, fieldType, fieldName);
}
else if (fieldType == typeof(Color[]))
{
if (value != null)
{
var parts = value.Split(',');
var colors = new Color[parts.Length];
for (var i = 0; i < colors.Length; i++)
if (!HSLColor.TryParseRGB(parts[i], out colors[i]))
return InvalidValueAction(value, fieldType, fieldName);
return colors;
}
return InvalidValueAction(value, fieldType, fieldName);
}
else if (fieldType == typeof(HSLColor))
{
if (value != null)
{
Color rgb;
if (HSLColor.TryParseRGB(value, out rgb))
return new HSLColor(rgb);
// Allow old HSLColor/ColorRamp formats to be parsed as HSLColor
var parts = value.Split(',');
if (parts.Length == 3 || parts.Length == 4)
return new HSLColor(
(byte)Exts.ParseIntegerInvariant(parts[0]).Clamp(0, 255),
(byte)Exts.ParseIntegerInvariant(parts[1]).Clamp(0, 255),
(byte)Exts.ParseIntegerInvariant(parts[2]).Clamp(0, 255));
}
return InvalidValueAction(value, fieldType, fieldName);
}
else if (fieldType == typeof(Hotkey))
{
Hotkey res;
@@ -414,6 +450,29 @@ namespace OpenRA
return InvalidValueAction(value, fieldType, fieldName);
}
}
else if (fieldType == typeof(ImageFormat))
{
if (value != null)
{
switch (value.ToLowerInvariant())
{
case "bmp":
return ImageFormat.Bmp;
case "gif":
return ImageFormat.Gif;
case "jpg":
case "jpeg":
return ImageFormat.Jpeg;
case "tif":
case "tiff":
return ImageFormat.Tiff;
default:
return ImageFormat.Png;
}
}
return InvalidValueAction(value, fieldType, fieldName);
}
else if (fieldType == typeof(bool))
return ParseYesNo(value, fieldType, fieldName);
else if (fieldType == typeof(int2[]))

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -12,6 +12,8 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.Linq;
using System.Reflection;
@@ -74,9 +76,21 @@ namespace OpenRA
var t = v.GetType();
// Color.ToString() does the wrong thing; force it to format as rgb[a] hex
if (t == typeof(Color))
{
return ((Color)v).ToString();
return HSLColor.ToHexString((Color)v);
}
// HSLColor.ToString() does the wrong thing; force it to format as rgb[a] hex
if (t == typeof(HSLColor))
{
return ((HSLColor)v).ToHexString();
}
if (t == typeof(ImageFormat))
{
return ((ImageFormat)v).ToString();
}
if (t == typeof(Rectangle))

View File

@@ -1,355 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 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 System.Linq;
using System.Net;
using System.Text;
using ICSharpCode.SharpZipLib.Checksum;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using OpenRA.Primitives;
namespace OpenRA.FileFormats
{
public class Png
{
static readonly byte[] Signature = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
public int Width { get; set; }
public int Height { get; set; }
public Color[] Palette { get; set; }
public byte[] Data { get; set; }
public Dictionary<string, string> EmbeddedData = new Dictionary<string, string>();
public Png(Stream s)
{
if (!Verify(s))
throw new InvalidDataException("PNG Signature is bogus");
s.Position += 8;
var headerParsed = false;
var isPaletted = false;
var is24Bit = false;
var data = new List<byte>();
while (true)
{
var length = IPAddress.NetworkToHostOrder(s.ReadInt32());
var type = Encoding.UTF8.GetString(s.ReadBytes(4));
var content = s.ReadBytes(length);
/*var crc = */s.ReadInt32();
if (!headerParsed && type != "IHDR")
throw new InvalidDataException("Invalid PNG file - header does not appear first.");
using (var ms = new MemoryStream(content))
{
switch (type)
{
case "IHDR":
{
if (headerParsed)
throw new InvalidDataException("Invalid PNG file - duplicate header.");
Width = IPAddress.NetworkToHostOrder(ms.ReadInt32());
Height = IPAddress.NetworkToHostOrder(ms.ReadInt32());
var bitDepth = ms.ReadUInt8();
var colorType = (PngColorType)ms.ReadByte();
isPaletted = IsPaletted(bitDepth, colorType);
is24Bit = colorType == PngColorType.Color;
var dataLength = Width * Height;
if (!isPaletted)
dataLength *= 4;
Data = new byte[dataLength];
var compression = ms.ReadByte();
/*var filter = */ms.ReadByte();
var interlace = ms.ReadByte();
if (compression != 0)
throw new InvalidDataException("Compression method not supported");
if (interlace != 0)
throw new InvalidDataException("Interlacing not supported");
headerParsed = true;
break;
}
case "PLTE":
{
Palette = new Color[256];
for (var i = 0; i < length / 3; i++)
{
var r = ms.ReadByte(); var g = ms.ReadByte(); var b = ms.ReadByte();
Palette[i] = Color.FromArgb(r, g, b);
}
break;
}
case "tRNS":
{
if (Palette == null)
throw new InvalidDataException("Non-Palette indexed PNG are not supported.");
for (var i = 0; i < length; i++)
Palette[i] = Color.FromArgb(ms.ReadByte(), Palette[i]);
break;
}
case "IDAT":
{
data.AddRange(content);
break;
}
case "tEXt":
{
var key = ms.ReadASCIIZ();
EmbeddedData.Add(key, ms.ReadASCII(length - key.Length - 1));
break;
}
case "IEND":
{
using (var ns = new MemoryStream(data.ToArray()))
{
using (var ds = new InflaterInputStream(ns))
{
var pxStride = isPaletted ? 1 : is24Bit ? 3 : 4;
var srcStride = Width * pxStride;
var destStride = Width * (isPaletted ? 1 : 4);
var prevLine = new byte[srcStride];
for (var y = 0; y < Height; y++)
{
var filter = (PngFilter)ds.ReadByte();
var line = ds.ReadBytes(srcStride);
for (var i = 0; i < srcStride; i++)
line[i] = i < pxStride
? UnapplyFilter(filter, line[i], 0, prevLine[i], 0)
: UnapplyFilter(filter, line[i], line[i - pxStride], prevLine[i], prevLine[i - pxStride]);
if (is24Bit)
{
// Fold alpha channel into RGB data
for (var i = 0; i < line.Length / 3; i++)
{
Array.Copy(line, 3 * i, Data, y * destStride + 4 * i, 3);
Data[y * destStride + 4 * i + 3] = 255;
}
}
else
Array.Copy(line, 0, Data, y * destStride, line.Length);
prevLine = line;
}
}
}
if (isPaletted && Palette == null)
throw new InvalidDataException("Non-Palette indexed PNG are not supported.");
return;
}
}
}
}
}
public Png(byte[] data, int width, int height, Color[] palette = null,
Dictionary<string, string> embeddedData = null)
{
var expectLength = width * height;
if (palette == null)
expectLength *= 4;
if (data.Length != expectLength)
throw new InvalidDataException("Input data does not match expected length");
Width = width;
Height = height;
Palette = palette;
Data = data;
if (embeddedData != null)
EmbeddedData = embeddedData;
}
public static bool Verify(Stream s)
{
var pos = s.Position;
var isPng = Signature.Aggregate(true, (current, t) => current && s.ReadUInt8() == t);
s.Position = pos;
return isPng;
}
static byte UnapplyFilter(PngFilter f, byte x, byte a, byte b, byte c)
{
switch (f)
{
case PngFilter.None: return x;
case PngFilter.Sub: return (byte)(x + a);
case PngFilter.Up: return (byte)(x + b);
case PngFilter.Average: return (byte)(x + (a + b) / 2);
case PngFilter.Paeth: return (byte)(x + Paeth(a, b, c));
default:
throw new InvalidOperationException("Unsupported Filter");
}
}
static byte Paeth(byte a, byte b, byte c)
{
var p = a + b - c;
var pa = Math.Abs(p - a);
var pb = Math.Abs(p - b);
var pc = Math.Abs(p - c);
return (pa <= pb && pa <= pc) ? a :
(pb <= pc) ? b : c;
}
[Flags]
enum PngColorType { Indexed = 1, Color = 2, Alpha = 4 }
enum PngFilter { None, Sub, Up, Average, Paeth }
static bool IsPaletted(byte bitDepth, PngColorType colorType)
{
if (bitDepth == 8 && colorType == (PngColorType.Indexed | PngColorType.Color))
return true;
if (bitDepth == 8 && colorType == (PngColorType.Color | PngColorType.Alpha))
return false;
if (bitDepth == 8 && colorType == PngColorType.Color)
return false;
throw new InvalidDataException("Unknown pixel format");
}
void WritePngChunk(Stream output, string type, Stream input)
{
input.Position = 0;
var typeBytes = Encoding.ASCII.GetBytes(type);
output.Write(IPAddress.HostToNetworkOrder((int)input.Length));
output.WriteArray(typeBytes);
var data = input.ReadAllBytes();
output.WriteArray(data);
var crc32 = new Crc32();
crc32.Update(typeBytes);
crc32.Update(data);
output.Write(IPAddress.NetworkToHostOrder((int)crc32.Value));
}
public byte[] Save()
{
using (var output = new MemoryStream())
{
output.WriteArray(Signature);
using (var header = new MemoryStream())
{
header.Write(IPAddress.HostToNetworkOrder(Width));
header.Write(IPAddress.HostToNetworkOrder(Height));
header.WriteByte(8); // Bit depth
var colorType = Palette != null
? PngColorType.Indexed | PngColorType.Color
: PngColorType.Color | PngColorType.Alpha;
header.WriteByte((byte)colorType);
header.WriteByte(0); // Compression
header.WriteByte(0); // Filter
header.WriteByte(0); // Interlacing
WritePngChunk(output, "IHDR", header);
}
bool alphaPalette = false;
if (Palette != null)
{
using (var palette = new MemoryStream())
{
foreach (var c in Palette)
{
palette.WriteByte(c.R);
palette.WriteByte(c.G);
palette.WriteByte(c.B);
alphaPalette |= c.A > 0;
}
WritePngChunk(output, "PLTE", palette);
}
}
if (alphaPalette)
{
using (var alpha = new MemoryStream())
{
foreach (var c in Palette)
alpha.WriteByte(c.A);
WritePngChunk(output, "tRNS", alpha);
}
}
using (var data = new MemoryStream())
{
using (var compressed = new DeflaterOutputStream(data))
{
var stride = Width * (Palette != null ? 1 : 4);
for (var y = 0; y < Height; y++)
{
// Write uncompressed scanlines for simplicity
compressed.WriteByte(0);
compressed.Write(Data, y * stride, stride);
}
compressed.Flush();
compressed.Finish();
WritePngChunk(output, "IDAT", data);
}
}
foreach (var kv in EmbeddedData)
{
using (var text = new MemoryStream())
{
text.WriteArray(Encoding.ASCII.GetBytes(kv.Key + (char)0 + kv.Value));
WritePngChunk(output, "tEXt", text);
}
}
WritePngChunk(output, "IEND", new MemoryStream());
return output.ToArray();
}
}
public void Save(string path)
{
File.WriteAllBytes(path, Save());
}
}
}

View File

@@ -0,0 +1,206 @@
#region Copyright & License Information
/*
* Copyright 2007-2018 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.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
namespace OpenRA.FileFormats
{
public static class PngLoader
{
public static Bitmap Load(string filename)
{
using (var s = File.OpenRead(filename))
return Load(s);
}
public static Bitmap Load(Stream s)
{
using (var br = new BinaryReader(s))
{
var signature = new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 };
foreach (var b in signature)
if (br.ReadByte() != b)
throw new InvalidDataException("PNG Signature is bogus");
Bitmap bitmap = null;
Color[] palette = null;
var data = new List<byte>();
try
{
for (;;)
{
var length = IPAddress.NetworkToHostOrder(br.ReadInt32());
var type = Encoding.UTF8.GetString(br.ReadBytes(4));
var content = br.ReadBytes(length);
/*var crc = */br.ReadInt32();
if (bitmap == null && type != "IHDR")
throw new InvalidDataException("Invalid PNG file - header does not appear first.");
using (var ms = new MemoryStream(content))
using (var cr = new BinaryReader(ms))
switch (type)
{
case "IHDR":
{
if (bitmap != null)
throw new InvalidDataException("Invalid PNG file - duplicate header.");
var width = IPAddress.NetworkToHostOrder(cr.ReadInt32());
var height = IPAddress.NetworkToHostOrder(cr.ReadInt32());
var bitDepth = cr.ReadByte();
var colorType = (PngColorType)cr.ReadByte();
var compression = cr.ReadByte();
/*var filter = */cr.ReadByte();
var interlace = cr.ReadByte();
if (compression != 0) throw new InvalidDataException("Compression method not supported");
if (interlace != 0) throw new InvalidDataException("Interlacing not supported");
bitmap = new Bitmap(width, height, MakePixelFormat(bitDepth, colorType));
}
break;
case "PLTE":
{
palette = new Color[256];
for (var i = 0; i < length / 3; i++)
{
var r = cr.ReadByte(); var g = cr.ReadByte(); var b = cr.ReadByte();
palette[i] = Color.FromArgb(r, g, b);
}
}
break;
case "tRNS":
{
if (palette == null)
throw new InvalidDataException("Non-Palette indexed PNG are not supported.");
for (var i = 0; i < length; i++)
palette[i] = Color.FromArgb(cr.ReadByte(), palette[i]);
}
break;
case "IDAT":
{
data.AddRange(content);
}
break;
case "IEND":
{
var bits = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
using (var ns = new MemoryStream(data.ToArray()))
{
// 'zlib' flags bytes; confuses the DeflateStream.
/*var flags = (byte)*/ns.ReadByte();
/*var moreFlags = (byte)*/ns.ReadByte();
using (var ds = new DeflateStream(ns, CompressionMode.Decompress))
using (var dr = new BinaryReader(ds))
{
var prevLine = new byte[bitmap.Width]; // all zero
for (var y = 0; y < bitmap.Height; y++)
{
var filter = (PngFilter)dr.ReadByte();
var line = dr.ReadBytes(bitmap.Width);
for (var i = 0; i < bitmap.Width; i++)
line[i] = i > 0
? UnapplyFilter(filter, line[i], line[i - 1], prevLine[i], prevLine[i - 1])
: UnapplyFilter(filter, line[i], 0, prevLine[i], 0);
Marshal.Copy(line, 0, new IntPtr(bits.Scan0.ToInt64() + y * bits.Stride), line.Length);
prevLine = line;
}
}
}
bitmap.UnlockBits(bits);
if (palette == null)
throw new InvalidDataException("Non-Palette indexed PNG are not supported.");
using (var temp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
{
var cp = temp.Palette;
for (var i = 0; i < 256; i++)
cp.Entries[i] = palette[i]; // finalize the palette.
bitmap.Palette = cp;
return bitmap;
}
}
}
}
}
catch
{
if (bitmap != null)
bitmap.Dispose();
throw;
}
}
}
static byte UnapplyFilter(PngFilter f, byte x, byte a, byte b, byte c)
{
switch (f)
{
case PngFilter.None: return x;
case PngFilter.Sub: return (byte)(x + a);
case PngFilter.Up: return (byte)(x + b);
case PngFilter.Average: return (byte)(x + (a + b) / 2);
case PngFilter.Paeth: return (byte)(x + Paeth(a, b, c));
default:
throw new InvalidOperationException("Unsupported Filter");
}
}
static byte Paeth(byte a, byte b, byte c)
{
var p = a + b - c;
var pa = Math.Abs(p - a);
var pb = Math.Abs(p - b);
var pc = Math.Abs(p - c);
return (pa <= pb && pa <= pc) ? a :
(pb <= pc) ? b : c;
}
[Flags]
enum PngColorType { Indexed = 1, Color = 2, Alpha = 4 }
enum PngFilter { None, Sub, Up, Average, Paeth }
static PixelFormat MakePixelFormat(byte bitDepth, PngColorType colorType)
{
if (bitDepth == 8 && colorType == (PngColorType.Indexed | PngColorType.Color))
return PixelFormat.Format8bppIndexed;
throw new InvalidDataException("Unknown pixel format");
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -328,7 +328,7 @@ namespace OpenRA.FileSystem
if (!(mod.Package is Folder))
return null;
path = Path.Combine(mod.Package.Name, filename);
path = Path.Combine(mod.Package.Name, filename);
}
else
path = Path.Combine(parentPath, filename);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -33,7 +33,7 @@ namespace OpenRA.FileSystem
public ReadOnlyZipFile(Stream s, string filename)
{
Name = filename;
pkg = new ZipFile(s);
pkg = ZipFileHelper.Create(s);
}
public Stream GetStream(string filename)
@@ -113,7 +113,7 @@ namespace OpenRA.FileSystem
}
pkgStream.Position = 0;
pkg = new ZipFile(pkgStream);
pkg = ZipFileHelper.Create(pkgStream);
Name = filename;
}

View File

@@ -1,37 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 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.Collections.Generic;
namespace OpenRA
{
public class FontData
{
public readonly string Font;
public readonly int Size;
public readonly int Ascender;
}
public class Fonts : IGlobalModData
{
[FieldLoader.LoadUsing("LoadFonts")]
public readonly Dictionary<string, FontData> FontList;
static object LoadFonts(MiniYaml y)
{
var ret = new Dictionary<string, FontData>();
foreach (var node in y.Nodes)
ret.Add(node.Key, FieldLoader.Load<FontData>(node.Value));
return ret;
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -12,6 +12,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -39,7 +41,6 @@ namespace OpenRA
public static ModData ModData;
public static Settings Settings;
public static ICursor Cursor;
public static bool HideCursor;
static WorldRenderer worldRenderer;
internal static OrderManager OrderManager;
@@ -51,12 +52,13 @@ namespace OpenRA
public static Sound Sound;
public static bool HasInputFocus = false;
public static bool BenchmarkMode = false;
public static string EngineVersion { get; private set; }
public static LocalPlayerProfile LocalPlayerProfile;
static Task discoverNat;
static bool takeScreenshot = false;
static Benchmark benchmark = null;
public static event Action OnShellmapLoaded = () => { };
@@ -166,8 +168,6 @@ namespace OpenRA
using (new PerfTimer("NewWorld"))
OrderManager.World = new World(ModData, map, OrderManager, type);
OrderManager.World.GameOver += FinishBenchmark;
worldRenderer = new WorldRenderer(ModData, OrderManager.World);
GC.Collect();
@@ -197,12 +197,7 @@ namespace OpenRA
var replay = OrderManager.Connection as ReplayConnection;
var replayName = replay != null ? replay.Filename : null;
var lobbyInfo = OrderManager.LobbyInfo;
// Reseed the RNG so this isn't an exact repeat of the last game
lobbyInfo.GlobalSettings.RandomSeed = CosmeticRandom.Next();
var orders = new[]
{
var orders = new[] {
Order.Command("sync_lobby {0}".F(lobbyInfo.Serialize())),
Order.Command("startgame")
};
@@ -295,7 +290,7 @@ namespace OpenRA
Log.AddChannel("perf", "perf.log");
Log.AddChannel("debug", "debug.log");
Log.AddChannel("server", "server.log", true);
Log.AddChannel("server", "server.log");
Log.AddChannel("sound", "sound.log");
Log.AddChannel("graphics", "graphics.log");
Log.AddChannel("geoip", "geoip.log");
@@ -471,9 +466,6 @@ namespace OpenRA
Log.Write("nat", e.ToString());
}
ChromeMetrics.TryGet("ChatMessageColor", out chatMessageColor);
ChromeMetrics.TryGet("SystemMessageColor", out systemMessageColor);
ModData.LoadScreen.StartGame(args);
}
@@ -533,26 +525,36 @@ namespace OpenRA
// Note: These delayed actions should only be used by widgets or disposing objects
// - things that depend on a particular world should be queuing them on the world actor.
static volatile ActionQueue delayedActions = new ActionQueue();
static Color systemMessageColor = Color.White;
static Color chatMessageColor = Color.White;
public static void RunAfterTick(Action a) { delayedActions.Add(a, RunTime); }
public static void RunAfterDelay(int delayMilliseconds, Action a) { delayedActions.Add(a, RunTime + delayMilliseconds); }
static void TakeScreenshotInner()
{
using (new PerfTimer("Renderer.SaveScreenshot"))
Log.Write("debug", "Taking screenshot");
Bitmap bitmap;
using (new PerfTimer("Renderer.TakeScreenshot"))
bitmap = Renderer.Context.TakeScreenshot();
ThreadPool.QueueUserWorkItem(_ =>
{
var mod = ModData.Manifest.Metadata;
var directory = Platform.ResolvePath(Platform.SupportDirPrefix, "Screenshots", ModData.Manifest.Id, mod.Version);
Directory.CreateDirectory(directory);
var filename = TimestampedFilename(true);
var path = Path.Combine(directory, string.Concat(filename, ".png"));
Log.Write("debug", "Taking screenshot " + path);
var format = Settings.Graphics.ScreenshotFormat;
var extension = ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.FormatID == format.Guid)
.FilenameExtension.Split(';').First().ToLowerInvariant().Substring(1);
var destination = Path.Combine(directory, string.Concat(filename, extension));
Renderer.Context.SaveScreenshot(path);
Debug("Saved screenshot " + filename);
}
using (new PerfTimer("Save Screenshot ({0})".F(format)))
bitmap.Save(destination, format);
bitmap.Dispose();
RunAfterTick(() => Debug("Saved screenshot " + filename));
});
}
static void InnerLogicTick(OrderManager orderManager)
@@ -568,11 +570,11 @@ namespace OpenRA
var integralTickTimestep = (uiTickDelta / Timestep) * Timestep;
Ui.LastTickTime += integralTickTimestep >= TimestepJankThreshold ? integralTickTimestep : Timestep;
Sync.RunUnsynced(Settings.Debug.SyncCheckUnsyncedCode, world, Ui.Tick);
Sync.CheckSyncUnchanged(world, Ui.Tick);
Cursor.Tick();
}
var worldTimestep = world == null ? Timestep : world.IsLoadingGameSave ? 1 : world.Timestep;
var worldTimestep = world == null ? Timestep : world.Timestep;
var worldTickDelta = tick - orderManager.LastTickTime;
if (worldTimestep != 0 && worldTickDelta >= worldTimestep)
{
@@ -586,7 +588,7 @@ namespace OpenRA
orderManager.LastTickTime += integralTickTimestep >= TimestepJankThreshold ? integralTickTimestep : worldTimestep;
Sound.Tick();
Sync.RunUnsynced(Settings.Debug.SyncCheckUnsyncedCode, world, orderManager.TickImmediate);
Sync.CheckSyncUnchanged(world, orderManager.TickImmediate);
if (world == null)
return;
@@ -599,12 +601,16 @@ namespace OpenRA
Log.Write("debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local");
if (BenchmarkMode)
Log.Write("cpu", "{0};{1}".F(LocalTick, PerfHistory.Items["tick_time"].LastValue));
if (isNetTick)
orderManager.Tick();
Sync.RunUnsynced(Settings.Debug.SyncCheckUnsyncedCode, world, () =>
Sync.CheckSyncUnchanged(world, () =>
{
world.OrderGenerator.Tick(world);
world.Selection.Tick(world);
});
world.Tick();
@@ -616,11 +622,8 @@ namespace OpenRA
// Wait until we have done our first world Tick before TickRendering
if (orderManager.LocalFrameNumber > 0)
Sync.RunUnsynced(Settings.Debug.SyncCheckUnsyncedCode, world, () => world.TickRender(worldRenderer));
Sync.CheckSyncUnchanged(world, () => world.TickRender(worldRenderer));
}
if (benchmark != null)
benchmark.Tick(LocalTick);
}
}
@@ -655,10 +658,7 @@ namespace OpenRA
{
Renderer.BeginFrame(worldRenderer.Viewport.TopLeft, worldRenderer.Viewport.Zoom);
Sound.SetListenerPosition(worldRenderer.Viewport.CenterPosition);
// Use worldRenderer.World instead of OrderManager.World to avoid a rendering mismatch while processing orders
if (!worldRenderer.World.IsLoadingGameSave)
worldRenderer.Draw();
worldRenderer.Draw();
}
else
Renderer.BeginFrame(int2.Zero, 1f);
@@ -673,13 +673,8 @@ namespace OpenRA
if (ModData != null && ModData.CursorProvider != null)
{
if (HideCursor)
Cursor.SetCursor(null);
else
{
Cursor.SetCursor(Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default");
Cursor.Render(Renderer);
}
Cursor.SetCursor(Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default");
Cursor.Render(Renderer);
}
}
@@ -697,6 +692,9 @@ namespace OpenRA
PerfHistory.Items["batches"].Tick();
PerfHistory.Items["render_widgets"].Tick();
PerfHistory.Items["render_flip"].Tick();
if (BenchmarkMode)
Log.Write("render", "{0};{1}".F(RenderFrame, PerfHistory.Items["render"].LastValue));
}
static void Loop()
@@ -753,13 +751,6 @@ namespace OpenRA
var maxFramerate = Settings.Graphics.CapFramerate ? Settings.Graphics.MaxFramerate.Clamp(1, 1000) : 1000;
var renderInterval = 1000 / maxFramerate;
// Tick as fast as possible while restoring game saves, capping rendering at 5 FPS
if (OrderManager.World != null && OrderManager.World.IsLoadingGameSave)
{
logicInterval = 1;
renderInterval = 200;
}
var now = RunTime;
// If the logic has fallen behind too much, skip it and catch up
@@ -779,7 +770,7 @@ namespace OpenRA
LogicTick();
// Force at least one render per tick during regular gameplay
if (OrderManager.World != null && !OrderManager.World.IsLoadingGameSave && !OrderManager.World.IsReplay)
if (OrderManager.World != null && !OrderManager.World.IsReplay)
forceRender = true;
}
@@ -843,19 +834,14 @@ namespace OpenRA
state = RunStatus.Success;
}
public static void AddSystemLine(string name, string text)
public static void AddChatLine(Color color, string name, string text)
{
OrderManager.AddChatLine(name, systemMessageColor, text, systemMessageColor);
}
public static void AddChatLine(string name, Color nameColor, string text)
{
OrderManager.AddChatLine(name, nameColor, text, chatMessageColor);
OrderManager.AddChatLine(color, name, text);
}
public static void Debug(string s, params object[] args)
{
AddSystemLine("Debug", string.Format(s, args));
AddChatLine(Color.White, "Debug", string.Format(s, args));
}
public static void Disconnect()
@@ -907,37 +893,5 @@ namespace OpenRA
{
return Renderer.Window.SetClipboardText(text);
}
public static void BenchmarkMode(string prefix)
{
benchmark = new Benchmark(prefix);
}
public static void LoadMap(string launchMap)
{
var orders = new List<Order>
{
Order.Command("option gamespeed {0}".F("default")),
Order.Command("state {0}".F(Session.ClientState.Ready))
};
var path = Platform.ResolvePath(launchMap);
var map = ModData.MapCache.SingleOrDefault(m => m.Uid == launchMap) ??
ModData.MapCache.SingleOrDefault(m => m.Package.Name == path);
if (map == null)
throw new InvalidOperationException("Could not find map '{0}'.".F(launchMap));
CreateAndStartLocalServer(map.Uid, orders);
}
public static void FinishBenchmark()
{
if (benchmark != null)
{
benchmark.Write();
Exit();
}
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -12,8 +12,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Network;
using OpenRA.Primitives;
namespace OpenRA
{
@@ -24,7 +24,6 @@ namespace OpenRA
public string MapUid;
public string MapTitle;
public int FinalGameTick;
/// <summary>Game start timestamp (when the recoding started).</summary>
public DateTime StartTimeUtc;
@@ -122,8 +121,7 @@ namespace OpenRA
Team = client.Team,
SpawnPoint = runtimePlayer.SpawnPoint,
IsRandomFaction = runtimePlayer.Faction.InternalName != client.Faction,
IsRandomSpawnPoint = runtimePlayer.SpawnPoint != client.SpawnPoint,
Fingerprint = client.Fingerprint
IsRandomSpawnPoint = runtimePlayer.SpawnPoint != client.SpawnPoint
};
playersByRuntime.Add(runtimePlayer, player);
@@ -156,7 +154,7 @@ namespace OpenRA
/// <summary>The faction ID, a.k.a. the faction's internal name.</summary>
public string FactionId;
public Color Color;
public HSLColor Color;
/// <summary>The team ID on start-up, or 0 if the player is not part of a team.</summary>
public int Team;
@@ -168,9 +166,6 @@ namespace OpenRA
/// <summary>True if the spawn point was chosen at random; otherwise, false.</summary>
public bool IsRandomSpawnPoint;
/// <summary>Player authentication fingerprint for the OpenRA forum.</summary>
public string Fingerprint;
#endregion
#region

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -147,6 +147,20 @@ namespace OpenRA
.Select(t => t.GetGenericArguments()[0]);
}
public IEnumerable<Pair<string, Type>> GetInitKeys()
{
var inits = traits.WithInterface<ITraitInfo>().SelectMany(
t => t.GetType().GetInterfaces()
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(UsesInit<>))
.Select(i => i.GetGenericArguments()[0])).ToList();
inits.Add(typeof(OwnerInit)); /* not exposed by a trait; this is used by the Actor itself */
return inits.Select(
i => Pair.New(
i.Name.Replace("Init", ""), i));
}
public bool HasTraitInfo<T>() where T : ITraitInfoInterface { return traits.Contains<T>(); }
public T TraitInfo<T>() where T : ITraitInfoInterface { return traits.Get<T>(); }
public T TraitInfoOrDefault<T>() where T : ITraitInfoInterface { return traits.GetOrDefault<T>(); }
@@ -155,7 +169,7 @@ namespace OpenRA
public BitSet<TargetableType> GetAllTargetTypes()
{
// PERF: Avoid LINQ.
var targetTypes = default(BitSet<TargetableType>);
var targetTypes = new BitSet<TargetableType>();
foreach (var targetable in TraitInfos<ITargetableInfo>())
targetTypes = targetTypes.Union(targetable.GetTargetTypes());
return targetTypes;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,6 +10,7 @@
#endregion
using System.IO;
using OpenRA.FileFormats;
using OpenRA.FileSystem;
namespace OpenRA.GameRules
@@ -19,7 +20,6 @@ namespace OpenRA.GameRules
public readonly string Filename;
public readonly string Title;
public readonly bool Hidden;
public readonly float VolumeModifier = 1f;
public int Length { get; private set; } // seconds
public bool Exists { get; private set; }
@@ -32,9 +32,6 @@ namespace OpenRA.GameRules
if (nd.ContainsKey("Hidden"))
bool.TryParse(nd["Hidden"].Value, out Hidden);
if (nd.ContainsKey("VolumeModifier"))
VolumeModifier = FieldLoader.GetValue<float>("VolumeModifier", nd["VolumeModifier"].Value);
var ext = nd.ContainsKey("Extension") ? nd["Extension"].Value : "aud";
Filename = (nd.ContainsKey("Filename") ? nd["Filename"].Value : key) + "." + ext;
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -33,39 +33,18 @@ namespace OpenRA.GameRules
{
FieldLoader.Load(this, y);
VoicePools = Exts.Lazy(() => Voices.ToDictionary(a => a.Key, a => new SoundPool(1f, a.Value)));
NotificationsPools = Exts.Lazy(() => ParseSoundPool(y, "Notifications"));
}
Dictionary<string, SoundPool> ParseSoundPool(MiniYaml y, string key)
{
var ret = new Dictionary<string, SoundPool>();
var classifiction = y.Nodes.First(x => x.Key == key);
foreach (var t in classifiction.Value.Nodes)
{
var volumeModifier = 1f;
var volumeModifierNode = t.Value.Nodes.FirstOrDefault(x => x.Key == "VolumeModifier");
if (volumeModifierNode != null)
volumeModifier = FieldLoader.GetValue<float>(volumeModifierNode.Key, volumeModifierNode.Value.Value);
var names = FieldLoader.GetValue<string[]>(t.Key, t.Value.Value);
var sp = new SoundPool(volumeModifier, names);
ret.Add(t.Key, sp);
}
return ret;
VoicePools = Exts.Lazy(() => Voices.ToDictionary(a => a.Key, a => new SoundPool(a.Value)));
NotificationsPools = Exts.Lazy(() => Notifications.ToDictionary(a => a.Key, a => new SoundPool(a.Value)));
}
}
public class SoundPool
{
public readonly float VolumeModifier;
readonly string[] clips;
readonly List<string> liveclips = new List<string>();
public SoundPool(float volumeModifier, params string[] clips)
public SoundPool(params string[] clips)
{
VolumeModifier = volumeModifier;
this.clips = clips;
}
@@ -74,9 +53,8 @@ namespace OpenRA.GameRules
if (liveclips.Count == 0)
liveclips.AddRange(clips);
// Avoid crashing if there's no clips at all
if (liveclips.Count == 0)
return null;
return null; /* avoid crashing if there's no clips at all */
var i = Game.CosmeticRandom.Next(liveclips.Count);
var s = liveclips[i];

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -25,7 +25,6 @@ namespace OpenRA.GameRules
public int[] InaccuracyModifiers;
public int[] RangeModifiers;
public int Facing;
public Func<int> CurrentMuzzleFacing;
public WPos Source;
public Func<WPos> CurrentSource;
public Actor SourceActor;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,8 +10,9 @@
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Primitives;
using OpenRA.Support;
namespace OpenRA.Graphics
@@ -49,7 +50,7 @@ namespace OpenRA.Graphics
this.paused = paused;
}
public int CurrentFrame { get { return backwards ? CurrentSequence.Length - frame - 1 : frame; } }
public int CurrentFrame { get { return backwards ? CurrentSequence.Start + CurrentSequence.Length - frame - 1 : frame; } }
public Sprite Image { get { return CurrentSequence.GetSprite(CurrentFrame, facingFunc()); } }
public IRenderable[] Render(WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,7 +10,8 @@
#endregion
using System;
using OpenRA.Primitives;
using System.Collections.Generic;
using System.Drawing;
namespace OpenRA.Graphics
{
@@ -57,4 +58,4 @@ namespace OpenRA.Graphics
return new AnimationWithOffset(a, null, null, null);
}
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -12,7 +12,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Graphics
{
@@ -27,18 +26,21 @@ namespace OpenRA.Graphics
var sequenceYaml = MiniYaml.Merge(modData.Manifest.Cursors.Select(
s => MiniYaml.FromStream(fileSystem.Open(s), s)));
var shadowIndex = new int[] { };
var nodesDict = new MiniYaml(null, sequenceYaml).ToDictionary();
if (nodesDict.ContainsKey("ShadowIndex"))
{
Array.Resize(ref shadowIndex, shadowIndex.Length + 1);
Exts.TryParseIntegerInvariant(nodesDict["ShadowIndex"].Value,
out shadowIndex[shadowIndex.Length - 1]);
}
// Overwrite previous definitions if there are duplicates
var pals = new Dictionary<string, IProvidesCursorPaletteInfo>();
foreach (var p in modData.DefaultRules.Actors["world"].TraitInfos<IProvidesCursorPaletteInfo>())
if (p.Palette != null)
pals[p.Palette] = p;
var palettes = new Dictionary<string, ImmutablePalette>();
foreach (var p in nodesDict["Palettes"].Nodes)
palettes.Add(p.Key, new ImmutablePalette(fileSystem.Open(p.Value.Value), shadowIndex));
Palettes = nodesDict["Cursors"].Nodes.Select(n => n.Value.Value)
.Distinct()
.ToDictionary(p => p, p => pals[p].ReadPalette(modData.DefaultFileSystem))
.AsReadOnly();
Palettes = palettes.AsReadOnly();
var frameCache = new FrameCache(fileSystem, modData.SpriteLoaders);
var cursors = new Dictionary<string, CursorSequence>();

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -0,0 +1,147 @@
#region Copyright & License Information
/*
* Copyright 2007-2018 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.Drawing;
using System.Globalization;
using OpenRA.Scripting;
namespace OpenRA.Graphics
{
public struct HSLColor : IScriptBindable
{
public readonly byte H;
public readonly byte S;
public readonly byte L;
public readonly Color RGB;
public static HSLColor FromHSV(float h, float s, float v)
{
var ll = 0.5f * (2 - s) * v;
var ss = (ll >= 1 || v <= 0) ? 0 : 0.5f * s * v / (ll <= 0.5f ? ll : 1 - ll);
return new HSLColor((byte)(255 * h), (byte)(255 * ss), (byte)(255 * ll));
}
public HSLColor(Color color)
{
RGB = color;
H = (byte)((color.GetHue() / 360.0f) * 255);
S = (byte)(color.GetSaturation() * 255);
L = (byte)(color.GetBrightness() * 255);
}
public static HSLColor FromRGB(int r, int g, int b)
{
return new HSLColor(Color.FromArgb(r, g, b));
}
public static Color RGBFromHSL(float h, float s, float l)
{
// Convert from HSL to RGB
var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
var p = 2 * l - q;
float[] trgb = { h + 1 / 3.0f, h, h - 1 / 3.0f };
float[] rgb = { 0, 0, 0 };
for (var k = 0; k < 3; k++)
{
while (trgb[k] < 0) trgb[k] += 1.0f;
while (trgb[k] > 1) trgb[k] -= 1.0f;
}
for (var k = 0; k < 3; k++)
{
if (trgb[k] < 1 / 6.0f)
rgb[k] = p + ((q - p) * 6 * trgb[k]);
else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5)
rgb[k] = q;
else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3)
rgb[k] = p + ((q - p) * 6 * (2.0f / 3 - trgb[k]));
else
rgb[k] = p;
}
return Color.FromArgb((int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255));
}
public static bool TryParseRGB(string value, out Color color)
{
color = new Color();
value = value.Trim();
if (value.Length != 6 && value.Length != 8)
return false;
byte red, green, blue, alpha = 255;
if (!byte.TryParse(value.Substring(0, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out red)
|| !byte.TryParse(value.Substring(2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out green)
|| !byte.TryParse(value.Substring(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out blue))
return false;
if (value.Length == 8
&& !byte.TryParse(value.Substring(6, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out alpha))
return false;
color = Color.FromArgb(alpha, red, green, blue);
return true;
}
public static bool operator ==(HSLColor me, HSLColor other)
{
// Binary floating point numbers (float, double) calculations can yield the same RGB color created by different functions with little different HSL representation
return (me.H == other.H && me.S == other.S && me.L == other.L) || me.RGB == other.RGB;
}
public static bool operator !=(HSLColor me, HSLColor other) { return !(me == other); }
public HSLColor(byte h, byte s, byte l)
{
H = h;
S = s;
L = l;
RGB = RGBFromHSL(H / 255f, S / 255f, L / 255f);
}
public void ToHSV(out float h, out float s, out float v)
{
var ll = 2 * L / 255f;
var ss = S / 255f * ((ll <= 1) ? ll : 2 - ll);
h = H / 255f;
s = (2 * ss) / (ll + ss);
v = (ll + ss) / 2;
}
public override string ToString()
{
return "{0},{1},{2}".F(H, S, L);
}
public static string ToHexString(Color color)
{
if (color.A == 255)
return color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2");
return color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2") + color.A.ToString("X2");
}
public string ToHexString()
{
return ToHexString(RGB);
}
public override int GetHashCode() { return H.GetHashCode() ^ S.GetHashCode() ^ L.GetHashCode(); }
public override bool Equals(object obj)
{
var o = obj as HSLColor?;
return o != null && o == this;
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,8 +11,8 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{
@@ -20,26 +20,12 @@ namespace OpenRA.Graphics
{
readonly Dictionary<string, IHardwareCursor[]> hardwareCursors = new Dictionary<string, IHardwareCursor[]>();
readonly CursorProvider cursorProvider;
readonly Dictionary<string, Sprite[]> sprites = new Dictionary<string, Sprite[]>();
readonly SheetBuilder sheetBuilder;
readonly HardwarePalette hardwarePalette = new HardwarePalette();
readonly Cache<string, PaletteReference> paletteReferences;
CursorSequence cursor;
bool isLocked = false;
int2 lockedPosition;
public HardwareCursor(CursorProvider cursorProvider)
{
this.cursorProvider = cursorProvider;
paletteReferences = new Cache<string, PaletteReference>(CreatePaletteReference);
foreach (var p in cursorProvider.Palettes)
hardwarePalette.AddPalette(p.Key, p.Value, false);
hardwarePalette.Initialize();
sheetBuilder = new SheetBuilder(SheetType.Indexed);
foreach (var kv in cursorProvider.Cursors)
{
var palette = cursorProvider.Palettes[kv.Value.Palette];
@@ -48,22 +34,11 @@ namespace OpenRA.Graphics
.ToArray();
hardwareCursors.Add(kv.Key, hc);
var s = kv.Value.Frames.Select(a => sheetBuilder.Add(a)).ToArray();
sprites.Add(kv.Key, s);
}
sheetBuilder.Current.ReleaseBuffer();
Update();
}
PaletteReference CreatePaletteReference(string name)
{
var pal = hardwarePalette.GetPalette(name);
return new PaletteReference(name, hardwarePalette.GetPaletteIndex(name), pal, hardwarePalette);
}
IHardwareCursor CreateCursor(ISpriteFrame f, ImmutablePalette palette, string name, CursorSequence sequence)
{
var hotspot = sequence.Hotspot - f.Offset.ToInt2() + new int2(f.Size) / 2;
@@ -121,7 +96,6 @@ namespace OpenRA.Graphics
int frame;
int ticks;
public void Tick()
{
if (cursor == null || cursor.Length == 1)
@@ -138,46 +112,18 @@ namespace OpenRA.Graphics
void Update()
{
if (cursor != null && frame >= cursor.Length)
frame %= cursor.Length;
if (cursor == null || isLocked)
if (cursor == null)
Game.Renderer.Window.SetHardwareCursor(null);
else
{
if (frame >= cursor.Length)
frame = frame % cursor.Length;
Game.Renderer.Window.SetHardwareCursor(hardwareCursors[cursor.Name][frame]);
}
}
public void Render(Renderer renderer)
{
if (cursor.Name == null || !isLocked)
return;
var cursorSequence = cursorProvider.GetCursorSequence(cursor.Name);
var cursorSprite = sprites[cursor.Name][frame];
var cursorOffset = cursorSequence.Hotspot + (0.5f * cursorSprite.Size.XY).ToInt2();
renderer.SetPalette(hardwarePalette);
renderer.SpriteRenderer.DrawSprite(cursorSprite,
lockedPosition - cursorOffset,
paletteReferences[cursorSequence.Palette],
cursorSprite.Size);
}
public void Lock()
{
lockedPosition = Viewport.LastMousePos;
Game.Renderer.Window.SetRelativeMouseMode(true);
isLocked = true;
Update();
}
public void Unlock()
{
Game.Renderer.Window.SetRelativeMouseMode(false);
isLocked = false;
Update();
}
public void Render(Renderer renderer) { }
public void Dispose()
{
@@ -185,8 +131,7 @@ namespace OpenRA.Graphics
foreach (var cursor in cursors.Value)
cursor.Dispose();
sheetBuilder.Dispose();
hardwareCursors.Clear();
}
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,7 +10,7 @@
#endregion
using System.Collections.Generic;
using OpenRA.Primitives;
using System.Drawing;
namespace OpenRA.Graphics
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,8 +10,8 @@
#endregion
using System;
using System.Drawing;
using OpenRA.FileSystem;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,7 +11,7 @@
using System;
using System.Collections.Generic;
using OpenRA.Primitives;
using System.Drawing;
namespace OpenRA.Graphics
{
@@ -55,4 +55,4 @@ namespace OpenRA.Graphics
}
}
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Primitives;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,8 +11,11 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using OpenRA.Primitives;
using System.Reflection;
using System.Runtime.InteropServices;
namespace OpenRA.Graphics
{
@@ -33,6 +36,35 @@ namespace OpenRA.Graphics
return Color.FromArgb((int)palette[index]);
}
public static ColorPalette AsSystemPalette(this IPalette palette)
{
ColorPalette pal;
using (var b = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
pal = b.Palette;
for (var i = 0; i < Size; i++)
pal.Entries[i] = palette.GetColor(i);
// hack around a mono bug -- the palette flags get set wrong.
if (Platform.CurrentPlatform != PlatformType.Windows)
typeof(ColorPalette).GetField("flags",
BindingFlags.Instance | BindingFlags.NonPublic).SetValue(pal, 1);
return pal;
}
public static Bitmap AsBitmap(this IPalette palette)
{
var b = new Bitmap(Size, 1, PixelFormat.Format32bppArgb);
var data = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
var temp = new uint[Size];
palette.CopyToArray(temp, 0);
Marshal.Copy((int[])(object)temp, 0, data.Scan0, Size);
b.UnlockBits(data);
return b;
}
public static IPalette AsReadOnly(this IPalette palette)
{
if (palette is ImmutablePalette)
@@ -85,12 +117,6 @@ namespace OpenRA.Graphics
var r = (byte)(reader.ReadByte() << 2);
var g = (byte)(reader.ReadByte() << 2);
var b = (byte)(reader.ReadByte() << 2);
// Replicate high bits into the (currently zero) low bits.
r |= (byte)(r >> 6);
g |= (byte)(g >> 6);
b |= (byte)(b >> 6);
colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,8 +10,8 @@
#endregion
using System;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Primitives;
namespace OpenRA
{
@@ -19,7 +19,6 @@ namespace OpenRA
{
IPlatformWindow CreateWindow(Size size, WindowMode windowMode, int batchSize);
ISoundEngine CreateSound(string device);
IFont CreateFont(byte[] data);
}
public interface IHardwareCursor : IDisposable { }
@@ -52,18 +51,18 @@ namespace OpenRA
IHardwareCursor CreateHardwareCursor(string name, Size size, byte[] data, int2 hotspot);
void SetHardwareCursor(IHardwareCursor cursor);
void SetRelativeMouseMode(bool mode);
}
public interface IGraphicsContext : IDisposable
{
IVertexBuffer<Vertex> CreateVertexBuffer(int size);
ITexture CreateTexture();
ITexture CreateTexture(Bitmap bitmap);
IFrameBuffer CreateFrameBuffer(Size s);
IShader CreateShader(string name);
void EnableScissor(int left, int top, int width, int height);
void DisableScissor();
void SaveScreenshot(string path);
Bitmap TakeScreenshot();
void Present();
void DrawPrimitives(PrimitiveType pt, int firstVertex, int numVertices);
void Clear();
@@ -98,6 +97,7 @@ namespace OpenRA
public interface ITexture : IDisposable
{
void SetData(Bitmap bitmap);
void SetData(uint[,] colors);
void SetData(byte[] colors, int width, int height);
byte[] GetData();
@@ -131,17 +131,4 @@ namespace OpenRA
Fullscreen,
PseudoFullscreen,
}
public interface IFont : IDisposable
{
FontGlyph CreateGlyph(char c, int size, float deviceScale);
}
public struct FontGlyph
{
public int2 Offset;
public Size Size;
public float Advance;
public byte[] Data;
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Primitives;
@@ -25,16 +26,12 @@ namespace OpenRA.Graphics
return ramp[i];
}
public PlayerColorRemap(int[] ramp, Color c, float rampFraction)
public PlayerColorRemap(int[] ramp, HSLColor c, float rampFraction)
{
var h = c.GetHue() / 360.0f;
var s = c.GetSaturation();
var l = c.GetBrightness();
// Increase luminosity if required to represent the full ramp
var rampRange = (byte)((1 - rampFraction) * l);
var c1 = Color.FromAhsl(h, s, Math.Max(rampRange, l));
var c2 = Color.FromAhsl(h, s, (byte)Math.Max(0, l - rampRange));
var rampRange = (byte)((1 - rampFraction) * c.L);
var c1 = new HSLColor(c.H, c.S, Math.Max(rampRange, c.L)).RGB;
var c2 = new HSLColor(c.H, c.S, (byte)Math.Max(0, c.L - rampRange)).RGB;
var baseIndex = ramp[0];
var remapRamp = ramp.Select(r => r - ramp[0]);
var rampMaxIndex = ramp.Length - 1;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -9,7 +9,7 @@
*/
#endregion
using OpenRA.Primitives;
using System.Drawing;
namespace OpenRA.Graphics
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,8 +11,8 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{
@@ -238,29 +238,6 @@ namespace OpenRA.Graphics
parent.DrawRGBAVertices(vertices);
}
public void FillRect(float3 a, float3 b, float3 c, float3 d, Color topLeftColor, Color topRightColor, Color bottomRightColor, Color bottomLeftColor)
{
vertices[0] = VertexWithColor(a + Offset, topLeftColor);
vertices[1] = VertexWithColor(b + Offset, topRightColor);
vertices[2] = VertexWithColor(c + Offset, bottomRightColor);
vertices[3] = VertexWithColor(c + Offset, bottomRightColor);
vertices[4] = VertexWithColor(d + Offset, bottomLeftColor);
vertices[5] = VertexWithColor(a + Offset, topLeftColor);
parent.DrawRGBAVertices(vertices);
}
static Vertex VertexWithColor(float3 xyz, Color color)
{
color = Util.PremultiplyAlpha(color);
var cr = color.R / 255.0f;
var cg = color.G / 255.0f;
var cb = color.B / 255.0f;
var ca = color.A / 255.0f;
return new Vertex(xyz, cr, cg, cb, ca, 0, 0);
}
public void FillEllipse(float3 tl, float3 br, Color color, int vertices = 32)
{
// TODO: Create an ellipse polygon instead

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,6 +10,9 @@
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
namespace OpenRA.Graphics
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,8 +11,8 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using OpenRA.FileSystem;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,9 +10,10 @@
#endregion
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using OpenRA.FileFormats;
using OpenRA.Primitives;
using System.Runtime.InteropServices;
namespace OpenRA.Graphics
{
@@ -49,10 +50,13 @@ namespace OpenRA.Graphics
public Sheet(SheetType type, Stream stream)
{
var png = new Png(stream);
Size = new Size(png.Width, png.Height);
data = new byte[4 * Size.Width * Size.Height];
Util.FastCopyIntoSprite(new Sprite(this, new Rectangle(0, 0, png.Width, png.Height), TextureChannel.Red), png);
using (var bitmap = (Bitmap)Image.FromStream(stream))
{
Size = bitmap.Size;
data = new byte[4 * Size.Width * Size.Height];
Util.FastCopyIntoSprite(new Sprite(this, bitmap.Bounds(), TextureChannel.Red), bitmap);
}
Type = type;
ReleaseBuffer();
@@ -77,27 +81,48 @@ namespace OpenRA.Graphics
return texture;
}
public Png AsPng()
{
return new Png(GetData(), Size.Width, Size.Height);
}
public Png AsPng(TextureChannel channel, IPalette pal)
public Bitmap AsBitmap()
{
var d = GetData();
var plane = new byte[Size.Width * Size.Height];
var dataStride = 4 * Size.Width;
var bitmap = new Bitmap(Size.Width, Size.Height);
var bd = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
for (var y = 0; y < Size.Height; y++)
Marshal.Copy(d, y * dataStride, IntPtr.Add(bd.Scan0, y * bd.Stride), dataStride);
bitmap.UnlockBits(bd);
return bitmap;
}
public Bitmap AsBitmap(TextureChannel channel, IPalette pal)
{
var d = GetData();
var dataStride = 4 * Size.Width;
var bitmap = new Bitmap(Size.Width, Size.Height);
var channelOffset = (int)channel;
for (var y = 0; y < Size.Height; y++)
for (var x = 0; x < Size.Width; x++)
plane[y * Size.Width + x] = d[y * dataStride + channelOffset + 4 * x];
var bd = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
unsafe
{
var colors = (uint*)bd.Scan0;
for (var y = 0; y < Size.Height; y++)
{
var dataRowIndex = y * dataStride + channelOffset;
var bdRowIndex = y * bd.Stride / 4;
for (var x = 0; x < Size.Width; x++)
{
var paletteIndex = d[dataRowIndex + 4 * x];
colors[bdRowIndex + x] = pal[paletteIndex];
}
}
}
var palColors = new Color[Palette.Size];
for (var i = 0; i < Palette.Size; i++)
palColors[i] = pal.GetColor(i);
bitmap.UnlockBits(bd);
return new Png(plane, Size.Width, Size.Height, palColors);
return bitmap;
}
public void CreateBuffer()

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,8 +11,7 @@
using System;
using System.Collections.Generic;
using OpenRA.FileFormats;
using OpenRA.Primitives;
using System.Drawing;
namespace OpenRA.Graphics
{
@@ -40,7 +39,7 @@ namespace OpenRA.Graphics
Sheet current;
TextureChannel channel;
int rowHeight = 0;
int2 p;
Point p;
public static Sheet AllocateSheet(SheetType type, int sheetSize)
{
@@ -76,9 +75,9 @@ namespace OpenRA.Graphics
return rect;
}
public Sprite Add(Png src)
public Sprite Add(Bitmap src)
{
var rect = Allocate(new Size(src.Width, src.Height));
var rect = Allocate(src.Size);
Util.FastCopyIntoSprite(rect, src);
current.CommitBufferedData();
return rect;
@@ -107,7 +106,7 @@ namespace OpenRA.Graphics
{
if (imageSize.Width + p.X > current.Size.Width)
{
p = new int2(0, p.Y + rowHeight);
p = new Point(0, p.Y + rowHeight);
rowHeight = imageSize.Height;
}
@@ -128,11 +127,11 @@ namespace OpenRA.Graphics
channel = next.Value;
rowHeight = imageSize.Height;
p = int2.Zero;
p = new Point(0, 0);
}
var rect = new Sprite(current, new Rectangle(p.X, p.Y, imageSize.Width, imageSize.Height), zRamp, spriteOffset, channel, BlendMode.Alpha);
p += new int2(imageSize.Width, 0);
var rect = new Sprite(current, new Rectangle(p, imageSize), zRamp, spriteOffset, channel, BlendMode.Alpha);
p.X += imageSize.Width;
return rect;
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -21,8 +21,6 @@ namespace OpenRA.Graphics
void Render(Renderer renderer);
void SetCursor(string cursor);
void Tick();
void Lock();
void Unlock();
}
public sealed class SoftwareCursor : ICursor
@@ -33,9 +31,6 @@ namespace OpenRA.Graphics
readonly CursorProvider cursorProvider;
readonly SheetBuilder sheetBuilder;
bool isLocked = false;
int2 lockedPosition;
public SoftwareCursor(CursorProvider cursorProvider)
{
this.cursorProvider = cursorProvider;
@@ -82,7 +77,7 @@ namespace OpenRA.Graphics
return;
var cursorSequence = cursorProvider.GetCursorSequence(cursorName);
var cursorSprite = sprites[cursorName][(int)cursorFrame % cursorSequence.Length];
var cursorSprite = sprites[cursorName][((int)cursorFrame % cursorSequence.Length)];
var cursorSize = CursorProvider.CursorViewportZoomed ? 2.0f * cursorSprite.Size : cursorSprite.Size;
var cursorOffset = CursorProvider.CursorViewportZoomed ?
@@ -90,26 +85,12 @@ namespace OpenRA.Graphics
cursorSequence.Hotspot + (0.5f * cursorSprite.Size.XY).ToInt2();
renderer.SetPalette(palette);
var mousePos = isLocked ? lockedPosition : Viewport.LastMousePos;
renderer.SpriteRenderer.DrawSprite(cursorSprite,
mousePos - cursorOffset,
Viewport.LastMousePos - cursorOffset,
paletteReferences[cursorSequence.Palette],
cursorSize);
}
public void Lock()
{
Game.Renderer.Window.SetRelativeMouseMode(true);
lockedPosition = Viewport.LastMousePos;
isLocked = true;
}
public void Unlock()
{
Game.Renderer.Window.SetRelativeMouseMode(false);
isLocked = false;
}
public void Dispose()
{
palette.Dispose();

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,7 +10,7 @@
#endregion
using System;
using OpenRA.Primitives;
using System.Drawing;
namespace OpenRA.Graphics
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,25 +10,28 @@
#endregion
using System;
using System.Drawing;
using System.Linq;
using OpenRA.Primitives;
using OpenRA.Support;
using OpenRA.Widgets;
using SharpFont;
namespace OpenRA.Graphics
{
public sealed class SpriteFont : IDisposable
{
public int TopOffset { get; private set; }
static readonly Library Library = new Library();
readonly int size;
readonly SheetBuilder builder;
readonly Func<string, float> lineWidth;
readonly IFont font;
readonly Face face;
readonly Cache<Pair<char, Color>, GlyphInfo> glyphs;
float deviceScale;
public SpriteFont(string name, byte[] data, int size, int ascender, float scale, SheetBuilder builder)
public SpriteFont(string name, byte[] data, int size, float scale, SheetBuilder builder)
{
if (builder.Type != SheetType.BGRA)
throw new ArgumentException("The sheet builder must create BGRA sheets.", "builder");
@@ -37,7 +40,8 @@ namespace OpenRA.Graphics
this.size = size;
this.builder = builder;
font = Game.Renderer.CreateFont(data);
face = new Face(Library, data, 0);
face.SetPixelSizes((uint)(size * deviceScale), (uint)(size * deviceScale));
glyphs = new Cache<Pair<char, Color>, GlyphInfo>(CreateGlyph, Pair<char, Color>.EqualityComparer);
@@ -47,19 +51,18 @@ namespace OpenRA.Graphics
if (size <= 24)
PrecacheColor(Color.White, name);
TopOffset = size - ascender;
}
public void SetScale(float scale)
{
deviceScale = scale;
face.SetPixelSizes((uint)(size * deviceScale), (uint)(size * deviceScale));
glyphs.Clear();
}
void PrecacheColor(Color c, string name)
{
using (new PerfTimer("PrecacheColor {0} {1}px {2}".F(name, size, c)))
using (new PerfTimer("PrecacheColor {0} {1}px {2}".F(name, size, c.Name)))
for (var n = (char)0x20; n < (char)0x7f; n++)
if (glyphs[Pair.New(n, c)] == null)
throw new InvalidOperationException();
@@ -86,53 +89,7 @@ namespace OpenRA.Graphics
new float2(
(int)Math.Round(p.X * deviceScale + g.Offset.X, 0) / deviceScale,
p.Y + g.Offset.Y / deviceScale),
g.Sprite.Size / deviceScale);
p += new float2(g.Advance / deviceScale, 0);
}
}
float3 Rotate(float3 v, float sina, float cosa, float2 offset)
{
return new float3(
v.X * cosa - v.Y * sina + offset.X,
v.X * sina + v.Y * cosa + offset.Y,
0);
}
public void DrawText(string text, float2 location, Color c, float angle)
{
// Offset from the baseline position to the top-left of the glyph for rendering
var offset = new float2(0, size);
var cosa = (float)Math.Cos(-angle);
var sina = (float)Math.Sin(-angle);
var p = offset;
foreach (var s in text)
{
if (s == '\n')
{
offset += new float2(0, size);
p = offset;
continue;
}
var g = glyphs[Pair.New(s, c)];
if (g.Sprite != null)
{
var tl = new float3(
(int)Math.Round(p.X * deviceScale + g.Offset.X, 0) / deviceScale,
p.Y + g.Offset.Y / deviceScale, 0);
var br = tl + g.Sprite.Size / deviceScale;
var tr = new float3(br.X, tl.Y, 0);
var bl = new float3(tl.X, br.Y, 0);
Game.Renderer.RgbaSpriteRenderer.DrawSprite(g.Sprite,
Rotate(tl, sina, cosa, location),
Rotate(tr, sina, cosa, location),
Rotate(br, sina, cosa, location),
Rotate(bl, sina, cosa, location));
}
g.Sprite.Size / deviceScale);
p += new float2(g.Advance / deviceScale, 0);
}
@@ -153,7 +110,7 @@ namespace OpenRA.Graphics
public void DrawTextWithContrast(string text, float2 location, Color fg, Color bgDark, Color bgLight, int offset)
{
DrawTextWithContrast(text, location, fg, GetContrastColor(fg, bgDark, bgLight), offset);
DrawTextWithContrast(text, location, fg, WidgetUtils.GetContrastColor(fg, bgDark, bgLight), offset);
}
public void DrawTextWithShadow(string text, float2 location, Color fg, Color bg, int offset)
@@ -166,20 +123,7 @@ namespace OpenRA.Graphics
public void DrawTextWithShadow(string text, float2 location, Color fg, Color bgDark, Color bgLight, int offset)
{
DrawTextWithShadow(text, location, fg, GetContrastColor(fg, bgDark, bgLight), offset);
}
public void DrawTextWithShadow(string text, float2 location, Color fg, Color bg, int offset, float angle)
{
if (offset != 0)
DrawText(text, location + new float2(offset, offset), bg, angle);
DrawText(text, location, fg, angle);
}
public void DrawTextWithShadow(string text, float2 location, Color fg, Color bgDark, Color bgLight, int offset, float angle)
{
DrawTextWithShadow(text, location, fg, GetContrastColor(fg, bgDark, bgLight), offset, angle);
DrawTextWithShadow(text, location, fg, WidgetUtils.GetContrastColor(fg, bgDark, bgLight), offset);
}
public int2 Measure(string text)
@@ -193,9 +137,11 @@ namespace OpenRA.Graphics
GlyphInfo CreateGlyph(Pair<char, Color> c)
{
var glyph = font.CreateGlyph(c.First, size, deviceScale);
if (glyph.Data == null)
try
{
face.LoadChar(c.First, LoadFlags.Default, LoadTarget.Normal);
}
catch (FreeTypeException)
{
return new GlyphInfo
{
@@ -205,31 +151,44 @@ namespace OpenRA.Graphics
};
}
var s = builder.Allocate(glyph.Size);
face.Glyph.RenderGlyph(RenderMode.Normal);
var size = new Size((int)face.Glyph.Metrics.Width, (int)face.Glyph.Metrics.Height);
var s = builder.Allocate(size);
var g = new GlyphInfo
{
Sprite = s,
Advance = glyph.Advance,
Offset = glyph.Offset
Advance = (float)face.Glyph.Metrics.HorizontalAdvance,
Offset = new int2(face.Glyph.BitmapLeft, -face.Glyph.BitmapTop)
};
var dest = s.Sheet.GetData();
var destStride = s.Sheet.Size.Width * 4;
for (var j = 0; j < s.Size.Y; j++)
// A new bitmap is generated each time this property is accessed, so we do need to dispose it.
using (var bitmap = face.Glyph.Bitmap)
{
for (var i = 0; i < s.Size.X; i++)
unsafe
{
var p = glyph.Data[j * glyph.Size.Width + i];
if (p != 0)
{
var q = destStride * (j + s.Bounds.Top) + 4 * (i + s.Bounds.Left);
var pmc = Util.PremultiplyAlpha(Color.FromArgb(p, c.Second));
var p = (byte*)bitmap.Buffer;
var dest = s.Sheet.GetData();
var destStride = s.Sheet.Size.Width * 4;
dest[q] = pmc.B;
dest[q + 1] = pmc.G;
dest[q + 2] = pmc.R;
dest[q + 3] = pmc.A;
for (var j = 0; j < s.Size.Y; j++)
{
for (var i = 0; i < s.Size.X; i++)
{
if (p[i] != 0)
{
var q = destStride * (j + s.Bounds.Top) + 4 * (i + s.Bounds.Left);
var pmc = Util.PremultiplyAlpha(Color.FromArgb(p[i], c.Second));
dest[q] = pmc.B;
dest[q + 1] = pmc.G;
dest[q + 2] = pmc.R;
dest[q + 3] = pmc.A;
}
}
p += bitmap.Pitch;
}
}
}
@@ -239,14 +198,9 @@ namespace OpenRA.Graphics
return g;
}
static Color GetContrastColor(Color fgColor, Color bgDark, Color bgLight)
{
return fgColor == Color.White || fgColor.GetBrightness() > 0.33 ? bgDark : bgLight;
}
public void Dispose()
{
font.Dispose();
face.Dispose();
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.FileSystem;
@@ -20,7 +21,7 @@ namespace OpenRA.Graphics
{
public interface ISpriteLoader
{
bool TryParseSprite(Stream s, out ISpriteFrame[] frames, out TypeDictionary metadata);
bool TryParseSprite(Stream s, out ISpriteFrame[] frames);
}
public interface ISpriteFrame
@@ -49,7 +50,6 @@ namespace OpenRA.Graphics
readonly Dictionary<string, List<Sprite[]>> sprites = new Dictionary<string, List<Sprite[]>>();
readonly Dictionary<string, ISpriteFrame[]> unloadedFrames = new Dictionary<string, ISpriteFrame[]>();
readonly Dictionary<string, TypeDictionary> metadata = new Dictionary<string, TypeDictionary>();
public SpriteCache(IReadOnlyFileSystem fileSystem, ISpriteLoader[] loaders, SheetBuilder sheetBuilder)
{
@@ -80,10 +80,8 @@ namespace OpenRA.Graphics
// the loaded cache (initially empty)
if (sprite == null)
{
TypeDictionary fileMetadata = null;
unloaded = FrameLoader.GetFrames(fileSystem, filename, loaders, out fileMetadata);
unloaded = FrameLoader.GetFrames(fileSystem, filename, loaders);
unloadedFrames[filename] = unloaded;
metadata[filename] = fileMetadata;
sprite = new Sprite[unloaded.Length];
allSprites.Add(sprite);
@@ -113,22 +111,6 @@ namespace OpenRA.Graphics
return sprite;
}
}
/// <summary>
/// Returns a TypeDictionary containing any metadata defined by the frame
/// or null if the frame does not define metadata.
/// </summary>
public TypeDictionary FrameMetadata(string filename)
{
TypeDictionary fileMetadata;
if (!metadata.TryGetValue(filename, out fileMetadata))
{
FrameLoader.GetFrames(fileSystem, filename, loaders, out fileMetadata);
metadata[filename] = fileMetadata;
}
return fileMetadata;
}
}
public class FrameCache
@@ -137,8 +119,7 @@ namespace OpenRA.Graphics
public FrameCache(IReadOnlyFileSystem fileSystem, ISpriteLoader[] loaders)
{
TypeDictionary metadata;
frames = new Cache<string, ISpriteFrame[]>(filename => FrameLoader.GetFrames(fileSystem, filename, loaders, out metadata));
frames = new Cache<string, ISpriteFrame[]>(filename => FrameLoader.GetFrames(fileSystem, filename, loaders));
}
public ISpriteFrame[] this[string filename] { get { return frames[filename]; } }
@@ -146,11 +127,11 @@ namespace OpenRA.Graphics
public static class FrameLoader
{
public static ISpriteFrame[] GetFrames(IReadOnlyFileSystem fileSystem, string filename, ISpriteLoader[] loaders, out TypeDictionary metadata)
public static ISpriteFrame[] GetFrames(IReadOnlyFileSystem fileSystem, string filename, ISpriteLoader[] loaders)
{
using (var stream = fileSystem.Open(filename))
{
var spriteFrames = GetFrames(stream, loaders, out metadata);
var spriteFrames = GetFrames(stream, loaders);
if (spriteFrames == null)
throw new InvalidDataException(filename + " is not a valid sprite file!");
@@ -158,13 +139,11 @@ namespace OpenRA.Graphics
}
}
public static ISpriteFrame[] GetFrames(Stream stream, ISpriteLoader[] loaders, out TypeDictionary metadata)
public static ISpriteFrame[] GetFrames(Stream stream, ISpriteLoader[] loaders)
{
ISpriteFrame[] frames;
metadata = null;
foreach (var loader in loaders)
if (loader.TryParseSprite(stream, out frames, out metadata))
if (loader.TryParseSprite(stream, out frames))
return frames;
return null;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,7 +10,8 @@
#endregion
using System.Collections.Generic;
using OpenRA.Primitives;
using System.Drawing;
using System.Linq;
namespace OpenRA.Graphics
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,7 +10,7 @@
#endregion
using System;
using OpenRA.Primitives;
using System.Drawing;
namespace OpenRA.Graphics
{
@@ -20,7 +20,7 @@ namespace OpenRA.Graphics
readonly IShader shader;
readonly Vertex[] vertices;
readonly Sheet[] sheets = new Sheet[7];
readonly Sheet[] sheets = new Sheet[8];
BlendMode currentBlend = BlendMode.Alpha;
int nv = 0;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,8 +10,8 @@
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{
@@ -19,15 +19,11 @@ namespace OpenRA.Graphics
{
readonly IEnumerable<WPos> waypoints;
readonly Color color;
readonly int width;
readonly int markerSize;
public TargetLineRenderable(IEnumerable<WPos> waypoints, Color color, int width = 1, int markerSize = 1)
public TargetLineRenderable(IEnumerable<WPos> waypoints, Color color)
{
this.waypoints = waypoints;
this.color = color;
this.width = width;
this.markerSize = markerSize;
}
public WPos Pos { get { return waypoints.First(); } }
@@ -46,23 +42,23 @@ namespace OpenRA.Graphics
if (!waypoints.Any())
return;
var sw = width / wr.Viewport.Zoom;
var iz = 1 / wr.Viewport.Zoom;
var first = wr.Screen3DPosition(waypoints.First());
var a = first;
foreach (var b in waypoints.Skip(1).Select(pos => wr.Screen3DPosition(pos)))
{
Game.Renderer.WorldRgbaColorRenderer.DrawLine(a, b, sw, color);
DrawTargetMarker(wr, color, b, markerSize);
Game.Renderer.WorldRgbaColorRenderer.DrawLine(a, b, iz, color);
DrawTargetMarker(wr, color, b);
a = b;
}
DrawTargetMarker(wr, color, first);
}
public static void DrawTargetMarker(WorldRenderer wr, Color color, float3 location, int size = 1)
public static void DrawTargetMarker(WorldRenderer wr, Color color, float3 location)
{
var sw = size / wr.Viewport.Zoom;
var offset = new float2(sw, sw);
var iz = 1 / wr.Viewport.Zoom;
var offset = new float2(iz, iz);
var tl = location - offset;
var br = location + offset;
Game.Renderer.WorldRgbaColorRenderer.FillRect(tl, br, color);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -9,31 +9,21 @@
*/
#endregion
using System;
using System.Collections.Generic;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
namespace OpenRA.Graphics
{
public class TerrainRendererInfo : ITraitInfo
{
public object Create(ActorInitializer init) { return new TerrainRenderer(init.World); }
}
public sealed class TerrainRenderer : IRenderTerrain, IWorldLoaded, INotifyActorDisposing
sealed class TerrainRenderer : IDisposable
{
readonly Map map;
readonly Dictionary<string, TerrainSpriteLayer> spriteLayers = new Dictionary<string, TerrainSpriteLayer>();
Theater theater;
bool disposed;
readonly Theater theater;
public TerrainRenderer(World world)
public TerrainRenderer(World world, WorldRenderer wr)
{
map = world.Map;
}
void IWorldLoaded.WorldLoaded(World world, WorldRenderer wr)
{
theater = wr.Theater;
foreach (var template in map.Rules.TileSet.Templates)
@@ -62,7 +52,7 @@ namespace OpenRA.Mods.Common.Traits
kv.Value.Update(cell, palette == kv.Key ? sprite : null);
}
void IRenderTerrain.RenderTerrain(WorldRenderer wr, Viewport viewport)
public void Draw(WorldRenderer wr, Viewport viewport)
{
foreach (var kv in spriteLayers.Values)
kv.Draw(wr.Viewport);
@@ -71,18 +61,13 @@ namespace OpenRA.Mods.Common.Traits
r.Render(wr);
}
void INotifyActorDisposing.Disposing(Actor self)
public void Dispose()
{
if (disposed)
return;
map.Tiles.CellEntryChanged -= UpdateCell;
map.Height.CellEntryChanged -= UpdateCell;
foreach (var kv in spriteLayers.Values)
kv.Dispose();
disposed = true;
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,8 +11,8 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,8 +11,8 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Primitives;
using OpenRA.Support;
namespace OpenRA.Graphics

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -9,7 +9,7 @@
*/
#endregion
using OpenRA.Primitives;
using System.Drawing;
namespace OpenRA.Graphics
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,8 +10,8 @@
#endregion
using System;
using OpenRA.FileFormats;
using OpenRA.Primitives;
using System.Drawing;
using System.Drawing.Imaging;
namespace OpenRA.Graphics
{
@@ -81,43 +81,53 @@ namespace OpenRA.Graphics
}
}
public static void FastCopyIntoSprite(Sprite dest, Png src)
public static void FastCopyIntoSprite(Sprite dest, Bitmap src)
{
var destData = dest.Sheet.GetData();
var destStride = dest.Sheet.Size.Width;
var width = dest.Bounds.Width;
var height = dest.Bounds.Height;
unsafe
var createdTempBitmap = false;
if (src.PixelFormat != PixelFormat.Format32bppArgb)
{
// Cast the data to an int array so we can copy the src data directly
fixed (byte* bd = &destData[0])
src = src.CloneWith32bbpArgbPixelFormat();
createdTempBitmap = true;
}
try
{
var destData = dest.Sheet.GetData();
var destStride = dest.Sheet.Size.Width;
var width = dest.Bounds.Width;
var height = dest.Bounds.Height;
var srcData = src.LockBits(src.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
var data = (int*)bd;
var x = dest.Bounds.Left;
var y = dest.Bounds.Top;
var c = (int*)srcData.Scan0;
var k = 0;
for (var j = 0; j < height; j++)
// Cast the data to an int array so we can copy the src data directly
fixed (byte* bd = &destData[0])
{
for (var i = 0; i < width; i++)
{
Color cc;
if (src.Palette == null)
{
var r = src.Data[k++];
var g = src.Data[k++];
var b = src.Data[k++];
var a = src.Data[k++];
cc = Color.FromArgb(a, r, g, b);
}
else
cc = src.Palette[src.Data[k++]];
var data = (int*)bd;
var x = dest.Bounds.Left;
var y = dest.Bounds.Top;
data[(y + j) * destStride + x + i] = PremultiplyAlpha(cc).ToArgb();
for (var j = 0; j < height; j++)
{
for (var i = 0; i < width; i++)
{
var cc = Color.FromArgb(*(c + (j * srcData.Stride >> 2) + i));
data[(y + j) * destStride + x + i] = PremultiplyAlpha(cc).ToArgb();
}
}
}
}
src.UnlockBits(srcData);
}
finally
{
if (createdTempBitmap)
src.Dispose();
}
}
@@ -320,7 +330,7 @@ namespace OpenRA.Graphics
public static float[] MakeFloatMatrix(Int32Matrix4x4 imtx)
{
var multipler = 1f / imtx.M44;
return new[]
return new float[]
{
imtx.M11 * multipler,
imtx.M12 * multipler,
@@ -352,16 +362,13 @@ namespace OpenRA.Graphics
var iz = new uint[] { 2, 5, 2, 5, 2, 5, 2, 5 };
// Vectors to opposing corner
var ret = new[]
{
float.MaxValue, float.MaxValue, float.MaxValue,
float.MinValue, float.MinValue, float.MinValue
};
var ret = new float[] { float.MaxValue, float.MaxValue, float.MaxValue,
float.MinValue, float.MinValue, float.MinValue };
// Transform vectors and find new bounding box
for (var i = 0; i < 8; i++)
{
var vec = new[] { bounds[ix[i]], bounds[iy[i]], bounds[iz[i]], 1 };
var vec = new float[] { bounds[ix[i]], bounds[iy[i]], bounds[iz[i]], 1 };
var tvec = MatrixVectorMultiply(mtx, vec);
ret[0] = Math.Min(ret[0], tvec[0] / tvec[3]);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,8 +11,8 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{
@@ -311,4 +311,4 @@ namespace OpenRA.Graphics
}
}
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,9 +11,9 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Graphics
@@ -34,7 +34,7 @@ namespace OpenRA.Graphics
readonly HashSet<Actor> onScreenActors = new HashSet<Actor>();
readonly HardwarePalette palette = new HardwarePalette();
readonly Dictionary<string, PaletteReference> palettes = new Dictionary<string, PaletteReference>();
readonly IRenderTerrain terrainRenderer;
readonly TerrainRenderer terrainRenderer;
readonly Lazy<DebugVisualizations> debugVis;
readonly Func<string, PaletteReference> createPaletteReference;
readonly bool enableDepthBuffer;
@@ -62,12 +62,12 @@ namespace OpenRA.Graphics
palette.Initialize();
Theater = new Theater(world.Map.Rules.TileSet);
terrainRenderer = world.WorldActor.TraitOrDefault<IRenderTerrain>();
terrainRenderer = new TerrainRenderer(world, this);
debugVis = Exts.Lazy(() => world.WorldActor.TraitOrDefault<DebugVisualizations>());
}
public void UpdatePalettesForPlayer(string internalName, Color color, bool replaceExisting)
public void UpdatePalettesForPlayer(string internalName, HSLColor color, bool replaceExisting)
{
foreach (var pal in World.WorldActor.TraitsImplementing<ILoadsPlayerPalettes>())
pal.LoadPlayerPalettes(this, internalName, color, replaceExisting);
@@ -181,9 +181,7 @@ namespace OpenRA.Graphics
if (enableDepthBuffer)
Game.Renderer.Context.EnableDepthBuffer();
if (terrainRenderer != null)
terrainRenderer.RenderTerrain(this, Viewport);
terrainRenderer.Draw(this, Viewport);
Game.Renderer.Flush();
for (var i = 0; i < renderables.Count; i++)
@@ -332,6 +330,7 @@ namespace OpenRA.Graphics
palette.Dispose();
Theater.Dispose();
terrainRenderer.Dispose();
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -37,4 +37,4 @@ namespace OpenRA
Types = FieldLoader.GetValue<HashSet<string>>("Types", typesNode.Value.Value);
}
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -34,10 +34,7 @@ namespace OpenRA
}
foreach (var kv in settings)
{
if (definitions.ContainsKey(kv.Key))
keys[kv.Key] = kv.Value;
}
keys[kv.Key] = kv.Value;
}
internal Func<Hotkey> GetHotkeyReference(string name)
@@ -67,20 +64,6 @@ namespace OpenRA
settings.Remove(name);
}
public HotkeyDefinition GetFirstDuplicate(string name, Hotkey value, HotkeyDefinition definition)
{
foreach (var kv in keys)
{
if (kv.Key == name)
continue;
if (kv.Value == value && definitions[kv.Key].Types.Overlaps(definition.Types))
return definitions[kv.Key];
}
return null;
}
public HotkeyReference this[string name]
{
get

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -26,17 +26,17 @@ namespace OpenRA
{
public MouseInputEvent Event;
public MouseButton Button;
public int ScrollDelta;
public int2 Location;
public int2 Delta;
public Modifiers Modifiers;
public int MultiTapCount;
public MouseInput(MouseInputEvent ev, MouseButton button, int2 location, int2 delta, Modifiers mods, int multiTapCount)
public MouseInput(MouseInputEvent ev, MouseButton button, int scrollDelta, int2 location, Modifiers mods, int multiTapCount)
{
Event = ev;
Button = button;
ScrollDelta = scrollDelta;
Location = location;
Delta = delta;
Modifiers = mods;
MultiTapCount = multiTapCount;
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -37,17 +37,17 @@ namespace OpenRA
public void OnKeyInput(KeyInput input)
{
Sync.RunUnsynced(Game.Settings.Debug.SyncCheckUnsyncedCode, world, () => Ui.HandleKeyPress(input));
Sync.CheckSyncUnchanged(world, () => Ui.HandleKeyPress(input));
}
public void OnTextInput(string text)
{
Sync.RunUnsynced(Game.Settings.Debug.SyncCheckUnsyncedCode, world, () => Ui.HandleTextInput(text));
Sync.CheckSyncUnchanged(world, () => Ui.HandleTextInput(text));
}
public void OnMouseInput(MouseInput input)
{
Sync.RunUnsynced(Game.Settings.Debug.SyncCheckUnsyncedCode, world, () => Ui.HandleInput(input));
Sync.CheckSyncUnchanged(world, () => Ui.HandleInput(input));
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -258,7 +258,7 @@ namespace OpenRA
{
static readonly Dictionary<Keycode, string> KeyNames = new Dictionary<Keycode, string>
{
{ Keycode.UNKNOWN, "Undefined" },
{ Keycode.UNKNOWN, "Unknown" },
{ Keycode.RETURN, "Return" },
{ Keycode.ESCAPE, "Escape" },
{ Keycode.BACKSPACE, "Backspace" },

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -12,9 +12,9 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.FileSystem;
using OpenRA.Graphics;
using OpenRA.Primitives;
@@ -83,7 +83,8 @@ namespace OpenRA
{
using (var stream = package.GetStream("icon.png"))
if (stream != null)
icons[id] = sheetBuilder.Add(new Png(stream));
using (var bitmap = new Bitmap(stream))
icons[id] = sheetBuilder.Add(bitmap);
}
else if (!manifest.Metadata.Hidden)
Log.Write("debug", "Mod '{0}' is missing 'icon.png'.".F(path));
@@ -127,4 +128,4 @@ namespace OpenRA
public bool TryGetValue(string key, out Manifest value) { return mods.TryGetValue(key, out value); }
IEnumerator IEnumerable.GetEnumerator() { return mods.GetEnumerator(); }
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -16,6 +16,7 @@ using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using OpenRA.Network;
namespace OpenRA
{
@@ -160,18 +161,14 @@ namespace OpenRA
}
innerState = LinkState.Uninitialized;
parameters = default(RSAParameters);
parameters = new RSAParameters();
innerFingerprint = null;
innerData = null;
}
public string Sign(params string[] data)
{
// If we don't have any keys, or we know for sure that they haven't been linked to the forum
// then we can't do much here. If we have keys but don't yet know if they have been linked to the
// forum (LinkState.CheckingLink or ConnectionFailed) then we sign to avoid blocking the main thread
// but accept that - if the cert is invalid - the server will reject the result.
if (State <= LinkState.Unlinked)
if (State != LinkState.Linked)
return null;
return CryptoUtil.Sign(parameters, data.Where(x => !string.IsNullOrEmpty(x)).JoinWith(string.Empty));
@@ -179,10 +176,10 @@ namespace OpenRA
public string DecryptString(string data)
{
if (State <= LinkState.Unlinked)
if (State != LinkState.Linked)
return null;
return CryptoUtil.DecryptString(parameters, data);
}
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -10,7 +10,7 @@
#endregion
using System;
using OpenRA.Primitives;
using System.Drawing;
namespace OpenRA
{
@@ -92,4 +92,4 @@ namespace OpenRA
public override string ToString() { return U + "," + V; }
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -66,19 +66,17 @@ namespace OpenRA
public readonly IReadOnlyDictionary<string, string> Packages;
public readonly IReadOnlyDictionary<string, string> MapFolders;
public readonly MiniYaml LoadScreen;
public readonly Dictionary<string, Pair<string, int>> Fonts;
public readonly string[] SoundFormats = { };
public readonly string[] SpriteFormats = { };
public readonly string[] PackageFormats = { };
readonly string[] reservedModuleNames =
{
"Metadata", "Folders", "MapFolders", "Packages", "Rules",
readonly string[] reservedModuleNames = { "Metadata", "Folders", "MapFolders", "Packages", "Rules",
"Sequences", "ModelSequences", "Cursors", "Chrome", "Assemblies", "ChromeLayout", "Weapons",
"Voices", "Notifications", "Music", "Translations", "TileSets", "ChromeMetrics", "Missions", "Hotkeys",
"ServerTraits", "LoadScreen", "SupportsMapsFrom", "SoundFormats", "SpriteFormats",
"RequiresMods", "PackageFormats"
};
"ServerTraits", "LoadScreen", "Fonts", "SupportsMapsFrom", "SoundFormats", "SpriteFormats",
"RequiresMods", "PackageFormats" };
readonly TypeDictionary modules = new TypeDictionary();
readonly Dictionary<string, MiniYaml> yaml;
@@ -122,6 +120,12 @@ namespace OpenRA
if (!yaml.TryGetValue("LoadScreen", out LoadScreen))
throw new InvalidDataException("`LoadScreen` section is not defined.");
Fonts = yaml["Fonts"].ToDictionary(my =>
{
var nd = my.ToDictionary();
return Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value));
});
// Allow inherited mods to import parent maps.
var compat = new List<string> { Id };

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -49,9 +49,7 @@ namespace OpenRA
public class LocationInit : IActorInit<CPos>
{
[FieldFromYamlKey]
readonly CPos value = CPos.Zero;
[FieldFromYamlKey] readonly CPos value = CPos.Zero;
public LocationInit() { }
public LocationInit(CPos init) { value = init; }
public CPos Value(World world) { return value; }
@@ -59,9 +57,7 @@ namespace OpenRA
public class OwnerInit : IActorInit<Player>
{
[FieldFromYamlKey]
public readonly string PlayerName = "Neutral";
[FieldFromYamlKey] public readonly string PlayerName = "Neutral";
Player player;
public OwnerInit() { }

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -28,8 +28,7 @@ namespace OpenRA
Lazy<TypeDictionary> initDict;
public ActorReference(string type)
: this(type, new Dictionary<string, MiniYaml>()) { }
public ActorReference(string type) : this(type, new Dictionary<string, MiniYaml>()) { }
public ActorReference(string type, Dictionary<string, MiniYaml> inits)
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -12,7 +12,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using OpenRA.Primitives;
using System.Drawing;
namespace OpenRA
{

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,12 +11,14 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using OpenRA.FileFormats;
using OpenRA.FileSystem;
using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Support;
using OpenRA.Traits;
@@ -566,10 +568,6 @@ namespace OpenRA
foreach (var field in YamlFields)
field.Serialize(this, root);
// HACK: map.yaml is expected to have empty lines between top-level blocks
for (var i = root.Count - 1; i > 0; i--)
root.Insert(i, new MiniYamlNode("", ""));
// Saving to a new package: copy over all the content from the map
if (Package != null && toPackage != Package)
foreach (var file in Package.Contents)
@@ -650,24 +648,8 @@ namespace OpenRA
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<Pair<MPos, Color>>();
foreach (var actor in actors)
{
var s = new ActorReference(actor.Value.Value, actor.Value.ToDictionary());
var ai = Rules.Actors[actor.Value.Value];
var impsis = ai.TraitInfos<IMapPreviewSignatureInfo>();
foreach (var impsi in impsis)
impsi.PopulateMapPreviewSignatureCells(this, ai, s, positions);
}
// ResourceLayer is on world actor, which isn't caught above, so an extra check for it.
var worldActorInfo = Rules.Actors["world"];
var worldimpsis = worldActorInfo.TraitInfos<IMapPreviewSignatureInfo>();
foreach (var worldimpsi in worldimpsis)
worldimpsi.PopulateMapPreviewSignatureCells(this, worldActorInfo, null, positions);
var resources = Rules.Actors["world"].TraitInfos<ResourceTypeInfo>()
.ToDictionary(r => r.ResourceType, r => r.TerrainType);
using (var stream = new MemoryStream())
{
@@ -683,64 +665,61 @@ namespace OpenRA
if (isRectangularIsometric)
bitmapWidth = 2 * bitmapWidth - 1;
var stride = bitmapWidth * 4;
var pxStride = 4;
var minimapData = new byte[stride * height];
Color leftColor, rightColor;
for (var y = 0; y < height; y++)
using (var bitmap = new Bitmap(bitmapWidth, height))
{
for (var x = 0; x < width; x++)
var bitmapData = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
var uv = new MPos(x + Bounds.Left, y + Bounds.Top);
var actorsThere = positions.Where(ap => ap.First == uv);
if (actorsThere.Any())
{
leftColor = rightColor = actorsThere.First().Second;
}
else
{
// Cell contains terrain
var type = tileset.GetTileInfo(Tiles[uv]);
leftColor = type != null ? type.LeftColor : Color.Black;
rightColor = type != null ? type.RightColor : Color.Black;
}
var colors = (int*)bitmapData.Scan0;
var stride = bitmapData.Stride / 4;
Color leftColor, rightColor;
if (isRectangularIsometric)
for (var y = 0; y < height; y++)
{
// Odd rows are shifted right by 1px
var dx = uv.V & 1;
var xOffset = pxStride * (2 * x + dx);
if (x + dx > 0)
for (var x = 0; x < width; x++)
{
var z = y * stride + xOffset - pxStride;
minimapData[z++] = leftColor.R;
minimapData[z++] = leftColor.G;
minimapData[z++] = leftColor.B;
minimapData[z++] = leftColor.A;
}
var uv = new MPos(x + Bounds.Left, y + Bounds.Top);
var resourceType = Resources[uv].Type;
if (resourceType != 0)
{
// Cell contains resources
string res;
if (!resources.TryGetValue(resourceType, out res))
continue;
if (xOffset < stride)
{
var z = y * stride + xOffset;
minimapData[z++] = rightColor.R;
minimapData[z++] = rightColor.G;
minimapData[z++] = rightColor.B;
minimapData[z++] = rightColor.A;
leftColor = rightColor = tileset[tileset.GetTerrainIndex(res)].Color;
}
else
{
// Cell contains terrain
var type = tileset.GetTileInfo(Tiles[uv]);
leftColor = type != null ? type.LeftColor : Color.Black;
rightColor = type != null ? type.RightColor : Color.Black;
}
if (isRectangularIsometric)
{
// Odd rows are shifted right by 1px
var dx = uv.V & 1;
if (x + dx > 0)
colors[y * stride + 2 * x + dx - 1] = leftColor.ToArgb();
if (2 * x + dx < stride)
colors[y * stride + 2 * x + dx] = rightColor.ToArgb();
}
else
colors[y * stride + x] = leftColor.ToArgb();
}
}
else
{
var z = y * stride + pxStride * x;
minimapData[z++] = leftColor.R;
minimapData[z++] = leftColor.G;
minimapData[z++] = leftColor.B;
minimapData[z++] = leftColor.A;
}
}
bitmap.UnlockBits(bitmapData);
bitmap.Save(stream, ImageFormat.Png);
}
var png = new Png(minimapData, bitmapWidth, height);
return png.Save();
return stream.ToArray();
}
}
@@ -752,11 +731,6 @@ namespace OpenRA
if (Grid.Type == MapGridType.RectangularIsometric && cell.X < cell.Y)
return false;
// If the mod uses flat & rectangular maps, ToMPos and Contains(MPos) create unnecessary cost.
// Just check if CPos is within map bounds.
if (Grid.MaximumTerrainHeight == 0 && Grid.Type == MapGridType.Rectangular)
return Bounds.Contains(cell.X, cell.Y);
return Contains(cell.ToMPos(this));
}
@@ -812,7 +786,7 @@ namespace OpenRA
public WPos CenterOfSubCell(CPos cell, SubCell subCell)
{
var index = (int)subCell;
if (index >= 0 && index < Grid.SubCellOffsets.Length)
if (index >= 0 && index <= Grid.SubCellOffsets.Length)
return CenterOfCell(cell) + Grid.SubCellOffsets[index];
return CenterOfCell(cell);
}
@@ -1084,8 +1058,7 @@ namespace OpenRA
var v = rand.Next(Bounds.Top, Bounds.Bottom);
cells = Unproject(new PPos(u, v));
}
while (!cells.Any());
} while (!cells.Any());
return cells.Random(rand).ToCPos(Grid.Type);
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -205,10 +205,6 @@ namespace OpenRA
var yaml = MiniYaml.FromString(data);
foreach (var kv in yaml)
maps[kv.Key].UpdateRemoteSearch(MapStatus.DownloadAvailable, kv.Value, mapDetailsReceived);
foreach (var map in maps)
if (map.Value.Status != MapStatus.DownloadAvailable)
map.Value.UpdateRemoteSearch(MapStatus.Unavailable, null);
}
catch (Exception e)
{
@@ -233,7 +229,7 @@ namespace OpenRA
var maxKeepAlive = 5000 / emptyDelay;
var keepAlive = maxKeepAlive;
while (true)
for (;;)
{
List<MapPreview> todo;
lock (syncRoot)
@@ -336,8 +332,8 @@ namespace OpenRA
if (string.IsNullOrEmpty(initialUid) || previews[initialUid].Status != MapStatus.Available)
{
var selected = previews.Values.Where(IsSuitableInitialMap).RandomOrDefault(random) ??
previews.Values.FirstOrDefault(m => m.Status == MapStatus.Available && m.Visibility.HasFlag(MapVisibility.Lobby));
return selected == null ? string.Empty : selected.Uid;
previews.Values.First(m => m.Status == MapStatus.Available && m.Visibility.HasFlag(MapVisibility.Lobby));
return selected.Uid;
}
return initialUid;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -11,9 +11,9 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA
@@ -168,11 +168,7 @@ namespace OpenRA
if (subCell == SubCell.Invalid || subCell == SubCell.Any)
return WVec.Zero;
var index = (int)subCell;
if (index >= 0 && index < SubCellOffsets.Length)
return SubCellOffsets[index];
return WVec.Zero;
return SubCellOffsets[(int)subCell];
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2018 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
@@ -19,8 +19,7 @@ namespace OpenRA
{
public readonly Dictionary<string, PlayerReference> Players;
public MapPlayers()
: this(new List<MiniYamlNode>()) { }
public MapPlayers() : this(new List<MiniYamlNode>()) { }
public MapPlayers(IEnumerable<MiniYamlNode> playerDefinitions)
{

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