214 lines
No EOL
8.1 KiB
C#
214 lines
No EOL
8.1 KiB
C#
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();
|
||
}
|
||
} |