/// <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); } }
/// <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="id">If the revealed identity is a model, the non-condensed CardModel guid. Otherwise this parameter should be Guid.Empty.</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); // 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(Database.GetCardById(guid)); // Raise a notification oldType.OnRevealed(oldType); } }