Files
UnrealEngineUWP/Engine/Source/Programs/AutomationTool/Scripts/RunProjectCommand.Automation.cs
Andrew Grant c60ffc4e26 Copying //UE4/Orion-Staging to //UE4/Main (Source: //Orion/Dev-General @ 3316439)
#lockdown Nick.Penwarden

Change 3315047 on 2017/02/21 by Mieszko.Zielinski@mieszko.zielinski_T4675_Orion

	HTN code first check in #UE4

	#rb none
	#test currently unused

Change 3314042 on 2017/02/21 by Jason.Bestimt@Jason.Bestimt_Dev-General

	#ORION_DG - DAILY Main @ CL 3313484

	#RB:none
	#Tests:none

Change 3313355 on 2017/02/20 by Uriel.Doyon@uriel.doyon_PC2_Orion

	Changed the preliminary GPU benchmark workloads to take into account the target workload.
	This is to prevent running the last test with poor performance, risking a driver reset.
	#jira OR-29915
	#rb marcus.wassmer
	#test Run the game triggering benchmarks

Change 3312553 on 2017/02/20 by Mieszko.Zielinski@mieszko.zielinski_T4675_Orion

	Implemented a simple AITask for running EQS queries #UE4

	#rb Lukasz.Furman
	#test golden path

Change 3311661 on 2017/02/20 by Jason.Bestimt@Jason.Bestimt_Dev-General

	#ORION_DG - Merge MAIN @ CL 3311631

	#RB:none
	#Tests:none

Change 3310392 on 2017/02/17 by Daniel.Lamb@daniel.lamb_T3905_6612

	Unreal pak now outputs to named log files instead of timestamps.
	#rb Trivial
	#test Cook deploy paragon
	#jira OR-36057

Change 3310196 on 2017/02/17 by Clayton.Langford@RDU-WD-8359_3635_Paragon_DevGen

	Created an event to be fired whenever a GameplayCue is routed that passes all relevant info about that GC. Added a listener in OrionPhasedFunctionalTest that parses that event into a string and stores it in an array to be accessed from a test phase later.

	#test PIE
	#rb Ben.Salem, Adric.Worley

Change 3308437 on 2017/02/16 by Jason.Bestimt@Jason.Bestimt_Dev-General

	#ORION_DG - Merge MAIN @ CL 3308413
	(Prep for Merge up)

	#RB:none
	#Tests:none

Change 3306497 on 2017/02/16 by Andrew.Grant@andrew.grant.T6730.orion.floating

	Fix for compilation issue with USE_MALLOC_STOMP
	#rb none
	#tests compiled with malloc_stomp

Change 3306468 on 2017/02/16 by Cody.Haskell@OrionStream

	#Orion

	- Text popup work for Shield. If you click on an OrionEditableTextBox while running the game with -gfn, a special popup is called. Should do nothing normally.

	#rb none
	#tests PIE, golden path.

Change 3305945 on 2017/02/16 by David.Ratti@David.Ratti_G6218_Orion.Dev-General

	Remove unused/deprecated UGameplayEffectExtension class
	#rb #tests none

Change 3304630 on 2017/02/15 by Jason.Bestimt@Jason.Bestimt_Dev-General

	#ORION_DG - Merge Mieszko stuff from MAIN to DG

	#RB:none
	#TestS:none

	#!codereview: mieszko.zielinski

Change 3303785 on 2017/02/15 by jason.bestimt@Jason.Bestimt_Dev-General

	#ORION_MAIN - Merge 38.3 @ CL 3303224

	#RB:none
	#Tests:none

	#!ROBOMERGE-SOURCE: CL 3303718 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

	#!ROBOMERGE-SAYS: Unresolved conflicts. jason.bestimt, please merge this change by hand.
	//Orion/Dev-General/OrionGame/Content/UI/DeckBuilder/DeckBuilderRoot.uasset - can't integrate exclusive file already opened
	//Orion/Dev-General/OrionGame/Content/UI/Master_Layouts/FrontEnd.uasset - can't integrate exclusive file already opened
	#!codereview: jason.bestimt

Change 3302382 on 2017/02/14 by Alexis.Matte@amatte-orion-dev-general

	Fix import of morph target when there is no animation
	#jira UE-41383
	#jira OR-35859
	#rb none
	#test none

Change 3301538 on 2017/02/14 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: jason.bestimt
	#ORION_MAIN - Merge 38.3 @ CL 3301392

	#RB:none
	#Tests:none

	#!ROBOMERGE-SOURCE: CL 3301481 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3299985 on 2017/02/13 by Lukasz.Furman@Lukasz.Furman_T7320_OrionStream

	added time limit to "get out of overlap" move for minons to avoid getting stuck in moving to inaccessbile spots
	#jira OR-35834
	#rb Mieszko.Zielinski
	#tests PIE

Change 3299732 on 2017/02/13 by Mieszko.Zielinski@mieszko.zielinski_T4675_Orion

	Tweaked the way EQS tests of negative score get normalized #UE4

	#rb none
	#test golden path + math
	#!codereview Lukasz.Furman, John.Abercrombie

Change 3299724 on 2017/02/13 by Mieszko.Zielinski@mieszko.zielinski_T4675_Orion

	Generic AI interface extensions #UE4

	Mostly getters

	#rb none
	#test golden path

Change 3299717 on 2017/02/13 by Mieszko.Zielinski@mieszko.zielinski_T4675_Orion

	A little tweak to VisLog's point labels drawing - if there's only one point in a set it will no longer append '_0' to the label #UE4

	#rb none
	#test PIE

Change 3299527 on 2017/02/13 by Paul.Moore@OrionWorkspace_Dev-General

	#orion #mms
	- Update libWebSockets binaries to fix Linux server web socket connections.
	#tests matchmaking, mms
	#rb none

Change 3299278 on 2017/02/13 by David.Ratti@David.Ratti_G6218_Orion.Dev-General

	Ability Task Pass: tasks should not broadcast out (back into ability graph) if the owning ability has completed EndAbility.
	#rb none
	#tests pie, golden path

Change 3297884 on 2017/02/10 by Paul.Moore@OrionWorkspace_Dev-General

	#mms
	- Enable SSL module for PS4 (needed by OpenSSL when using WebSockets).
	- Turn on verbose logging for WebSockets module for initial MMS debugging.
	#tests PS4
	#rb none

Change 3296911 on 2017/02/10 by John.Pollard@John.Pollard_T2802_Orion_DevGeneral

	Encode user search string so we support special characters

	#rb RyanG
	#tests Replays

Change 3296746 on 2017/02/10 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: jason.bestimt
	#ORION_MAIN - Merge 38.3 @ CL 3296659

	#RB:none
	#Tests:none

	#!ROBOMERGE-SOURCE: CL 3296735 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3296705 on 2017/02/10 by Daniel.Lamb@daniel.lamb_T3905_6612

	Added support to the cooker for iterating shared builds.
	#rb Not used yet
	#test Fast cook paragon

Change 3295747 on 2017/02/09 by Paul.Moore@OrionWorkspace_Dev-General

	#orion #mms
	- Integrated WS upgrade header functionality with latest Fortnite libws changes.
	- Added "ws" and "wss" protocols to web socket manager context.
	#rb rob.cannaday
	#!codereview rob.cannaday, james.hopkin
	#tests win64, ps4

Change 3295579 on 2017/02/09 by John.Pollard@John.Pollard_T2802_Orion_DevGeneral

	Fix for replay backward compatibility from John.Pollard
	#tests #rb na

	Merging using OrionScratchReleaseMapping

Change 3295506 on 2017/02/09 by Rolando.Caloca@rolando.caloca_T3903_OrionMainS

	O - Added option for force recompute tangents using skin cache
	#rb none
	#jira UE-41541
	#tests Editor run, toggle, restart

Change 3295461 on 2017/02/09 by Lukasz.Furman@Lukasz.Furman_T7320_OrionStream

	fixed huge interpolation times for linear network smoothing on stationary characters,
	fixed mismatch in movement Base between NavWalking server and Walking client, causing some stationary characters to float in midair

	copy of CL# 3295439
	#jira OR-35664, OR-35572
	#rb none
	#tests game

Change 3294954 on 2017/02/09 by Paul.Moore@OrionWorkspace_Dev-General

	#orion #mms

	- Integrating Fortnite WebSocket changes into Orion that fixes some win10 issues.

	#!codereview rob.cannaday, james.hopkin
	#tests compile ps4, linux, win64
	#rb none

Change 3294947 on 2017/02/09 by Daniel.Lamb@daniel.lamb_T3905_6612

	The generate stub return result is considered as success when saving cooked packages.
	Fixes bug with cooking blueprint nativized packages.
	#rb Trivial
	#test Cook paragon

Change 3293307 on 2017/02/08 by Andrew.Grant@andrew.grant.T6730.orion.floating

	Fix for issue in last checkin - need to clear activecontext regardless
	#rb none
	#tests solo smoke with nullrhi

Change 3293284 on 2017/02/08 by Ryan.Gerleve@Ryan.Gerleve_T3703_Orion

	Allow setting the per-frame time limit for processing queued bunches separately for instant replays, since they may have more strict timing/framerate requirements.

	#rb john.pollard
	#tests golden path

Change 3293148 on 2017/02/08 by Andrew.Grant@andrew.grant.T6730.orion.floating

	Fixed invalid memory access* with nullrhi and suppressed IME warning if no valid window handle exists

	(*Likely only an issue when running with memory validation)

	#rb none
	#tests verified invalid access exception no longer occurs with nullrhi
	#!review-3293149 @Matt.Khulenschmidt

Change 3293103 on 2017/02/08 by Max.Chen@Max.Chen_T4664_Orion_Main

	Sequencer: Fix build

	#jira OR-34918
	#rb none
	#tests none

Change 3292921 on 2017/02/08 by Max.Chen@Max.Chen_T4664_Orion_Main

	Sequencer: Force local player to maintain x fov axis.

	#jira OR-34918
	#rb david.ratti
	#tests Render/PIE a level sequence and test that the camera isn't zoomed in.

Change 3292869 on 2017/02/08 by David.Ratti@David.Ratti_G6218_Orion.Dev-General

	Yet more logging for OR-35448
	#rb #tests none

Change 3292821 on 2017/02/08 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: rob.cannaday
	PS4 libwebsockets build fix
	Update build cs files to point to PS4 file location
	Copy libwebsocket include directory from Fortnite to Orion
	#rb paul.moore
	#tests compile/link Win64 Development Editor, PS4 Debug, Linux Development Server

	#!ROBOMERGE-SOURCE: CL 3292820 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3292277 on 2017/02/08 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: jason.bestimt
	#ORION_MAIN - Merge DMM @ CL 3292219

	#RB:none
	#Tests:none

	[CODEREVIEW] paul.moore, benjamin.crocker
	#QAReview

	#!ROBOMERGE-SOURCE: CL 3292276 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3292211 on 2017/02/08 by Andrew.Grant@andrew.grant.T6730.orion.floating

	Pulling new ags library from Release-4.15 and reverting hack that disabled feature for AMD users
	#rb Marcus.Wassmer
	#tests compiled

Change 3292167 on 2017/02/08 by David.Ratti@David.Ratti_G6218_Orion.Dev-General

	Additional logging for OR-35448
	#rb none
	#tests pie

Change 3289462 on 2017/02/06 by Ben.Salem@ben.salem_OrionMain

	Adding priority filters to Automation tests, also commands to filter on priority levels.
	#rb adric worley
	#tests Compiled, ran a few commands to verify it works.

Change 3288801 on 2017/02/06 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: jason.bestimt
	#ORION_MAIN - Merge 37.2 (38.3) @ CL 3288681

	#RB:none
	#Tests:none

	#!ROBOMERGE-SOURCE: CL 3288800 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3288750 on 2017/02/06 by Daniel.Lamb@daniel.lamb_T3905_6612

	Fixed issue when cooking client and server platforms in single cook some packages would be marked incorrectly because they would be stripped when from client / server.
	#rb Andrew.Grant
	#test Cook paragon

Change 3288624 on 2017/02/06 by Andrew.Grant@andrew.grant.T6730.orion.floating

	Unlocked network version
	#rb #tests na
	OR-35603

Change 3288612 on 2017/02/06 by Daniel.Lamb@daniel.lamb_T3905_6612

	Added more ini settings to the iterative ini blacklist.
	#rb Trivial
	#test Iterative Cook Paragon

Change 3288184 on 2017/02/06 by Andrew.Grant@andrew.grant.T6730.orion.floating

	Downgraded warning to display
	#!review-3288185 @David.Ratti
	#rb none
	#tests none

Change 3287634 on 2017/02/06 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: jason.bestimt
	#ORION_MAIN - Merge 37.2 @ 3287498

	#RB:none
	#Tests:none

	#!ROBOMERGE-SOURCE: CL 3287619 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3286668 on 2017/02/03 by Alexis.Matte@amatte-orion-dev-general

	Fix a crash when importing a LOD containing different material with less sections
	#rb none
	#test none

Change 3286112 on 2017/02/03 by Alexis.Matte@amatte-orion-dev-general

	Fix the re-import skeletal mesh regression, where all material disapear.
	#jira UE-41294
	#rb matt.kuhlenschmidt
	#test see the jira

Change 3285859 on 2017/02/03 by Daniel.Lamb@daniel.lamb_T3905_6612

	Fixed merge error from last checkin with the DDC commandlet
	#!codereview Matthew.Griffin
	#test DDC commandlet paragon
	#rb None

Change 3285637 on 2017/02/03 by Ryan.Gerleve@Ryan.Gerleve_T3703_Orion

	Pass in the DemoNetDriver pointer to the ConcurrentWithSlateTickTask instead of accessing it from the world in the task itself.

	#rb john.pollard
	#tests golden path

Change 3285479 on 2017/02/03 by Mieszko.Zielinski@mieszko.zielinski_T4675_Orion

	Made bot communicate ults when they're up, not when they're using it #Orion

	CL also contains a bit of code shuffling around, preparing ground for HTN plug in

	#rb none
	#test golden path

Change 3285125 on 2017/02/03 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: jason.bestimt
	#ORION_MAIN - Merge 37.2 @ CL 3285078

	#RB:none
	#Tests:none

	#!ROBOMERGE-SOURCE: CL 3285124 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3283996 on 2017/02/02 by Michael.Trepka@Michael.Trepka_PC_Orion-Dev-General

	Added UGameUserSettings::GetRecommandedResolutionScale() to replace UOrionGameUserSettings::GetDefaultResolutionScale(). This makes things less confusing (UGameUserSettings::GetRecommandedResolutionScale() returns scale recommended based on results of the benchmark and UGameUserSettings::GetDefaultResolutionScale() returns scale based on user settings) and fixes a regression introduced in 3257936 (OR-35544)

	#rb Cody.Haskell
	#tests Tested on PC

Change 3283951 on 2017/02/02 by Daniel.Lamb@daniel.lamb_T3905_6612

	Ensure DDC commandlet calls begincacheforcookedplatformdata correctly.
	#rb None
	#!codereview Matthew.Griffin
	#test DDC commandlet paragon.

Change 3283874 on 2017/02/02 by Lina.Halper@Lina.Halper_Orion

	fix for invalid resource issue

	#rb: none
	#code review: Daniel.Wright
	#tests: compile and editor with wolf

Change 3283621 on 2017/02/02 by Laurent.Delayen@laurent.delayen_Work2016_Orion

	Femme WIP whip aiming for Q ability.

	#rb none
	#tests Femme

Change 3283216 on 2017/02/02 by jason.bestimt@Jason.Bestimt_Dev-General

	#ORION_MAIN - Merge 37.2 @ CL 3282900

	#RB:none
	#Tests:none

	#!ROBOMERGE-SOURCE: CL 3283199 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3282954 on 2017/02/02 by Lina.Halper@Lina.Halper_Orion

	It becomes invalid on the resource, so checking null, but still wip on verifying this with Daniel Wright. He's sick out.

	#rb:none
	#tests: compile
	#code review:Daniel.Wright
	#Jira: OR-35418

Change 3281993 on 2017/02/01 by Daniel.Lamb@daniel.lamb_T3905_6612

	Removed default unattended flag.
	#rb Trivial
	#test PS4 cook run paragon.

Change 3281990 on 2017/02/01 by Daniel.Lamb@daniel.lamb_T3905_6612

	Potential fix for deterministic cooking issue with UMovieSceneSignedObjects.
	#rb Andrew.Grant
	#!codereview Max.Preussner
	#test Cook and run paragon ps4.

Change 3281610 on 2017/02/01 by Laurent.Delayen@laurent.delayen_Work2016_Orion

	AimOffsetLookAt is now thread safe.

	#rb lina.halper
	#tests femme

Change 3281609 on 2017/02/01 by Laurent.Delayen@laurent.delayen_Work2016_Orion

	Fixed 'Convert to AimOffset LookAt' option being broken in Persona.

	#rb lina.halper
	#tests works for Femme now.

Change 3281019 on 2017/02/01 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: jason.bestimt
	#ORION_MAIN - Merge 37.2 @ CL 3280498

	#RB:none
	#Tests:none

	#!ROBOMERGE-SOURCE: CL 3281018 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3280813 on 2017/02/01 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: matthew.griffin
	Prevent inclusion of NotForLicensees files when staging CrashReportClient config files
	#rb none
	#tests none

	#!ROBOMERGE-SOURCE: CL 3280812 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3279921 on 2017/01/31 by Yanni.Tripolitis@yanni.tripolitis_Dev_General_Cary

	Fixed an error in the Round MF, that was somehow "leaked" into Paragon from Odin.

	#lockdown Billy.Rivers, Adam.Bellefeuil

	#!codereview Tim.Elek

Change 3279178 on 2017/01/31 by Daniel.Lamb@daniel.lamb_T3905_6612

	Fixed up diff files commandlet stack information
	#rb Joe.Conley
	#test Diff cooked packages

Change 3279084 on 2017/01/31 by Andrew.Grant@andrew.grant.T6730.orion.floating

	Merging //UE4/Main at 3276432  through Orion-Staging
	#rb #tests na

Change 3279078 on 2017/01/31 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: jason.bestimt
	#ORION_MAIN - Merge 37.2 @ CL 3279032

	#RB:none
	#Tests:none

	#!ROBOMERGE-SOURCE: CL 3279077 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3277908 on 2017/01/30 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: jason.bestimt
	#ORION_37 - Fix for "-game" crash with missing meta data

	#RB:none
	#Tests:none

	[CodeReviewed]: andrew.grant, jamie.dale, mieszko.zielinski

	#!ROBOMERGE-SOURCE: CL 3277901 in //Orion/Release-37/... via CL 3277902 via CL 3277904 via CL 3277905
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3277520 on 2017/01/30 by Andrew.Grant@andrew.grant.T6730.orion.floating

	Workaround for OR-35418
	#!ROBOMERGE: Main
	#rb none
	#tests verified ShortSoloGame test completes without a crash

Change 3277357 on 2017/01/30 by Daniel.Lamb@daniel.lamb_T3905_6612

	Fixed the rebuild lighting commandlet.
	#rb Trivial
	#test Rebuild lighting dev general

Change 3277322 on 2017/01/30 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: jason.bestimt
	#ORION_MAIN - Merge 37.2 @ CL 3277275

	#RB:none
	#Tests:none

	#!ROBOMERGE-SOURCE: CL 3277296 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3277210 on 2017/01/30 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: andrew.grant
	Non-shipping test changes:

	Fixed issue where with -stdout messages would be duplicated due to FeedbackContextAnsi echoing to stdout by default
	Changed stdout output to postfix instead of trail newlines
	Firstpass of finding and displaying crash callstacks in Orion Test Framework.

	#rb none
	#tests ran test framework with tests that purposefully crashed/checked

	#!ROBOMERGE-SOURCE: CL 3276889 in //Orion/Release-37/... via CL 3277207 via CL 3277208 via CL 3277209
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3276774 on 2017/01/29 by Andrew.Grant@andrew.grant.T6730.orion.floating

	Fix for non-unity issue.
	#tests compiled
	#rb none
	#!ROBOMERGE: Main, DUI

Change 3276594 on 2017/01/28 by Lina.Halper@Lina.Halper_Orion

	Checked in potential fix for nonunity build issue

	#rb:none
	#tests:compile

Change 3275806 on 2017/01/27 by Ben.Salem@ben.salem_OrionMain

	Adding in a checkpointing system for automated test passes where, if a client crashes while running a pass, on reboot and reissue of the automation command the test pass will start off where it left off, skipping the crashing test.
	#rb clayton.langford
	#tests Ran several dozen test passses. Seriously.
	#!codereview steve.white, bob.ferreira, clayton.langford, adric.worley

Change 3275803 on 2017/01/27 by Shaun.Kime@shaun.kime_RDU-WD-9788_oriondevgen

	Paragon has retainer widgets with no World set. When encountered, they can cause the scene list to be desynchronized with the rendering thread.
	This logic resolves the issue by registering a null scene in this case, properly setting the slate scene index for subsequent slate draw calls.

	#rb nick.darnell
	#jira OR-34919
	#TESTS na

Change 3275533 on 2017/01/27 by Max.Chen@Max.Chen_T4664_Orion_Main

	Sequencer: Switch to static pointer to fix crash when tearing down curve editor.

	#jira UE-40796
	#rb andrew.rodham
	#tests none

Change 3275093 on 2017/01/27 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: jason.bestimt
	#ORION_MAIN - Merge 37.2 @ CL 3273298

	#RB:none
	#Tests:none

	#!ROBOMERGE-SOURCE: CL 3273417 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3274700 on 2017/01/26 by Lina.Halper@Lina.Halper_Orion

	#Anim curve crash on cooking
	- fixed crash during cooking while accessing default value of material
	- this code doesn't have to run during cooking with inactive world, so I'm checking that

	#code review: Daniel.Wright, Chris.Bunner, Jurre.DeBaare
	#rb: none
	#tests: cooking

Change 3274129 on 2017/01/26 by Lina.Halper@Lina.Halper_Orion

	Fixed safer to get featurelevel

	#rb: Daniel.Wright
	#tests: compile/wolf

Change 3274012 on 2017/01/26 by Lukasz.Furman@Lukasz.Furman_T7320_OrionStream

	fixed crash in navigation grids
	#jira OR-35356
	#rb none
	#tests PIE

Change 3273803 on 2017/01/26 by Lina.Halper@Lina.Halper_Orion

	Fixed issue with animation curve getting reset to 0.f
	- the issue is that skeleton contains material flag types, so now it just keeps setting the value
	- even after I fix validation check, it still cleared it due to the material curve not found anymore, so added to support default value setting

	#jira: OR-34563
	#rb: Martin.Wilson, Chris.Bunner, Benn.Gallagher
	#code review: Martin.Wilson, Daniel.Wright
	#tests: wolf, coil

Change 3273257 on 2017/01/26 by Alexis.Matte@amatte-orion-dev-general

	Isolate by material slot instead of section index. Add UI to isolate and highlight material in the material panel
	#rb matt.kuhlenschmidt
	#jira UE-41131
	#tests none

Change 3272527 on 2017/01/25 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: chris.bunner
	Ensure FSceneRenderTargets snapshot copies default clear colors.
	#tests Golden path on lowest and high settings
	#rb None
	#lockdown Jason.Bestimt
	#jira OR-34905

	#!ROBOMERGE-SOURCE: CL 3272507 in //Orion/Release-37.1/... via CL 3272521 via CL 3272525
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3272244 on 2017/01/25 by Rolando.Caloca@rolando.caloca_T3903_OrionMainS

	Show more info when a material instance failed to compile
	#jira OR-34626
	#tests Forced crash in the debugger
	#rb Daniel.Wright

Change 3272109 on 2017/01/25 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: philip.buuck
	Fix bad merge from Main

	#rb Dan.Hertzka
	#tests PIE
	[CodeReviewed] Andrew.Grant
	#lockdown Andrew.Grant

	#!ROBOMERGE-SOURCE: CL 3272106 in //Orion/Release-37.1/... via CL 3272107 via CL 3272108
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

Change 3271721 on 2017/01/25 by Lukasz.Furman@Lukasz.Furman_T7320_OrionStream

	jungle minions will spawn navigation obstacles when they are stuck in static geometry, fixed issues with falling off cliffs
	#jira OR-35054
	#rb Mieszko.Zielinski
	#tests PIE

Change 3271432 on 2017/01/25 by Jason.Bestimt@ROBOMERGE_ORION_Dev_General

	#!ROBOMERGE-AUTHOR: jason.bestimt
	#ORION_MAIN - Merge 37.2 @ CL 3271043

	#RB:none
	#Tests:none

	#!ROBOMERGE-SOURCE: CL 3271429 in //Orion/Main/...
	#!ROBOMERGE-BOT: ORION (Main -> Dev-General)

[CL 3322856 by Andrew Grant in Main branch]
2017-02-25 19:37:22 -05:00

1096 lines
34 KiB
C#

// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using System.Reflection;
using System.Linq;
using System.Net.NetworkInformation;
using System.Collections;
using AutomationTool;
using UnrealBuildTool;
/// <summary>
/// Helper command to run a game.
/// </summary>
/// <remarks>
/// Uses the following command line params:
/// -cooked
/// -cookonthefly
/// -dedicatedserver
/// -win32
/// -noclient
/// -logwindow
/// </remarks>
public partial class Project : CommandUtils
{
#region Fields
/// <summary>
/// Thread used to read client log file.
/// </summary>
private static Thread ClientLogReaderThread = null;
/// <summary>
/// Process for the server, can be set by the cook command when a cook on the fly server is used
/// </summary>
public static IProcessResult ServerProcess;
#endregion
#region Run Command
// debug commands for the engine to crash
public static string[] CrashCommands =
{
"crash",
"CHECK",
"GPF",
"ASSERT",
"ENSURE",
"RENDERCRASH",
"RENDERCHECK",
"RENDERGPF",
"THREADCRASH",
"THREADCHECK",
"THREADGPF",
};
/// <summary>
/// For not-installed runs, returns a temp log folder to make sure it doesn't fall into sandbox paths
/// </summary>
/// <returns></returns>
private static string GetLogFolderOutsideOfSandbox()
{
return GlobalCommandLine.Installed ?
CmdEnv.LogFolder :
CombinePaths(Path.GetTempPath(), CommandUtils.EscapePath(CmdEnv.LocalRoot), "Logs");
}
/// <summary>
/// Fot not-installed runs, copies all logs from the temp log folder back to the UAT log folder.
/// </summary>
private static void CopyLogsBackToLogFolder()
{
if (!GlobalCommandLine.Installed)
{
var LogFolderOutsideOfSandbox = GetLogFolderOutsideOfSandbox();
var TempLogFiles = FindFiles_NoExceptions("*", false, LogFolderOutsideOfSandbox);
foreach (var LogFilename in TempLogFiles)
{
var DestFilename = CombinePaths(CmdEnv.LogFolder, Path.GetFileName(LogFilename));
CopyFile_NoExceptions(LogFilename, DestFilename);
}
}
}
public static void Run(ProjectParams Params)
{
Params.ValidateAndLog();
if (!Params.Run)
{
return;
}
Log("********** RUN COMMAND STARTED **********");
var LogFolderOutsideOfSandbox = GetLogFolderOutsideOfSandbox();
if (!GlobalCommandLine.Installed && ServerProcess == null)
{
// In the installed runs, this is the same folder as CmdEnv.LogFolder so delete only in not-installed
DeleteDirectory(LogFolderOutsideOfSandbox);
CreateDirectory(LogFolderOutsideOfSandbox);
}
var ServerLogFile = CombinePaths(LogFolderOutsideOfSandbox, "Server.log");
var ClientLogFile = CombinePaths(LogFolderOutsideOfSandbox, Params.EditorTest ? "Editor.log" : "Client.log");
try
{
RunInternal(Params, ServerLogFile, ClientLogFile);
}
catch
{
throw;
}
finally
{
CopyLogsBackToLogFolder();
}
Log("********** RUN COMMAND COMPLETED **********");
}
private static void RunInternal(ProjectParams Params, string ServerLogFile, string ClientLogFile)
{
// Setup server process if required.
if (Params.DedicatedServer && !Params.SkipServer)
{
if (Params.ServerTargetPlatforms.Count > 0)
{
TargetPlatformDescriptor ServerPlatformDesc = Params.ServerTargetPlatforms[0];
ServerProcess = RunDedicatedServer(Params, ServerLogFile, Params.RunCommandline);
// With dedicated server, the client connects to local host to load a map.
if (ServerPlatformDesc.Type == UnrealTargetPlatform.Linux)
{
Params.MapToRun = Params.ServerDeviceAddress;
}
else
{
Params.MapToRun = "127.0.0.1";
}
}
else
{
throw new AutomationException("Failed to run, server target platform not specified");
}
}
else if (Params.FileServer && !Params.SkipServer)
{
ServerProcess = RunFileServer(Params, ServerLogFile, Params.RunCommandline);
}
if (ServerProcess != null)
{
Log("Waiting a few seconds for the server to start...");
Thread.Sleep(5000);
}
if (!Params.NoClient)
{
Log("Starting Client....");
var SC = CreateDeploymentContext(Params, false);
ERunOptions ClientRunFlags;
string ClientApp;
string ClientCmdLine;
SetupClientParams(SC, Params, ClientLogFile, out ClientRunFlags, out ClientApp, out ClientCmdLine);
// Run the client.
if (ServerProcess != null)
{
RunClientWithServer(SC, ServerLogFile, ServerProcess, ClientApp, ClientCmdLine, ClientRunFlags, ClientLogFile, Params);
}
else
{
RunStandaloneClient(SC, ClientLogFile, ClientRunFlags, ClientApp, ClientCmdLine, Params);
}
}
}
#endregion
#region Client
private static void RunStandaloneClient(List<DeploymentContext> DeployContextList, string ClientLogFile, ERunOptions ClientRunFlags, string ClientApp, string ClientCmdLine, ProjectParams Params)
{
if (Params.Unattended)
{
string LookFor = "Bringing up level for play took";
bool bCommandlet = false;
if (Params.RunAutomationTest != "")
{
LookFor = "Automation Test Succeeded";
}
else if (Params.RunAutomationTests)
{
LookFor = "Automation Test Queue Empty";
}
else if (Params.EditorTest)
{
LookFor = "Asset discovery search completed in";
}
// If running a commandlet, just detect a normal exit
else if (ClientCmdLine.IndexOf("-run=", StringComparison.InvariantCultureIgnoreCase) >= 0)
{
LookFor = "Game engine shut down";
bCommandlet = true;
}
{
string AllClientOutput = "";
int LastAutoFailIndex = -1;
IProcessResult ClientProcess = null;
FileStream ClientProcessLog = null;
StreamReader ClientLogReader = null;
Log("Starting Client for unattended test....");
ClientProcess = Run(ClientApp, ClientCmdLine + " -testexit=\"" + LookFor + "\"", null, ClientRunFlags | ERunOptions.NoWaitForExit);
while (!FileExists(ClientLogFile) && !ClientProcess.HasExited)
{
Log("Waiting for client logging process to start...{0}", ClientLogFile);
Thread.Sleep(2000);
}
if (FileExists(ClientLogFile))
{
Thread.Sleep(2000);
Log("Client logging process started...{0}", ClientLogFile);
ClientProcessLog = File.Open(ClientLogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
ClientLogReader = new StreamReader(ClientProcessLog);
}
if (ClientLogReader == null)
{
throw new AutomationException("Client exited without creating a log file.");
}
bool bKeepReading = true;
bool WelcomedCorrectly = false;
bool bClientExited = false;
DateTime ExitTime = DateTime.UtcNow;
while (bKeepReading)
{
if (!bClientExited && ClientProcess.HasExited)
{
ExitTime = DateTime.UtcNow;
bClientExited = true;
}
string ClientOutput = ClientLogReader.ReadToEnd();
if (!String.IsNullOrEmpty(ClientOutput))
{
if (bClientExited)
{
ExitTime = DateTime.UtcNow; // as long as it is spewing, we reset the timer
}
AllClientOutput += ClientOutput;
Console.Write(ClientOutput);
if (AllClientOutput.LastIndexOf(LookFor) > AllClientOutput.IndexOf(LookFor))
{
WelcomedCorrectly = true;
Log("Test complete...");
bKeepReading = false;
}
else if (Params.RunAutomationTests)
{
int FailIndex = AllClientOutput.LastIndexOf("Automation Test Failed");
int ParenIndex = AllClientOutput.LastIndexOf(")");
if (FailIndex >= 0 && ParenIndex > FailIndex && FailIndex > LastAutoFailIndex)
{
string Tail = AllClientOutput.Substring(FailIndex);
int CloseParenIndex = Tail.IndexOf(")");
int OpenParenIndex = Tail.IndexOf("(");
string Test = "";
if (OpenParenIndex >= 0 && CloseParenIndex > OpenParenIndex)
{
Test = Tail.Substring(OpenParenIndex + 1, CloseParenIndex - OpenParenIndex - 1);
LogError("Automated test failed ({0}).", Test);
LastAutoFailIndex = FailIndex;
}
}
}
// Detect commandlet failure
else if (bCommandlet)
{
const string ResultLog = "Commandlet->Main return this error code: ";
int ResultStart = AllClientOutput.LastIndexOf(ResultLog);
int ResultValIdx = ResultStart + ResultLog.Length;
if (ResultStart >= 0 && ResultValIdx < AllClientOutput.Length &&
AllClientOutput.Substring(ResultValIdx, 1) == "1")
{
// Parse the full commandlet warning/error summary
string FullSummary = "";
int SummaryStart = AllClientOutput.LastIndexOf("Warning/Error Summary");
if (SummaryStart >= 0 && SummaryStart < ResultStart)
{
FullSummary = AllClientOutput.Substring(SummaryStart, ResultStart - SummaryStart);
}
if (FullSummary.Length > 0)
{
LogError("Commandlet failed, summary:" + Environment.NewLine +
FullSummary);
}
else
{
LogError("Commandlet failed.");
}
}
}
}
else if (bClientExited && (DateTime.UtcNow - ExitTime).TotalSeconds > 30)
{
Log("Client exited and has been quiet for 30 seconds...exiting");
bKeepReading = false;
}
}
if (ClientProcess != null && !ClientProcess.HasExited)
{
Log("Client is supposed to exit, lets wait a while for it to exit naturally...");
for (int i = 0; i < 120 && !ClientProcess.HasExited; i++)
{
Thread.Sleep(1000);
}
}
if (ClientProcess != null && !ClientProcess.HasExited)
{
Log("Stopping client...");
ClientProcess.StopProcess();
Thread.Sleep(10000);
}
while (ClientLogReader != null && !ClientLogReader.EndOfStream)
{
string ClientOutput = ClientLogReader.ReadToEnd();
if (!String.IsNullOrEmpty(ClientOutput))
{
Console.Write(ClientOutput);
}
}
if (!WelcomedCorrectly)
{
throw new AutomationException("Client exited before we asked it to.");
}
}
}
else
{
var SC = DeployContextList[0];
IProcessResult ClientProcess = SC.StageTargetPlatform.RunClient(ClientRunFlags, ClientApp, ClientCmdLine, Params);
if (ClientProcess != null)
{
// If the client runs without StdOut redirect we're going to read the log output directly from log file on
// a separate thread.
if ((ClientRunFlags & ERunOptions.NoStdOutRedirect) == ERunOptions.NoStdOutRedirect)
{
ClientLogReaderThread = new System.Threading.Thread(ClientLogReaderProc);
ClientLogReaderThread.Start(new object[] { ClientLogFile, ClientProcess });
}
do
{
Thread.Sleep(100);
}
while (ClientProcess.HasExited == false);
SC.StageTargetPlatform.PostRunClient(ClientProcess, Params);
// any non-zero exit code should propagate an exception. The Virtual function above may have
// already thrown a more specific exception or given a more specific ErrorCode, but this catches the rest.
if (ClientProcess.ExitCode != 0)
{
throw new AutomationException("Client exited with error code: " + ClientProcess.ExitCode);
}
}
}
}
private static void RunClientWithServer(List<DeploymentContext> DeployContextList, string ServerLogFile, IProcessResult ServerProcess, string ClientApp, string ClientCmdLine, ERunOptions ClientRunFlags, string ClientLogFile, ProjectParams Params)
{
IProcessResult ClientProcess = null;
var OtherClients = new List<IProcessResult>();
bool WelcomedCorrectly = false;
int NumClients = Params.NumClients;
string AllClientOutput = "";
int LastAutoFailIndex = -1;
if (Params.Unattended)
{
string LookFor = "Bringing up level for play took";
if (Params.DedicatedServer)
{
LookFor = "Welcomed by server";
}
else if (Params.RunAutomationTest != "")
{
LookFor = "Automation Test Succeeded";
}
else if (Params.RunAutomationTests)
{
LookFor = "Automation Test Queue Empty";
}
{
while (!FileExists(ServerLogFile) && !ServerProcess.HasExited)
{
Log("Waiting for logging process to start...");
Thread.Sleep(2000);
}
Thread.Sleep(1000);
string AllServerOutput = "";
using (FileStream ProcessLog = File.Open(ServerLogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
StreamReader LogReader = new StreamReader(ProcessLog);
bool bKeepReading = true;
FileStream ClientProcessLog = null;
StreamReader ClientLogReader = null;
// Read until the process has exited.
while (!ServerProcess.HasExited && bKeepReading)
{
while (!LogReader.EndOfStream && bKeepReading && ClientProcess == null)
{
string Output = LogReader.ReadToEnd();
if (!String.IsNullOrEmpty(Output))
{
AllServerOutput += Output;
if (ClientProcess == null &&
(AllServerOutput.Contains("Game Engine Initialized") || AllServerOutput.Contains("Unreal Network File Server is ready")))
{
Log("Starting Client for unattended test....");
ClientProcess = Run(ClientApp, ClientCmdLine + " -testexit=\"" + LookFor + "\"", null, ClientRunFlags | ERunOptions.NoWaitForExit);
//@todo no testing is done on these
if (NumClients > 1 && NumClients < 9)
{
for (int i = 1; i < NumClients; i++)
{
Log("Starting Extra Client....");
OtherClients.Add(Run(ClientApp, ClientCmdLine, null, ClientRunFlags | ERunOptions.NoWaitForExit));
}
}
while (!FileExists(ClientLogFile) && !ClientProcess.HasExited)
{
Log("Waiting for client logging process to start...{0}", ClientLogFile);
Thread.Sleep(2000);
}
if (!ClientProcess.HasExited)
{
Thread.Sleep(2000);
Log("Client logging process started...{0}", ClientLogFile);
ClientProcessLog = File.Open(ClientLogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
ClientLogReader = new StreamReader(ClientProcessLog);
}
}
else if (ClientProcess == null && !ServerProcess.HasExited)
{
Log("Waiting for server to start....");
Thread.Sleep(2000);
}
if (ClientProcess != null && ClientProcess.HasExited)
{
ServerProcess.StopProcess();
throw new AutomationException("Client exited before we asked it to.");
}
}
}
if (ClientLogReader != null)
{
if (ClientProcess.HasExited)
{
ServerProcess.StopProcess();
throw new AutomationException("Client exited or closed the log before we asked it to.");
}
while (!ClientProcess.HasExited && !ServerProcess.HasExited && bKeepReading)
{
while (!ClientLogReader.EndOfStream && bKeepReading && !ServerProcess.HasExited && !ClientProcess.HasExited)
{
string ClientOutput = ClientLogReader.ReadToEnd();
if (!String.IsNullOrEmpty(ClientOutput))
{
AllClientOutput += ClientOutput;
Console.Write(ClientOutput);
if (AllClientOutput.LastIndexOf(LookFor) > AllClientOutput.IndexOf(LookFor))
{
if (Params.FakeClient)
{
Log("Welcomed by server or client loaded, lets wait ten minutes...");
Thread.Sleep(60000 * 10);
}
else
{
Log("Welcomed by server or client loaded, lets wait 30 seconds...");
Thread.Sleep(30000);
}
WelcomedCorrectly = true;
bKeepReading = false;
}
else if (Params.RunAutomationTests)
{
int FailIndex = AllClientOutput.LastIndexOf("Automation Test Failed");
int ParenIndex = AllClientOutput.LastIndexOf(")");
if (FailIndex >= 0 && ParenIndex > FailIndex && FailIndex > LastAutoFailIndex)
{
string Tail = AllClientOutput.Substring(FailIndex);
int CloseParenIndex = Tail.IndexOf(")");
int OpenParenIndex = Tail.IndexOf("(");
string Test = "";
if (OpenParenIndex >= 0 && CloseParenIndex > OpenParenIndex)
{
Test = Tail.Substring(OpenParenIndex + 1, CloseParenIndex - OpenParenIndex - 1);
LogError("Automated test failed ({0}).", Test);
LastAutoFailIndex = FailIndex;
}
}
}
}
}
}
}
}
}
}
}
else
{
LogFileReaderProcess(ServerLogFile, ServerProcess, (string Output) =>
{
bool bKeepReading = true;
if (ClientProcess == null && !String.IsNullOrEmpty(Output))
{
AllClientOutput += Output;
if (ClientProcess == null && (AllClientOutput.Contains("Game Engine Initialized") || AllClientOutput.Contains("Unreal Network File Server is ready")))
{
Log("Starting Client....");
var SC = DeployContextList[0];
ClientProcess = SC.StageTargetPlatform.RunClient(ClientRunFlags | ERunOptions.NoWaitForExit, ClientApp, ClientCmdLine, Params);
// ClientProcess = Run(ClientApp, ClientCmdLine, null, ClientRunFlags | ERunOptions.NoWaitForExit);
if (NumClients > 1 && NumClients < 9)
{
for (int i = 1; i < NumClients; i++)
{
Log("Starting Extra Client....");
IProcessResult NewClient = SC.StageTargetPlatform.RunClient(ClientRunFlags | ERunOptions.NoWaitForExit, ClientApp, ClientCmdLine, Params);
OtherClients.Add(NewClient);
}
}
}
}
else if (ClientProcess == null && !ServerProcess.HasExited)
{
Log("Waiting for server to start....");
Thread.Sleep(2000);
}
if (String.IsNullOrEmpty(Output) == false)
{
Console.Write(Output);
}
if (ClientProcess != null && ClientProcess.HasExited)
{
Log("Client exited, stopping server....");
if (!GlobalCommandLine.NoKill)
{
ServerProcess.StopProcess();
}
bKeepReading = false;
}
return bKeepReading; // Keep reading
});
}
Log("Server exited....");
if (ClientProcess != null && !ClientProcess.HasExited)
{
ClientProcess.StopProcess();
}
foreach (var OtherClient in OtherClients)
{
if (OtherClient != null && !OtherClient.HasExited)
{
OtherClient.StopProcess();
}
}
if (Params.Unattended)
{
if (!WelcomedCorrectly)
{
throw new AutomationException("Server or client exited before we asked it to.");
}
}
}
private static void SetupClientParams(List<DeploymentContext> DeployContextList, ProjectParams Params, string ClientLogFile, out ERunOptions ClientRunFlags, out string ClientApp, out string ClientCmdLine)
{
if (Params.ClientTargetPlatforms.Count == 0)
{
throw new AutomationException("No ClientTargetPlatform set for SetupClientParams.");
}
// var DeployContextList = CreateDeploymentContext(Params, false);
if (DeployContextList.Count == 0)
{
throw new AutomationException("No DeployContextList for SetupClientParams.");
}
var SC = DeployContextList[0];
// Get client app name and command line.
ClientRunFlags = ERunOptions.AllowSpew | ERunOptions.AppMustExist;
ClientApp = "";
ClientCmdLine = "";
string TempCmdLine = "";
var PlatformName = Params.ClientTargetPlatforms[0].ToString();
if (Params.Cook || Params.CookOnTheFly)
{
List<string> Exes = SC.StageTargetPlatform.GetExecutableNames(SC, true);
ClientApp = Exes[0];
if (SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.IOS)
{
TempCmdLine += SC.ProjectArgForCommandLines + " ";
}
TempCmdLine += Params.MapToRun + " ";
if (Params.CookOnTheFly || Params.FileServer)
{
TempCmdLine += "-filehostip=";
bool FirstParam = true;
if (UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac)
{
NetworkInterface[] Interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in Interfaces)
{
if (adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback)
{
IPInterfaceProperties IP = adapter.GetIPProperties();
for (int Index = 0; Index < IP.UnicastAddresses.Count; ++Index)
{
if (IP.UnicastAddresses[Index].IsDnsEligible && IP.UnicastAddresses[Index].Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
if (!IsNullOrEmpty(Params.Port))
{
foreach (var Port in Params.Port)
{
if (!FirstParam)
{
TempCmdLine += "+";
}
FirstParam = false;
string[] PortProtocol = Port.Split(new char[] { ':' });
if (PortProtocol.Length > 1)
{
TempCmdLine += String.Format("{0}://{1}:{2}", PortProtocol[0], IP.UnicastAddresses[Index].Address.ToString(), PortProtocol[1]);
}
else
{
TempCmdLine += IP.UnicastAddresses[Index].Address.ToString();
TempCmdLine += ":";
TempCmdLine += Params.Port;
}
}
}
else
{
if (!FirstParam)
{
TempCmdLine += "+";
}
FirstParam = false;
// use default port
TempCmdLine += IP.UnicastAddresses[Index].Address.ToString();
}
}
}
}
}
}
else
{
NetworkInterface[] Interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in Interfaces)
{
if (adapter.OperationalStatus == OperationalStatus.Up)
{
IPInterfaceProperties IP = adapter.GetIPProperties();
for (int Index = 0; Index < IP.UnicastAddresses.Count; ++Index)
{
if (IP.UnicastAddresses[Index].IsDnsEligible)
{
if (!IsNullOrEmpty(Params.Port))
{
foreach (var Port in Params.Port)
{
if (!FirstParam)
{
TempCmdLine += "+";
}
FirstParam = false;
string[] PortProtocol = Port.Split(new char[] { ':' });
if (PortProtocol.Length > 1)
{
TempCmdLine += String.Format("{0}://{1}:{2}", PortProtocol[0], IP.UnicastAddresses[Index].Address.ToString(), PortProtocol[1]);
}
else
{
TempCmdLine += IP.UnicastAddresses[Index].Address.ToString();
TempCmdLine += ":";
TempCmdLine += Params.Port;
}
}
}
else
{
if (!FirstParam)
{
TempCmdLine += "+";
}
FirstParam = false;
// use default port
TempCmdLine += IP.UnicastAddresses[Index].Address.ToString();
}
}
}
}
}
}
const string LocalHost = "127.0.0.1";
if (!IsNullOrEmpty(Params.Port))
{
foreach (var Port in Params.Port)
{
if (!FirstParam)
{
TempCmdLine += "+";
}
FirstParam = false;
string[] PortProtocol = Port.Split(new char[] { ':' });
if (PortProtocol.Length > 1)
{
TempCmdLine += String.Format("{0}://{1}:{2}", PortProtocol[0], LocalHost, PortProtocol[1]);
}
else
{
TempCmdLine += LocalHost;
TempCmdLine += ":";
TempCmdLine += Params.Port;
}
}
}
else
{
if (!FirstParam)
{
TempCmdLine += "+";
}
FirstParam = false;
// use default port
TempCmdLine += LocalHost;
}
TempCmdLine += " ";
if (Params.CookOnTheFlyStreaming)
{
TempCmdLine += "-streaming ";
}
else if (SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.IOS)
{
// per josh, allowcaching is deprecated/doesn't make sense for iOS.
TempCmdLine += "-allowcaching ";
}
}
else if (Params.UsePak(SC.StageTargetPlatform))
{
if (Params.SignedPak)
{
TempCmdLine += "-signedpak ";
}
else
{
TempCmdLine += "-pak ";
}
}
else if (!Params.Stage)
{
var SandboxPath = CombinePaths(SC.RuntimeProjectRootDir, "Saved", "Cooked", SC.CookPlatform);
if (!SC.StageTargetPlatform.LaunchViaUFE)
{
TempCmdLine += "-sandbox=" + CommandUtils.MakePathSafeToUseWithCommandLine(SandboxPath) + " ";
}
else
{
TempCmdLine += "-sandbox=\'" + SandboxPath + "\' ";
}
}
}
else
{
ClientApp = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries", PlatformName, "UE4Editor.exe");
TempCmdLine += SC.ProjectArgForCommandLines + " ";
if (!Params.EditorTest)
{
TempCmdLine += "-game " + Params.MapToRun + " ";
}
else
{
TempCmdLine += Params.MapToRun + " ";
}
}
if (Params.LogWindow)
{
// Without NoStdOutRedirect '-log' doesn't log anything to the window
ClientRunFlags |= ERunOptions.NoStdOutRedirect;
TempCmdLine += "-log ";
}
else
{
TempCmdLine += "-stdout ";
}
if (Params.Unattended)
{
TempCmdLine += "-unattended ";
}
if (IsBuildMachine || Params.Unattended)
{
TempCmdLine += "-buildmachine ";
}
if (Params.CrashIndex > 0)
{
int RealIndex = Params.CrashIndex - 1;
if (RealIndex < 0 || RealIndex >= CrashCommands.Count())
{
throw new AutomationException("CrashIndex {0} is out of range...max={1}", Params.CrashIndex, CrashCommands.Count());
}
TempCmdLine += String.Format("-execcmds=\"debug {0}\" ", CrashCommands[RealIndex]);
}
else if (Params.RunAutomationTest != "")
{
TempCmdLine += "-execcmds=\"automation list;runtests " + Params.RunAutomationTest + "\" ";
}
else if (Params.RunAutomationTests)
{
TempCmdLine += "-execcmds=\"automation list;runall\" ";
}
if (SC.StageTargetPlatform.UseAbsLog)
{
TempCmdLine += "-abslog=" + CommandUtils.MakePathSafeToUseWithCommandLine(ClientLogFile) + " ";
}
if (SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.IOS && SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.Linux)
{
TempCmdLine += "-Messaging -nomcp -Windowed ";
}
else
{
// skip arguments which don't make sense for iOS
TempCmdLine += "-Messaging ";
}
if (Params.NullRHI && SC.StageTargetPlatform.PlatformType != UnrealTargetPlatform.Mac) // all macs have GPUs, and currently the mac dies with nullrhi
{
TempCmdLine += "-nullrhi ";
}
if (Params.Deploy && !Params.CookOnTheFly && (SC.StageTargetPlatform.PlatformType == UnrealTargetPlatform.PS4))
{
TempCmdLine += "-deployedbuild ";
}
TempCmdLine += "-CrashForUAT ";
TempCmdLine += Params.RunCommandline;
// todo: move this into the platform
if (SC.StageTargetPlatform.LaunchViaUFE)
{
ClientCmdLine = "-run=Launch ";
ClientCmdLine += "-Device=" + Params.Devices[0];
for (int DeviceIndex = 1; DeviceIndex < Params.Devices.Count; DeviceIndex++)
{
ClientCmdLine += "+" + Params.Devices[DeviceIndex];
}
ClientCmdLine += " ";
ClientCmdLine += "-Exe=\"" + ClientApp + "\" ";
ClientCmdLine += "-Targetplatform=" + Params.ClientTargetPlatforms[0].ToString() + " ";
ClientCmdLine += "-Params=\"" + TempCmdLine + "\"";
ClientApp = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/Win64/UnrealFrontend.exe");
Log("Launching via UFE:");
Log("\tClientCmdLine: " + ClientCmdLine + "");
}
else
{
ClientCmdLine = TempCmdLine;
}
}
#endregion
#region Client Thread
private static void ClientLogReaderProc(object ArgsContainer)
{
var Args = ArgsContainer as object[];
var ClientLogFile = (string)Args[0];
var ClientProcess = (IProcessResult)Args[1];
LogFileReaderProcess(ClientLogFile, ClientProcess, (string Output) =>
{
if (String.IsNullOrEmpty(Output) == false)
{
Log(Output);
}
return true;
});
}
#endregion
#region Servers
private static IProcessResult RunDedicatedServer(ProjectParams Params, string ServerLogFile, string AdditionalCommandLine)
{
ProjectParams ServerParams = new ProjectParams(Params);
ServerParams.Devices = new ParamList<string>(Params.ServerDevice);
if (ServerParams.ServerTargetPlatforms.Count == 0)
{
throw new AutomationException("No ServerTargetPlatform set for RunDedicatedServer.");
}
var DeployContextList = CreateDeploymentContext(ServerParams, true);
if (DeployContextList.Count == 0)
{
throw new AutomationException("No DeployContextList for RunDedicatedServer.");
}
var SC = DeployContextList[0];
var ServerApp = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/Win64/UE4Editor.exe");
if (ServerParams.Cook)
{
List<string> Exes = SC.StageTargetPlatform.GetExecutableNames(SC);
ServerApp = Exes[0];
}
var Args = ServerParams.Cook ? "" : (SC.ProjectArgForCommandLines + " ");
Console.WriteLine(Params.ServerDeviceAddress);
TargetPlatformDescriptor ServerPlatformDesc = ServerParams.ServerTargetPlatforms[0];
if (ServerParams.Cook && ServerPlatformDesc.Type == UnrealTargetPlatform.Linux && !String.IsNullOrEmpty(ServerParams.ServerDeviceAddress))
{
ServerApp = @"C:\Windows\system32\cmd.exe";
string plinkPath = CombinePaths(Environment.GetEnvironmentVariable("LINUX_ROOT"), "bin/PLINK.exe ");
string exePath = CombinePaths(SC.ShortProjectName, "Binaries", ServerPlatformDesc.Type.ToString(), SC.ShortProjectName + "Server");
if (ServerParams.ServerConfigsToBuild[0] != UnrealTargetConfiguration.Development)
{
exePath += "-" + ServerPlatformDesc.Type.ToString() + "-" + ServerParams.ServerConfigsToBuild[0].ToString();
}
exePath = CombinePaths("LinuxServer", exePath.ToLower()).Replace("\\", "/");
Args = String.Format("/k {0} -batch -ssh -t -i {1} {2}@{3} {4} {5} {6} -server -Messaging", plinkPath, ServerParams.DevicePassword, ServerParams.DeviceUsername, ServerParams.ServerDeviceAddress, exePath, Args, ServerParams.MapToRun);
}
else
{
var Map = ServerParams.MapToRun;
if (!String.IsNullOrEmpty(ServerParams.AdditionalServerMapParams))
{
Map += ServerParams.AdditionalServerMapParams;
}
if (Params.FakeClient)
{
Map += "?fake";
}
Args += String.Format("{0} -server -abslog={1} -log -Messaging", Map, CommandUtils.MakePathSafeToUseWithCommandLine(ServerLogFile));
if (Params.Unattended)
{
Args += " -unattended";
}
// Do not blindly add -nomcp, only do so if the client is using it
if (Params.RunCommandline.Contains("-nomcp"))
{
Args += " -nomcp";
}
if (Params.ServerCommandline.Length > 0)
{
Args += " " + Params.ServerCommandline;
}
}
if (ServerParams.UsePak(SC.StageTargetPlatform))
{
if (ServerParams.SignedPak)
{
Args += " -signedpak";
}
else
{
Args += " -pak";
}
}
if (IsBuildMachine || Params.Unattended)
{
Args += " -buildmachine";
}
Args += " -CrashForUAT";
Args += " " + AdditionalCommandLine;
if (ServerParams.Cook && ServerPlatformDesc.Type == UnrealTargetPlatform.Linux && !String.IsNullOrEmpty(ServerParams.ServerDeviceAddress))
{
Args += String.Format(" 2>&1 > {0}", ServerLogFile);
}
PushDir(Path.GetDirectoryName(ServerApp));
var Result = Run(ServerApp, Args, null, ERunOptions.AllowSpew | ERunOptions.NoWaitForExit | ERunOptions.AppMustExist | ERunOptions.NoStdOutRedirect);
PopDir();
return Result;
}
private static IProcessResult RunCookOnTheFlyServer(FileReference ProjectName, string ServerLogFile, string TargetPlatform, string AdditionalCommandLine)
{
var ServerApp = HostPlatform.Current.GetUE4ExePath("UE4Editor.exe");
var Args = String.Format("{0} -run=cook -cookonthefly -unattended -CrashForUAT -log",
CommandUtils.MakePathSafeToUseWithCommandLine(ProjectName.FullName));
if (!String.IsNullOrEmpty(ServerLogFile))
{
Args += " -abslog=" + CommandUtils.MakePathSafeToUseWithCommandLine(ServerLogFile);
}
if (IsBuildMachine)
{
Args += " -buildmachine";
}
Args += " " + AdditionalCommandLine;
// Run the server (Without NoStdOutRedirect -log doesn't log anything to the window)
PushDir(Path.GetDirectoryName(ServerApp));
var Result = Run(ServerApp, Args, null, ERunOptions.AllowSpew | ERunOptions.NoWaitForExit | ERunOptions.AppMustExist | ERunOptions.NoStdOutRedirect);
PopDir();
return Result;
}
private static IProcessResult RunFileServer(ProjectParams Params, string ServerLogFile, string AdditionalCommandLine)
{
#if false
// this section of code would provide UFS with a more accurate file mapping
var SC = new StagingContext(Params, false);
CreateStagingManifest(SC);
MaybeConvertToLowerCase(Params, SC);
var UnrealFileServerResponseFile = new List<string>();
foreach (var Pair in SC.UFSStagingFiles)
{
string Src = Pair.Key;
string Dest = Pair.Value;
Dest = CombinePaths(PathSeparator.Slash, SC.UnrealFileServerInternalRoot, Dest);
UnrealFileServerResponseFile.Add("\"" + Src + "\" \"" + Dest + "\"");
}
string UnrealFileServerResponseFileName = CombinePaths(CmdEnv.LogFolder, "UnrealFileServerList.txt");
File.WriteAllLines(UnrealFileServerResponseFileName, UnrealFileServerResponseFile);
#endif
var UnrealFileServerExe = HostPlatform.Current.GetUE4ExePath("UnrealFileServer.exe");
Log("Running UnrealFileServer *******");
var Args = String.Format("{0} -abslog={1} -unattended -CrashForUAT -log {2}",
CommandUtils.MakePathSafeToUseWithCommandLine(Params.RawProjectPath.FullName),
CommandUtils.MakePathSafeToUseWithCommandLine(ServerLogFile),
AdditionalCommandLine);
if (IsBuildMachine)
{
Args += " -buildmachine";
}
PushDir(Path.GetDirectoryName(UnrealFileServerExe));
var Result = Run(UnrealFileServerExe, Args, null, ERunOptions.AllowSpew | ERunOptions.NoWaitForExit | ERunOptions.AppMustExist | ERunOptions.NoStdOutRedirect);
PopDir();
return Result;
}
#endregion
}