121 lines
8.2 KiB
C#
121 lines
8.2 KiB
C#
#if UNITY_EDITOR
|
|
using System;
|
|
using System.Collections;
|
|
using BlockOutReplica.Infrastructure;
|
|
using UnityEngine;
|
|
|
|
namespace BlockOutReplica.Gameplay
|
|
{
|
|
public sealed partial class BlockOutGameController
|
|
{
|
|
private BlockOutProgress savedLoopProgress;
|
|
private BlockOutPlayerState savedLoopPlayer;
|
|
private BlockOutJourney savedLoopJourney;
|
|
private BlockOutEconomy savedLoopEconomy;
|
|
private bool savedLoopHome;
|
|
private bool savedLoopJourneyTab;
|
|
private string savedLoopJourneyNotice;
|
|
private int savedLoopCelebrationLevel;
|
|
private float savedLoopCelebrationTime;
|
|
public bool IsManualLoopSandbox { get; private set; }
|
|
public bool IsFullLoopSandbox => savedLoopProgress!=null;
|
|
public void BeginFullLoopSandbox(bool manual=false)
|
|
{
|
|
if(IsFullLoopSandbox) return;
|
|
savedLoopProgress=progress;savedLoopPlayer=Player;savedLoopJourney=Journey;savedLoopEconomy=economy;
|
|
savedLoopHome=ScreenState==BlockOutScreenState.Home;
|
|
savedLoopJourneyTab=JourneyTab;savedLoopJourneyNotice=JourneyNotice;
|
|
savedLoopCelebrationLevel=JourneyCelebrationLevel;savedLoopCelebrationTime=JourneyCelebrationStartedAt;
|
|
IsManualLoopSandbox=manual;
|
|
economy=BlockOutEconomy.Load(); economy.InitialUfoAmount=30;economy.InitialRocketAmount=30;
|
|
player=new BlockOutPlayerState(economy,"",_=>{});
|
|
journey=new BlockOutJourney(BlockOutJourneyConfig.Load(),"",_=>{});
|
|
// Controlled Home fixture at 9 exercises the exact win-9 -> current10
|
|
// native boundary; it does not claim original early Home accessibility.
|
|
progress=new BlockOutProgress(OriginalFlowRepository.Load(),false,9);
|
|
InitializeInteractions();LoadCurrentLevel();GoHome();
|
|
Debug.Log("BLOCKOUT_FULL_LOOP_SANDBOX: started, level=9, isolatedSaves=True");
|
|
}
|
|
public void RestoreFullLoopSandbox()
|
|
{
|
|
if(!IsFullLoopSandbox)return;
|
|
progress=savedLoopProgress;player=savedLoopPlayer;journey=savedLoopJourney;economy=savedLoopEconomy;
|
|
savedLoopProgress=null;savedLoopPlayer=null;savedLoopJourney=null;savedLoopEconomy=null;
|
|
IsManualLoopSandbox=false;
|
|
IsFirstTwentyPreview=false;
|
|
InitializeInteractions();LoadCurrentLevel();if(savedLoopHome)GoHome(false);
|
|
JourneyTab=savedLoopJourneyTab;JourneyNotice=savedLoopJourneyNotice;
|
|
JourneyCelebrationLevel=savedLoopCelebrationLevel;JourneyCelebrationStartedAt=savedLoopCelebrationTime;
|
|
JourneyRevision++;
|
|
Debug.Log("BLOCKOUT_FULL_LOOP_SANDBOX: restored, persistentPlayerDataUntouched=True");
|
|
}
|
|
public IEnumerator ReviewFullLoop()
|
|
{
|
|
if(IsFullLoopSandbox)throw new InvalidOperationException("Restore manual sandbox before running automated review.");
|
|
int checks=0; Action<bool,string> check=(ok,name)=>{if(!ok)throw new InvalidOperationException(name);checks++;};
|
|
BeginFullLoopSandbox();
|
|
try
|
|
{
|
|
check(ScreenState==BlockOutScreenState.Home&&LevelNumber==9,"controlled Home fixture at level 9");
|
|
RequestEnterLevel(); check(Modal==GameModal.PreLevel,"pre-level");
|
|
EnterPreparedLevel();IsInputReviewRunning=true;yield return null;
|
|
check(pieces.Count>0&&LevelNumber==9,"real level 9 loaded");
|
|
ClickBooster(BoosterType.Freeze);check(Player.Amount(BoosterType.Freeze)==2&&FreezeRemaining==10,"freeze activated");
|
|
yield return WaitReviewCondition(()=>FreezeAnimationTime>=.42f,"freeze pose");
|
|
CaptureLoop("freeze");yield return null;
|
|
yield return WaitReviewCondition(()=>FreezeAnimationTime>=2.3f,"ice clock pose");
|
|
check(HasNativeFreezeScreen&&ActiveFreezeParticleCount>0,"native freeze screen and ice particles visible");
|
|
CaptureLoop("freeze-clock");yield return null;
|
|
RequestPause();float frozenAnimation=FreezeAnimationTime;int frozenParticles=ActiveFreezeParticleCount;
|
|
yield return WaitReviewTime(.25f);
|
|
check(FreezeAnimationTime==frozenAnimation&&ActiveFreezeParticleCount==frozenParticles,"native freeze particles pause");CloseModal();
|
|
yield return WaitReviewCondition(()=>FreezeRemaining<=0&&!HasNativeFreezeScreen,"freeze end cleanup");
|
|
check(ActiveFreezeParticleCount==0,"ice effect expires and cleans up");
|
|
ClickBooster(BoosterType.Rocket);
|
|
var target=pieces[0];BeginDrag(gameCamera.WorldToScreenPoint(target.transform.position),gameCamera);
|
|
yield return WaitReviewCondition(()=>BoosterPlaybackTime>=.2f,"rocket entry pose");CaptureLoop("rocket-entry");yield return null;
|
|
RequestPause();float time=TimeLeft;yield return WaitReviewTime(.25f);
|
|
check(TimeLeft==time&&InputLocked,"effect and timer paused");CloseModal();
|
|
yield return WaitReviewCondition(()=>BoosterPlaybackTime>=1.45f,"rocket impact pose");
|
|
check(ActiveBoosterParticleCount>0,"native rocket impact particles emitted");CaptureLoop("rocket-impact");yield return null;
|
|
while(InputLocked&&ScreenState==BlockOutScreenState.Playing)yield return null;
|
|
check(target==null&&activeExits==0,"rocket impact retired target");
|
|
int guard=0;
|
|
while(ScreenState==BlockOutScreenState.Playing&&pieces.Count>0&&guard++<12)
|
|
{
|
|
ClickBooster(BoosterType.Ufo);target=pieces[0];
|
|
BeginDrag(gameCamera.WorldToScreenPoint(target.transform.position),gameCamera);
|
|
yield return WaitReviewCondition(()=>BoosterPlaybackTime>=1.55f,"ufo absorption pose");CaptureLoop("ufo-absorb");yield return null;
|
|
yield return WaitReviewCondition(()=>BoosterPlaybackTime>=1.85f,"ufo beam pose");
|
|
check(ActiveBoosterParticleCount>0,"native UFO beam particles emitted");CaptureLoop("ufo-beam");yield return null;
|
|
while(InputLocked&&ScreenState==BlockOutScreenState.Playing)yield return null;
|
|
}
|
|
check(ScreenState==BlockOutScreenState.LevelComplete,"actual board clear, no debug win");
|
|
check(LevelNumber==10&&Player.Coins==1020&&Journey.IsQueued(10)&&!Journey.IsClaimed(10),"win 9 pays ordinary20 and queues Journey50");
|
|
CaptureLoop("win");yield return null;ContinueAfterWin();
|
|
check(ScreenState==BlockOutScreenState.Home&&LevelNumber==10,"returned Home at current level 10");
|
|
check(Journey.IsClaimed(10)&&!Journey.IsQueued(10)&&Player.Coins==1070,"source level 10 reward automatically received");
|
|
ClaimJourneyReward(10);ClaimJourneyReward(10);
|
|
check(Player.Coins==1070&&Journey.IsClaimed(10),"repeated settlement cannot duplicate 50 coins");
|
|
OpenHomeTab(true);
|
|
CaptureLoop("journey-claimed");yield return null;
|
|
OpenHomeTab(false);CaptureLoop("home");yield return null;
|
|
RequestEnterLevel();EnterPreparedLevel();IsInputReviewRunning=true;yield return null;
|
|
check(ScreenState==BlockOutScreenState.Playing&&LevelNumber==10,"current level 10 enters from Home");
|
|
Debug.Log($"BLOCKOUT_FULL_LOOP_REVIEW: passed=True, checks={checks}, realBoardClear=True, debugWin=False, persistentPlayerDataUntouched=True");
|
|
}
|
|
finally{RestoreFullLoopSandbox();}
|
|
}
|
|
private IEnumerator WaitReviewTime(float seconds)
|
|
{float end=Time.realtimeSinceStartup+seconds;while(Time.realtimeSinceStartup<end)yield return null;}
|
|
private IEnumerator WaitReviewCondition(Func<bool> condition,string name)
|
|
{
|
|
float end=Time.realtimeSinceStartup+45;
|
|
while(!condition()) {if(Time.realtimeSinceStartup>end)throw new InvalidOperationException("Timed out: "+name);yield return null;}
|
|
}
|
|
private static void CaptureLoop(string suffix)
|
|
{System.IO.Directory.CreateDirectory("Docs/iterations");ScreenCapture.CaptureScreenshot("Docs/iterations/2026-10-19-full-loop-"+suffix+".png");}
|
|
}
|
|
}
|
|
#endif
|