Make user search, chatroom, leaderboards and icon marketplace into a popup

This commit is contained in:
Lncvrt committed 2026-03-16 21:43:00 -07:00
1 parent 70687c2856
commit 06ba845790
52 files changed
+30178 -31455

No files matched your search

@@ -0,0 +1,283 @@
using System;
using System.Collections;
using System.Linq;
using System.Numerics;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class IconMarketplaceDownloadIcon : MonoBehaviour {
private readonly static WaitForSeconds _waitForSeconds2 = new(2f);
[SerializeField] private IconMarketplaceManager marketplaceManager;
[SerializeField] private TMP_Text statusText;
[SerializeField] private TMP_Text balanceText;
[SerializeField] private Button backButton;
public GameObject content;
[SerializeField] private GameObject sample;
private string statusMessage;
private Coroutine statusRoutine;
public AudioSource iconPurchaseSound;
[SerializeField] internal Button refreshButton;
[SerializeField] private Button optionsButton;
[SerializeField] internal GameObject optionsPanel;
[SerializeField] internal Button optionsPanelSubmitButton;
[SerializeField] private Button optionsPanelResetButton;
public TMP_Dropdown optionsPanelSortByDropdown;
public Toggle optionsPanelPriceRangeToggle;
[SerializeField] private TMP_InputField optionsPanelPriceRangeMinInput;
[SerializeField] private TMP_InputField optionsPanelPriceRangeMaxInput;
internal string priceRangeMin = "10";
internal string priceRangeMax = "250";
public Toggle optionsPanelSearchForToggle;
[SerializeField] private TMP_InputField optionsPanelSearchForInputField;
internal string searchForValue = "";
[SerializeField] private Toggle optionsPanelOnlyShowToggle;
[SerializeField] private TMP_Dropdown optionsPanelOnlyShowDropdown;
internal bool anyChanges = false;
void Awake() {
optionsPanelPriceRangeMinInput.onSelect.AddListener((_) => optionsPanelPriceRangeMinInput.caretPosition = optionsPanelPriceRangeMinInput.text.Length);
optionsPanelPriceRangeMaxInput.onSelect.AddListener((_) => optionsPanelPriceRangeMaxInput.caretPosition = optionsPanelPriceRangeMaxInput.text.Length);
optionsPanelSearchForInputField.onSelect.AddListener((_) => optionsPanelSearchForInputField.caretPosition = optionsPanelSearchForInputField.text.Length);
backButton.onClick.AddListener(() => marketplaceManager.SwitchPanel(0));
refreshButton.onClick.AddListener(GetIcons);
optionsButton.onClick.AddListener(() => optionsPanel.SetActive(true));
optionsPanelSubmitButton.onClick.AddListener(() => {
optionsPanel.SetActive(false);
if (anyChanges) {
anyChanges = false;
GetIcons();
}
});
optionsPanelResetButton.onClick.AddListener(() => {
optionsPanelSortByDropdown.value = 3;
optionsPanelPriceRangeToggle.isOn = false;
optionsPanelSearchForToggle.isOn = false;
optionsPanelOnlyShowToggle.isOn = false;
});
optionsPanelPriceRangeToggle.onValueChanged.AddListener((on) => {
anyChanges = true;
if (!on) {
optionsPanelPriceRangeMinInput.text = "10";
optionsPanelPriceRangeMaxInput.text = "250";
}
optionsPanelPriceRangeMinInput.interactable = on;
optionsPanelPriceRangeMaxInput.interactable = on;
});
optionsPanelSearchForToggle.onValueChanged.AddListener((on) => {
anyChanges = true;
if (!on) optionsPanelSearchForInputField.text = "";
optionsPanelSearchForInputField.interactable = on;
});
optionsPanelOnlyShowToggle.onValueChanged.AddListener((on) => {
anyChanges = true;
if (!on) optionsPanelOnlyShowDropdown.value = 0;
optionsPanelOnlyShowDropdown.interactable = on;
});
optionsPanelSortByDropdown.onValueChanged.AddListener((_) => anyChanges = true);
optionsPanelPriceRangeMinInput.onValueChanged.AddListener((value) => {
anyChanges = true;
priceRangeMin = value;
});
optionsPanelPriceRangeMaxInput.onValueChanged.AddListener((value) => {
anyChanges = true;
priceRangeMax = value;
});
optionsPanelSearchForInputField.onValueChanged.AddListener((value) => {
anyChanges = true;
searchForValue = value;
});
optionsPanelOnlyShowDropdown.onValueChanged.AddListener((_) => anyChanges = true);
}
internal void Load() {
GetIcons();
balanceText.text = Tools.FormatWithCommas(BazookaManager.Instance.GetCustomBirdIconData().Balance);
}
internal async void GetIcons() {
refreshButton.interactable = false;
optionsButton.interactable = false;
backButton.interactable = false;
foreach (Transform item in content.transform) {
if (item.gameObject.activeSelf) {
Destroy(item.gameObject);
}
}
var currentIcons = new JArray();
foreach (var icon in BazookaManager.Instance.GetCustomBirdIconData().Purchased) {
currentIcons.Add(icon);
}
ShowStatus("Loading...");
WWWForm dataForm = new();
dataForm.AddField("sortBy", optionsPanelSortByDropdown.value.ToString());
dataForm.AddField("priceRangeEnabled", optionsPanelPriceRangeToggle.isOn.ToString());
dataForm.AddField("priceRangeMin", priceRangeMin);
dataForm.AddField("priceRangeMax", priceRangeMax);
dataForm.AddField("searchForEnabled", optionsPanelSearchForToggle.isOn.ToString());
dataForm.AddField("searchForValue", searchForValue);
dataForm.AddField("onlyShowEnabled", optionsPanelOnlyShowToggle.isOn.ToString());
dataForm.AddField("onlyShowValue", optionsPanelOnlyShowDropdown.value.ToString());
dataForm.AddField("currentIcons", Convert.ToBase64String(Encoding.UTF8.GetBytes(currentIcons.ToString(Formatting.None))));
using UnityWebRequest request = UnityWebRequest.Post(Endpoints.ICON_MARKETPLACE_ENDPOINT, dataForm);
request.SetRequestHeader("Authorization", BazookaManager.Instance.GetAccountSession() ?? "");
request.SetRequestHeader("Requester", "BerryDashClient");
request.SetRequestHeader("ClientVersion", Application.version);
request.SetRequestHeader("ClientPlatform", Application.platform.ToString());
await request.SendWebRequest();
if (request.downloadHandler.text == null) {
refreshButton.interactable = true;
optionsButton.interactable = true;
backButton.interactable = true;
ShowStatus("Failed to make HTTP request");
return;
}
ShowStatus(null);
var jsonResponse = JObject.Parse(request.downloadHandler.text);
var icons = JsonConvert.DeserializeObject<MarketplaceTempIcon[]>(jsonResponse["data"].ToString());
var localUserID = BazookaManager.Instance.GetAccountID();
foreach (var entry in icons) {
GameObject newIcon = Instantiate(sample, content.transform);
newIcon.name = "IconEntry";
newIcon.transform.GetChild(0).GetChild(0).gameObject.AddComponent<WaitingForCustomIcon>().ID = entry.ID;
newIcon.transform.GetChild(1).GetComponent<TMP_Text>().text = "Icon Name: " + entry.Name;
newIcon.transform.GetChild(2).GetComponent<TMP_Text>().text = "Price " + Tools.FormatWithCommas(entry.Price) + " coins";
newIcon.transform.GetChild(3).GetComponent<TMP_Text>().text = "Designer Name: " + entry.CreatorUsername;
var BtnGrid = newIcon.transform.GetChild(4);
var buyBtn = BtnGrid.transform.GetChild(0).GetComponent<Button>();
var buyBtnText = buyBtn.transform.GetChild(0).GetComponent<TMP_Text>();
var sellBtn = BtnGrid.transform.GetChild(1).GetComponent<Button>();
var sellBtnText = sellBtn.transform.GetChild(0).GetComponent<TMP_Text>();
sellBtn.onClick.AddListener(() => {
HandleSell(entry, buyBtn, buyBtnText, sellBtn, localUserID);
Tools.RefreshHierarchy(newIcon);
});
buyBtn.onClick.AddListener(() => {
HandlePurchase(entry, buyBtn, sellBtn, localUserID);
Tools.RefreshHierarchy(newIcon);
});
bool alreadyBought = BazookaManager.Instance.GetCustomBirdIconData().Purchased.Any(d => d == entry.ID);
if (alreadyBought) {
buyBtn.interactable = false;
sellBtn.gameObject.SetActive(true);
if (localUserID != entry.CreatorUserID)
buyBtnText.text = "Purchased";
else {
buyBtnText.text = "Claimed";
sellBtnText.text = "Unclaim";
}
} else {
if (localUserID != entry.CreatorUserID) buyBtnText.text = "Purchase";
else buyBtnText.text = "Claim";
}
newIcon.SetActive(true);
Tools.RefreshHierarchy(newIcon);
}
CustomIconLoader.Init(FindObjectsByType<WaitingForCustomIcon>(FindObjectsSortMode.None));
refreshButton.interactable = true;
optionsButton.interactable = true;
backButton.interactable = true;
}
void HandlePurchase(MarketplaceTempIcon data, Button button, Button sellButton, BigInteger? localUserID) {
button.interactable = false;
MarketplaceIconStorageType marketplaceIconStorage = BazookaManager.Instance.GetCustomBirdIconData();
if (localUserID != data.CreatorUserID) {
if (data.Price > marketplaceIconStorage.Balance) {
button.interactable = true;
ShowStatus("You can't afford this icon! You need " + Tools.FormatWithCommas(data.Price - marketplaceIconStorage.Balance) + " more coins");
return;
}
marketplaceIconStorage.Balance -= data.Price;
iconPurchaseSound.Stop();
iconPurchaseSound.Play();
}
marketplaceIconStorage.Purchased.Add(data.ID);
sellButton.gameObject.SetActive(true);
if (localUserID != data.CreatorUserID) {
button.transform.GetChild(0).GetComponent<TMP_Text>().text = "Purchased";
} else {
button.transform.GetChild(0).GetComponent<TMP_Text>().text = "Claimed";
sellButton.transform.GetChild(0).GetComponent<TMP_Text>().text = "Unclaim";
}
balanceText.text = Tools.FormatWithCommas(marketplaceIconStorage.Balance);
BazookaManager.Instance.SetCustomBirdIconData(marketplaceIconStorage);
}
void HandleSell(MarketplaceTempIcon data, Button buyBtn, TMP_Text buyBtnText, Button sellButton, BigInteger? localUserID) {
MarketplaceIconStorageType marketplaceIconStorage = BazookaManager.Instance.GetCustomBirdIconData();
var owned = marketplaceIconStorage.Purchased.Contains(data.ID);
if (owned) {
marketplaceIconStorage.Purchased.Remove(data.ID);
if (data.CreatorUserID != (BazookaManager.Instance.GetAccountID() ?? 0)) {
marketplaceIconStorage.Balance += data.Price;
iconPurchaseSound.Stop();
iconPurchaseSound.Play();
}
if (data.ID == marketplaceIconStorage.Selected) marketplaceIconStorage.Selected = null;
balanceText.text = Tools.FormatWithCommas(marketplaceIconStorage.Balance);
BazookaManager.Instance.SetCustomBirdIconData(marketplaceIconStorage);
if (localUserID != data.CreatorUserID) buyBtnText.text = "Purchase";
else {
buyBtnText.text = "Claim";
buyBtnText.text = "Claim";
}
buyBtn.interactable = true;
sellButton.gameObject.SetActive(false);
}
}
void ShowStatus(string content) {
if (content == null) {
if (statusRoutine != null) StopCoroutine(statusRoutine);
statusText.gameObject.SetActive(false);
statusText.text = "";
}
statusMessage = content;
if (statusRoutine != null) StopCoroutine(statusRoutine);
statusRoutine = StartCoroutine(StatusRoutine());
}
IEnumerator StatusRoutine() {
statusText.gameObject.SetActive(true);
statusText.text = statusMessage;
statusText.color = new Color(statusText.color.r, statusText.color.g, statusText.color.b, 0f);
float t = 0f;
while (t < 0.5f) {
t += Time.deltaTime;
float a = t / 0.5f;
statusText.color = new Color(statusText.color.r, statusText.color.g, statusText.color.b, a);
yield return null;
}
yield return _waitForSeconds2;
t = 0f;
while (t < 0.5f) {
t += Time.deltaTime;
float a = 1f - (t / 0.5f);
statusText.color = new Color(statusText.color.r, statusText.color.g, statusText.color.b, a);
yield return null;
}
statusText.gameObject.SetActive(false);
statusText.text = "";
statusRoutine = null;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b8133693b9ee6eec098e9cef8b719edf
@@ -0,0 +1,85 @@
using SimpleFileBrowser;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
public class IconMarketplaceManager : MonoBehaviour {
[SerializeField] private GameObject panel;
[SerializeField] private GameObject normalPanel;
[SerializeField] private GameObject downloadPanel;
[SerializeField] private GameObject uploadPanel;
[SerializeField] private IconMarketplaceUploadIcon uploadPanelScript;
[SerializeField] private IconMarketplaceDownloadIcon downloadPanelScript;
[SerializeField] private Button exitButton;
[SerializeField] private Button downloadButton;
[SerializeField] private Button uploadButton;
[SerializeField] private TMP_Text coinText;
void Start() {
downloadPanelScript.iconPurchaseSound.volume = BazookaManager.Instance.GetSettingSFXVolume();
downloadButton.onClick.AddListener(() => SwitchPanel(1));
if (BazookaManager.Instance.GetAccountID() != null && BazookaManager.Instance.GetAccountName() != null && BazookaManager.Instance.GetAccountSession() != null) {
uploadButton.onClick.AddListener(() => SwitchPanel(2));
} else {
uploadButton.interactable = false;
uploadButton.transform.GetChild(0).transform.localPosition = new Vector3(0, 10, 0);
uploadButton.transform.GetChild(1).GetComponent<TMP_Text>().text = "Not logged in to an account";
}
SwitchPanel(0);
exitButton.onClick.AddListener(() => Destroy(gameObject));
}
internal void SwitchPanel(int panelIndex) {
downloadPanelScript.iconPurchaseSound.Stop();
downloadPanelScript.anyChanges = false;
downloadPanelScript.optionsPanelSortByDropdown.value = 3;
downloadPanelScript.optionsPanelPriceRangeToggle.isOn = false;
downloadPanelScript.optionsPanelSearchForToggle.isOn = false;
switch (panelIndex) {
case 0:
panel.SetActive(false);
panel.SetActive(true);
coinText.text = "You have " + Tools.FormatWithCommas(BazookaManager.Instance.GetCustomBirdIconData().Balance) + " coins";
normalPanel.SetActive(true);
downloadPanel.SetActive(false);
uploadPanel.SetActive(false);
if (DiscordRPCHandler.Instance != null) DiscordRPCHandler.Instance.UpdateRPC("Choosing what to do in the icon marketplace", null);
break;
case 1:
panel.SetActive(false);
panel.SetActive(true);
foreach (Transform item in downloadPanelScript.content.transform) {
if (item.gameObject.activeSelf) {
Destroy(item.gameObject);
}
}
normalPanel.SetActive(false);
downloadPanel.SetActive(true);
uploadPanel.SetActive(false);
downloadPanelScript.Load();
if (DiscordRPCHandler.Instance != null) DiscordRPCHandler.Instance.UpdateRPC("Browsing the icon marketplace", "They have " + Tools.FormatWithCommas(BazookaManager.Instance.GetCustomBirdIconData().Balance) + " coins");
break;
case 2:
panel.SetActive(false);
panel.SetActive(true);
uploadPanelScript.Reset();
normalPanel.SetActive(false);
downloadPanel.SetActive(false);
uploadPanel.SetActive(true);
if (DiscordRPCHandler.Instance != null) DiscordRPCHandler.Instance.UpdateRPC("Uploading an icon to the icon marketplace", null);
break;
}
}
void Update() {
if (Keyboard.current.escapeKey.wasPressedThisFrame) {
if (downloadPanelScript.optionsPanel.activeSelf) downloadPanelScript.optionsPanelSubmitButton.onClick.Invoke();
else if (uploadPanel.activeSelf && FileBrowser.IsOpen) return;
else if (downloadPanel.activeSelf || uploadPanel.activeSelf) SwitchPanel(0);
else if (exitButton.interactable) exitButton.onClick.Invoke();
} else if (Keyboard.current.rKey.wasPressedThisFrame && downloadPanel.activeSelf && downloadPanelScript.refreshButton.interactable) downloadPanelScript.GetIcons();
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: dd46bad161f2c81e2a36dd6a25154ad4
@@ -0,0 +1,118 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using SimpleFileBrowser;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class IconMarketplaceUploadIcon : MonoBehaviour {
[SerializeField] private IconMarketplaceManager marketplaceManager;
[SerializeField] private TMP_Text statusText;
[SerializeField] private Button backButton;
[SerializeField] private Button uploadButton;
[SerializeField] private Button selectButton;
[SerializeField] private TMP_InputField verifyCodeInput;
[SerializeField] private TMP_InputField birdPriceInput;
[SerializeField] private TMP_InputField birdNameInput;
[SerializeField] private Image birdImage;
[SerializeField] private GameObject birdImageNone;
private string birdData = null;
void Awake() {
verifyCodeInput.onSelect.AddListener((_) => verifyCodeInput.caretPosition = verifyCodeInput.text.Length);
birdPriceInput.onSelect.AddListener((_) => birdPriceInput.caretPosition = birdPriceInput.text.Length);
birdNameInput.onSelect.AddListener((_) => birdNameInput.caretPosition = birdNameInput.text.Length);
backButton.onClick.AddListener(() => marketplaceManager.SwitchPanel(0));
uploadButton.onClick.AddListener(() => {
if (birdPriceInput.text.Trim() == string.Empty) {
Tools.UpdateStatusText(statusText, "Bird price can't be empty", Color.red);
} else if (birdNameInput.text.Trim() == string.Empty) {
Tools.UpdateStatusText(statusText, "Bird name can't be empty", Color.red);
} else if (birdData == null) {
Tools.UpdateStatusText(statusText, "You must upload an image", Color.red);
} else {
UploadIcon();
}
});
selectButton.onClick.AddListener(async () => {
string path = await OpenFilePicker();
if (path == null) return;
byte[] fileContent;
try {
fileContent = File.ReadAllBytes(path);
if (fileContent.Length > 1024 * 1024) {
Tools.UpdateStatusText(statusText, "File size exceeds 1 MB limit", Color.red);
return;
}
birdData = Convert.ToBase64String(fileContent);
birdImage.sprite = Tools.GetSpriteFromBase64(birdData);
birdImageNone.SetActive(false);
birdImage.gameObject.SetActive(true);
}
catch (Exception e) {
Tools.UpdateStatusText(statusText, "Failed to read file: " + e.Message, Color.red);
return;
}
});
}
async Task<string> OpenFilePicker() {
FileBrowser.SetFilters(true, new FileBrowser.Filter("Images", ".png"));
var tcs = new TaskCompletionSource<string>();
FileBrowser.ShowLoadDialog(
(paths) => tcs.SetResult(paths.Length > 0 ? paths[0] : null),
() => tcs.SetResult(null),
FileBrowser.PickMode.Files,
false
);
return await tcs.Task;
}
async void UploadIcon() {
uploadButton.interactable = false;
backButton.interactable = false;
selectButton.interactable = false;
WWWForm dataForm = new();
dataForm.AddField("verifyCode", verifyCodeInput.text);
dataForm.AddField("price", birdPriceInput.text);
dataForm.AddField("name", birdNameInput.text);
dataForm.AddField("fileContent", birdData);
using UnityWebRequest request = UnityWebRequest.Post(Endpoints.ICON_MARKETPLACE_UPLOAD_ENDPOINT, dataForm);
request.SetRequestHeader("Authorization", BazookaManager.Instance.GetAccountSession());
request.SetRequestHeader("Requester", "BerryDashClient");
request.SetRequestHeader("ClientVersion", Application.version);
request.SetRequestHeader("ClientPlatform", Application.platform.ToString());
await request.SendWebRequest();
if (request.downloadHandler.text == null) {
uploadButton.interactable = true;
backButton.interactable = true;
selectButton.interactable = true;
Tools.UpdateStatusText(statusText, "Failed to make HTTP request", Color.red);
return;
}
var jsonResponse = JObject.Parse(request.downloadHandler.text);
if ((bool)jsonResponse["success"]) Reset();
Tools.UpdateStatusText(statusText, (string)jsonResponse["message"], (bool)jsonResponse["success"] ? Color.green : Color.red);
uploadButton.interactable = true;
backButton.interactable = true;
selectButton.interactable = true;
}
internal void Reset() {
birdImage.sprite = null;
birdImageNone.SetActive(true);
birdImage.gameObject.SetActive(false);
birdData = null;
verifyCodeInput.text = string.Empty;
birdPriceInput.text = string.Empty;
birdNameInput.text = string.Empty;
statusText.text = string.Empty;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ac25b048bc0f6aded8697b98caef8382