forked from FabianTerhorst/coreclr-module
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAsyncEntityPool.cs
More file actions
165 lines (138 loc) · 5.38 KB
/
AsyncEntityPool.cs
File metadata and controls
165 lines (138 loc) · 5.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using AltV.Net.Async.Elements.Entities;
using AltV.Net.Elements.Entities;
using AltV.Net.Elements.Pools;
namespace AltV.Net.Async
{
//TODO: write GetOrCreateAsync for BaseEntityPool
/*public partial class AltAsync
{
/// <summary>
/// Create entity async in entity pool, don't provide a IntPtr.Zero
/// </summary>
/// <param name="entityPool"></param>
/// <param name="entityPointer"></param>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
public static async Task<TEntity> CreateAsync<TEntity>(this IEntityPool<TEntity> entityPool,
IntPtr entityPointer) where TEntity : IEntity
{
var id = await Do(() => Entity.GetId(entityPointer));
entityPool.Create(entityPointer, id, out var entity);
return entity;
}
/// <summary>
/// Get or create entity async in entity pool, don't provide a IntPtr.Zero
/// </summary>
/// <param name="entityPool"></param>
/// <param name="entityPointer"></param>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
public static async Task<TEntity> GetOrCreateAsync<TEntity>(this IEntityPool<TEntity> entityPool,
IntPtr entityPointer) where TEntity : IEntity
{
if (entityPool.Get(entityPointer, out var entity)) return entity;
entity = await entityPool.CreateAsync(entityPointer);
return entity;
}
}*/
public abstract class AsyncEntityPool<TEntity> : IEntityPool<TEntity> where TEntity : IEntity
{
private readonly ConcurrentDictionary<IntPtr, TEntity> entities = new();
private readonly IEntityFactory<TEntity> entityFactory;
private readonly bool forceAsync;
public AsyncEntityPool(IEntityFactory<TEntity> entityFactory, bool forceAsync)
{
this.entityFactory = entityFactory;
this.forceAsync = forceAsync;
}
public abstract ushort GetId(IntPtr entityPointer);
public TEntity Create(ICore core, IntPtr entityPointer, ushort id)
{
if (entityPointer == IntPtr.Zero) return default;
if (entities.TryGetValue(entityPointer, out var entity)) return entity;
entity = entityFactory.Create(core, entityPointer, id);
Add(entity);
return entity;
}
public TEntity Create(ICore core, IntPtr entityPointer)
{
return Create(core, entityPointer, GetId(entityPointer));
}
public void Add(TEntity entity)
{
entities[entity.NativePointer] = entity;
if (forceAsync && entity is not AsyncEntity)
throw new Exception("Tried to add sync entity to async pool. Probably you used \"new Vehicle\" syntax (should be \"new AsyncVehicle\"), or didn't adapt your custom entity class to new Async API.");
OnAdd(entity);
}
public bool Remove(TEntity entity)
{
return Remove(entity.NativePointer);
}
//TODO: what should happen on failure
public bool Remove(IntPtr entityPointer)
{
if (!entities.TryRemove(entityPointer, out var entity) || !entity.Exists) return false;
entity.OnRemove();
lock (entity)
{
BaseObjectPool<TEntity>.SetEntityNoLongerExists(entity);
}
OnRemove(entity);
return true;
}
public TEntity Get(IntPtr entityPointer)
{
return entities.TryGetValue(entityPointer, out var entity) ? entity : default;
}
public TEntity GetOrCreate(ICore core, IntPtr entityPointer)
{
if (entityPointer == IntPtr.Zero)
{
return default;
}
if (entities.TryGetValue(entityPointer, out var entity)) return entity;
return Create(core, entityPointer);
}
public TEntity GetOrCreate(ICore core, IntPtr entityPointer, ushort id)
{
if (entityPointer == IntPtr.Zero)
{
return default;
}
if (entities.TryGetValue(entityPointer, out var entity)) return entity;
return Create(core, entityPointer, id);
}
public IReadOnlyCollection<TEntity> GetAllEntities()
{
return (IReadOnlyCollection<TEntity>) entities.Values;
}
public KeyValuePair<IntPtr, TEntity>[] GetEntitiesArray()
{
return entities.ToArray();
}
public abstract void ForEach(IBaseObjectCallback<TEntity> baseObjectCallback);
public abstract Task ForEach(IAsyncBaseObjectCallback<TEntity> asyncBaseObjectCallback);
public virtual void OnAdd(TEntity entity)
{
}
public virtual void OnRemove(TEntity entity)
{
}
public void Dispose()
{
foreach (var entity in entities.Values)
{
if (!(entity is IInternalBaseObject internalEntity)) continue;
internalEntity.ClearData();
entity.OnRemove();
OnRemove(entity);
}
entities.Clear();
}
}
}