PJ/Assets/scripts/dotfs_scripts/MANAGER_Mail.cs

214 lines
8.1 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using Newtonsoft.Json;
using System.Linq;
public class MANAGER_Mail : MonoBehaviour
{
public static MANAGER_Mail Instance { get; private set; }
private const string MAIL_URL = "http://mc1.live-on.pro:64093/api/mail/mail.json";
private const string REWARDS_URL = "http://mc1.live-on.pro:64093/api/other/rewards_table_id.json";
// Данные сервера
public List<MailEntry> ActiveMails { get; private set; } = new List<MailEntry>();
public Dictionary<string, List<RewardItem>> RewardsTable { get; private set; } = new Dictionary<string, List<RewardItem>>();
// Состояние инициализации
public bool IsDataLoaded { get; private set; } = false;
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
private void Start()
{
StartCoroutine(LoadMailSystemData());
}
private IEnumerator LoadMailSystemData()
{
IsDataLoaded = false;
// 1. Загрузка конфигурации писем
UnityWebRequest mailReq = UnityWebRequest.Get(MAIL_URL);
yield return mailReq.SendWebRequest();
if (mailReq.result != UnityWebRequest.Result.Success)
{
yield break; // В реальном проекте здесь нужна логика ретрая
}
// 2. Загрузка таблицы наград
UnityWebRequest rewardsReq = UnityWebRequest.Get(REWARDS_URL);
yield return rewardsReq.SendWebRequest();
if (rewardsReq.result != UnityWebRequest.Result.Success)
{
yield break;
}
// 3. Десериализация
try
{
// 1. Десериализуем во временную обертку
var wrapper = JsonConvert.DeserializeObject<MailDataWrapper>(mailReq.downloadHandler.text);
// 2. Присваиваем список из обертки в ActiveMails
ActiveMails = wrapper != null ? wrapper.mails : new List<MailEntry>();
// Для наград (если там такая же структура с корневым объектом, проверьте rewards_table_id.json)
RewardsTable = JsonConvert.DeserializeObject<Dictionary<string, List<RewardItem>>>(rewardsReq.downloadHandler.text);
IsDataLoaded = true;
MANAGER_GameEvents.TriggerUIUpdate();
}
catch (System.Exception e)
{
}
}
public DateTime GetCurrentTime()
{
try
{
// Пытаемся получить локальное время устройства
return DateTime.Now;
}
catch
{
// Если по какой-то причине на Linux или другой ОС произошел сбой,
// берем UTC и прибавляем 7 часов (Красноярск)
return DateTime.UtcNow.AddHours(7);
}
}
public bool IsMailDeleted(string mailId)
{
return PlayerPrefs.GetInt($"Mail_Deleted_{mailId}", 0) == 1;
}
public void DeleteMail(string mailId)
{
PlayerPrefs.SetInt($"Mail_Deleted_{mailId}", 1);
PlayerPrefs.Save();
MANAGER_GameEvents.TriggerUIUpdate(); // Обновляем список, чтобы письмо исчезло
}
// --- ЛОГИКА СОСТОЯНИЙ (ПРОЧИТАНО / ЗАБРАНО) ---
public bool IsMailRead(string mailId)
{
return PlayerPrefs.GetInt($"Mail_Read_{mailId}", 0) == 1;
}
public void MarkAsRead(string mailId)
{
if (!IsMailRead(mailId))
{
PlayerPrefs.SetInt($"Mail_Read_{mailId}", 1);
PlayerPrefs.Save();
// Отправляем сигнал для визуального снятия метки "Новое"
MANAGER_GameEvents.TriggerUIUpdate();
}
}
// Добавьте это в MANAGER_Mail.cs
public string GetFormattedBody(MailEntry mail)
{
if (mail == null || mail.content == null) return "";
string body = mail.content.body;
// Проверяем наличие плейсхолдера
if (body.Contains("{today_reward}"))
{
string rewardText = "";
// Проверяем, есть ли ID таблицы наград и загружена ли она
if (!string.IsNullOrEmpty(mail.rewards_table_id) && RewardsTable.TryGetValue(mail.rewards_table_id, out var rewards))
{
// Собираем строку наград (например: "Золото x15, Меч x1")
// Здесь r.name — это то самое поле, которое мы договорились добавить в RewardItem
rewardText = string.Join(", ", rewards.Select(r => $"[g]x{r.amount} {r.name}[/c]"));
}
else
{
// Если награда не найдена, выводим заглушку или пустую строку
rewardText = "награды отсутствуют";
}
body = body.Replace("{today_reward}", rewardText);
}
return body;
}
private const int TEST_COOLDOWN_SECONDS = 86400;
public void ClaimReward(string mailId)
{
if (IsRewardClaimed(mailId)) return;
MailEntry mail = ActiveMails.FirstOrDefault(m => m.id == mailId);
if (mail != null)
{
// Сохраняем текущее время в формате Total Seconds
double totalSecondsNow = GetCurrentTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
PlayerPrefs.SetString($"Mail_LastClaimedTime_{mailId}", totalSecondsNow.ToString());
PlayerPrefs.Save();
MarkAsRead(mailId);
MANAGER_GameEvents.TriggerUIUpdate();
}
}
public bool IsRewardClaimed(string mailId)
{
string lastClaimedStr = PlayerPrefs.GetString($"Mail_LastClaimedTime_{mailId}", "0");
double lastClaimedSeconds = double.Parse(lastClaimedStr);
double currentSeconds = GetCurrentTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
// Письмо "забрано", если с момента последнего клика прошло МЕНЬШЕ 60 секунд
return (currentSeconds - lastClaimedSeconds) < TEST_COOLDOWN_SECONDS;
}
public List<MailEntry> GetAvailableMails()
{
return ActiveMails
.Where(mail =>
{
// Базовая фильтрация: удаленные и не подходящие по дате
if (IsMailDeleted(mail.id)) return false;
DateTime now = GetCurrentTime();
if (mail.logic.StartDate.HasValue && now < mail.logic.StartDate.Value) return false;
if (mail.logic.EndDate.HasValue && now > mail.logic.EndDate.Value) return false;
return true;
})
/* СОРТИРОВКА:
1. Сначала считаем приоритет:
Если награда ЗАБРАНА (IsRewardClaimed == true), ставим -99.
Если награда ДОСТУПНА, ставим 0 (или можно брать mail.priority, если он есть в классе).
*/
.OrderByDescending(mail => IsRewardClaimed(mail.id) ? -99 : 0)
// 2. Внутри групп (сначала новые/доступные) сортируем по дате начала
.ThenByDescending(mail => mail.logic.StartDate)
.ToList();
}
}