@@ -418,26 +418,16 @@ private static LockData readLockData(Block block) {
418418 for (Block containerBlock : getLinkedContainerBlocks (block )) {
419419 BlockState blockState = containerBlock .getState ();
420420 if (!(blockState instanceof Container container )) continue ;
421- PersistentDataContainer pdc = container .getPersistentDataContainer ();
422-
423- boolean hasLockedKey = pdc .has (lockedKey (), PersistentDataType .BYTE );
424- if (hasLockedKey ) {
421+ LockData partial = readLockDataFromPdc (container .getPersistentDataContainer ());
422+ if (partial .hasPdcData ()) {
425423 hasPdc = true ;
426- Byte lockedByte = pdc .get (lockedKey (), PersistentDataType .BYTE );
427- if (lockedByte != null && lockedByte != 0 ) {
428- locked = true ;
429- }
430424 }
431-
432- for (NamespacedKey key : pdc .getKeys ()) {
433- if (!isPermissionKey (key )) continue ;
434- hasPdc = true ;
435- String subject = decodeSubject (key .getKey ().substring (PERMISSION_KEY_PATH_PREFIX .length ()));
436- if (subject == null || subject .isBlank ()) continue ;
437-
438- String token = pdc .get (key , PersistentDataType .STRING );
439- PermissionAccess access = PermissionAccess .parseToken (token );
440- if (access == null || access == PermissionAccess .NONE ) continue ;
425+ if (partial .isLocked ()) {
426+ locked = true ;
427+ }
428+ for (Map .Entry <String , PermissionAccess > entry : partial .permissions ().entrySet ()) {
429+ String subject = entry .getKey ();
430+ PermissionAccess access = entry .getValue ();
441431 PermissionAccess old = permissions .get (subject );
442432 if (old == null || access .power > old .power ) {
443433 permissions .put (subject , access );
@@ -448,6 +438,38 @@ private static LockData readLockData(Block block) {
448438 return new LockData (hasPdc , locked , permissions );
449439 }
450440
441+ private static LockData readLockDataFromPdc (PersistentDataContainer pdc ) {
442+ boolean hasPdc = false ;
443+ boolean locked = false ;
444+ LinkedHashMap <String , PermissionAccess > permissions = new LinkedHashMap <>();
445+
446+ boolean hasLockedKey = pdc .has (lockedKey (), PersistentDataType .BYTE );
447+ if (hasLockedKey ) {
448+ hasPdc = true ;
449+ Byte lockedByte = pdc .get (lockedKey (), PersistentDataType .BYTE );
450+ if (lockedByte != null && lockedByte != 0 ) {
451+ locked = true ;
452+ }
453+ }
454+
455+ for (NamespacedKey key : pdc .getKeys ()) {
456+ if (!isPermissionKey (key )) continue ;
457+ hasPdc = true ;
458+ String subject = decodeSubject (key .getKey ().substring (PERMISSION_KEY_PATH_PREFIX .length ()));
459+ if (subject == null || subject .isBlank ()) continue ;
460+
461+ String token = pdc .get (key , PersistentDataType .STRING );
462+ PermissionAccess access = PermissionAccess .parseToken (token );
463+ if (access == null || access == PermissionAccess .NONE ) continue ;
464+ PermissionAccess old = permissions .get (subject );
465+ if (old == null || access .power > old .power ) {
466+ permissions .put (subject , access );
467+ }
468+ }
469+
470+ return new LockData (hasPdc , locked , permissions );
471+ }
472+
451473 private static boolean isPermissionKey (NamespacedKey key ) {
452474 if (!Objects .equals (key .getNamespace (), LOCKETTE_NAMESPACE )) return false ;
453475 return key .getKey ().startsWith (PERMISSION_KEY_PATH_PREFIX );
@@ -548,6 +570,68 @@ public static boolean refreshLockedContainerTag(Block block) {
548570 return true ;
549571 }
550572
573+ /**
574+ * Lightweight path for chunk-scan maintenance. Operates on the provided tile state
575+ * and only writes when the locked_container tag value actually changes.
576+ */
577+ public static boolean refreshLockedContainerTag (BlockState blockState ) {
578+ return refreshLockedContainerTag (blockState , null );
579+ }
580+
581+ /**
582+ * Lightweight path for chunk-scan maintenance with optional linked state (double chest pair).
583+ */
584+ public static boolean refreshLockedContainerTag (BlockState blockState , BlockState linkedState ) {
585+ if (!(blockState instanceof Container container )) return false ;
586+ PersistentDataContainer pdc = container .getPersistentDataContainer ();
587+ LockData data = readLockDataFromPdc (pdc );
588+ LockData linkedData = null ;
589+ Container linkedContainer = null ;
590+ PersistentDataContainer linkedPdc = null ;
591+
592+ if (linkedState instanceof Container containerState ) {
593+ linkedContainer = containerState ;
594+ linkedPdc = linkedContainer .getPersistentDataContainer ();
595+ linkedData = readLockDataFromPdc (linkedPdc );
596+ }
597+
598+ if (linkedData != null && linkedData .hasPdcData ()) {
599+ boolean mergedLocked = data .isLocked () || linkedData .isLocked ();
600+ LinkedHashMap <String , PermissionAccess > mergedPermissions = new LinkedHashMap <>(data .permissions ());
601+ for (Map .Entry <String , PermissionAccess > entry : linkedData .permissions ().entrySet ()) {
602+ PermissionAccess existing = mergedPermissions .get (entry .getKey ());
603+ if (existing == null || entry .getValue ().power > existing .power ) {
604+ mergedPermissions .put (entry .getKey (), entry .getValue ());
605+ }
606+ }
607+ data = new LockData (true , mergedLocked , mergedPermissions );
608+ }
609+
610+ if (!data .hasPdcData ()) return false ;
611+
612+ boolean shouldHaveTag = data .isLocked () && shouldSetLockedContainerTag (data .permissions );
613+ NamespacedKey key = lockedContainerKey ();
614+ applyLockedContainerTag (container , pdc , key , shouldHaveTag );
615+ if (linkedContainer != null && linkedPdc != null ) {
616+ applyLockedContainerTag (linkedContainer , linkedPdc , key , shouldHaveTag );
617+ }
618+ return true ;
619+ }
620+
621+ private static boolean applyLockedContainerTag (Container container , PersistentDataContainer pdc , NamespacedKey key , boolean shouldHaveTag ) {
622+ boolean hasTag = pdc .has (key , PersistentDataType .BYTE );
623+ if (hasTag == shouldHaveTag ) {
624+ return false ;
625+ }
626+ if (shouldHaveTag ) {
627+ pdc .set (key , PersistentDataType .BYTE , (byte ) 1 );
628+ } else {
629+ pdc .remove (key );
630+ }
631+ container .update (true , false );
632+ return true ;
633+ }
634+
551635 private static boolean shouldSetLockedContainerTag (Map <String , PermissionAccess > permissions ) {
552636 if (permissions == null || permissions .isEmpty ()) return false ;
553637 return !isOpenToEveryone (permissions ) && !hasBypassTag (permissions );
0 commit comments