Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
Entity.cs
浏览该文件的文档.
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.Linq;
5using System.Reflection;
8
9namespace GameEntitySystem {
10 public class Entity : IDisposable {
11 public struct FilteredComponentsEnumerable<T> : IEnumerable<T> where T : class {
13
14 public FilteredComponentsEnumerable(Entity entity) => m_entity = entity;
15
16 public FilteredComponentsEnumerator<T> GetEnumerator() => new(m_entity);
17
18 IEnumerator<T> IEnumerable<T>.GetEnumerator() => new FilteredComponentsEnumerator<T>(m_entity);
19
20 IEnumerator IEnumerable.GetEnumerator() => new FilteredComponentsEnumerator<T>(m_entity);
21 }
22
23 public struct FilteredComponentsEnumerator<T> : IEnumerator<T> where T : class {
25
27
29
30 public T Current => m_current;
31
32 object IEnumerator.Current => m_current;
33
35 m_entity = entity;
36 m_index = 0;
37 m_current = null;
38 }
39
40 public void Dispose() { }
41
42 public bool MoveNext() {
43 while (m_index < m_entity.m_components.Count) {
44 if (m_entity.m_components[m_index++] is T val) {
45 m_current = val;
46 return true;
47 }
48 }
49 m_current = null;
50 return false;
51 }
52
53 public void Reset() {
54 m_index = 0;
55 m_current = null;
56 }
57 }
58
60
62
63 List<Component> m_components;
64
65 public bool m_isAddedToProject;
66
68
70
72
73 public List<Component> Components => m_components;
74
75 public event EventHandler EntityAdded;
76
77 public event EventHandler EntityRemoved;
78
79 public int Id;
80
81 public Entity(Project project, ValuesDictionary valuesDictionary, int id) : this(project, valuesDictionary) => Id = id;
82
83 public static event Action<Entity, List<KeyValuePair<int, Component>>> EntityComponentsInitialized;
84
85 public Entity(Project project, ValuesDictionary valuesDictionary) {
86 if (valuesDictionary.DatabaseObject.Type != project.GameDatabase.EntityTemplateType) {
87 throw new InvalidOperationException("ValuesDictionary was not created from EntityTemplate.");
88 }
89 m_project = project;
90 m_valuesDictionary = valuesDictionary;
91 List<KeyValuePair<int, Component>> list = [];
92 foreach (ValuesDictionary item in from x in valuesDictionary.Values
93 select x as ValuesDictionary
94 into x
95 where x != null && x.DatabaseObject != null && x.DatabaseObject.Type == project.GameDatabase.MemberComponentTemplateType
96 select x) {
97 bool isOptional = item.GetValue<bool>("IsOptional");
98 string className = item.GetValue<string>("Class");
99 int loadOrder = item.GetValue<int>("LoadOrder");
100 Type type = TypeCache.FindType(className, false, !isOptional);
101 if (type != null) {
102 object obj;
103 try {
104#pragma warning disable IL2072
105 obj = Activator.CreateInstance(type);
106#pragma warning restore IL2072
107 }
108 catch (TargetInvocationException ex) {
109 if (ex.InnerException is not null) {
110 throw ex.InnerException;
111 }
112 throw;
113 }
114 if (obj is not Component component) {
115 throw new InvalidOperationException(
116 $"Type \"{className}\" cannot be used as a component because it does not inherit from Component class."
117 );
118 }
119 component.Initialize(this, item);
120 bool isModComponent = type.Namespace != "Game";
121 //如果是原版的组件,则按原来顺序,否则往后
122 int adjustedLoadOrder = isModComponent ? loadOrder + 10000 : loadOrder;
123 list.Add(new KeyValuePair<int, Component>(adjustedLoadOrder, component));
124 }
125 }
126 EntityComponentsInitialized?.Invoke(this, list);
127 // 按调整后的 LoadOrder 排序
128 list.Sort((x, y) => x.Key - y.Key);
129 m_components = new List<Component>(list.Select(x => x.Value));
130 }
131
132 public Component FindComponent(Type type, string name, bool throwOnError) {
133 foreach (Component component in m_components) {
134 if (type.GetTypeInfo().IsAssignableFrom(component.GetType().GetTypeInfo())
135 && (string.IsNullOrEmpty(name) || component.ValuesDictionary.DatabaseObject.Name == name)) {
136 return component;
137 }
138 }
139 if (throwOnError) {
140 if (string.IsNullOrEmpty(name)) {
141 throw new Exception($"Required component {type.FullName} does not exist in entity.");
142 }
143 throw new Exception($"Required component {type.FullName} with name \"{name}\" does not exist in entity.");
144 }
145 return null;
146 }
147
148 public Component FindComponent(string name, bool throwOnError) {
149 if (throwOnError) {
150 if (string.IsNullOrEmpty(name)) {
151 throw new ArgumentNullException(nameof(name));
152 }
153 }
154 foreach (Component component in m_components) {
155 if (component.ValuesDictionary.DatabaseObject.Name == name) {
156 return component;
157 }
158 }
159 if (throwOnError) {
160 throw new Exception($"Required component {name} does not exist in entity.");
161 }
162 return null;
163 }
164
165 public T FindComponent<T>() where T : class => FindComponent(typeof(T), null, false) as T;
166
167 public T FindComponent<T>(bool throwOnError) where T : class => FindComponent(typeof(T), null, throwOnError) as T;
168
169 public T FindComponent<T>(string name, bool throwOnError) where T : class => FindComponent(typeof(T), name, throwOnError) as T;
170
171 public void RemoveComponent(Component component) {
172 m_components.Remove(component);
173 }
174
175 public void ReplaceComponent(Component oldComponent, Component newComponent) {
176 if (newComponent.GetType().GetTypeInfo().IsAssignableFrom(oldComponent.GetType().GetTypeInfo())) {
177 newComponent.InheritFromComponent(oldComponent);
178 }
179 }
180
181 public FilteredComponentsEnumerable<T> FindComponents<T>() where T : class => new(this);
182
183 public void Dispose() {
184 foreach (Component component in m_components) {
185 component.DisposeInternal();
186 }
187 }
188
189 internal void DisposeInternal() {
190 GC.SuppressFinalize(this);
191 Dispose();
192 }
193
194 internal List<Entity> InternalGetOwnedEntities() {
195 List<Entity> list = null;
196 foreach (Component component in m_components) {
197 IEnumerable<Entity> ownedEntities = component.GetOwnedEntities();
198 list = list ?? [];
199 list.AddRange(ownedEntities);
200 }
201 return list;
202 }
203
204 public void InternalLoadEntity(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap) {
205 foreach (Component component in m_components) {
206 try {
207 component.Load(component.ValuesDictionary, idToEntityMap);
208 }
209 catch (Exception innerException) {
210 throw new InvalidOperationException($"Error loading component {component.GetType().FullName}.", innerException);
211 }
212 }
213 }
214
215 public void InternalSaveEntity(ValuesDictionary valuesDictionary, EntityToIdMap entityToIdMap) {
216 foreach (Component component in Components) {
217 ValuesDictionary valuesDictionary2 = [];
218 component.Save(valuesDictionary2, entityToIdMap);
219 if (valuesDictionary2.Count > 0) {
220 valuesDictionary.SetValue(component.ValuesDictionary.DatabaseObject.Name, valuesDictionary2);
221 }
222 }
223 }
224
225 public void FireEntityAddedEvent() {
226 EntityAdded?.Invoke(this, EventArgs.Empty);
227 }
228
230 EntityRemoved?.Invoke(this, EventArgs.Empty);
231 }
232 }
233}
static Type FindType(string typeName, bool skipSystemAssemblies, bool throwIfNotFound)
virtual void InheritFromComponent(Component baseComponent)
ValuesDictionary ValuesDictionary
virtual void Save(ValuesDictionary valuesDictionary, EntityToIdMap entityToIdMap)
virtual void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap)
virtual IEnumerable< Entity > GetOwnedEntities()
Entity(Project project, ValuesDictionary valuesDictionary, int id) static Action< Entity, List< KeyValuePair< int, Component > > > EntityComponentsInitialized
void ReplaceComponent(Component oldComponent, Component newComponent)
List< Entity > InternalGetOwnedEntities()
EventHandler EntityRemoved
FilteredComponentsEnumerable< T > FindComponents< T >()
Component FindComponent(string name, bool throwOnError)
Entity(Project project, ValuesDictionary valuesDictionary)
List< Component > Components
ValuesDictionary m_valuesDictionary
void InternalLoadEntity(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap)
ValuesDictionary ValuesDictionary
void InternalSaveEntity(ValuesDictionary valuesDictionary, EntityToIdMap entityToIdMap)
List< Component > m_components
void RemoveComponent(Component component)
Component FindComponent(Type type, string name, bool throwOnError)
DatabaseObjectType MemberComponentTemplateType
DatabaseObjectType EntityTemplateType
virtual GameDatabase GameDatabase
FilteredComponentsEnumerator< T > GetEnumerator()