ProjectDDD/Packages/SLUnity/UnitSytem/Zone.cs
2025-06-25 11:33:17 +09:00

244 lines
6.7 KiB (Stored with Git LFS)
C#

using System;
using System.Collections.Generic;
namespace Superlazy
{
public interface IZone
{
IEnumerable<IUnit> Units { get; }
SLEntity Entity { get; }
SLEntity Player { get; }
IUnit AddUnit(SLEntity unitEntity);
IUnit GetUnit(int handle);
SLEntity Message(string message, SLEntity context);
void Event(Unit unit, string message, SLEntity context);
}
public class Zone : IZone
{
public IEnumerable<Unit> Units => units;
IEnumerable<IUnit> IZone.Units => units; // 인터페이스에서는 IUnit만 적용
public SLEntity Entity { get; }
public SLEntity Player { get; }
public event Action<Unit, string, SLEntity> OnMessage;
private int handleIndex = 0;
private readonly Dictionary<int, Unit> unitHandles = new Dictionary<int, Unit>();
private readonly List<Unit> units = new List<Unit>();
private readonly List<Unit> addUnits = new List<Unit>();
private readonly List<int> removeHandles = new List<int>();
private bool useDelayUnit;
internal List<SLEntity> startComponents;
internal SortedList<int, List<SLEntity>> components;
internal Dictionary<string, SortedList<int, List<SLEntity>>> componentMessages;
public Zone(SLEntity session, SLEntity player)
{
Entity = session;
Player = player;
ZoneHandler.Begin(this);
}
public IUnit AddUnit(SLEntity unitEntity)
{
var unit = new Unit(unitEntity, this);
if (useDelayUnit)
{
addUnits.Add(unit);
}
else
{
AddUnit(unit);
}
return unit;
}
private void AddUnit(Unit unit)
{
if (unit == null)
{
SLLog.Error("Unit is null");
return;
}
handleIndex += 1;
unit.Entity["Handle"] = handleIndex;
Entity["Units"][handleIndex] = unit.Entity;
if (unit.Entity["UnitType"])
{
Entity["UnitTypes"][unit.Entity["UnitType"]][unit.Entity["EventID"]] = handleIndex;
}
if (unit.Entity["EventID"])
{
Entity["EventIDs"][unit.Entity["EventID"]] = handleIndex;
}
units.Add(unit);
unitHandles[handleIndex] = unit;
Event(unit, "AddUnit", unit.Entity);
UnitHandler.Begin(unit);
}
private void RemoveUnit(Unit unit)
{
Event(unit, "RemoveUnit", unit.Entity);
UnitHandler.End(unit);
if (unit.Entity["UnitType"])
{
Entity["UnitTypes"][unit.Entity["UnitType"]][unit.Entity["EventID"]] = false;
}
if (unit.Entity["EventID"])
{
Entity["EventIDs"][unit.Entity["EventID"]] = false;
}
Entity["Units"][unit.Entity["Handle"]] = false;
unitHandles.Remove(unit.Entity["Handle"]);
units.Remove(unit);
unit.Entity["Handle"] = false;
}
public IUnit GetUnit(int handle)
{
if (unitHandles.ContainsKey(handle))
{
return unitHandles[handle];
}
return null;
}
public void Update()
{
ZoneHandler.Update(this);
useDelayUnit = true;
foreach (var unit in units)
{
UnitHandler.Update(unit);
}
foreach (var unit in units)
{
unit.Message("OnEndUpdate", Entity);
}
useDelayUnit = false;
foreach (var unit in addUnits)
{
AddUnit(unit);
}
addUnits.Clear();
removeHandles.Clear();
foreach (var unit in units)
{
if (unit.Entity.HasChild("End"))
{
removeHandles.Add(unit.Entity["Handle"]);
}
}
foreach (var handle in removeHandles)
{
RemoveUnit(unitHandles[handle]);
}
}
public SLEntity Message(string message, SLEntity context)
{
if (context)
{
context = context.Override();
}
else
{
context = SLEntity.Empty; // TODO: 전달할때 빈거 전달한게 메모리가 아깝다면 최적화가 필요
}
ZoneHandler.Message(message, this, context);
return context;
}
public void Event(Unit unit, string message, SLEntity context)
{
OnMessage?.Invoke(unit, message, context);
}
public void AddComponent<T>() where T : ZoneComponent
{
ZoneHandler.AddComponent(this, typeof(T).Name, typeof(T).Name, SLEntity.Empty); // Start의 경우 이후 즉시 호출하는 케이스들 대응용으로 즉시 실행한다
}
public void AddComponent<T>(SLEntity context) where T : ZoneComponent
{
ZoneHandler.AddComponent(this, typeof(T).Name, typeof(T).Name, context);
}
public void AddComponent<T>(string key, SLEntity context) where T : ZoneComponent
{
ZoneHandler.AddComponent(this, key, typeof(T).Name, context);
}
public void AddComponent(string component)
{
ZoneHandler.AddComponent(this, component, component, SLEntity.Empty); // Start의 경우 이후 즉시 호출하는 케이스들 대응용으로 즉시 실행한다
}
public void AddComponent(string component, SLEntity context)
{
ZoneHandler.AddComponent(this, component, component, context);
}
public void AddComponent(string key, string component, SLEntity context)
{
ZoneHandler.AddComponent(this, key, component, context);
}
public void RemoveComponent<T>() where T : ZoneComponent
{
RemoveComponent(typeof(T).Name);
}
public void RemoveComponent(string component)
{
if (Entity["Components"][component] == false) return;
Entity["Components"][component]["End"] = true;
}
public void Clear()
{
foreach (var unit in Units)
{
unit.Entity["End"] = true;
unit.Entity["Force"] = true;
}
EffectView.ClearEffect();
Update();
handleIndex = 0;
ZoneHandler.End(this);
}
}
}