/// <summary>Part of a shuffle process.</summary> /// <param name="group">The group being shuffled.</param> /// <param name="card">An array containing the CardIdentity ids to shuffle.</param> //public void Shuffle(Group group, int[] card) //{ // // Array to hold the new aliases (sent to CreateAlias) // ulong[] aliases = new ulong[card.Length]; // // Intialize the group shuffle // group.FilledShuffleSlots = 0; // group.HasReceivedFirstShuffledMessage = false; // group.MyShufflePos = new short[card.Length]; // // Check if we received enough cards // if (Player.Count - 1 <= 0) return; // if (card.Length < group.Count / (Player.Count - 1)) // Program.Trace.TraceEvent(TraceEventType.Warning, EventIds.Event, "[Shuffle] Too few cards received."); // // Do the shuffling // var rnd = new CryptoRandom(); // for (int i = card.Length - 1; i >= 0; i--) // { // int r = rnd.Next(i + 1); // int tc = card[r]; // card[r] = card[i]; // // Create a new alias, if the card is not face up // CardIdentity ci = CardIdentity.Find(tc); // if (group.FindByCardIdentity(ci) != null) // { // card[i] = tc; aliases[i] = ulong.MaxValue; // ci.Visible = true; // } // else // { // ci = new CardIdentity(ExtensionMethods.GenerateCardId()); // ci.MySecret = ci.Alias = true; // ci.Key = ((ulong)Crypto.PositiveRandom()) << 32 | (uint)tc; // card[i] = ci.Id; aliases[i] = Crypto.ModExp(ci.Key); // ci.Visible = false; // } // // Give a random position to the card // group.MyShufflePos[i] = (short)Crypto.Random(group.Count); // } // // Send the results // Program.Client.Rpc.CreateAlias(card, aliases); // Program.Client.Rpc.Shuffled(group, card, group.MyShufflePos); //} public void Shuffled(Group group, int[] card, short[] pos) { // Check the args if (card.Length != pos.Length) { Program.TraceWarning("[Shuffled] Cards and positions lengths don't match."); return; } // Insert the cards for (int j = 0; j < card.Length; j++) { // Get the wished position int i = pos[j]; // Get the card CardIdentity ci = CardIdentity.Find(card[j]); if (ci == null) { Program.TraceWarning("[Shuffled] Card not found."); continue; } // Check if the slot is free, otherwise choose the first free one //if (i >= group.Count || group[i].Type != null) i = group.FindNextFreeSlot(i); //if (i >= group.Count) continue; // Set the type //group[i].Type = ci; var mcard = group[j]; group.Remove(group[j]); group.AddAt(mcard, i); group[i].SetVisibility(ci.Visible ? DataNew.Entities.GroupVisibility.Everybody : DataNew.Entities.GroupVisibility.Nobody, null); } group.OnShuffled(); }
public CardRun(CardIdentity id) : base(id.ToString()) { _card = id.Model; if (id.Model == null) id.Revealed += new CardIdentityNamer {Target = this}.Rename; }
public void End() { Player.Reset(); Card.Reset(); CardIdentity.Reset(); History.Reset(); Selection.Clear(); }
public void Shuffled(Group group, int[] card, short[] pos) { // Check the args if (card.Length != pos.Length) { Program.TraceWarning("[Shuffled] Cards and positions lengths don't match."); return; } group.FilledShuffleSlots += card.Length; if (group.FilledShuffleSlots > group.Count) { Program.TraceWarning("[Shuffled] Too many card positions received."); return; } // If it's the first packet we receive for this shuffle, clear all Types if (!group.HasReceivedFirstShuffledMessage) { foreach (Card c in group) { c.Type = null; } } group.HasReceivedFirstShuffledMessage = true; // Check that the server didn't change our positions if (card[0] >> 16 == Player.LocalPlayer.Id && group.MyShufflePos != null) { if (pos.Where((t, i) => t != @group.MyShufflePos[i]).Any()) { Program.TraceWarning("[Shuffled] The server has changed the order of the cards."); } group.MyShufflePos = null; } // Insert the cards for (int j = 0; j < card.Length; j++) { // Get the wished position int i = pos[j]; // Get the card CardIdentity ci = CardIdentity.Find(card[j]); if (ci == null) { Program.TraceWarning("[Shuffled] Card not found."); continue; } // Check if the slot is free, otherwise choose the first free one if (group[i].Type != null) { i = group.FindNextFreeSlot(i); } // Set the type group[i].Type = ci; group[i].SetVisibility(ci.Visible ? GroupVisibility.Everybody : GroupVisibility.Nobody, null); } if (group.FilledShuffleSlots == group.Count) { group.OnShuffled(); } }
public ChatCard(CardIdentity ci) { this.Card = ci.Model; if (ci.Model == null) { ci.Revealed += new CardIdentityNamer { Target = this } }
public void End() { Program.GameEngine = null; Player.Reset(); Card.Reset(); CardIdentity.Reset(); History.Reset(); Selection.Clear(); }
public CardRun(CardIdentity id) : base(id.ToString()) { _card = id.Model; if (id.Model == null) { id.Revealed += new CardIdentityNamer { Target = this } }
public void Reset() { TurnNumber = 0; ActivePlayer = null; foreach (var p in Player.All) { foreach (var g in p.Groups) { g.Reset(); } foreach (var c in p.Counters) { c.Reset(); } foreach (var g in Definition.Player.GlobalVariables) { p.GlobalVariables[g.Key] = g.Value.Value; } } foreach (var p in AllPhases) { p.Hold = false; } CurrentPhase = null; Table.Reset(); Card.Reset(); CardIdentity.Reset(); Selection.Clear(); if (Definition.GameBoards.ContainsKey("")) { GameBoard = Definition.GameBoards[""]; BoardImage = GameBoard.Source; } else { GameBoard = null; BoardImage = null; } foreach (var g in Definition.GlobalVariables) { GlobalVariables[g.Key] = g.Value.Value; } DeckStats.Reset(); //fix MAINWINDOW bug PlayWindow mainWin = WindowManager.PlayWindow; mainWin.RaiseEvent(new CardEventArgs(CardControl.CardHoveredEvent, mainWin)); EventProxy.OnGameStart_3_1_0_0(); EventProxy.OnGameStart_3_1_0_1(); EventProxy.OnGameStarted_3_1_0_2(); }
/// <summary>Completely remove all aliases from a group, e.g. before performing a shuffle.</summary> /// <param name="group">The group to remove all aliases from.</param> public void UnaliasGrp(Group group) { // Get the group Pile g = group as Pile; if (g == null) { Program.Trace.TraceEvent(TraceEventType.Warning, EventIds.NonGame, "[UnaliasGrp] Group is not a pile."); return; } // Collect aliases which we p List <int> cards = new List <int>(g.Count); List <ulong> types = new List <ulong>(g.Count); bool hasAlias = false; foreach (Card t in g) { CardIdentity ci = t.Type; if (ci == null) { continue; //Hack, should this ever be null? Sometimes it happens for whatever reason. } if (!ci.Alias) { continue; } hasAlias = true; if (ci.MySecret) { cards.Add(t.Id); types.Add(ci.Key); } } // Unalias cards that we know (if any) if (cards.Count > 0) { Program.Client.Rpc.Unalias(cards.ToArray(), types.ToArray()); } // If there are no alias, we may be ready to shuffle if (!hasAlias && g.WantToShuffle) { g.DoShuffle(); return; } // Mark the group for shuffling g.PreparingShuffle = true; // Notify the user Program.TracePlayerEvent(group.Owner, "{0} is being prepared for shuffle.", g); // Check for null because the chat can currently be muted (e.g. during a Mulligan scripted action) if (Program.LastChatTrace != null) { g.ShuffledTrace += (new ShuffleTraceChatHandler { Line = Program.LastChatTrace }).ReplaceText; } }
public void Reset() { TurnNumber = 0; TurnPlayer = null; foreach (var p in Player.All) { foreach (var g in p.Groups) { g.Reset(); } foreach (var c in p.Counters) { c.Reset(); } foreach (var varDef in Definition.Variables.Where(v => !v.Global && v.Reset)) { p.Variables[varDef.Name] = varDef.Default; } foreach (var g in Definition.Player.GlobalVariables) { p.GlobalVariables[g.Name] = g.DefaultValue; } } foreach (var p in AllPhases) { p.Hold = false; } CurrentPhase = null; Table.Reset(); Card.Reset(); CardIdentity.Reset(); Selection.Clear(); foreach (var varDef in Definition.Variables.Where(v => v.Global && v.Reset)) { Variables[varDef.Name] = varDef.Default; } foreach (var g in Definition.GlobalVariables) { GlobalVariables[g.Name] = g.DefaultValue; } //fix MAINWINDOW bug PlayWindow mainWin = WindowManager.PlayWindow; mainWin.RaiseEvent(new CardEventArgs(CardControl.CardHoveredEvent, mainWin)); EventProxy.OnGameStart_3_1_0_0(); EventProxy.OnGameStart_3_1_0_1(); EventProxy.OnGameStarted_3_1_0_2(); }
public void End() { Program.GameMess.OnMessage -= GameMess_OnMessage; SaveHistory(); ReplayWriter?.Dispose(); ReplayEngine?.Dispose(); _logStream?.Dispose(); Program.GameEngine = null; Player.Reset(); Card.Reset(); CardIdentity.Reset(); Selection.Clear(); }
/// <summary>Part of a shuffle process.</summary> /// <param name="group">The group being shuffled.</param> /// <param name="card">An array containing the CardIdentity ids to shuffle.</param> public void Shuffle(Group group, int[] card) { // Array to hold the new aliases (sent to CreateAlias) ulong[] aliases = new ulong[card.Length]; // Intialize the group shuffle group.FilledShuffleSlots = 0; group.HasReceivedFirstShuffledMessage = false; group.MyShufflePos = new short[card.Length]; // Check if we received enough cards if (Player.Count - 1 <= 0) { return; } if (card.Length < group.Count / (Player.Count - 1)) { Program.Trace.TraceEvent(TraceEventType.Warning, EventIds.Event, "[Shuffle] Too few cards received."); } // Do the shuffling var rnd = new CryptoRandom(); for (int i = card.Length - 1; i >= 0; i--) { int r = rnd.Next(i + 1); int tc = card[r]; card[r] = card[i]; // Create a new alias, if the card is not face up CardIdentity ci = CardIdentity.Find(tc); if (group.FindByCardIdentity(ci) != null) { card[i] = tc; aliases[i] = ulong.MaxValue; ci.Visible = true; } else { ci = new CardIdentity(Program.GameEngine.GenerateCardId()); ci.MySecret = ci.Alias = true; ci.Key = ((ulong)Crypto.PositiveRandom()) << 32 | (uint)tc; card[i] = ci.Id; aliases[i] = Crypto.ModExp(ci.Key); ci.Visible = false; } // Give a random position to the card group.MyShufflePos[i] = (short)Crypto.Random(group.Count); } // Send the results Program.Client.Rpc.CreateAlias(card, aliases); Program.Client.Rpc.Shuffled(group, card, group.MyShufflePos); }
public void Reset() { TurnNumber = 0; TurnPlayer = null; foreach (Player p in Player.All) { foreach (Group g in p.Groups) { g.Reset(); } foreach (Counter c in p.Counters) { c.Reset(); } foreach (VariableDef varDef in Definition.Variables.Where(v => !v.Global && v.Reset)) { p.Variables[varDef.Name] = varDef.DefaultValue; } foreach (GlobalVariableDef g in Definition.PlayerDefinition.GlobalVariables) { p.GlobalVariables[g.Name] = g.DefaultValue; } } Table.Reset(); Card.Reset(); CardIdentity.Reset(); Selection.Clear(); RandomRequests.Clear(); foreach (VariableDef varDef in Definition.Variables.Where(v => v.Global && v.Reset)) { Variables[varDef.Name] = varDef.DefaultValue; } foreach (GlobalVariableDef g in Definition.GlobalVariables) { GlobalVariables[g.Name] = g.DefaultValue; } //fix MAINWINDOW bug PlayWindow mainWin = Program.PlayWindow; mainWin.RaiseEvent(new CardEventArgs(CardControl.CardHoveredEvent, mainWin)); }
/// <summary>Create new CardIdentities, which hide aliases to other CardIdentities</summary> /// <param name="id">An array containing the new CardIdentity ids</param> /// <param name="type">An array with the aliased CardIdentity ids (encrypted)</param> public void CreateAlias(int[] id, ulong[] type) { byte playerId = (byte)(id[0] >> 16); // Ignore cards created by oneself if (playerId == Player.LocalPlayer.Id) { return; } for (int i = 0; i < id.Length; i++) { if (type[i] == ulong.MaxValue) { continue; } CardIdentity ci = new CardIdentity(id[i]) { Alias = true, Key = type[i] }; } }
public void SaveCard(CardParent card) { PlayerPrefs.SetString("SaveCard" + CardIdentityCollection.Count, card.NameCardType); PlayerPrefs.SetInt("SaveCardInt" + CardIdentityCollection.Count, card.IndexCard); CardIdentity[] car = new CardIdentity[CardIdentityCollection.Count]; for (int i = 0; i < CardIdentityCollection.Count; i++) { car[i] = new CardIdentity(); car[i].NameTypeCard = CardIdentityCollection[i].cardiden.NameTypeCard; car[i].IndeParentCard = CardIdentityCollection[i].cardiden.IndeParentCard; car[i].cardparentName = CardIdentityCollection[i].NameCardType; car[i].cardParent = CardIdentityCollection[i]; for (int j = 0; j < 4; j++) { car[i].Stats[j] = CardIdentityCollection[i].cardiden.Stats[j]; } } string json = JsonHelper.ToJson(car, true); File.WriteAllText(Application.dataPath + "/PlayerData.json", json + "\n"); }
/// <summary>Unalias some Cards, e.g. before a shuffle</summary> /// <param name="card">An array containing the Card ids to unalias.</param> /// <param name="type">An array containing the corresponding revealed CardIdentity ids.</param> public void Unalias(int[] card, ulong[] type) { if (card.Length != type.Length) { Program.TraceWarning("[Unalias] Card and type lengths don't match."); return; } Pile g = null; List <int> cards = new List <int>(card.Length); List <ulong> types = new List <ulong>(card.Length); for (int i = 0; i < card.Length; i++) { Card c = Card.Find(card[i]); if (c == null) { Program.TraceWarning("[Unalias] Card not found."); continue; } if (g == null) { g = c.Group as Pile; } else if (g != c.Group) { Program.TraceWarning("[Unalias] Not all cards belong to the same group!"); continue; } // Check nobody cheated if (!c.Type.MySecret) { if (c.Type.Key != Crypto.ModExp(type[i])) { Program.TraceWarning("[Unalias] Card identity doesn't match."); } } // Substitue the card's identity CardIdentity ci = CardIdentity.Find((int)type[i]); if (ci == null) { Program.TraceWarning("[Unalias] Card identity not found."); continue; } CardIdentity.Delete(c.Type.Id); c.Type = ci; // Propagate unaliasing if (ci.Alias && ci.MySecret) { cards.Add(c.Id); } types.Add(ci.Key); } if (cards.Count > 0) { Program.Client.Rpc.Unalias(cards.ToArray(), types.ToArray()); } if (g == null) { return; } if (!g.PreparingShuffle) { Program.TraceWarning("[Unalias] Cards revealed are not in a group prepared for shuffle."); return; } // If all cards are now revealed, one can proceed to shuffling if (!g.WantToShuffle) { return; } bool done = false; for (int i = 0; !done && i < g.Count; i++) { done = g[i].Type.Alias; } if (!done) { g.DoShuffle(); } }
/// <summary>Reveal a card's identity to one player only.</summary> /// <param name="players"> </param> /// <param name="card">The card, whose identity is revealed.</param> /// <param name="encrypted">Either a ulong[2] containing an encrypted aliased CardIdentity id. Or a ulong[5] containing an encrypted CardModel guid.</param> public void RevealTo(Player[] players, Card card, ulong[] encrypted) { var oldType = card.Type; ulong alias = 0; Guid id = Guid.Empty; players = players.Where(x => x != null).ToArray(); switch (encrypted.Length) { case 2: alias = Crypto.Decrypt(encrypted); break; case 5: id = Crypto.DecryptGuid(encrypted); break; default: Program.TraceWarning("[RevealTo] Invalid data received."); return; } if (!players.All(p => (card.Group.Visibility == DataNew.Entities.GroupVisibility.Custom && card.Group.Viewers.Contains(p)) || card.PlayersLooking.Contains(p) || card.PeekingPlayers.Contains(p))) { Program.TraceWarning("[RevealTo] Revealing a card to a player, who isn't allowed to see it. This indicates a bug or cheating."); } // If it's an alias, we must revealed it to the final recipient bool sendToMyself = true; if (alias != 0) { sendToMyself = false; CardIdentity ci = CardIdentity.Find((int)alias); if (ci == null) { Program.TraceWarning("[RevealTo] Identity not found."); return; } // If the revealed type is an alias, pass it to the one who owns it to continue the RevealTo chain. if (ci.Alias) { Player p = Player.Find((byte)(ci.Key >> 16)); Program.Client.Rpc.RevealToReq(p, players, card, Crypto.Encrypt(ci.Key, p.PublicKey)); } // Else revealed the card model to the ones, who must see it else { Player[] pArray = new Player[1]; foreach (Player p in players) { if (p != Player.LocalPlayer) { pArray[0] = p; Program.Client.Rpc.RevealToReq(p, pArray, card, Crypto.Encrypt(ci.Model.Id, p.PublicKey)); } else { sendToMyself = true; id = ci.Model.Id; } } } } // Else it's a type and we are the final recipients if (!sendToMyself) { return; } if (card.Type.Model == null) { card.SetModel(Program.GameEngine.Definition.GetCardById(id)); } // Raise a notification oldType.OnRevealed(card.Type); }
/// <summary>Reveal one card's identity</summary> /// <param name="card">The card, whose identity is revealed</param> /// <param name="revealed">Either the salted CardIdentity id (in the case of an alias), or the salted, condensed Card GUID.</param> /// <param name="guid"> </param> public void Reveal(Card card, ulong revealed, Guid guid) { // Save old id CardIdentity oldType = card.Type; // Check if the card is rightfully revealed if (!card.Type.Revealing) { Program.Trace.TraceEvent(TraceEventType.Warning, EventIds.Event, "Someone tries to reveal a card which is not visible to everybody."); } // Check if we can trust other clients if (!card.Type.MySecret) { if (guid != Guid.Empty && (uint)revealed != guid.Condense()) { Program.Trace.TraceEvent(TraceEventType.Warning, EventIds.Event, "[Reveal] Alias and id aren't the same. One client is buggy or tries to cheat."); } if (Crypto.ModExp(revealed) != card.Type.Key) { Program.Trace.TraceEvent(TraceEventType.Warning, EventIds.Event, "[Reveal] Card identity doesn't match. One client is buggy or tries to cheat."); } } else { card.Type.MySecret = false; } // Reveal an alias if (guid == Guid.Empty) { // Find the new type CardIdentity newId = CardIdentity.Find((int)revealed); // HACK: it is unclear to me how the CardIdentity could not be found and newId ends up null // see this bug report: https://octgn.16bugs.com/projects/3602/bugs/192070 // for now I'm just doing nothing (supposing that it means the type was already revealed). if (newId == null) { card.Reveal(); return; } // Possibly copy the model, if it was known and isn't anymore // (possible when the alias has beeen locally revealed) if (newId.Model == null) { newId.Model = card.Type.Model; } // Set the new type card.Type = newId; // Delete the old identity CardIdentity.Delete(oldType.Id); // Possibly reveal the alias further card.Reveal(); // Raise a notification oldType.OnRevealed(newId); } // Reveal a card's type else if (card.Type.Model == null) { card.SetModel(Program.GameEngine.Definition.GetCardById(guid)); // Raise a notification oldType.OnRevealed(oldType); } }
public ChatCard(CardIdentity ci) { this.Card = ci.Model; if (ci.Model == null) ci.Revealed += new CardIdentityNamer { Target = this }.Rename; }
public void Reset(bool isSoft) { TurnNumber = 0; ActivePlayer = null; foreach (var p in Player.All) { foreach (var g in p.Groups) { g.Reset(); } foreach (var c in p.Counters) { c.Reset(); } foreach (var g in Definition.Player.GlobalVariables) { p.GlobalVariables[g.Key] = g.Value.Value; } } foreach (var p in AllPhases) { p.Hold = false; } CurrentPhase = null; Table.Reset(); Card.Reset(); CardIdentity.Reset(); Selection.Clear(); ResetTableView(); foreach (var g in Definition.GlobalVariables) { GlobalVariables[g.Key] = g.Value.Value; } DeckStats.Reset(); //fix MAINWINDOW bug PlayWindow mainWin = WindowManager.PlayWindow; mainWin.RaiseEvent(new CardEventArgs(CardControl.CardHoveredEvent, mainWin)); EventProxy.OnGameStart_3_1_0_0(); EventProxy.OnGameStart_3_1_0_1(); EventProxy.OnGameStarted_3_1_0_2(); if (isSoft) { var currentDeck = new Deck() { GameId = LoadedCards.GameId, IsShared = LoadedCards.IsShared, Notes = LoadedCards.Notes, Sections = LoadedCards.Sections.ToList(), Sleeve = LoadedCards.Sleeve }; LoadedCards.Sections = new ObservableCollection <ObservableSection>(); LoadDeck(currentDeck, false); } else { LoadedCards.Sections = new ObservableCollection <ObservableSection>(); } }
public ChatCard(CardIdentity ci) { this.Card = ci.Model; }
public PlayingCard(CardSuit cardSuit, CardIdentity cardIdentity, Guid deckId) { Suit = cardSuit; Identity = cardIdentity; FromDeckId = deckId; }