Skip to content

Commit c0261a8

Browse files
committed
Migrate to Minecraft 1.21.4 (fabric 0.117.0, Java 21)
- Update gradle.properties: minecraft_version=1.21.4, yarn_mappings=1.21.4+build.8, fabric_api_version=0.117.0+1.21.4 - Update build.gradle.kts: Java 21, use yarn_mappings property - Update fabric.mod.json + gametest: minecraft >=1.21.0 <1.22, java >=21 - Replace removed classes (ToolItem, ElytraItem, EnchantedBookItem) with component/identity checks - Fix ItemStack.damage() signature for 1.21 (4 params) - Fix armor slot detection: use simpleName instead of index - Use Registries.ITEM.getId() for item registry lookups (1.21.4 API) - Cache by Item object instead of registry ID string - Add StackableToolsUtils.maxStackFor() shared helper
1 parent 316c6d8 commit c0261a8

13 files changed

Lines changed: 79 additions & 96 deletions

README.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
# StackableTools (Kotlin Edition)
22

3-
[![Minecraft Version](https://img.shields.io/badge/Minecraft-1.20-blue.svg?style=for-the-badge&logo=minecraft)](https://www.minecraft.net/)
4-
[![Minecraft Version](https://img.shields.io/badge/Minecraft-1.20.1-blue.svg?style=for-the-badge&logo=minecraft)](https://www.minecraft.net/)
5-
[![Minecraft Version](https://img.shields.io/badge/Minecraft-1.20.2-blue.svg?style=for-the-badge&logo=minecraft)](https://www.minecraft.net/)
6-
[![Minecraft Version](https://img.shields.io/badge/Minecraft-1.20.3-blue.svg?style=for-the-badge&logo=minecraft)](https://www.minecraft.net/)
7-
[![Minecraft Version](https://img.shields.io/badge/Minecraft-1.20.4-blue.svg?style=for-the-badge&logo=minecraft)](https://www.minecraft.net/)
3+
[![Minecraft Version](https://img.shields.io/badge/Minecraft-1.21-blue.svg?style=for-the-badge&logo=minecraft)](https://www.minecraft.net/)
4+
[![Minecraft Version](https://img.shields.io/badge/Minecraft-1.21.1-blue.svg?style=for-the-badge&logo=minecraft)](https://www.minecraft.net/)
5+
[![Minecraft Version](https://img.shields.io/badge/Minecraft-1.21.4-blue.svg?style=for-the-badge&logo=minecraft)](https://www.minecraft.net/)
6+
[![Minecraft Version](https://img.shields.io/badge/Minecraft-1.21.11-blue.svg?style=for-the-badge&logo=minecraft)](https://www.minecraft.net/)
87

98

109
[![Fabric API](https://img.shields.io/badge/Loader-Fabric-orange.svg?style=for-the-badge)](https://fabricmc.net/)
@@ -31,12 +30,12 @@
3130
## Version Support
3231
| Minecraft Version | Fabric Loader | Fabric API | Status | Notes |
3332
| :---------------- | :------------ | :--------- | :----------- | :-------------------------- |
34-
| 1.20.0 | ≥0.18.5 | ≥0.97.0 | ✅ Supported | Community-tested (untested) |
35-
| 1.20.1 | ≥0.18.5 | ≥0.97.0 | ✅ Supported | Community-tested (untested) |
36-
| 1.20.2 | ≥0.18.5 | ≥0.97.0 | ✅ Supported | Community-tested (untested) |
37-
| 1.20.3 | ≥0.18.5 | ≥0.97.0 | ✅ Supported | Community-tested (untested) |
38-
| 1.20.4 | ≥0.18.5 | ≥0.97.3 |**Tested** | Fully tested & recommended |
39-
| 1.20.5+ | ≥0.18.5 |1.0.0 | ⚠️ Untested | May require code updates |
33+
| 1.21 | ≥0.16.9 | ≥0.107.0 | ✅ Supported | Community-tested |
34+
| 1.21.1 | ≥0.16.9 | ≥0.107.0 | ✅ Supported | Community-tested |
35+
| 1.21.2 | ≥0.16.9 | ≥0.107.0 | ✅ Supported | Community-tested |
36+
| 1.21.3 | ≥0.16.9 | ≥0.107.0 | ✅ Supported | Community-tested |
37+
| 1.21.4 | ≥0.16.10 | ≥0.117.0 |**Tested** | Fully tested & recommended |
38+
| 1.21.5+ | ≥0.16.14 |0.120.0 | ⚠️ Untested | May require code updates |
4039

4140
## Main Features
4241
- **Stackable Tools**: Swords, pickaxes, shovels, axes, and more are now stackable!

README_FR.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# StackableTools (Édition Kotlin)
22

3-
[![Version Minecraft](https://img.shields.io/badge/Minecraft-1.20-1.20.4-blue.svg?style=for-the-badge&logo=minecraft)](https://www.minecraft.net/)
3+
[![Version Minecraft](https://img.shields.io/badge/Minecraft-1.21-1.21.11-blue.svg?style=for-the-badge&logo=minecraft)](https://www.minecraft.net/)
44
[![Fabric API](https://img.shields.io/badge/Loader-Fabric-orange.svg?style=for-the-badge)](https://fabricmc.net/)
55
[![Licence](https://img.shields.io/badge/License-CC0_1.0-green.svg?style=for-the-badge)](https://github.com/yoann/StackableTools/blob/master/LICENSE)
66
[![Release GitHub](https://img.shields.io/github/v/release/yoann/StackableTools?style=for-the-badge)](https://github.com/yoann/StackableTools/releases)
@@ -21,12 +21,12 @@
2121
## Support des versions
2222
| Version Minecraft | Fabric Loader | Fabric API | Statut | Remarques |
2323
| :---------------- | :------------ | :--------- | :----------- | :------------------------------------ |
24-
| 1.20.0 | ≥0.18.5 | ≥0.97.0 | ✅ Compatible | Testé par la communauté (non vérifié) |
25-
| 1.20.1 | ≥0.18.5 | ≥0.97.0 | ✅ Compatible | Testé par la communauté (non vérifié) |
26-
| 1.20.2 | ≥0.18.5 | ≥0.97.0 | ✅ Compatible | Testé par la communauté (non vérifié) |
27-
| 1.20.3 | ≥0.18.5 | ≥0.97.0 | ✅ Compatible | Testé par la communauté (non vérifié) |
28-
| 1.20.4 | ≥0.18.5 | ≥0.97.3 |**Testé** | Complètement testé & recommandé |
29-
| 1.20.5+ | ≥0.18.5 |1.0.0 | ⚠️ Non testé | Peut nécessiter des mises à jour |
24+
| 1.21 | ≥0.16.9 | ≥0.107.0 | ✅ Compatible | Testé par la communauté |
25+
| 1.21.1 | ≥0.16.9 | ≥0.107.0 | ✅ Compatible | Testé par la communauté |
26+
| 1.21.2 | ≥0.16.9 | ≥0.107.0 | ✅ Compatible | Testé par la communauté |
27+
| 1.21.3 | ≥0.16.9 | ≥0.107.0 | ✅ Compatible | Testé par la communauté |
28+
| 1.21.4 | ≥0.16.10 | ≥0.117.0 |**Testé** | Complètement testé & recommandé |
29+
| 1.21.5+ | ≥0.16.14 |0.120.0 | ⚠️ Non testé | Peut nécessiter des mises à jour |
3030

3131
## Fonctionnalités principales
3232
- **Outils empilables** : Épées, pioches, pelles, haches et plus sont désormais empilables !

build.gradle.kts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ fabricApi {
4949
dependencies {
5050
// To change the versions see the gradle.properties file
5151
minecraft("com.mojang:minecraft:${providers.gradleProperty("minecraft_version").get()}")
52-
mappings("net.fabricmc:yarn:1.20.5+build.1:v2")
52+
mappings("net.fabricmc:yarn:${providers.gradleProperty("yarn_mappings").get()}:v2")
5353
modImplementation("net.fabricmc:fabric-loader:${providers.gradleProperty("loader_version").get()}")
5454

5555
// Fabric API. This is technically optional, but you probably want it anyway.
@@ -72,12 +72,12 @@ tasks.processResources {
7272
}
7373

7474
tasks.withType<JavaCompile>().configureEach {
75-
options.release = 17
75+
options.release = 21
7676
}
7777

7878
kotlin {
7979
compilerOptions {
80-
jvmTarget = JvmTarget.JVM_17
80+
jvmTarget = JvmTarget.JVM_21
8181
}
8282
}
8383

@@ -87,8 +87,8 @@ java {
8787
// If you remove this line, sources will not be generated.
8888
withSourcesJar()
8989

90-
sourceCompatibility = JavaVersion.VERSION_17
91-
targetCompatibility = JavaVersion.VERSION_17
90+
sourceCompatibility = JavaVersion.VERSION_21
91+
targetCompatibility = JavaVersion.VERSION_21
9292
}
9393

9494
tasks.jar {

compile_config_sample.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"minecraft_version": "1.20.4",
3-
"fabric_loader_version": "0.16.9",
2+
"minecraft_version": "1.21.4",
3+
"fabric_loader_version": "0.18.5",
44
"launcherDir": "/path/to/launcher/",
55
"instanceDir": "instances/version/",
66
"location": "minecraft/mods/"

gradle.properties

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ org.gradle.configuration-cache=false
77

88
# Fabric Properties
99
# check these on https://fabricmc.net/develop
10-
minecraft_version=1.20.5
10+
minecraft_version=1.21.4
11+
yarn_mappings=1.21.4+build.8
1112
loader_version=0.18.5
1213
loom_version=1.15-SNAPSHOT
1314
fabric_kotlin_version=1.13.10+kotlin.2.3.20
@@ -18,4 +19,4 @@ maven_group=stackabletools
1819
archives_base_name=stackabletools
1920

2021
# Dependencies
21-
fabric_api_version=0.97.3+1.20.5
22+
fabric_api_version=0.117.0+1.21.4

src/gametest/resources/fabric.mod.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
},
2626
"depends": {
2727
"fabricloader": ">=0.18.5",
28-
"minecraft": ">=1.20.5 <1.20.7",
29-
"java": ">=17",
28+
"minecraft": ">=1.21.0 <1.22",
29+
"java": ">=21",
3030
"fabric-api": "*",
3131
"fabric-language-kotlin": "*"
3232
}

src/main/kotlin/stackabletools/StackableToolsUtils.kt

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package stackabletools
22

33
import net.minecraft.item.ArmorItem
4-
import net.minecraft.item.ElytraItem
5-
import net.minecraft.item.EnchantedBookItem
4+
import net.minecraft.item.Item
65
import net.minecraft.item.ItemStack
76
import net.minecraft.item.PotionItem
87
import net.minecraft.item.SwordItem
9-
import net.minecraft.item.ToolItem
108
import net.minecraft.item.TridentItem
119
import net.minecraft.registry.Registries
1210
import java.util.concurrent.ConcurrentHashMap
@@ -17,7 +15,7 @@ import net.minecraft.item.Items
1715

1816
object StackableToolsUtils {
1917

20-
private val stackableCache = ConcurrentHashMap<String, Boolean>()
18+
private val stackableCache = ConcurrentHashMap<Item, Boolean>()
2119
private var lastConfigHash = 0
2220

2321
/**
@@ -50,7 +48,7 @@ object StackableToolsUtils {
5048
if (a.item !== b.item) return false
5149

5250
// RULE: We only stack FRESH items (damage == 0).
53-
if (a.item is ToolItem || a.item is ArmorItem || a.item is SwordItem || a.item is TridentItem || a.item is ElytraItem) {
51+
if (a.item is ArmorItem || a.item is SwordItem || a.item is TridentItem || a.item === Items.ELYTRA) {
5452
if (a.damage > 0 || b.damage > 0) return false
5553
}
5654

@@ -83,16 +81,31 @@ object StackableToolsUtils {
8381
lastConfigHash = configHash
8482
}
8583

86-
val itemId = Registries.ITEM.getId(stack.item).toString()
87-
return stackableCache.getOrPut(itemId) {
88-
computeIsStackable(stack, config, itemId)
84+
val item = stack.item
85+
return stackableCache.getOrPut(item) {
86+
computeIsStackable(stack, config, item)
8987
}
9088
}
9189

9290
/**
9391
* Internal logic to compute if an item is stackable.
9492
*/
95-
private fun computeIsStackable(stack: ItemStack, config: stackabletools.config.StackableToolsConfig, itemId: String): Boolean {
93+
fun maxStackFor(stack: ItemStack, cfg: stackabletools.config.StackableToolsConfig.StackingConfig): Int {
94+
val hasToolComponent = stack.get(DataComponentTypes.TOOL) != null
95+
96+
return when {
97+
stack.item is SwordItem || stack.item is TridentItem -> cfg.maxWeaponsStackSize
98+
hasToolComponent && stack.item !is SwordItem && stack.item !is TridentItem -> cfg.maxToolStackSize
99+
stack.item is ArmorItem -> cfg.maxArmorPieceStackSize
100+
stack.item is PotionItem -> cfg.maxPotionStackSize
101+
stack.item === Items.ENCHANTED_BOOK -> cfg.maxEnchantedBooksStackSize
102+
stack.item === Items.ELYTRA -> cfg.maxElytraStackSize
103+
else -> cfg.maxStackSize
104+
}.toInt().coerceAtLeast(1)
105+
}
106+
107+
private fun computeIsStackable(stack: ItemStack, config: stackabletools.config.StackableToolsConfig, item: Item): Boolean {
108+
val itemId = Registries.ITEM.getId(item).toString()
96109
val shortItemId = itemId.substringAfter(':')
97110

98111
val excluded = config.stacking.excludedItemIds
@@ -101,13 +114,15 @@ object StackableToolsUtils {
101114
val active = config.stacking.activeCategories
102115
val isAll = StackingCategory.ALL in active
103116

104-
when (stack.item) {
105-
is SwordItem, is TridentItem -> if (isAll || StackingCategory.WEAPONS in active) return true
106-
is ToolItem -> if (isAll || StackingCategory.TOOLS in active) return true
107-
is ArmorItem -> if (isAll || StackingCategory.ARMORS in active) return true
108-
is PotionItem -> if (isAll || StackingCategory.POTIONS in active) return true
109-
is EnchantedBookItem -> if (isAll || StackingCategory.ENCHANTED_BOOKS in active) return true
110-
is ElytraItem -> if (isAll || StackingCategory.ELYTRA in active) return true
117+
val hasToolComponent = stack.get(DataComponentTypes.TOOL) != null
118+
119+
when {
120+
stack.item is SwordItem || stack.item is TridentItem -> if (isAll || StackingCategory.WEAPONS in active) return true
121+
hasToolComponent && stack.item !is SwordItem && stack.item !is TridentItem -> if (isAll || StackingCategory.TOOLS in active) return true
122+
stack.item is ArmorItem -> if (isAll || StackingCategory.ARMORS in active) return true
123+
stack.item is PotionItem -> if (isAll || StackingCategory.POTIONS in active) return true
124+
stack.item === Items.ENCHANTED_BOOK -> if (isAll || StackingCategory.ENCHANTED_BOOKS in active) return true
125+
stack.item === Items.ELYTRA -> if (isAll || StackingCategory.ELYTRA in active) return true
111126
}
112127

113128
val manual = config.stacking.manualStackableItemIds

src/main/kotlin/stackabletools/mixin/ArmorSlotMixin.kt

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
package stackabletools.mixin
22

33
import net.minecraft.item.ItemStack
4-
import net.minecraft.item.ArmorItem
5-
import net.minecraft.item.EnchantedBookItem
6-
import net.minecraft.item.ElytraItem
7-
import net.minecraft.item.PotionItem
8-
import net.minecraft.item.SwordItem
9-
import net.minecraft.item.ToolItem
10-
import net.minecraft.item.TridentItem
114
import net.minecraft.screen.slot.Slot
125
import org.spongepowered.asm.mixin.Mixin
136
import org.spongepowered.asm.mixin.injection.At
@@ -29,26 +22,15 @@ abstract class ArmorSlotMixin {
2922
*/
3023
@Inject(method = ["getMaxItemCount(Lnet/minecraft/item/ItemStack;)I"], at = [At("HEAD")], cancellable = true)
3124
private fun onGetMaxItemCount(stack: ItemStack, cir: CallbackInfoReturnable<Int>) {
32-
val slot = this as Slot
33-
34-
if (slot.javaClass.name.contains("PlayerScreenHandler") &&
35-
(slot.index in 5..8 || slot.javaClass.simpleName in listOf("OffhandSlot", "ArmorSlot"))) {
25+
if (this.javaClass.simpleName in listOf("ArmorSlot", "OffhandSlot")) {
3626
cir.returnValue = 1
3727
return
3828
}
3929

4030
if (stack.isEmpty || !StackableToolsUtils.isStackableItem(stack)) return
4131

4232
val cfg = ConfigManager.getConfig().stacking
43-
val maxStack = when (stack.item) {
44-
is SwordItem, is TridentItem -> cfg.maxWeaponsStackSize
45-
is ToolItem -> cfg.maxToolStackSize
46-
is PotionItem -> cfg.maxPotionStackSize
47-
is EnchantedBookItem -> cfg.maxEnchantedBooksStackSize
48-
is ElytraItem -> cfg.maxElytraStackSize
49-
is ArmorItem -> cfg.maxArmorPieceStackSize
50-
else -> cfg.maxStackSize
51-
}.toInt().coerceAtLeast(1)
33+
val maxStack = StackableToolsUtils.maxStackFor(stack, cfg)
5234

5335
cir.returnValue = maxStack
5436
cir.cancel()

src/main/kotlin/stackabletools/mixin/ElytraItemMixin.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package stackabletools.mixin
22

3-
import net.minecraft.item.ElytraItem
43
import net.minecraft.item.Item
4+
import net.minecraft.item.Items
55
import org.spongepowered.asm.mixin.Mixin
66
import org.spongepowered.asm.mixin.injection.At
77
import org.spongepowered.asm.mixin.injection.Inject
@@ -20,7 +20,7 @@ abstract class ElytraItemMixin {
2020
@Inject(method = ["getMaxCount"], at = [At("HEAD")], cancellable = true)
2121
private fun onGetMaxCount(cir: CallbackInfoReturnable<Int>) {
2222
val item = this as Any as Item
23-
if (item is ElytraItem) {
23+
if (item === Items.ELYTRA) {
2424
val config = try { ConfigManager.getConfig() } catch (e: Exception) { null }
2525
if (config != null && config.stacking.enable) {
2626
cir.returnValue = config.stacking.maxElytraStackSize.toInt().coerceAtLeast(1)

src/main/kotlin/stackabletools/mixin/InventoryMixin.kt

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@ package stackabletools.mixin
22

33
import net.minecraft.entity.player.PlayerInventory
44
import net.minecraft.item.ArmorItem
5-
import net.minecraft.item.ElytraItem
65
import net.minecraft.item.ItemStack
7-
import net.minecraft.item.PotionItem
8-
import net.minecraft.item.ToolItem
96
import net.minecraft.item.SwordItem
107
import net.minecraft.item.TridentItem
11-
import net.minecraft.item.EnchantedBookItem
8+
import net.minecraft.item.Items
129
import org.spongepowered.asm.mixin.Mixin
1310
import org.spongepowered.asm.mixin.Shadow
1411
import org.spongepowered.asm.mixin.injection.At
@@ -46,21 +43,12 @@ abstract class InventoryMixin {
4643
if (!StackableToolsUtils.isStackableItem(stack)) return
4744

4845
// RULE: We do not stack damaged items to avoid loss of durability data or complex merges
49-
if (stack.isDamaged && (stack.item is ToolItem || stack.item is ArmorItem || stack.item is SwordItem || stack.item is TridentItem || stack.item is ElytraItem)) {
46+
if (stack.isDamaged && (stack.item is ArmorItem || stack.item is SwordItem || stack.item is TridentItem || stack.item === Items.ELYTRA)) {
5047
return
5148
}
5249

5350
val cfg = ConfigManager.getConfig().stacking
54-
// Determine the max stack size based on item category
55-
val maxStackSize = when (stack.item) {
56-
is SwordItem, is TridentItem -> cfg.maxWeaponsStackSize
57-
is ToolItem -> cfg.maxToolStackSize
58-
is PotionItem -> cfg.maxPotionStackSize
59-
is EnchantedBookItem -> cfg.maxEnchantedBooksStackSize
60-
is ElytraItem -> cfg.maxElytraStackSize
61-
is ArmorItem -> cfg.maxArmorPieceStackSize
62-
else -> cfg.maxStackSize
63-
}.toInt()
51+
val maxStackSize = StackableToolsUtils.maxStackFor(stack, cfg)
6452

6553
var remaining = stack.count
6654
val originalCount = stack.count

0 commit comments

Comments
 (0)