Skip to content

Mécaniques d'Agrégation en Méga-Piles (MC 26.1.2)

Ce document fournit une analyse technique et mathématique de l'agrégation d'items au sol, du calcul du rayon de recherche et de la fusion d'entités dans Item Clumps pour Minecraft 26.1.2.


📊 Fiche Technique de Fonctionnalité

PropriétéSpécification
Nom du SystèmeAgrégateur de Méga-Piles d'Items au Sol
Classe Ciblenet.minecraft.world.entity.item.ItemEntity
Plafond par Défaut9 999 items (Configurable jusqu'à $2,147,483,647$)
Rayon de Recherche ($r$)Horizontal $1\text{ à }10\text{ blocs}$ (Défaut : $1\text{ bloc}$)
Injection du Rayon@ModifyArgs sur AABB.inflate(DDD)
GameRules de Contrôleitem_clumps:enable_clumping, item_clumps:max_clump_size, item_clumps:merge_radius

⚙️ Fonctionnement de l'Agrégation en Méga-Piles

Dans Minecraft Vanilla, les items au sol appellent mergeWithNeighbours() à chaque tick. Vanilla interdit toutefois la fusion si le total dépasse itemStack.getMaxStackSize() (généralement 64).

Item Clumps intercepte cette vérification via ItemEntityMixin.java pour lever cette restriction en préservant l'intégrité des composants de données.

                  ┌──────────────────────────────┐
                  │    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.│
       └───────────────────┘           └───────────────────┘

📐 Formules Mathématiques & Calculs de Précision

1. Élargissement Horizontal de la Boîte Englobante (@ModifyArgs)

$$\text{args.set}(0, r), \quad \text{args.set}(2, r)$$

Où :

  • $r = \text{DynamicGameRuleManager}.\text{getInt}(\text{level}, \text{MERGE_RADIUS}) \in [1, 10]$ blocs.
  • L'indice vertical ($1$) n'est pas modifié, préservant la séparation physique entre les étages.

2. Calcul du Transfert de Quantité d'Items

  • Absorption Complète ($S \le \text{maxClumpSize}$) : $$\text{count}_{\text{merged}} = \text{thisCount} + \text{otherCount}$$
  • Absorption Partielle ($S > \text{maxClumpSize}$) : $$\Delta = \text{maxClumpSize} - \text{thisCount}$$ $$\text{thisCount}' = \text{maxClumpSize}, \quad \text{otherCount}' = \text{otherCount} - \Delta$$

💻 Implémentation du Code Source Java Réel

Depuis ItemEntityMixin.java dans Minecraft 26.1.2 :

java
@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();
}

🔗 Documentation Associée (MC 26.1.2)

Official documentation & web portal for Dasik Igaijinn mods.