Files
Net.Like.Xue.Tokyo/Packages-Local/Com.Project.B.Unity/WorldNodeService/UnityElevatorService.cs

159 lines
6.3 KiB
C#
Raw Normal View History

2025-06-24 23:49:13 +08:00
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using BITKit;
using BITKit.Entities;
using BITKit.StateMachine;
using BITKit.Tween;
using BITKit.UX.Hotkey;
using BITKit.WorldNode;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Net.Project.B.Interaction;
using UnityEngine;
namespace Net.Project.B.WorldNode
{
public class UnityElevatorService:IDisposable
{
public sealed class ElevatorData
{
public int ElevatorId;
public Rigidbody Rigidbody;
public int ElevatorButtonId;
public readonly Dictionary<int, int> ButtonToFloor = new();
public readonly Dictionary<int, Transform> Floors = new();
}
public abstract class ElevatorState:StateAsync
{
}
public sealed class IdleState:ElevatorState
{
}
public sealed class TransportingState:ElevatorState
{
}
public sealed class FaultState:ElevatorState
{
}
private readonly ILogger<UnityElevatorService> _logger;
private readonly IEntitiesService _entitiesService;
private readonly Dictionary<int, UnityElevatorNode> _elevatorNodes=new();
private readonly Dictionary<int, ElevatorData> _elevatorData = new();
private readonly Dictionary<int,int> _buttonToElevator = new();
private readonly Dictionary<int, CancellationTokenSource> _cts = new();
private readonly IWorldInteractionService _interactionService;
private readonly IFixedTicker _fixedTicker;
private readonly IUXHotKey _uxHotKey;
public UnityElevatorService(IFixedTicker fixedTicker, IWorldInteractionService interactionService, IEntitiesService entitiesService, IUXHotKey uxHotKey, ILogger<UnityElevatorService> logger)
{
_fixedTicker = fixedTicker;
_interactionService = interactionService;
_entitiesService = entitiesService;
_uxHotKey = uxHotKey;
_logger = logger;
_interactionService.OnInteraction+=OnInteraction;
_entitiesService.OnAdd += OnNodeRegistered;
_entitiesService.OnRemove += OnRemove;
}
private void OnRemove(IEntity obj)
{
if (!_cts.TryGetValue(obj.Id, out var cts)) return;
cts.Cancel();
cts.Dispose();
}
private async void OnInteraction(object arg1, IWorldInteractable arg2, WorldInteractionProcess arg3, object arg4)
{
if(arg3 is not (WorldInteractionProcess.Performed or WorldInteractionProcess.System))return;
if(_buttonToElevator.TryGetValue(arg2.Id,out var elevatorId) is false)return;
if(_elevatorData.TryGetValue(elevatorId,out var elevatorData) is false)return;
if (elevatorData.ElevatorButtonId != arg2.Id)
{
if(elevatorData.ButtonToFloor.TryGetValue(arg2.Id,out var floor) is false)return;
if(elevatorData.Floors.TryGetValue(floor,out var floorTransform) is false)return;
var currentPosition = elevatorData.Rigidbody.position;
var targetPosition = currentPosition;
targetPosition.y = floorTransform.position.y;
_logger.LogInformation($"Elevator {elevatorId} to {floor+1}F");
if (_cts.TryGetValue(elevatorData.ElevatorId, out var cts))
{
cts.Cancel();
cts.Dispose();
}
cts = _cts[elevatorData.ElevatorId] = new CancellationTokenSource();
await BITween.MoveToForward(elevatorData.Rigidbody.MovePosition, currentPosition,targetPosition, 1, Vector3.MoveTowards,cts.Token);
}
else
{
_logger.LogInformation($"Elevator {elevatorId} Menu");
var hotKeyCollections = new HotkeyCollection();
foreach (var (buttonId,floor) in elevatorData.ButtonToFloor)
{
if(_entitiesService.TryGetEntity(buttonId,out var buttonEntity) is false)continue;
if(buttonEntity.ServiceProvider.QueryComponents(out IWorldInteractable buttonInteractable) is false)continue;
var hotkeyProvider = new HotkeyProvider
{
Name = $"{floor+1}F",
Description = $"Elevator to {floor+1}F",
Enabled = buttonId!=arg2.Id,
OnPerform = () =>
{
if(buttonEntity.CancellationToken.IsCancellationRequested)return;
OnInteraction(arg1, buttonInteractable, WorldInteractionProcess.System, arg4);
}
};
hotKeyCollections.Register(hotkeyProvider);
}
_uxHotKey.Perform(hotKeyCollections);
}
}
private void OnNodeRegistered(IEntity entity)
{
if (entity.ServiceProvider.QueryComponents(out UnityElevatorNode elevatorNode) is false) return;
_elevatorNodes[entity.Id]=elevatorNode;
var elevatorData = new ElevatorData
{
ElevatorId = entity.Id,
Rigidbody = elevatorNode.Platform,
};
for (var i = 0; i < elevatorNode.FloorButtons.Length; i++)
{
var button = elevatorNode.FloorButtons[i];
var buttonId = button.gameObject.GetInstanceID();
_buttonToElevator[buttonId] = entity.Id;
elevatorData.ButtonToFloor[buttonId] = i;
elevatorData.Floors[i] = elevatorNode.Floors[i].transform;
}
elevatorData.ElevatorButtonId = elevatorNode.ElevatorButton.GetInstanceID();
_buttonToElevator[elevatorData.ElevatorButtonId]=entity.Id;
_elevatorData[entity.Id] = elevatorData;
}
public void Dispose()
{
_entitiesService.OnAdd -= OnNodeRegistered;
_interactionService.OnInteraction-=OnInteraction;
}
}
}