2025-07-08 10:46:31 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
|
|
|
|
namespace Superlazy
|
|
|
|
|
{
|
|
|
|
|
public static class ZoneHandler
|
|
|
|
|
{
|
|
|
|
|
private delegate void ComponentMethod(Zone unit, SLEntity component, SLEntity context);
|
|
|
|
|
|
|
|
|
|
private static Dictionary<string, ZoneComponent> componentInstants;
|
|
|
|
|
private static Dictionary<string, Dictionary<string, ComponentMethod>> methodInstants;
|
|
|
|
|
|
|
|
|
|
private static Dictionary<string, int> componentOrders;
|
|
|
|
|
private static Dictionary<string, Dictionary<string, int>> methodOrders;
|
|
|
|
|
|
|
|
|
|
private static Queue<List<SLEntity>> messageComponents;
|
|
|
|
|
|
|
|
|
|
public static void Init()
|
|
|
|
|
{
|
|
|
|
|
if (componentInstants != null) return;
|
|
|
|
|
|
|
|
|
|
componentInstants = new Dictionary<string, ZoneComponent>();
|
|
|
|
|
componentInstants.CreateInstanceDictionary();
|
|
|
|
|
|
|
|
|
|
var methodInfos = new Dictionary<string, Dictionary<string, MethodInfo>>();
|
|
|
|
|
methodInfos.CreateMethodInfoDictionary<ZoneComponent>(false, typeof(Zone), typeof(SLEntity), typeof(SLEntity));
|
|
|
|
|
|
|
|
|
|
methodInstants = new Dictionary<string, Dictionary<string, ComponentMethod>>();
|
|
|
|
|
foreach (var methodInstant in methodInfos)
|
|
|
|
|
{
|
|
|
|
|
methodInstants.Add(methodInstant.Key, new Dictionary<string, ComponentMethod>());
|
|
|
|
|
foreach (var method in methodInstant.Value)
|
|
|
|
|
{
|
|
|
|
|
methodInstants[methodInstant.Key][method.Key] = (ComponentMethod)method.Value.CreateDelegate(typeof(ComponentMethod), componentInstants[methodInstant.Key]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentOrders = new Dictionary<string, int>();
|
|
|
|
|
methodOrders = new Dictionary<string, Dictionary<string, int>>();
|
|
|
|
|
|
|
|
|
|
foreach (var component in componentInstants)
|
|
|
|
|
{
|
|
|
|
|
var type = component.Value.GetType();
|
|
|
|
|
var name = component.Key;
|
|
|
|
|
var componentOrder = type.GetCustomAttribute<ComponentOrderAttribute>()?.order ?? 0;
|
|
|
|
|
componentOrders.Add(name, componentOrder);
|
|
|
|
|
|
|
|
|
|
if (methodOrders.ContainsKey(name) == false) methodOrders.Add(name, new Dictionary<string, int>());
|
|
|
|
|
var methodOrder = methodOrders[name];
|
|
|
|
|
|
|
|
|
|
if (methodInfos.TryGetValue(component.Key, out var methodCahces))
|
|
|
|
|
{
|
|
|
|
|
foreach (var methodInfo in methodCahces)
|
|
|
|
|
{
|
|
|
|
|
var attribute = methodInfo.Value.GetCustomAttribute<ComponentOrderAttribute>();
|
|
|
|
|
var method = attribute?.methodOverride ?? methodInfo.Value.Name;
|
|
|
|
|
var order = attribute?.order ?? componentOrder;
|
|
|
|
|
|
|
|
|
|
methodOrder.Add(method, order);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
messageComponents = new Queue<List<SLEntity>>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Begin(Zone zone)
|
|
|
|
|
{
|
|
|
|
|
if (zone.components is null)
|
|
|
|
|
{
|
|
|
|
|
zone.components = new SortedList<int, List<SLEntity>>();
|
|
|
|
|
zone.componentMessages = new Dictionary<string, SortedList<int, List<SLEntity>>>();
|
|
|
|
|
zone.startComponents = new List<SLEntity>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var component in zone.Entity["Components"].Where(c => c["Run"] == false))
|
|
|
|
|
{
|
|
|
|
|
var name = component["Component"];
|
|
|
|
|
var componentOrder = componentOrders[component["Component"]];
|
|
|
|
|
if (zone.components.ContainsKey(componentOrder) == false) zone.components[componentOrder] = new List<SLEntity>();
|
|
|
|
|
zone.components[componentOrder].Add(component);
|
|
|
|
|
|
|
|
|
|
foreach (var methodOrder in methodOrders[name])
|
|
|
|
|
{
|
|
|
|
|
var method = methodOrder.Key;
|
|
|
|
|
var order = methodOrder.Value;
|
|
|
|
|
|
|
|
|
|
if (zone.componentMessages.ContainsKey(method) == false) zone.componentMessages[method] = new SortedList<int, List<SLEntity>>();
|
|
|
|
|
var messages = zone.componentMessages[method];
|
|
|
|
|
if (messages.ContainsKey(order) == false) messages[order] = new List<SLEntity>();
|
|
|
|
|
messages[order].Add(component);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var componentOrders in zone.components)
|
|
|
|
|
{
|
|
|
|
|
foreach (var component in componentOrders.Value)
|
|
|
|
|
{
|
|
|
|
|
component["Run"] = true;
|
|
|
|
|
componentInstants[component["Component"]].Begin(zone, component);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void AddComponent(Zone zone, string componentKey, string componentName, SLEntity context)
|
|
|
|
|
{
|
|
|
|
|
if (zone.Entity["Components"].HasChild(componentKey))
|
|
|
|
|
{
|
|
|
|
|
var component = zone.Entity["Components"][componentKey];
|
|
|
|
|
if (component.HasChild("End") == false) SLLog.Error($"component cannot be added. {component} already exists");
|
|
|
|
|
|
|
|
|
|
componentInstants[component["Component"]].End(zone, component);
|
|
|
|
|
|
|
|
|
|
zone.components[componentOrders[componentName]].Remove(component);
|
|
|
|
|
|
|
|
|
|
foreach (var methodOrder in methodOrders[componentName])
|
|
|
|
|
{
|
|
|
|
|
zone.componentMessages[methodOrder.Key][methodOrder.Value].Remove(component);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zone.Entity["Components"][component.ID] = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zone.Entity["Components"][componentKey] = context;
|
|
|
|
|
zone.Entity["Components"][componentKey]["Component"] = componentName;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
var component = zone.Entity["Components"][componentKey];
|
|
|
|
|
|
|
|
|
|
foreach (var methodOrder in methodOrders[componentName])
|
|
|
|
|
{
|
|
|
|
|
var method = methodOrder.Key;
|
|
|
|
|
var order = methodOrder.Value;
|
|
|
|
|
|
|
|
|
|
if (zone.componentMessages.ContainsKey(method) == false) zone.componentMessages[method] = new SortedList<int, List<SLEntity>>();
|
|
|
|
|
var messages = zone.componentMessages[method];
|
|
|
|
|
if (messages.ContainsKey(order) == false) messages[order] = new List<SLEntity>();
|
|
|
|
|
messages[order].Add(component);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
component["Run"] = true;
|
|
|
|
|
componentInstants[componentName].Begin(zone, component);
|
|
|
|
|
zone.startComponents.Add(component); // AddComponent 때에는 딜레이 Add가 되어야해서 별도로 관리
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Update(Zone zone)
|
|
|
|
|
{
|
|
|
|
|
// 컴포넌트 업데이트는 추가된 다음프레임부터 발생, 그전에는 AddComponent등에서 메시지는 세팅 가능하다
|
|
|
|
|
//TODO: Run = false 등의 코드로 재갱신이 들어간다면 추가 필요
|
|
|
|
|
foreach (var component in zone.startComponents)
|
|
|
|
|
{
|
|
|
|
|
var componentOrder = componentOrders[component["Component"]];
|
|
|
|
|
|
|
|
|
|
if (zone.components.ContainsKey(componentOrder) == false) zone.components[componentOrder] = new List<SLEntity>();
|
|
|
|
|
zone.components[componentOrder].Add(component);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zone.startComponents.Clear();
|
|
|
|
|
|
|
|
|
|
foreach (var components in zone.components)
|
|
|
|
|
{
|
|
|
|
|
foreach (var component in components.Value)
|
|
|
|
|
{
|
|
|
|
|
if (component.HasChild("Run") && component.HasChild("End") == false)
|
|
|
|
|
{
|
|
|
|
|
componentInstants[component["Component"]].Update(zone, component);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var components in zone.components)
|
|
|
|
|
{
|
|
|
|
|
components.Value.RemoveAll(component =>
|
|
|
|
|
{
|
|
|
|
|
if (component.HasChild("End"))
|
|
|
|
|
{
|
|
|
|
|
string name = component["Component"];
|
|
|
|
|
componentInstants[name].End(zone, component);
|
|
|
|
|
foreach (var methodOrder in methodOrders[name])
|
|
|
|
|
{
|
|
|
|
|
zone.componentMessages[methodOrder.Key][methodOrder.Value].Remove(component);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zone.Entity["Components"][component.ID] = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void End(Zone zone)
|
|
|
|
|
{
|
|
|
|
|
foreach (var components in zone.components)
|
|
|
|
|
{
|
|
|
|
|
components.Value.RemoveAll(component =>
|
|
|
|
|
{
|
|
|
|
|
if (component["Run"])
|
|
|
|
|
{
|
|
|
|
|
string name = component["Component"];
|
|
|
|
|
componentInstants[name].End(zone, component);
|
|
|
|
|
foreach (var methodOrder in methodOrders[name])
|
|
|
|
|
{
|
|
|
|
|
zone.componentMessages[methodOrder.Key][methodOrder.Value].Remove(component);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zone.Entity["Components"][component.ID] = false;
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Message(string message, Zone zone, SLEntity context)
|
|
|
|
|
{
|
|
|
|
|
if (zone.componentMessages.ContainsKey(message))
|
|
|
|
|
{
|
|
|
|
|
List<SLEntity> components;
|
|
|
|
|
if (messageComponents.Count != 0)
|
|
|
|
|
{
|
|
|
|
|
components = messageComponents.Dequeue();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
components = new List<SLEntity>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var messages in zone.componentMessages[message])
|
|
|
|
|
{
|
|
|
|
|
components.AddRange(messages.Value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var component in components)
|
|
|
|
|
{
|
|
|
|
|
if (component.HasChild("Run") == false) continue;
|
|
|
|
|
if (component.HasChild("End")) continue;
|
|
|
|
|
string name = component["Component"];
|
|
|
|
|
var method = methodInstants[name][message];
|
|
|
|
|
method(zone, component, context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
components.Clear();
|
|
|
|
|
messageComponents.Enqueue(components);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zone.Event(null, message, context);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|