-
Notifications
You must be signed in to change notification settings - Fork 149
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Игральные карты + механика к ним. (#79)
* Add playable cards * SomeFixes * SomeFixes2 * SomeFixes3 * Apply suggestions from code review Co-authored-by: FN <[email protected]> * статик статик хуестатик * fix some * meh --------- Co-authored-by: AwareFoxy <[email protected]> Co-authored-by: FN <[email protected]> Co-authored-by: AwareFoxy <[email protected]>
- Loading branch information
Showing
245 changed files
with
3,425 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
using System.Linq; | ||
using Content.Shared._CorvaxNext.Cards.Card; | ||
using Robust.Client.GameObjects; | ||
using Robust.Shared.Utility; | ||
|
||
namespace Content.Client._CorvaxNext.Cards.Card; | ||
|
||
/// <summary> | ||
/// Handles the initialization and updating of card sprites on the client side, | ||
/// particularly when a card is flipped or when the component starts up. | ||
/// </summary> | ||
public sealed class CardSystem : EntitySystem | ||
{ | ||
/// <inheritdoc/> | ||
public override void Initialize() | ||
{ | ||
SubscribeLocalEvent<CardComponent, ComponentStartup>(OnComponentStartupEvent); | ||
SubscribeNetworkEvent<CardFlipUpdatedEvent>(OnFlip); | ||
} | ||
|
||
private void OnComponentStartupEvent(EntityUid uid, CardComponent comp, ComponentStartup args) | ||
{ | ||
if (!TryComp(uid, out SpriteComponent? spriteComponent)) | ||
return; | ||
|
||
var layerCount = spriteComponent.AllLayers.Count(); | ||
for (var i = 0; i < layerCount; i++) | ||
{ | ||
if (!spriteComponent.TryGetLayer(i, out var layer) || layer.State == null || layer.State.Name == null) | ||
continue; | ||
|
||
var rsi = layer.RSI ?? spriteComponent.BaseRSI; | ||
if (rsi == null) | ||
continue; | ||
|
||
comp.FrontSprite.Add(new SpriteSpecifier.Rsi(rsi.Path, layer.State.Name)); | ||
} | ||
|
||
comp.BackSprite ??= comp.FrontSprite; | ||
|
||
// Removed Dirty(uid, comp); as calling Dirty on the client is inappropriate. | ||
UpdateSprite(uid, comp); | ||
} | ||
|
||
private void OnFlip(CardFlipUpdatedEvent args) | ||
{ | ||
var entity = GetEntity(args.Card); | ||
if (!TryComp(entity, out CardComponent? comp)) | ||
return; | ||
|
||
UpdateSprite(entity, comp); | ||
} | ||
|
||
private void UpdateSprite(EntityUid uid, CardComponent comp) | ||
{ | ||
var newSprite = comp.Flipped ? comp.BackSprite : comp.FrontSprite; | ||
if (newSprite == null) | ||
return; | ||
|
||
if (!TryComp(uid, out SpriteComponent? spriteComponent)) | ||
return; | ||
|
||
var layerCount = newSprite.Count; | ||
var spriteLayerCount = spriteComponent.AllLayers.Count(); | ||
|
||
// Inserts missing layers | ||
if (spriteLayerCount < layerCount) | ||
{ | ||
for (var i = spriteLayerCount; i < layerCount; i++) | ||
{ | ||
spriteComponent.AddBlankLayer(i); | ||
} | ||
} | ||
// Removes extra layers | ||
else if (spriteLayerCount > layerCount) | ||
{ | ||
for (var i = spriteLayerCount - 1; i >= layerCount; i--) | ||
{ | ||
spriteComponent.RemoveLayer(i); | ||
} | ||
} | ||
|
||
for (var i = 0; i < layerCount; i++) | ||
{ | ||
var layer = newSprite[i]; | ||
spriteComponent.LayerSetSprite(i, layer); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
using System.Linq; | ||
using Content.Shared._CorvaxNext.Cards.Stack; | ||
using Robust.Client.GameObjects; | ||
|
||
namespace Content.Client._CorvaxNext.Cards; | ||
|
||
/// <summary> | ||
/// Manages the visual representation of card stacks by dynamically adjusting and configuring sprite layers | ||
/// based on the number of cards in the stack and their properties. | ||
/// </summary> | ||
public sealed class CardSpriteSystem : EntitySystem | ||
{ | ||
/// <inheritdoc/> | ||
public override void Initialize() | ||
{ | ||
|
||
} | ||
|
||
public bool TryAdjustLayerQuantity(Entity<SpriteComponent, CardStackComponent> uid, int? cardLimit = null) | ||
{ | ||
var sprite = uid.Comp1; | ||
var stack = uid.Comp2; | ||
var cardCount = cardLimit == null ? stack.Cards.Count : Math.Min(stack.Cards.Count, cardLimit.Value); | ||
|
||
var layerCount = 0; | ||
//Gets the quantity of layers | ||
foreach (var card in stack.Cards.TakeLast(cardCount)) | ||
{ | ||
if (!TryComp(card, out SpriteComponent? cardSprite)) | ||
return false; | ||
|
||
layerCount += cardSprite.AllLayers.Count(); | ||
} | ||
//inserts Missing Layers | ||
if (sprite.AllLayers.Count() < layerCount) | ||
{ | ||
for (var i = sprite.AllLayers.Count(); i < layerCount; i++) | ||
{ | ||
sprite.AddBlankLayer(i); | ||
} | ||
} | ||
//Removes extra layers | ||
else if (sprite.AllLayers.Count() > layerCount) | ||
{ | ||
for (var i = sprite.AllLayers.Count() - 1; i >= layerCount; i--) | ||
{ | ||
sprite.RemoveLayer(i); | ||
} | ||
} | ||
|
||
|
||
return true; | ||
} | ||
|
||
public bool TryHandleLayerConfiguration(Entity<SpriteComponent, CardStackComponent> uid, int cardCount, Func<Entity<SpriteComponent>, int, int, bool> layerFunc) | ||
{ | ||
var sprite = uid.Comp1; | ||
var stack = uid.Comp2; | ||
|
||
// int = index of what card it is from | ||
List<(int, ISpriteLayer)> layers = []; | ||
|
||
var i = 0; | ||
foreach (var card in stack.Cards.TakeLast(cardCount)) | ||
{ | ||
if (!TryComp(card, out SpriteComponent? cardSprite)) | ||
return false; | ||
layers.AddRange(cardSprite.AllLayers.Select(layer => (i, layer))); | ||
i++; | ||
} | ||
|
||
var j = 0; | ||
foreach (var obj in layers) | ||
{ | ||
var (cardIndex, layer) = obj; | ||
sprite.LayerSetVisible(j, true); | ||
sprite.LayerSetTexture(j, layer.Texture); | ||
sprite.LayerSetState(j, layer.RsiState.Name); | ||
layerFunc.Invoke((uid, sprite), cardIndex, j); | ||
j++; | ||
} | ||
|
||
return true; | ||
} | ||
} |
162 changes: 162 additions & 0 deletions
162
Content.Client/_CorvaxNext/Cards/Deck/CardDeckSystem.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
using System.Collections.Generic; | ||
using System.Numerics; | ||
using Content.Shared._CorvaxNext.Cards.Deck; | ||
using Content.Shared._CorvaxNext.Cards.Stack; | ||
using Robust.Client.GameObjects; | ||
|
||
namespace Content.Client._CorvaxNext.Cards.Deck; | ||
|
||
/// <summary> | ||
/// Handles the visual representation and sprite updates for card decks on the client side, | ||
/// responding to events such as card stack changes, flips, and reordering. | ||
/// </summary> | ||
public sealed class CardDeckSystem : EntitySystem | ||
{ | ||
private readonly Dictionary<EntityUid, int> _notInitialized = new(); | ||
[Dependency] private readonly CardSpriteSystem _cardSpriteSystem = default!; | ||
|
||
/// <inheritdoc/> | ||
public override void Initialize() | ||
{ | ||
UpdatesOutsidePrediction = false; | ||
SubscribeLocalEvent<CardDeckComponent, ComponentStartup>(OnComponentStartupEvent); | ||
SubscribeNetworkEvent<CardStackInitiatedEvent>(OnStackStart); | ||
SubscribeNetworkEvent<CardStackQuantityChangeEvent>(OnStackUpdate); | ||
SubscribeNetworkEvent<CardStackReorderedEvent>(OnReorder); | ||
SubscribeNetworkEvent<CardStackFlippedEvent>(OnStackFlip); | ||
SubscribeLocalEvent<CardDeckComponent, AppearanceChangeEvent>(OnAppearanceChanged); | ||
} | ||
|
||
public override void Update(float frameTime) | ||
{ | ||
base.Update(frameTime); | ||
|
||
// Lazy initialization of card deck sprites | ||
var entitiesToRemove = new List<EntityUid>(); | ||
|
||
foreach (var kvp in _notInitialized) | ||
{ | ||
var uid = kvp.Key; | ||
var attempts = kvp.Value; | ||
|
||
if (attempts >= 5) | ||
{ | ||
// Maximum attempts reached, remove from tracking | ||
entitiesToRemove.Add(uid); | ||
continue; | ||
} | ||
|
||
_notInitialized[uid] = attempts + 1; | ||
|
||
if (!TryComp(uid, out CardStackComponent? stack) || stack.Cards.Count <= 0) | ||
continue; | ||
|
||
// Check if the card's sprite layer is initialized | ||
if (!TryGetCardLayer(stack.Cards[^1], out _)) | ||
continue; | ||
|
||
// Update the sprite now that the card is initialized | ||
if (TryComp(uid, out CardDeckComponent? comp)) | ||
{ | ||
UpdateSprite(uid, comp); | ||
} | ||
|
||
entitiesToRemove.Add(uid); | ||
} | ||
|
||
// Remove entities outside the loop to avoid modifying the collection during iteration | ||
foreach (var uid in entitiesToRemove) | ||
{ | ||
_notInitialized.Remove(uid); | ||
} | ||
} | ||
|
||
private bool TryGetCardLayer(EntityUid card, out SpriteComponent.Layer? layer) | ||
{ | ||
layer = null; | ||
if (!TryComp(card, out SpriteComponent? cardSprite)) | ||
return false; | ||
|
||
if (!cardSprite.TryGetLayer(0, out var l)) | ||
return false; | ||
|
||
layer = l; | ||
return true; | ||
} | ||
|
||
private void UpdateSprite(EntityUid uid, CardDeckComponent comp) | ||
{ | ||
if (!TryComp(uid, out SpriteComponent? sprite)) | ||
return; | ||
|
||
if (!TryComp(uid, out CardStackComponent? cardStack)) | ||
return; | ||
|
||
// Prevent errors when the card stack is empty or not initialized | ||
if (cardStack.Cards.Count <= 0 || !TryGetCardLayer(cardStack.Cards[^1], out _)) | ||
{ | ||
_notInitialized[uid] = 0; | ||
return; | ||
} | ||
|
||
_cardSpriteSystem.TryAdjustLayerQuantity((uid, sprite, cardStack), comp.CardLimit); | ||
|
||
_cardSpriteSystem.TryHandleLayerConfiguration( | ||
(uid, sprite, cardStack), | ||
comp.CardLimit, | ||
(sprt, cardIndex, layerIndex) => | ||
{ | ||
sprite.LayerSetRotation(layerIndex, Angle.FromDegrees(90)); | ||
sprite.LayerSetOffset(layerIndex, new Vector2(0, comp.YOffset * cardIndex)); | ||
sprite.LayerSetScale(layerIndex, new Vector2(comp.Scale, comp.Scale)); | ||
return true; | ||
} | ||
); | ||
} | ||
|
||
private void OnStackUpdate(CardStackQuantityChangeEvent args) | ||
{ | ||
var entity = GetEntity(args.Stack); | ||
if (!TryComp(entity, out CardDeckComponent? comp)) | ||
return; | ||
|
||
UpdateSprite(entity, comp); | ||
} | ||
|
||
private void OnStackFlip(CardStackFlippedEvent args) | ||
{ | ||
var entity = GetEntity(args.CardStack); | ||
if (!TryComp(entity, out CardDeckComponent? comp)) | ||
return; | ||
|
||
UpdateSprite(entity, comp); | ||
} | ||
|
||
private void OnReorder(CardStackReorderedEvent args) | ||
{ | ||
var entity = GetEntity(args.Stack); | ||
if (!TryComp(entity, out CardDeckComponent? comp)) | ||
return; | ||
|
||
UpdateSprite(entity, comp); | ||
} | ||
|
||
private void OnAppearanceChanged(EntityUid uid, CardDeckComponent comp, AppearanceChangeEvent args) | ||
{ | ||
UpdateSprite(uid, comp); | ||
} | ||
|
||
private void OnComponentStartupEvent(EntityUid uid, CardDeckComponent comp, ComponentStartup args) | ||
{ | ||
UpdateSprite(uid, comp); | ||
} | ||
|
||
private void OnStackStart(CardStackInitiatedEvent args) | ||
{ | ||
var entity = GetEntity(args.CardStack); | ||
if (!TryComp(entity, out CardDeckComponent? comp)) | ||
return; | ||
|
||
UpdateSprite(entity, comp); | ||
} | ||
} |
Oops, something went wrong.