Files
MVP1/Assets/Scripts/Modules/Core/Contracts/ModuleContracts.cs
T

185 lines
6.3 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
// Контракты модулей: всё, что один модуль может попросить у другого.
// Реализация живёт в своём модуле, здесь -- только "что умеет".
// Добавляя метод сюда, обнови документ модуля в Docs/Modules.
// ---------------- Экономика: ресурсы и производство ----------------
public interface IEconomy
{
float Get(ResourceType type);
bool Has(ResourceType type, float amount);
void Add(ResourceType type, float amount);
bool TrySpend(ResourceType type, float amount);
bool CanAfford(IReadOnlyList<ResourceAmount> cost);
// Списывает всё или ничего
bool TrySpend(IReadOnlyList<ResourceAmount> cost);
}
// ---------------- Поселение: здания и развитие города ----------------
public interface ISettlement
{
int TownHallLevel { get; }
int BuildingCount { get; }
bool IsCityLoaded { get; } // открыта ли сейчас сцена города
}
// Здание с уровнем (добывающие постройки и т.п.) -- Поселение сохраняет уровень, не зная, чьё это здание
public interface ILeveledBuilding
{
int Level { get; set; }
}
// ---------------- Армия: войска ----------------
public interface IArmy
{
int SoldiersAtHome { get; }
// Забрать воинов из города в поход (запоминает состав похода)
bool TakeForMarch(int marchId, int count);
// Вернуть выживших из похода по тем же типам войск
void ReturnFromMarch(int marchId, int survivors);
}
// ---------------- Глобальный мир: карта и перемещения ----------------
public interface IWorld
{
int ActiveMarches { get; }
bool TryStartMarch(string targetId, int soldiers, out string error);
}
// ---------------- Боевая система: урон, потери, исход ----------------
public struct BattleRequest
{
public int Attackers;
public int Defenders;
}
public struct BattleOutcome
{
public bool Victory; // победил атакующий
public int AttackerLosses;
public int DefenderLosses;
public int Survivors; // сколько атакующих осталось
}
public interface IBattleSystem
{
BattleOutcome Resolve(BattleRequest request);
}
// ---------------- Чат: общий мир и Круг ----------------
public enum ChatChannel
{
World, // общий чат всего мира
Circle // чат своего Круга
}
[Serializable]
public class ChatMessage
{
public ChatChannel channel;
public string senderId;
public string senderName;
public string text;
public long timeMs; // Unix-время в миллисекундах
}
public interface IChat
{
int MaxMessageLength { get; }
IReadOnlyList<ChatMessage> GetMessages(ChatChannel channel);
bool CanWrite(ChatChannel channel); // в канал "Круг" -- только состоя в Круге
// Отправить от имени локального игрока. false -- пустое сообщение или канал "Круг" без Круга
bool Send(ChatChannel channel, string text);
}
// ---------------- Круг: объединение игроков ----------------
public enum CircleRole
{
Leader, // глава
Member // участник
}
[Serializable]
public class CircleMember
{
public string playerId;
public string name;
public CircleRole role;
}
[Serializable]
public class CircleInfo
{
public string id;
public string name;
public List<CircleMember> members = new List<CircleMember>();
public string LeaderName
{
get
{
foreach (var m in members) if (m.role == CircleRole.Leader) return m.name;
return "";
}
}
}
public interface ICircle
{
int MaxMembers { get; }
CircleInfo Current { get; } // Круг игрока; null -- игрок не в Круге
bool IsInCircle { get; }
bool IsLeader { get; }
IReadOnlyList<CircleInfo> GetCircles(); // все Круги, в которые можно вступить
bool TryCreate(string name, out string error); // создатель становится главой
bool TryJoin(string circleId, out string error);
void Leave(); // глава один в Круге -- Круг распускается
}
// ---------------- Сохранения: игровое состояние ----------------
public interface ISaveSystem
{
bool HasSave { get; }
void SaveNow();
void DeleteSave();
// Новая игра: все модули возвращаются к стартовому состоянию, файл перезаписывается
void ResetAll();
}
// Участник сохранения: каждый модуль сам решает, что и как хранит, в своей секции файла.
public interface ISaveParticipant
{
string SaveKey { get; } // имя секции в файле: "economy", "settlement", "world"...
string Capture(); // JSON секции; null -- оставить то, что уже было в файле
void Restore(string json);
void ResetState(); // вернуться к состоянию новой игры (сброс сохранений)
}
// Список участников. Модули регистрируются сами, модуль Сохранений обходит их при записи и загрузке.
public static class SaveRegistry
{
private static readonly List<ISaveParticipant> participants = new List<ISaveParticipant>();
public static IReadOnlyList<ISaveParticipant> All => participants;
public static void Register(ISaveParticipant participant)
{
participants.RemoveAll(p => p.SaveKey == participant.SaveKey);
participants.Add(participant);
}
public static void Unregister(ISaveParticipant participant)
{
participants.Remove(participant);
}
public static void Clear()
{
participants.Clear();
}
}