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 
7 module voxelman.entity.entityobservermanager;
8 
9 import voxelman.log;
10 import datadriven.api;
11 import datadriven.entityman;
12 import voxelman.container.hash.map;
13 import voxelman.container.hash.set;
14 import voxelman.world.storage;
15 import voxelman.entity.plugin;
16 import voxelman.net.plugin;
17 
18 struct EntityObserverManager
19 {
20 	HashMap!(ChunkWorldPos, HashSet!EntityId) chunkToEntitySet;
21 	//HashSet!ChunkWorldPos observedEntityChunks;
22 	HashMap!(EntityId, ChunkWorldPos) entityToChunk;
23 
24 	void addEntity(EntityId eid, ChunkWorldPos cwp)
25 	{
26 		entityToChunk[eid] = cwp;
27 		addEntityToChunk(eid, cwp);
28 	}
29 
30 	void updateEntityPos(EntityId eid, ChunkWorldPos newCwp)
31 	{
32 		bool wasCreated;
33 		ChunkWorldPos* cwp = entityToChunk.getOrCreate(eid, wasCreated, newCwp);
34 		if (wasCreated)
35 		{
36 			addEntityToChunk(eid, newCwp);
37 		}
38 		else if (*cwp != newCwp)
39 		{
40 			removeEntityFromChunk(eid, *cwp);
41 			addEntityToChunk(eid, newCwp);
42 			*cwp = newCwp;
43 		}
44 	}
45 
46 	void removeEntity(EntityId eid)
47 	{
48 		if (auto cwp = eid in entityToChunk)
49 		{
50 			removeEntityFromChunk(eid, *cwp);
51 			entityToChunk.remove(eid);
52 		}
53 	}
54 
55 	private void addEntityToChunk(EntityId eid, ChunkWorldPos cwp)
56 	{
57 		auto entitySetPtr = chunkToEntitySet.getOrCreate(cwp);
58 		entitySetPtr.put(eid);
59 		//observedEntityChunks.put(cwp);
60 	}
61 
62 	private void removeEntityFromChunk(EntityId eid, ChunkWorldPos cwp)
63 	{
64 		if (auto set = cwp in chunkToEntitySet)
65 		{
66 			set.remove(eid);
67 			if (set.empty)
68 			{
69 				chunkToEntitySet.remove(cwp);
70 				//observedEntityChunks.remove(cwp);
71 			}
72 		}
73 	}
74 
75 	package NetworkSaver netSaver;
76 	package ChunkObserverManager chunkObserverManager;
77 	package NetServerPlugin connection;
78 	package EntityManager* eman;
79 
80 	void sendEntitiesToObservers()
81 	{
82 		connection.sendToAll(ComponentSyncStartPacket());
83 		foreach(cwp, entities; chunkToEntitySet)
84 		{
85 			auto observers = chunkObserverManager.getChunkObservers(cwp);
86 			if (observers.length == 0) continue;
87 
88 			eman.savePartial(netSaver, entities);
89 			connection.sendTo(observers, ComponentSyncPacket(netSaver.data));
90 			netSaver.reset();
91 		}
92 		connection.sendToAll(ComponentSyncEndPacket());
93 	}
94 }