fix: 修正部分渲染问题

This commit is contained in:
叁玖领域 2025-09-20 18:47:15 +08:00
parent 32ac85d04e
commit c878df45e9
21 changed files with 197 additions and 151 deletions

View File

@ -148,6 +148,7 @@ configurations {
dependencies { dependencies {
annotationProcessor ('org.spongepowered:mixin:0.8.5:processor') annotationProcessor ('org.spongepowered:mixin:0.8.5:processor')
modRuntimeOnly("curse.maven:debug-utils-forge-783008:5337491") modRuntimeOnly("curse.maven:debug-utils-forge-783008:5337491")
modCompileOnly("blank:curtain-1.20.1:1.3.2")
modRuntimeOnly("blank:curtain-1.20.1:1.3.2") modRuntimeOnly("blank:curtain-1.20.1:1.3.2")
modCompileOnly("mezz.jei:jei-${minecraft_version}-forge-api:${jei_version}") modCompileOnly("mezz.jei:jei-${minecraft_version}-forge-api:${jei_version}")
modRuntimeOnly("mezz.jei:jei-${minecraft_version}-forge:${jei_version}") modRuntimeOnly("mezz.jei:jei-${minecraft_version}-forge:${jei_version}")

View File

@ -55,12 +55,12 @@ 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.1 mod_version=0.0.0.2
# 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
mod_group_id=top.r3944realms.superleadrope mod_group_id=top.r3944realms.superleadrope
# The authors of the mod. This is a simple text string that is used for display purposes in the mod list. # The authors of the mod. This is a simple text string that is used for display purposes in the mod list.
mod_authors=R3944realms mod_authors=R3944Realms
# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. # The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list.
mod_description= A Lead Rope which is better than Bugjump. mod_description= A Lead Rope which is better than Bugjump.

View File

@ -1,2 +1,2 @@
// 1.20.1 2025-09-11T20:29:48.0546389 Languages: zh_tw // 1.20.1 2025-09-20T18:20:23.4290773 Languages: zh_tw
852af450b5a31ef7436f17cb9e0d92d282e6831a assets/superleadrope/lang/zh_tw.json 0237411659cf392d87e4f866cec642396bc91382 assets/superleadrope/lang/zh_tw.json

View File

@ -1,2 +1,2 @@
// 1.20.1 2025-09-11T20:29:48.04512 Languages: zh_cn // 1.20.1 2025-09-20T18:20:23.4270438 Languages: zh_cn
78b1f4779544658700e3bf6e8f5f53ef15db7531 assets/superleadrope/lang/zh_cn.json c09eff43c9dc28c3fe516d4637ec6302af4c6656 assets/superleadrope/lang/zh_cn.json

View File

@ -1,2 +1,2 @@
// 1.20.1 2025-09-11T20:29:48.0526255 Languages: lzh // 1.20.1 2025-09-20T18:15:03.8019547 Languages: lzh
f20f2b37e9d7bfc332b5c579573e6de9f4504996 assets/superleadrope/lang/lzh.json f2ebd8aedd40b511793d238ff726c86f95693613 assets/superleadrope/lang/lzh.json

View File

@ -1,2 +1,2 @@
// 1.20.1 2025-09-11T20:29:48.0501199 Languages: en_us // 1.20.1 2025-09-20T18:20:23.4290773 Languages: en_us
d0fa9a0b01c9a2057af32d116fc8fb4e63192fa8 assets/superleadrope/lang/en_us.json 0b7f741121c31dd391168341de47844cd4a5a03c assets/superleadrope/lang/en_us.json

View File

@ -1,9 +1,15 @@
{ {
"command.leashdata.addApplyEntity.success": "§bAdded leash successfully. §a%s §7→ §e%s",
"command.leashdata.removeApplyEntity.success": "§bRemoved leash successfully. §a%s §7- §e%s",
"command.leashdata.setApplyEntity.success": "§bSet leash property successfully. §a%s §7: §e%s §7= §6%.1f",
"command.leashdata.transfer.success": "§bTransferred leash successfully. §a%s §7→ §e%s §7→ §6%s",
"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!",
"entity.superleadrope.super_lead_knot": "Super Lead Knot", "entity.superleadrope.super_lead_knot": "Super Lead Knot",
"gamerule.slp.TeleportWithLeashedEntities": "Teleport leashed player with player holder", "gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent": "Create Leash Fence Knot Entity if absent",
"gamerule.slp.TeleportWithLeashedEntities.description": "Holder will teleport with their leashed players ", "gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent.description": "Create LeashKnot Entity if it's absent on fence or other supported positions",
"gamerule.SLP.TeleportWithLeashedEntities": "Teleport leashed player with holder",
"gamerule.SLP.TeleportWithLeashedEntities.description": "Holder will teleport with their leashed players ",
"item.eternal_potato.msg.bind_msg": "§6Bound to you as the server-wide shared person.", "item.eternal_potato.msg.bind_msg": "§6Bound to you as the server-wide shared person.",
"item.eternal_potato.msg.cannot_drop": "§cThe Eternal Potato cannot be dropped! +%d punishments.", "item.eternal_potato.msg.cannot_drop": "§cThe Eternal Potato cannot be dropped! +%d punishments.",
"item.eternal_potato.msg.obligation_countdown": "Punish Countdown: §a%d §fseconds remaining", "item.eternal_potato.msg.obligation_countdown": "Punish Countdown: §a%d §fseconds remaining",
@ -25,6 +31,14 @@
"sound.superleadrope.subtitle.lead_break": "Lead Break", "sound.superleadrope.subtitle.lead_break": "Lead Break",
"sound.superleadrope.subtitle.lead_tied": "Lead Tied", "sound.superleadrope.subtitle.lead_tied": "Lead Tied",
"sound.superleadrope.subtitle.lead_untied": "Lead Untie", "sound.superleadrope.subtitle.lead_untied": "Lead Untie",
"superleadrope.command.leash.message..get.block": "§7Block: §e%s",
"superleadrope.command.leash.message..get.elastic": "§7Elastic: §6%.1f",
"superleadrope.command.leash.message..get.keep": "§7Keep: §c%d§7/§c%d",
"superleadrope.command.leash.message..get.max": "§7Max: §a%.1f",
"superleadrope.command.leash.message..get.reserved": "§7Reserved: §d%s",
"superleadrope.command.leash.message..get.title": "=== Leash Data for %s ===",
"superleadrope.command.leash.message..get.total": "Total leashes: %d",
"superleadrope.command.leash.message..get.uuid": "§7UUID: §b%s",
"superleadrope.command.motion.message.adder.successful": "§bAdd Successfully.§a%s§7:§f[§eVec§7:§a(§f%.2f§7,§f%.2f§7,§f%.2f§7)§f]§r", "superleadrope.command.motion.message.adder.successful": "§bAdd 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.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"

View File

@ -1,9 +1,15 @@
{ {
"command.leashdata.addApplyEntity.success": "§b繫繩既添. §a%s §7→ §e%s",
"command.leashdata.removeApplyEntity.success": "§b繫繩既除. §a%s §7- §e%s",
"command.leashdata.setApplyEntity.success": "§b繫繩性既定. §a%s §7: §e%s §7= §6%.1f",
"command.leashdata.transfer.success": "§b繫繩既移. §a%s §7→ §e%s §7→ §6%s",
"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 非汝所主,雷霆降身!",
"entity.superleadrope.super_lead_knot": "神駒羈縻索結", "entity.superleadrope.super_lead_knot": "神駒羈縻索結",
"gamerule.slp.TeleportWithLeashedEntities": "繫畜隨持者傳送", "gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent": "若阙则创超级繫绳结",
"gamerule.slp.TeleportWithLeashedEntities.description": "傳送時繫畜隨持者同傳", "gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent.description": "若栅等支处阙超级繫绳结,则创之",
"gamerule.SLP.TeleportWithLeashedEntities": "繫畜隨持者傳送",
"gamerule.SLP.TeleportWithLeashedEntities.description": "傳送時繫畜隨持者同傳",
"item.eternal_potato.msg.bind_msg": "§6已与汝绑定为全服共享之人。", "item.eternal_potato.msg.bind_msg": "§6已与汝绑定为全服共享之人。",
"item.eternal_potato.msg.cannot_drop": "§c永恒土豆不可丟棄懲罰數增加%d", "item.eternal_potato.msg.cannot_drop": "§c永恒土豆不可丟棄懲罰數增加%d",
"item.eternal_potato.msg.obligation_countdown": "受罚倒数§a%d §f瞬", "item.eternal_potato.msg.obligation_countdown": "受罚倒数§a%d §f瞬",
@ -25,6 +31,14 @@
"sound.superleadrope.subtitle.lead_break": "索絕", "sound.superleadrope.subtitle.lead_break": "索絕",
"sound.superleadrope.subtitle.lead_tied": "繫索", "sound.superleadrope.subtitle.lead_tied": "繫索",
"sound.superleadrope.subtitle.lead_untied": "解索", "sound.superleadrope.subtitle.lead_untied": "解索",
"superleadrope.command.leash.message..get.block": "§7磚石: §e%s",
"superleadrope.command.leash.message..get.elastic": "§7彈距: §6%.1f",
"superleadrope.command.leash.message..get.keep": "§7持時: §c%d§7/§c%d",
"superleadrope.command.leash.message..get.max": "§7極距: §a%.1f",
"superleadrope.command.leash.message..get.reserved": "§7備註: §d%s",
"superleadrope.command.leash.message..get.title": "=== %s 之繫繩數據 ===",
"superleadrope.command.leash.message..get.total": "繫繩總數: %d",
"superleadrope.command.leash.message..get.uuid": "§7UUID: §b%s",
"superleadrope.command.motion.message.adder.successful": "§b增益既成.§a%s§7:§f[§e速勢§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r", "superleadrope.command.motion.message.adder.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.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"

View File

@ -1,9 +1,15 @@
{ {
"command.leashdata.addApplyEntity.success": "§b添加拴绳成功. §a%s §7→ §e%s",
"command.leashdata.removeApplyEntity.success": "§b移除拴绳成功. §a%s §7- §e%s",
"command.leashdata.setApplyEntity.success": "§b设置拴绳属性成功. §a%s §7: §e%s §7= §6%.1f",
"command.leashdata.transfer.success": "§b转移拴绳成功. §a%s §7→ §e%s §7→ §6%s",
"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 因使用非自己绑定物品,受到闪电惩罚!",
"entity.superleadrope.super_lead_knot": "超级拴绳结", "entity.superleadrope.super_lead_knot": "超级拴绳结",
"gamerule.slp.TeleportWithLeashedEntities": "被拴实体随玩家持有者传送", "gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent": "如果缺失则创建超级拴绳结",
"gamerule.slp.TeleportWithLeashedEntities.description": "传送时将被拴实体与持有者一起传送", "gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent.description": "如果在栅栏等支持处缺失超级拴绳结,则创建它",
"gamerule.SLP.TeleportWithLeashedEntities": "被拴实体随持有者传送",
"gamerule.SLP.TeleportWithLeashedEntities.description": "传送时将被拴实体与持有者一起传送",
"item.eternal_potato.msg.bind_msg": "§6已与你绑定成为全服共有之人。", "item.eternal_potato.msg.bind_msg": "§6已与你绑定成为全服共有之人。",
"item.eternal_potato.msg.cannot_drop": "§c永恒土豆是不可丢弃的惩罚数加%d", "item.eternal_potato.msg.cannot_drop": "§c永恒土豆是不可丢弃的惩罚数加%d",
"item.eternal_potato.msg.obligation_countdown": "惩罚倒计时: §a%d §f秒", "item.eternal_potato.msg.obligation_countdown": "惩罚倒计时: §a%d §f秒",
@ -25,6 +31,14 @@
"sound.superleadrope.subtitle.lead_break": "拴绳断裂", "sound.superleadrope.subtitle.lead_break": "拴绳断裂",
"sound.superleadrope.subtitle.lead_tied": "拴绳系上", "sound.superleadrope.subtitle.lead_tied": "拴绳系上",
"sound.superleadrope.subtitle.lead_untied": "拴绳解开", "sound.superleadrope.subtitle.lead_untied": "拴绳解开",
"superleadrope.command.leash.message..get.block": "§7方块: §e%s",
"superleadrope.command.leash.message..get.elastic": "§7弹性距离: §6%.1f",
"superleadrope.command.leash.message..get.keep": "§7保持: §c%d§7/§c%d",
"superleadrope.command.leash.message..get.max": "§7最大距离: §a%.1f",
"superleadrope.command.leash.message..get.reserved": "§7保留字段: §d%s",
"superleadrope.command.leash.message..get.title": "=== %s 的拴绳数据 ===",
"superleadrope.command.leash.message..get.total": "总拴绳数: %d",
"superleadrope.command.leash.message..get.uuid": "§7UUID: §b%s",
"superleadrope.command.motion.message.adder.successful": "§b添加成功.§a%s§7:§f[§e加速§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r", "superleadrope.command.motion.message.adder.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.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"

View File

@ -1,9 +1,15 @@
{ {
"command.leashdata.addApplyEntity.success": "§b添加拴繩成功. §a%s §7→ §e%s",
"command.leashdata.removeApplyEntity.success": "§b移除拴繩成功. §a%s §7- §e%s",
"command.leashdata.setApplyEntity.success": "§b設置拴繩屬性成功. §a%s §7: §e%s §7= §6%.1f",
"command.leashdata.transfer.success": "§b轉移拴繩成功. §a%s §7→ §e%s §7→ §6%s",
"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 因使用非自己綁定物品,受到閃電懲罰!",
"entity.superleadrope.super_lead_knot": "超級拴繩結", "entity.superleadrope.super_lead_knot": "超級拴繩結",
"gamerule.slp.TeleportWithLeashedEntities": "被拴实体随玩家持有者傳送", "gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent": "如果缺失則創建超級拴繩結",
"gamerule.slp.TeleportWithLeashedEntities.description": "將被拴实体將隨持有者一起傳送", "gamerule.SLP.CreateSuperLeashKnotEntityIfAbsent.description": "如果在柵欄等支持處缺失超級拴繩結,則創建它",
"gamerule.SLP.TeleportWithLeashedEntities": "被拴实体随持有者傳送",
"gamerule.SLP.TeleportWithLeashedEntities.description": "將被拴实体將隨持有者一起傳送",
"item.eternal_potato.msg.bind_msg": "§6已與你綁定成為全服共有之人。", "item.eternal_potato.msg.bind_msg": "§6已與你綁定成為全服共有之人。",
"item.eternal_potato.msg.cannot_drop": "§c永恆土豆不可丟棄懲罰數加%d", "item.eternal_potato.msg.cannot_drop": "§c永恆土豆不可丟棄懲罰數加%d",
"item.eternal_potato.msg.obligation_countdown": "懲罰倒計時: §a%d §f秒", "item.eternal_potato.msg.obligation_countdown": "懲罰倒計時: §a%d §f秒",
@ -25,6 +31,14 @@
"sound.superleadrope.subtitle.lead_break": "拴繩斷裂", "sound.superleadrope.subtitle.lead_break": "拴繩斷裂",
"sound.superleadrope.subtitle.lead_tied": "拴繩係上", "sound.superleadrope.subtitle.lead_tied": "拴繩係上",
"sound.superleadrope.subtitle.lead_untied": "拴繩解開", "sound.superleadrope.subtitle.lead_untied": "拴繩解開",
"superleadrope.command.leash.message..get.block": "§7方塊: §e%s",
"superleadrope.command.leash.message..get.elastic": "§7彈性距離: §6%.1f",
"superleadrope.command.leash.message..get.keep": "§7保持: §c%d§7/§c%d",
"superleadrope.command.leash.message..get.max": "§7最大距離: §a%.1f",
"superleadrope.command.leash.message..get.reserved": "§7保留字段: §d%s",
"superleadrope.command.leash.message..get.title": "=== %s 的拴繩數據 ===",
"superleadrope.command.leash.message..get.total": "總拴繩數: %d",
"superleadrope.command.leash.message..get.uuid": "§7UUID: §b%s",
"superleadrope.command.motion.message.adder.successful": "§b添加成功.§a%s§7:§f[§e加速§7:(§a%.2f§7,§a%.2f§7,§a%.2f§7)§f]§r", "superleadrope.command.motion.message.adder.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.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"

View File

@ -47,9 +47,9 @@ public class SuperLeashRenderer {
Matrix4f matrix = poseStack.last().pose(); Matrix4f matrix = poseStack.last().pose();
int blockLightStart = getBlockLight(BlockPos.containing(startWorld)); int blockLightStart = getBlockLight(BlockPos.containing(startWorld));
int blockLightEnd = getBlockLight(BlockPos.containing(endWorld)); int blockLightEnd = getBlockLight(state.isFirstPerson() ? state.belowBlockPos() : (BlockPos.containing(endWorld)));
int skyLightStart = getSkyLight(BlockPos.containing(startWorld)); int skyLightStart = 15; //getSkyLight(BlockPos.containing(startWorld));
int skyLightEnd = getSkyLight(BlockPos.containing(endWorld)); int skyLightEnd = 15; //getSkyLight(BlockPos.containing(endWorld));
// 差向量 + 偏移 // 差向量 + 偏移
Offsets offsets = computeOffsets(startWorld, endWorld); Offsets offsets = computeOffsets(startWorld, endWorld);

View File

@ -21,11 +21,9 @@ import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import top.r3944realms.superleadrope.SuperLeadRope; import org.jetbrains.annotations.NotNull;
import top.r3944realms.superleadrope.client.renderer.state.SuperLeashRenderState; import top.r3944realms.superleadrope.client.renderer.state.SuperLeashRenderState;
import top.r3944realms.superleadrope.content.capability.impi.LeashDataImpl;
import top.r3944realms.superleadrope.content.capability.inter.ILeashData; import top.r3944realms.superleadrope.content.capability.inter.ILeashData;
import top.r3944realms.superleadrope.content.capability.inter.ILeashState; import top.r3944realms.superleadrope.content.capability.inter.ILeashState;
import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity; import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity;
@ -64,19 +62,19 @@ public class SuperLeashStateResolver {
ILeashState.LeashState leashState = leashStateOpt.get(); ILeashState.LeashState leashState = leashStateOpt.get();
// 计算实体端偏移 // 计算实体端偏移
Vec3 currentEntityOffset = getEntityLeashOffset(leashedEntity, leashState, partialTicks); Vec3 currentEntityOffset = getEntityLeashOffset(leashedEntity, leashState);
// 计算持有者端偏移 // 计算持有者端偏移
Vec3 holderOffset = getHolderOffset(holder, leashState); Vec3 holderOffset = getHolderOffset(holder, leashState);
boolean isFirstPerson = Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON;
// 获取插值后的位置 // 获取插值后的位置
Vec3 currentHolderPos; Vec3 currentHolderPos;
if (holder instanceof Player player) { if (holder instanceof Player player) {
// 玩家手部偏移 + 旋转矩阵第一人称/第三人称都适用 // 玩家手部偏移 + 旋转矩阵第一人称适用
if (Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON) { if (isFirstPerson && player == Minecraft.getInstance().player) {
currentHolderPos = getFirstPersonLeashPos(player, partialTicks); currentHolderPos = getFirstPersonLeashPos(player, partialTicks);
} else { } else {
currentHolderPos = getEntityLeashHolderPos(player, holderOffset, partialTicks); currentHolderPos = getEntityLeashHolderPos(player, (Minecraft.getInstance().player == holder) ? holderOffset : holderOffset.add(0,0,0.4), partialTicks);
} }
} else if (holder instanceof SuperLeashKnotEntity) { } else if (holder instanceof SuperLeashKnotEntity) {
@ -85,8 +83,7 @@ public class SuperLeashStateResolver {
// 普通实体偏移 + 插值 + 旋转 // 普通实体偏移 + 插值 + 旋转
currentHolderPos = getEntityLeashHolderPos(holder, holderOffset, partialTicks); currentHolderPos = getEntityLeashHolderPos(holder, holderOffset, partialTicks);
} }
Vec3 currentEntityPos = getInterpolatedPosition(leashedEntity, partialTicks) Vec3 currentEntityPos = applyOffsetWithRotation(leashedEntity, currentEntityOffset, partialTicks);
.add(currentEntityOffset);
// 上一帧缓存 // 上一帧缓存
FrameCache cache = frameCacheMap.get(leashedEntity.getUUID()); FrameCache cache = frameCacheMap.get(leashedEntity.getUUID());
@ -123,42 +120,21 @@ public class SuperLeashStateResolver {
selectColor(tension, isCritical), selectColor(tension, isCritical),
THICKNESS_BASE + tension * THICKNESS_TENSION, THICKNESS_BASE + tension * THICKNESS_TENSION,
swing.angle(), swing.speed(), swing.angle(), swing.speed(),
(float) leashInfo.maxDistance() (float) leashInfo.maxDistance(),
isFirstPerson, holder.blockPosition()
)); ));
} }
/* ------------------------ 实体偏移计算 ------------------------ */ /* ------------------------ 实体偏移计算 ------------------------ */
private static Vec3 getEntityLeashOffset(Entity entity, ILeashState.LeashState leashState, float partialTicks) { private static @NotNull Vec3 getEntityLeashOffset(Entity entity, ILeashState.@NotNull LeashState leashState) {
// 获取实体自身的 LeashState 偏移
Optional<ILeashState> entityStateOpt = LeashStateAPI.getLeashState(entity); Optional<ILeashState> entityStateOpt = LeashStateAPI.getLeashState(entity);
Vec3 baseOffset = entityStateOpt Vec3 baseOffset = entityStateOpt
.map(eState -> eState.getLeashApplyEntityLocationOffset() .map(eState -> eState.getLeashApplyEntityLocationOffset()
.orElse(eState.getDefaultLeashApplyEntityLocationOffset())) .orElse(eState.getDefaultLeashApplyEntityLocationOffset()))
.orElse(Vec3.ZERO); .orElse(Vec3.ZERO);
return baseOffset.add(leashState.applyEntityLocationOffset());
// 加上单条绳子的额外偏移
baseOffset = baseOffset.add(leashState.applyEntityLocationOffset());
// 获取旋转角度
float pitch = Mth.lerp(partialTicks, entity.getXRot(), entity.xRotO) * ((float)Math.PI / 180F);
float yaw = Mth.lerp(partialTicks, entity.getYRot(), entity.yRotO) * ((float)Math.PI / 180F);
float roll = 0f;
// 玩家特殊处理飞行/旋转攻击可能需要 roll
if (entity instanceof Player player && (player.isFallFlying() || player.isAutoSpinAttack())) {
Vec3 view = player.getViewVector(partialTicks);
Vec3 motion = player.getDeltaMovement();
double motionLenSq = motion.horizontalDistanceSqr();
double viewLenSq = view.horizontalDistanceSqr();
if (motionLenSq > 0 && viewLenSq > 0) {
double dot = (motion.x * view.x + motion.z * view.z) / Math.sqrt(motionLenSq * viewLenSq);
double cross = motion.x * view.z - motion.z * view.x;
roll = (float)(Math.signum(cross) * Math.acos(dot));
}
}
// 将偏移从局部坐标转换到世界坐标
return baseOffset.xRot(-pitch).yRot(-yaw).zRot(-roll);
} }
private static Vec3 getHolderOffset(Entity holder, ILeashState.LeashState leashState) { private static Vec3 getHolderOffset(Entity holder, ILeashState.LeashState leashState) {
if (LeashStateAPI.Query.hasLeashState(holder)) { if (LeashStateAPI.Query.hasLeashState(holder)) {
@ -172,94 +148,91 @@ public class SuperLeashStateResolver {
return Optional.ofNullable(leashState.holderLocationOffset()) return Optional.ofNullable(leashState.holderLocationOffset())
.orElse(leashState.defaultHolderLocationOffset()); .orElse(leashState.defaultHolderLocationOffset());
} }
private static boolean holderHasLeashState(Entity holder) { /**
if (LeashStateAPI.Query.hasLeashState(holder)) { * 将局部偏移向量应用到实体旋转返回世界坐标位置
Optional<ILeashState> holderStateOpt = LeashStateAPI.getLeashState(holder); * @param entity 实体
return holderStateOpt.isPresent(); * @param localOffset 局部偏移相对于实体局部坐标系
* @param partialTicks 插值参数
* @return 偏移旋转后的世界坐标位置
*/
public static @NotNull Vec3 applyOffsetWithRotation(Entity entity, Vec3 localOffset, float partialTicks) {
// 实体中心位置
Vec3 centerPos = getInterpolatedPosition(entity, partialTicks);
// 旋转角度
// float pitch = Mth.lerp(partialTicks, entity.getXRot(), entity.xRotO) * ((float)Math.PI / 180F);
float yaw = Mth.lerp(partialTicks, entity.getYRot(), entity.yRotO) * ((float)Math.PI / 180F);
float roll = 0f;
if (entity instanceof Player player && (player.isFallFlying() || player.isAutoSpinAttack())) {
roll = getRoll(player, partialTicks, roll);
} }
return false;
// 应用旋转到局部偏移
Vec3 rotatedOffset = localOffset.yRot(-yaw).zRot(-roll);
// 返回世界坐标
return centerPos.add(rotatedOffset);
} }
/** /**
* 获取玩家挂点位置支持旋转偏移 * 获取玩家挂点位置支持旋转偏移
*/ */
private static Vec3 getFirstPersonLeashPos(Player player, float partialTicks) { private static @NotNull Vec3 getFirstPersonLeashPos(@NotNull Player player, float partialTicks) {
// 插值旋转角度 // 插值旋转角度
float yaw = Mth.lerp(partialTicks, player.yRotO, player.getYRot()) * ((float)Math.PI / 180F); float yaw = Mth.lerp(partialTicks, player.yRotO, player.getYRot()) * ((float)Math.PI / 180F);
float pitch = Mth.lerp(partialTicks, player.xRotO, player.getXRot()) * ((float)Math.PI / 180F); // float pitch = Mth.lerp(partialTicks, player.xRotO, player.getXRot()) * ((float)Math.PI / 180F);
float roll = 0f; float roll = 0f;
// 计算 roll飞行或旋转攻击时 // 计算 roll飞行或旋转攻击时
if (player.isFallFlying() || player.isAutoSpinAttack()) { if (player.isFallFlying() || player.isAutoSpinAttack()) {
Vec3 view = player.getViewVector(partialTicks); roll = getRoll(player, partialTicks, roll);
Vec3 motion = player.getDeltaMovement();
double motionLenSq = motion.horizontalDistanceSqr();
double viewLenSq = view.horizontalDistanceSqr();
if (motionLenSq > 0 && viewLenSq > 0) {
double dot = (motion.x*view.x + motion.z*view.z) / Math.sqrt(motionLenSq*viewLenSq);
double cross = motion.x*view.z - motion.z*view.x;
roll = (float)(Math.signum(cross) * Math.acos(dot));
}
} }
// 手部偏移 // 手部偏移
double side = player.getMainArm() == HumanoidArm.RIGHT ? -1.0D : 1.0D; double side = player.getMainArm() == HumanoidArm.RIGHT ? -1.0D : 1.0D;
Vec3 localPos = new Vec3(0.39D * side, -0.6D, 0.3D); Vec3 localPos = new Vec3(0.39D * side, -0.6D, -0.5D);
// 局部坐标旋转到世界坐标 // 局部坐标旋转到世界坐标
Vec3 rotatedPos = localPos.xRot(-pitch).yRot(-yaw).zRot(-roll); Vec3 rotatedPos = localPos.yRot(-yaw).zRot(-roll);
// 返回世界坐标玩家眼睛位置 + 手部旋转偏移 // 返回世界坐标玩家眼睛位置 + 手部旋转偏移
return player.getEyePosition(partialTicks).add(rotatedPos); return player.getEyePosition(partialTicks).add(rotatedPos);
} }
private static float getRoll(@NotNull Player player, float partialTicks, float roll) {
Vec3 view = player.getViewVector(partialTicks);
Vec3 motion = player.getDeltaMovement();
double motionLenSq = motion.horizontalDistanceSqr();
double viewLenSq = view.horizontalDistanceSqr();
if (motionLenSq > 0 && viewLenSq > 0) {
double dot = (motion.x*view.x + motion.z*view.z) / Math.sqrt(motionLenSq*viewLenSq);
double cross = motion.x*view.z - motion.z*view.x;
roll = (float)(Math.signum(cross) * Math.acos(dot));
}
return roll;
}
/** /**
* 获取实体挂点位置支持旋转偏移 * 获取实体挂点位置支持旋转偏移
*/ */
public static Vec3 getEntityLeashHolderPos(Entity entity, Vec3 baseOffset, float partialTicks) { public static Vec3 getEntityLeashHolderPos(Entity entity, Vec3 baseOffset, float partialTicks) {
// 从眼睛位置头部开始
Vec3 pos = entity.getEyePosition(partialTicks);
Vec3 pos = entity.getPosition(partialTicks);
double xOffset = baseOffset.x(); double xOffset = baseOffset.x();
double yOffset = baseOffset.y(); double yOffset = baseOffset.y();
double zOffset = baseOffset.z(); double zOffset = baseOffset.z();
float pitch = Mth.lerp(partialTicks, entity.getXRot(), entity.xRotO) * ((float)Math.PI / 180F);
float yaw = Mth.lerp(partialTicks, entity.getYRot(), entity.yRotO) * ((float)Math.PI / 180F); float yaw = Mth.lerp(partialTicks, entity.getYRot(), entity.yRotO) * ((float)Math.PI / 180F);
if (entity instanceof Player player) { if (entity instanceof Player player) {
xOffset *= player.getMainArm() == HumanoidArm.RIGHT ? -1.0D : 1.0D; xOffset += 0.19D * (player.getMainArm() == HumanoidArm.RIGHT ? -1.0D : 1.0D);
if (!player.isFallFlying() && !player.isAutoSpinAttack()) {
if (player.isVisuallySwimming()) {
pos = pos.add(new Vec3(xOffset, 0.2D, -0.15D).xRot(-pitch).yRot(-yaw));
} else {
double yBase = player.getBoundingBox().getYsize() - 1.0D;
double yAdjust = player.isCrouching() ? -0.2D : 0.07D;
pos = pos.add(new Vec3(xOffset, yBase, yAdjust).yRot(-yaw));
}
} else {
Vec3 view = player.getViewVector(partialTicks);
Vec3 motion = player.getDeltaMovement();
float roll = computeRoll(view, motion);
pos = pos.add(new Vec3(xOffset, -0.11D, 0.85D).zRot(-roll).xRot(-pitch).yRot(-yaw));
}
} else {
double yBase = entity.getBbHeight() * 0.5 + yOffset;
pos = pos.add(new Vec3(xOffset, yBase, zOffset).yRot(-yaw).xRot(-pitch));
} }
// 直接在头部位置应用偏移不管手飞行游泳
pos = pos.add(new Vec3(xOffset, yOffset, zOffset).yRot(-yaw));
return pos; return pos;
} }
private static float computeRoll(Vec3 view, Vec3 motion) {
double d1 = motion.horizontalDistanceSqr();
double d2 = view.horizontalDistanceSqr();
if (d1 > 0.0 && d2 > 0.0) {
double dot = (motion.x * view.x + motion.z * view.z) / Math.sqrt(d1 * d2);
double cross = motion.x * view.z - motion.z * view.x;
return (float)(Math.signum(cross) * Math.acos(dot));
}
return 0.0F;
}
private static Vec3 getInterpolatedPosition(Entity entity, float partialTicks) { private static Vec3 getInterpolatedPosition(Entity entity, float partialTicks) {
return entity.getEyePosition(partialTicks); return entity.getEyePosition(partialTicks);
} }
@ -276,13 +249,13 @@ public class SuperLeashStateResolver {
Vec3 cross = lastDir.cross(currentDir); Vec3 cross = lastDir.cross(currentDir);
float angleChange = (float) Math.acos(Math.min(1.0, lastDir.dot(currentDir))); float angleChange = (float) Math.acos(Math.min(1.0, lastDir.dot(currentDir)));
angleChange *= Math.signum(cross.y); angleChange *= (float) Math.signum(cross.y);
float newSpeed = lastSpeed * 0.9f + angleChange * 0.5f * tension; float newSpeed = lastSpeed * 0.9f + angleChange * 0.5f * tension;
float newAngle = lastAngle + newSpeed; float newAngle = lastAngle + newSpeed;
if (tension > 0.3f) { if (tension > 0.3f) {
newSpeed += (Math.random() - 0.5) * 0.05 * tension; newSpeed += (float) ((Math.random() - 0.5) * 0.05 * tension);
} }
return new SwingDynamics(newAngle, newSpeed); return new SwingDynamics(newAngle, newSpeed);
@ -301,27 +274,4 @@ public class SuperLeashStateResolver {
return tension > 0.7f ? SuperLeashRenderState.COLOR_TENSION : SuperLeashRenderState.COLOR_NORMAL; return tension > 0.7f ? SuperLeashRenderState.COLOR_TENSION : SuperLeashRenderState.COLOR_NORMAL;
} }
/* ------------------------ 批量解析 ------------------------ */
public static List<SuperLeashRenderState> resolveAll(Entity leashedEntity,
LeashDataImpl leashData, float partialTicks) {
List<SuperLeashRenderState> states = new ArrayList<>();
Level level = leashedEntity.level();
for (ILeashData.LeashInfo leashInfo : leashData.getAllLeashes()) {
Entity holder = null;
if (leashInfo.blockPosOpt().isEmpty() && leashInfo.holderIdOpt().isPresent()){
holder = level.getEntity(leashInfo.holderIdOpt().get());
} else if (leashInfo.blockPosOpt().isPresent()) {
holder = SuperLeashKnotEntity.getOrCreateKnot(level, leashInfo.blockPosOpt().get());
}
if (holder != null) {
resolve(holder, leashedEntity, leashInfo, partialTicks)
.ifPresent(states::add);
} else SuperLeadRope.logger.error("Holder not found for leash of " + leashedEntity);
}
return states;
}
} }

View File

@ -15,6 +15,7 @@
package top.r3944realms.superleadrope.client.renderer.state; package top.r3944realms.superleadrope.client.renderer.state;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
public record SuperLeashRenderState( public record SuperLeashRenderState(
@ -30,7 +31,9 @@ public record SuperLeashRenderState(
float thickness, // 线宽(根据张力变化) float thickness, // 线宽(根据张力变化)
float swingAngle, // 当前摆动角度(弧度) float swingAngle, // 当前摆动角度(弧度)
float swingSpeed, // 摆动速度(弧度/tick) float swingSpeed, // 摆动速度(弧度/tick)
float maxDistance // 最大距离 float maxDistance, // 最大距离
boolean isFirstPerson, // 是否是第一人称
BlockPos belowBlockPos // 持有者位置
) { ) {
// 预定义颜色常量 // 预定义颜色常量
public static final int COLOR_NORMAL = 0xFF6B4E2E; // 深棕色木绳色温暖自然 public static final int COLOR_NORMAL = 0xFF6B4E2E; // 深棕色木绳色温暖自然

View File

@ -0,0 +1,30 @@
/*
* Super Lead rope mod
* Copyright (C) 2025 R3944Realms
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package top.r3944realms.superleadrope.compat;
import dev.dubhe.curtain.features.player.patches.EntityPlayerMPFake;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.fml.ModList;
public class CurtainCompat {
public final static boolean isModLoaded = ModList.get().isLoaded("curtain");
public static boolean isNotFakePlayer(Player player) {
if (isModLoaded) {
return !(player instanceof EntityPlayerMPFake);
}
return true;
}
}

View File

@ -113,7 +113,8 @@ public class LeashCommonConfig {
.defineListAllowEmpty( .defineListAllowEmpty(
List.of("defaultApplyEntityLocationOffset"), List.of("defaultApplyEntityLocationOffset"),
List.of( List.of(
"vec3(0,-0.5,0) : [*]", "vec3(0,-0.42,0) : [minecraft:player]" "vec3(0,-0.2,0) : [*]",
"vec3(0,-0.22,-0.2) : [minecraft:player]"
), ),
o -> o instanceof String s && isValidOffsetRefFormat(s) o -> o instanceof String s && isValidOffsetRefFormat(s)
); );
@ -130,13 +131,14 @@ public class LeashCommonConfig {
" - #modid : all entities from a mod (e.g. #minecraft)", " - #modid : all entities from a mod (e.g. #minecraft)",
" - * : all entities", " - * : all entities",
"Multiple entries can be separated by commas", "Multiple entries can be separated by commas",
"Example: vec3(0,1.5,0) : [minecraft:player]", "Example: vec3(0,-0.5,0) : [minecraft:player]",
"Priority order: specific entity > tag > mod > *" "Priority order: specific entity > tag > mod > *"
) )
.defineListAllowEmpty( .defineListAllowEmpty(
List.of("defaultHolderLocationOffset"), List.of("defaultHolderLocationOffset"),
List.of( List.of(
"vec3(0,-0.5,0) : [*]" "vec3(0,-0.2,0) : [*]",
"vec3(0,-0.6,0) : [minecraft:player]"
), ),
o -> o instanceof String s && isValidOffsetRefFormat(s) o -> o instanceof String s && isValidOffsetRefFormat(s)
); );

View File

@ -38,6 +38,7 @@ import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import top.r3944realms.superleadrope.CommonEventHandler; import top.r3944realms.superleadrope.CommonEventHandler;
import top.r3944realms.superleadrope.SuperLeadRope; import top.r3944realms.superleadrope.SuperLeadRope;
import top.r3944realms.superleadrope.compat.CurtainCompat;
import top.r3944realms.superleadrope.content.capability.inter.ILeashData; import top.r3944realms.superleadrope.content.capability.inter.ILeashData;
import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity; import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity;
import top.r3944realms.superleadrope.core.register.SLPSoundEvents; import top.r3944realms.superleadrope.core.register.SLPSoundEvents;
@ -489,7 +490,7 @@ public class LeashDataImpl implements ILeashData {
if (hasForce) { if (hasForce) {
// 处理玩家和其他实体 // 处理玩家和其他实体
if (finalApplyEntity instanceof ServerPlayer player) { if (finalApplyEntity instanceof ServerPlayer player && CurtainCompat.isNotFakePlayer(player)) {
RindingLeash.applyForceToPlayer(player, combinedForce); RindingLeash.applyForceToPlayer(player, combinedForce);
} else { } else {
finalApplyEntity.setDeltaMovement(finalApplyEntity.getDeltaMovement().add(combinedForce)); finalApplyEntity.setDeltaMovement(finalApplyEntity.getDeltaMovement().add(combinedForce));

View File

@ -337,7 +337,7 @@ public class LeashStateImpl implements ILeashState {
@Override @Override
public void copy(ILeashState other, Entity newEntity) { public void copy(ILeashState other, Entity newEntity) {
this.entity = newEntity; this.entity = newEntity;
this.defaultApplyEntityLocationOffset = other.getDefaultLeashApplyEntityLocationOffset(); this.defaultApplyEntityLocationOffset = CommonEventHandler.leashConfigManager.getDefaultEntityOffset(newEntity);
this.staticApplyEntityLocationOffset = other.getLeashApplyEntityLocationOffset().orElse(null); this.staticApplyEntityLocationOffset = other.getLeashApplyEntityLocationOffset().orElse(null);
} }

View File

@ -282,7 +282,7 @@ public class LeashDataCommand {
} }
} }
} }
public static final String SET_MAX_DISTANCE = SLP_LEASH_MESSAGE_ + "setApplyEntity.max_distance"; public static final String SET_MAX_DISTANCE = SLP_LEASH_MESSAGE_ + "set_apply_entity.max_distance";
private static int setMaxDistance(CommandContext<CommandSourceStack> context) throws CommandSyntaxException { private static int setMaxDistance(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
return setMaxDistance(context, CommonEventHandler.leashConfigManager.getMaxLeashLength(), ""); return setMaxDistance(context, CommonEventHandler.leashConfigManager.getMaxLeashLength(), "");
} }
@ -297,11 +297,11 @@ public class LeashDataCommand {
} }
return -1; return -1;
} }
public static final String REMOVE_ALL_BLOCK_LEASHES = SLP_LEASH_MESSAGE_ + "removeApplyEntity.all_block_leashes"; public static final String REMOVE_ALL_BLOCK_LEASHES = SLP_LEASH_MESSAGE_ + "remove_apply_entity.all_block_leashes";
private static int removeAllBlockLeashes(CommandContext<CommandSourceStack> context) throws CommandSyntaxException { private static int removeAllBlockLeashes(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
return -1; return -1;
} }
public static final String REMOVE_ALL_HOLDER_LEASHES = SLP_LEASH_MESSAGE_ + "removeApplyEntity.all_holder_leashes"; public static final String REMOVE_ALL_HOLDER_LEASHES = SLP_LEASH_MESSAGE_ + "remove_apply_entity.all_holder_leashes";
private static int removeAllHolderLeashes(CommandContext<CommandSourceStack> context) throws CommandSyntaxException { private static int removeAllHolderLeashes(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
return -1; return -1;
} }
@ -312,7 +312,7 @@ public class LeashDataCommand {
private static int transferFromBlock(CommandContext<CommandSourceStack> context, String reserved) throws CommandSyntaxException { private static int transferFromBlock(CommandContext<CommandSourceStack> context, String reserved) throws CommandSyntaxException {
return -1; return -1;
} }
public static final String SET_ELASTIC_DISTANCE = SLP_LEASH_MESSAGE_ + "setApplyEntity.elastic_distance"; public static final String SET_ELASTIC_DISTANCE = SLP_LEASH_MESSAGE_ + "set_apply_entity.elastic_distance";
private static int setElasticDistance(CommandContext<CommandSourceStack> context) throws CommandSyntaxException { private static int setElasticDistance(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
return setElasticDistance(context, 0 ,""); return setElasticDistance(context, 0 ,"");
} }
@ -322,7 +322,7 @@ public class LeashDataCommand {
private static int setElasticDistance(CommandContext<CommandSourceStack> context, int keepTicks, String reserved) throws CommandSyntaxException { private static int setElasticDistance(CommandContext<CommandSourceStack> context, int keepTicks, String reserved) throws CommandSyntaxException {
return -1; return -1;
} }
public static final String SET_BLOCK_MAX_DISTANCE = SLP_LEASH_MESSAGE_ + "setApplyEntity.block_max_distance"; public static final String SET_BLOCK_MAX_DISTANCE = SLP_LEASH_MESSAGE_ + "set_apply_entity.block_max_distance";
private static int setBlockMaxDistance(CommandContext<CommandSourceStack> context) throws CommandSyntaxException { private static int setBlockMaxDistance(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
return setBlockMaxDistance(context, 0 ,""); return setBlockMaxDistance(context, 0 ,"");
} }
@ -332,7 +332,7 @@ public class LeashDataCommand {
private static int setBlockMaxDistance(CommandContext<CommandSourceStack> context, int keepTicks, String reserved) throws CommandSyntaxException { private static int setBlockMaxDistance(CommandContext<CommandSourceStack> context, int keepTicks, String reserved) throws CommandSyntaxException {
return -1; return -1;
} }
public static final String SET_BLOCK_ELASTIC_DISTANCE = SLP_LEASH_MESSAGE_ + "setApplyEntity.block_elastic_distance"; public static final String SET_BLOCK_ELASTIC_DISTANCE = SLP_LEASH_MESSAGE_ + "set_apply_entity.block_elastic_distance";
private static int setBlockElasticDistance(CommandContext<CommandSourceStack> context) throws CommandSyntaxException { private static int setBlockElasticDistance(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
return setBlockElasticDistance(context, 0 ,""); return setBlockElasticDistance(context, 0 ,"");
} }
@ -351,6 +351,7 @@ public class LeashDataCommand {
for (Entity target : targets) { for (Entity target : targets) {
Collection<ILeashData.LeashInfo> leashes = LeashDataAPI.QueryOperations.getAllLeashes(target); Collection<ILeashData.LeashInfo> leashes = LeashDataAPI.QueryOperations.getAllLeashes(target);
// +++
source.sendSuccess(() -> Component.literal("=== Leash Data for " + target.getName().getString() + " ==="), false); source.sendSuccess(() -> Component.literal("=== Leash Data for " + target.getName().getString() + " ==="), false);
source.sendSuccess(() -> Component.literal("Total leashes: " + leashes.size()), false); source.sendSuccess(() -> Component.literal("Total leashes: " + leashes.size()), false);

View File

@ -24,7 +24,7 @@ public class SLPGamerules {
public static final SLPGameruleRegistry GAMERULE_REGISTRY = SLPGameruleRegistry.INSTANCE; public static final SLPGameruleRegistry GAMERULE_REGISTRY = SLPGameruleRegistry.INSTANCE;
public static final HashMap<String, Boolean> gamerulesBooleanValuesClient = new HashMap<>(); public static final HashMap<String, Boolean> gamerulesBooleanValuesClient = new HashMap<>();
public static final HashMap<String, Integer> gameruleIntegerValuesClient = new HashMap<>(); public static final HashMap<String, Integer> gameruleIntegerValuesClient = new HashMap<>();
public static final String RULE_KEY_PERFiX_ = "gamerule." + GAMERULE_PREFIX.toLowerCase(); public static final String RULE_KEY_PERFiX_ = "gamerule." + GAMERULE_PREFIX;
public static String getDescriptionKey(Class<?> gameRuleClass) { public static String getDescriptionKey(Class<?> gameRuleClass) {
return RULE_KEY_PERFiX_ + gameRuleClass.getSimpleName() + ".description"; return RULE_KEY_PERFiX_ + gameRuleClass.getSimpleName() + ".description";
} }

View File

@ -19,6 +19,7 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import top.r3944realms.superleadrope.content.gamerule.SLPGamerules; import top.r3944realms.superleadrope.content.gamerule.SLPGamerules;
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 java.util.HashMap; import java.util.HashMap;
@ -63,7 +64,7 @@ public enum SLPGameruleRegistry {
gameruleDataTypes.put(gameruleName, RuleDataType.BOOLEAN); gameruleDataTypes.put(gameruleName, RuleDataType.BOOLEAN);
} }
public void registerGamerule(String gameruleName, GameRules.Category category, int pDefault) { public void registerGamerule(String gameruleName, GameRules.Category category, int pDefault) {
registerGamerule(gameruleName, category, pDefault, (BiConsumer<MinecraftServer, GameRules.IntegerValue>) (s, i)->{});//最后一个仅占位无用 registerGamerule(gameruleName, category, pDefault, (s, i)->{});//最后一个仅占位无用
} }
public void registerGamerule(String gameruleName, GameRules.Category category, int pDefault, BiConsumer<MinecraftServer, GameRules.IntegerValue> pChangeListener) { public void registerGamerule(String gameruleName, GameRules.Category category, int pDefault, BiConsumer<MinecraftServer, GameRules.IntegerValue> pChangeListener) {
gamerules.put(gameruleName, GameRules.register(gameruleName, category, GameRules.IntegerValue.create(pDefault, pChangeListener))); gamerules.put(gameruleName, GameRules.register(gameruleName, category, GameRules.IntegerValue.create(pDefault, pChangeListener)));
@ -71,6 +72,7 @@ public enum SLPGameruleRegistry {
} }
public static void register() { public static void register() {
TeleportWithLeashedEntities.register(); TeleportWithLeashedEntities.register();
CreateSuperLeashKnotEntityIfAbsent.register();
} }
} }

View File

@ -206,9 +206,9 @@ public enum SLPLangKeyValue {
), ),
TELEPORT_WITH_LEASHED_ENTITIES_NAME( TELEPORT_WITH_LEASHED_ENTITIES_NAME(
TeleportWithLeashedEntities.NAME_KEY, ModPartEnum.GAME_RULE, TeleportWithLeashedEntities.NAME_KEY, ModPartEnum.GAME_RULE,
"Teleport leashed player with player holder", "Teleport leashed player with holder",
"被拴实体随玩家持有者传送", "被拴实体随持有者传送",
"被拴实体随玩家持有者傳送", "被拴实体随持有者傳送",
"繫畜隨持者傳送" "繫畜隨持者傳送"
), ),
CREATE_SUPER_LEASH_KNOT_ENTITY_IF_ABSENT_NAME( CREATE_SUPER_LEASH_KNOT_ENTITY_IF_ABSENT_NAME(