Защита от переполнения большого сундука
Проблема целочисленного переполнения
В Java и Minecraft вычисления предметов используют 32-битные знаковые целые числа (int). Максимальное представимое значение: $$I_{\max} = 2^{31} - 1 = 2,147,483,647$$
Когда большой сундук (54 слота) заполнен максимальными стаками, расчет суммы предметов внутри складывает все 54 слота.
🧮 Расчет порога безопасности
Если в каждом из 54 слотов лежит стак размера $L$: $$\text{Всего предметов в сундуке} = 54 \times L$$
Чтобы сумма не превысила $I_{\max}$: $$54 \times L \le 2,147,483,647$$ $$L \le \frac{2,147,483,647}{54} \approx 39,768,215.68$$
Таким образом, абсолютный безопасный порог стака составляет: $$L_{\text{safe}} = 39,768,215$$
Таблица последствий переполнения
| Лимит стака ($L$) | Всего предметов в сундуке | Статус числа | Риск |
|---|---|---|---|
| 128 (По умолчанию) | $6,912$ | Безопасно ($< 2.14\text{ млрд}$) | Нет риска |
| 1,000,000 | $54,000,000$ | Безопасно ($< 2.14\text{ млрд}$) | Нет риска |
| 39,768,215 | $2,147,483,610$ | Безопасно ($< 2.14\text{ млрд}$) | Рекомендуемый максимальный порог |
| 40,000,000 | $2,160,000,000$ | Переполнение! (Переходит в $-2,134,967,296$) | Пропадание предметов / сбой контейнера |
🛠️ Быстрый крафт с двойной точностью
В AbstractContainerMenuMixin расчет быстрого распределения предметов переписан на 64-битную арифметику с плавающей точкой (double), что исключает потерю точности и уход в отрицательные числа:
@Mixin(AbstractContainerMenu.class)
public class AbstractContainerMenuMixin {
@Overwrite
public static int getQuickCraftPlaceCount(int quickCraftSlotsSize, int quickCraftingType, ItemStack itemStack) {
return switch (quickCraftingType) {
case 0 -> (int) ((double) itemStack.getCount() / (double) quickCraftSlotsSize);
case 1 -> 1;
case 2 -> itemStack.getMaxStackSize();
default -> itemStack.getCount();
};
}
}