Compare commits

...

30 Commits

Author SHA1 Message Date
c46f753aee 更新了LOGO
Some checks failed
Build / build (push) Failing after 34s
2025-03-27 18:02:30 +08:00
4e005d8e91 2025/01/28
版本更新至1.21.3_0.0.3.9.9
迁移大部分1.21版本本模组的内容到1.21.3
1.药水拴绳箭
2.Neoforge物品
3.全身可戴物品
2025-01-28 20:29:52 +08:00
93e5d73fa4 2024/11/02
Fix some little bug
Add areaTalk Command
2024-11-02 23:25:06 +08:00
867a79f96b 2024/11/01
Up
2024-11-01 07:41:25 +08:00
107ef3dc7d 2024/11/01
Fix some BUG and Add new Item to break lead rope
2024-11-01 00:13:27 +08:00
f0d078e770 2024-10-28
修复了有关箭不能正常显示的BUG
将默认值调高减少拴绳断裂的可能性
2024/10/28
Fix some BUG
2024-10-28 22:47:07 +08:00
a990abad34 2024/10/28
Fix some BUG
2024-10-28 19:48:08 +08:00
ea2e64ac00 Updated 1.21 -> 1.21.3 2024-10-28 00:37:00 +08:00
3944Realms
4d166edc20
Merge pull request #21 from 3944Realms/1.21
2024-10-25
2024-10-25 16:59:19 +08:00
3944Realms
a0e2b95167
Merge pull request #20 from 3944Realms/1.21
2024-10-23
2024-10-24 23:18:37 +08:00
3944Realms
5e84120b52
Merge pull request #19 from 3944Realms/1.21
1.21
2024-10-23 16:23:46 +08:00
3944Realms
ca41573c6d
Merge pull request #18 from 3944Realms/1.21
2024-10-23
2024-10-23 13:04:58 +08:00
3944Realms
f19f3292d7
Merge pull request #17 from 3944Realms/1.21
1.21
2024-10-22 20:47:13 +08:00
3944Realms
c9a3962695
Merge pull request #16 from 3944Realms/1.21
2024-10-22
2024-10-22 17:45:04 +08:00
3944Realms
40ae2c14e1
Merge pull request #15 from 3944Realms/1.21
2024-10-21
2024-10-21 22:09:10 +08:00
3944Realms
88b1aadb72
Merge pull request #14 from 3944Realms/1.21
2024-10-06
2024-10-06 00:55:40 +08:00
3944Realms
056298b0b8
Merge pull request #13 from 3944Realms/1.21
2024-10-05
2024-10-05 22:57:59 +08:00
3944Realms
c680c4a2e1
Merge pull request #12 from 3944Realms/1.21
2024-10-02
2024-10-02 17:18:08 +08:00
3944Realms
2ed7ef6673
Merge pull request #11 from 3944Realms/1.21
2024-09-19
2024-09-19 12:47:03 +08:00
3944Realms
8c76921090
Merge pull request #10 from 3944Realms/1.21
1.21
2024-09-17 23:18:15 +08:00
3944Realms
d97ff2c944
Merge pull request #9 from 3944Realms/1.21
2024-09-10
2024-09-10 07:19:26 +08:00
3944Realms
0f5332d9f5
Merge pull request #8 from 3944Realms/1.21
1.21
2024-09-10 07:18:01 +08:00
3944Realms
7a8815c6f2
Merge pull request #7 from 3944Realms/1.21
2024-09-10
2024-09-10 00:36:30 +08:00
3944Realms
3918fdb763
Merge pull request #6 from 3944Realms/1.21
2024-09-09
2024-09-09 16:50:27 +08:00
3944Realms
1383071d69
Merge pull request #5 from 3944Realms/1.21
2024-09-07
2024-09-07 18:12:34 +08:00
3944Realms
8963e6a587
Merge pull request #4 from 3944Realms/1.21
2024-09-05
2024-09-07 18:04:21 +08:00
3944Realms
3a290351b5
Update issue templates 2024-09-04 16:03:15 +08:00
3944Realms
821db74f67
Merge pull request #3 from 3944Realms/1.21
2024-09-04
2024-09-04 15:54:04 +08:00
3944Realms
bd5ea4a47e
Merge pull request #2 from 3944Realms/1.21
1.21
2024-09-03 18:57:29 +08:00
3944Realms
6cba32481d
Merge pull request #1 from 3944Realms/1.21
2024-09-02
2024-09-03 18:19:38 +08:00
126 changed files with 3178 additions and 822 deletions

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,38 @@
---
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

@ -0,0 +1,20 @@
---
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 @@
# 版本 0.0.3.9.4 提前介绍c[最终版本对于0.0.4] 【注意:本解釋簡繁混寫,因爲趕時間,所以並不怎麽規範,請諒解】
# 版本 1.21.3 0.0.3.9.9
## 简介
现在开始你可以用拴绳拴住玩家,也可以拴住自己了,不如尝试拴住彼此来通关我的世界吧(
@ -18,6 +18,8 @@
### 拴绳箭 [有普通和荧光两种箭矢]
获得飞一样的感觉(操作不当可能会摔死
+ 拴绳箭可以拴其它可拴LivingEntity了
### 紫水晶剪刀
剪断拴绳链接,在发射器里可使用
#### 射中实体时会将射击者拴绳绑定在改实体上该实体父类必须是有LivingEntity类型同时拴绳箭会以普通的箭矢掉落
#### 射中栅栏时,会自动将玩家拴在上面 ,同时拴绳箭会以普通的箭矢掉落
#### 在地面上的箭可以通过按Shift靠近来捡起如果捡起实体为发射箭矢玩家则直接获取拴绳箭矢如果捡起者为非发射者则成为发送者的拴绳持有者并获得普通箭矢
@ -52,4 +54,4 @@
* `LP.KeepLeashNotDropTime` - 此规则决定,当拴绳关系创建时一段时间里,即是距离已经达到了断裂距离,也保持其不断裂 [默认值: 240ticks ,可设置范围[80, 1200]ticks]
* `LP.DisableMoveCheck` - 此规则启用将会禁止服务器对玩家进行速度过快修正 [默认值: True]

View File

@ -3,7 +3,7 @@ plugins {
id 'eclipse'
id 'idea'
id 'maven-publish'
id 'net.neoforged.gradle.userdev' version '7.0.145'
id 'net.neoforged.gradle.userdev' version '7.0.180'
}
tasks.named('wrapper', Wrapper).configure {
@ -25,11 +25,10 @@ repositories {
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.
@ -54,12 +53,12 @@ runs {
client {
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}
server {
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
programArgument '--nogui'
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}
// This run config launches GameTestServer and runs all registered gametests, then exits.
@ -72,9 +71,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.
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
arguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
}
}
@ -155,7 +154,7 @@ publishing {
}
repositories {
maven {
url "file://${project.projectDir}/repo"
url = "file://${project.projectDir}/repo"
}
}
}
@ -163,13 +162,11 @@ publishing {
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,25 +2,34 @@
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
neogradle.subsystems.parchment.mappingsVersion=2024.07.28
neogradle.subsystems.parchment.minecraftVersion=1.21.3
neogradle.subsystems.parchment.mappingsVersion=2024.12.07
# 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
minecraft_version=1.21.3
# 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,1.22)
minecraft_version_range=[1.21.3]
enable_accesstransformers=true
# The Neo version must agree with the Minecraft version to get a valid artifact
neo_version=21.0.157
neo_version=21.3.58
# The Neo version range can use any version of Neo as bounds
neo_version_range=[21.0.0-beta,)
neo_version_range=[21.3.58,)
# The loader version range can only use the major version of FML as bounds
loader_version_range=[4,)
loader_version_range=[1,)
## Mod Properties
@ -32,7 +41,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=0.0.3.9.4
mod_version=1.21.3_0.0.3.9.9
# 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

@ -0,0 +1,2 @@
#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.9-bin.zip
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.12-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,5 @@ pluginManagement {
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0'
}

View File

@ -1,4 +1,5 @@
// 1.21 2024-10-23T13:15:06.1102778 Item Models: leashedplayer
// 1.21.3 2025-01-27T17:55:02.7810616 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
@ -6,3 +7,4 @@
bb0d76077719c83c8a8bd4346a24ea1766175125 assets/leashedplayer/models/item/fabric.json
114d3cc5832ef047403114504483c6f3ea07e77c assets/leashedplayer/models/item/leash_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,2 +1,3 @@
// 1.21 2024-10-23T13:15:06.1082841 Registries
6f79a674215db9f9d2820b1c7f052c60ce729fee data/leashedplayer/painting_variant/group_photo.json
// 1.21.3 2025-01-27T17:42:59.0511618 Registries
f2536789df7f06362718a59ba4a96890e2f9b8aa data/leashedplayer/jukebox_song/what_does_the_fox_say.json
84106976f4f71012fc5bd1784303a0d135623c77 data/leashedplayer/painting_variant/group_photo.json

View File

@ -1,2 +1,8 @@
// 1.21 2024-10-23T13:15:06.1012494 Tags for minecraft:item mod id leashedplayer
36c1cccc1dfa448620c4e9cbc4a7d73986ff9e47 data/minecraft/tags/item/arrows.json
// 1.21.3 2025-01-27T21:03:10.3134854 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
84707301f1fe2490a899deb51302d413cfff5a89 data/minecraft/tags/item/enchantable/durability.json
84707301f1fe2490a899deb51302d413cfff5a89 data/minecraft/tags/item/enchantable/mining.json
84707301f1fe2490a899deb51302d413cfff5a89 data/minecraft/tags/item/enchantable/vanishing.json
5cf114c796db4c2235df11ee7f656bba09d72a7a data/minecraft/tags/item/head_armor.json

View File

@ -1,2 +1,2 @@
// 1.21 2024-10-23T14:43:16.8619078 Languages: en_us for mod: leashedplayer
4dc2ca922a540c7133a4a6867dfcd8bfec5a1db4 assets/leashedplayer/lang/en_us.json
// 1.21.3 2025-01-27T21:03:10.3134854 Languages: en_us for mod: leashedplayer
2c7f061dfc276db13135adce15c68cfc145ccf37 assets/leashedplayer/lang/en_us.json

View File

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

View File

@ -0,0 +1,2 @@
// 1.21.3 2025-01-27T17:42:59.0511618 Sound Definitions
81f1cc9f404c2670bf7cc679107177ffb0b48c77 assets/leashedplayer/sounds.json

View File

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

View File

@ -1,2 +1,2 @@
// 1.21 2024-10-23T13:15:06.1042677 Languages: lzh for mod: leashedplayer
bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f assets/leashedplayer/lang/lzh.json
// 1.21.3 2025-01-26T22:13:41.4090272 Languages: lzh for mod: leashedplayer
7536eb6d1c69695c06ebb9da5b57a391174b02cb assets/leashedplayer/lang/lzh.json

View File

@ -1,7 +0,0 @@
// 1.21 2024-10-23T13:15:06.1092763 Recipes
1b45d1ad8dc73f1787c97777ad13d9771c9e0ad1 data/leashedplayer/advancement/recipes/misc/leash_rope_arrow.json
974d74538b3e172946f2e169036b453b6eb6bc0a data/leashedplayer/recipe/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
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

View File

@ -1,2 +1,2 @@
// 1.21 2024-10-23T14:43:16.860909 Languages: zh_cn for mod: leashedplayer
35bc6c3001138c5306d1ee9d55ef3dfbfd417e08 assets/leashedplayer/lang/zh_cn.json
// 1.21.3 2025-01-27T21:03:10.3134854 Languages: zh_cn for mod: leashedplayer
f7bcf89907a8ca5f575e4b519d53cd0628bb1e6b assets/leashedplayer/lang/zh_cn.json

View File

@ -0,0 +1,11 @@
// 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 2024-10-23T14:19:10.2054361 Advancements
// 1.21.3 2025-01-26T22:13:41.4090272 Advancements
4d97adba079f1966090a52443bb439319f550680 data/leashedplayer/advancement/advancement_leash_arrow.json
f16184b81ea35a0fbd8f2c49b085a96c32818c69 data/leashedplayer/advancement/dog_running_player.json
bce12ed339b3b0fded263ba039f7a4e6fcfb84ca data/leashedplayer/advancement/follow_arrow.json
@ -6,4 +6,7 @@ bce12ed339b3b0fded263ba039f7a4e6fcfb84ca data/leashedplayer/advancement/follow_a
25f6b476b194a27c0fe0e75d74ac3a7ff4054789 data/leashedplayer/advancement/leashed_self.json
a69a455855fb6dd8a8ac131a55099de5de45d7c4 data/leashedplayer/advancement/leash_arrow.json
133f844ffafd37b9ba57cafa96350f035cac57f9 data/leashedplayer/advancement/leash_start.json
2d8bce7fd078f9cc6b73b77f2fbab30e6cc197f4 data/leashedplayer/advancement/leash_terminator.json
4e567c22e18462ad367fe1817140d1ffa13a6294 data/leashedplayer/advancement/neo_fox.json
4b0bcf6b372f52e954edcef37a6b04435ec2b4e8 data/leashedplayer/advancement/no_leash.json
72f40eb5816d1e8c296bdf4df6b599c15ba7e7e9 data/leashedplayer/advancement/tipped_leash_arrow.json

View File

@ -1,2 +1,2 @@
// 1.21 2024-10-23T14:43:16.8589078 Languages: zh_tw for mod: leashedplayer
c6df14a1f53a3e892ebc6b396b552ff27f1a7580 assets/leashedplayer/lang/zh_tw.json
// 1.21.3 2025-01-27T21:03:10.3134854 Languages: zh_tw for mod: leashedplayer
c23825af72a73bc54b72ad3817acb5a03d299375 assets/leashedplayer/lang/zh_tw.json

View File

@ -9,32 +9,55 @@
"advancement.leashedplayer.leash_arrow.desc": "Maybe you can using it to shoot some mob?",
"advancement.leashedplayer.leash_start": "The Power of Traction",
"advancement.leashedplayer.leash_start.desc": "Journey to becoming a Leash Expert",
"advancement.leashedplayer.leash_terminator": "The Lead Terminator",
"advancement.leashedplayer.leash_terminator.desc": "I am Lead Terminator!",
"advancement.leashedplayer.leashed_friend": "Be bound by Rope",
"advancement.leashedplayer.leashed_friend.desc": "Be Bond by player with lead",
"advancement.leashedplayer.leashed_self": "Stable Connection",
"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.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",
"advancement.leashedplayer.tipped_leash_arrow.desc": "A dazzling array of Leash Rope arrows",
"creativetab.leashedplayer.leashedplayer_tab": "Leashed Player",
"effect.leashedplayer.no_leash": "No Leash",
"entity.leashedplayer.kid_player": "Kid",
"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.CreateLeashFenceKnotEntityIfAbsent": "Create Leash Fence Knot Entity if absent",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent.description": "Create LeashKnot Entity if it's absent on fence",
"gamerule.LP.DisablePlayerMoveCheck": "Disable Player Move Check",
"gamerule.LP.DisablePlayerMoveCheck.description": "Disable the player's movement Check And Correct it.",
"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.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:",
"item.leash_rope_arrow.desc.2": "§c1.§r If it hits a fence or an entity, it will leash the owner to it and drop as a normal arrow.",
"item.leash_rope_arrow.desc.3": "§c2.§r Crouching near the arrow allows for faster retrieval. If the arrow's owner is not the player, the owner will be leashed to the player who picks it up.",
"item.leash_rope_arrow.desc.4": "§c3.§r When fired from its launcher, the first entity hit will become the arrow's owner and will fly along with it.",
"item.leash_rope_arrow.desc.5": "§c4.§r Under the §c§l\"no_leash\"§r effect, the behavior of the arrow when fired will follow the launchers behavior.",
"item.leash_rope_arrow.description": "Arrows with ropes attached?",
"item.leashedplayer.amethyst_shears": "Amethyst Shears",
"item.leashedplayer.fabric": "Fabric",
"item.leashedplayer.leash_rope_arrow": "Leash Rope Arrow",
"item.leashedplayer.neoforge": "NeoForge",
"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.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.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.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",
@ -50,6 +73,16 @@
"leashedplayer.command.motion.message.adder.successful": "§bAdd Successfully.§a%s§7:§f[§eVec§7: §a(§f%f§7,§f%f§7,§f%f§a)§f]§r",
"leashedplayer.command.motion.message.multiply.successful": "§bMultiply Successfully.§a%s§7:§f[§eVec§7: §a(§f%f§7,§f%f§7,§f%f§a)§f]§r",
"leashedplayer.command.motion.message.setter.successful": "§bSet Successfully.§a%s§7:§f[§eVec§7: §a(§f%f§7,§f%f§7,§f%f§a)§f]§r",
"leashedplayer.lead_breaker.item.desc": "§7can break the link of leash",
"leashedplayer.lead_breaker.item.use_fai": "§cFailed to break §f%1$s§c 's Leashed Link to §f%2$s",
"leashedplayer.lead_breaker.item.use_suf": "§aSuccessfully break §f%1$s§a 's Leashed Link to §f%2$s ",
"leashedplayer.leash_rope.length.decrease": "§Decrease the §f%s §cLength of Leash Rope§7(§bLength§7:§e%d§7)",
"leashedplayer.leash_rope.length.decrease.self": "§cDecrease the Length of Leash Rope§7(§bLength§7:§e%d§7)",
"leashedplayer.leash_rope.length.failed": "§cFailed",
"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",
"painting.leashedplayer.group_photo.author": "§9Leisure §4Time §eDock§r",
"painting.leashedplayer.group_photo.title": "§dGroup Photo §7[§6memorable§7]§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 +1,3 @@
{}
{
"entity.leashedplayer.kid_player": "幼"
}

View File

@ -9,32 +9,55 @@
"advancement.leashedplayer.leash_arrow.desc": "也许可以用它来发射生物?",
"advancement.leashedplayer.leash_start": "牵引之力",
"advancement.leashedplayer.leash_start.desc": "拴绳大师之路",
"advancement.leashedplayer.leash_terminator": "拴绳终结者",
"advancement.leashedplayer.leash_terminator.desc": "我來终结拴绳者!",
"advancement.leashedplayer.leashed_friend": "拴绳链接",
"advancement.leashedplayer.leashed_friend.desc": "被玩家用拴绳链接",
"advancement.leashedplayer.leashed_self": "稳固联结",
"advancement.leashedplayer.leashed_self.desc": "用拴绳拴住自己",
"advancement.leashedplayer.neo_fox": "NEOFORGE!",
"advancement.leashedplayer.neo_fox.desc": "似乎可以戴头上",
"advancement.leashedplayer.no_leash": "勿拴我",
"advancement.leashedplayer.no_leash.desc": "你不会被任何东西拴住",
"advancement.leashedplayer.tipped_leash_arrow": "神说要有更多箭矢",
"advancement.leashedplayer.tipped_leash_arrow.desc": "真是琳琅满目啊",
"creativetab.leashedplayer.leashedplayer_tab": "可拴玩家",
"effect.leashedplayer.no_leash": "禁拴",
"entity.leashedplayer.kid_player": "小孩",
"entity.leashedplayer.leash_rope_arrow": "拴绳箭",
"entity.leashedplayer.nestle_rope_arrow": "贴贴拴绳箭",
"entity.leashedplayer.spectral_leash_rope_arrow": "拴绳光灵箭",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent": "如果缺失则创建拴绳结",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent.description": "如果在栅栏处缺失拴绳结,则创建它",
"gamerule.LP.DisablePlayerMoveCheck": "禁止检查玩家移动",
"gamerule.LP.DisablePlayerMoveCheck.description": "禁止检查玩家移动并且纠正它",
"gamerule.LP.KeepLeashNotDropTime": "保持拴绳不掉落的时间",
"gamerule.LP.KeepLeashNotDropTime.description": "当距离过远时,保持新建拴绳不掉落的时间 (刻)",
"gamerule.LP.TeleportWithLeashedPlayers": "被拴玩家随玩家持有者传送",
"gamerule.LP.TeleportWithLeashedPlayers.description": "传送时将被拴玩家与持有者一起传送",
"item.leash_rope_arrow.desc.1": "§7该箭将会携带拥有者随其飞行",
"item.leash_rope_arrow.desc.2": "§c1.§r 若击中栅栏或生物时,将持有者拴在其上并已普通箭形式掉落;",
"item.leash_rope_arrow.desc.3": "§c2.§r 靠近该箭下蹲可以更快拾取该箭,如果该箭持有者不是自己,则持有者将被拾取者拴住;",
"item.leash_rope_arrow.desc.4": "§c3.§r 当前其发射器里发射,第一个射中的生物将成为此箭的持有者并随箭飞行;",
"item.leash_rope_arrow.desc.5": "§c4.§r 在§c§l禁拴§7(§c§lno_leash§7)§r效果下射出的箭行为同发射器。",
"item.leash_rope_arrow.description": "带有拴绳的箭矢?",
"item.leashedplayer.amethyst_shears": "紫水晶剪刀",
"item.leashedplayer.fabric": "Fabric",
"item.leashedplayer.leash_rope_arrow": "拴绳箭",
"item.leashedplayer.neoforge": "NeoForge",
"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.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.category": "可拴玩家",
"key.leashedplayer.leash_length.add": "增加拴绳长度",
"key.leashedplayer.leash_length.not_support_to_not_player_entity": "只在玩家身上有效",
"key.leashedplayer.leash_length.sub": "减小拴绳长度",
"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沒有拴绳数据实体",
@ -50,6 +73,16 @@
"leashedplayer.command.motion.message.adder.successful": "§b添加成功.§a%s§7:§f[§e加速度§7:§a(§f%f§7,§f%f§7,§f%f§a)§f]§r",
"leashedplayer.command.motion.message.multiply.successful": "§b倍乘成功.§a%s§7:§f[§e加速度§7:§a(§f%f§7,§f%f§7,§f%f§a)§f]§r",
"leashedplayer.command.motion.message.setter.successful": "§b设置成功.§a%s§7:§f[§e加速度§7:§a(§f%f§7,§f%f§7,§f%f§a)§f]§r",
"leashedplayer.lead_breaker.item.desc": "§7可以破坏拴绳链接",
"leashedplayer.lead_breaker.item.use_fai": "§c无法剪断§f%2$s§c对§f%1$s§c拴绳链接",
"leashedplayer.lead_breaker.item.use_suf": "§a成功剪断§f%2$s§a对§f%1$s§a拴绳链接",
"leashedplayer.leash_rope.length.decrease": "§c减少§f%s的拴绳长度§c§7(§b长度§7:§e%d§7)",
"leashedplayer.leash_rope.length.decrease.self": "§c减少拴绳长度§c§7(§b长度§7:§e%d§7)",
"leashedplayer.leash_rope.length.failed": "§c失败",
"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以加快拾取",
"painting.leashedplayer.group_photo.author": "§9闲趣§4时§e坞§r",
"painting.leashedplayer.group_photo.title": "§d集体照 §7[§6纪念§7]§r"
"painting.leashedplayer.group_photo.title": "§d集体照 §7[§6纪念§7]§r",
"sound.leashedplayer.subtitle.what_does_the_fox_say": "大楚兴~ 陈胜王~~"
}

View File

@ -9,32 +9,55 @@
"advancement.leashedplayer.leash_arrow.desc": "也許可以用它發射生物?",
"advancement.leashedplayer.leash_start": "牽引之力",
"advancement.leashedplayer.leash_start.desc": "拴繩大師之路",
"advancement.leashedplayer.leash_terminator": "拴繩終結者",
"advancement.leashedplayer.leash_terminator.desc": "吾將終結拴繩!",
"advancement.leashedplayer.leashed_friend": "拴繩鏈接",
"advancement.leashedplayer.leashed_friend.desc": "被玩家用拴繩鏈接",
"advancement.leashedplayer.leashed_self": "穩固聯結",
"advancement.leashedplayer.leashed_self.desc": "用栓繩拴住自己",
"advancement.leashedplayer.neo_fox": "NEOFORGE!",
"advancement.leashedplayer.neo_fox.desc": "似乎可以戴著",
"advancement.leashedplayer.no_leash": "請恁勿拴唔",
"advancement.leashedplayer.no_leash.desc": "恁不會被任何拴住",
"advancement.leashedplayer.tipped_leash_arrow": "神說要有更多箭矢",
"advancement.leashedplayer.tipped_leash_arrow.desc": "真是琳琅滿目啊",
"creativetab.leashedplayer.leashedplayer_tab": "可拴玩家",
"effect.leashedplayer.no_leash": "禁拴",
"entity.leashedplayer.kid_player": "小孩",
"entity.leashedplayer.leash_rope_arrow": "拴繩箭",
"entity.leashedplayer.nestle_rope_arrow": "貼貼拴繩箭",
"entity.leashedplayer.spectral_leash_rope_arrow": "拴繩光靈箭",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent": "如果缺失則創建拴繩結",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent.description": "如果在柵欄処缺失拴繩結,則創建它",
"gamerule.LP.DisablePlayerMoveCheck": "禁止檢查玩家移動",
"gamerule.LP.DisablePlayerMoveCheck.description": "禁止檢查玩家移動並糾正他它",
"gamerule.LP.KeepLeashNotDropTime": "保持其不掉落的時間",
"gamerule.LP.KeepLeashNotDropTime.description": "儅距離過遠時,保持其不掉落的時間(刻)",
"gamerule.LP.TeleportWithLeashedPlayers": "被拴玩家随玩家持有者傳送",
"gamerule.LP.TeleportWithLeashedPlayers.description": "將被拴玩家將隨持有者一起傳送",
"item.leash_rope_arrow.desc.1": "§7該箭將會攜帶擁有者隨其飛行",
"item.leash_rope_arrow.desc.2": "§c1.§r 若擊中柵欄或生物時,將持有者拴在其上並以普通箭的形式掉落;",
"item.leash_rope_arrow.desc.3": "§c2.§r 靠近該箭下蹲可以更快拾取該箭,如果該箭的持有者不是自己,則持有者將被拾取者拴住;",
"item.leash_rope_arrow.desc.4": "§c3.§r 當箭從發射器發射時,第一個射中的生物將成為此箭的持有者並隨箭飛行;",
"item.leash_rope_arrow.desc.5": "§c4.§r 在§c§l禁拴§7(§c§lno_leash§7)§r效果下射出的箭行為將與發射器的行為相同。",
"item.leash_rope_arrow.description": "帶有拴繩的箭矢?",
"item.leashedplayer.amethyst_shears": "紫水晶剪刀",
"item.leashedplayer.fabric": "Fabric",
"item.leashedplayer.leash_rope_arrow": "拴繩箭",
"item.leashedplayer.neoforge": "NeoForge",
"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.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.category": "可拴玩家",
"key.leashedplayer.leash_length.add": "增加拴繩長度",
"key.leashedplayer.leash_length.not_support_to_not_player_entity": "僅對玩家有效",
"key.leashedplayer.leash_length.sub": "減小拴繩長度",
"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沒有拴繩數據實體",
@ -50,6 +73,16 @@
"leashedplayer.command.motion.message.adder.successful": "§b添加成功.§a%s§7:§f[§e加速度§7:§a(§f%f§7,§f%f§7,§f%f§a)§f]§r",
"leashedplayer.command.motion.message.multiply.successful": "§b倍乘成功.§a%s§7:§f[§e加速度§7:§a(§f%f§7,§f%f§7,§f%f§a)§f]§r",
"leashedplayer.command.motion.message.setter.successful": "§b設置成功.§a%s§7:§f[§e加速度§7:§a(§f%f§7,§f%f§7,§f%f§a)§f]§r",
"leashedplayer.lead_breaker.item.desc": "§7可以破壞拴繩鏈接",
"leashedplayer.lead_breaker.item.use_fai": "§c未能剪斷§f%2$s§c對§f%1$s§c拴繩鏈接",
"leashedplayer.lead_breaker.item.use_suf": "§a成功剪斷§f%2$s§a對§f%1$s§a拴繩鏈接",
"leashedplayer.leash_rope.length.decrease": "§c減少§f%s§c的拴繩長度§7(§長度§7:§e%d§7)",
"leashedplayer.leash_rope.length.decrease.self": "§c減少拴繩長度§7(§長度§7:§e%d§7)",
"leashedplayer.leash_rope.length.failed": "§c失敗",
"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以加速拾取",
"painting.leashedplayer.group_photo.author": "§9閑趣§4時§e塢§r",
"painting.leashedplayer.group_photo.title": "§d集體照 §7[§6紀念§7]§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/generated",
"textures": {
"layer0": "leashedplayer:item/amethyst_shears"
}
}

View File

@ -0,0 +1,7 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "minecraft:item/tipped_arrow_head",
"layer1": "leashedplayer:item/tipped_leash_rope_arrow_base"
}
}

View File

@ -0,0 +1,8 @@
{
"music/what_does_the_fox_say": {
"sounds": [
"leashedplayer:music/what_does_the_fox_say"
],
"subtitle": "sound.leashedplayer.subtitle.what_does_the_fox_say"
}
}

View File

@ -0,0 +1,5 @@
{
"values": [
"leashedplayer:amethyst_shears"
]
}

View File

@ -0,0 +1,34 @@
{
"parent": "leashedplayer:leash_start",
"criteria": {
"has_amethyst_shears": {
"conditions": {
"items": [
{
"items": "leashedplayer:amethyst_shears"
}
]
},
"trigger": "minecraft:inventory_changed"
}
},
"display": {
"description": {
"translate": "advancement.leashedplayer.leash_terminator.desc"
},
"hidden": true,
"icon": {
"count": 1,
"id": "leashedplayer:amethyst_shears"
},
"title": {
"translate": "advancement.leashedplayer.leash_terminator"
}
},
"requirements": [
[
"has_amethyst_shears"
]
],
"sends_telemetry_event": true
}

View File

@ -0,0 +1,36 @@
{
"parent": "leashedplayer:leash_start",
"criteria": {
"has_neo_fox": {
"conditions": {
"items": [
{
"items": "leashedplayer:neoforge"
}
]
},
"trigger": "minecraft:inventory_changed"
}
},
"display": {
"announce_to_chat": false,
"description": {
"translate": "advancement.leashedplayer.neo_fox.desc"
},
"frame": "goal",
"hidden": true,
"icon": {
"count": 1,
"id": "leashedplayer:neoforge"
},
"title": {
"translate": "advancement.leashedplayer.neo_fox"
}
},
"requirements": [
[
"has_neo_fox"
]
],
"sends_telemetry_event": true
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,8 @@
{
"comparator_output": 15,
"description": {
"translate": "jukebox_song.leashedplayer.what_does_the_fox_say"
},
"length_in_seconds": 121.0,
"sound_event": "leashedplayer:what_does_the_fox_say"
}

View File

@ -1,5 +1,11 @@
{
"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

@ -0,0 +1,16 @@
{
"type": "minecraft:crafting_shaped",
"category": "misc",
"key": {
"#": "minecraft:amethyst_shard",
"%": "minecraft:stick"
},
"pattern": [
"#%",
"%#"
],
"result": {
"count": 1,
"id": "leashedplayer:amethyst_shears"
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,4 @@
{
"type": "leashedplayer:tipped_leash_rope_arrow_a_recipe",
"category": "misc"
}

View File

@ -0,0 +1,4 @@
{
"type": "leashedplayer:tipped_leash_rope_arrow_b_recipe",
"category": "misc"
}

View File

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

View File

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

View File

@ -0,0 +1,5 @@
{
"values": [
"leashedplayer:amethyst_shears"
]
}

View File

@ -0,0 +1,5 @@
{
"values": [
"leashedplayer:amethyst_shears"
]
}

View File

@ -0,0 +1,5 @@
{
"values": [
"leashedplayer:amethyst_shears"
]
}

View File

@ -0,0 +1,6 @@
{
"values": [
"leashedplayer:neoforge",
"minecraft:lead"
]
}

View File

@ -1,42 +1,146 @@
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.content.ModKeyMapping;
import com.r3944realms.leashedplayer.content.entities.ModEntityRegister;
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.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 net.minecraft.client.Minecraft;
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.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.PotionContents;
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.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
import net.neoforged.neoforge.client.event.*;
import net.neoforged.neoforge.network.PacketDistributor;
import java.util.List;
@EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD, modid = LeashedPlayer.MOD_ID)
public class ClientEventHandler {
@SubscribeEvent
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;
}));
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
));
});
@EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.GAME, modid = LeashedPlayer.MOD_ID)
public static class Game {
@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);
}
}
@SubscribeEvent
public static void onKetBoardInput(InputEvent.Key event) {
Minecraft minecraft = Minecraft.getInstance();
LocalPlayer player = minecraft.player;
assert player != null;
if (ModKeyMapping.KEY_ADD_LEASH_LENGTH.isDown()) {
PlayerLeashable playerLeashable = (PlayerLeashable) player;
if (playerLeashable.getLeashDataFromEntityData() == null) {
assert minecraft.level != null;
List<HitResult> refLookAtEntityHitResult = Util.getRefLookAtEntityHitResult(player, minecraft.level, 32, entity -> entity instanceof LivingEntity);
Entity theNearestEntityFromHitResultList = Util.getTheNearestEntityFromHitResultList(player, refLookAtEntityHitResult);
if(theNearestEntityFromHitResultList != null) {
if (theNearestEntityFromHitResultList instanceof Player refPlayer) {
PacketDistributor.sendToServer(new IncreaseLeashRopeLength(Code.OTHER_ST, refPlayer.getStringUUID()));
}
}
}
if (playerLeashable.getLeashDataFromEntityData() != null) {
PacketDistributor.sendToServer(new IncreaseLeashRopeLength(Code.SELF, player.getStringUUID()));
}
}
if (ModKeyMapping.KEY_SUB_LEASH_LENGTH.isDown()) {
PlayerLeashable playerLeashable = (PlayerLeashable) player;
if (playerLeashable.getLeashDataFromEntityData() == null) {
assert minecraft.level != null;
List<HitResult> refLookAtEntityHitResult = Util.getRefLookAtEntityHitResult(player, minecraft.level, 32, entity -> entity instanceof LivingEntity);
Entity theNearestEntityFromHitResultList = Util.getTheNearestEntityFromHitResultList(player, refLookAtEntityHitResult);
if(theNearestEntityFromHitResultList != null) {
if (theNearestEntityFromHitResultList instanceof Player refPlayer) {
PacketDistributor.sendToServer(new DecreaseLeashRopeLength(Code.OTHER_ST, refPlayer.getStringUUID()));
}
}
}
if (playerLeashable.getLeashDataFromEntityData() != null) {
PacketDistributor.sendToServer(new DecreaseLeashRopeLength(Code.SELF, player.getStringUUID()));
}
}
}
}
@EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD, modid = LeashedPlayer.MOD_ID)
public static class Mod {
@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) {
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;
}));
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
));
});
}
@SubscribeEvent
public static void RegisterRenderer(EntityRenderersEvent.RegisterRenderers event) {
event.registerEntityRenderer(ModEntityRegister.LEASH_ROPE_ARROW.get(), LeashRopeArrowRenderer::new);
event.registerEntityRenderer(ModEntityRegister.SPECTRAL_LEASH_ROPE_ARROW.get(), SpectralLeashRopeArrowRenderer::new);
}
@SubscribeEvent
public static void onRegisterItemColorHandlers (RegisterColorHandlersEvent.Item event){
event.register(
(color, i) -> i > 0
? -1
: color.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).getColor() | 0xFF000000,
ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get()
);
}
}
@SubscribeEvent
public static void RegisterRenderer(EntityRenderersEvent.RegisterRenderers event) {
event.registerEntityRenderer(ModEntityRegister.LEASH_ROPE_ARROW.get(), LeashRopeArrowRenderer::new);
event.registerEntityRenderer(ModEntityRegister.SPECTRAL_LEASH_ROPE_ARROW.get(), SpectralLeashRopeArrowRenderer::new);
}
}

View File

@ -4,23 +4,29 @@ 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.effects.ModEffectRegister;
import com.r3944realms.leashedplayer.content.effects.ModPotionRegister;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
import com.r3944realms.leashedplayer.content.misc.LeadBreakItemBehavior;
import com.r3944realms.leashedplayer.utils.Util;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Leashable;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.animal.Fox;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.PotionBrewing;
import net.minecraft.world.item.alchemy.Potions;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.DispenserBlock;
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.RegisterCommandsEvent;
import net.neoforged.neoforge.event.brewing.RegisterBrewingRecipesEvent;
import net.neoforged.neoforge.event.tick.EntityTickEvent;
@ -44,35 +50,56 @@ public class CommonEventHandler {
@SubscribeEvent
public static void OnLivingTickEvent(EntityTickEvent.Post event) {
Entity entity = event.getEntity();
if (entity.level().isClientSide()) {
Level level = entity.level();
if (level.isClientSide()) {
return;
}
if (entity instanceof LivingEntity living) {
MobEffectInstance effect = living.getEffect(ModEffectRegister.NO_LEASH_EFFECT);
if(effect != null && effect.getDuration() > 0){
if (entity instanceof PlayerLeashable player) {
if (player.getLeashHolder() != null) {
if (player.getLeashHolder() instanceof LeashRopeArrow arrow)
arrow.setOwner(null);
player.dropLeash(true, !(player.getLeashHolder() instanceof LeashRopeArrow));
}
} else if (entity instanceof Leashable leashable) {
if (leashable.getLeashHolder() != null) {
if (leashable.getLeashHolder() instanceof LeashRopeArrow arrow)
arrow.setOwner(null);
leashable.dropLeash(true, !(leashable.getLeashHolder() instanceof LeashRopeArrow));
}
}
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());
} 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));
event.setOutput(instance);
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) {
DispenserBlock.registerProjectileBehavior(ModItemRegister.LEASH_ROPE_ARROW.get());
DispenserBlock.registerProjectileBehavior(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get());
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());
});
}
}

View File

@ -7,7 +7,9 @@ import com.r3944realms.leashedplayer.content.effects.ModPotionRegister;
import com.r3944realms.leashedplayer.content.entities.ModEntityRegister;
import com.r3944realms.leashedplayer.content.items.ModCreativeTab;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import com.r3944realms.leashedplayer.content.items.repcipe.ModRecipeRegister;
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.ModLoadingContext;
@ -20,8 +22,12 @@ public class LeashedPlayer {
public static final String MOD_ID = "leashedplayer";
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);
ModEffectRegister.register(event);
ModPotionRegister.register(event);
@ -48,6 +54,17 @@ public class LeashedPlayer {
}
return M2;
}
public static Integer M3() {
if(M3 == null) {
M3 = LeashPlayerCommonConfig.MinimumLeashLengthCanBeSet.get();
}
return M3;
}
public static Integer M4() {
if(M4 == null) {
M4 = LeashPlayerCommonConfig.MaximumLeashLengthCanBeSet.get();
}
return M4;
}
}

View File

@ -0,0 +1,527 @@
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

@ -0,0 +1,41 @@
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

@ -0,0 +1,13 @@
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

@ -0,0 +1,120 @@
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> {
private final ItemInHandRenderer heldItemRenderer;
public ChestItemLayerRenderer(RenderLayerParent<S, 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) {
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();
}
}
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();
}
}
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();
}
}
}
}

View File

@ -4,20 +4,27 @@ 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> {
public class LeashRopeArrowRenderer extends ArrowRenderer<LeashRopeArrow, ArrowRenderState> {
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 ResourceLocation getTextureLocation(@NotNull LeashRopeArrow pEntity) {
public @NotNull ArrowRenderState createRenderState() {
return new ArrowRenderState();
}
@Override
protected @NotNull ResourceLocation getTextureLocation(@NotNull ArrowRenderState arrowRenderState) {
return LEASH_ROPE_ARROW;
}
}

View File

@ -4,20 +4,28 @@ 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> {
public class SpectralLeashRopeArrowRenderer extends ArrowRenderer<SpectralLeashRopeArrow, ArrowRenderState> {
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 ResourceLocation getTextureLocation(@NotNull SpectralLeashRopeArrow pEntity) {
public @NotNull ArrowRenderState createRenderState() {
return new ArrowRenderState();
}
@Override
protected @NotNull ResourceLocation getTextureLocation(@NotNull ArrowRenderState arrowRenderState) {
return SPECTRAL_LEASH_ROPE_ARROW;
}
}

View File

@ -27,7 +27,7 @@ public class LeashPlayerCommonConfig {
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:2.0f, Invalid Range:[2.0f, 5.0f] ]").defineInRange("BreakLengthTimeBase", 3.0f, 3.0f ,6.0f);
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);
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

@ -0,0 +1,37 @@
package com.r3944realms.leashedplayer.content;
import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.client.KeyMapping;
import net.neoforged.neoforge.client.settings.KeyConflictContext;
import net.neoforged.neoforge.client.settings.KeyModifier;
import org.lwjgl.glfw.GLFW;
public class ModKeyMapping {
static String KEY_ROOT_ = "key.leashedplayer.";
public static String CATEGORY = "key.leashedplayer.category";
public static String
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_ADD_LEASH_LENGTH =
new KeyMapping(
ADD_LEASH_LENGTH_KEY,
KeyConflictContext.IN_GAME,
KeyModifier.CONTROL,
InputConstants.Type.KEYSYM,
GLFW.GLFW_KEY_UP,
CATEGORY
);
public static final KeyMapping KEY_SUB_LEASH_LENGTH =
new KeyMapping(
SUB_LEASH_LENGTH_KEY,
KeyConflictContext.IN_GAME,
KeyModifier.CONTROL,
InputConstants.Type.KEYSYM,
GLFW.GLFW_KEY_DOWN,
CATEGORY
);
}

View File

@ -41,6 +41,7 @@ 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);
}
@ -59,6 +60,7 @@ 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);
}
@ -77,6 +79,7 @@ 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));
}

View File

@ -1,6 +1,7 @@
package com.r3944realms.leashedplayer.content.effects;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.effects.type.NoLeashEffect;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectCategory;
@ -14,7 +15,7 @@ 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(
"no_leash",
() -> new MobEffect(MobEffectCategory.NEUTRAL, 12063764)
() -> new NoLeashEffect(MobEffectCategory.NEUTRAL, 12063764)
);
public static <T extends MobEffect>DeferredHolder<MobEffect, T> register(String name, Supplier<T> effect) {
return MOB_EFFECT.register(name, effect);

View File

@ -0,0 +1,37 @@
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;
import net.minecraft.world.entity.Leashable;
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) {
MobEffectInstance effect = pLivingEntity.getEffect(ModEffectRegister.NO_LEASH_EFFECT);
if(effect != null && effect.getDuration() != 0) {
if (pLivingEntity instanceof Leashable leashable) {
if (leashable.getLeashHolder() instanceof LeashRopeArrow arrow) {
arrow.dropLeashHandler();
leashable.dropLeash(true, false);
}
leashable.dropLeash(true, true);
}
}
return true;
}
@Override
public boolean shouldApplyEffectTickThisTick(int pDuration, int pAmplifier) {
return true;
}
}

View File

@ -7,8 +7,16 @@ import com.r3944realms.leashedplayer.content.gamerules.Server.KeepLeashNotDropTi
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import com.r3944realms.leashedplayer.modInterface.ILivingEntityExtension;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.particles.ColorParticleOption;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.network.chat.Component;
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.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
@ -21,6 +29,7 @@ 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.item.alchemy.PotionContents;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult;
@ -28,79 +37,118 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class LeashRopeArrow extends AbstractArrow {
private static final int maxLifeTime = LeashPlayerCommonConfig.TheLeashArrowMaxLifeTime.get();
protected LeashRopeArrow(EntityType<? extends AbstractArrow> entityType,Level pLevel) {
super(entityType, pLevel);
}
public static final String PUSH_SHIFT_TO_PICKUP_QUICKLY = "leashedplayer.leash_rope_arrow.try_to_pickup.push_shift_tip";
private static final int EXPOSED_POTION_DECAY_TIME = 600;
private static final int NO_EFFECT_COLOR = -1;
private static final EntityDataAccessor<Integer> ID_EFFECT_COLOR = SynchedEntityData.defineId(LeashRopeArrow.class, EntityDataSerializers.INT);
private static final byte EVENT_POTION_PUFF = 0;
private static final int maxLifeTime = LeashPlayerCommonConfig.TheLeashArrowMaxLifeTime.get();
protected LeashRopeArrow(EntityType<? extends AbstractArrow> entityType,Level pLevel) {
super(entityType, pLevel);
public LeashRopeArrow(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) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity(serverPlayer, (ServerLevel) level());
if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.setOwner(null);
}
((PlayerLeashable)serverPlayer).setLeashedTo(this, true);
}
private PotionContents getPotionContents() {
ItemStack pickupItemStackOrigin = this.getPickupItemStackOrigin();
pickupItemStackOrigin.setCount(1);
return pickupItemStackOrigin.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
}
public void addEffect(MobEffectInstance pEffectInstance) {
this.setPotionContents(this.getPotionContents().withEffectAdded(pEffectInstance));
}
private void setPotionContents(PotionContents pPotionContents) {
this.getPickupItemStackOrigin().set(DataComponents.POTION_CONTENTS, pPotionContents);
this.updateColor();
}
private void updateColor() {
PotionContents potioncontents = this.getPotionContents();
this.entityData.set(ID_EFFECT_COLOR, potioncontents.equals(PotionContents.EMPTY) ? -1 : potioncontents.getColor());
}
@Override
protected void defineSynchedData(SynchedEntityData.@NotNull Builder pBuilder) {
super.defineSynchedData(pBuilder);
pBuilder.define(ID_EFFECT_COLOR, -1);
}
@Override
protected void setPickupItemStack(@NotNull ItemStack pPickupItemStack) {
super.setPickupItemStack(pPickupItemStack);
this.updateColor();
}
public LeashRopeArrow(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);
this.updateColor();
if(serverPlayer != null && !level().isClientSide) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity(serverPlayer, (ServerLevel) level());
if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.setOwner(null);//将先前的箭矢置空
}
((PlayerLeashable)serverPlayer).setLeashedTo(this, true);
}
}
public LeashRopeArrow(EntityType<? extends AbstractArrow> entityType, LivingEntity pOwner, Level pLevel, ItemStack pPickupItemStack, @Nullable ItemStack pFiredFromWeapon) {
super(entityType, pOwner, pLevel, pPickupItemStack, pFiredFromWeapon);
if(pOwner instanceof PlayerLeashable lPlayer && !level().isClientSide) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) lPlayer, (ServerLevel) level());
if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.setOwner(null);
}
lPlayer.setLeashedTo(this, true);
public LeashRopeArrow(EntityType<? extends AbstractArrow> entityType, LivingEntity pOwner, Level pLevel, ItemStack pPickupItemStack, @Nullable ItemStack pFiredFromWeapon) {
super(entityType, pOwner, pLevel, pPickupItemStack, pFiredFromWeapon);
this.updateColor();
if (pOwner instanceof PlayerLeashable lPlayer && !level().isClientSide) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) lPlayer, (ServerLevel) level());
if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.setOwner(null);
}
lPlayer.setLeashedTo(this, true);
}
}
@Override
protected @NotNull ItemStack getDefaultPickupItem() {
return ModItemRegister.LEASH_ROPE_ARROW.get().getDefaultInstance();
}
@Override
protected @NotNull ItemStack getDefaultPickupItem() {
return new ItemStack(ModItemRegister.LEASH_ROPE_ARROW.get());
}
@Override
public void setOwner(@Nullable Entity pEntity) {
// super.setOwner(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
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 boolean tryPickup(@NotNull Player pPlayer) {
//时间1.40 禁止
//时间2.240
@Override
protected boolean tryPickup(@NotNull Player pPlayer) {
//时间1.40 禁止
//时间2.240
// 如果(非仅创造拾取)
// 如果 (按Shift )
// 如果(拥有者) -> 拾取到完整箭取消绑定(super给父类处理)
// 否则:时间仍为原需时间 ->不能获取完整的箭重绑定当前拥有者的Holder是否为本箭才重绑定
// 否则: 禁止
// 否则:
// 如果 (按Shift )
// 如果(拥有者) -> 且拾取到完整箭取消绑定
// 否则:时间仍为原需时间 ->不能获取完整的箭重绑定
// 否则: 禁止
//时间3
// 如果 (按Shift )
// 如果(拥有者) -> 拾取到完整箭取消绑定(super给父类处理)
// 否则:时间仍为原需时间 ->不能获取完整的箭重绑定当前拥有者的Holder是否为本箭才重绑定
// 否则: 禁止
// 否则:
// 如果 (按Shift )
// 如果(拥有者) -> 且拾取到完整箭取消绑定
// 否则:时间仍为原需时间 ->不能获取完整的箭重绑定
// 否则: 禁止
//时间3
// 如果(拥有者) -> 拾取到完整箭取消绑定
// 否则:不能获取完整的箭重绑定
if(life <= 40 ) {
return false;
}
else {
PlayerLeashable playerLeashable = (PlayerLeashable) pPlayer;
if(this.getOwner() == null) {//未有Owner始终可检
return true;
}
if(life <= 40 ) {
return false;
} else {
PlayerLeashable playerLeashable = (PlayerLeashable) pPlayer;
if(this.getOwner() != null) {//未有Owner始终可检
if(life <= 240) {
if(pPlayer.isShiftKeyDown()) {
Entity leashDataEntity = this.getOwner() instanceof PlayerLeashable ? PlayerLeashable.getLeashDataEntity((ServerPlayer) this.getOwner(), (ServerLevel) level()) : this.getOwner();
if(this.ownedBy(pPlayer)) {
this.pickup = Pickup.ALLOWED;
if(this.equals(leashDataEntity)) playerLeashable.dropLeash(true, false);
if(this.equals(leashDataEntity)) {
pPlayer.playSound(SoundEvents.LEASH_KNOT_BREAK, 1, 1);
playerLeashable.dropLeash(true, false);
}
} else {
if(life >= 120) {
Entity owner = getOwner();
@ -108,30 +156,39 @@ public class LeashRopeArrow extends AbstractArrow {
// if(this.equals(leashDataEntity)) {
if(owner instanceof PlayerLeashable player) {
player.setLeashedTo(pPlayer, true);
pPlayer.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
} else if(owner instanceof Leashable leashable) {
leashable.setLeashedTo(pPlayer, true);
pPlayer.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
}
ItemEntity itemEntity = new ItemEntity(level(), getX(), getY(), getZ(), getOrginalItemStack());
level().addFreshEntity(itemEntity);
discard();
// }
} else return true;
}
} else return false;
}
} else return false;
} else {
((ServerPlayer)pPlayer).sendSystemMessage(Component.translatable(PUSH_SHIFT_TO_PICKUP_QUICKLY), true);
return false;
}
}
else {
} else {
Entity leashDataEntity = this.getOwner() instanceof PlayerLeashable ? PlayerLeashable.getLeashDataEntity((ServerPlayer) this.getOwner(), (ServerLevel) level()) : this.getOwner();
if(this.ownedBy(pPlayer)) {
this.pickup = Pickup.ALLOWED;
if(this.equals(leashDataEntity)) playerLeashable.dropLeash(true, false);
if(this.equals(leashDataEntity)) {
pPlayer.playSound(SoundEvents.LEASH_KNOT_BREAK, 1, 1);
playerLeashable.dropLeash(true, false);
}
} else {
Entity owner = getOwner();
if(owner instanceof PlayerLeashable player) {
player.setLeashedTo(pPlayer, true);
pPlayer.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
} else if(owner instanceof Leashable leashable) {
leashable.setLeashedTo(pPlayer, true);
pPlayer.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
}
ItemEntity itemEntity = new ItemEntity(level(), getX(), getY(), getZ(), getOrginalItemStack());
level().addFreshEntity(itemEntity);
@ -139,138 +196,262 @@ public class LeashRopeArrow extends AbstractArrow {
}
}
}
} else if (this.pickup != Pickup.CREATIVE_ONLY) this.pickup = Pickup.ALLOWED;
else return pPlayer.hasInfiniteMaterials() && this.pickup == Pickup.CREATIVE_ONLY;
return super.tryPickup(pPlayer);
}
protected void hitOnEntityHandler(Entity pEntity) {
//NOOP
}
protected ItemStack getOrginalItemStack() {
return Items.ARROW.getDefaultInstance();
}
protected ItemStack getSelfItemStack() {
return ModItemRegister.LEASH_ROPE_ARROW.get().getDefaultInstance();
}
@Override
protected void tickDespawn() {
this.life++;
if (this.life >= maxLifeTime) {
ItemEntity leash_rope_arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
this.level().addFreshEntity(leash_rope_arrow);
this.discard();
}
}
@Override
protected void onHitBlock(@NotNull BlockHitResult pResult) {
if(!level().isClientSide) {
if (getOwner() instanceof PlayerLeashable pL) {
if (this.level().getBlockState(pResult.getBlockPos()).is(BlockTags.FENCES)) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
if(leashDataEntity != null) {
pL.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
}
Entity leashKnotFence = PlayerLeashable.createLeashKnotFence((ServerLevel) this.level(), pResult.getBlockPos());
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
pL.setLeashedTo(leashKnotFence, true);
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
this.level().addFreshEntity(arrow);
discard();
}
} else if(getOwner() instanceof Leashable L) {
if (this.level().getBlockState(pResult.getBlockPos()).is(BlockTags.FENCES)) {
Entity leashDataEntity = this.getOwner();
if(leashDataEntity != null) {
L.dropLeash(true, false);
}
Entity leashKnotFence = LeashFenceKnotEntity.getOrCreateKnot(this.level(), pResult.getBlockPos());
L.setLeashedTo(leashKnotFence, true);
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
this.level().addFreshEntity(arrow);
discard();
}
return super.tryPickup(pPlayer);
}
protected void hitOnEntityHandler(Entity pEntity) {
if(pEntity instanceof LivingEntity pLiving) {
super.doPostHurtEffects(pLiving);
Entity entity = this.getEffectSource();
PotionContents potioncontents = this.getPotionContents();
if (potioncontents.potion().isPresent()) {
for (MobEffectInstance mobeffectinstance : potioncontents.potion().get().value().getEffects()) {
pLiving.addEffect(
new MobEffectInstance(
mobeffectinstance.getEffect(),
Math.max(mobeffectinstance.mapDuration(p_268168_ -> p_268168_ / 8), 1),
mobeffectinstance.getAmplifier(),
mobeffectinstance.isAmbient(),
mobeffectinstance.isVisible()
),
entity
);
}
}
super.onHitBlock(pResult);
for (MobEffectInstance effectInstance : potioncontents.customEffects()) {
pLiving.addEffect(effectInstance, entity);
}
}
}
protected ItemStack getOrginalItemStack() {
return Items.ARROW.getDefaultInstance();
}
protected ItemStack getSelfItemStack() {
return ModItemRegister.LEASH_ROPE_ARROW.get().getDefaultInstance();
}
@Override
protected void onHitEntity(@NotNull EntityHitResult pResult) {
if(!level().isClientSide()){
Entity entity = pResult.getEntity();
hitOnEntityHandler(entity);
if(this.getOwner() instanceof LivingEntity livingEntity ) {
MobEffectInstance effect = livingEntity.getEffect(ModEffectRegister.NO_LEASH_EFFECT);
if(effect != null && effect.getDuration() > 0) {
this.setOwner(null);
}
@Override
protected void tickDespawn() {
this.life++;
if (this.life >= maxLifeTime) {
ItemEntity leash_rope_arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getSelfItemStack());
this.level().addFreshEntity(leash_rope_arrow);
this.discard();
}
}
@Override
public void tick() {
super.tick();
if (this.level().isClientSide) {
if (this.isInGround()) {
if (this.inGroundTime % 5 == 0) {
this.makeParticle(1);
}
if(entity instanceof LivingEntity livingEntity) {
if(livingEntity.equals(this.getOwner())) return;
if(this.getOwner() == null && livingEntity instanceof PlayerLeashable pL) { //发射器发出或命令生成
setOwner(livingEntity);
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
if(leashDataEntity != null) pL.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
pL.setLeashedTo(this, true);
return;
} else if (this.getOwner() instanceof PlayerLeashable pL) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
if(leashDataEntity != null) pL.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
pL.setLeashedTo(pResult.getEntity(), true);
this.level().addFreshEntity(arrow);
discard();
} else {
if(entity instanceof Leashable leashable) {
if (getOwner() == null) {
Entity leashDataEntity = leashable.getLeashHolder();
if (leashDataEntity != null)
leashable.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
leashable.setLeashedTo(this, true);
this.setOwner(entity);
return;
}
} else {
this.makeParticle(2);
}
} else if (this.isInGround() && this.inGroundTime != 0 && !this.getPotionContents().equals(PotionContents.EMPTY) && this.inGroundTime >= 600) {
this.level().broadcastEntityEvent(this, (byte)0);
this.setPickupItemStack(new ItemStack(getSelfItemStack().getItem()));
}
}
private void makeParticle(int pParticleAmount) {
int i = this.getColor();
if (i != -1 && pParticleAmount > 0) {
for (int j = 0; j < pParticleAmount; j++) {
this.level()
.addParticle(
ColorParticleOption.create(ParticleTypes.ENTITY_EFFECT, i),
this.getRandomX(0.5),
this.getRandomY(),
this.getRandomZ(0.5),
0.0,
0.0,
0.0
);
}
}
}
public int getColor() {
return this.entityData.get(ID_EFFECT_COLOR);
}
@Override
protected void onHitBlock(@NotNull BlockHitResult pResult) {
if(!level().isClientSide) {
if (getOwner() instanceof PlayerLeashable pL) {
if (this.level().getBlockState(pResult.getBlockPos()).is(BlockTags.FENCES)) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
if(leashDataEntity != null) {
pL.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.dropLeashHandler();
}
if(entity instanceof LivingEntity living) {
if(this.getOwner() != null && this.getOwner()instanceof Leashable leashable) {
leashable.setLeashedTo(living, true);
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
this.level().addFreshEntity(arrow);
discard();
return;
}
}
ItemEntity lead = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, Items.LEAD.getDefaultInstance());
this.level().addFreshEntity(lead);
}
Entity leashKnotFence = PlayerLeashable.createLeashKnotFence((ServerLevel) this.level(), pResult.getBlockPos());
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
pL.setLeashedTo(leashKnotFence, true);
leashKnotFence.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
this.level().addFreshEntity(arrow);
discard();
}
else if (entity instanceof LeashFenceKnotEntity leashKnotFence) {
if (getOwner() instanceof PlayerLeashable pL) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
if(leashDataEntity != null) pL.dropLeash(true, true);
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
pL.setLeashedTo(leashKnotFence, true);
this.level().addFreshEntity(arrow);
discard();
return;
} else if(getOwner() instanceof Leashable L) {
if (this.level().getBlockState(pResult.getBlockPos()).is(BlockTags.FENCES)) {
Entity leashDataEntity = this.getOwner();
if(leashDataEntity != null) {
leashDataEntity.playSound(SoundEvents.LEASH_KNOT_BREAK, 1, 1);
L.dropLeash(true, false);
if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.setOwner(null);
}
}
Entity leashKnotFence = LeashFenceKnotEntity.getOrCreateKnot(this.level(), pResult.getBlockPos());
L.setLeashedTo(leashKnotFence, true);
leashKnotFence.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
this.level().addFreshEntity(arrow);
discard();
}
}
}
super.onHitBlock(pResult);
}
@Override
protected void onHitEntity(@NotNull EntityHitResult pResult) {
if (!level().isClientSide()) {
Entity entity = pResult.getEntity();
hitOnEntityHandler(entity);
if (this.getOwner() instanceof LivingEntity livingEntity ) {
MobEffectInstance effect = livingEntity.getEffect(ModEffectRegister.NO_LEASH_EFFECT);
if (effect != null && effect.getDuration() != 0) {
this.dropLeashHandler();
}
}
if(entity instanceof LivingEntity livingEntity) {
if(livingEntity.equals(this.getOwner())) return;
if(this.getOwner() == null && livingEntity instanceof PlayerLeashable pL) { //发射器发出或命令生成
setOwner(livingEntity);
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
if(leashDataEntity != null) {
pL.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.dropLeashHandler();
}
}
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
livingEntity.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
pL.setLeashedTo(this, true);
} else if (this.getOwner() instanceof PlayerLeashable pL) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
if(leashDataEntity != null) {
pL.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
if (leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.dropLeashHandler();
}
}
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
livingEntity.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
pL.setLeashedTo(pResult.getEntity(), true);
this.level().addFreshEntity(arrow);
discard();
} else {
if (entity instanceof Leashable leashable) {
if (getOwner() == null) {
Entity leashDataEntity = leashable.getLeashHolder();
if (leashDataEntity != null) {
leashable.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
if (leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.dropLeashHandler();
}
}
livingEntity.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
leashable.setLeashedTo(this, true);
this.setOwner(entity);
return;
}
}
if (entity instanceof LivingEntity living) {
if (this.getOwner() != null && this.getOwner()instanceof Leashable leashable) {
livingEntity.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
leashable.setLeashedTo(living, true);
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
this.level().addFreshEntity(arrow);
discard();
return;
}
}
ItemEntity lead = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, Items.LEAD.getDefaultInstance());
this.level().addFreshEntity(lead);
}
}
if(!level().isClientSide()) super.onHitEntity(pResult);
else if (entity instanceof LeashFenceKnotEntity leashKnotFence) {
if (getOwner() instanceof PlayerLeashable pL) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
if (leashDataEntity != null) {
pL.dropLeash(true, true);
if (leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.dropLeashHandler();
}
}
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
leashKnotFence.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
pL.setLeashedTo(leashKnotFence, true);
this.level().addFreshEntity(arrow);
discard();
}
} else {
ItemEntity lead = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, Items.LEAD.getDefaultInstance());
this.level().addFreshEntity(lead);
}
}
}
/**
* Handles an entity event received from a {@link net.minecraft.network.protocol.game.ClientboundEntityEventPacket}.
*/
@Override
public void handleEntityEvent(byte pId) {
if (pId == 0) {
int i = this.getColor();
if (i != -1) {
float f = (float)(i >> 16 & 0xFF) / 255.0F;
float f1 = (float)(i >> 8 & 0xFF) / 255.0F;
float f2 = (float)(i & 0xFF) / 255.0F;
for (int j = 0; j < 20; j++) {
this.level()
.addParticle(
ColorParticleOption.create(ParticleTypes.ENTITY_EFFECT, f, f1, f2),
this.getRandomX(0.5),
this.getRandomY(),
this.getRandomZ(0.5),
0.0,
0.0,
0.0
);
}
}
} else {
super.handleEntityEvent(pId);
}
}
public void dropLeashHandler() {
this.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
this.setOwner(null);
}
}

View File

@ -2,6 +2,8 @@ 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;
@ -17,7 +19,7 @@ public class ModEntityRegister {
.eyeHeight(0.13F)
.clientTrackingRange(4)
.updateInterval(20)
.build("leash_rope_arrow")
.build(ResourceKey.create(Registries.ENTITY_TYPE, ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "leash_rope_arrow")))
);
public static final DeferredHolder<EntityType<?>, EntityType<SpectralLeashRopeArrow>> SPECTRAL_LEASH_ROPE_ARROW = ENTITY_TYPE.register(
"spectral_leash_rope_arrow",
@ -26,14 +28,9 @@ public class ModEntityRegister {
.eyeHeight(0.13F)
.clientTrackingRange(4)
.updateInterval(20)
.build("spectral_leash_rope_arrow")
.build(ResourceKey.create(Registries.ENTITY_TYPE, ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "spectral_leash_rope_arrow")))
);
// 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

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

View File

@ -1,6 +1,8 @@
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;
@ -25,7 +27,7 @@ public enum GameruleRegistry {
if (gameruleDataTypes.get(gameruleName) != RuleDataType.BOOLEAN) {
return false;
}
return level.getGameRules().getBoolean((GameRules.Key<GameRules.BooleanValue>) gamerules.get(gameruleName));
return ((ServerLevel)level).getGameRules().getBoolean((GameRules.Key<GameRules.BooleanValue>) gamerules.get(gameruleName));
}
@SuppressWarnings("unchecked")
public static Integer getGameruleIntValue(Level level, String gameruleName) {
@ -35,7 +37,7 @@ public enum GameruleRegistry {
if (gameruleDataTypes.get(gameruleName) != RuleDataType.INTEGER) {
return 0;
}
return level.getGameRules().getInt((GameRules.Key<GameRules.IntegerValue>)gamerules.get(gameruleName));
return ((ServerLevel)level).getGameRules().getInt((GameRules.Key<GameRules.IntegerValue>)gamerules.get(gameruleName));
}
public void registerGamerule(String gameruleName, GameRules.Category category, boolean pDefault) {
@ -53,7 +55,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, pChangeListener)));
gamerules.put(gameruleName, GameRules.register(gameruleName, category, GameRules.IntegerValue.create(pDefault, pMin, pMax, FeatureFlagSet.of(), pChangeListener)));
gameruleDataTypes.put(gameruleName, RuleDataType.INTEGER);
}
public void registerGamerule(String gameruleName, GameRules.Category category,float value) {

View File

@ -4,6 +4,7 @@ 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;
@ -38,7 +39,8 @@ public class Gamerules {
(FloatArgumentType::floatArg,
pType -> new FloatValue(pType, pDefaultValue),
pChangeListener,
GameRules.GameRuleTypeVisitor::visit
GameRules.GameRuleTypeVisitor::visit,
FeatureFlagSet.of()
);
}
public static GameRules.Type<FloatValue> create(
@ -48,7 +50,8 @@ public class Gamerules {
() -> FloatArgumentType.floatArg(pMin, pMax),
pType -> new FloatValue(pType, pDefaultValue),
pChangeListener,
GameRules.GameRuleTypeVisitor::visit
GameRules.GameRuleTypeVisitor::visit,
FeatureFlagSet.of()
);
}
public FloatValue(GameRules.Type<FloatValue> pType, float value) {

View File

@ -1,25 +0,0 @@
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 DisablePlayerMoveCheck {
public static final boolean DEFAULT_VALUE = true;
public static final String ID = Util.getGameruleName(DisablePlayerMoveCheck.class);
public static final String DESCRIPTION_KEY = Gamerules.getDescriptionKey(DisablePlayerMoveCheck.class);
public static final String NAME_KEY = Gamerules.getNameKey(DisablePlayerMoveCheck.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

@ -4,8 +4,9 @@ import com.r3944realms.leashedplayer.LeashedPlayer;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.decoration.PaintingVariant;
import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.Potion;
import net.minecraft.world.item.alchemy.PotionContents;
@ -31,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());
pOutput.accept(ModItemRegister.AMETHYST_SHEARS.get());
HolderLookup.RegistryLookup<Potion> potionRegistryLookup = CommonHooks.resolveLookup(Registries.POTION);
if(potionRegistryLookup != null) {
potionRegistryLookup.listElements()
@ -45,8 +47,28 @@ 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()
)
);
}
})).build());
private static void generatePotionEffectTypes(
CreativeModeTab.Output pOutput, HolderLookup<Potion> pPotions, Item pItem, CreativeModeTab.TabVisibility pTabVisibility, FeatureFlagSet pRequiredFeatures
) {
pPotions.listElements()
.filter(potionReference -> potionReference.value().isEnabled(pRequiredFeatures))
.map(potionReference -> PotionContents.createItemStack(pItem, potionReference))
.forEach(itemStack -> pOutput.accept(itemStack, pTabVisibility));
}
public static String getCreativeMod(@NotNull String tabs) {
return LEASHED_PLAYER_TAB_STRING + "." + tabs;
}

View File

@ -1,12 +1,18 @@
package com.r3944realms.leashedplayer.content.items;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.items.type.LeashRopeArrowItem;
import com.r3944realms.leashedplayer.content.items.type.SpectralLeashRopeArrowItem;
import com.r3944realms.leashedplayer.content.items.type.TestItem;
import com.r3944realms.leashedplayer.content.items.type.*;
import com.r3944realms.leashedplayer.datagen.provider.attributes.ModJukeboxSongs;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries;
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.registries.DeferredRegister;
import java.util.ArrayList;
@ -16,23 +22,39 @@ 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<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 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 Supplier<Item> SPECTRAL_LEASH_ROPE_ARROW = ModItemRegister.register("spectral_leash_rope_arrow",
() -> new SpectralLeashRopeArrowItem(new Item.Properties().stacksTo(16)));
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 Supplier<Item> FABRIC = ModItemRegister.register("fabric",
() -> new TestItem(new Item.Properties().stacksTo(1))
);
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 Supplier<Item> register(String name, Supplier<Item> supplier) {
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) {
return register(name, supplier, true);
}
public static Supplier<Item> register(String name, Supplier<Item> supplier, boolean shouldJoinSupplierLists) {
Supplier<Item> supplierItem = ITEMS.register(name, supplier);
public static DeferredHolder<Item, Item> register(String name, Supplier<Item> supplier, boolean shouldJoinSupplierLists) {
DeferredHolder<Item, Item> supplierItem = ITEMS.register(name, supplier);
if(shouldJoinSupplierLists) ITEM_SUPPLIER.add(supplierItem);
return supplierItem;
}

View File

@ -0,0 +1,29 @@
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

@ -0,0 +1,13 @@
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,27 @@
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.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
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 =
RECIPE_SERIALIZER.register("tipped_leash_rope_arrow_a_recipe", () ->
new CustomRecipe.Serializer<>(TippedLeashRopeArrowRecipe.TippedLeashRopeArrowARecipe::new)
);
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<TippedLeashRopeArrowRecipe.TippedLeashRopeArrowBRecipe>> TIPPED_LEASH_ROPE_ARROW_B_RECIPE =
RECIPE_SERIALIZER.register("tipped_leash_rope_arrow_b_recipe", () ->
new CustomRecipe.Serializer<>(TippedLeashRopeArrowRecipe.TippedLeashRopeArrowBRecipe::new)
);
public static void register(IEventBus eventBus) {
RECIPE_SERIALIZER.register(eventBus);
}
}

View File

@ -0,0 +1,106 @@
package com.r3944realms.leashedplayer.content.items.repcipe;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.CraftingBookCategory;
import net.minecraft.world.item.crafting.CraftingInput;
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;
public abstract class TippedLeashRopeArrowRecipe {
public static class TippedLeashRopeArrowARecipe extends CustomRecipe {
public TippedLeashRopeArrowARecipe(CraftingBookCategory pCategory) {
super(pCategory);
}
public boolean matches(CraftingInput pInput, @NotNull Level pLevel) {
if (pInput.width() == 3 && pInput.height() == 3) {
for (int i = 0; i < pInput.height(); i++) {
for (int j = 0; j < pInput.width(); j++) {
ItemStack itemstack = pInput.getItem(j, i);
if (itemstack.isEmpty()) {
return false;
}
if (j == 1 && i == 1) {
if (!itemstack.is(Items.LINGERING_POTION)) {
return false;
}
} else if (!itemstack.is(ModItemRegister.LEASH_ROPE_ARROW.get())) {
return false;
}
}
}
return true;
} else {
return false;
}
}
public @NotNull ItemStack assemble(CraftingInput pInput, HolderLookup.@NotNull Provider pRegistries) {
ItemStack itemstack = pInput.getItem(1, 1);
if (!itemstack.is(Items.LINGERING_POTION)) {
return ItemStack.EMPTY;
} else {
ItemStack itemstack1 = new ItemStack(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get(), 8);
itemstack1.set(DataComponents.POTION_CONTENTS, itemstack.get(DataComponents.POTION_CONTENTS));
return itemstack1;
}
}
@Override
public @NotNull RecipeSerializer<? extends CustomRecipe> getSerializer() {
return ModRecipeRegister.TIPPED_LEASH_ROPE_ARROW_A_RECIPE.get();
}
}
public static class TippedLeashRopeArrowBRecipe extends CustomRecipe {
public TippedLeashRopeArrowBRecipe(CraftingBookCategory pCategory) {
super(pCategory);
}
@Override
public boolean matches(CraftingInput pInput, @NotNull Level pLevel) {
int tipped_arrow_count = 0, lead_count = 0;
for (int i = 0; i < pInput.width(); i++) {
for (int j = 0; j < pInput.height(); j++) {
if (pInput.getItem(i, j).is(Items.TIPPED_ARROW))
tipped_arrow_count++;
else if(pInput.getItem(i, j).is(Items.LEAD))
lead_count++;
}
}
return tipped_arrow_count == 1 && lead_count == 1;
}
@Override
public @NotNull ItemStack assemble(@NotNull CraftingInput pInput, HolderLookup.@NotNull Provider pRegistries) {
ItemStack tipped_arrow = null;
NODE:for (int i = 0; i < pInput.width(); i++) {
for (int j = 0; j < pInput.height(); j++) {
if (pInput.getItem(i, j).is(Items.TIPPED_ARROW)) {
tipped_arrow = pInput.getItem(i, j);
break NODE;
}
}
}
if(tipped_arrow != null) {
ItemStack itemstack1 = new ItemStack(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get(), 1);
itemstack1.set(DataComponents.POTION_CONTENTS, tipped_arrow.get(DataComponents.POTION_CONTENTS));
return itemstack1;
}
return ItemStack.EMPTY;
}
@Override
public @NotNull RecipeSerializer<? extends CustomRecipe> getSerializer() {
return ModRecipeRegister.TIPPED_LEASH_ROPE_ARROW_B_RECIPE.get();
}
}
}

View File

@ -0,0 +1,129 @@
package com.r3944realms.leashedplayer.content.items.type;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import com.r3944realms.leashedplayer.datagen.LanguageAndOtherData.ModItemTags;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
import net.minecraft.core.HolderGetter;
import net.minecraft.core.HolderSet;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Leashable;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ShearsItem;
import net.minecraft.world.item.ToolMaterial;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.component.Tool;
import net.minecraft.world.item.enchantment.Enchantable;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class LeadBreakerItem extends ShearsItem {
private final ToolMaterial toolMaterial;
public static final String HOVER_KEY = "leashedplayer.lead_breaker.item.desc",
MESSAGE_USE_SUF = "leashedplayer.lead_breaker.item.use_suf",
MESSAGE_USE_FAI = "leashedplayer.lead_breaker.item.use_fai";
public LeadBreakerItem(ToolMaterial toolMaterial, Properties properties) {
super(properties.durability(toolMaterial.durability())
.component(DataComponents.ENCHANTABLE, new Enchantable(toolMaterial.enchantmentValue()))
.repairable(ModItemTags.AMETHYST_TOOL_MATERIALS)
.enchantable(toolMaterial.enchantmentValue()));
this.toolMaterial = toolMaterial;
}
public static Tool createToolProperties() {
HolderGetter<Block> holdergetter = BuiltInRegistries.acquireBootstrapRegistrationLookup(BuiltInRegistries.BLOCK);
return new Tool(
List.of(
Tool.Rule.minesAndDrops(HolderSet.direct(BuiltInRegistries.BLOCK.wrapAsHolder(Blocks.COBWEB)), 18.0F),
Tool.Rule.overrideSpeed(holdergetter.getOrThrow(BlockTags.LEAVES), 25.0F),
Tool.Rule.overrideSpeed(holdergetter.getOrThrow(BlockTags.WOOL), 8.0F),
Tool.Rule.overrideSpeed(HolderSet.direct(BuiltInRegistries.BLOCK.wrapAsHolder(Blocks.VINE), BuiltInRegistries.BLOCK.wrapAsHolder(Blocks.GLOW_LICHEN)), 4.0F)
),
1.0F,
1
);
}
@Override
public @NotNull InteractionResult interactLivingEntity(@NotNull ItemStack stack, @NotNull Player player, @NotNull LivingEntity entity, net.minecraft.world.@NotNull InteractionHand hand) {
if(!entity.level().isClientSide) {
if (entity instanceof PlayerLeashable playerLeashable) {
if (playerLeashable.isLeashed()){
entity.playSound(SoundEvents.SHEEP_SHEAR, 1.0F, 1.0F);
Entity leashHolder = playerLeashable.getLeashHolder();
playerLeashable.dropLeash(true, !(leashHolder instanceof LeashRopeArrow));
if (leashHolder instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.setOwner(null);
}
if (!player.isCreative()) stack.hurtAndBreak(1, player, LivingEntity.getSlotForHand(hand));
if (leashHolder != null) {
((ServerPlayer)player).sendSystemMessage(Component.translatable(MESSAGE_USE_SUF, entity.getDisplayName(), leashHolder.getDisplayName()), true);
}
return InteractionResult.SUCCESS;
} else return InteractionResult.PASS;
} else if (entity instanceof Leashable leashable) {
if (leashable.isLeashed()){
entity.playSound(SoundEvents.SHEEP_SHEAR, 1.0F, 1.0F);
Entity leashHolder = leashable.getLeashHolder();
leashable.dropLeash(true, !(leashHolder instanceof LeashRopeArrow));
if (leashable.getLeashHolder() instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.setOwner(null);
}
if (!player.isCreative()) stack.hurtAndBreak(1, player, LivingEntity.getSlotForHand(hand));
if (leashHolder != null) {
((ServerPlayer)player).sendSystemMessage(Component.translatable(MESSAGE_USE_SUF, entity.getDisplayName(), leashHolder.getDisplayName()), true);
}
return InteractionResult.SUCCESS;
} else return InteractionResult.PASS;
}
}
return InteractionResult.PASS;
}
@Override
public @NotNull InteractionResult use(@NotNull Level pLevel, @NotNull Player pPlayer, @NotNull InteractionHand pUsedHand) {
if (!pLevel.isClientSide && pUsedHand == InteractionHand.MAIN_HAND) {
PlayerLeashable playerLeashable = (PlayerLeashable) pPlayer;
if (playerLeashable.isLeashed()) {
Entity leashHolder = playerLeashable.getLeashHolder();
if(!(leashHolder instanceof LeashRopeArrow)) {
playerLeashable.dropLeash(true, true);
pPlayer.getItemInHand(pUsedHand).hurtAndBreak(10, pPlayer, LivingEntity.getSlotForHand(pUsedHand));
if (leashHolder != null) {
((ServerPlayer)pPlayer).sendSystemMessage(Component.translatable(MESSAGE_USE_SUF, pPlayer.getDisplayName(), leashHolder.getDisplayName()), true);
}
return InteractionResult.SUCCESS;
}
((ServerPlayer)pPlayer).sendSystemMessage(Component.translatable(MESSAGE_USE_FAI, pPlayer.getDisplayName(), leashHolder.getDisplayName()), true);
}
}
if(pLevel.isClientSide) {
PlayerLeashable playerLeashable = (PlayerLeashable) pPlayer;
if (playerLeashable.getLeashDataFromEntityData() != null) {
pPlayer.playSound(SoundEvents.SHEEP_SHEAR, 1.0F, 1.0F);
}
}
return super.use(pLevel, pPlayer, pUsedHand);
}
@Override
public void appendHoverText(@NotNull ItemStack pStack, @NotNull TooltipContext pContext, @NotNull List<Component> pTooltipComponents, @NotNull TooltipFlag pTooltipFlag) {
pTooltipComponents.add(Component.translatable(HOVER_KEY));
}
}

View File

@ -20,9 +20,17 @@ import javax.annotation.Nullable;
import java.util.List;
public class LeashRopeArrowItem extends ArrowItem implements ILeashRopeArrow{
public static final String descKey = "item.leash_rope_arrow.description";
public static final String descKey = "item.leash_rope_arrow.description",
DESC_1 = "item.leash_rope_arrow.desc.1",
DESC_2 = "item.leash_rope_arrow.desc.2",
DESC_3 = "item.leash_rope_arrow.desc.3",
DESC_4 = "item.leash_rope_arrow.desc.4",
DESC_5 = "item.leash_rope_arrow.desc.5";
public static final String
DESC_V_1 = "item.variant.leash_rope_arrow.desc.1",
DESC_V_2 = "item.variant.leash_rope_arrow.desc.2";
public LeashRopeArrowItem(Item.Properties pProperties) {
super(pProperties);
super(pProperties) ;
}
public @NotNull AbstractArrow createArrow(@NotNull Level pLevel, @NotNull ItemStack pAmmo, @NotNull LivingEntity pShooter, @Nullable ItemStack pWeapon) {
@ -31,17 +39,22 @@ public class LeashRopeArrowItem extends ArrowItem implements ILeashRopeArrow{
@Override
public @NotNull Projectile asProjectile(@NotNull Level pLevel, @NotNull Position pPos, @NotNull ItemStack pStack, @NotNull Direction pDirection) {
LeashRopeArrow arrow = new LeashRopeArrow(ModEntityRegister.LEASH_ROPE_ARROW.get(), pPos.x(), pPos.y(), pPos.z(), pLevel, this.getDefaultInstance(),null, null);
LeashRopeArrow arrow = new LeashRopeArrow(ModEntityRegister.LEASH_ROPE_ARROW.get(), pPos.x(), pPos.y(), pPos.z(), pLevel, pStack,null, null);
arrow.pickup = AbstractArrow.Pickup.DISALLOWED;
return arrow;
}
@Override
public @NotNull Component getDescription() {
return Component.translatable(descKey).withStyle(ChatFormatting.GRAY);
}
public void appendHoverText(@NotNull ItemStack pStack, Item.@NotNull TooltipContext pContext, @NotNull List<Component> pTooltipComponents, @NotNull TooltipFlag pTooltipFlag) {
//TODO:也许会做
pTooltipComponents.addAll(List.of(
Component.translatable(DESC_1),
Component.translatable(DESC_2),
Component.translatable(DESC_3),
Component.translatable(DESC_4),
Component.translatable(DESC_5)
));
}
}

View File

@ -21,7 +21,8 @@ import javax.annotation.Nullable;
import java.util.List;
public class SpectralLeashRopeArrowItem extends ArrowItem implements ILeashRopeArrow{
public static final String descKey = "item.spectral_leash_rope_arrow.description";
public static final String descKey = "item.spectral_leash_rope_arrow.description",
DESC = "item.spectral_leash_rope_arrow.desc";
public SpectralLeashRopeArrowItem(Properties pProperties) {
super(pProperties);
}
@ -36,11 +37,14 @@ public class SpectralLeashRopeArrowItem extends ArrowItem implements ILeashRopeA
return arrow;
}
@Override
public @NotNull Component getDescription() {
return Component.translatable(descKey).withStyle(ChatFormatting.GRAY);
}
public void appendHoverText(@NotNull ItemStack pStack, Item.@NotNull TooltipContext pContext, @NotNull List<Component> pTooltipComponents, @NotNull TooltipFlag pTooltipFlag) {
//TODO:也许会做
pTooltipComponents.addAll(List.of(
Component.translatable(LeashRopeArrowItem.DESC_V_1),
Component.translatable(LeashRopeArrowItem.DESC_V_2),
Component.translatable(DESC)
));
}
}

View File

@ -7,10 +7,9 @@ import com.r3944realms.leashedplayer.client.renders.gui.IFadingProcessBarRendere
import com.r3944realms.leashedplayer.client.renders.gui.IProcessBarRenderer;
import com.r3944realms.leashedplayer.client.renders.gui.TestProcessBarRenderer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
@ -21,7 +20,7 @@ public class TestItem extends Item {
}
@Override
public @NotNull InteractionResultHolder<ItemStack> use(@NotNull Level pLevel, @NotNull Player pPlayer, @NotNull InteractionHand pUsedHand) {
public @NotNull InteractionResult use(@NotNull Level pLevel, @NotNull Player pPlayer, @NotNull InteractionHand pUsedHand) {
if(!pLevel.isClientSide()){
//some lo
}

View File

@ -0,0 +1,57 @@
package com.r3944realms.leashedplayer.content.items.type;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.alchemy.Potion;
import net.minecraft.world.item.alchemy.PotionContents;
import net.minecraft.world.item.alchemy.Potions;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Optional;
public class TippedLeashRopeArrowItem extends LeashRopeArrowItem {
public static final String TIPPED_LEASH_ROPE_ARROW_NAME = "item.tipped_leash_rope_arrow.name";
public static final String DESC = "item.tipped_leash_rope_arrow.desc";
public TippedLeashRopeArrowItem(Properties pProperties) {
super(pProperties);
}
@Override
public @NotNull ItemStack getDefaultInstance() {
ItemStack itemstack = super.getDefaultInstance();
itemstack.set(DataComponents.POTION_CONTENTS, new PotionContents(Potions.POISON));
return itemstack;
}
@Override
public void appendHoverText(@NotNull ItemStack pStack, @NotNull TooltipContext pContext, @NotNull List<Component> pTooltipComponents, @NotNull TooltipFlag pTooltipFlag) {
pTooltipComponents.addAll(List.of(
Component.translatable(LeashRopeArrowItem.DESC_V_1),
Component.translatable(LeashRopeArrowItem.DESC_V_2),
Component.translatable(DESC)
));
PotionContents potioncontents = pStack.get(DataComponents.POTION_CONTENTS);
if (potioncontents != null) {
potioncontents.addPotionTooltip(pTooltipComponents::add, 0.125F, pContext.tickRate());
}
}
@Override
public @NotNull Component getName(@NotNull ItemStack pStack) {
Optional<Holder<Potion>> pPotion = pStack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).potion();
String s = null,s1;
if (pPotion.isPresent()) {
s = pPotion.get().value().name();
}
boolean flag = s == null;
s1 = pPotion.flatMap(Holder::unwrapKey).map(p_331494_ -> p_331494_.location().getPath()).orElse("empty");
String potionTranslateKey = "item.minecraft.potion.effect." + (flag ? s1: s);
return Component.translatable(TIPPED_LEASH_ROPE_ARROW_NAME, Component.translatable(potionTranslateKey));
}
}

View File

@ -0,0 +1,77 @@
package com.r3944realms.leashedplayer.content.misc;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.dispenser.BlockSource;
import net.minecraft.core.dispenser.OptionalDispenseItemBehavior;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.entity.EntitySelector;
import net.minecraft.world.entity.Leashable;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.BeehiveBlock;
import net.minecraft.world.level.block.DispenserBlock;
import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.phys.AABB;
import org.jetbrains.annotations.NotNull;
public class LeadBreakItemBehavior extends OptionalDispenseItemBehavior {
@Override
protected @NotNull ItemStack execute(@NotNull BlockSource blockSource, @NotNull ItemStack item) {
ServerLevel serverLevel = blockSource.level();
if(!serverLevel.isClientSide()) {
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
this.setSuccess(tryShearBeehive(serverLevel, blockPos) || tryShearLivingEntity(serverLevel, blockPos, item));
if (this.isSuccess()) {
item.hurtAndBreak(1, serverLevel, null, p_348118_ -> {
});
}
}
return item;
}
private static boolean tryShearBeehive(ServerLevel level, BlockPos pos) {
BlockState blockstate = level.getBlockState(pos);
if (blockstate.is(BlockTags.BEEHIVES, p_202454_ -> p_202454_.hasProperty(BeehiveBlock.HONEY_LEVEL) && p_202454_.getBlock() instanceof BeehiveBlock)) {
int i = blockstate.getValue(BeehiveBlock.HONEY_LEVEL);
if (i >= 5) {
level.playSound(null, pos, SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F);
BeehiveBlock.dropHoneycomb(level, pos);
((BeehiveBlock)blockstate.getBlock())
.releaseBeesAndResetHoneyLevel(level, blockstate, pos, null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED);
level.gameEvent(null, GameEvent.SHEAR, pos);
return true;
}
}
return false;
}
private static boolean tryShearLivingEntity(ServerLevel level, BlockPos pos, ItemStack item) {
for (LivingEntity livingentity : level.getEntitiesOfClass(LivingEntity.class, new AABB(pos), EntitySelector.NO_SPECTATORS)) {
if (livingentity instanceof PlayerLeashable playerLeashable) {
if (playerLeashable.isLeashed()){
playerLeashable.dropLeash(true, !(playerLeashable.getLeashHolder() instanceof LeashRopeArrow));
if (playerLeashable.getLeashHolder() instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.setOwner(null);
}
return true;
} else return false;
} else if (livingentity instanceof Leashable leashable) {
if (leashable.isLeashed()) {
leashable.dropLeash(true, !(leashable.getLeashHolder() instanceof LeashRopeArrow));
if (leashable.getLeashHolder() instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.setOwner(null);
}
return true;
} else return false;
}
}
return false;
}
}

View File

@ -1,21 +1,24 @@
package com.r3944realms.leashedplayer.content.paintings;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.datagen.provider.attributes.ModPaintingVariants;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.decoration.PaintingVariant;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredRegister;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
import java.util.function.Supplier;
public class ModPaintingsRegister {
public static final DeferredRegister<PaintingVariant> PAINTING_VARIANT =
DeferredRegister.create(Registries.PAINTING_VARIANT, LeashedPlayer.MOD_ID);
public static final Supplier<PaintingVariant> GROUP_PHOTO = PAINTING_VARIANT.register("group_photo", () -> new PaintingVariant(1920, 1080, getAssetId("group_photo")));
public static final Supplier<PaintingVariant> GROUP_PHOTO = PAINTING_VARIANT.register("group_photo", () -> new PaintingVariant(1920, 1080, getAssetId("group_photo"), Optional.of(Component.translatable(ModPaintingVariants.getPaintingVariantTitleKey(ModPaintingVariants.GROUP_PHOTO))), Optional.of(Component.translatable(ModPaintingVariants.getPaintingVariantAuthorKey(ModPaintingVariants.GROUP_PHOTO)))));
private static @NotNull ResourceLocation getAssetId( String paint_name) {
private static @NotNull ResourceLocation getAssetId(String paint_name) {
return ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "textures/painting/"+paint_name+".png");
}

View File

@ -0,0 +1,35 @@
package com.r3944realms.leashedplayer.content.sounds;
import com.r3944realms.leashedplayer.LeashedPlayer;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
import java.util.function.Supplier;
public class ModSoundRegister {
public static DeferredRegister<SoundEvent> SOUNDS = DeferredRegister.create(BuiltInRegistries.SOUND_EVENT, LeashedPlayer.MOD_ID);
public static ResourceLocation RL_FOX_MUSIC = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "music/what_does_the_fox_say");
public static final DeferredHolder<SoundEvent, SoundEvent> FOX_MUSIC =
ModSoundRegister.register("what_does_the_fox_say", () -> SoundEvent.createFixedRangeEvent(
RL_FOX_MUSIC,
128
));
public static DeferredHolder<SoundEvent, SoundEvent> register(String name, Supplier<SoundEvent> supplier){
return SOUNDS.register(name, supplier);
}
public static void register(IEventBus modBus){
SOUNDS.register(modBus);
}
public static String getJukeboxSongTranslateKey(String name) {
return "jukebox_song." + LeashedPlayer.MOD_ID + "." + name;
}
public static String getSubTitleTranslateKey(String name) {
return "sound." + LeashedPlayer.MOD_ID + ".subtitle." + name;
}
}

View File

@ -15,6 +15,9 @@ public enum ModAdvancementKey {
FOLLOW_LEASH_ARROW("follow_arrow", LEASH_ARROW),
DOG_RUNNING_PLAYER("dog_running_player", LEASH_ARROW),
NO_LEASH("no_leash", LEASH_START),
LEASH_TERMINATOR("leash_terminator", LEASH_START),
TIPPED_LEASH_ARROW("tipped_leash_arrow", LEASH_ARROW),
NEO_FOX("neo_fox", LEASH_START),
;
private final String Name;
@Nullable

View File

@ -0,0 +1,21 @@
package com.r3944realms.leashedplayer.datagen.LanguageAndOtherData;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
public final class ModItemTags {
public static final TagKey<Item> AMETHYST_TOOL_MATERIALS = bind("amethyst_tool_materials");
private ModItemTags() {
}
private static TagKey<Item> bind(String name) {
return TagKey.create(Registries.ITEM, ResourceLocation.withDefaultNamespace(name));
}
public static TagKey<Item> create(final ResourceLocation name) {
return TagKey.create(Registries.ITEM, name);
}
}

View File

@ -1,18 +1,26 @@
package com.r3944realms.leashedplayer.datagen.LanguageAndOtherData;
import com.r3944realms.leashedplayer.content.ModKeyMapping;
import com.r3944realms.leashedplayer.content.commands.LeashCommand;
import com.r3944realms.leashedplayer.content.commands.MotionCommand;
import com.r3944realms.leashedplayer.content.effects.ModEffectRegister;
import com.r3944realms.leashedplayer.content.effects.ModPotionRegister;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import com.r3944realms.leashedplayer.content.entities.ModEntityRegister;
import com.r3944realms.leashedplayer.content.gamerules.Server.CreateLeashFenceKnotEntityIfAbsent;
import com.r3944realms.leashedplayer.content.gamerules.Server.DisablePlayerMoveCheck;
import com.r3944realms.leashedplayer.content.gamerules.Server.KeepLeashNotDropTime;
import com.r3944realms.leashedplayer.content.gamerules.Server.TeleportWithLeashedPlayers;
import com.r3944realms.leashedplayer.content.items.ModCreativeTab;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import com.r3944realms.leashedplayer.content.items.type.LeadBreakerItem;
import com.r3944realms.leashedplayer.content.items.type.LeashRopeArrowItem;
import com.r3944realms.leashedplayer.content.items.type.SpectralLeashRopeArrowItem;
import com.r3944realms.leashedplayer.content.items.type.TippedLeashRopeArrowItem;
import com.r3944realms.leashedplayer.content.sounds.ModSoundRegister;
import com.r3944realms.leashedplayer.datagen.provider.attributes.ModPaintingVariants;
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.Enum.LanguageEnum;
import com.r3944realms.leashedplayer.utils.Enum.ModPartEnum;
import net.minecraft.world.item.Item;
@ -25,18 +33,40 @@ import java.util.function.Supplier;
import static com.r3944realms.leashedplayer.content.items.ModCreativeTab.LEASHED_PLAYER_ITEM;
public enum ModLangKeyValue {
KEY_CATEGORY(ModKeyMapping.CATEGORY, ModPartEnum.NAME, "Leashed Player", "可拴玩家", "可拴玩家", false),
KEY_ADD_LEASH_OTHER_LEASH_LENGTH(ModKeyMapping.ADD_LEASH_LENGTH_KEY, ModPartEnum.NAME, "Increase the Length of Leash Rope", "增加拴绳长度", "增加拴繩長度", false),
KEY_SUB_LEASH_OTHER_LEASH_LENGTH(ModKeyMapping.SUB_LEASH_LENGTH_KEY, ModPartEnum.NAME, "Decrease the Length of Leash Rope", "减小拴绳长度", "減小拴繩長度", false),
//ITEM
ITEM_LEASH_ROPE_ARROW(ModItemRegister.LEASH_ROPE_ARROW, ModPartEnum.ITEM, "Leash Rope Arrow", "拴绳箭", "拴繩箭", true),
ITEM_SPECTRAL_LEASH_ROPE_ARROW(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW, ModPartEnum.ITEM, "Spectral Leash Rope Arrow", "拴绳光灵箭", "拴繩光靈箭", true),
TEST_FABRIC_ITEM(ModItemRegister.FABRIC, ModPartEnum.ITEM, "Fabric", "Fabric", "Fabric", true),
AMETHYST_SHEARS(ModItemRegister.AMETHYST_SHEARS, ModPartEnum.ITEM, "Amethyst Shears", "紫水晶剪刀", "紫水晶剪刀", true),
NEO_FORGE(ModItemRegister.NEOFORGE, ModPartEnum.ITEM, "NeoForge", "NeoForge", "NeoForge", false),
TIPPED_LEASH_ROPE_ARROW(TippedLeashRopeArrowItem.TIPPED_LEASH_ROPE_ARROW_NAME, ModPartEnum.ITEM, "Tipped Leash Rope Arrow Soaked By %1$s", "用%1$s浸泡过的拴绳箭", "蘸有%1$s的拴繩箭", false),
//ITEM_DESC
DESC_ITEM_LEASH_R_ARROW_ONE(LeashRopeArrowItem.DESC_1, ModPartEnum.DESCRIPTION, "§7This arrow will carry the owner along with its flight:", "§7该箭将会携带拥有者随其飞行", "§7該箭將會攜帶擁有者隨其飛行", false),
DESC_ITEM_LEASH_R_ARROW_TWO(LeashRopeArrowItem.DESC_2, ModPartEnum.DESCRIPTION, "§c1.§r If it hits a fence or an entity, it will leash the owner to it and drop as a normal arrow.", "§c1.§r 若击中栅栏或生物时,将持有者拴在其上并已普通箭形式掉落;", "§c1.§r 若擊中柵欄或生物時,將持有者拴在其上並以普通箭的形式掉落;", false),
DESC_ITEM_LEASH_R_ARROW_THREE(LeashRopeArrowItem.DESC_3, ModPartEnum.DESCRIPTION,"§c2.§r Crouching near the arrow allows for faster retrieval. If the arrow's owner is not the player, the owner will be leashed to the player who picks it up.", "§c2.§r 靠近该箭下蹲可以更快拾取该箭,如果该箭持有者不是自己,则持有者将被拾取者拴住;", "§c2.§r 靠近該箭下蹲可以更快拾取該箭,如果該箭的持有者不是自己,則持有者將被拾取者拴住;", false),
DESC_ITEM_LEASH_R_ARROW_FOUR(LeashRopeArrowItem.DESC_4, ModPartEnum.DESCRIPTION, "§c3.§r When fired from its launcher, the first entity hit will become the arrow's owner and will fly along with it.", "§c3.§r 当前其发射器里发射,第一个射中的生物将成为此箭的持有者并随箭飞行;", "§c3.§r 當箭從發射器發射時,第一個射中的生物將成為此箭的持有者並隨箭飛行;", false),
DESC_ITEM_LEASH_R_ARROW_FIVE(LeashRopeArrowItem.DESC_5, ModPartEnum.DESCRIPTION, "§c4.§r Under the §c§l\"no_leash\"§r effect, the behavior of the arrow when fired will follow the launchers behavior.", "§c4.§r 在§c§l禁拴§7(§c§lno_leash§7)§r效果下射出的箭行为同发射器。","§c4.§r 在§c§l禁拴§7(§c§lno_leash§7)§r效果下射出的箭行為將與發射器的行為相同。", false),
DESC_ITEM_LEASH_ROPE_ARROW(LeashRopeArrowItem.descKey, ModPartEnum.DESCRIPTION, "Arrows with ropes attached?","带有拴绳的箭矢?", "帶有拴繩的箭矢?", false),
DESC_ITEM_V_LEASH_R_ARROW_ONE(LeashRopeArrowItem.DESC_V_1, ModPartEnum.DESCRIPTION, "§7A variant of Leash Rope Arrow", "§7拴绳箭的一个变种", "§7拴繩箭矢的一個變種", false),
DESC_ITEM_V_LEASH_R_ARROW_TWO(LeashRopeArrowItem.DESC_V_2, ModPartEnum.DESCRIPTION, "§c1.§r The function is the same as its original one。", "§c1.§r 功能同其本体;", "§c1.§r 功能與本體一致;", false),
DESC_ITEM_S_LEASH_R_ARROW_THREE(SpectralLeashRopeArrowItem.DESC, ModPartEnum.DESCRIPTION, "§c2.§r Strike the entity to give it a §e§lGlowing§r effect.", "§c2.§r 击中实体给与其§e§l发光§7(§e§lGlowing§7)§r效果", "擊中實體給予其§e§l發光§7(§e§lGlowing§7)§r效果", false),
DESC_ITEM_T_LEASH_R_ARROW_THREE(TippedLeashRopeArrowItem.DESC, ModPartEnum.DESCRIPTION, "§c2.§rStrike the entity to give it a Potion effect.", "§c2.§r 击中实体给与其药水效果", "擊中實體給予其药水效果", false),
DESC_ITEM_LEAD_BREAKER(LeadBreakerItem.HOVER_KEY, ModPartEnum.DESCRIPTION, "§7can break the link of leash", "§7可以破坏拴绳链接", "§7可以破壞拴繩鏈接", false),
//PAINTING
GROUP_PHOTO_TITLE(ModPaintingVariants.getPaintingVariantTitleKey(ModPaintingVariants.GROUP_PHOTO),ModPartEnum.TITLE, "§dGroup Photo §7[§6memorable§7]§r", "§d集体照 §7[§6纪念§7]§r", "§d集體照 §7[§6紀念§7]§r", false),
GROUP_PHOTO_AUTHOR(ModPaintingVariants.getPaintingVariantAuthorKey(ModPaintingVariants.GROUP_PHOTO),ModPartEnum.AUTHOR, "§9Leisure §4Time §eDock§r","§9闲趣§4时§e坞§r","§9閑趣§4時§e塢§r",false),
//ENTITY
LEASH_ROPE_ARROW(ModEntityRegister.getEntityNameKey("leash_rope_arrow"), ModPartEnum.ENTITY, "Leash Rope Arrow", "拴绳箭", "拴繩箭", false),
SPECTRAL_LEASH_ROPE_ARROW(ModEntityRegister.getEntityNameKey("spectral_leash_rope_arrow"), ModPartEnum.ENTITY, "Spectral Leash Rope Arrow", "拴绳光灵箭", "拴繩光靈箭", false),
kID(ModEntityRegister.getEntityNameKey("kid_player"), ModPartEnum.ENTITY, "Kid", "小孩", "小孩", "", false),
NESTLE_ROPE_ARROW(ModEntityRegister.getEntityNameKey("nestle_rope_arrow"), ModPartEnum.ENTITY, "Nestle Rope Arrow", "贴贴拴绳箭", "貼貼拴繩箭", false),
//DIST
ST_WHAT_DOES_THE_FOX_SAY(ModSoundRegister.getSubTitleTranslateKey("what_does_the_fox_say"), ModPartEnum.TITLE, "Great Chu will rise again! Chen She will be king!", "大楚兴~ 陈胜王~~", "大楚興~ 陳勝王~~", false),
JB_WHAT_DOES_THE_FOX_SAY(ModSoundRegister.getJukeboxSongTranslateKey("what_does_the_fox_say"), ModPartEnum.DESCRIPTION, "What does the fox say?", "狐狸是怎么叫的?", "狐狸是怎麽叫的?", false),
//CREATIVE_TAB
CREATIVE_TAB_NAME(ModCreativeTab.getCreativeMod(LEASHED_PLAYER_ITEM), ModPartEnum.CREATIVE_TAB, "Leashed Player","可拴玩家", "可拴玩家", false),
//COMMAND_MESSAGE
@ -55,16 +85,26 @@ public enum ModLangKeyValue {
MESSAGE_MOTION_ADDER_SUCCESSFUL(MotionCommand.MOTION_ADDER_SUCCESSFUL, ModPartEnum.COMMAND, "§bAdd Successfully.§a%s§7:§f[§eVec§7: §a(§f%f§7,§f%f§7,§f%f§a)§f]§r","§b添加成功.§a%s§7:§f[§e加速度§7:§a(§f%f§7,§f%f§7,§f%f§a)§f]§r","§b添加成功.§a%s§7:§f[§e加速度§7:§a(§f%f§7,§f%f§7,§f%f§a)§f]§r", false),
MESSAGE_MOTION_SETTER_SUCCESSFUL(MotionCommand.MOTION_SETTER_SUCCESSFUL, ModPartEnum.COMMAND, "§bSet Successfully.§a%s§7:§f[§eVec§7: §a(§f%f§7,§f%f§7,§f%f§a)§f]§r","§b设置成功.§a%s§7:§f[§e加速度§7:§a(§f%f§7,§f%f§7,§f%f§a)§f]§r","§b設置成功.§a%s§7:§f[§e加速度§7:§a(§f%f§7,§f%f§7,§f%f§a)§f]§r",false),
MESSAGE_MOTION_MULTIPLY_SUCCESSFUL(MotionCommand.MOTION_MULTIPLY_SUCCESSFUL, ModPartEnum.COMMAND, "§bMultiply Successfully.§a%s§7:§f[§eVec§7: §a(§f%f§7,§f%f§7,§f%f§a)§f]§r","§b倍乘成功.§a%s§7:§f[§e加速度§7:§a(§f%f§7,§f%f§7,§f%f§a)§f]§r","§b倍乘成功.§a%s§7:§f[§e加速度§7:§a(§f%f§7,§f%f§7,§f%f§a)§f]§r",false),
MESSAGE_LEASH_BREAKER_USE_SUF(LeadBreakerItem.MESSAGE_USE_SUF, ModPartEnum.MESSAGE, "§aSuccessfully break §f%1$s§a 's Leashed Link to §f%2$s ", "§a成功剪断§f%2$s§a对§f%1$s§a拴绳链接", "§a成功剪斷§f%2$s§a對§f%1$s§a拴繩鏈接", false),
MESSAGE_LEASH_BREAKER_USE_FAI(LeadBreakerItem.MESSAGE_USE_FAI, ModPartEnum.MESSAGE, "§cFailed to break §f%1$s§c 's Leashed Link to §f%2$s", "§c无法剪断§f%2$s§c对§f%1$s§c拴绳链接", "§c未能剪斷§f%2$s§c對§f%1$s§c拴繩鏈接", false),
MESSAGE_LEASH_NOT_SUPPORT_TO_NOT_PLAYER_ENTITY(ModKeyMapping.NOT_SUPPORT_TO_NOT_PLAYER_ENTITY, ModPartEnum.MESSAGE, "Only work on Players", "只在玩家身上有效", "僅對玩家有效", false),
MESSAGE_LEASH_ADD_LEASH_LENGTH(IncreaseLeashRopeLength.INCREASE_LEASH_ROPE_LENGTH, ModPartEnum.MESSAGE, "§aIncrease the §f%s §aLength of Leash Rope§7(§bLength§7:§e%d§7)", "§a增加§f%s的拴绳长度§a§7(§b长度§7:§e%d§7)", "§a增加§f%s§a的拴繩長度§7(§長度§7:§e%d§7)", false),
MESSAGE_LEASH_SUB_LEASH_LENGTH(DecreaseLeashRopeLength.DECREASE_LEASH_ROPE_LENGTH, ModPartEnum.MESSAGE, "§Decrease the §f%s §cLength of Leash Rope§7(§bLength§7:§e%d§7)", "§c减少§f%s的拴绳长度§c§7(§b长度§7:§e%d§7)", "§c減少§f%s§c的拴繩長度§7(§長度§7:§e%d§7)", false),
MESSAGE_LEASH_ADD_SELF_LEASH_LENGTH(IncreaseLeashRopeLength.INCREASE_SELF_LEASH_ROPE_LENGTH, ModPartEnum.MESSAGE, "§aIncrease the Length of Leash Rope§7(§bLength§7:§e%d§7)", "§a增加拴绳长度§a§7(§b长度§7:§e%d§7)", "§a增加拴繩長度§7(§長度§7:§e%d§7)", false),
MESSAGE_LEASH_SUB_SELF_LEASH_LENGTH(DecreaseLeashRopeLength.DECREASE_SELF_LEASH_ROPE_LENGTH, ModPartEnum.MESSAGE, "§cDecrease the Length of Leash Rope§7(§bLength§7:§e%d§7)", "§c减少拴绳长度§c§7(§b长度§7:§e%d§7)", "§c減少拴繩長度§7(§長度§7:§e%d§7)", false),
MESSAGE_LEASH_FAILED_SET_LENGTH(Code.LEASH_LENGTH_FAILED_SET, ModPartEnum.MESSAGE, "§cFailed", "§c失败", "§c失敗", false),
//GAME_RULE_NAME
TELEPORT_WITH_LEASHED_PLAYERS(TeleportWithLeashedPlayers.NAME_KEY, ModPartEnum.NAME, "Teleport leashed player with player holder", "被拴玩家随玩家持有者传送", "被拴玩家随玩家持有者傳送" ,false),
CREATE_LEASH_FENCE_KNOT_ENTITY_IF_ABSENT(CreateLeashFenceKnotEntityIfAbsent.NAME_KEY, ModPartEnum.NAME, "Create Leash Fence Knot Entity if absent", "如果缺失则创建拴绳结", "如果缺失則創建拴繩結", false),
KEEP_LEASH_NOT_DROP_TIME(KeepLeashNotDropTime.NAME_KEY, ModPartEnum.NAME, "Keep leash alive Time", "保持拴绳不掉落的时间", "保持其不掉落的時間", false),
DISABLE_MOVE_CHECK(DisablePlayerMoveCheck.NAME_KEY, ModPartEnum.NAME, "Disable Player Move Check", "禁止检查玩家移动", "禁止檢查玩家移動", false),
TELEPORT_WITH_LEASHED_PLAYERS_NAME(TeleportWithLeashedPlayers.NAME_KEY, ModPartEnum.NAME, "Teleport leashed player with player holder", "被拴玩家随玩家持有者传送", "被拴玩家随玩家持有者傳送" ,false),
CREATE_LEASH_FENCE_KNOT_ENTITY_IF_ABSENT_NAME(CreateLeashFenceKnotEntityIfAbsent.NAME_KEY, ModPartEnum.NAME, "Create Leash Fence Knot Entity if absent", "如果缺失则创建拴绳结", "如果缺失則創建拴繩結", false),
KEEP_LEASH_NOT_DROP_TIME_NAME(KeepLeashNotDropTime.NAME_KEY, ModPartEnum.NAME, "Keep leash alive Time", "保持拴绳不掉落的时间", "保持其不掉落的時間", false),
TRY_TO_PICKUP_LEASHED_ROPE_ARROW(LeashRopeArrow.PUSH_SHIFT_TO_PICKUP_QUICKLY, ModPartEnum.MESSAGE, "§aPush §f§lShift§a to pick up quickly", "§a按下§f§lShift键§a以加快拾取", "§a按下§f§lShift鍵§a以加速拾取", false),
//GAME_RULE_DESCRIPTION
TELEPORT_WITH_LEASHED_DESCRIPTION(TeleportWithLeashedPlayers.DESCRIPTION_KEY, ModPartEnum.DESCRIPTION, "Holder will teleport with their leashed players ", "传送时将被拴玩家与持有者一起传送", "將被拴玩家將隨持有者一起傳送" ,false),
CREATE_LEASH_FENCE_KNOT_ENTITY_IF_ABSENT_DESCRIPTION(CreateLeashFenceKnotEntityIfAbsent.DESCRIPTION_KEY, ModPartEnum.DESCRIPTION, "Create LeashKnot Entity if it's absent on fence", "如果在栅栏处缺失拴绳结,则创建它", "如果在柵欄処缺失拴繩結,則創建它", false),
KEEP_LEASH_NOT_DROP_TIME_DESCRIPTION(KeepLeashNotDropTime.DESCRIPTION_KEY, ModPartEnum.DESCRIPTION,"The time of Keep new leash which has far distance alive (Tick)", "当距离过远时,保持新建拴绳不掉落的时间 (刻)", "儅距離過遠時,保持其不掉落的時間(刻)", false),
DISABLE_MOVE_CHECK_DESCRIPTION(DisablePlayerMoveCheck.DESCRIPTION_KEY, ModPartEnum.DESCRIPTION, "Disable the player's movement Check And Correct it.", "禁止检查玩家移动并且纠正它","禁止檢查玩家移動並糾正他它", false),
//ADV_NAME
LEASH_START(ModAdvancementKey.LEASH_START.getNameKey(), ModPartEnum.NAME, "The Power of Traction", "牵引之力", "牽引之力", false),
LEASH_LR_ARROW(ModAdvancementKey.LEASH_ARROW.getNameKey(), ModPartEnum.NAME, "Arrow with a Tether?" , "拴绳之箭?", "拴繩之箭?", false),
@ -73,7 +113,10 @@ public enum ModLangKeyValue {
LEASH_PLAYER(ModAdvancementKey.LEASHED_FRIEND.getNameKey(),ModPartEnum.NAME, "Be bound by Rope", "拴绳链接", "拴繩鏈接" , false),
FOLLOW_ARROW(ModAdvancementKey.FOLLOW_LEASH_ARROW.getNameKey(), ModPartEnum.NAME, "Launch!!!", "启航!!!" , "啓航!!!",false),
FOLLOW_WOLF(ModAdvancementKey.DOG_RUNNING_PLAYER.getNameKey(), ModPartEnum.NAME, "It's Walking human time.", "遛“人”时间", "遛“人”時間",false),
TERMINATOR(ModAdvancementKey.LEASH_TERMINATOR.getNameKey(), ModPartEnum.NAME, "The Lead Terminator", "拴绳终结者","拴繩終結者", false),
NO_LEASH(ModAdvancementKey.NO_LEASH.getNameKey(), ModPartEnum.NAME, "Don't tie me up", "勿拴我", "請恁勿拴唔", false),
TIPPED_LEASH_ARROW(ModAdvancementKey.TIPPED_LEASH_ARROW.getNameKey(), ModPartEnum.NAME, "God said there should be more arrows", "神说要有更多箭矢", "神說要有更多箭矢", false),
NEO_FOX(ModAdvancementKey.NEO_FOX.getNameKey(), ModPartEnum.NAME, "NEOFORGE!", "NEOFORGE!", "NEOFORGE!", false),
//ADV_DESC
LEASH_START_DESC(ModAdvancementKey.LEASH_START.getDescKey(), ModPartEnum.DESCRIPTION, "Journey to becoming a Leash Expert", "拴绳大师之路", "拴繩大師之路", false),
LEASH_LR_ARROW_DESC(ModAdvancementKey.LEASH_ARROW.getDescKey(), ModPartEnum.DESCRIPTION, "Maybe you can using it to shoot some mob?", "也许可以用它来发射生物?", "也許可以用它發射生物?", false),
@ -82,7 +125,11 @@ public enum ModLangKeyValue {
LEASH_PLAYER_DESC(ModAdvancementKey.LEASHED_FRIEND.getDescKey(),ModPartEnum.DESCRIPTION, "Be Bond by player with lead", "被玩家用拴绳链接", "被玩家用拴繩鏈接", false),
FOLLOW_ARROW_DESC(ModAdvancementKey.FOLLOW_LEASH_ARROW.getDescKey(), ModPartEnum.DESCRIPTION, "Mc, what are you talking about in physics?", "抱歉,我的世界不存在物理学" , "抱歉,麦块不講物理學",false),
FOLLOW_WOLF_DESC(ModAdvancementKey.DOG_RUNNING_PLAYER.getDescKey(), ModPartEnum.DESCRIPTION, "In the park where dogs are not allowed to be walked, the dog decided to walk the human instead", "公园不能遛狗,于是狗站起来遛人", "公園裏不許遛狗,於是狗站起來遛人",false),
NO_LEASH_DESC(ModAdvancementKey.NO_LEASH.getDescKey(), ModPartEnum.NAME, "You cannot be leashed by ANY", "你不会被任何东西拴住", "恁不會被任何拴住", false),
NO_LEASH_DESC(ModAdvancementKey.NO_LEASH.getDescKey(), ModPartEnum.DESCRIPTION, "You cannot be leashed by ANY", "你不会被任何东西拴住", "恁不會被任何拴住", false),
TERMINATOR_DESC(ModAdvancementKey.LEASH_TERMINATOR.getDescKey(), ModPartEnum.DESCRIPTION, "I am Lead Terminator!", "我來终结拴绳者!", "吾將終結拴繩!", false),
TIPPED_LEASH_ARROW_DESC(ModAdvancementKey.TIPPED_LEASH_ARROW.getDescKey(), ModPartEnum.DESCRIPTION, "A dazzling array of Leash Rope arrows", "真是琳琅满目啊", "真是琳琅滿目啊", false),
NEO_FOX_DESC(ModAdvancementKey.NEO_FOX.getDescKey(), ModPartEnum.DESCRIPTION, "It seems can be equipped.", "似乎可以戴头上", "似乎可以戴著", false),
//MOB_EFFECT
NO_LEASH_EFFECT(ModEffectRegister.getEffectKey(ModEffectRegister.NO_LEASH_EFFECT.get()), ModPartEnum.NAME, "No Leash", "禁拴", "禁拴", false),
//POTION

View File

@ -5,6 +5,7 @@ import com.r3944realms.leashedplayer.datagen.provider.*;
import com.r3944realms.leashedplayer.utils.Enum.LanguageEnum;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.DataProvider;
import net.minecraft.data.PackOutput;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
@ -17,7 +18,6 @@ public class ModDataGeneratorHandler {
@SubscribeEvent
public static void genData(GatherDataEvent event) {
CompletableFuture<HolderLookup.Provider> holderFolder = event.getLookupProvider();
ExistingFileHelper existingFileHelper = event.getExistingFileHelper();
/*Language Provider ENGLISH CHINESE(SIM/TRA)*/
addLanguage(event, LanguageEnum.English);
@ -29,6 +29,7 @@ public class ModDataGeneratorHandler {
ItemModelGenerator(event, existingFileHelper);
RecipeGenerator(event, holderFolder);
ModTagsProvider(event, event.getLookupProvider(), existingFileHelper);
ModSoundProvider(event, existingFileHelper);
ModAdvancementProvider(event, holderFolder, existingFileHelper);
}
private static void addLanguage(GatherDataEvent event, LanguageEnum language){
@ -44,9 +45,10 @@ public class ModDataGeneratorHandler {
);
}
private static void RecipeGenerator(GatherDataEvent event, CompletableFuture<HolderLookup.Provider> future) {
PackOutput packOutput = event.getGenerator().getPackOutput();
event.getGenerator().addProvider(
event.includeServer(),
(DataProvider.Factory<ModRecipeProvider>) pOutput -> new ModRecipeProvider(pOutput, future)
new ModRecipeProvider.Runner(packOutput, future)
);
}
private static void ModTagsProvider(GatherDataEvent event, CompletableFuture<HolderLookup.Provider> completableFuture, ExistingFileHelper helper) {
@ -61,7 +63,13 @@ public class ModDataGeneratorHandler {
new ModItemTagProvider(pOutput, completableFuture, modBlockTagProvider.contentsGetter(), helper)
);
}
private static void ModSoundProvider(GatherDataEvent event, ExistingFileHelper helper) {
event.getGenerator().addProvider(
event.includeServer(),
(DataProvider.Factory<ModSoundDefinitionsProvider>) pOutput ->
new ModSoundDefinitionsProvider(pOutput,LeashedPlayer.MOD_ID, helper)
);
}
private static void ModDataPackBuiltInEntriesProvider(GatherDataEvent event, CompletableFuture<HolderLookup.Provider> future) {
event.getGenerator().addProvider(
event.includeServer(),

View File

@ -10,7 +10,9 @@ import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.AdvancementHolder;
import net.minecraft.advancements.AdvancementType;
import net.minecraft.advancements.critereon.*;
import net.minecraft.core.HolderGetter;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EntityType;
@ -26,6 +28,7 @@ public class ModAdvancementGenerator implements AdvancementProvider.AdvancementG
private final ResourceLocation ADV_BG = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "textures/gui/advancements/backgrounds/leashed_player.png");
@Override
public void generate(HolderLookup.@NotNull Provider registries, @NotNull Consumer<AdvancementHolder> saver, @NotNull ExistingFileHelper existingFileHelper) {
HolderGetter<EntityType<?>> holdergetter = registries.lookupOrThrow(Registries.ENTITY_TYPE);
AdvancementHolder hasLeashRopeItem = Advancement.Builder.advancement().display(
Items.LEAD,
Component.translatable(ModAdvancementKey.LEASH_START.getNameKey()),
@ -74,7 +77,7 @@ public class ModAdvancementGenerator implements AdvancementProvider.AdvancementG
true,
true
).addCriterion("leash_self", LeashPlayerTrigger.TriggerInstance.LeashPlayer(
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(EntityType.LEASH_KNOT))
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(holdergetter, EntityType.LEASH_KNOT))
))
.parent(hasLeashRopeItem).save(saver, ModAdvancementKey.LEASHED_SELF.getNameWithNameSpace());
AdvancementHolder followLeashRopeArrow = Advancement.Builder.advancement().display(
@ -87,7 +90,7 @@ public class ModAdvancementGenerator implements AdvancementProvider.AdvancementG
false,
true
).addCriterion("leash_arrow", LeashPlayerTrigger.TriggerInstance.LeashPlayer(
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(ModEntityRegister.LEASH_ROPE_ARROW.get()))
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(holdergetter, ModEntityRegister.LEASH_ROPE_ARROW.get()))
))
.parent(hasLeashRopeArrow)
.save(saver, ModAdvancementKey.FOLLOW_LEASH_ARROW.getNameWithNameSpace());
@ -101,7 +104,7 @@ public class ModAdvancementGenerator implements AdvancementProvider.AdvancementG
true,
true
).addCriterion("leash_by_wo_do", LeashPlayerTrigger.TriggerInstance.LeashPlayer(
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(EntityType.WOLF))
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(holdergetter, EntityType.WOLF))
))
.parent(hasLeashRopeArrow).save(saver, ModAdvancementKey.DOG_RUNNING_PLAYER.getNameWithNameSpace());
@ -116,10 +119,22 @@ public class ModAdvancementGenerator implements AdvancementProvider.AdvancementG
true
).addCriterion("leash_other_player",
LeashPlayerTrigger.TriggerInstance.LeashPlayer(
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(EntityType.PLAYER))
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(holdergetter, EntityType.PLAYER))
)
)
.parent(hasLeashRopeItem).save(saver, ModAdvancementKey.LEASHED_FRIEND.getNameWithNameSpace());
AdvancementHolder lead_rope_terminator = Advancement.Builder.advancement().display(
ModItemRegister.AMETHYST_SHEARS.get(),
Component.translatable(ModAdvancementKey.LEASH_TERMINATOR.getNameKey()),
Component.translatable(ModAdvancementKey.LEASH_TERMINATOR.getDescKey()),
null,
AdvancementType.TASK,
true,
true,
true
).addCriterion("has_amethyst_shears", InventoryChangeTrigger.TriggerInstance.hasItems(ModItemRegister.AMETHYST_SHEARS.get())
).parent(hasLeashRopeItem).save(saver, ModAdvancementKey.LEASH_TERMINATOR.getNameWithNameSpace());
AdvancementHolder no_leash = Advancement.Builder.advancement().display(
Items.BARRIER,
Component.translatable(ModAdvancementKey.NO_LEASH.getNameKey()),
@ -135,6 +150,29 @@ public class ModAdvancementGenerator implements AdvancementProvider.AdvancementG
.and(ModEffectRegister.NO_LEASH_EFFECT)
)
).parent(hasLeashRopeItem).save(saver, ModAdvancementKey.NO_LEASH.getNameWithNameSpace());
AdvancementHolder tipped_leash_arrow = Advancement.Builder.advancement().display(
ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get(),
Component.translatable(ModAdvancementKey.TIPPED_LEASH_ARROW.getNameKey()),
Component.translatable(ModAdvancementKey.TIPPED_LEASH_ARROW.getDescKey()),
null,
AdvancementType.GOAL,
true,
true,
true
).addCriterion("has_tipped_leash_arrow", InventoryChangeTrigger.TriggerInstance.hasItems(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get())
).parent(hasLeashRopeArrow).save(saver, ModAdvancementKey.TIPPED_LEASH_ARROW.getNameWithNameSpace());
AdvancementHolder neo_fox = Advancement.Builder.advancement().display(
ModItemRegister.NEOFORGE.get(),
Component.translatable(ModAdvancementKey.NEO_FOX.getNameKey()),
Component.translatable(ModAdvancementKey.NEO_FOX.getDescKey()),
null,
AdvancementType.GOAL,
true,
false,
true
).addCriterion("has_neo_fox", InventoryChangeTrigger.TriggerInstance.hasItems(ModItemRegister.NEOFORGE.get())
).parent(hasLeashRopeItem).save(saver, ModAdvancementKey.NEO_FOX.getNameWithNameSpace());
}
}

View File

@ -1,6 +1,7 @@
package com.r3944realms.leashedplayer.datagen.provider;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.datagen.provider.attributes.ModJukeboxSongs;
import com.r3944realms.leashedplayer.datagen.provider.attributes.ModPaintingVariants;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.RegistrySetBuilder;
@ -13,7 +14,8 @@ import java.util.concurrent.CompletableFuture;
public class ModDataPackBuiltInEntriesProvider extends DatapackBuiltinEntriesProvider {
public static final RegistrySetBuilder BUILDER = new RegistrySetBuilder()
.add(Registries.PAINTING_VARIANT, ModPaintingVariants::bootstrap);
.add(Registries.PAINTING_VARIANT, ModPaintingVariants::bootstrap)
.add(Registries.JUKEBOX_SONG, ModJukeboxSongs::bootstrap);
public ModDataPackBuiltInEntriesProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> registries) {
super(output, registries, BUILDER, Set.of(LeashedPlayer.MOD_ID));
CompletableFuture<HolderLookup.Provider> registryProvider = getRegistryProvider();

View File

@ -46,6 +46,10 @@ public class ModItemModelProvider extends ItemModelProvider {
getBuilder("bow_lra_pulling_2")
.parent(new ModelFile.UncheckedModelFile("item/bow"))
.texture("layer0", ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "item/bow_lra_pulling_2"));
getBuilder("tipped_leash_rope_arrow")
.parent(new ModelFile.UncheckedModelFile("item/generated"))
.texture("layer0", ResourceLocation.withDefaultNamespace("item/tipped_arrow_head"))
.texture("layer1", ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "item/tipped_leash_rope_arrow_base"));
}
@Override

View File

@ -2,11 +2,14 @@ package com.r3944realms.leashedplayer.datagen.provider;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import com.r3944realms.leashedplayer.datagen.LanguageAndOtherData.ModItemTags;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.PackOutput;
import net.minecraft.data.tags.ItemTagsProvider;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Block;
import net.neoforged.neoforge.common.Tags;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import org.jetbrains.annotations.NotNull;
@ -22,6 +25,20 @@ public class ModItemTagProvider extends ItemTagsProvider {
protected void addTags(HolderLookup.@NotNull Provider pProvider) {
this.tag(ItemTags.ARROWS)
.add(ModItemRegister.LEASH_ROPE_ARROW.get())
.add(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get());
.add(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get())
.add(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get());
this.tag(ModItemTags.AMETHYST_TOOL_MATERIALS)
.add(Items.AMETHYST_SHARD);
this.tag(ItemTags.HEAD_ARMOR)
.add(ModItemRegister.NEOFORGE.get())
.add(Items.LEAD);
this.tag(ItemTags.MINING_ENCHANTABLE)
.add(ModItemRegister.AMETHYST_SHEARS.get());
this.tag(ItemTags.VANISHING_ENCHANTABLE)
.add(ModItemRegister.AMETHYST_SHEARS.get());
this.tag(ItemTags.DURABILITY_ENCHANTABLE)
.add(ModItemRegister.AMETHYST_SHEARS.get());
this.tag(Tags.Items.TOOLS_SHEAR)
.add(ModItemRegister.AMETHYST_SHEARS.get());
}
}

View File

@ -1,34 +1,37 @@
package com.r3944realms.leashedplayer.datagen.provider;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import com.r3944realms.leashedplayer.content.items.repcipe.TippedLeashRopeArrowRecipe;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.PackOutput;
import net.minecraft.data.recipes.*;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.data.recipes.RecipeOutput;
import net.minecraft.data.recipes.RecipeProvider;
import net.minecraft.data.recipes.SpecialRecipeBuilder;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.CompletableFuture;
public class ModRecipeProvider extends RecipeProvider {
public ModRecipeProvider(PackOutput pOutput, CompletableFuture<HolderLookup.Provider> future) {
super(pOutput, future);
public ModRecipeProvider(HolderLookup.Provider registries, RecipeOutput output) {
super(registries, output);
}
@Override
protected void buildRecipes(@NotNull RecipeOutput pRecipeOutput) {
ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ModItemRegister.LEASH_ROPE_ARROW.get(),1)
protected void buildRecipes() {
this.shapeless(RecipeCategory.MISC, ModItemRegister.LEASH_ROPE_ARROW.get(), 1)
.requires(Items.LEAD)
.requires(Items.ARROW)
.unlockedBy("has_lead",has(Items.LEAD))
.save(pRecipeOutput);
ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get(),1)
.save(this.output);
this.shapeless(RecipeCategory.MISC, ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get(),1)
.requires(Items.LEAD)
.requires(Items.SPECTRAL_ARROW)
.unlockedBy("has_lead",has(Items.LEAD))
.unlockedBy("has_spectral_arrow",has(Items.SPECTRAL_ARROW))
.save(pRecipeOutput, "spectral_leash_rope_arrow_with_leash_rope_arrow");
ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get(),1)
.save(this.output);
this.shaped(RecipeCategory.MISC, ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get(),1)
.pattern(" $ ")
.pattern("$#$")
.pattern(" $ ")
@ -36,7 +39,33 @@ public class ModRecipeProvider extends RecipeProvider {
.define('$', Items.GLOWSTONE_DUST)
.unlockedBy("has_lead",has(Items.LEAD))
.unlockedBy("has_glowstone_dust",has(Items.GLOWSTONE_DUST))
.save(pRecipeOutput,"spectral_leash_rope_arrow_with_glowstone_dust");
.save(this.output,"leash_rope_arrow_shape");
this.shaped(RecipeCategory.MISC, ModItemRegister.AMETHYST_SHEARS.get(),1)
.pattern("#%")
.pattern("%#")
.define('#', Items.AMETHYST_SHARD)
.define('%', Items.STICK)
.unlockedBy("has_amethyst_shard",has(Items.AMETHYST_SHARD))
.save(this.output);
SpecialRecipeBuilder.special(TippedLeashRopeArrowRecipe.TippedLeashRopeArrowARecipe::new).save(this.output, "tipped_leash_rope_arrow_a");
SpecialRecipeBuilder.special(TippedLeashRopeArrowRecipe.TippedLeashRopeArrowBRecipe::new).save(this.output, "tipped_leash_rope_arrow_b");
}
public static class Runner extends RecipeProvider.Runner {
public Runner(PackOutput pPackOutput, CompletableFuture<HolderLookup.Provider> providerCompletableFuture) {
super(pPackOutput, providerCompletableFuture);
}
@Override
@NotNull
public RecipeProvider createRecipeProvider(HolderLookup.@NotNull Provider provider, @NotNull RecipeOutput output) {
return new ModRecipeProvider(provider, output);
}
@Override
public @NotNull String getName() {
return "LeashedPlayer Recipes";
}
}

View File

@ -0,0 +1,37 @@
package com.r3944realms.leashedplayer.datagen.provider;
import com.r3944realms.leashedplayer.content.sounds.ModSoundRegister;
import net.minecraft.data.PackOutput;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import net.neoforged.neoforge.common.data.SoundDefinition;
import net.neoforged.neoforge.common.data.SoundDefinitionsProvider;
public class ModSoundDefinitionsProvider extends SoundDefinitionsProvider {
/**
* Creates a new instance of this data provider.
*
* @param output The {@linkplain PackOutput} instance provided by the data generator.
* @param modId The mod ID of the current mod.
* @param helper The existing file helper provided by the event you are initializing this provider in.
*/
public ModSoundDefinitionsProvider(PackOutput output, String modId, ExistingFileHelper helper) {
super(output, modId, helper);
}
public SoundDefinition getSoundDefinition(String subTitle, SoundDefinition.Sound... sounds) {
return SoundDefinition.definition().subtitle(subTitle).with(sounds);
}
@Override
public void registerSounds() {
add(
ModSoundRegister.FOX_MUSIC,
getSoundDefinition(
ModSoundRegister.getSubTitleTranslateKey("what_does_the_fox_say"),
sound(ModSoundRegister.RL_FOX_MUSIC, SoundDefinition.SoundType.SOUND)
)
);
}
}

View File

@ -0,0 +1,39 @@
package com.r3944realms.leashedplayer.datagen.provider.attributes;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.sounds.ModSoundRegister;
import net.minecraft.Util;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.item.JukeboxSong;
public class ModJukeboxSongs {
public static ResourceKey<JukeboxSong> FOX_MUSIC = create("what_does_the_fox_say");
public static void bootstrap(BootstrapContext<JukeboxSong> pContext) {
JukeboxSongBootstrap(pContext);
}
public static void JukeboxSongBootstrap(BootstrapContext<JukeboxSong> pContext) {
register(pContext, FOX_MUSIC, ModSoundRegister.FOX_MUSIC, 121, 15);
}
private static void register(
BootstrapContext<JukeboxSong> pContext, ResourceKey<JukeboxSong> pKey, Holder<SoundEvent> pSoundEvent, int pLengthInSeconds, int pComparatorOutput
) {
pContext.register(
pKey,
new JukeboxSong(pSoundEvent, Component.translatable(Util.makeDescriptionId("jukebox_song", pKey.location())), (float)pLengthInSeconds, pComparatorOutput)
);
}
private static ResourceKey<JukeboxSong> create(String pName) {
return ResourceKey.create(Registries.JUKEBOX_SONG, ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, pName));
}
}

View File

@ -3,10 +3,13 @@ package com.r3944realms.leashedplayer.datagen.provider.attributes;
import com.r3944realms.leashedplayer.LeashedPlayer;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.decoration.PaintingVariant;
import java.util.Optional;
public class ModPaintingVariants {
public static final ResourceKey<PaintingVariant> GROUP_PHOTO = create("group_photo");
@ -14,10 +17,10 @@ public class ModPaintingVariants {
PaintingVariantBootstrap(pContext);
}
public static void PaintingVariantBootstrap(BootstrapContext<PaintingVariant> pContext) {
ModPaintingVariants.register(pContext, ModPaintingVariants.GROUP_PHOTO, 4, 3);
ModPaintingVariants.register(pContext, ModPaintingVariants.GROUP_PHOTO, 4, 3, Component.translatable(ModPaintingVariants.getPaintingVariantTitleKey(ModPaintingVariants.GROUP_PHOTO)), Component.translatable(ModPaintingVariants.getPaintingVariantAuthorKey(ModPaintingVariants.GROUP_PHOTO)));
}
private static void register(BootstrapContext<PaintingVariant> pContext, ResourceKey<PaintingVariant> pKey, int pWidth, int pHeight) {
pContext.register(pKey, new PaintingVariant(pWidth, pHeight, pKey.location()));
private static void register(BootstrapContext<PaintingVariant> pContext, ResourceKey<PaintingVariant> pKey, int pWidth, int pHeight, Component title, Component author) {
pContext.register(pKey, new PaintingVariant(pWidth, pHeight, pKey.location(), Optional.of(title), Optional.of(author)));
}
private static ResourceKey<PaintingVariant> create(String pName) {
return ResourceKey.create(Registries.PAINTING_VARIANT, ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, pName));

View File

@ -1,8 +1,10 @@
package com.r3944realms.leashedplayer.mixin.both;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Leashable;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@ -12,6 +14,8 @@ import org.spongepowered.asm.mixin.injection.Redirect;
public abstract class MixinEntity {
@Shadow public abstract void igniteForSeconds(float pSeconds);
@Shadow public abstract Level level();
/**
* 这里重定向当实体类实现了{@link PlayerLeashable}接口时<br/>
* 阻止原版的{@link Leashable} 的tickLeash方法调用将其<br/>
@ -21,11 +25,11 @@ public abstract class MixinEntity {
*/
@Redirect(
method = "baseTick",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Leashable;tickLeash(Lnet/minecraft/world/entity/Entity;)V")
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Leashable;tickLeash(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;)V")
)
<E extends Entity & Leashable> void checkAndCancelIfTure(E entity) {
if(!(entity instanceof PlayerLeashable)) {
Leashable.tickLeash(entity);
<E extends Entity & Leashable> void checkAndCancelIfTure(ServerLevel f, E entity) {
if(!(entity instanceof PlayerLeashable) && level() instanceof ServerLevel serverLevel_) {
Leashable.tickLeash(serverLevel_, entity);
}
}

View File

@ -2,7 +2,6 @@ package com.r3944realms.leashedplayer.mixin.both;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.commands.LeashCommand;
import com.r3944realms.leashedplayer.content.effects.ModEffectRegister;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import com.r3944realms.leashedplayer.modInterface.ILivingEntityExtension;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
@ -12,7 +11,6 @@ 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.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Leashable;
@ -47,7 +45,7 @@ public abstract class MixinPlayer extends LivingEntity implements PlayerLeashabl
private static final EntityDataAccessor<CompoundTag> Pl$LEASH_DATA = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG);
@Unique
@SuppressWarnings("WrongEntityDataParameterClass")
@SuppressWarnings("WrongEntityDataParameterClass")
private static final EntityDataAccessor<Float> DATA_ENTITY_LEASH_LENGTH = SynchedEntityData.defineId(Player.class, EntityDataSerializers.FLOAT);
@SuppressWarnings("AddedMixinMembersNamePattern")
@ -203,12 +201,6 @@ public abstract class MixinPlayer extends LivingEntity implements PlayerLeashabl
ILivingEntityExtension iEntityExtension = this;//获取设定值
float leashLengthSelf = iEntityExtension.getLeashLength();
leashLength = leashLengthSelf > LeashCommand.MIN_VALUE ? leashLengthSelf : LeashCommand.MIN_VALUE;
MobEffectInstance effect = this.getEffect(ModEffectRegister.NO_LEASH_EFFECT);
if(effect != null && effect.getDuration() > 0) {
if (entity instanceof LeashRopeArrow arrow)
arrow.setOwner(null);
this.dropLeash(true, !(entity instanceof LeashRopeArrow));
}
if (entity != null) {
double breakDistanceTime = (entity instanceof LeashRopeArrow) ? LeashedPlayer.M1() * LeashedPlayer.M2() : LeashedPlayer.M1();
if(!isAlive() || !entity.isAlive() ||( distanceTo(entity) > Math.max(leashLength * breakDistanceTime, LeashCommand.MIN_VALUE * breakDistanceTime) && keepLeashTick == 0)){

View File

@ -1,30 +0,0 @@
package com.r3944realms.leashedplayer.mixin.client;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(EntityRenderer.class)
public abstract class MixinEntityRenderer {
@Redirect(
method = {"renderLeash"},
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/Entity;getLeashOffset(F)Lnet/minecraft/world/phys/Vec3;"
)
)
private @NotNull Vec3 ret(Entity instance, float pPartialTick) {
if(instance instanceof AbstractClientPlayer) {
//为了使拴绳在在第三视角下位于玩家脖子处
return instance.getLeashOffset(pPartialTick).add(0, -0.2, -0.2);//TODO:待擴展Vec3
}
return instance.getLeashOffset(pPartialTick);//非实现这个接口则不变
}
}

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