forked from northwood-studios/LabAPI
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCustomDataStore.cs
More file actions
161 lines (135 loc) · 6.37 KB
/
Copy pathCustomDataStore.cs
File metadata and controls
161 lines (135 loc) · 6.37 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
using System;
using System.Collections.Generic;
using System.Linq;
using LabApi.Features.Wrappers;
using NorthwoodLib.Pools;
namespace LabApi.Features.Stores;
/// <summary>
/// Represents a Custom Data Store that plugins can use to store data with a player.
/// </summary>
public abstract class CustomDataStore
{
private static readonly Dictionary<Type, Dictionary<Player, CustomDataStore>> StoreInstances = new ();
/// <summary>
/// Gets the <see cref="Player"/> that this instance is associated with.
/// </summary>
public Player Owner { get; internal set; }
/// <summary>
/// Initializes a new instance of the <see cref="CustomDataStore"/> class.
/// </summary>
/// <param name="owner">The <see cref="Player"/> that this instance is associated with.</param>
protected CustomDataStore(Player owner)
{
Owner = owner;
InternalOnInstanceCreated();
}
/// <summary>
/// Gets the <see cref="CustomDataStore"/> for the specified <see cref="Player"/>, or creates a new one if it doesn't exist.
/// </summary>
/// <param name="player">The <see cref="Player"/> to get the <see cref="CustomDataStore"/> for.</param>
/// <typeparam name="TStore">The type of the <see cref="CustomDataStore"/>.</typeparam>
/// <returns>The <see cref="CustomDataStore"/> for the specified <see cref="Player"/>.</returns>
public static TStore GetOrAdd<TStore>(Player player)
where TStore : CustomDataStore
{
Type type = typeof(TStore);
if (!CustomDataStoreManager.IsRegistered<TStore>())
CustomDataStoreManager.RegisterStore<TStore>();
if (!StoreInstances.TryGetValue(type, out Dictionary<Player, CustomDataStore>? playerStores))
{
playerStores = new Dictionary<Player, CustomDataStore>();
StoreInstances[type] = playerStores;
}
if (playerStores.TryGetValue(player, out CustomDataStore? store))
return (TStore)store;
store = (TStore)Activator.CreateInstance(type, player);
playerStores[player] = store;
return (TStore)store;
}
/// <summary>
/// Checks if the <see cref="CustomDataStore"/> for the specified <see cref="Player"/> exists.
/// </summary>
/// <param name="player"> The <see cref="Player"/> to check the <see cref="CustomDataStore"/> for.</param>
/// <typeparam name="TStore">The type of the <see cref="CustomDataStore"/></typeparam>
/// <returns>True if the <see cref="CustomDataStore"/> exists for the specified <see cref="Player"/>, false if not.</returns>
public static bool Exists<TStore>(Player player)
where TStore : CustomDataStore
{
Type type = typeof(TStore);
if (!StoreInstances.TryGetValue(type, out Dictionary<Player, CustomDataStore>? playerStores))
return false;
return playerStores.ContainsKey(player);
}
/// <summary>
/// Called when a new instance of the <see cref="CustomDataStore"/> is created.
/// </summary>
protected virtual void OnInstanceCreated() { }
/// <summary>
/// Called when an instance of the <see cref="CustomDataStore"/> is going to be destroyed.
/// </summary>
protected virtual void OnInstanceDestroyed() { }
/// <summary>
/// Destroys the <see cref="CustomDataStore"/> for the specified <see cref="Player"/>.
/// </summary>
/// <param name="player">The <see cref="Player"/> to destroy the <see cref="CustomDataStore"/> for.</param>
/// <typeparam name="TStore">The type of the <see cref="CustomDataStore"/>.</typeparam>
internal static void Destroy<TStore>(Player player)
where TStore : CustomDataStore
{
if (!StoreInstances.TryGetValue(typeof(TStore), out Dictionary<Player, CustomDataStore>? playerStores))
return;
if (!playerStores.TryGetValue(player, out CustomDataStore? store))
return;
store.Destroy();
}
/// <summary>
/// Destroys all instances of the <see cref="CustomDataStore"/> for the specified type.
/// </summary>
/// <typeparam name="TStore">The type of the <see cref="CustomDataStore"/>.</typeparam>
internal static void DestroyAll<TStore>()
{
List<CustomDataStore>? storesToRemove = ListPool<CustomDataStore>.Shared.Rent(StoreInstances.SelectMany(entry =>
entry.Value.Where(playerStore => playerStore.Value.GetType() == typeof(TStore)).Select(playerStore => playerStore.Value)));
foreach (CustomDataStore? store in storesToRemove)
store.Destroy();
ListPool<CustomDataStore>.Shared.Return(storesToRemove);
}
/// <summary>
/// Destroys this instance of the <see cref="CustomDataStore"/>.
/// </summary>
internal void Destroy()
{
OnInstanceDestroyed();
StoreInstances[this.GetType()].Remove(Owner);
}
private void InternalOnInstanceCreated() => OnInstanceCreated();
}
/// <summary>
/// Represents a Custom Data Store that plugins can use to store data with a player.
/// </summary>
/// <typeparam name="TStore">The type of the <see cref="CustomDataStore"/>.</typeparam>
public abstract class CustomDataStore<TStore> : CustomDataStore
where TStore : CustomDataStore<TStore>
{
/// <summary>
/// Initializes a new instance of the <see cref="CustomDataStore"/> class.
/// </summary>
/// <param name="owner">The <see cref="Player"/> that this instance is associated with.</param>
protected CustomDataStore(Player owner)
: base(owner)
{
}
/// <summary>
/// Gets the <see cref="CustomDataStore"/> for the specified <see cref="Player"/>.
/// </summary>
/// <param name="player">The <see cref="Player"/> to get the <see cref="CustomDataStore"/> for.</param>
/// <returns>The <see cref="CustomDataStore"/> for the specified <see cref="Player"/>.</returns>
public static TStore Get(Player player) => GetOrAdd<TStore>(player);
/// <summary>
/// Checks if the <see cref="CustomDataStore"/> for the specified <see cref="Player"/> exists.
/// </summary>
/// <param name="player"> The <see cref="Player"/> to check the <see cref="CustomDataStore"/> for.</param>
/// <typeparam name="TStore">The type of the <see cref="CustomDataStore"/></typeparam>
/// <returns>True if the <see cref="CustomDataStore"/> exists for the specified <see cref="Player"/>, false if not.</returns>
public static bool Exists(Player player) => Exists<TStore>(player);
}