版本更新到1.0.0
1. 对WayStone做进一步适配(显然WS自己有问题) 2. 添加了禁拴效果及其对应的药水 3. 添加了彩蛋内容(暂无非作弊获取方式) 4. 添加了最大拴绳拉力阈值,在配置中调整
This commit is contained in:
parent
186103e0c5
commit
ad275c4d37
|
|
@ -167,6 +167,7 @@ dependencies {
|
||||||
modImplementation("curse.maven:bendy-lib-623373:4550371")
|
modImplementation("curse.maven:bendy-lib-623373:4550371")
|
||||||
modImplementation("curse.maven:waystones-245755:6856603")
|
modImplementation("curse.maven:waystones-245755:6856603")
|
||||||
modImplementation("curse.maven:balm-531761:7087245")
|
modImplementation("curse.maven:balm-531761:7087245")
|
||||||
|
// modImplementation("curse.maven:kaleidoscope-doll-1233277:7201584")
|
||||||
// modRuntimeOnly("curse.maven:luckperms-431733:4738950")
|
// modRuntimeOnly("curse.maven:luckperms-431733:4738950")
|
||||||
modImplementation("software.bernie.geckolib:geckolib-forge-${minecraft_version}:${geckolib_version}")
|
modImplementation("software.bernie.geckolib:geckolib-forge-${minecraft_version}:${geckolib_version}")
|
||||||
implementation("com.eliotlash.mclib:mclib:20")
|
implementation("com.eliotlash.mclib:mclib:20")
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ mod_name=Super Lead Rope
|
||||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||||
mod_license=GPLv3
|
mod_license=GPLv3
|
||||||
# The mod version. See https://semver.org/
|
# The mod version. See https://semver.org/
|
||||||
mod_version=0.0.0.9
|
mod_version=1.0.0
|
||||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
# 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.
|
# This should match the base package used for the mod sources.
|
||||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||||
|
|
|
||||||
1
res/doll.bbmodel
Normal file
1
res/doll.bbmodel
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.20.1 2025-12-04T18:55:51.5054614 Languages: zh_tw
|
// 1.20.1 2025-12-11T17:31:55.2360112 Languages: zh_tw
|
||||||
ff7556f7a8bd62a8c4cc776e45947835ffc19689 assets/superleadrope/lang/zh_tw.json
|
d1253ab3534285cc6a4d6c0e5495720f48edd62f assets/superleadrope/lang/zh_tw.json
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.20.1 2025-12-04T18:55:51.5004568 Languages: zh_cn
|
// 1.20.1 2025-12-11T17:31:55.2360112 Languages: zh_cn
|
||||||
f5128cf6058db0e79f91aece8de7f5bdd8e04193 assets/superleadrope/lang/zh_cn.json
|
7f4db04637eb656488388de206cad9070a53ae48 assets/superleadrope/lang/zh_cn.json
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// 1.20.1 2025-09-05T21:41:43.7307014 Item Models: superleadrope
|
// 1.20.1 2025-12-11T18:08:58.6978167 Item Models: superleadrope
|
||||||
c982e91b60c03a6460d1cc7b516628cf09a28417 assets/superleadrope/models/item/broken_super_lead_rope.json
|
c982e91b60c03a6460d1cc7b516628cf09a28417 assets/superleadrope/models/item/broken_super_lead_rope.json
|
||||||
|
50782bef004ff1c69c09aa397a8ee92b71a8b858 assets/superleadrope/models/item/doll.json
|
||||||
7b072a8cc70b53d54e37e5fa72d705bd07780943 assets/superleadrope/models/item/eternal_potato.json
|
7b072a8cc70b53d54e37e5fa72d705bd07780943 assets/superleadrope/models/item/eternal_potato.json
|
||||||
4fb737a5f8f15642212aa581a02a81cf649fc36f assets/superleadrope/models/item/super_lead_rope.json
|
4fb737a5f8f15642212aa581a02a81cf649fc36f assets/superleadrope/models/item/super_lead_rope.json
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
// 1.20.1 2025-12-11T17:31:55.2360112 Block States: superleadrope
|
||||||
|
6e9e15398c0d85d14941797931eb3f7c886a800a assets/superleadrope/blockstates/doll.json
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
// 1.20.1 2025-12-11T17:31:55.2360112 Loot Tables
|
||||||
|
c31110372e9281cf7264482c2c89c8927fb67fe2 data/superleadrope/loot_tables/blocks/doll.json
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.20.1 2025-12-04T18:55:51.5034621 Languages: lzh
|
// 1.20.1 2025-12-11T17:31:55.2360112 Languages: lzh
|
||||||
8dde976f77c0ca836ed66627ea2af29b20e5f7c5 assets/superleadrope/lang/lzh.json
|
c03cdd0fb0e9a7bcf525fc0e18fe31e2b906f8f0 assets/superleadrope/lang/lzh.json
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.20.1 2025-12-04T18:55:51.5024633 Languages: en_us
|
// 1.20.1 2025-12-11T17:31:55.2360112 Languages: en_us
|
||||||
b1f5523a28ab74acc8bd5b0ec167bf254e0b0dea assets/superleadrope/lang/en_us.json
|
d1d1d2a67f7602340c0f0e0dcf1ea1b93fdc23f4 assets/superleadrope/lang/en_us.json
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"facing=east,waterlogged=false": {
|
||||||
|
"model": "superleadrope:block/doll",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,waterlogged=true": {
|
||||||
|
"model": "superleadrope:block/doll",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=north,waterlogged=false": {
|
||||||
|
"model": "superleadrope:block/doll"
|
||||||
|
},
|
||||||
|
"facing=north,waterlogged=true": {
|
||||||
|
"model": "superleadrope:block/doll"
|
||||||
|
},
|
||||||
|
"facing=south,waterlogged=false": {
|
||||||
|
"model": "superleadrope:block/doll",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,waterlogged=true": {
|
||||||
|
"model": "superleadrope:block/doll",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=west,waterlogged=false": {
|
||||||
|
"model": "superleadrope:block/doll",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=west,waterlogged=true": {
|
||||||
|
"model": "superleadrope:block/doll",
|
||||||
|
"y": 270
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
{
|
{
|
||||||
|
"block.superleadrope.doll": "Doll",
|
||||||
"death.attack.eternal_potato_not_complete": "§c%1$s was not the rightful owner, struck by lightning!",
|
"death.attack.eternal_potato_not_complete": "§c%1$s was not the rightful owner, struck by lightning!",
|
||||||
"death.attack.eternal_potato_not_owner": "§c%1$s was not the rightful owner, struck by lightning!",
|
"death.attack.eternal_potato_not_owner": "§c%1$s was not the rightful owner, struck by lightning!",
|
||||||
|
"effect.superleadrope.no_super_leash": "No Super Leash",
|
||||||
"entity.superleadrope.super_lead_knot": "Super Lead Knot",
|
"entity.superleadrope.super_lead_knot": "Super Lead Knot",
|
||||||
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent": "Create Leash Fence Knot Entity if absent",
|
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent": "Create Leash Fence Knot Entity if absent",
|
||||||
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent.description": "Create LeashKnot Entity if it's absent on fence or other supported positions",
|
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent.description": "Create LeashKnot Entity if it's absent on fence or other supported positions",
|
||||||
|
|
@ -22,6 +24,9 @@
|
||||||
"item.eternal_potato.tooltip.punish": "§cOverdue punishments: §4%d §7(will be applied), grace exceeded: §4%d",
|
"item.eternal_potato.tooltip.punish": "§cOverdue punishments: §4%d §7(will be applied), grace exceeded: §4%d",
|
||||||
"item.eternal_potato.tooltip.title": "§6Mythical Item §7- §6Eternal Potato",
|
"item.eternal_potato.tooltip.title": "§6Mythical Item §7- §6Eternal Potato",
|
||||||
"item.eternal_potato.tooltip.unbound": "§cUnbound",
|
"item.eternal_potato.tooltip.unbound": "§cUnbound",
|
||||||
|
"item.minecraft.lingering_potion.effect.no_super_leash": "Splash No Super Leash Potion",
|
||||||
|
"item.minecraft.potion.effect.no_super_leash": "No Super Leash Potion",
|
||||||
|
"item.minecraft.splash_potion.effect.no_super_leash": "Splash No Super Leash Potion",
|
||||||
"item.superleadrope.eternal_potato": "Eternal Potato",
|
"item.superleadrope.eternal_potato": "Eternal Potato",
|
||||||
"item.superleadrope.super_lead_rope": "Super Lead Rope",
|
"item.superleadrope.super_lead_rope": "Super Lead Rope",
|
||||||
"sound.superleadrope.subtitle.lead_break": "Lead Break",
|
"sound.superleadrope.subtitle.lead_break": "Lead Break",
|
||||||
|
|
@ -105,5 +110,6 @@
|
||||||
"superleadrope.command.motion.message.multiply.successful": "§bMultiply Successfully.§a%s§7:§f[§eVec§7:§a(§f%.2f§7,§f%.2f§7,§f%.2f§7)§f]§r",
|
"superleadrope.command.motion.message.multiply.successful": "§bMultiply Successfully.§a%s§7:§f[§eVec§7:§a(§f%.2f§7,§f%.2f§7,§f%.2f§7)§f]§r",
|
||||||
"superleadrope.command.motion.message.setter.successful": "§bSet Successfully.§a%s§7:§f[§eVec§7:§a(§f%.2f§7,§f%.2f§7,§f%.2f§7)§f]§r",
|
"superleadrope.command.motion.message.setter.successful": "§bSet Successfully.§a%s§7:§f[§eVec§7:§a(§f%.2f§7,§f%.2f§7,§f%.2f§7)§f]§r",
|
||||||
"superleadrope.command.none": "<None>",
|
"superleadrope.command.none": "<None>",
|
||||||
"superleadrope.command.state": "State"
|
"superleadrope.command.state": "State",
|
||||||
|
"tooltip.superleadrope.author": "Author : R3944Realms"
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
{
|
{
|
||||||
|
"block.superleadrope.doll": "戲像",
|
||||||
"death.attack.eternal_potato_not_complete": "§c%1$s 非汝所主,雷霆降身!",
|
"death.attack.eternal_potato_not_complete": "§c%1$s 非汝所主,雷霆降身!",
|
||||||
"death.attack.eternal_potato_not_owner": "§c%1$s 非汝所主,雷霆降身!",
|
"death.attack.eternal_potato_not_owner": "§c%1$s 非汝所主,雷霆降身!",
|
||||||
|
"effect.superleadrope.no_super_leash": "禁系之效",
|
||||||
"entity.superleadrope.super_lead_knot": "神駒羈縻索結",
|
"entity.superleadrope.super_lead_knot": "神駒羈縻索結",
|
||||||
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent": "若阙则创超级繫绳结",
|
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent": "若阙则创超级繫绳结",
|
||||||
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent.description": "若栅等支处阙超级繫绳结,则创之",
|
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent.description": "若栅等支处阙超级繫绳结,则创之",
|
||||||
|
|
@ -22,6 +24,9 @@
|
||||||
"item.eternal_potato.tooltip.punish": "§c逾期责务尚未完成: §4%d §7(將受懲罰),超出寬限數: §4%d",
|
"item.eternal_potato.tooltip.punish": "§c逾期责务尚未完成: §4%d §7(將受懲罰),超出寬限數: §4%d",
|
||||||
"item.eternal_potato.tooltip.title": "§6永恒土豆 §7- §6传奇之物",
|
"item.eternal_potato.tooltip.title": "§6永恒土豆 §7- §6传奇之物",
|
||||||
"item.eternal_potato.tooltip.unbound": "§c尚未绑定主人",
|
"item.eternal_potato.tooltip.unbound": "§c尚未绑定主人",
|
||||||
|
"item.minecraft.lingering_potion.effect.no_super_leash": "缠绵禁系汤",
|
||||||
|
"item.minecraft.potion.effect.no_super_leash": "禁系汤剂",
|
||||||
|
"item.minecraft.splash_potion.effect.no_super_leash": "飞溅禁系汤",
|
||||||
"item.superleadrope.eternal_potato": "不滅薯",
|
"item.superleadrope.eternal_potato": "不滅薯",
|
||||||
"item.superleadrope.super_lead_rope": "神駒羈縻索",
|
"item.superleadrope.super_lead_rope": "神駒羈縻索",
|
||||||
"sound.superleadrope.subtitle.lead_break": "索絕",
|
"sound.superleadrope.subtitle.lead_break": "索絕",
|
||||||
|
|
@ -105,5 +110,6 @@
|
||||||
"superleadrope.command.motion.message.multiply.successful": "§b倍乘既成.§a%s§7:§f[§e速勢§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r",
|
"superleadrope.command.motion.message.multiply.successful": "§b倍乘既成.§a%s§7:§f[§e速勢§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r",
|
||||||
"superleadrope.command.motion.message.setter.successful": "§b定值既成.§a%s§7:§f[§e速勢§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r",
|
"superleadrope.command.motion.message.setter.successful": "§b定值既成.§a%s§7:§f[§e速勢§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r",
|
||||||
"superleadrope.command.none": "無",
|
"superleadrope.command.none": "無",
|
||||||
"superleadrope.command.state": "狀"
|
"superleadrope.command.state": "狀",
|
||||||
|
"tooltip.superleadrope.author": "作者 : R3944Realms"
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
{
|
{
|
||||||
|
"block.superleadrope.doll": "玩偶",
|
||||||
"death.attack.eternal_potato_not_complete": "§c%1$s 因使用非自己绑定物品,受到闪电惩罚!",
|
"death.attack.eternal_potato_not_complete": "§c%1$s 因使用非自己绑定物品,受到闪电惩罚!",
|
||||||
"death.attack.eternal_potato_not_owner": "§c%1$s 因使用非自己绑定物品,受到闪电惩罚!",
|
"death.attack.eternal_potato_not_owner": "§c%1$s 因使用非自己绑定物品,受到闪电惩罚!",
|
||||||
|
"effect.superleadrope.no_super_leash": "禁拴",
|
||||||
"entity.superleadrope.super_lead_knot": "超级拴绳结",
|
"entity.superleadrope.super_lead_knot": "超级拴绳结",
|
||||||
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent": "如果缺失则创建超级拴绳结",
|
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent": "如果缺失则创建超级拴绳结",
|
||||||
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent.description": "如果在栅栏等支持处缺失超级拴绳结,则创建它",
|
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent.description": "如果在栅栏等支持处缺失超级拴绳结,则创建它",
|
||||||
|
|
@ -22,6 +24,9 @@
|
||||||
"item.eternal_potato.tooltip.punish": "§c逾期未完成责务: §4%d §7(将会受罚),超出宽限数: §4%d",
|
"item.eternal_potato.tooltip.punish": "§c逾期未完成责务: §4%d §7(将会受罚),超出宽限数: §4%d",
|
||||||
"item.eternal_potato.tooltip.title": "§6神话物品 §7- §6永恒土豆",
|
"item.eternal_potato.tooltip.title": "§6神话物品 §7- §6永恒土豆",
|
||||||
"item.eternal_potato.tooltip.unbound": "§c未绑定主人",
|
"item.eternal_potato.tooltip.unbound": "§c未绑定主人",
|
||||||
|
"item.minecraft.lingering_potion.effect.no_super_leash": "滞留型禁拴药水",
|
||||||
|
"item.minecraft.potion.effect.no_super_leash": "禁拴药水",
|
||||||
|
"item.minecraft.splash_potion.effect.no_super_leash": "喷溅型禁拴药水",
|
||||||
"item.superleadrope.eternal_potato": "永恒土豆",
|
"item.superleadrope.eternal_potato": "永恒土豆",
|
||||||
"item.superleadrope.super_lead_rope": "超级拴绳",
|
"item.superleadrope.super_lead_rope": "超级拴绳",
|
||||||
"sound.superleadrope.subtitle.lead_break": "拴绳断裂",
|
"sound.superleadrope.subtitle.lead_break": "拴绳断裂",
|
||||||
|
|
@ -105,5 +110,6 @@
|
||||||
"superleadrope.command.motion.message.multiply.successful": "§b倍乘成功.§a%s§7:§f[§e加速§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r",
|
"superleadrope.command.motion.message.multiply.successful": "§b倍乘成功.§a%s§7:§f[§e加速§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r",
|
||||||
"superleadrope.command.motion.message.setter.successful": "§b设置成功.§a%s§7:§f[§e加速§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r",
|
"superleadrope.command.motion.message.setter.successful": "§b设置成功.§a%s§7:§f[§e加速§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r",
|
||||||
"superleadrope.command.none": "无",
|
"superleadrope.command.none": "无",
|
||||||
"superleadrope.command.state": "状态"
|
"superleadrope.command.state": "状态",
|
||||||
|
"tooltip.superleadrope.author": "作者 : R3944Realms"
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
{
|
{
|
||||||
|
"block.superleadrope.doll": "玩偶",
|
||||||
"death.attack.eternal_potato_not_complete": "§c%1$s 因使用非自己綁定物品,受到閃電懲罰!",
|
"death.attack.eternal_potato_not_complete": "§c%1$s 因使用非自己綁定物品,受到閃電懲罰!",
|
||||||
"death.attack.eternal_potato_not_owner": "§c%1$s 因使用非自己綁定物品,受到閃電懲罰!",
|
"death.attack.eternal_potato_not_owner": "§c%1$s 因使用非自己綁定物品,受到閃電懲罰!",
|
||||||
|
"effect.superleadrope.no_super_leash": "禁拴",
|
||||||
"entity.superleadrope.super_lead_knot": "超級拴繩結",
|
"entity.superleadrope.super_lead_knot": "超級拴繩結",
|
||||||
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent": "如果缺失則創建超級拴繩結",
|
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent": "如果缺失則創建超級拴繩結",
|
||||||
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent.description": "如果在柵欄等支持處缺失超級拴繩結,則創建它",
|
"gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent.description": "如果在柵欄等支持處缺失超級拴繩結,則創建它",
|
||||||
|
|
@ -22,6 +24,9 @@
|
||||||
"item.eternal_potato.tooltip.punish": "§c逾期未完成责務: §4%d §7(將會受罰),超出寬限數: §4%d",
|
"item.eternal_potato.tooltip.punish": "§c逾期未完成责務: §4%d §7(將會受罰),超出寬限數: §4%d",
|
||||||
"item.eternal_potato.tooltip.title": "§6神話物品 §7- §6永恒土豆",
|
"item.eternal_potato.tooltip.title": "§6神話物品 §7- §6永恒土豆",
|
||||||
"item.eternal_potato.tooltip.unbound": "§c未綁定主人",
|
"item.eternal_potato.tooltip.unbound": "§c未綁定主人",
|
||||||
|
"item.minecraft.lingering_potion.effect.no_super_leash": "滯留型禁拴藥水",
|
||||||
|
"item.minecraft.potion.effect.no_super_leash": "禁拴藥水",
|
||||||
|
"item.minecraft.splash_potion.effect.no_super_leash": "噴濺型禁拴藥水",
|
||||||
"item.superleadrope.eternal_potato": "永恆馬鈴薯",
|
"item.superleadrope.eternal_potato": "永恆馬鈴薯",
|
||||||
"item.superleadrope.super_lead_rope": "超級拴繩",
|
"item.superleadrope.super_lead_rope": "超級拴繩",
|
||||||
"sound.superleadrope.subtitle.lead_break": "拴繩斷裂",
|
"sound.superleadrope.subtitle.lead_break": "拴繩斷裂",
|
||||||
|
|
@ -105,5 +110,6 @@
|
||||||
"superleadrope.command.motion.message.multiply.successful": "§b倍乘成功.§a%s§7:§f[§e加速§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r",
|
"superleadrope.command.motion.message.multiply.successful": "§b倍乘成功.§a%s§7:§f[§e加速§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r",
|
||||||
"superleadrope.command.motion.message.setter.successful": "§b設置成功.§a%s§7:§f[§e加速§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r",
|
"superleadrope.command.motion.message.setter.successful": "§b設置成功.§a%s§7:§f[§e加速§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r",
|
||||||
"superleadrope.command.none": "無",
|
"superleadrope.command.none": "無",
|
||||||
"superleadrope.command.state": "狀態"
|
"superleadrope.command.state": "狀態",
|
||||||
|
"tooltip.superleadrope.author": "作者 : R3944Realms"
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"parent": "superleadrope:block/doll"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"type": "minecraft:block",
|
||||||
|
"pools": [
|
||||||
|
{
|
||||||
|
"bonus_rolls": 0.0,
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"condition": "minecraft:survives_explosion"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:item",
|
||||||
|
"name": "superleadrope:doll"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rolls": 1.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"random_sequence": "superleadrope:blocks/doll"
|
||||||
|
}
|
||||||
|
|
@ -74,6 +74,7 @@ import top.r3944realms.superleadrope.core.leash.LeashSyncManager;
|
||||||
import top.r3944realms.superleadrope.core.potato.EternalPotatoFacade;
|
import top.r3944realms.superleadrope.core.potato.EternalPotatoFacade;
|
||||||
import top.r3944realms.superleadrope.core.register.SLPGameruleRegistry;
|
import top.r3944realms.superleadrope.core.register.SLPGameruleRegistry;
|
||||||
import top.r3944realms.superleadrope.core.register.SLPItems;
|
import top.r3944realms.superleadrope.core.register.SLPItems;
|
||||||
|
import top.r3944realms.superleadrope.core.register.SLPPotionRecipeRegistry;
|
||||||
import top.r3944realms.superleadrope.core.util.PotatoMode;
|
import top.r3944realms.superleadrope.core.util.PotatoMode;
|
||||||
import top.r3944realms.superleadrope.core.util.PotatoModeHelper;
|
import top.r3944realms.superleadrope.core.util.PotatoModeHelper;
|
||||||
import top.r3944realms.superleadrope.datagen.data.SLPLangKeyValue;
|
import top.r3944realms.superleadrope.datagen.data.SLPLangKeyValue;
|
||||||
|
|
@ -499,6 +500,7 @@ public class CommonEventHandler {
|
||||||
public static void onFMLCommonInit(FMLCommonSetupEvent event) {
|
public static void onFMLCommonInit(FMLCommonSetupEvent event) {
|
||||||
event.enqueueWork(Mod::checkAndSet);
|
event.enqueueWork(Mod::checkAndSet);
|
||||||
event.enqueueWork(SLPGameruleRegistry::register);
|
event.enqueueWork(SLPGameruleRegistry::register);
|
||||||
|
event.enqueueWork(SLPPotionRecipeRegistry::init);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import top.r3944realms.superleadrope.compat.WayStoneCompat;
|
import top.r3944realms.superleadrope.compat.WayStoneCompat;
|
||||||
import top.r3944realms.superleadrope.config.LeashCommonConfig;
|
import top.r3944realms.superleadrope.config.LeashCommonConfig;
|
||||||
import top.r3944realms.superleadrope.core.register.SLPEntityTypes;
|
import top.r3944realms.superleadrope.core.register.*;
|
||||||
import top.r3944realms.superleadrope.core.register.SLPItems;
|
|
||||||
import top.r3944realms.superleadrope.core.register.SLPSoundEvents;
|
|
||||||
import top.r3944realms.superleadrope.network.NetworkHandler;
|
import top.r3944realms.superleadrope.network.NetworkHandler;
|
||||||
import top.r3944realms.superleadrope.util.file.ConfigUtil;
|
import top.r3944realms.superleadrope.util.file.ConfigUtil;
|
||||||
|
|
||||||
|
|
@ -53,8 +51,11 @@ public class SuperLeadRope {
|
||||||
public SuperLeadRope() {
|
public SuperLeadRope() {
|
||||||
IEventBus eventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
IEventBus eventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||||
SLPItems.register(eventBus);
|
SLPItems.register(eventBus);
|
||||||
|
SLPBlocks.register(eventBus);
|
||||||
SLPEntityTypes.register(eventBus);
|
SLPEntityTypes.register(eventBus);
|
||||||
SLPSoundEvents.register(eventBus);
|
SLPSoundEvents.register(eventBus);
|
||||||
|
SLPEffects.register(eventBus);
|
||||||
|
SLPPotions.register(eventBus);
|
||||||
NetworkHandler.register();
|
NetworkHandler.register();
|
||||||
initialize();
|
initialize();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,137 @@
|
||||||
package top.r3944realms.superleadrope.compat;
|
package top.r3944realms.superleadrope.compat;
|
||||||
|
|
||||||
|
import com.ibm.icu.impl.Pair;
|
||||||
import net.blay09.mods.waystones.api.WaystoneTeleportEvent;
|
import net.blay09.mods.waystones.api.WaystoneTeleportEvent;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.Pose;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.fml.ModList;
|
import net.minecraftforge.fml.ModList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import top.r3944realms.superleadrope.api.event.SuperLeadRopeEvent;
|
||||||
|
import top.r3944realms.superleadrope.api.type.capabilty.LeashInfo;
|
||||||
import top.r3944realms.superleadrope.api.type.util.ILeashHelper;
|
import top.r3944realms.superleadrope.api.type.util.ILeashHelper;
|
||||||
import top.r3944realms.superleadrope.api.workspace.Services;
|
import top.r3944realms.superleadrope.api.workspace.Services;
|
||||||
|
import top.r3944realms.superleadrope.content.gamerule.server.TeleportWithLeashedEntities;
|
||||||
|
import top.r3944realms.superleadrope.core.leash.LeashSyncManager;
|
||||||
|
import top.r3944realms.superleadrope.core.register.SLPGameruleRegistry;
|
||||||
|
import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI;
|
||||||
|
import top.r3944realms.superleadrope.util.capability.LeashStateInnerAPI;
|
||||||
|
import top.r3944realms.superleadrope.util.entity.TeleportUtil;
|
||||||
|
import top.r3944realms.superleadrope.util.model.RidingRelationship;
|
||||||
|
import top.r3944realms.superleadrope.util.riding.RidingApplier;
|
||||||
|
import top.r3944realms.superleadrope.util.riding.RidingDismounts;
|
||||||
|
import top.r3944realms.superleadrope.util.riding.RidingFinder;
|
||||||
|
import top.r3944realms.superleadrope.util.riding.RidingSaver;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
public class WayStoneCompat {
|
public class WayStoneCompat {
|
||||||
public final static boolean isModLoaded = ModList.get().isLoaded("waystones");
|
public final static boolean isModLoaded = ModList.get().isLoaded("waystones");
|
||||||
|
public final static Map<UUID, Set<Pair<Entity, OriginalState>>> tempLeashMap = new ConcurrentHashMap<>();
|
||||||
|
public final static Map<UUID, UUID> uuidMap = new ConcurrentHashMap<>();
|
||||||
|
public record OriginalState(Pose pose, boolean isSprinting, float yaw, float pitch, Vec3 deltaMovement, LeashInfo leashInfo, RidingRelationship ridingRelationship) {}
|
||||||
public static void init() {
|
public static void init() {
|
||||||
if (isModLoaded) {
|
if (isModLoaded) {
|
||||||
MinecraftForge.EVENT_BUS.addListener(WayStoneCompat::onWayStoneTeleport);
|
MinecraftForge.EVENT_BUS.addListener(WayStoneCompat::onWayStoneTeleport$Pre);
|
||||||
|
MinecraftForge.EVENT_BUS.addListener(WayStoneCompat::onWayStoneTeleport$Post);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static void onWayStoneTeleport(WaystoneTeleportEvent.@NotNull Pre event) {
|
public static void onWayStoneTeleport$Pre(WaystoneTeleportEvent.@NotNull Pre event) {
|
||||||
Entity entity = event.getContext().getEntity();
|
Entity telEntity = event.getContext().getEntity();
|
||||||
ILeashHelper.IHolder holderHelper = Services.WORK_SPACE.getLeashHelper().getHolderHelper(entity);
|
ILeashHelper.IHolder holderHelper = Services.WORK_SPACE.getLeashHelper().getHolderHelper(telEntity);
|
||||||
Set<Entity> allLeashedEntities = holderHelper.getAllLeashedEntities();
|
Set<Entity> allLeashedEntities = holderHelper.getAllLeashedEntities();
|
||||||
allLeashedEntities.forEach(event::addAdditionalEntity);
|
if(!SLPGameruleRegistry.getGameruleBoolValue(telEntity.level(), TeleportWithLeashedEntities.ID)) {
|
||||||
|
holderHelper.getAllLeashedEntities();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ServerLevel level = event.getContext().getDestination().getLevel();
|
||||||
|
Vec3 destination = event.getContext().getDestination().getLocation();
|
||||||
|
Set<Pair<Entity, OriginalState>> set = new HashSet<>();
|
||||||
|
for (Entity beLeashedEntity : allLeashedEntities) {
|
||||||
|
// --- 保存状态快照 ---
|
||||||
|
if (MinecraftForge.EVENT_BUS.post(new SuperLeadRopeEvent.teleportWithHolder(beLeashedEntity, telEntity, beLeashedEntity.level(), level, beLeashedEntity.position(), destination)))
|
||||||
|
continue;
|
||||||
|
Pose originalPose = beLeashedEntity.getPose();
|
||||||
|
boolean originalIsSprinting = beLeashedEntity.isSprinting();
|
||||||
|
float originalYaw = beLeashedEntity.getYRot();
|
||||||
|
float originalPitch = beLeashedEntity.getXRot();
|
||||||
|
Vec3 originalDeltaMovement = beLeashedEntity.getDeltaMovement();
|
||||||
|
|
||||||
|
AtomicReference<LeashInfo> originalLeashInfo = new AtomicReference<>();
|
||||||
|
LeashDataInnerAPI.getLeashData(beLeashedEntity).ifPresent(data -> {
|
||||||
|
originalLeashInfo.set(data.getLeashInfo(telEntity).orElse(null));
|
||||||
|
data.removeLeash(telEntity);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// --- 保存骑乘关系(可修改列表) ---
|
||||||
|
RidingRelationship originalRidingRelationship = RidingSaver.save(beLeashedEntity, true);
|
||||||
|
|
||||||
|
// --- 解除骑乘 ---
|
||||||
|
List<Entity> allPassengers = RidingFinder.getEntityFromRidingShip(originalRidingRelationship, level::getEntity);
|
||||||
|
RidingDismounts.dismountEntities(allPassengers);
|
||||||
|
set.add(Pair.of(beLeashedEntity, new OriginalState(
|
||||||
|
originalPose,
|
||||||
|
originalIsSprinting,
|
||||||
|
originalYaw,
|
||||||
|
originalPitch,
|
||||||
|
originalDeltaMovement,
|
||||||
|
originalLeashInfo.get(),
|
||||||
|
originalRidingRelationship
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
tempLeashMap.put(telEntity.getUUID(), set);
|
||||||
|
}
|
||||||
|
public static void onWayStoneTeleport$Post(WaystoneTeleportEvent.@NotNull Post event) {
|
||||||
|
Entity telEntity = event.getContext().getEntity();
|
||||||
|
ServerLevel serverLevel = event.getContext().getDestination().getLevel();
|
||||||
|
Vec3 destination = event.getContext().getDestination().getLocation();
|
||||||
|
Set<Pair<Entity, OriginalState>> set = tempLeashMap.get(telEntity.getUUID());
|
||||||
|
Set<UUID> shouldBeRemoved = new HashSet<>();
|
||||||
|
if (set != null) {
|
||||||
|
HashSet<Pair<Entity, OriginalState>> newSet = new HashSet<>();
|
||||||
|
// --- 传送实体及乘客 ---
|
||||||
|
for (Pair<Entity, OriginalState> entityPair : set) {
|
||||||
|
Entity beLeashedEntity = entityPair.first;
|
||||||
|
Entity newEntity = TeleportUtil.teleportEntity(beLeashedEntity, serverLevel, destination, beLeashedEntity.getDirection());
|
||||||
|
if (!beLeashedEntity.getUUID().equals(newEntity.getUUID())){
|
||||||
|
uuidMap.put(beLeashedEntity.getUUID(), newEntity.getUUID());
|
||||||
|
}
|
||||||
|
newSet.add(Pair.of(newEntity, entityPair.second));
|
||||||
|
}
|
||||||
|
for (Pair<Entity, OriginalState> entityPair : newSet) {
|
||||||
|
// --- 恢复状态 ---
|
||||||
|
Entity beLeashedEntity = entityPair.first;
|
||||||
|
OriginalState originalState = entityPair.second;
|
||||||
|
LeashStateInnerAPI.getLeashState(beLeashedEntity).ifPresent(LeashSyncManager.State::track);
|
||||||
|
LeashDataInnerAPI.getLeashData(beLeashedEntity).ifPresent(LeashSyncManager.Data::track);
|
||||||
|
beLeashedEntity.setDeltaMovement(originalState.deltaMovement);
|
||||||
|
beLeashedEntity.setPose(originalState.pose);
|
||||||
|
beLeashedEntity.setSprinting(originalState.isSprinting);
|
||||||
|
// --- 将holder替换 ---
|
||||||
|
LeashInfo leashInfo = Optional.ofNullable(originalState.leashInfo)
|
||||||
|
.orElse(LeashInfo.EMPTY);
|
||||||
|
if (leashInfo.holderUUIDOpt().isPresent() && uuidMap.containsKey(leashInfo.holderUUIDOpt().get())) {
|
||||||
|
leashInfo.transferHolder(beLeashedEntity);
|
||||||
|
shouldBeRemoved.add(leashInfo.holderUUIDOpt().get());
|
||||||
|
}
|
||||||
|
LeashDataInnerAPI.LeashOperations.attachWithInfo(beLeashedEntity, telEntity, leashInfo);
|
||||||
|
// --- 重新应用骑乘关系,仅保留白名单根载具 ---
|
||||||
|
uuidMap.forEach((oldUUID, newUUID) -> {
|
||||||
|
int andReplaceAll = originalState.ridingRelationship.findAndReplaceAll(oldUUID, newUUID);
|
||||||
|
if (andReplaceAll != 0) shouldBeRemoved.add(oldUUID);
|
||||||
|
});
|
||||||
|
RidingRelationship filteredRelationship = RidingSaver.filterByWhitelistRoot(originalState.ridingRelationship);
|
||||||
|
RidingApplier.applyRidingRelationship(filteredRelationship, serverLevel::getEntity);
|
||||||
|
}
|
||||||
|
shouldBeRemoved.forEach(uuidMap::remove);
|
||||||
|
tempLeashMap.remove(telEntity.getUUID());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ public class LeashCommonConfig {
|
||||||
*/
|
*/
|
||||||
// Leash settings
|
// Leash settings
|
||||||
public final ForgeConfigSpec.DoubleValue maxLeashLength;
|
public final ForgeConfigSpec.DoubleValue maxLeashLength;
|
||||||
|
public final ForgeConfigSpec.DoubleValue maxMovement;
|
||||||
/**
|
/**
|
||||||
* The Elastic distance scale.
|
* The Elastic distance scale.
|
||||||
*/
|
*/
|
||||||
|
|
@ -155,7 +156,9 @@ public class LeashCommonConfig {
|
||||||
maxLeashLength = builder
|
maxLeashLength = builder
|
||||||
.comment("Maximum leash distance (in blocks) for any entity")
|
.comment("Maximum leash distance (in blocks) for any entity")
|
||||||
.defineInRange("maxLeashLength", 6.0, LeashConfigManager.MAX_DISTANCE_MIN_VALUE, LeashConfigManager.MAX_DISTANCE_MAX_VALUE);
|
.defineInRange("maxLeashLength", 6.0, LeashConfigManager.MAX_DISTANCE_MIN_VALUE, LeashConfigManager.MAX_DISTANCE_MAX_VALUE);
|
||||||
|
maxMovement = builder
|
||||||
|
.comment("Defines the maximum acceleration in standard coordinate directions (X/Y/Z axes)")
|
||||||
|
.defineInRange("maxMovement", 100.0, 10.0, Double.MAX_VALUE);
|
||||||
elasticDistanceScale = builder
|
elasticDistanceScale = builder
|
||||||
.comment("Default elastic distance for the Super Lead rope")
|
.comment("Default elastic distance for the Super Lead rope")
|
||||||
.defineInRange("elasticDistanceScale", 1.0, LeashConfigManager.ELASTIC_DISTANCE_MIN_VALUE, LeashConfigManager.ELASTIC_DISTANCE_MAX_VALUE);
|
.defineInRange("elasticDistanceScale", 1.0, LeashConfigManager.ELASTIC_DISTANCE_MIN_VALUE, LeashConfigManager.ELASTIC_DISTANCE_MAX_VALUE);
|
||||||
|
|
@ -200,6 +203,8 @@ public class LeashCommonConfig {
|
||||||
.defineInRange("mobSpringFactor", 0.5, 0.05, 2.0);
|
.defineInRange("mobSpringFactor", 0.5, 0.05, 2.0);
|
||||||
builder.pop();
|
builder.pop();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ===== Leash State Offsets =====
|
// ===== Leash State Offsets =====
|
||||||
builder.push("LeashStateSettings");
|
builder.push("LeashStateSettings");
|
||||||
defaultApplyEntityLocationOffset = builder
|
defaultApplyEntityLocationOffset = builder
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ public class LeashConfigManager {
|
||||||
private volatile double mobSpringFactor = 0.5;
|
private volatile double mobSpringFactor = 0.5;
|
||||||
|
|
||||||
private volatile double maxLeashLength = 12.0;
|
private volatile double maxLeashLength = 12.0;
|
||||||
|
private volatile double maxMovement = 100.0;
|
||||||
private volatile double elasticDistanceScale = 1.0;
|
private volatile double elasticDistanceScale = 1.0;
|
||||||
private volatile double extremeSnapFactor = 2.0;
|
private volatile double extremeSnapFactor = 2.0;
|
||||||
private volatile double springDampening = 0.7;
|
private volatile double springDampening = 0.7;
|
||||||
|
|
@ -318,6 +319,7 @@ public class LeashConfigManager {
|
||||||
* @return the max leash length
|
* @return the max leash length
|
||||||
*/
|
*/
|
||||||
public double getMaxLeashLength() { return maxLeashLength; }
|
public double getMaxLeashLength() { return maxLeashLength; }
|
||||||
|
public double getMaxMovement() { return maxMovement; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets elastic distance scale.
|
* Gets elastic distance scale.
|
||||||
|
|
@ -399,6 +401,7 @@ public class LeashConfigManager {
|
||||||
commandPrefixEnabledCache = LeashCommonConfig.COMMON.enableSLPModCommandPrefix.get();
|
commandPrefixEnabledCache = LeashCommonConfig.COMMON.enableSLPModCommandPrefix.get();
|
||||||
|
|
||||||
maxLeashLength = LeashCommonConfig.COMMON.maxLeashLength.get();
|
maxLeashLength = LeashCommonConfig.COMMON.maxLeashLength.get();
|
||||||
|
maxMovement = LeashCommonConfig.COMMON.maxMovement.get();
|
||||||
elasticDistanceScale = LeashCommonConfig.COMMON.elasticDistanceScale.get();
|
elasticDistanceScale = LeashCommonConfig.COMMON.elasticDistanceScale.get();
|
||||||
extremeSnapFactor = LeashCommonConfig.COMMON.extremeSnapFactor.get();
|
extremeSnapFactor = LeashCommonConfig.COMMON.extremeSnapFactor.get();
|
||||||
springDampening = LeashCommonConfig.COMMON.springDampening.get();
|
springDampening = LeashCommonConfig.COMMON.springDampening.get();
|
||||||
|
|
@ -489,6 +492,7 @@ public class LeashConfigManager {
|
||||||
tag.putDouble("mob_spring_factor", mobSpringFactor);
|
tag.putDouble("mob_spring_factor", mobSpringFactor);
|
||||||
|
|
||||||
tag.putDouble("max_leash_length", maxLeashLength);
|
tag.putDouble("max_leash_length", maxLeashLength);
|
||||||
|
tag.putDouble("max_movement", maxMovement);
|
||||||
tag.putDouble("elastic_distance_scale", elasticDistanceScale);
|
tag.putDouble("elastic_distance_scale", elasticDistanceScale);
|
||||||
tag.putDouble("extreme_snap_factor", extremeSnapFactor);
|
tag.putDouble("extreme_snap_factor", extremeSnapFactor);
|
||||||
tag.putDouble("spring_dampening", springDampening);
|
tag.putDouble("spring_dampening", springDampening);
|
||||||
|
|
@ -524,6 +528,7 @@ public class LeashConfigManager {
|
||||||
|
|
||||||
// ========== 更新物理参数 ==========
|
// ========== 更新物理参数 ==========
|
||||||
LeashCommonConfig.COMMON.maxLeashLength.set(maxLeashLength);
|
LeashCommonConfig.COMMON.maxLeashLength.set(maxLeashLength);
|
||||||
|
LeashCommonConfig.COMMON.maxMovement.set(maxMovement);
|
||||||
LeashCommonConfig.COMMON.elasticDistanceScale.set(elasticDistanceScale);
|
LeashCommonConfig.COMMON.elasticDistanceScale.set(elasticDistanceScale);
|
||||||
LeashCommonConfig.COMMON.extremeSnapFactor.set(extremeSnapFactor);
|
LeashCommonConfig.COMMON.extremeSnapFactor.set(extremeSnapFactor);
|
||||||
LeashCommonConfig.COMMON.springDampening.set(springDampening);
|
LeashCommonConfig.COMMON.springDampening.set(springDampening);
|
||||||
|
|
@ -641,6 +646,9 @@ public class LeashConfigManager {
|
||||||
if (tag.contains("max_leash_length", Tag.TAG_DOUBLE)) {
|
if (tag.contains("max_leash_length", Tag.TAG_DOUBLE)) {
|
||||||
maxLeashLength = tag.getDouble("max_leash_length");
|
maxLeashLength = tag.getDouble("max_leash_length");
|
||||||
}
|
}
|
||||||
|
if (tag.contains("max_movement", Tag.TAG_DOUBLE)) {
|
||||||
|
maxLeashLength = tag.getDouble("max_movement");
|
||||||
|
}
|
||||||
if (tag.contains("elastic_distance_scale", Tag.TAG_DOUBLE)) {
|
if (tag.contains("elastic_distance_scale", Tag.TAG_DOUBLE)) {
|
||||||
elasticDistanceScale = tag.getDouble("elastic_distance_scale");
|
elasticDistanceScale = tag.getDouble("elastic_distance_scale");
|
||||||
}
|
}
|
||||||
|
|
@ -696,6 +704,7 @@ public class LeashConfigManager {
|
||||||
hash = fnv1aHashLong(hash, Double.doubleToLongBits(playerSpringFactor));
|
hash = fnv1aHashLong(hash, Double.doubleToLongBits(playerSpringFactor));
|
||||||
hash = fnv1aHashLong(hash, Double.doubleToLongBits(mobSpringFactor));
|
hash = fnv1aHashLong(hash, Double.doubleToLongBits(mobSpringFactor));
|
||||||
hash = fnv1aHashLong(hash, Double.doubleToLongBits(maxLeashLength));
|
hash = fnv1aHashLong(hash, Double.doubleToLongBits(maxLeashLength));
|
||||||
|
hash = fnv1aHashLong(hash, Double.doubleToLongBits(maxMovement));
|
||||||
hash = fnv1aHashLong(hash, Double.doubleToLongBits(elasticDistanceScale));
|
hash = fnv1aHashLong(hash, Double.doubleToLongBits(elasticDistanceScale));
|
||||||
hash = fnv1aHashLong(hash, Double.doubleToLongBits(extremeSnapFactor));
|
hash = fnv1aHashLong(hash, Double.doubleToLongBits(extremeSnapFactor));
|
||||||
hash = fnv1aHashLong(hash, Double.doubleToLongBits(springDampening));
|
hash = fnv1aHashLong(hash, Double.doubleToLongBits(springDampening));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
package top.r3944realms.superleadrope.content.block;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.core.particles.ParticleTypes;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.sounds.SoundEvents;
|
||||||
|
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.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.Block;
|
||||||
|
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||||
|
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
|
||||||
|
import net.minecraft.world.level.block.SoundType;
|
||||||
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||||
|
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;
|
||||||
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||||
|
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.phys.BlockHitResult;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public class DollBlock extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock {
|
||||||
|
private static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
|
||||||
|
private static final VoxelShape DOLL_SHAPE = Block.box(2.0d, 0.0d, 2.0d, 14.0d, 12.0d, 14.0d);
|
||||||
|
|
||||||
|
private static final double PARTICLE_OFFSET_RANGE = 0.25;
|
||||||
|
private static final double PARTICLE_HEIGHT_OFFSET = 1.0;
|
||||||
|
private static final double PARTICLE_HEIGHT_VARIANCE = 0.2;
|
||||||
|
private static final float NOTE_COLOR_DIVISOR = 24.0F;
|
||||||
|
private static final int MAX_NOTE_COLORS = 4;
|
||||||
|
|
||||||
|
private static final float BASE_VOLUME = 1.0f;
|
||||||
|
private static final float PITCH_VARIANCE = 0.5f;
|
||||||
|
private static final float BASE_PITCH = 0.75f;
|
||||||
|
|
||||||
|
public DollBlock() {
|
||||||
|
super(BlockBehaviour.Properties.of()
|
||||||
|
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||||
|
.sound(SoundType.WOOL)
|
||||||
|
.strength(0f, 10f)
|
||||||
|
.noOcclusion());
|
||||||
|
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.SOUTH)
|
||||||
|
.setValue(WATERLOGGED, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull BlockState updateShape(@NotNull BlockState currentState, @NotNull Direction direction, @NotNull BlockState neighborState,
|
||||||
|
@NotNull LevelAccessor level, @NotNull BlockPos currentPos, @NotNull BlockPos neighborPos) {
|
||||||
|
if (currentState.getValue(WATERLOGGED)) {
|
||||||
|
level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
|
||||||
|
}
|
||||||
|
return super.updateShape(currentState, direction, neighborState, level, currentPos, neighborPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull FluidState getFluidState(@NotNull BlockState blockState) {
|
||||||
|
return blockState.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull InteractionResult use(@NotNull BlockState blockState, @NotNull Level level, @NotNull BlockPos blockPos, @NotNull Player player,
|
||||||
|
@NotNull InteractionHand hand, @NotNull BlockHitResult hitResult) {
|
||||||
|
if (level instanceof ServerLevel serverLevel) {
|
||||||
|
// 播放粒子效果
|
||||||
|
spawnNoteParticles(serverLevel, blockPos);
|
||||||
|
// 播放音效
|
||||||
|
playDollSound(serverLevel, blockPos);
|
||||||
|
}
|
||||||
|
return InteractionResult.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在玩偶位置生成音符粒子效果
|
||||||
|
*/
|
||||||
|
private void spawnNoteParticles(ServerLevel serverLevel, BlockPos blockPos) {
|
||||||
|
Vec3 particlePosition = calculateParticlePosition(serverLevel, blockPos);
|
||||||
|
float noteColor = calculateNoteColor(serverLevel);
|
||||||
|
|
||||||
|
serverLevel.sendParticles(ParticleTypes.NOTE,
|
||||||
|
particlePosition.x(), particlePosition.y(), particlePosition.z(),
|
||||||
|
0, noteColor, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算粒子生成位置,添加随机偏移
|
||||||
|
*/
|
||||||
|
private @NotNull Vec3 calculateParticlePosition(@NotNull ServerLevel serverLevel, BlockPos blockPos) {
|
||||||
|
return Vec3.atBottomCenterOf(blockPos).add(
|
||||||
|
(serverLevel.getRandom().nextFloat() - 0.5) * PARTICLE_OFFSET_RANGE * 2,
|
||||||
|
PARTICLE_HEIGHT_OFFSET + serverLevel.getRandom().nextFloat() * PARTICLE_HEIGHT_VARIANCE,
|
||||||
|
(serverLevel.getRandom().nextFloat() - 0.5) * PARTICLE_OFFSET_RANGE * 2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算音符粒子的颜色
|
||||||
|
*/
|
||||||
|
private float calculateNoteColor(@NotNull ServerLevel serverLevel) {
|
||||||
|
return serverLevel.getRandom().nextInt(MAX_NOTE_COLORS) / NOTE_COLOR_DIVISOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 播放玩偶音效
|
||||||
|
*/
|
||||||
|
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(),
|
||||||
|
SoundSource.BLOCKS, BASE_VOLUME, pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable BlockState getStateForPlacement(@NotNull BlockPlaceContext context) {
|
||||||
|
FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos());
|
||||||
|
boolean isWaterlogged = fluidState.getType() == Fluids.WATER;
|
||||||
|
|
||||||
|
return this.defaultBlockState()
|
||||||
|
.setValue(FACING, context.getHorizontalDirection().getOpposite())
|
||||||
|
.setValue(WATERLOGGED, isWaterlogged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull VoxelShape getShape(@NotNull BlockState blockState, @NotNull BlockGetter level, @NotNull BlockPos blockPos, @NotNull CollisionContext context) {
|
||||||
|
return DOLL_SHAPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createBlockStateDefinition(StateDefinition.@NotNull Builder<Block, BlockState> builder) {
|
||||||
|
builder.add(FACING, WATERLOGGED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -64,6 +64,7 @@ import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预期行为
|
* 预期行为
|
||||||
|
* <pre>
|
||||||
* <table border="1">
|
* <table border="1">
|
||||||
* <thead>
|
* <thead>
|
||||||
* <tr>
|
* <tr>
|
||||||
|
|
@ -90,6 +91,7 @@ import java.util.stream.Stream;
|
||||||
* </tr>
|
* </tr>
|
||||||
* </tbody>
|
* </tbody>
|
||||||
* </table>
|
* </table>
|
||||||
|
* </pre>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("DuplicatedCode")
|
@SuppressWarnings("DuplicatedCode")
|
||||||
public class LeashDataImpl implements ILeashData {
|
public class LeashDataImpl implements ILeashData {
|
||||||
|
|
@ -804,7 +806,24 @@ public class LeashDataImpl implements ILeashData {
|
||||||
boolean hasForce = !combinedForce.equals(Vec3.ZERO);
|
boolean hasForce = !combinedForce.equals(Vec3.ZERO);
|
||||||
Entity targetEntity = RindingLeash.getFinalEntityForLeashIfForce(entity, hasForce);
|
Entity targetEntity = RindingLeash.getFinalEntityForLeashIfForce(entity, hasForce);
|
||||||
if(targetEntity instanceof LocalPlayer && hasForce){
|
if(targetEntity instanceof LocalPlayer && hasForce){
|
||||||
entity.addDeltaMovement(combinedForce);
|
entity.addDeltaMovement(limitMovement(combinedForce));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3 limitMovement(@NotNull Vec3 movement) {
|
||||||
|
double maxMovement = CommonEventHandler.leashConfigManager.getMaxMovement();
|
||||||
|
return new Vec3(
|
||||||
|
clamp(movement.x, maxMovement),
|
||||||
|
clamp(movement.y, maxMovement),
|
||||||
|
clamp(movement.z, maxMovement)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double clamp(double value, double max) {
|
||||||
|
if (value > 0) {
|
||||||
|
return Math.min(value, max);
|
||||||
|
} else {
|
||||||
|
return Math.max(value, -max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -842,6 +861,7 @@ public class LeashDataImpl implements ILeashData {
|
||||||
boolean hasForce = !combinedForce.equals(Vec3.ZERO);
|
boolean hasForce = !combinedForce.equals(Vec3.ZERO);
|
||||||
Entity targetEntity = RindingLeash.getFinalEntityForLeashIfForce(entity, hasForce);
|
Entity targetEntity = RindingLeash.getFinalEntityForLeashIfForce(entity, hasForce);
|
||||||
if (targetEntity != null && hasForce) {
|
if (targetEntity != null && hasForce) {
|
||||||
|
combinedForce = limitMovement(combinedForce);
|
||||||
SuperLeadRopeEvent.hasFocus hasFocus = new SuperLeadRopeEvent.hasFocus(this.entity, targetEntity, combinedForce, vaildLeashHolders, vaildLeashKnots);
|
SuperLeadRopeEvent.hasFocus hasFocus = new SuperLeadRopeEvent.hasFocus(this.entity, targetEntity, combinedForce, vaildLeashHolders, vaildLeashKnots);
|
||||||
if (MinecraftForge.EVENT_BUS.post(hasFocus)) return;
|
if (MinecraftForge.EVENT_BUS.post(hasFocus)) return;
|
||||||
combinedForce = hasFocus.getCombinedForce();
|
combinedForce = hasFocus.getCombinedForce();
|
||||||
|
|
@ -850,11 +870,11 @@ public class LeashDataImpl implements ILeashData {
|
||||||
// 是真实玩家则交给客户端自行处理拴绳逻辑
|
// 是真实玩家则交给客户端自行处理拴绳逻辑
|
||||||
// DO NOTHING
|
// DO NOTHING
|
||||||
if(targetEntity != entity){
|
if(targetEntity != entity){
|
||||||
NetworkHandler.sendToPlayer(new UpdatePlayerMovementPacket(UpdatePlayerMovementPacket.Operation.ADD, combinedForce), player);
|
NetworkHandler.sendToPlayer(new UpdatePlayerMovementPacket(UpdatePlayerMovementPacket.Operation.ADD, limitMovement(combinedForce)), player);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
applyForceToNonPlayerEntity(targetEntity, combinedForce, validLeashes, combinedDirection);
|
applyForceToNonPlayerEntity(targetEntity, limitMovement(combinedForce), validLeashes, combinedDirection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
package top.r3944realms.superleadrope.content.effect;
|
||||||
|
|
||||||
|
import net.minecraft.sounds.SoundSource;
|
||||||
|
import net.minecraft.world.effect.MobEffect;
|
||||||
|
import net.minecraft.world.effect.MobEffectCategory;
|
||||||
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import top.r3944realms.superleadrope.api.type.capabilty.ILeashData;
|
||||||
|
import top.r3944realms.superleadrope.core.register.SLPEffects;
|
||||||
|
import top.r3944realms.superleadrope.core.register.SLPSoundEvents;
|
||||||
|
import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class NoSuperLeashEffect extends MobEffect {
|
||||||
|
public NoSuperLeashEffect(MobEffectCategory category, int color) {
|
||||||
|
super(category, color);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void applyEffectTick(@NotNull LivingEntity pLivingEntity, int pAmplifier) {
|
||||||
|
MobEffectInstance effect = pLivingEntity.getEffect(SLPEffects.NO_SUPER_LEASH_EFFECT.get());
|
||||||
|
if(effect != null && effect.getDuration() != 0) {
|
||||||
|
Optional<ILeashData> leashData = LeashDataInnerAPI.getLeashData(pLivingEntity);
|
||||||
|
if (leashData.isPresent() && leashData.get().hasLeash()) {
|
||||||
|
LeashDataInnerAPI.LeashOperations.detachAll(pLivingEntity);
|
||||||
|
pLivingEntity.level().playSound(null,
|
||||||
|
pLivingEntity.getOnPos(),
|
||||||
|
SLPSoundEvents.LEAD_UNTIED.get(),
|
||||||
|
SoundSource.AMBIENT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDurationEffectTick(int duration, int amplifier) {
|
||||||
|
return duration >= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package top.r3944realms.superleadrope.content.item;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
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 org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import top.r3944realms.superleadrope.core.register.SLPBlocks;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DollItem extends BlockItem {
|
||||||
|
public DollItem(Properties properties) {
|
||||||
|
super(SLPBlocks.DOLL.get(), properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendHoverText(@NotNull ItemStack stack, @Nullable Level level, List<Component> tooltip, @NotNull TooltipFlag flag) {
|
||||||
|
tooltip.add(Component.translatable("tooltip.superleadrope.author"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@ import net.minecraft.sounds.SoundSource;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.InteractionResultHolder;
|
import net.minecraft.world.InteractionResultHolder;
|
||||||
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
@ -34,6 +35,7 @@ import top.r3944realms.superleadrope.api.SuperLeadRopeApi;
|
||||||
import top.r3944realms.superleadrope.api.type.capabilty.ILeashData;
|
import top.r3944realms.superleadrope.api.type.capabilty.ILeashData;
|
||||||
import top.r3944realms.superleadrope.content.SLPToolTier;
|
import top.r3944realms.superleadrope.content.SLPToolTier;
|
||||||
import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity;
|
import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity;
|
||||||
|
import top.r3944realms.superleadrope.core.register.SLPEffects;
|
||||||
import top.r3944realms.superleadrope.core.register.SLPSoundEvents;
|
import top.r3944realms.superleadrope.core.register.SLPSoundEvents;
|
||||||
import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI;
|
import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI;
|
||||||
|
|
||||||
|
|
@ -195,6 +197,10 @@ public class SuperLeadRopeItem extends TieredItem implements IForgeItem {
|
||||||
|
|
||||||
// 情况一:拴自己到新 knot
|
// 情况一:拴自己到新 knot
|
||||||
if (shouldBindSelf && list.isEmpty()) {
|
if (shouldBindSelf && list.isEmpty()) {
|
||||||
|
MobEffectInstance effect = player.getEffect(SLPEffects.NO_SUPER_LEASH_EFFECT.get());
|
||||||
|
if (effect != null && effect.getDuration() >= 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (leashStack.isEmpty() || !canUse(leashStack)) {
|
if (leashStack.isEmpty() || !canUse(leashStack)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@ import net.minecraft.sounds.SoundEvents;
|
||||||
import net.minecraft.sounds.SoundSource;
|
import net.minecraft.sounds.SoundSource;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
@ -31,6 +33,7 @@ import top.r3944realms.superleadrope.api.SuperLeadRopeApi;
|
||||||
import top.r3944realms.superleadrope.api.type.capabilty.ILeashData;
|
import top.r3944realms.superleadrope.api.type.capabilty.ILeashData;
|
||||||
import top.r3944realms.superleadrope.content.capability.impi.LeashDataImpl;
|
import top.r3944realms.superleadrope.content.capability.impi.LeashDataImpl;
|
||||||
import top.r3944realms.superleadrope.content.item.SuperLeadRopeItem;
|
import top.r3944realms.superleadrope.content.item.SuperLeadRopeItem;
|
||||||
|
import top.r3944realms.superleadrope.core.register.SLPEffects;
|
||||||
import top.r3944realms.superleadrope.core.register.SLPItems;
|
import top.r3944realms.superleadrope.core.register.SLPItems;
|
||||||
import top.r3944realms.superleadrope.core.register.SLPSoundEvents;
|
import top.r3944realms.superleadrope.core.register.SLPSoundEvents;
|
||||||
import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI;
|
import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI;
|
||||||
|
|
@ -53,7 +56,6 @@ public class LeashInteractHandler {
|
||||||
//只有玩家可以互动触发(其它的暂不支持(考虑到0 Mixin)
|
//只有玩家可以互动触发(其它的暂不支持(考虑到0 Mixin)
|
||||||
public static void onEntityRightInteract(Level level, InteractionHand hand, Entity target , Player player, PlayerInteractEvent.EntityInteract event) {
|
public static void onEntityRightInteract(Level level, InteractionHand hand, Entity target , Player player, PlayerInteractEvent.EntityInteract event) {
|
||||||
//WARNING: 主手和副手都会触发一次该事件
|
//WARNING: 主手和副手都会触发一次该事件
|
||||||
|
|
||||||
// ===== 卫语句 =====
|
// ===== 卫语句 =====
|
||||||
if (level.isClientSide) {
|
if (level.isClientSide) {
|
||||||
if (hand == InteractionHand.MAIN_HAND &&
|
if (hand == InteractionHand.MAIN_HAND &&
|
||||||
|
|
@ -63,6 +65,12 @@ public class LeashInteractHandler {
|
||||||
event.setCanceled(true);
|
event.setCanceled(true);
|
||||||
event.setCancellationResult(InteractionResult.SUCCESS);
|
event.setCancellationResult(InteractionResult.SUCCESS);
|
||||||
}
|
}
|
||||||
|
if (target instanceof LivingEntity livingEntity) { //禁止拴绳效果存在则取消下面的逻辑
|
||||||
|
MobEffectInstance effect = livingEntity.getEffect(SLPEffects.NO_SUPER_LEASH_EFFECT.get());
|
||||||
|
if (effect != null && effect.getDuration() >= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (SuperLeadRopeApi.isLeashHolder(target, player)) {
|
if (SuperLeadRopeApi.isLeashHolder(target, player)) {
|
||||||
event.setCanceled(true);
|
event.setCanceled(true);
|
||||||
event.setCancellationResult(InteractionResult.SUCCESS);
|
event.setCancellationResult(InteractionResult.SUCCESS);
|
||||||
|
|
@ -97,6 +105,12 @@ public class LeashInteractHandler {
|
||||||
event.setCancellationResult(InteractionResult.SUCCESS);
|
event.setCancellationResult(InteractionResult.SUCCESS);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (target instanceof LivingEntity livingEntity) { //禁止拴绳效果存在则取消下面的逻辑
|
||||||
|
MobEffectInstance effect = livingEntity.getEffect(SLPEffects.NO_SUPER_LEASH_EFFECT.get());
|
||||||
|
if (effect != null && effect.getDuration() >= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (SuperLeadRopeApi.isLeashHolder(target, player)) {
|
if (SuperLeadRopeApi.isLeashHolder(target, player)) {
|
||||||
LeashCap.ifPresent(
|
LeashCap.ifPresent(
|
||||||
iLeashDataCapability -> iLeashDataCapability.removeLeash(player.getUUID())
|
iLeashDataCapability -> iLeashDataCapability.removeLeash(player.getUUID())
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package top.r3944realms.superleadrope.core.register;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
|
import net.minecraftforge.registries.DeferredRegister;
|
||||||
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
import net.minecraftforge.registries.RegistryObject;
|
||||||
|
import top.r3944realms.superleadrope.SuperLeadRope;
|
||||||
|
import top.r3944realms.superleadrope.content.block.DollBlock;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class SLPBlocks {
|
||||||
|
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, SuperLeadRope.MOD_ID);
|
||||||
|
public static final RegistryObject<Block> DOLL = BLOCKS.register("doll", DollBlock::new);
|
||||||
|
public static Collection<RegistryObject<Block>> getEntries() {
|
||||||
|
return BLOCKS.getEntries();
|
||||||
|
}
|
||||||
|
public static void register(IEventBus eventBus) {
|
||||||
|
BLOCKS.register(eventBus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package top.r3944realms.superleadrope.core.register;
|
||||||
|
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.world.effect.MobEffect;
|
||||||
|
import net.minecraft.world.effect.MobEffectCategory;
|
||||||
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
|
import net.minecraftforge.registries.DeferredRegister;
|
||||||
|
import net.minecraftforge.registries.RegistryObject;
|
||||||
|
import top.r3944realms.superleadrope.SuperLeadRope;
|
||||||
|
import top.r3944realms.superleadrope.content.effect.NoSuperLeashEffect;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class SLPEffects {
|
||||||
|
public static DeferredRegister<MobEffect> MOB_EFFECT = DeferredRegister.create(Registries.MOB_EFFECT, SuperLeadRope.MOD_ID);
|
||||||
|
public static RegistryObject<MobEffect> NO_SUPER_LEASH_EFFECT = register(
|
||||||
|
"no_super_leash",
|
||||||
|
() -> new NoSuperLeashEffect(MobEffectCategory.NEUTRAL, 12063764)
|
||||||
|
);
|
||||||
|
public static <T extends MobEffect> RegistryObject<MobEffect> register(String name, Supplier<T> effect) {
|
||||||
|
return MOB_EFFECT.register(name, effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getEffectKey(MobEffect effect) {
|
||||||
|
return effect.getDescriptionId();
|
||||||
|
}
|
||||||
|
public static String getModEffectKey(RegistryObject<MobEffect> effect) {
|
||||||
|
return getEffectKey(effect.get());
|
||||||
|
}
|
||||||
|
public static void register(IEventBus eventBus) {
|
||||||
|
MOB_EFFECT.register(eventBus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,11 +16,13 @@
|
||||||
package top.r3944realms.superleadrope.core.register;
|
package top.r3944realms.superleadrope.core.register;
|
||||||
|
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.Rarity;
|
||||||
import net.minecraftforge.eventbus.api.IEventBus;
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
import net.minecraftforge.registries.DeferredRegister;
|
import net.minecraftforge.registries.DeferredRegister;
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
import net.minecraftforge.registries.RegistryObject;
|
import net.minecraftforge.registries.RegistryObject;
|
||||||
import top.r3944realms.superleadrope.SuperLeadRope;
|
import top.r3944realms.superleadrope.SuperLeadRope;
|
||||||
|
import top.r3944realms.superleadrope.content.item.DollItem;
|
||||||
import top.r3944realms.superleadrope.content.item.EternalPotatoItem;
|
import top.r3944realms.superleadrope.content.item.EternalPotatoItem;
|
||||||
import top.r3944realms.superleadrope.content.item.SuperLeadRopeItem;
|
import top.r3944realms.superleadrope.content.item.SuperLeadRopeItem;
|
||||||
|
|
||||||
|
|
@ -49,6 +51,15 @@ public class SLPItems {
|
||||||
.stacksTo(1) // 只能有一颗
|
.stacksTo(1) // 只能有一颗
|
||||||
.fireResistant() // 防火
|
.fireResistant() // 防火
|
||||||
));
|
));
|
||||||
|
public static final RegistryObject<Item> DOLL =
|
||||||
|
ITEMS.register("doll",
|
||||||
|
() -> new DollItem(
|
||||||
|
new Item.Properties()
|
||||||
|
.stacksTo(1)
|
||||||
|
.fireResistant()
|
||||||
|
.rarity(Rarity.EPIC)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register.
|
* Register.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package top.r3944realms.superleadrope.core.register;
|
||||||
|
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.Items;
|
||||||
|
import net.minecraft.world.item.alchemy.Potion;
|
||||||
|
import net.minecraft.world.item.alchemy.PotionUtils;
|
||||||
|
import net.minecraft.world.item.alchemy.Potions;
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
|
import net.minecraftforge.common.brewing.BrewingRecipe;
|
||||||
|
import net.minecraftforge.common.brewing.BrewingRecipeRegistry;
|
||||||
|
import net.minecraftforge.registries.RegistryObject;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
|
||||||
|
public class SLPPotionRecipeRegistry {
|
||||||
|
public static class ProperBrewingRecipe extends BrewingRecipe {
|
||||||
|
private final Ingredient input;
|
||||||
|
|
||||||
|
public ProperBrewingRecipe(Ingredient input, Ingredient ingredient, ItemStack output) {
|
||||||
|
super(input, ingredient, output);
|
||||||
|
this.input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInput(@NotNull ItemStack stack) {
|
||||||
|
ItemStack[] matchingStacks = input.getItems();
|
||||||
|
if (matchingStacks.length == 0) {
|
||||||
|
return stack.isEmpty();
|
||||||
|
} else {
|
||||||
|
for (ItemStack itemstack : matchingStacks) {
|
||||||
|
if (ItemStack.isSameItem(stack, itemstack) && ItemStack.isSameItemSameTags(itemstack, stack)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Contract("_ -> new")
|
||||||
|
public static @NotNull ItemStack createPotion(@NotNull RegistryObject<Potion> potion){
|
||||||
|
return PotionUtils.setPotion(new ItemStack(Items.POTION), potion.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Contract("_ -> new")
|
||||||
|
public static @NotNull ItemStack createPotion(Potion potion){
|
||||||
|
return PotionUtils.setPotion(new ItemStack(Items.POTION), potion);
|
||||||
|
}
|
||||||
|
public static void init() {
|
||||||
|
BrewingRecipeRegistry.addRecipe(
|
||||||
|
new ProperBrewingRecipe(Ingredient.of(createPotion(Potions.INVISIBILITY)), Ingredient.of(Items.SLIME_BALL), createPotion(SLPPotions.NO_SUPER_LEASH)));
|
||||||
|
BrewingRecipeRegistry.addRecipe(
|
||||||
|
new ProperBrewingRecipe(Ingredient.of(createPotion(Potions.LONG_INVISIBILITY)), Ingredient.of(Items.SLIME_BALL), createPotion(SLPPotions.LONG_NO_SUPER_LEASH)));
|
||||||
|
BrewingRecipeRegistry.addRecipe(
|
||||||
|
new ProperBrewingRecipe(Ingredient.of(createPotion(SLPPotions.NO_SUPER_LEASH)), Ingredient.of(Items.REDSTONE), createPotion(SLPPotions.LONG_NO_SUPER_LEASH)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package top.r3944realms.superleadrope.core.register;
|
||||||
|
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
|
import net.minecraft.world.item.alchemy.Potion;
|
||||||
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
|
import net.minecraftforge.registries.DeferredRegister;
|
||||||
|
import net.minecraftforge.registries.RegistryObject;
|
||||||
|
import top.r3944realms.superleadrope.SuperLeadRope;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class SLPPotions {
|
||||||
|
public static DeferredRegister<Potion> POTIONS = DeferredRegister.create(Registries.POTION, SuperLeadRope.MOD_ID);
|
||||||
|
public static final RegistryObject<Potion> NO_SUPER_LEASH = register("no_super_leash",
|
||||||
|
() -> new Potion("no_super_leash", new MobEffectInstance(SLPEffects.NO_SUPER_LEASH_EFFECT.get(), 1200, 0))
|
||||||
|
);
|
||||||
|
public static final RegistryObject<Potion> LONG_NO_SUPER_LEASH = register("long_no_super_leash",
|
||||||
|
() -> new Potion("no_super_leash", new MobEffectInstance(SLPEffects.NO_SUPER_LEASH_EFFECT.get(), 3600, 0))
|
||||||
|
);
|
||||||
|
public static <T extends Potion>RegistryObject<Potion> register(String Name, Supplier<T> supplier) {
|
||||||
|
return POTIONS.register(Name, supplier);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param name the Name of Potion
|
||||||
|
* @param type (char)<br/> [ <br/> 0 & 3 ~ 255 : potion <br/>1 : lingering_potion <br/>2 : splash_potion<br/>]
|
||||||
|
* @return Language Key
|
||||||
|
*/
|
||||||
|
public static String getPotionNameKey(String name, char type) {
|
||||||
|
return "item.minecraft." +
|
||||||
|
(type == 1 ? "lingering_potion" :
|
||||||
|
(type == 2 ? "splash_potion" : "potion")
|
||||||
|
)
|
||||||
|
+ ".effect." + name;
|
||||||
|
}
|
||||||
|
public static String getTippedArrowNameKey(String Name) {
|
||||||
|
return "item.minecraft.tipped_arrow.effect." + Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(IEventBus eventBus) {
|
||||||
|
POTIONS.register(eventBus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -54,7 +54,9 @@ public class SLPDataGenEvent {
|
||||||
LanguageGenerator(event, LanguageEnum.LiteraryChinese);
|
LanguageGenerator(event, LanguageEnum.LiteraryChinese);
|
||||||
RecipeGenerator(event);
|
RecipeGenerator(event);
|
||||||
ModelDataGenerate(event);
|
ModelDataGenerate(event);
|
||||||
|
BlockStateGenerate(event);
|
||||||
TagsProvider(event, lookupProvider);
|
TagsProvider(event, lookupProvider);
|
||||||
|
LootTableGenerate(event);
|
||||||
SoundProvider(event);
|
SoundProvider(event);
|
||||||
}
|
}
|
||||||
private static void LanguageGenerator(GatherDataEvent event, LanguageEnum language) {
|
private static void LanguageGenerator(GatherDataEvent event, LanguageEnum language) {
|
||||||
|
|
@ -97,4 +99,16 @@ public class SLPDataGenEvent {
|
||||||
(DataProvider.Factory<SLPItemModelProvider>) pOutput -> new SLPItemModelProvider(pOutput, event.getExistingFileHelper())
|
(DataProvider.Factory<SLPItemModelProvider>) pOutput -> new SLPItemModelProvider(pOutput, event.getExistingFileHelper())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
private static void LootTableGenerate(GatherDataEvent event) {
|
||||||
|
event.getGenerator().addProvider(
|
||||||
|
event.includeClient(),
|
||||||
|
(DataProvider.Factory<SLPLootTableProvider>) SLPLootTableProvider::new
|
||||||
|
);
|
||||||
|
}
|
||||||
|
private static void BlockStateGenerate(GatherDataEvent event) {
|
||||||
|
event.getGenerator().addProvider(
|
||||||
|
event.includeClient(),
|
||||||
|
(DataProvider.Factory<SLPBlockStateGenerator>) pOutput -> new SLPBlockStateGenerator(pOutput, event.getExistingFileHelper())
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,7 @@ import top.r3944realms.superleadrope.content.command.MotionCommand;
|
||||||
import top.r3944realms.superleadrope.content.gamerule.server.CreateSuperLeashKnotEntityIfAbsent;
|
import top.r3944realms.superleadrope.content.gamerule.server.CreateSuperLeashKnotEntityIfAbsent;
|
||||||
import top.r3944realms.superleadrope.content.gamerule.server.TeleportWithLeashedEntities;
|
import top.r3944realms.superleadrope.content.gamerule.server.TeleportWithLeashedEntities;
|
||||||
import top.r3944realms.superleadrope.content.item.EternalPotatoItem;
|
import top.r3944realms.superleadrope.content.item.EternalPotatoItem;
|
||||||
import top.r3944realms.superleadrope.core.register.SLPEntityTypes;
|
import top.r3944realms.superleadrope.core.register.*;
|
||||||
import top.r3944realms.superleadrope.core.register.SLPItems;
|
|
||||||
import top.r3944realms.superleadrope.core.register.SLPSoundEvents;
|
|
||||||
import top.r3944realms.superleadrope.util.lang.LanguageEnum;
|
import top.r3944realms.superleadrope.util.lang.LanguageEnum;
|
||||||
import top.r3944realms.superleadrope.util.lang.ModPartEnum;
|
import top.r3944realms.superleadrope.util.lang.ModPartEnum;
|
||||||
|
|
||||||
|
|
@ -917,6 +915,47 @@ public enum SLPLangKeyValue {
|
||||||
"成功觸發%s的力",
|
"成功觸發%s的力",
|
||||||
"%s之力,今已發"
|
"%s之力,今已發"
|
||||||
),
|
),
|
||||||
|
NO_LEASH_EFFECT(
|
||||||
|
SLPEffects.getEffectKey(SLPEffects.NO_SUPER_LEASH_EFFECT.get()), ModPartEnum.NAME,
|
||||||
|
"No Super Leash",
|
||||||
|
"禁拴",
|
||||||
|
"禁拴",
|
||||||
|
"禁系之效"
|
||||||
|
),
|
||||||
|
NO_LEASH_POTION(
|
||||||
|
SLPPotions.getPotionNameKey("no_super_leash", (char) 0), ModPartEnum.NAME,
|
||||||
|
"No Super Leash Potion",
|
||||||
|
"禁拴药水",
|
||||||
|
"禁拴藥水",
|
||||||
|
"禁系汤剂"
|
||||||
|
),
|
||||||
|
NO_LEASH_POTION_SPLASH(
|
||||||
|
SLPPotions.getPotionNameKey("no_super_leash", (char) 2), ModPartEnum.NAME,
|
||||||
|
"Splash No Super Leash Potion",
|
||||||
|
"喷溅型禁拴药水",
|
||||||
|
"噴濺型禁拴藥水",
|
||||||
|
"飞溅禁系汤"
|
||||||
|
),
|
||||||
|
NO_LEASH_POTION_LINGERING(
|
||||||
|
SLPPotions.getPotionNameKey("no_super_leash", (char) 1), ModPartEnum.NAME,
|
||||||
|
"Splash No Super Leash Potion",
|
||||||
|
"滞留型禁拴药水",
|
||||||
|
"滯留型禁拴藥水",
|
||||||
|
"缠绵禁系汤"
|
||||||
|
),
|
||||||
|
DOLL_BLOCK(
|
||||||
|
SLPBlocks.DOLL, ModPartEnum.BLOCK,
|
||||||
|
"Doll", "玩偶", "玩偶", "戲像"
|
||||||
|
),
|
||||||
|
DOLL_ITEM(
|
||||||
|
SLPItems.DOLL, ModPartEnum.ITEM,
|
||||||
|
"Doll", "玩偶", "玩偶", "戲像"
|
||||||
|
),
|
||||||
|
AUTHOR_TOOLTIP(
|
||||||
|
"tooltip.superleadrope.author", ModPartEnum.DESCRIPTION,
|
||||||
|
"Author : R3944Realms", "作者 : R3944Realms",
|
||||||
|
"作者 : R3944Realms", "作者 : R3944Realms"
|
||||||
|
)
|
||||||
|
|
||||||
;
|
;
|
||||||
private final Supplier<?> supplier;
|
private final Supplier<?> supplier;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* *
|
||||||
|
* * Copyright (c) 2025 R3944Realms. All rights reserved.
|
||||||
|
* *
|
||||||
|
* * This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
|
||||||
|
* * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
* * or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
|
||||||
|
* *
|
||||||
|
* * 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package top.r3944realms.superleadrope.datagen.provider;
|
||||||
|
|
||||||
|
import net.minecraft.data.loot.BlockLootSubProvider;
|
||||||
|
import net.minecraft.world.flag.FeatureFlags;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraftforge.registries.RegistryObject;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import top.r3944realms.superleadrope.core.register.SLPBlocks;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
|
public class SLPBlockLootTables extends BlockLootSubProvider {
|
||||||
|
public SLPBlockLootTables() {
|
||||||
|
super(Set.of(), FeatureFlags.REGISTRY.allFlags());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void generate() {
|
||||||
|
dropSelf(SLPBlocks.DOLL.get());
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected @NotNull Iterable<Block> getKnownBlocks() {
|
||||||
|
return SLPBlocks.getEntries().stream().map(RegistryObject::get)::iterator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package top.r3944realms.superleadrope.datagen.provider;
|
||||||
|
|
||||||
|
import net.minecraft.data.PackOutput;
|
||||||
|
import net.minecraftforge.client.model.generators.BlockStateProvider;
|
||||||
|
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||||
|
import top.r3944realms.superleadrope.SuperLeadRope;
|
||||||
|
import top.r3944realms.superleadrope.core.register.SLPBlocks;
|
||||||
|
|
||||||
|
public class SLPBlockStateGenerator extends BlockStateProvider {
|
||||||
|
public SLPBlockStateGenerator(PackOutput output, ExistingFileHelper exFileHelper) {
|
||||||
|
super(output, SuperLeadRope.MOD_ID, exFileHelper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerStatesAndModels() {
|
||||||
|
horizontalBlock(SLPBlocks.DOLL.get(), models().getExistingFile(modLoc("block/doll")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,6 +24,7 @@ import net.minecraftforge.client.model.generators.ModelFile;
|
||||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
import top.r3944realms.superleadrope.SuperLeadRope;
|
import top.r3944realms.superleadrope.SuperLeadRope;
|
||||||
|
import top.r3944realms.superleadrope.core.register.SLPItems;
|
||||||
import top.r3944realms.superleadrope.datagen.data.SLPLangKeyValue;
|
import top.r3944realms.superleadrope.datagen.data.SLPLangKeyValue;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -35,6 +36,7 @@ import java.util.Objects;
|
||||||
*/
|
*/
|
||||||
public class SLPItemModelProvider extends ItemModelProvider {
|
public class SLPItemModelProvider extends ItemModelProvider {
|
||||||
private static List<Item> objectList;
|
private static List<Item> objectList;
|
||||||
|
public static final ResourceLocation DOLL = new ResourceLocation(SuperLeadRope.MOD_ID, "block/doll");
|
||||||
/**
|
/**
|
||||||
* The constant GENERATED.
|
* The constant GENERATED.
|
||||||
*/
|
*/
|
||||||
|
|
@ -60,6 +62,7 @@ public class SLPItemModelProvider extends ItemModelProvider {
|
||||||
protected void registerModels() {
|
protected void registerModels() {
|
||||||
DefaultModItemModelRegister();
|
DefaultModItemModelRegister();
|
||||||
superLeadRopeModel();
|
superLeadRopeModel();
|
||||||
|
generateDollItemModel();
|
||||||
}
|
}
|
||||||
private void init() {
|
private void init() {
|
||||||
for(SLPLangKeyValue obj : SLPLangKeyValue.values()) {
|
for(SLPLangKeyValue obj : SLPLangKeyValue.values()) {
|
||||||
|
|
@ -93,6 +96,10 @@ public class SLPItemModelProvider extends ItemModelProvider {
|
||||||
public void itemHandHeldModel(Item item, ResourceLocation location){
|
public void itemHandHeldModel(Item item, ResourceLocation location){
|
||||||
withExistingParent(itemName(item), HANDHELD).texture("layer0", location);
|
withExistingParent(itemName(item), HANDHELD).texture("layer0", location);
|
||||||
}
|
}
|
||||||
|
private void generateDollItemModel() {
|
||||||
|
withExistingParent(itemName(SLPItems.DOLL.get()), DOLL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Super lead rope model.
|
* Super lead rope model.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package top.r3944realms.superleadrope.datagen.provider;
|
||||||
|
|
||||||
|
import net.minecraft.data.PackOutput;
|
||||||
|
import net.minecraft.data.loot.LootTableProvider;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.level.storage.loot.LootTable;
|
||||||
|
import net.minecraft.world.level.storage.loot.ValidationContext;
|
||||||
|
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Simple loot table provider.
|
||||||
|
*/
|
||||||
|
public class SLPLootTableProvider extends LootTableProvider {
|
||||||
|
/**
|
||||||
|
* Instantiates a new Simple loot table provider.
|
||||||
|
*
|
||||||
|
* @param output the output
|
||||||
|
* @param subProvidersWrapper the sub providers wrapper
|
||||||
|
*/
|
||||||
|
public SLPLootTableProvider(PackOutput output) {
|
||||||
|
super(output, Set.of(), List.of(new LootTableProvider.SubProviderEntry(
|
||||||
|
SLPBlockLootTables::new,
|
||||||
|
LootContextParamSets.BLOCK
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void validate(@NotNull Map<ResourceLocation, LootTable> map, @NotNull ValidationContext validationcontext) {
|
||||||
|
map.forEach((id, table) -> table.validate(validationcontext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
package top.r3944realms.superleadrope.util.entity;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.entity.*;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraft.server.level.TicketType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class TeleportUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用实体传送(支持玩家、普通生物、跨维度、生物停飞、导航停止等)
|
||||||
|
*/
|
||||||
|
public static @NotNull Entity teleportEntity(Entity oldEntity, ServerLevel targetWorld, @NotNull Vec3 targetPos, @NotNull Direction direction) {
|
||||||
|
float yaw = direction.toYRot();
|
||||||
|
double x = targetPos.x;
|
||||||
|
double y = targetPos.y;
|
||||||
|
double z = targetPos.z;
|
||||||
|
|
||||||
|
if (oldEntity instanceof ServerPlayer player) {
|
||||||
|
teleportPlayer(player, targetWorld, x, y, z, yaw);
|
||||||
|
} else {
|
||||||
|
oldEntity = teleportNonPlayer(oldEntity, targetWorld, x, y, z, yaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 停止滑翔,否则 Elytra 无限飞
|
||||||
|
if (!(oldEntity instanceof LivingEntity living) || !living.isFallFlying()) {
|
||||||
|
oldEntity.setDeltaMovement(oldEntity.getDeltaMovement().multiply(1.0, 0.0, 1.0));
|
||||||
|
oldEntity.setOnGround(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 停止 AI 导航,避免卡行为树
|
||||||
|
if (oldEntity instanceof PathfinderMob mob) {
|
||||||
|
mob.getNavigation().stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
sendHackySyncPacketsAfterTeleport(oldEntity);
|
||||||
|
|
||||||
|
return oldEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --- 分离后的子方法 ------------------------------------------------
|
||||||
|
|
||||||
|
private static void teleportPlayer(@NotNull ServerPlayer player, @NotNull ServerLevel targetWorld,
|
||||||
|
double x, double y, double z, float yaw) {
|
||||||
|
|
||||||
|
ChunkPos chunkPos = new ChunkPos(BlockPos.containing(x, y, z));
|
||||||
|
targetWorld.getChunkSource().addRegionTicket(
|
||||||
|
TicketType.POST_TELEPORT,
|
||||||
|
chunkPos,
|
||||||
|
1,
|
||||||
|
player.getId()
|
||||||
|
);
|
||||||
|
|
||||||
|
// 玩家睡觉状态处理
|
||||||
|
if (player.isSleeping()) {
|
||||||
|
player.stopSleepInBed(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
player.stopRiding();
|
||||||
|
|
||||||
|
// 同维度直接 connection.teleport
|
||||||
|
if (targetWorld == player.level()) {
|
||||||
|
player.connection.teleport(x, y, z, yaw, player.getXRot(), Collections.emptySet());
|
||||||
|
} else {
|
||||||
|
player.teleportTo(targetWorld, x, y, z, yaw, player.getXRot());
|
||||||
|
}
|
||||||
|
|
||||||
|
player.setYHeadRot(yaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static @NotNull Entity teleportNonPlayer(@NotNull Entity entity, ServerLevel targetWorld,
|
||||||
|
double x, double y, double z, float yaw) {
|
||||||
|
|
||||||
|
float pitch = Mth.clamp(entity.getXRot(), -90, 90);
|
||||||
|
|
||||||
|
// 同维度移动
|
||||||
|
if (targetWorld == entity.level()) {
|
||||||
|
entity.moveTo(x, y, z, yaw, pitch);
|
||||||
|
entity.setYHeadRot(yaw);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跨维度传送
|
||||||
|
entity.unRide();
|
||||||
|
|
||||||
|
Entity newEntity = entity.getType().create(targetWorld);
|
||||||
|
|
||||||
|
if (newEntity == null) {
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
newEntity.restoreFrom(entity);
|
||||||
|
newEntity.moveTo(x, y, z, yaw, pitch);
|
||||||
|
newEntity.setYHeadRot(yaw);
|
||||||
|
|
||||||
|
entity.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION);
|
||||||
|
targetWorld.addDuringTeleport(newEntity);
|
||||||
|
|
||||||
|
return newEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修复玩家经验条显示等问题的同步包
|
||||||
|
*/
|
||||||
|
private static void sendHackySyncPacketsAfterTeleport(Entity entity) {
|
||||||
|
if (entity instanceof ServerPlayer player) {
|
||||||
|
player.connection.send(
|
||||||
|
new ClientboundSetExperiencePacket(
|
||||||
|
player.experienceProgress,
|
||||||
|
player.totalExperience,
|
||||||
|
player.experienceLevel
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
package top.r3944realms.superleadrope.util.model;
|
package top.r3944realms.superleadrope.util.model;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -138,6 +140,121 @@ public class RidingRelationship {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 查找并替换所有匹配的UUID
|
||||||
|
*
|
||||||
|
* @param oldUuid 要查找的旧UUID
|
||||||
|
* @param newUuid 要替换的新UUID
|
||||||
|
* @return 替换的数量
|
||||||
|
*/
|
||||||
|
public int findAndReplaceAll(UUID oldUuid, UUID newUuid) {
|
||||||
|
int replacedCount = 0;
|
||||||
|
|
||||||
|
// 替换当前节点的entityId
|
||||||
|
if (Objects.equals(this.entityId, oldUuid)) {
|
||||||
|
this.entityId = newUuid;
|
||||||
|
replacedCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 替换当前节点的vehicleId
|
||||||
|
if (Objects.equals(this.vehicleId, oldUuid)) {
|
||||||
|
this.vehicleId = newUuid;
|
||||||
|
replacedCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归替换所有乘客
|
||||||
|
for (RidingRelationship passenger : passengers) {
|
||||||
|
replacedCount += passenger.findAndReplaceAll(oldUuid, newUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return replacedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找所有出现的UUID位置
|
||||||
|
*
|
||||||
|
* @param targetUuid 要查找的UUID
|
||||||
|
* @return 包含位置的列表,格式为"角色(实体/载具)-索引"
|
||||||
|
*/
|
||||||
|
public List<String> findAllOccurrences(UUID targetUuid) {
|
||||||
|
List<String> occurrences = new ArrayList<>();
|
||||||
|
findAllOccurrencesRecursive(targetUuid, this, occurrences, "");
|
||||||
|
return occurrences;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findAllOccurrencesRecursive(UUID targetUuid, @NotNull RidingRelationship node,
|
||||||
|
List<String> occurrences, String path) {
|
||||||
|
// 检查当前节点的entityId
|
||||||
|
if (Objects.equals(node.entityId, targetUuid)) {
|
||||||
|
String fullPath = path.isEmpty() ? "根实体" : path + "->乘客";
|
||||||
|
occurrences.add(fullPath + "(实体ID)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查当前节点的vehicleId
|
||||||
|
if (Objects.equals(node.vehicleId, targetUuid)) {
|
||||||
|
String fullPath = path.isEmpty() ? "根实体" : path;
|
||||||
|
occurrences.add(fullPath + "(载具ID)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归检查乘客
|
||||||
|
for (int i = 0; i < node.passengers.size(); i++) {
|
||||||
|
String newPath = path.isEmpty() ? "乘客[" + i + "]" : path + "->乘客[" + i + "]";
|
||||||
|
findAllOccurrencesRecursive(targetUuid, node.passengers.get(i), occurrences, newPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找并替换所有UUID(支持批量替换)
|
||||||
|
*
|
||||||
|
* @param replacements 替换映射表,key为旧UUID,value为新UUID
|
||||||
|
* @return 总替换数量
|
||||||
|
*/
|
||||||
|
public int batchFindAndReplace(Map<UUID, UUID> replacements) {
|
||||||
|
int totalReplaced = 0;
|
||||||
|
|
||||||
|
// 替换当前节点的entityId
|
||||||
|
if (this.entityId != null && replacements.containsKey(this.entityId)) {
|
||||||
|
this.entityId = replacements.get(this.entityId);
|
||||||
|
totalReplaced++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 替换当前节点的vehicleId
|
||||||
|
if (this.vehicleId != null && replacements.containsKey(this.vehicleId)) {
|
||||||
|
this.vehicleId = replacements.get(this.vehicleId);
|
||||||
|
totalReplaced++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归批量替换所有乘客
|
||||||
|
for (RidingRelationship passenger : passengers) {
|
||||||
|
totalReplaced += passenger.batchFindAndReplace(replacements);
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalReplaced;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取树中所有唯一的UUID集合
|
||||||
|
*
|
||||||
|
* @return 包含所有UUID的集合
|
||||||
|
*/
|
||||||
|
public Set<UUID> getAllUniqueUUIDs() {
|
||||||
|
Set<UUID> uuids = new HashSet<>();
|
||||||
|
getAllUniqueUUIDsRecursive(this, uuids);
|
||||||
|
return uuids;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getAllUniqueUUIDsRecursive(RidingRelationship node, Set<UUID> uuids) {
|
||||||
|
if (node.entityId != null) {
|
||||||
|
uuids.add(node.entityId);
|
||||||
|
}
|
||||||
|
if (node.vehicleId != null) {
|
||||||
|
uuids.add(node.vehicleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (RidingRelationship passenger : node.passengers) {
|
||||||
|
getAllUniqueUUIDsRecursive(passenger, uuids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,10 @@ package top.r3944realms.superleadrope.util.riding;
|
||||||
|
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.EntityType;
|
import net.minecraft.world.entity.EntityType;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import top.r3944realms.superleadrope.CommonEventHandler;
|
import top.r3944realms.superleadrope.CommonEventHandler;
|
||||||
|
import top.r3944realms.superleadrope.SuperLeadRope;
|
||||||
import top.r3944realms.superleadrope.core.exception.RidingCycleException;
|
import top.r3944realms.superleadrope.core.exception.RidingCycleException;
|
||||||
import top.r3944realms.superleadrope.core.util.ImmutablePair;
|
import top.r3944realms.superleadrope.core.util.ImmutablePair;
|
||||||
import top.r3944realms.superleadrope.util.model.RidingRelationship;
|
import top.r3944realms.superleadrope.util.model.RidingRelationship;
|
||||||
|
|
@ -36,7 +39,8 @@ public class RidingSaver {
|
||||||
* @param entity the entity
|
* @param entity the entity
|
||||||
* @return the riding relationship
|
* @return the riding relationship
|
||||||
*/
|
*/
|
||||||
public static RidingRelationship save(@Nullable Entity entity) {
|
@Contract("null -> new")
|
||||||
|
public static @NotNull RidingRelationship save(@Nullable Entity entity) {
|
||||||
return save(entity, true);
|
return save(entity, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,7 +51,8 @@ public class RidingSaver {
|
||||||
* @param findRoot the find root
|
* @param findRoot the find root
|
||||||
* @return the riding relationship
|
* @return the riding relationship
|
||||||
*/
|
*/
|
||||||
public static RidingRelationship save(@Nullable Entity entity, boolean findRoot) {
|
@Contract("null, _ -> new")
|
||||||
|
public static @NotNull RidingRelationship save(@Nullable Entity entity, boolean findRoot) {
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
return new RidingRelationship(Collections.emptyList(), null, null);
|
return new RidingRelationship(Collections.emptyList(), null, null);
|
||||||
}
|
}
|
||||||
|
|
@ -118,33 +123,37 @@ public class RidingSaver {
|
||||||
*/
|
*/
|
||||||
public static RidingRelationship filterByWhitelistRoot(RidingRelationship relationship) {
|
public static RidingRelationship filterByWhitelistRoot(RidingRelationship relationship) {
|
||||||
if (relationship == null) return null;
|
if (relationship == null) return null;
|
||||||
|
try {
|
||||||
// 如果当前根节点在白名单,则直接处理子节点
|
// 如果当前根节点在白名单,则直接处理子节点
|
||||||
if (CommonEventHandler.leashConfigManager.isEntityTeleportAllowed(Objects.requireNonNull(getEntityType(relationship.getEntityId())))) {
|
if (CommonEventHandler.leashConfigManager.isEntityTeleportAllowed(Objects.requireNonNull(getEntityType(relationship.getEntityId())))) {
|
||||||
RidingRelationship filtered = new RidingRelationship();
|
RidingRelationship filtered = new RidingRelationship();
|
||||||
filtered.setEntityId(relationship.getEntityId());
|
filtered.setEntityId(relationship.getEntityId());
|
||||||
filtered.setVehicleId(relationship.getVehicleId());
|
filtered.setVehicleId(relationship.getVehicleId());
|
||||||
filtered.setPassengers(filterPassengers(relationship.getPassengers()));
|
filtered.setPassengers(filterPassengers(relationship.getPassengers()));
|
||||||
return filtered;
|
return filtered;
|
||||||
} else {
|
} else {
|
||||||
// 根节点不在白名单,尝试找到合法的子节点作为新的根
|
// 根节点不在白名单,尝试找到合法的子节点作为新的根
|
||||||
for (RidingRelationship child : relationship.getPassengers()) {
|
for (RidingRelationship child : relationship.getPassengers()) {
|
||||||
if (CommonEventHandler.leashConfigManager.isEntityTeleportAllowed(Objects.requireNonNull(getEntityType(child.getEntityId())))) {
|
if (CommonEventHandler.leashConfigManager.isEntityTeleportAllowed(Objects.requireNonNull(getEntityType(child.getEntityId())))) {
|
||||||
// 设置父节点为当前节点的父(倒二叉逻辑)
|
// 设置父节点为当前节点的父(倒二叉逻辑)
|
||||||
RidingRelationship newRoot = new RidingRelationship();
|
RidingRelationship newRoot = new RidingRelationship();
|
||||||
newRoot.setEntityId(child.getEntityId());
|
newRoot.setEntityId(child.getEntityId());
|
||||||
newRoot.setVehicleId(relationship.getVehicleId());
|
newRoot.setVehicleId(relationship.getVehicleId());
|
||||||
newRoot.setPassengers(filterPassengers(child.getPassengers()));
|
newRoot.setPassengers(filterPassengers(child.getPassengers()));
|
||||||
return newRoot;
|
return newRoot;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
SuperLeadRope.logger.error("Catch null", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果整个子树都不在白名单,返回空关系
|
// 如果整个子树都不在白名单,返回空关系
|
||||||
return new RidingRelationship(new ArrayList<>(), null, null);
|
return new RidingRelationship(new ArrayList<>(), null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<RidingRelationship> filterPassengers(List<RidingRelationship> passengers) {
|
@Contract("null -> new")
|
||||||
|
private static @NotNull List<RidingRelationship> filterPassengers(List<RidingRelationship> passengers) {
|
||||||
if (passengers == null || passengers.isEmpty()) return new ArrayList<>();
|
if (passengers == null || passengers.isEmpty()) return new ArrayList<>();
|
||||||
List<RidingRelationship> filtered = new ArrayList<>();
|
List<RidingRelationship> filtered = new ArrayList<>();
|
||||||
for (RidingRelationship passenger : passengers) {
|
for (RidingRelationship passenger : passengers) {
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
291
src/main/resources/assets/superleadrope/models/block/doll.json
Normal file
291
src/main/resources/assets/superleadrope/models/block/doll.json
Normal file
|
|
@ -0,0 +1,291 @@
|
||||||
|
{
|
||||||
|
"format_version": "1.21.6",
|
||||||
|
"credit": "3D Model © 2025 LeisureTimeDock",
|
||||||
|
"render_type": "cutout",
|
||||||
|
"textures": {
|
||||||
|
"0": "superleadrope:block/custom/author",
|
||||||
|
"1": "block/pink_tulip",
|
||||||
|
"particle": "block/white_wool"
|
||||||
|
},
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"name": "Toggle_Helmet",
|
||||||
|
"from": [3.5, 8.8, 7.5],
|
||||||
|
"to": [12.5, 17.8, 16.5],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, 9.3, 12]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [10, 2, 12, 4], "texture": "#0"},
|
||||||
|
"east": {"uv": [8, 2, 10, 4], "texture": "#0"},
|
||||||
|
"south": {"uv": [14, 2, 16, 4], "texture": "#0"},
|
||||||
|
"west": {"uv": [12, 2, 14, 4], "texture": "#0"},
|
||||||
|
"up": {"uv": [10, 2, 12, 0], "texture": "#0"},
|
||||||
|
"down": {"uv": [12, 0, 14, 2], "texture": "#0"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Head",
|
||||||
|
"from": [4, 9.3, 8],
|
||||||
|
"to": [12, 17.3, 16],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, 9.3, 12]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [2, 2, 4, 4], "texture": "#0"},
|
||||||
|
"east": {"uv": [0, 2, 2, 4], "texture": "#0"},
|
||||||
|
"south": {"uv": [6, 2, 8, 4], "texture": "#0"},
|
||||||
|
"west": {"uv": [4, 2, 6, 4], "texture": "#0"},
|
||||||
|
"up": {"uv": [4, 2, 2, 0], "texture": "#0"},
|
||||||
|
"down": {"uv": [6, 0, 4, 2], "texture": "#0"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Toggle_Chest_Armor",
|
||||||
|
"from": [4.75, 2.05, 9.75],
|
||||||
|
"to": [11.25, 9.55, 13.25],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, 5.8, 11.5]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [5, 9, 7, 12], "texture": "#0"},
|
||||||
|
"east": {"uv": [4, 9, 5, 12], "texture": "#0"},
|
||||||
|
"south": {"uv": [8, 9, 10, 12], "texture": "#0"},
|
||||||
|
"west": {"uv": [7, 9, 8, 12], "texture": "#0"},
|
||||||
|
"up": {"uv": [5, 8, 7, 9], "texture": "#0"},
|
||||||
|
"down": {"uv": [7, 8, 9, 9], "texture": "#0"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Body",
|
||||||
|
"from": [5, 2.3, 10],
|
||||||
|
"to": [11, 9.3, 13],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, 5.8, 11.5]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [5, 5, 7, 8], "texture": "#0"},
|
||||||
|
"east": {"uv": [4, 5, 5, 8], "texture": "#0"},
|
||||||
|
"south": {"uv": [8, 5, 10, 8], "texture": "#0"},
|
||||||
|
"west": {"uv": [7, 5, 8, 8], "texture": "#0"},
|
||||||
|
"up": {"uv": [7, 5, 5, 4], "texture": "#0"},
|
||||||
|
"down": {"uv": [9, 4, 7, 5], "texture": "#0"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Toggle_Left_Arm_Armor",
|
||||||
|
"from": [2.75, 6.25, 3.8],
|
||||||
|
"to": [5.25, 9.75, 13.3],
|
||||||
|
"rotation": {"angle": -22.5, "axis": "y", "origin": [3, 8, 12.5]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [13.75, 12, 14.5, 13], "rotation": 180, "texture": "#0"},
|
||||||
|
"east": {"uv": [12, 13, 13, 16], "rotation": 270, "texture": "#0"},
|
||||||
|
"south": {"uv": [13, 12, 13.75, 13], "texture": "#0"},
|
||||||
|
"west": {"uv": [13.75, 13, 14.75, 16], "rotation": 90, "texture": "#0"},
|
||||||
|
"up": {"uv": [13, 13, 13.75, 16], "rotation": 180, "texture": "#0"},
|
||||||
|
"down": {"uv": [14.75, 13, 15.5, 16], "texture": "#0"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Left_arm",
|
||||||
|
"from": [3, 6.5, 3.8],
|
||||||
|
"to": [5, 9.5, 12.8],
|
||||||
|
"rotation": {"angle": -22.5, "axis": "y", "origin": [4, 8, 12.5]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [10.5, 12, 9.75, 13], "rotation": 180, "texture": "#0"},
|
||||||
|
"east": {"uv": [8, 13, 9, 16], "rotation": 270, "texture": "#0"},
|
||||||
|
"south": {"uv": [9.75, 13, 9, 12], "texture": "#0"},
|
||||||
|
"west": {"uv": [9.75, 13, 10.5, 16], "rotation": 90, "texture": "#0"},
|
||||||
|
"up": {"uv": [9, 13, 9.75, 16], "rotation": 180, "texture": "#0"},
|
||||||
|
"down": {"uv": [10.5, 13, 11.5, 16], "texture": "#0"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Toggle_Right_Arm_Armor",
|
||||||
|
"from": [10.75, 6.25, 3.8],
|
||||||
|
"to": [13.25, 9.75, 13.3],
|
||||||
|
"rotation": {"angle": 22.5, "axis": "y", "origin": [12, 8, 11.5]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [11.75, 8, 12.5, 9], "rotation": 180, "texture": "#0"},
|
||||||
|
"east": {"uv": [10, 9, 11, 12], "rotation": 270, "texture": "#0"},
|
||||||
|
"south": {"uv": [11, 8, 11.75, 9], "texture": "#0"},
|
||||||
|
"west": {"uv": [11.75, 9, 12.75, 12], "rotation": 90, "texture": "#0"},
|
||||||
|
"up": {"uv": [11, 9, 11.75, 12], "rotation": 180, "texture": "#0"},
|
||||||
|
"down": {"uv": [12.75, 9, 13.5, 12], "texture": "#0"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Right_arm",
|
||||||
|
"from": [11, 6.5, 3.8],
|
||||||
|
"to": [13.5, 9.5, 12.8],
|
||||||
|
"rotation": {"angle": 22.5, "axis": "y", "origin": [12, 8, 11.5]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [12.5, 4, 11.75, 5], "rotation": 180, "texture": "#0"},
|
||||||
|
"east": {"uv": [10, 5, 11, 8], "rotation": 270, "texture": "#0"},
|
||||||
|
"south": {"uv": [11.75, 5, 11, 4], "texture": "#0"},
|
||||||
|
"west": {"uv": [11.75, 5, 12.5, 8], "rotation": 90, "texture": "#0"},
|
||||||
|
"up": {"uv": [11, 5, 11.75, 8], "rotation": 180, "texture": "#0"},
|
||||||
|
"down": {"uv": [12.5, 5, 13.5, 8], "texture": "#0"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Toggle_Left_Leg_Armor",
|
||||||
|
"from": [5.2, -0.25, 3.05],
|
||||||
|
"to": [8.7, 3.25, 12.55],
|
||||||
|
"rotation": {"angle": 22.5, "axis": "y", "origin": [5.7, 2, 13]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [2, 12, 3, 13], "rotation": 180, "texture": "#0"},
|
||||||
|
"east": {"uv": [0, 13, 1, 16], "rotation": 270, "texture": "#0"},
|
||||||
|
"south": {"uv": [1, 12, 2, 13], "texture": "#0"},
|
||||||
|
"west": {"uv": [2, 13, 3, 16], "rotation": 90, "texture": "#0"},
|
||||||
|
"up": {"uv": [1, 13, 2, 16], "rotation": 180, "texture": "#0"},
|
||||||
|
"down": {"uv": [3, 13, 4, 16], "texture": "#0"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Left_leg",
|
||||||
|
"from": [5.5, 0, 3.3],
|
||||||
|
"to": [8.5, 3, 12.3],
|
||||||
|
"rotation": {"angle": 22.5, "axis": "y", "origin": [6, 2, 13]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [7, 12, 6, 13], "rotation": 180, "texture": "#0"},
|
||||||
|
"east": {"uv": [4, 13, 5, 16], "rotation": 270, "texture": "#0"},
|
||||||
|
"south": {"uv": [5.95, 13, 5, 11.925], "texture": "#0"},
|
||||||
|
"west": {"uv": [6, 13, 7, 16], "rotation": 90, "texture": "#0"},
|
||||||
|
"up": {"uv": [5, 13, 6, 16], "rotation": 180, "texture": "#0"},
|
||||||
|
"down": {"uv": [7, 13, 8, 16], "texture": "#0"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Toggle_Right_Leg_Armor",
|
||||||
|
"from": [7.2, -0.25, 3.05],
|
||||||
|
"to": [10.7, 3.25, 12.55],
|
||||||
|
"rotation": {"angle": -22.5, "axis": "y", "origin": [8.7, 2, 13]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [2, 8, 3, 9], "rotation": 180, "texture": "#0"},
|
||||||
|
"east": {"uv": [0, 9, 1, 12], "rotation": 270, "texture": "#0"},
|
||||||
|
"south": {"uv": [1, 8, 2, 9], "texture": "#0"},
|
||||||
|
"west": {"uv": [2, 9, 3, 12], "rotation": 90, "texture": "#0"},
|
||||||
|
"up": {"uv": [1, 9, 2, 12], "rotation": 180, "texture": "#0"},
|
||||||
|
"down": {"uv": [3, 9, 4, 12], "texture": "#0"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Right_leg",
|
||||||
|
"from": [7.5, 0, 3.3],
|
||||||
|
"to": [10.5, 3, 12.3],
|
||||||
|
"rotation": {"angle": -22.5, "axis": "y", "origin": [9, 2, 13]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [3, 4, 2, 5], "rotation": 180, "texture": "#0"},
|
||||||
|
"east": {"uv": [0, 5, 1, 8], "rotation": 270, "texture": "#0"},
|
||||||
|
"south": {"uv": [2, 5, 1, 4], "texture": "#0"},
|
||||||
|
"west": {"uv": [2, 5, 3, 8], "rotation": 90, "texture": "#0"},
|
||||||
|
"up": {"uv": [1, 5, 2, 8], "rotation": 180, "texture": "#0"},
|
||||||
|
"down": {"uv": [3, 5, 4, 8], "texture": "#0"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [7, 6, 1],
|
||||||
|
"to": [7, 14, 9],
|
||||||
|
"rotation": {"angle": 45, "axis": "y", "origin": [7, 10, 3.5]},
|
||||||
|
"faces": {
|
||||||
|
"east": {"uv": [0, 0, 16, 16], "texture": "#1"},
|
||||||
|
"west": {"uv": [0, 0, 16, 16], "texture": "#1"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [9, 6, 1],
|
||||||
|
"to": [9, 14, 9],
|
||||||
|
"rotation": {"angle": -45, "axis": "y", "origin": [9, 10, 3.5]},
|
||||||
|
"faces": {
|
||||||
|
"east": {"uv": [0, 0, 16, 16], "texture": "#1"},
|
||||||
|
"west": {"uv": [0, 0, 16, 16], "texture": "#1"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"display": {
|
||||||
|
"thirdperson_righthand": {
|
||||||
|
"rotation": [75, 45, 0],
|
||||||
|
"translation": [0, 2.5, 0],
|
||||||
|
"scale": [0.375, 0.375, 0.375]
|
||||||
|
},
|
||||||
|
"thirdperson_lefthand": {
|
||||||
|
"rotation": [75, 45, 0],
|
||||||
|
"translation": [0, 2.5, 0],
|
||||||
|
"scale": [0.375, 0.375, 0.375]
|
||||||
|
},
|
||||||
|
"firstperson_righthand": {
|
||||||
|
"rotation": [0, 124, 0],
|
||||||
|
"translation": [2, 3, 0],
|
||||||
|
"scale": [0.4, 0.4, 0.4]
|
||||||
|
},
|
||||||
|
"firstperson_lefthand": {
|
||||||
|
"rotation": [0, 120, 0],
|
||||||
|
"translation": [1.5, 2.75, 0],
|
||||||
|
"scale": [0.4, 0.4, 0.4]
|
||||||
|
},
|
||||||
|
"ground": {
|
||||||
|
"translation": [0, 2, 0],
|
||||||
|
"scale": [0.5, 0.5, 0.5]
|
||||||
|
},
|
||||||
|
"gui": {
|
||||||
|
"rotation": [30, -135, 0],
|
||||||
|
"translation": [0.75, -1, 0],
|
||||||
|
"scale": [0.625, 0.625, 0.625]
|
||||||
|
},
|
||||||
|
"head": {
|
||||||
|
"translation": [0, 14, -0.75]
|
||||||
|
},
|
||||||
|
"fixed": {
|
||||||
|
"translation": [0, 0, -2.75],
|
||||||
|
"scale": [0.5, 0.5, 0.5]
|
||||||
|
},
|
||||||
|
"on_shelf": {
|
||||||
|
"rotation": [0, -180, 0],
|
||||||
|
"translation": [0, 0, 5.25]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"name": "Player",
|
||||||
|
"origin": [3, -6.7, 6],
|
||||||
|
"color": 0,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"name": "Head",
|
||||||
|
"origin": [8, 16, 8],
|
||||||
|
"color": 0,
|
||||||
|
"children": [0, 1]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Body",
|
||||||
|
"origin": [8, 11, 8],
|
||||||
|
"color": 0,
|
||||||
|
"children": [2, 3]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Left_Arm",
|
||||||
|
"origin": [5, 15, 6],
|
||||||
|
"color": 0,
|
||||||
|
"children": [4, 5]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Right_Arm",
|
||||||
|
"origin": [11, 15, 6],
|
||||||
|
"color": 0,
|
||||||
|
"children": [6, 7]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Left_Leg",
|
||||||
|
"origin": [7, 13, 7],
|
||||||
|
"color": 0,
|
||||||
|
"children": [8, 9]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Right_Leg",
|
||||||
|
"origin": [10, 13, 7],
|
||||||
|
"color": 0,
|
||||||
|
"children": [10, 11]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "item",
|
||||||
|
"origin": [0, 4, 2.5],
|
||||||
|
"color": 0,
|
||||||
|
"children": [12, 13]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 372 B |
Loading…
Reference in New Issue
Block a user