1 /**
2 Copyright: Copyright (c) 2016-2018 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 module voxelman.world.storage.dimensionobservermanager;
7 
8 import voxelman.log;
9 import voxelman.container.buffer;
10 import voxelman.container.hash.map;
11 import voxelman.container.multihashset;
12 import netlib : SessionId;
13 import voxelman.core.config : DimensionId;
14 
15 /// Stores a list of observers (i.e. players), per dimension
16 /// Can be used to notify players about some dimension local events,
17 /// or change of dimension's parameters (like borders)
18 struct DimensionObserverManager {
19 	void delegate(DimensionId, SessionId) dimensionObserverAdded;
20 	HashMap!(DimensionId, MultiHashSet!SessionId) dimObservers;
21 	// current observer dimension
22 	HashMap!(SessionId, DimensionId) observerDimensions;
23 
24 	void updateObserver(SessionId sessionId, DimensionId dimensionId) {
25 		DimensionId* observerDim = sessionId in observerDimensions;
26 		if (observerDim is null)
27 		{
28 			observerDimensions[sessionId] = dimensionId;
29 			dimensionObserverAdded(dimensionId, sessionId);
30 			return;
31 		}
32 
33 		if (dimensionId != (*observerDim))
34 		{
35 			if (auto oldObservers = (*observerDim) in dimObservers)
36 				oldObservers.remove(sessionId);
37 			auto observers = dimObservers.getOrCreate(dimensionId);
38 			if (observers.add(sessionId))
39 				dimensionObserverAdded(dimensionId, sessionId);
40 			(*observerDim) = dimensionId;
41 		}
42 	}
43 
44 	void removeObserver(SessionId sessionId) {
45 		if (auto observerDim = sessionId in observerDimensions)
46 		{
47 			if (auto oldObservers = (*observerDim) in dimObservers)
48 			{
49 				oldObservers.remove(sessionId);
50 			}
51 			observerDimensions.remove(sessionId);
52 		}
53 	}
54 
55 	// can use result in foreach
56 	auto getDimensionObservers(DimensionId dimensionId) {
57 		return dimObservers.get(dimensionId);
58 	}
59 }