From aae0949a31864bac3a86e92555f24679791bf7a4 Mon Sep 17 00:00:00 2001 From: Fabric Bot <159731069+FabricMCBot@users.noreply.github.com> Date: Wed, 10 Apr 2024 22:15:32 +0100 Subject: [PATCH 1/7] Translation updates (#3618) * New translations en_us.json (Korean) * New translations en_us.json (Vietnamese) * New translations en_us.json (Korean) * New translations en_us.json (Korean) * New translations en_us.json (Vietnamese) * New translations en_us.json (Korean) * New translations en_us.json (Portuguese, Brazilian) * New translations en_us.json (French) * New translations en_us.json (Portuguese, Brazilian) * New translations en_us.json (Estonian) * New translations en_us.json (Malay) * New translations en_us.json (Malay) * New translations en_us.json (Malay) * New translations en_us.json (German) * New translations en_us.json (Czech) * New translations en_us.json (Chinese Simplified) * New translations en_us.json (Chinese Simplified) * New translations en_us.json (Spanish, Chile) * New translations en_us.json (Spanish, Chile) * New translations en_us.json (Spanish, Chile) * New translations en_us.json (Chinese Traditional) * New translations en_us.json (Chinese Traditional) * New translations en_us.json (Polish) * New translations en_us.json (Toki Pona) * New translations en_us.json (Toki Pona) --- .../src/main/resources/assets/fabric/lang/es_cl.json | 3 +++ .../src/main/resources/assets/fabric/lang/ko_kr.json | 2 +- .../src/main/resources/assets/fabric/lang/ms_my.json | 3 +++ .../src/main/resources/assets/fabric/lang/tok.json | 3 +++ .../assets/fabric-registry-sync-v0/lang/de_de.json | 2 +- .../assets/fabric-registry-sync-v0/lang/es_cl.json | 7 +++++++ .../assets/fabric-registry-sync-v0/lang/et_ee.json | 2 +- .../assets/fabric-registry-sync-v0/lang/fr_fr.json | 2 +- .../assets/fabric-registry-sync-v0/lang/ko_kr.json | 7 +++++++ .../assets/fabric-registry-sync-v0/lang/ms_my.json | 7 +++++++ .../assets/fabric-registry-sync-v0/lang/pt_br.json | 7 +++++++ .../assets/fabric-registry-sync-v0/lang/tok.json | 7 +++++++ .../assets/fabric-registry-sync-v0/lang/vi_vn.json | 7 +++++++ .../assets/fabric-registry-sync-v0/lang/zh_cn.json | 7 +++++++ .../assets/fabric-registry-sync-v0/lang/zh_tw.json | 7 +++++++ .../assets/fabric-resource-loader-v0/lang/cs_cz.json | 9 +++++++++ .../assets/fabric-resource-loader-v0/lang/es_cl.json | 5 ++++- .../assets/fabric-resource-loader-v0/lang/ko_kr.json | 6 ++++-- .../assets/fabric-resource-loader-v0/lang/ms_my.json | 9 +++++++++ .../assets/fabric-resource-loader-v0/lang/pl_pl.json | 2 +- .../assets/fabric-resource-loader-v0/lang/pt_br.json | 7 ++++++- .../assets/fabric-resource-loader-v0/lang/vi_vn.json | 4 +++- .../assets/fabric-resource-loader-v0/lang/zh_cn.json | 4 ++-- .../assets/fabric-resource-loader-v0/lang/zh_tw.json | 2 +- 24 files changed, 108 insertions(+), 13 deletions(-) create mode 100644 fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/es_cl.json create mode 100644 fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/ms_my.json create mode 100644 fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/tok.json create mode 100644 fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/es_cl.json create mode 100644 fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/ko_kr.json create mode 100644 fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/ms_my.json create mode 100644 fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/pt_br.json create mode 100644 fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/tok.json create mode 100644 fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/vi_vn.json create mode 100644 fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/zh_cn.json create mode 100644 fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/zh_tw.json create mode 100644 fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/cs_cz.json create mode 100644 fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/ms_my.json diff --git a/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/es_cl.json b/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/es_cl.json new file mode 100644 index 0000000000..dbaa4aee13 --- /dev/null +++ b/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/es_cl.json @@ -0,0 +1,3 @@ +{ + "fabric.gui.creativeTabPage": "Página %d/%d" +} \ No newline at end of file diff --git a/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/ko_kr.json b/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/ko_kr.json index 8b731cf72e..f3de648fe3 100644 --- a/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/ko_kr.json +++ b/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/ko_kr.json @@ -1,3 +1,3 @@ { - "fabric.gui.creativeTabPage": "%d/%d 페이지" + "fabric.gui.creativeTabPage": "%d/%d쪽" } \ No newline at end of file diff --git a/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/ms_my.json b/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/ms_my.json new file mode 100644 index 0000000000..6efe80f02e --- /dev/null +++ b/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/ms_my.json @@ -0,0 +1,3 @@ +{ + "fabric.gui.creativeTabPage": "Halaman %d/%d" +} \ No newline at end of file diff --git a/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/tok.json b/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/tok.json new file mode 100644 index 0000000000..99ed92e4f4 --- /dev/null +++ b/fabric-item-group-api-v1/src/main/resources/assets/fabric/lang/tok.json @@ -0,0 +1,3 @@ +{ + "fabric.gui.creativeTabPage": "kipisi nanpa %d/%d" +} \ No newline at end of file diff --git a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/de_de.json b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/de_de.json index ed0c6a34b7..2f1c5e71ba 100644 --- a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/de_de.json +++ b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/de_de.json @@ -1,7 +1,7 @@ { "fabric-registry-sync-v0.unknown-remote.title.singular": "Es wurde ein Registrierungseintrag empfangen, der für diesen Client unbekannt ist.\n", "fabric-registry-sync-v0.unknown-remote.title.plural": "Es wurden %d Registrierungseinträge empfangen, die für diesen Client unbekannt sind.\n", - "fabric-registry-sync-v0.unknown-remote.subtitle.1": "Dies wird in der Regel durch eine nicht übereinstimmende Menge von Mods zwischen Client und Server verursacht.", + "fabric-registry-sync-v0.unknown-remote.subtitle.1": "Dies wird in der Regel durch ein nicht übereinstimmendes Mod-Set zwischen Client und Server verursacht.", "fabric-registry-sync-v0.unknown-remote.subtitle.2": " Weitere Einzelheiten siehst du in den Client-Logs.\nDie folgenden Namensräume für Registrierungseinträge könnten miteinander in Verbindung stehen:\n\n", "fabric-registry-sync-v0.unknown-remote.footer": "Und %d mehr..." } diff --git a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/es_cl.json b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/es_cl.json new file mode 100644 index 0000000000..31f96a6578 --- /dev/null +++ b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/es_cl.json @@ -0,0 +1,7 @@ +{ + "fabric-registry-sync-v0.unknown-remote.title.singular": "Se ha recibido una entrada de registro desconocida para este cliente.\n", + "fabric-registry-sync-v0.unknown-remote.title.plural": "Se han recibido %d entradas de registro desconocidas para este cliente.\n", + "fabric-registry-sync-v0.unknown-remote.subtitle.1": "Usualmente esto es ocasionado debido a que la lista de mods del cliente y el servidor no coinciden.", + "fabric-registry-sync-v0.unknown-remote.subtitle.2": " Verifica los logs del cliente para más detalles.\nLos siguientes espacios de nombre de entradas de registro pueden estar relacionadas:\n\n", + "fabric-registry-sync-v0.unknown-remote.footer": "Y %d más..." +} diff --git a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/et_ee.json b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/et_ee.json index 222e8a6fe7..41bea8a377 100644 --- a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/et_ee.json +++ b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/et_ee.json @@ -1,7 +1,7 @@ { "fabric-registry-sync-v0.unknown-remote.title.singular": "Kliendile tundmatu registrikirje vastuvõetud.\n", "fabric-registry-sync-v0.unknown-remote.title.plural": "%d kliendile tundmatut registrikirjet vastuvõetud.\n", - "fabric-registry-sync-v0.unknown-remote.subtitle.1": "See on üldjuhul põhjustatud sellest, kui kliendis kasutatud modid erinevad serveri omadest.", + "fabric-registry-sync-v0.unknown-remote.subtitle.1": "See on üldjuhul põhjustatud sellest, kui kliendis kasutatavad modid erinevad serveri omadest.", "fabric-registry-sync-v0.unknown-remote.subtitle.2": " Rohkemate andmete nägemiseks vaata kliendilogisid.\nNeed registrikirje nimeruumid võivad olla seotud:\n\n", "fabric-registry-sync-v0.unknown-remote.footer": "Ja veel %d..." } diff --git a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/fr_fr.json b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/fr_fr.json index f0192893ad..613691a338 100644 --- a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/fr_fr.json +++ b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/fr_fr.json @@ -1,7 +1,7 @@ { "fabric-registry-sync-v0.unknown-remote.title.singular": "Ce client a reçu une entrée de registre qui lui est inconnue.\n", "fabric-registry-sync-v0.unknown-remote.title.plural": "Ce client a reçu %d entrées de registre qui lui sont inconnues.\n", - "fabric-registry-sync-v0.unknown-remote.subtitle.1": "Ce problème est généralement dû à une différence entre le jeu de mods du client et celui du serveur.", + "fabric-registry-sync-v0.unknown-remote.subtitle.1": "Ce problème est généralement dû à une différence entre les mods du client et ceux du serveur.", "fabric-registry-sync-v0.unknown-remote.subtitle.2": " Voir les logs du client pour plus de détails.\nLes namespaces d'entrée de registre pourraient être liés :\n\n", "fabric-registry-sync-v0.unknown-remote.footer": "Et %d de plus..." } diff --git a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/ko_kr.json b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/ko_kr.json new file mode 100644 index 0000000000..9ae22e8b0c --- /dev/null +++ b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/ko_kr.json @@ -0,0 +1,7 @@ +{ + "fabric-registry-sync-v0.unknown-remote.title.singular": "이 클라이언트에서 알 수 없는 레지스트리 항목을 받았습니다.\n", + "fabric-registry-sync-v0.unknown-remote.title.plural": "이 클라이언트에서 %d개의 알 수 없는 레지스트리 항목을 받았습니다.\n", + "fabric-registry-sync-v0.unknown-remote.subtitle.1": "이는 일반적으로 클라이언트와 서버 간에 일치하지 않는 모드 세트로 인해 발생합니다.", + "fabric-registry-sync-v0.unknown-remote.subtitle.2": " 클라이언트 로그에서 자세한 정보를 확인할 수 있습니다.\n다음 레지스트리 항목 네임스페이스가 관련되어 있을 수 있습니다:\n\n", + "fabric-registry-sync-v0.unknown-remote.footer": "외 %d개 더..." +} diff --git a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/ms_my.json b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/ms_my.json new file mode 100644 index 0000000000..6423e8fff5 --- /dev/null +++ b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/ms_my.json @@ -0,0 +1,7 @@ +{ + "fabric-registry-sync-v0.unknown-remote.title.singular": "Telah menerima satu entri pendaftaran yang tidak diketahui oleh klien ini.\n", + "fabric-registry-sync-v0.unknown-remote.title.plural": "Telah menerima %d entri pendaftaran yang tidak diketahui oleh klien ini.\n", + "fabric-registry-sync-v0.unknown-remote.subtitle.1": "Ini biasanya disebabkan oleh set mod yang tidak sepadan antara klien dan pelayan.", + "fabric-registry-sync-v0.unknown-remote.subtitle.2": " Lihat log klien untuk butiran lanjut.\nRuang nama entri pendaftaran berikut mungkin berkaitan:\n\n", + "fabric-registry-sync-v0.unknown-remote.footer": "Dan %d lagi..." +} diff --git a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/pt_br.json b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/pt_br.json new file mode 100644 index 0000000000..c536b5d23a --- /dev/null +++ b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/pt_br.json @@ -0,0 +1,7 @@ +{ + "fabric-registry-sync-v0.unknown-remote.title.singular": "Recebido uma entrada de registo desconhecida para este cliente.\n", + "fabric-registry-sync-v0.unknown-remote.title.plural": "Recebido %d entradas de registo desconhecidas para este cliente.\n", + "fabric-registry-sync-v0.unknown-remote.subtitle.1": "Isto é normalmente causado por um conjunto de mods incompatíveis entre o cliente e o servidor.", + "fabric-registry-sync-v0.unknown-remote.subtitle.2": " Veja os logs do cliente para mais detalhes.\nOs seguintes namespaces de entradas de registo podem estar relacionados:\n\n", + "fabric-registry-sync-v0.unknown-remote.footer": "E %d mais..." +} diff --git a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/tok.json b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/tok.json new file mode 100644 index 0000000000..d0a8c24aee --- /dev/null +++ b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/tok.json @@ -0,0 +1,7 @@ +{ + "fabric-registry-sync-v0.unknown-remote.title.singular": "ma kulupu li toki e ijo. taso, mi sona ala e ona.\n", + "fabric-registry-sync-v0.unknown-remote.title.plural": "ma kulupu li toki e ijo %d. taso, mi sona ala e ona.\n", + "fabric-registry-sync-v0.unknown-remote.subtitle.1": "ken suli la, ni li tan ni: kulupu ante pi ilo pana en kulupu ante pi ilo lanpan li kulupu ante ante.", + "fabric-registry-sync-v0.unknown-remote.subtitle.2": " sina wile sona namako la, o lukin e lipu musi pi ilo lanpan.\nken la, ni li tan nimi kulupu ni:\n\n", + "fabric-registry-sync-v0.unknown-remote.footer": "ijo %d namako..." +} diff --git a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/vi_vn.json b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/vi_vn.json new file mode 100644 index 0000000000..c5f09b7cc4 --- /dev/null +++ b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/vi_vn.json @@ -0,0 +1,7 @@ +{ + "fabric-registry-sync-v0.unknown-remote.title.singular": "Đã nhận được mục đăng ký mà client này không xác định.\n", + "fabric-registry-sync-v0.unknown-remote.title.plural": "Đã nhận được %d mục đăng ký mà client này không xác định.\n​.\n", + "fabric-registry-sync-v0.unknown-remote.subtitle.1": "Điều này thường xảy ra do bộ mod giữa máy khách và máy chủ không khớp.\n​.", + "fabric-registry-sync-v0.unknown-remote.subtitle.2": " Xem nhật ký khách hàng để biết thêm chi tiết.\nCác không gian tên mục đăng ký sau đây có thể liên quan:\n​:\n\n", + "fabric-registry-sync-v0.unknown-remote.footer": "Và %d nữa..." +} diff --git a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/zh_cn.json b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/zh_cn.json new file mode 100644 index 0000000000..aa561f29fe --- /dev/null +++ b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/zh_cn.json @@ -0,0 +1,7 @@ +{ + "fabric-registry-sync-v0.unknown-remote.title.singular": "接收到 1 个本客户端未知的注册表项。\n", + "fabric-registry-sync-v0.unknown-remote.title.plural": "接收到 %d 个本客户端未知的注册表项。\n", + "fabric-registry-sync-v0.unknown-remote.subtitle.1": "这通常是客户端和服务器上安装的模组不一致而造成的。", + "fabric-registry-sync-v0.unknown-remote.subtitle.2": " 更多详情见客户端日志。\n以下注册表项命名空间可能有所关系:\n\n", + "fabric-registry-sync-v0.unknown-remote.footer": "以及 %d 项未显示……" +} diff --git a/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/zh_tw.json b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/zh_tw.json new file mode 100644 index 0000000000..8771dfe2fd --- /dev/null +++ b/fabric-registry-sync-v0/src/main/resources/assets/fabric-registry-sync-v0/lang/zh_tw.json @@ -0,0 +1,7 @@ +{ + "fabric-registry-sync-v0.unknown-remote.title.singular": "客戶端接收到未知的登錄項。\n", + "fabric-registry-sync-v0.unknown-remote.title.plural": "客戶端接收到 %d 個未知的登錄項。\n", + "fabric-registry-sync-v0.unknown-remote.subtitle.1": "這通常是由於客戶端和伺服器之間的 mod 設定不匹配造成的。", + "fabric-registry-sync-v0.unknown-remote.subtitle.2": " 有關更多詳細信息,請參閱客戶端日誌。\n可能與以下登錄項目的命名空間有關:\n\n", + "fabric-registry-sync-v0.unknown-remote.footer": "還有其他 %d 項…" +} diff --git a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/cs_cz.json b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/cs_cz.json new file mode 100644 index 0000000000..5d2f0f65a7 --- /dev/null +++ b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/cs_cz.json @@ -0,0 +1,9 @@ +{ + "pack.description.modResources": "Modové zdroje.", + "pack.source.fabricmod": "Fabric Mod", + "pack.source.builtinMod": "zabudováný: %s", + "pack.name.fabricMod": "Fabric Mod \"%s\"", + "pack.name.fabricMods": "Fabric Mody", + "pack.name.fabricMod.subPack": "Fabric Mod \"%s\" (%s)", + "commands.datapack.fabric.internal": "Nelze zapnout ani vypnout zabudováný balíček Fabricu \"%s\"." +} diff --git a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/es_cl.json b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/es_cl.json index a774e7c7a5..43cff92a58 100644 --- a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/es_cl.json +++ b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/es_cl.json @@ -1,6 +1,9 @@ { + "pack.description.modResources": "Recursos de mods.", "pack.source.fabricmod": "Mod de Fabric", "pack.source.builtinMod": "Integrado: %s", "pack.name.fabricMod": "Mod de Fabric \"%s\"", - "pack.name.fabricMods": "Mods de Fabric" + "pack.name.fabricMods": "Mods Fabric", + "pack.name.fabricMod.subPack": "Mod de Fabric \"%s\" (%s)", + "commands.datapack.fabric.internal": "No se ha podido habilitar o deshabilitar paquete interno de Fabric \"%s\"." } diff --git a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/ko_kr.json b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/ko_kr.json index bcf6893210..144212153e 100644 --- a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/ko_kr.json +++ b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/ko_kr.json @@ -1,7 +1,9 @@ { "pack.description.modResources": "모드 리소스.", "pack.source.fabricmod": "Fabric 모드", - "pack.source.builtinMod": "%s 에 내장됨", + "pack.source.builtinMod": "내장: %s", "pack.name.fabricMod": "\"%s\" Fabric 모드", - "pack.name.fabricMods": "Fabric 모드" + "pack.name.fabricMods": "Fabric 모드", + "pack.name.fabricMod.subPack": "\"%s\" (%s) Fabric 모드", + "commands.datapack.fabric.internal": "Fabric 내부 팩 \"%s\"을(를) 활성화 또는 비활성화할 수 없습니다." } diff --git a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/ms_my.json b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/ms_my.json new file mode 100644 index 0000000000..53b61f2daf --- /dev/null +++ b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/ms_my.json @@ -0,0 +1,9 @@ +{ + "pack.description.modResources": "Sumber mod.", + "pack.source.fabricmod": "Mod Fabric", + "pack.source.builtinMod": "terbina: %s", + "pack.name.fabricMod": "Mod Fabric \"%s\"", + "pack.name.fabricMods": "Mod Fabric", + "pack.name.fabricMod.subPack": "Mod Fabric \"%s\" (%s)", + "commands.datapack.fabric.internal": "Tidak boleh mendayakan atau menyahdayakan pek dalaman Fabric \"%s\"." +} diff --git a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/pl_pl.json b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/pl_pl.json index 3016c13d09..361f054964 100644 --- a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/pl_pl.json +++ b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/pl_pl.json @@ -1,7 +1,7 @@ { "pack.description.modResources": "Zasoby modów.", "pack.source.fabricmod": "Mod Fabric", - "pack.source.builtinMod": "wbudowana: %s", + "pack.source.builtinMod": "wbudowane: %s", "pack.name.fabricMod": "Mod Fabric \"%s\"", "pack.name.fabricMods": "Mody Fabric", "pack.name.fabricMod.subPack": "Mod Fabric \"%s\" (%s)", diff --git a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/pt_br.json b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/pt_br.json index 6f0eea6e80..1e0b4f61ad 100644 --- a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/pt_br.json +++ b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/pt_br.json @@ -1,4 +1,9 @@ { + "pack.description.modResources": "Recursos de mod.", "pack.source.fabricmod": "Mod Fabric", - "pack.source.builtinMod": "integrado: %s" + "pack.source.builtinMod": "integrado: %s", + "pack.name.fabricMod": "Mod do Fabric \"%s\"", + "pack.name.fabricMods": "Mods do Fabric", + "pack.name.fabricMod.subPack": "Mod do Fabric \"%s\" (%s)", + "commands.datapack.fabric.internal": "Não é possível ativar ou desativar o pacote interno do Fabric \"%s\"." } diff --git a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/vi_vn.json b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/vi_vn.json index b631f2aa6a..1ab09d3010 100644 --- a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/vi_vn.json +++ b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/vi_vn.json @@ -3,5 +3,7 @@ "pack.source.fabricmod": "Mod Fabric", "pack.source.builtinMod": "tích hợp: %s", "pack.name.fabricMod": "Mod Fabric \"%s\"", - "pack.name.fabricMods": "Các Mod Fabric" + "pack.name.fabricMods": "Các Mod Fabric", + "pack.name.fabricMod.subPack": "Mod Fabric \"%s\" (%s)", + "commands.datapack.fabric.internal": "Không thể bật hoặc tắt gói nội bộ Fabric \"%s\"." } diff --git a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/zh_cn.json b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/zh_cn.json index 3a83ae785e..9f00295cfa 100644 --- a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/zh_cn.json +++ b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/zh_cn.json @@ -4,6 +4,6 @@ "pack.source.builtinMod": "内置:%s", "pack.name.fabricMod": "Fabric 模组“%s”", "pack.name.fabricMods": "Fabric 模组", - "pack.name.fabricMod.subPack": "Fabric 模组“%s”(%s)", - "commands.datapack.fabric.internal": "无法启用或禁用Fabric内部包“%s”。" + "pack.name.fabricMod.subPack": "Fabric 模组 \"%s\" (%s)", + "commands.datapack.fabric.internal": "无法启用或禁用 Fabric 内部包 \"%s\"。" } diff --git a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/zh_tw.json b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/zh_tw.json index a20c58511f..26c7b7b245 100644 --- a/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/zh_tw.json +++ b/fabric-resource-loader-v0/src/main/resources/assets/fabric-resource-loader-v0/lang/zh_tw.json @@ -5,5 +5,5 @@ "pack.name.fabricMod": "Fabric 模組「%s」", "pack.name.fabricMods": "Fabric 模組", "pack.name.fabricMod.subPack": "Fabric 模組「%s」(%s)", - "commands.datapack.fabric.internal": "無法啟用或停用內建資料夾「%s」。" + "commands.datapack.fabric.internal": "無法啟用或停用內建資料包「%s」。" } From d73f36528475a606fa124fbafd5eca1b26152042 Mon Sep 17 00:00:00 2001 From: ToBinio <81473300+tobinio@users.noreply.github.com> Date: Wed, 10 Apr 2024 22:14:36 +0100 Subject: [PATCH 2/7] Fix links in transfer-api README.md (#3694) --- fabric-transfer-api-v1/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fabric-transfer-api-v1/README.md b/fabric-transfer-api-v1/README.md index 42186b22ca..90e176a0da 100644 --- a/fabric-transfer-api-v1/README.md +++ b/fabric-transfer-api-v1/README.md @@ -18,8 +18,8 @@ The [`storage/base`](src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/b implementation of `Storage`. Implementors of inventories with a fixed number of "slots" or "tanks" can use -[`SingleVariantStorage`](src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/base/SingleStorage.java), -and combine them with `CombinedStorage`. +[`SingleVariantStorage`](src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/base/SingleVariantStorage.java), +and combine them with [`CombinedStorage`](src/main/java/net/fabricmc/fabric/api/transfer/v1/storage/base/CombinedStorage.java). ## Fluid transfer A `Storage` is any object that can store fluids. It is just a `Storage`, where `T` is @@ -30,10 +30,10 @@ The unit for fluid transfer is 1/81000ths of a bucket, also known as _droplets_. [`FluidConstants`](src/main/java/net/fabricmc/fabric/api/transfer/v1/fluid/FluidConstants.java) contains a few helpful constants to work with droplets. -Client-side [Fluid variant rendering](src/main/java/net/fabricmc/fabric/api/transfer/v1/client/fluid/FluidVariantRendering.java) will use regular fluid rendering by default, +Client-side [Fluid variant rendering](src/client/java/net/fabricmc/fabric/api/transfer/v1/client/fluid/FluidVariantRendering.java) will use regular fluid rendering by default, ignoring the additional components. `Fluid`s that wish to render differently depending on the stored components can register a -[`FluidVariantRenderHandler`](src/main/java/net/fabricmc/fabric/api/transfer/v1/client/fluid/FluidVariantRenderHandler.java). +[`FluidVariantRenderHandler`](src/client/java/net/fabricmc/fabric/api/transfer/v1/client/fluid/FluidVariantRenderHandler.java). ## Item transfer A `Storage` is any object that can store items. From 44e6689f3cafc7480491ec2e93ef338a366e7c63 Mon Sep 17 00:00:00 2001 From: modmuss Date: Wed, 10 Apr 2024 22:15:13 +0100 Subject: [PATCH 3/7] Deprecate FabricEntityTypeBuilder & FabricBlockEntityTypeBuilder in favour of the vanilla classes (#3677) * Replace FabricEntityTypeBuilder with EntityTypeBuilder + iface injection * Finish and test entity type builder * Deprecate FabricBlockEntityTypeBuilder * Review fix * Fixes based on review * Some fixes * Checkstyle --- build.gradle | 2 +- .../block/entity/FabricBlockEntityType.java | 43 ++++++ .../entity/FabricBlockEntityTypeBuilder.java | 23 ++++ .../builder/v1/entity/FabricEntityType.java | 126 ++++++++++++++++++ .../v1/entity/FabricEntityTypeBuilder.java | 98 ++++++++++++-- .../impl/object/builder/FabricEntityType.java | 44 ------ .../object/builder/FabricEntityTypeImpl.java | 106 +++++++++++++++ .../builder/BlockEntityTypeBuilderMixin.java | 37 +++++ .../builder/EntityTypeBuilderMixin.java | 114 ++++++++++++++++ .../mixin/object/builder/EntityTypeMixin.java | 45 +++++++ .../fabric-object-builder-v1.mixins.json | 3 + .../src/main/resources/fabric.mod.json | 6 +- .../object/builder/FabricEntityTypeTest.java | 86 ++++++++++++ 13 files changed, 674 insertions(+), 59 deletions(-) create mode 100644 fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityType.java create mode 100644 fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType.java delete mode 100644 fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityType.java create mode 100644 fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityTypeImpl.java create mode 100644 fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/BlockEntityTypeBuilderMixin.java create mode 100644 fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeBuilderMixin.java create mode 100644 fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeMixin.java create mode 100644 fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java diff --git a/build.gradle b/build.gradle index 861bbf523b..ddcc981b79 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { id "idea" id "maven-publish" id 'jacoco' - id "fabric-loom" version "1.6.3" apply false + id "fabric-loom" version "1.6.5" apply false id "com.diffplug.spotless" version "6.20.0" id "org.ajoberstar.grgit" version "3.1.0" id "me.modmuss50.remotesign" version "0.4.0" apply false diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityType.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityType.java new file mode 100644 index 0000000000..7aeba75362 --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityType.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.object.builder.v1.block.entity; + +import com.mojang.datafixers.types.Type; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; + +/** + * General-purpose Fabric-provided extensions for {@link BlockEntityType}. + */ +public interface FabricBlockEntityType { + /** + * General-purpose Fabric-provided extensions for {@link BlockEntityType.Builder}. + * + *

Note: This interface is automatically implemented on {@link BlockEntityType.Builder} via Mixin and interface injection. + */ + interface Builder { + /** + * Builds the {@link BlockEntityType}, see {@link BlockEntityType.Builder#build(Type)}. + * + * @return the built {@link BlockEntityType} + */ + default BlockEntityType build() { + throw new AssertionError("Implemented in Mixin"); + } + } +} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityTypeBuilder.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityTypeBuilder.java index 1229c3d11c..898afc17ef 100644 --- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityTypeBuilder.java +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityTypeBuilder.java @@ -33,7 +33,10 @@ * *

Alternatively, use the access widener for {@link BlockEntityType.BlockEntityFactory} * in Fabric Transitive Access Wideners (v1). + * + * @deprecated Use {@link BlockEntityType.Builder} directly. */ +@Deprecated public final class FabricBlockEntityTypeBuilder { private final Factory factory; private final List blocks; @@ -43,6 +46,10 @@ private FabricBlockEntityTypeBuilder(Factory factory, List b this.blocks = blocks; } + /** + * @deprecated Use {@link BlockEntityType.Builder#create(BlockEntityType.BlockEntityFactory, Block...)}. + */ + @Deprecated public static FabricBlockEntityTypeBuilder create(Factory factory, Block... blocks) { List blocksList = new ArrayList<>(blocks.length); Collections.addAll(blocksList, blocks); @@ -55,7 +62,9 @@ public static FabricBlockEntityTypeBuilder create(Fac * * @param block the supported block * @return this builder + * @deprecated Use {@link BlockEntityType.Builder#create(BlockEntityType.BlockEntityFactory, Block...)}. */ + @Deprecated public FabricBlockEntityTypeBuilder addBlock(Block block) { this.blocks.add(block); return this; @@ -66,22 +75,36 @@ public FabricBlockEntityTypeBuilder addBlock(Block block) { * * @param blocks the supported blocks * @return this builder + * @deprecated Use {@link BlockEntityType.Builder#create(BlockEntityType.BlockEntityFactory, Block...)}. */ + @Deprecated public FabricBlockEntityTypeBuilder addBlocks(Block... blocks) { Collections.addAll(this.blocks, blocks); return this; } + /** + * @deprecated Use {@link BlockEntityType.Builder#build()}. + */ + @Deprecated public BlockEntityType build() { return build(null); } + /** + * @deprecated Use {@link BlockEntityType.Builder#build(Type)}. + */ + @Deprecated public BlockEntityType build(Type type) { return BlockEntityType.Builder.create(factory::create, blocks.toArray(new Block[0])) .build(type); } + /** + * @deprecated Use {@link BlockEntityType.BlockEntityFactory}. + */ @FunctionalInterface + @Deprecated public interface Factory { T create(BlockPos blockPos, BlockState blockState); } diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType.java new file mode 100644 index 0000000000..7f60377ac3 --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.object.builder.v1.entity; + +import java.util.function.Supplier; +import java.util.function.UnaryOperator; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.entity.SpawnRestriction; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.world.Heightmap; + +import net.fabricmc.fabric.impl.object.builder.FabricEntityTypeImpl; + +/** + * General-purpose Fabric-provided extensions for {@link EntityType}. + */ +public interface FabricEntityType { + /** + * General-purpose Fabric-provided extensions for {@link EntityType.Builder}. + * + *

Note: This interface is automatically implemented on {@link EntityType.Builder} via Mixin and interface injection. + */ + interface Builder { + /** + * Sets whether the entity's velocity should always be updated. + * + * @param alwaysUpdateVelocity whether the entity's velocity should always be updated + * @return this builder + */ + default EntityType.Builder alwaysUpdateVelocity(boolean alwaysUpdateVelocity) { + throw new AssertionError("Implemented in Mixin"); + } + + /** + * Build the entity type from the builder. Same as {@link EntityType.Builder#build(String)} but without an id. + * + * @return the entity type instance + */ + default EntityType build() { + throw new AssertionError("Implemented in Mixin"); + } + + /** + * Creates an entity type builder for a living entity. + * + *

This entity's spawn group will automatically be set to {@link SpawnGroup#MISC}. + * + * @param the type of entity + * @param livingBuilder a function to configure living entity specific properties + * + * @return a new living entity type builder + */ + static EntityType.Builder createLiving(EntityType.EntityFactory factory, SpawnGroup spawnGroup, UnaryOperator> livingBuilder) { + return FabricEntityTypeImpl.Builder.createLiving(factory, spawnGroup, livingBuilder); + } + + /** + * Creates an entity type builder for a mob entity. + * + * @param the type of entity + * @param mobBuilder a function to configure mob entity specific properties + * + * @return a new mob entity type builder + */ + static EntityType.Builder createMob(EntityType.EntityFactory factory, SpawnGroup spawnGroup, UnaryOperator> mobBuilder) { + return FabricEntityTypeImpl.Builder.createMob(factory, spawnGroup, mobBuilder); + } + + /** + * A builder for additional properties of a living entity, use via {@link #createLiving(EntityType.EntityFactory, SpawnGroup, UnaryOperator)}. + * @param the type of living entity + */ + interface Living { + /** + * Sets the default attributes for a type of living entity. + * + * @param defaultAttributeBuilder a function to generate the default attribute builder from the entity type + * @return this builder for chaining + */ + Living defaultAttributes(Supplier defaultAttributeBuilder); + } + + /** + * A builder for additional properties of a mob entity, use via {@link #createMob(EntityType.EntityFactory, SpawnGroup, UnaryOperator)}. + * @param the type of mob entity + */ + interface Mob extends Living { + /** + * Registers a spawn restriction for this entity. + * + *

This is used by mobs to determine whether Minecraft should spawn an entity within a certain context. + * + * @return this builder for chaining. + */ + Mob spawnRestriction(SpawnRestriction.Location location, Heightmap.Type heightmap, SpawnRestriction.SpawnPredicate spawnPredicate); + + /** + * Sets the default attributes for a type of mob entity. + * + * @param defaultAttributeBuilder a function to generate the default attribute builder from the entity type + * @return this builder for chaining + */ + @Override + Mob defaultAttributes(Supplier defaultAttributeBuilder); + } + } +} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java index d8d1b02f43..da52194975 100644 --- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java @@ -18,6 +18,7 @@ import java.util.Objects; import java.util.function.Supplier; +import java.util.function.UnaryOperator; import com.google.common.collect.ImmutableSet; import org.jetbrains.annotations.Nullable; @@ -33,19 +34,13 @@ import net.minecraft.entity.attribute.DefaultAttributeContainer; import net.minecraft.entity.mob.MobEntity; import net.minecraft.resource.featuretoggle.FeatureFlag; -import net.minecraft.resource.featuretoggle.FeatureFlags; -import net.minecraft.resource.featuretoggle.FeatureSet; import net.minecraft.world.Heightmap; import net.minecraft.world.World; -import net.fabricmc.fabric.impl.object.builder.FabricEntityType; - /** - * Extended version of {@link EntityType.Builder} with added registration for - * server->client entity tracking values. - * - * @param Entity class. + * @deprecated replace with {@link EntityType.Builder} */ +@Deprecated public class FabricEntityTypeBuilder { private SpawnGroup spawnGroup; private EntityType.EntityFactory factory; @@ -59,7 +54,8 @@ public class FabricEntityTypeBuilder { private EntityDimensions dimensions = EntityDimensions.changing(-1.0f, -1.0f); private ImmutableSet specificSpawnBlocks = ImmutableSet.of(); - private FeatureSet requiredFeatures = FeatureFlags.VANILLA_FEATURES; + @Nullable + private FeatureFlag[] requiredFeatures = null; protected FabricEntityTypeBuilder(SpawnGroup spawnGroup, EntityType.EntityFactory factory) { this.spawnGroup = spawnGroup; @@ -75,7 +71,9 @@ protected FabricEntityTypeBuilder(SpawnGroup spawnGroup, EntityType.EntityFactor * @param the type of entity * * @return a new entity type builder + * @deprecated use {@link EntityType.Builder#create(SpawnGroup)} */ + @Deprecated public static FabricEntityTypeBuilder create() { return create(SpawnGroup.MISC); } @@ -87,7 +85,9 @@ public static FabricEntityTypeBuilder create() { * @param the type of entity * * @return a new entity type builder + * @deprecated use {@link EntityType.Builder#create(SpawnGroup)} */ + @Deprecated public static FabricEntityTypeBuilder create(SpawnGroup spawnGroup) { return create(spawnGroup, FabricEntityTypeBuilder::emptyFactory); } @@ -100,7 +100,9 @@ public static FabricEntityTypeBuilder create(SpawnGroup sp * @param the type of entity * * @return a new entity type builder + * @deprecated use {@link EntityType.Builder#create(EntityType.EntityFactory, SpawnGroup)} */ + @Deprecated public static FabricEntityTypeBuilder create(SpawnGroup spawnGroup, EntityType.EntityFactory factory) { return new FabricEntityTypeBuilder<>(spawnGroup, factory); } @@ -113,7 +115,9 @@ public static FabricEntityTypeBuilder create(SpawnGroup sp * @param the type of entity * * @return a new living entity type builder + * @deprecated use {@link FabricEntityType.Builder#createLiving(UnaryOperator)} */ + @Deprecated public static FabricEntityTypeBuilder.Living createLiving() { return new FabricEntityTypeBuilder.Living<>(SpawnGroup.MISC, FabricEntityTypeBuilder::emptyFactory); } @@ -124,6 +128,7 @@ public static FabricEntityTypeBuilder.Living createL * @param the type of entity * * @return a new mob entity type builder + * @deprecated use {@link FabricEntityType.Builder#createMob(UnaryOperator)} */ public static FabricEntityTypeBuilder.Mob createMob() { return new FabricEntityTypeBuilder.Mob<>(SpawnGroup.MISC, FabricEntityTypeBuilder::emptyFactory); @@ -133,12 +138,14 @@ private static T emptyFactory(EntityType type, World world return null; } + @Deprecated public FabricEntityTypeBuilder spawnGroup(SpawnGroup group) { Objects.requireNonNull(group, "Spawn group cannot be null"); this.spawnGroup = group; return this; } + @Deprecated public FabricEntityTypeBuilder entityFactory(EntityType.EntityFactory factory) { Objects.requireNonNull(factory, "Entity Factory cannot be null"); this.factory = (EntityType.EntityFactory) factory; @@ -149,12 +156,18 @@ public FabricEntityTypeBuilder entityFactory(EntityType.EntityF * Whether this entity type is summonable using the {@code /summon} command. * * @return this builder for chaining + * @deprecated use {@link EntityType.Builder#disableSummon()} */ + @Deprecated public FabricEntityTypeBuilder disableSummon() { this.summonable = false; return this; } + /** + * @deprecated use {@link EntityType.Builder#disableSaving()} + */ + @Deprecated public FabricEntityTypeBuilder disableSaving() { this.saveable = false; return this; @@ -164,7 +177,9 @@ public FabricEntityTypeBuilder disableSaving() { * Sets this entity type to be fire immune. * * @return this builder for chaining + * @deprecated use {@link EntityType.Builder#makeFireImmune()} */ + @Deprecated public FabricEntityTypeBuilder fireImmune() { this.fireImmune = true; return this; @@ -174,7 +189,9 @@ public FabricEntityTypeBuilder fireImmune() { * Sets whether this entity type can be spawned far away from a player. * * @return this builder for chaining + * @deprecated use {@link EntityType.Builder#spawnableFarFromPlayer()} */ + @Deprecated public FabricEntityTypeBuilder spawnableFarFromPlayer() { this.spawnableFarFromPlayer = true; return this; @@ -186,7 +203,9 @@ public FabricEntityTypeBuilder spawnableFarFromPlayer() { * @param dimensions the dimensions representing the entity's size * * @return this builder for chaining + * @deprecated use {@link EntityType.Builder#setDimensions(float, float)} */ + @Deprecated public FabricEntityTypeBuilder dimensions(EntityDimensions dimensions) { Objects.requireNonNull(dimensions, "Cannot set null dimensions"); this.dimensions = dimensions; @@ -218,7 +237,9 @@ public FabricEntityTypeBuilder trackable(int trackRangeBlocks, int trackedUpd * @param range the tracking range in chunks * * @return this builder for chaining + * @deprecated use {@link FabricEntityTypeBuilder#trackRangeBlocks(int)} */ + @Deprecated public FabricEntityTypeBuilder trackRangeChunks(int range) { this.trackRange = range; return this; @@ -230,16 +251,26 @@ public FabricEntityTypeBuilder trackRangeChunks(int range) { * @param range the tracking range in blocks * * @return this builder for chaining + * @deprecated use {@link FabricEntityTypeBuilder#trackRangeChunks(int)} */ + @Deprecated public FabricEntityTypeBuilder trackRangeBlocks(int range) { return trackRangeChunks((range + 15) / 16); } + /** + * @deprecated use {@link FabricEntityTypeBuilder#trackRangeBlocks(int)} + */ + @Deprecated public FabricEntityTypeBuilder trackedUpdateRate(int rate) { this.trackedUpdateRate = rate; return this; } + /** + * @deprecated use {@link FabricEntityTypeBuilder#trackRangeBlocks(int)} + */ + @Deprecated public FabricEntityTypeBuilder forceTrackedVelocityUpdates(boolean forceTrackedVelocityUpdates) { this.forceTrackedVelocityUpdates = forceTrackedVelocityUpdates; return this; @@ -250,7 +281,9 @@ public FabricEntityTypeBuilder forceTrackedVelocityUpdates(boolean forceTrack * * @param blocks the blocks the entity can spawn on * @return this builder for chaining + * @deprecated use {@link EntityType.Builder#allowSpawningInside(Block...)} */ + @Deprecated public FabricEntityTypeBuilder specificSpawnBlocks(Block... blocks) { this.specificSpawnBlocks = ImmutableSet.copyOf(blocks); return this; @@ -261,9 +294,11 @@ public FabricEntityTypeBuilder specificSpawnBlocks(Block... blocks) { * the entity cannot be spawned, and existing ones will despawn immediately. * @param requiredFeatures the features * @return this builder for chaining + * @deprecated use {@link EntityType.Builder#requires(FeatureFlag...)} */ + @Deprecated public FabricEntityTypeBuilder requires(FeatureFlag... requiredFeatures) { - this.requiredFeatures = FeatureFlags.FEATURE_MANAGER.featureSetOf(requiredFeatures); + this.requiredFeatures = requiredFeatures; return this; } @@ -271,19 +306,50 @@ public FabricEntityTypeBuilder requires(FeatureFlag... requiredFeatures) { * Creates the entity type. * * @return a new {@link EntityType} + * @deprecated use {@link EntityType.Builder#build()} */ + @Deprecated public EntityType build() { - // Modded DFU is a dream, currently not possible without screwing it up. + EntityType.Builder builder = EntityType.Builder.create(this.factory, this.spawnGroup) + .allowSpawningInside(specificSpawnBlocks.toArray(Block[]::new)) + .maxTrackingRange(this.trackRange) + .trackingTickInterval(this.trackedUpdateRate) + .setDimensions(this.dimensions.width, this.dimensions.height); + + if (!this.saveable) { + builder = builder.disableSaving(); + } - //TODO 1.20.5, new field - return new FabricEntityType<>(this.factory, this.spawnGroup, this.saveable, this.summonable, this.fireImmune, this.spawnableFarFromPlayer, this.specificSpawnBlocks, dimensions, 1, trackRange, trackedUpdateRate, forceTrackedVelocityUpdates, this.requiredFeatures); + if (!this.summonable) { + builder = builder.disableSummon(); + } + + if (this.fireImmune) { + builder = builder.makeFireImmune(); + } + + if (this.spawnableFarFromPlayer) { + builder = builder.spawnableFarFromPlayer(); + } + + if (this.requiredFeatures != null) { + builder = builder.requires(this.requiredFeatures); + } + + if (this.forceTrackedVelocityUpdates != null) { + builder = builder.alwaysUpdateVelocity(this.forceTrackedVelocityUpdates); + } + + return builder.build(null); } /** * An extended version of {@link FabricEntityTypeBuilder} with support for features on present on {@link LivingEntity living entities}, such as default attributes. * * @param Entity class. + * @deprecated use {@link EntityType.Builder#createLiving(UnaryOperator)} */ + @Deprecated public static class Living extends FabricEntityTypeBuilder { @Nullable private Supplier defaultAttributeBuilder; @@ -399,13 +465,16 @@ public FabricEntityTypeBuilder.Living specificSpawnBlocks(Block... blocks) { * * @param defaultAttributeBuilder a function to generate the default attribute builder from the entity type * @return this builder for chaining + * @deprecated use {@link FabricEntityType.Builder.Living#defaultAttributes(Supplier)} */ + @Deprecated public FabricEntityTypeBuilder.Living defaultAttributes(Supplier defaultAttributeBuilder) { Objects.requireNonNull(defaultAttributeBuilder, "Cannot set null attribute builder"); this.defaultAttributeBuilder = defaultAttributeBuilder; return this; } + @Deprecated @Override public EntityType build() { final EntityType type = super.build(); @@ -423,6 +492,7 @@ public EntityType build() { * * @param Entity class. */ + @Deprecated public static class Mob extends FabricEntityTypeBuilder.Living { private SpawnLocation spawnLocation; private Heightmap.Type restrictionHeightmap; @@ -536,7 +606,9 @@ public FabricEntityTypeBuilder.Mob defaultAttributes(SupplierThis is used by mobs to determine whether Minecraft should spawn an entity within a certain context. * * @return this builder for chaining. + * @deprecated use {@link FabricEntityType.Builder.Mob#spawnRestriction(SpawnRestriction.Location, Heightmap.Type, SpawnRestriction.SpawnPredicate)} */ + @Deprecated public FabricEntityTypeBuilder.Mob spawnRestriction(SpawnLocation spawnLocation, Heightmap.Type heightmap, SpawnRestriction.SpawnPredicate spawnPredicate) { this.spawnLocation = Objects.requireNonNull(spawnLocation, "Spawn location cannot be null."); this.restrictionHeightmap = Objects.requireNonNull(heightmap, "Heightmap type cannot be null."); diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityType.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityType.java deleted file mode 100644 index dde18eec8c..0000000000 --- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityType.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.impl.object.builder; - -import com.google.common.collect.ImmutableSet; - -import net.minecraft.block.Block; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityDimensions; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.SpawnGroup; -import net.minecraft.resource.featuretoggle.FeatureSet; - -public class FabricEntityType extends EntityType { - private final Boolean alwaysUpdateVelocity; - - public FabricEntityType(EntityType.EntityFactory factory, SpawnGroup spawnGroup, boolean bl, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet spawnBlocks, EntityDimensions entityDimensions, float field_50125, int maxTrackDistance, int trackTickInterval, Boolean alwaysUpdateVelocity, FeatureSet featureSet) { - super(factory, spawnGroup, bl, summonable, fireImmune, spawnableFarFromPlayer, spawnBlocks, entityDimensions, field_50125, maxTrackDistance, trackTickInterval, featureSet); - this.alwaysUpdateVelocity = alwaysUpdateVelocity; - } - - @Override - public boolean alwaysUpdateVelocity() { - if (alwaysUpdateVelocity != null) { - return alwaysUpdateVelocity; - } - - return super.alwaysUpdateVelocity(); - } -} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityTypeImpl.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityTypeImpl.java new file mode 100644 index 0000000000..3a563912b6 --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityTypeImpl.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.object.builder; + +import java.util.Objects; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.entity.SpawnRestriction; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.world.Heightmap; + +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityType; + +public interface FabricEntityTypeImpl { + void fabric_setAlwaysUpdateVelocity(Boolean alwaysUpdateVelocity); + + interface Builder { + void fabric_setLivingEntityBuilder(Living livingBuilder); + + void fabric_setMobEntityBuilder(Mob mobBuilder); + + static EntityType.Builder createLiving(EntityType.EntityFactory factory, SpawnGroup spawnGroup, UnaryOperator> livingBuilder) { + EntityType.Builder builder = EntityType.Builder.create(factory, spawnGroup); + Living builderImpl = new Living<>(); + livingBuilder.apply(builderImpl); + ((Builder) builder).fabric_setLivingEntityBuilder(builderImpl); + return builder; + } + + static EntityType.Builder createMob(EntityType.EntityFactory factory, SpawnGroup spawnGroup, UnaryOperator> mobBuilder) { + EntityType.Builder builder = EntityType.Builder.create(factory, spawnGroup); + Mob builderImpl = new Mob<>(); + mobBuilder.apply(builderImpl); + ((Builder) builder).fabric_setMobEntityBuilder(builderImpl); + return builder; + } + + sealed class Living implements FabricEntityType.Builder.Living permits Mob { + @Nullable + private Supplier defaultAttributeBuilder; + + @Override + public FabricEntityType.Builder.Living defaultAttributes(Supplier defaultAttributeBuilder) { + Objects.requireNonNull(defaultAttributeBuilder, "Cannot set null attribute builder"); + this.defaultAttributeBuilder = defaultAttributeBuilder; + return this; + } + + public void onBuild(EntityType type) { + if (this.defaultAttributeBuilder != null) { + FabricDefaultAttributeRegistry.register(type, this.defaultAttributeBuilder.get()); + } + } + } + + final class Mob extends Living implements FabricEntityType.Builder.Mob { + private SpawnRestriction.Location restrictionLocation; + private Heightmap.Type restrictionHeightmap; + private SpawnRestriction.SpawnPredicate spawnPredicate; + + @Override + public FabricEntityType.Builder.Mob spawnRestriction(SpawnRestriction.Location location, Heightmap.Type heightmap, SpawnRestriction.SpawnPredicate spawnPredicate) { + this.restrictionLocation = Objects.requireNonNull(location, "Location cannot be null."); + this.restrictionHeightmap = Objects.requireNonNull(heightmap, "Heightmap type cannot be null."); + this.spawnPredicate = Objects.requireNonNull(spawnPredicate, "Spawn predicate cannot be null."); + return this; + } + + @Override + public FabricEntityType.Builder.Mob defaultAttributes(Supplier defaultAttributeBuilder) { + super.defaultAttributes(defaultAttributeBuilder); + return this; + } + + public void onBuild(EntityType type) { + super.onBuild(type); + + if (this.spawnPredicate != null) { + SpawnRestriction.register(type, this.restrictionLocation, this.restrictionHeightmap, this.spawnPredicate); + } + } + } + } +} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/BlockEntityTypeBuilderMixin.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/BlockEntityTypeBuilderMixin.java new file mode 100644 index 0000000000..5d9342ec1f --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/BlockEntityTypeBuilderMixin.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.object.builder; + +import com.mojang.datafixers.types.Type; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; + +import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityType; + +@Mixin(BlockEntityType.Builder.class) +public abstract class BlockEntityTypeBuilderMixin implements FabricBlockEntityType.Builder { + @Shadow + public abstract BlockEntityType build(Type type); + + @Override + public BlockEntityType build() { + return build(null); + } +} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeBuilderMixin.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeBuilderMixin.java new file mode 100644 index 0000000000..286dfdde15 --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeBuilderMixin.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.object.builder; + +import java.util.Objects; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.datafixers.DSL; +import com.mojang.datafixers.types.Type; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.mob.MobEntity; + +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityType; +import net.fabricmc.fabric.impl.object.builder.FabricEntityTypeImpl; + +@Mixin(EntityType.Builder.class) +public abstract class EntityTypeBuilderMixin implements FabricEntityType.Builder, FabricEntityTypeImpl.Builder { + @Shadow + public abstract EntityType build(String id); + + @Unique + private Boolean alwaysUpdateVelocity = null; + + @Unique + private FabricEntityTypeImpl.Builder.Living livingBuilder = null; + @Unique + private FabricEntityTypeImpl.Builder.Mob mobBuilder = null; + + @Override + public EntityType.Builder alwaysUpdateVelocity(boolean forceTrackedVelocityUpdates) { + alwaysUpdateVelocity = forceTrackedVelocityUpdates; + return (EntityType.Builder) (Object) this; + } + + @Override + public EntityType build() { + return build(null); + } + + @Inject(method = "build", at = @At("RETURN")) + private void applyChildBuilders(String id, CallbackInfoReturnable> cir) { + if (!(cir.getReturnValue() instanceof FabricEntityTypeImpl entityType)) { + throw new IllegalStateException(); + } + + entityType.fabric_setAlwaysUpdateVelocity(alwaysUpdateVelocity); + + if (livingBuilder != null) { + livingBuilder.onBuild(castLiving(cir.getReturnValue())); + } + + if (mobBuilder != null) { + mobBuilder.onBuild(castMob(cir.getReturnValue())); + } + } + + @SuppressWarnings("unchecked") + @Unique + private static EntityType castLiving(EntityType type) { + return (EntityType) type; + } + + @SuppressWarnings("unchecked") + @Unique + private static EntityType castMob(EntityType type) { + return (EntityType) type; + } + + @WrapOperation(method = "build", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Util;getChoiceType(Lcom/mojang/datafixers/DSL$TypeReference;Ljava/lang/String;)Lcom/mojang/datafixers/types/Type;")) + private @Nullable Type allowNullId(DSL.TypeReference typeReference, String id, Operation> original) { + if (id == null) { + return null; + } + + return original.call(typeReference, id); + } + + @Override + public void fabric_setLivingEntityBuilder(FabricEntityTypeImpl.Builder.Living livingBuilder) { + Objects.requireNonNull(livingBuilder, "Cannot set null living entity builder"); + this.livingBuilder = livingBuilder; + } + + @Override + public void fabric_setMobEntityBuilder(FabricEntityTypeImpl.Builder.Mob mobBuilder) { + Objects.requireNonNull(mobBuilder, "Cannot set null mob entity builder"); + this.mobBuilder = mobBuilder; + } +} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeMixin.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeMixin.java new file mode 100644 index 0000000000..4d493d6d61 --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeMixin.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.object.builder; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.entity.EntityType; + +import net.fabricmc.fabric.impl.object.builder.FabricEntityTypeImpl; + +@Mixin(EntityType.class) +public abstract class EntityTypeMixin implements FabricEntityTypeImpl { + @Unique + private Boolean alwaysUpdateVelocity; + + @Inject(method = "alwaysUpdateVelocity", at = @At("HEAD"), cancellable = true) + public void alwaysUpdateVelocity(CallbackInfoReturnable cir) { + if (alwaysUpdateVelocity != null) { + cir.setReturnValue(alwaysUpdateVelocity); + } + } + + @Override + public void fabric_setAlwaysUpdateVelocity(Boolean alwaysUpdateVelocity) { + this.alwaysUpdateVelocity = alwaysUpdateVelocity; + } +} diff --git a/fabric-object-builder-api-v1/src/main/resources/fabric-object-builder-v1.mixins.json b/fabric-object-builder-api-v1/src/main/resources/fabric-object-builder-v1.mixins.json index a5c4f877c0..22d799f1ed 100644 --- a/fabric-object-builder-api-v1/src/main/resources/fabric-object-builder-v1.mixins.json +++ b/fabric-object-builder-api-v1/src/main/resources/fabric-object-builder-v1.mixins.json @@ -5,9 +5,12 @@ "mixins": [ "AbstractBlockAccessor", "AbstractBlockSettingsAccessor", + "BlockEntityTypeBuilderMixin", "DefaultAttributeRegistryAccessor", "DefaultAttributeRegistryMixin", "DetectorRailBlockMixin", + "EntityTypeBuilderMixin", + "EntityTypeMixin", "PersistentStateManagerMixin", "TradeOffersTypeAwareBuyForOneEmeraldFactoryMixin" ], diff --git a/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json b/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json index 940c46c6d7..8aa8fb234f 100644 --- a/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json +++ b/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json @@ -29,6 +29,10 @@ ], "accessWidener" : "fabric-object-builder-api-v1.accesswidener", "custom": { - "fabric-api:module-lifecycle": "stable" + "fabric-api:module-lifecycle": "stable", + "loom:injected_interfaces": { + "net/minecraft/class_1299\u0024class_1300": ["net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType\u0024Builder"], + "net/minecraft/class_2591\u0024class_2592": ["net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityType\u0024Builder"] + } } } diff --git a/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java b/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java new file mode 100644 index 0000000000..f3f477518c --- /dev/null +++ b/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.object.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import net.minecraft.Bootstrap; +import net.minecraft.SharedConstants; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.entity.SpawnRestriction; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.attribute.DefaultAttributeRegistry; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.passive.PigEntity; +import net.minecraft.world.Heightmap; + +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityType; + +public class FabricEntityTypeTest { + @BeforeAll + static void beforeAll() { + SharedConstants.createGameVersion(); + Bootstrap.initialize(); + } + + @Test + void buildEntityType() { + EntityType type = EntityType.Builder.create(SpawnGroup.MISC) + .alwaysUpdateVelocity(true) + .build(); + + assertNotNull(type); + assertTrue(type.alwaysUpdateVelocity()); + } + + @Test + void buildLivingEntityType() { + EntityType type = FabricEntityType.Builder.createLiving((t, w) -> null, SpawnGroup.MISC, living -> living + .defaultAttributes(FabricEntityTypeTest::createAttributes) + ).build(); + + assertNotNull(type); + assertNotNull(DefaultAttributeRegistry.get(type)); + } + + @Test + void buildMobEntityType() { + EntityType type = FabricEntityType.Builder.createMob((t, w) -> null, SpawnGroup.MISC, mob -> mob + .spawnRestriction(SpawnRestriction.Location.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, PigEntity::canMobSpawn) + .defaultAttributes(FabricEntityTypeTest::createAttributes) + ).build(); + + assertNotNull(type); + assertEquals(SpawnRestriction.Location.ON_GROUND, SpawnRestriction.getLocation(type)); + assertNotNull(DefaultAttributeRegistry.get(type)); + } + + private static DefaultAttributeContainer.Builder createAttributes() { + return MobEntity.createMobAttributes() + .add(EntityAttributes.GENERIC_MAX_HEALTH, 10.0) + .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25); + } +} From 6793dde11728b6a722e03300b4c8ffdb61ee5610 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Wed, 10 Apr 2024 22:24:01 +0100 Subject: [PATCH 4/7] Fix EntityType.Builder for 1.20.5 --- .../api/object/builder/v1/entity/FabricEntityType.java | 3 ++- .../object/builder/v1/entity/FabricEntityTypeBuilder.java | 2 +- .../fabric/impl/object/builder/FabricEntityTypeImpl.java | 5 +++-- .../fabric/test/object/builder/FabricEntityTypeTest.java | 8 ++++++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType.java index 7f60377ac3..69ed4d52b1 100644 --- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType.java +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType.java @@ -23,6 +23,7 @@ import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.SpawnGroup; +import net.minecraft.entity.SpawnLocation; import net.minecraft.entity.SpawnRestriction; import net.minecraft.entity.attribute.DefaultAttributeContainer; import net.minecraft.entity.mob.MobEntity; @@ -111,7 +112,7 @@ interface Mob extends Living { * * @return this builder for chaining. */ - Mob spawnRestriction(SpawnRestriction.Location location, Heightmap.Type heightmap, SpawnRestriction.SpawnPredicate spawnPredicate); + Mob spawnRestriction(SpawnLocation location, Heightmap.Type heightmap, SpawnRestriction.SpawnPredicate spawnPredicate); /** * Sets the default attributes for a type of mob entity. diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java index da52194975..9c0c93e074 100644 --- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java @@ -314,7 +314,7 @@ public EntityType build() { .allowSpawningInside(specificSpawnBlocks.toArray(Block[]::new)) .maxTrackingRange(this.trackRange) .trackingTickInterval(this.trackedUpdateRate) - .setDimensions(this.dimensions.width, this.dimensions.height); + .dimensions(this.dimensions.width(), this.dimensions.height()); if (!this.saveable) { builder = builder.disableSaving(); diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityTypeImpl.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityTypeImpl.java index 3a563912b6..3d57204b83 100644 --- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityTypeImpl.java +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityTypeImpl.java @@ -25,6 +25,7 @@ import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.SpawnGroup; +import net.minecraft.entity.SpawnLocation; import net.minecraft.entity.SpawnRestriction; import net.minecraft.entity.attribute.DefaultAttributeContainer; import net.minecraft.entity.mob.MobEntity; @@ -76,12 +77,12 @@ public void onBuild(EntityType type) { } final class Mob extends Living implements FabricEntityType.Builder.Mob { - private SpawnRestriction.Location restrictionLocation; + private SpawnLocation restrictionLocation; private Heightmap.Type restrictionHeightmap; private SpawnRestriction.SpawnPredicate spawnPredicate; @Override - public FabricEntityType.Builder.Mob spawnRestriction(SpawnRestriction.Location location, Heightmap.Type heightmap, SpawnRestriction.SpawnPredicate spawnPredicate) { + public FabricEntityType.Builder.Mob spawnRestriction(SpawnLocation location, Heightmap.Type heightmap, SpawnRestriction.SpawnPredicate spawnPredicate) { this.restrictionLocation = Objects.requireNonNull(location, "Location cannot be null."); this.restrictionHeightmap = Objects.requireNonNull(heightmap, "Heightmap type cannot be null."); this.spawnPredicate = Objects.requireNonNull(spawnPredicate, "Spawn predicate cannot be null."); diff --git a/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java b/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java index f3f477518c..42f27a8f6b 100644 --- a/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java +++ b/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java @@ -20,6 +20,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import net.minecraft.entity.SpawnLocation; + +import net.minecraft.entity.SpawnLocationTypes; + import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -69,12 +73,12 @@ void buildLivingEntityType() { @Test void buildMobEntityType() { EntityType type = FabricEntityType.Builder.createMob((t, w) -> null, SpawnGroup.MISC, mob -> mob - .spawnRestriction(SpawnRestriction.Location.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, PigEntity::canMobSpawn) + .spawnRestriction(SpawnLocationTypes.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, PigEntity::canMobSpawn) .defaultAttributes(FabricEntityTypeTest::createAttributes) ).build(); assertNotNull(type); - assertEquals(SpawnRestriction.Location.ON_GROUND, SpawnRestriction.getLocation(type)); + assertEquals(SpawnLocationTypes.ON_GROUND, SpawnRestriction.getLocation(type)); assertNotNull(DefaultAttributeRegistry.get(type)); } From 8f5205a8a127f86c4938bce1a101f4c9f528dc42 Mon Sep 17 00:00:00 2001 From: Syst3ms Date: Thu, 11 Apr 2024 00:02:11 +0200 Subject: [PATCH 5/7] Enchantment API (#3627) * ALLOW_ENCHANTING event * Intrinsic enchantments + testmod also fixed a bug in the testmod that prevented the custom damage handler from ever working * Item-based override mechanism * Replaces part of the use cases of the event with a convenient method to override in FabricItem. * Updated and tested the testmod. * javadoc * Move event logic to FabricItemStack * oops * Simplify mixin * Replace ActionResult with TriState * Use TriState in testmod * requests * Clarify jdoc * Ship without intrinsic enchantments at first * Checkstyle * Checkstyle --------- Co-authored-by: modmuss50 --- .../fabric/api/item/v1/EnchantingContext.java | 55 ++++++++++++ .../fabric/api/item/v1/EnchantmentEvents.java | 84 +++++++++++++++++++ .../fabric/api/item/v1/FabricItem.java | 21 +++++ .../fabric/api/item/v1/FabricItemStack.java | 23 +++++ .../mixin/item/AnvilScreenHandlerMixin.java | 50 +++++++++++ .../mixin/item/EnchantCommandMixin.java | 38 +++++++++ .../EnchantRandomlyLootFunctionMixin.java | 38 +++++++++ .../mixin/item/EnchantmentHelperMixin.java | 38 +++++++++ .../resources/fabric-item-api-v1.mixins.json | 4 + .../fabric/test/item/CustomDamageTest.java | 42 +++++++--- .../data/minecraft/tags/items/pickaxes.json | 6 ++ .../object/builder/FabricEntityTypeTest.java | 5 +- 12 files changed, 390 insertions(+), 14 deletions(-) create mode 100644 fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantingContext.java create mode 100644 fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantmentEvents.java create mode 100644 fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/AnvilScreenHandlerMixin.java create mode 100644 fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/EnchantCommandMixin.java create mode 100644 fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/EnchantRandomlyLootFunctionMixin.java create mode 100644 fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/EnchantmentHelperMixin.java create mode 100644 fabric-item-api-v1/src/testmod/resources/data/minecraft/tags/items/pickaxes.json diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantingContext.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantingContext.java new file mode 100644 index 0000000000..8b55209893 --- /dev/null +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantingContext.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.item.v1; + +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.random.Random; + +/* + * There is one context for each vanilla call to Enchantment#isAcceptableItem. The reason why RANDOM_ENCHANTMENT + * feels like a kitchen sink is because it corresponds to the one in EnchantmentHelper, which is shared across multiple + * uses. + * + * This also gets in the way of adding further context (nullable Player and BlockPos have been suggested + * in the past). It's not impossible to do so, but a probably a bit more brittle. + */ +/** + * An enum that describes the various contexts in which the game checks whether an enchantment can be applied to an item. + */ +public enum EnchantingContext { + /** + * When generating a random enchantment for the item. This includes the enchanting table, random + * mob equipment, and the {@code enchant_with_levels} loot function. + * + * @see EnchantmentHelper#generateEnchantments(Random, ItemStack, int, boolean) + */ + RANDOM_ENCHANTMENT, + /** + * When trying to apply an enchantment in an anvil. + */ + ANVIL, + /** + * When using the {@code /enchant} command. + */ + ENCHANT_COMMAND, + /** + * When randomly enchanting an item using the {@code enchant_randomly} loot function without a list of enchantments + * to choose from. + */ + LOOT_RANDOM_ENCHANTMENT +} diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantmentEvents.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantmentEvents.java new file mode 100644 index 0000000000..5f624ff6ac --- /dev/null +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantmentEvents.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.item.v1; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.item.ItemStack; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.fabricmc.fabric.api.util.TriState; + +/** + * Events relating to enchantments, allowing for finer control of what enchantments can apply to different items. + */ +public final class EnchantmentEvents { + private EnchantmentEvents() { } + + /** + * An event that allows overriding whether an {@link Enchantment} can be applied to an {@link ItemStack}. + * + *

This should only be used to modify the behavior of external items with regards to external enchantments, + * where 'external' means either vanilla or from another mod. For instance, a mod might allow enchanting a pickaxe + * with Sharpness (and only Sharpness) under certain specific conditions.

+ * + *

To modify the behavior of your own modded enchantments, use {@link Enchantment#isAcceptableItem(ItemStack)} instead. + * To modify the behavior of your own modded items, use {@link FabricItem#canBeEnchantedWith(ItemStack, Enchantment, EnchantingContext)} instead. + * Note that this event triggers before {@link FabricItem#canBeEnchantedWith(ItemStack, Enchantment, EnchantingContext)}, + * and that method will only be called if no listeners override it.

+ * + *

Note that allowing an enchantment using this event does not guarantee the item will receive that enchantment, + * only that it isn't forbidden from doing so.

+ * + * @see AllowEnchanting#allowEnchanting(Enchantment, ItemStack, EnchantingContext) + * @see Enchantment#isAcceptableItem(ItemStack) + * @see FabricItem#canBeEnchantedWith(ItemStack, Enchantment, EnchantingContext) + */ + public static final Event ALLOW_ENCHANTING = EventFactory.createArrayBacked( + AllowEnchanting.class, + callbacks -> (enchantment, target, context) -> { + for (AllowEnchanting callback : callbacks) { + TriState result = callback.allowEnchanting(enchantment, target, context); + + if (result != TriState.DEFAULT) { + return result; + } + } + + return TriState.DEFAULT; + } + ); + + @FunctionalInterface + public interface AllowEnchanting { + /** + * Checks whether an {@link Enchantment} should be applied to a given {@link ItemStack}. + * + * @param enchantment the enchantment that may be applied + * @param target the target item + * @param enchantingContext the enchanting context in which this check is made + * @return {@link TriState#TRUE} if the enchantment may be applied, {@link TriState#FALSE} if it + * may not, {@link TriState#DEFAULT} to fall back to other callbacks/vanilla behavior + * @see EnchantingContext + */ + TriState allowEnchanting( + Enchantment enchantment, + ItemStack target, + EnchantingContext enchantingContext + ); + } +} diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItem.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItem.java index 8cb80e2e63..a029eb09f7 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItem.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItem.java @@ -17,6 +17,7 @@ package net.fabricmc.fabric.api.item.v1; import net.minecraft.component.type.AttributeModifiersComponent; +import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -107,6 +108,26 @@ default ItemStack getRecipeRemainder(ItemStack stack) { return ((Item) this).hasRecipeRemainder() ? ((Item) this).getRecipeRemainder().getDefaultStack() : ItemStack.EMPTY; } + /** + * Determines if the item is allowed to receive an {@link Enchantment}. This can be used to manually override what + * enchantments a modded item is able to receive. + * + *

For example, one might want a modded item to be able to receive Unbreaking, but not Mending, which cannot be + * achieved with the vanilla tag system alone. Alternatively, one might want to do the same thing with enchantments + * from other mods, which don't have a similar tag system in general.

+ * + *

Note that this method is only called after the {@link EnchantmentEvents#ALLOW_ENCHANTING} event, and + * only if none of the listeners to that event override the result.

+ * + * @param stack the current stack + * @param enchantment the enchantment to check + * @param context the context in which the enchantment is being checked + * @return whether the enchantment is allowed to apply to the stack + */ + default boolean canBeEnchantedWith(ItemStack stack, Enchantment enchantment, EnchantingContext context) { + return enchantment.isAcceptableItem(stack); + } + /** * Fabric-provided extensions for {@link Item.Settings}. * This interface is automatically implemented on all item settings via Mixin and interface injection. diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItemStack.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItemStack.java index 0c646a6aad..50c3959a25 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItemStack.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/FabricItemStack.java @@ -16,9 +16,12 @@ package net.fabricmc.fabric.api.item.v1; +import net.minecraft.enchantment.Enchantment; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.fabricmc.fabric.api.util.TriState; + /* * Fabric-provided extensions for {@link ItemStack}. * This interface is automatically implemented on all item stacks via Mixin and interface injection. @@ -36,4 +39,24 @@ public interface FabricItemStack { default ItemStack getRecipeRemainder() { return ((ItemStack) this).getItem().getRecipeRemainder((ItemStack) this); } + + /** + * Determines whether this {@link ItemStack} can be enchanted with the given {@link Enchantment}. + * + *

When checking whether an enchantment can be applied to an {@link ItemStack}, use this method instead of + * {@link Enchantment#isAcceptableItem(ItemStack)}

+ * + * @param enchantment the enchantment to check + * @param context the context in which the enchantment is being checked + * @return whether the enchantment is allowed to apply to the stack + * @see FabricItem#canBeEnchantedWith(ItemStack, Enchantment, EnchantingContext) + */ + default boolean canBeEnchantedWith(Enchantment enchantment, EnchantingContext context) { + TriState result = EnchantmentEvents.ALLOW_ENCHANTING.invoker().allowEnchanting( + enchantment, + (ItemStack) this, + context + ); + return result.orElseGet(() -> ((ItemStack) this).getItem().canBeEnchantedWith((ItemStack) this, enchantment, context)); + } } diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/AnvilScreenHandlerMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/AnvilScreenHandlerMixin.java new file mode 100644 index 0000000000..15771f78ea --- /dev/null +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/AnvilScreenHandlerMixin.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.item; + +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.AnvilScreenHandler; +import net.minecraft.screen.ForgingScreenHandler; +import net.minecraft.screen.ScreenHandlerContext; +import net.minecraft.screen.ScreenHandlerType; + +import net.fabricmc.fabric.api.item.v1.EnchantingContext; + +@Mixin(AnvilScreenHandler.class) +abstract class AnvilScreenHandlerMixin extends ForgingScreenHandler { + AnvilScreenHandlerMixin(@Nullable ScreenHandlerType type, int syncId, PlayerInventory playerInventory, ScreenHandlerContext context) { + super(type, syncId, playerInventory, context); + } + + @Redirect( + method = "updateResult", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/enchantment/Enchantment;isAcceptableItem(Lnet/minecraft/item/ItemStack;)Z" + ) + ) + private boolean callAllowEnchantingEvent(Enchantment instance, ItemStack stack) { + return stack.canBeEnchantedWith(instance, EnchantingContext.ANVIL); + } +} diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/EnchantCommandMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/EnchantCommandMixin.java new file mode 100644 index 0000000000..2f945c282e --- /dev/null +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/EnchantCommandMixin.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.item; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.item.ItemStack; +import net.minecraft.server.command.EnchantCommand; + +import net.fabricmc.fabric.api.item.v1.EnchantingContext; + +@Mixin(EnchantCommand.class) +abstract class EnchantCommandMixin { + @Redirect( + method = "execute", + at = @At(value = "INVOKE", target = "Lnet/minecraft/enchantment/Enchantment;isAcceptableItem(Lnet/minecraft/item/ItemStack;)Z") + ) + private static boolean callAllowEnchantingEvent(Enchantment instance, ItemStack stack) { + return stack.canBeEnchantedWith(instance, EnchantingContext.ENCHANT_COMMAND); + } +} diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/EnchantRandomlyLootFunctionMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/EnchantRandomlyLootFunctionMixin.java new file mode 100644 index 0000000000..d884bb01b3 --- /dev/null +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/EnchantRandomlyLootFunctionMixin.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.item; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.item.ItemStack; +import net.minecraft.loot.function.EnchantRandomlyLootFunction; + +import net.fabricmc.fabric.api.item.v1.EnchantingContext; + +@Mixin(EnchantRandomlyLootFunction.class) +abstract class EnchantRandomlyLootFunctionMixin { + @Redirect( + method = "method_53327", + at = @At(value = "INVOKE", target = "Lnet/minecraft/enchantment/Enchantment;isAcceptableItem(Lnet/minecraft/item/ItemStack;)Z") + ) + private static boolean callAllowEnchantingEvent(Enchantment instance, ItemStack stack) { + return stack.canBeEnchantedWith(instance, EnchantingContext.LOOT_RANDOM_ENCHANTMENT); + } +} diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/EnchantmentHelperMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/EnchantmentHelperMixin.java new file mode 100644 index 0000000000..b06fe3284d --- /dev/null +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/EnchantmentHelperMixin.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.item; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.item.ItemStack; + +import net.fabricmc.fabric.api.item.v1.EnchantingContext; + +@Mixin(EnchantmentHelper.class) +abstract class EnchantmentHelperMixin { + @Redirect( + method = "getPossibleEntries", + at = @At(value = "INVOKE", target = "Lnet/minecraft/enchantment/Enchantment;isAcceptableItem(Lnet/minecraft/item/ItemStack;)Z") + ) + private static boolean useCustomEnchantingChecks(Enchantment instance, ItemStack stack) { + return stack.canBeEnchantedWith(instance, EnchantingContext.RANDOM_ENCHANTMENT); + } +} diff --git a/fabric-item-api-v1/src/main/resources/fabric-item-api-v1.mixins.json b/fabric-item-api-v1/src/main/resources/fabric-item-api-v1.mixins.json index a56c7c35b2..0a0e6e667c 100644 --- a/fabric-item-api-v1/src/main/resources/fabric-item-api-v1.mixins.json +++ b/fabric-item-api-v1/src/main/resources/fabric-item-api-v1.mixins.json @@ -4,7 +4,11 @@ "compatibilityLevel": "JAVA_17", "mixins": [ "AbstractFurnaceBlockEntityMixin", + "AnvilScreenHandlerMixin", "BrewingStandBlockEntityMixin", + "EnchantCommandMixin", + "EnchantmentHelperMixin", + "EnchantRandomlyLootFunctionMixin", "ItemMixin", "ItemSettingsMixin", "ItemStackMixin", diff --git a/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/CustomDamageTest.java b/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/CustomDamageTest.java index 1db6a5253a..1b39db7f48 100644 --- a/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/CustomDamageTest.java +++ b/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/CustomDamageTest.java @@ -17,8 +17,12 @@ package net.fabricmc.fabric.test.item; import net.minecraft.component.DataComponentType; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.Enchantments; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.item.PickaxeItem; import net.minecraft.item.ToolMaterials; import net.minecraft.network.codec.PacketCodecs; @@ -30,21 +34,14 @@ import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.item.v1.CustomDamageHandler; +import net.fabricmc.fabric.api.item.v1.EnchantingContext; +import net.fabricmc.fabric.api.item.v1.EnchantmentEvents; import net.fabricmc.fabric.api.registry.FuelRegistry; +import net.fabricmc.fabric.api.util.TriState; public class CustomDamageTest implements ModInitializer { - public static final Item WEIRD_PICK = new WeirdPick(); public static final DataComponentType WEIRD = Registry.register(Registries.DATA_COMPONENT_TYPE, new Identifier("fabric-item-api-v1-testmod", "weird"), DataComponentType.builder().codec(Codecs.NONNEGATIVE_INT).packetCodec(PacketCodecs.VAR_INT).build()); - - @Override - public void onInitialize() { - Registry.register(Registries.ITEM, new Identifier("fabric-item-api-v1-testmod", "weird_pickaxe"), WEIRD_PICK); - FuelRegistry.INSTANCE.add(WEIRD_PICK, 200); - // TODO 1.20.5 - // FabricBrewingRecipeRegistry.registerPotionRecipe(Potions.WATER, Ingredient.ofItems(WEIRD_PICK), Potions.AWKWARD); - } - public static final CustomDamageHandler WEIRD_DAMAGE_HANDLER = (stack, amount, entity, slot, breakCallback) -> { // If sneaking, apply all damage to vanilla. Otherwise, increment a tag on the stack by one and don't apply any damage if (entity.isSneaking()) { @@ -54,6 +51,25 @@ public void onInitialize() { return 0; } }; + // Do this static init *after* the damage handler otherwise it's still null while inside the constructor + public static final Item WEIRD_PICK = new WeirdPick(); + + @Override + public void onInitialize() { + Registry.register(Registries.ITEM, new Identifier("fabric-item-api-v1-testmod", "weird_pickaxe"), WEIRD_PICK); + FuelRegistry.INSTANCE.add(WEIRD_PICK, 200); + // TODO 1.20.5 + // FabricBrewingRecipeRegistry.registerPotionRecipe(Potions.WATER, Ingredient.ofItems(WEIRD_PICK), Potions.AWKWARD); + EnchantmentEvents.ALLOW_ENCHANTING.register(((enchantment, target, enchantingContext) -> { + if (target.isOf(Items.DIAMOND_PICKAXE) + && enchantment == Enchantments.SHARPNESS + && EnchantmentHelper.hasSilkTouch(target)) { + return TriState.TRUE; + } + + return TriState.DEFAULT; + })); + } public static class WeirdPick extends PickaxeItem { protected WeirdPick() { @@ -77,5 +93,11 @@ public ItemStack getRecipeRemainder(ItemStack stack) { return ItemStack.EMPTY; } + + @Override + public boolean canBeEnchantedWith(ItemStack stack, Enchantment enchantment, EnchantingContext context) { + return context == EnchantingContext.ANVIL && enchantment == Enchantments.FIRE_ASPECT + || enchantment != Enchantments.FORTUNE && super.canBeEnchantedWith(stack, enchantment, context); + } } } diff --git a/fabric-item-api-v1/src/testmod/resources/data/minecraft/tags/items/pickaxes.json b/fabric-item-api-v1/src/testmod/resources/data/minecraft/tags/items/pickaxes.json new file mode 100644 index 0000000000..ff5e7c4601 --- /dev/null +++ b/fabric-item-api-v1/src/testmod/resources/data/minecraft/tags/items/pickaxes.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "fabric-item-api-v1-testmod:weird_pickaxe" + ] +} \ No newline at end of file diff --git a/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java b/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java index 42f27a8f6b..511b820836 100644 --- a/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java +++ b/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java @@ -20,10 +20,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import net.minecraft.entity.SpawnLocation; - -import net.minecraft.entity.SpawnLocationTypes; - import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -33,6 +29,7 @@ import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.SpawnGroup; +import net.minecraft.entity.SpawnLocationTypes; import net.minecraft.entity.SpawnRestriction; import net.minecraft.entity.attribute.DefaultAttributeContainer; import net.minecraft.entity.attribute.DefaultAttributeRegistry; From c5fc38b3f7ba927819a16ba8d619a50a948bb96e Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Sun, 14 Apr 2024 21:26:09 +0900 Subject: [PATCH 6/7] Finish port to 1.20.5-pre1 (#3706) * Buildscript changes * Particle API: port and some refactor * Add support for Ingredient in FabricBrewingRecipeRegistry * Add private ctor to ClientPlayerBlockBreakEvents Not related to port, but something I've found during the process. Also adds final to CommonLifecycleEvents. * Fix Sound API testmod * Fix broken javadocs * Codec-related changes * Document behavior of SUCCESS_NO_ITEM_USED in UseEntityCallback * Add getEnabledFeatures * checkstyle --- .../BrewingRecipeRegistryBuilderCallback.java | 43 ------------ .../FabricBrewingRecipeRegistryBuilder.java | 70 +++++++++++++++++++ .../BrewingRecipeRegistryBuilderMixin.java | 65 +++++++++++++++-- .../src/main/resources/fabric.mod.json | 5 +- .../content/registry/ContentRegistryTest.java | 19 +++-- .../player/ClientPlayerBlockBreakEvents.java | 5 +- .../api/event/player/UseEntityCallback.java | 2 +- .../fabric/api/item/v1/EnchantingContext.java | 3 +- .../fabric/test/item/CustomDamageTest.java | 5 +- .../lifecycle/v1/CommonLifecycleEvents.java | 2 +- .../FabricDefaultAttributeRegistry.java | 4 +- .../v1/entity/FabricEntityTypeBuilder.java | 10 +-- .../particle/v1/ParticleFactoryRegistry.java | 3 + .../api/particle/v1/FabricParticleTypes.java | 33 ++++----- .../test/particle/ParticleTestSetup.java | 2 +- .../builtin/CustomDataIngredient.java | 16 +---- .../fabric/test/sound/client/SineStream.java | 2 +- .../fabric/impl/transfer/VariantCodecs.java | 11 ++- gradle.properties | 4 +- settings.gradle | 2 +- 20 files changed, 198 insertions(+), 108 deletions(-) delete mode 100644 fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/api/registry/BrewingRecipeRegistryBuilderCallback.java create mode 100644 fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/api/registry/FabricBrewingRecipeRegistryBuilder.java diff --git a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/api/registry/BrewingRecipeRegistryBuilderCallback.java b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/api/registry/BrewingRecipeRegistryBuilderCallback.java deleted file mode 100644 index f167a77006..0000000000 --- a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/api/registry/BrewingRecipeRegistryBuilderCallback.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.api.registry; - -import net.minecraft.recipe.BrewingRecipeRegistry; - -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; - -/** - * Use this event to register custom brewing recipes. - */ -public interface BrewingRecipeRegistryBuilderCallback { - /** - * An event that is called when the brewing recipe registry is being built. - */ - Event BUILD = EventFactory.createArrayBacked(BrewingRecipeRegistryBuilderCallback.class, listeners -> builder -> { - for (BrewingRecipeRegistryBuilderCallback listener : listeners) { - listener.build(builder); - } - }); - - /** - * Called when the brewing recipe registry is being built. - * - * @param builder the {@link BrewingRecipeRegistry} instance - */ - void build(BrewingRecipeRegistry.class_9665 builder); -} diff --git a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/api/registry/FabricBrewingRecipeRegistryBuilder.java b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/api/registry/FabricBrewingRecipeRegistryBuilder.java new file mode 100644 index 0000000000..1f8d540a1c --- /dev/null +++ b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/api/registry/FabricBrewingRecipeRegistryBuilder.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.registry; + +import net.minecraft.item.Item; +import net.minecraft.potion.Potion; +import net.minecraft.recipe.BrewingRecipeRegistry; +import net.minecraft.recipe.Ingredient; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.resource.featuretoggle.FeatureSet; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; + +/** + * An extension of {@link BrewingRecipeRegistry.Builder} to support ingredients. + */ +public interface FabricBrewingRecipeRegistryBuilder { + /** + * An event that is called when the brewing recipe registry is being built. + */ + Event BUILD = EventFactory.createArrayBacked(FabricBrewingRecipeRegistryBuilder.BuildCallback.class, listeners -> builder -> { + for (FabricBrewingRecipeRegistryBuilder.BuildCallback listener : listeners) { + listener.build(builder); + } + }); + + default void registerItemRecipe(Item input, Ingredient ingredient, Item output) { + throw new AssertionError("Must be implemented via interface injection"); + } + + default void registerPotionRecipe(RegistryEntry input, Ingredient ingredient, RegistryEntry output) { + throw new AssertionError("Must be implemented via interface injection"); + } + + default void registerRecipes(Ingredient ingredient, RegistryEntry potion) { + throw new AssertionError("Must be implemented via interface injection"); + } + + default FeatureSet getEnabledFeatures() { + throw new AssertionError("Must be implemented via interface injection"); + } + + /** + * Use this event to register custom brewing recipes. + */ + @FunctionalInterface + interface BuildCallback { + /** + * Called when the brewing recipe registry is being built. + * + * @param builder the {@link BrewingRecipeRegistry} instance + */ + void build(BrewingRecipeRegistry.Builder builder); + } +} diff --git a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/mixin/content/registry/BrewingRecipeRegistryBuilderMixin.java b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/mixin/content/registry/BrewingRecipeRegistryBuilderMixin.java index cf5c0f0c46..4c85965142 100644 --- a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/mixin/content/registry/BrewingRecipeRegistryBuilderMixin.java +++ b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/mixin/content/registry/BrewingRecipeRegistryBuilderMixin.java @@ -16,19 +16,74 @@ package net.fabricmc.fabric.mixin.content.registry; +import java.util.List; + +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import net.minecraft.item.Item; +import net.minecraft.potion.Potion; +import net.minecraft.potion.Potions; import net.minecraft.recipe.BrewingRecipeRegistry; +import net.minecraft.recipe.Ingredient; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.resource.featuretoggle.FeatureSet; + +import net.fabricmc.fabric.api.registry.FabricBrewingRecipeRegistryBuilder; -import net.fabricmc.fabric.api.registry.BrewingRecipeRegistryBuilderCallback; +@Mixin(BrewingRecipeRegistry.Builder.class) +public abstract class BrewingRecipeRegistryBuilderMixin implements FabricBrewingRecipeRegistryBuilder { + @Shadow + @Final + private FeatureSet enabledFeatures; + + @Shadow + private static void assertPotion(Item potionType) { + } -@Mixin(BrewingRecipeRegistry.class_9665.class) -public class BrewingRecipeRegistryBuilderMixin { - @Inject(method = "method_59701", at = @At("HEAD")) + @Shadow + @Final + private List> itemRecipes; + + @Shadow + @Final + private List> potionRecipes; + + @Inject(method = "build", at = @At("HEAD")) private void build(CallbackInfoReturnable cir) { - BrewingRecipeRegistryBuilderCallback.BUILD.invoker().build((BrewingRecipeRegistry.class_9665) (Object) this); + FabricBrewingRecipeRegistryBuilder.BUILD.invoker().build((BrewingRecipeRegistry.Builder) (Object) this); + } + + @Override + public void registerItemRecipe(Item input, Ingredient ingredient, Item output) { + if (input.isEnabled(this.enabledFeatures) && output.isEnabled(this.enabledFeatures)) { + assertPotion(input); + assertPotion(output); + this.itemRecipes.add(new BrewingRecipeRegistry.Recipe<>(input.getRegistryEntry(), ingredient, output.getRegistryEntry())); + } + } + + @Override + public void registerPotionRecipe(RegistryEntry input, Ingredient ingredient, RegistryEntry output) { + if (input.value().isEnabled(this.enabledFeatures) && output.value().isEnabled(this.enabledFeatures)) { + this.potionRecipes.add(new BrewingRecipeRegistry.Recipe<>(input, ingredient, output)); + } + } + + @Override + public void registerRecipes(Ingredient ingredient, RegistryEntry potion) { + if (potion.value().isEnabled(this.enabledFeatures)) { + this.registerPotionRecipe(Potions.WATER, ingredient, Potions.MUNDANE); + this.registerPotionRecipe(Potions.AWKWARD, ingredient, potion); + } + } + + @Override + public FeatureSet getEnabledFeatures() { + return this.enabledFeatures; } } diff --git a/fabric-content-registries-v0/src/main/resources/fabric.mod.json b/fabric-content-registries-v0/src/main/resources/fabric.mod.json index 3b6958e485..8820f2a842 100644 --- a/fabric-content-registries-v0/src/main/resources/fabric.mod.json +++ b/fabric-content-registries-v0/src/main/resources/fabric.mod.json @@ -27,6 +27,9 @@ ], "accessWidener" : "fabric-content-registries-v0.accesswidener", "custom": { - "fabric-api:module-lifecycle": "stable" + "fabric-api:module-lifecycle": "stable", + "loom:injected_interfaces": { + "net/minecraft/class_1845\u0024class_9665": ["net/fabricmc/fabric/api/registry/FabricBrewingRecipeRegistryBuilder"] + } } } diff --git a/fabric-content-registries-v0/src/testmod/java/net/fabricmc/fabric/test/content/registry/ContentRegistryTest.java b/fabric-content-registries-v0/src/testmod/java/net/fabricmc/fabric/test/content/registry/ContentRegistryTest.java index b42c7772e1..ecd347be53 100644 --- a/fabric-content-registries-v0/src/testmod/java/net/fabricmc/fabric/test/content/registry/ContentRegistryTest.java +++ b/fabric-content-registries-v0/src/testmod/java/net/fabricmc/fabric/test/content/registry/ContentRegistryTest.java @@ -30,6 +30,8 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.item.PotionItem; +import net.minecraft.potion.Potions; +import net.minecraft.recipe.Ingredient; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKey; @@ -37,6 +39,7 @@ import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.tag.BlockTags; import net.minecraft.registry.tag.ItemTags; +import net.minecraft.resource.featuretoggle.FeatureFlags; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import net.minecraft.util.Identifier; @@ -47,8 +50,8 @@ import net.minecraft.world.event.GameEvent; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.registry.BrewingRecipeRegistryBuilderCallback; import net.fabricmc.fabric.api.registry.CompostingChanceRegistry; +import net.fabricmc.fabric.api.registry.FabricBrewingRecipeRegistryBuilder; import net.fabricmc.fabric.api.registry.FlammableBlockRegistry; import net.fabricmc.fabric.api.registry.FlattenableBlockRegistry; import net.fabricmc.fabric.api.registry.FuelRegistry; @@ -84,6 +87,7 @@ public void onInitialize() { // - assign a loot table to the nitwit villager type // - right-clicking a 'test_event' block will emit a 'test_event' game event, which will have a sculk sensor frequency of 2 // - instant health potions can be brewed from awkward potions with any item in the 'minecraft:small_flowers' tag + // - if Bundle experiment is enabled, luck potions can be brewed from awkward potions with a bundle // - dirty potions can be brewed by adding any item in the 'minecraft:dirt' tag to any standard potion CompostingChanceRegistry.INSTANCE.add(Items.OBSIDIAN, 0.5F); @@ -156,11 +160,14 @@ public void onInitialize() { dirtyPotion); /* Mods should use BrewingRecipeRegistry.registerPotionType(Item), which is access widened by fabric-transitive-access-wideners-v1 * This testmod uses an accessor due to Loom limitations that prevent TAWs from applying across Gradle subproject boundaries */ - BrewingRecipeRegistryBuilderCallback.BUILD.register(builder -> { - builder.method_59702(dirtyPotion); - // TODO 1.20.5 Ingredient.fromTag(ItemTags.DIRT) - builder.method_59703(Items.POTION, Items.DIRT, dirtyPotion); - // registerPotionRecipe(Potions.AWKWARD, Ingredient.fromTag(ItemTags.SMALL_FLOWERS), Potions.HEALING); + FabricBrewingRecipeRegistryBuilder.BUILD.register(builder -> { + builder.registerPotionType(dirtyPotion); + builder.registerItemRecipe(Items.POTION, Ingredient.fromTag(ItemTags.DIRT), dirtyPotion); + builder.registerPotionRecipe(Potions.AWKWARD, Ingredient.fromTag(ItemTags.SMALL_FLOWERS), Potions.HEALING); + + if (builder.getEnabledFeatures().contains(FeatureFlags.BUNDLE)) { + builder.registerPotionRecipe(Potions.AWKWARD, Ingredient.ofItems(Items.BUNDLE), Potions.LUCK); + } }); } diff --git a/fabric-events-interaction-v0/src/client/java/net/fabricmc/fabric/api/event/client/player/ClientPlayerBlockBreakEvents.java b/fabric-events-interaction-v0/src/client/java/net/fabricmc/fabric/api/event/client/player/ClientPlayerBlockBreakEvents.java index d817088c3a..ecefa3549a 100644 --- a/fabric-events-interaction-v0/src/client/java/net/fabricmc/fabric/api/event/client/player/ClientPlayerBlockBreakEvents.java +++ b/fabric-events-interaction-v0/src/client/java/net/fabricmc/fabric/api/event/client/player/ClientPlayerBlockBreakEvents.java @@ -30,7 +30,10 @@ *

For preventing block breaking client side and other purposes, see {@link net.fabricmc.fabric.api.event.player.AttackBlockCallback}. * For server side block break events, see {@link net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents}. */ -public class ClientPlayerBlockBreakEvents { +public final class ClientPlayerBlockBreakEvents { + private ClientPlayerBlockBreakEvents() { + } + /** * Callback after a block is broken client side. * diff --git a/fabric-events-interaction-v0/src/main/java/net/fabricmc/fabric/api/event/player/UseEntityCallback.java b/fabric-events-interaction-v0/src/main/java/net/fabricmc/fabric/api/event/player/UseEntityCallback.java index 0a2e73d45d..cf892d7fb8 100644 --- a/fabric-events-interaction-v0/src/main/java/net/fabricmc/fabric/api/event/player/UseEntityCallback.java +++ b/fabric-events-interaction-v0/src/main/java/net/fabricmc/fabric/api/event/player/UseEntityCallback.java @@ -34,7 +34,7 @@ * *

On the logical client, the return values have the following meaning: *

    - *
  • SUCCESS cancels further processing, causes a hand swing, and sends a packet to the server.
  • + *
  • SUCCESS/SUCCESS_NO_ITEM_USED cancels further processing, causes a hand swing, and sends a packet to the server.
  • *
  • CONSUME cancels further processing, and sends a packet to the server. It does NOT cause a hand swing.
  • *
  • PASS falls back to further processing.
  • *
  • FAIL cancels further processing and does not send a packet to the server.
  • diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantingContext.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantingContext.java index 8b55209893..7e139710ec 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantingContext.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantingContext.java @@ -18,6 +18,7 @@ import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.item.ItemStack; +import net.minecraft.resource.featuretoggle.FeatureSet; import net.minecraft.util.math.random.Random; /* @@ -36,7 +37,7 @@ public enum EnchantingContext { * When generating a random enchantment for the item. This includes the enchanting table, random * mob equipment, and the {@code enchant_with_levels} loot function. * - * @see EnchantmentHelper#generateEnchantments(Random, ItemStack, int, boolean) + * @see EnchantmentHelper#generateEnchantments(FeatureSet, Random, ItemStack, int, boolean) */ RANDOM_ENCHANTMENT, /** diff --git a/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/CustomDamageTest.java b/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/CustomDamageTest.java index 1b39db7f48..80389272f7 100644 --- a/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/CustomDamageTest.java +++ b/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/CustomDamageTest.java @@ -26,6 +26,7 @@ import net.minecraft.item.PickaxeItem; import net.minecraft.item.ToolMaterials; import net.minecraft.network.codec.PacketCodecs; +import net.minecraft.potion.Potions; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.text.Text; @@ -36,6 +37,7 @@ import net.fabricmc.fabric.api.item.v1.CustomDamageHandler; import net.fabricmc.fabric.api.item.v1.EnchantingContext; import net.fabricmc.fabric.api.item.v1.EnchantmentEvents; +import net.fabricmc.fabric.api.registry.FabricBrewingRecipeRegistryBuilder; import net.fabricmc.fabric.api.registry.FuelRegistry; import net.fabricmc.fabric.api.util.TriState; @@ -58,8 +60,7 @@ public class CustomDamageTest implements ModInitializer { public void onInitialize() { Registry.register(Registries.ITEM, new Identifier("fabric-item-api-v1-testmod", "weird_pickaxe"), WEIRD_PICK); FuelRegistry.INSTANCE.add(WEIRD_PICK, 200); - // TODO 1.20.5 - // FabricBrewingRecipeRegistry.registerPotionRecipe(Potions.WATER, Ingredient.ofItems(WEIRD_PICK), Potions.AWKWARD); + FabricBrewingRecipeRegistryBuilder.BUILD.register(builder -> builder.registerPotionRecipe(Potions.WATER, WEIRD_PICK, Potions.AWKWARD)); EnchantmentEvents.ALLOW_ENCHANTING.register(((enchantment, target, enchantingContext) -> { if (target.isOf(Items.DIAMOND_PICKAXE) && enchantment == Enchantments.SHARPNESS diff --git a/fabric-lifecycle-events-v1/src/main/java/net/fabricmc/fabric/api/event/lifecycle/v1/CommonLifecycleEvents.java b/fabric-lifecycle-events-v1/src/main/java/net/fabricmc/fabric/api/event/lifecycle/v1/CommonLifecycleEvents.java index 8c3f9a82e7..27750b6539 100644 --- a/fabric-lifecycle-events-v1/src/main/java/net/fabricmc/fabric/api/event/lifecycle/v1/CommonLifecycleEvents.java +++ b/fabric-lifecycle-events-v1/src/main/java/net/fabricmc/fabric/api/event/lifecycle/v1/CommonLifecycleEvents.java @@ -21,7 +21,7 @@ import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; -public class CommonLifecycleEvents { +public final class CommonLifecycleEvents { private CommonLifecycleEvents() { } diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricDefaultAttributeRegistry.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricDefaultAttributeRegistry.java index 2da45120a4..455382f876 100644 --- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricDefaultAttributeRegistry.java +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricDefaultAttributeRegistry.java @@ -71,11 +71,11 @@ public static void register(EntityType type, DefaultAttr *

    If a registration overrides another, a debug log message will be emitted. Existing registrations * can be checked at {@link net.minecraft.entity.attribute.DefaultAttributeRegistry#hasDefinitionFor(EntityType)}.

    * - *

    For convenience, this can also be done on the {@link FabricEntityTypeBuilder} to simplify the building process. + *

    For convenience, this can also be done on the {@link FabricEntityType.Builder} to simplify the building process. * * @param type the entity type * @param container the container for the default attribute - * @see FabricEntityTypeBuilder.Living#defaultAttributes(Supplier) + * @see FabricEntityType.Builder.Living#defaultAttributes(Supplier) */ public static void register(EntityType type, DefaultAttributeContainer container) { if (DefaultAttributeRegistryAccessor.getRegistry().put(type, container) != null) { diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java index 9c0c93e074..d0bcb2964d 100644 --- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java @@ -115,7 +115,7 @@ public static FabricEntityTypeBuilder create(SpawnGroup sp * @param the type of entity * * @return a new living entity type builder - * @deprecated use {@link FabricEntityType.Builder#createLiving(UnaryOperator)} + * @deprecated use {@link FabricEntityType.Builder#createLiving(EntityType.EntityFactory, SpawnGroup, UnaryOperator)} */ @Deprecated public static FabricEntityTypeBuilder.Living createLiving() { @@ -128,7 +128,7 @@ public static FabricEntityTypeBuilder.Living createL * @param the type of entity * * @return a new mob entity type builder - * @deprecated use {@link FabricEntityType.Builder#createMob(UnaryOperator)} + * @deprecated use {@link FabricEntityType.Builder#createMob(EntityType.EntityFactory, SpawnGroup, UnaryOperator)} */ public static FabricEntityTypeBuilder.Mob createMob() { return new FabricEntityTypeBuilder.Mob<>(SpawnGroup.MISC, FabricEntityTypeBuilder::emptyFactory); @@ -203,7 +203,7 @@ public FabricEntityTypeBuilder spawnableFarFromPlayer() { * @param dimensions the dimensions representing the entity's size * * @return this builder for chaining - * @deprecated use {@link EntityType.Builder#setDimensions(float, float)} + * @deprecated use {@link EntityType.Builder#dimensions(float, float)} */ @Deprecated public FabricEntityTypeBuilder dimensions(EntityDimensions dimensions) { @@ -347,7 +347,7 @@ public EntityType build() { * An extended version of {@link FabricEntityTypeBuilder} with support for features on present on {@link LivingEntity living entities}, such as default attributes. * * @param Entity class. - * @deprecated use {@link EntityType.Builder#createLiving(UnaryOperator)} + * @deprecated use {@link EntityType.Builder#createLiving(EntityType.EntityFactory, SpawnGroup, UnaryOperator)} */ @Deprecated public static class Living extends FabricEntityTypeBuilder { @@ -606,7 +606,7 @@ public FabricEntityTypeBuilder.Mob defaultAttributes(SupplierThis is used by mobs to determine whether Minecraft should spawn an entity within a certain context. * * @return this builder for chaining. - * @deprecated use {@link FabricEntityType.Builder.Mob#spawnRestriction(SpawnRestriction.Location, Heightmap.Type, SpawnRestriction.SpawnPredicate)} + * @deprecated use {@link FabricEntityType.Builder.Mob#spawnRestriction(SpawnLocation, Heightmap.Type, SpawnRestriction.SpawnPredicate)} */ @Deprecated public FabricEntityTypeBuilder.Mob spawnRestriction(SpawnLocation spawnLocation, Heightmap.Type heightmap, SpawnRestriction.SpawnPredicate spawnPredicate) { diff --git a/fabric-particles-v1/src/client/java/net/fabricmc/fabric/api/client/particle/v1/ParticleFactoryRegistry.java b/fabric-particles-v1/src/client/java/net/fabricmc/fabric/api/client/particle/v1/ParticleFactoryRegistry.java index 7cd96a1562..9fa32b16bf 100644 --- a/fabric-particles-v1/src/client/java/net/fabricmc/fabric/api/client/particle/v1/ParticleFactoryRegistry.java +++ b/fabric-particles-v1/src/client/java/net/fabricmc/fabric/api/client/particle/v1/ParticleFactoryRegistry.java @@ -16,6 +16,8 @@ package net.fabricmc.fabric.api.client.particle.v1; +import org.jetbrains.annotations.ApiStatus; + import net.minecraft.client.particle.ParticleFactory; import net.minecraft.particle.ParticleEffect; import net.minecraft.particle.ParticleType; @@ -29,6 +31,7 @@ * * @see FabricParticleTypes */ +@ApiStatus.NonExtendable public interface ParticleFactoryRegistry { static ParticleFactoryRegistry getInstance() { return ParticleFactoryRegistryImpl.INSTANCE; diff --git a/fabric-particles-v1/src/main/java/net/fabricmc/fabric/api/particle/v1/FabricParticleTypes.java b/fabric-particles-v1/src/main/java/net/fabricmc/fabric/api/particle/v1/FabricParticleTypes.java index e6258eccad..e39aa19887 100644 --- a/fabric-particles-v1/src/main/java/net/fabricmc/fabric/api/particle/v1/FabricParticleTypes.java +++ b/fabric-particles-v1/src/main/java/net/fabricmc/fabric/api/particle/v1/FabricParticleTypes.java @@ -18,14 +18,13 @@ import java.util.function.Function; -import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec; import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.codec.PacketCodec; -import net.minecraft.particle.DefaultParticleType; import net.minecraft.particle.ParticleEffect; import net.minecraft.particle.ParticleType; +import net.minecraft.particle.SimpleParticleType; /** * Methods for creating particle types, both simple and using an existing attribute factory. @@ -33,8 +32,8 @@ *

    Usage: *

    *
    - * public static final DefaultParticleType SIMPLE_TEST_PARTICLE = FabricParticleTypes.simple();
    - * public static final DefaultParticleType CUSTOM_TEST_PARTICLE = FabricParticleTypes.simple();
    + * public static final SimpleParticleType SIMPLE_TEST_PARTICLE = FabricParticleTypes.simple();
    + * public static final SimpleParticleType CUSTOM_TEST_PARTICLE = FabricParticleTypes.simple();
      *
      * {@literal @}Override
      * public void onInitialize() {
    @@ -50,7 +49,7 @@ private FabricParticleTypes() { }
     	/**
     	 * Creates a new, default particle type for the given id.
     	 */
    -	public static DefaultParticleType simple() {
    +	public static SimpleParticleType simple() {
     		return simple(false);
     	}
     
    @@ -59,31 +58,29 @@ public static DefaultParticleType simple() {
     	 *
     	 * @param alwaysSpawn True to always spawn the particle regardless of distance.
     	 */
    -	public static DefaultParticleType simple(boolean alwaysSpawn) {
    -		return new DefaultParticleType(alwaysSpawn) { };
    +	public static SimpleParticleType simple(boolean alwaysSpawn) {
    +		return new SimpleParticleType(alwaysSpawn) { };
     	}
     
     	/**
     	 * Creates a new particle type with a custom factory and codecs for packet/data serialization.
     	 *
    -	 * @param factory	 A factory for serializing string command parameters into a particle effect.
     	 * @param codec The codec for serialization.
     	 * @param packetCodec The packet codec for network serialization.
     	 */
    -	public static  ParticleType complex(ParticleEffect.Factory factory, final Function, Codec> codecGetter, final MapCodec codec, final PacketCodec packetCodec) {
    -		return complex(false, factory, codec, packetCodec);
    +	public static  ParticleType complex(final MapCodec codec, final PacketCodec packetCodec) {
    +		return complex(false, codec, packetCodec);
     	}
     
     	/**
     	 * Creates a new particle type with a custom factory and codecs for packet/data serialization.
     	 *
     	 * @param alwaysSpawn True to always spawn the particle regardless of distance.
    -	 * @param factory	 A factory for serializing string command parameters into a particle effect.
     	 * @param codec The codec for serialization.
     	 * @param packetCodec The packet codec for network serialization.
     	 */
    -	public static  ParticleType complex(boolean alwaysSpawn, ParticleEffect.Factory factory, final MapCodec codec, final PacketCodec packetCodec) {
    -		return new ParticleType(alwaysSpawn, factory) {
    +	public static  ParticleType complex(boolean alwaysSpawn, final MapCodec codec, final PacketCodec packetCodec) {
    +		return new ParticleType<>(alwaysSpawn) {
     			@Override
     			public MapCodec getCodec() {
     				return codec;
    @@ -100,12 +97,11 @@ public PacketCodec getPacketCodec() {
     	 * Creates a new particle type with a custom factory and codecs for packet/data serialization.
     	 * This method is useful when two different {@link ParticleType}s share the same {@link ParticleEffect} implementation.
     	 *
    -	 * @param factory	 A factory for serializing string command parameters into a particle effect.
     	 * @param codecGetter A function that, given the newly created type, returns the codec for serialization.
     	 * @param packetCodecGetter A function that, given the newly created type, returns the packet codec for network serialization.
     	 */
    -	public static  ParticleType complex(ParticleEffect.Factory factory, final Function, MapCodec> codecGetter, final Function, PacketCodec> packetCodecGetter) {
    -		return complex(false, factory, codecGetter, packetCodecGetter);
    +	public static  ParticleType complex(final Function, MapCodec> codecGetter, final Function, PacketCodec> packetCodecGetter) {
    +		return complex(false, codecGetter, packetCodecGetter);
     	}
     
     	/**
    @@ -113,12 +109,11 @@ public static  ParticleType complex(ParticleEffect.
     	 * This method is useful when two different {@link ParticleType}s share the same {@link ParticleEffect} implementation.
     	 *
     	 * @param alwaysSpawn True to always spawn the particle regardless of distance.
    -	 * @param factory	 A factory for serializing string command parameters into a particle effect.
     	 * @param codecGetter A function that, given the newly created type, returns the codec for serialization.
     	 * @param packetCodecGetter A function that, given the newly created type, returns the packet codec for network serialization.
     	 */
    -	public static  ParticleType complex(boolean alwaysSpawn, ParticleEffect.Factory factory, final Function, MapCodec> codecGetter, final Function, PacketCodec> packetCodecGetter) {
    -		return new ParticleType(alwaysSpawn, factory) {
    +	public static  ParticleType complex(boolean alwaysSpawn, final Function, MapCodec> codecGetter, final Function, PacketCodec> packetCodecGetter) {
    +		return new ParticleType<>(alwaysSpawn) {
     			@Override
     			public MapCodec getCodec() {
     				return codecGetter.apply(this);
    diff --git a/fabric-particles-v1/src/testmod/java/net/fabricmc/fabric/test/particle/ParticleTestSetup.java b/fabric-particles-v1/src/testmod/java/net/fabricmc/fabric/test/particle/ParticleTestSetup.java
    index a6869df036..dc6b92fe19 100644
    --- a/fabric-particles-v1/src/testmod/java/net/fabricmc/fabric/test/particle/ParticleTestSetup.java
    +++ b/fabric-particles-v1/src/testmod/java/net/fabricmc/fabric/test/particle/ParticleTestSetup.java
    @@ -48,7 +48,7 @@ public void onInitialize() {
     
     		CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
     			dispatcher.register(CommandManager.literal("addparticletestblocks").executes(context -> {
    -				PlayerInventory inventory = context.getSource().getPlayer().getInventory();
    +				PlayerInventory inventory = context.getSource().getPlayerOrThrow().getInventory();
     				inventory.offerOrDrop(new ItemStack(ALWAYS_TINTED));
     				inventory.offerOrDrop(new ItemStack(TINTED_OVER_WATER));
     				inventory.offerOrDrop(new ItemStack(NEVER_TINTED));
    diff --git a/fabric-recipe-api-v1/src/main/java/net/fabricmc/fabric/impl/recipe/ingredient/builtin/CustomDataIngredient.java b/fabric-recipe-api-v1/src/main/java/net/fabricmc/fabric/impl/recipe/ingredient/builtin/CustomDataIngredient.java
    index b2962f61a5..8a8f9786ef 100644
    --- a/fabric-recipe-api-v1/src/main/java/net/fabricmc/fabric/impl/recipe/ingredient/builtin/CustomDataIngredient.java
    +++ b/fabric-recipe-api-v1/src/main/java/net/fabricmc/fabric/impl/recipe/ingredient/builtin/CustomDataIngredient.java
    @@ -19,10 +19,7 @@
     import java.util.ArrayList;
     import java.util.List;
     
    -import com.mojang.brigadier.exceptions.CommandSyntaxException;
    -import com.mojang.datafixers.util.Either;
     import com.mojang.serialization.Codec;
    -import com.mojang.serialization.DataResult;
     import com.mojang.serialization.MapCodec;
     import com.mojang.serialization.codecs.RecordCodecBuilder;
     
    @@ -94,17 +91,6 @@ private NbtCompound getNbt() {
     	private static class Serializer implements CustomIngredientSerializer {
     		private static final Identifier ID = new Identifier("fabric", "custom_data");
     
    -		// Supports decoding the NBT as a string as well as the object.
    -		private static final Codec NBT_CODEC = Codec.xor(
    -				Codec.STRING, NbtCompound.CODEC
    -		).flatXmap(either -> either.map(s -> {
    -			try {
    -				return DataResult.success(StringNbtReader.parse(s));
    -			} catch (CommandSyntaxException e) {
    -				return DataResult.error(e::getMessage);
    -			}
    -		}, DataResult::success), nbtCompound -> DataResult.success(Either.left(nbtCompound.asString())));
    -
     		private static final MapCodec ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
     		private static final MapCodec DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
     
    @@ -118,7 +104,7 @@ private static MapCodec createCodec(Codec ingr
     			return RecordCodecBuilder.mapCodec(instance ->
     					instance.group(
     							ingredientCodec.fieldOf("base").forGetter(CustomDataIngredient::getBase),
    -							NBT_CODEC.fieldOf("nbt").forGetter(CustomDataIngredient::getNbt)
    +							StringNbtReader.NBT_COMPOUND_CODEC.fieldOf("nbt").forGetter(CustomDataIngredient::getNbt)
     					).apply(instance, CustomDataIngredient::new)
     			);
     		}
    diff --git a/fabric-sound-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/sound/client/SineStream.java b/fabric-sound-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/sound/client/SineStream.java
    index 2d4fd4af42..3bfd628e9f 100644
    --- a/fabric-sound-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/sound/client/SineStream.java
    +++ b/fabric-sound-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/sound/client/SineStream.java
    @@ -39,7 +39,7 @@ public AudioFormat getFormat() {
     	}
     
     	@Override
    -	public ByteBuffer getBuffer(int capacity) {
    +	public ByteBuffer read(int capacity) {
     		ByteBuffer buffer = BufferUtils.createByteBuffer(capacity);
     
     		for (int i = 0; i < capacity; i++) {
    diff --git a/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/VariantCodecs.java b/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/VariantCodecs.java
    index 1ec91fa30a..f8cc74ced8 100644
    --- a/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/VariantCodecs.java
    +++ b/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/VariantCodecs.java
    @@ -17,9 +17,12 @@
     package net.fabricmc.fabric.impl.transfer;
     
     import com.mojang.serialization.Codec;
    +import com.mojang.serialization.DataResult;
     import com.mojang.serialization.codecs.RecordCodecBuilder;
     
     import net.minecraft.component.ComponentChanges;
    +import net.minecraft.component.ComponentMapImpl;
    +import net.minecraft.item.ItemStack;
     import net.minecraft.network.RegistryByteBuf;
     import net.minecraft.network.codec.PacketCodec;
     import net.minecraft.network.codec.PacketCodecs;
    @@ -32,11 +35,13 @@
     import net.fabricmc.fabric.impl.transfer.item.ItemVariantImpl;
     
     public class VariantCodecs {
    -	public static final Codec ITEM_CODEC = RecordCodecBuilder.create(instance -> instance.group(
    +	// AIR is valid (for some reason), don't use ItemStack#ITEM_CODEC
    +	private static final Codec UNVALIDATED_ITEM_CODEC = RecordCodecBuilder.create(instance -> instance.group(
     			Registries.ITEM.getEntryCodec().fieldOf("item").forGetter(ItemVariant::getRegistryEntry),
     			ComponentChanges.CODEC.optionalFieldOf("components", ComponentChanges.EMPTY).forGetter(ItemVariant::getComponents)
     		).apply(instance, ItemVariantImpl::of)
     	);
    +	public static final Codec ITEM_CODEC = UNVALIDATED_ITEM_CODEC.validate(VariantCodecs::validateComponents);
     	public static final PacketCodec ITEM_PACKET_CODEC = PacketCodec.tuple(
     			PacketCodecs.registryEntry(RegistryKeys.ITEM), ItemVariant::getRegistryEntry,
     			ComponentChanges.PACKET_CODEC, ItemVariant::getComponents,
    @@ -53,4 +58,8 @@ public class VariantCodecs {
     			ComponentChanges.PACKET_CODEC, FluidVariant::getComponents,
     			FluidVariantImpl::of
     	);
    +
    +	private static DataResult validateComponents(ItemVariant variant) {
    +		return ItemStack.validateComponents(ComponentMapImpl.create(variant.getItem().getComponents(), variant.getComponents())).map(v -> variant);
    +	}
     }
    diff --git a/gradle.properties b/gradle.properties
    index ed36cce09f..17bd06b327 100644
    --- a/gradle.properties
    +++ b/gradle.properties
    @@ -4,9 +4,9 @@ fabric.loom.multiProjectOptimisation=true
     
     version=0.96.15
     minecraft_version=1.20.5-pre1
    -yarn_version=+build.2
    +yarn_version=+build.5
     loader_version=0.15.6
    -installer_version=0.11.1
    +installer_version=1.0.1
     
     prerelease=true
     curseforge_minecraft_version=1.20.5-Snapshot
    diff --git a/settings.gradle b/settings.gradle
    index 9be28e117b..3e01c05696 100644
    --- a/settings.gradle
    +++ b/settings.gradle
    @@ -42,7 +42,7 @@ include 'fabric-message-api-v1'
     include 'fabric-model-loading-api-v1'
     include 'fabric-networking-api-v1'
     include 'fabric-object-builder-api-v1'
    -//include 'fabric-particles-v1'
    +include 'fabric-particles-v1'
     include 'fabric-recipe-api-v1'
     include 'fabric-registry-sync-v0'
     include 'fabric-renderer-api-v1'
    
    From cfb0a2d3d2a1aaf3adee5710343422795b630430 Mon Sep 17 00:00:00 2001
    From: modmuss50 
    Date: Sun, 14 Apr 2024 13:40:56 +0100
    Subject: [PATCH 7/7] Bump version
    
    ---
     gradle.properties | 98 +++++++++++++++++++++++------------------------
     1 file changed, 49 insertions(+), 49 deletions(-)
    
    diff --git a/gradle.properties b/gradle.properties
    index 17bd06b327..7227874fd9 100644
    --- a/gradle.properties
    +++ b/gradle.properties
    @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx2560M
     org.gradle.parallel=true
     fabric.loom.multiProjectOptimisation=true
     
    -version=0.96.15
    +version=0.97.0
     minecraft_version=1.20.5-pre1
     yarn_version=+build.5
     loader_version=0.15.6
    @@ -12,51 +12,51 @@ prerelease=true
     curseforge_minecraft_version=1.20.5-Snapshot
     
     # Do not manually update, use the bumpversions task:
    -fabric-api-base-version=0.4.39
    -fabric-api-lookup-api-v1-version=1.6.58
    -fabric-biome-api-v1-version=13.0.22
    -fabric-block-api-v1-version=1.0.19
    -fabric-block-view-api-v2-version=1.0.7
    -fabric-blockrenderlayer-v1-version=1.1.49
    -fabric-command-api-v1-version=1.2.44
    -fabric-command-api-v2-version=2.2.23
    -fabric-commands-v0-version=0.2.61
    -fabric-content-registries-v0-version=7.0.0
    -fabric-crash-report-info-v1-version=0.2.26
    -fabric-data-attachment-api-v1-version=1.1.11
    -fabric-data-generation-api-v1-version=19.0.0
    -fabric-dimensions-v1-version=2.1.66
    -fabric-entity-events-v1-version=1.6.7
    -fabric-events-interaction-v0-version=0.7.5
    -fabric-game-rule-api-v1-version=1.0.49
    -fabric-gametest-api-v1-version=1.3.12
    -fabric-item-api-v1-version=8.0.0
    -fabric-item-group-api-v1-version=4.0.34
    -fabric-key-binding-api-v1-version=1.0.44
    -fabric-keybindings-v0-version=0.2.42
    -fabric-lifecycle-events-v1-version=2.3.3
    -fabric-loot-api-v2-version=3.0.0
    -fabric-message-api-v1-version=6.0.9
    -fabric-model-loading-api-v1-version=1.0.11
    -fabric-models-v0-version=0.4.10
    -fabric-networking-api-v1-version=4.0.6
    -fabric-object-builder-api-v1-version=15.0.2
    -fabric-particles-v1-version=3.0.0
    -fabric-recipe-api-v1-version=5.0.1
    -fabric-registry-sync-v0-version=5.0.12
    -fabric-renderer-api-v1-version=3.2.11
    -fabric-renderer-indigo-version=1.5.11
    -fabric-renderer-registries-v1-version=3.2.60
    -fabric-rendering-data-attachment-v1-version=0.3.45
    -fabric-rendering-fluids-v1-version=3.1.2
    -fabric-rendering-v0-version=1.1.63
    -fabric-rendering-v1-version=4.2.3
    -fabric-resource-conditions-api-v1-version=4.0.0
    -fabric-resource-loader-v0-version=1.0.1
    -fabric-screen-api-v1-version=2.0.20
    -fabric-screen-handler-api-v1-version=1.3.69
    -fabric-sound-api-v1-version=1.0.20
    -fabric-transfer-api-v1-version=5.1.5
    -fabric-transitive-access-wideners-v1-version=6.0.9
    -fabric-convention-tags-v1-version=1.5.16
    -fabric-client-tags-api-v1-version=1.1.10
    +fabric-api-base-version=0.4.40
    +fabric-api-lookup-api-v1-version=1.6.59
    +fabric-biome-api-v1-version=13.0.23
    +fabric-block-api-v1-version=1.0.20
    +fabric-block-view-api-v2-version=1.0.8
    +fabric-blockrenderlayer-v1-version=1.1.50
    +fabric-command-api-v1-version=1.2.45
    +fabric-command-api-v2-version=2.2.24
    +fabric-commands-v0-version=0.2.62
    +fabric-content-registries-v0-version=8.0.0
    +fabric-crash-report-info-v1-version=0.2.27
    +fabric-data-attachment-api-v1-version=1.1.12
    +fabric-data-generation-api-v1-version=19.0.1
    +fabric-dimensions-v1-version=2.1.67
    +fabric-entity-events-v1-version=1.6.8
    +fabric-events-interaction-v0-version=0.7.6
    +fabric-game-rule-api-v1-version=1.0.50
    +fabric-gametest-api-v1-version=1.3.13
    +fabric-item-api-v1-version=8.1.0
    +fabric-item-group-api-v1-version=4.0.35
    +fabric-key-binding-api-v1-version=1.0.45
    +fabric-keybindings-v0-version=0.2.43
    +fabric-lifecycle-events-v1-version=2.3.4
    +fabric-loot-api-v2-version=3.0.1
    +fabric-message-api-v1-version=6.0.10
    +fabric-model-loading-api-v1-version=1.0.12
    +fabric-models-v0-version=0.4.11
    +fabric-networking-api-v1-version=4.0.7
    +fabric-object-builder-api-v1-version=15.1.0
    +fabric-particles-v1-version=4.0.0
    +fabric-recipe-api-v1-version=5.0.2
    +fabric-registry-sync-v0-version=5.0.13
    +fabric-renderer-api-v1-version=3.2.12
    +fabric-renderer-indigo-version=1.5.12
    +fabric-renderer-registries-v1-version=3.2.61
    +fabric-rendering-data-attachment-v1-version=0.3.46
    +fabric-rendering-fluids-v1-version=3.1.3
    +fabric-rendering-v0-version=1.1.64
    +fabric-rendering-v1-version=4.2.4
    +fabric-resource-conditions-api-v1-version=4.0.1
    +fabric-resource-loader-v0-version=1.0.2
    +fabric-screen-api-v1-version=2.0.21
    +fabric-screen-handler-api-v1-version=1.3.70
    +fabric-sound-api-v1-version=1.0.21
    +fabric-transfer-api-v1-version=5.1.6
    +fabric-transitive-access-wideners-v1-version=6.0.10
    +fabric-convention-tags-v1-version=1.5.17
    +fabric-client-tags-api-v1-version=1.1.11