geometry-tower-defense-base/src-ref/UI/Game/Controller/RepoFormController.cs

426 lines
14 KiB
C#

using System.Collections.Generic;
using GeometryTD.CustomEvent;
using GeometryTD.CustomUtility;
using GeometryTD.Definition;
using GameFramework.Event;
using GeometryTD.CustomComponent;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace GeometryTD.UI
{
public partial class RepoFormController : UIFormControllerCommonBase<RepoFormContext, RepoForm>
{
private const int MaxParticipantCount = 4;
private RepoFormUseCase _useCase;
private readonly Dictionary<long, RepoItemClickActionType> _itemClickActionMap =
new Dictionary<long, RepoItemClickActionType>();
private readonly Dictionary<long, ItemDescSeed> _itemDescSeedMap = new Dictionary<long, ItemDescSeed>();
private readonly HashSet<long> _participantTowerIds = new HashSet<long>();
private readonly HashSet<long> _compAreaTowerIds = new HashSet<long>();
private sealed class ItemDescSeed
{
public string Title;
public string TypeText;
public string Description;
public TagType[] Tags;
public TagRuntimeData[] TagRuntimes;
}
protected override UIFormType UIFormTypeId => UIFormType.RepoForm;
protected override void RefreshUI(RepoForm form, RepoFormContext context)
{
form.RefreshUI(context);
ApplyParticipantSelection();
}
protected override void SubscribeCustomEvents()
{
GameEntry.Event.Subscribe(RepoItemClickedEventArgs.EventId, OnRepoItemClicked);
GameEntry.Event.Subscribe(RepoItemDragEndedEventArgs.EventId, OnRepoItemDragEnded);
GameEntry.Event.Subscribe(CombineSlotClickedEventArgs.EventId, OnCombineSlotClicked);
GameEntry.Event.Subscribe(RepoCombineRequestedEventArgs.EventId, OnRepoCombineRequested);
GameEntry.Event.Subscribe(RepoParticipantAssignRequestedEventArgs.EventId, OnRepoParticipantAssignRequested);
GameEntry.Event.Subscribe(RepoFormReturnEventArgs.EventId, OnRepoFormReturn);
GameEntry.Event.Subscribe(RepoSellModeToggleRequestedEventArgs.EventId, OnRepoSellModeToggleRequested);
GameEntry.Event.Subscribe(RepoSellCancelRequestedEventArgs.EventId, OnRepoSellCancelRequested);
GameEntry.Event.Subscribe(RepoSellConfirmRequestedEventArgs.EventId, OnRepoSellConfirmRequested);
}
protected override void UnsubscribeCustomEvents()
{
GameEntry.Event.Unsubscribe(RepoItemClickedEventArgs.EventId, OnRepoItemClicked);
GameEntry.Event.Unsubscribe(RepoItemDragEndedEventArgs.EventId, OnRepoItemDragEnded);
GameEntry.Event.Unsubscribe(CombineSlotClickedEventArgs.EventId, OnCombineSlotClicked);
GameEntry.Event.Unsubscribe(RepoCombineRequestedEventArgs.EventId, OnRepoCombineRequested);
GameEntry.Event.Unsubscribe(RepoParticipantAssignRequestedEventArgs.EventId, OnRepoParticipantAssignRequested);
GameEntry.Event.Unsubscribe(RepoFormReturnEventArgs.EventId, OnRepoFormReturn);
GameEntry.Event.Unsubscribe(RepoSellModeToggleRequestedEventArgs.EventId, OnRepoSellModeToggleRequested);
GameEntry.Event.Unsubscribe(RepoSellCancelRequestedEventArgs.EventId, OnRepoSellCancelRequested);
GameEntry.Event.Unsubscribe(RepoSellConfirmRequestedEventArgs.EventId, OnRepoSellConfirmRequested);
}
public override int? OpenUI(object userData = null)
{
if (userData is RepoFormContext repoFormContext)
{
return OpenUIInternal(repoFormContext);
}
if (userData is RepoFormRawData rawDataFromUserData)
{
return OpenUI(rawDataFromUserData);
}
if (userData != null)
{
Log.Warning("RepoFormController.OpenUI() userData type is invalid.");
return null;
}
if (_useCase == null)
{
Log.Error("RepoFormController.OpenUI() useCase is null.");
return null;
}
RepoFormRawData rawData = _useCase.CreateInitialModel();
return OpenUI(rawData);
}
public int? OpenUI(RepoFormRawData rawData)
{
RepoFormContext context = BuildContext(rawData);
return OpenUIInternal(context);
}
public override void BindUseCase(IUIUseCase useCase)
{
if (!(useCase is RepoFormUseCase repoFormUseCase))
{
Log.Error("RepoFormController.BindUseCase() useCase is invalid.");
return;
}
_useCase = repoFormUseCase;
}
#region Event Handlers
private void OnRepoItemClicked(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender))
{
return;
}
if (!(e is RepoItemClickedEventArgs args))
{
return;
}
RepoItemClickActionType clickActionType = RepoItemClickActionType.OpenDetail;
if (_itemClickActionMap.TryGetValue(args.ItemId, out RepoItemClickActionType mappedAction))
{
clickActionType = mappedAction;
}
if (args.ItemId <= 0)
{
return;
}
if (_useCase != null && _useCase.State == RepoFormState.Sell)
{
if (_useCase.TryToggleSellSelection(
args.ItemId,
out RepoFormRawData sellModeRawData,
out PlayerInventorySaleFailureReason failureReason))
{
SetContext(BuildContext(sellModeRawData));
RefreshCurrentUI();
}
else if (failureReason == PlayerInventorySaleFailureReason.ParticipantTower)
{
OpenSellBlockedDialog("参战防御塔不能直接出售,请先移出参战区。");
}
return;
}
if (clickActionType == RepoItemClickActionType.RemoveParticipant)
{
if (_useCase == null || Form == null)
{
return;
}
if (!_useCase.TryRemoveParticipantTower(args.ItemId))
{
return;
}
RefreshParticipantAreaOnly();
return;
}
if (!_itemDescSeedMap.TryGetValue(args.ItemId, out ItemDescSeed seed))
{
return;
}
GameEntry.UIRouter.OpenUI(UIFormType.ItemDescForm, new ItemDescFormRawData
{
Title = seed.Title,
TypeText = seed.TypeText,
Description = seed.Description ?? string.Empty,
Price = 0,
ScreenPosition = args.ScreenPosition,
Tags = seed.Tags,
TagRuntimes = seed.TagRuntimes
});
}
private void OnRepoItemDragEnded(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender))
{
return;
}
if (Context != null && Context.State == RepoFormState.Sell)
{
return;
}
if (!(e is RepoItemDragEndedEventArgs args))
{
return;
}
if (Form == null || !_itemClickActionMap.ContainsKey(args.ItemId))
{
return;
}
bool isSelected = _compAreaTowerIds.Contains(args.ItemId)
? _participantTowerIds.Contains(args.ItemId)
: args.Assigned;
Form.SetRepoItemSelected(args.ItemId, isSelected);
}
private void OnCombineSlotClicked(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender))
{
return;
}
if (Context != null && Context.State == RepoFormState.Sell)
{
return;
}
if (!(e is CombineSlotClickedEventArgs args))
{
return;
}
if (Form == null)
{
return;
}
if (Form.TryClearCombineSlot(args.SlotIndex, out long removedItemId) && removedItemId > 0)
{
Form.SetRepoItemSelected(removedItemId, false);
}
}
private void OnRepoFormReturn(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender) || !(e is RepoFormReturnEventArgs))
{
return;
}
if (Form == null)
{
return;
}
CloseUI();
}
private void OnRepoCombineRequested(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender))
{
return;
}
if (!(e is RepoCombineRequestedEventArgs args))
{
return;
}
if (_useCase == null || Form == null)
{
return;
}
if (!_useCase.TryAssembleTower(args.MuzzleItemId, args.BearingItemId, args.BaseItemId))
{
return;
}
RepoFormRawData latestRawData = _useCase.CreateInitialModel();
RepoFormContext latestContext = BuildContext(latestRawData);
if (latestContext != null)
{
SetContext(latestContext);
RefreshCurrentUI();
}
}
private void OnRepoParticipantAssignRequested(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender))
{
return;
}
if (Context != null && Context.State == RepoFormState.Sell)
{
return;
}
if (!(e is RepoParticipantAssignRequestedEventArgs args))
{
return;
}
if (_useCase == null || Form == null || args.TowerItemId <= 0)
{
return;
}
ParticipantTowerAssignResult result = _useCase.TryAddParticipantTower(args.TowerItemId);
if (result == null || !result.IsSuccess)
{
if (result != null)
{
Log.Warning(
"RepoFormController denied participant assignment. TowerId={0}, FailureReason={1}, ValidationFailureReason={2}.",
result.TowerInstanceId,
result.FailureReason,
result.ValidationFailureReason);
GameEntry.UIRouter.OpenUI(
UIFormType.DialogForm,
RepoParticipantAssignDialogUtility.BuildDialog(result, MaxParticipantCount));
}
return;
}
RefreshParticipantAreaOnly();
}
private void OnRepoSellModeToggleRequested(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender) || !(e is RepoSellModeToggleRequestedEventArgs) || _useCase == null)
{
return;
}
if (_useCase.State != RepoFormState.Assemble)
{
return;
}
RepoFormRawData rawData = _useCase.EnterSellState();
SetContext(BuildContext(rawData));
RefreshCurrentUI();
}
private void OnRepoSellCancelRequested(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender) || !(e is RepoSellCancelRequestedEventArgs) || _useCase == null)
{
return;
}
if (_useCase.State != RepoFormState.Sell)
{
return;
}
SetContext(BuildContext(_useCase.ExitSellState()));
RefreshCurrentUI();
}
private void OnRepoSellConfirmRequested(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender) || !(e is RepoSellConfirmRequestedEventArgs) || _useCase == null)
{
return;
}
if (!_useCase.TryConfirmSellSelection(out RepoFormRawData rawData, out PlayerInventorySaleResult result))
{
if (result != null && result.FailureReason == PlayerInventorySaleFailureReason.ParticipantTower)
{
OpenSellBlockedDialog("参战防御塔不能直接出售,请先移出参战区。");
}
return;
}
SetContext(BuildContext(rawData));
RefreshCurrentUI();
if (GameEntry.UI.GetUIForm(UIFormType.ShopForm) != null)
{
GameEntry.UIRouter.OpenUI(UIFormType.ShopForm);
}
}
private bool IsEventFromCurrentForm(object sender)
{
if (Form == null)
{
return false;
}
if (ReferenceEquals(sender, Form))
{
return true;
}
if (sender is Component component)
{
RepoForm ownerForm = component.GetComponentInParent<RepoForm>();
return ownerForm == Form;
}
return false;
}
private static void OpenSellBlockedDialog(string message)
{
GameEntry.UIRouter.OpenUI(UIFormType.DialogForm, new DialogFormRawData
{
Mode = 1,
Title = "无法出售",
Message = message,
PauseGame = false,
ConfirmText = "知道了"
});
}
#endregion
}
}