Skip to content

Mega-Stapel-Aggregationsmechanik (MC 26.2)

Dieses Dokument liefert eine umfassende technische und mathematische Aufschlüsselung der Item-Aggregation, Suchradiusberechnung, 64-Bit-Überlaufsicherung und Speicheroptimierungen in Item Clumps für Minecraft 26.2.


📊 Feature-Infobox

EigenschaftSpezifikation
SystemnameMega-Stapel-Aggregator für Boden-Items
Zielklassenet.minecraft.world.entity.item.ItemEntity
Standard-Verschmelzungslimit9.999 Items (Konfigurierbar bis $2.147.483.647$)
Suchradius ($r$)Horizontal $1\text{ bis }10\text{ Blöcke}$ (Standard: $1\text{ Block}$)
Tick-Overhead$0.00\text{ ms}$ bei ruhenden Items (Aufruf nur bei setItem())
SpeicherallokationNull Objektallokationen bei Suche & Aufnahme (copyWithCount(int))
Steuernde GameRulesitem_clumps:enable_clumping, item_clumps:max_clump_size, item_clumps:merge_radius

⚙️ Funktionsweise der Mega-Stapel-Aggregation

In Vanilla Minecraft rufen gedroppte Items während ihres Ticks mergeWithNeighbours() auf, um nach gleichartigen Items in der Nähe zu suchen. Vanilla verbietet das Verschmelzen jedoch strikt, wenn die Anzahl itemStack.getMaxStackSize() überschreiten würde (üblicherweise 64, bzw. 16 bei Enderperlen/Eiern).

Item Clumps fängt diese Prüfung über ItemEntityMixin.java ab, um diese künstliche Einschränkung aufzuheben, während die Datenkomponentensicherheit strikt gewahrt bleibt.

                  ┌──────────────────────────────┐
                  │    ItemEntity A Ticks In     │
                  └──────────────┬───────────────┘


                  ┌──────────────────────────────┐
                  │     Fast-Path Validation     │
                  │  - Matching player target?   │
                  │  - Identical DataComponents? │
                  └──────────────┬───────────────┘
                                 │ (Pass)

                  ┌──────────────────────────────┐
                  │   In-Flight Magnet Check     │
                  │ (Is either item magnetized?) │
                  └──────────────┬───────────────┘
                                 │ (No)

                  ┌──────────────────────────────┐
                  │    64-Bit Arithmetic Sum     │
                  │   S = (long) A + (long) B    │
                  └──────────────┬───────────────┘

                 ┌───────────────┴───────────────┐
                 │                               │
        S <= maxClumpSize                S > maxClumpSize
                 │                               │
                 ▼                               ▼
       ┌───────────────────┐           ┌───────────────────┐
       │   Complete Merge  │           │   Partial Merge   │
       │ Larger absorbs    │           │ Fill entity A to  │
       │ smaller entity;   │           │ maxClumpSize;     │
       │ Younger age kept. │           │ B keeps remainder.│
       └───────────────────┘           └───────────────────┘

📐 Mathematische Formeln & Präzisionsberechnungen

1. Horizontale Bounding-Box-Vergrößerung

Vanilla durchsucht eine winzige Bounding-Box: $\text{AABB}_{\text{vanilla}} = \text{AABB}.\text{inflate}(0.5, 0.0, 0.5)$.

Item Clumps erweitert die horizontale Bounding-Box dynamisch über eine speicherfreie @Redirect-Injektion:

$$\text{AABB}_{\text{clump}} = \text{boundingBox}.\text{inflate}(r, y, r)$$

Wobei:

  • $r = \text{DynamicGameRuleManager}.\text{getInt}(\text{level}, \text{MERGE_RADIUS}) \in [1, 10]$ Blöcke.
  • $y = 0.0$ (vertikale Suchhöhe bleibt strikt unberührt, damit Items auf verschiedenen Etagen oder über Trichtern nicht fehlerhaft verschmelzen).

2. 64-Bit-Ganzzahlsumme & Schutz vor arithmetischem Überlauf

Wenn zwei riesige Stapel auf Großservern verschmelzen (z. B. Limit bei 2 Milliarden), kann eine normale 32-Bit-int-Addition in negative Zahlen überlaufen ($\text{Integer.MAX_VALUE} + 1 = -2,147,483,648$), was Entitätszustände beschädigt.

Item Clumps berechnet die Summe mit 64-Bit-Präzision:

$$S = (\text{long}),\text{thisCount} + (\text{long}),\text{otherCount}$$

  • Vollständige Absorption ($S \le \text{maxClumpSize}$): $$\text{count}_{\text{merged}} = (\text{int}),S$$
  • Partielle Absorption ($S > \text{maxClumpSize}$): $$\Delta = \text{maxClumpSize} - \text{thisCount}$$ $$\text{thisCount}' = \text{maxClumpSize}, \quad \text{otherCount}' = \text{otherCount} - \Delta$$

3. Strenge Komponenten- & Zustandskonsistenz

Items verschmelzen niemals, es sei denn, alle Datenkomponenten (Verzauberungen, Haltbarkeit, Namen, Rüstungsbesätze, Trankeffekte) stimmen bitgenau zu 100 % überein:

$$\text{ItemStack}.\text{isSameItemSameComponents}(\text{stack}_A, \text{stack}_B) == \text{true}$$


💻 Reale Java-Quellcode-Implementierung

Aus ItemEntityMixin.java in Minecraft 26.2:

java
@Inject(method = "tryToMerge", at = @At("HEAD"), cancellable = true)
private void item_clumps$customMerge(ItemEntity other, CallbackInfo ci) {
    ItemStack thisStack = this.getItem();
    ItemStack otherStack = other.getItem();

    // Fast-path exit before GameRule lookups
    if (!Objects.equals(this.target, ((ItemEntityMixin)(Object)other).target) || 
        !ItemStack.isSameItemSameComponents(thisStack, otherStack)) {
        return;
    }

    if (!DynamicGameRuleManager.getBoolean(this.level(), ItemClumpsFabric.ENABLE_CLUMPING)) return;

    // Magnet mod in-flight protection
    if (net.fabricmc.loader.api.FabricLoader.getInstance().isModLoaded("magnet")) {
        try {
            java.lang.reflect.Method isMagnetizedMethod;
            try {
                isMagnetizedMethod = this.getClass().getMethod("ig_magnet$isMagnetized");
            } catch (NoSuchMethodException e) {
                isMagnetizedMethod = this.getClass().getMethod("ig$isMagnetized");
            }
            if ((boolean) isMagnetizedMethod.invoke(this) || (boolean) isMagnetizedMethod.invoke(other)) {
                ci.cancel();
                return;
            }
        } catch (Throwable ignored) {}
    }

    int thisCount = thisStack.getCount();
    int otherCount = otherStack.getCount();
    int maxClump = (ItemClumpsFabric.MAX_CLUMP_SIZE == null) 
        ? thisStack.getMaxStackSize() 
        : DynamicGameRuleManager.getInt(this.level(), ItemClumpsFabric.MAX_CLUMP_SIZE);

    long sum = (long) thisCount + (long) otherCount;
    if (sum > (long) maxClump) {
        int spaceLeft = maxClump - thisCount;
        if (spaceLeft > 0) {
            ItemStack thisCopy = thisStack.copyWithCount(maxClump);
            this.setItem(thisCopy);
            
            ItemStack otherCopy = otherStack.copyWithCount(otherCount - spaceLeft);
            other.setItem(otherCopy);

            this.pickupDelay = Math.max(this.pickupDelay, ((ItemEntityMixin)(Object)other).pickupDelay);
            this.age = Math.min(this.age, ((ItemEntityMixin)(Object)other).age);
        }
        ci.cancel();
        return;
    }

    // Full Merge: larger stack absorbs the smaller stack
    if (otherCount < thisCount) {
        ItemStack thisCopy = thisStack.copyWithCount((int) sum);
        this.setItem(thisCopy);
        this.pickupDelay = Math.max(this.pickupDelay, ((ItemEntityMixin)(Object)other).pickupDelay);
        this.age = Math.min(this.age, ((ItemEntityMixin)(Object)other).age);
        other.discard();
    } else {
        ItemStack otherCopy = otherStack.copyWithCount((int) sum);
        other.setItem(otherCopy);
        ((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();
}

🔗 Verwandte Dokumentation (MC 26.2)

Official documentation & web portal for Dasik Igaijinn mods.