2026-07-18 23:26:56 +08:00
|
|
|
using MessagePack;
|
|
|
|
|
using OECS;
|
|
|
|
|
|
2026-07-20 16:41:10 +08:00
|
|
|
namespace Game.Blackjack;
|
2026-07-18 23:26:56 +08:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Player hits: draws one card from the deck to the player's hand.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[MessagePackObject]
|
|
|
|
|
public struct HitCommand : ICommand
|
|
|
|
|
{
|
|
|
|
|
public void Execute(World world)
|
|
|
|
|
{
|
|
|
|
|
ref var state = ref world.GetSingleton<GameState>();
|
|
|
|
|
|
|
|
|
|
if (state.Phase != GamePhase.PlayerTurn)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
DrawCard<PlayerHand>(world);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Draws the top card from the deck and adds it to the given hand.
|
|
|
|
|
/// </summary>
|
|
|
|
|
internal static void DrawCard<THand>(World world)
|
|
|
|
|
where THand : struct
|
|
|
|
|
{
|
|
|
|
|
var singletonEntity = World.SingletonEntity;
|
|
|
|
|
var deckEntity = FindEntity<Deck>(world, singletonEntity);
|
|
|
|
|
var handEntity = FindEntity<THand>(world, singletonEntity);
|
|
|
|
|
|
|
|
|
|
if (deckEntity == Entity.Null || handEntity == Entity.Null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Find a card still in the deck.
|
|
|
|
|
var cardsInDeck = world.GetSources<InDeck>(deckEntity);
|
|
|
|
|
if (cardsInDeck.Count == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var cardEntity = cardsInDeck.First();
|
|
|
|
|
|
|
|
|
|
// Remove from deck, add to hand.
|
|
|
|
|
world.RemoveComponent<InDeck>(cardEntity);
|
2026-07-20 22:59:27 +08:00
|
|
|
world.AddComponent(cardEntity, new Holds { Target = handEntity });
|
2026-07-18 23:26:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static Entity FindEntity<T>(World world, Entity singletonEntity)
|
|
|
|
|
where T : struct
|
|
|
|
|
{
|
|
|
|
|
using var iter = world.Select<T>();
|
|
|
|
|
while (iter.MoveNext())
|
|
|
|
|
{
|
|
|
|
|
if (iter.CurrentEntity != singletonEntity)
|
|
|
|
|
return iter.CurrentEntity;
|
|
|
|
|
}
|
|
|
|
|
return Entity.Null;
|
|
|
|
|
}
|
|
|
|
|
}
|