스마트 줍기 및 인벤토리 분배 (MC 26.1.2)
이 문서는 Minecraft 26.1.2 버전의 Item Clumps에 대한 분할 반복 인벤토리 흡수, 용량 시뮬레이션, 바닐라 스택 생성 및 NBT 무오염 아키텍처에 대해 다룹니다.
📊 기능 정보 상자
| 속성 | 세부 정보 |
|---|---|
| 시스템 이름 | 분할 인벤토리 분배기 |
| 대상 클래스 | net.minecraft.world.entity.item.ItemEntity |
| 인벤토리 제한 | 바닐라 기준 완벽 준수 (일반 아이템: $64$, 진주/달걀: $16$) |
| 데이터 순수성 | $100%$ 순수 바닐라 ItemStack (NBT 또는 태그 오염 제로) |
| 줍기 루프 | 분할 반복 (Math.min(count, maxStack)) |
| 통계 추적 | 바닐라 Stats.ITEM_PICKED_UP.get(item) 정상 작동 |
🎒 분할 줍기 루프 아키텍처
Minecraft 26.1.2에서 Item Clumps는 분할 while 루프를 사용하여 대량의 아이템을 안전한 바닐라 크기 스택(예: 한 번에 64개)으로 나누어 플레이어 인벤토리에 지급합니다:
┌──────────────────────────────────────────────┐
│ Player Collides with Ground Clump (e.g. 500x)│
└──────────────────────┬───────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Pickup Validity & Target Check │
│ - pickupDelay == 0? │
│ - target == null || target == player? │
└──────────────────────┬───────────────────────┘
│ (Pass)
▼
┌──────────────────────────────────────────────┐
│ Iterative Chunked Loop │
│ toTake = Math.min(count, maxStackSize) │
│ player.getInventory().add(chunk) │
└──────────────────────┬───────────────────────┘
│
┌─────────────────┴─────────────────┐
│ │
Inventory Has Space Inventory Becomes Full
│ │
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────┐
│ Entire Clump Absorbed │ │ Partial Pickup │
│ - 500 items transferred │ │ - Transferred what fits │
│ - Clump entity removed │ │ - Remaining items stay │
│ - Sound & particles play│ │ in ground clump │
└─────────────────────────┘ └─────────────────────────┘💻 실제 Java 소스 코드 구현
Minecraft 26.1.2의 ItemEntityMixin.java 출처:
java
@Inject(method = "playerTouch", at = @At("HEAD"), cancellable = true)
private void item_clumps$smartPickup(Player player, CallbackInfo ci) {
if (!DynamicGameRuleManager.getBoolean(this.level(), ItemClumpsFabric.ENABLE_CLUMPING) ||
this.level().isClientSide()) return;
int count = this.getItem().getCount();
if (count <= 1) return; // Allow vanilla to handle normal 1-count items
ItemStack baseItem = this.getItem().copy();
baseItem.setCount(1); // Ensure base count is 1 for simulation
if (this.pickupDelay == 0 && (this.target == null || this.target.equals(player.getUUID()))) {
int originalCount = count;
int maxStack = baseItem.getMaxStackSize();
while (count > 0) {
int toTake = Math.min(count, maxStack);
ItemStack chunk = baseItem.copy();
chunk.setCount(toTake);
player.getInventory().add(chunk);
int added = toTake - chunk.getCount();
if (added > 0) {
count -= added;
player.take(this, added);
player.awardStat(net.minecraft.stats.Stats.ITEM_PICKED_UP.get(baseItem.getItem()), added);
}
if (!chunk.isEmpty()) {
// Player inventory is full
break;
}
}
if (count != originalCount) {
ItemStack stack = this.getItem();
stack.setCount(count);
this.setItem(stack);
if (count <= 0) {
player.onItemPickup((ItemEntity) (Object) this);
}
}
ci.cancel(); // Prevent vanilla pickup interference
}
}