Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Draft) Initial game mode POC #417

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions src/Randomizer.Abstractions/GameModeBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using Randomizer.Data.Options;
using Randomizer.Data.Tracking;
using Randomizer.Data.WorldData;
using Randomizer.Data.WorldData.Regions;
using Randomizer.Shared.Enums;

namespace Randomizer.Abstractions;

public abstract class GameModeBase
{
public abstract GameModeType GameModeType { get; }

public abstract string Name { get; }

public abstract string Description { get; }

public virtual void ModifyWorldConfig(Config config)
{
Console.WriteLine($"Modify world config for{Name}");
}

public virtual void ModifyWorldItemPools(WorldItemPools itemPool)
{
Console.WriteLine($"Modify item pool for {Name}");
}

public virtual void PreWorldGeneration()
{

}

public virtual ICollection<RomPatch> GetPatches(World world)
{
return new List<RomPatch>();
}

public virtual void ItemTracked(Item item, Location? location, TrackerBase? tracker)
{

}

public virtual void DungeonCleared(IDungeon dungeon, TrackerBase? tracker)
{

}

public virtual void BossDefeated(Boss boss, TrackerBase? tracker)
{

}

public virtual void ZeldaStateChanged(AutoTrackerZeldaState currentState, AutoTrackerZeldaState? previousState, TrackerBase? tracker)
{

}

public virtual void MetroidStateChanged(AutoTrackerMetroidState currentState, AutoTrackerMetroidState? previousState, TrackerBase? tracker)
{

}
}
30 changes: 30 additions & 0 deletions src/Randomizer.Abstractions/IGameModeService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Microsoft.Extensions.DependencyInjection;
using Randomizer.Data.Options;
using Randomizer.Data.Tracking;
using Randomizer.Data.WorldData;
using Randomizer.Data.WorldData.Regions;

namespace Randomizer.Abstractions;

public interface IGameModeService
{
public Dictionary<string, GameModeBase> GameModeTypes { get; }

public void SetTracker(TrackerBase tracker, GameModeConfigs gameModeConfigs);

public void ModifyConfig(Config config);

public void ModifyWorldItemPools(World world);

public IEnumerable<RomPatch> GetPatches(World world);

public void ItemTracked(Item item, Location? location);

public void DungeonCleared(IDungeon dungeon);

public void BossDefeated(Boss boss);

public void ZeldaStateChanged(AutoTrackerZeldaState currentState, AutoTrackerZeldaState? previousState);

public void MetroidStateChanged(AutoTrackerMetroidState currentState, AutoTrackerMetroidState? previousState);
}
73 changes: 73 additions & 0 deletions src/Randomizer.Abstractions/RomPatch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System.Text;
using Randomizer.SMZ3.FileData;
using Randomizer.SMZ3.FileData.Patches;

namespace Randomizer.Abstractions;

/// <summary>
/// Represents one or more changes that can be applied to a generated SMZ3
/// ROM.
/// </summary>
public abstract class RomPatch
{
/// <summary>
/// Returns the PC offset for the specified SNES address.
/// </summary>
/// <param name="addr">The SNES address to convert.</param>
/// <returns>
/// The PC offset equivalent to the SNES <paramref name="addr"/>.
/// </returns>
protected static int Snes(int addr)
{
addr = addr switch
{
/* Redirect hi bank $30 access into ExHiRom lo bank $40 */
_ when (addr & 0xFF8000) == 0x308000 => 0x400000 | (addr & 0x7FFF),
/* General case, add ExHi offset for banks < $80, and collapse mirroring */
_ => (addr < 0x800000 ? 0x400000 : 0) | (addr & 0x3FFFFF),
};
if (addr > 0x600000)
throw new InvalidOperationException($"Unmapped pc address target ${addr:X}");
return addr;
}

/// <summary>
/// Returns a byte array representing the specified 32-bit unsigned
/// integer.
/// </summary>
/// <param name="value">The 32-bit unsigned integer.</param>
/// <returns>
/// A new byte array containing the 32-bit unsigned integer.
/// </returns>
protected static byte[] UintBytes(int value) => BitConverter.GetBytes((uint)value);

/// <summary>
/// Returns a byte array representing the specified 16-bit unsigned
/// integer.
/// </summary>
/// <param name="value">The 16-bit unsigned integer.</param>
/// <returns>
/// A new byte array containing the 16-bit unsigned integer.
/// </returns>
protected static byte[] UshortBytes(int value) => BitConverter.GetBytes((ushort)value);

/// <summary>
/// Returns a byte array representing the specified ASCII-encoded text.
/// </summary>
/// <param name="text">The text.</param>
/// <returns>
/// A new byte array containing the ASCII representation of the
/// <paramref name="text"/>.
/// </returns>
protected static byte[] AsAscii(string text) => Encoding.ASCII.GetBytes(text);

/// <summary>
/// Returns the changes to be applied to an SMZ3 ROM file.
/// </summary>
/// <param name="data">Patcher Data with the world and config information</param>
/// <returns>
/// A collection of changes, represented by the data to overwrite at the
/// specified ROM offset.
/// </returns>
public abstract IEnumerable<GeneratedPatch> GetChanges(GetPatchesRequest data);
}
6 changes: 5 additions & 1 deletion src/Randomizer.CrossPlatform/ConsoleTrackerDisplayService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Randomizer.Shared;
using Randomizer.Shared.Enums;
using Randomizer.Shared.Models;
using Randomizer.SMZ3.GameModes;
using Randomizer.SMZ3.Generation;
using Randomizer.SMZ3.Tracking;
using Randomizer.SMZ3.Tracking.AutoTracking;
Expand All @@ -22,15 +23,17 @@ public class ConsoleTrackerDisplayService
private readonly TrackerOptionsAccessor _trackerOptionsAccessor;
private readonly RandomizerOptions _options;
private readonly IServiceProvider _serviceProvider;
private readonly IGameModeService _gameModeService;
private TrackerBase _trackerBase = null!;
private World _world = null!;
private IWorldService _worldService = null!;
private Region _lastRegion = null!;

public ConsoleTrackerDisplayService(IServiceProvider serviceProvider, Smz3GeneratedRomLoader romLoaderService, TrackerOptionsAccessor trackerOptionsAccessor, OptionsFactory optionsFactory)
public ConsoleTrackerDisplayService(IServiceProvider serviceProvider, Smz3GeneratedRomLoader romLoaderService, TrackerOptionsAccessor trackerOptionsAccessor, OptionsFactory optionsFactory, IGameModeService gameModeService)
{
_romLoaderService = romLoaderService;
_trackerOptionsAccessor = trackerOptionsAccessor;
_gameModeService = gameModeService;
_options = optionsFactory.Create();
_serviceProvider = serviceProvider;
_timer = new System.Timers.Timer(TimeSpan.FromMilliseconds(250));
Expand All @@ -43,6 +46,7 @@ public async Task StartTracking(GeneratedRom rom, string romPath)
_world = _romLoaderService.LoadGeneratedRom(rom).First(x => x.IsLocalWorld);
_worldService = _serviceProvider.GetRequiredService<IWorldService>();
_trackerBase = _serviceProvider.GetRequiredService<TrackerBase>();
_gameModeService.SetTracker(_trackerBase, _world.Config.GameModeConfigs);
_trackerBase.Load(rom, romPath);
_trackerBase.TryStartTracking();
_trackerBase.AutoTracker?.SetConnector(_options.AutoTrackerDefaultConnector, _options.AutoTrackerQUsb2SnesIp);
Expand Down
9 changes: 7 additions & 2 deletions src/Randomizer.CrossPlatform/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,15 @@ public static void Main(string[] args)
.Where(x => x.ValidTracks.Count > 10).ToList();

result = DisplayMenu("Which msu do you want to use?",
msus.Select(x => $"{x.Name} ({x.MsuTypeName})").ToList());
if (result != null)
msus.Select(x => $"{x.Name} ({x.MsuTypeName})").Append("None").ToList());
if (result != null && result.Value.Item1 < msus.Count)
{
randomizerOptions.PatchOptions.MsuPaths = new List<string>() { msus[result.Value.Item1].Path };
}
else
{
randomizerOptions.PatchOptions.MsuPaths = new List<string>();
}
}

// Generate the rom
Expand All @@ -81,6 +85,7 @@ public static void Main(string[] args)
Console.WriteLine($"Rom generated successfully: {romPath}");
launcher.LaunchRom(romPath, randomizerOptions.GeneralOptions.LaunchApplication,
randomizerOptions.GeneralOptions.LaunchArguments);
randomizerOptions.Save();
_ = s_services.GetRequiredService<ConsoleTrackerDisplayService>().StartTracking(results.Rom, romPath);
}
else
Expand Down
6 changes: 3 additions & 3 deletions src/Randomizer.Data/Configuration/ConfigTypes/ItemData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,10 @@ public bool IsJunk(Config? config)
if (InternalItemType == ItemType.Nothing || InternalItemType.IsInAnyCategory(new[] { ItemCategory.Junk, ItemCategory.Scam, ItemCategory.NonRandomized, ItemCategory.Compass }))
return true;

if (config?.ZeldaKeysanity == false && InternalItemType.IsInAnyCategory(new[] { ItemCategory.SmallKey, ItemCategory.BigKey, ItemCategory.Map }))
if (config?.GameModeConfigs.KeysanityConfig.ZeldaKeysanity == false && InternalItemType.IsInAnyCategory(new[] { ItemCategory.SmallKey, ItemCategory.BigKey, ItemCategory.Map }))
return true;

if (config?.MetroidKeysanity == false && InternalItemType.IsInCategory(ItemCategory.Keycard))
if (config?.GameModeConfigs.KeysanityConfig.MetroidKeysanity == false && InternalItemType.IsInCategory(ItemCategory.Keycard))
return true;

return false;
Expand All @@ -297,7 +297,7 @@ public bool IsJunk(Config? config)
public bool IsProgression(Config? config)
{
// Todo: We can add special logic like checking if it's one of the first two swords
return InternalItemType.IsPossibleProgression(config?.ZeldaKeysanity == true, config?.MetroidKeysanity == true);
return InternalItemType.IsPossibleProgression(config?.GameModeConfigs.KeysanityConfig.ZeldaKeysanity == true, config?.GameModeConfigs.KeysanityConfig.MetroidKeysanity == true);
}

/// <summary>
Expand Down
26 changes: 26 additions & 0 deletions src/Randomizer.Data/Generation/GameModeTypeAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using Randomizer.Shared.Enums;

namespace Randomizer.Shared;

[AttributeUsage(AttributeTargets.Property,
Inherited = false, AllowMultiple = false)]
public class GameModeTypeAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see
/// cref="GameModeTypeAttribute"/> class with the specified game mode type.
/// </summary>
/// <param name="gameModeType">
/// The game mode type applicable to the property
/// </param>
public GameModeTypeAttribute(GameModeType gameModeType)
{
GameModeType = gameModeType;
}

/// <summary>
/// The game mode of property
/// </summary>
public GameModeType GameModeType { get; }
}
Loading
Loading