Compare commits

..

36 Commits

Author SHA1 Message Date
6f69a24ed4 202/01/03
Some checks failed
Build / build (push) Failing after 1h8m30s
4.0.0.3->4.0.0.4
1.填完了对JEI适配的坑
(希望是Teacon的)最后一个版本
2.修补可能会存在的问题
2025-01-03 22:00:58 +08:00
8490da915d 2024/12/16
4.0.0.2->4.0.0.3
2024-12-16 23:59:38 +08:00
ab54ed1521 2024/12/15
消息小调整
2024-12-16 23:56:15 +08:00
cf930334cb 2024/12/15
更新版本 4.0.0.1 -> 4.0.0.2
修复了
1.小纰漏(
2024-12-16 23:52:17 +08:00
0b5b011eb8 2024/12/16
更新版本 4.0.0.0 -> 4.0.0.1
修复了
1.第三者不可见拴绳箭的问题
调整了
1.拴绳调整消息为调整双方都可见
2024-12-16 23:10:37 +08:00
24af58d4a4 2024/12/15
更新版本 3.9.9.9 -> 4.0.0
修复了
1.创造模式不能正确拾取先前发射的拴绳箭的BUG
2.发射器里的拴绳箭不能正常关注的问题
2024-12-15 17:53:29 +08:00
8b759259ad 2024/12/07
修复发射器发射拴绳类箭矢拾取时数量直接copy发射器里的数量的BUG
2024-12-07 17:10:55 +08:00
0ecfe88683 2024/12/07
修复些可能会存在的问题
2024-12-07 13:46:04 +08:00
22fc64797d 2024/12/07
实装了贴贴拴绳箭的内容
整理了下代码结构
先推测试
2024-12-07 13:33:46 +08:00
f10221a2c0 2024/12/07
实装了贴贴拴绳箭的内容
整理了下代码结构
先推测试
2024-12-07 13:33:39 +08:00
e615fc6f09 2024/12/03
小修复
2024-12-03 10:53:36 +08:00
d53481150a 2024/12/01
小更新
修改长时间不动掉落物
2024-12-01 11:05:26 +08:00
800a60ab97 2024/11/26
联动内容#3
增加一些提示内容
添加了按键
2024-11-27 00:25:37 +08:00
52f30a4275 2024/11/26
联动内容#2
增加一些提示内容
2024-11-26 17:21:15 +08:00
b6cbcdd677 2024/11/25
提升版本号,联动内容#1
2024-11-26 07:30:49 +08:00
78c92d4e42 2024/11/24
修改了下+2
2024-11-24 22:09:08 +08:00
8e0c06f392 2024/11/24
修改了下
2024-11-24 19:53:13 +08:00
094143c522 2024/11/24
修改了下
2024-11-24 18:36:45 +08:00
c80f53d5c9 2024/11/23
进一步完善了一下
2024-11-23 19:30:26 +08:00
f81569bde3 2024/11/23
搞了一个TOP检测关闭GUI
2024-11-23 16:16:19 +08:00
eedf4b64cf 2024/11/23
搞了一个TOP检测
和重命名了
2024-11-23 11:49:24 +08:00
ce337667dc 2024/11/22
好玩(
2024-11-22 17:50:55 +08:00
00eb0e8d68 2024/11/17
修复了部分纰漏
2024-11-17 11:53:26 +08:00
f416520f5d 2024/11/16
补充了一些内容
2024-11-16 17:55:39 +08:00
db41f395f7 2024/11/11
優化了彩蛋物品的獲取方式
2024-11-11 17:40:36 +08:00
6c9f27041d 2024/11/11
添加了彩蛋物品的獲取方式
2024-11-11 13:56:19 +08:00
087f203e00 2024/11/11
修复成就BUG
添加了种新的拴绳药水箭的合成方式:药水箭+拴绳
2024-11-11 00:55:55 +08:00
17134e0d84 2024/11/11
修复成就BUG
添加了种新的拴绳药水箭的合成方式:药水箭+拴绳
2024-11-11 00:54:07 +08:00
e236e4a718 2024/11/08
优化部分逻辑
扩展了新的箭矢
添加了使用时的音效
2024-11-08 22:09:13 +08:00
7f8b24beb8 2024/11/05
Expend Item Capacity
2024-11-05 23:07:42 +08:00
7d0ae3beef 2024/11/02
Update version
2024-11-03 13:49:24 +08:00
6471f956fa 2024/11/02
Add New Entity
2024-11-03 12:37:33 +08:00
3cb1cc3ccc 2024/11/02
Fix some little bug
Add areaTalk Command
2024-11-02 23:25:07 +08:00
6fcdbefe61 2024/11/01
Up
2024-11-01 07:41:27 +08:00
b4f592be46 2024/11/01
Fix some BUG and Add new Item to break lead rope
2024-11-01 00:13:56 +08:00
0cce76511f 2024-10-28
修复了有关箭不能正常显示的BUG
将默认值调高减少拴绳断裂的可能性
2024/10/28
Fix some BUG
2024-10-28 22:47:18 +08:00
150 changed files with 2762 additions and 1438 deletions

View File

@ -1,38 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -1,4 +1,4 @@
# 版本 1.21.3 0.0.3.9.9
# 版本 0.0.4.0.4 提前介绍c[没有BUG的话TeaCon最终版本将会是0.0.4] 【注意:本解釋簡繁混寫,因爲趕時間,所以並不怎麽規範,請諒解】
## 简介
现在开始你可以用拴绳拴住玩家,也可以拴住自己了,不如尝试拴住彼此来通关我的世界吧(
@ -15,11 +15,11 @@
4. 拴绳箭最大存活时间
## 新物品 和 实体
### 拴绳箭 [有普通和荧光种箭矢]
### 拴绳箭 [有普通和荧光和药水三种箭矢]
获得飞一样的感觉(操作不当可能会摔死
+ 拴绳箭可以拴其它可拴LivingEntity了
### 紫水晶剪刀
剪断拴绳链接,在发射器里可使用
剪断拴绳链接,在发射器里可使用,对自己也可使用,但耗费更多耐久
#### 射中实体时会将射击者拴绳绑定在改实体上该实体父类必须是有LivingEntity类型同时拴绳箭会以普通的箭矢掉落
#### 射中栅栏时,会自动将玩家拴在上面 ,同时拴绳箭会以普通的箭矢掉落
#### 在地面上的箭可以通过按Shift靠近来捡起如果捡起实体为发射箭矢玩家则直接获取拴绳箭矢如果捡起者为非发射者则成为发送者的拴绳持有者并获得普通箭矢
@ -44,8 +44,13 @@
* `/lp motion [<实体[可多个对象]>] add/set/multiply <x> <y> <z>` - 给实体添加/设置/倍乘 加速度
* `/lp talkArea <[<玩家[可多个对象]>]> set/setPreference/unlimited/currentConfig <数值>` - 设置玩家聊天可见半径/设置半径预期/应用预期/取消限制/获取目前配置
* `/lp tick ...` - 用法同原版Tick但权限降为2只用于调试切勿滥用后期考虑可能写成区域性的
* `/lp debug ...` - Debug指令未来可能会移除
## 游戏规则
* `LP.TeleportWithLeashedPlayers` - 此規則啓用后, 被栓玩家將會随玩家拴绳持有者一起传送 [默认值: True]
@ -54,4 +59,12 @@
* `LP.KeepLeashNotDropTime` - 此规则决定,当拴绳关系创建时一段时间里,即是距离已经达到了断裂距离,也保持其不断裂 [默认值: 240ticks ,可设置范围[80, 1200]ticks]
* `LP.DefaultTalkArea` - 此规则决定,聊天半径最小正值 [默认值: -1]
* `LP.OpenTOPNeededModeWhenScreenIsNotNull` - 此规则决定,是否在在打开 屏幕{除Top的NoteGui 和 聊天GUI外} 情况下改变Top的显示模式为NEEDED [默认值: true]
* `LP.CanCommonPlayerChangeSelfTalkArea` - 此规则决定,是否普通玩家可以修改自己的聊天可见区域 [默认值: true]
## 联动内容
# 与Nestle 的 贴贴拴绳箭
射中实体生成贴贴拴绳实体并绑定在一起,解除需用到贴贴拴绳(不太好个人觉得)

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 B

8
Resource/neoforge.json Normal file
View File

@ -0,0 +1,8 @@
{
"credit": "Made with Blockbench",
"parent": "minecraft:item/generated",
"textures": {
"1": "leashedplayer:item/neoforge",
"particle": "leashedplayer:item/neoforge"
}
}

BIN
Resource/nestle-0.1.1.jar Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

View File

@ -3,7 +3,7 @@ plugins {
id 'eclipse'
id 'idea'
id 'maven-publish'
id 'net.neoforged.gradle.userdev' version '7.0.180'
id 'net.neoforged.gradle.userdev' version '7.0.145'
}
tasks.named('wrapper', Wrapper).configure {
@ -19,16 +19,30 @@ version = mod_version
group = mod_group_id
repositories {
maven {
// location of the maven that hosts JEI files since January 2023
name = "Jared's maven"
url = "https://maven.blamejared.com/"
}
maven {
// location of a maven mirror for JEI files, as a fallback
name = "ModMaven"
url = "https://modmaven.dev"
}
maven { // TOP
url "https://maven.k-4u.nl"
}
mavenLocal()
}
base {
archivesName = mod_id
}
// Mojang ships Java 21 to end users starting in 1.20.5, so mods should target Java 21.
java.toolchain.languageVersion = JavaLanguageVersion.of(21)
minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg')
//minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg')
//minecraft.accessTransformers.entry public net.minecraft.client.Minecraft textureManager # textureManager
// Default run configurations.
@ -53,12 +67,11 @@ runs {
client {
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
}
server {
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
}
// This run config launches GameTestServer and runs all registered gametests, then exits.
@ -71,9 +84,9 @@ runs {
data {
// example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it
// workingDirectory project.file('run-data')
systemProperty 'gradle.task', 'runData'
systemProperty('gradle.task', 'runData')
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
arguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
}
}
@ -96,7 +109,14 @@ dependencies {
// And its provides the option to then use net.minecraft as the group, and one of; client, server or joined as the module name, plus the game version as version.
// For all intends and purposes: You can treat this dependency as if it is a normal library you would use.
implementation "net.neoforged:neoforge:${neo_version}"
compileOnly "mcjty.theoneprobe:theoneprobe:${top_version}"
runtimeOnly("mezz.jei:jei-${mc_version}-neoforge:${jei_version}")
// compile against the JEI API but do not include it at runtime
compileOnly("mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}")
compileOnly(files("Resource/nestle-0.1.1.jar"))
runtimeOnly(files("Resource/nestle-0.1.1.jar"))
// at runtime, use the full JEI jar for NeoForge
// compileOnly("mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}")
// Example optional mod dependency with JEI
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
// compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}"
@ -154,19 +174,31 @@ publishing {
}
repositories {
maven {
url = "file://${project.projectDir}/repo"
url "file://${project.projectDir}/repo"
}
// maven {
// // location of the maven that hosts JEI files since January 2023
// name = "Jared's maven"
// url = "https://maven.blamejared.com/"
// }
// maven {
// // location of a maven mirror for JEI files, as a fallback
// name = "ModMaven"
// url = "https://modmaven.dev"
// }
}
}
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
}
minecraft {
accessTransformers.file("src/main/resources/META-INF/accesstransformer.cfg")
}
// IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior.
idea {
module {
downloadSources = true
downloadJavadoc = true
}
}
}

View File

@ -2,35 +2,29 @@
org.gradle.jvmargs=-Xmx8G
org.gradle.daemon=false
org.gradle.debug=false
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=false
#read more on this at https://github.com/neoforged/ModDevGradle?tab=readme-ov-file#better-minecraft-parameter-names--javadoc-parchment
# you can also find the latest versions at: https://parchmentmc.org/docs/getting-started
parchment_minecraft_version=1.21
parchment_mappings_version=2024.07.28
#read more on this at https://github.com/neoforged/NeoGradle/blob/NG_7.0/README.md#apply-parchment-mappings
# you can also find the latest versions at: https://parchmentmc.org/docs/getting-started
neogradle.subsystems.parchment.minecraftVersion=1.21.3
neogradle.subsystems.parchment.mappingsVersion=2024.12.07
neogradle.subsystems.parchment.minecraftVersion=1.21
neogradle.subsystems.parchment.mappingsVersion=2024.07.28
# Environment Properties
# You can find the latest versions here: https://projects.neoforged.net/neoforged/neoforge
# The Minecraft version must agree with the Neo version to get a valid artifact
minecraft_version=1.21.3
minecraft_version=1.21
# The Minecraft version range can use any release version of Minecraft as bounds.
# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly
# as they do not follow standard versioning conventions.
minecraft_version_range=[1.21.3]
enable_accesstransformers=true
minecraft_version_range=[1.21,1.22)
# The Neo version must agree with the Minecraft version to get a valid artifact
neo_version=21.3.58
neo_version=21.0.157
# The Neo version range can use any version of Neo as bounds
neo_version_range=[21.3.58,)
neo_version_range=[21.0.0-beta,)
# The loader version range can only use the major version of FML as bounds
loader_version_range=[1,)
loader_version_range=[4,)
top_version = 1.21_neo-12.0.4-6
#jei_setting
jei_version=19.8.2.99
mc_version=1.21
## Mod Properties
# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63}
@ -41,7 +35,7 @@ mod_name=Leashed Player
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=MIT
# The mod version. See https://semver.org/
mod_version=1.21.3_0.0.3.9.9
mod_version=0.0.4.0.4
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html

View File

@ -1,2 +0,0 @@
#This file is generated by updateDaemonJvm
toolchainVersion=21

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.12-bin.zip
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

2
gradlew vendored
View File

@ -249,4 +249,4 @@ eval "set -- $(
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
exec "$JAVACMD" "$@"

2
gradlew.bat vendored
View File

@ -91,4 +91,4 @@ exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
:omega

View File

@ -7,5 +7,7 @@ pluginManagement {
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0'
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
}
include 'leashedplayer_1_21_3'

View File

@ -1,10 +1,16 @@
// 1.21.3 2025-01-27T17:55:02.7810616 Item Models: leashedplayer
// 1.21 2024-11-25T23:55:52.7726677 Item Models: leashedplayer
766c487fbf0c59e9045eeaf81daf583eb679b0e1 assets/leashedplayer/models/item/amethyst_shears.json
5846df9d85726428905701120ef34c9324c20faf assets/leashedplayer/models/item/bow_lra_pulling_0.json
845a7316b86e26f88c6932d4ef2656126503727a assets/leashedplayer/models/item/bow_lra_pulling_1.json
5bd1f9f28b91005c587f1c38fb77cd19b59495e3 assets/leashedplayer/models/item/bow_lra_pulling_2.json
90909de0fcb2a6b0b9731bb998f8d866841de6d2 assets/leashedplayer/models/item/bow_nra_pulling_0.json
de6fed69522a94812c66ba1864ae6df7465aad9c assets/leashedplayer/models/item/bow_nra_pulling_1.json
1e34de6579d5c250eff9871e589c584d888c3c6d assets/leashedplayer/models/item/bow_nra_pulling_2.json
83946f4d60d0fb1758d6553c36330506c8e48ada assets/leashedplayer/models/item/crossbow_leash_rope_arrow.json
7d9d1678faf41b58d2934d0335f700e17c372c10 assets/leashedplayer/models/item/crossbow_nestle_rope_arrow.json
bb0d76077719c83c8a8bd4346a24ea1766175125 assets/leashedplayer/models/item/fabric.json
63ec6c618a3a23eab4cab9c52d7d3250de9b516e assets/leashedplayer/models/item/kid_spawn_egg.json
114d3cc5832ef047403114504483c6f3ea07e77c assets/leashedplayer/models/item/leash_rope_arrow.json
f77241714f5233f127eee3c7521b448add1eaad2 assets/leashedplayer/models/item/nestle_rope_arrow.json
c4748995a5fe190d20e3bd16f4b2244164ec0f83 assets/leashedplayer/models/item/spectral_leash_rope_arrow.json
c4ef06f3162fe85f152c5b4a25ecdb4c2c56f945 assets/leashedplayer/models/item/tipped_leash_rope_arrow.json

View File

@ -1,3 +1,3 @@
// 1.21.3 2025-01-27T17:42:59.0511618 Registries
// 1.21 2024-11-05T23:00:18.5223698 Registries
f2536789df7f06362718a59ba4a96890e2f9b8aa data/leashedplayer/jukebox_song/what_does_the_fox_say.json
84106976f4f71012fc5bd1784303a0d135623c77 data/leashedplayer/painting_variant/group_photo.json
6f79a674215db9f9d2820b1c7f052c60ce729fee data/leashedplayer/painting_variant/group_photo.json

View File

@ -1,7 +1,6 @@
// 1.21.3 2025-01-27T21:03:10.3134854 Tags for minecraft:item mod id leashedplayer
// 1.21 2024-11-25T23:24:58.9769291 Tags for minecraft:item mod id leashedplayer
84707301f1fe2490a899deb51302d413cfff5a89 data/c/tags/item/tools/shear.json
bde6ca31173d1f22d5f6fe355dc90c9faa35b239 data/minecraft/tags/item/amethyst_tool_materials.json
63e4ad58dc8397171f84264d53dfe4fb503c7b1e data/minecraft/tags/item/arrows.json
a91f0f4956d65c981d76c9f41de5272b2e0b5786 data/minecraft/tags/item/arrows.json
84707301f1fe2490a899deb51302d413cfff5a89 data/minecraft/tags/item/enchantable/durability.json
84707301f1fe2490a899deb51302d413cfff5a89 data/minecraft/tags/item/enchantable/mining.json
84707301f1fe2490a899deb51302d413cfff5a89 data/minecraft/tags/item/enchantable/vanishing.json

View File

@ -1,2 +1,2 @@
// 1.21.3 2025-01-27T21:03:10.3134854 Languages: en_us for mod: leashedplayer
2c7f061dfc276db13135adce15c68cfc145ccf37 assets/leashedplayer/lang/en_us.json
// 1.21 2024-12-15T17:40:40.0369665 Languages: en_us for mod: leashedplayer
d88b57505584fdfde48b00652789cb078b469830 assets/leashedplayer/lang/en_us.json

View File

@ -1 +1 @@
// 1.21.3 2024-10-27T23:14:21.0429914 Tags for minecraft:block mod id leashedplayer
// 1.21 2024-10-23T13:15:06.1052755 Tags for minecraft:block mod id leashedplayer

View File

@ -1,2 +1,2 @@
// 1.21.3 2025-01-27T17:42:59.0511618 Sound Definitions
// 1.21 2024-11-05T22:44:13.1754334 Sound Definitions
81f1cc9f404c2670bf7cc679107177ffb0b48c77 assets/leashedplayer/sounds.json

View File

@ -1,2 +1,2 @@
// 1.21.3 2024-10-27T23:14:21.0429914 Tags for minecraft:painting_variant mod id leashedplayer
// 1.21 2024-10-23T13:15:06.1052755 Tags for minecraft:painting_variant mod id leashedplayer
e081a053d7c2f2d3238cf38436185ef23d234505 data/minecraft/tags/painting_variant/placeable.json

View File

@ -1,2 +1,2 @@
// 1.21.3 2025-01-26T22:13:41.4090272 Languages: lzh for mod: leashedplayer
7536eb6d1c69695c06ebb9da5b57a391174b02cb assets/leashedplayer/lang/lzh.json
// 1.21 2024-11-03T11:56:02.1150382 Languages: lzh for mod: leashedplayer
a9b5a3116c6381872e174909553b8dac080dede8 assets/leashedplayer/lang/lzh.json

View File

@ -0,0 +1,15 @@
// 1.21 2024-11-26T16:39:25.2156177 Recipes
13ebe9a580731296eb10c05d1844657d58e07cc1 data/leashedplayer/advancement/recipes/misc/amethyst_shears.json
1b45d1ad8dc73f1787c97777ad13d9771c9e0ad1 data/leashedplayer/advancement/recipes/misc/leash_rope_arrow.json
a89ec35176f84a580181c5839d6f249e482a65a9 data/leashedplayer/advancement/recipes/misc/nestle_rope_arrow.json
04bd2d8a0c7288776da2119eb9a9f9cf694be1b6 data/leashedplayer/recipe/amethyst_shears.json
974d74538b3e172946f2e169036b453b6eb6bc0a data/leashedplayer/recipe/leash_rope_arrow.json
093bae9d2e24a901ce8450d802ad5d142d1d74ed data/leashedplayer/recipe/nestle_rope_arrow.json
8de575d00dcc51fce8ebfa2542e193ffda1bafa8 data/minecraft/advancement/recipes/misc/nestle_rope_arrow_with_leash_rope_arrow.json
c0e05f359296d3e28573fa1b205ac44736376622 data/minecraft/advancement/recipes/misc/spectral_leash_rope_arrow_with_glowstone_dust.json
131fcbef603bfde7204d8e1ad15e4544696926bf data/minecraft/advancement/recipes/misc/spectral_leash_rope_arrow_with_leash_rope_arrow.json
fb35ec6670c3711b7e1d0e96f39ad914cb2419ae data/minecraft/recipe/nestle_rope_arrow_with_leash_rope_arrow.json
bb5909aa91d878c8f0ef9999881cfe89532509dd data/minecraft/recipe/spectral_leash_rope_arrow_with_glowstone_dust.json
a1381da885fbedec01243c78afbb0a50ca803ee4 data/minecraft/recipe/spectral_leash_rope_arrow_with_leash_rope_arrow.json
4dffdb7a2a537b409d1ec2630d9b74300649e1d8 data/minecraft/recipe/tipped_leash_rope_arrow_a.json
7810cb5e8c165f479fc6cd030bd1cf7bc508993b data/minecraft/recipe/tipped_leash_rope_arrow_b.json

View File

@ -1,2 +1,2 @@
// 1.21.3 2025-01-27T21:03:10.3134854 Languages: zh_cn for mod: leashedplayer
f7bcf89907a8ca5f575e4b519d53cd0628bb1e6b assets/leashedplayer/lang/zh_cn.json
// 1.21 2024-12-15T17:48:33.0549249 Languages: zh_cn for mod: leashedplayer
72797aa9107025df7d91eaff3ea51745d410261c assets/leashedplayer/lang/zh_cn.json

View File

@ -1,11 +0,0 @@
// 1.21.3 2025-01-27T17:42:59.0511618 LeashedPlayer Recipes
13ebe9a580731296eb10c05d1844657d58e07cc1 data/leashedplayer/advancement/recipes/misc/amethyst_shears.json
1b45d1ad8dc73f1787c97777ad13d9771c9e0ad1 data/leashedplayer/advancement/recipes/misc/leash_rope_arrow.json
a26d63c2360b32df0b636a5dec96dd919139e022 data/leashedplayer/advancement/recipes/misc/spectral_leash_rope_arrow.json
af1f65626735f1001426e0984217139e15649725 data/leashedplayer/recipe/amethyst_shears.json
db45be6e2bbddc49e60a6c1b12e2ef44afad30d8 data/leashedplayer/recipe/leash_rope_arrow.json
db37bd69a700eaae69bff48c77ed49ca55fb9bf1 data/leashedplayer/recipe/spectral_leash_rope_arrow.json
935d8732ca65dd73e4668a197cda60480053fbcd data/minecraft/advancement/recipes/misc/leash_rope_arrow_shape.json
5811048f18527a45b36b8b927de4e5d7c12a75eb data/minecraft/recipe/leash_rope_arrow_shape.json
4dffdb7a2a537b409d1ec2630d9b74300649e1d8 data/minecraft/recipe/tipped_leash_rope_arrow_a.json
7810cb5e8c165f479fc6cd030bd1cf7bc508993b data/minecraft/recipe/tipped_leash_rope_arrow_b.json

View File

@ -1,4 +1,4 @@
// 1.21.3 2025-01-26T22:13:41.4090272 Advancements
// 1.21 2024-11-26T16:52:31.259654 Advancements
4d97adba079f1966090a52443bb439319f550680 data/leashedplayer/advancement/advancement_leash_arrow.json
f16184b81ea35a0fbd8f2c49b085a96c32818c69 data/leashedplayer/advancement/dog_running_player.json
bce12ed339b3b0fded263ba039f7a4e6fcfb84ca data/leashedplayer/advancement/follow_arrow.json
@ -8,5 +8,6 @@ a69a455855fb6dd8a8ac131a55099de5de45d7c4 data/leashedplayer/advancement/leash_ar
133f844ffafd37b9ba57cafa96350f035cac57f9 data/leashedplayer/advancement/leash_start.json
2d8bce7fd078f9cc6b73b77f2fbab30e6cc197f4 data/leashedplayer/advancement/leash_terminator.json
4e567c22e18462ad367fe1817140d1ffa13a6294 data/leashedplayer/advancement/neo_fox.json
95486932f200c278f23444adca2e328a82e7f863 data/leashedplayer/advancement/nestle_arrow.json
4b0bcf6b372f52e954edcef37a6b04435ec2b4e8 data/leashedplayer/advancement/no_leash.json
72f40eb5816d1e8c296bdf4df6b599c15ba7e7e9 data/leashedplayer/advancement/tipped_leash_arrow.json

View File

@ -1,2 +1,2 @@
// 1.21.3 2025-01-27T21:03:10.3134854 Languages: zh_tw for mod: leashedplayer
c23825af72a73bc54b72ad3817acb5a03d299375 assets/leashedplayer/lang/zh_tw.json
// 1.21 2024-12-15T17:48:33.0539432 Languages: zh_tw for mod: leashedplayer
a01c64ca969974766c47baadd465b24b6fb5803b assets/leashedplayer/lang/zh_tw.json

View File

@ -17,6 +17,8 @@
"advancement.leashedplayer.leashed_self.desc": "“Restrain oneself with a rope",
"advancement.leashedplayer.neo_fox": "NEOFORGE!",
"advancement.leashedplayer.neo_fox.desc": "It seems can be equipped.",
"advancement.leashedplayer.nestle_arrow": "Arrow with the Power of Nestle!",
"advancement.leashedplayer.nestle_arrow.desc": "The Power of Nestle!!!",
"advancement.leashedplayer.no_leash": "Don't tie me up",
"advancement.leashedplayer.no_leash.desc": "You cannot be leashed by ANY",
"advancement.leashedplayer.tipped_leash_arrow": "God said there should be more arrows",
@ -27,10 +29,16 @@
"entity.leashedplayer.leash_rope_arrow": "Leash Rope Arrow",
"entity.leashedplayer.nestle_rope_arrow": "Nestle Rope Arrow",
"entity.leashedplayer.spectral_leash_rope_arrow": "Spectral Leash Rope Arrow",
"gamerule.LP.CanCommonPlayerChangeSelfTalkArea": "Should Non-OP Player can change their TalkArea",
"gamerule.LP.CanCommonPlayerChangeSelfTalkArea.description": "Above on its Name",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent": "Create Leash Fence Knot Entity if absent",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent.description": "Create LeashKnot Entity if it's absent on fence",
"gamerule.LP.DefaultTalkArea": "Default Area Talk",
"gamerule.LP.DefaultTalkArea.description": "When the global setting is non-negative, it limits the chat range for all players. If a player's configured chat range is smaller than this value, this rule applies. Otherwise, the player's custom value is used.",
"gamerule.LP.KeepLeashNotDropTime": "Keep leash alive Time",
"gamerule.LP.KeepLeashNotDropTime.description": "The time of Keep new leash which has far distance alive (Tick)",
"gamerule.LP.OpenTOPNeededModeWhenScreenIsNotNull": "Open TOP NEEDED Mode When Screen isn't null",
"gamerule.LP.OpenTOPNeededModeWhenScreenIsNotNull.description": "The One Probe will automatic to be in the Needed Mode when Gui Screen is not NULL",
"gamerule.LP.TeleportWithLeashedPlayers": "Teleport leashed player with player holder",
"gamerule.LP.TeleportWithLeashedPlayers.description": "Holder will teleport with their leashed players ",
"item.leash_rope_arrow.desc.1": "§7This arrow will carry the owner along with its flight:",
@ -41,23 +49,43 @@
"item.leash_rope_arrow.description": "Arrows with ropes attached?",
"item.leashedplayer.amethyst_shears": "Amethyst Shears",
"item.leashedplayer.fabric": "Fabric",
"item.leashedplayer.kid_spawn_egg": "Kid Spawn Egg",
"item.leashedplayer.leash_rope_arrow": "Leash Rope Arrow",
"item.leashedplayer.neoforge": "NeoForge",
"item.leashedplayer.nestle_rope_arrow": "Nestle Rope Arrow",
"item.leashedplayer.spectral_leash_rope_arrow": "Spectral Leash Rope Arrow",
"item.minecraft.lingering_potion.effect.no_leash": "Splash No Leash Potion",
"item.minecraft.potion.effect.no_leash": "No Leash Potion",
"item.minecraft.splash_potion.effect.no_leash": "Splash No Leash Potion",
"item.minecraft.tipped_arrow.effect.no_leash": "Arrow of No Leash",
"item.nestle_rope_arrow.desc.1": "§7This arrow will carry the owner along with its flight:",
"item.nestle_rope_arrow.desc.2": "§c1.§r If it hits an entity, it will leash the owner with the entity and drop as a normal arrow;",
"item.nestle_rope_arrow.desc.3": "§c2.§r When fired from its launcher, the first player hit will become the arrow's owner and will fly along with it.",
"item.nestle_rope_arrow.desc.4": "",
"item.nestle_rope_arrow.desc.5": "",
"item.spectral_leash_rope_arrow.desc": "§c2.§r Strike the entity to give it a §e§lGlowing§r effect.",
"item.tipped_leash_rope_arrow.desc": "§c2.§rStrike the entity to give it a Potion effect.",
"item.tipped_leash_rope_arrow.name": "Tipped Leash Rope Arrow Soaked By %1$s",
"item.variant.leash_rope_arrow.desc.1": "§7A variant of Leash Rope Arrow",
"item.variant.leash_rope_arrow.desc.2": "§c1.§r The function is the same as its original one。",
"jukebox_song.leashedplayer.what_does_the_fox_say": "What does the fox say?",
"key.leashedplayer.apply_talkarea_preference": "Apply TalkArea Preference",
"key.leashedplayer.category": "Leashed Player",
"key.leashedplayer.leash_length.add": "Increase the Length of Leash Rope",
"key.leashedplayer.leash_length.not_support_to_not_player_entity": "Only work on Players",
"key.leashedplayer.leash_length.sub": "Decrease the Length of Leash Rope",
"leashedplayer.chat.none_heard_you": "Nobody heard your message",
"leashedplayer.command.chat.message.no_right": "You haven't the right to do that!",
"leashedplayer.command.chat.message.talkarea.current_config": "%s 's §6TalkArea Current§7:§e %d §6blocks §f(§aPrefence§7:§e %d §ablocks§f)§r",
"leashedplayer.command.chat.message.talkarea.preference.set": "%s 's §atalk area preference set to §e%d§a blocks!§r",
"leashedplayer.command.chat.message.talkarea.preference_not_set": "%s 's talk area preference is not set!",
"leashedplayer.command.chat.message.talkarea.self.current_config": "§6TalkArea Current§7:§e %d §6blocks §f(§aPrefence§7:§e %d §ablocks§f)§r",
"leashedplayer.command.chat.message.talkarea.self.preference.set": "§aTalk area preference set to §e%d§a blocks!§r",
"leashedplayer.command.chat.message.talkarea.self.preference_not_set": "Your talk area preference is not set!",
"leashedplayer.command.chat.message.talkarea.self.set": "§aTalk area set to §e%d§a blocks!§r",
"leashedplayer.command.chat.message.talkarea.self.unlimited": "§aTalk area unlimited!§r",
"leashedplayer.command.chat.message.talkarea.set": "%s 's §atalk area set to §e%d§a blocks!§r",
"leashedplayer.command.chat.message.talkarea.unlimited": "%s 's §atalk area unlimited!§r",
"leashedplayer.command.leash.message.leash.data.clear": "%1$s's LeashData(LeashHolderEntity: %2$s) now is clear",
"leashedplayer.command.leash.message.leash.data.clear.leash.clear.failed.no_data": "%1$s has no LeashData can be clear",
"leashedplayer.command.leash.message.leash.data.null": "%1$s has no LeashDataEntity",
@ -82,6 +110,7 @@
"leashedplayer.leash_rope.length.increase": "§aIncrease the §f%s §aLength of Leash Rope§7(§bLength§7:§e%d§7)",
"leashedplayer.leash_rope.length.increase.self": "§aIncrease the Length of Leash Rope§7(§bLength§7:§e%d§7)",
"leashedplayer.leash_rope_arrow.try_to_pickup.push_shift_tip": "§aPush §f§lShift§a to pick up quickly",
"multiplayer.disconnect.addiction": "You've triggered the anti-addiction mechanic, and you'll come back when you rest!",
"painting.leashedplayer.group_photo.author": "§9Leisure §4Time §eDock§r",
"painting.leashedplayer.group_photo.title": "§dGroup Photo §7[§6memorable§7]§r",
"sound.leashedplayer.subtitle.what_does_the_fox_say": "Great Chu will rise again! Chen She will be king!"

View File

@ -1,3 +1,15 @@
{
"entity.leashedplayer.kid_player": "幼"
"entity.leashedplayer.kid_player": "幼",
"gamerule.LP.DefaultTalkArea.description": "阖局初置非负数,则限一顾之日下,若立聊城小在直则用其常,若用玩义直上跻之地",
"leashedplayer.chat.none_heard_you": "无人受子问",
"leashedplayer.command.chat.message.talkarea.current_config": "%s§6今聊城可知半径置§e %d§6格§f(§a默§7§e%d格§f)§r",
"leashedplayer.command.chat.message.talkarea.preference.set": "%s§6默置§e %d§6格§r",
"leashedplayer.command.chat.message.talkarea.preference_not_set": "%s未置默视之",
"leashedplayer.command.chat.message.talkarea.self.current_config": "§6今聊城可知半径置§e %d§6格§f(§a默§7§e%d格§f)§r",
"leashedplayer.command.chat.message.talkarea.self.preference.set": "§6默置§e %d§6格§r",
"leashedplayer.command.chat.message.talkarea.self.preference_not_set": "未置默视之",
"leashedplayer.command.chat.message.talkarea.self.set": "§6今聊城可知半径置§e%d §6格§r",
"leashedplayer.command.chat.message.talkarea.self.unlimited": "§a语矢无限§r",
"leashedplayer.command.chat.message.talkarea.set": "%s§6今聊城可知半径置§e%d §6格§r",
"leashedplayer.command.chat.message.talkarea.unlimited": "%s§a语矢无限§r"
}

View File

@ -17,6 +17,8 @@
"advancement.leashedplayer.leashed_self.desc": "用拴绳拴住自己",
"advancement.leashedplayer.neo_fox": "NEOFORGE!",
"advancement.leashedplayer.neo_fox.desc": "似乎可以戴头上",
"advancement.leashedplayer.nestle_arrow": "贴贴之箭!",
"advancement.leashedplayer.nestle_arrow.desc": "贴贴之力!!!",
"advancement.leashedplayer.no_leash": "勿拴我",
"advancement.leashedplayer.no_leash.desc": "你不会被任何东西拴住",
"advancement.leashedplayer.tipped_leash_arrow": "神说要有更多箭矢",
@ -27,10 +29,16 @@
"entity.leashedplayer.leash_rope_arrow": "拴绳箭",
"entity.leashedplayer.nestle_rope_arrow": "贴贴拴绳箭",
"entity.leashedplayer.spectral_leash_rope_arrow": "拴绳光灵箭",
"gamerule.LP.CanCommonPlayerChangeSelfTalkArea": "非OP应该可以修改自己的聊天可见半径吗?",
"gamerule.LP.CanCommonPlayerChangeSelfTalkArea.description": "同名",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent": "如果缺失则创建拴绳结",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent.description": "如果在栅栏处缺失拴绳结,则创建它",
"gamerule.LP.DefaultTalkArea": "默认聊天区域可见半径",
"gamerule.LP.DefaultTalkArea.description": "全局区域设置为非负数时,则限制全体玩家的聊天区域。若玩家设置的聊天区域小于该值则采用该规则,反之则采用玩家自定义值",
"gamerule.LP.KeepLeashNotDropTime": "保持拴绳不掉落的时间",
"gamerule.LP.KeepLeashNotDropTime.description": "当距离过远时,保持新建拴绳不掉落的时间 (刻)",
"gamerule.LP.OpenTOPNeededModeWhenScreenIsNotNull": "当屏幕不为空时自动打开探测器的Needed模式",
"gamerule.LP.OpenTOPNeededModeWhenScreenIsNotNull.description": "当屏幕不为空时自动打开探测器的Needed模式",
"gamerule.LP.TeleportWithLeashedPlayers": "被拴玩家随玩家持有者传送",
"gamerule.LP.TeleportWithLeashedPlayers.description": "传送时将被拴玩家与持有者一起传送",
"item.leash_rope_arrow.desc.1": "§7该箭将会携带拥有者随其飞行",
@ -41,23 +49,43 @@
"item.leash_rope_arrow.description": "带有拴绳的箭矢?",
"item.leashedplayer.amethyst_shears": "紫水晶剪刀",
"item.leashedplayer.fabric": "Fabric",
"item.leashedplayer.kid_spawn_egg": "小孩生成蛋",
"item.leashedplayer.leash_rope_arrow": "拴绳箭",
"item.leashedplayer.neoforge": "NeoForge",
"item.leashedplayer.nestle_rope_arrow": "贴贴拴绳箭",
"item.leashedplayer.spectral_leash_rope_arrow": "拴绳光灵箭",
"item.minecraft.lingering_potion.effect.no_leash": "滞留型禁拴药水",
"item.minecraft.potion.effect.no_leash": "禁拴药水",
"item.minecraft.splash_potion.effect.no_leash": "喷溅型禁拴药水",
"item.minecraft.tipped_arrow.effect.no_leash": "禁拴之箭",
"item.nestle_rope_arrow.desc.1": "§7该箭将会携带拥有者随其飞行",
"item.nestle_rope_arrow.desc.2": "§c1.§r 若击中生物时,将持有者与其拴在一起并已普通箭形式掉落;",
"item.nestle_rope_arrow.desc.3": "§c2.§r 当前其发射器里发射,第一个射中的玩家将成为此箭的持有者并随箭飞行.",
"item.nestle_rope_arrow.desc.4": "",
"item.nestle_rope_arrow.desc.5": "",
"item.spectral_leash_rope_arrow.desc": "§c2.§r 击中实体给与其§e§l发光§7(§e§lGlowing§7)§r效果",
"item.tipped_leash_rope_arrow.desc": "§c2.§r 击中实体给与其药水效果",
"item.tipped_leash_rope_arrow.name": "用%1$s浸泡过的拴绳箭",
"item.variant.leash_rope_arrow.desc.1": "§7拴绳箭的一个变种",
"item.variant.leash_rope_arrow.desc.2": "§c1.§r 功能同其本体;",
"jukebox_song.leashedplayer.what_does_the_fox_say": "狐狸是怎么叫的?",
"key.leashedplayer.apply_talkarea_preference": "应用可见区域预设",
"key.leashedplayer.category": "可拴玩家",
"key.leashedplayer.leash_length.add": "增加拴绳长度",
"key.leashedplayer.leash_length.not_support_to_not_player_entity": "只在玩家身上有效",
"key.leashedplayer.leash_length.sub": "减小拴绳长度",
"leashedplayer.chat.none_heard_you": "沒有人接收到你的消息",
"leashedplayer.command.chat.message.no_right": "你无权这样做!",
"leashedplayer.command.chat.message.talkarea.current_config": "%s§6目前聊天区域可见半径设置§7:§e %d §6格 §f(§a默认值§7:§e %d §a格§f)§r",
"leashedplayer.command.chat.message.talkarea.preference.set": "%s§a默认聊天区域可见消息半径设置为 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.preference_not_set": "%s未设置默认可见消息聊天区域半径",
"leashedplayer.command.chat.message.talkarea.self.current_config": "§6目前聊天区域可见半径设置§7:§e %d §6格 §f(§a默认值§7:§e %d §a格§f)§r",
"leashedplayer.command.chat.message.talkarea.self.preference.set": "§a默认聊天区域可见消息半径设置为 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.self.preference_not_set": "未设置默认可见消息聊天区域半径",
"leashedplayer.command.chat.message.talkarea.self.set": "§a聊天区域可见消息半径设置为 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.self.unlimited": "§a聊天区域半径无限制§r",
"leashedplayer.command.chat.message.talkarea.set": "%s§a聊天区域可见消息半径设置为 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.unlimited": "%s§a聊天区域半径无限制§r",
"leashedplayer.command.leash.message.leash.data.clear": "%1$s的拴绳数据拴绳持有者实体%2$s现在已清除",
"leashedplayer.command.leash.message.leash.data.clear.leash.clear.failed.no_data": "%1$s沒有拴绳数据可清除",
"leashedplayer.command.leash.message.leash.data.null": "%1$s沒有拴绳数据实体",
@ -82,6 +110,7 @@
"leashedplayer.leash_rope.length.increase": "§a增加§f%s的拴绳长度§a§7(§b长度§7:§e%d§7)",
"leashedplayer.leash_rope.length.increase.self": "§a增加拴绳长度§a§7(§b长度§7:§e%d§7)",
"leashedplayer.leash_rope_arrow.try_to_pickup.push_shift_tip": "§a按下§f§lShift键§a以加快拾取",
"multiplayer.disconnect.addiction": "你触发了防沉迷机制,休息会再来吧!",
"painting.leashedplayer.group_photo.author": "§9闲趣§4时§e坞§r",
"painting.leashedplayer.group_photo.title": "§d集体照 §7[§6纪念§7]§r",
"sound.leashedplayer.subtitle.what_does_the_fox_say": "大楚兴~ 陈胜王~~"

View File

@ -17,6 +17,8 @@
"advancement.leashedplayer.leashed_self.desc": "用栓繩拴住自己",
"advancement.leashedplayer.neo_fox": "NEOFORGE!",
"advancement.leashedplayer.neo_fox.desc": "似乎可以戴著",
"advancement.leashedplayer.nestle_arrow": "貼貼之箭!",
"advancement.leashedplayer.nestle_arrow.desc": "貼貼之力!!!",
"advancement.leashedplayer.no_leash": "請恁勿拴唔",
"advancement.leashedplayer.no_leash.desc": "恁不會被任何拴住",
"advancement.leashedplayer.tipped_leash_arrow": "神說要有更多箭矢",
@ -27,10 +29,16 @@
"entity.leashedplayer.leash_rope_arrow": "拴繩箭",
"entity.leashedplayer.nestle_rope_arrow": "貼貼拴繩箭",
"entity.leashedplayer.spectral_leash_rope_arrow": "拴繩光靈箭",
"gamerule.LP.CanCommonPlayerChangeSelfTalkArea": "非OP應該可以修改自己的聊天可見半徑嗎",
"gamerule.LP.CanCommonPlayerChangeSelfTalkArea.description": "同名",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent": "如果缺失則創建拴繩結",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent.description": "如果在柵欄処缺失拴繩結,則創建它",
"gamerule.LP.DefaultTalkArea": "默認聊天區域可見半徑",
"gamerule.LP.DefaultTalkArea.description": "儅全局區域為非負時,則限制全服玩家聊天區域。若玩家自定義值小於該規則則采用,反之則用玩家自定義值",
"gamerule.LP.KeepLeashNotDropTime": "保持其不掉落的時間",
"gamerule.LP.KeepLeashNotDropTime.description": "儅距離過遠時,保持其不掉落的時間(刻)",
"gamerule.LP.OpenTOPNeededModeWhenScreenIsNotNull": "避免糠測器糠屏幕",
"gamerule.LP.OpenTOPNeededModeWhenScreenIsNotNull.description": "避免糠測器糠屏幕",
"gamerule.LP.TeleportWithLeashedPlayers": "被拴玩家随玩家持有者傳送",
"gamerule.LP.TeleportWithLeashedPlayers.description": "將被拴玩家將隨持有者一起傳送",
"item.leash_rope_arrow.desc.1": "§7該箭將會攜帶擁有者隨其飛行",
@ -41,23 +49,43 @@
"item.leash_rope_arrow.description": "帶有拴繩的箭矢?",
"item.leashedplayer.amethyst_shears": "紫水晶剪刀",
"item.leashedplayer.fabric": "Fabric",
"item.leashedplayer.kid_spawn_egg": "小孩生成蛋",
"item.leashedplayer.leash_rope_arrow": "拴繩箭",
"item.leashedplayer.neoforge": "NeoForge",
"item.leashedplayer.nestle_rope_arrow": "貼貼拴繩箭",
"item.leashedplayer.spectral_leash_rope_arrow": "拴繩光靈箭",
"item.minecraft.lingering_potion.effect.no_leash": "滯留型禁拴藥水",
"item.minecraft.potion.effect.no_leash": "禁拴藥水",
"item.minecraft.splash_potion.effect.no_leash": "噴濺型禁拴藥水",
"item.minecraft.tipped_arrow.effect.no_leash": "禁拴之箭",
"item.nestle_rope_arrow.desc.1": "§7該箭將會攜帶擁有者隨其飛行",
"item.nestle_rope_arrow.desc.2": "§c1.§r 若擊中生物時,將持有者與其拴在一起其上並以普通箭的形式掉落;",
"item.nestle_rope_arrow.desc.3": "§c2.§r 當箭從發射器發射時,第一個射中的玩家將成為此箭的持有者並隨箭飛行;",
"item.nestle_rope_arrow.desc.4": "",
"item.nestle_rope_arrow.desc.5": "",
"item.spectral_leash_rope_arrow.desc": "擊中實體給予其§e§l發光§7(§e§lGlowing§7)§r效果",
"item.tipped_leash_rope_arrow.desc": "擊中實體給予其药水效果",
"item.tipped_leash_rope_arrow.name": "蘸有%1$s的拴繩箭",
"item.variant.leash_rope_arrow.desc.1": "§7拴繩箭矢的一個變種",
"item.variant.leash_rope_arrow.desc.2": "§c1.§r 功能與本體一致;",
"jukebox_song.leashedplayer.what_does_the_fox_say": "狐狸是怎麽叫的?",
"key.leashedplayer.apply_talkarea_preference": "應用設置可見區域預設",
"key.leashedplayer.category": "可拴玩家",
"key.leashedplayer.leash_length.add": "增加拴繩長度",
"key.leashedplayer.leash_length.not_support_to_not_player_entity": "僅對玩家有效",
"key.leashedplayer.leash_length.sub": "減小拴繩長度",
"leashedplayer.chat.none_heard_you": "無人接收到你的訊息",
"leashedplayer.command.chat.message.no_right": "你無權這麽做!",
"leashedplayer.command.chat.message.talkarea.current_config": "%s§6目前可見訊息聊天半徑設置§7:§e%d §6格 §f(§a默認值§7:§e%d §a格§f)§r",
"leashedplayer.command.chat.message.talkarea.preference.set": "%s§a默認聊天區域可見訊息半徑設置為 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.preference_not_set": "%s未設置可見訊息聊天半徑",
"leashedplayer.command.chat.message.talkarea.self.current_config": "§6目前可見訊息聊天半徑設置§7:§e%d §6格 §f(§a默認值§7:§e%d §a格§f)§r",
"leashedplayer.command.chat.message.talkarea.self.preference.set": "§a默認聊天區域可見訊息半徑設置為 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.self.preference_not_set": "未設置可見訊息聊天半徑",
"leashedplayer.command.chat.message.talkarea.self.set": "§a聊天區域可見半徑為 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.self.unlimited": "§a聊天區域半徑無限制§r",
"leashedplayer.command.chat.message.talkarea.set": "%s§a聊天區域可見半徑為 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.unlimited": "%s§a聊天區域半徑無限制§r",
"leashedplayer.command.leash.message.leash.data.clear": "%1$s的拴繩數據拴繩持有者實體%2$s現在已清除",
"leashedplayer.command.leash.message.leash.data.clear.leash.clear.failed.no_data": "%1$s沒有拴繩數據實體可被清除",
"leashedplayer.command.leash.message.leash.data.null": "%1$s沒有拴繩數據實體",
@ -82,6 +110,7 @@
"leashedplayer.leash_rope.length.increase": "§a增加§f%s§a的拴繩長度§7(§長度§7:§e%d§7)",
"leashedplayer.leash_rope.length.increase.self": "§a增加拴繩長度§7(§長度§7:§e%d§7)",
"leashedplayer.leash_rope_arrow.try_to_pickup.push_shift_tip": "§a按下§f§lShift鍵§a以加速拾取",
"multiplayer.disconnect.addiction": "你觸發了防沉迷機制,休息會再來吧!",
"painting.leashedplayer.group_photo.author": "§9閑趣§4時§e塢§r",
"painting.leashedplayer.group_photo.title": "§d集體照 §7[§6紀念§7]§r",
"sound.leashedplayer.subtitle.what_does_the_fox_say": "大楚興~ 陳勝王~~"

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/bow",
"textures": {
"layer0": "leashedplayer:item/bow_nra_pulling_0"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/bow",
"textures": {
"layer0": "leashedplayer:item/bow_nra_pulling_1"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/bow",
"textures": {
"layer0": "leashedplayer:item/bow_nra_pulling_2"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/crossbow",
"textures": {
"layer0": "leashedplayer:item/crossbow_nestle_rope_arrow"
}
}

View File

@ -0,0 +1,3 @@
{
"parent": "minecraft:item/template_spawn_egg"
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "leashedplayer:item/nestle_rope_arrow"
}
}

View File

@ -0,0 +1,35 @@
{
"parent": "leashedplayer:leash_arrow",
"criteria": {
"has_nestle_rope_arrow": {
"conditions": {
"items": [
{
"items": "leashedplayer:nestle_rope_arrow"
}
]
},
"trigger": "minecraft:inventory_changed"
}
},
"display": {
"description": {
"translate": "advancement.leashedplayer.nestle_arrow.desc"
},
"frame": "goal",
"hidden": true,
"icon": {
"count": 1,
"id": "leashedplayer:nestle_rope_arrow"
},
"title": {
"translate": "advancement.leashedplayer.nestle_arrow"
}
},
"requirements": [
[
"has_nestle_rope_arrow"
]
],
"sends_telemetry_event": true
}

View File

@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_nestle_rope": {
"conditions": {
"items": [
{
"items": "nestle:nestle_lead"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "leashedplayer:nestle_rope_arrow"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_nestle_rope"
]
],
"rewards": {
"recipes": [
"leashedplayer:nestle_rope_arrow"
]
}
}

View File

@ -1,11 +1,5 @@
{
"asset_id": "leashedplayer:group_photo",
"author": {
"translate": "painting.leashedplayer.group_photo.author"
},
"height": 3,
"title": {
"translate": "painting.leashedplayer.group_photo.title"
},
"width": 4
}

View File

@ -2,8 +2,12 @@
"type": "minecraft:crafting_shaped",
"category": "misc",
"key": {
"#": "minecraft:amethyst_shard",
"%": "minecraft:stick"
"#": {
"item": "minecraft:amethyst_shard"
},
"%": {
"item": "minecraft:stick"
}
},
"pattern": [
"#%",

View File

@ -2,8 +2,12 @@
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
"minecraft:lead",
"minecraft:arrow"
{
"item": "minecraft:lead"
},
{
"item": "minecraft:arrow"
}
],
"result": {
"count": 1,

View File

@ -0,0 +1,16 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
{
"item": "nestle:nestle_lead"
},
{
"item": "minecraft:arrow"
}
],
"result": {
"count": 1,
"id": "leashedplayer:nestle_rope_arrow"
}
}

View File

@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_nestle": {
"conditions": {
"items": [
{
"items": "nestle:nestle"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "minecraft:nestle_rope_arrow_with_leash_rope_arrow"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_nestle"
]
],
"rewards": {
"recipes": [
"minecraft:nestle_rope_arrow_with_leash_rope_arrow"
]
}
}

View File

@ -23,7 +23,7 @@
},
"has_the_recipe": {
"conditions": {
"recipe": "minecraft:leash_rope_arrow_shape"
"recipe": "minecraft:spectral_leash_rope_arrow_with_glowstone_dust"
},
"trigger": "minecraft:recipe_unlocked"
}
@ -37,7 +37,7 @@
],
"rewards": {
"recipes": [
"minecraft:leash_rope_arrow_shape"
"minecraft:spectral_leash_rope_arrow_with_glowstone_dust"
]
}
}

View File

@ -23,7 +23,7 @@
},
"has_the_recipe": {
"conditions": {
"recipe": "leashedplayer:spectral_leash_rope_arrow"
"recipe": "minecraft:spectral_leash_rope_arrow_with_leash_rope_arrow"
},
"trigger": "minecraft:recipe_unlocked"
}
@ -37,7 +37,7 @@
],
"rewards": {
"recipes": [
"leashedplayer:spectral_leash_rope_arrow"
"minecraft:spectral_leash_rope_arrow_with_leash_rope_arrow"
]
}
}

View File

@ -0,0 +1,16 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
{
"item": "nestle:nestle"
},
{
"item": "leashedplayer:leash_rope_arrow"
}
],
"result": {
"count": 1,
"id": "leashedplayer:nestle_rope_arrow"
}
}

View File

@ -2,8 +2,12 @@
"type": "minecraft:crafting_shaped",
"category": "misc",
"key": {
"#": "leashedplayer:leash_rope_arrow",
"$": "minecraft:glowstone_dust"
"#": {
"item": "leashedplayer:leash_rope_arrow"
},
"$": {
"item": "minecraft:glowstone_dust"
}
},
"pattern": [
" $ ",

View File

@ -2,8 +2,12 @@
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
"minecraft:lead",
"minecraft:spectral_arrow"
{
"item": "minecraft:lead"
},
{
"item": "minecraft:spectral_arrow"
}
],
"result": {
"count": 1,

View File

@ -1,5 +0,0 @@
{
"values": [
"minecraft:amethyst_shard"
]
}

View File

@ -2,6 +2,7 @@
"values": [
"leashedplayer:leash_rope_arrow",
"leashedplayer:spectral_leash_rope_arrow",
"leashedplayer:tipped_leash_rope_arrow"
"leashedplayer:tipped_leash_rope_arrow",
"leashedplayer:nestle_rope_arrow"
]
}

View File

@ -1,28 +1,35 @@
package com.r3944realms.leashedplayer;
import com.r3944realms.leashedplayer.client.renders.LeashRendererUtil;
import com.r3944realms.leashedplayer.client.renders.PlayerLeashState;
import com.r3944realms.leashedplayer.client.renders.entities.ChestItemLayerRenderer;
import com.r3944realms.leashedplayer.client.renders.entities.LeashRopeArrowRenderer;
import com.r3944realms.leashedplayer.client.renders.entities.SpectralLeashRopeArrowRenderer;
import com.r3944realms.leashedplayer.client.renders.entities.*;
import com.r3944realms.leashedplayer.content.ModKeyMapping;
import com.r3944realms.leashedplayer.content.commands.Command;
import com.r3944realms.leashedplayer.content.entities.ModEntityRegister;
import com.r3944realms.leashedplayer.content.gamerules.GameruleRegistry;
import com.r3944realms.leashedplayer.content.gamerules.Server.OpenTOPNeededModeWhenScreenIsNotNull;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import com.r3944realms.leashedplayer.content.items.type.ILeashRopeArrow;
import com.r3944realms.leashedplayer.modInterface.IPlayerRenderStateExtension;
import com.r3944realms.leashedplayer.content.items.type.INestleRopeArrow;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
import com.r3944realms.leashedplayer.network.server.Code;
import com.r3944realms.leashedplayer.network.server.DecreaseLeashRopeLength;
import com.r3944realms.leashedplayer.network.server.IncreaseLeashRopeLength;
import com.r3944realms.leashedplayer.utils.Util;
import mcjty.theoneprobe.config.Config;
import mcjty.theoneprobe.gui.GuiNote;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.ChatScreen;
import net.minecraft.client.gui.screens.DisconnectedScreen;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraft.client.resources.PlayerSkin;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.DisconnectionDetails;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.FastColor;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
@ -32,6 +39,7 @@ import net.minecraft.world.item.component.ChargedProjectiles;
import net.minecraft.world.phys.HitResult;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModList;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.neoforge.client.event.*;
@ -40,18 +48,46 @@ import net.neoforged.neoforge.network.PacketDistributor;
import java.util.List;
public class ClientEventHandler {
public abstract class ClientEventHandler {
public static final String ADDICTION = "multiplayer.disconnect.addiction";
@EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.GAME, modid = LeashedPlayer.MOD_ID)
public static class Game {
public static class Game extends ClientEventHandler {
private static int oldSelect;
private static boolean configSaved = false;
private static final boolean IS_TOP_LOADED = ModList.get().isLoaded("theoneprobe");
@SubscribeEvent
public static void onPlayerRendererEventPre(RenderPlayerEvent.Post event) {
PlayerRenderState renderState = event.getRenderState();
PlayerLeashState playerLeashState = ((IPlayerRenderStateExtension) renderState).getPlayerLeashState();
if(playerLeashState != null) {
if (playerLeashState.vanilaLeashState != null)
LeashRendererUtil.renderLeash(event.getPoseStack(), event.getMultiBufferSource(), playerLeashState.vanilaLeashState);
else
LeashRendererUtil.renderLeash(event.getPoseStack(), event.getMultiBufferSource(), renderState);
public static void onClientTick(ClientTickEvent.Pre event) {
Minecraft mc = Minecraft.getInstance();
if (mc.level == null) return;
if (GameruleRegistry.getGameruleBoolValue(mc.level, OpenTOPNeededModeWhenScreenIsNotNull.ID)){
Screen currentScreen = mc.screen;
if (IS_TOP_LOADED) {
if (currentScreen != null) {
if (currentScreen instanceof GuiNote || currentScreen instanceof ChatScreen) {
configSaved = false;
oldSelect = Config.needsProbe.get();
} else {
if (!configSaved) {
oldSelect = Config.needsProbe.get();
Config.setProbeNeeded(Config.PROBE_NEEDED);
configSaved = true;
} else {
Config.setProbeNeeded(Config.PROBE_NEEDED);
}
}
} else {
Config.setProbeNeeded(oldSelect);
configSaved = false;
}
}
}
}
@SubscribeEvent
public static void onScreenOpen(ScreenEvent.Opening opening) {
if(opening.getNewScreen() instanceof DisconnectedScreen screen) {
if (screen.details.reason().getString().equals("You are already connected to this proxy!")) {
screen.details = new DisconnectionDetails(Component.translatable(ADDICTION).withStyle(ChatFormatting.RED));
}
}
}
@SubscribeEvent
@ -59,6 +95,10 @@ public class ClientEventHandler {
Minecraft minecraft = Minecraft.getInstance();
LocalPlayer player = minecraft.player;
assert player != null;
if (ModKeyMapping.KEY_APPLY_TALKAREA_PREFERENCE.isDown()) {
String prefix = (Command.SHOULD_USE_PREFIX ? Command.PREFIX : "") + " ";
player.connection.sendCommand(prefix + "talkArea usePreference");
}
if (ModKeyMapping.KEY_ADD_LEASH_LENGTH.isDown()) {
PlayerLeashable playerLeashable = (PlayerLeashable) player;
if (playerLeashable.getLeashDataFromEntityData() == null) {
@ -95,52 +135,70 @@ public class ClientEventHandler {
}
@EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD, modid = LeashedPlayer.MOD_ID)
public static class Mod {
public static class Mod extends ClientEventHandler {
@SubscribeEvent
public static void registerKeyMapping(RegisterKeyMappingsEvent event) {
event.register(ModKeyMapping.KEY_ADD_LEASH_LENGTH);
event.register(ModKeyMapping.KEY_SUB_LEASH_LENGTH);
}
@SubscribeEvent
public static void onAddLayers (EntityRenderersEvent.AddLayers event){
PlayerRenderer renderer = event.getSkin(PlayerSkin.Model.WIDE);
if (renderer instanceof PlayerRenderer playerRenderer) {
playerRenderer.addLayer(new ChestItemLayerRenderer<>(playerRenderer, event.getContext().getEntityRenderDispatcher().getItemInHandRenderer()));
}
PlayerRenderer slimRenderer = event.getSkin(PlayerSkin.Model.SLIM);
if (slimRenderer instanceof PlayerRenderer slimPlayerRenderer) {
slimPlayerRenderer.addLayer(new ChestItemLayerRenderer<>(slimPlayerRenderer, event.getContext().getEntityRenderDispatcher().getItemInHandRenderer()));
}
}
@SubscribeEvent
public static void onRegisterItemProperties(FMLClientSetupEvent event) {
public static void onRegisterItemProperties (FMLClientSetupEvent event){
event.enqueueWork(() -> {
ItemProperties.register(Items.CROSSBOW, ResourceLocation.withDefaultNamespace("leash_rope_arrow"),
((pStack, pLevel, pEntity, pSeed) -> {
ChargedProjectiles chargedProjectiles = pStack.get(DataComponents.CHARGED_PROJECTILES);
return chargedProjectiles != null && (chargedProjectiles.contains(ModItemRegister.LEASH_ROPE_ARROW.get()) || chargedProjectiles.contains(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get())) ? 1.0F : 0.0F;
}));
return chargedProjectiles != null && (chargedProjectiles.contains(ModItemRegister.LEASH_ROPE_ARROW.get()) || chargedProjectiles.contains(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get())) ? 1.0F : 0.0F;}
));
ItemProperties.register(Items.CROSSBOW, ResourceLocation.withDefaultNamespace("nestle_rope_arrow"),
((pStack, pLevel, pEntity, pSeed) -> {
ChargedProjectiles chargedProjectiles = pStack.get(DataComponents.CHARGED_PROJECTILES);
return chargedProjectiles != null && (chargedProjectiles.contains(ModItemRegister.NESTLE_ROPE_ARROW.get())) ? 1.0F : 0.0F;}
));
ItemProperties.register(Items.BOW, ResourceLocation.withDefaultNamespace("leash_rope_arrow_pulling"),
((pStack, pLevel, pEntity, pSeed) ->
(pEntity != null && pEntity.isUsingItem() && pEntity.getUseItem() == pStack && ILeashRopeArrow.isLeashRopeArrow(pStack, pEntity)) ? 1.0F: 0.0F
));
(pEntity != null && pEntity.isUsingItem() && pEntity.getUseItem() == pStack && ILeashRopeArrow.isLeashRopeArrow(pStack, pEntity)) ? 1.0F : 0.0F
));
ItemProperties.register(Items.BOW, ResourceLocation.withDefaultNamespace("nestle_rope_arrow_pulling"),
((pStack, pLevel, pEntity, pSeed) ->
(pEntity != null && pEntity.isUsingItem() && pEntity.getUseItem() == pStack && INestleRopeArrow.isNestleRopeArrow(pStack, pEntity)) ? 1.0F : 0.0F
));
});
}
@SubscribeEvent
public static void RegisterRenderer(EntityRenderersEvent.RegisterRenderers event) {
public static void registerKeyMapping(RegisterKeyMappingsEvent event) {
event.register(ModKeyMapping.KEY_APPLY_TALKAREA_PREFERENCE);
event.register(ModKeyMapping.KEY_ADD_LEASH_LENGTH);
event.register(ModKeyMapping.KEY_SUB_LEASH_LENGTH);
}
@SubscribeEvent
public static void onRegisterRenderer (EntityRenderersEvent.RegisterRenderers event) {
event.registerEntityRenderer(ModEntityRegister.NESTLE_ROPE_ARROW.get(), NestleRopeArrowRenderer::new);
event.registerEntityRenderer(ModEntityRegister.LEASH_ROPE_ARROW.get(), LeashRopeArrowRenderer::new);
event.registerEntityRenderer(ModEntityRegister.SPECTRAL_LEASH_ROPE_ARROW.get(), SpectralLeashRopeArrowRenderer::new);
event.registerEntityRenderer(ModEntityRegister.KID.get(), KidPlayerRenderer::create);
}
@SubscribeEvent
public static void onAddLayers (EntityRenderersEvent.AddLayers event){
PlayerRenderer renderer = event.getSkin(PlayerSkin.Model.WIDE);
if (renderer instanceof PlayerRenderer playerRenderer) {
playerRenderer.addLayer(new ChestItemLayerRenderer<>(playerRenderer, event.getContext().getItemInHandRenderer()));
}
PlayerRenderer slimRenderer = event.getSkin(PlayerSkin.Model.SLIM);
if (slimRenderer instanceof PlayerRenderer slimPlayerRenderer) {
slimPlayerRenderer.addLayer(new ChestItemLayerRenderer<>(slimPlayerRenderer, event.getContext().getItemInHandRenderer()));
}
}
@SubscribeEvent
public static void onRegisterItemColorHandlers (RegisterColorHandlersEvent.Item event){
event.register(
(color, i) -> i > 0
? -1
: color.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).getColor() | 0xFF000000,
: FastColor.ARGB32.opaque(color.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).getColor()),
ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get()
);
}
}
}

View File

@ -1,22 +1,28 @@
package com.r3944realms.leashedplayer;
import com.mojang.brigadier.CommandDispatcher;
import com.r3944realms.leashedplayer.content.commands.LeashCommand;
import com.r3944realms.leashedplayer.content.commands.MotionCommand;
import com.r3944realms.leashedplayer.content.commands.TickCommand;
import com.r3944realms.leashedplayer.content.commands.*;
import com.r3944realms.leashedplayer.content.effects.ModPotionRegister;
import com.r3944realms.leashedplayer.content.entities.LittlePlayer;
import com.r3944realms.leashedplayer.content.entities.ModEntityRegister;
import com.r3944realms.leashedplayer.content.gamerules.GameruleRegistry;
import com.r3944realms.leashedplayer.content.gamerules.Server.OpenTOPNeededModeWhenScreenIsNotNull;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import com.r3944realms.leashedplayer.content.misc.LeadBreakItemBehavior;
import com.r3944realms.leashedplayer.network.client.BooleanGameRuleValueChangeData;
import com.r3944realms.leashedplayer.utils.Logger;
import com.r3944realms.leashedplayer.utils.Util;
import io.github.kunosayo.nestle.init.ModCreativeTab;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.animal.Fox;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.PotionBrewing;
@ -27,9 +33,13 @@ import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.neoforge.event.AnvilUpdateEvent;
import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent;
import net.neoforged.neoforge.event.RegisterCommandsEvent;
import net.neoforged.neoforge.event.brewing.RegisterBrewingRecipesEvent;
import net.neoforged.neoforge.event.entity.EntityAttributeCreationEvent;
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.event.tick.EntityTickEvent;
import net.neoforged.neoforge.network.PacketDistributor;
public class CommonEventHandler {
@ -40,48 +50,37 @@ public class CommonEventHandler {
CommandDispatcher<CommandSourceStack> dispatcher = event.getDispatcher();
LeashCommand.register(dispatcher);
MotionCommand.register(dispatcher);
ChatCommand.register(dispatcher);
TickCommand.register(dispatcher);
DebugCommand.register(dispatcher);
}
@SubscribeEvent
public static void onJoinServer(PlayerEvent.PlayerLoggedInEvent event) {
PacketDistributor.sendToPlayer((ServerPlayer) event.getEntity(),
new BooleanGameRuleValueChangeData(
OpenTOPNeededModeWhenScreenIsNotNull.ID,
GameruleRegistry.getGameruleBoolValue(
event.getEntity().level(),
OpenTOPNeededModeWhenScreenIsNotNull.ID)
)
);
}
@SubscribeEvent
public static void OnRegisterPotionBrewing(RegisterBrewingRecipesEvent event) {
PotionBrewing.Builder builder = event.getBuilder();
builder.addMix(Potions.WATER, Items.SLIME_BALL, ModPotionRegister.NO_LEASH);
}
@SubscribeEvent
public static void OnLivingTickEvent(EntityTickEvent.Post event) {
Entity entity = event.getEntity();
Level level = entity.level();
if (level.isClientSide()) {
return;
}
if (entity instanceof Fox fox) {
if (fox.getMainHandItem().is(ItemTags.ANVIL)) {
fox.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
Util.throwItemTowardsLook(fox, ModItemRegister.NEOFORGE.get(), 0.3f, 0.1f);
fox.playSound(SoundEvents.FOX_EAT);
} else if (fox.getMainHandItem().is(ModItemRegister.NEOFORGE.get())) {
// 繞圈參數
float rotationSpeed = 10.0f; // tick 旋轉的角度
// 計算新的旋轉角度
fox.yBodyRot += rotationSpeed; // 身體旋轉
fox.yHeadRot += rotationSpeed; // 頭部旋轉
fox.yRotO += rotationSpeed; // 當前旋轉角度
fox.yHeadRotO += rotationSpeed; // 頭部的當前旋轉角度
// 確保旋轉角度不超出 360 重置為 0 以便持續旋轉
if (fox.yBodyRot >= 360) fox.yBodyRot -= 360;
if (fox.yHeadRot >= 360) fox.yHeadRot -= 360;
}
}
}
@SubscribeEvent
public static void OnAnvilUpdated(AnvilUpdateEvent event) {
String name = event.getName();
ItemStack left = event.getLeft();
if (left.is(Items.ANVIL) && name != null && name.equals("NeoForge")) {
event.setCost(1);
event.setOutput(ModItemRegister.NEOFORGE.get().getDefaultInstance());
event.setOutput(ModItemRegister.NEOFORGE.get().getDefaultInstance());
} else if (left.is(ModItemRegister.NEOFORGE.get().asItem()) && name != null && name.equals("Forge")) {
ItemStack instance = Items.ANVIL.getDefaultInstance();
instance.set(DataComponents.CUSTOM_NAME, Component.literal("Forge").withStyle(ChatFormatting.BOLD).withStyle(ChatFormatting.AQUA));
@ -89,20 +88,70 @@ public class CommonEventHandler {
event.setCost(1);
}
}
}
@EventBusSubscriber(modid = LeashedPlayer.MOD_ID, bus = EventBusSubscriber.Bus.MOD)
public static class Mod extends CommonEventHandler {
@SubscribeEvent
public static void onCommonSetup(FMLCommonSetupEvent event) {
event.enqueueWork(() -> {
DispenserBlock.registerProjectileBehavior(ModItemRegister.LEASH_ROPE_ARROW.get());
DispenserBlock.registerProjectileBehavior(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get());
DispenserBlock.registerProjectileBehavior(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get());
DispenserBlock.registerBehavior(ModItemRegister.AMETHYST_SHEARS.get(), new LeadBreakItemBehavior());
});
public static void OnLivingTickEvent(EntityTickEvent.Post event) {
Entity entity = event.getEntity();
Level level = entity.level();
if (level.isClientSide()) {
return;
}
if (entity instanceof Fox fox) {
if (fox.getMainHandItem().is(ItemTags.ANVIL)) {
fox.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
Util.throwItemTowardsLook(fox, ModItemRegister.NEOFORGE.get(), 0.3f, 0.1f);
fox.playSound(fox.getEatingSound(ItemStack.EMPTY));
} else if (fox.getMainHandItem().is(ModItemRegister.NEOFORGE.get())) {
// 繞圈參數
float rotationSpeed = 10.0f; // tick 旋轉的角度
// 計算新的旋轉角度
fox.yBodyRot += rotationSpeed; // 身體旋轉
fox.yHeadRot += rotationSpeed; // 頭部旋轉
fox.yRotO += rotationSpeed; // 當前旋轉角度
fox.yHeadRotO += rotationSpeed; // 頭部的當前旋轉角度
// 確保旋轉角度不超出 360 重置為 0 以便持續旋轉
if (fox.yBodyRot >= 360) fox.yBodyRot -= 360;
if (fox.yHeadRot >= 360) fox.yHeadRot -= 360;
}
}
}
}
}
@EventBusSubscriber(modid = LeashedPlayer.MOD_ID, bus = EventBusSubscriber.Bus.MOD)
public static class Mod extends CommonEventHandler {
@SubscribeEvent
public static void onCommonSetup(FMLCommonSetupEvent event) {
event.enqueueWork(() -> {
if (LeashedPlayer.IS_NESTLE_LOADED) {
Logger.logger.info("[LeashedPlayer] Hello, Nestle");
DispenserBlock.registerProjectileBehavior(ModItemRegister.NESTLE_ROPE_ARROW.get());
}
DispenserBlock.registerProjectileBehavior(ModItemRegister.LEASH_ROPE_ARROW.get());
DispenserBlock.registerProjectileBehavior(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get());
DispenserBlock.registerProjectileBehavior(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get());
DispenserBlock.registerBehavior(ModItemRegister.AMETHYST_SHEARS.get(), new LeadBreakItemBehavior());
});
}
@SubscribeEvent
public static void onEntityAttributeEvent(EntityAttributeCreationEvent event) {
event.put(ModEntityRegister.KID.get(), LittlePlayer.createAttributes().build());
}
@SubscribeEvent
public static void onBuiltCreativeModeTabContents(BuildCreativeModeTabContentsEvent event) {
if (LeashedPlayer.IS_NESTLE_LOADED){
CreativeModeTab tab = event.getTab();
if (tab == ModCreativeTab.MAIN_TABS.get()) {
event.accept(ModItemRegister.NESTLE_ROPE_ARROW.get());
}
}
}
}
}

View File

@ -12,6 +12,7 @@ import com.r3944realms.leashedplayer.content.paintings.ModPaintingsRegister;
import com.r3944realms.leashedplayer.content.sounds.ModSoundRegister;
import com.r3944realms.leashedplayer.utils.Util;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.ModList;
import net.neoforged.fml.ModLoadingContext;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.config.ModConfig;
@ -20,24 +21,27 @@ import static com.r3944realms.leashedplayer.utils.Logger.logger;
@Mod(LeashedPlayer.MOD_ID)
public class LeashedPlayer {
public static final String MOD_ID = "leashedplayer";
public static boolean IS_NESTLE_LOADED;
private static Double M1;//拴繩掉落距離倍基數
private static Double M2;//繩箭拴繩掉落距離倍基數
private static Integer M3; //拴绳最小长度
private static Integer M4; //拴绳最大长度
public LeashedPlayer(IEventBus event) {
ModItemRegister.register(event);
ModRecipeRegister.register(event);
ModSoundRegister.register(event);
ModPaintingsRegister.register(event);
ModSoundRegister.register(event);
ModEffectRegister.register(event);
ModPotionRegister.register(event);
ModEntityRegister.register(event);
ModCreativeTab.register(event);
ModCriteriaTriggers.register(event);
ModRecipeRegister.register(event);
initiation();
}
private void initiation() {
logger.info("Initializing LeashedPlayer Mod");
IS_NESTLE_LOADED = ModList.get().isLoaded("nestle");
String leashedPlayerCommonConfig = "LeashedPlayerCommonConfig";
Util.configFileCreate(new String[]{leashedPlayerCommonConfig});
ModLoadingContext.get().getActiveContainer().registerConfig(ModConfig.Type.COMMON, LeashPlayerCommonConfig.SPEC, MOD_ID + "/" + leashedPlayerCommonConfig + "/LeashPlayer.toml");
@ -67,4 +71,5 @@ public class LeashedPlayer {
return M4;
}
}

View File

@ -1,527 +0,0 @@
package com.r3944realms.leashedplayer.client.renders;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.datafixers.util.Either;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import com.r3944realms.leashedplayer.modInterface.ILivingEntityExtension;
import com.r3944realms.leashedplayer.modInterface.IPlayerRenderStateExtension;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.state.EntityRenderState;
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Leashable;
import net.minecraft.world.entity.decoration.LeashFenceKnotEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.entity.vehicle.NewMinecartBehavior;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.joml.Matrix4f;
import java.util.List;
import java.util.UUID;
@OnlyIn(Dist.CLIENT)
public class LeashRendererUtil {
public static void renderLeash(PoseStack poseStack, MultiBufferSource buffer, EntityRenderState.LeashState leashState) {
float f = 0.025F;
float f1 = (float)(leashState.end.x - leashState.start.x);
float f2 = (float)(leashState.end.y - leashState.start.y + 0.2);
float f3 = (float)(leashState.end.z - leashState.start.z);
float f4 = Mth.invSqrt(f1 * f1 + f3 * f3) * 0.025F / 2.0F;
float f5 = f3 * f4;
float f6 = f1 * f4;
poseStack.pushPose();
poseStack.translate(leashState.offset.add(0, -0.2, -0.2));
VertexConsumer vertexconsumer = buffer.getBuffer(RenderType.leash());
Matrix4f matrix4f = poseStack.last().pose();
for (int i = 0; i <= 24; i++) {
addVertexPair(
vertexconsumer,
matrix4f,
f1,
f2,
f3,
leashState.startBlockLight,
leashState.endBlockLight,
leashState.startSkyLight,
leashState.endSkyLight,
0.025F,
0.025F,
f5,
f6,
i,
false
);
}
for (int j = 24; j >= 0; j--) {
addVertexPair(
vertexconsumer,
matrix4f,
f1,
f2,
f3,
leashState.startBlockLight,
leashState.endBlockLight,
leashState.startSkyLight,
leashState.endSkyLight,
0.025F,
0.0F,
f5,
f6,
j,
true
);
}
poseStack.popPose();
}
/**
* <h1>1. 角度与弧度转换</h1>
* {@snippet lang=java :
* double d0 = (double)(pEntity.getPreciseBodyRotation(pPartialTick) * (float)(Math.PI / 180.0)) + (Math.PI / 2);
* }
* <ul>
* <li><code>pEntity.getPreciseBodyRotation(pPartialTick)</code> 返回实体的旋转角度通常是以度为单位/li>
* <li> <code>(Math.PI / 180.0)</code> 是将度数转换为弧度的乘数因为大多数三角函数 <code>cos</code> <code>sin</code>都需要弧度值</li>
* <li><code>+ (Math.PI / 2)</code> 用于将结果平移90度四分之一圆可能是为了校正方向或设置起始方向 </li>
* </ul>
*
* <p>
* <h1> 2. 三角函数计算位移</h1>
* {@snippet lang=java :
* double d1 = Math.cos(d0) * vec31.z + Math.sin(d0) * vec31.x;
* double d2 = Math.sin(d0) * vec31.z - Math.cos(d0) * vec31.x;
* }
* <ul>
* <li><code>d1</code> <code>d2</code> 是利用三角函数 <code>cos</code> <code>sin</code> 计算出来的位移量用于确定实体相对于其旋转的实际位置</li>
* <li><code>Math.cos(d0) * vec31.z</code> <code>Math.sin(d0) * vec31.x</code> 分别计算沿 X Z 轴的位移分量这种计算通常用于旋转一个点或向量</li>
* <li>两个公式结合起来用于旋转平面内的一个点 <code>(vec31.x, vec31.z)</code>从而得到旋转后的新坐标</li>
* </ul>
* <p>
* <h1> 3. 线性插值 (Lerp) </h1>
* {@snippet lang=java :
* double d3 = Mth.lerp(pPartialTick, pEntity.xo, pEntity.getX()) + d1;
* double d4 = Mth.lerp(pPartialTick, pEntity.yo, pEntity.getY()) + vec31.y;
* double d5 = Mth.lerp(pPartialTick, pEntity.zo, pEntity.getZ()) + d2;
* }
* <ul>
* <li><code>Mth.lerp</code> 是线性插值函数通常用于在两个值之间平滑过渡</li>
* <li><code>pEntity.xo</code>, <code>pEntity.yo</code>, <code>pEntity.zo</code> 是实体在上一个刻度tick中的位置 <code>pEntity.getX()</code>, <code>pEntity.getY()</code>, <code>pEntity.getZ()</code> 是当前刻度的位置</li>
* <li><code>pPartialTick</code> 介于 <code>0</code> <code>1</code> 之间用来平滑过渡使得动画更加流畅</li>
* </ul>
* <p>
* <h1> 4. 向量差值 </h1>
* {@snippet lang=java :
* float f = (float)(vec3.x - d3);
* float f1 = (float)(vec3.y - d4);
* float f2 = (float)(vec3.z - d5);
* }
* <ul>
* <li>计算两个点<code>vec3</code> <code>(d3, d4, d5)</code>之间的差值得到的 <code>f</code><code>f1</code><code>f2</code> 是向量差用于后续的渲染计算</li>
* </ul>
* <p>
* <h1> 5. 逆平方根与比例因子 </h1>
* {@snippet lang=java :
* float f4 = Mth.invSqrt(f * f + f2 * f2) * 0.025F / 2.0F;
* }
* <ul>
* <li><code>Mth.invSqrt</code> 计算的是逆平方根通常用于归一化向量或调整比例</li>
* <li><code>f * f + f2 * f2</code> 是计算向量 <code>(f, f2)</code> 的平方和用于得到其长度的平方</li>
* <li>乘以 <code>0.025F / 2.0F</code> 用于缩放结果使得线条在渲染时具有合适的比例</li>
* </ul>
* <p>
* <h1> 6. 循环绘制 </h1>
* {@snippet lang=java :
* for (int i1 = 0; i1 <= 24; i1++) {
* addVertexPair(vertexconsumer, matrix4f, f, f1, f2, i, j, k, l, 0.025F, 0.025F, f5, f6, i1, false);
* }
* }
* <ul>
* <li>循环从 <code>0</code> <code>24</code>用于创建24个顶点对形成一个链状结构或绳索的外观</li>
* <li>每个循环迭代都会更新顶点的位置颜色光照等属性使得链状结构被绘制出来</li>
* </ul>
* <p>
* <h1> 总结 </h1>
* 这些数学运算主要用于计算实体在三维空间中的位置和方向以确保在渲染链状结构如拴住的绳索链条能够跟随实体的移动和旋转并正确显示在图形编程中这些计算非常常见尤其是在处理旋转插值和光照效果时
*/
public static void renderLeash(
com.mojang.blaze3d.vertex.PoseStack poseStack,
net.minecraft.client.renderer.MultiBufferSource bufferSource,
PlayerRenderState playerRenderState
) {
float f = 0.025F;
// 获得绳索持有者的位置
PlayerLeashState leashState = ((IPlayerRenderStateExtension)playerRenderState).getPlayerLeashState();
if (leashState == null)
return;
Vec3 Holder = leashState.pos;//TODO问题修复
Vec3 o = leashState.o;
// 计算实体的朝向角度弧度
float partialTick = playerRenderState.partialTick;
double entityRotationAngleRadians = (double)(leashState.getPreciseBodyRotation(partialTick) * (float) (Math.PI / 180.0)) + (Math.PI / 2);
// 计算实体的绳索偏移此处add偏移让渲染拴绳显示在玩家头部下大约在脖子处
// Logger.logger.info("eyeHeight:{}",playerRenderState.eyeHeight);
Vec3 cameraEntityLeashOffset = new Vec3(0.0, leashState.eyeHeight , playerRenderState.boundingBoxWidth * 0.4F).add(0, -0.2, -0.2);
double leashOffsetX = Math.cos(entityRotationAngleRadians) * cameraEntityLeashOffset.z + Math.sin(entityRotationAngleRadians) * cameraEntityLeashOffset.x;
double leashOffsetZ = Math.sin(entityRotationAngleRadians) * cameraEntityLeashOffset.z - Math.cos(entityRotationAngleRadians) * cameraEntityLeashOffset.x;
// 计算实体当前的实际位置
double entityPosX = Mth.lerp(partialTick, o.x, playerRenderState.x) + leashOffsetX;
double entityPosY = Mth.lerp(partialTick, o.y, playerRenderState.y) + cameraEntityLeashOffset.y;
double entityPosZ = Mth.lerp(partialTick, o.z, playerRenderState.z) + leashOffsetZ;
// 计算绳索的相对位置差
float deltaX = (float)(Holder.x - entityPosX);
float deltaY = (float)(Holder.y - entityPosY);
float deltaZ = (float)(Holder.z - entityPosZ);
// 计算比例因子用于调节绳索的粗细
float leashLengthRatio = Mth.invSqrt(deltaX * deltaX + deltaZ * deltaZ) * 0.025F / 2.0F;
// 计算比例因子用于调节绳索的粗细
float leashXZScaleX = deltaZ * leashLengthRatio;
float leashXZScaleZ = deltaX * leashLengthRatio;
poseStack.pushPose();
poseStack.translate(leashOffsetX, cameraEntityLeashOffset.y,leashOffsetZ);
VertexConsumer vertexconsumer = bufferSource.getBuffer(RenderType.leash());
Matrix4f matrix4f = poseStack.last().pose();
for (int i = 0; i <= 24; i++) {
addVertexPair(
vertexconsumer,
matrix4f,
deltaX,
deltaY,
deltaZ,
leashState.startBlockLight,
leashState.endBlockLight,
leashState.startSkyLight,
leashState.endSkyLight,
0.025F,
0.025F,
leashXZScaleX,
leashXZScaleZ,
i,
false
);
}
for (int j = 24; j >= 0; j--) {
addVertexPair(
vertexconsumer,
matrix4f,
deltaX,
deltaY,
deltaZ,
leashState.startBlockLight,
leashState.endBlockLight,
leashState.startSkyLight,
leashState.endSkyLight,
0.025F,
0.0F,
leashXZScaleX,
leashXZScaleZ,
j,
true
);
}
poseStack.popPose();
}
protected static void addVertexPair(
VertexConsumer buffer,
Matrix4f pose,
float startX,
float startY,
float startZ,
int entityBlockLight,
int holderBlockLight,
int entitySkyLight,
int holderSkyLight,
float yOffset,
float dy,
float dx,
float dz,
int index,
boolean reverse
) {
float f = (float)index / 24.0F;
int i = (int)Mth.lerp(f, (float)entityBlockLight, (float)holderBlockLight);
int j = (int)Mth.lerp(f, (float)entitySkyLight, (float)holderSkyLight);
int k = LightTexture.pack(i, j);
float f1 = index % 2 == (reverse ? 1 : 0) ? 0.7F : 1.0F;
float f2 = 0.5F * f1;
float f3 = 0.4F * f1;
float f4 = 0.3F * f1;
float f5 = startX * f;
float f6 = startY > 0.0F ? startY * f * f : startY - startY * (1.0F - f) * (1.0F - f);
float f7 = startZ * f;
buffer.addVertex(pose, f5 - dx, f6 + dy, f7 + dz).setColor(f2, f3, f4, 1.0F).setLight(k);
buffer.addVertex(pose, f5 + dx, f6 + yOffset - dy, f7 - dz).setColor(f2, f3, f4, 1.0F).setLight(k);
}
public static <E extends net.minecraft.world.entity.Entity> void renderLeashForCamera(
Camera camera,
float partialTick,
com.mojang.blaze3d.vertex.PoseStack poseStack,
net.minecraft.client.renderer.MultiBufferSource bufferSource,
E leashHolder,
Vec3 holderOffset
) {
poseStack.pushPose();
// Logger.logger.info("eyeHeight{}", camera.getEntity().getEyeHeight());
// 获得绳索持有者的位置
Vec3 leashHolderPosition = leashHolder.getRopeHoldPosition(partialTick).add(holderOffset);
// 获取当前观察的实体
Entity cameraEntity = camera.getEntity();
// 计算实体的朝向角度弧度
double entityRotationAngleRadians = (double)(cameraEntity.getPreciseBodyRotation(partialTick) * (float) (Math.PI / 180.0)) + (Math.PI / 2);
// 计算实体的绳索偏移此处add偏移让渲染拴绳显示在玩家头部下大约在脖子处
Vec3 cameraEntityLeashOffset = cameraEntity.getLeashOffset(partialTick).add(0, -0.2, -0.5);
double leashOffsetX = Math.cos(entityRotationAngleRadians) * cameraEntityLeashOffset.z + Math.sin(entityRotationAngleRadians) * cameraEntityLeashOffset.x;
double leashOffsetZ = Math.sin(entityRotationAngleRadians) * cameraEntityLeashOffset.z - Math.cos(entityRotationAngleRadians) * cameraEntityLeashOffset.x;
// 计算实体当前的实际位置
double entityPosX = Mth.lerp(partialTick, cameraEntity.xo, cameraEntity.getX()) + leashOffsetX;
double entityPosY = Mth.lerp(partialTick, cameraEntity.yo, cameraEntity.getY()) + cameraEntityLeashOffset.y;
double entityPosZ = Mth.lerp(partialTick, cameraEntity.zo, cameraEntity.getZ()) + leashOffsetZ;
// 在当前变换矩阵上应用偏移
poseStack.translate(leashOffsetX, cameraEntityLeashOffset.y , leashOffsetZ);
// 计算绳索的相对位置差
float deltaX = (float)(leashHolderPosition.x - entityPosX);
float deltaY = (float)(leashHolderPosition.y - entityPosY);
float deltaZ = (float)(leashHolderPosition.z - entityPosZ);
// 获取顶点消费者用于绘制绳索
VertexConsumer vertexConsumer = bufferSource.getBuffer(RenderType.leash());
Matrix4f matrix = poseStack.last().pose();
// 计算比例因子用于调节绳索的粗细
float leashLengthRatio = Mth.invSqrt(deltaX * deltaX + deltaZ * deltaZ) * 0.025F / 2.0F;
float leashXZScaleX = deltaZ * leashLengthRatio;
float leashXZScaleZ = deltaX * leashLengthRatio;
// 获取光照信息
BlockPos cameraEntityBlockPos = BlockPos.containing(cameraEntity.getEyePosition(partialTick));
BlockPos leashHolderBlockPos = BlockPos.containing(leashHolder.getEyePosition(partialTick));
int cameraEntityBlockLightLevel = 0;
int leashHolderBlockLightLevel = 0; //getBlockLightLevel(leashHolder, leashHolderBlockPos);
int cameraEntitySkyLightLevel = cameraEntity.level().getBrightness(LightLayer.SKY, cameraEntityBlockPos);
int leashHolderSkyLightLevel = cameraEntity.level().getBrightness(LightLayer.SKY, leashHolderBlockPos);
// 绘制绳索的上半部分
for (int segment = 0; segment <= 24; segment++) {
addVertexPair(vertexConsumer, matrix, deltaX, deltaY, deltaZ, cameraEntityBlockLightLevel, leashHolderBlockLightLevel, cameraEntitySkyLightLevel, leashHolderSkyLightLevel, 0.025F, 0.025F, leashXZScaleX, leashXZScaleZ, segment, false);
}
// 绘制绳索的下半部分
for (int segment = 24; segment >= 0; segment--) {
addVertexPair(vertexConsumer, matrix, deltaX, deltaY, deltaZ, cameraEntityBlockLightLevel, leashHolderBlockLightLevel, cameraEntitySkyLightLevel, leashHolderSkyLightLevel, 0.025F, 0.0F, leashXZScaleX, leashXZScaleZ, segment, true);
}
poseStack.popPose();
}
public static void levelRenderLeash(ClientLevel level, Camera pCamera, PoseStack poseStack, MultiBufferSource.BufferSource multibuffersource$buffersource) {
for(Entity entity : level.entitiesForRendering()) {
//对于玩家实体拴绳渲染从第一人称视角
if (entity instanceof AbstractClientPlayer abstractClientPlayer) {
if(!(pCamera.getEntity() instanceof AbstractClientPlayer)) continue;
Minecraft mc = Minecraft.getInstance();
if (mc.options.getCameraType().isFirstPerson()) {
Leashable.LeashData leashDataFromEntityData = ((PlayerLeashable) abstractClientPlayer).getLeashDataFromEntityData();
if(leashDataFromEntityData == null) continue;
Either<UUID, BlockPos> delayedLeashInfo = leashDataFromEntityData.delayedLeashInfo;
if(delayedLeashInfo != null) {
float partialTickTime = pCamera.getPartialTickTime();
Vec3 position = pCamera.getPosition();
double dX = Mth.lerp(partialTickTime, abstractClientPlayer.xOld, abstractClientPlayer.getX()) - position.x;
double dY = Mth.lerp(partialTickTime, abstractClientPlayer.yOld, abstractClientPlayer.getY()) - position.y;
double dZ = Mth.lerp(partialTickTime, abstractClientPlayer.zOld, abstractClientPlayer.getZ()) - position.z;
Vec3 vec3 = getRenderOffset(entity, partialTickTime);
double dX_ = dX + vec3.x();
double dY_ = dY + vec3.y();
double dZ_ = dZ + vec3.z();
poseStack.pushPose();
poseStack.translate(dX_, dY_, dZ_);
if (delayedLeashInfo.right().isPresent() && delayedLeashInfo.left().isEmpty()) {
renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, LeashFenceKnotEntity.getOrCreateKnot(level, delayedLeashInfo.right().get()), Vec3.ZERO);
} else if (delayedLeashInfo.right().isEmpty() && delayedLeashInfo.left().isPresent()) {
Player playerByUUID = level.getPlayerByUUID(delayedLeashInfo.left().get());
if (playerByUUID != null) {
renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, playerByUUID, Vec3.ZERO);
} else {
double MaxLeashLength = ((ILivingEntityExtension) abstractClientPlayer).getLeashLength() * LeashedPlayer.M1() * LeashedPlayer.M2();
List<Entity> entities = level.getEntities(
null,
new AABB(
abstractClientPlayer.getX() - MaxLeashLength,
abstractClientPlayer.getY() - MaxLeashLength,
abstractClientPlayer.getZ() - MaxLeashLength,
abstractClientPlayer.getX() + MaxLeashLength,
abstractClientPlayer.getY() + MaxLeashLength,
abstractClientPlayer.getZ() + MaxLeashLength
)
);
Entity holder = null;
for (Entity entity_ : entities) {
if(entity_.getUUID().equals(delayedLeashInfo.left().get())) {
holder = entity_;
break;
}
}
if (holder != null) {
if(holder instanceof LeashRopeArrow) {
renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, holder, new Vec3(0.,-0.09, 0));//TODO: 待擴展Vec3吗
}
else renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, holder, Vec3.ZERO);
}
}
break;
}
}
}
}
}
}
public static Vec3 getRenderOffset(Entity entity, float partialTickTime) {
Vec3 ret = Vec3.ZERO;
if(entity.isPassenger()
&& entity.getVehicle() instanceof AbstractMinecart abstractminecart
&& abstractminecart.getBehavior() instanceof NewMinecartBehavior newminecartbehavior
&& newminecartbehavior.cartHasPosRotLerp()
) {
double d2 = Mth.lerp(partialTickTime, abstractminecart.xOld, abstractminecart.getX());
double d0 = Mth.lerp(partialTickTime, abstractminecart.yOld, abstractminecart.getY());
double d1 = Mth.lerp(partialTickTime, abstractminecart.zOld, abstractminecart.getZ());
ret = newminecartbehavior.getCartLerpPosition(partialTickTime).subtract(new Vec3(d2, d0, d1));
}
return ret;
}
public static void createPlayerLeashState(AbstractClientPlayer abstractClientPlayer, IPlayerRenderStateExtension playerRenderState, float partialTick) {
Leashable.LeashData leashDataFromEntityData = ((PlayerLeashable) abstractClientPlayer).getLeashDataFromEntityData();
Leashable.LeashData leashData = ((PlayerLeashable) abstractClientPlayer).getLeashData();
PlayerRenderState playerRs = (PlayerRenderState)playerRenderState;
if (leashDataFromEntityData != null) {
Entity leashHolder = leashDataFromEntityData.leashHolder;
Either<UUID, BlockPos> delayedLeashInfo = leashDataFromEntityData.delayedLeashInfo;
PlayerLeashState playerLeashState = new PlayerLeashState();
if (delayedLeashInfo != null) {
createPlayerLeashState_(abstractClientPlayer, playerRenderState, leashDataFromEntityData, delayedLeashInfo, playerLeashState, partialTick);
} else if(leashHolder != null) {
createPlayerLeashState__(abstractClientPlayer, playerRenderState, leashHolder, playerLeashState, partialTick);
} else {
playerRenderState.setPlayerLeashState(null);
}
} else if(leashData != null) {
playerRs.leashState = null;
Entity leashHolder = ((PlayerLeashable) abstractClientPlayer).getLeashHolder();
PlayerLeashState playerLeashState = playerRenderState.getPlayerLeashState();
if (leashHolder != null & playerLeashState != null) {
float f = leashHolder.getPreciseBodyRotation(partialTick) * (float) (Math.PI / 180.0);
Vec3 vec3 = abstractClientPlayer.getLeashOffset(partialTick).yRot(-f);
BlockPos blockpos1 = BlockPos.containing(abstractClientPlayer.getEyePosition(partialTick));
BlockPos blockpos = BlockPos.containing(leashHolder.getEyePosition(partialTick));
playerLeashState.vanilaLeashState = new EntityRenderState.LeashState();
EntityRenderState.LeashState entityrenderstate$leashstate = playerLeashState.vanilaLeashState;
entityrenderstate$leashstate.offset = vec3;
entityrenderstate$leashstate.start = abstractClientPlayer.getPosition(partialTick).add(vec3);
entityrenderstate$leashstate.end = leashHolder.getRopeHoldPosition(partialTick);
entityrenderstate$leashstate.startBlockLight = getBlockLightLevel(abstractClientPlayer, blockpos1);
entityrenderstate$leashstate.endBlockLight = getBlockLightLevel(leashHolder, blockpos);
entityrenderstate$leashstate.startSkyLight = abstractClientPlayer.level().getBrightness(LightLayer.SKY, blockpos1);
entityrenderstate$leashstate.endSkyLight = abstractClientPlayer.level().getBrightness(LightLayer.SKY, blockpos);
} else {
playerRenderState.setPlayerLeashState(null);
}
} else {
playerRenderState.setPlayerLeashState(null);
}
}
private static <T extends Entity> int getBlockLightLevel(T entity, BlockPos pos) {
return entity.isOnFire() ? 15 : entity.level().getBrightness(LightLayer.BLOCK, pos);
}
private static void createPlayerLeashState__(AbstractClientPlayer abstractClientPlayer, IPlayerRenderStateExtension playerRenderState, Entity leashHolder, PlayerLeashState playerLeashState, float partialTick) {
playerLeashState.pos = leashHolder.position().add(0.0, leashHolder.getEyeHeight() * 0.6, -0.2);
playerLeashState.o = abstractClientPlayer.getPosition(partialTick);
playerLeashState.yRotO = abstractClientPlayer.yRotO;
playerLeashState.yRot = abstractClientPlayer.getYRot();
playerLeashState.eyeHeight = abstractClientPlayer.getEyeHeight();
playerRenderState.setPlayerLeashState(playerLeashState);
}
private static void createPlayerLeashState_(AbstractClientPlayer abstractClientPlayer, IPlayerRenderStateExtension playerRenderState, Leashable.LeashData leashDataFromEntityData, Either<UUID, BlockPos> delayedLeashInfo, PlayerLeashState playerLeashState, float partialTick) {
Minecraft mc = Minecraft.getInstance();
ClientLevel level = mc.level;
if (delayedLeashInfo.right().isPresent() && delayedLeashInfo.left().isEmpty()) {
assert level != null;
playerLeashState.pos = delayedLeashInfo.right().get().getCenter();
} else if (delayedLeashInfo.right().isEmpty() && delayedLeashInfo.left().isPresent()) {
assert level != null;
Player playerByUUID = level.getPlayerByUUID(delayedLeashInfo.left().get());
if (playerByUUID != null) {
playerLeashState.pos = playerByUUID.position().add(0.0, playerByUUID.getEyeHeight() * 0.6, 0);
} else {
double breakDistanceTime = (leashDataFromEntityData.leashHolder instanceof LeashRopeArrow) ? LeashedPlayer.M1() * LeashedPlayer.M2() : LeashedPlayer.M1();
double MaxLeashLength = ((ILivingEntityExtension) abstractClientPlayer).getLeashLength() * breakDistanceTime;
List<Entity> entities = level.getEntities(
null,
new AABB(
abstractClientPlayer.getX() - MaxLeashLength * LeashedPlayer.M2(),
abstractClientPlayer.getY() - MaxLeashLength * LeashedPlayer.M2(),
abstractClientPlayer.getZ() - MaxLeashLength * LeashedPlayer.M2(),
abstractClientPlayer.getX() + MaxLeashLength * LeashedPlayer.M2(),
abstractClientPlayer.getY() + MaxLeashLength * LeashedPlayer.M2(),
abstractClientPlayer.getZ() + MaxLeashLength * LeashedPlayer.M2()
)
);
Entity holder = null;
for (Entity entity_ : entities) {
if (entity_.getUUID().equals(delayedLeashInfo.left().get())) {
holder = entity_;
break;
}
}
if (holder != null) {
playerLeashState.pos = holder.position().add(0.0, holder.getEyeHeight() * 0.6, 0);//TODO: 待擴展Vec3
} else {
playerLeashState.pos = abstractClientPlayer.position();
}
}
}
playerLeashState.o = abstractClientPlayer.getPosition(partialTick);
playerLeashState.yRotO = abstractClientPlayer.yRotO;
playerLeashState.yRot = abstractClientPlayer.getYRot();
playerLeashState.eyeHeight = abstractClientPlayer.getEyeHeight();
playerRenderState.setPlayerLeashState(playerLeashState);
}
}

View File

@ -1,41 +0,0 @@
package com.r3944realms.leashedplayer.client.renders;
import net.minecraft.client.renderer.entity.state.EntityRenderState;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import javax.annotation.Nullable;
@OnlyIn(Dist.CLIENT)
public class PlayerLeashState {
public Vec3 o, pos, offset;
public float yRotO, yRot;
public float eyeHeight;
public int startBlockLight;
public int endBlockLight;
public int startSkyLight;
public int endSkyLight;
@Nullable
public EntityRenderState.LeashState vanilaLeashState;
public float getPreciseBodyRotation(float pPartialTick) {
return Mth.lerp(pPartialTick, this.yRotO, this.yRot);
}
public PlayerLeashState() {
this.offset = Vec3.ZERO;
this.o = Vec3.ZERO;
this.pos = Vec3.ZERO;
this.yRot = 0.0f;
this.yRotO = 0.0f;
this.eyeHeight = 0.0f;
this.startBlockLight = 0;
this.endBlockLight = 0;
this.startSkyLight = 15;
this.endSkyLight = 15;
this.vanilaLeashState = null;
}
}

View File

@ -1,13 +0,0 @@
package com.r3944realms.leashedplayer.client.renders;
import net.minecraft.world.entity.LivingEntity;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class PlayerSlotItemLayerState {
public LivingEntity entity;
public PlayerSlotItemLayerState(LivingEntity entity) {
this.entity = entity;
}
}

View File

@ -2,118 +2,113 @@ package com.r3944realms.leashedplayer.client.renders.entities;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import com.r3944realms.leashedplayer.modInterface.IPlayerRenderStateExtension;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.renderer.ItemInHandRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.client.renderer.entity.layers.RenderLayer;
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;
public class ChestItemLayerRenderer<S extends PlayerRenderState, M extends EntityModel<S>> extends RenderLayer<S, M> {
public class ChestItemLayerRenderer<T extends LivingEntity, M extends EntityModel<T>> extends RenderLayer<T, M> {
private final ItemInHandRenderer heldItemRenderer;
public ChestItemLayerRenderer(RenderLayerParent<S, M> context, ItemInHandRenderer heldItemRenderer) {
public ChestItemLayerRenderer(RenderLayerParent<T, M> context, ItemInHandRenderer heldItemRenderer) {
super(context);
this.heldItemRenderer = heldItemRenderer;
}
@Override
public void render(@NotNull PoseStack poseStack, @NotNull MultiBufferSource bufferSource, int packedLight, @NotNull S renderState, float yRot, float xRot) {
public void render(@NotNull PoseStack matrices, @NotNull MultiBufferSource vertexConsumers, int light, @NotNull T entity, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
ItemDisplayContext mode = ItemDisplayContext.FIXED;
IPlayerRenderStateExtension rs = (IPlayerRenderStateExtension) renderState;
LivingEntity entity = rs.getPlayerSlotItemLayerState().entity;
ItemStack chestStack = entity.getItemBySlot(EquipmentSlot.CHEST);
if (!chestStack.isEmpty()) {
if (!(entity.getEquipmentSlotForItem(chestStack).equals(EquipmentSlot.CHEST))) {
poseStack.pushPose();
((PlayerModel) this.getParentModel()).body.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.translate(0, -0.24f, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, poseStack, bufferSource, packedLight);
poseStack.scale(1.01f, 1.01f, 1.01f);
poseStack.translate(0, -1 / 4f, 0);
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, poseStack, bufferSource, packedLight);
poseStack.popPose();
poseStack.pushPose();
((PlayerModel) this.getParentModel()).rightArm.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.scale(2/3f, 2/3f, 2/3f);
poseStack.translate(-1/12f, 0, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, poseStack, bufferSource, packedLight);
poseStack.scale(0.99f, 0.99f, 0.99f);
poseStack.translate(0, -1/2f, 0);
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, poseStack, bufferSource, packedLight);
poseStack.popPose();
poseStack.pushPose();
((PlayerModel) this.getParentModel()).leftArm.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.scale(2/3f, 2/3f, 2/3f);
poseStack.translate(1/12f, 0, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, poseStack, bufferSource, packedLight);
poseStack.scale(0.99f, 0.99f, 0.99f);
poseStack.translate(0, -1/2f, 0);
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, poseStack, bufferSource, packedLight);
poseStack.popPose();
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).body.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.translate(0, -1 / 4f, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, matrices, vertexConsumers, light);
matrices.scale(1.01f, 1.01f, 1.01f);
matrices.translate(0, -1 / 4f, 0);
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).rightArm.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.scale(2/3f, 2/3f, 2/3f);
matrices.translate(-1/12f, 0, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, matrices, vertexConsumers, light);
matrices.scale(0.99f, 0.99f, 0.99f);
matrices.translate(0, -1/2f, 0);
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).leftArm.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.scale(2/3f, 2/3f, 2/3f);
matrices.translate(1/12f, 0, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, matrices, vertexConsumers, light);
matrices.scale(0.99f, 0.99f, 0.99f);
matrices.translate(0, -1/2f, 0);
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
}
}
ItemStack legsStack = entity.getItemBySlot(EquipmentSlot.LEGS);
if (!legsStack.isEmpty()) {
if (!(entity.getEquipmentSlotForItem(legsStack).equals(EquipmentSlot.LEGS))) {
poseStack.pushPose();
((PlayerModel) this.getParentModel()).rightLeg.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.scale(2/3f, 2/3f, 2/3f);
poseStack.translate(0, -1/6f, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, legsStack, mode, false, poseStack, bufferSource, packedLight);
poseStack.scale(1.01f, 1.01f, 1.01f);
poseStack.translate(0, -1/3f, 0);
this.heldItemRenderer.renderItem(entity, legsStack, mode, false, poseStack, bufferSource, packedLight);
poseStack.popPose();
poseStack.pushPose();
((PlayerModel) this.getParentModel()).leftLeg.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.scale(2/3f, 2/3f, 2/3f);
poseStack.translate(0, -1/6f, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, legsStack, mode, false, poseStack, bufferSource, packedLight);
poseStack.scale(1.01f, 1.01f, 1.01f);
poseStack.translate(0, -1/3f, 0);
this.heldItemRenderer.renderItem(entity, legsStack, mode, false, poseStack, bufferSource, packedLight);
poseStack.popPose();
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).rightLeg.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.scale(2/3f, 2/3f, 2/3f);
matrices.translate(0, -1/6f, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, legsStack, mode, false, matrices, vertexConsumers, light);
matrices.scale(1.01f, 1.01f, 1.01f);
matrices.translate(0, -1/3f, 0);
this.heldItemRenderer.renderItem(entity, legsStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).leftLeg.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.scale(2/3f, 2/3f, 2/3f);
matrices.translate(0, -1/6f, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, legsStack, mode, false, matrices, vertexConsumers, light);
matrices.scale(1.01f, 1.01f, 1.01f);
matrices.translate(0, -1/3f, 0);
this.heldItemRenderer.renderItem(entity, legsStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
}
}
ItemStack feetStack = entity.getItemBySlot(EquipmentSlot.FEET);
if (!feetStack.isEmpty()) {
if (!(entity.getEquipmentSlotForItem(feetStack).equals(EquipmentSlot.FEET))) {
poseStack.pushPose();
((PlayerModel) this.getParentModel()).rightLeg.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.scale(0.75f, 0.75f, 0.75f);
poseStack.translate(0, -0.8f, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, feetStack, mode, false, poseStack, bufferSource, packedLight);
poseStack.popPose();
poseStack.pushPose();
((PlayerModel) this.getParentModel()).leftLeg.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.scale(0.75f, 0.75f, 0.75f);
poseStack.translate(0, -0.8f, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, feetStack, mode, false, poseStack, bufferSource, packedLight);
poseStack.popPose();
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).rightLeg.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.scale(0.75f, 0.75f, 0.75f);
matrices.translate(0, -0.8f, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, feetStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).leftLeg.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.scale(0.75f, 0.75f, 0.75f);
matrices.translate(0, -0.8f, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, feetStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
}
}
}

View File

@ -0,0 +1,107 @@
package com.r3944realms.leashedplayer.client.renders.entities;
import com.mojang.blaze3d.vertex.PoseStack;
import com.r3944realms.leashedplayer.content.entities.LittlePlayer;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.model.geom.ModelLayers;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.HumanoidMobRenderer;
import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.item.CrossbowItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.UseAnim;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
@OnlyIn(Dist.CLIENT)
public class KidPlayerRenderer extends HumanoidMobRenderer<LittlePlayer, PlayerModel<LittlePlayer>> {
public static @NotNull KidPlayerRenderer create(@NotNull EntityRendererProvider.Context pContext) {
if (pContext instanceof PlayerContext pc) {
return new KidPlayerRenderer(pc);
}
return new KidPlayerRenderer(new PlayerContext(pContext, true));
}
public static class PlayerContext extends EntityRendererProvider.Context {
boolean isUseSlimModel;
public PlayerContext(EntityRendererProvider.Context pContext, boolean pIsSlimModel) {
super(pContext.getEntityRenderDispatcher(), pContext.getItemRenderer(), pContext.getBlockRenderDispatcher(), pContext.getItemInHandRenderer(), pContext.getResourceManager(), pContext.getModelSet(), pContext.getFont());
this.isUseSlimModel = pIsSlimModel;
}
public boolean isUseSlimModel() {
return isUseSlimModel;
}
}
public KidPlayerRenderer(PlayerContext pContext) {
super(pContext, new PlayerModel<>(pContext.bakeLayer(pContext.isUseSlimModel() ? ModelLayers.PLAYER_SLIM : ModelLayers.PLAYER), pContext.isUseSlimModel()), 0.5F);
this.addLayer(new HumanoidArmorLayer<>(this,
new HumanoidModel<>(pContext.bakeLayer(ModelLayers.PLAYER_INNER_ARMOR)),
new HumanoidModel<>(pContext.bakeLayer(ModelLayers.PLAYER_OUTER_ARMOR)),
pContext.getModelManager()
));
}
@Override
public @NotNull ResourceLocation getTextureLocation(@NotNull LittlePlayer pEntity) {
return pEntity.getSkin().texture();
}
public void render(@NotNull LittlePlayer companion, float companionYaw, float pPartialTicks, @NotNull PoseStack pMatrixStack,
@NotNull MultiBufferSource pBuffer, int pPackedLight) {
this.setModelProperties(companion);
super.render(companion, companionYaw, pPartialTicks, pMatrixStack, pBuffer, pPackedLight);
}
private void setModelProperties(LittlePlayer companion) {
PlayerModel<LittlePlayer> companionModel = this.getModel();
HumanoidModel.ArmPose humanoidmodel$armpose = getArmPose(companion, InteractionHand.MAIN_HAND);
HumanoidModel.ArmPose humanoidmodel$armpose1 = getArmPose(companion, InteractionHand.OFF_HAND);
if (companion.getMainArm() == HumanoidArm.RIGHT) {
companionModel.rightArmPose = humanoidmodel$armpose;
companionModel.leftArmPose = humanoidmodel$armpose1;
} else {
companionModel.rightArmPose = humanoidmodel$armpose1;
companionModel.leftArmPose = humanoidmodel$armpose;
}
}
private static HumanoidModel.ArmPose getArmPose(LittlePlayer companion, InteractionHand hand) {
ItemStack itemstack = companion.getItemInHand(hand);
if (itemstack.isEmpty()) {
return HumanoidModel.ArmPose.EMPTY;
} else {
if (companion.getUsedItemHand() == hand && companion.getUseItemRemainingTicks() > 0) {
UseAnim useanim = itemstack.getUseAnimation();
if (useanim == UseAnim.BOW) {
return HumanoidModel.ArmPose.BOW_AND_ARROW;
}
if (useanim == UseAnim.CROSSBOW && hand == companion.getUsedItemHand()) {
return HumanoidModel.ArmPose.CROSSBOW_CHARGE;
}
} else if (!companion.swinging && itemstack.is(Items.CROSSBOW) && CrossbowItem.isCharged(itemstack)) {
return HumanoidModel.ArmPose.CROSSBOW_HOLD;
}
return HumanoidModel.ArmPose.ITEM;
}
}
protected void scale(@NotNull LittlePlayer player, PoseStack pPoseStack, float pPartialTickTime) {
float f = 0.9375F;
pPoseStack.scale(f, f, f);
}
}

View File

@ -4,27 +4,20 @@ import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import net.minecraft.client.renderer.entity.ArrowRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.state.ArrowRenderState;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
@OnlyIn(Dist.CLIENT)
public class LeashRopeArrowRenderer extends ArrowRenderer<LeashRopeArrow, ArrowRenderState> {
public class LeashRopeArrowRenderer extends ArrowRenderer<LeashRopeArrow> {
public static final ResourceLocation LEASH_ROPE_ARROW = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "textures/entity/projectiles/leash_rope_arrow.png");
public LeashRopeArrowRenderer(EntityRendererProvider.Context pContext) {
super(pContext);
}
@Override
public @NotNull ArrowRenderState createRenderState() {
return new ArrowRenderState();
}
@Override
protected @NotNull ResourceLocation getTextureLocation(@NotNull ArrowRenderState arrowRenderState) {
public @NotNull ResourceLocation getTextureLocation(@NotNull LeashRopeArrow pEntity) {
return LEASH_ROPE_ARROW;
}
}

View File

@ -0,0 +1,21 @@
package com.r3944realms.leashedplayer.client.renders.entities;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.entities.NestleRopeArrow;
import net.minecraft.client.renderer.entity.ArrowRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.NotNull;
public class NestleRopeArrowRenderer extends ArrowRenderer<NestleRopeArrow> {
public static final ResourceLocation NESTLE_ROPE_ARROW = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "textures/entity/projectiles/nestle_rope_arrow.png");
public NestleRopeArrowRenderer(EntityRendererProvider.Context pContext) {
super(pContext);
}
@Override
public @NotNull ResourceLocation getTextureLocation(@NotNull NestleRopeArrow pEntity) {
return NESTLE_ROPE_ARROW;
}
}

View File

@ -4,28 +4,20 @@ import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.entities.SpectralLeashRopeArrow;
import net.minecraft.client.renderer.entity.ArrowRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.state.ArrowRenderState;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
@OnlyIn(Dist.CLIENT)
public class SpectralLeashRopeArrowRenderer extends ArrowRenderer<SpectralLeashRopeArrow, ArrowRenderState> {
public class SpectralLeashRopeArrowRenderer extends ArrowRenderer<SpectralLeashRopeArrow> {
public static final ResourceLocation SPECTRAL_LEASH_ROPE_ARROW = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "textures/entity/projectiles/spectral_leash_rope_arrow.png");
public SpectralLeashRopeArrowRenderer(EntityRendererProvider.Context pContext) {
super(pContext);
}
@Override
public @NotNull ArrowRenderState createRenderState() {
return new ArrowRenderState();
}
@Override
protected @NotNull ResourceLocation getTextureLocation(@NotNull ArrowRenderState arrowRenderState) {
public @NotNull ResourceLocation getTextureLocation(@NotNull SpectralLeashRopeArrow pEntity) {
return SPECTRAL_LEASH_ROPE_ARROW;
}
}

View File

@ -0,0 +1,32 @@
package com.r3944realms.leashedplayer.compat.jei;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.compat.jei.common.PotionSubtypeInterpreter;
import com.r3944realms.leashedplayer.compat.jei.crafting.TippedLeashArrowRecipeMaker;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.constants.RecipeTypes;
import mezz.jei.api.registration.IRecipeRegistration;
import mezz.jei.api.registration.ISubtypeRegistration;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.NotNull;
@JeiPlugin
public class JEIPlugin implements IModPlugin {
private static final ResourceLocation UID = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "jei_plugin");
@Override
public @NotNull ResourceLocation getPluginUid() {
return UID;
}
@Override
public void registerItemSubtypes(ISubtypeRegistration registration) {
registration.registerSubtypeInterpreter(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get(), PotionSubtypeInterpreter.INSTANCE);
}
@Override
public void registerRecipes(@NotNull IRecipeRegistration registration) {
registration.addRecipes(RecipeTypes.CRAFTING, TippedLeashArrowRecipeMaker.createRecipes());
}
}

View File

@ -0,0 +1,28 @@
package com.r3944realms.leashedplayer.compat.jei.common;
import mezz.jei.api.ingredients.subtypes.IIngredientSubtypeInterpreter;
import mezz.jei.api.ingredients.subtypes.UidContext;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.alchemy.PotionContents;
import org.jetbrains.annotations.NotNull;
public class PotionSubtypeInterpreter implements IIngredientSubtypeInterpreter<ItemStack> {
public static final PotionSubtypeInterpreter INSTANCE = new PotionSubtypeInterpreter();
private PotionSubtypeInterpreter() {
}
@Override
public @NotNull String apply(ItemStack itemStack, @NotNull UidContext context) {
if (itemStack.getComponentsPatch().isEmpty()) {
return IIngredientSubtypeInterpreter.NONE;
}
PotionContents contents = itemStack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
String itemDescriptionId = itemStack.getItem().getDescriptionId();
String potionEffectId = contents.potion().map(Holder::getRegisteredName).orElse("none");
return itemDescriptionId + ".effect_id." + potionEffectId;
}
}

View File

@ -0,0 +1,77 @@
package com.r3944realms.leashedplayer.compat.jei.crafting;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.compat.jei.util.RegistryUtil;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import net.minecraft.core.NonNullList;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
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.PotionContents;
import net.minecraft.world.item.crafting.*;
import net.neoforged.neoforge.common.crafting.DataComponentIngredient;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public final class TippedLeashArrowRecipeMaker {
private static List<RecipeHolder<CraftingRecipe>> createRecipesA() {
String group = "jei.tipped.leash_rope_arrow_a";
ItemStack arrowStack = new ItemStack(ModItemRegister.LEASH_ROPE_ARROW.get());
Ingredient arrowIngredient = Ingredient.of(arrowStack);
Registry<Potion> potionRegistry = RegistryUtil.getRegistry(Registries.POTION);
return potionRegistry.holders()
.map(potion -> {
ItemStack input = PotionContents.createItemStack(Items.LINGERING_POTION, potion);
ItemStack output = PotionContents.createItemStack(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get(), potion);
output.setCount(8);
Ingredient potionIngredient = DataComponentIngredient.of(false, input);
NonNullList<Ingredient> inputs = NonNullList.of(Ingredient.EMPTY,
arrowIngredient, arrowIngredient, arrowIngredient,
arrowIngredient, potionIngredient, arrowIngredient,
arrowIngredient, arrowIngredient, arrowIngredient
);
ResourceLocation id = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, group + "." + output.getDescriptionId());
ShapedRecipePattern recipe = new ShapedRecipePattern(3,3, inputs, Optional.empty());
CraftingRecipe recipe_ = new ShapedRecipe(group, CraftingBookCategory.MISC, recipe, output);
return new RecipeHolder<>(id, recipe_);
}).toList();
}
private static List<RecipeHolder<CraftingRecipe>> createRecipesB() {
String group = "jei.tipped.leash_rope_arrow_b";
ItemStack arrowStack = new ItemStack(Items.LEAD);
Ingredient arrowIngredient = Ingredient.of(arrowStack);
Registry<Potion> potionRegistry = RegistryUtil.getRegistry(Registries.POTION);
return potionRegistry.holders()
.map(potion -> {
ItemStack input = PotionContents.createItemStack(Items.TIPPED_ARROW, potion);
ItemStack output = PotionContents.createItemStack(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get(), potion);
output.setCount(1);
Ingredient potionIngredient = DataComponentIngredient.of(false, input);
NonNullList<Ingredient> inputs = NonNullList.of(Ingredient.EMPTY,
arrowIngredient,potionIngredient
);
ResourceLocation id = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, group + "." + output.getDescriptionId());
CraftingRecipe recipe_ = new ShapelessRecipe(group, CraftingBookCategory.MISC, output, inputs);
return new RecipeHolder<>(id, recipe_);
}).toList();
}
public static List<RecipeHolder<CraftingRecipe>> createRecipes() {
List<RecipeHolder<CraftingRecipe>> ret = new ArrayList<>();
ret.addAll(createRecipesA());
ret.addAll(createRecipesB());
return ret;
}
private TippedLeashArrowRecipeMaker() {
}
}

View File

@ -0,0 +1,23 @@
package com.r3944realms.leashedplayer.compat.jei.util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceKey;
public class RegistryUtil {
public static <T> Registry<T> getRegistry(ResourceKey<? extends Registry<T>> key) {
RegistryAccess registryAccess = getRegistryAccess();
return registryAccess.registryOrThrow(key);
}
public static RegistryAccess getRegistryAccess() {
Minecraft minecraft = Minecraft.getInstance();
ClientLevel level = minecraft.level;
if (level == null) {
throw new IllegalStateException("Could not get registry, registry access is unavailable because the level is currently null");
}
return level.registryAccess();
}
}

View File

@ -7,7 +7,7 @@ public class LeashPlayerCommonConfig {
public static final ModConfigSpec SPEC;
public static final ModConfigSpec.ConfigValue<String> LeashedPlayerModCommandPrefix;
public static final ModConfigSpec.BooleanValue EnableLeashPlayerCommandPrefix;
public static ModConfigSpec.IntValue MinimumLeashLengthCanBeSet, MaximumLeashLengthCanBeSet, TheLeashArrowMaxLifeTime;
public static ModConfigSpec.IntValue MinimumLeashLengthCanBeSet, MaximumLeashLengthCanBeSet, TheLeashArrowMaxLifeTime, TheNestleArrowMaxLifeTime;
public static ModConfigSpec.DoubleValue TheMultipleThatLeashRopeArrowBreakLength, TheLeashBreakLengthTimesBase;
static {
BUILDER.comment("Leash Player Config");
@ -20,14 +20,15 @@ public class LeashPlayerCommonConfig {
BUILDER.pop();
BUILDER.comment("Leash Player Arrow");
BUILDER.push("LeashRopeArrow");
TheMultipleThatLeashRopeArrowBreakLength = BUILDER.comment("How many times is the length of the arrow rope based on BreakLength TimeBase", "[ Default : 5.0f, Invalid Range:[2.0f, 10.0f] ]").defineInRange("TheMultipleArrowBreak", 5.0f, 2.0f , 10.0f);
TheMultipleThatLeashRopeArrowBreakLength = BUILDER.comment("How many times is the length of the arrow rope based on BreakLength TimeBase", "[ Default : 5.0f, Invalid Range:[2.0f, 10.0f] ]").defineInRange("TheMultipleArrowBreak", 5.0f, 2.0f, 10.0f);
TheLeashArrowMaxLifeTime = BUILDER.comment("If the LeashArrowEntity's life is bigger than this value ,it will be discarded", "[ Default : 2400, Invalid Range:[1200 , 10240]]").defineInRange("TheLeashArrowMaxLifeTime",2400, 1200, 10240);
TheNestleArrowMaxLifeTime = BUILDER.comment("If the NestleArrowEntity's life is bigger than this value ,it will be discarded\", \"[ Default : 2400, Invalid Range:[1200 , 10240]]").defineInRange("TheNestleArrowMaxLifeTime",2400, 1200, 10240);
BUILDER.pop();
BUILDER.comment("Leash Player Misc");
BUILDER.push("Misc");
BUILDER.comment("Leash Player Length");
BUILDER.push("LeashLength");
TheLeashBreakLengthTimesBase = BUILDER.comment("When it exceeds how many times, the leash will drop"," [ Default:3.0f, Valid Range:[3.0f, 6.0f] ]").defineInRange("BreakLengthTimeBase", 3.0f, 3.0f ,6.0f);
TheLeashBreakLengthTimesBase = BUILDER.comment("When it exceeds how many times, the leash will drop"," [ Default:2.0f, Invalid Range:[2.0f, 5.0f] ]").defineInRange("BreakLengthTimeBase", 3.0f, 3.0f ,6.0f);
MinimumLeashLengthCanBeSet = BUILDER.comment("The minimum integer's length of Leash", " [ Default:5, Invalid Range:[2,10] ]").defineInRange("MinLeashLength", 5, 2, 10);
MaximumLeashLengthCanBeSet = BUILDER.comment("The maximum integer's length of Leash", " [ Default:1024, Invalid Range:[32, 1024] ]").defineInRange("MaxLeashLength", 1024, 32, 1024);
BUILDER.pop().pop();

View File

@ -9,12 +9,20 @@ import org.lwjgl.glfw.GLFW;
public class ModKeyMapping {
static String KEY_ROOT_ = "key.leashedplayer.";
public static String CATEGORY = "key.leashedplayer.category";
public static String
public static String APPLY_TALKAREA_PREFERENCE_KEY = KEY_ROOT_ + "apply_talkarea_preference",
ADD_LEASH_LENGTH_KEY = KEY_ROOT_ + "leash_length.add",
SUB_LEASH_LENGTH_KEY = KEY_ROOT_ + "leash_length.sub",
NOT_SUPPORT_TO_NOT_PLAYER_ENTITY = KEY_ROOT_ + "leash_length.not_support_to_not_player_entity";
public static final KeyMapping KEY_APPLY_TALKAREA_PREFERENCE =
new KeyMapping(
APPLY_TALKAREA_PREFERENCE_KEY,
KeyConflictContext.IN_GAME,
KeyModifier.NONE,
InputConstants.Type.KEYSYM,
GLFW.GLFW_KEY_I,
CATEGORY
);
public static final KeyMapping KEY_ADD_LEASH_LENGTH =
new KeyMapping(
ADD_LEASH_LENGTH_KEY,
@ -34,4 +42,3 @@ public class ModKeyMapping {
CATEGORY
);
}

View File

@ -0,0 +1,184 @@
package com.r3944realms.leashedplayer.content.commands;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.r3944realms.leashedplayer.content.gamerules.GameruleRegistry;
import com.r3944realms.leashedplayer.content.gamerules.Server.CanCommonPlayerChangeSelfTalkArea;
import com.r3944realms.leashedplayer.modInterface.ServerPlayerCapacity;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static com.r3944realms.leashedplayer.content.commands.Command.SHOULD_USE_PREFIX;
import static com.r3944realms.leashedplayer.content.commands.Command.getLiterArgumentBuilderOfCSS;
public class ChatCommand {
private static final String LP_CHAT_MESSAGE_ = "leashedplayer.command.chat.message.";
public static final String NO_RIGHT = LP_CHAT_MESSAGE_ + "no_right";
public static final String SELF_TALK_AREA_SET = LP_CHAT_MESSAGE_ + "talkarea.self.set",
SELF_TALK_AREA_PREFERENCE_SET = LP_CHAT_MESSAGE_ + "talkarea.self.preference.set",
SELF_TALK_AREA_PREFERENCE_NOT_SET = LP_CHAT_MESSAGE_ + "talkarea.self.preference_not_set",
SELF_TALK_AREA_UNLIMITED = LP_CHAT_MESSAGE_ + "talkarea.self.unlimited",
SELF_TALK_AREA_CURRENT_CONFIG = LP_CHAT_MESSAGE_ + "talkarea.self.current_config",
TALK_AREA_SET = LP_CHAT_MESSAGE_ + "talkarea.set",
TALK_AREA_PREFERENCE_SET = LP_CHAT_MESSAGE_ + "talkarea.preference.set",
TALK_AREA_PREFERENCE_NOT_SET = LP_CHAT_MESSAGE_ + "talkarea.preference_not_set",
TALK_AREA_UNLIMITED = LP_CHAT_MESSAGE_ + "talkarea.unlimited",
TALK_AREA_CURRENT_CONFIG = LP_CHAT_MESSAGE_ + "talkarea.current_config";
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
@Nullable List<LiteralArgumentBuilder<CommandSourceStack>> nodeList = SHOULD_USE_PREFIX ? null : new ArrayList<>();
LiteralArgumentBuilder<CommandSourceStack> literalArgumentBuilder = Commands.literal(com.r3944realms.leashedplayer.content.commands.Command.PREFIX);
LiteralArgumentBuilder<CommandSourceStack> $$leashRoot = getLiterArgumentBuilderOfCSS("talkArea", !SHOULD_USE_PREFIX, nodeList);
Command<CommandSourceStack> chat$self$talkArea_set = (context -> {
CommandSourceStack source = context.getSource();
ServerPlayer player = source.getPlayerOrException();
ServerPlayerCapacity serverPlayer = (ServerPlayerCapacity) player;
if((!player.hasPermissions(2) && !GameruleRegistry.getGameruleBoolValue(source.getLevel(), CanCommonPlayerChangeSelfTalkArea.ID))) {
source.sendFailure(Component.translatable(NO_RIGHT));
return 1;
}
int integer = IntegerArgumentType.getInteger(context, "talkAreaRadius");
serverPlayer.setTalkArea(integer);
source.sendSuccess(() -> Component.translatable(SELF_TALK_AREA_SET, integer),true);
return 0;
});
Command<CommandSourceStack> chat$self$talkArea_preference_set = (context -> {
CommandSourceStack source = context.getSource();
ServerPlayer player = source.getPlayerOrException();
ServerPlayerCapacity serverPlayer = (ServerPlayerCapacity) player;
if((!player.hasPermissions(2) && !GameruleRegistry.getGameruleBoolValue(source.getLevel(), CanCommonPlayerChangeSelfTalkArea.ID))) {
source.sendFailure(Component.translatable(NO_RIGHT));
return 1;
}
int integer = IntegerArgumentType.getInteger(context, "talkAreaPreferenceRadius");
serverPlayer.setTalkAreaPreference(integer);
source.sendSuccess(() -> Component.translatable(SELF_TALK_AREA_PREFERENCE_SET, integer),true);
return 0;
});
Command<CommandSourceStack> chat$self$talkArea_usePreference = (context -> {
CommandSourceStack source = context.getSource();
ServerPlayer player = source.getPlayerOrException();
ServerPlayerCapacity serverPlayer = (ServerPlayerCapacity) player;
if((!player.hasPermissions(2) && !GameruleRegistry.getGameruleBoolValue(source.getLevel(), CanCommonPlayerChangeSelfTalkArea.ID))) {
source.sendFailure(Component.translatable(NO_RIGHT));
return 1;
}
if(serverPlayer.getTalkAreaPreference() == -1) {
source.sendFailure(Component.translatable(SELF_TALK_AREA_PREFERENCE_NOT_SET));
return 1;
}
int currentPreference = serverPlayer.getTalkAreaPreference();
serverPlayer.setTalkArea(currentPreference);
source.sendSuccess(() -> Component.translatable(SELF_TALK_AREA_PREFERENCE_SET, currentPreference),true);
return 0;
});
Command<CommandSourceStack> chat$self$talkArea_unlimited = (context -> {
CommandSourceStack source = context.getSource();
ServerPlayer player = source.getPlayerOrException();
if((!player.hasPermissions(2) && !GameruleRegistry.getGameruleBoolValue(source.getLevel(), CanCommonPlayerChangeSelfTalkArea.ID))) {
source.sendFailure(Component.translatable(NO_RIGHT));
return 1;
}
source.sendSuccess(() -> Component.translatable(SELF_TALK_AREA_UNLIMITED),true);
return 0;
});
Command<CommandSourceStack> chat$self$talkArea_getCurrentConfig = (context -> {
CommandSourceStack source = context.getSource();
ServerPlayerCapacity serverPlayer = (ServerPlayerCapacity) source.getPlayerOrException();
source.sendSuccess(() -> Component.translatable(SELF_TALK_AREA_CURRENT_CONFIG,serverPlayer.getTalkArea(),serverPlayer.getTalkAreaPreference()),true);
return 0;
});
Command<CommandSourceStack> chat$talkArea_set = (context -> {
CommandSourceStack source = context.getSource();
Collection<ServerPlayer> players = EntityArgument.getPlayers(context, "players");
int integer = IntegerArgumentType.getInteger(context, "talkAreaRadius");
players.forEach(i-> {
((ServerPlayerCapacity)i).setTalkArea(integer);
source.sendSuccess(() -> Component.translatable(TALK_AREA_SET, i.getName().copy().withStyle(), integer),true);
});
return 0;
});
Command<CommandSourceStack> chat$talkArea_preference_set = (context -> {
CommandSourceStack source = context.getSource();
Collection<ServerPlayer> players = EntityArgument.getPlayers(context, "players");
int integer = IntegerArgumentType.getInteger(context, "talkAreaPreferenceRadius");
players.forEach(i-> {
((ServerPlayerCapacity)i).setTalkAreaPreference(integer);
source.sendSuccess(() -> Component.translatable(TALK_AREA_PREFERENCE_SET, i.getName().copy().withStyle(), integer),true);
});
return 0;
});
Command<CommandSourceStack> chat$talkArea_usePreference = (context -> {
CommandSourceStack source = context.getSource();
Collection<ServerPlayer> players = EntityArgument.getPlayers(context, "players");
players.forEach(i-> {
int talkAreaPreference = ((ServerPlayerCapacity)i).getTalkAreaPreference();
if(talkAreaPreference == -1) {
source.sendFailure(Component.translatable(TALK_AREA_PREFERENCE_NOT_SET,i.getName().copy().withStyle()));
} else {
((ServerPlayerCapacity) i).setTalkArea(talkAreaPreference);
source.sendSuccess(() -> Component.translatable(TALK_AREA_PREFERENCE_SET, i.getName().copy().withStyle(), talkAreaPreference),true);
}
});
return 0;
});
Command<CommandSourceStack> chat$talkArea_unlimited = (context -> {
CommandSourceStack source = context.getSource();
Collection<ServerPlayer> players = EntityArgument.getPlayers(context, "players");
players.forEach(i-> {
((ServerPlayerCapacity)i).setTalkArea(-1);
source.sendSuccess(() -> Component.translatable(TALK_AREA_UNLIMITED, i.getName().copy().withStyle()),true);
});
return 0;
});
Command<CommandSourceStack> chat$talkArea_getCurrentConfig = (context -> {
CommandSourceStack source = context.getSource();
Collection<ServerPlayer> players = EntityArgument.getPlayers(context, "players");
players.forEach(i-> source.sendSuccess(() -> Component.translatable(TALK_AREA_CURRENT_CONFIG, i.getName().copy().withStyle(),((ServerPlayerCapacity)i).getTalkArea(),((ServerPlayerCapacity)i).getTalkAreaPreference()), true));
return 0;
});
LiteralArgumentBuilder<CommandSourceStack> selfTalkAreaSet = $$leashRoot.then(Commands.literal("set")
.then(Commands.argument("talkAreaRadius", IntegerArgumentType.integer(0))
.executes(chat$self$talkArea_set)))
.then(Commands.literal("setPreference")
.then(Commands.argument("talkAreaPreferenceRadius", IntegerArgumentType.integer(0))
.executes(chat$self$talkArea_preference_set)))
.then(Commands.literal("usePreference")
.executes(chat$self$talkArea_usePreference))
.then(Commands.literal("unlimited")
.executes(chat$self$talkArea_unlimited))
.then(Commands.literal("currentConfig")
.executes(chat$self$talkArea_getCurrentConfig));
LiteralArgumentBuilder<CommandSourceStack> TalkAreaCommon = $$leashRoot.then(Commands.argument("players", EntityArgument.players()).requires(cs -> cs.hasPermission(2))
.then(Commands.literal("set")
.then(Commands.argument("talkAreaRadius", IntegerArgumentType.integer(0))
.executes(chat$talkArea_set)))
.then(Commands.literal("setPreference")
.then(Commands.argument("talkAreaPreferenceRadius", IntegerArgumentType.integer(0))
.executes(chat$talkArea_preference_set)))
.then(Commands.literal("usePreference")
.executes(chat$talkArea_usePreference))
.then(Commands.literal("unlimited")
.executes(chat$talkArea_unlimited))
.then(Commands.literal("currentConfig")
.executes(chat$talkArea_getCurrentConfig)));
if(SHOULD_USE_PREFIX) {
literalArgumentBuilder.then(selfTalkAreaSet);
literalArgumentBuilder.then(TalkAreaCommon);
dispatcher.register(literalArgumentBuilder);
} else {
nodeList.forEach(dispatcher::register);
}
}
}

View File

@ -10,7 +10,7 @@ import java.util.List;
public class Command {
public static final String PREFIX = LeashPlayerCommonConfig.LeashedPlayerModCommandPrefix.get();
public static boolean SHOULD_USE_PREFIX = LeashPlayerCommonConfig.EnableLeashPlayerCommandPrefix.get();
static LiteralArgumentBuilder<CommandSourceStack> getLiterArgumentBuilderOfCSS(String name, boolean shouldAddToList, @Nullable List<LiteralArgumentBuilder<CommandSourceStack>> list) {
LiteralArgumentBuilder<CommandSourceStack> literal = Commands.literal(name);
if (shouldAddToList) {

View File

@ -0,0 +1,58 @@
package com.r3944realms.leashedplayer.content.commands;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.network.Connection;
import net.minecraft.network.PacketSendListener;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.protocol.common.ClientboundDisconnectPacket;
import net.minecraft.server.level.ServerPlayer;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static com.r3944realms.leashedplayer.content.commands.Command.SHOULD_USE_PREFIX;
import static com.r3944realms.leashedplayer.content.commands.Command.getLiterArgumentBuilderOfCSS;
public class DebugCommand {
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
@Nullable List<LiteralArgumentBuilder<CommandSourceStack>> nodeList = SHOULD_USE_PREFIX ? null : new ArrayList<>();
LiteralArgumentBuilder<CommandSourceStack> literalArgumentBuilder = Commands.literal(com.r3944realms.leashedplayer.content.commands.Command.PREFIX);
LiteralArgumentBuilder<CommandSourceStack> $$DebugRoot = getLiterArgumentBuilderOfCSS("debug", !SHOULD_USE_PREFIX, nodeList);
com.mojang.brigadier.Command<CommandSourceStack> kickTargets = context -> {
for(ServerPlayer entity : EntityArgument.getPlayers(context, "targets")){
MutableComponent literal = Component.literal("You are already connected to this proxy!");
Connection connection = entity.connection.getConnection();
connection.send(new ClientboundDisconnectPacket(literal), PacketSendListener.thenRun(() -> connection.disconnect(literal)));
}
return 0;
};
com.mojang.brigadier.Command<CommandSourceStack> kickSelf = context -> {
CommandSourceStack source = context.getSource();
if (source.getEntity() instanceof ServerPlayer serverPlayer) {
MutableComponent literal = Component.literal("You are already connected to this proxy!");
Connection connection = serverPlayer.connection.getConnection();
connection.send(new ClientboundDisconnectPacket(literal), PacketSendListener.thenRun(() -> connection.disconnect(literal)));
}
return 0;
};
LiteralArgumentBuilder<CommandSourceStack> debugKick = $$DebugRoot.requires(commandSourceStack -> commandSourceStack.hasPermission(2))
.then(
Commands.literal("kick").executes(kickSelf)
.then(Commands.argument("targets", EntityArgument.entities())
.executes(kickTargets)
)
);
if(SHOULD_USE_PREFIX){
literalArgumentBuilder.then(debugKick);
dispatcher.register(literalArgumentBuilder);
} else {
nodeList.forEach(dispatcher::register);
}
}
}

View File

@ -28,6 +28,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static com.r3944realms.leashedplayer.content.commands.Command.SHOULD_USE_PREFIX;
import static com.r3944realms.leashedplayer.content.commands.Command.getLiterArgumentBuilderOfCSS;
public class LeashCommand {
@ -54,10 +55,9 @@ public class LeashCommand {
;
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
boolean shouldUsePrefix = LeashPlayerCommonConfig.EnableLeashPlayerCommandPrefix.get();
@Nullable List<LiteralArgumentBuilder<CommandSourceStack>> nodeList = shouldUsePrefix ? null : new ArrayList<>();
@Nullable List<LiteralArgumentBuilder<CommandSourceStack>> nodeList = SHOULD_USE_PREFIX ? null : new ArrayList<>();
LiteralArgumentBuilder<CommandSourceStack> literalArgumentBuilder = Commands.literal(com.r3944realms.leashedplayer.content.commands.Command.PREFIX);
LiteralArgumentBuilder<CommandSourceStack> $$leashRoot = getLiterArgumentBuilderOfCSS("leash", !shouldUsePrefix, nodeList);
LiteralArgumentBuilder<CommandSourceStack> $$leashRoot = getLiterArgumentBuilderOfCSS("leash", !SHOULD_USE_PREFIX, nodeList);
Command<CommandSourceStack> getSelfLeashLength = context -> {
CommandSourceStack source = context.getSource();
@ -250,9 +250,7 @@ public class LeashCommand {
CommandSourceStack source = context.getSource();
try {
Collection<ServerPlayer> playerCol = EntityArgument.getPlayers(context, "targetPlayers");
playerCol.forEach(player -> {
LeashDataBlockPosSetResultInt(context, source, player);
});
playerCol.forEach(player -> LeashDataBlockPosSetResultInt(context, source, player));
} catch (Exception e) {
source.sendFailure(Component.translatable(LEASH_FAILED));
@ -292,7 +290,7 @@ public class LeashCommand {
try {
ServerPlayer player = EntityArgument.getPlayer(context, "targetPlayer");
Integer x = LeashDataClearResultInt(source, PlayerLeashable.getLeashDataEntity(player, source.getLevel()),player);
if (x != null) return x;
} catch (Exception e) {
source.sendFailure(Component.translatable(LEASH_FAILED));
return -1;
@ -395,7 +393,7 @@ public class LeashCommand {
)
);
if(shouldUsePrefix) {
if(SHOULD_USE_PREFIX) {
literalArgumentBuilder
.then(RefPlayerLeashLength)
.then(SelfLeashLength)

View File

@ -4,7 +4,6 @@ import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.DoubleArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.r3944realms.leashedplayer.config.LeashPlayerCommonConfig;
import com.r3944realms.leashedplayer.network.client.UpdatePlayerMovement;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
@ -19,6 +18,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static com.r3944realms.leashedplayer.content.commands.Command.SHOULD_USE_PREFIX;
import static com.r3944realms.leashedplayer.content.commands.Command.getLiterArgumentBuilderOfCSS;
public class MotionCommand {
@ -27,10 +27,9 @@ public class MotionCommand {
MOTION_ADDER_SUCCESSFUL = LEASHED_PLAYER_MOTION_MESSAGE_ + "adder.successful",
MOTION_MULTIPLY_SUCCESSFUL = LEASHED_PLAYER_MOTION_MESSAGE_ + "multiply.successful";
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
boolean shouldUsePrefix = LeashPlayerCommonConfig.EnableLeashPlayerCommandPrefix.get();
@Nullable List<LiteralArgumentBuilder<CommandSourceStack>> nodeList = shouldUsePrefix ? null : new ArrayList<>();
@Nullable List<LiteralArgumentBuilder<CommandSourceStack>> nodeList = SHOULD_USE_PREFIX ? null : new ArrayList<>();
LiteralArgumentBuilder<CommandSourceStack> literalArgumentBuilder = Commands.literal(com.r3944realms.leashedplayer.content.commands.Command.PREFIX);
LiteralArgumentBuilder<CommandSourceStack> $$motionRoot = getLiterArgumentBuilderOfCSS("motion", !shouldUsePrefix, nodeList);
LiteralArgumentBuilder<CommandSourceStack> $$motionRoot = getLiterArgumentBuilderOfCSS("motion", !SHOULD_USE_PREFIX, nodeList);
com.mojang.brigadier.Command<CommandSourceStack> motionVecAdder = context -> {
CommandSourceStack source = context.getSource();
for(Entity entity : EntityArgument.getEntities(context, "targets")){
@ -41,7 +40,6 @@ public class MotionCommand {
);
if(entity instanceof ServerPlayer player) {
PacketDistributor.sendToPlayer(player, new UpdatePlayerMovement(UpdatePlayerMovement.Operation.ADD, motionVec.x, motionVec.y, motionVec.z));
player.addDeltaMovement(new Vec3(motionVec.x, motionVec.y, motionVec.z));
} else {
entity.addDeltaMovement(motionVec);
}
@ -60,12 +58,11 @@ public class MotionCommand {
);
if(entity instanceof ServerPlayer player) {
PacketDistributor.sendToPlayer(player, new UpdatePlayerMovement(UpdatePlayerMovement.Operation.SET, motionVec.x, motionVec.y, motionVec.z));
player.setDeltaMovement(new Vec3(motionVec.x, motionVec.y, motionVec.z));
} else {
entity.setDeltaMovement(motionVec);
}
double vecX = entity.getDeltaMovement().x, vecY = entity.getDeltaMovement().y, vecZ = entity.getDeltaMovement().z;
source.sendSuccess(() -> Component.translatable(MOTION_SETTER_SUCCESSFUL, entity.getName().copy(), vecX, vecY, vecZ), true);
source.sendSuccess(() -> Component.translatable(MOTION_SETTER_SUCCESSFUL, entity.getName().copy().withStyle(), vecX, vecY, vecZ), true);
}
return 0;
};
@ -79,12 +76,11 @@ public class MotionCommand {
);
if(entity instanceof ServerPlayer player) {
PacketDistributor.sendToPlayer(player, new UpdatePlayerMovement(UpdatePlayerMovement.Operation.MULTIPLY, motionFactorVec.x, motionFactorVec.y, motionFactorVec.z));
player.setDeltaMovement(entity.getDeltaMovement().multiply(motionFactorVec));
} else {
entity.setDeltaMovement(entity.getDeltaMovement().multiply(motionFactorVec));
}
double vecX = entity.getDeltaMovement().x, vecY = entity.getDeltaMovement().y, vecZ = entity.getDeltaMovement().z;
source.sendSuccess(() -> Component.translatable(MOTION_MULTIPLY_SUCCESSFUL, entity.getName().copy(), vecX, vecY, vecZ), true);
source.sendSuccess(() -> Component.translatable(MOTION_MULTIPLY_SUCCESSFUL, entity.getName().copy().withStyle(), vecX, vecY, vecZ), true);
}
return 0;
};
@ -119,7 +115,7 @@ public class MotionCommand {
)
)
);
if(shouldUsePrefix){
if(SHOULD_USE_PREFIX){
literalArgumentBuilder.then(Motion);
dispatcher.register(literalArgumentBuilder);
} else {

View File

@ -4,7 +4,6 @@ import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.FloatArgumentType;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.r3944realms.leashedplayer.config.LeashPlayerCommonConfig;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.SharedSuggestionProvider;
@ -18,17 +17,16 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.r3944realms.leashedplayer.content.commands.Command.SHOULD_USE_PREFIX;
import static com.r3944realms.leashedplayer.content.commands.Command.getLiterArgumentBuilderOfCSS;
public class TickCommand {
private static final float MAX_TICKRATE = 10000.0F;
private static final String DEFAULT_TICKRATE = String.valueOf(20);
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
boolean shouldUsePrefix = LeashPlayerCommonConfig.EnableLeashPlayerCommandPrefix.get();
@Nullable List<LiteralArgumentBuilder<CommandSourceStack>> nodeList = shouldUsePrefix ? null : new ArrayList<>();
@Nullable List<LiteralArgumentBuilder<CommandSourceStack>> nodeList = SHOULD_USE_PREFIX ? null : new ArrayList<>();
LiteralArgumentBuilder<CommandSourceStack> literalArgumentBuilder = Commands.literal(com.r3944realms.leashedplayer.content.commands.Command.PREFIX);
LiteralArgumentBuilder<CommandSourceStack> $$TickRoot = getLiterArgumentBuilderOfCSS("tick", !shouldUsePrefix, nodeList);
LiteralArgumentBuilder<CommandSourceStack> $$TickRoot = getLiterArgumentBuilderOfCSS("tick", !SHOULD_USE_PREFIX, nodeList);
LiteralArgumentBuilder<CommandSourceStack> Tick = $$TickRoot.requires(p_308941_ -> p_308941_.hasPermission(2))
.then(Commands.literal("query").executes(p_308950_ -> tickQuery(p_308950_.getSource())))
@ -61,7 +59,7 @@ public class TickCommand {
)
.then(Commands.literal("unfreeze").executes(p_309184_ -> setFreeze(p_309184_.getSource(), false)))
.then(Commands.literal("freeze").executes(p_309070_ -> setFreeze(p_309070_.getSource(), true)));
if(shouldUsePrefix){
if(SHOULD_USE_PREFIX){
literalArgumentBuilder.then(Tick);
dispatcher.register(literalArgumentBuilder);
} else {

View File

@ -13,7 +13,7 @@ import java.util.function.Supplier;
public class ModEffectRegister {
public static DeferredRegister<MobEffect> MOB_EFFECT = DeferredRegister.create(Registries.MOB_EFFECT, LeashedPlayer.MOD_ID);
public static DeferredHolder<MobEffect, ? extends MobEffect> NO_LEASH_EFFECT = register(
public static DeferredHolder<MobEffect, NoLeashEffect> NO_LEASH_EFFECT = register(
"no_leash",
() -> new NoLeashEffect(MobEffectCategory.NEUTRAL, 12063764)
);

View File

@ -2,7 +2,6 @@ package com.r3944realms.leashedplayer.content.effects.type;
import com.r3944realms.leashedplayer.content.effects.ModEffectRegister;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.effect.MobEffectInstance;
@ -11,12 +10,13 @@ import net.minecraft.world.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
public class NoLeashEffect extends MobEffect {
public NoLeashEffect(MobEffectCategory pCategory, int pColor) {
super(pCategory, pColor);
}
@Override
public boolean applyEffectTick(@NotNull ServerLevel level, @NotNull LivingEntity pLivingEntity, int pAmplifier) {
public boolean applyEffectTick(@NotNull LivingEntity pLivingEntity, int pAmplifier) {
MobEffectInstance effect = pLivingEntity.getEffect(ModEffectRegister.NO_LEASH_EFFECT);
if(effect != null && effect.getDuration() != 0) {
if (pLivingEntity instanceof Leashable leashable) {

View File

@ -0,0 +1,11 @@
package com.r3944realms.leashedplayer.content.effects.type;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectCategory;
public class StunnedEffect extends MobEffect {
public StunnedEffect() {
super(MobEffectCategory.HARMFUL, 0XFFFBC5);
}
}

View File

@ -121,22 +121,22 @@ public class LeashRopeArrow extends AbstractArrow {
protected boolean tryPickup(@NotNull Player pPlayer) {
//时间1.40 禁止
//时间2.240
// 如果(非仅创造拾取)
// 如果 (按Shift )
// 如果(拥有者) -> 拾取到完整箭取消绑定(super给父类处理)
// 否则:时间仍为原需时间 ->不能获取完整的箭重绑定当前拥有者的Holder是否为本箭才重绑定
// 否则: 禁止
// 如果(非仅创造拾取)
// 如果 (按Shift )
// 如果(拥有者) -> 拾取到完整箭取消绑定(super给父类处理)
// 否则:时间仍为原需时间 ->不能获取完整的箭重绑定当前拥有者的Holder是否为本箭才重绑定
// 否则: 禁止
// 否则:
// 如果 (按Shift )
// 如果(拥有者) -> 且拾取到完整箭取消绑定
// 否则:时间仍为原需时间 ->不能获取完整的箭重绑定
// 否则: 禁止
// 如果 (按Shift )
// 如果(拥有者) -> 且拾取到完整箭取消绑定
// 否则:时间仍为原需时间 ->不能获取完整的箭重绑定
// 否则: 禁止
//时间3
// 如果(拥有者) -> 拾取到完整箭取消绑定
// 否则:不能获取完整的箭重绑定
// 如果(拥有者) -> 拾取到完整箭取消绑定
// 否则:不能获取完整的箭重绑定
if(life <= 40 ) {
return false;
return false;
} else {
PlayerLeashable playerLeashable = (PlayerLeashable) pPlayer;
if(this.getOwner() != null) {//未有Owner始终可检
@ -247,14 +247,14 @@ public class LeashRopeArrow extends AbstractArrow {
public void tick() {
super.tick();
if (this.level().isClientSide) {
if (this.isInGround()) {
if (this.inGround) {
if (this.inGroundTime % 5 == 0) {
this.makeParticle(1);
}
} else {
this.makeParticle(2);
}
} else if (this.isInGround() && this.inGroundTime != 0 && !this.getPotionContents().equals(PotionContents.EMPTY) && this.inGroundTime >= 600) {
} else if (this.inGround && this.inGroundTime != 0 && !this.getPotionContents().equals(PotionContents.EMPTY) && this.inGroundTime >= 600) {
this.level().broadcastEntityEvent(this, (byte)0);
this.setPickupItemStack(new ItemStack(getSelfItemStack().getItem()));
}

View File

@ -0,0 +1,80 @@
package com.r3944realms.leashedplayer.content.entities;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.PlayerInfo;
import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.client.resources.PlayerSkin;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.AgeableMob;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.util.Objects;
import static net.minecraft.world.entity.EquipmentSlot.*;
public class LittlePlayer extends AgeableMob {
private static final EntityDataAccessor<Integer> DATA_TYPE_ID = SynchedEntityData.defineId(LittlePlayer.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> BASE_HEALTH = SynchedEntityData.defineId(LittlePlayer.class,EntityDataSerializers.INT);
public EquipmentSlot[] armorTypes = new EquipmentSlot[]{FEET, LEGS,
CHEST, EquipmentSlot.HEAD};
@Nullable
private PlayerInfo playerInfo;
protected LittlePlayer(EntityType<? extends AgeableMob> pEntityType, Level pLevel) {
super(pEntityType, pLevel);
}
public static AttributeSupplier.Builder createAttributes() {
return AgeableMob.createMobAttributes()
.add(Attributes.MAX_HEALTH, 20.0D)
.add(Attributes.MOVEMENT_SPEED, 0.32D);
}
@Nullable
public PlayerInfo getPlayerInfo() {
if (this.playerInfo == null) {
try {
this.playerInfo = Objects.requireNonNull(Minecraft.getInstance().getConnection()).getPlayerInfo(this.getUUID());
} catch (Exception ignored) {
}
}
return this.playerInfo;
}
public PlayerSkin getSkin() {
PlayerInfo playerinfo = this.getPlayerInfo();
return playerinfo == null ? DefaultPlayerSkin.get(this.getUUID()) : playerinfo.getSkin();
}
@Override
public AgeableMob getBreedOffspring(@NotNull ServerLevel pLevel, @NotNull AgeableMob pOtherParent) {
return ModEntityRegister.KID.get().create(pLevel);
}
@Override
protected void defineSynchedData(SynchedEntityData.@NotNull Builder pBuilder) {
super.defineSynchedData(pBuilder);
pBuilder.define(DATA_TYPE_ID, 1);
pBuilder.define(BASE_HEALTH, 20);
}
public void setBaseHealth(int health) {
this.entityData.set(BASE_HEALTH, health);
}
public float getBaseHealth() {
return this.entityData.get(BASE_HEALTH);
}
@Override
public boolean isBaby() {
return true;
}
}

View File

@ -2,8 +2,6 @@ package com.r3944realms.leashedplayer.content.entities;
import com.r3944realms.leashedplayer.LeashedPlayer;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.neoforged.bus.api.IEventBus;
@ -19,7 +17,7 @@ public class ModEntityRegister {
.eyeHeight(0.13F)
.clientTrackingRange(4)
.updateInterval(20)
.build(ResourceKey.create(Registries.ENTITY_TYPE, ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "leash_rope_arrow")))
.build("leash_rope_arrow")
);
public static final DeferredHolder<EntityType<?>, EntityType<SpectralLeashRopeArrow>> SPECTRAL_LEASH_ROPE_ARROW = ENTITY_TYPE.register(
"spectral_leash_rope_arrow",
@ -28,9 +26,28 @@ public class ModEntityRegister {
.eyeHeight(0.13F)
.clientTrackingRange(4)
.updateInterval(20)
.build(ResourceKey.create(Registries.ENTITY_TYPE, ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "spectral_leash_rope_arrow")))
.build("spectral_leash_rope_arrow")
);
public static final DeferredHolder<EntityType<?>, EntityType<NestleRopeArrow>> NESTLE_ROPE_ARROW = ENTITY_TYPE.register(
"nestle_rope_arrow",
() -> EntityType.Builder.<NestleRopeArrow>of(NestleRopeArrow::new, MobCategory.MISC)
.sized(0.5F, 0.5F)
.eyeHeight(0.13F)
.clientTrackingRange(4)
.updateInterval(20)
.build("nestle_rope_arrow")
);
public static final DeferredHolder<EntityType<?>, EntityType<LittlePlayer>> KID = ENTITY_TYPE.register("kid_player",
() -> EntityType.Builder.of(LittlePlayer::new, MobCategory.MISC)
.sized(0.6f,1.08f)
.build("kid_player")
);
// public static final DeferredHolder<EntityType<?>, EntityType<ChainTieEntity>> CHAIN_TIE = ENTITY_TYPE.register(
// "chain_tie",
// () -> EntityType.Builder.<ChainTieEntity>of(ChainTieEntity::new, MobCategory.MISC)
// .sized(0.8F, 0.9F)
// .build("chain_tie")
// );
public static String getEntityNameKey(String entityName) {
return "entity." + LeashedPlayer.MOD_ID + "." + entityName;
}

View File

@ -0,0 +1,156 @@
package com.r3944realms.leashedplayer.content.entities;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.config.LeashPlayerCommonConfig;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import io.github.kunosayo.nestle.entity.NestleLeadNormalEntity;
import io.github.kunosayo.nestle.entity.NestleLeadPlayerEntity;
import io.github.kunosayo.nestle.entity.data.NestleLeadData;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.EntityHitResult;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class NestleRopeArrow extends AbstractArrow {
private static final int maxLifeTime = LeashPlayerCommonConfig.TheNestleArrowMaxLifeTime.get();
protected NestleRopeArrow(EntityType<? extends AbstractArrow> pEntityType, Level pLevel) {
super(pEntityType, pLevel);
}
public NestleRopeArrow(EntityType<? extends AbstractArrow> entityType, double pX, double pY, double pZ, Level pLevel, ItemStack pPickupItemStack, @Nullable ItemStack pFiredFromWeapon, @Nullable ServerPlayer serverPlayer) {
super(entityType, pX, pY, pZ, pLevel, pPickupItemStack, pFiredFromWeapon);
if (serverPlayer != null && !level().isClientSide) {
if(serverPlayer.getVehicle() instanceof NestleRopeArrow nestleRopeArrow) {
nestleRopeArrow.removePassenger(serverPlayer);//重置先前的箭矢
nestleRopeArrow.setOwner(null);
}
serverPlayer.startRiding(this);
this.setOwner(serverPlayer);
} else this.setOwner(null);
}
public NestleRopeArrow(EntityType<? extends AbstractArrow> entityType, LivingEntity pOwner, Level pLevel, ItemStack pPickupItemStack, @Nullable ItemStack pFiredFromWeapon) {
super(entityType, pOwner, pLevel, pPickupItemStack, pFiredFromWeapon);
if (!level().isClientSide) {
if(pOwner.getVehicle() instanceof NestleRopeArrow nestleRopeArrow) {
nestleRopeArrow.removePassenger(pOwner);//重置先前的箭矢
nestleRopeArrow.setOwner(null);
}
pOwner.startRiding(this);
this.setOwner(pOwner);
}
}
@Override
protected @NotNull ItemStack getDefaultPickupItem() {
return ModItemRegister.NESTLE_ROPE_ARROW.get().getDefaultInstance();
}
protected ItemStack getOrginalItemStack() {
return Items.ARROW.getDefaultInstance();
}
protected ItemStack getSelfItemStack() {
return ModItemRegister.NESTLE_ROPE_ARROW.get().getDefaultInstance();
}
protected void hitOnEntityHandler(Entity pEntity) {
//NOOP
}
@Override
public void setOwner(@Nullable Entity pEntity) {
boolean isNull = pEntity == null;
this.ownerUUID = isNull ? null : pEntity.getUUID();
this.cachedOwner = isNull ? null : pEntity;
this.pickup = this.pickup == Pickup.CREATIVE_ONLY ? this.pickup : Pickup.DISALLOWED;
}
@Override
protected void tickDespawn() {
this.life++;
if (this.life >= maxLifeTime) {
ItemEntity nestle_arrow_item = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getSelfItemStack());
this.level().addFreshEntity(nestle_arrow_item);
this.discard();
}
}
@Override
protected boolean tryPickup(@NotNull Player pPlayer) {
if (life <= 40)
return false;
else {
this.pickup = Pickup.ALLOWED;
}
return super.tryPickup(pPlayer);
}
@Override
public void tick() {
super.tick();
Entity owner = getOwner();
if (owner != null && !owner.level().isClientSide) {
if (!inGround) {
if (owner.getVehicle() == null) owner.startRiding(this);
}
else {
owner.stopRiding();
setOwner(null);
}
}
if (this.inGround && this.inGroundTime != 0) {
this.level().broadcastEntityEvent(this, (byte)0);
this.setPickupItemStack(new ItemStack(getSelfItemStack().getItem()));
}
}
@Override
protected void onHitEntity(@NotNull EntityHitResult pResult) {
if(!level().isClientSide) {
Entity entity = pResult.getEntity();
hitOnEntityHandler(entity);
Entity owner = this.getOwner();
if (owner == null && entity instanceof Player player) {
this.setOwner(player);
}
else if (owner != null && entity != owner ) {
if (entity instanceof LivingEntity livingEntity && LeashedPlayer.IS_NESTLE_LOADED) {//保证即使没Nestle 也不会导致使用该物品会抛异常
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
if (livingEntity instanceof Player player) {
if (NestleLeadData.isNestle(player, livingEntity)) {
arrow.setItem(getSelfItemStack());
} else {
NestleLeadData.nestleTwo((Player) owner, player);
NestleLeadPlayerEntity.inParamFrom = player.getUUID();
NestleLeadPlayerEntity.inParamTarget = entity.getUUID();
NestleLeadPlayerEntity.ENTITY_TYPE.spawn((ServerLevel)player.level(), player.getBlockPosBelowThatAffectsMyMovement(), MobSpawnType.EVENT);
}
} else {
Player player = (Player) owner;
if (NestleLeadData.isNestle(player, livingEntity)) {
arrow.setItem(getSelfItemStack());
} else {
NestleLeadData.nestleTwo(player, livingEntity);
NestleLeadNormalEntity.inParamFrom = player;
NestleLeadNormalEntity.inParamTarget = livingEntity;
NestleLeadNormalEntity.ENTITY_TYPE.spawn((ServerLevel)player.level(), player.getBlockPosBelowThatAffectsMyMovement(), MobSpawnType.EVENT);
NestleLeadNormalEntity.inParamFrom = null;
NestleLeadNormalEntity.inParamTarget = null;
}
}
this.level().addFreshEntity(arrow);
discard();
}
}
}
else super.onHitEntity(pResult);
}
}

View File

@ -33,7 +33,7 @@ public class SpectralLeashRopeArrow extends LeashRopeArrow {
@Override
public void tick() {
super.tick();
if (this.level().isClientSide && !this.isInGround()) {
if (this.level().isClientSide && !this.inGround) {
this.level().addParticle(ParticleTypes.INSTANT_EFFECT, this.getX(), this.getY(), this.getZ(), 0.0, 0.0, 0.0);
}
}

View File

@ -1,8 +1,6 @@
package com.r3944realms.leashedplayer.content.gamerules;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
@ -27,7 +25,7 @@ public enum GameruleRegistry {
if (gameruleDataTypes.get(gameruleName) != RuleDataType.BOOLEAN) {
return false;
}
return ((ServerLevel)level).getGameRules().getBoolean((GameRules.Key<GameRules.BooleanValue>) gamerules.get(gameruleName));
return level.getGameRules().getBoolean((GameRules.Key<GameRules.BooleanValue>) gamerules.get(gameruleName));
}
@SuppressWarnings("unchecked")
public static Integer getGameruleIntValue(Level level, String gameruleName) {
@ -37,7 +35,7 @@ public enum GameruleRegistry {
if (gameruleDataTypes.get(gameruleName) != RuleDataType.INTEGER) {
return 0;
}
return ((ServerLevel)level).getGameRules().getInt((GameRules.Key<GameRules.IntegerValue>)gamerules.get(gameruleName));
return level.getGameRules().getInt((GameRules.Key<GameRules.IntegerValue>)gamerules.get(gameruleName));
}
public void registerGamerule(String gameruleName, GameRules.Category category, boolean pDefault) {
@ -55,7 +53,7 @@ public enum GameruleRegistry {
gameruleDataTypes.put(gameruleName, RuleDataType.INTEGER);
}
public void registerGamerule(String gameruleName, GameRules.Category category, int pDefault, int pMin, int pMax, BiConsumer<MinecraftServer, GameRules.IntegerValue> pChangeListener) {
gamerules.put(gameruleName, GameRules.register(gameruleName, category, GameRules.IntegerValue.create(pDefault, pMin, pMax, FeatureFlagSet.of(), pChangeListener)));
gamerules.put(gameruleName, GameRules.register(gameruleName, category, GameRules.IntegerValue.create(pDefault, pMin, pMax, pChangeListener)));
gameruleDataTypes.put(gameruleName, RuleDataType.INTEGER);
}
public void registerGamerule(String gameruleName, GameRules.Category category,float value) {

View File

@ -4,7 +4,6 @@ import com.mojang.brigadier.arguments.FloatArgumentType;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.level.GameRules;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -39,8 +38,7 @@ public class Gamerules {
(FloatArgumentType::floatArg,
pType -> new FloatValue(pType, pDefaultValue),
pChangeListener,
GameRules.GameRuleTypeVisitor::visit,
FeatureFlagSet.of()
GameRules.GameRuleTypeVisitor::visit
);
}
public static GameRules.Type<FloatValue> create(
@ -50,8 +48,7 @@ public class Gamerules {
() -> FloatArgumentType.floatArg(pMin, pMax),
pType -> new FloatValue(pType, pDefaultValue),
pChangeListener,
GameRules.GameRuleTypeVisitor::visit,
FeatureFlagSet.of()
GameRules.GameRuleTypeVisitor::visit
);
}
public FloatValue(GameRules.Type<FloatValue> pType, float value) {

View File

@ -0,0 +1,25 @@
package com.r3944realms.leashedplayer.content.gamerules.Server;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.gamerules.Gamerules;
import com.r3944realms.leashedplayer.utils.Util;
import net.minecraft.world.level.GameRules;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import static com.r3944realms.leashedplayer.content.gamerules.Gamerules.GAMERULE_REGISTRY;
@EventBusSubscriber(modid = LeashedPlayer.MOD_ID, bus = EventBusSubscriber.Bus.MOD)
public class CanCommonPlayerChangeSelfTalkArea {
public static final boolean DEFAULT_VALUE = true;
public static final String ID = Util.getGameruleName(CanCommonPlayerChangeSelfTalkArea.class);
public static final String DESCRIPTION_KEY = Gamerules.getDescriptionKey(CanCommonPlayerChangeSelfTalkArea.class);
public static final String NAME_KEY = Gamerules.getNameKey(CanCommonPlayerChangeSelfTalkArea.class);
public static final GameRules.Category CATEGORY = GameRules.Category.PLAYER;
@SubscribeEvent
public static void onCommonSetup(final FMLCommonSetupEvent event) {
GAMERULE_REGISTRY.registerGamerule(ID, CATEGORY, DEFAULT_VALUE);
}
}

View File

@ -0,0 +1,26 @@
package com.r3944realms.leashedplayer.content.gamerules.Server;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.gamerules.Gamerules;
import com.r3944realms.leashedplayer.utils.Util;
import net.minecraft.world.level.GameRules;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import static com.r3944realms.leashedplayer.content.gamerules.Gamerules.GAMERULE_REGISTRY;
@EventBusSubscriber(modid = LeashedPlayer.MOD_ID, bus = EventBusSubscriber.Bus.MOD)
public class DefaultTalkArea {
public static final String CHAT_NONE_HEARD_YOU = "leashedplayer.chat.none_heard_you";
public static final int DEFAULT_VALUE = -1;
public static final String ID = Util.getGameruleName(DefaultTalkArea.class);
public static final String DESCRIPTION_KEY = Gamerules.getDescriptionKey(DefaultTalkArea.class);
public static final String NAME_KEY = Gamerules.getNameKey(DefaultTalkArea.class);
public static final GameRules.Category CATEGORY = GameRules.Category.CHAT;
@SubscribeEvent
public static void commonSetup(final FMLCommonSetupEvent event) {
GAMERULE_REGISTRY.registerGamerule(ID, CATEGORY, DEFAULT_VALUE);
}
}

View File

@ -0,0 +1,29 @@
package com.r3944realms.leashedplayer.content.gamerules.Server;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.gamerules.Gamerules;
import com.r3944realms.leashedplayer.network.client.BooleanGameRuleValueChangeData;
import com.r3944realms.leashedplayer.utils.Util;
import net.minecraft.world.level.GameRules;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.neoforge.network.PacketDistributor;
import static com.r3944realms.leashedplayer.content.gamerules.Gamerules.GAMERULE_REGISTRY;
@EventBusSubscriber(modid = LeashedPlayer.MOD_ID, bus = EventBusSubscriber.Bus.MOD)
public class OpenTOPNeededModeWhenScreenIsNotNull {
public static final boolean DEFAULT_VALUE = true;
public static final String ID = Util.getGameruleName(OpenTOPNeededModeWhenScreenIsNotNull.class);
public static final String DESCRIPTION_KEY = Gamerules.getDescriptionKey(OpenTOPNeededModeWhenScreenIsNotNull.class);
public static final String NAME_KEY = Gamerules.getNameKey(OpenTOPNeededModeWhenScreenIsNotNull.class);
public static final GameRules.Category CATEGORY = GameRules.Category.MISC;
@SubscribeEvent
public static void onCommonSetup(final FMLCommonSetupEvent event) {
GAMERULE_REGISTRY.registerGamerule(ID, CATEGORY, DEFAULT_VALUE, (server, value)->{
PacketDistributor.sendToAllPlayers(new BooleanGameRuleValueChangeData(ID, value.get()));
});
}
}

View File

@ -23,7 +23,7 @@ public class ModCreativeTab {
DeferredRegister.create(Registries.CREATIVE_MODE_TAB, LeashedPlayer.MOD_ID);
public static final String LEASHED_PLAYER_TAB_STRING = "creativetab." + LeashedPlayer.MOD_ID;
public static final String LEASHED_PLAYER_ITEM = "leashedplayer_tab";
public static final Supplier<CreativeModeTab> TEST_TAB = CREATIVE_MODE_TABS.register(LEASHED_PLAYER_ITEM,() -> CreativeModeTab.builder()
public static final Supplier<CreativeModeTab> MODE_TAB_SUPPLIER = CREATIVE_MODE_TABS.register(LEASHED_PLAYER_ITEM,() -> CreativeModeTab.builder()
.title(Component.translatable(getCreativeMod(LEASHED_PLAYER_ITEM)))
.icon(() -> ModItemRegister.LEASH_ROPE_ARROW.get().getDefaultInstance())
.displayItems(((pParameters, pOutput) -> {
@ -32,6 +32,7 @@ public class ModCreativeTab {
pOutput.accept(Items.CROSSBOW);
pOutput.accept(ModItemRegister.LEASH_ROPE_ARROW.get());
pOutput.accept(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get());
if(LeashedPlayer.IS_NESTLE_LOADED) pOutput.accept(ModItemRegister.NESTLE_ROPE_ARROW.get());
pOutput.accept(ModItemRegister.AMETHYST_SHEARS.get());
HolderLookup.RegistryLookup<Potion> potionRegistryLookup = CommonHooks.resolveLookup(Registries.POTION);
if(potionRegistryLookup != null) {
@ -47,19 +48,19 @@ public class ModCreativeTab {
.filter(p_337926_ -> Objects.requireNonNull(p_337926_.getKey()).location().getNamespace().equals(LeashedPlayer.MOD_ID))
.map(p_330083_ -> PotionContents.createItemStack(Items.LINGERING_POTION, p_330083_))
.forEach(pOutput::accept);
pOutput.accept(ModItemRegister.NEOFORGE.get());
pParameters.holders()
.lookup(Registries.POTION)
.ifPresent(
pPotions -> generatePotionEffectTypes(
pOutput,
pPotions,
ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get(),
CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS,
pParameters.enabledFeatures()
)
);
}
pOutput.accept(ModItemRegister.NEOFORGE.get());
pParameters.holders()
.lookup(Registries.POTION)
.ifPresent(
pPotions -> generatePotionEffectTypes(
pOutput,
pPotions,
ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get(),
CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS,
pParameters.enabledFeatures()
)
);
})).build());
private static void generatePotionEffectTypes(
CreativeModeTab.Output pOutput, HolderLookup<Potion> pPotions, Item pItem, CreativeModeTab.TabVisibility pTabVisibility, FeatureFlagSet pRequiredFeatures

View File

@ -1,6 +1,7 @@
package com.r3944realms.leashedplayer.content.items;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.entities.ModEntityRegister;
import com.r3944realms.leashedplayer.content.items.type.*;
import com.r3944realms.leashedplayer.datagen.provider.attributes.ModJukeboxSongs;
import net.minecraft.core.component.DataComponents;
@ -9,10 +10,9 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.JukeboxSong;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.item.ShearsItem;
import net.minecraft.world.item.alchemy.PotionContents;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.common.DeferredSpawnEggItem;
import net.neoforged.neoforge.registries.DeferredRegister;
import java.util.ArrayList;
@ -22,39 +22,44 @@ import java.util.function.Supplier;
public class ModItemRegister {
public static final DeferredRegister<Item> ITEMS =
DeferredRegister.create(BuiltInRegistries.ITEM, LeashedPlayer.MOD_ID);
public static final List<DeferredHolder<Item, Item>> ITEM_SUPPLIER = new ArrayList<>();
public static final DeferredHolder<Item, Item> LEASH_ROPE_ARROW = ModItemRegister.register("leash_rope_arrow",
() -> new LeashRopeArrowItem(new Item.Properties().stacksTo(16)
.setId(ModItemResourceKeys.LEASH_ROPE_ARROW.getResourceKey()))
);
public static final DeferredHolder<Item, Item> SPECTRAL_LEASH_ROPE_ARROW = ModItemRegister.register("spectral_leash_rope_arrow",
() -> new SpectralLeashRopeArrowItem(new Item.Properties().stacksTo(16)
.setId(ModItemResourceKeys.SPECTRAL_LEASH_ROPE_ARROW.getResourceKey())));
public static final DeferredHolder<Item, Item> TIPPED_LEASH_ROPE_ARROW = ModItemRegister.register("tipped_leash_rope_arrow",
() -> new TippedLeashRopeArrowItem(new Item.Properties().stacksTo(16).component(DataComponents.POTION_CONTENTS, PotionContents.EMPTY)
.setId(ModItemResourceKeys.TIPPED_LEASH_ROPE_ARROW.getResourceKey())));
public static final DeferredHolder<Item, Item> AMETHYST_SHEARS = ModItemRegister.register("amethyst_shears",
() -> new LeadBreakerItem(ModToolMaterials.AMETHYST, new Item.Properties().durability(100).component(DataComponents.TOOL, ShearsItem.createToolProperties())
.stacksTo(1)
.setId(ModItemResourceKeys.AMETHYST_SHEARS.getResourceKey())));
public static final DeferredHolder<Item, Item> FABRIC = ModItemRegister.register("fabric",
() -> new TestItem(new Item.Properties().stacksTo(1)
.setId(ModItemResourceKeys.FABRIC.getResourceKey())));
public static final DeferredHolder<Item, Item> NEOFORGE = ModItemRegister.register("neoforge",
() -> new Item(DistProperties(ModJukeboxSongs.FOX_MUSIC)
.setId(ModItemResourceKeys.NEOFORGE.getResourceKey())));
public static final List<Supplier<Item>> ITEM_SUPPLIER = new ArrayList<>();
public static final Supplier<Item> LEASH_ROPE_ARROW = ModItemRegister.register("leash_rope_arrow",
() -> new LeashRopeArrowItem(new Item.Properties().stacksTo(16))
);
public static final Supplier<Item> SPECTRAL_LEASH_ROPE_ARROW = ModItemRegister.register("spectral_leash_rope_arrow",
() -> new SpectralLeashRopeArrowItem(new Item.Properties().stacksTo(16)));
public static final Supplier<Item> TIPPED_LEASH_ROPE_ARROW = ModItemRegister.register("tipped_leash_rope_arrow",
() -> new TippedLeashRopeArrow(new Item.Properties().stacksTo(16).component(DataComponents.POTION_CONTENTS, PotionContents.EMPTY)));
public static final Supplier<Item> NESTLE_ROPE_ARROW = ModItemRegister.register("nestle_rope_arrow",
() -> new NestleRopeArrowItem(new Item.Properties().stacksTo(16)));
public static final Supplier<Item> AMETHYST_SHEARS = ModItemRegister.register("amethyst_shears",
() -> new LeadBreakerItem(ModToolTier.AMETHYST, new Item.Properties().component(DataComponents.TOOL, LeadBreakerItem.createToolProperties())
.stacksTo(1)));
public static final Supplier<Item> KID_SPAWN_EGG = ModItemRegister.register("kid_spawn_egg",
() -> new DeferredSpawnEggItem(ModEntityRegister.KID, 0x3F4F1F, 0x3D0D4D, new Item.Properties()));
public static final Supplier<Item> FABRIC = ModItemRegister.register("fabric",
() -> new TestProcessBarItem(new Item.Properties().stacksTo(1))
);
public static final Supplier<Item> NEOFORGE = ModItemRegister.register("neoforge",
() -> new CanEquipOnHead(DistProperties(ModJukeboxSongs.FOX_MUSIC)));
public static Item.Properties DistProperties(ResourceKey<JukeboxSong> song) {
return new Item.Properties().stacksTo(1).rarity(Rarity.RARE).jukeboxPlayable(song);
}
public static DeferredHolder<Item, Item> register(String name, Supplier<Item> supplier) {
public static Supplier<Item> register(String name, Supplier<Item> supplier) {
return register(name, supplier, true);
}
public static DeferredHolder<Item, Item> register(String name, Supplier<Item> supplier, boolean shouldJoinSupplierLists) {
DeferredHolder<Item, Item> supplierItem = ITEMS.register(name, supplier);
public static Supplier<Item> register(String name, Supplier<Item> supplier, boolean shouldJoinSupplierLists) {
Supplier<Item> supplierItem = ITEMS.register(name, supplier);
if(shouldJoinSupplierLists) ITEM_SUPPLIER.add(supplierItem);
return supplierItem;
}

View File

@ -1,29 +0,0 @@
package com.r3944realms.leashedplayer.content.items;
import com.r3944realms.leashedplayer.LeashedPlayer;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.neoforged.neoforge.registries.DeferredHolder;
public enum ModItemResourceKeys {
LEASH_ROPE_ARROW(ModItemRegister.LEASH_ROPE_ARROW),
SPECTRAL_LEASH_ROPE_ARROW(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW),
TIPPED_LEASH_ROPE_ARROW (ModItemRegister.TIPPED_LEASH_ROPE_ARROW),
AMETHYST_SHEARS(ModItemRegister.AMETHYST_SHEARS),
FABRIC(ModItemRegister.FABRIC),
NEOFORGE(ModItemRegister.NEOFORGE)
;
private final ResourceKey<Item> resourceKey;
ModItemResourceKeys(String name) {
resourceKey = ResourceKey.create(Registries.ITEM, ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, name));
}
ModItemResourceKeys(DeferredHolder<Item, Item> item) {
resourceKey = ResourceKey.create(Registries.ITEM, item.getId());
}
public ResourceKey<Item> getResourceKey() {
return resourceKey;
}
}

View File

@ -1,13 +0,0 @@
package com.r3944realms.leashedplayer.content.items;
import com.r3944realms.leashedplayer.datagen.LanguageAndOtherData.ModItemTags;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.item.ToolMaterial;
public class ModToolMaterials {
public static final ToolMaterial AMETHYST =
new ToolMaterial(BlockTags.INCORRECT_FOR_DIAMOND_TOOL,
100, 8.0F, 2.0F, 15,
ModItemTags.AMETHYST_TOOL_MATERIALS
);
}

View File

@ -0,0 +1,62 @@
package com.r3944realms.leashedplayer.content.items;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.Tier;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.block.Block;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
public enum ModToolTier implements Tier {
AMETHYST(BlockTags.INCORRECT_FOR_DIAMOND_TOOL, 100, 8.0F, 2.0F, 15, () -> Ingredient.of(Items.AMETHYST_SHARD));
private final TagKey<Block> incorrectBlocksForDrops;
private final int uses;
private final float speed;
private final float attackDamageBonus;
private final int enchantmentValue;
private final Supplier<Ingredient> repairIngredient;
ModToolTier(TagKey<Block> incorrectBlocksForDrops, int uses, float speed, float attackDamageBonus, int enchantmentValue, Supplier<Ingredient> repairIngredient) {
this.incorrectBlocksForDrops = incorrectBlocksForDrops;
this.uses = uses;
this.speed = speed;
this.attackDamageBonus = attackDamageBonus;
this.enchantmentValue = enchantmentValue;
this.repairIngredient = repairIngredient;
}
@Override
public int getUses() {
return this.uses;
}
@Override
public float getSpeed() {
return this.speed;
}
@Override
public float getAttackDamageBonus() {
return this.attackDamageBonus;
}
@Override
public @NotNull TagKey<Block> getIncorrectBlocksForDrops() {
return this.incorrectBlocksForDrops;
}
@Override
public int getEnchantmentValue() {
return this.enchantmentValue;
}
@Override
public @NotNull Ingredient getRepairIngredient() {
return this.repairIngredient.get();
}
}

View File

@ -2,8 +2,8 @@ package com.r3944realms.leashedplayer.content.items.repcipe;
import com.r3944realms.leashedplayer.LeashedPlayer;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.item.crafting.CustomRecipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
@ -12,13 +12,13 @@ public class ModRecipeRegister {
public static final DeferredRegister<RecipeSerializer<?>> RECIPE_SERIALIZER =
DeferredRegister.create(BuiltInRegistries.RECIPE_SERIALIZER, LeashedPlayer.MOD_ID);
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<TippedLeashRopeArrowRecipe.TippedLeashRopeArrowARecipe>> TIPPED_LEASH_ROPE_ARROW_A_RECIPE =
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<?>> TIPPED_LEASH_ROPE_ARROW_A_RECIPE =
RECIPE_SERIALIZER.register("tipped_leash_rope_arrow_a_recipe", () ->
new CustomRecipe.Serializer<>(TippedLeashRopeArrowRecipe.TippedLeashRopeArrowARecipe::new)
new SimpleCraftingRecipeSerializer<>(TippedLeashRopeArrowRecipe.TippedLeashRopeArrowARecipe::new)
);
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<TippedLeashRopeArrowRecipe.TippedLeashRopeArrowBRecipe>> TIPPED_LEASH_ROPE_ARROW_B_RECIPE =
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<?>> TIPPED_LEASH_ROPE_ARROW_B_RECIPE =
RECIPE_SERIALIZER.register("tipped_leash_rope_arrow_b_recipe", () ->
new CustomRecipe.Serializer<>(TippedLeashRopeArrowRecipe.TippedLeashRopeArrowBRecipe::new)
new SimpleCraftingRecipeSerializer<>(TippedLeashRopeArrowRecipe.TippedLeashRopeArrowBRecipe::new)
);
public static void register(IEventBus eventBus) {

View File

@ -11,6 +11,7 @@ import net.minecraft.world.item.crafting.CustomRecipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class TippedLeashRopeArrowRecipe {
public static class TippedLeashRopeArrowARecipe extends CustomRecipe {
@ -54,10 +55,25 @@ public abstract class TippedLeashRopeArrowRecipe {
}
}
/**
* Used to determine if this recipe can fit in a grid of the given width/height
*/
@Override
public @NotNull RecipeSerializer<? extends CustomRecipe> getSerializer() {
public boolean canCraftInDimensions(int pWidth, int pHeight) {
return pWidth >= 3 && pHeight >= 3;
}
@Override
public @NotNull RecipeSerializer<?> getSerializer() {
return ModRecipeRegister.TIPPED_LEASH_ROPE_ARROW_A_RECIPE.get();
}
@Override
public @NotNull ItemStack getResultItem(@Nullable HolderLookup.Provider pRegistries) {
return new ItemStack(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get());
}
public @NotNull ItemStack getResultItem() {
return getResultItem(null);
}
}
public static class TippedLeashRopeArrowBRecipe extends CustomRecipe {
@ -97,10 +113,23 @@ public abstract class TippedLeashRopeArrowRecipe {
}
return ItemStack.EMPTY;
}
@Override
public @NotNull RecipeSerializer<? extends CustomRecipe> getSerializer() {
public boolean canCraftInDimensions(int pWidth, int pHeight) {
return pWidth >= 2 && pHeight >= 2;
}
@Override
public @NotNull RecipeSerializer<?> getSerializer() {
return ModRecipeRegister.TIPPED_LEASH_ROPE_ARROW_B_RECIPE.get();
}
@Override
public @NotNull ItemStack getResultItem(@Nullable HolderLookup.Provider pRegistries) {
return new ItemStack(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get());
}
public @NotNull ItemStack getResultItem() {
return getResultItem(null);
}
}
}

View File

@ -0,0 +1,17 @@
package com.r3944realms.leashedplayer.content.items.type;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.Equipable;
import net.minecraft.world.item.Item;
import org.jetbrains.annotations.NotNull;
public class CanEquipOnHead extends Item implements Equipable {
public CanEquipOnHead(Properties pProperties) {
super(pProperties);
}
@Override
public @NotNull EquipmentSlot getEquipmentSlot() {
return EquipmentSlot.HEAD;
}
}

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