This commit is contained in:
yaoyanwei
2025-08-04 16:45:48 +08:00
parent 565aa16389
commit 2f2a601227
2296 changed files with 522745 additions and 93 deletions

View File

@@ -0,0 +1,47 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TcgEngine.Client;
namespace TcgEngine.UI
{
public class AdventurePanel : UIPanel
{
private List<LevelUI> level_uis = new List<LevelUI>();
private static AdventurePanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
}
protected override void Start()
{
base.Start();
level_uis.AddRange(GetComponentsInChildren<LevelUI>());
}
private void RefreshLevels()
{
foreach (LevelUI level in level_uis)
{
level.RefreshLevel();
}
}
public override void Show(bool instant = false)
{
base.Show(instant);
RefreshLevels();
}
public static AdventurePanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d5c3b04c40d2d164383a02cb820d8207
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,235 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// When clicking on a card in menu, a box will appear with additional game info
/// You can also buy cards in this panel
/// </summary>
public class CardZoomPanel : UIPanel
{
public CardUI card_ui;
public Text desc;
public Image quantity_bar;
public Text quantity_txt;
public GameObject trade_area;
public InputField trade_quantity;
public Text buy_cost;
public Text sell_cost;
public Text trade_error;
private CardData card;
private VariantData variant;
private static CardZoomPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
TabButton.onClickAny += OnClickTab;
}
private void OnDestroy()
{
TabButton.onClickAny -= OnClickTab;
}
protected override void Update()
{
base.Update();
if (card != null)
{
int quantity = GetBuyQuantity();
int cost = quantity * card.cost * variant.cost_factor;
buy_cost.text = cost.ToString();
sell_cost.text = Mathf.RoundToInt(cost * GameplayData.Get().sell_ratio).ToString();
}
}
public void ShowCard(CardData card, VariantData variant)
{
this.card = card;
this.variant = variant;
UserData udata = Authenticator.Get().UserData;
int quantity = udata.GetCardQuantity(card, variant);
quantity_txt.text = quantity.ToString();
quantity_txt.enabled = quantity > 0;
quantity_bar.enabled = quantity > 0;
trade_quantity.text = "1";
trade_error.text = "";
trade_area?.SetActive(card.deckbuilding && card.cost > 0);
card_ui.SetCard(card, variant);
string desc = card.GetDesc();
string adesc = card.GetAbilitiesDesc();
if(!string.IsNullOrWhiteSpace(desc))
this.desc.text = desc + "\n\n" + adesc;
else
this.desc.text = adesc;
Show();
}
public void RefreshCard()
{
ShowCard(card, variant);
}
private async void BuyCardTest()
{
int quantity = GetBuyQuantity();
int cost = (quantity * card.cost * variant.cost_factor);
if (quantity <= 0)
return;
UserData udata = Authenticator.Get().UserData;
if (udata.coins < cost)
return;
udata.AddCard(card.id, variant.id, quantity);
udata.coins -= cost;
await Authenticator.Get().SaveUserData();
CollectionPanel.Get().ReloadUser();
Hide();
}
private async void BuyCardApi()
{
BuyCardRequest req = new BuyCardRequest();
req.card = card.id;
req.variant = variant.id;
req.quantity = GetBuyQuantity();
if (req.quantity <= 0)
return;
string url = ApiClient.ServerURL + "/users/cards/buy/";
string jdata = ApiTool.ToJson(req);
trade_error.text = "";
WebResponse res = await ApiClient.Get().SendPostRequest(url, jdata);
if (res.success)
{
CollectionPanel.Get().ReloadUser();
Hide();
}
else
{
trade_error.text = res.error;
}
}
private async void SellCardTest()
{
int quantity = GetBuyQuantity();
int cost = Mathf.RoundToInt(quantity * card.cost * variant.cost_factor * GameplayData.Get().sell_ratio);
if (quantity <= 0)
return;
UserData udata = Authenticator.Get().UserData;
if (!udata.HasCard(card.id, variant.id, quantity))
return;
udata.AddCard(card.id, variant.id, -quantity);
udata.coins += cost;
await Authenticator.Get().SaveUserData();
CollectionPanel.Get().ReloadUser();
MainMenu.Get().RefreshDeckList();
Hide();
}
private async void SellCardApi()
{
BuyCardRequest req = new BuyCardRequest();
req.card = card.id;
req.variant = variant.id;
req.quantity = GetBuyQuantity();
if (req.quantity <= 0)
return;
string url = ApiClient.ServerURL + "/users/cards/sell/";
string jdata = ApiTool.ToJson(req);
trade_error.text = "";
WebResponse res = await ApiClient.Get().SendPostRequest(url, jdata);
if (res.success)
{
CollectionPanel.Get().ReloadUser();
Hide();
}
else
{
trade_error.text = res.error;
}
}
public void OnClickBuy()
{
if (Authenticator.Get().IsTest())
{
BuyCardTest();
}
if (Authenticator.Get().IsApi())
{
BuyCardApi();
}
}
public void OnClickSell()
{
if (Authenticator.Get().IsTest())
{
SellCardTest();
}
if (Authenticator.Get().IsApi())
{
SellCardApi();
}
}
private void OnClickTab(TabButton btn)
{
if (btn.group == "menu")
Hide();
}
public int GetBuyQuantity()
{
bool success = int.TryParse(trade_quantity.text, out int quantity);
if (success)
return quantity;
return 0;
}
public CardData GetCard()
{
return card;
}
public string GetCardId()
{
return card.id;
}
public string GetCardVariant()
{
return variant.id;
}
public static CardZoomPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 442f677c08eff7b4b99b96ddf607c8ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,74 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Visual representation of a card in your collection in the Deckbuilder
/// </summary>
public class CollectionCard : MonoBehaviour
{
public CardUI card_ui;
public Image quantity_bar;
public Text quantity;
[Header("Mat")]
public Material color_mat;
public Material grayscale_mat;
public UnityAction<CardUI> onClick;
public UnityAction<CardUI> onClickRight;
private void Start()
{
card_ui.onClick += onClick;
card_ui.onClickRight += onClickRight;
}
public void SetCard(CardData card, VariantData variant, int quantity)
{
card_ui.SetCard(card, variant);
SetQuantity(quantity);
}
public void SetQuantity(int quantity)
{
if (this.quantity_bar != null)
this.quantity_bar.enabled = quantity > 0;
if (this.quantity != null)
this.quantity.text = quantity.ToString();
if (this.quantity != null)
this.quantity.enabled = quantity > 0;
}
public void SetGrayscale(bool grayscale)
{
if (grayscale)
{
quantity_bar.material = grayscale_mat;
quantity_bar.material = grayscale_mat;
card_ui.SetMaterial(grayscale_mat);
}
else
{
quantity_bar.material = color_mat;
quantity_bar.material = color_mat;
card_ui.SetMaterial(color_mat);
}
}
public CardData GetCard()
{
return card_ui.GetCard();
}
public VariantData GetVariant()
{
return card_ui.GetVariant();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6c852677ab215914a84efd0489cd3719
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,773 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// CollectionPanel is the panel where players can see all the cards they own
/// Also the panel where they can use the deckbuilder
/// </summary>
public class CollectionPanel : UIPanel
{
[Header("Cards")]
public ScrollRect scroll_rect;
public RectTransform scroll_content;
public CardGrid grid_content;
public GameObject card_prefab;
[Header("Left Side")]
public IconButton[] team_filters;
public Toggle toggle_owned;
public Toggle toggle_not_owned;
public Toggle toggle_character;
public Toggle toggle_spell;
public Toggle toggle_artifact;
public Toggle toggle_equipment;
public Toggle toggle_secret;
public Toggle toggle_common;
public Toggle toggle_uncommon;
public Toggle toggle_rare;
public Toggle toggle_mythic;
public Toggle toggle_foil;
public Dropdown sort_dropdown;
public InputField search;
[Header("Right Side")]
public UIPanel deck_list_panel;
public UIPanel card_list_panel;
public DeckLine[] deck_lines;
[Header("Deckbuilding")]
public InputField deck_title;
public Text deck_quantity;
public GameObject deck_cards_prefab;
public RectTransform deck_content;
public GridLayoutGroup deck_grid;
public IconButton[] hero_powers;
private TeamData filter_team = null;
private int filter_dropdown = 0;
private string filter_search = "";
private List<CollectionCard> card_list = new List<CollectionCard>();
private List<CollectionCard> all_list = new List<CollectionCard>();
private List<DeckLine> deck_card_lines = new List<DeckLine>();
private string current_deck_tid;
private bool editing_deck = false;
private bool saving = false;
private bool spawned = false;
private bool update_grid = false;
private float update_grid_timer = 0f;
private List<UserCardData> deck_cards = new List<UserCardData>();
private static CollectionPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
//Delete grid content
for (int i = 0; i < grid_content.transform.childCount; i++)
Destroy(grid_content.transform.GetChild(i).gameObject);
for (int i = 0; i < deck_grid.transform.childCount; i++)
Destroy(deck_grid.transform.GetChild(i).gameObject);
foreach (DeckLine line in deck_lines)
line.onClick += OnClickDeckLine;
foreach (DeckLine line in deck_lines)
line.onClickDelete += OnClickDeckDelete;
foreach (IconButton button in team_filters)
button.onClick += OnClickTeam;
}
protected override void Start()
{
base.Start();
//Set power abilities hover text
foreach (IconButton btn in hero_powers)
{
CardData icard = CardData.Get(btn.value);
HoverTargetUI hover = btn.GetComponent<HoverTargetUI>();
AbilityData iability = icard?.GetAbility(AbilityTrigger.Activate);
if (icard != null && hover != null && iability != null)
{
string color = ColorUtility.ToHtmlStringRGBA(icard.team.color);
hover.text = "<b><color=#" + color + ">Hero Power: </color>";
hover.text += icard.title + "</b>\n " + iability.GetDesc(icard);
if (iability.mana_cost > 0)
hover.text += " <size=16>Mana: " + iability.mana_cost + "</size>";
}
}
}
protected override void Update()
{
base.Update();
}
private void LateUpdate()
{
//Resize grid
update_grid_timer += Time.deltaTime;
if (update_grid && update_grid_timer > 0.2f)
{
grid_content.GetColumnAndRow(out int rows, out int cols);
if (cols > 0)
{
float row_height = grid_content.GetGrid().cellSize.y + grid_content.GetGrid().spacing.y;
float height = rows * row_height;
scroll_content.sizeDelta = new Vector2(scroll_content.sizeDelta.x, height + 100);
update_grid = false;
}
}
}
private void SpawnCards()
{
spawned = true;
foreach (CollectionCard card in all_list)
Destroy(card.gameObject);
all_list.Clear();
foreach (VariantData variant in VariantData.GetAll())
{
foreach (CardData card in CardData.GetAll())
{
GameObject nCard = Instantiate(card_prefab, grid_content.transform);
CollectionCard dCard = nCard.GetComponent<CollectionCard>();
dCard.SetCard(card, variant, 0);
dCard.onClick += OnClickCard;
dCard.onClickRight += OnClickCardRight;
all_list.Add(dCard);
nCard.SetActive(false);
}
}
}
//----- Reload User Data ---------------
public async void ReloadUser()
{
await Authenticator.Get().LoadUserData();
MainMenu.Get().RefreshDeckList();
RefreshCardsQuantities();
if (!editing_deck)
RefreshDeckList();
}
public async void ReloadUserCards()
{
await Authenticator.Get().LoadUserData();
RefreshCardsQuantities();
}
public async void ReloadUserDecks()
{
await Authenticator.Get().LoadUserData();
MainMenu.Get().RefreshDeckList();
RefreshDeckList();
}
//----- Refresh UI --------
private void RefreshAll()
{
RefreshFilters();
RefreshCards();
RefreshDeckList();
RefreshStarterDeck();
}
private void RefreshFilters()
{
search.text = "";
sort_dropdown.value = 0;
foreach (IconButton button in team_filters)
button.Deactivate();
filter_team = null;
filter_dropdown = 0;
filter_search = "";
}
private void ShowDeckList()
{
deck_list_panel.Show();
card_list_panel.Hide();
editing_deck = false;
}
private void ShowDeckCards()
{
deck_list_panel.Hide();
card_list_panel.Show();
}
public void RefreshCards()
{
if (!spawned)
SpawnCards();
card_list.Clear();
UserData udata = Authenticator.Get().UserData;
if (udata == null)
return;
VariantData variant = VariantData.GetDefault();
VariantData special = VariantData.GetSpecial();
if (toggle_foil.isOn && special != null)
variant = special;
List<CardDataQ> all_cards = new List<CardDataQ>();
List<CardDataQ> shown_cards = new List<CardDataQ>();
foreach (CardData icard in CardData.GetAll())
{
CardDataQ card = new CardDataQ();
card.card = icard;
card.variant = variant;
card.quantity = udata.GetCardQuantity(icard, variant);
all_cards.Add(card);
}
if (filter_dropdown == 0) //Name
all_cards.Sort((CardDataQ a, CardDataQ b) => { return a.card.title.CompareTo(b.card.title); });
if (filter_dropdown == 1) //Attack
all_cards.Sort((CardDataQ a, CardDataQ b) => { return b.card.attack == a.card.attack ? b.card.hp.CompareTo(a.card.hp) : b.card.attack.CompareTo(a.card.attack); });
if (filter_dropdown == 2) //hp
all_cards.Sort((CardDataQ a, CardDataQ b) => { return b.card.hp == a.card.hp ? b.card.attack.CompareTo(a.card.attack) : b.card.hp.CompareTo(a.card.hp); });
if (filter_dropdown == 3) //Cost
all_cards.Sort((CardDataQ a, CardDataQ b) => { return b.card.mana == a.card.mana ? a.card.title.CompareTo(b.card.title) : a.card.mana.CompareTo(b.card.mana); });
foreach (CardDataQ card in all_cards)
{
if (card.card.deckbuilding)
{
CardData icard = card.card;
if (filter_team == null || filter_team == icard.team)
{
bool owned = card.quantity > 0;
RarityData rarity = icard.rarity;
CardType type = icard.type;
bool owned_check = (owned && toggle_owned.isOn)
|| (!owned && toggle_not_owned.isOn)
|| toggle_owned.isOn == toggle_not_owned.isOn;
bool type_check = (type == CardType.Character && toggle_character.isOn)
|| (type == CardType.Spell && toggle_spell.isOn)
|| (type == CardType.Artifact && toggle_artifact.isOn)
|| (type == CardType.Equipment && toggle_equipment.isOn)
|| (type == CardType.Secret && toggle_secret.isOn)
|| (!toggle_character.isOn && !toggle_spell.isOn && !toggle_artifact.isOn && !toggle_equipment.isOn && !toggle_secret.isOn);
bool rarity_check = (rarity.rank == 1 && toggle_common.isOn)
|| (rarity.rank == 2 && toggle_uncommon.isOn)
|| (rarity.rank == 3 && toggle_rare.isOn)
|| (rarity.rank == 4 && toggle_mythic.isOn)
|| (!toggle_common.isOn && !toggle_uncommon.isOn && !toggle_rare.isOn && !toggle_mythic.isOn);
string search = filter_search.ToLower();
bool search_check = string.IsNullOrWhiteSpace(search)
|| icard.id.Contains(search)
|| icard.title.ToLower().Contains(search)
|| icard.GetText().ToLower().Contains(search);
if (owned_check && type_check && rarity_check && search_check)
{
shown_cards.Add(card);
}
}
}
}
int index = 0;
foreach (CardDataQ qcard in shown_cards)
{
if (index < all_list.Count)
{
CollectionCard dcard = all_list[index];
dcard.SetCard(qcard.card, qcard.variant, 0);
card_list.Add(dcard);
if (!dcard.gameObject.activeSelf)
dcard.gameObject.SetActive(true);
index++;
}
}
for (int i = index; i < all_list.Count; i++)
all_list[i].gameObject.SetActive(false);
update_grid = true;
update_grid_timer = 0f;
scroll_rect.verticalNormalizedPosition = 1f;
RefreshCardsQuantities();
}
private void RefreshCardsQuantities()
{
UserData udata = Authenticator.Get().UserData;
foreach (CollectionCard card in card_list)
{
CardData icard = card.GetCard();
VariantData ivariant = card.GetVariant();
bool owned = IsCardOwned(udata, icard, ivariant, 1);
int quantity = udata.GetCardQuantity(icard, ivariant);
card.SetQuantity(quantity);
card.SetGrayscale(!owned);
}
}
private void RefreshDeckList()
{
foreach (DeckLine line in deck_lines)
line.Hide();
deck_cards.Clear();
editing_deck = false;
saving = false;
UserData udata = Authenticator.Get().UserData;
if (udata == null)
return;
int index = 0;
foreach (UserDeckData deck in udata.decks)
{
if (index < deck_lines.Length)
{
DeckLine line = deck_lines[index];
line.SetLine(udata, deck);
}
index++;
}
if (index < deck_lines.Length)
{
DeckLine line = deck_lines[index];
line.SetLine("+");
}
RefreshCardsQuantities();
}
private void RefreshDeck(UserDeckData deck)
{
deck_title.text = "Deck Name";
current_deck_tid = GameTool.GenerateRandomID(7);
deck_cards.Clear();
saving = false;
editing_deck = true;
foreach (IconButton btn in hero_powers)
btn.Deactivate();
if (deck != null)
{
deck_title.text = deck.title;
current_deck_tid = deck.tid;
foreach (IconButton btn in hero_powers)
{
if (deck.hero != null && btn.value == deck.hero.tid)
btn.Activate();
}
for (int i = 0; i < deck.cards.Length; i++)
{
CardData card = CardData.Get(deck.cards[i].tid);
VariantData variant = VariantData.Get(deck.cards[i].variant);
if (card != null && variant != null)
{
AddDeckCard(card, variant, deck.cards[i].quantity);
}
}
}
RefreshDeckCards();
}
private void RefreshDeckCards()
{
foreach (DeckLine line in deck_card_lines)
line.Hide();
List<CardDataQ> list = new List<CardDataQ>();
foreach (UserCardData card in deck_cards)
{
CardDataQ acard = new CardDataQ();
acard.card = CardData.Get(card.tid);
acard.variant = VariantData.Get(card.variant);
acard.quantity = card.quantity;
list.Add(acard);
}
list.Sort((CardDataQ a, CardDataQ b) => { return a.card.title.CompareTo(b.card.title); });
UserData udata = Authenticator.Get().UserData;
int index = 0;
int count = 0;
foreach (CardDataQ card in list)
{
if (index >= deck_card_lines.Count)
CreateDeckCard();
if (index < deck_card_lines.Count)
{
DeckLine line = deck_card_lines[index];
if (line != null)
{
line.SetLine(card.card, card.variant, card.quantity, !IsCardOwned(udata, card.card, card.variant, card.quantity));
count += card.quantity;
}
}
index++;
}
deck_quantity.text = count + "/" + GameplayData.Get().deck_size;
deck_quantity.color = count >= GameplayData.Get().deck_size ? Color.white : Color.red;
RefreshCardsQuantities();
}
private void RefreshStarterDeck()
{
UserData udata = Authenticator.Get().UserData;
if (udata != null && (udata.cards.Length == 0 || udata.rewards.Length == 0))
{
if (GameplayData.Get().starter_decks.Length > 0)
{
StarterDeckPanel.Get().Show();
}
}
}
//-------- Deck editing actions
private void CreateDeckCard()
{
GameObject deck_line = Instantiate(deck_cards_prefab, deck_grid.transform);
DeckLine line = deck_line.GetComponent<DeckLine>();
deck_card_lines.Add(line);
float height = deck_card_lines.Count * 70f + 20f;
deck_content.sizeDelta = new Vector2(deck_content.sizeDelta.x, height);
line.onClick += OnClickCardLine;
line.onClickRight += OnRightClickCardLine;
}
private void AddDeckCard(CardData card, VariantData variant, int quantity = 1)
{
AddDeckCard(card.id, variant.id, quantity);
}
private void RemoveDeckCard(CardData card, VariantData variant)
{
RemoveDeckCard(card.id, variant.id);
}
private void AddDeckCard(string tid, string variant, int quantity = 1)
{
UserCardData ucard = GetDeckCard(tid, variant);
if (ucard != null)
{
ucard.quantity += quantity;
}
else
{
ucard = new UserCardData(tid, variant);
ucard.quantity = quantity;
deck_cards.Add(ucard);
}
}
private void RemoveDeckCard(string tid, string variant)
{
for (int i = deck_cards.Count - 1; i >= 0; i--)
{
UserCardData ucard = deck_cards[i];
if (ucard.tid == tid && ucard.variant == variant)
{
ucard.quantity--;
if(ucard.quantity <= 0)
deck_cards.RemoveAt(i);
}
}
}
private UserCardData GetDeckCard(string tid, string variant)
{
foreach (UserCardData ucard in deck_cards)
{
if (ucard.tid == tid && ucard.variant == variant)
return ucard;
}
return null;
}
private void SaveDeck()
{
UserData udata = Authenticator.Get().UserData;
UserDeckData udeck = new UserDeckData();
udeck.tid = current_deck_tid;
udeck.title = deck_title.text;
udeck.hero = new UserCardData();
udeck.hero.tid = GetSelectedHeroId();
udeck.hero.variant = VariantData.GetDefault().id;
udeck.cards = deck_cards.ToArray();
saving = true;
if (Authenticator.Get().IsTest())
SaveDeckTest(udata, udeck);
if (Authenticator.Get().IsApi())
SaveDeckAPI(udata, udeck);
ShowDeckList();
}
private async void SaveDeckTest(UserData udata, UserDeckData udeck)
{
udata.SetDeck(udeck);
await Authenticator.Get().SaveUserData();
ReloadUserDecks();
}
private async void SaveDeckAPI(UserData udata, UserDeckData udeck)
{
string url = ApiClient.ServerURL + "/users/deck/" + udeck.tid;
string jdata = ApiTool.ToJson(udeck);
WebResponse res = await ApiClient.Get().SendPostRequest(url, jdata);
UserDeckData[] decks = ApiTool.JsonToArray<UserDeckData>(res.data);
saving = res.success;
if (res.success && decks != null)
{
udata.decks = decks;
await Authenticator.Get().SaveUserData();
ReloadUserDecks();
}
}
private async void DeleteDeck(string deck_tid)
{
UserData udata = Authenticator.Get().UserData;
UserDeckData udeck = udata.GetDeck(deck_tid);
List<UserDeckData> decks = new List<UserDeckData>(udata.decks);
decks.Remove(udeck);
udata.decks = decks.ToArray();
if (Authenticator.Get().IsApi())
{
string url = ApiClient.ServerURL + "/users/deck/" + deck_tid;
await ApiClient.Get().SendRequest(url, "DELETE", "");
}
await Authenticator.Get().SaveUserData();
ReloadUserDecks();
}
//---- Left Panel Filters Clicks -----------
public void OnClickTeam(IconButton button)
{
filter_team = null;
if (button.IsActive())
{
foreach (TeamData team in TeamData.GetAll())
{
if (button.value == team.id)
filter_team = team;
}
}
RefreshCards();
}
public void OnChangeToggle()
{
RefreshCards();
}
public void OnChangeDropdown()
{
filter_dropdown = sort_dropdown.value;
RefreshCards();
}
public void OnChangeSearch()
{
filter_search = search.text;
RefreshCards();
}
//---- Card grid clicks ----------
public void OnClickCard(CardUI card)
{
if (!editing_deck)
{
CardZoomPanel.Get().ShowCard(card.GetCard(), card.GetVariant());
return;
}
CardData icard = card.GetCard();
VariantData variant = card.GetVariant();
if (icard != null)
{
int in_deck = CountDeckCards(icard, variant);
int in_deck_same = CountDeckCards(icard);
UserData udata = Authenticator.Get().UserData;
bool owner = IsCardOwned(udata, card.GetCard(), card.GetVariant(), in_deck + 1);
bool deck_limit = in_deck_same < GameplayData.Get().deck_duplicate_max;
if (owner && deck_limit)
{
AddDeckCard(icard, variant);
RefreshDeckCards();
}
}
}
public void OnClickCardRight(CardUI card)
{
CardZoomPanel.Get().ShowCard(card.GetCard(), card.GetVariant());
}
//---- Right Panel Click -------
public void OnClickDeckLine(DeckLine line)
{
if (line.IsHidden() || saving)
return;
UserDeckData deck = line.GetUserDeck();
RefreshDeck(deck);
ShowDeckCards();
}
private void OnClickCardLine(DeckLine line)
{
CardData card = line.GetCard();
VariantData variant = line.GetVariant();
if (card != null)
{
RemoveDeckCard(card, variant);
}
RefreshDeckCards();
}
private void OnRightClickCardLine(DeckLine line)
{
CardData icard = line.GetCard();
if (icard != null)
CardZoomPanel.Get().ShowCard(icard, line.GetVariant());
}
// ---- Deck editing Click -----
public void OnClickSaveDeck()
{
if (!saving)
{
SaveDeck();
}
}
public void OnClickDeckBack()
{
ShowDeckList();
}
public void OnClickDeleteDeck()
{
if (editing_deck && !string.IsNullOrEmpty(current_deck_tid))
{
DeleteDeck(current_deck_tid);
}
}
public void OnClickDeckDelete(DeckLine line)
{
if (line.IsHidden())
return;
UserDeckData deck = line.GetUserDeck();
if (deck != null)
{
DeleteDeck(deck.tid);
}
}
// ---- Getters -----
public int CountDeckCards(CardData card, VariantData cvariant)
{
int count = 0;
foreach (UserCardData ucard in deck_cards)
{
if (ucard.tid == card.id && ucard.variant == cvariant.id)
count += ucard.quantity;
}
return count;
}
public int CountDeckCards(CardData card)
{
int count = 0;
foreach (UserCardData ucard in deck_cards)
{
if (ucard.tid == card.id)
count += ucard.quantity;
}
return count;
}
private bool IsCardOwned(UserData udata, CardData card, VariantData variant, int quantity)
{
return udata.GetCardQuantity(card, variant) >= quantity;
}
private string GetSelectedHeroId()
{
foreach (IconButton btn in hero_powers)
{
if (btn.IsActive())
return btn.value;
}
return "";
}
//-----
public override void Show(bool instant = false)
{
base.Show(instant);
RefreshAll();
ShowDeckList();
}
public static CollectionPanel Get()
{
return instance;
}
}
public struct CardDataQ
{
public CardData card;
public VariantData variant;
public int quantity;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8c21fdd2942c6eb408727ee91fb6f9ae
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,236 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// One line in the deckbuilder (can contain a card or a deck title)
/// </summary>
public class DeckLine : MonoBehaviour, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler
{
public Image image;
public Image frame;
public Text title;
public Text value;
public IconValue cost;
public UIPanel delete_btn;
public AudioClip click_audio;
public Material disabled_mat;
public Material default_mat;
public UnityAction<DeckLine> onClick;
public UnityAction<DeckLine> onClickRight;
public UnityAction<DeckLine> onClickDelete;
private CardData card;
private VariantData variant;
private DeckData deck;
private UserDeckData udeck;
private bool hidden = false;
private bool hover = false;
void Awake()
{
}
void Update()
{
if (delete_btn != null)
{
bool visi = hover || GameTool.IsMobile();
delete_btn.SetVisible(visi && !hidden && udeck != null);
}
}
public void SetLine(CardData card, VariantData variant, int quantity, bool invalid = false)
{
this.card = card;
this.variant = variant;
this.deck = null;
this.udeck = null;
hidden = false;
if (title != null)
title.text = card.title;
if (title != null)
title.color = variant.color;
if (value != null)
value.text = quantity.ToString();
if (value != null)
value.enabled = quantity > 1;
if (cost != null)
cost.value = card.mana;
if (this.value != null)
this.value.color = invalid ? Color.red : Color.white;
if(invalid)
title.color = Color.gray;
if (image != null)
{
image.sprite = card.GetFullArt(variant);
image.enabled = true;
image.material = invalid ? disabled_mat : default_mat;
}
if (frame != null)
{
frame.sprite = variant.frame;
frame.enabled = true;
frame.material = invalid ? disabled_mat : default_mat;
}
gameObject.SetActive(true);
}
public void SetLine(DeckData deck)
{
this.card = null;
this.deck = deck;
this.udeck = null;
hidden = false;
if (this.title != null)
this.title.text = deck.title;
if (this.title != null)
this.title.color = Color.white;
if (this.value != null)
this.value.text = deck.GetQuantity().ToString();
if (this.value != null)
this.value.enabled = deck.GetQuantity() > 0;
gameObject.SetActive(true);
}
public void SetLine(UserData udata, UserDeckData deck)
{
this.card = null;
this.deck = null;
this.udeck = deck;
hidden = false;
if (this.title != null)
this.title.text = deck.title;
if (this.title != null)
this.title.color = Color.white;
if (this.value != null)
this.value.text = deck.GetQuantity().ToString() + "/" + GameplayData.Get().deck_size;
if (this.value != null)
this.value.enabled = deck.GetQuantity() > 0;
if (this.value != null)
this.value.color = udata.IsDeckValid(deck) ? Color.white : Color.red;
gameObject.SetActive(true);
}
public void SetLine(string title)
{
this.card = null;
this.deck = null;
this.udeck = null;
hidden = false;
if (this.title != null)
this.title.text = title;
if (this.title != null)
this.title.color = Color.white;
if (this.value != null)
this.value.enabled = false;
gameObject.SetActive(true);
}
public void Hide()
{
this.card = null;
this.deck = null;
this.udeck = null;
hidden = true;
hover = false;
if (title != null)
title.text = "";
if (this.title != null)
this.title.color = Color.white;
if (value != null)
value.text = "";
if (value != null)
value.enabled = true;
if (cost != null)
cost.value = 0;
if (image != null)
image.enabled = false;
if (frame != null)
frame.enabled = false;
if (delete_btn != null)
delete_btn.SetVisible(false);
gameObject.SetActive(false);
}
public CardData GetCard()
{
return card;
}
public VariantData GetVariant()
{
return variant;
}
public DeckData GetDeck()
{
return deck;
}
public UserDeckData GetUserDeck()
{
return udeck;
}
public bool IsHidden()
{
return hidden;
}
public void OnPointerClick(PointerEventData eventData)
{
if (hidden)
return;
if (eventData.button == PointerEventData.InputButton.Left)
{
onClick?.Invoke(this);
AudioTool.Get().PlaySFX("ui", click_audio);
}
if (eventData.button == PointerEventData.InputButton.Right)
{
onClickRight?.Invoke(this);
AudioTool.Get().PlaySFX("ui", click_audio);
}
}
public void OnClickDelete()
{
onClickDelete?.Invoke(this);
AudioTool.Get().PlaySFX("ui", click_audio);
}
public void OnPointerEnter(PointerEventData eventData)
{
hover = true;
}
public void OnPointerExit(PointerEventData eventData)
{
hover = false;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a983e14bd852ed04c8139d01f5db1451
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// One friend in the friend panel
/// displays avatar, username and has buttons to interact with the friend
/// </summary>
public class FriendLine : MonoBehaviour
{
public Text username;
public Image avatar;
public Image online_img;
public Sprite online_sprite;
public Sprite offline_sprite;
public Button accept_btn;
public Button reject_btn;
public Button watch_btn;
public Button challenge_btn;
public UnityAction<FriendLine> onClick;
public UnityAction<FriendLine> onClickAccept;
public UnityAction<FriendLine> onClickReject;
public UnityAction<FriendLine> onClickWatch;
public UnityAction<FriendLine> onClickChallenge;
private FriendData fdata;
private Sprite default_avat;
private void Awake()
{
default_avat = avatar.sprite;
if (accept_btn != null)
accept_btn.onClick.AddListener(() => { onClickAccept?.Invoke(this); });
if (reject_btn != null)
reject_btn.onClick.AddListener(() => { onClickReject?.Invoke(this); });
if (watch_btn != null)
watch_btn.onClick.AddListener(() => { onClickWatch?.Invoke(this); });
if (challenge_btn != null)
challenge_btn.onClick.AddListener(() => { onClickChallenge?.Invoke(this); });
}
public void SetLine(FriendData user, bool online, bool is_request = false)
{
fdata = user;
username.text = user.username;
avatar.sprite = default_avat;
if (avatar != null)
{
AvatarData avat = AvatarData.Get(user.avatar);
if (avat != null)
avatar.sprite = avat.avatar;
}
if (online_img != null)
{
online_img.sprite = online ? online_sprite : offline_sprite;
}
if (watch_btn != null)
watch_btn.gameObject.SetActive(online && !is_request);
if (challenge_btn != null)
challenge_btn.gameObject.SetActive(online && !is_request);
if (accept_btn != null)
accept_btn.gameObject.SetActive(is_request);
if (reject_btn != null)
reject_btn.gameObject.SetActive(is_request);
gameObject.SetActive(true);
}
public void Hide()
{
gameObject.SetActive(false);
}
public void OnClick()
{
onClick?.Invoke(this);
}
public FriendData GetFriend()
{
return fdata;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c3d909095a277d84294ae75bf86a1898
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,237 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Friend panel is the panel that contain all your list of friend, and where you can invite new ones
/// </summary>
public class FriendPanel : UIPanel
{
public ScrollRect friend_scroll;
public RectTransform friend_content;
public FriendLine line_prefab;
public InputField friend_input;
public TabButton friends_tab;
public TabButton requests_tab;
public int online_duration = 10; //In minutes
public Text test_msg;
public Text error;
private List<FriendLine> friend_lines = new List<FriendLine>();
private static FriendPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
InitLines();
}
protected override void Start()
{
base.Start();
friends_tab.onClick += RefreshPanel;
requests_tab.onClick += RefreshPanel;
}
private void InitLines()
{
int nlines = 100;
for (int i = 0; i < nlines; i++)
{
FriendLine line = AddLine(line_prefab, i);
line.Hide();
friend_lines.Add(line);
}
friend_scroll.verticalNormalizedPosition = 1f;
}
private FriendLine AddLine(FriendLine template, int index)
{
GameObject line = Instantiate(template.gameObject, friend_content);
RectTransform rtrans = line.GetComponent<RectTransform>();
FriendLine rline = line.GetComponent<FriendLine>();
rline.onClick += OnClickFriendLine;
rline.onClickAccept += OnClickFriendAccept;
rline.onClickReject += OnClickFriendReject;
rline.onClickWatch += OnClickFriendWatch;
rline.onClickChallenge += OnClickFriendChallenge;
return rline;
}
private async void RefreshPanel()
{
foreach (FriendLine line in friend_lines)
line.Hide();
if(test_msg != null)
test_msg.enabled = Authenticator.Get().IsTest();
if (!Authenticator.Get().IsApi())
return;
string url = ApiClient.ServerURL + "/users/friends/list";
WebResponse res = await ApiClient.Get().SendGetRequest(url);
if (res.success)
{
FriendResponse contract_list = ApiTool.JsonToObject<FriendResponse>(res.data);
if (friends_tab.active)
SetFriends(contract_list);
else if (requests_tab.active)
SetRequests(contract_list);
}
}
private void SetFriends(FriendResponse contract_list)
{
DateTime server_time = DateTime.Parse(contract_list.server_time);
DateTime login_time = server_time.AddMinutes(-online_duration);
int index = 0;
foreach (FriendData user in contract_list.friends)
{
if (index < friend_lines.Count)
{
FriendLine line = friend_lines[index];
bool valid = DateTime.TryParse(user.last_online_time, out DateTime last_login);
bool online = valid && last_login > login_time;
line.SetLine(user, online);
}
index++;
}
}
private void SetRequests(FriendResponse contract_list)
{
DateTime server_time = DateTime.Parse(contract_list.server_time);
DateTime login_time = server_time.AddMinutes(-10);
int index = 0;
foreach (FriendData user in contract_list.friends_requests)
{
if (index < friend_lines.Count)
{
FriendLine line = friend_lines[index];
bool valid = DateTime.TryParse(user.last_online_time, out DateTime last_login);
bool online = valid && last_login > login_time;
line.SetLine(user, online, true);
}
index++;
}
}
private async void AddFriend(string fuser)
{
FriendAddRequest req = new FriendAddRequest();
req.username = fuser;
string url = ApiClient.ServerURL + "/users/friends/add";
string json = ApiTool.ToJson(req);
WebResponse res = await ApiClient.Get().SendPostRequest(url, json);
if (res.success)
{
RefreshPanel();
}
else
{
error.text = res.error;
}
}
private async void RemoveFriend(string fuser)
{
FriendAddRequest req = new FriendAddRequest();
req.username = fuser;
string url = ApiClient.ServerURL + "/users/friends/remove";
string json = ApiTool.ToJson(req);
WebResponse res = await ApiClient.Get().SendPostRequest(url, json);
if (res.success)
{
RefreshPanel();
}
else
{
error.text = res.error;
}
}
public void OnClickBack()
{
Hide();
}
private void OnClickFriendLine(FriendLine user)
{
}
private void OnClickFriendAccept(FriendLine user)
{
FriendData friend = user.GetFriend();
AddFriend(friend.username);
}
private void OnClickFriendReject(FriendLine user)
{
FriendData friend = user.GetFriend();
RemoveFriend(friend.username);
}
private void OnClickFriendWatch(FriendLine user)
{
FriendData friend = user.GetFriend();
MainMenu.Get().StartObserve(friend.username);
}
private void OnClickFriendChallenge(FriendLine user)
{
FriendData friend = user.GetFriend();
MainMenu.Get().StartChallenge(friend.username);
}
public void OnClickAddFriend()
{
string fuser = friend_input.text;
if (string.IsNullOrWhiteSpace(fuser))
return;
error.text = "";
AddFriend(fuser);
}
public void OnClickRemoveFriend()
{
string fuser = friend_input.text;
if (string.IsNullOrWhiteSpace(fuser))
return;
error.text = "";
RemoveFriend(fuser);
}
public override void Show(bool instant = false)
{
base.Show(instant);
error.text = "";
friend_input.text = "";
friends_tab.Activate();
RefreshPanel();
}
public static FriendPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8101e7d3742bfc3498352704c05474ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
public class JoinCodePanel : UIPanel
{
public InputField code_field;
private string game_code = "";
private static JoinCodePanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
}
protected override void Update()
{
base.Update();
}
public void OnClickRandomize()
{
game_code = GameTool.GenerateRandomID(4,6).ToUpper();
code_field.text = game_code;
}
public void OnClickJoinCode()
{
if (code_field.text.Length < 3)
return;
game_code = code_field.text.ToUpper();
MainMenu.Get().StartMathmaking(GameMode.Casual, "code_" + game_code);
Hide();
}
public override void Show(bool instant = false)
{
base.Show(instant);
code_field.text = "";
}
public string GetCode()
{
return game_code;
}
public static JoinCodePanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c89aca657ab2247438f1cb2eb877dafb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,135 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Leaderboard panel contains the ranking of all top players
/// </summary>
public class LeaderboardPanel : UIPanel
{
public RectTransform content;
public RankLine line_template;
public RankLine my_line;
public float line_spacing = 80f;
public Text test_text;
private List<RankLine> lines = new List<RankLine>();
private static LeaderboardPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
//lines = scroll_content.GetComponentsInChildren<RankLine>();
my_line.onClick += OnClickLine;
InitLines();
}
private void OnDestroy()
{
}
private void InitLines()
{
for (int i = 0; i < content.transform.childCount; i++)
Destroy(content.transform.GetChild(i).gameObject);
int nlines = 100;
for (int i = 0; i < nlines; i++)
{
RankLine line = AddLine(line_template, i);
lines.Add(line);
}
content.sizeDelta = new Vector2(content.sizeDelta.x, nlines * line_spacing + 20f);
}
private RankLine AddLine(RankLine template, int index)
{
Vector2 pos = Vector2.down * line_spacing;
GameObject line = Instantiate(template.gameObject, content);
RectTransform rtrans = line.GetComponent<RectTransform>();
RankLine rline = line.GetComponent<RankLine>();
rtrans.anchorMin = new Vector2(0.5f, 1f);
rtrans.anchorMax = new Vector2(0.5f, 1f);
rtrans.anchoredPosition = pos + Vector2.down * index * line_spacing;
rline.onClick += OnClickLine;
return rline;
}
private async void RefreshPanel()
{
my_line.Hide();
foreach (RankLine line in lines)
line.Hide();
test_text.enabled = !Authenticator.Get().IsApi();
if (!Authenticator.Get().IsApi())
return;
UserData udata = ApiClient.Get().UserData;
int index = 0;
string url = ApiClient.ServerURL + "/users";
WebResponse res = await ApiClient.Get().SendGetRequest(url);
UserData[] users = ApiTool.JsonToArray<UserData>(res.data);
List<UserData> sorted_users = new List<UserData>(users);
sorted_users.Sort((UserData a, UserData b) => { return b.elo.CompareTo(a.elo); });
int previous_rank = 0;
int previous_index = 0;
foreach (UserData user in sorted_users)
{
if (user.permission_level != 1 || user.matches == 0)
continue; //Dont show admins and user with no matches
if (user.username == udata.username)
{
my_line.SetLine(user, index + 1, true);
}
if (index < lines.Count)
{
RankLine line = lines[index];
int rank_order = (previous_rank == user.elo) ? previous_index : index;
line.SetLine(user, rank_order + 1, user.username == udata.username);
previous_rank = user.elo;
previous_index = rank_order;
}
index++;
}
}
private void OnClickLine(string username)
{
}
public override void Show(bool instant = false)
{
base.Show(instant);
RefreshPanel();
}
public void OnClickBack()
{
Hide();
}
public static LeaderboardPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 013b4a582c8245d4d806a612e1f40c5f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,72 @@
using System.Collections;
using System.Collections.Generic;
using TcgEngine.Client;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
public class LevelUI : MonoBehaviour
{
[Header("Level")]
public LevelData level;
[Header("UI")]
public Text title;
public Text subtitle;
public DeckDisplay deck;
public GameObject completed;
void Start()
{
Button btn = GetComponent<Button>();
btn.onClick.AddListener(OnClick);
completed.SetActive(false);
if (level != null)
SetLevel(level);
else
Hide();
}
public void SetLevel(LevelData level)
{
this.level = level;
RefreshLevel();
}
public void RefreshLevel()
{
if (level != null)
{
title.text = level.title;
subtitle.text = "LEVEL " + level.level;
deck.SetDeck(level.player_deck);
gameObject.SetActive(true);
UserData udata = Authenticator.Get().GetUserData();
if(udata != null)
completed.SetActive(udata.HasReward(level.id));
}
}
public void Hide()
{
gameObject.SetActive(false);
}
public void OnClick()
{
if (level != null)
{
GameClient.game_settings.level = level.id;
GameClient.game_settings.scene = level.scene;
GameClient.player_settings.deck = new UserDeckData(level.player_deck);
GameClient.ai_settings.deck = new UserDeckData(level.ai_deck);
GameClient.ai_settings.ai_level = level.ai_level;
MainMenu.Get().StartGame(GameType.Adventure, GameMode.Casual);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ceaf1c3e9e82d624ab97e375323a23ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,248 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Main script for the login menu scene
/// </summary>
public class LoginMenu : MonoBehaviour
{
[Header("Login")]
public UIPanel login_panel;
public InputField login_user;
public InputField login_password;
public Button login_button;
public GameObject login_bottom;
public Text error_msg;
[Header("Register")]
public UIPanel register_panel;
public InputField register_username;
public InputField register_email;
public InputField register_password;
public InputField register_password_confirm;
public Button register_button;
[Header("Other")]
public GameObject test_area;
[Header("Music")]
public AudioClip music;
private bool clicked = false;
private static LoginMenu instance;
void Awake()
{
instance = this;
}
private void Start()
{
AudioTool.Get().PlayMusic("music", music);
BlackPanel.Get().Show(true);
error_msg.text = "";
test_area.SetActive(Authenticator.Get().IsTest());
string user = PlayerPrefs.GetString("tcg_last_user", "");
login_user.text = user;
if (Authenticator.Get().IsTest())
{
login_password.gameObject.SetActive(false);
login_bottom.SetActive(false);
}
else if (!string.IsNullOrEmpty(user))
{
SelectField(login_password);
}
RefreshLogin();
}
void Update()
{
login_button.interactable = !clicked && !string.IsNullOrWhiteSpace(login_user.text);
register_button.interactable = !clicked && !string.IsNullOrWhiteSpace(register_username.text) && !string.IsNullOrWhiteSpace(register_email.text)
&& !string.IsNullOrWhiteSpace(register_password.text) && register_password.text == register_password_confirm.text;
if (login_panel.IsVisible())
{
if (Input.GetKeyDown(KeyCode.Tab))
{
if (login_user.isFocused)
SelectField(login_password);
else
SelectField(login_user);
}
if (Input.GetKeyDown(KeyCode.Return))
{
if (login_button.interactable)
OnClickLogin();
}
}
if (register_panel.IsVisible())
{
if (Input.GetKeyDown(KeyCode.Tab))
{
if (register_username.isFocused)
SelectField(register_email);
else if (register_email.isFocused)
SelectField(register_password);
else if (register_password.isFocused)
SelectField(register_password_confirm);
else
SelectField(register_username);
}
if (Input.GetKeyDown(KeyCode.Return))
{
if (register_button.interactable)
OnClickRegister();
}
}
}
private async void RefreshLogin()
{
bool success = await Authenticator.Get().RefreshLogin();
if (success)
{
SceneNav.GoTo("Menu");
}
else
{
login_panel.Show();
BlackPanel.Get().Hide();
}
}
private async void Login(string user, string password)
{
clicked = true;
error_msg.text = "";
bool success = await Authenticator.Get().Login(user, password);
if (success)
{
PlayerPrefs.SetString("tcg_last_user", login_user.text);
FadeToScene("Menu");
}
else
{
clicked = false;
error_msg.text = Authenticator.Get().GetError();
}
}
private async void Register(string email, string user, string password)
{
clicked = true;
error_msg.text = "";
bool success = await Authenticator.Get().Register(register_email.text, register_username.text, register_password.text);
if (success)
{
login_user.text = register_username.text;
login_password.text = register_password.text;
login_panel.Show();
register_panel.Hide();
}
else
{
error_msg.text = Authenticator.Get().GetError();
}
clicked = false;
}
public void OnClickLogin()
{
if (string.IsNullOrWhiteSpace(login_user.text))
return;
if (clicked)
return;
Login(login_user.text, login_password.text);
}
public void OnClickRegister()
{
if (string.IsNullOrWhiteSpace(register_username.text))
return;
if (string.IsNullOrWhiteSpace(register_email.text))
return;
if (register_password.text != register_password_confirm.text)
return;
if (clicked)
return;
Register(register_email.text, register_username.text, register_password.text);
}
public void OnClickSwitchLogin()
{
login_panel.Show();
register_panel.Hide();
login_user.text = "";
login_password.text = "";
error_msg.text = "";
SelectField(login_user);
}
public void OnClickSwitchRegister()
{
login_panel.Hide();
register_panel.Show();
error_msg.text = "";
SelectField(register_username);
}
public void OnClickSwitchReset()
{
RecoveryPanel.Get().Show();
}
public void OnClickGo()
{
FadeToScene("Menu");
}
public void OnClickQuit()
{
Application.Quit();
}
private void SelectField(InputField field)
{
if (!GameTool.IsMobile())
field.Select();
}
public void FadeToScene(string scene)
{
StartCoroutine(FadeToRun(scene));
}
private IEnumerator FadeToRun(string scene)
{
BlackPanel.Get().Show();
AudioTool.Get().FadeOutMusic("music");
yield return new WaitForSeconds(1f);
SceneNav.GoTo(scene);
}
public static LoginMenu Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 54f5c2c32048d6541ad339bf1c47fd94
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,308 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
namespace TcgEngine.UI
{
/// <summary>
/// Main script for the main menu scene
/// </summary>
public class MainMenu : MonoBehaviour
{
public AudioClip music;
public AudioClip ambience;
[Header("Player UI")]
public Text username_txt;
public Text credits_txt;
public AvatarUI avatar;
public GameObject loader;
[Header("UI")]
public Text version_text;
public DeckSelector deck_selector;
public DeckDisplay deck_preview;
private bool starting = false;
private static MainMenu instance;
void Awake()
{
instance = this;
//Set default settings
Application.targetFrameRate = 120;
GameClient.game_settings = GameSettings.Default;
}
private void Start()
{
BlackPanel.Get().Show(true);
AudioTool.Get().PlayMusic("music", music);
AudioTool.Get().PlaySFX("ambience", ambience, 0.5f, true, true);
username_txt.text = "";
credits_txt.text = "";
version_text.text = "Version " + Application.version;
deck_selector.onChange += OnChangeDeck;
if (Authenticator.Get().IsConnected())
AfterLogin();
else
RefreshLogin();
}
void Update()
{
UserData udata = Authenticator.Get().UserData;
if (udata != null)
{
credits_txt.text = GameUI.FormatNumber(udata.coins);
}
bool matchmaking = GameClientMatchmaker.Get().IsMatchmaking();
if (loader.activeSelf != matchmaking)
loader.SetActive(matchmaking);
if (MatchmakingPanel.Get().IsVisible() != matchmaking)
MatchmakingPanel.Get().SetVisible(matchmaking);
}
private async void RefreshLogin()
{
bool success = await Authenticator.Get().RefreshLogin();
if (success)
AfterLogin();
else
SceneNav.GoTo("LoginMenu");
}
private void AfterLogin()
{
BlackPanel.Get().Hide();
//Events
GameClientMatchmaker matchmaker = GameClientMatchmaker.Get();
matchmaker.onMatchmaking += OnMatchmakingDone;
matchmaker.onMatchList += OnReceiveObserver;
//Deck
GameClient.player_settings.deck.tid = PlayerPrefs.GetString("tcg_deck_" + Authenticator.Get().Username, "");
//UserData
RefreshUserData();
//Friend list
//FriendPanel.Get().Show();
}
public async void RefreshUserData()
{
UserData user = await Authenticator.Get().LoadUserData();
if (user != null)
{
username_txt.text = user.username;
credits_txt.text = GameUI.FormatNumber(user.coins);
AvatarData avatar = AvatarData.Get(user.avatar);
this.avatar.SetAvatar(avatar);
//Decks
RefreshDeckList();
}
}
public void RefreshDeckList()
{
deck_selector.SetupUserDeckList();
deck_selector.SelectDeck(GameClient.player_settings.deck.tid);
RefreshDeck(deck_selector.GetDeckID());
}
private void RefreshDeck(string tid)
{
if (deck_preview != null)
{
deck_preview.SetDeck(tid);
}
}
private void OnChangeDeck(string tid)
{
GameClient.player_settings.deck = deck_selector.GetDeck();
PlayerPrefs.SetString("tcg_deck_" + Authenticator.Get().Username, tid);
RefreshDeck(tid);
}
private void OnMatchmakingDone(MatchmakingResult result)
{
if (result == null)
return;
if (result.success)
{
Debug.Log("Matchmaking found: " + result.success + " " + result.server_url + "/" + result.game_uid);
StartGame(GameType.Multiplayer, result.game_uid, result.server_url);
}
else
{
MatchmakingPanel.Get().SetCount(result.players);
}
}
private void OnReceiveObserver(MatchList list)
{
MatchListItem target = null;
foreach (MatchListItem item in list.items)
{
if (item.username == GameClient.observe_user)
target = item;
}
if (target != null)
{
StartGame(GameType.Observer, target.game_uid, target.game_url);
}
}
public void StartGame(GameType type, GameMode mode)
{
string uid = GameTool.GenerateRandomID();
GameClient.game_settings.game_type = type;
GameClient.game_settings.game_mode = mode;
StartGame(uid);
}
public void StartGame(GameType type, string game_uid, string server_url = "")
{
GameClient.game_settings.game_type = type;
StartGame(game_uid, server_url);
}
public void StartGame(string game_uid, string server_url = "")
{
if (!starting)
{
starting = true;
GameClient.game_settings.server_url = server_url; //Empty server_url will use the default one in NetworkData
GameClient.game_settings.game_uid = game_uid;
GameClientMatchmaker.Get().Disconnect();
FadeToScene(GameClient.game_settings.GetScene());
}
}
public void StartObserve(string user)
{
GameClient.observe_user = user;
GameClientMatchmaker.Get().StopMatchmaking();
GameClientMatchmaker.Get().RefreshMatchList(user);
}
public void StartChallenge(string user)
{
string self = Authenticator.Get().Username;
if (self == user)
return; //Cant challenge self
string key;
if (self.CompareTo(user) > 0)
key = self + "-" + user;
else
key = user + "-" + self;
StartMathmaking(GameMode.Casual, key);
}
public void StartMathmaking(GameMode mode, string group)
{
UserDeckData deck = deck_selector.GetDeck();
if (deck != null)
{
GameClient.game_settings.game_type = GameType.Multiplayer;
GameClient.game_settings.game_mode = mode;
GameClient.player_settings.deck = deck;
GameClient.game_settings.scene = GameplayData.Get().GetRandomArena();
GameClientMatchmaker.Get().StartMatchmaking(group, GameClient.game_settings.nb_players);
}
}
public void OnClickSolo()
{
if (!Authenticator.Get().IsConnected())
{
FadeToScene("LoginMenu");
return;
}
SoloPanel.Get().Show();
}
public void OnClickPvP()
{
if (!Authenticator.Get().IsConnected())
{
FadeToScene("LoginMenu");
return;
}
UserDeckData deck = deck_selector.GetDeck();
if (deck == null || !deck.IsValid())
return;
StartMathmaking(GameMode.Ranked, "");
}
public void OnClickAdventure()
{
AdventurePanel.Get().Show();
}
public void OnClickPlayCode()
{
JoinCodePanel.Get().Show();
}
public void OnClickCancelMatch()
{
GameClientMatchmaker.Get().StopMatchmaking();
}
public void OnClickSettings()
{
SettingsPanel.Get().Show();
}
public void FadeToScene(string scene)
{
StartCoroutine(FadeToRun(scene));
}
private IEnumerator FadeToRun(string scene)
{
BlackPanel.Get().Show();
AudioTool.Get().FadeOutMusic("music");
yield return new WaitForSeconds(1f);
SceneNav.GoTo(scene);
}
public void OnClickLogout()
{
TcgNetwork.Get().Disconnect();
Authenticator.Get().Logout();
FadeToScene("LoginMenu");
}
public void OnClickQuit()
{
Application.Quit();
}
public static MainMenu Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a8e583b854bee243b818256874f8a1b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,73 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using TcgEngine.Client;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// Matchmaking panel is just a loading panel that displays how many players are found yet
/// </summary>
public class MatchmakingPanel : UIPanel
{
public Text text;
public Text players_txt;
public Text code_txt;
private static MatchmakingPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
}
protected override void Start()
{
base.Start();
code_txt.text = "";
}
protected override void Update()
{
base.Update();
if (GameClientMatchmaker.Get().IsConnected())
text.text = "Finding Opponent...";
else
text.text = "Connecting to server...";
code_txt.text = "";
string group = GameClientMatchmaker.Get().GetGroup();
if (group != null && group.StartsWith("code_"))
code_txt.text = group.Replace("code_", "");
}
public void SetCount(int players)
{
if (players_txt != null)
players_txt.text = players.ToString() + "/" + GameClientMatchmaker.Get().GetNbPlayers();
}
public void OnClickCancel()
{
GameClientMatchmaker.Get().StopMatchmaking();
Hide();
}
public override void Show(bool instant = false)
{
base.Show(instant);
if (players_txt != null)
players_txt.text = "";
}
public static MatchmakingPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 726315068a2ad3c4cbed6c689ab69ed8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,243 @@
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
namespace TcgEngine.Client
{
/// <summary>
/// Main script for the open pack scene
/// </summary>
public class OpenPackMenu : MonoBehaviour
{
public GameObject card_prefab;
private bool revealing = false;
private static OpenPackMenu instance;
void Awake()
{
instance = this;
}
void Update()
{
if (revealing && Input.GetMouseButtonDown(0))
{
bool all_revealed = true;
foreach (PackCard card in PackCard.GetAll())
{
if (!card.IsRevealed())
all_revealed = false;
}
if (all_revealed && PackCard.GetAll().Count > 0)
StopReveal();
}
}
public void OpenPack(string pack_tid)
{
PackData pack = PackData.Get(pack_tid);
if (pack != null)
{
OpenPack(pack);
}
}
public void OpenPack(PackData pack)
{
if (Authenticator.Get().IsApi())
{
OpenPackApi(pack);
}
if (Authenticator.Get().IsTest())
{
OpenPackTest(pack);
}
}
public async void OpenPackTest(PackData pack)
{
UserData udata = Authenticator.Get().UserData;
if (!udata.HasPack(pack.id))
return;
List<UserCardData> cards = new List<UserCardData>();
List <CardData> all_cards = CardData.GetAll(pack);
if (pack.type == PackType.Random)
{
for (int i = 0; i < pack.cards; i++)
{
RarityData rarity = GetRandomRarity(pack, i == 0);
VariantData variant = GetRandomVariant(pack);
List<CardData> vcards = GetCardArray(all_cards, rarity);
if (vcards.Count > 0)
{
CardData card = vcards[Random.Range(0, vcards.Count)];
UserCardData ucard = new UserCardData(card, variant);
cards.Add(ucard);
}
}
}
if (pack.type == PackType.Fixed)
{
for (int i = 0; i < Mathf.Min(pack.cards, all_cards.Count); i++)
{
CardData card = all_cards[i];
VariantData variant = VariantData.GetDefault();
UserCardData ucard = new UserCardData(card, variant);
cards.Add(ucard);
}
}
//Reveal cards
RevealCards(pack, cards.ToArray());
//Save cards
udata.AddPack(pack.id, -1);
foreach (UserCardData card in cards)
{
udata.AddCard(card.tid, card.variant, card.quantity);
}
await Authenticator.Get().SaveUserData();
HandPackArea.Get().LoadPacks();
}
public async void OpenPackApi(PackData pack)
{
UserData udata = Authenticator.Get().UserData;
if (!udata.HasPack(pack.id))
return;
udata.AddPack(pack.id, -1);
OpenPackRequest req = new OpenPackRequest();
req.pack = pack.id;
string url = ApiClient.ServerURL + "/users/packs/open";
string json = ApiTool.ToJson(req);
WebResponse res = await ApiClient.Get().SendPostRequest(url, json);
if (res.success)
{
UserCardData[] cards = ApiTool.JsonToArray<UserCardData>(res.data);
RevealCards(pack, cards);
}
HandPackArea.Get().LoadPacks();
}
public void RevealCards(PackData pack, UserCardData[] cards)
{
UserData udata = Authenticator.Get().UserData;
CardbackData cb = CardbackData.Get(udata.cardback);
HandPackArea.Get().Lock(true);
revealing = true;
int index = 0;
foreach (UserCardData card in cards)
{
CardData icard = CardData.Get(card.tid);
VariantData variant = VariantData.Get(card.variant);
if (icard != null && variant != null)
{
GameObject cobj = Instantiate(card_prefab, new Vector3(0f, -3f, 0f), Quaternion.identity);
PackCard pcard = cobj.GetComponent<PackCard>();
pcard.SetCard(pack, icard, variant);
BoardRef bref = BoardRef.Get(BoardRefType.PackCard, index);
Vector3 pos = bref != null ? bref.transform.position : Vector3.zero;
pcard.SetTarget(pos);
index++;
}
}
}
private List<CardData> GetCardArray(List<CardData> all_cards, RarityData rarity)
{
List<CardData> cards = new List<CardData>();
foreach (CardData acard in all_cards)
{
if (acard.rarity == rarity)
cards.Add(acard);
}
return cards;
}
private RarityData GetRandomRarity(PackData pack, bool is_first)
{
PackRarity[] rarities = is_first ? pack.rarities_1st : pack.rarities;
if (rarities == null || rarities.Length == 0)
return RarityData.GetFirst();
int total = 0;
foreach (PackRarity rarity in rarities)
{
total += rarity.probability;
}
int rvalue = Mathf.FloorToInt(Random.value * total);
for (int i = 0; i < rarities.Length; i++)
{
PackRarity rarity = rarities[i];
if (rvalue < rarity.probability)
{
return rarity.rarity;
}
rvalue -= rarity.probability;
}
return RarityData.GetFirst();
}
private VariantData GetRandomVariant(PackData pack)
{
PackVariant[] variants = pack.variants;
if (variants == null || variants.Length == 0)
return VariantData.GetDefault();
int total = 0;
foreach (PackVariant variant in variants)
{
total += variant.probability;
}
int rvalue = Mathf.FloorToInt(Random.value * total);
for (int i = 0; i < variants.Length; i++)
{
PackVariant variant = variants[i];
if (rvalue < variant.probability)
{
return variant.variant;
}
rvalue -= variant.probability;
}
return VariantData.GetDefault();
}
public void StopReveal()
{
revealing = false;
HandPackArea.Get().Lock(false);
foreach (PackCard card in PackCard.GetAll())
{
card.Remove();
}
}
public void OnClickBack()
{
SceneNav.GoTo("Menu");
}
public static OpenPackMenu Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 208d7d47c1ef5f341a74d402d51cfbcf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,116 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Pack panel is similar to the collection, but shows all the packs you own and all available packs
/// </summary>
public class PackPanel : UIPanel
{
[Header("Packs")]
public ScrollRect scroll_rect;
public RectTransform scroll_content;
public CardGrid grid_content;
public GameObject pack_prefab;
private List<GameObject> pack_list = new List<GameObject>();
private static PackPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
//Delete grid content
for (int i = 0; i < grid_content.transform.childCount; i++)
Destroy(grid_content.transform.GetChild(i).gameObject);
}
protected override void Start()
{
base.Start();
}
protected override void Update()
{
base.Update();
}
public async void ReloadUserPack()
{
await Authenticator.Get().LoadUserData();
RefreshPacks();
}
private void RefreshAll()
{
RefreshPacks();
RefreshStarterDeck();
}
public void RefreshPacks()
{
UserData udata = Authenticator.Get().UserData;
foreach (GameObject card in pack_list)
Destroy(card.gameObject);
pack_list.Clear();
foreach (PackData pack in PackData.GetAllAvailable())
{
GameObject nPack = Instantiate(pack_prefab, grid_content.transform);
PackUI pack_ui = nPack.GetComponentInChildren<PackUI>();
pack_ui.SetPack(pack, udata.GetPackQuantity(pack.id));
pack_ui.onClick += OnClickPack;
pack_ui.onClickRight += OnClickPack;
pack_list.Add(nPack);
}
}
private void RefreshStarterDeck()
{
UserData udata = Authenticator.Get().UserData;
if (udata != null && (udata.cards.Length == 0 || udata.rewards.Length == 0))
{
if (GameplayData.Get().starter_decks.Length > 0)
{
StarterDeckPanel.Get().Show();
}
}
}
public void OnClickPack(PackUI pack)
{
PackZoomPanel.Get().ShowPack(pack.GetPack());
}
public void OnClickCardRight(PackUI pack)
{
PackZoomPanel.Get().ShowPack(pack.GetPack());
}
public void OnClickOpenPacks()
{
MainMenu.Get().FadeToScene("OpenPack");
}
public override void Show(bool instant = false)
{
base.Show(instant);
RefreshAll();
}
public static PackPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c936547332fedec409fd9042638c6560
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,145 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// When you click on a pack in the PackPanel, a box will appear to show more information about it
/// You can also buy pack in this panel
/// </summary>
public class PackZoomPanel : UIPanel
{
public PackUI pack_ui;
public Text desc;
public GameObject buy_area;
public InputField buy_quantity;
public Text buy_cost;
public Text buy_error;
private PackData pack;
private static PackZoomPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
TabButton.onClickAny += OnClickTab;
}
private void OnDestroy()
{
TabButton.onClickAny -= OnClickTab;
}
protected override void Update()
{
base.Update();
if (pack != null)
{
int quantity = GetBuyQuantity();
buy_cost.text = (pack.cost * quantity).ToString();
}
}
public void ShowPack(PackData pack)
{
this.pack = pack;
UserData udata = Authenticator.Get().UserData;
int quantity = udata.GetPackQuantity(pack.id);
pack_ui.SetPack(pack, quantity);
desc.text = pack.GetDesc();
buy_quantity.text = "1";
buy_error.text = "";
buy_area?.SetActive(pack.available);
Show();
}
private async void BuyPackTest()
{
int quantity = GetBuyQuantity();
int cost = (quantity * pack.cost);
if (quantity <= 0)
return;
UserData udata = Authenticator.Get().UserData;
if (udata.coins < cost)
return;
udata.AddPack(pack.id, quantity);
udata.coins -= cost;
await Authenticator.Get().SaveUserData();
PackPanel.Get().ReloadUserPack();
Hide();
}
private async void BuyPackApi()
{
BuyPackRequest req = new BuyPackRequest();
req.pack = pack.id;
req.quantity = GetBuyQuantity();
if (req.quantity <= 0)
return;
string url = ApiClient.ServerURL + "/users/packs/buy/";
string jdata = ApiTool.ToJson(req);
buy_error.text = "";
WebResponse res = await ApiClient.Get().SendPostRequest(url, jdata);
if (res.success)
{
PackPanel.Get().ReloadUserPack();
Hide();
}
else
{
buy_error.text = res.error;
}
}
public void OnClickBuy()
{
if (Authenticator.Get().IsTest())
{
BuyPackTest();
}
if (Authenticator.Get().IsApi())
{
BuyPackApi();
}
}
private void OnClickTab(TabButton btn)
{
if (btn.group == "menu")
Hide();
}
public int GetBuyQuantity()
{
bool success = int.TryParse(buy_quantity.text, out int quantity);
if (success)
return quantity;
return 0;
}
public PackData GetPack()
{
return pack;
}
public static PackZoomPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 82a0dbb7c3002914c9c31cce85449593
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,397 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
namespace TcgEngine.UI
{
/// <summary>
/// Player panel appears when you click on your avatar in the menu
/// it shows all stats related to your account, and let you change avatar/cardback
/// </summary>
public class PlayerPanel : UIPanel
{
[Header("Player")]
public Text player_name;
public Text player_level;
public AvatarUI avatar;
public CardbackUI cardback;
public Text elo;
public Text winrate;
public Text cards_all;
public Text victories;
public Text defeats;
[Header("Bottom bar")]
public GameObject buttons_area;
public GameObject account_button;
public GameObject sell_button;
[Header("Avatars")]
public UIPanel avatar_panel;
public AvatarUI[] avatars;
[Header("Cardbacks")]
public UIPanel cardback_panel;
public CardbackUI[] cardbacks;
[Header("Edit Panel")]
public UIPanel edit_panel;
public InputField user_email;
public InputField user_password_prev;
public InputField user_password_new;
public InputField user_password_confirm;
public Button edit_change_email;
public Button edit_change_password;
public Button resend_button;
public Button confirm_button;
public Text edit_error;
private string username;
private UserData user_data;
private static PlayerPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
foreach (AvatarUI icon in avatars)
icon.onClick += OnClickAvatar;
foreach (CardbackUI icon in cardbacks)
icon.onClick += OnClickCardback;
}
protected override void Update()
{
base.Update();
}
protected override void Start()
{
base.Start();
}
private async void LoadData()
{
if (IsYou())
user_data = Authenticator.Get().UserData;
else
user_data = await ApiClient.Get().LoadUserData(username);
RefreshPanel();
}
private void ClearPanel()
{
player_name.text = "";
elo.text = "";
winrate.text = "";
player_level.text = "";
avatar.Hide();
cardback.Hide();
}
private void RefreshPanel()
{
avatar_panel.Hide();
//cardback_panel.Hide();
if (user_data != null)
{
UserData user = user_data;
player_name.text = user.username;
player_level.text = GameplayData.Get().GetPlayerLevel(user.xp).ToString();
AvatarData avatar = AvatarData.Get(user.avatar);
this.avatar.SetAvatar(avatar);
CardbackData cb = CardbackData.Get(user.cardback);
this.cardback.SetCardback(cb);
int winrate_val = user.matches > 0 ? Mathf.RoundToInt(user.victories * 100f / user.matches) : 0;
winrate.text = winrate_val + "%";
elo.text = user.elo.ToString();
victories.text = user.victories.ToString();
defeats.text = user.defeats.ToString();
cards_all.text = user.CountUniqueCards() + " / " + CardData.GetAllDeckbuilding().Count;
buttons_area?.SetActive(IsYou()); //Buttons like logout only active if your account
account_button?.SetActive(Authenticator.Get().IsApi());
sell_button?.SetActive(Authenticator.Get().IsApi());
}
}
private void RefreshAvatarList()
{
foreach (AvatarUI icon in avatars)
icon.SetDefaultAvatar();
int index = 0;
foreach (AvatarData adata in AvatarData.GetAll())
{
if (index < avatars.Length)
{
AvatarUI line = avatars[index];
if (adata != null)
{
line.SetAvatar(adata);
index++;
}
}
}
}
private void RefreshCardBackList()
{
foreach (CardbackUI line in cardbacks)
line.Hide();
int index = 0;
foreach (CardbackData cbdata in CardbackData.GetAll())
{
if (index < cardbacks.Length)
{
CardbackUI line = cardbacks[index];
if (cbdata != null)
{
line.SetCardback(cbdata);
index++;
}
}
}
}
private void OnClickAvatar(AvatarData avatar)
{
user_data = Authenticator.Get().UserData;
if (avatar != null && user_data != null && IsYou())
{
user_data.avatar = avatar.id;
RefreshPanel();
SaveUserAvatar(avatar);
avatar_panel.Hide();
}
}
private void OnClickCardback(CardbackData cb)
{
user_data = Authenticator.Get().UserData;
if (cb != null && user_data != null && IsYou())
{
user_data.cardback = cb.id;
RefreshPanel();
SaveUserCardback(cb);
cardback_panel.Hide();
}
}
private async void SaveUserAvatar(AvatarData avatar)
{
if (ApiClient.Get().IsConnected())
{
string url = ApiClient.ServerURL + "/users/edit/" + ApiClient.Get().UserID;
EditUserRequest req = new EditUserRequest();
req.avatar = avatar.id;
string json_data = ApiTool.ToJson(req);
await ApiClient.Get().SendRequest(url, "POST", json_data);
}
await Authenticator.Get().SaveUserData();
MainMenu.Get().RefreshUserData();
RefreshPanel();
}
private async void SaveUserCardback(CardbackData cardback)
{
if (ApiClient.Get().IsConnected())
{
string url = ApiClient.ServerURL + "/users/edit/" + ApiClient.Get().UserID;
EditUserRequest req = new EditUserRequest();
req.cardback = cardback.id;
string json_data = ApiTool.ToJson(req);
await ApiClient.Get().SendRequest(url, "POST", json_data);
}
await Authenticator.Get().SaveUserData();
MainMenu.Get().RefreshUserData();
RefreshPanel();
}
public void OnClickAvatar()
{
if (!IsYou())
return;
RefreshAvatarList();
avatar_panel.Show();
}
public void OnClickCardBack()
{
if (!IsYou())
return;
RefreshCardBackList();
cardback_panel.Show();
}
public void OnClickFriends()
{
FriendPanel.Get().Show();
}
public void OnClickDuplicates()
{
SellDuplicatePanel.Get().Show();
}
public void OnClickEdit()
{
user_email.readOnly = true;
user_password_prev.readOnly = true;
user_password_new.readOnly = true;
user_password_confirm.readOnly = true;
user_password_new.gameObject.SetActive(false);
user_password_confirm.gameObject.SetActive(false);
UserData udata = Authenticator.Get().UserData;
user_email.text = udata.email;
user_password_prev.text = "password";
user_password_new.text = "password";
user_password_confirm.text = "password";
edit_change_email.gameObject.SetActive(true);
edit_change_password.gameObject.SetActive(true);
resend_button.gameObject.SetActive(udata.validation_level == 0);
confirm_button.gameObject.SetActive(false);
edit_error.text = "";
edit_panel.Show();
}
public void OnClickChangePass()
{
OnClickEdit();
user_password_prev.readOnly = false;
user_password_new.readOnly = false;
user_password_confirm.readOnly = false;
user_password_prev.text = "";
user_password_new.text = "";
user_password_confirm.text = "";
user_password_new.gameObject.SetActive(true);
user_password_confirm.gameObject.SetActive(true);
edit_change_email.gameObject.SetActive(false);
edit_change_password.gameObject.SetActive(false);
resend_button.gameObject.SetActive(false);
confirm_button.gameObject.SetActive(true);
user_password_prev.Select();
}
public void OnClickChangeEmail()
{
OnClickEdit();
user_email.readOnly = false;
edit_change_email.gameObject.SetActive(false);
edit_change_password.gameObject.SetActive(false);
resend_button.gameObject.SetActive(false);
confirm_button.gameObject.SetActive(true);
user_email.Select();
}
public async void OnClickResendConfirm()
{
edit_error.text = "";
string url = ApiClient.ServerURL + "/users/email/resend";
WebResponse res = await ApiClient.Get().SendPostRequest(url, "");
if (res.success)
{
edit_panel.Hide();
}
else
{
edit_error.text = res.error;
}
}
public async void OnClickEditConfirm()
{
edit_error.text = "";
if (!user_email.readOnly && user_email.text.Length > 0)
{
EditEmailRequest req = new EditEmailRequest();
req.email = user_email.text;
string url = ApiClient.ServerURL + "/users/email/edit/";
string json = ApiTool.ToJson(req);
WebResponse res = await ApiClient.Get().SendPostRequest(url, json);
if (res.success)
{
edit_panel.Hide();
MainMenu.Get().RefreshUserData();
}
else
{
edit_error.text = res.error;
}
}
else if (!user_password_new.readOnly && user_password_new.text.Length > 0)
{
if (user_password_new.text == user_password_confirm.text)
{
EditPasswordRequest req = new EditPasswordRequest();
req.password_previous = user_password_prev.text;
req.password_new = user_password_new.text;
string url = ApiClient.ServerURL + "/users/password/edit/";
string json = ApiTool.ToJson(req);
WebResponse res = await ApiClient.Get().SendPostRequest(url, json);
if (res.success)
{
edit_panel.Hide();
}
else
{
edit_error.text = res.error;
}
}
}
}
public bool IsYou()
{
return username == ApiClient.Get().Username;
}
public void ShowPlayer()
{
string user = ApiClient.Get().Username;
ShowPlayer(user);
}
public void ShowPlayer(string user)
{
if (username != user)
ClearPanel();
username = user;
LoadData();
}
public override void Show(bool instant = false)
{
base.Show(instant);
ShowPlayer();
}
public override void Hide(bool instant = false)
{
base.Hide(instant);
edit_panel.Hide();
}
public static PlayerPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ba3253b4bb8825b47827d69c31b4e3c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,59 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// One line in the LeaderboardPanel
/// </summary>
public class RankLine : MonoBehaviour
{
public Text ranking;
public Text player;
public Text elo_txt;
public Text winrate_txt;
public Image highlight;
public UnityAction<string> onClick;
private string username;
void Start()
{
highlight.enabled = false;
}
public void SetLine(UserData udata, int ranking, bool highlight)
{
this.username = udata.username;
this.ranking.text = ranking.ToString();
this.player.text = username;
this.elo_txt.text = udata.elo.ToString();
int win_rate = Mathf.RoundToInt(udata.victories * 100f / Mathf.Max(udata.matches, 1));
this.winrate_txt.text = win_rate.ToString() + "%";
this.highlight.enabled = highlight;
gameObject.SetActive(true);
}
public void Hide()
{
gameObject.SetActive(false);
}
public string GetUsername()
{
return username;
}
public void OnClick()
{
onClick?.Invoke(username);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17282db61bfef9349bc6f80c6d52e9b3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,152 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Password recovery panel in the login menu
/// Only available in API mode
/// </summary>
public class RecoveryPanel : UIPanel
{
public InputField reset_email;
public Text reset_error;
public UIPanel confirm_panel;
public InputField confirm_code;
public InputField confirm_password;
public InputField confirm_pass_confirm;
public Text confirm_error;
private static RecoveryPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
}
public virtual void RefreshPanel()
{
confirm_panel.Hide(true);
reset_email.text = "";
confirm_code.text = "";
confirm_password.text = "";
confirm_pass_confirm.text = "";
reset_error.text = "";
confirm_error.text = "";
}
public async void ResetPassword()
{
if (ApiClient.Get().IsBusy())
return;
reset_error.text = "";
if (reset_email.text.Length == 0)
return;
ResetPasswordRequest req = new ResetPasswordRequest();
req.email = reset_email.text;
string url = ApiClient.ServerURL + "/users/password/reset";
string json = ApiTool.ToJson(req);
WebResponse res = await ApiClient.Get().SendPostRequest(url, json);
if (!res.success)
{
reset_error.text = res.error;
}
else
{
confirm_panel.Show();
}
}
public async void ResetPasswordConfirm()
{
if (ApiClient.Get().IsBusy())
return;
confirm_error.text = "";
if (confirm_code.text.Length == 0 || confirm_password.text.Length == 0 || confirm_pass_confirm.text.Length == 0)
return;
if (confirm_password.text != confirm_pass_confirm.text)
{
confirm_error.text = "Passwords don't match";
return;
}
ResetConfirmPasswordRequest req = new ResetConfirmPasswordRequest();
req.email = reset_email.text;
req.code = confirm_code.text;
req.password = confirm_password.text;
string url = ApiClient.ServerURL + "/users/password/reset/confirm";
string json = ApiTool.ToJson(req);
WebResponse res = await ApiClient.Get().SendPostRequest(url, json);
if (!res.success)
{
confirm_error.text = res.error;
}
else
{
LoginMenu.Get().login_user.text = req.email;
LoginMenu.Get().login_password.text = "";
Hide();
}
}
public override void Show(bool instant = false)
{
base.Show(instant);
RefreshPanel();
}
public override void Hide(bool instant = false)
{
base.Hide(instant);
confirm_panel.Hide();
}
public void OnClickReset()
{
ResetPassword();
}
public void OnClickResetConfirm()
{
ResetPasswordConfirm();
}
public void OnClickBack()
{
Hide();
}
public static RecoveryPanel Get()
{
return instance;
}
}
[Serializable]
public class ResetPasswordRequest
{
public string email;
}
[Serializable]
public class ResetConfirmPasswordRequest
{
public string email;
public string code;
public string password;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ace3adb17e0f47748b3bbe9ae5b7c94a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,88 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using TcgEngine.Client;
namespace TcgEngine.UI
{
public class SoloPanel : UIPanel
{
public Text username;
public DeckSelector selector_player;
public DeckSelector selector_ai;
public DeckDisplay display_player;
public DeckDisplay display_ai;
private static SoloPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
}
protected override void Start()
{
base.Start();
selector_player.onChange += OnChangeDeck;
selector_ai.onChange += OnChangeDeck;
}
private void RefreshDecks()
{
if(username != null)
username.text = Authenticator.Get().Username;
string selected_id = MainMenu.Get().deck_selector.GetDeckID();
selector_player.SetupUserDeckList();
selector_player.SelectDeck(selected_id);
selector_ai.SetupAIDeckList();
selector_ai.SelectDeck(0);
RefreshDeckDisplay();
}
private void RefreshDeckDisplay()
{
display_player.SetDeck(selector_player.GetDeckID());
display_ai.SetDeck(selector_ai.GetDeckID());
}
private void OnChangeDeck(string id)
{
RefreshDeckDisplay();
}
public override void Show(bool instant = false)
{
base.Show(instant);
RefreshDecks();
}
public void OnClickPlay()
{
UserDeckData deck = selector_player.GetDeck();
if (deck == null || !deck.IsValid())
return;
UserDeckData aideck = selector_ai.GetDeck();
if (aideck == null || !aideck.IsValid())
return;
GameClient.player_settings.deck = deck;
GameClient.ai_settings.deck = aideck;
GameClient.ai_settings.ai_level = GameplayData.Get().ai_level;
GameClient.game_settings.scene = GameplayData.Get().GetRandomArena();
MainMenu.Get().StartGame(GameType.Solo, GameMode.Casual);
}
public static SoloPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 643b2ad69f1002445b976b92d749ed51
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,124 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Selection of your starter deck
/// Will only appear in the main menu when in API mode with a new account
/// </summary>
public class StarterDeckPanel : UIPanel
{
public DeckDisplay[] decks;
public Text error;
private static StarterDeckPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
}
private void RefreshPanel()
{
int index = 0;
foreach (DeckData deck in GameplayData.Get().starter_decks)
{
if (index < decks.Length)
{
DeckDisplay display = decks[index];
display.SetDeck(deck);
index++;
}
}
}
private void ChooseDeck(string deck_id)
{
if (Authenticator.Get().IsTest())
ChooseDeckTest(deck_id);
if (Authenticator.Get().IsApi())
ChooseDeckApi(deck_id);
}
private async void ChooseDeckTest(string deck_id)
{
UserData udata = Authenticator.Get().UserData;
DeckData deck = DeckData.Get(deck_id);
if (deck == null)
return;
UserDeckData udeck = new UserDeckData();
udeck.tid = deck_id + "_" + GameTool.GenerateRandomID(4, 7); //Add random id to differentiate from the starter deck if edited
udeck.title = deck.title;
udeck.hero = new UserCardData(deck.hero, VariantData.GetDefault());
List<UserCardData> cards = new List<UserCardData>();
foreach (CardData card in deck.cards)
{
UserCardData ucard = new UserCardData(card, VariantData.GetDefault());
cards.Add(ucard);
}
udeck.cards = cards.ToArray();
udata.AddDeck(udeck);
udata.AddReward(udeck.tid);
await Authenticator.Get().SaveUserData();
CollectionPanel.Get().ReloadUserDecks();
Hide();
}
private async void ChooseDeckApi(string deck_id)
{
RewardGainRequest req = new RewardGainRequest();
req.reward = deck_id;
if (error != null)
error.text = "";
string url = ApiClient.ServerURL + "/users/rewards/gain/" + ApiClient.Get().UserID;
string json = ApiTool.ToJson(req);
WebResponse res = await ApiClient.Get().SendPostRequest(url, json);
if (res.success)
{
CollectionPanel.Get().ReloadUserDecks();
Hide();
}
else
{
if (error != null)
error.text = res.error;
}
}
public override void Show(bool instant = false)
{
base.Show(instant);
if(error != null)
error.text = "";
RefreshPanel();
}
public void OnClickDeck(int index)
{
if (index < decks.Length)
{
DeckDisplay display = decks[index];
string deck = display.GetDeck();
ChooseDeck(deck);
}
}
public static StarterDeckPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: caee5417592af2340bc4bd8467c06243
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,142 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
using TcgEngine.UI;
namespace TcgEngine
{
/// <summary>
/// Main script for the P2P menu scene
/// </summary>
public class TestP2P : MonoBehaviour
{
public UIPanel deck_panel;
public UIPanel join_panel;
public InputField username;
public InputField password;
public DeckSelector deck_selector;
public DeckDisplay deck_preview;
public InputField join_ip;
public Text error;
private bool starting = false;
void Start()
{
GameClient.game_settings = GameSettings.Default;
GameClient.player_settings = PlayerSettings.Default;
GameClient.game_settings.game_uid = "test_p2p";
deck_selector.onChange += OnChangeDeck;
error.text = "";
}
void Update()
{
}
private async void Login()
{
error.text = "";
bool success = await Authenticator.Get().Login(username.text, password.text);
if (success)
{
UserData udata = await Authenticator.Get().LoadUserData();
GameClient.player_settings.avatar = udata.GetAvatar();
GameClient.player_settings.cardback = udata.GetCardback();
deck_panel.Show();
RefreshDeckList();
}
else
{
error.text = Authenticator.Get().GetError();
}
}
public void StartGame()
{
if (!starting)
{
starting = true;
SceneNav.GoTo(GameClient.game_settings.GetScene());
}
}
public void RefreshDeckList()
{
deck_selector.SetupUserDeckList();
deck_selector.SelectDeck(GameClient.player_settings.deck.tid);
RefreshDeck(deck_selector.GetDeckID());
}
private void RefreshDeck(string tid)
{
UserData user = Authenticator.Get().UserData;
UserDeckData udeck = user.GetDeck(tid);
DeckData ddeck = DeckData.Get(tid);
if (udeck != null)
deck_preview.SetDeck(udeck);
else if (ddeck != null)
deck_preview.SetDeck(ddeck);
else
deck_preview.Clear();
}
public void OnChangeDeck(string tid)
{
GameClient.player_settings.deck = deck_selector.GetDeck();
PlayerPrefs.SetString("tcg_deck", tid);
RefreshDeck(tid);
}
public void OnClickLogin()
{
if (username.text.Length == 0)
return;
Login();
}
public void OnClickHost()
{
GameClient.game_settings.game_type = GameType.HostP2P;
GameClient.game_settings.server_url = "127.0.0.1";
GameClient.player_settings.deck = deck_selector.GetDeck();
StartGame();
}
public void OnClickGoJoin()
{
GameClient.player_settings.deck = deck_selector.GetDeck();
deck_panel.Hide();
join_panel.Show();
}
public void OnClickJoin()
{
if (join_ip.text.Length == 0)
return;
GameClient.game_settings.game_type = GameType.Multiplayer;
GameClient.game_settings.server_url = join_ip.text;
StartGame();
}
public void OnClickBack()
{
if (join_panel.IsVisible())
{
join_panel.Hide();
deck_panel.Show();
}
else
{
deck_panel.Hide();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 36ca80d492f20d240a71091b70e3c4b7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: