ported from perforce

This commit is contained in:
2026-04-19 00:43:27 +02:00
commit 6c0c33f5d4
700 changed files with 19735 additions and 0 deletions

View File

@@ -0,0 +1,232 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using DonkeysAndDroids;
using Godot;
using RobotAndDonkey.Game;
using RobotAndDonkey.Game.Execution;
using RobotAndDonkey.Game.Execution.Commands;
using RobotAndDonkey.Game.Execution.Requests;
using RobotAndDonkey.Game.Execution.Results;
using RobotAndDonkey.Game.GameState;
using RobotAndDonkey.Game.Utils;
public partial class Main : CanvasLayer
{
public enum EScreenId
{
Logo,
MetaGame,
CoreLoop,
Victory
}
public override void _Ready()
{
#if DEBUG
if (!Trace.Listeners.OfType<DefaultTraceListener>().Any())
Trace.Listeners.Add(new DefaultTraceListener());
#endif
Instance = this;
m_Runtime = new();
m_Runtime.Published += (_, e) => OnGameEvent(e);
m_Background = GetNode<Background>("Background");
m_LogoScreen = GetNode<LogoScreen>("LogoScreen");
m_MetaGameScreen = GetNode<MetaGameScreen>("MetaGameScreen");
m_CoreLoopScreen = GetNode<CoreLoopScreen>("CoreLoopScreen");
m_VictoryScreen = GetNode<VictoryScreen>("VictoryScreen");
OptionsMenu = GetNode<OptionsMenu>("OptionsMenu");
m_CurrentScreen = m_LogoScreen;
Music.Init(this);
Music.PlaySong(MusicManager.ESong.MetaGame);
}
public void StartMetaGame()
{
Music.PlaySong(MusicManager.ESong.MetaGame);
var tween = GetTree().CreateTween();
TransitionScreen(m_MetaGameScreen, tween);
}
public void TransitionScreen<T>(T newScreen, Tween tween) where T : Control, IScreen
{
newScreen.EnableInputs();
if (m_CurrentScreen == newScreen)
return;
MoveChild(newScreen, 1);
var oldControl = (Control)m_CurrentScreen;
var oldScreen = m_CurrentScreen;
m_CurrentScreen = newScreen;
newScreen.Modulate = new(1, 1, 1);
newScreen.Visible = true;
newScreen.Activate();
tween.TweenProperty(oldControl, "modulate", new Color(0, 0, 0, 0), 0.25);
tween.TweenCallback(Callable.From(() =>
{
oldScreen.Deactivate();
oldControl.Visible = false;
oldControl.Modulate = new(1, 1, 1);
}));
}
public void StartCoreLoop(int seed, EDifficulty difficulty, ERobotType selectedRobot)
{
Seed = seed;
CoreLoop = new(new((ulong)seed), new(selectedRobot, difficulty, seed));
m_Runtime.Start(CoreLoop);
}
private void OnGameEvent(GameEvent gameEvent)
{
switch (gameEvent.Payload)
{
case NextStepIssued { Step: { } request }:
{
m_NextRequest = request;
if (m_Tween != null)
break;
ProcessNextRequest();
break;
}
case StepApplied { Results: var results }:
{
GD.Print("Results available");
foreach (var result in results)
{
Results.Enqueue(result);
}
break;
}
case StateChanged:
{
GD.Print("State changed");
m_Tween = GetTree().CreateTween();
while (Results.TryDequeue(out var result))
{
GD.Print(result.ToString());
if (m_CurrentScreen.HandleResult(result, m_Tween))
m_Tween.SetParallel(false);
else
GD.Print("> Unhandled result!");
}
m_Tween.TweenCallback(Callable.From(() =>
{
m_Tween = null;
ProcessNextRequest();
}));
break;
}
case StepRejected r:
{
GD.Print($"Invalid action: {r.Reason}");
break;
}
case GameOver:
{
GD.Print("Game over");
break;
}
}
}
private void ProcessNextRequest()
{
m_CurrentScreen.DisableInputs();
CurrentRequest = m_NextRequest;
m_NextRequest = null;
GD.Print($"Next step: {CurrentRequest}");
m_Tween = GetTree().CreateTween();
var tween = m_Tween;
switch (CurrentRequest)
{
case DrawGlitchRequest drawCardRequest:
{
Music.PlaySong(MusicManager.ESong.Shop);
TransitionScreen(m_CoreLoopScreen, tween);
m_CoreLoopScreen.DrawGlitch(drawCardRequest.Card, tween);
break;
}
case ImproveRequest:
{
TransitionScreen(m_CoreLoopScreen, tween);
m_CoreLoopScreen.Improve(tween);
break;
}
case GambleRequest:
{
TransitionScreen(m_CoreLoopScreen, tween);
m_CoreLoopScreen.CosmicRays(CoreLoop.BoosterPack, tween);
break;
}
case BufferOverflowRequest:
{
TransitionScreen(m_CoreLoopScreen, tween);
m_CoreLoopScreen.BufferOverflow(tween);
break;
}
case ExecuteProgramRequest:
{
Music.PlaySong(MusicManager.ESong.CoreLoop);
TransitionScreen(m_CoreLoopScreen, tween);
m_CoreLoopScreen.ExecuteProgram(tween);
break;
}
case ScoringRequest:
{
Music.PlaySong(MusicManager.ESong.Scoring);
TransitionScreen(m_VictoryScreen, tween);
m_VictoryScreen.Configure(CoreLoop, tween);
break;
}
}
}
public void Execute(Command command)
{
if (command == null)
return;
GD.Print($"Execute {command}");
m_Runtime.Submit(command);
}
public static Main Instance { get; set; }
public Request CurrentRequest { get; private set; } = Request.s_Empty;
public Queue<Result> Results { get; } = [];
public CoreLoop CoreLoop { get; private set; }
public int Seed { get; private set; }
public string StringSeed => SeedString.ToString(Seed);
public MusicManager Music { get; } = new();
public OptionsMenu OptionsMenu { get; private set; }
private Background m_Background;
private CoreLoopScreen m_CoreLoopScreen;
private IScreen m_CurrentScreen;
private LogoScreen m_LogoScreen;
private MetaGameScreen m_MetaGameScreen;
private Request m_NextRequest;
private GameRuntime m_Runtime;
private Tween m_Tween;
private VictoryScreen m_VictoryScreen;
}