@@ -82,6 +82,7 @@ private record SerialNode(long id, BlockNode node) {
8282 private final Short2ObjectMap <LongSet > graphsInPos = new Short2ObjectLinkedOpenHashMap <>();
8383 private final LongSet graphsInChunk = new LongLinkedOpenHashSet ();
8484 private final Short2ObjectMap <Object2LongMap <BlockNode >> blockNodes = new Short2ObjectLinkedOpenHashMap <>();
85+ private boolean blockNodesPopulated ;
8586
8687 private SimpleBlockGraphChunk (@ NotNull SimpleServerGraphWorld world , @ NotNull SectionPos chunkPos ,
8788 @ NotNull Runnable markDirty , @ NotNull Serial serial ) {
@@ -93,7 +94,6 @@ private SimpleBlockGraphChunk(@NotNull SimpleServerGraphWorld world, @NotNull Se
9394 for (SerialInPos serialInPos : serial .inPos ()) {
9495 BlockPos pos = serialInPos .pos ();
9596 short shortPos = SectionPos .sectionRelativePos (pos );
96- BlockPos keyPos = pos .offset (chunkPos .minBlockX (), chunkPos .minBlockY (), chunkPos .minBlockZ ());
9797
9898 LongSet inPos = graphsInPos .computeIfAbsent (shortPos , pos1 -> new LongLinkedOpenHashSet ());
9999 Object2LongMap <BlockNode > nodes =
@@ -105,24 +105,14 @@ private SimpleBlockGraphChunk(@NotNull SimpleServerGraphWorld world, @NotNull Se
105105 inPos .add (serialNode .id ());
106106 nodes .put (serialNode .node (), serialNode .id ());
107107 }
108+ blockNodesPopulated = true ;
108109 });
109110
110111 // Legacy route
111112 serialInPos .either ().ifRight (longs -> {
112113 inPos .addAll (longs );
113114
114- // build missing node->graphId map
115- for (LongIterator it = longs .iterator (); it .hasNext (); ) {
116- long graphId = it .nextLong ();
117-
118- SimpleBlockGraph graph = world .getGraph (graphId );
119- if (graph != null ) {
120- for (var iter = graph .getNodesAt (keyPos ).iterator (); iter .hasNext (); ) {
121- var holder = iter .next ();
122- nodes .put (holder .getNode (), graphId );
123- }
124- }
125- }
115+ blockNodesPopulated = false ;
126116 });
127117 }
128118 }
@@ -135,18 +125,29 @@ public SimpleBlockGraphChunk(@NotNull SectionPos chunkPos, @NotNull Runnable mar
135125 private @ NotNull Serial toSerial () {
136126 List <SerialInPos > inPosList = new ObjectArrayList <>();
137127
138- for (ShortIterator keyIter = blockNodes .keySet ().iterator (); keyIter .hasNext (); ) {
139- short shortPos = keyIter .nextShort ();
140- BlockPos localPos =
141- new BlockPos (SectionPos .sectionRelativeX (shortPos ), SectionPos .sectionRelativeY (shortPos ),
142- SectionPos .sectionRelativeZ (shortPos ));
128+ if (blockNodesPopulated ) {
129+ for (ShortIterator keyIter = blockNodes .keySet ().iterator (); keyIter .hasNext (); ) {
130+ short shortPos = keyIter .nextShort ();
131+ BlockPos localPos =
132+ new BlockPos (SectionPos .sectionRelativeX (shortPos ), SectionPos .sectionRelativeY (shortPos ),
133+ SectionPos .sectionRelativeZ (shortPos ));
143134
144- List <SerialNode > serialNodes = new ObjectArrayList <>();
145- for (Object2LongMap .Entry <BlockNode > nodeEntry : blockNodes .get (shortPos ).object2LongEntrySet ()) {
146- serialNodes .add (new SerialNode (nodeEntry .getLongValue (), nodeEntry .getKey ()));
147- }
135+ List <SerialNode > serialNodes = new ObjectArrayList <>();
136+ for (Object2LongMap .Entry <BlockNode > nodeEntry : blockNodes .get (shortPos ).object2LongEntrySet ()) {
137+ serialNodes .add (new SerialNode (nodeEntry .getLongValue (), nodeEntry .getKey ()));
138+ }
148139
149- inPosList .add (new SerialInPos (localPos , Either .left (serialNodes )));
140+ inPosList .add (new SerialInPos (localPos , Either .left (serialNodes )));
141+ }
142+ } else {
143+ for (ShortIterator keyIter = graphsInPos .keySet ().iterator (); keyIter .hasNext (); ) {
144+ short shortPos = keyIter .nextShort ();
145+ BlockPos localPos =
146+ new BlockPos (SectionPos .sectionRelativeX (shortPos ), SectionPos .sectionRelativeY (shortPos ),
147+ SectionPos .sectionRelativeZ (shortPos ));
148+
149+ inPosList .add (new SerialInPos (localPos , Either .right (graphsInPos .get (shortPos ))));
150+ }
150151 }
151152
152153 return new Serial (graphsInChunk , inPosList );
@@ -158,6 +159,33 @@ public void clear() {
158159 blockNodes .clear ();
159160 }
160161
162+ public void ensureBlockNodesPopulated (@ NotNull Long2ObjectFunction <SimpleBlockGraph > graphGetter ) {
163+ if (blockNodesPopulated ) return ;
164+
165+ // build missing node->graphId map
166+ for (LongIterator it = graphsInChunk .iterator (); it .hasNext (); ) {
167+ long graphId = it .nextLong ();
168+
169+ SimpleBlockGraph graph = graphGetter .get (graphId );
170+ if (graph != null ) {
171+ for (var iter = graph .getNodes ().iterator (); iter .hasNext (); ) {
172+ var holder = iter .next ();
173+
174+ BlockPos keyPos = holder .getBlockPos ();
175+ if (chunkPos .minBlockX () <= keyPos .getX () && keyPos .getX () <= chunkPos .maxBlockX () &&
176+ chunkPos .minBlockY () <= keyPos .getY () && keyPos .getY () <= chunkPos .maxBlockY () &&
177+ chunkPos .minBlockZ () <= keyPos .getZ () && keyPos .getZ () <= chunkPos .maxBlockZ ()) {
178+
179+ blockNodes .computeIfAbsent (SectionPos .sectionRelativePos (keyPos ),
180+ pos1 -> new Object2LongLinkedOpenHashMap <>()).put (holder .getNode (), graphId );
181+ }
182+ }
183+ }
184+ }
185+
186+ blockNodesPopulated = true ;
187+ }
188+
161189 public void putGraphWithNode (long id , @ NotNull NodePos key ) {
162190 markDirty .run ();
163191
@@ -198,14 +226,16 @@ public void removeGraph(long id) {
198226 }
199227
200228 public @ Nullable SimpleBlockGraph getGraphForNode (NodePos key , Long2ObjectFunction <SimpleBlockGraph > graphGetter ) {
229+ ensureBlockNodesPopulated (graphGetter );
201230 Object2LongMap <BlockNode > uNodes = blockNodes .get (SectionPos .sectionRelativePos (key .pos ()));
202231 if (uNodes == null ) return null ;
203232 if (!uNodes .containsKey (key .node ())) return null ;
204233
205234 return graphGetter .get (uNodes .getLong (key .node ()));
206235 }
207236
208- public boolean containsNode (NodePos key ) {
237+ public boolean containsNode (NodePos key , Long2ObjectFunction <SimpleBlockGraph > graphGetter ) {
238+ ensureBlockNodesPopulated (graphGetter );
209239 Object2LongMap <BlockNode > uNodes = blockNodes .get (SectionPos .sectionRelativePos (key .pos ()));
210240 if (uNodes == null ) return false ;
211241 return uNodes .containsKey (key .node ());
0 commit comments