@@ -60,6 +60,8 @@ private void load()
6060 entry .ensureBounds ();
6161 }
6262 this .entries = read ;
63+ if (dedupeLoadedEntries ())
64+ save ();
6365 }
6466 }
6567 }catch (Exception e )
@@ -122,7 +124,7 @@ public synchronized void upsert(ChestEntry entry)
122124 entries .remove (e );
123125 entry .touch ();
124126 entries .add (entry );
125- save ( );
127+ finalizeInsert ( entry );
126128 System .out .println (
127129 "[ChestDatabase] merged entry by contents; preserved primary="
128130 + entry .x + "," + entry .y + "," + entry .z );
@@ -148,7 +150,7 @@ public synchronized void upsert(ChestEntry entry)
148150 entry .touch ();
149151 it .remove ();
150152 entries .add (entry );
151- save ( );
153+ finalizeInsert ( entry );
152154 System .out .println ("[ChestDatabase] updated entry at bounds "
153155 + entry .getMinPos () + " -> " + entry .getMaxPos ()
154156 + " facing=" + entry .facing + " (preserved primary="
@@ -158,7 +160,7 @@ public synchronized void upsert(ChestEntry entry)
158160 }
159161 entry .touch ();
160162 entries .add (entry );
161- save ( );
163+ finalizeInsert ( entry );
162164 System .out .println (
163165 "[ChestDatabase] added entry at bounds " + entry .getMinPos ()
164166 + " -> " + entry .getMaxPos () + " facing=" + entry .facing );
@@ -208,7 +210,7 @@ private boolean equalsPos(ChestEntry a, ChestEntry b)
208210 {
209211 if (a == null || b == null )
210212 return false ;
211- // Compare canonical bounds (min/max) and facing
213+ // Compare canonical bounds (min/max)
212214 int aMinX = Math .min (a .x , a .maxX );
213215 int aMinY = Math .min (a .y , a .maxY );
214216 int aMinZ = Math .min (a .z , a .maxZ );
@@ -227,11 +229,78 @@ private boolean equalsPos(ChestEntry a, ChestEntry b)
227229 && aMaxX == bMaxX && aMaxY == bMaxY && aMaxZ == bMaxZ ;
228230 if (!boundsEqual )
229231 return false ;
230- if (a .facing == null && b .facing == null )
231- return true ;
232- if (a .facing == null || b .facing == null )
232+ return true ;
233+ }
234+
235+ private void finalizeInsert (ChestEntry entry )
236+ {
237+ boolean removed = removeOverlappingDuplicates (entry );
238+ if (removed )
239+ System .out .println (
240+ "[ChestDatabase] cleaned overlapping duplicates after insert." );
241+ save ();
242+ }
243+
244+ private boolean removeOverlappingDuplicates (ChestEntry reference )
245+ {
246+ String refKey = contentsKey (reference );
247+ if (refKey == null )
233248 return false ;
234- return a .facing .equals (b .facing );
249+ int refMinX = Math .min (reference .x , reference .maxX );
250+ int refMinY = Math .min (reference .y , reference .maxY );
251+ int refMinZ = Math .min (reference .z , reference .maxZ );
252+ int refMaxX = Math .max (reference .x , reference .maxX );
253+ int refMaxY = Math .max (reference .y , reference .maxY );
254+ int refMaxZ = Math .max (reference .z , reference .maxZ );
255+ boolean removed = false ;
256+ java .util .Iterator <ChestEntry > it = entries .iterator ();
257+ while (it .hasNext ())
258+ {
259+ ChestEntry other = it .next ();
260+ if (other == reference )
261+ continue ;
262+ if (!equalsServerDim (other , reference ))
263+ continue ;
264+ String otherKey = contentsKey (other );
265+ if (otherKey == null || !refKey .equals (otherKey ))
266+ continue ;
267+ int otherMinX = Math .min (other .x , other .maxX );
268+ int otherMinY = Math .min (other .y , other .maxY );
269+ int otherMinZ = Math .min (other .z , other .maxZ );
270+ int otherMaxX = Math .max (other .x , other .maxX );
271+ int otherMaxY = Math .max (other .y , other .maxY );
272+ int otherMaxZ = Math .max (other .z , other .maxZ );
273+ boolean overlap = refMinX <= otherMaxX && refMaxX >= otherMinX
274+ && refMinY <= otherMaxY && refMaxY >= otherMinY
275+ && refMinZ <= otherMaxZ && refMaxZ >= otherMinZ ;
276+ if (!overlap )
277+ continue ;
278+ it .remove ();
279+ System .out
280+ .println ("[ChestDatabase] removed overlapping duplicate at "
281+ + other .getMinPos () + " -> " + other .getMaxPos ());
282+ removed = true ;
283+ }
284+ return removed ;
285+ }
286+
287+ private boolean dedupeLoadedEntries ()
288+ {
289+ if (entries == null || entries .isEmpty ())
290+ return false ;
291+ java .util .List <ChestEntry > copy = new ArrayList <>(entries );
292+ entries = new ArrayList <>();
293+ boolean removedAny = false ;
294+ for (ChestEntry entry : copy )
295+ {
296+ if (entry == null )
297+ continue ;
298+ entry .ensureBounds ();
299+ entries .add (entry );
300+ if (removeOverlappingDuplicates (entry ))
301+ removedAny = true ;
302+ }
303+ return removedAny ;
235304 }
236305
237306 private boolean equalsServerDim (ChestEntry a , ChestEntry b )
0 commit comments