更新内容

1. 重新添加回玩偶
This commit is contained in:
叁玖领域 2026-01-02 22:26:00 +08:00
parent 33427074fd
commit 6a4a15c1f4
109 changed files with 968 additions and 1700 deletions

View File

@ -109,6 +109,7 @@ dependencies {
implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:0.4.1"))
modImplementation(jarJar("io.github.llamalad7:mixinextras-forge:0.4.1"))
modImplementation("blank:carryon-1.20.1:2.1.2.7")
implementation 'org.joml:joml:1.10.5'
//

View File

@ -33,7 +33,7 @@ mod_name=3944Realms 's Lib Mod
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=MIT
# The mod version. See https://semver.org/
mod_version=0.0.28
mod_version=0.0.29
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html

Binary file not shown.

View File

@ -1,2 +1,2 @@
// 1.20.1 2025-12-08T02:17:25.3481161 Languages: zh_tw
53425c42eb07613ff9575cf3562ae0b6c06d801c assets/lib39/lang/zh_tw.json
// 1.20.1 2026-01-02T21:20:53.7969072 Languages: zh_tw
79fece6715632a6fe3df3d0c666c7f428cc97dad assets/lib39/lang/zh_tw.json

View File

@ -1,2 +1,2 @@
// 1.20.1 2025-12-08T02:17:25.3288872 Languages: zh_cn
4dd73f63979fedb90c9dbe7ef5cbefca10e17066 assets/lib39/lang/zh_cn.json
// 1.20.1 2026-01-02T21:20:53.7939092 Languages: zh_cn
3ea1846920a8b807e45cd160c1aeeb483cadb202 assets/lib39/lang/zh_cn.json

View File

@ -1,4 +1,4 @@
// 1.20.1 2025-12-22T20:31:52.8060707 Item Models: lib39
// 1.20.1 2026-01-02T15:14:31.7762095 Item Models: lib39
663f22009a9420c3eeae3c829fc9f37d16f0901b assets/lib39/models/item/doll.json
14f581c8f8e7f0de004c57a180f371e60e7b12ae assets/lib39/models/item/fabric.json
70583055336790fc837836ea6b49d16cfc8b64b8 assets/lib39/models/item/forge.json

View File

@ -1,2 +1,2 @@
// 1.20.1 2025-12-22T20:31:52.804071 Block States: lib39
1dda476533f87cc377e800d537c22b48509a25cf assets/lib39/blockstates/doll.json
// 1.20.1 2026-01-02T15:29:13.3418663 Block States: lib39
af9aae34357e6c630ed5037a6993ff211eba37ee assets/lib39/blockstates/doll.json

View File

@ -0,0 +1,2 @@
// 1.20.1 2026-01-02T15:11:02.2242532 Loot Tables
ac8ee9efcf316b2181fb0b56946ff6805b40c6f0 data/lib39/loot_tables/blocks/doll.json

View File

@ -0,0 +1,2 @@
// 1.20.1 2026-01-02T20:50:48.567559 Sound Definitions
474de39bdc277c91961609c6bddec279a755c846 assets/lib39/sounds.json

View File

@ -1,2 +1,2 @@
// 1.20.1 2025-12-08T02:17:25.3461162 Languages: lzh
36cdcf9b4b09c9731e504f22094c55b97a20c61c assets/lib39/lang/lzh.json
// 1.20.1 2026-01-02T21:20:53.7969072 Languages: lzh
3d0e4dde6733bcf76f908f01d54ebbd8b840e07c assets/lib39/lang/lzh.json

View File

@ -0,0 +1,3 @@
// 1.20.1 2026-01-02T20:34:46.0679751 Recipes
d65b7847071b919cdda2351bee53d2693de856c8 data/lib39/advancements/recipes/misc/doll.json
fbb6d29d5bfc1a2cef3888165671ac5e12ecc40f data/lib39/recipes/doll.json

View File

@ -1,52 +1 @@
// 1.20.1 2025-12-22T20:33:59.3988473 Block Models: lib39
c5ecf989c3bbea8d7886f1cc5e6986df20d49698 assets/lib39/models/block/doll_item/acacia_sapling.json
d9ab870bd2b3dade81ab3b7a505b3a197693cc89 assets/lib39/models/block/doll_item/allium.json
6ab8299a91006367c1000578a2410efc740709ab assets/lib39/models/block/doll_item/amethyst_cluster.json
1b00e53ffbb576a6d8fe04f96f7411ef04c2724b assets/lib39/models/block/doll_item/azure_bluet.json
d6428f2e4ef38110c7d59d6bdff2317e69e30426 assets/lib39/models/block/doll_item/bamboo.json
9b488ddadd205146eed679512778abe922fce1c7 assets/lib39/models/block/doll_item/birch_sapling.json
f5f280c1f843e404e9d7d99d63c82a1aae899580 assets/lib39/models/block/doll_item/brain_coral.json
3cfb8312fc32af3adbb459b10b3bfd8150e1403e assets/lib39/models/block/doll_item/brain_coral_fan.json
796a2922e18478c84d1a4306268441c43e6e3fc5 assets/lib39/models/block/doll_item/brown_mushroom.json
2537bff63cdbaab6b6bc43f797a414d20ee42aa5 assets/lib39/models/block/doll_item/bubble_coral.json
d763db2c432f22c852b101ebf191ae1a4b4a79ca assets/lib39/models/block/doll_item/bubble_coral_fan.json
9992fc8b3e3a7372735ebd3c80f82ca38a7457b6 assets/lib39/models/block/doll_item/cherry_sapling.json
f37ceb94c45a68e5c925c307d6a442b86b2b228f assets/lib39/models/block/doll_item/cobweb.json
98a09fb2c8d72f3b3f56b21c71deb4d2bb7f75ec assets/lib39/models/block/doll_item/cornflower.json
351ced2ab09ee4e5a19f3ef58889210ade727cdf assets/lib39/models/block/doll_item/crimson_fungus.json
c548fcaabd73cd290671ee97684f50383fa6156d assets/lib39/models/block/doll_item/crimson_roots_pot.json
904c9ae4b9cc9a7b1afa00644695991850eb3a36 assets/lib39/models/block/doll_item/dandelion.json
5a1ee4a909258d0b825df723620bf06192b6a749 assets/lib39/models/block/doll_item/dark_oak_sapling.json
7d4c5880048705f2f9559d789b882eded4c01fea assets/lib39/models/block/doll_item/dead_brain_coral.json
1a45a06a788a193b16a0c55fae90f37caf26c10b assets/lib39/models/block/doll_item/dead_brain_coral_fan.json
8d62831e32744f5db4e59c3af9d718c3cab8c7c4 assets/lib39/models/block/doll_item/dead_bubble_coral.json
e53df0a329f1783252bf030a5febbcb09ba3ec46 assets/lib39/models/block/doll_item/dead_bubble_coral_fan.json
667f005c0d8bc16041209e07689243394a8d7aa1 assets/lib39/models/block/doll_item/dead_bush.json
b865c16c3b6e2dacbb75584b21c0b26269509e2e assets/lib39/models/block/doll_item/dead_fire_coral.json
be2219050188a813b319353a37413cc36ee38a10 assets/lib39/models/block/doll_item/dead_fire_coral_fan.json
79e23f620de796b6c383a4f953a544049c7209f9 assets/lib39/models/block/doll_item/dead_horn_coral.json
9b32e7a03b4990566268ff52eccf0087fddcd712 assets/lib39/models/block/doll_item/dead_horn_coral_fan.json
3138e486029ec07363d805d4e71caee95502b53a assets/lib39/models/block/doll_item/dead_tube_coral.json
07168397dc495328ca37caf326bbc781b4b0722d assets/lib39/models/block/doll_item/dead_tube_coral_fan.json
b5c8204ed6e9beb363a6ba854d648905a3e7b53e assets/lib39/models/block/doll_item/fire_coral.json
b29f30c717c5d323eaaec63f95e3a8839c6dbfc8 assets/lib39/models/block/doll_item/fire_coral_fan.json
1a54d4d417f72fd4aa9741ff866077abdf34afa6 assets/lib39/models/block/doll_item/horn_coral.json
c16714c69082efa11fbbbf7cd9d9fc7c17ffd5c8 assets/lib39/models/block/doll_item/horn_coral_fan.json
1bb0cbc2f014eaa10c9516c647cd7c09d32dbd3c assets/lib39/models/block/doll_item/jungle_sapling.json
521d825ef6bf88a79a6cd8ccb0a4753dbb74edd6 assets/lib39/models/block/doll_item/lily_of_the_valley.json
deffb3cd7a99f5134ad3bd8cf928af204aa2ef3f assets/lib39/models/block/doll_item/oak_sapling.json
5b80569184a739339f18a5033beed3ee4ebb0504 assets/lib39/models/block/doll_item/orange_tulip.json
e0d2b8614290b05bbf163353f698973bf32ceb25 assets/lib39/models/block/doll_item/oxeye_daisy.json
89140e446bd57faf28a24d46eda361f7145d03a9 assets/lib39/models/block/doll_item/pink_tulip.json
09ab4c411f4c3b17322dcb98446ef31732704402 assets/lib39/models/block/doll_item/poppy.json
a00c7798791d60522fb137102f5ee0306d28ea55 assets/lib39/models/block/doll_item/redstone_torch.json
e13f43e34d6233f61ebc7f7e168a220f84dbd38a assets/lib39/models/block/doll_item/red_mushroom.json
a3816cd847793723d414d9bcca8dda3194b6cf27 assets/lib39/models/block/doll_item/red_tulip.json
26ed0d78ccb1b5da9b11bdc6d5c2112b437bb51c assets/lib39/models/block/doll_item/spruce_sapling.json
d1fab112ede88c85e5488663ddec0dbcb78429e5 assets/lib39/models/block/doll_item/torch.json
5d6724324b565fa3de05a627391d02ccc9d04548 assets/lib39/models/block/doll_item/tube_coral.json
b6c57db3885cb1420f3ac59c8a29e0239e2bae1b assets/lib39/models/block/doll_item/tube_coral_fan.json
bd6a7ab81ab39d958ff5ebcf081448515e0acb9e assets/lib39/models/block/doll_item/warped_fungus.json
d9419e9991d5eca4e184b37e1a4f6416f3adf74e assets/lib39/models/block/doll_item/warped_roots_pot.json
05d7f1b2bc7f71428ed92f4e981a6be3683ee0a5 assets/lib39/models/block/doll_item/white_tulip.json
7cfe81215ed76a9d5dad392a012575f12b59edc6 assets/lib39/models/block/doll_item/wither_rose.json
// 1.20.1 2026-01-02T15:11:02.2272522 Block Models: lib39

View File

@ -1,2 +1,2 @@
// 1.20.1 2025-12-08T02:17:25.3441085 Languages: en_us
5759567e5c2f2d3410a92a9c47e8d8db63cc583d assets/lib39/lang/en_us.json
// 1.20.1 2026-01-02T21:20:53.7959072 Languages: en_us
4e6a2291b5064949b18583735a1e31599b4db2e8 assets/lib39/lang/en_us.json

View File

@ -2,63 +2,63 @@
"variants": {
"facing=east,pose=default,waterlogged=false": {
"model": "lib39:block/base_doll",
"y": 180
"y": 90
},
"facing=east,pose=default,waterlogged=true": {
"model": "lib39:block/base_doll",
"y": 180
"y": 90
},
"facing=east,pose=without_item,waterlogged=false": {
"facing=east,pose=further,waterlogged=false": {
"model": "lib39:block/base_doll",
"y": 180
"y": 90
},
"facing=east,pose=without_item,waterlogged=true": {
"facing=east,pose=further,waterlogged=true": {
"model": "lib39:block/base_doll",
"y": 180
"y": 90
},
"facing=north,pose=default,waterlogged=false": {
"model": "lib39:block/base_doll",
"y": 90
"model": "lib39:block/base_doll"
},
"facing=north,pose=default,waterlogged=true": {
"model": "lib39:block/base_doll",
"y": 90
"model": "lib39:block/base_doll"
},
"facing=north,pose=without_item,waterlogged=false": {
"model": "lib39:block/base_doll",
"y": 90
"facing=north,pose=further,waterlogged=false": {
"model": "lib39:block/base_doll"
},
"facing=north,pose=without_item,waterlogged=true": {
"model": "lib39:block/base_doll",
"y": 90
"facing=north,pose=further,waterlogged=true": {
"model": "lib39:block/base_doll"
},
"facing=south,pose=default,waterlogged=false": {
"model": "lib39:block/base_doll",
"y": 270
"y": 180
},
"facing=south,pose=default,waterlogged=true": {
"model": "lib39:block/base_doll",
"y": 270
"y": 180
},
"facing=south,pose=without_item,waterlogged=false": {
"facing=south,pose=further,waterlogged=false": {
"model": "lib39:block/base_doll",
"y": 270
"y": 180
},
"facing=south,pose=without_item,waterlogged=true": {
"facing=south,pose=further,waterlogged=true": {
"model": "lib39:block/base_doll",
"y": 270
"y": 180
},
"facing=west,pose=default,waterlogged=false": {
"model": "lib39:block/base_doll"
"model": "lib39:block/base_doll",
"y": 270
},
"facing=west,pose=default,waterlogged=true": {
"model": "lib39:block/base_doll"
"model": "lib39:block/base_doll",
"y": 270
},
"facing=west,pose=without_item,waterlogged=false": {
"model": "lib39:block/base_doll"
"facing=west,pose=further,waterlogged=false": {
"model": "lib39:block/base_doll",
"y": 270
},
"facing=west,pose=without_item,waterlogged=true": {
"model": "lib39:block/base_doll"
"facing=west,pose=further,waterlogged=true": {
"model": "lib39:block/base_doll",
"y": 270
}
}
}

View File

@ -1,4 +1,5 @@
{
"block.lib39.doll": "Doll",
"commands.lib39.calculate": "Calculate sum of two numbers",
"commands.lib39.calculate.result": "%d + %d = %d",
"commands.lib39.config": "Show configuration",
@ -49,7 +50,10 @@
"commands.lib39.test": "Test command",
"commands.lib39.test.success": "Test command executed successfully!",
"commands.lib39.test.with_param": "Test command with parameter: %s",
"invalid.player_name.too_long": "§c§lPlayer 's Name is too long than 16 characters.",
"item.lib39.fabric": "Fabric",
"item.lib39.forge": "Forge",
"item.lib39.neoforge": "NeoForge"
"item.lib39.neoforge": "NeoForge",
"tooltip.lib39.content.doll.hover.1": "§eSkinOwner §7:§a %s ",
"tooltip.lib39.content.doll.hover.2": "§7Rename with a player name in an anvil to change skin"
}

View File

@ -1,4 +1,5 @@
{
"block.lib39.doll": "偶",
"commands.lib39.calculate": "算二數和",
"commands.lib39.calculate.result": "%d 加 %d 等 %d",
"commands.lib39.config": "示配",
@ -49,7 +50,10 @@
"commands.lib39.test": "試令",
"commands.lib39.test.success": "試令行成!",
"commands.lib39.test.with_param": "帶參試令:%s",
"invalid.player_name.too_long": "§c§l玩家名過長限十六字",
"item.lib39.fabric": "織",
"item.lib39.forge": "砧",
"item.lib39.neoforge": "狸"
"item.lib39.neoforge": "狸",
"tooltip.lib39.content.doll.hover.1": "§e膚主§7:§a%s",
"tooltip.lib39.content.doll.hover.2": "§7鐵砧之上更名以易膚"
}

View File

@ -1,4 +1,5 @@
{
"block.lib39.doll": "人偶",
"commands.lib39.calculate": "計算兩個數字的和",
"commands.lib39.calculate.result": "%d + %d = %d",
"commands.lib39.config": "顯示配置",
@ -49,7 +50,10 @@
"commands.lib39.test": "測試命令",
"commands.lib39.test.success": "測試命令執行成功!",
"commands.lib39.test.with_param": "帶參數的測試命令:%s",
"invalid.player_name.too_long": "§c§l玩家名称过长最多16个字符",
"item.lib39.fabric": "织布",
"item.lib39.forge": "铁砧",
"item.lib39.neoforge": "小狐狸"
"item.lib39.neoforge": "小狐狸",
"tooltip.lib39.content.doll.hover.1": "§e皮肤所有者§7:§a%s",
"tooltip.lib39.content.doll.hover.2": "§7在铁砧上可通过重命名对应玩家名来改变皮肤"
}

View File

@ -1,4 +1,5 @@
{
"block.lib39.doll": "人偶",
"commands.lib39.calculate": "計算兩個數字的和",
"commands.lib39.calculate.result": "%d + %d = %d",
"commands.lib39.config": "顯示設定",
@ -49,7 +50,10 @@
"commands.lib39.test": "測試指令",
"commands.lib39.test.success": "測試指令執行成功!",
"commands.lib39.test.with_param": "帶參數的測試指令:%s",
"invalid.player_name.too_long": "§c§l玩家名稱過長最多16個字符",
"item.lib39.fabric": "織布",
"item.lib39.forge": "铁砧",
"item.lib39.neoforge": "狐狸"
"item.lib39.neoforge": "狐狸",
"tooltip.lib39.content.doll.hover.1": "§e皮膚所有者§7:§a%s",
"tooltip.lib39.content.doll.hover.2": "§7在鐵砧上可通過重命名對應玩家名來改變皮膚"
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/acacia_sapling"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/allium"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/amethyst_cluster"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/azure_bluet"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/bamboo_stage0"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/birch_sapling"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/brain_coral"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/brain_coral_fan"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/brown_mushroom"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/bubble_coral"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/bubble_coral_fan"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/cherry_sapling"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/cobweb"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/cornflower"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/crimson_fungus"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/crimson_roots_pot"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dandelion"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dark_oak_sapling"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dead_brain_coral"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dead_brain_coral_fan"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dead_bubble_coral"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dead_bubble_coral_fan"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dead_bush"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dead_fire_coral"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dead_fire_coral_fan"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dead_horn_coral"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dead_horn_coral_fan"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dead_tube_coral"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/dead_tube_coral_fan"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/fire_coral"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/fire_coral_fan"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/horn_coral"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/horn_coral_fan"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/jungle_sapling"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/lily_of_the_valley"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/oak_sapling"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/orange_tulip"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/oxeye_daisy"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/pink_tulip"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/poppy"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/red_mushroom"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/red_tulip"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/redstone_torch"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/spruce_sapling"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/torch"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/tube_coral"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/tube_coral_fan"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/warped_fungus"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/warped_roots_pot"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/white_tulip"
}
}

View File

@ -1,7 +0,0 @@
{
"parent": "lib39:block/base_doll_item",
"ambientocclusion": false,
"textures": {
"item": "minecraft:block/wither_rose"
}
}

View File

@ -0,0 +1,8 @@
{
"duck_toy": {
"sounds": [
"lib39:duck_toy"
],
"subtitle": "sound.lib39.subtitle.duck_toy"
}
}

View File

@ -0,0 +1,35 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_armor_stand": {
"conditions": {
"items": [
{
"items": [
"minecraft:armor_stand"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "lib39:doll"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_armor_stand",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"lib39:doll"
]
},
"sends_telemetry_event": false
}

View File

@ -0,0 +1,21 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "lib39:doll"
}
],
"rolls": 1.0
}
],
"random_sequence": "lib39:blocks/doll"
}

View File

@ -0,0 +1,15 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
{
"tag": "minecraft:wool"
},
{
"item": "minecraft:armor_stand"
}
],
"result": {
"item": "lib39:doll"
}
}

View File

@ -1,13 +1,19 @@
package top.r3944realms.lib39;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.FMLEnvironment;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.r3944realms.lib39.content.register.Lib39BlockEntities;
import top.r3944realms.lib39.content.register.Lib39Blocks;
import top.r3944realms.lib39.content.register.Lib39Items;
import top.r3944realms.lib39.content.register.Lib39SoundEvents;
import top.r3944realms.lib39.core.network.NetworkHandler;
import top.r3944realms.lib39.example.Lib39Example;
@ -42,10 +48,11 @@ public class Lib39 {
*/
public static void initialize() {
LOGGER.info("[Lib39] Initializing Lib39");
// IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
// Lib39Blocks.register(modEventBus);
// Lib39BlockEntities.register(modEventBus);
// Lib39Items.register(modEventBus);
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
Lib39Blocks.register(modEventBus);
Lib39BlockEntities.register(modEventBus);
Lib39Items.register(modEventBus);
Lib39SoundEvents.register(modEventBus);
NetworkHandler.register();
if (shouldRegisterExamples()) {
LOGGER.info("[Lib39] Registering Examples");

View File

@ -6,11 +6,11 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.base.datagen.provider.Lib39BlockModelProvider;
import top.r3944realms.lib39.base.datagen.provider.Lib39BlockStatesProvider;
import top.r3944realms.lib39.base.datagen.provider.Lib39ItemModelProvider;
import top.r3944realms.lib39.base.datagen.provider.*;
import top.r3944realms.lib39.base.datagen.value.Lib39LangKey;
import top.r3944realms.lib39.datagen.provider.SimpleLanguageProvider;
import top.r3944realms.lib39.datagen.provider.SimpleLootTableProvider;
import top.r3944realms.lib39.datagen.provider.SubProvidersWrapper;
import top.r3944realms.lib39.datagen.value.McLocale;
/**
@ -36,6 +36,9 @@ public class Lib39BaseDataGenEvent {
BlockModelDataGenerate(event);
BlockStateDataGenerate(event);
ItemModelDataGenerate(event);
LootTableDataGenerate(event);
SoundDefinitionDataGenerate(event);
RecipeGenerator(event);
}
private static void LanguageGenerator(@NotNull GatherDataEvent event, McLocale language) {
event.getGenerator().addProvider(
@ -61,4 +64,22 @@ public class Lib39BaseDataGenEvent {
(DataProvider.Factory<Lib39BlockStatesProvider>) pOutput -> new Lib39BlockStatesProvider(pOutput, event.getExistingFileHelper())
);
}
private static void SoundDefinitionDataGenerate(@NotNull GatherDataEvent event) {
event.getGenerator().addProvider(
event.includeClient(),
(DataProvider.Factory<Lib39SoundDefinitionsProvider>) pOutput -> new Lib39SoundDefinitionsProvider(pOutput, event.getExistingFileHelper())
);
}
private static void LootTableDataGenerate(@NotNull GatherDataEvent event) {
event.getGenerator().addProvider(
event.includeServer(),
(DataProvider.Factory<SimpleLootTableProvider>) pOutput -> new SimpleLootTableProvider(pOutput, new SubProvidersWrapper().addBlockEntry(new Lib39BlockLootTable()))
);
}
private static void RecipeGenerator(@NotNull GatherDataEvent event) {
event.getGenerator().addProvider(
event.includeServer(),
(DataProvider.Factory<Lib39RecipeProvider>) Lib39RecipeProvider::new
);
}
}

View File

@ -0,0 +1,11 @@
package top.r3944realms.lib39.base.datagen.provider;
import top.r3944realms.lib39.content.register.Lib39Blocks;
import top.r3944realms.lib39.datagen.provider.subprovider.BlockLootTables;
public class Lib39BlockLootTable extends BlockLootTables {
public Lib39BlockLootTable() {
super(Lib39Blocks.BLOCKS);
dropSelf(Lib39Blocks.DOLL);
}
}

View File

@ -31,10 +31,10 @@ public class Lib39BlockModelProvider extends BlockModelProvider {
*/
protected void registerPlants() {
for (PlantHelper.Plant plant: PlantHelper.Plant.values()) {
createCuffBedHeadModel(plant);
createPlantsModel(plant);
}
}
private void createCuffBedHeadModel(PlantHelper.Plant plant) {
private void createPlantsModel(PlantHelper.Plant plant) {
ResourceLocation rl = PlantHelper.getTextureRL(plant);
getBuilder("block/doll_item/" + plant)
.parent(getExistingFile(Lib39.rl("block/base_doll_item")))

View File

@ -28,7 +28,7 @@ public class Lib39BlockStatesProvider extends BlockStateProvider {
}
@Override
protected void registerStatesAndModels() {
// generateDollBlockStatesSimple();
generateDollBlockStatesSimple();
}
private void generateDollBlockStatesSimple() {
Block doll = Lib39Blocks.DOLL.get();
@ -41,7 +41,7 @@ public class Lib39BlockStatesProvider extends BlockStateProvider {
getVariantBuilder(doll).forAllStates(state -> {
Direction direction = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
int rotationY = getMainWestRotationY(direction);
int rotationY = getMainNorthRotationY(direction);
return ConfiguredModel.builder()
.modelFile(modelFile)

View File

@ -58,7 +58,7 @@ public class Lib39ItemModelProvider extends net.minecraftforge.client.model.gene
@Override
protected void registerModels() {
defaultModItemModelRegister();
// generateDollItemModel();
generateDollItemModel();
}
private void init() {
for(LangKeyValue obj : Lib39LangKey.INSTANCE.getValues()) {

View File

@ -0,0 +1,28 @@
package top.r3944realms.lib39.base.datagen.provider;
import net.minecraft.data.PackOutput;
import net.minecraft.data.recipes.FinishedRecipe;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.data.recipes.RecipeProvider;
import net.minecraft.data.recipes.ShapelessRecipeBuilder;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.content.register.Lib39Items;
import java.util.function.Consumer;
public class Lib39RecipeProvider extends RecipeProvider {
public Lib39RecipeProvider(PackOutput output) {
super(output);
}
@Override
protected void buildRecipes(@NotNull Consumer<FinishedRecipe> consumer) {
ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, Lib39Items.DOLL.get())
.requires(ItemTags.WOOL)
.requires(Items.ARMOR_STAND)
.unlockedBy("has_armor_stand",has(Items.ARMOR_STAND))
.save(consumer);
}
}

View File

@ -0,0 +1,29 @@
package top.r3944realms.lib39.base.datagen.provider;
import net.minecraft.data.PackOutput;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.common.data.SoundDefinition;
import net.minecraftforge.common.data.SoundDefinitionsProvider;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.content.register.Lib39SoundEvents;
public class Lib39SoundDefinitionsProvider extends SoundDefinitionsProvider {
public Lib39SoundDefinitionsProvider(PackOutput output, ExistingFileHelper helper) {
super(output, Lib39.MOD_ID, helper);
}
public SoundDefinition getSoundDefinition(String subTitle, SoundDefinition.Sound... sounds) {
return SoundDefinition.definition().subtitle(subTitle).with(sounds);
}
@Override
public void registerSounds() {
add(
Lib39SoundEvents.DUCK_TOY,
getSoundDefinition(
Lib39SoundEvents.getSubTitleTranslateKey("duck_toy"),
sound(Lib39SoundEvents.RL_DUCK_TOY, SoundDefinition.SoundType.SOUND)
)
);
}
}

View File

@ -3,6 +3,8 @@ package top.r3944realms.lib39.base.datagen.value;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Unmodifiable;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.content.register.Lib39Blocks;
import top.r3944realms.lib39.content.register.Lib39Items;
import top.r3944realms.lib39.datagen.value.ILangKeyValueCollection;
import top.r3944realms.lib39.datagen.value.LangKeyValue;
import top.r3944realms.lib39.datagen.value.ModPartEnum;
@ -223,6 +225,28 @@ public enum Lib39LangKey implements ILangKeyValueCollection {
*/
public void initLangKeyValues() {
Message.getItems().forEach(this::addLang);
LangKeyValue dollName = LangKeyValue.ofSupplier(
Lib39Items.DOLL, ModPartEnum.ITEM,
"Doll", "人偶", "人偶", "", false
);
addLang(dollName);
addLang(LangKeyValue.copyOf(
Lib39Blocks.DOLL, ModPartEnum.BLOCK, dollName
));
addLang(LangKeyValue.ofKey(
"tooltip.lib39.content.doll.hover.1", ModPartEnum.DESCRIPTION,
"§eSkinOwner §7:§a %s ", "§e皮肤所有者§7:§a%s", "§e皮膚所有者§7:§a%s", "§e膚主§7:§a%s"
));
addLang(LangKeyValue.ofKey(
"tooltip.lib39.content.doll.hover.2", ModPartEnum.DESCRIPTION,
"§7Rename with a player name in an anvil to change skin",
"§7在铁砧上可通过重命名对应玩家名来改变皮肤", "§7在鐵砧上可通過重命名對應玩家名來改變皮膚", "§7鐵砧之上更名以易膚"
));
addLang(LangKeyValue.ofKey(
"invalid.player_name.too_long", ModPartEnum.DESCRIPTION,
"§c§lPlayer 's Name is too long than 16 characters.",
"§c§l玩家名称过长最多16个字符", "§c§l玩家名稱過長最多16個字符", "§c§l玩家名過長限十六字"
));
if (Lib39.shouldRegisterExamples()) {
addLang(LangKeyValue.ofSupplier(
ExLib39Items.FABRIC, ModPartEnum.ITEM,

View File

@ -0,0 +1,72 @@
package top.r3944realms.lib39.client.model;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.model.Model;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.client.model.geom.PartPose;
import net.minecraft.client.model.geom.builders.*;
import net.minecraft.client.renderer.RenderType;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39;
public class DollModel extends Model {
public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation(Lib39.rl("doll_model"), "main");
public boolean slim = false;
private final ModelPart head;
private final ModelPart body;
private final ModelPart rightArm;
private final ModelPart leftArm;
private final ModelPart rightLeg;
private final ModelPart rightArmSlim;
private final ModelPart leftArmSlim;
private final ModelPart leftLeg;
public DollModel(ModelPart root) {
super(RenderType::entityTranslucent);
this.head = root.getChild("head");
this.body = root.getChild("body");
this.rightArm = root.getChild("right_arm");
this.leftArm = root.getChild("left_arm");
this.rightArmSlim = root.getChild("right_arm_slim");
this.leftArmSlim = root.getChild("left_arm_slim");
this.rightLeg = root.getChild("right_leg");
this.leftLeg = root.getChild("left_leg");
}
public static LayerDefinition createBodyLayer() {
MeshDefinition meshdefinition = new MeshDefinition();
PartDefinition partdefinition = meshdefinition.getRoot();
partdefinition.addOrReplaceChild("head", CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new CubeDeformation(0.0F)).texOffs(32, 0).addBox(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new CubeDeformation(0.5F)), PartPose.offset(0.0F, 9.0F, 0.0F));
partdefinition.addOrReplaceChild("body", CubeListBuilder.create().texOffs(16, 16).addBox(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(16, 32).addBox(-4.0F, 0.0F, -2.0F, 8.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offset(0.0F, 9.0F, 0.0F));
partdefinition.addOrReplaceChild("right_arm", CubeListBuilder.create().texOffs(40, 16).addBox(-3.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(40, 32).addBox(-3.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offsetAndRotation(-5.0F, 11.0F, 0.0F, 0.0F, 0.0F, 0.3927F));
partdefinition.addOrReplaceChild("right_arm_slim", CubeListBuilder.create().texOffs(40, 16).addBox(-2.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(40, 32).addBox(-2.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offsetAndRotation(-5.0F, 11.0F, 0.0F, 0.0F, 0.0F, 0.3927F));
partdefinition.addOrReplaceChild("left_arm_slim", CubeListBuilder.create().texOffs(32, 48).addBox(-1.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(48, 48).addBox(-1.0F, -2.0F, -2.0F, 3.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offsetAndRotation(5.0F, 11.0F, 0.0F, 0.0F, 0.0F, -0.3927F));
partdefinition.addOrReplaceChild("left_arm", CubeListBuilder.create().texOffs(32, 48).addBox(-1.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(48, 48).addBox(-1.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offsetAndRotation(5.0F, 11.0F, 0.0F, 0.0F, 0.0F, -0.3927F));
partdefinition.addOrReplaceChild("right_leg", CubeListBuilder.create().texOffs(0, 16).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(0, 32).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offsetAndRotation(-2.0F, 19.0F, -2.0F, -1.5708F, 0.3927F, 0.0F));
partdefinition.addOrReplaceChild("left_leg", CubeListBuilder.create().texOffs(16, 48).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).texOffs(0, 48).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offsetAndRotation(2.0F, 19.0F, -2.0F, -1.5708F, -0.3927F, 0.0F));
return LayerDefinition.create(meshdefinition, 64, 64);
}
@Override
public void renderToBuffer(PoseStack poseStack, @NotNull VertexConsumer vertexConsumer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
poseStack.pushPose();
poseStack.scale(0.5F, 0.5F, 0.5F);
poseStack.translate(0.0, 1.5010000467300415, 0.0);
this.head.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
this.body.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
if (this.slim) {
this.rightArmSlim.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
this.leftArmSlim.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
} else {
this.rightArm.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
this.leftArm.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
}
this.rightLeg.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
this.leftLeg.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
poseStack.popPose();
}
}

View File

@ -1,91 +1,47 @@
package top.r3944realms.lib39.client.renderer.block;
import com.mojang.authlib.GameProfile;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.Minecraft;
import com.mojang.math.Axis;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraftforge.client.model.data.ModelData;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.client.model.DollModel;
import top.r3944realms.lib39.client.renderer.item.DollItemRenderer;
import top.r3944realms.lib39.content.block.DollBlock;
import top.r3944realms.lib39.content.block.blockentity.DollBlockEntity;
import top.r3944realms.lib39.util.PlantHelper;
import top.r3944realms.lib39.util.SkinHelper;
import top.r3944realms.lib39.util.lang.Pair;
import java.util.HashMap;
import java.util.Map;
/**
* The type Doll block entity renderer.
*/
public class DollBlockEntityRenderer implements BlockEntityRenderer<DollBlockEntity> {
/**
* The Doll without item model.
*/
public BakedModel dollWithoutItemModel;
/**
* The Doll need item model.
*/
public BakedModel dollNeedItemModel;
/**
* The Item models.
*/
public final Map<PlantHelper.Plant, BakedModel> itemModels = new HashMap<>();
private final DollModel dollModel;
public DollBlockEntityRenderer(BlockEntityRendererProvider.@NotNull Context context) {
this.dollModel = new DollModel(context.bakeLayer(DollModel.LAYER_LOCATION));
}
@Override
public void render(@NotNull DollBlockEntity blockEntity, float partialTick, @NotNull PoseStack poseStack,
@NotNull MultiBufferSource buffer, int packedLight, int packedOverlay) {
Minecraft minecraft = Minecraft.getInstance();
ModelManager modelManager = minecraft.getModelManager();
if (dollNeedItemModel == null) {
dollNeedItemModel = modelManager.getModel(DollItemRenderer.DOLL_WITHOUT_ITEM_MODEL);
public void render(@NotNull DollBlockEntity dollBlockEntity, float partialTick, @NotNull PoseStack poseStack, @NotNull MultiBufferSource buffer, int packedLight, int packedOverlay) {
BlockState blockState = dollBlockEntity.getBlockState();
if (blockState.getBlock() instanceof DollBlock) {
Direction facing = blockState.getValue(DollBlock.FACING);
GameProfile profile = dollBlockEntity.getOwnerProfile();
Pair<ResourceLocation, Boolean> resourceLocationBooleanPair = DollItemRenderer.loadSkin(profile);
poseStack.pushPose();
poseStack.translate(0.5, 1.5, 0.5);
poseStack.scale(1.0F, -1.0F, -1.0F);
float rotation = facing.toYRot();
poseStack.mulPose(Axis.YP.rotationDegrees(rotation));
VertexConsumer vertexConsumer = buffer.getBuffer(RenderType.entityTranslucent(resourceLocationBooleanPair.first));
this.dollModel.slim = resourceLocationBooleanPair.second;
this.dollModel.renderToBuffer(poseStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F);
poseStack.popPose();
}
if (dollWithoutItemModel == null) {
dollWithoutItemModel = modelManager.getModel(DollItemRenderer.DOLL_NEED_ITEM_MODEL);
}
PlantHelper.Plant holdItem = blockEntity.getHoldItem();
renderModel(blockEntity, poseStack, buffer, packedLight, packedOverlay, holdItem != null ? dollNeedItemModel : dollWithoutItemModel, SkinHelper.getSkinTexture(blockEntity.getOwnerProfile()));
if (holdItem != null) {
BakedModel itemModel = itemModels.get(holdItem);
if (itemModel == null) {
BakedModel model = modelManager.getModel(Lib39.rl( "block/doll_item/" + holdItem));
itemModels.put(holdItem, model);
itemModel = model;
}
renderModel(blockEntity, poseStack, buffer, packedLight, packedOverlay, itemModel, PlantHelper.getTextureRL(holdItem));
}
}
private void renderModel(@NotNull DollBlockEntity blockEntity, @NotNull PoseStack poseStack, @NotNull MultiBufferSource buffer,
int packedLight, int packedOverlay,
BakedModel model, ResourceLocation texture) {
poseStack.pushPose();
poseStack.translate(0.5, 0.5, 0.5);
Minecraft minecraft = Minecraft.getInstance();
RandomSource rand = RandomSource.create();
ModelData data = ModelData.EMPTY;
for (RenderType rt : model.getRenderTypes(blockEntity.getBlockState(), rand, data)) {
VertexConsumer vc = buffer.getBuffer(rt);
// 渲染所有面
minecraft.getBlockRenderer().getModelRenderer().renderModel(
poseStack.last(), vc, null, model,
1.0f, 1.0f, 1.0f,
packedLight, packedOverlay,
data, rt
);
}
poseStack.popPose();
}
}

View File

@ -3,503 +3,81 @@ package top.r3944realms.lib39.client.renderer.item;
import com.mojang.authlib.GameProfile;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.Util;
import com.mojang.math.Axis;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
import net.minecraft.client.renderer.texture.SimpleTexture;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.client.resources.SkinManager;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.model.data.ModelData;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.util.PlantHelper;
import top.r3944realms.lib39.util.SkinHelper;
import top.r3944realms.lib39.util.nbt.NBTReader;
import top.r3944realms.lib39.client.model.DollModel;
import top.r3944realms.lib39.content.item.DollItem;
import top.r3944realms.lib39.util.GameProfileHelper;
import top.r3944realms.lib39.util.lang.Pair;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
/**
* The type Doll item renderer.
*/
@OnlyIn(Dist.CLIENT)
public class DollItemRenderer extends BlockEntityWithoutLevelRenderer {
private static final DollItemRenderer INSTANCE = new DollItemRenderer();
/**
* The constant BETag.
*/
public static final String BETag = "BlockEntityTag";
// 模型缓存系统
private static class ModelCacheEntry {
private final ResourceLocation modelLocation;
private BakedModel model;
private long lastAccessTime;
private boolean isMissingModel;
/**
* Instantiates a new Model cache entry.
*
* @param modelLocation the model location
*/
ModelCacheEntry(ResourceLocation modelLocation) {
this.modelLocation = modelLocation;
this.lastAccessTime = System.currentTimeMillis();
this.isMissingModel = false;
}
/**
* Gets model.
*
* @return the model
*/
BakedModel getModel() {
if (model == null && !isMissingModel) {
loadModel();
}
this.lastAccessTime = System.currentTimeMillis();
return model;
}
private void loadModel() {
Minecraft minecraft = Minecraft.getInstance();
ModelManager modelManager = minecraft.getModelManager();
this.model = modelManager.getModel(modelLocation);
// 检查是否是缺失模型
BakedModel missingModel = modelManager.getMissingModel();
this.isMissingModel = this.model == missingModel;
if (isMissingModel) {
Lib39.LOGGER.warn("Missing model: {}", modelLocation);
}
}
/**
* Should refresh boolean.
*
* @return the boolean
*/
boolean shouldRefresh() {
return model == null || (!isMissingModel && System.currentTimeMillis() - lastAccessTime > CACHE_DURATION);
}
}
// 缓存管理器
private static class ModelCacheManager {
private final Map<ResourceLocation, ModelCacheEntry> cache = new ConcurrentHashMap<>();
private final Set<ResourceLocation> pendingReloads = Collections.newSetFromMap(new ConcurrentHashMap<>());
private static final long CLEANUP_INTERVAL = 30000; // 30秒清理一次
private long lastCleanupTime = 0;
/**
* Gets model.
*
* @param location the location
* @return the model
*/
BakedModel getModel(ResourceLocation location) {
ModelCacheEntry entry = cache.computeIfAbsent(location, ModelCacheEntry::new);
// 定期检查是否需要刷新
if (entry.shouldRefresh() && !pendingReloads.contains(location)) {
scheduleModelReload(location);
}
return entry.getModel();
}
private void scheduleModelReload(ResourceLocation location) {
pendingReloads.add(location);
// 异步重新加载模型
CompletableFuture.runAsync(() -> {
try {
ModelCacheEntry entry = cache.get(location);
if (entry != null) {
entry.loadModel();
}
} finally {
pendingReloads.remove(location);
}
}, Util.backgroundExecutor());
}
/**
* Clear.
*/
void clear() {
cache.clear();
pendingReloads.clear();
}
/**
* Cleanup.
*/
void cleanup() {
long now = System.currentTimeMillis();
if (now - lastCleanupTime > CLEANUP_INTERVAL) {
cache.entrySet().removeIf(entry ->
entry.getValue().model == null ||
(entry.getValue().isMissingModel &&
now - entry.getValue().lastAccessTime > CACHE_DURATION * 2)
);
lastCleanupTime = now;
}
}
}
// 纹理缓存系统
private static class TextureCacheEntry {
private final ResourceLocation textureLocation;
private ResourceLocation registeredLocation;
private long lastAccessTime;
/**
* Instantiates a new Texture cache entry.
*
* @param textureLocation the texture location
*/
TextureCacheEntry(ResourceLocation textureLocation) {
this.textureLocation = textureLocation;
this.lastAccessTime = System.currentTimeMillis();
}
/**
* Gets texture.
*
* @return the texture
*/
ResourceLocation getTexture() {
if (registeredLocation == null) {
registerTexture();
}
this.lastAccessTime = System.currentTimeMillis();
return registeredLocation;
}
private void registerTexture() {
Minecraft minecraft = Minecraft.getInstance();
TextureManager textureManager = minecraft.getTextureManager();
// 检查纹理是否已加载
textureManager.getTexture(textureLocation, MissingTextureAtlasSprite.getTexture());
registeredLocation = textureLocation;
}
private void loadTextureAsync() {
CompletableFuture.runAsync(() -> {
try {
Minecraft minecraft = Minecraft.getInstance();
TextureManager textureManager = minecraft.getTextureManager();
// 加载纹理
textureManager.register(textureLocation,
new SimpleTexture(textureLocation));
registeredLocation = textureLocation;
} catch (Exception e) {
Lib39.LOGGER.error("Failed to load texture: {}", textureLocation, e);
}
});
}
/**
* Should refresh boolean.
*
* @return the boolean
*/
boolean shouldRefresh() {
return registeredLocation == null ||
System.currentTimeMillis() - lastAccessTime > CACHE_DURATION;
}
}
// 常量定义
private static final long CACHE_DURATION = 5000; // 5秒
private static final long ITEM_TEXTURE_CACHE_DURATION = 30000; // 30秒材质不常变
/**
* The constant DOLL_NEED_ITEM_MODEL.
*/
public static final ResourceLocation DOLL_NEED_ITEM_MODEL = Lib39.rl("block/doll_default");
/**
* The constant DOLL_WITHOUT_ITEM_MODEL.
*/
public static final ResourceLocation DOLL_WITHOUT_ITEM_MODEL = Lib39.rl("block/doll_without_item");
/**
* The constant DOLL_ITEM_MODEL.
*/
public static final ResourceLocation DOLL_ITEM_MODEL = Lib39.rl("block/base_doll_item");
/**
* The constant ITEM_MODELS.
*/
public static final Map<PlantHelper.Plant, ResourceLocation> ITEM_MODELS = new HashMap<>();
static {
initItemModels();
}
/**
* Init item models.
*/
public static void initItemModels() {
for (PlantHelper.Plant plant : PlantHelper.Plant.values()) {
ITEM_MODELS.put(plant, Lib39.rl("block/doll_item/" + plant));
}
}
// 缓存实例
private final ModelCacheManager modelCache = new ModelCacheManager();
private final Map<String, TextureCacheEntry> itemTextureCache = new ConcurrentHashMap<>();
private final Map<UUID, TextureCacheEntry> skinTextureCache = new ConcurrentHashMap<>();
private final TextureCacheEntry defaultSkinTexture;
// 花材质映射静态初始化
private static final Map<String, ResourceLocation> ITEM_TEXTURE_MAP = createItemTextureMap();
private static @Unmodifiable Map<String, ResourceLocation> createItemTextureMap() {
Map<String, ResourceLocation> map = new HashMap<>();
for (PlantHelper.Plant value : PlantHelper.Plant.values()) {
map.put(value.toString(), new ResourceLocation(value.name));
}
return Map.copyOf(map);
}
private static DollItemRenderer instance;
private final DollModel dollModel;
private DollItemRenderer() {
super(Minecraft.getInstance().getBlockEntityRenderDispatcher(),
Minecraft.getInstance().getEntityModels());
// 初始化默认皮肤纹理
this.defaultSkinTexture = new TextureCacheEntry(
DefaultPlayerSkin.getDefaultSkin()
super(
Minecraft.getInstance().getBlockEntityRenderDispatcher(),
Minecraft.getInstance().getEntityModels()
);
this.dollModel = new DollModel(
Minecraft.getInstance().getEntityModels().bakeLayer(DollModel.LAYER_LOCATION)
);
}
/**
* Gets instance.
*
* @return the instance
*/
public static DollItemRenderer getInstance() {
return INSTANCE;
if (instance == null) {
instance = new DollItemRenderer();
}
return instance;
}
@Override
public void renderByItem(@NotNull ItemStack stack, @NotNull ItemDisplayContext displayContext,
@NotNull PoseStack poseStack, @NotNull MultiBufferSource buffer,
int packedLight, int packedOverlay) {
// 1. 从NBT获取数据
DollRenderData renderData = extractRenderData(stack);
// 2. 执行渲染
renderDoll(renderData, displayContext, poseStack, buffer, packedLight, packedOverlay);
// 3. 定期清理缓存
modelCache.cleanup();
cleanupTextureCache();
}
// 提取渲染数据
@Contract("_ -> new")
private @NotNull DollRenderData extractRenderData(@NotNull ItemStack stack) {
AtomicReference<String> itemType = new AtomicReference<>();
AtomicReference<GameProfile> gameProfile = new AtomicReference<>();
CompoundTag tag = stack.getTag();
if (tag != null) {
NBTReader.of(tag)
.compound(BETag, compoundTag -> NBTReader.of(compoundTag)
.string("ItemType", itemType::set)
.compound("ProfileOwner", profile -> gameProfile.set(NbtUtils.readGameProfile(profile)))
);
}
return new DollRenderData(itemType.get(), gameProfile.get());
}
private void renderDoll(@NotNull DollRenderData data, ItemDisplayContext displayContext,
@NotNull PoseStack poseStack, MultiBufferSource buffer,
int packedLight, int packedOverlay) {
// 总是渲染基础人偶模型
BakedModel baseModel = data.hasItem() ? getCachedModel(DOLL_NEED_ITEM_MODEL) : getCachedModel(DOLL_WITHOUT_ITEM_MODEL);
if (baseModel == null || baseModel == Minecraft.getInstance().getModelManager().getMissingModel()) {
return; // 模型不存在不渲染
}
// 获取纹理
ResourceLocation skinTexture = getSkinTexture(data.gameProfile);
// 开始渲染
poseStack.pushPose();
try {
// 应用物品变换
applyItemTransforms(displayContext, poseStack);
// 渲染基础模型皮肤部分
renderModelWithTexture(baseModel, skinTexture, poseStack, buffer,
packedLight, packedOverlay);
// 如果有手持物品渲染物品部分
if (data.hasItem()) {
renderHeldItem(data, poseStack, buffer, packedLight, packedOverlay);
}
} finally {
poseStack.popPose();
}
}
private void renderHeldItem(DollRenderData data, PoseStack poseStack,
MultiBufferSource buffer, int packedLight, int packedOverlay) {
BakedModel itemModel = getCachedModel(ITEM_MODELS.get(PlantHelper.Plant.valueOf(data.itemType)));
if (itemModel == null || itemModel == Minecraft.getInstance().getModelManager().getMissingModel()) {
public void renderByItem(@NotNull ItemStack stack, @NotNull ItemDisplayContext displayContext, @NotNull PoseStack poseStack, @NotNull MultiBufferSource buffer, int packedLight, int packedOverlay) {
if (!(stack.getItem() instanceof DollItem)) {
return;
}
ResourceLocation itemTexture = getItemTexture(data.itemType);
if (itemTexture == null) return;
GameProfile profile = GameProfileHelper.getProfileFromItemStack(stack);
Pair<ResourceLocation, Boolean> resourceLocationBooleanPair = loadSkin(profile);
ResourceLocation playerSkin = resourceLocationBooleanPair.first;
boolean isSlim = resourceLocationBooleanPair.second;
poseStack.pushPose();
try {
renderModelWithTexture(itemModel, itemTexture, poseStack, buffer,
packedLight, packedOverlay);
} finally {
poseStack.popPose();
}
}
VertexConsumer vertexConsumer = buffer.getBuffer(
RenderType.entityTranslucent(playerSkin)
);
// 获取缓存的模型
private BakedModel getCachedModel(ResourceLocation modelLoc) {
return modelCache.getModel(modelLoc);
}
/**
* Gets skin texture.
*
* @param gameProfile the game profile
* @return the skin texture
*/
// 获取皮肤纹理带缓存
public ResourceLocation getSkinTexture(@Nullable GameProfile gameProfile) {
if (gameProfile == null) {
return defaultSkinTexture.getTexture();
}
// 优先使用UUID
UUID cacheKey = gameProfile.getId();
TextureCacheEntry entry = skinTextureCache.get(cacheKey);
if (entry == null || entry.shouldRefresh()) {
ResourceLocation textureLocation = SkinHelper.resolveSkinTexture(gameProfile);
entry = new TextureCacheEntry(textureLocation);
skinTextureCache.put(cacheKey, entry);
}
return entry.getTexture();
}
// 获取花纹理带缓存
private ResourceLocation getItemTexture(String itemType) {
ResourceLocation textureLocation = ITEM_TEXTURE_MAP.getOrDefault(itemType,
PlantHelper.getTextureRL(PlantHelper.Plant.ALLIUM));
TextureCacheEntry entry = itemTextureCache.get(itemType);
if (entry == null || entry.shouldRefresh()) {
entry = new TextureCacheEntry(textureLocation);
itemTextureCache.put(itemType, entry);
}
return entry.getTexture();
}
// 应用物品变换
@SuppressWarnings("deprecation")
private void applyItemTransforms(ItemDisplayContext displayContext, PoseStack poseStack) {
BakedModel baseModel = getCachedModel(DOLL_WITHOUT_ITEM_MODEL);
if (baseModel != null) {
baseModel.getTransforms().getTransform(displayContext)
.apply(false, poseStack);
}
poseStack.translate(-0.5, -0.5, -0.5);
}
// 渲染模型带纹理
private void renderModelWithTexture(BakedModel model, ResourceLocation texture,
@NotNull PoseStack poseStack, @NotNull MultiBufferSource buffer,
int packedLight, int packedOverlay) {
Minecraft minecraft = Minecraft.getInstance();
RenderType renderType = RenderType.entityCutout(texture);
VertexConsumer vertexConsumer = buffer.getBuffer(renderType);
minecraft.getBlockRenderer().getModelRenderer().renderModel(
poseStack.last(),
poseStack.translate(0.5, 2.6, 0.8);
poseStack.scale(1.8F, -1.8F, -1.8F);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.dollModel.slim = isSlim;
this.dollModel.renderToBuffer(
poseStack,
vertexConsumer,
null,
model,
1.0f, 1.0f, 1.0f,
packedLight,
packedOverlay,
ModelData.EMPTY,
renderType
);
}
// 清理纹理缓存
private void cleanupTextureCache() {
long now = System.currentTimeMillis();
// 清理皮肤缓存超过2分钟未访问
skinTextureCache.entrySet().removeIf(entry ->
now - entry.getValue().lastAccessTime > 120000
1.0F, 1.0F, 1.0F, 1.0F
);
// 清理花纹理缓存超过5分钟未访问
itemTextureCache.entrySet().removeIf(entry ->
now - entry.getValue().lastAccessTime > ITEM_TEXTURE_CACHE_DURATION
);
poseStack.popPose();
}
/**
* Clear all caches.
*/
// 清除所有缓存用于资源包重载
public void clearAllCaches() {
modelCache.clear();
skinTextureCache.clear();
itemTextureCache.clear();
}
// 渲染数据持有类
private record DollRenderData(String itemType, GameProfile gameProfile) {
/**
* Has item boolean.
*
* @return the boolean
*/
public boolean hasItem() {
return itemType != null;
public static @NotNull Pair<ResourceLocation,Boolean> loadSkin(GameProfile profile) {
SkinManager skinManager = Minecraft.getInstance().getSkinManager();
ResourceLocation playerSkin;
boolean isSlim;
if (profile != null) {
playerSkin = skinManager.getInsecureSkinLocation(profile);
isSlim = GameProfileHelper.isSlimArms(profile);
} else {
playerSkin = DefaultPlayerSkin.getDefaultSkin(); //6 new SkinType("textures/entity/player/slim/steve.png", DefaultPlayerSkin.ModelType.SLIM),
isSlim = true;
}
}
@Override
public void onResourceManagerReload(@NotNull ResourceManager resourceManager) {
super.onResourceManagerReload(resourceManager);
clearAllCaches();
return Pair.of(playerSkin, isSlim);
}
}

View File

@ -1,5 +1,6 @@
package top.r3944realms.lib39.content.block;
import com.mojang.authlib.GameProfile;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleTypes;
@ -9,12 +10,14 @@ import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.piston.PistonBaseBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
@ -23,14 +26,24 @@ import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import top.r3944realms.lib39.content.block.blockentity.DollBlockEntity;
import top.r3944realms.lib39.content.block.property.DollPose;
import top.r3944realms.lib39.content.register.Lib39BlockEntities;
import top.r3944realms.lib39.content.register.Lib39Items;
import top.r3944realms.lib39.content.register.Lib39SoundEvents;
import top.r3944realms.lib39.util.GameProfileHelper;
import java.util.List;
/**
* The type Doll block.
@ -70,6 +83,16 @@ public class DollBlock extends HorizontalDirectionalBlock implements SimpleWater
.setValue(WATERLOGGED, false));
}
@Override
public boolean canBeReplaced(@NotNull BlockState state, @NotNull BlockPlaceContext useContext) {
return false;
}
@Override
public @Nullable PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.DESTROY;
}
@Override
public @NotNull BlockState updateShape(@NotNull BlockState currentState, @NotNull Direction direction, @NotNull BlockState neighborState,
@NotNull LevelAccessor level, @NotNull BlockPos currentPos, @NotNull BlockPos neighborPos) {
@ -131,7 +154,7 @@ public class DollBlock extends HorizontalDirectionalBlock implements SimpleWater
*/
private void playDollSound(@NotNull ServerLevel serverLevel, BlockPos blockPos) {
float pitch = BASE_PITCH + serverLevel.random.nextFloat() * PITCH_VARIANCE;
serverLevel.playSound(null, blockPos, SoundEvents.NOTE_BLOCK_BASEDRUM.get(),
serverLevel.playSound(null, blockPos, Lib39SoundEvents.DUCK_TOY.get(),
SoundSource.BLOCKS, BASE_VOLUME, pitch);
}
@ -153,6 +176,7 @@ public class DollBlock extends HorizontalDirectionalBlock implements SimpleWater
@Override
protected void createBlockStateDefinition(StateDefinition.@NotNull Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(FACING, WATERLOGGED, POSE);
}
@ -167,4 +191,53 @@ public class DollBlock extends HorizontalDirectionalBlock implements SimpleWater
public @NotNull RenderShape getRenderShape(@NotNull BlockState state) {
return RenderShape.ENTITYBLOCK_ANIMATED;
}
@Override
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos, Player player) {
ItemStack stack = super.getCloneItemStack(state, target, level, pos, player);
BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof DollBlockEntity doll) {
GameProfile profile = doll.getOwnerProfile();
if (profile != null) {
GameProfileHelper.saveProfileToItemStack(stack, profile);
}
}
return stack;
}
/**
* 最重要的方法重写掉落逻辑
*/
@Override
@NotNull
public List<ItemStack> getDrops(@NotNull BlockState state, @NotNull LootParams.Builder params) {
// 获取方块实体
BlockEntity blockEntity = params.getOptionalParameter(LootContextParams.BLOCK_ENTITY);
if (blockEntity instanceof DollBlockEntity dollEntity) {
List<ItemStack> customDrops = getCustomDrops(dollEntity, params);
if (customDrops != null) return customDrops;
}
return super.getDrops(state, params);
}
/**
* 生成自定义掉落物
*/
@Nullable
private List<ItemStack> getCustomDrops(DollBlockEntity dollEntity, LootParams.Builder params) {
if (params.getOptionalParameter(LootContextParams.THIS_ENTITY) instanceof Player player) {
if (player.isCreative()) {
return List.of();
}
}
GameProfile profile = dollEntity.getOwnerProfile();
if (profile != null) {
ItemStack instance = Lib39Items.DOLL.get().getDefaultInstance();
GameProfileHelper.saveProfileToItemStack(instance, profile);
return List.of(instance);
}
return null;
}
}

View File

@ -1,6 +1,7 @@
package top.r3944realms.lib39.content.block.blockentity;
import com.mojang.authlib.GameProfile;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
@ -10,7 +11,7 @@ import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.content.register.Lib39BlockEntities;
import top.r3944realms.lib39.util.PlantHelper;
import top.r3944realms.lib39.util.GameProfileHelper;
import top.r3944realms.lib39.util.nbt.NBTReader;
import top.r3944realms.lib39.util.nbt.NBTWriter;
@ -20,19 +21,9 @@ import javax.annotation.Nullable;
* The type Doll block entity.
*/
public class DollBlockEntity extends BlockEntity {
/**
* The constant TAG_OWNER.
*/
public static final String TAG_OWNER = "ProfileOwner";
/**
* The constant TAG_HOLD_ITEM.
*/
public static final String TAG_HOLD_ITEM = "ItemType";
@Nullable
private GameProfile owner;
@Nullable
private PlantHelper.Plant holdItem;
/**
* Instantiates a new Doll block entity.
@ -46,17 +37,14 @@ public class DollBlockEntity extends BlockEntity {
protected void saveAdditional(@NotNull CompoundTag tag) {
super.saveAdditional(tag);
//noinspection DataFlowIssue
NBTWriter.of(tag)
.compoundIf(TAG_OWNER, owner != null, () -> NbtUtils.writeGameProfile(new CompoundTag(), this.owner))
.stringIf(TAG_HOLD_ITEM, () -> holdItem.name,holdItem != null);
.compoundIf(GameProfileHelper.TAG_OWN_PROFILE, owner != null, () -> NbtUtils.writeGameProfile(new CompoundTag(), this.owner));
}
public void load(@NotNull CompoundTag tag) {
super.load(tag);
NBTReader.of(tag)
.compound(TAG_OWNER, compoundTag -> setOwner(NbtUtils.readGameProfile(compoundTag)))
.string(TAG_HOLD_ITEM, holdItem -> setHoldItem(PlantHelper.Plant.valueOf(holdItem)));
.compound(GameProfileHelper.TAG_OWN_PROFILE, compoundTag -> setOwner(NbtUtils.readGameProfile(compoundTag)));
}
/**
@ -69,15 +57,6 @@ public class DollBlockEntity extends BlockEntity {
return this.owner;
}
/**
* Gets hold item.
*
* @return the hold item
*/
@Nullable
public PlantHelper.Plant getHoldItem() {
return this.holdItem;
}
public ClientboundBlockEntityDataPacket getUpdatePacket() {
return ClientboundBlockEntityDataPacket.create(this);
@ -93,20 +72,14 @@ public class DollBlockEntity extends BlockEntity {
* @param owner the owner
*/
public void setOwner(@Nullable GameProfile owner) {
synchronized(this) {
synchronized (this) {
this.owner = owner;
}
this.updateOwnerProfile();
}
/**
* Sets hold item.
*
* @param holdItem the hold item
*/
public void setHoldItem(@Nullable PlantHelper.Plant holdItem) {
this.holdItem = holdItem;
public void setOwner(@Nullable String ownerName) {
setOwner(new GameProfile(Util.NIL_UUID, ownerName));
}
private void updateOwnerProfile() {

View File

@ -12,9 +12,9 @@ public enum DollPose implements StringRepresentable {
*/
DEFAULT("default"),
/**
* Without item doll pose.
* further support
*/
WITHOUT_ITEM("without_item"),
FURTHER("further"),
;
private final String name;
DollPose(String name) {

View File

@ -1,12 +1,22 @@
package top.r3944realms.lib39.content.item;
import com.mojang.authlib.GameProfile;
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.Level;
import net.minecraftforge.client.extensions.common.IClientItemExtensions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import top.r3944realms.lib39.client.renderer.item.DollItemRenderer;
import top.r3944realms.lib39.content.register.Lib39Blocks;
import top.r3944realms.lib39.util.GameProfileHelper;
import java.util.List;
import java.util.function.Consumer;
/**
@ -31,4 +41,18 @@ public class DollItem extends BlockItem {
}
});
}
@Override
public boolean canEquip(ItemStack stack, EquipmentSlot armorType, Entity entity) {
return armorType == EquipmentSlot.HEAD;
}
@Override
public void appendHoverText(@NotNull ItemStack stack, @Nullable Level level, @NotNull List<Component> tooltip, @NotNull TooltipFlag flag) {
GameProfile profileFromItemStack = GameProfileHelper.getProfileFromItemStack(stack);
if (profileFromItemStack != null && profileFromItemStack.getName() != null) {
tooltip.add(Component.translatable("tooltip.lib39.content.doll.hover.1", profileFromItemStack.getName()));
}
tooltip.add(Component.translatable("tooltip.lib39.content.doll.hover.2"));
}
}

View File

@ -27,6 +27,7 @@ public class Lib39Blocks {
.registerBlock(BLOCKS, DollBlock::new)
.build();
/**
* Register.
*

View File

@ -0,0 +1,25 @@
package top.r3944realms.lib39.content.register;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import top.r3944realms.lib39.Lib39;
public class Lib39SoundEvents {
public static final DeferredRegister<SoundEvent> SOUND_EVENTS = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, Lib39.MOD_ID);
public static final ResourceLocation RL_DUCK_TOY = Lib39.rl("duck_toy");
public static final RegistryObject<SoundEvent> DUCK_TOY = SOUND_EVENTS.register("duck_toy",
() -> SoundEvent.createFixedRangeEvent(RL_DUCK_TOY, 32.0f));
public static void register(IEventBus bus) {
SOUND_EVENTS.register(bus);
}
public static String getSubTitleTranslateKey(String name) {
return "sound." + Lib39.MOD_ID + ".subtitle." + name;
}
}

View File

@ -59,7 +59,7 @@ public class CompatManager {
* @param compat the compat
*/
public void registerCompat(String namespace, String path, ICompat compat) {
registerCompat(new ResourceLocation(namespace, path), compat);
registerCompat(Lib39.rl(namespace, path), compat);
}
/**

View File

@ -10,7 +10,10 @@ import net.minecraftforge.client.event.RegisterShadersEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.client.model.DollModel;
import top.r3944realms.lib39.client.renderer.block.DollBlockEntityRenderer;
import top.r3944realms.lib39.client.shader.Lib39Shaders;
import top.r3944realms.lib39.content.register.Lib39BlockEntities;
import java.util.Map;
@ -40,48 +43,14 @@ public class ClientEventHandler {
*/
@SubscribeEvent
public static void onRegisterRenderer (EntityRenderersEvent.RegisterRenderers event) {
// event.registerBlockEntityRenderer(Lib39BlockEntities.DOLL_BLOCK_ENTITY.get(), context -> new DollBlockEntityRenderer());
event.registerBlockEntityRenderer(Lib39BlockEntities.DOLL_BLOCK_ENTITY.get(),DollBlockEntityRenderer::new);
}
/**
* On model baking.
*
* @param event the event
*/
@SubscribeEvent
public static void onModelBaking(ModelEvent.RegisterAdditional event) {
// event.register(DollItemRenderer.DOLL_ITEM_MODEL);
// DollItemRenderer.ITEM_MODELS.values().forEach(event::register);
// event.register(DollItemRenderer.DOLL_WITHOUT_ITEM_MODEL);
// event.register(DollItemRenderer.DOLL_NEED_ITEM_MODEL);
public static void registerLayerDefinitions(EntityRenderersEvent.RegisterLayerDefinitions event) {
event.registerLayerDefinition(DollModel.LAYER_LOCATION, DollModel::createBodyLayer);
}
/**
* On model baking.
*
* @param event the event
*/
@SubscribeEvent
public static void onModelBaking(ModelEvent.ModifyBakingResult event) {
// Map<ResourceLocation, BakedModel> modelRegistry = event.getModels();
//
// // 检查模型是否被正确加载
// checkModelLoaded(modelRegistry, DollItemRenderer.DOLL_NEED_ITEM_MODEL);
// checkModelLoaded(modelRegistry, DollItemRenderer.DOLL_WITHOUT_ITEM_MODEL);
// checkModelLoaded(modelRegistry, DollItemRenderer.DOLL_ITEM_MODEL);
}
private static void checkModelLoaded(@NotNull Map<ResourceLocation, BakedModel> registry, ResourceLocation location) {
BakedModel model = registry.get(location);
if (model == null) {
Lib39.LOGGER.warn("Model not found in registry: {}", location);
} else if (model == Minecraft.getInstance().getModelManager().getMissingModel()) {
Lib39.LOGGER.warn("Model is missing: {}", location);
} else {
Lib39.LOGGER.debug("Model loaded successfully: {}", location);
}
}
}
/**

View File

@ -1,14 +1,21 @@
package top.r3944realms.lib39.core.event;
import com.mojang.authlib.GameProfile;
import net.minecraft.Util;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.data.event.GatherDataEvent;
import net.minecraftforge.event.AnvilUpdateEvent;
import net.minecraftforge.event.BuildCreativeModeTabContentsEvent;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.event.TickEvent;
@ -18,7 +25,6 @@ import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.RegistryObject;
import top.r3944realms.lib39.Lib39;
@ -26,9 +32,12 @@ import top.r3944realms.lib39.api.event.RegisterCompatEvent;
import top.r3944realms.lib39.api.event.SyncManagerRegisterEvent;
import top.r3944realms.lib39.base.command.Lib39HelpCommand;
import top.r3944realms.lib39.base.datagen.Lib39BaseDataGenEvent;
import top.r3944realms.lib39.content.item.DollItem;
import top.r3944realms.lib39.content.register.Lib39Items;
import top.r3944realms.lib39.core.compat.CompatManager;
import top.r3944realms.lib39.core.sync.ISyncData;
import top.r3944realms.lib39.core.sync.SyncData2Manager;
import top.r3944realms.lib39.util.GameProfileHelper;
import java.util.ArrayList;
import java.util.List;
@ -126,6 +135,26 @@ public class CommonEventHandler {
syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::checkIfDirtyThenUpdate)));
}
}
@SubscribeEvent
public static void onAnvilRename(AnvilUpdateEvent event) {
if (event.getLeft().getItem() instanceof DollItem) {
String name = event.getName();
if (name != null && name.length() < 15) {
GameProfile profile = new GameProfile(Util.NIL_UUID, name);
ItemStack copied = Lib39Items.DOLL.get().getDefaultInstance();
SkullBlockEntity.updateGameprofile(profile,
profile1 -> GameProfileHelper.saveProfileToItemStack(copied, profile1)
);
copied.setCount(event.getLeft().getCount());
event.setOutput(copied);
event.setCost(1);
} else {
ItemStack defaultInstance = Items.BARRIER.getDefaultInstance();
defaultInstance.setHoverName(Component.translatable("invalid.player_name.too_long"));
event.setOutput(defaultInstance);
}
}
}
/**
* On entity join world.

View File

@ -20,7 +20,7 @@ public class NetworkHandler {
* The constant INSTANCE.
*/
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
new ResourceLocation(Lib39.MOD_ID, "main"),
Lib39.rl(Lib39.MOD_ID, "main"),
() -> Lib39.ModInfo.VERSION,
Lib39.ModInfo.VERSION::equals,
Lib39.ModInfo.VERSION::equals

View File

@ -18,6 +18,7 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePrope
import net.minecraft.world.level.storage.loot.predicates.MatchTool;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.RegistryObject;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@ -26,6 +27,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* The type Block loot tables.
@ -34,12 +36,18 @@ import java.util.function.Function;
public class BlockLootTables extends BlockLootSubProvider {
private final List<BlockEntry> blockEntries = new ArrayList<>();
private final DeferredRegister<Block> knowBlocks;
/**
* Instantiates a new Block loot tables.
*/
public BlockLootTables() {
public BlockLootTables(DeferredRegister<Block> deferredRegister) {
super(Set.of(), FeatureFlags.REGISTRY.allFlags());
knowBlocks = deferredRegister;
}
@Override
protected @NotNull Iterable<Block> getKnownBlocks() {
return knowBlocks.getEntries().stream().map(RegistryObject::get).collect(Collectors.toSet());
}
// ==================== 流畅 API 构建方法 ====================
@ -326,9 +334,9 @@ public class BlockLootTables extends BlockLootSubProvider {
*
* @return the block loot tables
*/
@Contract(" -> new")
public static @NotNull BlockLootTables create() {
return new BlockLootTables();
@Contract("_ -> new")
public static @NotNull BlockLootTables create(DeferredRegister<Block> deferredRegister) {
return new BlockLootTables(deferredRegister);
}
/**

View File

@ -19,7 +19,7 @@ public class TestSyncCapProvider implements ICapabilitySerializable<CompoundTag>
/**
* The constant TEST_SYNC_REL.
*/
public static final ResourceLocation TEST_SYNC_REL = new ResourceLocation(Lib39.MOD_ID, "test_sync_data");
public static final ResourceLocation TEST_SYNC_REL = Lib39.rl(Lib39.MOD_ID, "test_sync_data");
private final AbstractedTestSyncData instance;
private final LazyOptional<AbstractedTestSyncData> optional;

View File

@ -21,7 +21,7 @@ public class TestSyncData extends AbstractedTestSyncData {
/**
* The constant ID.
*/
public static final ResourceLocation ID = new ResourceLocation(Lib39.MOD_ID, "test_sync_data");
public static final ResourceLocation ID = Lib39.rl(Lib39.MOD_ID, "test_sync_data");
// NBT 键常量
private static final String NBT_KEY_STRING = "test_string";

View File

@ -17,7 +17,7 @@ public class ExNetworkHandler {
static {
INSTANCE = NetworkRegistry.newSimpleChannel(
new ResourceLocation(Lib39.MOD_ID, "test"),
Lib39.rl(Lib39.MOD_ID, "test"),
() -> "1.0",
s -> true,
s -> true

View File

@ -0,0 +1,50 @@
package top.r3944realms.lib39.mixin.carryon;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Pseudo;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import top.r3944realms.lib39.content.item.DollItem;
import top.r3944realms.lib39.util.GameProfileHelper;
import tschipp.carryon.client.render.CarriedObjectRender;
import tschipp.carryon.common.carry.CarryOnDataManager;
@Pseudo
@Mixin(value = CarriedObjectRender.class, remap = false)
public class MixinCarriedObjectRender {
@ModifyVariable(
method = "drawFirstPersonBlock",
at = @At(
value = "INVOKE",
target = "Ltschipp/carryon/client/render/CarryRenderHelper;renderBakedModel(Lnet/minecraft/world/item/ItemStack;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/client/resources/model/BakedModel;)V"
),
name = "stack"
)
private static ItemStack warpDollItem$1(ItemStack stack, @Local(ordinal = 0, argsOnly = true) Player player) {
if (stack.getItem() instanceof DollItem) {
CompoundTag compound = CarryOnDataManager.getCarryData(player).getNbt().getCompound("tile").getCompound(GameProfileHelper.TAG_OWN_PROFILE);
stack.getOrCreateTag().put(GameProfileHelper.TAG_OWN_PROFILE, compound);
}
return stack;
}
@ModifyVariable(
method = "drawThirdPerson",
at = @At(
value = "INVOKE",
target = "Ltschipp/carryon/client/render/CarryRenderHelper;renderBakedModel(Lnet/minecraft/world/item/ItemStack;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/client/resources/model/BakedModel;)V"
),
name = "tileItem"
)
private static ItemStack warpDollItem$2(ItemStack stack, @Local(ordinal = 0) Player player) {
if (stack.getItem() instanceof DollItem) {
CompoundTag compound = CarryOnDataManager.getCarryData(player).getNbt().getCompound("tile").getCompound(GameProfileHelper.TAG_OWN_PROFILE);
stack.getOrCreateTag().put(GameProfileHelper.TAG_OWN_PROFILE, compound);
}
return stack;
}
}

Some files were not shown because too many files have changed in this diff Show More