-
Notifications
You must be signed in to change notification settings - Fork 0
26.1.2 Clumping Mechanics and Mega Stacks
This document provides a technical and mathematical breakdown of ground item aggregation, search radius math, and entity merging in Item Clumps for Minecraft 26.1.2.
| Property | Specification |
|---|---|
| System Name | Ground Item Mega-Stack Aggregator |
| Target Class | net.minecraft.world.entity.item.ItemEntity |
| Default Merge Cap |
9,999 items (Configurable up to |
| Search Radius ( |
Horizontal |
| Radius Injection |
@ModifyArgs on AABB.inflate(DDD)
|
| Controlling GameRules |
item_clumps:enable_clumping, item_clumps:max_clump_size, item_clumps:merge_radius
|
In vanilla Minecraft, dropped items call mergeWithNeighbours() during their tick cycle, searching for nearby items of the same type. However, vanilla strictly prohibits merging if the target entity's item count would exceed itemStack.getMaxStackSize() (typically 64).
Item Clumps intercepts this check via ItemEntityMixin.java to lift this constraint while preserving strict data component safety.
┌──────────────────────────────┐
│ ItemEntity A Ticks In │
└──────────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ Feasibility Check │
│ - Matching player target? │
│ - Identical DataComponents? │
└──────────────┬───────────────┘
│ (Pass)
▼
┌──────────────────────────────┐
│ Combine Stacks Math Check │
└──────────────┬───────────────┘
│
┌───────────────┴───────────────┐
│ │
thisCount + otherCount <= maxClump thisCount + otherCount > maxClump
│ │
▼ ▼
┌───────────────────┐ ┌───────────────────┐
│ Complete Merge │ │ Partial Merge │
│ Larger absorbs │ │ Fill entity A to │
│ smaller entity; │ │ maxClumpSize; │
│ Younger age kept. │ │ B keeps remainder.│
└───────────────────┘ └───────────────────┘
Where:
-
$r = \text{DynamicGameRuleManager}.\text{getInt}(\text{level}, \text{MERGE_RADIUS}) \in [1, 10]$ blocks. - Vertical height index (
$1$ ) is untouched, preserving vertical separation between different floor levels.
-
Full Absorption (
$S \le \text{maxClumpSize}$ ):$$\text{count}_{\text{merged}} = \text{thisCount} + \text{otherCount}$$ -
Partial Absorption (
$S > \text{maxClumpSize}$ ):$$\Delta = \text{maxClumpSize} - \text{thisCount}$$ $$\text{thisCount}' = \text{maxClumpSize}, \quad \text{otherCount}' = \text{otherCount} - \Delta$$
From ItemEntityMixin.java in Minecraft 26.1.2:
@ModifyArgs(method = "mergeWithNeighbours", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/AABB;inflate(DDD)Lnet/minecraft/world/phys/AABB;"))
private void item_clumps$modifySearchRadius(Args args) {
if (DynamicGameRuleManager.getBoolean(this.level(), ItemClumpsFabric.ENABLE_CLUMPING)) {
double radius = DynamicGameRuleManager.getInt(this.level(), ItemClumpsFabric.MERGE_RADIUS);
args.set(0, radius);
args.set(2, radius);
}
}
@Inject(method = "tryToMerge", at = @At("HEAD"), cancellable = true)
private void item_clumps$customMerge(ItemEntity other, CallbackInfo ci) {
if (!DynamicGameRuleManager.getBoolean(this.level(), ItemClumpsFabric.ENABLE_CLUMPING)) return;
ItemStack thisStack = this.getItem();
ItemStack otherStack = other.getItem();
if (!Objects.equals(this.target, ((ItemEntityMixin)(Object)other).target) ||
!ItemStack.isSameItemSameComponents(thisStack, otherStack)) {
return;
}
int thisCount = thisStack.getCount();
int otherCount = otherStack.getCount();
int maxClump = DynamicGameRuleManager.getInt(this.level(), ItemClumpsFabric.MAX_CLUMP_SIZE);
if (thisCount + otherCount > maxClump) {
int spaceLeft = maxClump - thisCount;
if (spaceLeft > 0) {
thisStack.setCount(maxClump);
this.setItem(thisStack);
otherStack.setCount(otherCount - spaceLeft);
other.setItem(otherStack);
}
ci.cancel();
return;
}
// Full Merge: larger stack absorbs the smaller stack
if (otherCount < thisCount) {
thisStack.setCount(thisCount + otherCount);
this.setItem(thisStack);
this.pickupDelay = Math.max(this.pickupDelay, ((ItemEntityMixin)(Object)other).pickupDelay);
this.age = Math.min(this.age, ((ItemEntityMixin)(Object)other).age);
other.discard();
} else {
otherStack.setCount(thisCount + otherCount);
other.setItem(otherStack);
((ItemEntityMixin)(Object)other).pickupDelay = Math.max(((ItemEntityMixin)(Object)other).pickupDelay, this.pickupDelay);
((ItemEntityMixin)(Object)other).age = Math.min(((ItemEntityMixin)(Object)other).age, this.age);
this.discard();
}
ci.cancel();
}Item Clumps is engineered with ❤️ by Dasik (Rifaditya) | Licensed under GNU General Public License v3.0 (GPL-3.0-or-later).
📌 Repository Source Disclaimer: The documentation in this Wiki reflects the current source code state in the repository, which may include recent unreleased commits or developmental features ahead of public release builds on CurseForge and Modrinth.
- 26.2 Hub
- 26.2 Mega-Stack Clumping
- 26.2 Smart Pickup System
- 26.2 Hopper Integration
- 26.2 Despawn Age Rules
- 26.2 Holographic Labels
- 26.2 Mod Compatibility
- 26.2 GameRules Table
- 26.2 Commands & Admin
- 26.2 Advancements
- 26.2 Configuration
- 26.2 ModVersionGuard
- 26.2 Architecture & Mixins
- 26.2 Developer Setup
- 26.2 API & Addons
- 26.2 FAQ & Diagnostics
- 26.1.2 Hub
- 26.1.2 Mega-Stack Clumping
- 26.1.2 Smart Pickup System
- 26.1.2 Hopper Integration
- 26.1.2 Despawn Age Rules
- 26.1.2 Holographic Labels
- 26.1.2 GameRules Table
- 26.1.2 Commands & Admin
- 26.1.2 Advancements
- 26.1.2 Configuration
- 26.1.2 Architecture & Mixins
- 26.1.2 Developer Setup
- 26.1.2 API & Addons
- 26.1.2 FAQ & Diagnostics